allow global app components
This commit is contained in:
parent
fbd5fd4429
commit
375f30ef70
94
com/app.js
94
com/app.js
|
@ -5,11 +5,13 @@ AFRAME.app = new Proxy({
|
||||||
|
|
||||||
order:0,
|
order:0,
|
||||||
|
|
||||||
add(component, entity){
|
components: {}, // component-strings in this array are automatically
|
||||||
|
// added to each app
|
||||||
|
add(component, entity){
|
||||||
// categorize by component to prevent similar apps loading duplicate dependencies simultaniously
|
// categorize by component to prevent similar apps loading duplicate dependencies simultaniously
|
||||||
this[component] = this[component] || []
|
this[component] = this[component] || []
|
||||||
this[component].push(entity)
|
this[component].push(entity)
|
||||||
entity.data.order = entity.data.order || this.count()
|
entity.data.order = entity.data.order || this.count()
|
||||||
},
|
},
|
||||||
count(){
|
count(){
|
||||||
let n = 0
|
let n = 0
|
||||||
|
@ -34,7 +36,7 @@ AFRAME.app = new Proxy({
|
||||||
* This is the abstract 'app' component
|
* This is the abstract 'app' component
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AFRAME.registerComponent('app', {
|
appComponent = {
|
||||||
schema:{
|
schema:{
|
||||||
"uri":{ type:"string"}
|
"uri":{ type:"string"}
|
||||||
},
|
},
|
||||||
|
@ -43,8 +45,12 @@ AFRAME.registerComponent('app', {
|
||||||
"app:ready": function(){
|
"app:ready": function(){
|
||||||
let {id,component,type} = this.parseAppURI(this.data.uri)
|
let {id,component,type} = this.parseAppURI(this.data.uri)
|
||||||
AFRAME.app[component].map( (app) => {
|
AFRAME.app[component].map( (app) => {
|
||||||
if( !app.el.getAttribute(component) ) app.el.setAttribute(component,app.data)
|
if( !app.el.getAttribute(component) ){
|
||||||
})
|
if( AFRAME.components[ component ] ){
|
||||||
|
app.el.setAttribute(component,app.data)
|
||||||
|
}else console.warn(`${component} was not fully downloaded yet (${app.data.uri})`)
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
"requires:ready": function(){
|
"requires:ready": function(){
|
||||||
let {id,component,type} = this.parseAppURI(this.data.uri)
|
let {id,component,type} = this.parseAppURI(this.data.uri)
|
||||||
|
@ -55,16 +61,16 @@ AFRAME.registerComponent('app', {
|
||||||
app.el.emit('ready')
|
app.el.emit('ready')
|
||||||
app.readyFired = true
|
app.readyFired = true
|
||||||
},400) // big js scripts need some parsing time
|
},400) // big js scripts need some parsing time
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
let {id,component,type} = this.parseAppURI(this.data.uri)
|
let {id,component,type} = this.parseAppURI(this.data.uri)
|
||||||
let sel = `script#${component}`
|
let sel = `script#${component}`
|
||||||
if( AFRAME.app[component] || AFRAME.components[component] || document.head.querySelector(sel) ) return AFRAME.app.add(component,this)
|
if( AFRAME.app[component] || AFRAME.components[component] || document.head.querySelector(sel) ) return AFRAME.app.add(component,this)
|
||||||
AFRAME.app.add(component,this)
|
AFRAME.app.add(component,this)
|
||||||
this.require([ this.data.uri ], 'app:ready')
|
this.require([ this.data.uri ], 'app:ready')
|
||||||
},
|
},
|
||||||
|
|
||||||
parseAppURI: AFRAME.AComponent.prototype.parseAppURI = function(uri){
|
parseAppURI: AFRAME.AComponent.prototype.parseAppURI = function(uri){
|
||||||
|
@ -84,7 +90,7 @@ AFRAME.registerComponent('app', {
|
||||||
let id = package.split("/").pop()
|
let id = package.split("/").pop()
|
||||||
// prevent duplicate requests
|
// prevent duplicate requests
|
||||||
if( AFRAME.required[id] ) return
|
if( AFRAME.required[id] ) return
|
||||||
AFRAME.required[id] = true
|
AFRAME.required[id] = true
|
||||||
|
|
||||||
if( !document.head.querySelector(`script#${id}`) ){
|
if( !document.head.querySelector(`script#${id}`) ){
|
||||||
let {component,type} = this.parseAppURI(package)
|
let {component,type} = this.parseAppURI(package)
|
||||||
|
@ -111,21 +117,24 @@ AFRAME.registerComponent('app', {
|
||||||
}catch(e){ console.error(`package ${package} could not be retrieved..aborting :(`); throw e; }
|
}catch(e){ console.error(`package ${package} could not be retrieved..aborting :(`); throw e; }
|
||||||
})
|
})
|
||||||
Promise.all(deps).then( () => {
|
Promise.all(deps).then( () => {
|
||||||
this.el.emit( readyEvent || 'requireReady', packages)
|
this.el.emit( readyEvent || 'requireReady', packages)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
}
|
||||||
|
|
||||||
|
AFRAME.registerComponent('app', appComponent)
|
||||||
|
AFRAME.registerComponent('com', appComponent)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Here are monkeypatched AFRAME component prototype functions
|
* Here are monkeypatched AFRAME component prototype functions
|
||||||
*
|
*
|
||||||
* monkeypatching initComponent will trigger events when components
|
* monkeypatching initComponent will trigger events when components
|
||||||
* are initialized (that way apps can react to attached components)
|
* are initialized (that way apps can react to attached components)
|
||||||
* basically, in both situations:
|
* basically, in both situations:
|
||||||
* <a-entity foo="a:1"/>
|
* <a-entity foo="a:1"/>
|
||||||
* <a-entity app="uri: myapp.js"/> <!-- myapp.js calls this.require(['foo.js']) -->
|
* <a-entity app="uri: myapp.js"/> <!-- myapp.js calls this.require(['foo.js']) -->
|
||||||
*
|
*
|
||||||
* event 'foo' will be triggered as both entities (in)directly require component 'foo'
|
* event 'foo' will be triggered as both entities (in)directly require component 'foo'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -151,22 +160,16 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
|
||||||
overlay.id = "overlay"
|
overlay.id = "overlay"
|
||||||
document.body.appendChild(overlay)
|
document.body.appendChild(overlay)
|
||||||
document.querySelector("a-scene").setAttribute("webxr","overlayElement:#overlay")
|
document.querySelector("a-scene").setAttribute("webxr","overlayElement:#overlay")
|
||||||
// let menu = document.createElement('div')
|
|
||||||
// menu.id = 'iconmenu'
|
|
||||||
// document.body.appendChild(menu)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // add menu button
|
const reactify = (el,aframe) => new Proxy(this.data,{
|
||||||
// if( this.manifest && this.manifest.icons ){
|
get(me,k,v) { return me[k]
|
||||||
// let btn = document.createElement('button')
|
},
|
||||||
// btn.app = this
|
set(me,k,v){
|
||||||
// if( this.manifest.icons.length ){
|
me[k] = v
|
||||||
// btn.innerHTML = `<img src="${this.manifest.icons[0].src}"/>`
|
aframe.emit(k,{el,k,v})
|
||||||
// }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
|
// reactify components with dom-definition
|
||||||
if( this.data.uri && this.dom && !this.el.dom ){
|
if( this.data.uri && this.dom && !this.el.dom ){
|
||||||
|
@ -174,14 +177,6 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
|
||||||
tasks = {
|
tasks = {
|
||||||
|
|
||||||
createReactiveDOMElement: () => {
|
createReactiveDOMElement: () => {
|
||||||
const reactify = (el,aframe) => new Proxy(this.data,{
|
|
||||||
get(me,k,v) { return me[k]
|
|
||||||
},
|
|
||||||
set(me,k,v){
|
|
||||||
me[k] = v
|
|
||||||
aframe.emit(k,{el,k,v})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.el.dom = document.createElement('div')
|
this.el.dom = document.createElement('div')
|
||||||
this.el.dom.className = this.parseAppURI(this.data.uri).component
|
this.el.dom.className = this.parseAppURI(this.data.uri).component
|
||||||
this.el.dom.innerHTML = this.dom.html(this)
|
this.el.dom.innerHTML = this.dom.html(this)
|
||||||
|
@ -206,12 +201,19 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
|
||||||
setupListeners: () => {
|
setupListeners: () => {
|
||||||
this.scene.addEventListener('apps:2D', () => this.el.setAttribute('visible', false) )
|
this.scene.addEventListener('apps:2D', () => this.el.setAttribute('visible', false) )
|
||||||
this.scene.addEventListener('apps:XR', () => {
|
this.scene.addEventListener('apps:XR', () => {
|
||||||
this.el.setAttribute('visible', true)
|
this.el.setAttribute('visible', true)
|
||||||
this.el.setAttribute("html",`html:#${this.el.uid}; cursor:#cursor`)
|
this.el.setAttribute("html",`html:#${this.el.uid}; cursor:#cursor`)
|
||||||
})
|
})
|
||||||
return tasks
|
return tasks
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initAutoComponents: () => {
|
||||||
|
for ( let i in AFRAME.app.components ) {
|
||||||
|
this.el.setAttribute( i, AFRAME.app.components[i] )
|
||||||
|
}
|
||||||
|
return tasks
|
||||||
|
},
|
||||||
|
|
||||||
triggerKeyboardForInputs: () => {
|
triggerKeyboardForInputs: () => {
|
||||||
// https://developer.oculus.com/documentation/web/webxr-keyboard ;
|
// https://developer.oculus.com/documentation/web/webxr-keyboard ;
|
||||||
[...this.el.dom.querySelectorAll('[type=text]')].map( (input) => {
|
[...this.el.dom.querySelectorAll('[type=text]')].map( (input) => {
|
||||||
|
@ -232,16 +234,24 @@ AFRAME.AComponent.prototype.updateProperties = function(updateProperties){
|
||||||
.scaleDOMvsXR()
|
.scaleDOMvsXR()
|
||||||
.triggerKeyboardForInputs()
|
.triggerKeyboardForInputs()
|
||||||
.setupListeners()
|
.setupListeners()
|
||||||
|
.initAutoComponents()
|
||||||
|
|
||||||
document.querySelector('#overlay').appendChild(this.el.dom)
|
document.querySelector('#overlay').appendChild(this.el.dom)
|
||||||
this.el.emit('DOMready',{el: this.el.dom})
|
this.el.emit('DOMready',{el: this.el.dom})
|
||||||
|
|
||||||
}
|
}else this.data = reactify( this.el, this.el )
|
||||||
|
|
||||||
// assign unique app id
|
// assign unique app id
|
||||||
if( !this.el.uid ) this.el.uid = '_'+String(Math.random()).substr(10)
|
if( !this.el.uid ) this.el.uid = '_'+String(Math.random()).substr(10)
|
||||||
|
|
||||||
if( this.requires ) this.require( this.requires, 'requires:ready' )
|
// require coms
|
||||||
else this.el.emit('requires:ready')
|
let requires = {}
|
||||||
|
for ( let i in AFRAME.app.components ) {
|
||||||
|
if( !AFRAME.components[i] ) requires[i] = AFRAME.app.components[i]
|
||||||
|
}
|
||||||
|
if( this.requires ) requires = {...requires, ...this.requires }
|
||||||
|
if( Object.values(requires).length ) this.require( requires, 'requires:ready' )
|
||||||
|
else this.el.emit('requires:ready' )
|
||||||
|
|
||||||
// mark app as being initialized
|
// mark app as being initialized
|
||||||
this.isApp = true
|
this.isApp = true
|
||||||
|
|
Loading…
Reference in New Issue