From f758c5087fc787b4a6ec6dbda7379ecb6e08f4a8 Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Wed, 23 Aug 2017 17:53:06 +0200 Subject: [PATCH] affected objects pt. 2 --- src/game-lib-a-1-event.js | 2 + src/game-lib-a-2-utils.js | 70 ++- src/game-lib-d3-input-editor.js | 50 +- src/game-lib-d3-mesh-0.js | 36 ++ src/game-lib-d3-mesh-plane.js | 16 +- src/game-lib-entity-manager.js | 23 + src/game-lib-gui.js | 954 +---------------------------- src/game-lib-system-gui.js | 1020 ++++++++++++++++++++++++++++--- src/game-lib-system-input.js | 2 +- src/game-lib-system-linking.js | 91 ++- 10 files changed, 1162 insertions(+), 1102 deletions(-) diff --git a/src/game-lib-a-1-event.js b/src/game-lib-a-1-event.js index 480d0c5..6f5917e 100644 --- a/src/game-lib-a-1-event.js +++ b/src/game-lib-a-1-event.js @@ -54,6 +54,8 @@ GameLib.Event.COMPONENT_REGISTER = 0x26; GameLib.Event.IMAGE_NOT_FOUND = 0x27; GameLib.Event.BLENDER_DATA_RECEIVED = 0x28; GameLib.Event.IMAGE_UPLOAD_COMPLETE = 0x29; +GameLib.Event.COMPONENT_REMOVE = 0x2a; + /** * Subscribe to some events diff --git a/src/game-lib-a-2-utils.js b/src/game-lib-a-2-utils.js index 80271b4..9098bd1 100644 --- a/src/game-lib-a-2-utils.js +++ b/src/game-lib-a-2-utils.js @@ -1,14 +1,4 @@ GameLib.Utils = function() {}; -GameLib.Utils.Extend = function( - child, // child class - parent // parent class -) { - for(var prop in parent.prototype) { - if(!child.prototype[prop]) { - child.prototype[prop] = parent.prototype[prop]; - } - } -}; /** * Strips image extension from given path @@ -35,7 +25,7 @@ GameLib.Utils.ObjectIdWithNameInArray = function(name, array) { return result; } - if (name == object.name) { + if (name === object.name) { return object.id; } @@ -378,12 +368,12 @@ GameLib.Utils.FixWindingOrder = function(faces, orientationEdge) { for (var i = 0; i < faces.length; i++) { if ( - (faces[i].v0 == edge.x && faces[i].v1 == edge.y) || - (faces[i].v1 == edge.x && faces[i].v2 == edge.y) || - (faces[i].v2 == edge.x && faces[i].v0 == edge.y) || - (faces[i].v0 == edge.y && faces[i].v1 == edge.x) || - (faces[i].v1 == edge.y && faces[i].v2 == edge.x) || - (faces[i].v2 == edge.y && faces[i].v0 == edge.x) + (faces[i].v0 === edge.x && faces[i].v1 === edge.y) || + (faces[i].v1 === edge.x && faces[i].v2 === edge.y) || + (faces[i].v2 === edge.x && faces[i].v0 === edge.y) || + (faces[i].v0 === edge.y && faces[i].v1 === edge.x) || + (faces[i].v1 === edge.y && faces[i].v2 === edge.x) || + (faces[i].v2 === edge.y && faces[i].v0 === edge.x) ) { var triangle = new GameLib.D3.TriangleFace( @@ -436,12 +426,12 @@ GameLib.Utils.FixWindingOrder = function(faces, orientationEdge) { * to have the same winding order) */ if ( - (triangleEdge.triangle.v0 == triangleEdge.edge.x && - triangleEdge.triangle.v1 == triangleEdge.edge.y) || - (triangleEdge.triangle.v1 == triangleEdge.edge.x && - triangleEdge.triangle.v2 == triangleEdge.edge.y) || - (triangleEdge.triangle.v2 == triangleEdge.edge.x && - triangleEdge.triangle.v0 == triangleEdge.edge.y) + (triangleEdge.triangle.v0 === triangleEdge.edge.x && + triangleEdge.triangle.v1 === triangleEdge.edge.y) || + (triangleEdge.triangle.v1 === triangleEdge.edge.x && + triangleEdge.triangle.v2 === triangleEdge.edge.y) || + (triangleEdge.triangle.v2 === triangleEdge.edge.x && + triangleEdge.triangle.v0 === triangleEdge.edge.y) ) { var backupV = triangleEdge.triangle.v1; triangleEdge.triangle.v1 = triangleEdge.triangle.v2; @@ -508,7 +498,7 @@ GameLib.Utils.FixWindingOrder = function(faces, orientationEdge) { */ GameLib.Utils.FixPolyZPlane = function(verticesFlat, grain) { - if ((verticesFlat.length % 3) != 0 && !(verticesFlat.length > 9)) { + if ((verticesFlat.length % 3) !== 0 && !(verticesFlat.length > 9)) { console.log("The vertices are not in the right length : " + verticesFlat.length); } @@ -637,6 +627,7 @@ GameLib.Utils.Difference = function (a, b) { * @constructor */ GameLib.Utils.PushUnique = function(array, object) { + if (array.indexOf(object) === -1) { array.push(object); } @@ -652,6 +643,37 @@ GameLib.Utils.IsEmpty = function(obj) { return (Object.keys(obj).length === 0 && obj.constructor === Object); }; +GameLib.Utils.isString = function(member) { + return (typeof member === 'string'); +}; + +GameLib.Utils.isBoolean = function(member) { + return (member === true || member === false); +}; + +GameLib.Utils.isColor = function(member) { + return (member instanceof GameLib.Color); +}; + +GameLib.Utils.isNumber = function(member) { + return (typeof member === 'number'); +}; + +GameLib.Utils.isVector2 = function(member) { + return (member instanceof GameLib.Vector2); +}; + +GameLib.Utils.isVector3 = function(member) { + return (member instanceof GameLib.Vector3); +}; + +GameLib.Utils.isVector4 = function(member) { + return (member instanceof GameLib.Vector4); +}; + +/** + * @return {string} + */ GameLib.Utils.LowerUnderscore = function(name) { return name.toLowerCase().replace(/\s+/, '_'); }; diff --git a/src/game-lib-d3-input-editor.js b/src/game-lib-d3-input-editor.js index fe1962e..9e27064 100644 --- a/src/game-lib-d3-input-editor.js +++ b/src/game-lib-d3-input-editor.js @@ -178,23 +178,14 @@ GameLib.D3.Input.Editor.prototype.onKeyDown = function(entity, entityManager) { } else { this.deSelectMesh(mesh); } - }.bind(this)) + }.bind(this)); + + GameLib.Event.Emit( + GameLib.Event.BUILD_GUI, + null + ) } - - // 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( - // function(result, system){ - // if (system.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { - // result = system; - // } - // return result; - // }, - // null - // ); - // - // inputSystem.stop(); } }; @@ -207,20 +198,6 @@ GameLib.D3.Input.Editor.prototype.onKeyUp = function(entity, entityManager) { if (event.code === 'ControlLeft') { this.controlLeft = false; } - - // 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( - // function(result, system){ - // if (system.systemType === GameLib.System.SYSTEM_TYPE_INPUT) { - // result = system; - // } - // return result; - // }, - // null - // ); - // - // inputSystem.stop(); } }; @@ -334,23 +311,22 @@ GameLib.D3.Input.Editor.prototype.deSelectMesh = function(mesh) { mesh.selected = false; + this.removeHelper(mesh); + GameLib.Event.Emit( GameLib.Event.MESH_DESELECTED, { mesh : mesh } ); - - this.removeHelper(mesh); }; /** * MouseDown events * @param entity GameLib.Entity - * @param entityManager GameLib.EntityManager * @returns {Function} */ -GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity, entityManager) { +GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity) { return function(event) { @@ -427,6 +403,14 @@ GameLib.D3.Input.Editor.prototype.onMouseDown = function(entity, entityManager) } else { this.selectMesh(mesh); } + + /** + * Notify our GUI system to build a GUI + */ + GameLib.Event.Emit( + GameLib.Event.BUILD_GUI, + null + ) } } } diff --git a/src/game-lib-d3-mesh-0.js b/src/game-lib-d3-mesh-0.js index d737fc8..3b350c7 100644 --- a/src/game-lib-d3-mesh-0.js +++ b/src/game-lib-d3-mesh-0.js @@ -788,4 +788,40 @@ GameLib.D3.Mesh.prototype.applyLocalPositionRotationScale = function() { // } this.updateInstance(); +}; + +GameLib.D3.Mesh.prototype.getChildrenComponents = function() { + + var components = []; + + this.materials.map( + function (material) { + + GameLib.Utils.PushUnique(components, 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]); + } + } + } + } + + }.bind(this) + ); + + return components; }; \ No newline at end of file diff --git a/src/game-lib-d3-mesh-plane.js b/src/game-lib-d3-mesh-plane.js index e542381..4924326 100644 --- a/src/game-lib-d3-mesh-plane.js +++ b/src/game-lib-d3-mesh-plane.js @@ -68,15 +68,15 @@ GameLib.D3.Mesh.Plane.prototype.createInstance = function() { this.updateVerticesFromGeometryInstance(geometry); } - this.applyBones(geometry); + var materialInstances = this.materials.reduce( + function(result, material) { + result.push(material.instance); + return result; + }, + [] + ); - var instance = null; - - if (this.skeleton) { - instance = new THREE.SkinnedMesh(geometry) - } else { - instance = new THREE.Mesh(geometry); - } + var instance = new THREE.Mesh(geometry, materialInstances); instance.userData.width = this.width; instance.userData.height = this.height; diff --git a/src/game-lib-entity-manager.js b/src/game-lib-entity-manager.js index 6290655..c45bc01 100644 --- a/src/game-lib-entity-manager.js +++ b/src/game-lib-entity-manager.js @@ -22,6 +22,11 @@ GameLib.EntityManager = function() { this.registerComponent.bind(this) ); + GameLib.Event.Subscribe( + GameLib.Event.COMPONENT_REMOVE, + this.removeComponent.bind(this) + ); + GameLib.Component.call( this, GameLib.Component.COMPONENT_ENTITY_MANAGER, @@ -48,6 +53,24 @@ GameLib.EntityManager.prototype.registerComponent = function(data) { ); }; +GameLib.EntityManager.prototype.removeComponent = function(data) { + + var index = this.register.indexOf(data.component); + + if (index !== -1) { + + this.register.splice(index, 1); + + GameLib.Event.Emit( + GameLib.Event.REGISTER_UPDATE, + { + register : this.register + } + ); + } + +}; + /** * Creates an GameLib.Entity and adds it to entities array * @returns {*} diff --git a/src/game-lib-gui.js b/src/game-lib-gui.js index 4fba999..31c8f5e 100644 --- a/src/game-lib-gui.js +++ b/src/game-lib-gui.js @@ -73,952 +73,25 @@ GameLib.GUI.prototype.updateInstance = function() { this.instance = new dat.GUI( { autoPlace: false } ); }; -GameLib.GUI.prototype.addObject = function(object) { - this.objects.push(object); -}; - -GameLib.GUI.prototype.removeObject = function(object) { - - var index = this.objects.indexOf(object); - - if (index === -1) { - console.warn('could not find object to remove'); - return false; - } else { - this.objects.splice(index, 1); - } - - return true; -}; - -GameLib.GUI.prototype.isString = function(member) { - return (typeof member === 'string'); -}; - -GameLib.GUI.prototype.isBoolean = function(member) { - return (member === true || member === false); -}; - -GameLib.GUI.prototype.isColor = function(member) { - return (member instanceof GameLib.API.Color); -}; - -GameLib.GUI.prototype.isNumber = function(member) { - return (typeof member === 'number'); -}; - -GameLib.GUI.prototype.isVector2 = function(member) { - return (member instanceof GameLib.Vector2); -}; - -// GameLib.GUI.prototype.isColor = function(member) { -// return (member instanceof GameLib.API.Color); -// }; -// -// -// Editor.prototype.isLiteral = function(object) { -// return _.isString(object) || _.isBoolean(object) || _.isNumber(object) || this.isColor(object); -// }; -// -// Editor.prototype.isEqual = function(object, object2) { -// if (object instanceof GameLib.Color && object2 instanceof GameLib.Color) { -// return object.r == object2.r && -// object.g == object2.g && -// object.b == object2.b; -// } else { -// return _.isEqual(object, object2); -// } -// }; -// -// Editor.prototype.isString = function(object) { -// return _.isString(object); -// }; -// -// Editor.prototype.isBoolean = function(object) { -// return _.isBoolean(object); -// }; -// -// Editor.prototype.isNumber = function(object) { -// return _.isNumber(object) -// }; -// -// Editor.prototype.isArray = function(object) { -// return _.isArray(object); -// }; -// -// Editor.prototype.isQuaternion = function(member) { -// return (member instanceof GameLib.Quaternion) -// }; - -GameLib.GUI.prototype.buildControl = function(folder, object, property, entityManager) { - - var handles = []; - - if ( - this.isString(object[property]) || - this.isBoolean(object[property]) - ) { - handles.push(folder.add(object, property).name(property).listen()); - } - - if (this.isNumber(object[property])) { - - var grain = 0.001; - - if (object.grain) { - grain = object.grain; - } - - // if (object instanceof GameLib.Entity && property == 'componentToCreate') { - // handles.push( - // folder.add( - // object, - // property, - // { - // 'path_following' : GameLib.Component.COMPONENT_PATH_FOLLOWING, - // 'material' : GameLib.Component.COMPONENT_MATERIAL, - // 'renderer' : GameLib.Component.COMPONENT_RENDERER, - // 'look_at' : GameLib.Component.COMPONENT_LOOK_AT, - // 'camera' : GameLib.Component.COMPONENT_CAMERA, - // 'follow' : GameLib.Component.COMPONENT_FOLLOW, - // 'mesh' : GameLib.Component.COMPONENT_MESH, - // 'spline' : GameLib.Component.COMPONENT_SPLINE, - // 'light' : GameLib.Component.COMPONENT_LIGHT, - // 'input_drive' : GameLib.Component.COMPONENT_INPUT_DRIVE, - // 'composer' : GameLib.Component.COMPONENT_COMPOSER, - // 'render_target' : GameLib.Component.COMPONENT_RENDER_TARGET, - // 'pass' : GameLib.Component.COMPONENT_PASS, - // 'scene' : GameLib.Component.COMPONENT_SCENE, - // 'game' : GameLib.Component.COMPONENT_GAME, - // 'input_editor' : GameLib.Component.COMPONENT_INPUT_EDITOR, - // 'editor' : GameLib.Component.COMPONENT_EDITOR, - // 'viewport' : GameLib.Component.COMPONENT_VIEWPORT, - // 'system' : GameLib.Component.COMPONENT_SYSTEM, - // 'graphics' : GameLib.Component.COMPONENT_GRAPHICS, - // 'helper' : GameLib.Component.COMPONENT_HELPER, - // 'custom_code' : GameLib.Component.COMPONENT_CUSTOM_CODE, - // 'mouse' : GameLib.Component.COMPONENT_MOUSE, - // 'skeleton' : GameLib.Component.COMPONENT_SKELETON, - // 'texture' : GameLib.Component.COMPONENT_TEXTURE, - // 'entity_manager' : GameLib.Component.COMPONENT_ENTITY_MANAGER - // } - // ).name(property).listen() - // ); - // - // } else if (object instanceof GameLib.System && property == 'systemType') { - // handles.push( - // folder.add( - // object, - // property, - // { - // 'render' : GameLib.System.SYSTEM_TYPE_RENDER, - // 'animation' : GameLib.System.SYSTEM_TYPE_ANIMATION, - // 'input' : GameLib.System.SYSTEM_TYPE_INPUT, - // 'all' : GameLib.System.SYSTEM_TYPE_ALL - // } - // ).name(property).listen() - // ); - // } else - - if (object instanceof GameLib.System && property === 'systemType') { - handles.push( - folder.add( - object, - property, - { - 'animation' : GameLib.System.SYSTEM_TYPE_ANIMATION, - 'gui' : GameLib.System.SYSTEM_TYPE_GUI, - 'input' : GameLib.System.SYSTEM_TYPE_INPUT, - 'render' : GameLib.System.SYSTEM_TYPE_RENDER, - 'storage' : GameLib.System.SYSTEM_TYPE_STORAGE, - 'linking' : GameLib.System.SYSTEM_TYPE_LINKING, - 'physics' : GameLib.System.SYSTEM_TYPE_PHYSICS - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Broadphase && property === 'broadphaseType') { - handles.push( - folder.add( - object, - property, - { - 'naive' : GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE, - 'grid' : GameLib.D3.Image.BROADPHASE_TYPE_GRID, - 'sap' : GameLib.D3.Image.BROADPHASE_TYPE_SAP - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Image && property === 'imageType') { - handles.push( - folder.add( - object, - property, - { - 'sphere' : GameLib.D3.Image.IMAGE_TYPE_SPHERE, - 'cube' : GameLib.D3.Image.IMAGE_TYPE_CUBE, - 'normal' : GameLib.D3.Image.IMAGE_TYPE_NORMAL - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Mesh && property === 'meshType') { - handles.push( - folder.add( - object, - property, - { - 'normal' : GameLib.D3.Mesh.MESH_TYPE_NORMAL, - 'curve' : GameLib.D3.Mesh.MESH_TYPE_CURVE, - 'skinned' : GameLib.D3.Mesh.MESH_TYPE_SKINNED, - 'plane' : GameLib.D3.Mesh.MESH_TYPE_PLANE, - 'sphere' : GameLib.D3.Mesh.MESH_TYPE_SPHERE - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'materialType') { - handles.push( - folder.add( - object, - property, - { - 'standard': GameLib.D3.Material.MATERIAL_TYPE_STANDARD, - 'basic': GameLib.D3.Material.MATERIAL_TYPE_BASIC, - 'phong': GameLib.D3.Material.MATERIAL_TYPE_PHONG, - 'points': GameLib.D3.Material.MATERIAL_TYPE_POINTS - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'side') { - handles.push( - folder.add( - object, - property, - { - 'double': GameLib.D3.Material.TYPE_DOUBLE_SIDE, - 'front': GameLib.D3.Material.TYPE_FRONT_SIDE, - 'back': GameLib.D3.Material.TYPE_BACK_SIDE - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'combine') { - handles.push( - folder.add( - object, - property, - { - 'multiply': GameLib.D3.Material.TYPE_MULTIPLY_OPERATION, - 'mix': GameLib.D3.Material.TYPE_MIX_OPERATION, - 'add': GameLib.D3.Material.TYPE_ADD_OPERATION - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'vertexColors') { - handles.push( - folder.add( - object, - property, - { - 'none': GameLib.D3.Material.TYPE_NO_COLORS, - 'face': GameLib.D3.Material.TYPE_FACE_COLORS, - 'vertex': GameLib.D3.Material.TYPE_VERTEX_COLORS - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'blending') { - handles.push( - folder.add( - object, - property, - { - 'normal': GameLib.D3.Material.TYPE_NORMAL_BLENDING, - 'additive': GameLib.D3.Material.TYPE_ADDITIVE_BLENDING, - 'subtractive': GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING, - 'multiply': GameLib.D3.Material.TYPE_MULTIPLY_BLENDING - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'blendSrc') { - handles.push( - folder.add( - object, - property,- - { - 'zero': GameLib.D3.Material.TYPE_ZERO_FACTOR, - 'one': GameLib.D3.Material.TYPE_ONE_FACTOR, - 'source color': GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR, - 'one minus source color': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR, - 'source alpha': GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR, - 'one minus source alpha': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR, - 'destination alpha': GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR, - 'one minus destination alpha': GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR, - 'destination color': GameLib.D3.Material.TYPE_DST_COLOR_FACTOR, - 'one minus destination color': GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR, - 'source alpha saturate': GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'blendDst') { - handles.push( - folder.add( - object, - property, - { - 'zero': GameLib.D3.Material.TYPE_ZERO_FACTOR, - 'one': GameLib.D3.Material.TYPE_ONE_FACTOR, - 'source color': GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR, - 'one minus source color': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR, - 'source alpha': GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR, - 'one minus source alpha': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR, - 'destination alpha': GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR, - 'one minus destination alpha': GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR, - 'destination color': GameLib.D3.Material.TYPE_DST_COLOR_FACTOR, - 'one minus destination color': GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR, - 'source alpha saturate': GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'blendEquation') { - handles.push( - folder.add( - object, - property, - { - 'add': GameLib.D3.Material.TYPE_ADD_EQUATION, - 'subtract': GameLib.D3.Material.TYPE_SUBTRACT_EQUATION, - 'reverse subtract': GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION, - 'min': GameLib.D3.Material.TYPE_MIN_EQUATION, - 'max': GameLib.D3.Material.TYPE_MAX_EQUATION - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'depthFunc') { - handles.push( - folder.add( - object, - property, - { - 'never': GameLib.D3.Material.TYPE_NEVER_DEPTH, - 'always': GameLib.D3.Material.TYPE_ALWAYS_DEPTH, - 'less depth': GameLib.D3.Material.TYPE_LESS_DEPTH, - 'less equal depth': GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH, - 'equal depth': GameLib.D3.Material.TYPE_EQUAL_DEPTH, - 'greated equal depth': GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH, - 'greated depth': GameLib.D3.Material.TYPE_GREATER_DEPTH, - 'not equal depth': GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Material && property === 'shading') { - handles.push( - folder.add( - object, - property, - { - 'flat': GameLib.D3.Material.TYPE_FLAT_SHADING, - 'smooth': GameLib.D3.Material.TYPE_SMOOTH_SHADING - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'wrapS') { - handles.push( - folder.add( - object, - property, - { - 'repeat': GameLib.D3.Texture.TYPE_REPEAT_WRAPPING, - 'clamp': GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING, - 'mirrored repeat': GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'wrapT') { - handles.push( - folder.add( - object, - property, - { - 'repeat': GameLib.D3.Texture.TYPE_REPEAT_WRAPPING, - 'clamp': GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING, - 'mirrored repeat': GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'format') { - handles.push( - folder.add( - object, - property, - { - 'alpha': GameLib.D3.Texture.TYPE_ALPHA_FORMAT, - 'rgb': GameLib.D3.Texture.TYPE_RGB_FORMAT, - 'rgba': GameLib.D3.Texture.TYPE_RGBA_FORMAT, - 'luminance': GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT, - 'luminance alpha': GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT, - 'depth': GameLib.D3.Texture.TYPE_DEPTH_FORMAT - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'mapping') { - handles.push( - folder.add( - object, - property, - { - 'uv': GameLib.D3.Texture.TYPE_UV_MAPPING, - 'cube reflection': GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING, - 'cube refraction': GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING, - 'equi rectangular reflection': GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING, - 'equi rectangular refraction': GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING, - 'spherical reflection': GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING, - 'cube uv reflection': GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING, - 'cube uv refraction': GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'magFilter') { - handles.push( - folder.add( - object, - property, - { - 'nearest': GameLib.D3.Texture.TYPE_NEAREST_FILTER, - 'nearest mipmap nearest': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER, - 'nearest mipmap linear': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER, - 'linear': GameLib.D3.Texture.TYPE_LINEAR_FILTER, - 'linear mipmap nearest': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER, - 'linear mipmap linear': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'minFilter') { - handles.push(folder.add( - object, - property, - { - 'nearest': GameLib.D3.Texture.TYPE_NEAREST_FILTER, - 'nearest mipmap nearest': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER, - 'nearest mipmap linear': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER, - 'linear': GameLib.D3.Texture.TYPE_LINEAR_FILTER, - 'linear mipmap nearest': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER, - 'linear mipmap linear': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'typeId') { - handles.push( - folder.add( - object, - property, - { - 'normal': GameLib.D3.Texture.TEXTURE_TYPE_NORMAL, - 'cube': GameLib.D3.Texture.TEXTURE_TYPE_CUBE - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'textureType') { - handles.push( - folder.add( - object, - property, - { - 'unsigned byte': GameLib.D3.Texture.TYPE_UNSIGNED_BYTE, - 'byte': GameLib.D3.Texture.TYPE_BYTE, - 'short': GameLib.D3.Texture.TYPE_SHORT, - 'unsigned short': GameLib.D3.Texture.TYPE_UNSIGNED_SHORT, - 'int': GameLib.D3.Texture.TYPE_INT, - 'unsigned int': GameLib.D3.Texture.TYPE_UNSIGNED_INT, - 'float': GameLib.D3.Texture.TYPE_FLOAT, - 'half float': GameLib.D3.Texture.TYPE_HALF_FLOAT - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Texture && property === 'encoding') { - handles.push( - folder.add( - object, - property, - { - 'linear': GameLib.D3.Texture.TYPE_LINEAR_ENCODING, - 'srgb': GameLib.D3.Texture.TYPE_SRGB_ENCODING, - 'gamma': GameLib.D3.Texture.TYPE_GAMMA_ENCODING, - 'rgbe': GameLib.D3.Texture.TYPE_RGBE_ENCODING, - 'log luv': GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING, - 'rgbm7': GameLib.D3.Texture.TYPE_RGBM7_ENCODING, - 'rgbm16': GameLib.D3.Texture.TYPE_RGBM16_ENCODING, - 'rgbd': GameLib.D3.Texture.TYPE_RGBD_ENCODING - } - ).name(property).listen() - ); - } else if (object instanceof GameLib.D3.Light && property === 'lightType') { - handles.push( - folder.add( - object, - property, - { - 'ambient': GameLib.D3.Light.LIGHT_TYPE_AMBIENT, - 'directional': GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL, - 'spot': GameLib.D3.Light.LIGHT_TYPE_SPOT, - 'point': GameLib.D3.Light.LIGHT_TYPE_POINT - } - ).name(property).listen() - ); - } else { - - /** - * Try to guess a scale for this property - */ - if ( - property === 'opacity' || - property === 'metalness' || - property === 'roughness' - ) { - handles.push(folder.add(object, property, 0, 1.0).step(0.001).name(property).listen()); - } else if ( - property === 'shininess' || - property === 'fov' - ) { - handles.push(folder.add(object, property, -255, 255).step(1).name(property).listen()); - } else if ( - property === 'aspect' - ) { - handles.push(folder.add(object, property, 0, 5).step(0.001).name(property).listen()); - } else if ( - property === 'widthSegments' || - property === 'heightSegments' - ) { - handles.push(folder.add(object, property, 1, 1000).step(1).name(property).listen()); - } else if ( - property === 'angle' || - property === 'width' || - property === 'height' || - property === 'depth' - ) { - handles.push(folder.add(object, property, -1000, 1000).step(1).name(property).listen()); - } else if ( - property === 'near' || - property === 'distanceGrain' || - property === 'bumpScale' || - property === 'envMapIntensity' - ) { - handles.push(folder.add(object, property, -10, 100).step(0.001).name(property).listen()); - } else if ( - property === 'heightOffset' || - property === 'rotationFactor' - ) { - handles.push(folder.add(object, property, -100, 100).step(0.001).name(property).listen()); - } else { - handles.push(folder.add(object, property, -10000, 10000).step(grain).name(property).listen()); - } - } - } - - if (this.isColor(object[property])) { - handles.push(folder.addColor({hexColor : object[property].toHex()}, 'hexColor').name(property).listen()); - } - // - // if (this.isFutureObject(object, property)) { - // - // var result = this.getObjectPropertyType(object, property); - // - // var objectType = result.propertyType; - // - // var isArray = result.isArray; - // - // if (isArray) { - // - // - // - // } else { - // - // var selection = {}; - // - // selection['select...'] = null; - // - // var guiObject = { - // id : null - // }; - // - // for (var o in idToObject) { - // if (idToObject.hasOwnProperty(o)) { - // if (idToObject[o] instanceof objectType) { - // - // var name = idToObject[o].name; - // - // if (name.indexOf(idToObject[o].id) == -1) { - // name += '(' + idToObject[o].id + ')'; - // } - // - // selection[name] = idToObject[o].id; - // - // if (object[property] && object[property].id == idToObject[o].id) { - // guiObject.id = idToObject[o].id; - // } - // } - // } - // } - // - // handles.push( - // folder.add( - // guiObject, - // 'id', - // selection - // ).name(property).listen() - // ); - // } - // - // var createObjectFunction = function(constructor, __object, __property, editor) { - // return function() { - // - // if (__object[__property] instanceof Array) { - // __object[__property].push(new constructor( - // editor.graphics - // )); - // } else { - // __object[__property] = new constructor( - // editor.graphics - // ); - // } - // - // editor.editor.buildIdToObject(); - // - // editor.buildObjectSelection(); - // - // editor.buildGUI(); - // } - // }(objectType, object, property, this); - // - // var createObject = { - // 'create': createObjectFunction - // }; - // - // folder.add( - // createObject, - // 'create' - // ).name('create a ' + property.replace(/s$/,'')); - // } - // - - // handles.map(function(handle){ - // - // handle.onChange( - // this.onPropertyChange( - // this, - // affectedObjectProperties - // ) - // ); - // - // - // }); - - handles.map( - function(gui) { - return function(handle) { - if (property === 'name') { - handle.onFinishChange( - function(){gui.build(entityManager)} - ); - } else { - handle.onChange( - function (value) { - if (object[property] instanceof GameLib.Color) { - object[property].fromHex(value); - object[property].updateInstance(); - } else if (typeof this.initialValue === 'number') { - object[property] = Number(value); - } else { - object[property] = value; - } - object.updateInstance(); - } - ); - } - } - }(this) - ); - -}; - - - -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' - ) { - step = 0.001; - } - - if (dimension === 4) { - folder.add( - object[property], - 'w', - -100, - 100, - step - ).name(property + '.w').listen().onChange( - function(value) { - affected.map(function(component){ - component[property].w = value; - component.updateInstance(); - }.bind(this)); - } - ); - } - - folder.add( - object[property], - 'x', - -100, - 100, - step - ).name(property + '.x').listen().onChange( - function(value) { - affected.map(function(component){ - component[property].x = value; - component.updateInstance(); - }.bind(this)); - } - ); - - folder.add( - object[property], - 'y', - -100, - 100, - step - ).name(property + '.y').listen().onChange( - function(value) { - affected.map(function(component){ - component[property].y = value; - component.updateInstance(); - }.bind(this)); - } - ); - - if ( - dimension === 3 || - dimension === 4 - ) { - folder.add( - object[property], - 'z', - -100, - 100, - step - ).name(property + '.z').listen().onChange( - function(value) { - affected.map(function(component){ - component[property].z = value; - component.updateInstance(); - }.bind(this)); - } - ); - } -}; - -GameLib.GUI.prototype.buildSelectControl = function(folder, object, property, entityManager, constructor) { - - var objects = entityManager.queryComponents(constructor); - - var idToObject = {}; - - var options = objects.reduce( - function(result, obj) { - result[obj.name] = obj; - idToObject[obj.id] = obj; - return result; - }, - { - 'none' : null - } - ); - - folder.add( - object, - property, - options - ).name(property).listen().onChange( - - function(gui) { - - return function (value) { - - if (value !== 'null') { - object[property] = idToObject[value]; - } else { - object[property] = null; - } - - if (property === 'parentScene') { - /** - * New way of doing things - */ - GameLib.Event.Emit( - GameLib.Event.PARENT_SCENE_CHANGE, - { - originalScene: this.initialValue, - newScene: object[property], - object: object, - entityManager: entityManager - } - ); - - } - else { - /** - * Old way of doing things - */ - object.updateInstance(); - } - - - /** - * Properties changed - rebuild GUI - */ - //gui.build(entityManager); - - }; - - }(this) - ); -}; - /** - * + * Removes empty folders from instance */ -GameLib.GUI.prototype.buildArrayManager = function( - folder, - object, - property, - constructor, - entityManager -) { - - var array = object[property]; - - var addArrayItem = function(item, index){ - - var controller = folder.add( - { - 'remove' : function() { - object[property].splice(object[property].indexOf(item), 1); - folder.remove(controller); - } - }, - 'remove' - ).name('remove ' + property + '[' + index + '] - ' + item.name); - }; - - array.map(addArrayItem); - - var idToObject = {}; - - var selectionObject = entityManager.queryComponents(constructor).reduce( - function(result, component) { - result[component.name] = component; - idToObject[component.id] = component; - return result; - }, - { - 'none' : null - } - ); - - var activeSelection = function(__object, __property) { - - var object = __object; - var property = __property; - - return { - component : null, - add : function() { - if (object[property].indexOf(activeSelection.component) === -1) { - object[property].push(activeSelection.component); - addArrayItem(activeSelection.component, object[property].length - 1) - } - } - }; - - }(object, property); - - folder.add(activeSelection, 'component', selectionObject).name('select ' + property).onChange( - function(value){ - if (value === 'null') { - activeSelection['component'] = null; - } else { - activeSelection['component'] = idToObject[value]; - } - } - ).listen(); - - folder.add(activeSelection, 'add').name('add to ' + property); - -}; - -GameLib.GUI.prototype.buildEntitySelectionControlFromArray = function( - folder, - object, - property, - entityManager -) { - - var options = entityManager.entities.reduce( - function(result, obj){ - if (obj instanceof Object) { - result[obj.name] = obj; - } else { - console.log('not an object'); - } - return result; - }, - { - 'none' : null - } - ); - - folder.add(object, property, options).name(property).listen().onChange( - function(entityManager, gui) { - return function(value) { - - if (value !== 'null') { - object[property] = entityManager.findEntityById(value); - } else { - object[property] = null; - } - - GameLib.Event.Emit( - GameLib.Event.PARENT_ENTITY_CHANGE, - { - originalEntity : this.initialValue, - newEntity : entityManager.findEntityById(value), - object : object - } - ); - - this.initialValue = entityManager.findEntityById(value); - }; - }(entityManager, this) - ).onFinishChange(function(gui, entityManager){ - return function() { - gui.build(entityManager); - } - }(this, entityManager)); -}; - GameLib.GUI.prototype.removeEmtpyFolders = function() { this.instance.removeEmptyFolders(); }; +/** + * Remove all folders from instance + */ GameLib.GUI.prototype.removeAllFolders = function() { this.instance.removeAllFolders(); }; +/** + * Adds a folder to instance + * @param folderName + * @returns {*} + */ GameLib.GUI.prototype.addFolder = function(folderName) { try { return this.instance.addFolder(folderName); @@ -1027,12 +100,3 @@ GameLib.GUI.prototype.addFolder = function(folderName) { return null; } }; - -/** - * Builds the GUI - */ -GameLib.GUI.prototype.build = function(entityManager) { - - 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 7c4c0ca..9f021d6 100644 --- a/src/game-lib-system-gui.js +++ b/src/game-lib-system-gui.js @@ -13,7 +13,16 @@ GameLib.System.GUI = function( this.guis = []; - this.selected = []; + this.components = []; + + /** + * When we want to show a specific set of components - we backup the current components and then restore them + * later when we are done. + * @type {null} + */ + this.backupComponents = null; + + this.exclusiveMode = false; this.buildGUISubscription = null; @@ -85,46 +94,866 @@ GameLib.System.GUI.prototype.start = function() { this.meshSelectedSubscription = this.subscribe( GameLib.Event.MESH_SELECTED, - this.meshSelectionChange + this.meshSelected ); this.meshDeselectedSubscription = this.subscribe( GameLib.Event.MESH_DESELECTED, - this.meshSelectionChange + this.meshDeslected ); this.newEntitySubscription = this.subscribe( GameLib.Event.NEW_ENTITY, this.newEntity - ) + ); + + this.componentRemovedSubscription = this.subscribe( + GameLib.Event.COMPONENT_REMOVE, + this.removeComponent + ) }; +GameLib.System.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' + ) { + step = 0.001; + } + + if (dimension === 4) { + folder.add( + object[property], + 'w', + -100, + 100, + step + ).name(property + '.w').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].w = value; + component.updateInstance(); + }.bind(this)); + } + ); + } + + folder.add( + object[property], + 'x', + -100, + 100, + step + ).name(property + '.x').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].x = value; + component.updateInstance(); + }.bind(this)); + } + ); + + folder.add( + object[property], + 'y', + -100, + 100, + step + ).name(property + '.y').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].y = value; + component.updateInstance(); + }.bind(this)); + } + ); + + if ( + dimension === 3 || + dimension === 4 + ) { + folder.add( + object[property], + 'z', + -100, + 100, + step + ).name(property + '.z').listen().onChange( + function(value) { + affected.map(function(component){ + component[property].z = value; + component.updateInstance(); + }.bind(this)); + } + ); + } +}; + +/** + * Builds an Entity Selection control + * @param folder + * @param componentTemplate + */ +GameLib.System.GUI.prototype.buildEntitySelectionControl = function(folder, componentTemplate) { + + var options = GameLib.EntityManager.Instance.queryComponents(GameLib.Entity).reduce( + function(result, entity) { + result[entity.name] = entity; + return result; + }, + { + 'none' : null + } + ); + + var object = componentTemplate.template; + + var affected = componentTemplate.affected; + + folder.add(object, 'parentEntity', options).listen().onChange( + + function(value) { + + var newEntity = null; + + if (value !== 'null') { + newEntity = GameLib.EntityManager.Instance.findEntityById(value); + } + + affected.map( + function(component) { + + component.parentEntity = newEntity; + + GameLib.Event.Emit( + GameLib.Event.PARENT_ENTITY_CHANGE, + { + originalEntity : this.initialValue, + newEntity : newEntity, + object : component + } + ); + }.bind(this) + ); + + this.initialValue = newEntity; + } + ).onFinishChange( + function(){ + // GameLib.Event.Emit( + // GameLib.Event.BUILD_GUI, + // { + // + // } + // ) + } + ); +}; + +GameLib.System.GUI.prototype.buildArrayManagerControl = function( + folder, + componentTemplate, + property, + constructor +) { + console.log('TODO: array manager control'); + // var array = object[property]; + // + // var addArrayItem = function(item, index){ + // + // var controller = folder.add( + // { + // 'remove' : function() { + // object[property].splice(object[property].indexOf(item), 1); + // folder.remove(controller); + // } + // }, + // 'remove' + // ).name('remove ' + property + '[' + index + '] - ' + item.name); + // }; + // + // array.map(addArrayItem); + // + // var idToObject = {}; + // + // var selectionObject = entityManager.queryComponents(constructor).reduce( + // function(result, component) { + // result[component.name] = component; + // idToObject[component.id] = component; + // return result; + // }, + // { + // 'none' : null + // } + // ); + // + // var activeSelection = function(__object, __property) { + // + // var object = __object; + // var property = __property; + // + // return { + // component : null, + // add : function() { + // if (object[property].indexOf(activeSelection.component) === -1) { + // object[property].push(activeSelection.component); + // addArrayItem(activeSelection.component, object[property].length - 1) + // } + // } + // }; + // + // }(object, property); + // + // folder.add(activeSelection, 'component', selectionObject).name('select ' + property).onChange( + // function(value){ + // if (value === 'null') { + // activeSelection['component'] = null; + // } else { + // activeSelection['component'] = idToObject[value]; + // } + // } + // ).listen(); + // + // folder.add(activeSelection, 'add').name('add to ' + property); + +}; + +GameLib.System.GUI.prototype.buildSelectControl = function(folder, object, property, entityManager, constructor) { + + var objects = entityManager.queryComponents(constructor); + + var idToObject = {}; + + var options = objects.reduce( + function(result, obj) { + result[obj.name] = obj; + idToObject[obj.id] = obj; + return result; + }, + { + 'none' : null + } + ); + + folder.add( + object, + property, + options + ).name(property).listen().onChange( + + function(gui) { + + return function (value) { + + if (value !== 'null') { + object[property] = idToObject[value]; + } else { + object[property] = null; + } + + if (property === 'parentScene') { + /** + * New way of doing things + */ + GameLib.Event.Emit( + GameLib.Event.PARENT_SCENE_CHANGE, + { + originalScene: this.initialValue, + newScene: object[property], + object: object, + entityManager: entityManager + } + ); + + } + else { + /** + * Old way of doing things + */ + object.updateInstance(); + } + + + /** + * Properties changed - rebuild GUI + */ + //gui.build(entityManager); + + }; + + }(this) + ); +}; + +GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate, property) { + + var object = componentTemplate.template; + + var componentType = componentTemplate.componentType; + + var handles = []; + + if ( + GameLib.Utils.isString(object[property]) || + GameLib.Utils.isBoolean(object[property]) + ) { + handles.push(folder.add(object, property).name(property).listen()); + } + + if (GameLib.Utils.isNumber(object[property])) { + + var grain = 0.001; + + if (object.grain) { + grain = object.grain; + } + + if (property === 'systemType') { + handles.push( + folder.add( + object, + property, + { + 'animation' : GameLib.System.SYSTEM_TYPE_ANIMATION, + 'gui' : GameLib.System.SYSTEM_TYPE_GUI, + 'input' : GameLib.System.SYSTEM_TYPE_INPUT, + 'render' : GameLib.System.SYSTEM_TYPE_RENDER, + 'storage' : GameLib.System.SYSTEM_TYPE_STORAGE, + 'linking' : GameLib.System.SYSTEM_TYPE_LINKING, + 'physics' : GameLib.System.SYSTEM_TYPE_PHYSICS + } + ).listen() + ); + } else if (property === 'broadphaseType') { + handles.push( + folder.add( + object, + property, + { + 'naive': GameLib.D3.Broadphase.BROADPHASE_TYPE_NAIVE, + 'grid': GameLib.D3.Image.BROADPHASE_TYPE_GRID, + 'sap': GameLib.D3.Image.BROADPHASE_TYPE_SAP + } + ).listen() + ); + } else if (property === 'meshType') { + handles.push( + folder.add( + object, + property, + { + 'normal' : GameLib.D3.Mesh.MESH_TYPE_NORMAL, + 'curve' : GameLib.D3.Mesh.MESH_TYPE_CURVE, + 'skinned' : GameLib.D3.Mesh.MESH_TYPE_SKINNED, + 'plane' : GameLib.D3.Mesh.MESH_TYPE_PLANE, + 'sphere' : GameLib.D3.Mesh.MESH_TYPE_SPHERE + } + ).listen() + ); + } else if (property === 'materialType') { + handles.push( + folder.add( + object, + property, + { + 'standard': GameLib.D3.Material.MATERIAL_TYPE_STANDARD, + 'basic': GameLib.D3.Material.MATERIAL_TYPE_BASIC, + 'phong': GameLib.D3.Material.MATERIAL_TYPE_PHONG, + 'points': GameLib.D3.Material.MATERIAL_TYPE_POINTS + } + ).listen() + ); + } else if (property === 'side') { + handles.push( + folder.add( + object, + property, + { + 'double': GameLib.D3.Material.TYPE_DOUBLE_SIDE, + 'front': GameLib.D3.Material.TYPE_FRONT_SIDE, + 'back': GameLib.D3.Material.TYPE_BACK_SIDE + } + ).listen() + ); + } else if (property === 'combine') { + handles.push( + folder.add( + object, + property, + { + 'multiply': GameLib.D3.Material.TYPE_MULTIPLY_OPERATION, + 'mix': GameLib.D3.Material.TYPE_MIX_OPERATION, + 'add': GameLib.D3.Material.TYPE_ADD_OPERATION + } + ).listen() + ); + } else if (property === 'vertexColors') { + handles.push( + folder.add( + object, + property, + { + 'none': GameLib.D3.Material.TYPE_NO_COLORS, + 'face': GameLib.D3.Material.TYPE_FACE_COLORS, + 'vertex': GameLib.D3.Material.TYPE_VERTEX_COLORS + } + ).listen() + ); + } else if (property === 'blending') { + handles.push( + folder.add( + object, + property, + { + 'normal': GameLib.D3.Material.TYPE_NORMAL_BLENDING, + 'additive': GameLib.D3.Material.TYPE_ADDITIVE_BLENDING, + 'subtractive': GameLib.D3.Material.TYPE_SUBTRACTIVE_BLENDING, + 'multiply': GameLib.D3.Material.TYPE_MULTIPLY_BLENDING + } + ).listen() + ); + } else if (property === 'blendSrc') { + handles.push( + folder.add( + object, + property,- + { + 'zero': GameLib.D3.Material.TYPE_ZERO_FACTOR, + 'one': GameLib.D3.Material.TYPE_ONE_FACTOR, + 'source color': GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR, + 'one minus source color': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR, + 'source alpha': GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR, + 'one minus source alpha': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR, + 'destination alpha': GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR, + 'one minus destination alpha': GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR, + 'destination color': GameLib.D3.Material.TYPE_DST_COLOR_FACTOR, + 'one minus destination color': GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR, + 'source alpha saturate': GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR + } + ).listen() + ); + } else if (property === 'blendDst') { + handles.push( + folder.add( + object, + property, + { + 'zero': GameLib.D3.Material.TYPE_ZERO_FACTOR, + 'one': GameLib.D3.Material.TYPE_ONE_FACTOR, + 'source color': GameLib.D3.Material.TYPE_SRC_COLOR_FACTOR, + 'one minus source color': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_COLOR_FACTOR, + 'source alpha': GameLib.D3.Material.TYPE_SRC_ALPHA_FACTOR, + 'one minus source alpha': GameLib.D3.Material.TYPE_ONE_MINUS_SRC_ALPHA_FACTOR, + 'destination alpha': GameLib.D3.Material.TYPE_DST_ALPHA_FACTOR, + 'one minus destination alpha': GameLib.D3.Material.TYPE_ONE_MINUS_DST_ALPHA_FACTOR, + 'destination color': GameLib.D3.Material.TYPE_DST_COLOR_FACTOR, + 'one minus destination color': GameLib.D3.Material.TYPE_ONE_MINUS_DST_COLOR_FACTOR, + 'source alpha saturate': GameLib.D3.Material.TYPE_SRC_ALPHA_SATURATE_FACTOR + } + ).listen() + ); + } else if (property === 'blendEquation') { + handles.push( + folder.add( + object, + property, + { + 'add': GameLib.D3.Material.TYPE_ADD_EQUATION, + 'subtract': GameLib.D3.Material.TYPE_SUBTRACT_EQUATION, + 'reverse subtract': GameLib.D3.Material.TYPE_REVERSE_SUBTRACT_EQUATION, + 'min': GameLib.D3.Material.TYPE_MIN_EQUATION, + 'max': GameLib.D3.Material.TYPE_MAX_EQUATION + } + ).listen() + ); + } else if (property === 'depthFunc') { + handles.push( + folder.add( + object, + property, + { + 'never': GameLib.D3.Material.TYPE_NEVER_DEPTH, + 'always': GameLib.D3.Material.TYPE_ALWAYS_DEPTH, + 'less depth': GameLib.D3.Material.TYPE_LESS_DEPTH, + 'less equal depth': GameLib.D3.Material.TYPE_LESS_EQUAL_DEPTH, + 'equal depth': GameLib.D3.Material.TYPE_EQUAL_DEPTH, + 'greated equal depth': GameLib.D3.Material.TYPE_GREATER_EQUAL_DEPTH, + 'greated depth': GameLib.D3.Material.TYPE_GREATER_DEPTH, + 'not equal depth': GameLib.D3.Material.TYPE_NOT_EQUAL_DEPTH + } + ).listen() + ); + } else if (property === 'wrapS') { + handles.push( + folder.add( + object, + property, + { + 'repeat': GameLib.D3.Texture.TYPE_REPEAT_WRAPPING, + 'clamp': GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING, + 'mirrored repeat': GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING + } + ).listen() + ); + } else if (property === 'wrapT') { + handles.push( + folder.add( + object, + property, + { + 'repeat': GameLib.D3.Texture.TYPE_REPEAT_WRAPPING, + 'clamp': GameLib.D3.Texture.TYPE_CLAMP_TO_EDGE_WRAPPING, + 'mirrored repeat': GameLib.D3.Texture.TYPE_MIRRORED_REPEAT_WRAPPING + } + ).listen() + ); + } else if (property === 'format') { + handles.push( + folder.add( + object, + property, + { + 'alpha': GameLib.D3.Texture.TYPE_ALPHA_FORMAT, + 'rgb': GameLib.D3.Texture.TYPE_RGB_FORMAT, + 'rgba': GameLib.D3.Texture.TYPE_RGBA_FORMAT, + 'luminance': GameLib.D3.Texture.TYPE_LUMINANCE_FORMAT, + 'luminance alpha': GameLib.D3.Texture.TYPE_LUMINANCE_ALPHA_FORMAT, + 'depth': GameLib.D3.Texture.TYPE_DEPTH_FORMAT + } + ).listen() + ); + } else if (property === 'mapping') { + handles.push( + folder.add( + object, + property, + { + 'uv': GameLib.D3.Texture.TYPE_UV_MAPPING, + 'cube reflection': GameLib.D3.Texture.TYPE_CUBE_REFLECTION_MAPPING, + 'cube refraction': GameLib.D3.Texture.TYPE_CUBE_REFRACTION_MAPPING, + 'equi rectangular reflection': GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFLECTION_MAPPING, + 'equi rectangular refraction': GameLib.D3.Texture.TYPE_EQUI_RECTANGULAR_REFRACTION_MAPPING, + 'spherical reflection': GameLib.D3.Texture.TYPE_SPHERICAL_REFLECTION_MAPPING, + 'cube uv reflection': GameLib.D3.Texture.TYPE_CUBE_UV_REFLECTION_MAPPING, + 'cube uv refraction': GameLib.D3.Texture.TYPE_CUBE_UV_REFRACTION_MAPPING + } + ).listen() + ); + } else if (property === 'magFilter') { + handles.push( + folder.add( + object, + property, + { + 'nearest': GameLib.D3.Texture.TYPE_NEAREST_FILTER, + 'nearest mipmap nearest': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER, + 'nearest mipmap linear': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER, + 'linear': GameLib.D3.Texture.TYPE_LINEAR_FILTER, + 'linear mipmap nearest': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER, + 'linear mipmap linear': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER + } + ).listen() + ); + } else if (property === 'minFilter') { + handles.push(folder.add( + object, + property, + { + 'nearest': GameLib.D3.Texture.TYPE_NEAREST_FILTER, + 'nearest mipmap nearest': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_NEAREST_FILTER, + 'nearest mipmap linear': GameLib.D3.Texture.TYPE_NEAREST_MIPMAP_LINEAR_FILTER, + 'linear': GameLib.D3.Texture.TYPE_LINEAR_FILTER, + 'linear mipmap nearest': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_NEAREST_FILTER, + 'linear mipmap linear': GameLib.D3.Texture.TYPE_LINEAR_MIPMAP_LINEAR_FILTER + } + ).listen() + ); + } else if (componentType === GameLib.Component.COMPONENT_TEXTURE && property === 'typeId') { + handles.push( + folder.add( + object, + property, + { + 'normal': GameLib.D3.Texture.TEXTURE_TYPE_NORMAL, + 'cube': GameLib.D3.Texture.TEXTURE_TYPE_CUBE + } + ).listen() + ); + } else if (property === 'textureType') { + handles.push( + folder.add( + object, + property, + { + 'unsigned byte': GameLib.D3.Texture.TYPE_UNSIGNED_BYTE, + 'byte': GameLib.D3.Texture.TYPE_BYTE, + 'short': GameLib.D3.Texture.TYPE_SHORT, + 'unsigned short': GameLib.D3.Texture.TYPE_UNSIGNED_SHORT, + 'int': GameLib.D3.Texture.TYPE_INT, + 'unsigned int': GameLib.D3.Texture.TYPE_UNSIGNED_INT, + 'float': GameLib.D3.Texture.TYPE_FLOAT, + 'half float': GameLib.D3.Texture.TYPE_HALF_FLOAT + } + ).listen() + ); + } else if (property === 'encoding') { + handles.push( + folder.add( + object, + property, + { + 'linear': GameLib.D3.Texture.TYPE_LINEAR_ENCODING, + 'srgb': GameLib.D3.Texture.TYPE_SRGB_ENCODING, + 'gamma': GameLib.D3.Texture.TYPE_GAMMA_ENCODING, + 'rgbe': GameLib.D3.Texture.TYPE_RGBE_ENCODING, + 'log luv': GameLib.D3.Texture.TYPE_LOG_LUV_ENCODING, + 'rgbm7': GameLib.D3.Texture.TYPE_RGBM7_ENCODING, + 'rgbm16': GameLib.D3.Texture.TYPE_RGBM16_ENCODING, + 'rgbd': GameLib.D3.Texture.TYPE_RGBD_ENCODING + } + ).listen() + ); + } else if (property === 'lightType') { + handles.push( + folder.add( + object, + property, + { + 'ambient': GameLib.D3.Light.LIGHT_TYPE_AMBIENT, + 'directional': GameLib.D3.Light.LIGHT_TYPE_DIRECTIONAL, + 'spot': GameLib.D3.Light.LIGHT_TYPE_SPOT, + 'point': GameLib.D3.Light.LIGHT_TYPE_POINT + } + ).listen() + ); + } else { + + /** + * Try to guess a scale for this property + */ + if ( + property === 'opacity' || + property === 'metalness' || + property === 'roughness' + ) { + handles.push(folder.add(object, property, 0, 1.0, 0.001).listen()); + } else if ( + property === 'shininess' || + property === 'fov' + ) { + handles.push(folder.add(object, property, -255, 255, 1).listen()); + } else if ( + property === 'aspect' + ) { + handles.push(folder.add(object, property, 0, 5, 0.001).listen()); + } else if ( + property === 'widthSegments' || + property === 'heightSegments' + ) { + handles.push(folder.add(object, property, 1, 1000, 1).listen()); + } else if ( + property === 'angle' || + property === 'width' || + property === 'height' || + property === 'depth' + ) { + handles.push(folder.add(object, property, -1000, 1000, 1).listen()); + } else if ( + property === 'near' || + property === 'distanceGrain' || + property === 'bumpScale' || + property === 'envMapIntensity' + ) { + handles.push(folder.add(object, property, -10, 100, 0.001).listen()); + } else if ( + property === 'heightOffset' || + property === 'rotationFactor' + ) { + handles.push(folder.add(object, property, -100, 100, 0.001).step(0.001).listen()); + } else { + handles.push(folder.add(object, property, -10000, 10000, grain).listen()); + } + } + } + + handles.map( + function(handle) { + if (property === 'name') { + handle.onFinishChange( + function(__handle) { + return function(value) { + componentTemplate.affected.map( + function(component){ + component[property] = value; + component.updateInstance(); + } + ); + } + }(handle) + ); + } else { + handle.onChange( + function (value) { + + if (typeof this.initialValue === 'number') { + value = Number(value); + } + + componentTemplate.affected.map( + function(component){ + component[property] = value; + component.updateInstance(); + } + ); + } + ); + } + } + ); + +}; + +/** + * Push the mesh to our backup components, if in exclusiveMode (menu at top is selected), + * otherwise, just to our normal components + * @param data + */ +GameLib.System.GUI.prototype.meshSelected = function(data) { + + if (this.exclusiveMode) { + GameLib.Utils.PushUnique(this.backupComponents, data.mesh); + } else { + GameLib.Utils.PushUnique(this.components, data.mesh); + } + +}; + +/** + * Same as selected above, but removes the mesh from the components + * @param data + */ +GameLib.System.GUI.prototype.meshDeslected = function(data) { + + var index = -1; + + if (this.exclusiveMode) { + index = this.backupComponents.indexOf(data.mesh); + if (index !== -1) { + this.backupComponents.splice(index, 1); + } + } else { + index = this.components.indexOf(data.mesh); + if (index !== -1) { + this.components.splice(index, 1); + } + } + +}; + +/** + * This function responds to the BUILD_GUI event, data contains the components to build a GUI for + * @param data + */ GameLib.System.GUI.prototype.buildGUI = function(data) { this.guis.map(function(gui){ /** - * Check if we have data - */ - if (GameLib.Utils.UndefinedOrNull(data.components)) { - console.log('no data components'); - return; - } - - if (GameLib.Utils.UndefinedOrNull(data.components.length) || data.components.length === 0) { - console.log('no components selected'); - return; - } - - /** - * First, start fresh - remove all folders + * First, start fresh - remove all folders */ gui.removeAllFolders(); + if (data) { + + if (data.components) { + + this.exclusiveMode = true; + + /** + * Backup the current selection + */ + this.backupComponents = this.components.map( + function(component) { + return component; + } + ); + + this.components = data.components.map( + function(component) { + return component; + } + ); + } else { + + this.exclusiveMode = false; + + /** + * Time to restore the backup + */ + this.components = this.backupComponents.map( + function(component) { + return component; + } + ) + } + } + + /** + * For all mesh components - (if not in exclusive mode) - try to discover all materials, textures, etc + */ + if (!this.exclusiveMode) { + + /** + * We first remove everything which is not a Mesh + */ + this.components = this.components.filter( + function (component) { + return (component instanceof GameLib.D3.Mesh); + } + ); + } + + /** + * Check if we have components to build a GUI for + */ + if (GameLib.Utils.UndefinedOrNull(this.components.length) || this.components.length < 1) { + console.log('no components selected'); + return; + } + + /** + * Now continue to discover materials, textures, images etc. children of this component + */ + if (!this.exclusiveMode) { + + this.components = this.components.reduce( + function(result, component) { + + var components = component.getChildrenComponents(); + + GameLib.Utils.PushUnique(result, component); + + components.map(function(component){ + GameLib.Utils.PushUnique(result, component); + }); + + return result; + }.bind(this), + [] + ); + } + /** * Sort the components by component type */ - data.components.sort( + this.components.sort( function(a, b) { @@ -143,7 +972,7 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { /** * Split the components into groups of componentType */ - var componentGroups = data.components.reduce( + var componentGroups = this.components.reduce( function(result, component) { var componentData = result.pop(); @@ -169,12 +998,49 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { }, [ { - componentType : data.components[0].componentType, + componentType : this.components[0].componentType, components : [] } ] ); + /** + * We have all the components split into groups - now add the individual components + */ + this.components.map( + function(component) { + + /** + * Check for possible duplicates + * @type {boolean} + */ + var duplicate = false; + componentGroups.map(function(componentGroup){ + + if ( + componentGroup.componentType === component.componentType && + componentGroup.components.length === 1 && + componentGroup.components[0] === component + ) { + duplicate = true; + } + }); + + if (!duplicate) { + GameLib.Utils.PushUnique( + componentGroups, + { + componentType : component.componentType, + components : [component] + } + ); + } + } + ); + + /** + * componentGroups should now contain the whole list of stuff we want to build GUI for. + */ componentGroups.map( function(componentGroup){ @@ -281,7 +1147,7 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { var name; if (GameLib.Utils.UndefinedOrNull(componentTemplate.template.name)) { - name = GameLib.Component.GetComponentName(componentTemplate.componentType); + name = GameLib.Component.GetComponentName(componentTemplate.componentType) + ' (All Selected (' + componentTemplate.affected.length + '))'; } else { name = componentTemplate.template.name; } @@ -289,7 +1155,7 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { var folder = gui.addFolder(name); if (!folder) { - throw new Error('Could not create folder'); + return; } for (var templateProperty in componentTemplate.template) { @@ -305,20 +1171,38 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { } if (componentTemplate.template[templateProperty] instanceof GameLib.Vector2) { - gui.buildVectorControl(folder, componentTemplate, templateProperty, 2); + this.buildVectorControl(folder, componentTemplate, templateProperty, 2); continue; } if (componentTemplate.template[templateProperty] instanceof GameLib.Vector3) { - gui.buildVectorControl(folder, componentTemplate, templateProperty, 3); + this.buildVectorControl(folder, componentTemplate, templateProperty, 3); continue; } if (componentTemplate.template[templateProperty] instanceof GameLib.Vector4) { - gui.buildVectorControl(folder, componentTemplate, templateProperty, 4); + this.buildVectorControl(folder, componentTemplate, templateProperty, 4); continue; } + if (templateProperty === 'parentEntity') { + this.buildEntitySelectionControl(folder, componentTemplate); + continue; + } + + if (componentTemplate.template[templateProperty] instanceof Array) { + this.buildArrayManagerControl(folder, componentTemplate, templateProperty); + continue; + } + + if (typeof componentTemplate.template[templateProperty] === 'object') { + /** + * ignore objects for now + */ + continue; + } + + this.buildControl(folder, componentTemplate, templateProperty); // if ( // component.linkedObjects && // component.linkedObjects[property] @@ -356,83 +1240,37 @@ GameLib.System.GUI.prototype.buildGUI = function(data) { } } - } + }.bind(this) ); - }); + }.bind(this)); }; GameLib.System.GUI.prototype.meshDeleted = function(data) { + data.meshes.map(function(mesh){ + this.meshDeslected({ + mesh : mesh + }) + }.bind(this)); + + this.buildGUI(null); }; -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) { +GameLib.System.GUI.prototype.removeComponent = function(data) { + var index = this.backupComponents.indexOf(data.component); + if (index !== -1) { + this.backupComponents.splice(index, 1); + } + index = this.components.indexOf(data.component); + if (index !== -1) { + this.components.splice(index, 1); + } }; -GameLib.System.GUI.prototype.meshDeslected = function(data) { - -}; GameLib.System.GUI.prototype.newEntity = function(data) { @@ -458,6 +1296,8 @@ GameLib.System.GUI.prototype.stop = function() { this.newEntitySubscription.remove(); + this.componentRemovedSubscription.remove(); + this.guis = []; }; diff --git a/src/game-lib-system-input.js b/src/game-lib-system-input.js index 429921a..745899e 100644 --- a/src/game-lib-system-input.js +++ b/src/game-lib-system-input.js @@ -26,7 +26,7 @@ GameLib.System.Input.prototype.start = function() { var component = entity.getFirstComponent(GameLib.D3.Input.Editor); - component.mouseDown = component.onMouseDown(entity, GameLib.EntityManager.Instance).bind(component); + component.mouseDown = component.onMouseDown(entity).bind(component); component.mouseMove = component.onMouseMove(entity).bind(component); component.keyDown = component.onKeyDown(entity, GameLib.EntityManager.Instance).bind(component); component.keyUp = component.onKeyUp(entity, GameLib.EntityManager.Instance).bind(component); diff --git a/src/game-lib-system-linking.js b/src/game-lib-system-linking.js index 9a0d0ba..2e0554c 100644 --- a/src/game-lib-system-linking.js +++ b/src/game-lib-system-linking.js @@ -34,6 +34,7 @@ GameLib.System.Linking = function( this.imageInstanceCreatedSubscription = null; this.textureInstanceCreatedSubscription = null; this.materialInstanceCreatedSubscription = null; + this.meshDeletedSubscription = null; }; GameLib.System.Linking.prototype = Object.create(GameLib.System.prototype); @@ -89,7 +90,12 @@ GameLib.System.Linking.prototype.start = function() { this.imageNotFoundSubscription = this.subscribe( GameLib.Event.IMAGE_NOT_FOUND, this.imageNotFound - ) + ); + + this.meshDeletedSubscription = this.subscribe( + GameLib.Event.MESH_DELETED, + this.meshDeleted + ); }; GameLib.System.Linking.prototype.link = function(component, data) { @@ -540,6 +546,88 @@ GameLib.System.Linking.prototype.onParentEntityChange = function(data) { }; +/** + * When a mesh is deleted - build a list of all the mesh children objects - also - find out if any of these + * children objects are in use by another object - if it is - don't delete it, otherwise, do + * @param data + */ +GameLib.System.Linking.prototype.meshDeleted = function(data) { + + console.log('to delete'); + + /** + * First we get the list of all components we would like to delete + */ + var componentsToDelete = data.meshes.reduce( + function(result, mesh) { + + result.push(mesh); + + var components = mesh.getChildrenComponents(); + + components.map(function(component){ + result.push(component); + }); + + return result; + }, + [] + ); + + /** + * Now, we want to get a list of all the meshes which we don't want to delete, and all their children + */ + var meshes = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.Mesh); + meshes = meshes.filter(function(mesh){ + return data.meshes.indexOf(mesh) === -1; + }); + + /** + * Now we have a list of meshes still in use in meshes, now find all their children + */ + var componentsInUse = meshes.reduce( + function(result, mesh) { + + result.push(mesh); + + var components = mesh.getChildrenComponents(); + + components.map(function(component){ + result.push(component); + }); + + return result; + }, + [] + ); + + /** + * Now we don't want to remove any children in use, so filter out the components in use + */ + componentsToDelete = componentsToDelete.filter( + function(component) { + return componentsInUse.indexOf(component) === -1; + } + ); + + /** + * componentsToDelete should now be the final list of components to delete + */ + componentsToDelete.map(function(component){ + GameLib.Event.Emit( + GameLib.Event.COMPONENT_REMOVE, + { + component : component + } + ) + }); + + GameLib.Event.Emit( + GameLib.Event.BUILD_GUI, + null + ); +}; + GameLib.System.Linking.prototype.stop = function() { this.imageNotFoundSubscription.remove(); this.componentCreatedSubscription.remove(); @@ -551,5 +639,6 @@ GameLib.System.Linking.prototype.stop = function() { this.imageInstanceCreatedSubscription.remove(); this.textureInstanceCreatedSubscription.remove(); this.materialInstanceCreatedSubscription.remove(); + this.meshDeletedSubscription.remove(); };