From def400d3855748c440fb86a9077c9ca614b2696e Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Tue, 22 Aug 2017 19:18:14 +0200 Subject: [PATCH] move to faster buffergeometries - blender upload working again - gui starts to support multiple selections again --- package.json | 2 +- src/game-lib-a-component-a.js | 3 +- src/game-lib-api-vector2.js | 4 + src/game-lib-api-vector3.js | 4 + src/game-lib-api-vector4.js | 4 + src/game-lib-d3-api-light.js | 19 +- src/game-lib-d3-api-material.js | 12 +- src/game-lib-d3-helper.js | 5 +- src/game-lib-d3-image.js | 7 +- src/game-lib-d3-input-editor.js | 149 ++++++----- src/game-lib-d3-material.js | 32 +-- src/game-lib-d3-mesh-0.js | 430 +++++++++++++++++++++----------- src/game-lib-d3-raycaster.js | 65 ++--- src/game-lib-d3-texture.js | 50 ++-- src/game-lib-gui.js | 232 ++++------------- src/game-lib-system-gui.js | 428 +++++++++++++++++++++++++------ src/game-lib-system-linking.js | 106 ++++++-- 17 files changed, 994 insertions(+), 558 deletions(-) diff --git a/package.json b/package.json index e6eab7a..bbd24b3 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "lodash": "^4.17.2", "npm": "^4.0.2", "q": "^1.4.1", - "three": "^0.84.0", + "three": "*", "through2": "^2.0.1" }, "repository": "https://github.com/ToywheelDev/game-lib.git", diff --git a/src/game-lib-a-component-a.js b/src/game-lib-a-component-a.js index a5d36ab..c3cae1e 100644 --- a/src/game-lib-a-component-a.js +++ b/src/game-lib-a-component-a.js @@ -38,7 +38,8 @@ GameLib.Component = function( ); if (this.dependencies.length === 0) { - delete this.dependencies; + + delete this.dependencies; this.instance = this.createInstance(); diff --git a/src/game-lib-api-vector2.js b/src/game-lib-api-vector2.js index 0aa316e..c1a3093 100644 --- a/src/game-lib-api-vector2.js +++ b/src/game-lib-api-vector2.js @@ -19,6 +19,10 @@ GameLib.API.Vector2.prototype.copy = function () { ); }; +GameLib.API.Vector2.prototype.equals = function (v) { + return this.x === v.x && this.y === v.y; +}; + /** * Returns an API vector from an Object vector * @param objectVector diff --git a/src/game-lib-api-vector3.js b/src/game-lib-api-vector3.js index 5a8beca..b23429f 100644 --- a/src/game-lib-api-vector3.js +++ b/src/game-lib-api-vector3.js @@ -40,6 +40,10 @@ GameLib.API.Vector3.prototype.sub = function (v) { ); }; +GameLib.API.Vector3.prototype.equals = function (v) { + return this.x === v.x && this.y === v.y && this.z === v.z; +}; + GameLib.API.Vector3.prototype.cross = function (v) { return new GameLib.API.Vector3( this.y * v.z - this.z * v.y, diff --git a/src/game-lib-api-vector4.js b/src/game-lib-api-vector4.js index c68bca1..f5b59ad 100644 --- a/src/game-lib-api-vector4.js +++ b/src/game-lib-api-vector4.js @@ -21,6 +21,10 @@ GameLib.API.Vector4 = function (x, y, z, w) { this.w = w; }; +GameLib.API.Vector4.prototype.equals = function (v) { + return this.x === v.x && this.y === v.y && this.z === v.z && this.w === v.w; +}; + /** * Returns an API vector from an Object vector * @param objectVector diff --git a/src/game-lib-d3-api-light.js b/src/game-lib-d3-api-light.js index eee33fc..ffa48c1 100644 --- a/src/game-lib-d3-api-light.js +++ b/src/game-lib-d3-api-light.js @@ -49,7 +49,24 @@ GameLib.D3.API.Light = function( this.lightType = lightType; if (GameLib.Utils.UndefinedOrNull(name)) { - name = 'Light (' + id + ')'; + + if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_AMBIENT) { + name = 'Ambient '; + } + + if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL) { + name = 'Directional '; + } + + if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_POINT) { + name = 'Point '; + } + + if (this.lightType === GameLib.D3.Light.LIGHT_TYPE_SPOT) { + name = 'Spot '; + } + + name += 'Light (' + id + ')'; } this.name = name; diff --git a/src/game-lib-d3-api-material.js b/src/game-lib-d3-api-material.js index f367d62..5a156d4 100644 --- a/src/game-lib-d3-api-material.js +++ b/src/game-lib-d3-api-material.js @@ -45,7 +45,7 @@ * @param clipShadows * @param visible * @param overdraw - * @param shading + * @param flatShading * @param bumpScale * @param normalScale * @param displacementScale @@ -117,7 +117,7 @@ GameLib.D3.API.Material = function( clipShadows, visible, overdraw, - shading, + flatShading, bumpScale, normalScale, displacementScale, @@ -368,10 +368,10 @@ GameLib.D3.API.Material = function( } this.visible = visible; - if (GameLib.Utils.UndefinedOrNull(shading)) { - shading = GameLib.D3.Material.TYPE_FLAT_SHADING; + if (GameLib.Utils.UndefinedOrNull(flatShading)) { + flatShading = false; } - this.shading = shading; + this.flatShading = flatShading; if (GameLib.Utils.UndefinedOrNull(bumpScale)) { bumpScale = 1; @@ -608,7 +608,7 @@ GameLib.D3.API.Material.FromObject = function(objectMaterial) { objectMaterial.clipShadows, objectMaterial.visible, objectMaterial.overdraw, - objectMaterial.shading, + objectMaterial.flatShading, objectMaterial.bumpScale, objectMaterial.normalScale, objectMaterial.displacementScale, diff --git a/src/game-lib-d3-helper.js b/src/game-lib-d3-helper.js index e16d58c..b587af9 100644 --- a/src/game-lib-d3-helper.js +++ b/src/game-lib-d3-helper.js @@ -100,8 +100,9 @@ GameLib.D3.Helper.prototype.createInstance = function() { var instance = null; if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_EDGES) { - instance = new THREE.EdgesHelper(this.object.instance, 0x00FF00); - } + var edges = new THREE.EdgesGeometry(this.object.instance.geometry); + instance = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({color:0x00ff00, linewidth:2})) + } if (this.helperType === GameLib.D3.Helper.HELPER_TYPE_DIRECTIONAL_LIGHT) { instance = new THREE.DirectionalLightHelper(this.object.instance); diff --git a/src/game-lib-d3-image.js b/src/game-lib-d3-image.js index 3c7a89e..77b437d 100644 --- a/src/game-lib-d3-image.js +++ b/src/game-lib-d3-image.js @@ -42,11 +42,14 @@ GameLib.D3.Image.prototype = Object.create(GameLib.D3.API.Image.prototype); GameLib.D3.Image.prototype.constructor = GameLib.D3.Image; /** - * Creates a light instance + * Creates an image instance * @returns {*} */ GameLib.D3.Image.prototype.createInstance = function() { - return null; + + console.log('image create instance'); + + return null; }; /** diff --git a/src/game-lib-d3-input-editor.js b/src/game-lib-d3-input-editor.js index cc82575..fe1962e 100644 --- a/src/game-lib-d3-input-editor.js +++ b/src/game-lib-d3-input-editor.js @@ -58,6 +58,8 @@ GameLib.D3.Input.Editor = function ( this.mouseUp = null; this.mouseWheel = null; + this.selectAll = false; + this.controlLeft = false; this.raycaster = new GameLib.D3.Raycaster( @@ -123,11 +125,14 @@ GameLib.D3.Input.Editor.FromObject = function(graphics, objectComponent) { GameLib.D3.Input.Editor.prototype.onKeyDown = function(entity, entityManager) { return function(event) { + console.log('entity ' + entity.name + ' emitted keypress ' + event.code); + var meshes = null; + if (event.code === 'Delete') { - var meshes = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Mesh]); + meshes = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Mesh]); var deletedMeshes = []; @@ -161,6 +166,22 @@ GameLib.D3.Input.Editor.prototype.onKeyDown = function(entity, entityManager) { this.controlLeft = true; } + if (event.code === 'KeyA') { + + this.selectAll = !this.selectAll; + + meshes = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Mesh]); + + meshes.map(function(mesh){ + if (this.selectAll) { + this.selectMesh(mesh); + } else { + this.deSelectMesh(mesh); + } + }.bind(this)) + + } + // BELOW is just a test to stop systems from keypress - it works nicely :) // but of course, when the system is stopped it can no longer be started by keypress // var inputSystem = entity.getComponents(GameLib.System).reduce( @@ -234,9 +255,9 @@ GameLib.D3.Input.Editor.prototype.onMouseWheel = function(entity) { }; }; -GameLib.D3.Input.Editor.prototype.removeHelper = function(mesh, entity) { +GameLib.D3.Input.Editor.prototype.removeHelper = function(mesh) { - var components = entity.getComponents(GameLib.D3.Helper); + var components = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Helper); var helper = components.reduce( function (result, component) { @@ -257,13 +278,72 @@ GameLib.D3.Input.Editor.prototype.removeHelper = function(mesh, entity) { */ mesh.instance.material.polygonOffset = mesh.polygonOffset; - entity.removeComponent(helper); - } else { console.warn('failed to locate helper object which should exist for ' + mesh.name); } + return helper; }; + +GameLib.D3.Input.Editor.prototype.selectMesh = function(mesh) { + + /** + * If mesh is already selected, do nothing + */ + if (mesh.selected === true) { + return; + } + + /** + * Notify our component as being 'selected' + * @type {boolean} + */ + mesh.selected = true; + + /** + * Add a helper to the scene + * @type GameLib.D3.Helper + */ + + var helper = new GameLib.D3.Helper( + this.graphics, + null, + mesh.name + ' Helper', + mesh, + GameLib.D3.Helper.HELPER_TYPE_EDGES + ); + + /** + * Backup the polygonOffset value, then set it to 'true' - helps for clear nice outlines + */ + mesh.polygonOffset = mesh.instance.material.polygonOffset; + + mesh.instance.material.polygonOffset = true; + + mesh.parentScene.instance.add(helper.instance); + + GameLib.Event.Emit( + GameLib.Event.MESH_SELECTED, + { + mesh : mesh + } + ); +}; + +GameLib.D3.Input.Editor.prototype.deSelectMesh = function(mesh) { + + mesh.selected = false; + + GameLib.Event.Emit( + GameLib.Event.MESH_DESELECTED, + { + mesh : mesh + } + ); + + this.removeHelper(mesh); +}; + /** * MouseDown events * @param entity GameLib.Entity @@ -285,8 +365,6 @@ GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity, entityManager) this.mouse.x = (event.offsetX / renderer.instance.domElement.width) * 2 - 1; this.mouse.y = -(event.offsetY / renderer.instance.domElement.height) * 2 + 1; - var cameras = entity.getComponents(GameLib.D3.Camera); - var scenes = entity.getComponents(GameLib.D3.Scene); var intersects = scenes.reduce( @@ -344,63 +422,10 @@ GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity, entityManager) */ event.stopImmediatePropagation(); - /** - * Notify our component as being 'selected' - * @type {boolean} - */ - mesh.selected = !mesh.selected; - - /** - * Add a helper to the scene - * @type GameLib.D3.Helper - */ - var helper = null; - - var scene = mesh.parentScene; - - if (!scene) { - console.warn('the scene object for this mesh could not be located : ' + mesh.name); - return; - } - if (mesh.selected) { - - helper = new GameLib.D3.Helper( - this.graphics, - null, - mesh.name + ' Helper', - mesh, - GameLib.D3.Helper.HELPER_TYPE_EDGES - ); - - /** - * Backup the polygonOffset value, then set it to 'true' - helps for clear nice outlines - */ - mesh.polygonOffset = mesh.instance.material.polygonOffset; - - mesh.instance.material.polygonOffset = true; - - entity.addComponent(helper); - - scene.instance.add(helper.instance); - - GameLib.Event.Emit( - GameLib.Event.MESH_SELECTED, - { - mesh : mesh - } - ) - + this.deSelectMesh(mesh); } else { - - GameLib.Event.Emit( - GameLib.Event.MESH_DESELECTED, - { - mesh : mesh - } - ); - - this.removeHelper(mesh, entity); + this.selectMesh(mesh); } } } diff --git a/src/game-lib-d3-material.js b/src/game-lib-d3-material.js index 76e0551..f4423ab 100644 --- a/src/game-lib-d3-material.js +++ b/src/game-lib-d3-material.js @@ -69,7 +69,7 @@ GameLib.D3.Material = function( apiMaterial.clipShadows, apiMaterial.visible, apiMaterial.overdraw, - apiMaterial.shading, + apiMaterial.flatShading, apiMaterial.bumpScale, apiMaterial.normalScale, apiMaterial.displacementScale, @@ -372,12 +372,12 @@ GameLib.D3.Material.prototype.createStandardMaterialInstance = function() { displacementScale: this.displacementScale, refractionRatio: this.refractionRatio, fog: this.fog, - shading: this.shading, + flatShading: this.flatShading, wireframe: this.wireframe, wireframeLinewidth: this.wireframeLineWidth, wireframeLinecap: this.wireframeLineCap, wireframeLinejoin: this.wireframeLineJoin, - vertexColors: this.vertexColors, + vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS, skinning: this.skinning, morphTargets: this.morphTargets, morphNormals: this.morphNormals @@ -408,7 +408,7 @@ GameLib.D3.Material.prototype.createPointsMaterialInstance = function() { color: this.color.instance, size: this.pointSize, sizeAttenuation: this.pointSizeAttenuation, - vertexColors: GameLib.D3.Material.TYPE_NO_COLORS, + vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS, fog: this.fog }); }; @@ -447,12 +447,12 @@ GameLib.D3.Material.prototype.createPhongMaterialInstance = function() { combine: this.combine, refractionRatio: this.refractionRatio, fog: this.fog, - shading: this.shading, + flatShading: this.flatShading, wireframe: this.wireframe, wireframeLinewidth: this.wireframeLineWidth, wireframeLinecap: this.wireframeLineCap, wireframeLinejoin: this.wireframeLineJoin, - vertexColors: this.vertexColors, + vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS, skinning: this.skinning, morphTargets: this.morphTargets, morphNormals: this.morphNormals @@ -481,7 +481,7 @@ GameLib.D3.Material.prototype.createMeshBasicMaterialInstance = function() { visible: this.visible, side: this.side, color: this.color.instance, - vertexColors: GameLib.D3.Material.TYPE_NO_COLORS, + vertexColors: GameLib.D3.Material.TYPE_VERTEX_COLORS, fog: this.fog }); }; @@ -586,12 +586,12 @@ GameLib.D3.Material.prototype.updateStandardMaterialInstance = function() { this.instance.displacementScale = this.displacementScale; this.instance.refractionRatio = this.refractionRatio; this.instance.fog = this.fog; - this.instance.shading = this.shading; + this.instance.flatShading = this.flatShading; this.instance.wireframe = this.wireframe; this.instance.wireframeLinewidth = this.wireframeLineWidth; this.instance.wireframeLinecap = this.wireframeLineCap; this.instance.wireframeLinejoin = this.wireframeLineJoin; - this.instance.vertexColors = this.vertexColors; + this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS; this.instance.skinning = this.skinning; this.instance.morphTargets = this.morphTargets; this.instance.morphNormals = this.morphNormals; @@ -620,7 +620,7 @@ GameLib.D3.Material.prototype.updatePointsMaterialInstance = function() { this.instance.color = this.color.instance; this.instance.size = this.pointSize; this.instance.sizeAttenuation = this.pointSizeAttenuation; - this.instance.vertexColors = GameLib.D3.Material.TYPE_NO_COLORS; + this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS; this.instance.fog = this.fog; }; @@ -658,12 +658,12 @@ GameLib.D3.Material.prototype.updatePhongMaterialInstance = function() { this.instance.combine = this.combine; this.instance.refractionRatio = this.refractionRatio; this.instance.fog = this.fog; - this.instance.shading = this.shading; + this.instance.flatShading = this.flatShading; this.instance.wireframe = this.wireframe; this.instance.wireframeLinewidth = this.wireframeLineWidth; this.instance.wireframeLinecap = this.wireframeLineCap; this.instance.wireframeLinejoin = this.wireframeLineJoin; - this.instance.vertexColors = this.vertexColors; + this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS; this.instance.skinning = this.skinning; this.instance.morphTargets = this.morphTargets; this.instance.morphNormals = this.morphNormals; @@ -690,7 +690,7 @@ GameLib.D3.Material.prototype.updateMeshBasicMaterialInstance = function() { this.instance.visible = this.visible; this.instance.side = this.side; this.instance.color = this.color.instance; - this.instance.vertexColors = GameLib.D3.Material.TYPE_NO_COLORS; + this.instance.vertexColors = GameLib.D3.Material.TYPE_VERTEX_COLORS; this.instance.fog = this.fog; }; @@ -700,6 +700,8 @@ GameLib.D3.Material.prototype.updateMeshBasicMaterialInstance = function() { */ GameLib.D3.Material.prototype.createInstance = function() { + console.log('material create instance'); + var instance = null; if (this.materialType === GameLib.D3.Material.MATERIAL_TYPE_STANDARD) { @@ -736,6 +738,8 @@ GameLib.D3.Material.prototype.createInstance = function() { */ GameLib.D3.Material.prototype.updateInstance = function() { + console.log('material update instance'); + if (!this.instance) { console.warn('Attempt to update a non-existent instance'); return; @@ -939,7 +943,7 @@ GameLib.D3.Material.prototype.toApiObject = function(save) { this.clipShadows, this.visible, this.overdraw, - this.shading, + this.flatShading, this.bumpScale, this.normalScale, this.displacementScale, diff --git a/src/game-lib-d3-mesh-0.js b/src/game-lib-d3-mesh-0.js index c8e7aad..d737fc8 100644 --- a/src/game-lib-d3-mesh-0.js +++ b/src/game-lib-d3-mesh-0.js @@ -189,134 +189,6 @@ GameLib.D3.Mesh.prototype.updateVerticesFromGeometryInstance = function(geometry }; -/** - * Apply vertex data to geometry instance - * @param geometry - */ -GameLib.D3.Mesh.prototype.applyVertexDataToInstance = function(geometry) { - - if (this.vertices.length > 0) { - geometry.vertices = []; - this.vertices.map( - function(vertex) { - geometry.vertices.push( - new THREE.Vector3( - vertex.position.x, - vertex.position.y, - vertex.position.z - ) - ) - }.bind(this) - ); - geometry.verticesNeedUpdate = true; - } - -}; - -/** - * Applies face data information to the geometry - * @param geometry - */ -GameLib.D3.Mesh.prototype.applyFaceDataToGeometry = function(geometry) { - - for (var f = 0; f < this.faces.length; f++) { - - var face = new this.graphics.instance.Face3( - this.faces[f].v0, - this.faces[f].v1, - this.faces[f].v2, - new this.graphics.instance.Vector3( - this.faces[f].normal.x, - this.faces[f].normal.y, - this.faces[f].normal.z - ), - new this.graphics.instance.Color( - this.faces[f].color.r, - this.faces[f].color.g, - this.faces[f].color.b - ), - this.faces[f].materialIndex - ); - - face.vertexColors = [ - new this.graphics.instance.Color( - this.faces[f].vertexColors[0].r, - this.faces[f].vertexColors[0].g, - this.faces[f].vertexColors[0].b - ), - new this.graphics.instance.Color( - this.faces[f].vertexColors[1].r, - this.faces[f].vertexColors[1].g, - this.faces[f].vertexColors[1].b - ), - new this.graphics.instance.Color( - this.faces[f].vertexColors[2].r, - this.faces[f].vertexColors[2].g, - this.faces[f].vertexColors[2].b - ) - ]; - - face.normal = new this.graphics.instance.Vector3( - this.faces[f].normal.x, - this.faces[f].normal.y, - this.faces[f].normal.z - ); - - face.vertexNormals = [ - new this.graphics.instance.Vector3( - this.faces[f].vertexNormals[0].x, - this.faces[f].vertexNormals[0].y, - this.faces[f].vertexNormals[0].z - ), - new this.graphics.instance.Vector3( - this.faces[f].vertexNormals[1].x, - this.faces[f].vertexNormals[1].y, - this.faces[f].vertexNormals[1].z - ), - new this.graphics.instance.Vector3( - this.faces[f].vertexNormals[2].x, - this.faces[f].vertexNormals[2].y, - this.faces[f].vertexNormals[2].z - ) - ]; - - geometry.faces.push(face); - } -}; - -/** - * Apply UV data to geometry instance - * @param geometry - */ -GameLib.D3.Mesh.prototype.applyUVDataToGeometry = function(geometry) { - - geometry.faceVertexUvs = []; - - for (var fm = 0; fm < this.faceVertexUvs.length; fm++) { - - var faceMaterialVertexUvs = this.faceVertexUvs[fm]; - - geometry.faceVertexUvs[fm] = []; - - for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) { - geometry.faceVertexUvs[fm][fuv] = []; - geometry.faceVertexUvs[fm][fuv].push( - new this.graphics.instance.Vector2( - faceMaterialVertexUvs[fuv][0].x, - faceMaterialVertexUvs[fuv][0].y - ), - new this.graphics.instance.Vector2( - faceMaterialVertexUvs[fuv][1].x, - faceMaterialVertexUvs[fuv][1].y - ), - new this.graphics.instance.Vector2( - faceMaterialVertexUvs[fuv][2].x, - faceMaterialVertexUvs[fuv][2].y - ) - ); - } - } -}; GameLib.D3.Mesh.prototype.applyBones = function(geometry) { @@ -412,19 +284,48 @@ GameLib.D3.Mesh.prototype.createInstanceDefaults = function(instance) { instance.rotateZ(this.localRotation.z); } - if (this.materials.length === 1 && this.materials[0].instance) { - instance.material = this.materials[0].instance; - } + instance.renderOrder = this.renderOrder; this.subscribe( GameLib.Event.MATERIAL_TYPE_CHANGED, function (data) { - if (this.materials[0] === data.material) { - this.instance.material = data.material.instance; - this.instance.geometry.uvsNeedUpdate = true; + + /** + * Check if this material is in use by the mesh + */ + + var inUse = this.materials.reduce( + function(result, material) { + if (material === data.material) { + result = true; + } + return result; + }, + false + ); + + /** + * If the material is in use, assign all the new material instances to the mesh instance, and update + * geometry uvs + */ + if (inUse) { + + this.instance.material = this.materials.map( + function(material){ + return material.instance; + } + ); + + this.instance.geometry.uvsNeedUpdate = true; } + + + // if (this.materials[0] === data.material) { + // this.instance.material = data.material.instance; + // this.instance.geometry.uvsNeedUpdate = true; + // } } ); }; @@ -434,27 +335,201 @@ GameLib.D3.Mesh.prototype.createInstanceDefaults = function(instance) { */ GameLib.D3.Mesh.prototype.createInstance = function() { - var geometry = new THREE.Geometry(); + console.log('mesh create instance'); - /** - * Setup vertices - */ - this.applyVertexDataToInstance(geometry); + function disposeArray() { + // this.array = null; + } - /** - * Setup faces - */ - this.applyFaceDataToGeometry(geometry); + var geometry = new THREE.BufferGeometry(); + + /** + * Setup face indexes - first we sort according to the material index, because later we will create + * groups for each vertice group + */ + this.faces.sort(function(a, b){ + + if (a.materialIndex < b.materialIndex) { + return -1; + } + + if (a.materialIndex > b.materialIndex) { + return 1; + } + + return 0; + }); + + /** + * Setup mesh vertices positions + * @type {Float32Array} + */ + var vertices = new Float32Array( + + this.faces.reduce( + function(result, face){ + result.push(this.vertices[face.v0].position.x); + result.push(this.vertices[face.v0].position.y); + result.push(this.vertices[face.v0].position.z); + result.push(this.vertices[face.v1].position.x); + result.push(this.vertices[face.v1].position.y); + result.push(this.vertices[face.v1].position.z); + result.push(this.vertices[face.v2].position.x); + result.push(this.vertices[face.v2].position.y); + result.push(this.vertices[face.v2].position.z); + return result; + }.bind(this), + [] + ) + + // this.vertices.reduce( + // function(result, vertex) { + // result.push(vertex.position.x); + // result.push(vertex.position.y); + // result.push(vertex.position.z); + // return result; + // }, + // [] + // ) + ); + geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3).onUpload( disposeArray )); + + /** + * Setyp mesh vertices colors + */ + var colors = Float32Array.from( + this.faces.reduce( + function(result, face){ + result.push(1,1,1,1,1,1,1,1,1); + // result.push(face.color.r); + // result.push(face.color.g); + // result.push(face.color.b); + // result.push(face.color.r); + // result.push(face.color.g); + // result.push(face.color.b); + // result.push(face.color.r); + // result.push(face.color.g); + // result.push(face.color.b); + return result; + }.bind(this), + [] + ) + ); + geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3, true).onUpload( disposeArray )); /** * Setup face UVs */ - this.applyUVDataToGeometry(geometry); + var uvs = Float32Array.from( + this.faceVertexUvs[0].reduce( + function(result, uv) { + result.push(uv[0].x); + result.push(uv[0].y); + result.push(uv[1].x); + result.push(uv[1].y); + result.push(uv[2].x); + result.push(uv[2].y); + return result; + }, + [] + ) + ); + geometry.addAttribute('uv', new THREE.BufferAttribute(uvs, 2).onUpload( disposeArray )); + + + // geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).onUpload( disposeArray ) ); + // geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ).onUpload( disposeArray ) ); + // geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ).onUpload( disposeArray ) ); + + + /** + * Now we create the face indices + */ + // var faceIndices = Uint32Array.from( + // this.faces.reduce( + // function(result, face) { + // result.push(face.v0); + // result.push(face.v1); + // result.push(face.v2); + // return result; + // }, + // [] + // ) + // ); + // geometry.setIndex(new THREE.BufferAttribute(faceIndices, 1)); + + /** + * Setup material groups - this means creating a new group for each material index change + * We know faces are sorted according to material index + */ + var groupIndexCounts = this.faces.reduce( + function(result, face) { + + var currentGroup = result.pop(); + + if (currentGroup.index !== face.materialIndex) { + /** + * We have a new group + */ + result.push(currentGroup); + result.push({ + index: face.materialIndex, + count: 3 + }) + } else { + currentGroup.count += 3; + result.push(currentGroup); + } + + return result; + }, + [ + { + index : 0, + count : 0 + } + ] + ); + + groupIndexCounts.reduce( + function(start, group) { + geometry.addGroup(start, group.count, group.index); + return start + group.count; + }, + 0 + ); + + //geometry.addGroup(0, vertices.length, this.materials.length - 1); + // + // for (var fm = 0; fm < this.faceVertexUvs.length; fm++) { + // + // var faceMaterialVertexUvs = this.faceVertexUvs[fm]; + // + // geometry.faceVertexUvs[fm] = []; + // + // for (var fuv = 0; fuv < faceMaterialVertexUvs.length; fuv++) { + // geometry.faceVertexUvs[fm][fuv] = []; + // geometry.faceVertexUvs[fm][fuv].push( + // new this.graphics.instance.Vector2( + // faceMaterialVertexUvs[fuv][0].x, + // faceMaterialVertexUvs[fuv][0].y + // ), + // new this.graphics.instance.Vector2( + // faceMaterialVertexUvs[fuv][1].x, + // faceMaterialVertexUvs[fuv][1].y + // ), + // new this.graphics.instance.Vector2( + // faceMaterialVertexUvs[fuv][2].x, + // faceMaterialVertexUvs[fuv][2].y + // ) + // ); + // } + // } /** * Apply skin indices */ - this.applyBones(geometry); + // this.applyBones(geometry); /** * Re-compute normals @@ -464,15 +539,32 @@ GameLib.D3.Mesh.prototype.createInstance = function() { var instance = null; + var instanceMaterials = function(result, material){ + result.push(material.instance); + return result; + }; + if (this.skeleton) { - instance = new THREE.SkinnedMesh(geometry); + instance = new THREE.SkinnedMesh( + geometry, + this.materials.reduce( + instanceMaterials, + [] + ) + ); instance.add(this.skeleton.rootBoneInstance); instance.bind(this.skeleton.instance); } else { - instance = new THREE.Mesh(geometry); + instance = new THREE.Mesh( + geometry, + this.materials.reduce( + instanceMaterials, + [] + ) + ); } - this.createInstanceDefaults(instance); + //this.createInstanceDefaults(instance); return instance; }; @@ -482,6 +574,8 @@ GameLib.D3.Mesh.prototype.createInstance = function() { */ GameLib.D3.Mesh.prototype.updateInstance = function() { + console.log('mesh update instance'); + if (this.parentMesh && this.parentMesh.loaded) { if (this.instance.parent !== this.parentMesh.instance) { @@ -653,5 +747,45 @@ GameLib.D3.Mesh.prototype.centerAroundOrigin = function() { this.localPosition.y = -localPosition.y; this.localPosition.z = -localPosition.z; + this.updateInstance(); +}; + +/** + * Applies position, rotation and scale to the object vertice data, resets scale, rotation and sets position to origin. + */ +GameLib.D3.Mesh.prototype.applyLocalPositionRotationScale = function() { + + this.instance.updateMatrix(); + + this.instance.geometry.applyMatrix(this.instance.matrix); + + this.instance.position.set(0,0,0); + this.instance.rotation.set(0,0,0); + this.instance.scale.set(1,1,1); + + this.instance.updateMatrix(); + + this.localPosition.x = this.instance.position.x; + this.localPosition.y = this.instance.position.y; + this.localPosition.z = this.instance.position.z; + + this.localScale.x = this.instance.scale.x; + this.localScale.y = this.instance.scale.y; + this.localScale.z = this.instance.scale.z; + + this.localRotation.x = this.instance.rotation.x; + this.localRotation.y = this.instance.rotation.y; + this.localRotation.z = this.instance.rotation.z; + + console.log('TODO: update vertices from vertex array - we store them indexed but they live non-indexed'); + // var vertices = this.instance.geometry.getAttribute('position').array; + // + // for (var v = 0; v < vertices.length; v+=3) { + // + // this.vertices[v/3].position.x = vertices[v+0]; + // this.vertices[v/3].position.y = vertices[v+1]; + // this.vertices[v/3].position.z = vertices[v+2]; + // } + this.updateInstance(); }; \ No newline at end of file diff --git a/src/game-lib-d3-raycaster.js b/src/game-lib-d3-raycaster.js index bd74135..56fb6ee 100644 --- a/src/game-lib-d3-raycaster.js +++ b/src/game-lib-d3-raycaster.js @@ -149,41 +149,48 @@ GameLib.D3.Raycaster.prototype.setPosition = function( */ GameLib.D3.Raycaster.prototype.getIntersectedObjects = function(meshes) { - var meshInstances = meshes.reduce( + return meshes.reduce( function (result, mesh) { - if (mesh.instance) { - result.push(mesh.instance); - } + var intersects = this.instance.intersectObject(mesh.instance); - return result; - }, + if (intersects.length > 0) { + result.push( + { + mesh: mesh, + distance : intersects[0].distance + } + ); + } + + return result; + }.bind(this), [] ); - var intersects = this.instance.intersectObjects(meshInstances); - - return intersects.reduce( - - function (result, intersect) { - - meshes.map( - function(mesh){ - if (mesh.instance === intersect.object){ - result.push( - { - mesh : mesh, - distance : intersect.distance - } - ); - } - } - ); - - return result; - }, - [] - ); + // var intersects = this.instance.intersectObjects(meshInstances); + // + // return intersects.reduce( + // + // function (result, intersect) { + // + // meshes.map( + // function(mesh){ + // if (mesh.instance === intersect.object){ + // result.push( + // { + // mesh : mesh, + // distance : intersect.distance + // } + // ); + // } + // } + // ); + // + // return result; + // }, + // [] + // ); }; diff --git a/src/game-lib-d3-texture.js b/src/game-lib-d3-texture.js index d760f51..857bd71 100644 --- a/src/game-lib-d3-texture.js +++ b/src/game-lib-d3-texture.js @@ -155,6 +155,8 @@ GameLib.D3.Texture.TEXTURE_TYPE_CUBE = 0x2; */ GameLib.D3.Texture.prototype.createInstance = function() { + console.log('texture create instance'); + var instance = null; if (this.typeId === GameLib.D3.Texture.TEXTURE_TYPE_CUBE) { @@ -197,18 +199,18 @@ GameLib.D3.Texture.prototype.createInstance = function() { this.mapping = GameLib.D3.Texture.TYPE_UV_MAPPING; } } - - instance.name = this.name; - instance.flipY = this.flipY; - instance.encoding = this.encoding; - instance.offset.x = this.offset.x; - instance.offset.y = this.offset.y; - instance.repeat.x = this.repeat.x; - instance.repeat.y = this.repeat.y; - instance.mapping = this.mapping; - instance.format = this.format; - instance.wrapS = this.wrapS; - instance.wrapT = this.wrapT; + // + // instance.name = this.name; + // instance.flipY = this.flipY; + // instance.encoding = this.encoding; + // instance.offset.x = this.offset.x; + // instance.offset.y = this.offset.y; + // instance.repeat.x = this.repeat.x; + // instance.repeat.y = this.repeat.y; + // instance.mapping = this.mapping; + // instance.format = this.format; + // instance.wrapS = this.wrapS; + // instance.wrapT = this.wrapT; return instance; }; @@ -218,6 +220,8 @@ GameLib.D3.Texture.prototype.createInstance = function() { */ GameLib.D3.Texture.prototype.updateInstance = function() { + console.log('texture update instance'); + if (!this.instance) { console.error('no texture instance'); return; @@ -251,17 +255,17 @@ GameLib.D3.Texture.prototype.updateInstance = function() { } } - this.instance.name = this.name; - this.instance.flipY = this.flipY; - this.instance.encoding = this.encoding; - this.instance.offset.x = this.offset.x; - this.instance.offset.y = this.offset.y; - this.instance.repeat.x = this.repeat.x; - this.instance.repeat.y = this.repeat.y; - this.instance.mapping = this.mapping; - this.instance.format = this.format; - this.instance.wrapS = this.wrapS; - this.instance.wrapT = this.wrapT; + // this.instance.name = this.name; + // this.instance.flipY = this.flipY; + // this.instance.encoding = this.encoding; + // this.instance.offset.x = this.offset.x; + // this.instance.offset.y = this.offset.y; + // this.instance.repeat.x = this.repeat.x; + // this.instance.repeat.y = this.repeat.y; + // this.instance.mapping = this.mapping; + // this.instance.format = this.format; + // this.instance.wrapS = this.wrapS; + // this.instance.wrapT = this.wrapT; this.instance.needsUpdate = true; }; diff --git a/src/game-lib-gui.js b/src/game-lib-gui.js index addbb88..4fba999 100644 --- a/src/game-lib-gui.js +++ b/src/game-lib-gui.js @@ -21,39 +21,6 @@ GameLib.GUI = function( } this.gui = gui; - /** - * Add some GUI behaviour - */ - this.gui.prototype.removeEmtpyFolders = function() { - for (var property in this.__folders) { - if (this.__folders.hasOwnProperty(property)){ - - var folder = this.__folders[property]; - - if (folder.__listening.length === 0) { - folder.close(); - this.__ul.removeChild(folder.domElement.parentNode); - delete this.__folders[property]; - this.onResize(); - } - } - } - }; - - this.gui.prototype.removeAllFolders = function() { - for (var property in this.__folders) { - if (this.__folders.hasOwnProperty(property)){ - - var folder = this.__folders[property]; - - folder.close(); - this.__ul.removeChild(folder.domElement.parentNode); - delete this.__folders[property]; - this.onResize(); - } - } - }; - if (GameLib.Utils.UndefinedOrNull(id)) { id = GameLib.Utils.RandomId(); } @@ -92,13 +59,6 @@ GameLib.GUI = function( GameLib.GUI.prototype = Object.create(GameLib.Component.prototype); GameLib.GUI.prototype.constructor = GameLib.GUI; -/** - * Resize function - */ -GameLib.GUI.prototype.resize = function() { - console.log('override me per implementation'); -}; - /** * Creates a helper instance */ @@ -779,10 +739,14 @@ GameLib.GUI.prototype.buildControl = function(folder, object, property, entityMa -GameLib.GUI.prototype.buildVectorControl = function(folder, object, property, dimension) { +GameLib.GUI.prototype.buildVectorControl = function(folder, templateObject, property, dimension) { var step = 0.1; + var object = templateObject.template; + + var affected = templateObject.affected; + if ( property === 'localRotation' || property === 'localPosition' @@ -795,10 +759,14 @@ GameLib.GUI.prototype.buildVectorControl = function(folder, object, property, di object[property], 'w', -100, - 100 - ).name(property + '.w').listen().step(step).onChange( - function() { - object.updateInstance(); + 100, + step + ).name(property + '.w').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].w = value; + component.updateInstance(); + }.bind(this)); } ); } @@ -807,10 +775,14 @@ GameLib.GUI.prototype.buildVectorControl = function(folder, object, property, di object[property], 'x', -100, - 100 - ).name(property + '.x').listen().step(step).onChange( - function() { - object.updateInstance(); + 100, + step + ).name(property + '.x').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].x = value; + component.updateInstance(); + }.bind(this)); } ); @@ -818,10 +790,14 @@ GameLib.GUI.prototype.buildVectorControl = function(folder, object, property, di object[property], 'y', -100, - 100 - ).name(property + '.y').listen().step(step).onChange( - function() { - object.updateInstance(); + 100, + step + ).name(property + '.y').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].y = value; + component.updateInstance(); + }.bind(this)); } ); @@ -833,10 +809,14 @@ GameLib.GUI.prototype.buildVectorControl = function(folder, object, property, di object[property], 'z', -100, - 100 - ).name(property + '.z').listen().step(step).onChange( - function() { - object.updateInstance(); + 100, + step + ).name(property + '.z').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].z = value; + component.updateInstance(); + }.bind(this)); } ); } @@ -1031,130 +1011,28 @@ GameLib.GUI.prototype.buildEntitySelectionControlFromArray = function( }(this, entityManager)); }; +GameLib.GUI.prototype.removeEmtpyFolders = function() { + this.instance.removeEmptyFolders(); +}; + +GameLib.GUI.prototype.removeAllFolders = function() { + this.instance.removeAllFolders(); +}; + +GameLib.GUI.prototype.addFolder = function(folderName) { + try { + return this.instance.addFolder(folderName); + } catch (e) { + console.log(e.message); + return null; + } +}; + /** * Builds the GUI */ GameLib.GUI.prototype.build = function(entityManager) { - this.instance.removeAllFolders(); - - this.objects.sort( - function(a, b) { - if (a.name > b.name) { - return 1; - } - - if (a.name < b.name) { - return -1; - } - - return 0; - } - ); - // - // var discoveredObjects = []; - // - // var parentObject = this.objects[0]; - // - // this.objects.map( - // - // function(object) { - // - // if (object.idToObject) { - // for (var property in object.idToObject) { - // if (object.idToObject.hasOwnProperty(property)) { - // if (discoveredObjects.indexOf(object.idToObject[property]) === -1) { - // discoveredObjects.push(object.idToObject[property]); - // } - // } - // } - // } - // - // }.bind(this) - // ); - // - // discoveredObjects - // ); - - this.objects.map( - - function(object) { - - var apiObject = object.toApiObject(); - - if (typeof(apiObject) === 'string') { - return; - } - - var folder = null; - - try { - folder = this.instance.addFolder(apiObject.name); - } catch (e) { - console.log(e.message); - return; - } - - if (!folder) { - throw new Error('Could not create folder'); - } - - var property; - - for (property in apiObject) { - if ( - apiObject.hasOwnProperty(property) && - object.hasOwnProperty(property) - ) { - if ( - object.linkedObjects && - object.linkedObjects[property] - ) { - if (property === 'parentEntity') { - this.buildEntitySelectionControlFromArray( - folder, - object, - property, - entityManager - ) - } else if (object.linkedObjects[property] instanceof Array) { - this.buildArrayManager( - folder, - object, - property, - object.linkedObjects[property], - entityManager - ) - } else { - this.buildSelectControl(folder, object, property, entityManager, object.linkedObjects[property]); - } - - } else if (typeof (object[property]) === 'object') { - - if (this.isColor(object[property])) { - this.buildControl(folder, object, property); - } else if (object[property] instanceof GameLib.Vector2) { - this.buildVectorControl(folder, object, property, 2); - } else if (object[property] instanceof GameLib.Vector3) { - this.buildVectorControl(folder, object, property, 3); - } else if (object[property] instanceof GameLib.Vector4) { - this.buildVectorControl(folder, object, property, 4); - } else { - console.log('ignored: ' + property); - } - } else { - this.buildControl(folder, object, property, entityManager); - } - } - } - - for (property in object) { - if (typeof (object[property]) === 'function') { - folder.add(object, property); - } - } - }.bind(this) - - ); + console.log('hi'); }; \ No newline at end of file diff --git a/src/game-lib-system-gui.js b/src/game-lib-system-gui.js index d3374eb..7c4c0ca 100644 --- a/src/game-lib-system-gui.js +++ b/src/game-lib-system-gui.js @@ -13,6 +13,8 @@ GameLib.System.GUI = function( this.guis = []; + this.selected = []; + this.buildGUISubscription = null; this.meshDeletedSubscription = null; @@ -34,6 +36,39 @@ GameLib.System.GUI.prototype.start = function() { this.guis = GameLib.EntityManager.Instance.queryComponents(GameLib.GUI); + /** + * Add some GUI behaviour + */ + dat.GUI.prototype.removeEmtpyFolders = function() { + for (var property in this.__folders) { + if (this.__folders.hasOwnProperty(property)){ + + var folder = this.__folders[property]; + + if (folder.__listening.length === 0) { + folder.close(); + this.__ul.removeChild(folder.domElement.parentNode); + delete this.__folders[property]; + this.onResize(); + } + } + } + }; + + dat.GUI.prototype.removeAllFolders = function() { + for (var property in this.__folders) { + if (this.__folders.hasOwnProperty(property)){ + + var folder = this.__folders[property]; + + folder.close(); + this.__ul.removeChild(folder.domElement.parentNode); + delete this.__folders[property]; + this.onResize(); + } + } + }; + this.guis.map(function(gui){ gui.domElement.instance.parentElement.appendChild(gui.instance.domElement); }); @@ -50,12 +85,12 @@ GameLib.System.GUI.prototype.start = function() { this.meshSelectedSubscription = this.subscribe( GameLib.Event.MESH_SELECTED, - this.meshSelected + this.meshSelectionChange ); this.meshDeselectedSubscription = this.subscribe( GameLib.Event.MESH_DESELECTED, - this.meshDeslected + this.meshSelectionChange ); this.newEntitySubscription = this.subscribe( @@ -66,19 +101,263 @@ GameLib.System.GUI.prototype.start = function() { GameLib.System.GUI.prototype.buildGUI = function(data) { - - this.guis.map(function(gui){ - gui.objects = []; - if ( - data.components && - data.components.length > 0 - ) { - gui.objects = data.components; + /** + * Check if we have data + */ + if (GameLib.Utils.UndefinedOrNull(data.components)) { + console.log('no data components'); + return; } - gui.build(GameLib.EntityManager.Instance); + if (GameLib.Utils.UndefinedOrNull(data.components.length) || data.components.length === 0) { + console.log('no components selected'); + return; + } + + /** + * First, start fresh - remove all folders + */ + gui.removeAllFolders(); + + /** + * Sort the components by component type + */ + data.components.sort( + + function(a, b) { + + if (a.componentType > b.componentType) { + return 1; + } + + if (a.componentType < b.componentType) { + return -1; + } + + return 0; + } + ); + + /** + * Split the components into groups of componentType + */ + var componentGroups = data.components.reduce( + function(result, component) { + + var componentData = result.pop(); + + if (component.componentType === componentData.componentType) { + /** + * This is the first component + */ + componentData.components.push(component); + result.push(componentData); + return result; + } + + if (component.componentType !== componentData.componentType) { + result.push(componentData); + result.push({ + componentType : component.componentType, + components:[component] + }); + return result; + } + + }, + [ + { + componentType : data.components[0].componentType, + components : [] + } + ] + ); + + componentGroups.map( + + function(componentGroup){ + + if (componentGroup.components.length < 1) { + console.warn('invalid number of components'); + } + + var templateObject = { + template : { + /** + * Doing this here is just to put parentEntity at the top of the gui + */ + 'parentEntity' : componentGroup.components[0].parentEntity + }, + affected : [componentGroup.components[0]], + componentType : componentGroup.componentType + }; + + for (var property in componentGroup.components[0]) { + if ( + componentGroup.components[0].hasOwnProperty(property) || + typeof componentGroup.components[0][property] === 'function' + ) { + + if (typeof componentGroup.components[0][property] === 'function') { + + templateObject.template[property] = function(__property) { + + return function() { + + this.affected.map( + function(component) { + component[__property].bind(component)(); + } + ) + + }.bind(templateObject); + + }(property); + + } else { + + templateObject.template[property] = componentGroup.components[0][property]; + + } + } + } + + var componentTemplate = componentGroup.components.reduce( + + function(result, component) { + + if (component === componentGroup.components[0]) { + /** + * This is the first component, just return + */ + return result; + } + + /** + * Now start to filter out the properties + */ + for (var property in component) { + if ( + component.hasOwnProperty(property) + ) { + if (!result.template.hasOwnProperty(property)) { + continue; + } + + if ( + result.template[property] instanceof GameLib.Vector2 || + result.template[property] instanceof GameLib.Vector3 || + result.template[property] instanceof GameLib.Vector4 + ) { + if (!result.template[property].equals(component[property])) { + delete result.template[property]; + } + + continue; + } + + if (result.template[property] !== component[property]) { + delete result.template[property]; + } + } + } + + /** + * Store the affected component + */ + result.affected.push(component); + return result; + + }, + templateObject + ); + + /** + * componentTemplate now contains for this particular component type group - all + * the properties which are modifiable, and also the objects affected by this property changes + */ + var name; + + if (GameLib.Utils.UndefinedOrNull(componentTemplate.template.name)) { + name = GameLib.Component.GetComponentName(componentTemplate.componentType); + } else { + name = componentTemplate.template.name; + } + + var folder = gui.addFolder(name); + + if (!folder) { + throw new Error('Could not create folder'); + } + + for (var templateProperty in componentTemplate.template) { + + if ( + componentTemplate.template.hasOwnProperty(templateProperty) || + typeof (componentTemplate.template[templateProperty]) === 'function' + ) { + + if (typeof (componentTemplate.template[templateProperty]) === 'function') { + folder.add(componentTemplate.template, templateProperty); + continue; + } + + if (componentTemplate.template[templateProperty] instanceof GameLib.Vector2) { + gui.buildVectorControl(folder, componentTemplate, templateProperty, 2); + continue; + } + + if (componentTemplate.template[templateProperty] instanceof GameLib.Vector3) { + gui.buildVectorControl(folder, componentTemplate, templateProperty, 3); + continue; + } + + if (componentTemplate.template[templateProperty] instanceof GameLib.Vector4) { + gui.buildVectorControl(folder, componentTemplate, templateProperty, 4); + continue; + } + + // if ( + // component.linkedObjects && + // component.linkedObjects[property] + // ) { + // if (property === 'parentEntity') { + // this.buildEntitySelectionControlFromArray( + // folder, + // component, + // property, + // entityManager + // ) + // } else if (component.linkedObjects[property] instanceof Array) { + // this.buildArrayManager( + // folder, + // component, + // property, + // component.linkedObjects[property], + // entityManager + // ) + // } else { + // this.buildSelectControl(folder, component, property, entityManager, component.linkedObjects[property]); + // } + // + // } else if (typeof (component[property]) === 'object') { + // + // if (this.isColor(component[property])) { + // this.buildControl(folder, component, property); + // } else { + // //console.log('ignored: ' + property); + // } + // } else { + // this.buildControl(folder, component, property, entityManager); + // } + + + } + } + } + ); }); }; @@ -87,79 +366,72 @@ GameLib.System.GUI.prototype.meshDeleted = function(data) { }; +GameLib.System.GUI.prototype.meshSelectionChange = function(data) { + + var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh); + + var components = []; + + meshes.map(function(mesh){ + + if (!mesh.selected) { + return; + } + + if (mesh.parentEntity) { + GameLib.Utils.PushUnique(components, mesh.parentEntity); + } + components.push(mesh); + + mesh.materials.map( + function(material){ + GameLib.Utils.PushUnique(components, material); + } + ); + + mesh.materials.map( + function(material){ + for (var property in material.linkedObjects) { + if ( + material.linkedObjects.hasOwnProperty(property) && + material.hasOwnProperty(property) && + material[property] && + property !== 'parentEntity' + ) + { + GameLib.Utils.PushUnique(components, material[property]); + for (var tProperty in material[property].linkedObjects) { + if ( + material[property].linkedObjects.hasOwnProperty(tProperty) && + material[property].hasOwnProperty(tProperty) && + material[property][tProperty] && + tProperty !== 'parentEntity' + ) { + GameLib.Utils.PushUnique(components, material[property][tProperty]); + } + } + } + } + } + ); + }); + + GameLib.Event.Emit( + GameLib.Event.BUILD_GUI, + { + components : components + } + ); +}; + GameLib.System.GUI.prototype.meshSelected = function(data) { - var mesh = data.mesh; - - var objectsToAdd = []; - - this.guis.map( - function(gui) { - if (mesh.parentEntity) { - GameLib.Utils.PushUnique(objectsToAdd, mesh.parentEntity); - } - objectsToAdd.push(mesh); - mesh.materials.map( - function(material){ - GameLib.Utils.PushUnique(objectsToAdd, material); - } - ); - mesh.materials.map( - function(material){ - for (var property in material.linkedObjects) { - if ( - material.linkedObjects.hasOwnProperty(property) && - material.hasOwnProperty(property) && - material[property] && - property !== 'parentEntity' - ) - { - GameLib.Utils.PushUnique(objectsToAdd, material[property]); - for (var tProperty in material[property].linkedObjects) { - if ( - material[property].linkedObjects.hasOwnProperty(tProperty) && - material[property].hasOwnProperty(tProperty) && - material[property][tProperty] && - tProperty !== 'parentEntity' - ) { - GameLib.Utils.PushUnique(objectsToAdd, material[property][tProperty]); - } - } - } - } - } - ) - } - ); - this.guis.map(function(gui){ - objectsToAdd.map(function(object){ - gui.addObject(object); - }.bind(this)); - gui.build(GameLib.EntityManager.Instance); - }); - - this.meshSelectionObjects[mesh.id] = objectsToAdd; }; GameLib.System.GUI.prototype.meshDeslected = function(data) { - if (GameLib.Utils.UndefinedOrNull(this.meshSelectionObjects[data.mesh.id])) { - console.warn('selected mesh data not available'); - return; - } - - this.guis.map( - function(gui) { - this.meshSelectionObjects[data.mesh.id].map(function(object){ - gui.removeObject(object); - }.bind(this)); - - gui.build(GameLib.EntityManager.Instance); - }.bind(this) - ) - }; GameLib.System.GUI.prototype.newEntity = function(data) { @@ -172,6 +444,10 @@ GameLib.System.GUI.prototype.stop = function() { gui.domElement.instance.parentElement.removeChild(gui.instance.domElement); }); + delete dat.GUI.removeEmtpyFolders; + + delete dat.GUI.removeAllFolders; + this.buildGUISubscription.remove(); this.meshDeletedSubscription.remove(); diff --git a/src/game-lib-system-linking.js b/src/game-lib-system-linking.js index 85deb76..9a0d0ba 100644 --- a/src/game-lib-system-linking.js +++ b/src/game-lib-system-linking.js @@ -146,7 +146,18 @@ GameLib.System.Linking.prototype.resolveDependencies = function(component) { this.resolved.push(component); } - /** + /** + * First check if the dependencies have already been met + */ + if (GameLib.Utils.UndefinedOrNull(parentComponent.dependencies)) { + /** + * These dependencies have already been met - it is time to update the instance + */ + parentComponent.updateInstance(); + return; + } + + /** * Remove the actual dependency */ var index = parentComponent.dependencies.indexOf(component.id); @@ -304,7 +315,13 @@ GameLib.System.Linking.prototype.componentCreated = function(data) { GameLib.System.Linking.prototype.imageNotFound = function(data) { /** - * For blender files (and others) - we need to create the textures without images + * 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); @@ -315,26 +332,46 @@ GameLib.System.Linking.prototype.imageNotFound = function(data) { */ if (texture.image === data.image.id) { - /** - * This texture will never load because the image does not exist - so create - * its instance (without the image) - */ - texture.instance = texture.createInstance(); + 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; + } /** - * We override the 'loaded' value - we say its loaded because it will be just with defaults - * @type {boolean} + * Remove this image as a dependency */ - texture.loaded = true; + var index = texture.dependencies.indexOf(data.image.id); + if (index !== -1) { + texture.dependencies.splice(index, 1); + } - GameLib.Event.Emit( - GameLib.Event.TEXTURE_INSTANCE_CREATED, - { - texture: texture + /** + * If all dependencies have been met - create the instance and notify other listeners. + */ + if (texture.dependencies.length === 0) { + delete texture.dependencies; + + texture.instance = texture.createInstance(); + + if (texture.instance) { + texture.loaded = true; + + this.resolveDependencies(texture); + + texture.buildIdToObject(); + + GameLib.Event.EmitInstanceEvents(texture); } - ); + } } - }); + }.bind(this)); }; @@ -407,7 +444,44 @@ GameLib.System.Linking.prototype.sceneInstanceCreated = function(data) { }; GameLib.System.Linking.prototype.imageInstanceCreated = function(data) { + /** + * We resolve the dependencies + */ this.resolveDependencies(data.image); + + /** + * At this point - updateInstance on the texture will have been called - we need to update the material + */ + var textures = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Texture]); + + var materials = GameLib.EntityManager.Instance.queryComponents([GameLib.D3.Material]); + + /** + * For each material that uses this texture + */ + textures.map(function(texture){ + + materials.map(function(material){ + + var materialNeedsUpdate = false; + + for (var property in material) { + if (material.hasOwnProperty(property) && + material[property] === texture) { + materialNeedsUpdate = true; + } + } + + if (materialNeedsUpdate) { + material.updateInstance(); + } + + }); + + }); + + + }; GameLib.System.Linking.prototype.textureInstanceCreated = function(data) {