From 7d58a692e6fa0a9bc6ddfc4a02397d7771a94bbf Mon Sep 17 00:00:00 2001
From: Amanda Ghassaei <amandaghassaei@gmail.com>
Date: Wed, 12 Aug 2015 16:35:21 -0400
Subject: [PATCH] beginning to do component tree editing

---
 js/cam/assemblers/Assembler.js                | 45 +++++++--
 js/cam/assemblers/Component.js                | 97 +++++++++++++++++--
 js/cam/assemblers/StaplerAssembler.js         | 12 +--
 js/cam/cam.js                                 |  6 +-
 js/menus/AssemblerSetupMenuView.js            |  3 +-
 js/menus/EditComponentMenuView.js             | 13 ++-
 .../templates/AssemblerSetupMenuView.html     | 15 ++-
 js/menus/templates/EditComponentMenuView.html | 21 ++--
 8 files changed, 175 insertions(+), 37 deletions(-)

diff --git a/js/cam/assemblers/Assembler.js b/js/cam/assemblers/Assembler.js
index e53d0404..ea57acac 100644
--- a/js/cam/assemblers/Assembler.js
+++ b/js/cam/assemblers/Assembler.js
@@ -8,6 +8,7 @@ define(['underscore', 'appState', 'lattice', 'three', 'threeModel', 'cam', 'comp
     
     function Assembler(){
 
+        this.components = {};
         this.stock = this._buildStock();
         this._positionStockRelativeToEndEffector(this.stock);
 
@@ -31,9 +32,20 @@ define(['underscore', 'appState', 'lattice', 'three', 'threeModel', 'cam', 'comp
         var allSTLs = this._getSTLs();
         var self = this;
         _.each(allSTLs, function(geometry, name){
-            self[name] = new Component(geometry, assemblerMaterial);
+            var component = new Component(geometry, assemblerMaterial, name);
+            self.components[component.getID()] = component;
         });
     };
+
+    Assembler.prototype.getComponentByName = function(name){
+        return _.find(_.values(this.components), function(component){
+            return component.name == name;
+        });
+    };
+
+    Assembler.prototype.getComponentById = function(id){
+        return this.components[id];
+    };
     
     Assembler.prototype._configureAssemblerMovementDependencies = function(){
         //override in subclasses
@@ -46,7 +58,7 @@ define(['underscore', 'appState', 'lattice', 'three', 'threeModel', 'cam', 'comp
     };
     
     Assembler.prototype._setTranslucent = function(){
-        assemblerMaterial.transparent = (appState.get("currentTab") == "cam");
+        assemblerMaterial.transparent = (appState.get("currentTab") == "cam" || appState.get("currentTab") == "assemblerSetup");
     };
 
     Assembler.prototype.moveMachine = function(){//origin selection
@@ -208,15 +220,15 @@ define(['underscore', 'appState', 'lattice', 'three', 'threeModel', 'cam', 'comp
     
     
     
-    
+    //helper
     
     Assembler.prototype.destroy = function(){
-        this.stock.destroy();
-        this.zAxis.destroy();
-        this.xAxis.destroy();
-        this.yAxis.destroy();
-        this.frame.destroy();
-        this.substrate.destroy();
+        var self = this;
+        _.each(this.components, function(component, index){
+            component.destroy();
+            self[index] = null;
+        });
+        this.components = null;
         three.sceneRemove(this.object3D);
         this.stock = null;
         this.zAxis = null;
@@ -227,5 +239,20 @@ define(['underscore', 'appState', 'lattice', 'three', 'threeModel', 'cam', 'comp
         this.object3D = null;
     };
 
+    Assembler.prototype.toJSON = function(){
+        var componentsJSON = {};
+        _.each(this.components, function(component, id){
+            componentsJSON[id] = component.toJSON();
+        });
+        return {
+            components: componentsJSON,
+            translation: this.object3D.position,
+            scale: this.object3D.scale.x,
+            rotation: this.object3D.rotation
+        }
+    };
+
+
+
     return Assembler;
 });
diff --git a/js/cam/assemblers/Component.js b/js/cam/assemblers/Component.js
index 9fa4e15b..4579565a 100644
--- a/js/cam/assemblers/Component.js
+++ b/js/cam/assemblers/Component.js
@@ -5,10 +5,67 @@
 
 define(['underscore', 'cam', 'three'], function(_, cam, THREE){
 
-    function Component(geometry, material){
+    var id = 0;
+
+    function Component(geometry, material, name){
         this.object3D = new THREE.Mesh(geometry, material);
+        this.id = "id" + id++;
+        this.name = name || "";
+        this.parent = null;
+        this.children = [];
     }
 
+    //assembler setup
+
+    Component.prototype.addChild = function(child){
+        if (this.checkAncestry(child)){
+            console.warn("can't add parent as child");
+            return;
+        }
+        if (this.children.indexOf(child)>-1){
+            console.warn("already added as a child");
+            return;
+        }
+        if (child.addParent){//todo stock has no "addParent" or id
+            this.children.push(child);
+            child.addParent(this);
+        }
+        this.object3D.add(child.getObject3D());
+    };
+
+    Component.prototype.checkAncestry = function(component){//return true if this is a parent/grandparent/great-grandparent...
+        if (this.parent){
+            if (this.parent === component) return true;
+            else return this.parent.checkAncestry(component);
+        }
+        return false;
+    };
+
+    Component.prototype.removeChild = function(child){
+        if (this.children.indexOf(child) == -1){
+            console.warn("not a child");
+            return;
+        }
+        this.children.splice(this.children.indexOf(child),1);
+        this.object3D.remove(child.getObject3D());
+    };
+
+    Component.prototype.addParent = function(parent){
+        if (this.parent) {
+            this.parent.removeChild(this);
+            this.parent = null;
+        }
+        this.parent = parent;
+    };
+
+    Component.prototype.getID = function(){
+        return this.id;
+    };
+
+
+
+    //simulation animation
+
     Component.prototype.getPosition = function(){
         return this.object3D.position.clone();
     };
@@ -17,10 +74,6 @@ define(['underscore', 'cam', 'three'], function(_, cam, THREE){
         return this.object3D;
     };
 
-    Component.prototype.addChild = function(child){
-        this.object3D.add(child.getObject3D());
-    };
-
     Component.prototype.moveTo = function(target, speed, callback){
         var currentPosition = this.getPosition();
         var diff = _.clone(target);
@@ -84,10 +137,42 @@ define(['underscore', 'cam', 'three'], function(_, cam, THREE){
         }, 10);
     };
 
+
+
+
+
+    //helper
+
     Component.prototype.destroy = function(){
-        if (this.object3D && this.object3D.parent) this.object3D.parent.remove(this.object3D);
+        if (this.parent) this.parent.removeChild(this);
+        this.parent = null;
+        var self = this;
+        _.each(this.children, function(child){
+            self.removeChild(child);
+        });
+        this.children = null;
+        this.name = null;
         this.object3D = null;
     };
 
+
+    Component.prototype.toJSON = function(){
+        var childIds = [];
+        _.each(this.children, function(child){
+            childIds.push(child.id);
+        });
+        var parentName = "";
+        if (this.parent) parentName = this.parent.name;
+        return {
+            id: this.id,
+            name: this.name,
+            children: childIds,
+            parent: parentName,
+            translation: this.object3D.position,
+            scale: this.object3D.scale.x,
+            rotation: this.object3D.rotation
+        }
+    };
+
     return Component;
 });
\ No newline at end of file
diff --git a/js/cam/assemblers/StaplerAssembler.js b/js/cam/assemblers/StaplerAssembler.js
index 6c58aa87..5b5f36c7 100644
--- a/js/cam/assemblers/StaplerAssembler.js
+++ b/js/cam/assemblers/StaplerAssembler.js
@@ -44,12 +44,12 @@ define(['underscore', 'assembler', 'stlLoader', 'gikSuperCell',
     };
 
     StaplerAssembler.prototype._configureAssemblerMovementDependencies = function(){
-        this.zAxis.addChild(this.stock);
-        this.xAxis.addChild(this.zAxis);
-        this.frame.addChild(this.xAxis);
-        this.frame.addChild(this.yAxis);
-        this.object3D.add(this.frame.getObject3D());
-        this.object3D.add(this.substrate.getObject3D());
+        this.getComponentByName("zAxis").addChild(this.stock);
+        this.getComponentByName("xAxis").addChild(this.getComponentByName("zAxis"));
+        this.getComponentByName("frame").addChild(this.getComponentByName("xAxis"));
+        this.getComponentByName("frame").addChild(this.getComponentByName("yAxis"));
+        this.getComponentByName("substrate").addChild(this.getComponentByName("frame"));
+        this.object3D.add(this.getComponentByName("substrate").getObject3D());
     };
 
     StaplerAssembler.prototype._getSTLs = function(){
diff --git a/js/cam/cam.js b/js/cam/cam.js
index 910934e3..39f1715a 100644
--- a/js/cam/cam.js
+++ b/js/cam/cam.js
@@ -16,6 +16,8 @@ define(['underscore', 'three', 'backbone', 'appState', 'latticeCAM', 'threeModel
             assembler: null,
             exporter: null,
 
+            editingComponent: null,
+
             dataOut: "",
             needsPostProcessing: true,
             editsMadeToProgram: false,//warn the user that they will override changes
@@ -84,7 +86,7 @@ define(['underscore', 'three', 'backbone', 'appState', 'latticeCAM', 'threeModel
             this._navChanged();
     //        this._initOriginAndStock();
 
-
+            this.selectMachine();
         },
 
 
@@ -186,7 +188,7 @@ define(['underscore', 'three', 'backbone', 'appState', 'latticeCAM', 'threeModel
 
         isVisible: function(){
             var currentTab = appState.get("currentTab");
-            return (currentTab == "cam" || currentTab == "animate" || currentTab == "send");
+            return (currentTab == "assemblerSetup" || currentTab == "cam" || currentTab == "animate" || currentTab == "send");
         },
 
 
diff --git a/js/menus/AssemblerSetupMenuView.js b/js/menus/AssemblerSetupMenuView.js
index 2b363cc6..d5074c23 100644
--- a/js/menus/AssemblerSetupMenuView.js
+++ b/js/menus/AssemblerSetupMenuView.js
@@ -19,6 +19,7 @@ define(['jquery', 'underscore', 'menuParent', 'plist', 'cam', 'text!assemblerSet
 
         _editMachineComponent: function(e){
             e.preventDefault();
+            cam.set("editingComponent", $(e.target).data("id"));
             this.model.set("currentNav", "navMachineComponent");
         },
 
@@ -28,7 +29,7 @@ define(['jquery', 'underscore', 'menuParent', 'plist', 'cam', 'text!assemblerSet
         },
 
         _makeTemplateJSON: function(){
-            return _.extend(this.model.toJSON(), cam.toJSON());
+            return _.extend(this.model.toJSON(), cam.toJSON(), cam.get("assembler").toJSON());
         },
 
         template: _.template(template)
diff --git a/js/menus/EditComponentMenuView.js b/js/menus/EditComponentMenuView.js
index 0489c74f..c1211846 100644
--- a/js/menus/EditComponentMenuView.js
+++ b/js/menus/EditComponentMenuView.js
@@ -17,22 +17,23 @@ define(['jquery', 'underscore', 'menuParent', 'plist', 'cam', 'text!editComponen
         },
 
         _initialize: function(){
-
         },
 
         _save: function(e){
             e.preventDefault();
             console.log("save component");
+            this._stopEditing();
         },
 
         _cancel: function(e){
             e.preventDefault();
-            this.model.set("currentNav", "navAssemble");
+            this._stopEditing();
         },
 
         _delete: function(e){
             e.preventDefault();
             console.log("delete component");
+            this._stopEditing();
         },
 
         _saveToFile: function(e){
@@ -40,15 +41,21 @@ define(['jquery', 'underscore', 'menuParent', 'plist', 'cam', 'text!editComponen
             console.log("save component to file");
         },
 
+        _stopEditing: function(){
+            cam.set("editingComponent", null);
+            this.model.set("currentNav", "navAssemble");
+        },
+
         _removeChild: function(e){
             e.preventDefault();
             console.log("remove child");
         },
 
         _makeTemplateJSON: function(){
-            return _.extend(this.model.toJSON(), cam.toJSON(), {translation:{x:1, y:2, z:3}, scale:2, rotation:{x:0,y:90,z:127}});
+            return _.extend(this.model.toJSON(), cam.toJSON(), cam.get("assembler").toJSON());
         },
 
         template: _.template(template)
+
     });
 });
\ No newline at end of file
diff --git a/js/menus/templates/AssemblerSetupMenuView.html b/js/menus/templates/AssemblerSetupMenuView.html
index 51a9cb9e..944d3ff2 100644
--- a/js/menus/templates/AssemblerSetupMenuView.html
+++ b/js/menus/templates/AssemblerSetupMenuView.html
@@ -1,6 +1,17 @@
-Parent/Child Tree:<br/><br/>
-Component 1 <a class="editMachineComponent" href="#">Edit</a><br/><br/>
+Parent/Child Tree:<br/>
+<% _.each(components, function(component){ %>
+    <%= component.name %> <a data-id="<%= component.id %>" class="editMachineComponent" href="#">Edit</a><br/>
+<% }); %><br/>
 <a href="#" id="newMachineComponent" class=" btn btn-block btn-lg btn-default">+ New Machine Component</a><br/>
+Offset (xyz):&nbsp;&nbsp;
+    <input data-property="translation" data-key="x" value="<%= translation.x %>" placeholder="X" class="form-control floatInput component" type="text">&nbsp;
+    <input data-property="translation" data-key="y" value="<%= translation.y %>" placeholder="Y" class="form-control floatInput component" type="text">&nbsp;
+    <input data-property="translation" data-key="z" value="<%= translation.z %>" placeholder="Z" class="form-control floatInput component" type="text"><br/><br/>
+Rotation (xyz):&nbsp;&nbsp;
+    <input data-property="rotation" data-key="x" value="<%= rotation.x %>" placeholder="X" class="form-control floatInput component" type="text">&nbsp;
+    <input data-property="rotation" data-key="y" value="<%= rotation.y %>" placeholder="Y" class="form-control floatInput component" type="text">&nbsp;
+    <input data-property="rotation" data-key="z" value="<%= rotation.z %>" placeholder="Z" class="form-control floatInput component" type="text"><br/><br/>
+Scale: &nbsp;&nbsp;<input data-property="scale" value="<%= scale %>" placeholder="Scale" class="form-control floatInput component" type="text"><br/><br/>
 Edit Code:<br/><br/>
 Header  <a class="editMachineCode" href="#">Edit</a><br/>
 Go Home <a class="editMachineCode" href="#">Edit</a><br/>
diff --git a/js/menus/templates/EditComponentMenuView.html b/js/menus/templates/EditComponentMenuView.html
index 9f51ce18..79c7232c 100644
--- a/js/menus/templates/EditComponentMenuView.html
+++ b/js/menus/templates/EditComponentMenuView.html
@@ -1,22 +1,27 @@
-Name: &nbsp;&nbsp;<input data-property="name" value="name" placeholder="Enter Name" class="seventyFiveWidth form-control textInput component" type="text"><br/><br/>
+Name: &nbsp;&nbsp;<input data-property="name" value="<%= components[editingComponent].name %>" placeholder="Enter Name" class="seventyFiveWidth form-control textInput component" type="text"><br/><br/>
 Parent: &nbsp;&nbsp;
     <div class="btn-group">
-        <button data-toggle="dropdown" class="btn dropdown-toggle" type="button">my parent<span class="caret"></span></button>
+        <button data-toggle="dropdown" class="btn dropdown-toggle" type="button"><%= components[editingComponent].parent || "No Parent Selected" %><span class="caret"></span></button>
         <ul role="menu" class="dropdown-menu">
-            <li><a class="component dropdownSelector" data-property="parent" data-value="thing" href="#">thing 1</a></li>
-            <li><a class="component dropdownSelector" data-property="parent" data-value="thing" href="#">thing 2</a></li>
+            <% _.each(components, function(component){ %>
+                <% if (component.id == editingComponent) return; %>
+                <li><a class="component dropdownSelector" data-property="parent" data-value="<%= component.id %>" href="#"><%= component.name %></a></li>
+            <% }); %>
         </ul>
     </div><br/><br/>
 Children: &nbsp;&nbsp;
 <div class="btn-group">
     <button data-toggle="dropdown" class="btn dropdown-toggle" type="button">+ Add Child<span class="caret"></span></button>
     <ul role="menu" class="dropdown-menu">
-        <li><a class="component dropdownSelector" data-property="parent" data-value="thing" href="#">thing 1</a></li>
-        <li><a class="component dropdownSelector" data-property="parent" data-value="thing" href="#">thing 2</a></li>
+        <% _.each(components, function(component, id){ %>
+            <% if (component.id == editingComponent || component.id == components[editingComponent].parent) return; %>
+            <li><a class="component dropdownSelector" data-property="newChild" data-value="<%= id %>" href="#"><%= component.name %></a></li>
+        <% }); %>
     </ul>
 </div><br/>
-    child 1 <a href="#" class="removeChild">Remove</a><br/>
-    child 2 <a href="#" class="removeChild">Remove</a><br/><br/>
+    <% _.each(components[editingComponent].children, function(childID){ console.log(components[editingComponent].children);%>
+        <%= components[childID].name %> <a class="removeChild" data-id="<%= childID %>" href="#">Remove</a><br/>
+    <% }); %><br/>
 STL: &nbsp;&nbsp;STL Name<br/><br/>
 <a id="uploadStl" href="#" class="btn btn-block btn-lg btn-default">Upload STL</a><br/>
 Offset (xyz):&nbsp;&nbsp;
-- 
GitLab