diff --git a/src/game-lib-a-component-a.js b/src/game-lib-a-component-a.js index ac8c4bd..f3bee44 100644 --- a/src/game-lib-a-component-a.js +++ b/src/game-lib-a-component-a.js @@ -50,37 +50,7 @@ GameLib.Component = function( if (this.dependencies.length === 0) { - delete this.dependencies; - - /** - * Build ID to object should run through all sub components - - * if one is found which is not linked, this component is not linked fully - */ - this.buildIdToObject(); - - /** - * Don't try to create an instance of this object until it is fully linked - */ - if (this.linked) { - try { - - if (!this.delayed) { - this.createInstance(); - } - // else { - // GameLib.Event.Subscribe( - // GameLib.Event.DELAYED_INSTANCE, - // function(data) { - // - // } - // ) - // } - // - - } catch (error) { - console.error(error); - } - } + this.performInstanceCreation(); } else { GameLib.Event.Emit( @@ -97,6 +67,54 @@ GameLib.Component = function( GameLib.Component.prototype = Object.create(GameLib.API.Component.prototype); GameLib.Component.prototype.constructor = GameLib.Component; +/** + * This function, performs standard instance creation steps for all our components, which means + * Ensure we have no dependencies + * Build a list of all child components - if they are all linked, we are ready to create an instance + * Ensure we are linked + * Ensure we are not delayed + * Try to create the instance + * Error Log if failed + * Don't do anything if we are not fully linked + */ +GameLib.Component.prototype.performInstanceCreation = function() { + + var dependencies = true; + + if (GameLib.Utils.UndefinedOrNull(this.dependencies)) { + dependencies = false; + } + + if (this.dependencies && this.dependencies instanceof Array && this.dependencies.length === 0) { + dependencies = false; + } + + if (dependencies) { + throw new Error('performInstanceCreation called while this object still has dependencies'); + } + + delete this.dependencies; + + /** + * Build ID to object should run through all sub components - + * if one is found which is not linked, this component is not linked fully + */ + this.buildIdToObject(); + + /** + * Don't try to create an instance of this object until it is fully linked + */ + if (this.linked) { + if (!this.delayed) { + try { + this.createInstance(); + } catch (error) { + console.error(error); + } + } + } +}; + GameLib.Component.prototype.createInstance = function() { console.log('create instance : '+ this.name); diff --git a/src/game-lib-d3-api-z-animation.js b/src/game-lib-d3-api-z-animation.js index 7921205..7522b2a 100644 --- a/src/game-lib-d3-api-z-animation.js +++ b/src/game-lib-d3-api-z-animation.js @@ -59,51 +59,52 @@ GameLib.D3.Animation.ANIMATION_FUNCTION_TYPE_SCALE = 3; GameLib.D3.Animation.prototype.createInstance = function() { + this.instance = { + rotation : null, + translation : null, + scale : null + }; + try { - - var instance = { - rotation : null, - translation : null, - scale : null - }; - if (this.rotationFn) { - instance.rotation = new Function( + this.instance.rotation = new Function( 'data', this.rotationFn ).bind(this); } if (this.translationFn) { - instance.translation = new Function( + this.instance.translation = new Function( 'data', this.translationFn ).bind(this); } if (this.scaleFn) { - instance.scale = new Function( + this.instance.scale = new Function( 'data', this.scaleFn ).bind(this); } + } catch (error) { + console.error(error); + this.publish( + GameLib.Event.ANIMATION_COMPILE_FAILED, + { + component : this + } + ) + } - return instance; - - } catch (error) { - /** - * Return true here to indicate that even though the compilation failed, the instance will be fine and - * this component loaded fine. - */ - return true; - } + GameLib.Component.prototype.createInstance.call(this); }; /** * Updates the instance with the current state */ GameLib.D3.Animation.prototype.updateInstance = function() { - try { + + try { if (this.rotationFn) { this.instance.rotation = new Function('data', this.rotationFn).bind(this); @@ -139,6 +140,7 @@ GameLib.D3.Animation.prototype.updateInstance = function() { } } catch (error) { + console.error(error); this.publish( GameLib.Event.ANIMATION_COMPILE_FAILED, { diff --git a/src/game-lib-system-linking.js b/src/game-lib-system-linking.js index 391d7e5..a283bbd 100644 --- a/src/game-lib-system-linking.js +++ b/src/game-lib-system-linking.js @@ -203,10 +203,6 @@ GameLib.System.Linking.prototype.start = function() { }; -GameLib.System.Linking.prototype.registerDependenciesDirect = function(data) { - this.registerDependencies(data.component); -}; - GameLib.System.Linking.prototype.link = function(component, data) { for (var property in component.linkedObjects) { if (component.linkedObjects.hasOwnProperty(property)) { @@ -259,15 +255,18 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { if (!component.loaded) { /** - * This component has not fully loaded - we should resolve its dependencies later + * This component has not fully loaded - we should resolve dependencies to it later */ return false; } + /** + * Now find all the components which depend on this component + */ var parentComponents = this.dependencies[component.id]; /** - * Now find all the components which depend on this component + * If we don't have any components which depend on this component, simply return */ if (GameLib.Utils.UndefinedOrNull(parentComponents)) { @@ -278,6 +277,9 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { return false; } + /** + * Otherwise, process them all + */ parentComponents.map( function (parentComponent) { @@ -290,31 +292,32 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { /** * We record that we linked a child component to a parent component */ - if (this.resolved.indexOf(component) === -1) { - this.resolved.push(component); - } + GameLib.Utils.PushUnique(this.resolved, component); /** * First check if the dependencies have already been met */ - if (GameLib.Utils.UndefinedOrNull(parentComponent.dependencies)) { + if ( + GameLib.Utils.UndefinedOrNull(parentComponent.dependencies) || + ( + parentComponent.dependencies instanceof Array && + parentComponent.dependencies.length === 0 + ) + ) { /** * This means - a parent component instance could maybe have been delayed to be created * because the component constructor or linking system did not know at time of 'createInstance' * that it required another object to fully become active */ - if (GameLib.Utils.UndefinedOrNull(parentComponent.instance)) { + if ( + !parentComponent.loaded || + GameLib.Utils.UndefinedOrNull(parentComponent.instance) + ) { try { - parentComponent.buildIdToObject(); - - if (parentComponent.loaded) { - parentComponent.createInstance(); - } - - GameLib.Utils.PushUnique(this.resolved, parentComponent); + parentComponent.performInstanceCreation(); } catch (error) { console.error(error); @@ -326,47 +329,34 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { * It is time to 'update' this instance with this information (if any of it is relevant - depends * on the component) */ - parentComponent.updateInstance(); + // parentComponent.updateInstance(); } - return; - } - - /** - * Remove the actual dependency - */ - var index = parentComponent.dependencies.indexOf(component.id); - if (index === -1) { - // console.warn('dependency mismatch'); } else { - parentComponent.dependencies.splice(index, 1); - } - /** - * If we now managed to link the objects, and this object has no more dependencies - */ - if (parentComponent.dependencies.length === 0) { + /** + * Remove the actual dependency + */ + var index = parentComponent.dependencies.indexOf(component.id); + if (index !== -1) { + parentComponent.dependencies.splice(index, 1); + } - delete parentComponent.dependencies; - - try { - - parentComponent.buildIdToObject(); - - if (parentComponent.loaded) { - parentComponent.createInstance(); - } - - GameLib.Utils.PushUnique(this.resolved, parentComponent); - - } catch (error) { - console.error(error); + /** + * If we now managed to link the objects, and this object has no more dependencies + */ + if (parentComponent.dependencies.length === 0) { + parentComponent.performInstanceCreation(); } } }.bind(this) ); + /** + * We now linked all the components which depends on this component, to this component. Time to cleanup our + * dependencies + */ delete this.dependencies[component.id]; /** @@ -379,6 +369,9 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { } ); + /** + * If we happen to have no more dependencies - we linked a bunch of components which are ready to use + */ if (GameLib.Utils.IsEmpty(this.dependencies)) { /** @@ -396,30 +389,30 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { ); this.resolved = []; - } - /** - * And this is it - we need to check if the dependencies array contains any 'resolved' components - - * If it is - resolve the dependencies of this newly 'resolved' component - */ - this.resolved.map( - function(component) { - for (var key in this.dependencies) { - if (this.dependencies.hasOwnProperty(key)) { - if (key === component.id) { - /** - * We found a resolved component - which is a dependency for another component. - * Resolve the dependencies of this component - this is recursive and should be done carefully - */ - this.resolveDependencies(component); - } + } else { + + var keys = Object.keys(this.dependencies); + + /** + * And this is it - we need to check if the dependencies array contains any 'resolved' components - + * If it does - resolve the dependencies of this newly 'resolved' component + */ + this.resolved.map( + + function(component) { + + if (keys.indexOf(component.id) !== -1) { + /** + * We found a resolved component - which is a dependency for another component. + * Resolve the dependencies of this component - this is recursive and should be done carefully + */ + this.resolveDependencies(component); } - } - }.bind(this) - ); - - return true; + }.bind(this) + ); + } }; @@ -485,22 +478,15 @@ GameLib.System.Linking.prototype.registerDependencies = function(component) { ); if (component.dependencies.length === 0) { - - delete component.dependencies; - - component.buildIdToObject(); - - if (component.loaded) { - try { - component.createInstance(); - } catch (error) { - console.log(error); - } - } + component.performInstanceCreation(); } } }; +/** + * When a component is created, register its dependencies, and try to resolve them + * @param data + */ GameLib.System.Linking.prototype.componentCreated = function(data) { /** @@ -520,69 +506,17 @@ GameLib.System.Linking.prototype.componentCreated = function(data) { }; - -GameLib.System.Linking.prototype.imageNotFound = function(data) { - - /** - * OK - here we do not have an image. - * The right thing to do - is to simply create a MeshBasicMaterial - we completely - * ignore the dependencies - because we want to resolve them still later. - */ - - /** - * For blender files (and others) - we create Basic Material Instances - */ - var textures = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Texture); - - textures.map(function(texture){ - - /** - * data.image is a runtime image - */ - if (texture.image === data.image.id) { - - if (GameLib.Utils.UndefinedOrNull(texture.dependencies)) { - - /** - * The texture instance has already been created, we need to update the instance - */ - if (texture && texture.instance) { - texture.updateInstance(); - } - - return; - } - - /** - * Remove this image as a dependency - */ - var index = texture.dependencies.indexOf(data.image.id); - if (index !== -1) { - texture.dependencies.splice(index, 1); - } - - /** - * If all dependencies have been met - create the instance and notify other listeners. - */ - if (texture.dependencies.length === 0) { - delete texture.dependencies; - - texture.buildIdToObject(); - - if (texture.loaded) { - try { - texture.createInstance(); - this.resolveDependencies(texture); - } catch (error) { - console.error(error); - } - } - } - } - }.bind(this)); - +/** + * When you want to register dependencies directly - Component constructor does this when it knows the + * component instance cannot be created because it has a bunch of dependencies. So it tells the linking + * system about it, so the linking system can create the instance when the dependency loads or already exists + * @param data + */ +GameLib.System.Linking.prototype.registerDependenciesDirect = function(data) { + this.registerDependencies(data.component); }; + GameLib.System.Linking.prototype.imageChanged = function(data) { var materials = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Material); @@ -599,15 +533,6 @@ GameLib.System.Linking.prototype.imageChanged = function(data) { }; -GameLib.System.Linking.prototype.arrayItemAdded = function(data) { -}; - -GameLib.System.Linking.prototype.arrayItemRemoved = function(data) { -}; - -GameLib.System.Linking.prototype.instanceCreated = function(data) { -}; - GameLib.System.Linking.prototype.meshInstanceCreated = function(data) { this.resolveDependencies(data.mesh); @@ -791,6 +716,8 @@ GameLib.System.Linking.prototype.arrayItemAdded = function(data) { GameLib.System.Linking.prototype.instanceCreated = function(data) { + this.resolveDependencies(data.component); + if (data.component instanceof GameLib.D3.RaycastVehicle) { var worlds = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.PhysicsWorld);