From 0aa539b6cfcacfcaafdd1612be14b23a327e2f21 Mon Sep 17 00:00:00 2001 From: "Theunis J. Botha" Date: Thu, 12 Jan 2017 17:40:17 +0100 Subject: [PATCH] selected objects start --- {src => bak}/game-lib-d3-api-input-editor.bak | 0 bak/game-lib-d3-api-selected-object.js | 46 +++ {src => bak}/game-lib-d3-broadphase.js | 0 {src => bak}/game-lib-d3-engine.js | 0 {src => bak}/game-lib-d3-fly-controls.js | 0 {src => bak}/game-lib-d3-heightmap.js | 0 {src => bak}/game-lib-d3-input-editor.bak | 0 {src => bak}/game-lib-d3-input-fly.bak | 0 src/game-lib-component-a.js | 2 + src/game-lib-d3-api-graphics.js | 55 +++ src/game-lib-d3-api-helper.js | 87 +++++ src/game-lib-d3-api-input-drive.js | 2 +- src/game-lib-d3-api-input-editor.js | 47 ++- src/game-lib-d3-api-pass.js | 7 +- src/game-lib-d3-api-render-target.js | 12 +- src/game-lib-d3-bone-weight.js | 6 +- src/game-lib-d3-bone.js | 6 +- src/game-lib-d3-camera.js | 20 +- src/game-lib-d3-composer.js | 4 + src/game-lib-d3-editor.js | 58 ++- src/game-lib-d3-follow.js | 4 + src/game-lib-d3-game.js | 29 +- src/game-lib-d3-graphics.js | 91 ++++- src/game-lib-d3-helper.js | 101 +++-- src/game-lib-d3-input-drive.js | 16 +- src/game-lib-d3-input-editor.js | 344 ++++++++++++++++-- src/game-lib-d3-render-target.js | 10 +- src/game-lib-d3-selected-object.js | 41 +++ src/game-lib-d3-viewport.js | 22 +- src/game-lib-dom.js | 13 + src/game-lib-system.js | 8 +- 31 files changed, 909 insertions(+), 122 deletions(-) rename {src => bak}/game-lib-d3-api-input-editor.bak (100%) create mode 100644 bak/game-lib-d3-api-selected-object.js rename {src => bak}/game-lib-d3-broadphase.js (100%) rename {src => bak}/game-lib-d3-engine.js (100%) rename {src => bak}/game-lib-d3-fly-controls.js (100%) rename {src => bak}/game-lib-d3-heightmap.js (100%) rename {src => bak}/game-lib-d3-input-editor.bak (100%) rename {src => bak}/game-lib-d3-input-fly.bak (100%) create mode 100644 src/game-lib-d3-api-graphics.js create mode 100644 src/game-lib-d3-api-helper.js create mode 100644 src/game-lib-d3-selected-object.js create mode 100644 src/game-lib-dom.js diff --git a/src/game-lib-d3-api-input-editor.bak b/bak/game-lib-d3-api-input-editor.bak similarity index 100% rename from src/game-lib-d3-api-input-editor.bak rename to bak/game-lib-d3-api-input-editor.bak diff --git a/bak/game-lib-d3-api-selected-object.js b/bak/game-lib-d3-api-selected-object.js new file mode 100644 index 0000000..6eb9520 --- /dev/null +++ b/bak/game-lib-d3-api-selected-object.js @@ -0,0 +1,46 @@ +/** + * This component makes the parentEntity (ex. car) follow the path provided by the spline + * @param id String + * @param name String + * @param object + * @param helper + * @param lastUpdate + * @constructor + */ +GameLib.D3.API.SelectedObject = function ( + object, + helper, + lastUpdate +) { + if (GameLib.Utils.UndefinedOrNull(object)) { + console.warn('Cannot select no object'); + throw new Error('Cannot select no object'); + } + this.object = object; + + if (GameLib.Utils.UndefinedOrNull(helper)) { + helper = null; + } + this.helper = helper; + + if (GameLib.Utils.UndefinedOrNull(lastUpdate)) { + lastUpdate = Date.now(); + } + this.lastUpdate = lastUpdate; +}; + +/** + * Object to GameLib.D3.API.SelectedObject + * @param objectComponent + * @returns {GameLib.D3.API.SelectedObject} + * @constructor + */ +GameLib.D3.API.SelectedObject.FromObjectSelectedObject = function(objectComponent) { + return new GameLib.D3.API.SelectedObject( + objectComponent.id, + objectComponent.name, + objectComponent.object, + objectComponent.helper, + objectComponent.lastUpdate + ); +}; diff --git a/src/game-lib-d3-broadphase.js b/bak/game-lib-d3-broadphase.js similarity index 100% rename from src/game-lib-d3-broadphase.js rename to bak/game-lib-d3-broadphase.js diff --git a/src/game-lib-d3-engine.js b/bak/game-lib-d3-engine.js similarity index 100% rename from src/game-lib-d3-engine.js rename to bak/game-lib-d3-engine.js diff --git a/src/game-lib-d3-fly-controls.js b/bak/game-lib-d3-fly-controls.js similarity index 100% rename from src/game-lib-d3-fly-controls.js rename to bak/game-lib-d3-fly-controls.js diff --git a/src/game-lib-d3-heightmap.js b/bak/game-lib-d3-heightmap.js similarity index 100% rename from src/game-lib-d3-heightmap.js rename to bak/game-lib-d3-heightmap.js diff --git a/src/game-lib-d3-input-editor.bak b/bak/game-lib-d3-input-editor.bak similarity index 100% rename from src/game-lib-d3-input-editor.bak rename to bak/game-lib-d3-input-editor.bak diff --git a/src/game-lib-d3-input-fly.bak b/bak/game-lib-d3-input-fly.bak similarity index 100% rename from src/game-lib-d3-input-fly.bak rename to bak/game-lib-d3-input-fly.bak diff --git a/src/game-lib-component-a.js b/src/game-lib-component-a.js index 16e3ef2..4eaa86d 100644 --- a/src/game-lib-component-a.js +++ b/src/game-lib-component-a.js @@ -45,6 +45,8 @@ GameLib.Component.COMPONENT_INPUT_EDITOR = 0x11; GameLib.Component.COMPONENT_EDITOR = 0x12; GameLib.Component.COMPONENT_VIEWPORT = 0x13; GameLib.Component.COMPONENT_SYSTEM = 0x14; +GameLib.Component.COMPONENT_GRAPHICS = 0x15; +GameLib.Component.COMPONENT_HELPER = 0x16; /** * Components are linked at runtime - for storing, we just store the ID diff --git a/src/game-lib-d3-api-graphics.js b/src/game-lib-d3-api-graphics.js new file mode 100644 index 0000000..1d941a8 --- /dev/null +++ b/src/game-lib-d3-api-graphics.js @@ -0,0 +1,55 @@ +/** + * Graphics API + * @param id String + * @param name + * @param graphicsType + * @param parentEntity + * @constructor + */ +GameLib.D3.API.Graphics = function ( + id, + name, + graphicsType, + parentEntity +) { + + GameLib.Component.call( + this, + GameLib.Component.COMPONENT_GRAPHICS, + null, + null, + parentEntity + ); + + if (GameLib.Utils.UndefinedOrNull(id)) { + id = GameLib.Utils.RandomId(); + } + this.id = id; + + if (GameLib.Utils.UndefinedOrNull(name)) { + name = 'Graphics (' + id + ')'; + } + this.name = name; + + if (GameLib.Utils.UndefinedOrNull(graphicsType)) { + graphicsType = GameLib.D3.Graphics.GRAPHICS_TYPE_THREE; + } + this.graphicsType = graphicsType; +}; + +GameLib.D3.API.Graphics.prototype = Object.create(GameLib.Component.prototype); +GameLib.D3.API.Graphics.prototype.constructor = GameLib.D3.API.Graphics; + +/** + * Object to GameLib.D3.API.Graphics + * @param objectComponent + * @constructor + */ +GameLib.D3.API.Graphics.FromObjectComponent = function(objectComponent) { + return new GameLib.D3.API.Graphics( + objectComponent.id, + objectComponent.name, + objectComponent.graphicsType, + objectComponent.parentEntity + ); +}; diff --git a/src/game-lib-d3-api-helper.js b/src/game-lib-d3-api-helper.js new file mode 100644 index 0000000..9984ebb --- /dev/null +++ b/src/game-lib-d3-api-helper.js @@ -0,0 +1,87 @@ +/** + * This component renders a scene + * @param id String + * @param name String + * @param helperType + * @param object + * @param parentEntity + * @constructor + */ +GameLib.D3.API.Helper = function ( + id, + name, + helperType, + object, + parentEntity +) { + + GameLib.Component.call( + this, + GameLib.Component.COMPONENT_PASS, + null, + null, + parentEntity + ); + + if (GameLib.Utils.UndefinedOrNull(id)) { + id = GameLib.Utils.RandomId(); + } + this.id = id; + + if (GameLib.Utils.UndefinedOrNull(name)) { + name = 'Helper (' + id + ')'; + } + this.name = name; + + if (GameLib.Utils.UndefinedOrNull(object)) { + console.warn('Cannot create a helper for an Object which does not exist'); + throw new Error('Cannot create a helper for an Object which does not exist'); + } + + if (GameLib.Utils.UndefinedOrNull(helperType)) { + if ( + object instanceof GameLib.D3.Mesh && + object.meshType != GameLib.D3.Mesh.TYPE_CURVE + ) { + helperType = GameLib.D3.Helper.HELPER_TYPE_WIREFRAME; + } + + if (object instanceof GameLib.D3.Light) { + if (object.lightType == GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL) { + helperType = GameLib.D3.Helper.HELPER_TYPE_DIRECTIONAL_LIGHT; + } + + if (object.lightType == GameLib.D3.Light.LIGHT_TYPE_POINT) { + helperType = GameLib.D3.Helper.HELPER_TYPE_POINT_LIGHT; + } + + if (object.lightType == GameLib.D3.Light.LIGHT_TYPE_SPOT) { + helperType = GameLib.D3.Helper.HELPER_TYPE_SPOT_LIGHT; + } + } + + if (object instanceof GameLib.D3.Skeleton) { + helperType = GameLib.D3.Helper.HELPER_TYPE_SKELETON; + } + } + this.helperType = helperType; + +}; + +GameLib.D3.API.Helper.prototype = Object.create(GameLib.Component.prototype); +GameLib.D3.API.Helper.prototype.constructor = GameLib.D3.API.Helper; + +/** + * Object to GameLib.D3.API.Helper + * @param objectComponent + * @constructor + */ +GameLib.D3.API.Helper.FromObjectComponent = function(objectComponent) { + return new GameLib.D3.API.Helper( + objectComponent.id, + objectComponent.name, + objectComponent.helperType, + objectComponent.object, + objectComponent.parentEntity + ); +}; diff --git a/src/game-lib-d3-api-input-drive.js b/src/game-lib-d3-api-input-drive.js index fc93a3c..7eeae12 100644 --- a/src/game-lib-d3-api-input-drive.js +++ b/src/game-lib-d3-api-input-drive.js @@ -50,7 +50,7 @@ GameLib.D3.API.Input.Drive = function ( this.id = id; if (GameLib.Utils.UndefinedOrNull(name)) { - name = this.constructor.name; + name = 'Input.Drive (' + this.id + ')'; } this.name = name; diff --git a/src/game-lib-d3-api-input-editor.js b/src/game-lib-d3-api-input-editor.js index 76ece1b..731b685 100644 --- a/src/game-lib-d3-api-input-editor.js +++ b/src/game-lib-d3-api-input-editor.js @@ -2,24 +2,36 @@ * This component makes the parentEntity (ex. car) follow the path provided by the spline * @param id String * @param name String + * @param domElementId + * @param domContainerId * @param editor GameLib.D3.API.Editor * @param camera + * @param widthOffset + * @param heightOffset + * @param containerWidthOffset + * @param containerHeightOffset * @param parentEntity * @constructor */ GameLib.D3.API.Input.Editor = function ( id, name, + domElementId, + domContainerId, editor, camera, + widthOffset, + heightOffset, + containerWidthOffset, + containerHeightOffset, parentEntity ) { GameLib.Component.call( this, GameLib.Component.COMPONENT_INPUT_EDITOR, { - 'camera' : GameLib.D3.Camera, - 'editor' : GameLib.D3.Editor + 'editor' : GameLib.D3.Editor, + 'camera' : GameLib.D3.Camera }, null, parentEntity @@ -45,10 +57,35 @@ GameLib.D3.API.Input.Editor = function ( } this.domElementId = domElementId; + if (GameLib.Utils.UndefinedOrNull(domContainerId)) { + domContainerId = 'divContainer'; + } + this.domContainerId = domContainerId; + if (GameLib.Utils.UndefinedOrNull(camera)) { camera = null; } this.camera = camera; + + if (GameLib.Utils.UndefinedOrNull(widthOffset)) { + widthOffset = 400; + } + this.widthOffset = widthOffset; + + if (GameLib.Utils.UndefinedOrNull(heightOffset)) { + heightOffset = 0; + } + this.heightOffset = heightOffset; + + if (GameLib.Utils.UndefinedOrNull(containerWidthOffset)) { + containerWidthOffset = 0; + } + this.containerWidthOffset = containerWidthOffset; + + if (GameLib.Utils.UndefinedOrNull(containerHeightOffset)) { + containerHeightOffset = 80; + } + this.containerHeightOffset = containerHeightOffset; }; GameLib.D3.API.Input.Editor.prototype = Object.create(GameLib.Component.prototype); @@ -65,7 +102,13 @@ GameLib.D3.API.Input.Editor.FromObjectComponent = function(objectComponent) { objectComponent.id, objectComponent.name, objectComponent.domElementId, + objectComponent.domContainerId, + objectComponent.editor, objectComponent.camera, + objectComponent.widthOffset, + objectComponent.heightOffset, + objectComponent.containerWidthOffset, + objectComponent.containerHeightOffset, objectComponent.parentEntity ); }; diff --git a/src/game-lib-d3-api-pass.js b/src/game-lib-d3-api-pass.js index 333360c..f092e4e 100644 --- a/src/game-lib-d3-api-pass.js +++ b/src/game-lib-d3-api-pass.js @@ -36,12 +36,7 @@ GameLib.D3.API.Pass = function ( this.id = id; if (GameLib.Utils.UndefinedOrNull(name)) { - name = 'Render Pass (' + id + ')'; - } - this.name = name; - - if (GameLib.Utils.UndefinedOrNull(name)) { - name = 'Render Pass (' + id + ')'; + name = 'Pass (' + id + ')'; } this.name = name; diff --git a/src/game-lib-d3-api-render-target.js b/src/game-lib-d3-api-render-target.js index 7664359..9d2e840 100644 --- a/src/game-lib-d3-api-render-target.js +++ b/src/game-lib-d3-api-render-target.js @@ -8,6 +8,7 @@ * @param magFilter * @param format * @param stencilBuffer + * @param texture * @param parentEntity * @constructor */ @@ -20,13 +21,16 @@ GameLib.D3.API.RenderTarget = function ( magFilter, format, stencilBuffer, + texture, parentEntity ) { GameLib.Component.call( this, GameLib.Component.COMPONENT_RENDER_TARGET, - null, + { + texture : GameLib.D3.Texture + }, null, parentEntity ); @@ -71,6 +75,11 @@ GameLib.D3.API.RenderTarget = function ( } this.stencilBuffer = stencilBuffer; + if (GameLib.Utils.UndefinedOrNull(texture)) { + texture = null; + } + this.texture = texture; + }; GameLib.D3.API.RenderTarget.prototype = Object.create(GameLib.Component.prototype); @@ -91,6 +100,7 @@ GameLib.D3.API.RenderTarget.FromObjectComponent = function(objectComponent) { objectComponent.magFilter, objectComponent.format, objectComponent.stencilBuffer, + objectComponent.texture, objectComponent.parentEntity ); }; diff --git a/src/game-lib-d3-bone-weight.js b/src/game-lib-d3-bone-weight.js index 0ed77bb..3378288 100644 --- a/src/game-lib-d3-bone-weight.js +++ b/src/game-lib-d3-bone-weight.js @@ -10,7 +10,11 @@ GameLib.D3.BoneWeight = function ( ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); - + + if (GameLib.Utils.UndefinedOrNull(apiBoneWeight)) { + apiBoneWeight = {}; + } + GameLib.D3.API.BoneWeight.call( this, apiBoneWeight.boneIndex, diff --git a/src/game-lib-d3-bone.js b/src/game-lib-d3-bone.js index a5c5076..4a6bace 100644 --- a/src/game-lib-d3-bone.js +++ b/src/game-lib-d3-bone.js @@ -10,7 +10,11 @@ GameLib.D3.Bone = function ( ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); - + + if (GameLib.Utils.UndefinedOrNull(apiBone)) { + apiBone = {}; + } + GameLib.D3.API.Bone.call( this, apiBone.id, diff --git a/src/game-lib-d3-camera.js b/src/game-lib-d3-camera.js index e1f650e..2bbc078 100644 --- a/src/game-lib-d3-camera.js +++ b/src/game-lib-d3-camera.js @@ -12,6 +12,10 @@ GameLib.D3.Camera = function( this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiCamera)) { + apiCamera = {}; + } + GameLib.D3.API.Camera.call( this, apiCamera.id, @@ -112,18 +116,20 @@ GameLib.D3.Camera.prototype.createInstance = function(update) { instance.maxZ = this.maxZ; } - if (this.cameraType == GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE) { - instance.fov = this.fov; - instance.aspect = this.aspect; - instance.near = this.near; - instance.far = this.far; + if ( + this.cameraType == GameLib.D3.Camera.CAMERA_TYPE_PERSPECTIVE || + this.cameraType == GameLib.D3.Camera.CAMERA_TYPE_STEREO + ) { + instance.fov = this.fov; + instance.aspect = this.aspect; + instance.near = this.near; + instance.far = this.far; } if (this.cameraType == GameLib.D3.Camera.CAMERA_TYPE_STEREO) { instance.eyeSeparation = this.eyeSeparation; instance.focalLength = this.focalLength; - - instance.update(this.camera.instance); + instance.update(instance); } } diff --git a/src/game-lib-d3-composer.js b/src/game-lib-d3-composer.js index 9cffe20..f7925dc 100644 --- a/src/game-lib-d3-composer.js +++ b/src/game-lib-d3-composer.js @@ -12,6 +12,10 @@ GameLib.D3.Composer = function ( this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiComposer)) { + apiComposer = {}; + } + GameLib.D3.API.Composer.call( this, apiComposer.id, diff --git a/src/game-lib-d3-editor.js b/src/game-lib-d3-editor.js index 1c4f0d3..4fecbd09 100644 --- a/src/game-lib-d3-editor.js +++ b/src/game-lib-d3-editor.js @@ -6,12 +6,17 @@ */ GameLib.D3.Editor = function( graphics, - apiEditor + apiEditor, + onSelectionChange ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiEditor)) { + apiEditor = {}; + } + GameLib.D3.API.Editor.call( this, apiEditor.id, @@ -22,18 +27,43 @@ GameLib.D3.Editor = function( apiEditor.viewports, apiEditor.parentEntity ); - // - //if (GameLib.Utils.UndefinedOrNull(document)) { - // console.warn('Cannot create an Editor Object without reference to the DOM document'); - // throw new Error('Cannot create an Editor Object without reference to the DOM document'); - //} - //this.document = document; - // - //if (GameLib.Utils.UndefinedOrNull(window)) { - // console.warn('Cannot create an Editor Object without reference to the DOM window'); - // throw new Error('Cannot create an Editor Object without reference to the DOM window'); - //} - //this.window = window; + + this.games = this.games.map( + function(apiGame) { + + if (apiGame instanceof GameLib.D3.API.Game) { + return GameLib.D3.Game( + this.graphics, + apiGame + ) + } else { + console.warn('Game not of type API.Game'); + throw new Error('Game not of type API.Game'); + } + + }.bind(this) + ); + + this.viewports = this.viewports.map( + function(apiViewport) { + + if (apiViewport instanceof GameLib.D3.API.Viewport) { + return GameLib.D3.Viewport( + this.graphics, + apiViewport + ) + } else { + console.warn('Viewport not of type API.Viewport'); + throw new Error('Viewport not of type API.Viewport'); + } + + }.bind(this) + ); + + if (GameLib.Utils.UndefinedOrNull(onSelectionChange)) { + onSelectionChange = null; + } + this.onSelectionChange = onSelectionChange; this.instance = this.createInstance(); }; @@ -88,7 +118,7 @@ GameLib.D3.Editor.prototype.toApiEditor = function() { apiViewports = this.viewports.map( function(viewport) { if (viewport instanceof GameLib.D3.Viewport) { - return viewport.toApiViewport(); + return viewport.toApiComponent(); } else { console.warn('Viewport not an instance of Viewport'); throw new Error('Viewport not an instance of Viewport'); diff --git a/src/game-lib-d3-follow.js b/src/game-lib-d3-follow.js index 2af3080..249f52c 100644 --- a/src/game-lib-d3-follow.js +++ b/src/game-lib-d3-follow.js @@ -11,6 +11,10 @@ GameLib.D3.Follow = function ( this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiFollow)) { + apiFollow = {}; + } + GameLib.D3.API.Follow.call( this, apiFollow.id, diff --git a/src/game-lib-d3-game.js b/src/game-lib-d3-game.js index 4dd28ac..28e683f 100644 --- a/src/game-lib-d3-game.js +++ b/src/game-lib-d3-game.js @@ -11,7 +11,11 @@ GameLib.D3.Game = function ( this.graphics = graphics; this.graphics.isNotThreeThrow(); - + + if (GameLib.Utils.UndefinedOrNull(apiGame)) { + apiGame = {}; + } + GameLib.D3.API.Game.call( this, apiGame.id, @@ -182,6 +186,29 @@ GameLib.D3.Game.prototype.createInstance = function(update) { return instance; }; +GameLib.D3.Game.prototype.setSize = function(width, height) { + + // var w = 0; + // var h = 0; + + this.viewports.map( + function(viewport) { + // w = viewport.width; + // h = viewport.height; + // + // //TODO : calculate width and height decrease or increase ratio and adjust viewport x and y offset according + // var wx = width / w; + // var hx = height / h; + + viewport.width = width; + viewport.height = height; + + viewport.updateInstance(); + } + ) + +}; + /** * Updates the instance with the current state */ diff --git a/src/game-lib-d3-graphics.js b/src/game-lib-d3-graphics.js index 578a410..731df4d 100644 --- a/src/game-lib-d3-graphics.js +++ b/src/game-lib-d3-graphics.js @@ -1,15 +1,88 @@ /** * Graphics Superset - * @param graphicsType - * @param instance {THREE} + * @param apiGraphics * @constructor */ GameLib.D3.Graphics = function Graphics( - graphicsType, - instance + apiGraphics ) { - this.graphicsType = graphicsType; - this.instance = instance; + + if (GameLib.Utils.UndefinedOrNull(apiGraphics)) { + apiGraphics = {}; + } + + GameLib.D3.API.Graphics.call( + this, + apiGraphics.id, + apiGraphics.name, + apiGraphics.graphicsType, + apiGraphics.parentEntity + ); + + this.instance = this.createInstance(); +}; + +GameLib.D3.Graphics.prototype = Object.create(GameLib.D3.API.Graphics.prototype); +GameLib.D3.Graphics.prototype.constructor = GameLib.D3.Graphics; + +/** + * GameLib.D3.Graphics Types + * @type {number} + */ +GameLib.D3.Graphics.GRAPHICS_TYPE_THREE = 0x1; + +/** + * @returns {THREE.Graphics} + */ +GameLib.D3.Graphics.prototype.createInstance = function(update) { + + var instance = null; + + if (update) { + instance = this.instance; + } else { + instance = THREE; + } + + return instance; +}; + +/** + * Updates the instance with the current state + */ +GameLib.D3.Graphics.prototype.updateInstance = function() { + this.instance = this.createInstance(true); +}; + +/** + * Converts a GameLib.D3.Graphics to a new GameLib.D3.API.Graphics + * @returns {GameLib.D3.API.Graphics} + */ +GameLib.D3.Graphics.prototype.toApiGraphics = function() { + return new GameLib.D3.API.Graphics( + this.id, + this.name, + this.graphicsType, + this.parentEntity + ); +}; + +/** + * Converts from an Object Graphics to a GameLib.D3.Graphics + * @param graphics GameLib.D3.Graphics + * @param objectGraphics Object + * @returns {GameLib.D3.Graphics} + * @constructor + */ +GameLib.D3.Graphics.FromObjectGraphics = function(graphics, objectGraphics) { + + var apiGraphics = GameLib.D3.API.Graphics.FromObjectComponent(objectGraphics); + + return new GameLib.D3.Graphics( + graphics, + apiGraphics + ); + }; /** @@ -29,9 +102,3 @@ GameLib.D3.Graphics.prototype.isNotThreeThrow = function() { throw new Error('Only THREE supported for this function'); } }; - -/** - * Physics GameLib.D3.Graphics Types - * @type {number} - */ -GameLib.D3.Graphics.GRAPHICS_TYPE_THREE = 0x1; \ No newline at end of file diff --git a/src/game-lib-d3-helper.js b/src/game-lib-d3-helper.js index 578386a..ad1ecaa 100644 --- a/src/game-lib-d3-helper.js +++ b/src/game-lib-d3-helper.js @@ -1,45 +1,35 @@ /** * Helpers for displaying outlines or making 'invisible' scene objects visible - * @param id - * @param object GameLib.D3.Object - * @param name - * @param graphics - * @param helperType + * @param graphics GameLib.D3.Graphics + * @param apiHelper GameLib.D3.API.Helper * @constructor */ GameLib.D3.Helper = function Helper( - id, - object, - helperType, - name, - graphics + graphics, + apiHelper ) { - if (GameLib.Utils.UndefinedOrNull(id)) { - id = GameLib.Utils.RandomId(); - } - this.id = id; - - if (GameLib.Utils.UndefinedOrNull(object)) { - throw new Error('Cannot create helpers for unknown objects'); - } - this.object = object; - - if (GameLib.Utils.UndefinedOrNull(helperType)) { - helperType = GameLib.D3.Helper.HELPER_TYPE_EDGES; - } - this.helperType = helperType; - - if (GameLib.Utils.UndefinedOrNull(name)) { - name = 'Helper (' + this.helperType + ')'; - } - this.name = name; - this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiHelper)) { + apiHelper = {}; + } + + GameLib.D3.API.Helper.call( + this, + apiHelper.id, + apiHelper.name, + apiHelper.helperType, + apiHelper.object, + apiHelper.parentEntity + ); + this.instance = this.createInstance(); }; +GameLib.D3.Helper.prototype = Object.create(GameLib.D3.API.Helper.prototype); +GameLib.D3.Helper.prototype.constructor = GameLib.D3.Helper; + /** * Helper types * @type {string} @@ -60,6 +50,10 @@ GameLib.D3.Helper.prototype.createInstance = function(update) { var instance = null; + if (update) { + instance = this.instance; + } + if (this.helperType == GameLib.D3.Helper.HELPER_TYPE_EDGES) { instance = new THREE.WireframeHelper(this.object.instance, 0x007700); } @@ -81,16 +75,53 @@ GameLib.D3.Helper.prototype.createInstance = function(update) { } if (this.helperType == GameLib.D3.Helper.HELPER_TYPE_SKELETON) { - instance = new THREE.SkeletonHelper(this.object.skeleton.instance); + instance = new THREE.SkeletonHelper(this.object.instance); } if (!instance) { throw new Error('Unsupported helper type: ' + this.helperType); } - if (update) { - this.instance = instance; - } - return instance; }; + +/** + * Updates the instance with the current state + */ +GameLib.D3.Helper.prototype.updateInstance = function() { + this.instance = this.createInstance(true); +}; + +/** + * Converts a GameLib.D3.Helper to a new GameLib.D3.API.Helper + * @returns {GameLib.D3.API.Helper} + */ +GameLib.D3.Helper.prototype.toApiHelper = function() { + + return new GameLib.D3.API.Helper( + this.id, + this.name, + this.helperType, + GameLib.Utils.IdOrNull(this.object), + GameLib.Utils.IdOrNull(this.parentEntity) + ); + +}; + +/** + * Converts from an Object Helper to a GameLib.D3.Helper + * @param graphics GameLib.D3.Graphics + * @param objectHelper Object + * @returns {GameLib.D3.Helper} + * @constructor + */ +GameLib.D3.Helper.FromObjectHelper = function(graphics, objectHelper) { + + var apiHelper = GameLib.D3.API.Helper.FromObjectHelper(objectHelper); + + return new GameLib.D3.Helper( + graphics, + apiHelper + ); + +}; diff --git a/src/game-lib-d3-input-drive.js b/src/game-lib-d3-input-drive.js index 619acab..dde8548 100644 --- a/src/game-lib-d3-input-drive.js +++ b/src/game-lib-d3-input-drive.js @@ -2,16 +2,22 @@ * Input parent class * @param graphics GameLib.D3.Graphics * @param apiInputDrive GameLib.D3.API.Input.Drive + * @param dom GameLib.Dom * @constructor */ GameLib.D3.Input.Drive = function ( graphics, - apiInputDrive + apiInputDrive, + dom ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiInputDrive)) { + apiInputDrive = {}; + } + GameLib.D3.API.Input.Drive.call( this, apiInputDrive.id, @@ -29,6 +35,12 @@ GameLib.D3.Input.Drive = function ( apiInputDrive.rotationFactor ); + if (GameLib.Utils.UndefinedOrNull(dom)) { + console.warn('Cannot create Input without an handle to the DOM'); + throw new Error('Cannot create Input without an handle to the DOM'); + } + this.dom = dom; + this.keyLeft = false; this.keyRight = false; @@ -45,7 +57,7 @@ GameLib.D3.Input.Drive.prototype.createInstance = function(update) { return this.instance; } - var instance = document.getElementById(this.domElementId); + var instance = this.dom.document.getElementById(this.domElementId); instance.addEventListener( 'keydown', diff --git a/src/game-lib-d3-input-editor.js b/src/game-lib-d3-input-editor.js index 426787c..8a2a5dc 100644 --- a/src/game-lib-d3-input-editor.js +++ b/src/game-lib-d3-input-editor.js @@ -2,24 +2,56 @@ * Input parent class * @param graphics GameLib.D3.Graphics * @param apiInputEditor GameLib.D3.API.Input.Editor + * @param dom GameLib.DOM * @constructor */ GameLib.D3.Input.Editor = function ( graphics, - apiInputEditor + apiInputEditor, + dom ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); + if (GameLib.Utils.UndefinedOrNull(apiInputEditor)) { + apiInputEditor = {}; + } + GameLib.D3.API.Input.Editor.call( this, apiInputEditor.id, apiInputEditor.name, + apiInputEditor.domElementId, + apiInputEditor.domContainerId, + apiInputEditor.editor, apiInputEditor.camera, + apiInputEditor.widthOffset, + apiInputEditor.heightOffset, + apiInputEditor.containerWidthOffset, + apiInputEditor.containerHeightOffset, apiInputEditor.parentEntity ); + if (GameLib.Utils.UndefinedOrNull(dom)) { + console.warn('Cannot create Input without an handle to the DOM'); + throw new Error('Cannot create Input without an handle to the DOM'); + } + this.dom = dom; + + this.element = null; + this.container = null; + + /** + * We need new function pointers with scope bound to this so we can remove the + * window event handlers when we need to + * @type {function()} + */ + this.resize = this.onWindowResize.bind(this); + this.mouseMove = this.onMouseMove.bind(this); + this.mouseDown = this.onMouseDown.bind(this); + this.keyPress = this.onKeyPress.bind(this); + this.contextMenu = this.onContextMenu.bind(this); this.instance = this.createInstance(); }; @@ -29,36 +61,58 @@ GameLib.D3.Input.Editor.prototype.constructor = GameLib.D3.Input.Editor; GameLib.D3.Input.Editor.prototype.createInstance = function(update) { + var instance = null; + if (update) { - return this.instance; + instance = this.instance; + return instance; } - var instance = document.getElementById(this.domElementId); + instance = this.dom.document.getElementById(this.domElementId); - this.resize = this.onWindowResize.bind(this); + if (!instance) { + console.warn('Could not locate DOM element with ID: ' + this.domElementId); + throw new Error('Could not locate DOM element with ID: ' + this.domElementId); + } - window.addEventListener('resize', this.resize, false ); + this.element = instance; - // this.clearScene(); - this.boundMouseMove = this.mouseMove.bind(this); + this.container = this.dom.document.getElementById(this.domContainerId); - instance.addEventListener('contextmenu', function(event){ + if (!this.container) { + console.warn('Could not locate DOM container with ID: ' + this.domContainerId); + throw new Error('Could not locate DOM container with ID: ' + this.domContainerId); + } - if (event.stopPropagation) { - event.stopPropagation(); - } + instance.addEventListener( + 'mousemove', + this.mouseMove, + false + ); - if (event.preventDefault) { - event.preventDefault(); - } + instance.addEventListener( + 'contextmenu', + this.contextMenu, + false + ); - event.cancelBubble = true; - return false; - }, false); + instance.addEventListener( + 'mousedown', + this.mouseDown, + false + ); - instance.addEventListener('mousedown', this.mouseDown.bind(this), false); - instance.addEventListener('keydown', this.keypress.bind(this), false); - instance.addEventListener('mousemove', this.boundMouseMove, false); + instance.addEventListener( + 'keydown', + this.keyPress, + false + ); + + this.dom.window.addEventListener( + 'resize', + this.resize, + false + ); return instance; }; @@ -77,16 +131,9 @@ GameLib.D3.Input.Editor.prototype.toApiComponent = function() { this.id, this.name, this.domElementId, - GameLib.Utils.IdOrNull(this.pathFollowingComponent), - GameLib.Utils.IdOrNull(this.parentEntity), - GameLib.Utils.IdOrNull(this.wheelFL), - GameLib.Utils.IdOrNull(this.wheelFR), - GameLib.Utils.IdOrNull(this.wheelRL), - GameLib.Utils.IdOrNull(this.wheelRR), - this.heightOffset, - this.distance, - this.distanceGrain, - this.rotationFactor + GameLib.Utils.IdOrNull(this.editor), + GameLib.Utils.IdOrNull(this.camera), + GameLib.Utils.IdOrNull(this.parentEntity) ); return apiInputEditor; @@ -102,6 +149,243 @@ GameLib.D3.Input.Editor.FromObjectComponent = function(graphics, objectComponent ); }; +GameLib.D3.Input.Editor.prototype.onWindowResize = function() { + + this.container.style.height = (this.window.innerHeight - this.containerHeightOffset) + 'px'; + this.container.style.width = (this.window.innerWidth - this.containerWidthOffset) + 'px'; + + this.games.map( + function(width, height) { + return function(game) { + game.width = width; + game.height = height; + game.updateInstance(); + } + }(this.window.innerWidth - this.widthOffset, this.window.innerHeight - this.heightOffset) + ); + // + // this.scene.cameras[this.scene.activeCameraIndex].aspect = () / window.innerHeight; + // this.scene.cameras[this.scene.activeCameraIndex].updateInstance(); + // + // this.scene.renderers[this.scene.activeRendererIndex].width = window.innerWidth - 400; + // this.scene.renderers[this.scene.activeRendererIndex].height = window.innerHeight; + // this.scene.renderers[this.scene.activeRendererIndex].updateInstance(); +}; + +/** + * Keypress events + * @param event + */ +GameLib.D3.Input.Editor.prototype.onKeyPress = function(event) { + + if (event.code == "KeyQ") { + + this.editor.allSelected = !this.editor.allSelected; + + if (this.editor.allSelected) { + + this.editor.games.map( + function(game) { + + for (var property in game.idToObject) { + if (game.idToObject.hasOwnProperty(property)) { + this.editor.selectedObjects.push( + new GameLib.D3.SelectedObject( + this.graphics, + game.idToObject(property) + ) + ) + } + } + + }.bind(this) + ); + + } else { + this.editor.selectedObjects = []; + } + + if (this.editor.onSelectionChange) { + this.editor.onSelectionChange(this.editor); + } + } + + if (event.code == 'KeyG') { + if (!this.meshMoveMode) { + console.log('move mode'); + this.meshMoveMode = true; + } + } + + if (event.code == 'KeyX') { + if (this.meshMoveMode) { + console.log('move along x'); + this.meshMoveXMode = true; + this.meshMoveYMode = false; + this.meshMoveZMode = false; + } + } + + if (event.code == 'KeyY') { + if (this.meshMoveMode) { + console.log('move along y'); + this.meshMoveXMode = false; + this.meshMoveYMode = true; + this.meshMoveZMode = false; + } + } + + if (event.code == 'KeyZ') { + if (this.meshMoveMode) { + console.log('move along z'); + this.meshMoveXMode = false; + this.meshMoveYMode = false; + this.meshMoveZMode = true; + } + } + + if (event.code == 'Escape') { + if (this.meshMoveMode) { + this.meshMoveMode = false; + console.log('TODO: implement restore positions'); + } + } + + if (event.code == 'Enter') { + if (this.meshMoveMode) { + this.meshMoveMode = false; + console.log('TODO: implement apply positions'); + } + } +}; + +/** + * Mouse click events + * @param event + * @returns {boolean} + */ +GameLib.D3.Input.Editor.prototype.onMouseDown = function(event) { + + if (event.button == 2) { + + event.cancelBubble = true; + + event.preventDefault(); + + if (event.stopPropagation) { + event.stopPropagation(); + } + + var meshInstances = []; + + for (var m = 0; m < this.scene.meshes.length; m++) { + meshInstances.push(this.scene.meshes[m].instance); + } + + var intersects = this.scene.raycaster.instance.intersectObjects(meshInstances); + + if (intersects.length > 0) { + + var index = -1; + + for (var s = 0; s < this.selectedObjects.length; s++) { + if (this.selectedObjects[s].object.instance == intersects[0].object) { + index = s; + break; + } + } + + if (index == -1) { + /** + * The object is not selected, select it + */ + this.selectObject(intersects[0].object.gameLibObject); + + this.buildSelectedObjects(); + + this.buildGUI(); + + } else { + /** + * De-select the objec + */ + var delta = Date.now() - this.selectedObjects[index].lastUpdate; + if (delta > 300) { + + this.unselectObject(intersects[0].object.gameLibObject); + + this.buildSelectedObjects(); + + this.buildGUI(); + } + } + } + + return false; + } + + if (event.button == 0) { + if (this.meshMoveMode) { + this.meshMoveMode = false; + this.meshMoveXMode = false; + this.meshMoveYMode = false; + this.meshMoveZMode = false; + } + } +}; + +/** + * Mouse move events + * @param event + */ +GameLib.D3.Input.Editor.prototype.onMouseMove = function(event) { + var clientX = event.clientX - 400; + + this.scene.mouse.x = ((clientX/ (window.innerWidth - 400))) * 2 - 1; + this.scene.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; + + this.scene.raycaster.instance.setFromCamera( + this.scene.mouse, + this.scene.cameras[this.scene.activeCameraIndex].instance + ); + + if (this.meshMoveMode) { + + var units = event.movementY; + + if (this.meshMoveXMode) { + this.moveSelectedObjects('x', units); + } + + if (this.meshMoveYMode) { + this.moveSelectedObjects('y', units); + } + + if (this.meshMoveZMode) { + this.moveSelectedObjects('z', units); + } + } +}; + +/** + * Prevent Context Menu creation + * @param event + * @returns {boolean} + */ +GameLib.D3.Input.Editor.prototype.onContextMenu = function(event){ + + if (event.stopPropagation) { + event.stopPropagation(); + } + + if (event.preventDefault) { + event.preventDefault(); + } + + event.cancelBubble = true; + return false; +}; + GameLib.D3.Input.Editor.prototype.update = function(deltaTime) { if (this.pathFollowingComponent) { diff --git a/src/game-lib-d3-render-target.js b/src/game-lib-d3-render-target.js index b708f3c..43562f2 100644 --- a/src/game-lib-d3-render-target.js +++ b/src/game-lib-d3-render-target.js @@ -21,7 +21,8 @@ GameLib.D3.RenderTarget = function ( apiRenderTarget.minFilter, apiRenderTarget.magFilter, apiRenderTarget.format, - apiRenderTarget.stencilBuffer + apiRenderTarget.stencilBuffer, + apiRenderTarget.texture ); this.instance = this.createInstance(); @@ -55,6 +56,8 @@ GameLib.D3.RenderTarget.prototype.createInstance = function(update) { instance.magFilter = this.magFilter; instance.format = this.format; instance.stencilBuffer = this.stencilBuffer; + instance.texture = this.texture.instance; + instance.texture.needsUpdate = true; } else { instance = new THREE.WebGLRenderTarget( this.width, @@ -66,6 +69,10 @@ GameLib.D3.RenderTarget.prototype.createInstance = function(update) { stencilBuffer : this.stencilBuffer } ); + + if (this.texture instanceof GameLib.D3.Texture && this.texture.instance) { + instance.texture = this.texture.instance; + } } return instance; @@ -93,6 +100,7 @@ GameLib.D3.RenderTarget.prototype.toApiComponent = function() { this.magFilter, this.format, this.stencilBuffer, + GameLib.Utils.IdOrNull(this.texture), GameLib.Utils.IdOrNull(this.parentEntity) ); diff --git a/src/game-lib-d3-selected-object.js b/src/game-lib-d3-selected-object.js new file mode 100644 index 0000000..f430675 --- /dev/null +++ b/src/game-lib-d3-selected-object.js @@ -0,0 +1,41 @@ +/** + * Selected Objects + * @param graphics GameLib.D3.Graphics + * @param object + * @param helper + * @param lastUpdate + * @constructor + */ +GameLib.D3.SelectedObject = function SelectedObject( + graphics, + object, + helper, + lastUpdate +) { + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + if (GameLib.Utils.UndefinedOrNull(object)) { + console.warn('Cannot select no object'); + throw new Error('Cannot select no object'); + } + this.object = object; + + if (GameLib.Utils.UndefinedOrNull(helper)) { + helper = new GameLib.D3.Helper( + graphics, + new GameLib.D3.API.Helper( + null, + null, + null, + object + ) + ); + } + this.helper = helper; + + if (GameLib.Utils.UndefinedOrNull(lastUpdate)) { + lastUpdate = Date.now(); + } + this.lastUpdate = lastUpdate; +}; diff --git a/src/game-lib-d3-viewport.js b/src/game-lib-d3-viewport.js index ed79742..af14f39 100644 --- a/src/game-lib-d3-viewport.js +++ b/src/game-lib-d3-viewport.js @@ -74,8 +74,8 @@ GameLib.D3.Viewport.prototype.createInstance = function(update) { } if (this.renderer) { - this.renderer.width = this.width; - this.renderer.height = this.height; + this.renderer.width = this.width - this.x; + this.renderer.height = this.height - this.y; this.renderer.updateInstance(); this.renderer.instance.setViewport( @@ -85,8 +85,8 @@ GameLib.D3.Viewport.prototype.createInstance = function(update) { this.height ); } else if (this.composer) { - this.composer.renderer.width = this.width; - this.composer.renderer.height = this.height; + this.composer.renderer.width = this.width - this.x; + this.composer.renderer.height = this.height - this.y; this.composer.renderer.updateInstance(); this.composer.renderer.instance.setViewport( @@ -94,9 +94,23 @@ GameLib.D3.Viewport.prototype.createInstance = function(update) { this.y, this.width, this.height + ); + + this.composer.passes.map( + function(pass) { + if (pass.camera instanceof GameLib.D3.Camera) { + pass.camera.aspect = (this.width - this.x) / (this.height / this.y); + pass.camera.updateInstance(); + } + }.bind(this) ) } + if (this.camera) { + this.camera.aspect = (this.width - this.x) / (this.height / this.y); + this.camera.updateInstance(); + } + return instance; }; diff --git a/src/game-lib-dom.js b/src/game-lib-dom.js new file mode 100644 index 0000000..913360c --- /dev/null +++ b/src/game-lib-dom.js @@ -0,0 +1,13 @@ +/** + * Runtime Dom + * @constructor + * @param document DOM Document + * @param window DOM Window + */ +GameLib.Dom = function( + document, + window +) { + this.document = document; + this.window = window; +}; diff --git a/src/game-lib-system.js b/src/game-lib-system.js index 95abf45..d9cae52 100644 --- a/src/game-lib-system.js +++ b/src/game-lib-system.js @@ -35,10 +35,10 @@ GameLib.System = function( GameLib.System.prototype = Object.create(GameLib.API.System.prototype); GameLib.System.prototype.constructor = GameLib.System; -GameLib.System.SYSTEM_TYPE_RENDER = 0x1; -GameLib.System.SYSTEM_TYPE_ANIMATION = 0x2; -GameLib.System.SYSTEM_TYPE_INPUT = 0x3; -GameLib.System.SYSTEM_TYPE_ALL = 0x4; +GameLib.System.SYSTEM_TYPE_RENDER = 0x1; +GameLib.System.SYSTEM_TYPE_ANIMATION = 0x2; +GameLib.System.SYSTEM_TYPE_INPUT = 0x4; +GameLib.System.SYSTEM_TYPE_ALL = 0x7; /** * @callback