diff --git a/src/game-lib-d3-editor.js b/src/game-lib-d3-editor.js index c70d5df..40cf5ef 100644 --- a/src/game-lib-d3-editor.js +++ b/src/game-lib-d3-editor.js @@ -482,17 +482,57 @@ GameLib.D3.Editor.prototype.setSize = function(width, height) { */ GameLib.D3.Editor.prototype.addScene = function(scene) { - if (scene instanceof GameLib.D3.Scene) { - this.scenes.push(scene); - this.buildIdToObject(); - return; + if (!scene instanceof GameLib.D3.Scene && + !scene instanceof GameLib.D3.API.Scene) { + throw new Error('Unhandled scene type : ' + scene); } - if (scene instanceof GameLib.D3.API.Scene) { - scene = new GameLib.D3.Scene(this.graphics, scene); - this.scenes.push(scene); - this.buildIdToObject(); - } + scene = new GameLib.D3.Scene(this.graphics, scene); + + this.scenes.push(scene); + + this.buildIdToObject(); + + /** + * We need to add the meshes as components of this scene to the entity 'editor' of the 'entityManager' in this. + * + * We need a notify mechanism to notify the system of new mesh components + */ + scene.meshes.map( + function(mesh){ + + /** + * Get all entities with 3D renderers and some systems + */ + var entities = this.entityManager.query( + [ + GameLib.D3.Renderer, + GameLib.System + ] + ); + + entities.map( + function(entity){ + /** + * Add all meshes to this entity + */ + entity.addComponent(mesh); + + /** + * Now we need to notify all systems of this new components + */ + var systems = entity.getComponent(GameLib.System); + + systems.map( + function(system){ + system.notify('meshes', GameLib.D3.Mesh) + }.bind(this) + ) + + }.bind(this) + ); + + }.bind(this) + ); - throw new Error('Unhandled scene type : ' + scene); }; \ No newline at end of file diff --git a/src/game-lib-entity-manager.js b/src/game-lib-entity-manager.js index b998c2e..6ece800 100644 --- a/src/game-lib-entity-manager.js +++ b/src/game-lib-entity-manager.js @@ -85,7 +85,32 @@ GameLib.EntityManager.prototype.createEntity = function(name) { }; /** - * Removes an entity + * Adds an entity to this manager + * @param entity + */ +GameLib.EntityManager.prototype.addEntity = function(entity) { + this.entities.push(entity); +}; + +/** + * Returns entity by name + * @param name + * @returns {*} + */ +GameLib.EntityManager.prototype.queryByName = function(name) { + return this.entities.reduce( + function(result, entity){ + if (entity.name === name) { + result = entity; + } + return result; + }, + null + ) +}; + +/** + * Removes an entity - do we remove all its components as well? * @param entity GameLib.D3.Entity * @returns boolean true if successful */ @@ -93,7 +118,7 @@ GameLib.EntityManager.prototype.removeEntity = function(entity) { var index = this.entities.indexOf(entity); - if (index == -1) { + if (index === -1) { console.log('failed to remove entity : ', entity); return false; } @@ -103,71 +128,122 @@ GameLib.EntityManager.prototype.removeEntity = function(entity) { }; /** - * Returns all the objects with the following components + * Returns all the entities with the following components * @param components GameLib.Component[] */ GameLib.EntityManager.prototype.query = function(components) { - var result = this.entities.reduce( - function(__queryComponents) { - return function(result, entity) { + var entities = this.entities.reduce( + function(result, entity) { - var results = __queryComponents.reduce( - - function(__entity) { - return function(componentResult, queryComponent) { - - var components = __entity.components.reduce( - function(__queryComponent) { - return function(__components, entityComponent) { - - if (__queryComponent == entityComponent.constructor) { - // arrow should point towards a window or sergej ---> - __components[entityComponent.id] = entityComponent; - } - - return __components; - - } - }(queryComponent), - {} - ); - - for (var property in components) { - if (components.hasOwnProperty(property)) { - componentResult[property] = components[property]; - } - } - - return componentResult; - } - }(entity), - {} - - ); - - for (var property in results) { - if (results.hasOwnProperty(property)) { - result[property] = results[property]; + var hasAllComponents = components.reduce( + function(componentResult, component) { + if (!entity.hasComponent(component)) { + componentResult = false; } - } - - return result; + return componentResult; + }, + true + ); + if (hasAllComponents) { + result.push(entity); } - }(components), - {} + + return result; + }, + [] ); - var array = []; + return entities; - for (var property in result) { - if (result.hasOwnProperty(property)) { - array.push(result[property]); - } - } + // var result = this.entities.reduce( + // + // function(__queryComponents) { + // + // return function(result, entity) { + // + // var results = __queryComponents.reduce( + // + // function(__entity) { + // + // return function(componentResult, queryComponent) { + // + // var components = __entity.components.reduce( + // + // function(__queryComponent) { + // + // return function(__components, entityComponent) { + // + // if (__queryComponent === entityComponent.constructor) { + // // arrow should point towards a window or sergej ---> + // __components[entityComponent.id] = entityComponent; + // } + // + // return __components; + // + // } + // }(queryComponent), + // {} + // ); + // + // for (var property in components) { + // if (components.hasOwnProperty(property)) { + // componentResult[property] = components[property]; + // } + // } + // + // return componentResult; + // } + // }(entity), + // {} + // + // ); + // + // for (var property in results) { + // if (results.hasOwnProperty(property)) { + // result[property] = results[property]; + // } + // } + // + // return result; + // + // } + // }(components), + // {} + // ); + // + // var array = []; + // + // for (var property in result) { + // if (result.hasOwnProperty(property)) { + // array.push(result[property]); + // } + // } + // + // return array; +}; - return array; +/** + * Returns all actual components of all entities that contain this component + * @param constructor + */ +GameLib.EntityManager.prototype.queryComponents = function(constructor) { + + var entities = this.query([constructor]); + + var components = entities.reduce( + function(result, entity){ + var ecs = entity.getComponent(constructor); + ecs.map(function(ec){ + result.push(ec); + }); + return result; + }, + [] + ); + + return components; }; /** diff --git a/src/game-lib-entity.js b/src/game-lib-entity.js index a1a1766..66f6053 100644 --- a/src/game-lib-entity.js +++ b/src/game-lib-entity.js @@ -102,16 +102,64 @@ GameLib.Entity.prototype.createInstance = function() { * Adds a component to this entity through the instance (should notify the entity manager instance) * @param component */ -GameLib.Entity.prototype.addComponent = function() { - - if (this.componentToCreate == GameLib.Component.COMPONENT_CUSTOM_CODE) { - var component = new GameLib.D3.CustomCode(); - } - +GameLib.Entity.prototype.addComponent = function(component) { this.components.push(component); component.parentEntity = this; }; +/** + * Returns all components of type 'constructor' + * @param constructor + */ +GameLib.Entity.prototype.getComponent = function(constructor) { + + var components = this.components.reduce( + function(result, component) { + if (component instanceof constructor) { + result.push(component); + } + return result; + }, + [] + ); + + return components; +}; + +/** + * Returns the first component or null + * @param constructor + */ +GameLib.Entity.prototype.getFirstComponent = function(constructor) { + + var components = this.getComponent(constructor); + + if (components.length > 0) { + return components[0]; + } + + return null; +}; + +/** + * Returns true when this entity has a certain component, false otherwise + * @param constructor + */ +GameLib.Entity.prototype.hasComponent = function(constructor) { + + var has = this.components.reduce( + function(result, component) { + if (component instanceof constructor) { + result = true; + } + return result; + }, + false + ); + + return has; +}; + /** * * @param component @@ -122,7 +170,7 @@ GameLib.Entity.prototype.removeComponent = function(component) { var index = this.components.indexOf(component); - if (index == -1) { + if (index === -1) { console.log('failed to remove component : ', component); return false; } diff --git a/src/game-lib-system.js b/src/game-lib-system.js index 2168fe3..011c8b0 100644 --- a/src/game-lib-system.js +++ b/src/game-lib-system.js @@ -60,7 +60,7 @@ GameLib.System.SYSTEM_TYPE_ALL = 0x7; GameLib.System.prototype.start = function() { if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { - this.driveInputObjects = this.entityManager.query([GameLib.D3.Input.Drive]); + // this.driveInputObjects = this.entityManager.query([GameLib.D3.Input.Drive]); } if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) { @@ -76,25 +76,36 @@ GameLib.System.prototype.start = function() { //this.domElement.instance.appendChild(this.domStats.instance); } - this.renderers = this.entityManager.query([GameLib.D3.Renderer]); + this.renderers = this.entityManager.queryComponents(GameLib.D3.Renderer); + this.renderers.forEach( function (renderer) { renderer.domElement.instance.appendChild(renderer.instance.domElement); }.bind(this) ); - this.viewports = this.entityManager.query([GameLib.D3.Viewport]); + this.renderEntities = this.entityManager.query( + [ + GameLib.D3.Viewport, + GameLib.D3.Scene, + GameLib.D3.Renderer, + GameLib.D3.Camera + ] + ); + } if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) { - this.pathFollowingObjects = this.entityManager.query([GameLib.D3.PathFollowing]); - this.followObjects = this.entityManager.query([GameLib.D3.Follow]); - this.meshObjects = this.entityManager.query([GameLib.D3.Mesh]); - this.lookAtObjects = this.entityManager.query([GameLib.D3.LookAt]); - this.cameraObjects = this.entityManager.query([GameLib.D3.Camera]); - this.lightObjects = this.entityManager.query([GameLib.D3.Light]); + // this.pathFollowingObjects = this.entityManager.query([GameLib.D3.PathFollowing]); + // this.followObjects = this.entityManager.query([GameLib.D3.Follow]); + // this.meshObjects = this.entityManager.query([GameLib.D3.Mesh]); + // this.lookAtObjects = this.entityManager.query([GameLib.D3.LookAt]); + // this.cameraObjects = this.entityManager.query([GameLib.D3.Camera]); + // this.lightObjects = this.entityManager.query([GameLib.D3.Light]); } + this.update(); + }; /** @@ -151,11 +162,32 @@ GameLib.System.prototype.update = function(deltaTime) { } if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) { - this.viewports.forEach( - function (viewport) { - viewport.update(deltaTime); - } - ); + + this.renderEntities.map( + + function(renderEntity) { + + var renderer = renderEntity.getFirstComponent(GameLib.D3.Renderer); + var camera = renderEntity.getFirstComponent(GameLib.D3.Camera); + var viewport = renderEntity.getFirstComponent(GameLib.D3.Viewport); + + renderer.instance.setViewport( + viewport.x, + viewport.y, + viewport.width, + viewport.height + ); + + var scenes = renderEntity.getComponent(GameLib.D3.Scene); + + scenes.map(function(scene){ + renderer.instance.render( + scene.instance, + camera.instance + ); + }); + } + ); } }; @@ -167,22 +199,23 @@ GameLib.System.prototype.update = function(deltaTime) { GameLib.System.prototype.stop = function() { if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { - this.driveInputObjects = []; + // this.driveInputObjects = []; } if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) { this.domElement.innerHTML = 'Rendering System Stopped'; - this.renderers = []; - this.viewports = []; + this.renderers = []; + this.viewports = []; + this.meshes = []; } if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) { - this.pathFollowingObjects = []; - this.followObjects = []; - this.meshObjects = []; - this.lookAtObjects = []; - this.cameraObjects = []; - this.lightObjects = []; + // this.pathFollowingObjects = []; + // this.followObjects = []; + // this.meshObjects = []; + // this.lookAtObjects = []; + // this.cameraObjects = []; + // this.lightObjects = []; } }; @@ -213,3 +246,16 @@ GameLib.System.prototype.toApiSystem = function() { GameLib.Utils.IdOrNull(this.parentEntity) ); }; + +GameLib.System.prototype.notify = function(property, constructor) { + + this[property] = this.entityManager.queryComponents(constructor); + + /** + * For meshes, we need to notify all scene objects + */ + if (constructor === GameLib.D3.Mesh) { + + } + +}; \ No newline at end of file