diff --git a/css/main.css b/css/main.css
index 1d8ce3dd6b57d4d3fbfee1923195d4f116142333..f00328c6605c0d682601d84060e5ff08785e80c0 100644
--- a/css/main.css
+++ b/css/main.css
@@ -242,4 +242,8 @@ input.numberInput{
     -webkit-border-radius: 6px 0 6px 6px;
     -moz-border-radius: 6px 0 6px 6px;
     border-radius: 6px 0 6px 6px;
+}
+
+.btn-halfWidth {
+    width: 47%;
 }
\ No newline at end of file
diff --git a/data/users/ben.user b/data/users/ben.user
index 22d8053648ccacd9ff3216143c06cf0ad93be91f..2669675032ab40c958603c6ef932ca8e27598e97 100644
--- a/data/users/ben.user
+++ b/data/users/ben.user
@@ -1 +1 @@
-{"lattice":{"units":"inches","scale":2.78388,"shouldPreserveCells":true,"cellSeparation":{"xy":0,"z":0},"cellType":"octa","connectionType":"edgeRot","partType":"beam"},"assembler":{"camStrategy":"xRaster","placementOrder":"XYZ","camProcess":"shopbot","machine":"shopbot","rapidHeight":6.9,"safeHeight":0.5,"originPosition":{"x":-1.39194,"y":1.39194,"z":0},"stockPosition":{"x":-4.713,"y":-13.321,"z":-1.303},"rapidSpeeds":{"xy":6,"z":4},"feedRate":{"xy":0.1,"z":0.1},"stockHeight":0}}
\ No newline at end of file
+{"lattice":{"units":"inches","scale":2.78388,"shouldPreserveCells":true,"cellSeparation":{"xy":0,"z":0},"cellType":"octa","connectionType":"edgeRot","partType":"beam"},"assembler":{"camStrategy":"xRaster","placementOrder":"XYZ","camProcess":"shopbot","machineName":"shopbot","rapidHeight":6.9,"safeHeight":0.5,"originPosition":{"x":-1.39194,"y":1.39194,"z":0},"stockPosition":{"x":-4.713,"y":-13.321,"z":-1.303},"rapidSpeeds":{"xy":6,"z":4},"feedRate":{"xy":0.1,"z":0.1},"stockHeight":0}}
\ No newline at end of file
diff --git a/js/cam/Assembler.js b/js/cam/Assembler.js
index 60d287cff9390e3c339e65b9f6282335102e6474..c7339c30bfe0d99765fe677df6eb78de164ebf57 100644
--- a/js/cam/Assembler.js
+++ b/js/cam/Assembler.js
@@ -8,8 +8,10 @@ Assembler = Backbone.Model.extend({
         camStrategy: "xRaster",
         placementOrder: "XYZ",//used for manual strategy entry
         camProcess: "shopbot",
-        machine: "shopbot",
+        machineName: "shopbot",
+        machine: null,
         exporter: null,
+
         dataOut: "",
         needsPostProcessing: true,
         editsMadeToProgram: false,//warn the user that they will override changes
@@ -23,11 +25,15 @@ Assembler = Backbone.Model.extend({
         stockPosition: new THREE.Vector3(20,0,0),
 
         rapidSpeeds:{xy: 3, z: 2},//rapids at clearance height
-        feedRate:{xy: 0.1, z: 0.1}//speed when heading towards assembly
+        feedRate:{xy: 0.1, z: 0.1},//speed when heading towards assembly
+
+        simLineNumber: 1//used for stock simulation, reading through gcode
     },
 
     initialize: function(options){
 
+        this.set("machine", new Machine());
+
         _.bindAll(this, "postProcess");
 
         //bind events
@@ -53,6 +59,7 @@ Assembler = Backbone.Model.extend({
                 "change:connectionType",
             this._setNeedsPostProcessing);
         this.listenTo(options.lattice, "change:scale", this._setCAMScale);
+        this.listenTo(dmaGlobals.appState, "change:stockSimulationPlaying", this._stockSimulation);
 
         //init origin mesh
         var origin = new THREE.Mesh(new THREE.SphereGeometry(1),
@@ -70,6 +77,15 @@ Assembler = Backbone.Model.extend({
         this._setCAMVisibility();
     },
 
+    makeProgramEdits: function(data){
+        this.set("dataOut", data, {silent:true});
+        this.set("editsMadeToProgram", true, {silent: true});
+    },
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////STOCK / ORIGIN/////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
     _setCAMScale: function(){
         var scale = dmaGlobals.lattice.get("scale")/8;
         this.get("origin").scale.set(scale, scale, scale);
@@ -97,41 +113,41 @@ Assembler = Backbone.Model.extend({
         dmaGlobals.three.render();
     },
 
-    _setNeedsPostProcessing: function(){
-        this.set("needsPostProcessing", true);
-    },
-
-    makeProgramEdits: function(data){
-        this.set("dataOut", data, {silent:true});
-        this.set("editsMadeToProgram", true, {silent: true});
-    },
-
-    _getExporter: function(){
-        var currentExporter = this.get("exporter");
-        if (this.get("camProcess") == "shopbot") {
-            if (currentExporter && currentExporter.constructor == ShopbotExporter){
-                return currentExporter;
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////SIMULATION//////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+    _stockSimulation: function(){
+        if (dmaGlobals.appState.get("stockSimulationPlaying")){
+            var currentLine = this.get("simLineNumber");
+            var allLines = this.get("dataOut").split("\n");
+            if(currentLine<allLines.length){
+                var self = this;
+                this.get("exporter").simulate(allLines[currentLine], this.get("machine"), function(){
+                    currentLine++;
+                    self.set("simLineNumber", currentLine);
+                    self._stockSimulation();
+                });
             } else {
-                return new ShopbotExporter();
+                //finished simulation
+                this.set("simLineNumber", 1);
+                dmaGlobals.appState.set("stockSimulationPlaying", false);
             }
-        } else if (this.get("camProcess") == "gcode") {
-            if (currentExporter && currentExporter.constructor == GCodeExporter){
-                return currentExporter;
-            } else {
-                return new GCodeExporter();
-            }
-        } else console.warn("cam process not supported");
+        } else {
+            this.get("machine").pause();
+        }
+
     },
 
-    _getOrder: function(strategy){
-        if (strategy == "xRaster") return "XYZ";
-        if (strategy == "yRaster") return "YXZ";
-        if (strategy == "manual") return this.get("placementOrder");
-        console.warn("strategy not recognized");
-        return "";
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////POST PROCESSING////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+    _setNeedsPostProcessing: function(){
+        this.set("needsPostProcessing", true);
     },
 
-    postProcess: function(){
+        postProcess: function(){
         this.set("needsPostProcessing", false);
         var exporter = this._getExporter();
 
@@ -164,9 +180,35 @@ Assembler = Backbone.Model.extend({
 
         this.set("dataOut", data);
         this.set("exporter", exporter);
+        this.set("simLineNumber", 1);
         return {data:data, exporter:exporter};
     },
 
+    _getExporter: function(){
+        var currentExporter = this.get("exporter");
+        if (this.get("camProcess") == "shopbot") {
+            if (currentExporter && currentExporter.constructor == ShopbotExporter){
+                return currentExporter;
+            } else {
+                return new ShopbotExporter();
+            }
+        } else if (this.get("camProcess") == "gcode") {
+            if (currentExporter && currentExporter.constructor == GCodeExporter){
+                return currentExporter;
+            } else {
+                return new GCodeExporter();
+            }
+        } else console.warn("cam process not supported");
+    },
+
+    _getOrder: function(strategy){
+        if (strategy == "xRaster") return "XYZ";
+        if (strategy == "yRaster") return "YXZ";
+        if (strategy == "manual") return this.get("placementOrder");
+        console.warn("strategy not recognized");
+        return "";
+    },
+
     _grabStock: function(exporter, stockPosition, rapidHeight, safeHeight){
         var data = "";
         data += exporter.rapidXY(stockPosition.x, stockPosition.y);
@@ -195,9 +237,6 @@ Assembler = Backbone.Model.extend({
             return;
         }
         this.get("exporter").save(this.get("dataOut"));
-    },
-
-    destroy: function(){
     }
 
 });
\ No newline at end of file
diff --git a/js/cam/Machine.js b/js/cam/Machine.js
new file mode 100644
index 0000000000000000000000000000000000000000..5745d77ebbda9f3e50259c2de63681041e7da1d4
--- /dev/null
+++ b/js/cam/Machine.js
@@ -0,0 +1,26 @@
+/**
+ * Created by fab on 3/16/15.
+ */
+
+
+function Machine() {
+    var mesh = new THREE.Mesh(new THREE.BoxGeometry(2,2,2));
+    dmaGlobals.three.sceneAdd(mesh);
+    this.mesh = mesh;
+}
+
+Machine.prototype.pause = function(){
+
+};
+
+Machine.prototype.moveTo = function(x, y, z, speed, callback){
+    var self = this;
+    setTimeout( function() {
+        if (x != "") self.mesh.position.x = x;
+        if (y != "") self.mesh.position.y = y;
+        if (z != "") self.mesh.position.z = z;
+        dmaGlobals.three.render();
+        return callback();
+    }, 300);
+
+};
\ No newline at end of file
diff --git a/js/cam/ShopbotExporter.js b/js/cam/ShopbotExporter.js
index bba1c191eb98f1912074e5872e50b6dffd267dca..68c756a5f9fb4ce23a10e0e6e9c3605a1434af46 100644
--- a/js/cam/ShopbotExporter.js
+++ b/js/cam/ShopbotExporter.js
@@ -80,4 +80,40 @@ ShopbotExporter.prototype.save = function(data){
 
 ShopbotExporter.prototype.convertToInches = function(mm){
     return mm*0.0393701;
-}
+};
+
+
+ShopbotExporter.prototype.simulate = function(line, machine, callback){
+    if (line == "" || line[0] == "'" || (line[0] != "J" && line[0] != "M")) {
+        return callback();
+    }
+    if (line[0] == "J"){
+        return this.simulateGetPosition(line, dmaGlobals.assembler.get("rapidSpeeds"), machine, callback);
+    } else if (line[0] == "M"){
+        return this.simulateGetPosition(line, dmaGlobals.assembler.get("feedRate"), machine, callback);
+    } else {
+        console.warn("problem parsing sbp");
+        return callback();
+    }
+};
+
+ShopbotExporter.prototype.simulateGetPosition = function(line, speed, machine, callback){
+    if (line[1] == 3 || line[1] == 2) {
+        var data = line.split(" ");
+        for (var i=0;i<data.length;i++){
+            var item = data[i];
+            if (item[item.length-1] == ",") data[i] = item.substring(0, item.length - 1)
+        }
+        if (line[1] == 3){
+            console.log(machine);
+            machine.moveTo(data[1], data[2], data[3], speed, callback);
+        } else {
+            machine.moveTo(data[1], data[2], "", speed, callback);
+        }
+    } else if (line[1] == "S"){
+        return callback();
+    } else {
+        console.warn("problem parsing sbp");
+        return callback();
+    }
+};
diff --git a/js/menus/AnimationMenuView.js b/js/menus/AnimationMenuView.js
index bc556eb0e1d37ead7db64e896da4d36ca9a2e8c1..3a816996f45ed5c45a72cb380ad4bc6537ef6d3c 100644
--- a/js/menus/AnimationMenuView.js
+++ b/js/menus/AnimationMenuView.js
@@ -10,6 +10,7 @@ AnimationMenuView = Backbone.View.extend({
     events: {
         "click #playStockSim":                                      "_playStockSim",
         "click #pauseStockSim":                                     "_pauseStockSim",
+        "click #resetStockSim":                                     "_resetStockSim",
         "click #saveSendMenu":                                      "_save",
         "click #overrideEdits":                                     "_postProcess"
     },
@@ -51,6 +52,11 @@ AnimationMenuView = Backbone.View.extend({
         this.model.set("stockSimulationPlaying", false);
     },
 
+    _resetStockSim: function(e){
+        e.preventDefault();
+        dmaGlobals.assembler.set("simLineNumber", 1);
+    },
+
     render: function(){
         if (this.model.get("currentTab") != "animate") return;
         if (dmaGlobals.assembler.get("needsPostProcessing")) dmaGlobals.assembler.postProcess();
@@ -61,7 +67,12 @@ AnimationMenuView = Backbone.View.extend({
         <% if (stockSimulationPlaying){ %>\
         <a href="#" id="pauseStockSim" class=" btn btn-block btn-lg btn-warning">Pause</a><br/>\
         <% } else { %>\
-        <a href="#" id="playStockSim" class=" btn btn-block btn-lg btn-success">Play</a><br/>\
+            <% if (simLineNumber != 1){ %>\
+                <a href="#" id="playStockSim" class=" btn btn-lg btn-halfWidth btn-success">Play</a>\
+                <a href="#" id="resetStockSim" class=" btn btn-lg btn-halfWidth pull-right btn-default">Reset</a><br/><br/>\
+            <% } else { %>\
+                <a href="#" id="playStockSim" class=" btn btn-block btn-lg btn-success">Play</a><br/>\
+            <% } %>\
         <% } %>\
         <a href="#" id="saveSendMenu" class=" btn btn-block btn-lg btn-default">Save</a><br/>\
         Assembly Time:&nbsp;&nbsp;<br/><br/>\
diff --git a/js/menus/AssemblerMenuView.js b/js/menus/AssemblerMenuView.js
index 31d390315e0694258c9d7b67881df14618a8dc8d..8de418301bfa2530e348f1f1e5dc9eb32c16cd34 100644
--- a/js/menus/AssemblerMenuView.js
+++ b/js/menus/AssemblerMenuView.js
@@ -41,7 +41,7 @@ AssemblerMenuView = Backbone.View.extend({
 
     _selectMachine: function(e){
         e.preventDefault();
-        this.assembler.set("machine", $(e.target).data("type"));
+        this.assembler.set("machineName", $(e.target).data("type"));
     },
 
     render: function(){
@@ -53,7 +53,7 @@ AssemblerMenuView = Backbone.View.extend({
     template: _.template('\
         Machine: &nbsp;&nbsp;\
             <div class="btn-group">\
-                <button data-toggle="dropdown" class="btn dropdown-toggle" type="button"><%= allMachineTypes[machine] %><span class="caret"></span></button>\
+                <button data-toggle="dropdown" class="btn dropdown-toggle" type="button"><%= allMachineTypes[machineName] %><span class="caret"></span></button>\
                 <ul role="menu" class="dropdown-menu">\
                     <% _.each(_.keys(allMachineTypes), function(key){ %>\
                         <li><a class="machineType" data-type="<%= key %>" href="#"><%= allMachineTypes[key] %></a></li>\
diff --git a/js/models/AppState.js b/js/models/AppState.js
index e79f39678bf12c0997c60998bc8a6f3a8f2d0243..87633b930dc915e3c02523afb900c0f112e45848 100644
--- a/js/models/AppState.js
+++ b/js/models/AppState.js
@@ -301,7 +301,7 @@ AppState = Backbone.Model.extend({
     },
 
     _getAssemblerDataToSave: function(){
-        var assemblerData = _.omit(dmaGlobals.assembler.toJSON(), ["origin", "stock", "exporter", "appState", "lattice"]);
+        var assemblerData = _.omit(dmaGlobals.assembler.toJSON(), ["origin", "stock", "exporter", "appState", "lattice", "machine", "simLineNumber"]);
         if (!dmaGlobals.assembler.get("editsMadeToProgram")) assemblerData.dataOut = "";
         return assemblerData;
     },
@@ -328,6 +328,7 @@ AppState = Backbone.Model.extend({
 
     loadUser: function(data, isParsed){
         if (!isParsed) data = JSON.parse(data);
+        console.log(data);
         this._setData(data, false);
     },
 
diff --git a/js/threeViews/ThreeView.js b/js/threeViews/ThreeView.js
index 1cec6490a454b6f213bbe4dfa321ff055912d355..5a0c2cbcf98f4668bbca720f4bc7fa68d2054244 100644
--- a/js/threeViews/ThreeView.js
+++ b/js/threeViews/ThreeView.js
@@ -26,7 +26,7 @@ ThreeView = Backbone.View.extend({
 
         this.appState = options.appState;
 
-        _.bindAll(this, "_animate", "_mouseMoved");
+        _.bindAll(this, "_mouseMoved");//"_animate"
 
         //bind events
         this.listenTo(this.appState, "change:deleteMode change:extrudeMode change:shift", this._setControlsEnabled);
@@ -40,17 +40,17 @@ ThreeView = Backbone.View.extend({
         this.$el.append(this.model.domElement);//render only once
 
         this.model.render();
-        this._animate();
+        //this._animate();
     },
 
     ////////////////////////////////////////////////////////////////////////////////
     ///////////////////////////////////CONTROLS/////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////////////
 
-    _animate: function(){
-        requestAnimationFrame(this._animate);
-        this.controls.update();
-    },
+    //_animate: function(){
+    //    requestAnimationFrame(this._animate);
+    //    this.controls.update();
+    //},
 
     _setControlsEnabled: function(){
         var state = this.appState.get("deleteMode") || this.appState.get("shift") || this.appState.get("extrudeMode");
diff --git a/main.html b/main.html
index 0e48077ca88080b0c027228a8b92f514372be240..afb20398ecbfb358e7407af2e1904477a3f0b64d 100644
--- a/main.html
+++ b/main.html
@@ -63,6 +63,7 @@
     <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/Assembler.js"></script>
     <script src="js/cam/ShopbotExporter.js"></script>
     <script src="js/cam/GCodeExporter.js"></script>