/** * System takes care of updating all the entities (based on their component data) * @param graphics * @param apiSystem GameLib.API.System * @constructor */ GameLib.System = function( graphics, apiSystem ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (GameLib.Utils.UndefinedOrNull(apiSystem)) { apiSystem = {}; } if (apiSystem instanceof GameLib.System) { return apiSystem; } GameLib.API.System.call( this, apiSystem.id, apiSystem.name, apiSystem.systemType, apiSystem.entityManager, apiSystem.parentEntity ); if (this.entityManager instanceof GameLib.API.EntityManager) { this.entityManager = new GameLib.EntityManager( this.graphics, this.entityManager ); } this.saveCallback = null; this.loadCallback = null; }; GameLib.System.prototype = Object.create(GameLib.API.System.prototype); GameLib.System.prototype.constructor = GameLib.System; GameLib.System.SYSTEM_TYPE_NONE = 0x0; GameLib.System.SYSTEM_TYPE_RENDER = 0x1; GameLib.System.SYSTEM_TYPE_ANIMATION = 0x2; GameLib.System.SYSTEM_TYPE_INPUT = 0x4; GameLib.System.SYSTEM_TYPE_STORAGE = 0x8; GameLib.System.SYSTEM_TYPE_GUI = 0x10; GameLib.System.SYSTEM_TYPE_ALL = 0xFFFF; /** * @callback * @override */ GameLib.System.prototype.start = function() { if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { /** * Hookup all editor input capabilities */ var entities = this.entityManager.query([GameLib.D3.Input.Editor]); entities.map(function(entity){ var component = entity.getFirstComponent(GameLib.D3.Input.Editor); component.mouseDown = component.onMouseDown(entity, this.entityManager).bind(component); component.mouseMove = component.onMouseMove(entity).bind(component); component.keyDown = component.onKeyDown(entity, this.entityManager).bind(component); component.keyUp = component.onKeyUp(entity, this.entityManager).bind(component); component.domElement.instance.addEventListener('mousedown', component.mouseDown, false); component.domElement.instance.addEventListener('mousemove', component.mouseMove, false); component.domElement.instance.addEventListener('keydown', component.keyDown, false); component.domElement.instance.addEventListener('keyup', component.keyUp, false); component.controls = new THREE.EditorControls( component.camera.instance, component.domElement.instance ); /** * After our mouse 'up' editor controls would have updated our camera * instance, so we need to update our game-lib camera to reflect these * changes - we override */ component.mouseUp = function(center) { return function() { var camera = entity.getFirstComponent(GameLib.D3.Camera); camera.position.x = camera.instance.position.x; camera.position.y = camera.instance.position.y; camera.position.z = camera.instance.position.z; camera.quaternion.x = camera.instance.quaternion.x; camera.quaternion.y = camera.instance.quaternion.y; camera.quaternion.z = camera.instance.quaternion.z; camera.quaternion.w = camera.instance.quaternion.w; camera.lookAt.x = center.x; camera.lookAt.y = center.y; camera.lookAt.z = center.z; camera.lookAt.instance.copy(center); }; }(component.controls.center).bind(component); /** * Same applies to our mouse 'scroll' event */ component.mouseWheel = function() { return function() { var camera = entity.getFirstComponent(GameLib.D3.Camera); camera.position.x = camera.instance.position.x; camera.position.y = camera.instance.position.y; camera.position.z = camera.instance.position.z; }; }.bind(component); component.domElement.instance.addEventListener('mousewheel', component.mouseWheel, false); component.domElement.instance.addEventListener('mouseup', component.mouseUp, false); }.bind(this)) } if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) { this.renderEntities = this.entityManager.query( [ GameLib.D3.Viewport, GameLib.D3.Scene, GameLib.D3.Renderer, GameLib.D3.Camera ] ); this.renderEntities.map( function(entity) { var stats = entity.getFirstComponent(GameLib.D3.Stats); stats.resize(); stats.domElement.instance.parentElement.appendChild(stats.instance.dom); } ) } if (this.systemType === GameLib.System.SYSTEM_TYPE_GUI) { var guis = this.entityManager.queryComponents(GameLib.GUI); guis.map(function(gui){ gui.domElement.instance.parentElement.appendChild(gui.instance.domElement); }) } 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]); } if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) { this.subscribe( GameLib.Event.SAVE, this.save ); this.subscribe( GameLib.Event.LOAD, this.load ) } this.update(); }; /** * @callback * @override */ GameLib.System.prototype.update = function(deltaTime) { if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { // this.driveInputObjects.forEach( // function(object) { // object.update(deltaTime); // } // ); } if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) { this.pathFollowingObjects.forEach( function(object) { object.update(deltaTime); } ); this.followObjects.forEach( function(object) { object.update(deltaTime); } ); this.lookAtObjects.forEach( function(object) { object.update(deltaTime); } ); this.meshObjects.forEach( function(object) { object.updateInstance(); } ); this.cameraObjects.forEach( function(object) { object.updateInstance(); } ); this.lightObjects.forEach( function(object) { object.updateInstance(); } ); } if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) { this.renderEntities.map( function(renderEntity) { var stats = renderEntity.getFirstComponent(GameLib.D3.Stats); stats.instance.begin(); var renderer = renderEntity.getFirstComponent(GameLib.D3.Renderer); var camera = renderEntity.getFirstComponent(GameLib.D3.Camera); var viewports = renderEntity.getComponents(GameLib.D3.Viewport); var scenes = renderEntity.getComponents(GameLib.D3.Scene); if (viewports.length > 1) { renderer.instance.autoClear = false; } if (scenes.length > 1) { renderer.instance.autoClear = false; } renderer.instance.clear(); viewports.map( function(viewport){ renderer.instance.setViewport( viewport.x * renderer.width, viewport.y * renderer.height, viewport.width * renderer.width, viewport.height * renderer.height ); function renderScene(scene) { if (scene.activeCamera) { renderer.instance.render( scene.instance, scene.activeCamera.instance ); } else { renderer.instance.render( scene.instance, camera.instance ); } } if (viewport.scenes && viewport.scenes.length > 0) { viewport.scenes.map(renderScene); } else { scenes.map(renderScene); } } ); stats.instance.end(); } ); } }; /** * @callback * @override */ GameLib.System.prototype.stop = function() { if (this.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { /** * Now remove all editor input capabilities */ var entities = this.entityManager.query([GameLib.D3.Input.Editor]); entities.map(function(entity){ var component = entity.getFirstComponent(GameLib.D3.Input.Editor); component.domElement.instance.removeEventListener('mousedown', component.mouseDown, false); component.domElement.instance.removeEventListener('mousemove', component.mouseMove, false); component.domElement.instance.removeEventListener('keydown', component.keyDown, false); component.domElement.instance.removeEventListener('keyup', component.keyUp, false); component.controls.dispose(); component.domElement.instance.removeEventListener('mouseup', component.mouseUp, false); component.domElement.instance.removeEventListener('mousewheel', component.mouseWheel, false); }); console.log('stopped all input systems'); } if (this.systemType === GameLib.System.SYSTEM_TYPE_GUI) { console.log('stopping GUI system'); var guis = this.entityManager.queryComponents(GameLib.GUI); guis.map(function(gui){ gui.domElement.instance.parentElement.removeChild(gui.instance.domElement); }) } if (this.systemType === GameLib.System.SYSTEM_TYPE_RENDER) { this.renderEntities.map( function(entity) { var stats = entity.getFirstComponent(GameLib.D3.Stats); stats.domElement.instance.parentElement.removeChild(stats.instance.dom); } ); this.renderEntities = []; } if (this.systemType === GameLib.System.SYSTEM_TYPE_ANIMATION) { // this.pathFollowingObjects = []; // this.followObjects = []; // this.meshObjects = []; // this.lookAtObjects = []; // this.cameraObjects = []; // this.lightObjects = []; } if (this.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) { this.unsubscribe( GameLib.Event.SAVE, this.save ); this.unsubscribe( GameLib.Event.LOAD, this.load ) } }; /** * Converts runtime vector to API Vector * @returns {GameLib.API.System} */ GameLib.System.prototype.toApiObject = function() { return new GameLib.API.System( this.id, this.name, this.systemType, GameLib.Utils.IdOrNull(this.entityManager), GameLib.Utils.IdOrNull(this.parentEntity) ); };