/** * Creates a Editor object * @param graphics R3.D3.Graphics * @param apiEditor R3.D3.API.Editor * @param onSelectionChanged * @param onSelectObject * @param onDeSelectObject * @constructor */ R3.D3.Editor = function( graphics, apiEditor, onSelectionChanged, onSelectObject, onDeSelectObject ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (R3.Utils.UndefinedOrNull(apiEditor)) { apiEditor = {}; } if (apiEditor instanceof R3.D3.Editor) { return apiEditor; } R3.D3.API.Editor.call( this, apiEditor.id, apiEditor.name, apiEditor.baseUrl, apiEditor.path, apiEditor.imageFactory, apiEditor.games, apiEditor.scenes, apiEditor.cameras, apiEditor.composers, apiEditor.viewports, apiEditor.renderers, apiEditor.renderTargets, apiEditor.systems, apiEditor.entityManager, apiEditor.allSelected, apiEditor.selectedObjects, apiEditor.parentEntity ); if (this.imageFactory instanceof R3.D3.API.ImageFactory) { this.imageFactory = new R3.D3.ImageFactory( this.graphics, this.imageFactory ); } if (this.games) { this.games = this.games.map( function (apiGame) { if (apiGame instanceof R3.D3.API.Game) { return new R3.D3.Game( this.graphics, apiGame, this.imageFactory ) } else { console.warn('game not of type API.Game'); throw new Error('game not of type API.Game'); } }.bind(this) ) } this.scenes = this.scenes.map( function (apiScene) { if (apiScene instanceof R3.D3.API.Scene) { return new R3.D3.Scene( this.graphics, apiScene, this.imageFactory, true ) } else { console.warn('apiScene not of type API.Scene'); throw new Error('apiScene not of type API.Scene'); } }.bind(this) ); this.cameras = this.cameras.map( function (apiCamera) { if (apiCamera instanceof R3.D3.API.Camera) { return new R3.D3.Camera( this.graphics, apiCamera ) } else { console.warn('apiCamera not of type API.Camera'); throw new Error('apiCamera not of type API.Camera'); } }.bind(this) ); this.composers = this.composers.map( function (apiComposer) { if (apiComposer instanceof R3.D3.API.Composer) { return new R3.D3.Composer( this.graphics, apiComposer ) } else { console.warn('apiComposer not of type API.Composer'); throw new Error('apiComposer not of type API.Composer'); } }.bind(this) ); this.viewports = this.viewports.map( function (apiViewport) { if (apiViewport instanceof R3.D3.API.Viewport) { return new R3.D3.Viewport( this.graphics, apiViewport ) } else { console.warn('apiViewport not of type API.Viewport'); throw new Error('apiViewport not of type API.Viewport'); } }.bind(this) ); this.renderers = this.renderers.map( function (apiRenderer) { if (apiRenderer instanceof R3.D3.API.Renderer) { return new R3.D3.Renderer( this.graphics, apiRenderer ) } else { console.warn('apiRenderer not of type API.Renderer'); throw new Error('apiRenderer not of type API.Renderer'); } }.bind(this) ); this.renderTargets = this.renderTargets.map( function (apiRenderTarget) { if (apiRenderTarget instanceof R3.D3.API.RenderTarget) { return new R3.D3.RenderTarget( this.graphics, apiRenderTarget ) } else { console.warn('apiRenderTarget not of type API.RenderTarget'); throw new Error('apiRenderTarget not of type API.RenderTarget'); } }.bind(this) ); this.systems = this.systems.map( function (apiSystem) { if (apiSystem instanceof R3.API.System) { return new R3.System( this.graphics, apiSystem ) } else { console.warn('apiSystem not of type API.System'); throw new Error('apiSystem not of type API.System'); } }.bind(this) ); if (this.entityManager) { if (this.entityManager instanceof R3.API.EntityManager) { this.entityManager = new R3.EntityManager( this.graphics, this.entityManager ); } else { console.warn('entityManager not of type API.EntityManager'); throw new Error('entityManager not of type API.EntityManager'); } } if (R3.Utils.UndefinedOrNull(onSelectionChanged)) { onSelectionChanged = null; } this.onSelectionChanged = onSelectionChanged; if (R3.Utils.UndefinedOrNull(onSelectObject)) { onSelectObject = null; } this.onSelectObject = onSelectObject; if (R3.Utils.UndefinedOrNull(onDeSelectObject)) { onDeSelectObject = null; } this.onDeSelectObject = onDeSelectObject; this.meshMoveMode = false; this.meshMoveXMode = false; this.meshMoveYMode = false; this.meshMoveZMode = false; this.buildIdToObject(); this.linkObjects(this.idToObject); this.instance = this.createInstance(); }; R3.D3.Editor.prototype = Object.create(R3.D3.API.Editor.prototype); R3.D3.Editor.prototype.constructor = R3.D3.Editor; /** * Creates a camera instance of 'graphics' type (only THREE for now) * @returns {THREE.Editor} */ R3.D3.Editor.prototype.createInstance = function(update) { var instance = null; if (update) { instance = this.instance; } return instance; }; /** * Updates the instance with the current state */ R3.D3.Editor.prototype.updateInstance = function() { this.instance = this.createInstance(true); }; /** * Converts a R3.D3.Editor to a new R3.D3.API.Editor * @returns {R3.D3.API.Editor} */ R3.D3.Editor.prototype.toApiObject = function() { var apiImageFactory = null; var apiGames = []; var apiScenes = []; var apiCameras = []; var apiComposers = []; var apiViewports = []; var apiRenderers = []; var apiRenderTargets = []; var apiSystems = []; var apiEntityManager = null; if (this.imageFactory instanceof R3.D3.ImageFactory) { apiImageFactory = this.imageFactory.toApiObject(); } if (this.games) { apiGames = this.games.map( function(game) { if (game instanceof R3.D3.Game) { return game.toApiObject(); } else { console.warn('game not an instance of Game'); throw new Error('game not an instance of Game'); } } ); } if (this.scenes) { apiScenes = this.scenes.map( function(scene) { if (scene instanceof R3.D3.Scene) { return scene.toApiObject(); } else { console.warn('scene not an instance of Scene'); throw new Error('scene not an instance of Scene'); } } ); } if (this.cameras) { apiCameras = this.cameras.map( function(camera) { if (camera instanceof R3.D3.Camera) { return camera.toApiObject(); } else { console.warn('camera not an instance of Camera'); throw new Error('camera not an instance of Camera'); } } ); } if (this.composers) { apiComposers = this.composers.map( function(composer) { if (composer instanceof R3.D3.Composer) { return composer.toApiObject(); } else { console.warn('composer not an instance of Composer'); throw new Error('composer not an instance of Composer'); } } ); } if (this.viewports) { apiViewports = this.viewports.map( function(viewport) { if (viewport instanceof R3.D3.Viewport) { return viewport.toApiObject(); } else { console.warn('viewport not an instance of Viewport'); throw new Error('viewport not an instance of Viewport'); } } ); } if (this.renderers) { apiRenderers = this.renderers.map( function(renderer) { if (renderer instanceof R3.D3.Renderer) { return renderer.toApiObject(); } else { console.warn('renderer not an instance of Renderer'); throw new Error('renderer not an instance of Renderer'); } } ); } if (this.renderTargets) { apiRenderTargets = this.renderTargets.map( function(renderTarget) { if (renderTarget instanceof R3.D3.RenderTarget) { return renderTarget.toApiObject(); } else { console.warn('renderTarget not an instance of RenderTarget'); throw new Error('renderTarget not an instance of RenderTarget'); } } ); } if (this.systems) { apiSystems = this.systems.map( function(system) { if (system instanceof R3.System) { return system.toApiObject(); } else { console.warn('system not an instance of System'); throw new Error('system not an instance of System'); } } ); } if (this.entityManager) { if (this.entityManager instanceof R3.EntityManager) { apiEntityManager = this.entityManager.toApiObject(); } else { console.warn('entityManager not an instance of EntityManager'); throw new Error('entityManager not an instance of EntityManager'); } } return new R3.D3.API.Editor( this.id, this.name, this.baseUrl, this.path, apiImageFactory, apiGames, apiScenes, apiCameras, apiComposers, apiViewports, apiRenderers, apiRenderTargets, apiSystems, apiEntityManager, this.allSelected, this.selectedObjects, R3.Utils.IdOrNull(this.parentEntity) ); }; /** * Converts from an Object Editor to a R3.D3.Editor * @param graphics R3.D3.Graphics * @param objectEditor Object * @returns {R3.D3.Editor} * @constructor */ R3.D3.Editor.FromObjectEditor = function(graphics, objectEditor) { var apiEditor = R3.D3.API.Editor.FromObjectEditor(objectEditor); return new R3.D3.Editor( graphics, apiEditor ); }; /** * Selects a R3 Object * @param object R3.* */ R3.D3.Editor.prototype.selectObject = function(object) { this.selectedObjects.push( new R3.D3.SelectedObject( this.graphics, object ) ); if (this.onSelectObject) { this.onSelectObject(); } }; /** * Selects a R3 Object * @param object R3.* */ R3.D3.Editor.prototype.deSelectObject = function(object) { var results = this.selectedObjects.reduce( function(results, selectedObject) { if (selectedObject.object.id == object.id) { results.removed = selectedObject; } else { results.rest.push(selectedObject); } return results; }, { removed : null, rest : [] } ); if (this.onDeSelectObject) { this.onDeSelectObject(results); } }; R3.D3.Editor.prototype.setSize = function(width, height) { this.viewports.map( function(viewport){ viewport.width = width; viewport.height = height; viewport.updateInstance(); } ); this.renderers.map( function(renderer) { renderer.setSize(width, height); } ); }; /** * Adds a scene to the Editor * @param scene R3.D3.API.Scene */ R3.D3.Editor.prototype.addScene = function(scene) { if (!scene instanceof R3.D3.Scene && !scene instanceof R3.D3.API.Scene) { throw new Error('Unhandled scene type : ' + scene); } scene = new R3.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( [ R3.D3.Renderer, R3.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.getComponents(R3.System); systems.map( function(system){ system.notify('meshes', R3.D3.Mesh) }.bind(this) ) }.bind(this) ); }.bind(this) ); };