diff --git a/assets/stls/stapler/zStageDualHead.stl b/assets/stls/stapler/zStageDualHead.stl
new file mode 100644
index 0000000000000000000000000000000000000000..ac0b305dfaad43b935f68b14c8f1599956790046
Binary files /dev/null and b/assets/stls/stapler/zStageDualHead.stl differ
diff --git a/index.html b/index.html
index 4b00a34b85f3442cbe6e4e58ef579dfd85f02805..47aa3078001c2ceabcd5cb66e0ac3d83687580e0 100644
--- a/index.html
+++ b/index.html
@@ -85,8 +85,9 @@
     <script src="js/models/BasePlane.js"></script>
     <script src="js/models/extrudeVisualizer.js"></script>
     <script src="js/models/AppState.js"></script>
-    <script src="js/cam/Machine.js"></script>
+    <script src="js/cam/assemblers/Assembler.js"></script>
     <script src="js/cam/MachineOneBit.js"></script>
+    <script src="js/cam/assemblers/StaplerAssembler.js"></script>
     <script src="js/cam/cam.js"></script>
     <script src="js/cam/ShopbotExporter.js"></script>
     <script src="js/cam/GCodeExporter.js"></script>
diff --git a/js/cam/MachineOneBit.js b/js/cam/MachineOneBit.js
index 56f5c76fad17cd91cf8c7f7132a085c498016bff..f944aae1a6dda6f3769c1f42f50779560563fdda 100644
--- a/js/cam/MachineOneBit.js
+++ b/js/cam/MachineOneBit.js
@@ -3,9 +3,9 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 function OneBitBot(){
-    Machine.call(this);
+    Assembler.call(this);
 }
-OneBitBot.prototype = Object.create(Machine.prototype);
+OneBitBot.prototype = Object.create(Assembler.prototype);
 
 OneBitBot.prototype._setDefaults = function(){
     Machine.prototype._setDefaults.call(this);
diff --git a/js/cam/assemblers/Assembler.js b/js/cam/assemblers/Assembler.js
new file mode 100644
index 0000000000000000000000000000000000000000..37a41b1048c44cf6db1e60b10aaeb9f968deb1c1
--- /dev/null
+++ b/js/cam/assemblers/Assembler.js
@@ -0,0 +1,51 @@
+/**
+ * Created by aghassaei on 5/28/15.
+ */
+
+
+var assemblerMaterial = new THREE.MeshLambertMaterial({color:0xaaaaaa, shading: THREE.FlatShading, transparent:true, opacity:1});
+
+function Assembler(){
+
+    this.stock = this._buildStock();
+    this.object3D = new THREE.Object3D();
+    globals.three.sceneAdd(this.object3D);
+    var self = this;
+    this._loadStls(function(){
+        self._configureAssemblerMovementDependencies();
+    });
+}
+
+Assembler.prototype._buildStock = function(){
+    if (globals.lattice.makeSuperCell) return globals.lattice.makeSuperCell();
+    return globals.lattice.makeCellForLatticeType(null);
+};
+
+Assembler.prototype._loadStls = function(callback){
+    callback();
+};
+
+Assembler.prototype._configureAssemblerMovementDependencies = function(){
+};
+
+Assembler.prototype.setVisibility = function(visible){
+    this.object3D.visible = visible;
+    globals.three.render();
+};
+
+Assembler.prototype.destroy = function(){
+    this.stock.destroy();
+    this.zAxis.parent.remove(this.zAxis);
+    this.xAxis.parent.remove(this.xAxis);
+    this.yAxis.parent.remove(this.yAxis);
+    this.frame.parent.remove(this.frame);
+    this.substrate.parent.remove(this.substrate);
+    globals.three.sceneRemove(this.object3D);
+    this.stock = null;
+    this.zAxis = null;
+    this.xAxis = null;
+    this.yAxis = null;
+    this.frame = null;
+    this.substrate = null;
+    this.object3D = null;
+};
diff --git a/js/cam/assemblers/StaplerAssembler.js b/js/cam/assemblers/StaplerAssembler.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f97f7b0877df011920830ebcf98e84221a91cd3
--- /dev/null
+++ b/js/cam/assemblers/StaplerAssembler.js
@@ -0,0 +1,54 @@
+/**
+ * Created by aghassaei on 5/28/15.
+ */
+
+
+function StaplerAssembler(){
+    Assembler.call(this);
+}
+StaplerAssembler.prototype = Object.create(Assembler.prototype);
+
+StaplerAssembler.prototype._configureAssemblerMovementDependencies = function(){
+    this.zAxis.add(this.stock.getObject3D());
+    this.xAxis.add(this.zAxis);
+    this.frame.add(this.xAxis);
+    this.frame.add(this.yAxis);
+    this.object3D.add(this.frame);
+    this.object3D.add(this.substrate);
+};
+
+StaplerAssembler.prototype._loadStls = function(callback){
+    var meshes = [];
+    var numMeshes = 5;
+    function allLoaded(){
+        numMeshes -= 1;
+        return numMeshes <= 0;
+    }
+    function geometryScale(geometry){
+        var unitScale = 1;
+        geometry.applyMatrix(new THREE.Matrix4().makeScale(unitScale, unitScale, unitScale));
+        return geometry;
+    }
+    var material = assemblerMaterial;
+    var self = this;
+    function meshPrep(geometry, name){
+        self[name] = new THREE.Mesh(geometry, material);
+        if (allLoaded()) callback(meshes);
+    }
+    var loader = new THREE.STLLoader();
+    loader.load("assets/stls/stapler/frame.stl", function(geometry){
+        meshPrep(geometryScale(geometry), "frame");
+    });
+    loader.load("assets/stls/stapler/zStage.stl", function(geometry){
+        meshPrep(geometryScale(geometry), "zAxis");
+    });
+    loader.load("assets/stls/stapler/yStage.stl", function(geometry){
+        meshPrep(geometryScale(geometry), "yAxis");
+    });
+    loader.load("assets/stls/stapler/xStage.stl", function(geometry){
+        meshPrep(geometryScale(geometry), "xAxis");
+    });
+    loader.load("assets/stls/stapler/substrate.stl", function(geometry){
+        meshPrep(geometryScale(geometry), "substrate");
+    });
+};
\ No newline at end of file
diff --git a/js/cam/cam.js b/js/cam/cam.js
index 05a6f3c5c0dcfb8a8a3b202296d7581dafe1bb8e..d1bbe8e4c34ae35bab53cef36580c4d3829269e1 100644
--- a/js/cam/cam.js
+++ b/js/cam/cam.js
@@ -8,8 +8,8 @@ Cam = Backbone.Model.extend({
         camStrategy: "raster",
         placementOrder: "XYZ",//used for raster strategy entry
         camProcess: "gcode",
-        machineName: "handOfGod",
-        machine: null,
+        machineName: "stapler",
+        assembler: null,
         exporter: null,
 
         dataOut: "",
@@ -37,12 +37,12 @@ Cam = Backbone.Model.extend({
         simSpeed: 4//#X times real speed
     },
 
-    initialize: function(options){
+    initialize: function(){
 
         _.bindAll(this, "postProcess");
 
         //bind events
-        this.listenTo(options.appState, "change:currentTab", this._tabChanged);
+        this.listenTo(globals.appState, "change:currentTab", this._tabChanged);
         this.listenTo(this, "change:originPosition", this._moveOrigin);
         this.listenTo(this, "change:stockPosition", this._moveStock);
         this.listenTo(this,
@@ -60,19 +60,19 @@ Cam = Backbone.Model.extend({
                 "change:rapidHeight " +
                 "change:machineName",
             this._setNeedsPostProcessing);
-        this.listenTo(options.lattice,
+        this.listenTo(globals.lattice,
                 "change:numCells " +
                 "change:units " +
                 "change:scale " +
                 "change:cellType " +
                 "change:connectionType",
             this._setNeedsPostProcessing);
-        this.listenTo(options.lattice, "change:scale", this._setCAMScale);
+        this.listenTo(globals.lattice, "change:scale", this._setCAMScale);
         this.listenTo(globals.appState, "change:stockSimulationPlaying", this._stockSimulation);
 
-        this.listenTo(options.lattice, "change:partType", this._updatePartType);
-        this.listenTo(options.lattice, "change:cellType change:connectionType", this._updateCellType);
-        this.listenTo(options.appState, "change:cellMode", this._updateCellMode);
+        this.listenTo(globals.lattice, "change:partType", this._updatePartType);
+        this.listenTo(globals.lattice, "change:cellType change:connectionType", this._updateCellType);
+        this.listenTo(globals.appState, "change:cellMode", this._updateCellMode);
         this.listenTo(this, "change:machineName", this.selectMachine);
 
         this._initOriginAndStock();
@@ -80,15 +80,21 @@ Cam = Backbone.Model.extend({
 
     selectMachine: function(){
         var machineName = this.get("machineName");
-        if (this.get("machine")) this.get("machine").destroy();
-        this.set("machine", null);
+        if (this.get("assembler")) this.get("assembler").destroy();
+        this.set("assembler", null);
         if (machineName == "shopbot"){
-            this.set("machine", new Shopbot());
+            this.set("assembler", new Shopbot());
         } else if (machineName == "handOfGod"){
-            this.set("machine", new God());
+            this.set("assembler", new God());
         } else if (machineName == "oneBitBot"){
-            this.set("machine", new OneBitBot());
-        } else console.warn("selected machine not recognized");
+            this.set("assembler", new OneBitBot());
+        } else if (machineName == "stapler"){
+            this.set("assembler", new StaplerAssembler());
+        } else if (machineName == "staplerDual"){
+            this.set("assembler", new StaplerAssembler());
+        } else{
+            console.warn("selected assembler not recognized");
+        }
     },
 
     makeProgramEdits: function(data){
@@ -106,17 +112,17 @@ Cam = Backbone.Model.extend({
     },
 
     _updateCellType: function(){
-        if (this.get("machine")) this.get("machine").updateCellType();
+        if (this.get("assembler")) this.get("assembler").updateCellType();
         this.set("machineName", "handOfGod");//todo this should go away with dynamic allocation of this model
 
     },
 
     _updatePartType: function(){
-        if (this.get("machine")) this.get("machine").updatePartType();
+        if (this.get("assembler")) this.get("assembler").updatePartType();
     },
 
     _updateCellMode: function(){
-        if (this.get("machine")) this.get("machine").setVisibility(this.isVisible());
+        if (this.get("assembler")) this.get("assembler").setVisibility(this.isVisible());
         globals.three.render();
     },
 
@@ -124,7 +130,7 @@ Cam = Backbone.Model.extend({
         var scale = globals.lattice.get("scale");
         this.get("origin").scale.set(scale/8, scale/8, scale/8);
         this.get("stock").scale.set(scale/8, scale/8, scale/8);
-        if (this.get("machine")) this.get("machine").setScale(scale);
+        if (this.get("assembler")) this.get("assembler").setScale(scale);
     },
 
     _tabChanged: function(){
@@ -136,8 +142,8 @@ Cam = Backbone.Model.extend({
         var visible = this.isVisible();
         this.get("origin").visible = visible;
         this.get("stock").visible = visible;
-        if (visible && !this.get("machine")) this.selectMachine();
-        if (this.get("machine")) this.get("machine").setVisibility(visible);
+        if (visible && !this.get("assembler")) this.selectMachine();
+        if (this.get("assembler")) this.get("assembler").setVisibility(visible);
         globals.three.render();
     },
 
@@ -162,7 +168,7 @@ Cam = Backbone.Model.extend({
         this.get("origin").position.set(position.x, position.y, position.z);
         if (this.get("stockFixed")) this._updateStockPosToOrigin(position, this.previous("originPosition"));
         globals.three.render();
-        if (this.get("machine") && this.get("machine").setMachinePosition) this.get("machine").setMachinePosition();
+        if (this.get("assembler") && this.get("assembler").setMachinePosition) this.get("assembler").setMachinePosition();
     },
 
     _updateStockPosToOrigin: function(newOrigin, lastOrigin){
@@ -201,7 +207,7 @@ Cam = Backbone.Model.extend({
             var allLines = this.get("dataOut").split("\n");
             if(currentLine<allLines.length){
                 var self = this;
-                this.get("exporter").simulate(allLines[currentLine], this.get("machine"),
+                this.get("exporter").simulate(allLines[currentLine], this.get("assembler"),
                     this.get("originPosition"), function(){
                     currentLine++;
                     self.set("simLineNumber", currentLine);
@@ -213,7 +219,7 @@ Cam = Backbone.Model.extend({
             }
         } else {
             globals.three.stopAnimationLoop();
-            this.get("machine").pause();
+            this.get("assembler").pause();
         }
 
     },
@@ -236,7 +242,7 @@ Cam = Backbone.Model.extend({
         data += exporter.addComment("begin program");
         data += "\n";
 
-        data = this.get("machine").postProcess(data, exporter);
+        data = this.get("assembler").postProcess(data, exporter);
 
         data += "\n\n";
         data += exporter.addComment("end program");
diff --git a/js/cells/DMACell.js b/js/cells/DMACell.js
index 73b1644b9ee00e512b35d8bd55b6cd2b5ab69749..954e515e6ec40d387d843fedccd8508a0df94737 100644
--- a/js/cells/DMACell.js
+++ b/js/cells/DMACell.js
@@ -25,11 +25,16 @@ DMACell.prototype._buildObject3D = function(){
     return object3D;
 };
 
+DMACell.prototype.getObject3D = function(){//careful, used for stock sim only for now
+    return this.object3D;
+};
+
 DMACell.prototype._rotateCell = function(object3D){
     return object3D;//by default, no mesh transformations
 };
 
 DMACell.prototype._translateCell = function(object3D){
+    if (!this.indices) return object3D;
     var position = globals.lattice.getPositionForIndex(this.indices);
     object3D.position.set(position.x, position.y, position.z);
     return object3D;
diff --git a/js/cells/supercells/GIKSuperCell.js b/js/cells/supercells/GIKSuperCell.js
index 62b476758c4c3f3db1301f487918ca3a874779b0..e399954839fa55336ae626b2e09553af8b8baeb6 100644
--- a/js/cells/supercells/GIKSuperCell.js
+++ b/js/cells/supercells/GIKSuperCell.js
@@ -54,15 +54,15 @@ GIKSuperCell.prototype._buildObject3D = function(){
     return this._translateCell(this._rotateCell(new THREE.Object3D()));
 };
 
-GIKSuperCell.prototype.addChildCell = function(object3D){
-    this._addChildren(object3D);
-};
-
 GIKSuperCell.prototype._rotateCell = function(object3D){
     if (this.indices && this.indices.z%2 != 0) object3D.rotateZ(Math.PI/2);
     return object3D;
 };
 
+GIKSuperCell.prototype.addChildCell = function(object3D){
+    this._addChildren(object3D);
+};
+
 GIKSuperCell.prototype._buildMesh = function(length){
     var meshes = [];
     var superCellGeo = new THREE.BoxGeometry(1,1,1.28);
diff --git a/js/lattice/GIKLattice.js b/js/lattice/GIKLattice.js
index f796133dad930f409ac03de2c6930510bf61b674..ec285c1ce5f31c25e6076a2c21d929a4d7c91bcc 100644
--- a/js/lattice/GIKLattice.js
+++ b/js/lattice/GIKLattice.js
@@ -42,7 +42,7 @@ latticeSubclasses["GIKLattice"] = {
             var length = this.get("gikLength");
             var cells;
             if (range) cells = this.addCellsInRange(range);
-            else {
+            else {//this is for assembler stock only
                 cells = [];
                 for (var i=0;i<length;i++){
                     cells.push(this.makeCellForLatticeType(null));
diff --git a/js/main.js b/js/main.js
index 7bfbac32543ea639f0591ace74ac16210add237f..5d01decff55ca87f5f99d3dab8d05bf79736b509 100644
--- a/js/main.js
+++ b/js/main.js
@@ -19,7 +19,7 @@ $(function(){
     globals.basePlane = null;
     globals.highlighter = null;
     globals.lattice.delayedInit();//todo need this?
-    globals.cam = new Cam({appState: globals.appState, lattice:globals.lattice});
+    globals.cam = new Cam({appState: globals.appState});
     globals.fileSaver = GlobalFilesaver();
 
     //ui
diff --git a/js/menus/NavViewMenu.js b/js/menus/NavViewMenu.js
index 5859af1bc12eccd08dce7dd5ce1c696b8614081d..92e396e992d7d263d117e77da176684aa69a3415 100644
--- a/js/menus/NavViewMenu.js
+++ b/js/menus/NavViewMenu.js
@@ -40,7 +40,6 @@ NavViewMenu = Backbone.View.extend({
     },
 
     render: function(){
-        console.log("render");
         this.$el.html(this.template(this.model.toJSON()));
 
         _.each($(".boolProperty"), function(item){
diff --git a/js/models/AllAppPLists.js b/js/models/AllAppPLists.js
index 7eaedfa7bfd018e26f58e2fb118d9b766e6a6cf7..fbccb975343252a20e1e77b56800d449d21a25a7 100644
--- a/js/models/AllAppPLists.js
+++ b/js/models/AllAppPLists.js
@@ -147,7 +147,11 @@ function AppPList(){
         },
         cube:{
             face:{handOfGod: "Hand of God"},
-            gik: {handOfGod: "Hand of God"}
+            gik: {
+                stapler: "Stapler",
+                staplerDual: "Dual Head Stapler"
+//                handOfGod: "Hand of God"
+            }
         },
         truncatedCube:{
             face:{handOfGod: "Hand of God"}