@@ -9,7 +9,6 @@ var AEntity;
99var isNode = re . isNode ;
1010var debug = utils . debug ( 'core:a-entity:debug' ) ;
1111var registerElement = re . registerElement ;
12- var styleParser = utils . styleParser ;
1312
1413/**
1514 * Entity is a container object that components are plugged into to comprise everything in
@@ -58,7 +57,7 @@ var proto = Object.create(ANode.prototype, {
5857 this . addToParent ( ) ;
5958 if ( ! this . isScene ) {
6059 this . load ( ) ;
61- if ( ! this . parentNode . paused ) { this . play ( ) ; }
60+ if ( this . parentEl . isPlaying ) { this . play ( ) ; }
6261 }
6362 }
6463 } ,
@@ -246,33 +245,29 @@ var proto = Object.create(ANode.prototype, {
246245 * Initialize component.
247246 */
248247 initComponent : {
249- value : function ( name , isDependency ) {
248+ value : function ( name , isDependency , attr ) {
250249 var component ;
251- var isComponentDefined = checkComponentDefined ( this , name ) ;
250+ var isComponentDefined = checkComponentDefined ( this , name ) || attr !== undefined ;
252251
253- // Check if component is registered and whether component should be iniitalized .
252+ // Check if component is registered and whether component should be initalized .
254253 if ( ! components [ name ] || ( ! isComponentDefined && ! isDependency ) ) {
255254 return ;
256255 }
257256
258257 // Initialize dependencies.
259258 this . initComponentDependencies ( name ) ;
260259
261- if ( isDependency && ! isComponentDefined ) {
262- // Add component if it is a dependency and not yet defined.
263- this . setAttribute ( name , '' ) ;
264- } else {
265- if ( this . isScene && ! this . hasAttribute ( name ) && name in this . defaultComponents ) {
266- // For scene default components, expose them in the DOM.
267- HTMLElement . prototype . setAttribute . call ( this , name , this . defaultComponents [ name ] ) ;
268- }
260+ // if (this.isScene && !this.hasAttribute(name) && name in this.defaultComponents) {
261+ // For scene default components, expose them in the DOM.
262+ // HTMLElement.prototype.setAttribute.call(this, name, this.defaultComponents[name]);
263+ // }
269264
270- // Check if component already initialized.
271- if ( name in this . components ) { return ; }
265+ // Check if component already initialized.
266+ if ( name in this . components ) { return ; }
267+
268+ component = this . components [ name ] = new components [ name ] . Component ( this , attr ) ;
269+ if ( this . isPlaying ) { playComponent ( component , this . sceneEl ) ; }
272270
273- component = this . components [ name ] = new components [ name ] . Component ( this ) ;
274- if ( this . isPlaying ) { playComponent ( component , this . sceneEl ) ; }
275- }
276271 debug ( 'Component initialized: %s' , name ) ;
277272 } ,
278273 writable : window . debug
@@ -301,14 +296,56 @@ var proto = Object.create(ANode.prototype, {
301296 }
302297 } ,
303298
299+ getMixedInComponents : {
300+ value : function ( ) {
301+ var mixinEls = this . mixinEls ;
302+ var i ;
303+ var components = [ ] ;
304+ for ( i = 0 ; i < mixinEls . length ; ++ i ) {
305+ var keys = Object . keys ( mixinEls [ i ] . attrs ) ;
306+ keys . forEach ( function ( key ) {
307+ components . push ( key ) ;
308+ } ) ;
309+ }
310+ return components ;
311+ }
312+ } ,
313+
304314 updateComponents : {
305315 value : function ( ) {
306316 var self = this ;
307- var allComponents = Object . keys ( components ) ;
308- allComponents . forEach ( updateComponent ) ;
309- function updateComponent ( name ) {
310- var elValue = self . getAttribute ( name ) ;
311- self . updateComponent ( name , elValue ) ;
317+ var elValue ;
318+ var attrs = { } ;
319+ var componentName ;
320+ var i ;
321+ if ( ! this . hasLoaded ) { return ; }
322+ var elComponents = Object . keys ( this . components ) ;
323+ for ( i = 0 ; i < elComponents . length ; ++ i ) {
324+ attrs [ elComponents [ i ] ] = true ;
325+ }
326+ var attributes = this . attributes ;
327+ for ( i = 0 ; i < attributes . length ; ++ i ) {
328+ if ( ! components [ attributes [ i ] . name ] ) { continue ; }
329+ attrs [ attributes [ i ] . name ] = true ;
330+ }
331+ var mixedInComponents = this . getMixedInComponents ( ) ;
332+ mixedInComponents . forEach ( function ( key ) {
333+ attrs [ key ] = true ;
334+ } ) ;
335+ var defaultComponents = Object . keys ( this . defaultComponents ) ;
336+ for ( i = 0 ; i < defaultComponents . length ; ++ i ) {
337+ componentName = defaultComponents [ i ] ;
338+ delete attrs [ componentName ] ;
339+ elValue = self . getAttribute ( componentName ) || undefined ;
340+ if ( components [ componentName ] ) {
341+ this . updateComponent ( componentName , elValue ) ;
342+ }
343+ }
344+ attrs = Object . keys ( attrs ) ;
345+ for ( i = 0 ; i < attrs . length ; ++ i ) {
346+ componentName = attrs [ i ] ;
347+ elValue = self . getAttribute ( componentName ) ;
348+ this . updateComponent ( componentName , elValue ) ;
312349 }
313350 }
314351 } ,
@@ -324,15 +361,19 @@ var proto = Object.create(ANode.prototype, {
324361 updateComponent : {
325362 value : function ( name , newData ) {
326363 var component = this . components [ name ] ;
327- var isDefault = name in this . defaultComponents ;
364+ var defaultComponents = this . defaultComponents ;
365+ var isDefault = name in defaultComponents ;
328366 var isMixedIn = isComponentMixedIn ( name , this . mixinEls ) ;
367+ var elValue = this . getAttribute ( defaultComponents [ name ] ) ;
368+
329369 if ( component ) {
330370 // Attribute was removed, remove component if:
331371 // 1. If component not defined in the defaults/mixins/attribute.
332372 // 2. If new data is null, then not a default component and component is not defined
333373 // via mixins
334- if ( ! checkComponentDefined ( this , name ) ||
335- newData === null && ! isDefault && ! isMixedIn ) {
374+ if ( ! checkComponentDefined ( this , name ) && ! elValue ||
375+ newData === null ) {
376+ if ( isDefault || isMixedIn ) { return ; }
336377 this . removeComponent ( name ) ;
337378 return ;
338379 }
@@ -341,7 +382,7 @@ var proto = Object.create(ANode.prototype, {
341382 return ;
342383 }
343384 // Component not yet initialized. Initialize component.
344- this . initComponent ( name ) ;
385+ this . initComponent ( name , false , newData ) ;
345386 }
346387 } ,
347388
@@ -356,8 +397,9 @@ var proto = Object.create(ANode.prototype, {
356397 var component = components [ attr ] ;
357398 if ( component ) {
358399 this . setEntityAttribute ( attr , undefined , null ) ;
400+ } else {
401+ HTMLElement . prototype . removeAttribute . call ( this , attr ) ;
359402 }
360- HTMLElement . prototype . removeAttribute . call ( this , attr ) ;
361403 }
362404 } ,
363405
@@ -372,7 +414,7 @@ var proto = Object.create(ANode.prototype, {
372414 var sceneEl = this . sceneEl ;
373415
374416 // Already playing.
375- if ( this . isPlaying ) { return ; }
417+ if ( this . isPlaying || ! this . hasLoaded ) { return ; }
376418 this . isPlaying = true ;
377419
378420 // Wake up all components.
@@ -427,18 +469,15 @@ var proto = Object.create(ANode.prototype, {
427469 */
428470 setEntityAttribute : {
429471 value : function ( attr , oldVal , newVal ) {
430- var component = components [ attr ] ;
431- oldVal = oldVal || this . getAttribute ( attr ) ;
432- // When creating entities programatically and setting attributes, it is not part
433- // of the scene until it is inserted into the DOM. This does not apply to scenes as
434- // scenes depend on its child entities to load.
435- if ( ! this . hasLoaded && ! this . isScene ) { return ; }
472+ if ( components [ attr ] ) {
473+ this . updateComponent ( attr , newVal ) ;
474+ return ;
475+ }
436476 if ( attr === 'mixin' ) {
437477 this . updateStateMixins ( newVal , oldVal ) ;
438478 this . updateComponents ( ) ;
439479 return ;
440480 }
441- if ( component ) { this . updateComponent ( attr , newVal ) ; }
442481 }
443482 } ,
444483
@@ -464,25 +503,25 @@ var proto = Object.create(ANode.prototype, {
464503 var self = this ;
465504 var component = this . components [ attr ] || components [ attr ] ;
466505 var partialComponentData ;
467- value = value === undefined ? '' : value ;
468506 var componentObj = value ; // Deserialized value to send to the component.
469507 var componentStr = value ; // Serialized value to send to the DOM.
470- var oldValue ;
508+ var oldValue = { } ;
471509
472510 if ( component ) {
473511 if ( typeof value === 'string' && componentPropValue !== undefined ) {
474512 // Update currently-defined component data with the new property value.
475513 // Use native setAttribute in order not to double-parse properties.
476- partialComponentData = styleParser . parse (
477- HTMLElement . prototype . getAttribute . call ( this , attr ) ) || { } ;
514+ partialComponentData = component . attr || { } ;
478515 partialComponentData [ value ] = componentPropValue ;
479516 componentObj = partialComponentData ;
480517 }
518+ oldValue = utils . extend ( { } , component . attr ) ;
481519 componentStr = component . stringify ( componentObj ) ;
520+ self . setEntityAttribute ( attr , oldValue , componentObj ) ;
521+ } else {
522+ ANode . prototype . setAttribute . call ( self , attr , componentStr ) ;
523+ if ( attr === 'mixin' ) { self . setEntityAttribute ( 'mixin' , undefined , componentObj ) ; }
482524 }
483- oldValue = this . getAttribute ( attr ) ;
484- ANode . prototype . setAttribute . call ( self , attr , componentStr ) ;
485- self . setEntityAttribute ( attr , oldValue , componentObj ) ;
486525 } ,
487526 writable : window . debug
488527 } ,
@@ -500,10 +539,12 @@ var proto = Object.create(ANode.prototype, {
500539 */
501540 getAttribute : {
502541 value : function ( attr ) {
503- var component = this . components [ attr ] || components [ attr ] ;
504- var value = HTMLElement . prototype . getAttribute . call ( this , attr ) ;
505- if ( ! component || typeof value !== 'string' ) { return value ; }
506- return component . parse ( value , true ) ;
542+ var component = this . components [ attr ] ;
543+ // If there's a cached value we just return it
544+ if ( component && component . attr !== undefined ) {
545+ return component . attr ;
546+ }
547+ return HTMLElement . prototype . getAttribute . call ( this , attr ) ;
507548 } ,
508549 writable : window . debug
509550 } ,
@@ -570,6 +611,8 @@ function checkComponentDefined (el, name) {
570611 // Check if element contains the component.
571612 if ( el . hasAttribute ( name ) ) { return true ; }
572613
614+ if ( el . components [ name ] ) { return true ; }
615+
573616 return isComponentMixedIn ( name , el . mixinEls ) ;
574617}
575618
0 commit comments