diff --git a/app/helloworld-html.js b/app/example/helloworld-html.js
similarity index 100%
rename from app/helloworld-html.js
rename to app/example/helloworld-html.js
diff --git a/app/helloworld-htmlform.js b/app/example/helloworld-htmlform.js
similarity index 100%
rename from app/helloworld-htmlform.js
rename to app/example/helloworld-htmlform.js
diff --git a/app/helloworld-window.js b/app/example/helloworld-window.js
similarity index 100%
rename from app/helloworld-window.js
rename to app/example/helloworld-window.js
diff --git a/app/helloworld.js b/app/example/helloworld.js
similarity index 100%
rename from app/helloworld.js
rename to app/example/helloworld.js
diff --git a/app/helloworld.old.js b/app/example/helloworld.old.js
similarity index 100%
rename from app/helloworld.old.js
rename to app/example/helloworld.old.js
diff --git a/app/launcher.js b/app/launcher.js
index dcae6d2..acd034f 100644
--- a/app/launcher.js
+++ b/app/launcher.js
@@ -37,7 +37,7 @@ AFRAME.registerComponent('launcher', {
scale: 3,
events: ['click'],
html: (me) => `
-
+
`,
css: `#iconmenu {
@@ -53,6 +53,7 @@ AFRAME.registerComponent('launcher', {
padding-bottom: 72px;
box-sizing: border-box;
pointer-events: none;
+ visibility: visible !important;
}
#iconmenu > button {
pointer-events:all;
@@ -84,9 +85,8 @@ AFRAME.registerComponent('launcher', {
padding: 5px;
border-radius: 0px;
}
- #iconmenu > button > img:hover,
- #iconmenu > button.enable > img {
- border:2px solid #444;
+ #iconmenu > button > img:hover{
+ background: #AAA;
transition:0.gg3s;
border-radius: 50%;
}`
@@ -110,24 +110,21 @@ AFRAME.registerComponent('launcher', {
clearTimeout(this.timeout)
this.timeout = setTimeout( () => {
AFRAME.app.foreach( (app) => {
- console.dir(app)
if( !app.manifest ) return
- console.log("--rendering button")
- return
+ console.log(app.data.uri+" "+app.data.order)
+
let btn = app.btn = document.createElement('button')
if( app.manifest.icons?.length > 0){
let img = document.createElement('img')
img.src = app.manifest.icons[0].src
- img.alt = app.manifest.name
+ img.title = app.manifest.name + ": " + app.manifest.description
btn.appendChild(img)
}else btn.innerText = app.manifest.short_name
- btn.addEventListener('click', () => {
- app.el.emit('launcher',app)
- })
+ btn.addEventListener('click', () => app.el.emit('launcher',app) )
this.el.dom.querySelector('#iconmenu').appendChild(btn)
})
- },200)
+ },100)
},
manifest: { // HTML5 manifest to identify app to xrsh
diff --git a/app/spatialize.js b/app/spatialize.js
index a574eae..18bc533 100644
--- a/app/spatialize.js
+++ b/app/spatialize.js
@@ -9,6 +9,17 @@ AFRAME.registerComponent('spatialize', {
document.querySelector('a-scene').addEventListener('exit-vr', () => this.toggle(false) )
// toggle immersive with ESCAPE
document.body.addEventListener('keydown', (e) => e.key == 'Escape' && this.toggle() )
+
+ document.head.innerHTML += ``
},
requires:{
@@ -31,7 +42,8 @@ AFRAME.registerComponent('spatialize', {
state = state || !document.body.className.match(/XR/)
document.body.classList[ state ? 'add' : 'remove'](['XR'])
AFRAME.scenes[0].emit( state ? 'apps:XR' : 'apps:2D')
- this.btn.classList.toggle('enable')
+ this.btn.querySelector('img').src = state ? this.manifest.icons[0].src_2D
+ : this.manifest.icons[0].src
},
manifest: { // HTML5 manifest to identify app to xrsh
@@ -39,7 +51,8 @@ AFRAME.registerComponent('spatialize', {
"name": "spatialize",
"icons": [
{
- "src": "https://css.gg/stack.svg",
+ "src": "https://css.gg/display-grid.svg",
+ "src_2D": "https://css.gg/stack.svg",
"type": "image/svg+xml",
"sizes": "512x512"
}
@@ -66,7 +79,7 @@ AFRAME.registerComponent('spatialize', {
"icons": [{ "src": "/images/today.png", "sizes": "192x192" }]
}
],
- "description": "Hello world information",
+ "description": "use ESC-key to toggle between 2D / 3D",
"screenshots": [
{
"src": "/images/screenshot1.png",
diff --git a/com/app.js b/com/app.js
index d15952d..111fd92 100644
--- a/com/app.js
+++ b/com/app.js
@@ -3,20 +3,37 @@
AFRAME.required = {}
AFRAME.app = new Proxy({
+ order:0,
+
add(component, entity){
+ // categorize by component to prevent similar apps loading duplicate dependencies simultaniously
this[component] = this[component] || []
this[component].push(entity)
+ entity.data.order = entity.data.order || this.count()
+ },
+ count(){
+ let n = 0
+ this.foreach( () => n++ )
+ return n
},
foreach(cb){
+ const isArray = (e) => e.push
+ let arr = []
for( let i in this ){
- if( typeof this[i] != 'function' ) this[i].map( (app) => cb({app,component:i}) )
+ if( isArray(this[i]) ) this[i].map( (app) => arr.push(app.el.app) )
}
+ arr.sort( (a,b) => a.data.order > b.data.order )
+ .map( cb )
}
},{
get(me,k) { return me[k] },
set(me,k,v){ me[k] = v }
})
+/*
+ * This is the abstract 'app' component
+ */
+
AFRAME.registerComponent('app', {
schema:{
"uri":{ type:"string"}
@@ -57,7 +74,6 @@ AFRAME.registerComponent('app', {
type: String(uri).split(".").pop() // 'mycom.js' => 'js'
}
},
-
// usage: require(["./app/foo.js"])
// require({foo: "https://foo.com/foo.js"})
require: AFRAME.AComponent.prototype.require = function(packages,readyEvent){
@@ -101,13 +117,17 @@ AFRAME.registerComponent('app', {
})
-// monkeypatching initComponent will trigger events when components
-// are initialized (that way apps can react to attached components)
-// basically, in both situations:
-//
-//
-//
-// event 'foo' will be triggered as both entities (in)directly require component 'foo'
+/*
+ * Here are monkeypatched AFRAME component prototype functions
+ *
+ * monkeypatching initComponent will trigger events when components
+ * are initialized (that way apps can react to attached components)
+ * basically, in both situations:
+ *
+ *
+ *
+ * event 'foo' will be triggered as both entities (in)directly require component 'foo'
+ */
AFRAME.AComponent.prototype.initComponent = function(initComponent){
return function(){
@@ -122,7 +142,7 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
return function(){
updateProperties.apply(this,arguments)
- if( !this.data || !this.data.uri ) return // only deal with apps
+ if( !this.data || !this.data.uri || this.isApp ) return // only deal with apps (once)
// ensure overlay
let overlay = document.querySelector('#overlay')
@@ -131,22 +151,22 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
overlay.id = "overlay"
document.body.appendChild(overlay)
document.querySelector("a-scene").setAttribute("webxr","overlayElement:#overlay")
- let menu = document.createElement('div')
- menu.id = 'iconmenu'
- document.body.appendChild(menu)
+// let menu = document.createElement('div')
+// menu.id = 'iconmenu'
+// document.body.appendChild(menu)
}
- // add menu button
- if( this.manifest && this.manifest.icons ){
- let btn = document.createElement('button')
- btn.app = this
- if( this.manifest.icons.length ){
- btn.innerHTML = ``
- }else btn.innerText = this.manifest.short_name
- btn.setAttribute("alt", this.manifest.name )
- btn.addEventListener('click', (e) => this.el.emit('launcher',{}) )
- document.querySelector("#iconmenu").appendChild(btn)
- }
+// // add menu button
+// if( this.manifest && this.manifest.icons ){
+// let btn = document.createElement('button')
+// btn.app = this
+// if( this.manifest.icons.length ){
+// btn.innerHTML = ``
+// }else btn.innerText = this.manifest.short_name
+// btn.setAttribute("alt", this.manifest.name )
+// btn.addEventListener('click', (e) => this.el.emit('launcher',{}) )
+// document.querySelector("#iconmenu").appendChild(btn)
+// }
// reactify components with dom-definition
if( this.data.uri && this.dom && !this.el.dom ){
@@ -220,9 +240,12 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
// assign unique app id
if( !this.el.uid ) this.el.uid = '_'+String(Math.random()).substr(10)
- // fetch requires
if( this.requires ) this.require( this.requires, 'requires:ready' )
else this.el.emit('requires:ready')
+
+ // mark app as being initialized
+ this.isApp = true
+ this.el.app = this
}
}( AFRAME.AComponent.prototype.updateProperties)
@@ -249,62 +272,5 @@ document.head.innerHTML += `
#overlay.hide{
z-index:-10;
}
-
- #toggle_overlay{
- display:none;
- position: fixed;
- right: 20px;
- bottom: 73px;
- width: 58px;
- text-align: center;
- height: 40px;
- padding: 0;
- z-index: 100;
- border: 3px solid #3aacff;
- border-radius:11px;
- transition:0.3s;
- padding: 0px;
- font-weight: bold;
- cursor:pointer;
- font-family:sans-serif;
- font-size:15px;
- color: #FFF;
- background: #3aacff;
- transition:0.5s;
- }
- .XR #toggle_overlay{
- background: transparent;
- color: #3aacff;
- }
-
- .XR #overlay{
- visibility: hidden;
- }
`
-
-// draw a button so we can toggle apps between 2D / XR
-let toggle = (state) => {
- state = state || !document.body.className.match(/XR/)
- document.body.classList[ state ? 'add' : 'remove'](['XR'])
- AFRAME.scenes[0].emit( state ? 'apps:XR' : 'apps:2D')
-}
-
-document.addEventListener("DOMContentLoaded", (event) => {
- let btn = document.createElement("button")
- btn.id = "toggle_overlay"
- btn.innerHTML = ""
- btn.addEventListener('click', (e) => toggle() )
- document.body.appendChild(btn)
-
- document.querySelector('a-scene').addEventListener('enter-vr',() => toggle(true) )
- document.querySelector('a-scene').addEventListener('exit-vr', () => toggle(false) )
- document.querySelector('a-scene').addEventListener('loaded', () => {
- let VRbtn = document.querySelector('a-scene .a-enter-vr')
- let ARbtn = document.querySelector('a-scene .a-enter-ar')
- if( VRbtn ) document.body.appendChild(VRbtn) // move to body
- if( ARbtn ) document.body.appendChild(ARbtn) // so they will always be visible
- })
- // toggle immersive with ESCAPE
- document.body.addEventListener('keydown', (e) => e.key == 'Escape' && toggle() )
-})