From 0062dd099b9f6c8be8d54b3c5fac8d770df44740 Mon Sep 17 00:00:00 2001
From: Fabian Neumann <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Wed, 28 Feb 2018 13:37:13 +0100
Subject: [PATCH 01/39] - changed default to SparkMaker settings

---
 js/main.js | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/js/main.js b/js/main.js
index 416f74f..e2a322a 100644
--- a/js/main.js
+++ b/js/main.js
@@ -14,7 +14,7 @@ var settings = new SLAcer.Settings({
             height: 100 // μm
         },
         light: {
-            on : 1000,
+            on : 12000,
             off: 500
         },
         zip: true,
@@ -27,8 +27,8 @@ var settings = new SLAcer.Settings({
             position : 1
         },
         lifting: {
-            speed : 50, // mm/min
-            height: 3,  // mm
+            speed : 30, // mm/min
+            height: 5,  // mm
         }
     },
     mesh: {
@@ -45,7 +45,7 @@ var settings = new SLAcer.Settings({
         mirror: false
     },
     buildVolume: {
-        size     : { x: 100,  y: 100,  z: 100 }, // mm
+        size     : { x: 102,  y: 56,  z: 125 }, // mm
         unit     : 'mm',                         // mm or in
         color    : 0xcccccc,
         opacity  : 0.1,
@@ -56,7 +56,7 @@ var settings = new SLAcer.Settings({
     },
     resin: {
         density  : 1.1, // g/cm3
-        price    : 50,   // $
+        price    : 60,   // $
         panel    : {
             collapsed: false,
             position : 5
@@ -65,7 +65,7 @@ var settings = new SLAcer.Settings({
     screen: {
         width    : window.screen.width,
         height   : window.screen.height,
-        diagonal : { size: 22, unit: 'in' },
+        diagonal : { size: 4.6, unit: 'in' },
         panel    : {
             collapsed: false,
             position : 6

From 7b5f2c97d90dd14055a084842fff807cf720946b Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Thu, 1 Mar 2018 11:38:36 +0100
Subject: [PATCH 02/39] Update README.md

---
 README.md | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 28df2da..10064f8 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,10 @@
-# SLAcer.js ([demo](http://lautr3k.github.io/SLAcer.js/))
+# SLAcer.js for SparkMaker ([demo](https://n0sr3v.github.io/SLAcer.js/))
 ![Screenshot](/screenshot.png?raw=true)
 
-# Main features
+# Work in Progress
+- currently working on an option to slice .wow files
+
+# Default main features
 - Browse or drag/drop STL file.
 - Mesh information: size, volume, cost, etc...
 - Mesh transformation: scale, rotate, translate, mirror.

From c598a92cef49e1adc067b80b70be74c8a6f7cad8 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Thu, 1 Mar 2018 13:14:13 +0100
Subject: [PATCH 03/39] - first console debugs - slicing not working with wow

---
 index.html |  3 ++-
 js/main.js | 32 +++++++++++++++++++++++++++-----
 2 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/index.html b/index.html
index 76c8219..cf752ed 100644
--- a/index.html
+++ b/index.html
@@ -187,8 +187,9 @@ <h3 class="panel-title">Slicer</h3>
 
                         <div class="form-group">
                             <label for="slicer-image-extension">Output type</label>
-                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-png" value="png" checked="checked" /> png
+                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-png" value="png" /> png
                             <input type="radio" name="slicer-image-extension" id="slicer-image-extension-svg" value="svg" /> svg
+                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-wow" value="wow" checked="checked" /> wow
                         </div>
 
                         <hr />
diff --git a/js/main.js b/js/main.js
index e2a322a..b71f840 100644
--- a/js/main.js
+++ b/js/main.js
@@ -18,8 +18,9 @@ var settings = new SLAcer.Settings({
             off: 500
         },
         zip: true,
+        wow: true,
         svg: false,
-        png: true,
+        png: false,
         speed: false,
         speedDelay: 10, // ms
         panel: {
@@ -63,8 +64,8 @@ var settings = new SLAcer.Settings({
         }
     },
     screen: {
-        width    : window.screen.width,
-        height   : window.screen.height,
+        width    : 854,//window.screen.width,
+        height   : 480,//window.screen.height,
         diagonal : { size: 4.6, unit: 'in' },
         panel    : {
             collapsed: false,
@@ -187,6 +188,16 @@ function getSlice(layerNumber) {
             var fileName = layerNumber + '.png';
             var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
             zipFolder.file(fileName, imgData, { base64: true });
+        }else if (WOWExport) {
+            console.log('layer number:', layerNumber);
+            console.log('z position :', zPosition);
+            // console.log('faces', faces);
+            var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
+            var data = imgData.data;
+            myLogger(data);
+            // TODO: remove (just to have a result)
+            var fileName = layerNumber + '.png';
+            zipFolder.file(fileName, imgData, { base64: true });
         }
     });
 
@@ -270,6 +281,12 @@ function getSlice(layerNumber) {
         // add svg file to zip
         zipFolder.file(layerNumber + '.svg', svg);
     }
+
+}
+function myLogger(message){
+    return function(){
+        console.log(message);
+    }
 }
 
 // -----------------------------------------------------------------------------
@@ -470,6 +487,7 @@ var $slicerLiftingHeight = $slicerBody.find('#slicer-lifting-height');
 
 var $slicerExportPNG = $slicerBody.find('#slicer-image-extension-png');
 var $slicerExportSVG = $slicerBody.find('#slicer-image-extension-svg');
+var $slicerExportWOW = $slicerBody.find('#slicer-image-extension-wow');
 
 var $slicerSpeedYes    = $slicerBody.find('#slicer-speed-yes');
 var $slicerSpeedNo     = $slicerBody.find('#slicer-speed-no');
@@ -502,6 +520,7 @@ function updateSlicerSettings() {
 
     settings.set('slicer.png', $slicerExportPNG[0].checked);
     settings.set('slicer.svg', $slicerExportSVG[0].checked);
+    settings.set('slicer.wow', $slicerExportWOW[0].checked);
 
     settings.set('slicer.zip', $slicerMakeZipYes[0].checked);
     settings.set('slicer.speed', $slicerSpeedYes[0].checked);
@@ -519,6 +538,7 @@ var slicesNumber;
 var zipFile;
 var zipFolder;
 
+var WOWExport;
 var SVGExport;
 var PNGExport;
 
@@ -577,6 +597,7 @@ function startSlicing() {
 
     zipFile   = null;
     zipFolder = null;
+    WOWExport = null;
     SVGExport = null;
     PNGExport = null;
 
@@ -585,7 +606,7 @@ function startSlicing() {
         zipFolder = zipFile.folder('slices');
         zipFile.file("README.txt", 'Generated by SLAcer.js\r\nhttp://lautr3k.github.io/SLAcer.js/\r\n');
         zipFile.file("slacer.json", JSON.stringify({
-            imageExtension: settings.get('slicer.png') ? 'png' : 'svg',
+            imageExtension: settings.get('slicer.png') ? 'png' : settings.get('slicer.svg') ? 'svg' : 'wow',
             imageDirectory: 'slices',
             screenWidth   : settings.get('screen.width'),
             screenHeight  : settings.get('screen.height'),
@@ -597,6 +618,7 @@ function startSlicing() {
             liftingSpeed  : parseInt(settings.get('slicer.lifting.speed')),  // mm/min
             liftingHeight : parseInt(settings.get('slicer.lifting.height'))  // mm
         }, null, 2));
+        WOWExport = settings.get('slicer.wow')
         SVGExport = settings.get('slicer.svg');
         PNGExport = settings.get('slicer.png');
     }
@@ -630,7 +652,7 @@ $abortButton.on('click', function(e) {
     endSlicing();
 });
 
-$('#slicer-image-extension-' + (settings.get('slicer.png') ? 'png' : 'svg')).prop('checked', true);
+$('#slicer-image-extension-' + (settings.get('slicer.png') ? 'png' : settings.get('slicer.svg') ? 'svg' : 'wow')).prop('checked', true);
 $('#slicer-make-zip-' + (settings.get('slicer.zip') ? 'yes' : 'no')).prop('checked', true);
 $('#slicer-speed-' + (settings.get('slicer.speed') ? 'yes' : 'no')).prop('checked', true);
 $('#slicer input').on('input, change', updateSlicerSettings);

From 82d7f705fbc2e74bc37e930be2e7f34bd631e5e3 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Fri, 2 Mar 2018 05:20:48 +0100
Subject: [PATCH 04/39] - binary string layers

---
 js/main.js          | 72 ++++++++++++++++++++++++++++++++++++++-------
 js/slacer/viewer.js |  6 ++++
 2 files changed, 68 insertions(+), 10 deletions(-)

diff --git a/js/main.js b/js/main.js
index b71f840..3a6c463 100644
--- a/js/main.js
+++ b/js/main.js
@@ -192,12 +192,53 @@ function getSlice(layerNumber) {
             console.log('layer number:', layerNumber);
             console.log('z position :', zPosition);
             // console.log('faces', faces);
-            var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
-            var data = imgData.data;
-            myLogger(data);
-            // TODO: remove (just to have a result)
-            var fileName = layerNumber + '.png';
-            zipFolder.file(fileName, imgData, { base64: true });
+            //var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
+            //var data = imgData.data;
+            //console.log('canvas :', canvas);
+            //console.log('canvas.getContext(2d) :', canvas.getContext('2d'));
+            //var imgData = canvas.getContext('2d').getImageData(0,0,canvas.width,canvas.height);
+            //var ctx = canvas.getContext('2d');
+            //var data = imgData.data;
+
+            convertURIToImageData(dataURL).then(function(imageData) {
+                // Here you can use imageData
+                // console.log(imageData);
+                /*
+                 var red = data[i];
+                 var green = data[i+1];
+                 var blue = data[i+2];
+                 var alpha = data[i+3];
+                 2 Options:
+                 Black red=0, green=0, blue=0, alpha=255;
+                 White red=255, green=255, blue=255, alpha=255;
+                 */
+                var width = settings.get('screen.width');
+                var height = settings.get('screen.height');
+
+                var result = "";
+                var tmp_byte = "";
+                var pixel = 0;
+
+                var data = imageData.data;
+
+                for(var w=0; w<data.length/height*4; w+=4) {
+                    for(var h=w; h<width*height*4; h+=(4*width)) {
+                        if(data[h]===0){
+                            tmp_byte = "0" + tmp_byte;
+                        }else{
+                            tmp_byte = "1" + tmp_byte;
+                        }
+                        if((pixel+1)%8===0){
+                            result += tmp_byte +";";
+                            tmp_byte = "";
+                        }
+                        pixel+=1;
+                    }
+                }
+                var fileName = layerNumber + '.txt';
+                zipFolder.file(fileName, result);
+            });
+
         }
     });
 
@@ -283,10 +324,21 @@ function getSlice(layerNumber) {
     }
 
 }
-function myLogger(message){
-    return function(){
-        console.log(message);
-    }
+
+function convertURIToImageData(URI) {
+    return new Promise(function(resolve, reject) {
+        if (URI == null) return reject();
+        var canvas = document.createElement('canvas'),
+            context = canvas.getContext('2d'),
+            image = new Image();
+        image.addEventListener('load', function() {
+            canvas.width = image.width;
+            canvas.height = image.height;
+            context.drawImage(image, 0, 0, canvas.width, canvas.height);
+            resolve(context.getImageData(0, 0, canvas.width, canvas.height));
+        }, false);
+        image.src = URI;
+    });
 }
 
 // -----------------------------------------------------------------------------
diff --git a/js/slacer/viewer.js b/js/slacer/viewer.js
index 4464c7f..939478e 100644
--- a/js/slacer/viewer.js
+++ b/js/slacer/viewer.js
@@ -123,6 +123,12 @@ var SLAcer = SLAcer || {};
         callback(this.canvas.toDataURL());
     };
 
+    Viewer.prototype.screenshot_canvas = function(callback) {
+        this.render();
+        console.log('canvas.getContext(2d) :', this.canvas.getContext('2d'));
+        callback(this.canvas);
+    };
+
     // -------------------------------------------------------------------------
 
     // global settings

From 464c811928e8148912dcad669667b19f77fb2e0b Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Fri, 2 Mar 2018 16:35:25 +0100
Subject: [PATCH 05/39] - changed default demo url - added full wow gcode
 support - currently still having problems with binary layers - removed dead
 code

---
 index.html          |   2 +-
 js/main.js          | 122 +++++++++++++++++++++++++++++++++++---------
 js/slacer/viewer.js |   6 ---
 3 files changed, 100 insertions(+), 30 deletions(-)

diff --git a/index.html b/index.html
index cf752ed..54d80fe 100644
--- a/index.html
+++ b/index.html
@@ -360,6 +360,6 @@ <h3 class="panel-title">Colors</h3>
         <script src="js/loader/stl.js" type="text/javascript"></script>
         <script src="vendor/FileSaver.min.js" type="text/javascript"></script>
         <script src="vendor/jszip.min.js" type="text/javascript"></script>
-        <script src="js/main.js" type="text/javascript"></script>
+        <script src="js/main.js" type="text/javascript" charset="utf-8"></script>
     </body>
 </html>
diff --git a/js/main.js b/js/main.js
index 3a6c463..d0fcda2 100644
--- a/js/main.js
+++ b/js/main.js
@@ -189,16 +189,8 @@ function getSlice(layerNumber) {
             var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
             zipFolder.file(fileName, imgData, { base64: true });
         }else if (WOWExport) {
-            console.log('layer number:', layerNumber);
-            console.log('z position :', zPosition);
-            // console.log('faces', faces);
-            //var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
-            //var data = imgData.data;
-            //console.log('canvas :', canvas);
-            //console.log('canvas.getContext(2d) :', canvas.getContext('2d'));
-            //var imgData = canvas.getContext('2d').getImageData(0,0,canvas.width,canvas.height);
-            //var ctx = canvas.getContext('2d');
-            //var data = imgData.data;
+            //console.log('layer number:', layerNumber);
+            //console.log('z position :', zPosition);
 
             convertURIToImageData(dataURL).then(function(imageData) {
                 // Here you can use imageData
@@ -215,28 +207,35 @@ function getSlice(layerNumber) {
                 var width = settings.get('screen.width');
                 var height = settings.get('screen.height');
 
-                var result = "";
-                var tmp_byte = "";
                 var pixel = 0;
 
+                var array = new Uint8Array(width*height/8);
+
                 var data = imageData.data;
 
                 for(var w=0; w<data.length/height*4; w+=4) {
                     for(var h=w; h<width*height*4; h+=(4*width)) {
-                        if(data[h]===0){
-                            tmp_byte = "0" + tmp_byte;
-                        }else{
-                            tmp_byte = "1" + tmp_byte;
-                        }
-                        if((pixel+1)%8===0){
-                            result += tmp_byte +";";
-                            tmp_byte = "";
+                        if(data[h]!=0){
+                            array[(pixel/8) | 0] += Math.pow(2,(pixel%8))
                         }
-                        pixel+=1;
+                        pixel++;
                     }
                 }
-                var fileName = layerNumber + '.txt';
-                zipFolder.file(fileName, result);
+                //console.log('array :', array);
+                //var fileName = layerNumber + '.txt';
+                //zipFolder.file(fileName, array, {type: 'text/plain'});
+
+
+                // GCode logic
+
+                wowFile += ";L:"+layerNumber+";\nM106 S0;\nG1 Z"+settings.get('slicer.lifting.height')+
+                    " F"+settings.get('slicer.lifting.speed')+
+                    ";\nG1 Z-"+(settings.get('slicer.lifting.height')-settings.get('slicer.layers.height')/1000)+
+                    " F"+settings.get('slicer.lifting.speed')+";\n{{\n"
+                wowFile += (new TextDecoder("utf-8")).decode(array)+"\n"
+                zipFolder.file(layerNumber+".txt", array);
+                // GCode logic
+                wowFile += "}}\nM106 S255;\nG4 S"+settings.get('slicer.light.on')/1000+";\n"
             });
 
         }
@@ -341,6 +340,52 @@ function convertURIToImageData(URI) {
     });
 }
 
+function bin2string(array){
+    var result = "";
+    for(var i = 0; i < array.length; ++i){
+        //result+= (String.fromCharCode(array[i]));
+        result+= convertHexToString(array[i]);
+    }
+    console.log(result);
+    return result;
+}
+
+function BinToText(input) {
+    return parseInt(input,2).toString(10);
+}
+
+function uintToString(buffer) {
+    var encodedString = String.fromCharCode.apply(null, buffer),
+        decodedString = decodeURIComponent(escape(encodedString));
+    return decodedString;
+}
+
+function convertHexToString(input) {
+
+    // split input into groups of two
+    var hex = input.match(/[\s\S]{2}/g) || [];
+    var output = '';
+
+    // build a hex-encoded representation of your string
+    for (var i = 0, j = hex.length; i < j; i++) {
+        output += '%' + ('0' + hex[i]).slice(-2);
+    }
+
+    // decode it using this trick
+    output = decodeURIComponent(output);
+
+    return output;
+}
+
+function arrayToHEXString(input) {
+
+    var result = "";
+    for(var i = 0; i < input.length; ++i){
+        result+= "\X"+input[i].toString(16);
+    }
+    return result;
+}
+
 // -----------------------------------------------------------------------------
 // UI
 // -----------------------------------------------------------------------------
@@ -589,6 +634,7 @@ var currentSliceNumber;
 var slicesNumber;
 var zipFile;
 var zipFolder;
+var wowFile;
 
 var WOWExport;
 var SVGExport;
@@ -610,7 +656,9 @@ function slice() {
         return endSlicing();
     }
 
+
     getSlice(currentSliceNumber);
+
     $sliderInput.slider('setValue', currentSliceNumber);
 
     var time = Date.now();
@@ -625,6 +673,29 @@ function slice() {
 }
 
 function endSlicing() {
+
+    // GCode logic
+    wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
+    wowFile += "\n"
+    var array = new Uint8Array(5);
+    array[0] = 255;
+    array[1] = 0;
+    array[2] = 255;
+    array[3] = 0;
+    array[4] = 255;
+    wowFile += (new TextDecoder("ASCII")).decode(array)+"\n"
+    wowFile += (new TextDecoder("utf-8")).decode(array)+"\n"
+    wowFile += (new TextDecoder("utf-16")).decode(array)+"\n"
+    //wowFile += (new TextDecoder("ISO 8859-15")).decode(array)+"\n"
+   //wowFile += (new TextDecoder("ISO 8859-1")).decode(array)+"\n"
+    wowFile += (new TextDecoder("Cp1252")).decode(array)+"\n"
+    //wowFile += (new TextDecoder("utf8.bin")).decode(array)+"\n"
+    //wowFile += (new TextDecoder("utf16le.bin")).decode(array)+"\n"
+    //wowFile += (new TextDecoder("utf-16le")).decode(array)+"\n"
+
+
+    zipFile.file("print.wow", wowFile);
+
     sliceImage('none');
     $sidebar.find('input, button').prop('disabled', false);
     $sliderInput.slider('enable');
@@ -649,6 +720,7 @@ function startSlicing() {
 
     zipFile   = null;
     zipFolder = null;
+    wowFile   = null;
     WOWExport = null;
     SVGExport = null;
     PNGExport = null;
@@ -675,6 +747,10 @@ function startSlicing() {
         PNGExport = settings.get('slicer.png');
     }
 
+    // GCode logic
+    wowFile = "";
+    wowFile += "G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n"
+
     slicesNumber && slice();
 }
 
diff --git a/js/slacer/viewer.js b/js/slacer/viewer.js
index 939478e..4464c7f 100644
--- a/js/slacer/viewer.js
+++ b/js/slacer/viewer.js
@@ -123,12 +123,6 @@ var SLAcer = SLAcer || {};
         callback(this.canvas.toDataURL());
     };
 
-    Viewer.prototype.screenshot_canvas = function(callback) {
-        this.render();
-        console.log('canvas.getContext(2d) :', this.canvas.getContext('2d'));
-        callback(this.canvas);
-    };
-
     // -------------------------------------------------------------------------
 
     // global settings

From 2a7bb41a790637483ab8ac52d6970174ed4c9056 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Fri, 2 Mar 2018 17:29:14 +0100
Subject: [PATCH 06/39] - added samples - disabled debug - still not clean -
 still binary problems

---
 js/main.js                  |   8 +++++++-
 other/print.wow             | Bin 0 -> 820951 bytes
 other/self_sliced_print.wow | Bin 0 -> 982185 bytes
 other/slices/1.txt          | Bin 0 -> 51240 bytes
 other/slices/10.txt         | Bin 0 -> 51240 bytes
 other/slices/11.txt         | Bin 0 -> 51240 bytes
 other/slices/12.txt         | Bin 0 -> 51240 bytes
 other/slices/13.txt         | Bin 0 -> 51240 bytes
 other/slices/14.txt         | Bin 0 -> 51240 bytes
 other/slices/15.txt         | Bin 0 -> 51240 bytes
 other/slices/16.txt         | Bin 0 -> 51240 bytes
 other/slices/2.txt          | Bin 0 -> 51240 bytes
 other/slices/3.txt          | Bin 0 -> 51240 bytes
 other/slices/4.txt          | Bin 0 -> 51240 bytes
 other/slices/5.txt          | Bin 0 -> 51240 bytes
 other/slices/6.txt          | Bin 0 -> 51240 bytes
 other/slices/7.txt          | Bin 0 -> 51240 bytes
 other/slices/8.txt          | Bin 0 -> 51240 bytes
 other/slices/9.txt          | Bin 0 -> 51240 bytes
 19 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 other/print.wow
 create mode 100644 other/self_sliced_print.wow
 create mode 100644 other/slices/1.txt
 create mode 100644 other/slices/10.txt
 create mode 100644 other/slices/11.txt
 create mode 100644 other/slices/12.txt
 create mode 100644 other/slices/13.txt
 create mode 100644 other/slices/14.txt
 create mode 100644 other/slices/15.txt
 create mode 100644 other/slices/16.txt
 create mode 100644 other/slices/2.txt
 create mode 100644 other/slices/3.txt
 create mode 100644 other/slices/4.txt
 create mode 100644 other/slices/5.txt
 create mode 100644 other/slices/6.txt
 create mode 100644 other/slices/7.txt
 create mode 100644 other/slices/8.txt
 create mode 100644 other/slices/9.txt

diff --git a/js/main.js b/js/main.js
index d0fcda2..dabbf40 100644
--- a/js/main.js
+++ b/js/main.js
@@ -221,6 +221,10 @@ function getSlice(layerNumber) {
                         pixel++;
                     }
                 }
+                /*
+                for(var i=0*array.length; i<1/4*array.length; i++){
+                    array[i]=255;
+                }*/
                 //console.log('array :', array);
                 //var fileName = layerNumber + '.txt';
                 //zipFolder.file(fileName, array, {type: 'text/plain'});
@@ -233,6 +237,7 @@ function getSlice(layerNumber) {
                     ";\nG1 Z-"+(settings.get('slicer.lifting.height')-settings.get('slicer.layers.height')/1000)+
                     " F"+settings.get('slicer.lifting.speed')+";\n{{\n"
                 wowFile += (new TextDecoder("utf-8")).decode(array)+"\n"
+                // Backup text file
                 zipFolder.file(layerNumber+".txt", array);
                 // GCode logic
                 wowFile += "}}\nM106 S255;\nG4 S"+settings.get('slicer.light.on')/1000+";\n"
@@ -676,6 +681,7 @@ function endSlicing() {
 
     // GCode logic
     wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
+    /*
     wowFile += "\n"
     var array = new Uint8Array(5);
     array[0] = 255;
@@ -692,7 +698,7 @@ function endSlicing() {
     //wowFile += (new TextDecoder("utf8.bin")).decode(array)+"\n"
     //wowFile += (new TextDecoder("utf16le.bin")).decode(array)+"\n"
     //wowFile += (new TextDecoder("utf-16le")).decode(array)+"\n"
-
+*/
 
     zipFile.file("print.wow", wowFile);
 
diff --git a/other/print.wow b/other/print.wow
new file mode 100644
index 0000000000000000000000000000000000000000..30876dca994462274772635be3c3218bba6ed8d5
GIT binary patch
diff --git a/other/self_sliced_print.wow b/other/self_sliced_print.wow
new file mode 100644
index 0000000000000000000000000000000000000000..275fed2811bce555d0aeaa0c1d07c1817aeccb66
GIT binary patch
diff --git a/other/slices/1.txt b/other/slices/1.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c3f753559ea786e10622725618304e49b35075c5
GIT binary patch
diff --git a/other/slices/10.txt b/other/slices/10.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8bcf39fa6953cae11709e2e9c49d031612434c00
GIT binary patch
diff --git a/other/slices/11.txt b/other/slices/11.txt
new file mode 100644
index 0000000000000000000000000000000000000000..495161cbc844ab320ae990d026bcee8ee159a916
GIT binary patch
diff --git a/other/slices/12.txt b/other/slices/12.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e31606222f5954ad78a3a8e5238f0a328e7e48dd
GIT binary patch
diff --git a/other/slices/13.txt b/other/slices/13.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b2f1bb29cf808ecb82315a2c2f2ba1fe2b671647
GIT binary patch
diff --git a/other/slices/14.txt b/other/slices/14.txt
new file mode 100644
index 0000000000000000000000000000000000000000..21e46dea724e9875f91eb894b3dd5f90e254d6b5
GIT binary patch
diff --git a/other/slices/15.txt b/other/slices/15.txt
new file mode 100644
index 0000000000000000000000000000000000000000..85ac93c687cebf8e474640ea5c601b7be76803be
GIT binary patch
diff --git a/other/slices/16.txt b/other/slices/16.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0a94909520a670b572e7d579b6f1ab3329a467a9
GIT binary patch
diff --git a/other/slices/2.txt b/other/slices/2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c3f753559ea786e10622725618304e49b35075c5
GIT binary patch
diff --git a/other/slices/3.txt b/other/slices/3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c3f753559ea786e10622725618304e49b35075c5
GIT binary patch
diff --git a/other/slices/4.txt b/other/slices/4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c3f753559ea786e10622725618304e49b35075c5
GIT binary patch
diff --git a/other/slices/5.txt b/other/slices/5.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c3f753559ea786e10622725618304e49b35075c5
GIT binary patch
diff --git a/other/slices/6.txt b/other/slices/6.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d10e4af90e4d0749a008edb74f81b967b5c9eaea
GIT binary patch
diff --git a/other/slices/7.txt b/other/slices/7.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e0f2344113d8b93c6bdda86090097b07e9a87fdb
GIT binary patch
diff --git a/other/slices/8.txt b/other/slices/8.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0dbe9f6e44fad74a59551d8b349247e94b8b963e
GIT binary patch
diff --git a/other/slices/9.txt b/other/slices/9.txt
new file mode 100644
index 0000000000000000000000000000000000000000..143fda1d6970db35c9b89622c98cba519bbbae79
GIT binary patch

From e72369213a6271c62a75a2625e5fba7dda89e85b Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 01:59:11 +0100
Subject: [PATCH 07/39] - first working commit!

---
 js/main.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 4 deletions(-)

diff --git a/js/main.js b/js/main.js
index dabbf40..d9ae364 100644
--- a/js/main.js
+++ b/js/main.js
@@ -221,6 +221,7 @@ function getSlice(layerNumber) {
                         pixel++;
                     }
                 }
+
                 /*
                 for(var i=0*array.length; i<1/4*array.length; i++){
                     array[i]=255;
@@ -236,11 +237,33 @@ function getSlice(layerNumber) {
                     " F"+settings.get('slicer.lifting.speed')+
                     ";\nG1 Z-"+(settings.get('slicer.lifting.height')-settings.get('slicer.layers.height')/1000)+
                     " F"+settings.get('slicer.lifting.speed')+";\n{{\n"
-                wowFile += (new TextDecoder("utf-8")).decode(array)+"\n"
+                wowBuffer.push(";L:"+layerNumber+";\n");
+                wowBuffer.push("M106 S0;\n");
+                wowBuffer.push("G1 Z"+settings.get('slicer.lifting.height')+
+                    " F"+settings.get('slicer.lifting.speed')+
+                    ";\n");
+                wowBuffer.push("G1 Z-"+(settings.get('slicer.lifting.height')-settings.get('slicer.layers.height')/1000)+
+                    " F"+settings.get('slicer.lifting.speed')+";\n");
+                wowBuffer.push("{{\n");
+
+
+                //var binary_layer = (new TextDecoder("utf-8")).decode(array)
+                //console.log(binary_layer);
+                //wowFile += binary_layer;
+                wowFile += bin2string(array);
+                wowFile += "\n";
+
+                wowBuffer.push(array);
+
                 // Backup text file
                 zipFolder.file(layerNumber+".txt", array);
                 // GCode logic
                 wowFile += "}}\nM106 S255;\nG4 S"+settings.get('slicer.light.on')/1000+";\n"
+
+                wowBuffer.push("\n");
+                wowBuffer.push("}}\n");
+                wowBuffer.push("M106 S255;\n");
+                wowBuffer.push("G4 S"+settings.get('slicer.light.on')/1000+";\n");
             });
 
         }
@@ -348,8 +371,8 @@ function convertURIToImageData(URI) {
 function bin2string(array){
     var result = "";
     for(var i = 0; i < array.length; ++i){
-        //result+= (String.fromCharCode(array[i]));
-        result+= convertHexToString(array[i]);
+        result+= (String.fromCharCode(array[i]));
+        //result+= convertHexToString(array[i]);
     }
     console.log(result);
     return result;
@@ -640,6 +663,7 @@ var slicesNumber;
 var zipFile;
 var zipFolder;
 var wowFile;
+var wowBuffer;
 
 var WOWExport;
 var SVGExport;
@@ -681,6 +705,13 @@ function endSlicing() {
 
     // GCode logic
     wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
+
+
+    wowBuffer.push("M106 S0;\n ");
+    wowBuffer.push("G1 Z20.0;\n ");
+    wowBuffer.push("G4 S300;\n ");
+    wowBuffer.push("M18;");
+
     /*
     wowFile += "\n"
     var array = new Uint8Array(5);
@@ -700,7 +731,8 @@ function endSlicing() {
     //wowFile += (new TextDecoder("utf-16le")).decode(array)+"\n"
 */
 
-    zipFile.file("print.wow", wowFile);
+    zipFile.file("print.wow", wowFile, {binary: true});
+    zipFile.file("print2.wow", wowBuffer);
 
     sliceImage('none');
     $sidebar.find('input, button').prop('disabled', false);
@@ -727,6 +759,7 @@ function startSlicing() {
     zipFile   = null;
     zipFolder = null;
     wowFile   = null;
+    wowBuffer = null;
     WOWExport = null;
     SVGExport = null;
     PNGExport = null;
@@ -755,8 +788,26 @@ function startSlicing() {
 
     // GCode logic
     wowFile = "";
+
+    var array = new Uint8Array(2);
+    array[1]=255;
+    console.log(array);
+    var textDecoder = new TextDecoder("utf-8");
+    var binary_layer = textDecoder.decode(array);
+    console.log(binary_layer);
+    //console.log(textDecoder.encode(binary_layer));
+
     wowFile += "G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n"
 
+    wowBuffer = [];
+    wowBuffer.push("G21;\n");
+    wowBuffer.push("G91;\n");
+    wowBuffer.push("M17;\n");
+    wowBuffer.push("M106 S0;\n");
+    wowBuffer.push("G28 Z0;\n");
+    wowBuffer.push(";W:480;\n");
+    wowBuffer.push(";H:854;\n");
+
     slicesNumber && slice();
 }
 

From 82453149113367bed2824ba1e2317680161dd9e0 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 04:41:35 +0100
Subject: [PATCH 08/39] - clean up - beautify - added custom bottom exposure
 settings - added multiple options - noticed 2d bug

---
 index.html |  63 ++++++++++-----
 js/main.js | 233 +++++++++++++++++++++++++++++------------------------
 2 files changed, 170 insertions(+), 126 deletions(-)

diff --git a/index.html b/index.html
index 54d80fe..cabd9f0 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
         <meta charset="utf-8" />
         <meta http-equiv="X-UA-Compatible" content="IE=edge" />
         <meta name="viewport" content="width=device-width, initial-scale=1" />
-        <title>SLAcer.js (bêta)</title>
+        <title>SLAcer.js for SparkMaker (bêta)</title>
         <link rel="stylesheet" type="text/css" href="vendor/jquery-ui/jquery-ui.min.css" />
         <link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css" />
         <link rel="stylesheet" type="text/css" href="vendor/bootstrap-slider/css/bootstrap-slider.min.css" />
@@ -21,11 +21,12 @@
                         <span class="icon-bar"></span>
                         <span class="icon-bar"></span>
                     </button>
-                    <a class="navbar-brand" href="#">SLAcer.js (bêta)</a>
+                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (bêta) - .wow addon by n0sr3v</a>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
                         <li><a href="#">About</a></li>
+                        <li><a href="https://github.com/n0sr3v/SLAcer.js">GitHub (Fork)</a></li>
                         <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></li>
                     </ul>
                 </div>
@@ -162,6 +163,10 @@ <h3 class="panel-title">Slicer</h3>
                                 <span id="slicer-layer-value">0</span> / <span id="slicer-layers-value">0</span>
                             </span>
                         </div>
+                        <div class="info">
+                            <span class="info-label">Print Time <small>(h:m:s.ms)</small></span>
+                            <span class="info-value" id="print-time">0</span>
+                        </div>
 
                         <hr />
 
@@ -171,16 +176,31 @@ <h3 class="panel-title">Slicer</h3>
                         </div>
                         <div class="form-group">
                             <label for="slicer-light-on">Exposure time <small>(ms)</small></label>
-                            <input type="number" id="slicer-light-on" class="form-control input-sm" placeholder="1000" min="1" />
+                            <input type="number" id="slicer-light-on" class="form-control input-sm" placeholder="10000" min="1" />
+                        </div>
+                        <!-- new -->
+                        <div class="form-group">
+                            <label for="slicer-light-strength">Exposure Strength Grade <small>(bit)</small></label>
+                            <input type="number" id="slicer-light-strength" class="form-control input-sm" placeholder="225" min="1" max="255" />
+                        </div>
+                        <!-- new -->
+                        <div class="form-group">
+                            <label for="slicer-light-bottom">Bottom Layers Exposure Time <small>(ms)</small></label>
+                            <input type="number" id="slicer-light-bottom" class="form-control input-sm" placeholder="60000" min="1" />
                         </div>
 
                         <div class="form-group clearfix">
                             <label for="slicer-lifting-height">Lifting height <small>(mm)</small></label>
-                            <input type="number" id="slicer-lifting-height" class="form-control input-sm" placeholder="3" min="1" />
+                            <input type="number" id="slicer-lifting-height" class="form-control input-sm" placeholder="5" min="1" />
                         </div>
                         <div class="form-group clearfix">
                             <label for="slicer-lifting-speed">Lifting speed <small>(mm/min)</small></label>
-                            <input type="number" id="slicer-lifting-speed" class="form-control input-sm" placeholder="50" min="1" />
+                            <input type="number" id="slicer-lifting-speed" class="form-control input-sm" placeholder="30" min="1" />
+                        </div>
+                        <!-- new -->
+                        <div class="form-group clearfix">
+                            <label for="slicer-decline-speed">Decline speed <small>(mm/min)</small></label>
+                            <input type="number" id="slicer-decline-speed" class="form-control input-sm" placeholder="100" min="1" />
                         </div>
 
                         <hr />
@@ -201,17 +221,22 @@ <h3 class="panel-title">Slicer</h3>
 
                         <div class="form-group">
                             <label for="slicer-make-zip">Make ZIP file</label>
-                            <input type="radio" name="slicer-make-zip" id="slicer-make-zip-yes" value="yes" /> yes
-                            <input type="radio" name="slicer-make-zip" id="slicer-make-zip-no" value="no" checked="checked" /> no
+                            <input type="radio" name="slicer-make-zip" id="slicer-make-zip-yes" value="yes" checked="checked" /> yes
+                            <input type="radio" name="slicer-make-zip" id="slicer-make-zip-no" value="no"  /> no
+                        </div>
+                        <div class="form-group">
+                            <label for="slicer-make-folder">Make layer-folder</label>
+                            <input type="radio" name="slicer-make-folder" id="slicer-make-folder-yes" value="yes" /> yes
+                            <input type="radio" name="slicer-make-folder" id="slicer-make-folder-no" value="no"  checked="checked" /> no
                         </div>
                         <div class="form-group">
-                            <label for="slicer-speed">Speed mode</label>
-                            <input type="radio" name="slicer-speed" id="slicer-speed-yes" value="yes" /> yes
-                            <input type="radio" name="slicer-speed" id="slicer-speed-no" value="no" checked="checked" /> no
+                            <label for="slicer-speed">Slicing mode</label>
+                            <input type="radio" name="slicer-speed" id="slicer-speed-yes" value="yes" checked="checked" /> yes
+                            <input type="radio" name="slicer-speed" id="slicer-speed-no" value="no"  /> no
                         </div>
                         <div class="form-group">
-                            <label for="slicer-speed-delay">Speed mode<br />delay <small>(ms)</small></label>
-                            <input type="number" id="slicer-speed-delay" class="form-control input-sm" placeholder="100" min="1" />
+                            <label for="slicer-speed-delay">Slicing delay<br />delay <small>(ms)</small></label>
+                            <input type="number" id="slicer-speed-delay" class="form-control input-sm" placeholder="10" min="1" />
                         </div>
                     </div>
                 </div><!-- #slicer -->
@@ -226,15 +251,15 @@ <h3 class="panel-title">Build volume</h3>
                     <div id="build-volume-body" class="panel-body collapse in">
                         <div class="form-group">
                             <label for="build-volume-x">X <small>(width)</small></label>
-                            <input type="number" id="build-volume-x" class="form-control input-sm" placeholder="100" min="0" />
+                            <input type="number" id="build-volume-x" class="form-control input-sm" placeholder="102" min="0" />
                         </div>
                         <div class="form-group">
                             <label for="build-volume-y">Y <small>(depth)</small></label>
-                            <input type="number" id="build-volume-y" class="form-control input-sm" placeholder="100" min="0" />
+                            <input type="number" id="build-volume-y" class="form-control input-sm" placeholder="56" min="0" />
                         </div>
                         <div class="form-group">
                             <label for="build-volume-z">Z <small>(height)</small></label>
-                            <input type="number" id="build-volume-z" class="form-control input-sm" placeholder="100" min="0" />
+                            <input type="number" id="build-volume-z" class="form-control input-sm" placeholder="125" min="0" />
                         </div>
                         <div class="form-group">
                             <label for="build-volume-unit">unit</label>
@@ -258,7 +283,7 @@ <h3 class="panel-title">Resin</h3>
                         </div>
                         <div class="form-group">
                             <label for="resin-price">Price <small>($ / l)</small></label>
-                            <input type="number" id="resin-price" class="form-control input-sm" placeholder="50" min="0" />
+                            <input type="number" id="resin-price" class="form-control input-sm" placeholder="60" min="0" />
                         </div>
                     </div>
                 </div><!-- #resin -->
@@ -277,15 +302,15 @@ <h3 class="panel-title">Screen</h3>
                         </div>
                         <div class="form-group">
                             <label for="screen-width">Width <small>(px)</small></label>
-                            <input type="number" id="screen-width" class="form-control input-sm" placeholder="1680" min="0" />
+                            <input type="number" id="screen-width" class="form-control input-sm" placeholder="854" min="0" />
                         </div>
                         <div class="form-group">
                             <label for="screen-height">Height <small>(px)</small></label>
-                            <input type="number" id="screen-height" class="form-control input-sm" placeholder="1050" min="0" />
+                            <input type="number" id="screen-height" class="form-control input-sm" placeholder="480" min="0" />
                         </div>
                         <div class="form-group">
                             <label for="screen-diagonal-size">Diagonal size</label>
-                            <input type="number" id="screen-diagonal-size" class="form-control input-sm" placeholder="22" min="0" />
+                            <input type="number" id="screen-diagonal-size" class="form-control input-sm" placeholder="4.6" min="0" />
                         </div>
                         <div class="form-group">
                             <label for="screen-diagonal-unit">Diagonal unit</label>
diff --git a/js/main.js b/js/main.js
index d9ae364..27c973d 100644
--- a/js/main.js
+++ b/js/main.js
@@ -11,17 +11,21 @@ var settings = new SLAcer.Settings({
     },
     slicer: {
         layers: {
-            height: 100 // μm
+            height: 100, // μm
+            bottom: 3
         },
         light: {
             on : 12000,
-            off: 500
+            bottom: 60000,
+            off: 500,
+            strength: 225
         },
         zip: true,
+        folder: false,
         wow: true,
         svg: false,
         png: false,
-        speed: false,
+        speed: true,
         speedDelay: 10, // ms
         panel: {
             collapsed: false,
@@ -29,6 +33,7 @@ var settings = new SLAcer.Settings({
         },
         lifting: {
             speed : 30, // mm/min
+            decline: 100, // mm/min
             height: 5,  // mm
         }
     },
@@ -121,6 +126,8 @@ function hexToDec(hex) {
 }
 
 function sliceImage(dataURL) {
+
+    console.log("dataURL", dataURL);
     settings.set('slice.dataURL', dataURL || 'none');
 }
 
@@ -187,14 +194,15 @@ function getSlice(layerNumber) {
         if (PNGExport) {
             var fileName = layerNumber + '.png';
             var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
-            zipFolder.file(fileName, imgData, { base64: true });
+            if (settings.get('slicer.folder')) {
+                zipFolder.file(fileName, imgData, {base64: true});
+            }
         }else if (WOWExport) {
             //console.log('layer number:', layerNumber);
             //console.log('z position :', zPosition);
 
             convertURIToImageData(dataURL).then(function(imageData) {
                 // Here you can use imageData
-                // console.log(imageData);
                 /*
                  var red = data[i];
                  var green = data[i+1];
@@ -206,11 +214,8 @@ function getSlice(layerNumber) {
                  */
                 var width = settings.get('screen.width');
                 var height = settings.get('screen.height');
-
                 var pixel = 0;
-
                 var array = new Uint8Array(width*height/8);
-
                 var data = imageData.data;
 
                 for(var w=0; w<data.length/height*4; w+=4) {
@@ -222,48 +227,30 @@ function getSlice(layerNumber) {
                     }
                 }
 
-                /*
-                for(var i=0*array.length; i<1/4*array.length; i++){
-                    array[i]=255;
-                }*/
-                //console.log('array :', array);
-                //var fileName = layerNumber + '.txt';
-                //zipFolder.file(fileName, array, {type: 'text/plain'});
-
-
-                // GCode logic
-
-                wowFile += ";L:"+layerNumber+";\nM106 S0;\nG1 Z"+settings.get('slicer.lifting.height')+
-                    " F"+settings.get('slicer.lifting.speed')+
-                    ";\nG1 Z-"+(settings.get('slicer.lifting.height')-settings.get('slicer.layers.height')/1000)+
-                    " F"+settings.get('slicer.lifting.speed')+";\n{{\n"
-                wowBuffer.push(";L:"+layerNumber+";\n");
-                wowBuffer.push("M106 S0;\n");
-                wowBuffer.push("G1 Z"+settings.get('slicer.lifting.height')+
-                    " F"+settings.get('slicer.lifting.speed')+
-                    ";\n");
-                wowBuffer.push("G1 Z-"+(settings.get('slicer.lifting.height')-settings.get('slicer.layers.height')/1000)+
-                    " F"+settings.get('slicer.lifting.speed')+";\n");
-                wowBuffer.push("{{\n");
-
-
-                //var binary_layer = (new TextDecoder("utf-8")).decode(array)
-                //console.log(binary_layer);
-                //wowFile += binary_layer;
-                wowFile += bin2string(array);
-                wowFile += "\n";
-
-                wowBuffer.push(array);
-
-                // Backup text file
-                zipFolder.file(layerNumber+".txt", array);
-                // GCode logic
-                wowFile += "}}\nM106 S255;\nG4 S"+settings.get('slicer.light.on')/1000+";\n"
-
-                wowBuffer.push("\n");
-                wowBuffer.push("}}\n");
-                wowBuffer.push("M106 S255;\n");
-                wowBuffer.push("G4 S"+settings.get('slicer.light.on')/1000+";\n");
+                if(WOWExport) {// GCode logic
+                    wowFile += ";L:" + layerNumber + ";\nM106 S0;\nG1 Z" + settings.get('slicer.lifting.height') +
+                        " F" + settings.get('slicer.lifting.speed') +
+                        ";\nG1 Z-" + (settings.get('slicer.lifting.height') - settings.get('slicer.layers.height') / 1000) +
+                        " F" + settings.get('slicer.lifting.decline') + ";\n{{\n"
+
+                    //var binary_layer = (new TextDecoder("utf-8")).decode(array)
+                    wowFile += bin2string(array.reverse());
+                    wowFile += "\n";
+
+                    if (settings.get('slicer.folder')) {
+                        // Backup text file
+                        zipFolder.file(layerNumber + ".txt", array.reverse());
+                    }
+
+                    //bottom layer
+                    var exposure_time;
+                    if(layerNumber<=settings.get('slicer.layers.bottom')){
+                        exposure_time = settings.get('slicer.light.bottom');
+                    }else{
+                        exposure_time = settings.get('slicer.light.on');
+                    }
+                    wowFile += "}}\nM106 S"+settings.get('slicer.light.strength')+";\nG4 S" + exposure_time / 1000 + ";\n"
+                }
             });
 
         }
@@ -346,8 +333,10 @@ function getSlice(layerNumber) {
         svg += '</g>';
         svg += '</svg>';
 
-        // add svg file to zip
-        zipFolder.file(layerNumber + '.svg', svg);
+        if (settings.get('slicer.folder')) {
+            // add svg file to zip
+            zipFolder.file(layerNumber + '.svg', svg);
+        }
     }
 
 }
@@ -374,7 +363,6 @@ function bin2string(array){
         result+= (String.fromCharCode(array[i]));
         //result+= convertHexToString(array[i]);
     }
-    console.log(result);
     return result;
 }
 
@@ -486,9 +474,37 @@ function updateSliderUI() {
     var layersHeight = settings.get('slicer.layers.height') / 1000;
     var layersNumber = Math.floor(slicer.mesh.getSize().z / layersHeight);
 
+    console.log("layersHeight", layersHeight);
+    console.log("layersNumber", layersNumber);
+
     $sliderInput.slider('setAttribute', 'max', layersNumber);
     $sliderMaxValue.html(layersNumber);
     $slicerLayersValue.html(layersNumber);
+
+    $printTimeValue.html(msToTime(calcPrintTime(layersHeight, layersNumber)));
+}
+function calcPrintTime(layersHeight, layersNumber){
+    // ([object height]/[layer height])([exposure time]+[uplift time]+[downlift time])+3([ground exposure time]-[exposure time])
+    var result = 0;
+    var uplift_time = settings.get('slicer.lifting.height')/settings.get('slicer.lifting.speed')*60*1000
+    var downlift_time = (settings.get('slicer.lifting.height')-layersHeight)/settings.get('slicer.lifting.decline')*60*1000
+    result += layersNumber*(settings.get('slicer.light.on')+uplift_time+downlift_time)+settings.get('slicer.layers.bottom')*(settings.get('slicer.light.bottom')-settings.get('slicer.light.on'))
+    console.log("downlift_time (ms)", downlift_time);
+    console.log("uplift_time (ms)", uplift_time);
+
+    return result;
+}
+function msToTime(duration) {
+    var milliseconds = parseInt((duration%1000)/100)
+        , seconds = parseInt((duration/1000)%60)
+        , minutes = parseInt((duration/(1000*60))%60)
+        , hours = parseInt((duration/(1000*60*60))%24);
+
+    hours = (hours < 10) ? "0" + hours : hours;
+    minutes = (minutes < 10) ? "0" + minutes : minutes;
+    seconds = (seconds < 10) ? "0" + seconds : seconds;
+
+    return hours + ":" + minutes + ":" + seconds + "." + milliseconds;
 }
 
 // Sidebar
@@ -607,6 +623,13 @@ var $slicerLayerValue  = $slicerBody.find('#slicer-layer-value');
 var $slicerLightOff    = $slicerBody.find('#slicer-light-off');
 var $slicerLightOn     = $slicerBody.find('#slicer-light-on');
 
+//new
+var $slicerLightStrength     = $slicerBody.find('#slicer-light-strength');
+var $slicerLightBottum     = $slicerBody.find('#slicer-light-bottom');
+var $slicerDeclineSpeed     = $slicerBody.find('#slicer-decline-speed');
+var $slicerBottomLayers = settings.get('slicer.layers.bottom');
+var $printTimeValue  = $slicerBody.find('#print-time');
+
 var $slicerLiftingSpeed  = $slicerBody.find('#slicer-lifting-speed');
 var $slicerLiftingHeight = $slicerBody.find('#slicer-lifting-height');
 
@@ -619,6 +642,11 @@ var $slicerSpeedNo     = $slicerBody.find('#slicer-speed-no');
 var $slicerSpeedDelay  = $slicerBody.find('#slicer-speed-delay');
 var $slicerMakeZipYes  = $slicerBody.find('#slicer-make-zip-yes');
 var $slicerMakeZipNo   = $slicerBody.find('#slicer-make-zip-no');
+
+//new
+var $slicerMakeFolderYes  = $slicerBody.find('#slicer-make-folder-yes');
+var $slicerMakeFolderNo  = $slicerBody.find('#slicer-make-folder-no');
+
 var $sliceButton       = $sidebar.find('#slice-button');
 var $abortButton       = $sidebar.find('#abort-button');
 var $zipButton         = $sidebar.find('#zip-button');
@@ -630,6 +658,11 @@ function updateSlicerUI() {
     $slicerLayerHeight.val(slicer.layers.height);
     $slicerLightOff.val(slicer.light.off);
     $slicerLightOn.val(slicer.light.on);
+    //new
+    $slicerLightStrength.val(slicer.light.strength);
+    $slicerLightBottum.val(slicer.light.bottom);
+    $slicerDeclineSpeed.val(slicer.lifting.decline);
+    //$slicerBottomLayers.val(slicer.layers.bottom);
 
     $slicerLiftingSpeed.val(slicer.lifting.speed);
     $slicerLiftingHeight.val(slicer.lifting.height);
@@ -640,6 +673,12 @@ function updateSlicerSettings() {
     settings.set('slicer.light.off', $slicerLightOff.val());
     settings.set('slicer.light.on', $slicerLightOn.val());
 
+    //new
+    settings.set('slicer.light.strength', $slicerLightStrength.val());
+    settings.set('slicer.light.bottom', $slicerLightBottum.val());
+    settings.set('slicer.lifting.decline', $slicerDeclineSpeed.val());
+    settings.set('slicer.layers.bottom', $slicerBottomLayers.val());
+
     settings.set('slicer.lifting.speed', $slicerLiftingSpeed.val());
     settings.set('slicer.lifting.height', $slicerLiftingHeight.val());
 
@@ -648,6 +687,10 @@ function updateSlicerSettings() {
     settings.set('slicer.wow', $slicerExportWOW[0].checked);
 
     settings.set('slicer.zip', $slicerMakeZipYes[0].checked);
+
+    //new
+    settings.set('slicer.folder', $slicerMakeFolderYes[0].checked);
+
     settings.set('slicer.speed', $slicerSpeedYes[0].checked);
     settings.set('slicer.speedDelay', $slicerSpeedDelay.val());
 
@@ -663,7 +706,6 @@ var slicesNumber;
 var zipFile;
 var zipFolder;
 var wowFile;
-var wowBuffer;
 
 var WOWExport;
 var SVGExport;
@@ -703,36 +745,11 @@ function slice() {
 
 function endSlicing() {
 
-    // GCode logic
-    wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
-
-
-    wowBuffer.push("M106 S0;\n ");
-    wowBuffer.push("G1 Z20.0;\n ");
-    wowBuffer.push("G4 S300;\n ");
-    wowBuffer.push("M18;");
-
-    /*
-    wowFile += "\n"
-    var array = new Uint8Array(5);
-    array[0] = 255;
-    array[1] = 0;
-    array[2] = 255;
-    array[3] = 0;
-    array[4] = 255;
-    wowFile += (new TextDecoder("ASCII")).decode(array)+"\n"
-    wowFile += (new TextDecoder("utf-8")).decode(array)+"\n"
-    wowFile += (new TextDecoder("utf-16")).decode(array)+"\n"
-    //wowFile += (new TextDecoder("ISO 8859-15")).decode(array)+"\n"
-   //wowFile += (new TextDecoder("ISO 8859-1")).decode(array)+"\n"
-    wowFile += (new TextDecoder("Cp1252")).decode(array)+"\n"
-    //wowFile += (new TextDecoder("utf8.bin")).decode(array)+"\n"
-    //wowFile += (new TextDecoder("utf16le.bin")).decode(array)+"\n"
-    //wowFile += (new TextDecoder("utf-16le")).decode(array)+"\n"
-*/
-
-    zipFile.file("print.wow", wowFile, {binary: true});
-    zipFile.file("print2.wow", wowBuffer);
+    if(WOWExport) {// GCode & export logic
+        wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
+
+        zipFile.file("print.wow", wowFile, {binary: true});
+    }
 
     sliceImage('none');
     $sidebar.find('input, button').prop('disabled', false);
@@ -759,18 +776,20 @@ function startSlicing() {
     zipFile   = null;
     zipFolder = null;
     wowFile   = null;
-    wowBuffer = null;
     WOWExport = null;
     SVGExport = null;
     PNGExport = null;
 
     if (settings.get('slicer.zip')) {
         zipFile   = new JSZip();
-        zipFolder = zipFile.folder('slices');
-        zipFile.file("README.txt", 'Generated by SLAcer.js\r\nhttp://lautr3k.github.io/SLAcer.js/\r\n');
+        if (settings.get('slicer.folder')) {
+            zipFolder = zipFile.folder('slices');
+        }
+        zipFile.file("README.txt", 'Generated by SLAcer.js for SparkMaker\r\nhttps://n0sr3v.github.io/SLAcer.js/\r\n\r\nProject based on: \r\nhttps://github.com/lautr3k/SLAcer.js\r\nAppreciate this work!\r\n');
         zipFile.file("slacer.json", JSON.stringify({
             imageExtension: settings.get('slicer.png') ? 'png' : settings.get('slicer.svg') ? 'svg' : 'wow',
-            imageDirectory: 'slices',
+            imageDirectoryCreated: settings.get('slicer.folder') ? 'false' : 'true',
+            imageDirectory: !settings.get('slicer.folder') ? '' : 'slices',
             screenWidth   : settings.get('screen.width'),
             screenHeight  : settings.get('screen.height'),
             screenSize    : settings.get('screen.diagonal.size'),
@@ -778,7 +797,10 @@ function startSlicing() {
             layersNumber  : slicesNumber,
             layersHeight  : settings.get('slicer.layers.height') / 1000,     // mm
             exposureTime  : parseInt(settings.get('slicer.light.on')),       // ms
+            exposureStrength  : parseInt(settings.get('slicer.light.strength')),       // ms
+            bottomExposureTime  : parseInt(settings.get('slicer.light.bottom')),       // ms
             liftingSpeed  : parseInt(settings.get('slicer.lifting.speed')),  // mm/min
+            declineSpeed  : parseInt(settings.get('slicer.lifting.decline')),  // mm/min
             liftingHeight : parseInt(settings.get('slicer.lifting.height'))  // mm
         }, null, 2));
         WOWExport = settings.get('slicer.wow')
@@ -786,27 +808,20 @@ function startSlicing() {
         PNGExport = settings.get('slicer.png');
     }
 
-    // GCode logic
-    wowFile = "";
+    if(WOWExport){// GCode logic
+        wowFile = "";
 
-    var array = new Uint8Array(2);
-    array[1]=255;
-    console.log(array);
-    var textDecoder = new TextDecoder("utf-8");
-    var binary_layer = textDecoder.decode(array);
-    console.log(binary_layer);
-    //console.log(textDecoder.encode(binary_layer));
+        // Tests
+        var array = new Uint8Array(2);
+        array[1]=255;
+        console.log(array);
+        var textDecoder = new TextDecoder("utf-8");
+        var binary_layer = textDecoder.decode(array);
+        console.log(binary_layer);
+        //console.log(textDecoder.encode(binary_layer));
 
-    wowFile += "G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n"
-
-    wowBuffer = [];
-    wowBuffer.push("G21;\n");
-    wowBuffer.push("G91;\n");
-    wowBuffer.push("M17;\n");
-    wowBuffer.push("M106 S0;\n");
-    wowBuffer.push("G28 Z0;\n");
-    wowBuffer.push(";W:480;\n");
-    wowBuffer.push(";H:854;\n");
+        wowFile += "G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n"
+    }
 
     slicesNumber && slice();
 }
@@ -839,6 +854,10 @@ $abortButton.on('click', function(e) {
 
 $('#slicer-image-extension-' + (settings.get('slicer.png') ? 'png' : settings.get('slicer.svg') ? 'svg' : 'wow')).prop('checked', true);
 $('#slicer-make-zip-' + (settings.get('slicer.zip') ? 'yes' : 'no')).prop('checked', true);
+
+//new
+$('#slicer-make-folder-' + (settings.get('slicer.folder') ? 'yes' : 'no')).prop('checked', true);
+
 $('#slicer-speed-' + (settings.get('slicer.speed') ? 'yes' : 'no')).prop('checked', true);
 $('#slicer input').on('input, change', updateSlicerSettings);
 updateSlicerUI();

From ff58536422d1ef0fa7af89d36bd047668b15bdad Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 04:45:22 +0100
Subject: [PATCH 09/39] - removed debug

---
 js/main.js | 2 --
 1 file changed, 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 27c973d..b9c5656 100644
--- a/js/main.js
+++ b/js/main.js
@@ -126,8 +126,6 @@ function hexToDec(hex) {
 }
 
 function sliceImage(dataURL) {
-
-    console.log("dataURL", dataURL);
     settings.set('slice.dataURL', dataURL || 'none');
 }
 

From f467f482f340c58851ed0e5142061fec539a4104 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 04:52:46 +0100
Subject: [PATCH 10/39] - changed stl file - added stl file

---
 js/main.js         |   4 +++-
 stl/SparkMaker.stl | Bin 0 -> 43084 bytes
 2 files changed, 3 insertions(+), 1 deletion(-)
 create mode 100644 stl/SparkMaker.stl

diff --git a/js/main.js b/js/main.js
index b9c5656..56857e5 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1284,8 +1284,10 @@ loader.onError = errorHandler;
 // -----------------------------------------------------------------------------
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
-var stl = 'stl/StressTest.stl';
+//var stl = 'stl/StressTest.stl';
 //var stl = 'stl/SLAcer.stl';
+var stl = 'stl/SparkMaker.stl';
+
 
 // File url
 // var url = 'http://' + window.location.hostname + window.location.pathname + stl;
diff --git a/stl/SparkMaker.stl b/stl/SparkMaker.stl
new file mode 100644
index 0000000000000000000000000000000000000000..d05e6f08c5c63bb872c9e73ff7626d200909faa9
GIT binary patch

From 4fb4e593c7216427b72d0c58034e9c170b57cf21 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 04:58:40 +0100
Subject: [PATCH 11/39] - changed stl file

---
 js/main.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 56857e5..a8324d4 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1285,8 +1285,8 @@ loader.onError = errorHandler;
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
 //var stl = 'stl/StressTest.stl';
-//var stl = 'stl/SLAcer.stl';
-var stl = 'stl/SparkMaker.stl';
+var stl = 'stl/SLAcer.stl';
+//var stl = 'stl/SparkMaker.stl';
 
 
 // File url

From 1999626fb79af4dcd87131ae09b623d1fb4122d5 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 04:59:43 +0100
Subject: [PATCH 12/39] - changed stl file

---
 js/main.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index a8324d4..56857e5 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1285,8 +1285,8 @@ loader.onError = errorHandler;
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
 //var stl = 'stl/StressTest.stl';
-var stl = 'stl/SLAcer.stl';
-//var stl = 'stl/SparkMaker.stl';
+//var stl = 'stl/SLAcer.stl';
+var stl = 'stl/SparkMaker.stl';
 
 
 // File url

From 342b64eb82397cdfd9bf66a0752a594f597c4540 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 05:10:21 +0100
Subject: [PATCH 13/39] - changed stl file - added favicon

---
 favicon.ico | Bin 0 -> 16958 bytes
 js/main.js  |   4 ++--
 2 files changed, 2 insertions(+), 2 deletions(-)
 create mode 100644 favicon.ico

diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..6ca7273d62118fc6046d887e74856ede6ca23f5e
GIT binary patch
diff --git a/js/main.js b/js/main.js
index 56857e5..404e521 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1284,9 +1284,9 @@ loader.onError = errorHandler;
 // -----------------------------------------------------------------------------
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
-//var stl = 'stl/StressTest.stl';
+var stl = 'stl/StressTest.stl';
 //var stl = 'stl/SLAcer.stl';
-var stl = 'stl/SparkMaker.stl';
+//var stl = 'stl/SparkMaker.stl';
 
 
 // File url

From 756d17fc6b01a27429ed276fa9431ed70cfa39f5 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 05:11:31 +0100
Subject: [PATCH 14/39] - changed heading

---
 index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/index.html b/index.html
index cabd9f0..59f16ce 100644
--- a/index.html
+++ b/index.html
@@ -21,7 +21,7 @@
                         <span class="icon-bar"></span>
                         <span class="icon-bar"></span>
                     </button>
-                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (bêta) - .wow addon by n0sr3v</a>
+                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (bêta)</a>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">

From 6dab4c6b969a75461472ee04df6d2e0a31bb50d1 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 05:15:18 +0100
Subject: [PATCH 15/39] - changed stl

---
 js/main.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 404e521..56857e5 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1284,9 +1284,9 @@ loader.onError = errorHandler;
 // -----------------------------------------------------------------------------
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
-var stl = 'stl/StressTest.stl';
+//var stl = 'stl/StressTest.stl';
 //var stl = 'stl/SLAcer.stl';
-//var stl = 'stl/SparkMaker.stl';
+var stl = 'stl/SparkMaker.stl';
 
 
 // File url

From 995e8249ede43c589da1ea6bd2d5b5ecf689404a Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Sun, 4 Mar 2018 05:22:25 +0100
Subject: [PATCH 16/39] Update main.js

stl/SparkMaker.stl seems not to be working .. changed to default.
---
 js/main.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 56857e5..404e521 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1284,9 +1284,9 @@ loader.onError = errorHandler;
 // -----------------------------------------------------------------------------
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
-//var stl = 'stl/StressTest.stl';
+var stl = 'stl/StressTest.stl';
 //var stl = 'stl/SLAcer.stl';
-var stl = 'stl/SparkMaker.stl';
+//var stl = 'stl/SparkMaker.stl';
 
 
 // File url

From b219d3d2a539ad5014abaae1e657e8e670cc227c Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Sun, 4 Mar 2018 05:24:38 +0100
Subject: [PATCH 17/39] Update index.html

- added link
---
 index.html | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/index.html b/index.html
index 59f16ce..1d36d69 100644
--- a/index.html
+++ b/index.html
@@ -21,11 +21,12 @@
                         <span class="icon-bar"></span>
                         <span class="icon-bar"></span>
                     </button>
-                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (bêta)</a>
+                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta)</a>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
                         <li><a href="#">About</a></li>
+                        <li><a href="https://www.thingiverse.com/groups/sparkmaker/forums/gadgets/topic:28168">Thingiverse</a></li>
                         <li><a href="https://github.com/n0sr3v/SLAcer.js">GitHub (Fork)</a></li>
                         <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></li>
                     </ul>

From 4bcc1fcf6e126a263b3e5fc341b7d9abb9978183 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 05:41:27 +0100
Subject: [PATCH 18/39] - mirror bug hotfix

---
 js/main.js | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 56857e5..006c7a7 100644
--- a/js/main.js
+++ b/js/main.js
@@ -232,12 +232,12 @@ function getSlice(layerNumber) {
                         " F" + settings.get('slicer.lifting.decline') + ";\n{{\n"
 
                     //var binary_layer = (new TextDecoder("utf-8")).decode(array)
-                    wowFile += bin2string(array.reverse());
+                    wowFile += bin2string(array);
                     wowFile += "\n";
 
                     if (settings.get('slicer.folder')) {
                         // Backup text file
-                        zipFolder.file(layerNumber + ".txt", array.reverse());
+                        zipFolder.file(layerNumber + ".txt", array);
                     }
 
                     //bottom layer
@@ -747,6 +747,9 @@ function endSlicing() {
         wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
 
         zipFile.file("print.wow", wowFile, {binary: true});
+
+        // hotfix for mirror bug
+        flipGeometry();
     }
 
     sliceImage('none');
@@ -807,6 +810,10 @@ function startSlicing() {
     }
 
     if(WOWExport){// GCode logic
+
+        // hotfix for mirror bug
+        flipGeometry();
+
         wowFile = "";
 
         // Tests

From d0967b99ed6a01c89503393da17345c3a5908644 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 06:40:24 +0100
Subject: [PATCH 19/39] - mirror bug mesh

---
 js/main.js | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/js/main.js b/js/main.js
index bd37836..8892285 100644
--- a/js/main.js
+++ b/js/main.js
@@ -608,9 +608,11 @@ function updateMeshInfoUI() {
     var cost   = volume * settings.get('resin.price') / 1000;
 
     $meshFaces.html(mesh.geometry.faces.length);
-    $meshVolume.html(volume);
-    $meshWeight.html(weight);
-    $meshCost.html(cost);
+
+    // mirror bugfix
+    $meshVolume.html(Math.abs(volume));
+    $meshWeight.html(Math.abs(weight));
+    $meshCost.html(Math.abs(weight));
 }
 
 // Slicer panel

From 8e667f328d380b875ca525507fc33751965d36bc Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Sun, 4 Mar 2018 06:54:42 +0100
Subject: [PATCH 20/39] Update index.html

- credits
---
 index.html | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/index.html b/index.html
index 1d36d69..5606461 100644
--- a/index.html
+++ b/index.html
@@ -21,7 +21,8 @@
                         <span class="icon-bar"></span>
                         <span class="icon-bar"></span>
                     </button>
-                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta)</a>
+                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta) </a>
+                    Big thank you to lautr3k! (project core dev) see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">

From 23b873cf2dad7c12621ef639bc576fae217dc20b Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Sun, 4 Mar 2018 06:56:18 +0100
Subject: [PATCH 21/39] Update index.html

- style
---
 index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/index.html b/index.html
index 5606461..6750748 100644
--- a/index.html
+++ b/index.html
@@ -22,7 +22,7 @@
                         <span class="icon-bar"></span>
                     </button>
                     <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta) </a>
-                    Big thank you to lautr3k! (project core dev) see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>
+                    <div class="navbar-brand">Big thank you to lautr3k! (project core dev) see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></div>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">

From ad725afbf02e73eacb1308e9587d92ecb810bbf3 Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Sun, 4 Mar 2018 06:59:09 +0100
Subject: [PATCH 22/39] Update index.html

- style
---
 index.html | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/index.html b/index.html
index 6750748..2cfde39 100644
--- a/index.html
+++ b/index.html
@@ -21,8 +21,8 @@
                         <span class="icon-bar"></span>
                         <span class="icon-bar"></span>
                     </button>
-                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta) </a>
-                    <div class="navbar-brand">Big thank you to lautr3k! (project core dev) see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></div>
+                    <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta)</a>
+                    <div class="navbar-brand">| Big thank you to lautr3k! (project core dev) see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></div>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">

From 46e66e6ecd1612544384d5c85a0fb5a8cc9c9ef4 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 14:06:01 +0100
Subject: [PATCH 23/39] - runtime tests - exchanged stl (hope it works this
 time)

---
 index.html               |   5 +++--
 js/main.js               |  16 ++++++++++++----
 stl/SparkMaker_fixed.stl | Bin 0 -> 43084 bytes
 3 files changed, 15 insertions(+), 6 deletions(-)
 create mode 100644 stl/SparkMaker_fixed.stl

diff --git a/index.html b/index.html
index 2cfde39..9637ea2 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,7 @@
         <meta http-equiv="X-UA-Compatible" content="IE=edge" />
         <meta name="viewport" content="width=device-width, initial-scale=1" />
         <title>SLAcer.js for SparkMaker (bêta)</title>
+        <link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
         <link rel="stylesheet" type="text/css" href="vendor/jquery-ui/jquery-ui.min.css" />
         <link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css" />
         <link rel="stylesheet" type="text/css" href="vendor/bootstrap-slider/css/bootstrap-slider.min.css" />
@@ -22,7 +23,7 @@
                         <span class="icon-bar"></span>
                     </button>
                     <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta)</a>
-                    <div class="navbar-brand">| Big thank you to lautr3k! (project core dev) see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></div>
+                    <div class="navbar-brand"><small>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</small></div>
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
@@ -106,7 +107,7 @@ <h3 class="panel-title">File</h3>
                             <span class="btn btn-default btn-file btn-xs">
                                 Browse <input type="file" name="file" id="file-input" accept=".stl" />
                             </span>
-                            <small>Or drop an STL file anywhere.</small>
+                            <small>Or drop an STL file anywhere.<br>In case of error check your model <a href="https://service.netfabb.com/service.php">here</a>!</small>
                         </div>
                     </div>
                 </div><!-- #file -->
diff --git a/js/main.js b/js/main.js
index 8892285..e57ceb9 100644
--- a/js/main.js
+++ b/js/main.js
@@ -218,8 +218,8 @@ function getSlice(layerNumber) {
 
                 for(var w=0; w<data.length/height*4; w+=4) {
                     for(var h=w; h<width*height*4; h+=(4*width)) {
-                        if(data[h]!=0){
-                            array[(pixel/8) | 0] += Math.pow(2,(pixel%8))
+                        if(data[h]!==0){
+                            array[~~(pixel/8)] += Math.pow(2,(pixel%8))
                         }
                         pixel++;
                     }
@@ -233,6 +233,7 @@ function getSlice(layerNumber) {
 
                     //var binary_layer = (new TextDecoder("utf-8")).decode(array)
                     wowFile += bin2string(array);
+                    //wowFile += array.map(intBytetoHexBin);
                     wowFile += "\n";
 
                     if (settings.get('slicer.folder')) {
@@ -359,10 +360,16 @@ function bin2string(array){
     var result = "";
     for(var i = 0; i < array.length; ++i){
         result+= (String.fromCharCode(array[i]));
-        //result+= convertHexToString(array[i]);
+        //result+= intBytetoHexBin(array[i]);
     }
     return result;
 }
+// array.map(intBytetoHexBin);
+function intBytetoHexBin(value){
+    //var hex_array = ["\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F","\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F","\x20","\x21","\x22","\x23","\x24","\x25","\x26","\x27","\x28","\x29","\x2A","\x2B","\x2C","\x2D","\x2E","\x2F","\x30","\x31","\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\x3A","\x3B","\x3C","\x3D","\x3E","\x3F","\x40","\x41","\x42","\x43","\x44","\x45","\x46","\x47","\x48","\x49","\x4A","\x4B","\x4C","\x4D","\x4E","\x4F","\x50","\x51","\x52","\x53","\x54","\x55","\x56","\x57","\x58","\x59","\x5A","\x5B","\x5C","\x5D","\x5E","\x5F","\x60","\x61","\x62","\x63","\x64","\x65","\x66","\x67","\x68","\x69","\x6A","\x6B","\x6C","\x6D","\x6E","\x6F","\x70","\x71","\x72","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7A","\x7B","\x7C","\x7D","\x7E","\x7F","\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E","\x8F","\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E","\x9F","\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6","\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE","\xAF","\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6","\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE","\xBF","\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6","\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE","\xCF","\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6","\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE","\xDF","\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6","\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE","\xEF","\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6","\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE","\xFF"];
+    //return hex_array[value];
+    return ["\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F","\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F","\x20","\x21","\x22","\x23","\x24","\x25","\x26","\x27","\x28","\x29","\x2A","\x2B","\x2C","\x2D","\x2E","\x2F","\x30","\x31","\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\x3A","\x3B","\x3C","\x3D","\x3E","\x3F","\x40","\x41","\x42","\x43","\x44","\x45","\x46","\x47","\x48","\x49","\x4A","\x4B","\x4C","\x4D","\x4E","\x4F","\x50","\x51","\x52","\x53","\x54","\x55","\x56","\x57","\x58","\x59","\x5A","\x5B","\x5C","\x5D","\x5E","\x5F","\x60","\x61","\x62","\x63","\x64","\x65","\x66","\x67","\x68","\x69","\x6A","\x6B","\x6C","\x6D","\x6E","\x6F","\x70","\x71","\x72","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7A","\x7B","\x7C","\x7D","\x7E","\x7F","\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E","\x8F","\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E","\x9F","\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6","\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE","\xAF","\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6","\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE","\xBF","\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6","\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE","\xCF","\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6","\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE","\xDF","\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6","\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE","\xEF","\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6","\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE","\xFF"][value];
+}
 
 function BinToText(input) {
     return parseInt(input,2).toString(10);
@@ -1293,9 +1300,10 @@ loader.onError = errorHandler;
 // -----------------------------------------------------------------------------
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
-var stl = 'stl/StressTest.stl';
+//var stl = 'stl/StressTest.stl';
 //var stl = 'stl/SLAcer.stl';
 //var stl = 'stl/SparkMaker.stl';
+var stl = 'stl/SparkMaker_fixed.stl';
 
 
 // File url
diff --git a/stl/SparkMaker_fixed.stl b/stl/SparkMaker_fixed.stl
new file mode 100644
index 0000000000000000000000000000000000000000..e6479c128eb8f5eec3ea1ed5038b9c5059c0fe8d
GIT binary patch

From 948e650f15f3e5103d3130b9e577bb154a584a98 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Sun, 4 Mar 2018 14:07:33 +0100
Subject: [PATCH 24/39] - exchanged stl (it does not work)

---
 js/main.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index e57ceb9..a979c32 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1300,10 +1300,10 @@ loader.onError = errorHandler;
 // -----------------------------------------------------------------------------
 // example STL file
 //var stl = 'stl/Octocat-v2.stl';
-//var stl = 'stl/StressTest.stl';
+var stl = 'stl/StressTest.stl';
 //var stl = 'stl/SLAcer.stl';
 //var stl = 'stl/SparkMaker.stl';
-var stl = 'stl/SparkMaker_fixed.stl';
+//var stl = 'stl/SparkMaker_fixed.stl';
 
 
 // File url

From 32680152c0ca2ad51974c2f3a3cd4268eba81100 Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Mon, 5 Mar 2018 02:13:09 +0100
Subject: [PATCH 25/39] - fixed estimated print time

---
 js/main.js | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index a979c32..998f77b 100644
--- a/js/main.js
+++ b/js/main.js
@@ -493,9 +493,17 @@ function calcPrintTime(layersHeight, layersNumber){
     var result = 0;
     var uplift_time = settings.get('slicer.lifting.height')/settings.get('slicer.lifting.speed')*60*1000
     var downlift_time = (settings.get('slicer.lifting.height')-layersHeight)/settings.get('slicer.lifting.decline')*60*1000
-    result += layersNumber*(settings.get('slicer.light.on')+uplift_time+downlift_time)+settings.get('slicer.layers.bottom')*(settings.get('slicer.light.bottom')-settings.get('slicer.light.on'))
+    result = layersNumber*(parseInt(settings.get('slicer.light.on'))+uplift_time+downlift_time)+
+        settings.get('slicer.layers.bottom')*(settings.get('slicer.light.bottom')-settings.get('slicer.light.on'))
+    console.log("slicer.light.on (ms)", settings.get('slicer.light.on'));
+    console.log("slicer.layers.bottom)", settings.get('slicer.layers.bottom'));
+    console.log("slicer.light.bottom)", settings.get('slicer.light.bottom'));
     console.log("downlift_time (ms)", downlift_time);
     console.log("uplift_time (ms)", uplift_time);
+    console.log("tmp 0 (ms)", parseInt(settings.get('slicer.light.on')) + uplift_time );
+    console.log("tmp 1 (ms)", layersNumber*(parseInt(settings.get('slicer.light.on'))+uplift_time+downlift_time));
+    console.log("tmp 2 (ms)", settings.get('slicer.layers.bottom')*(settings.get('slicer.light.bottom')-settings.get('slicer.light.on')));
+    console.log("result (ms)", result);
 
     return result;
 }
@@ -684,7 +692,7 @@ function updateSlicerSettings() {
     settings.set('slicer.light.strength', $slicerLightStrength.val());
     settings.set('slicer.light.bottom', $slicerLightBottum.val());
     settings.set('slicer.lifting.decline', $slicerDeclineSpeed.val());
-    settings.set('slicer.layers.bottom', $slicerBottomLayers.val());
+    //settings.set('slicer.layers.bottom', $slicerBottomLayers.val());
 
     settings.set('slicer.lifting.speed', $slicerLiftingSpeed.val());
     settings.set('slicer.lifting.height', $slicerLiftingHeight.val());

From ca382bd13b46d392c6deaada9ae51f90ee4c8712 Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Mon, 5 Mar 2018 02:45:39 +0100
Subject: [PATCH 26/39] Update index.html

- improved responsive layout (mobile)
---
 index.html | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/index.html b/index.html
index 9637ea2..bc0d435 100644
--- a/index.html
+++ b/index.html
@@ -23,11 +23,12 @@
                         <span class="icon-bar"></span>
                     </button>
                     <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta)</a>
-                    <div class="navbar-brand"><small>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</small></div>
+
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
                         <li><a href="#">About</a></li>
+                        <li><small>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</small></li>
                         <li><a href="https://www.thingiverse.com/groups/sparkmaker/forums/gadgets/topic:28168">Thingiverse</a></li>
                         <li><a href="https://github.com/n0sr3v/SLAcer.js">GitHub (Fork)</a></li>
                         <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></li>

From 2a82c0a71b552ca357d2eb3a5b1cededb424ec97 Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Mon, 5 Mar 2018 02:49:00 +0100
Subject: [PATCH 27/39] Update index.html

- layout
---
 index.html | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/index.html b/index.html
index bc0d435..f5eba26 100644
--- a/index.html
+++ b/index.html
@@ -27,8 +27,9 @@
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
-                        <li><a href="#">About</a></li>
                         <li><small>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</small></li>
+                        
+                        <li><a href="#">About</a></li>
                         <li><a href="https://www.thingiverse.com/groups/sparkmaker/forums/gadgets/topic:28168">Thingiverse</a></li>
                         <li><a href="https://github.com/n0sr3v/SLAcer.js">GitHub (Fork)</a></li>
                         <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></li>

From 4c5c2b516baf0d5d5deecf1489ec9b139c467534 Mon Sep 17 00:00:00 2001
From: n0sr3v <n0sr3v@googlemail.com>
Date: Mon, 5 Mar 2018 02:55:48 +0100
Subject: [PATCH 28/39] Update index.html

- beautify
---
 index.html | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/index.html b/index.html
index f5eba26..8a15ddd 100644
--- a/index.html
+++ b/index.html
@@ -23,13 +23,11 @@
                         <span class="icon-bar"></span>
                     </button>
                     <a class="navbar-brand" href="#">SLAcer.js for SparkMaker (beta)</a>
-
                 </div>
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
-                        <li><small>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</small></li>
-                        
                         <li><a href="#">About</a></li>
+                        <li>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</li>
                         <li><a href="https://www.thingiverse.com/groups/sparkmaker/forums/gadgets/topic:28168">Thingiverse</a></li>
                         <li><a href="https://github.com/n0sr3v/SLAcer.js">GitHub (Fork)</a></li>
                         <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></li>

From f2d3ec5d3e33d73221049221007d0cabcdc22afb Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Mon, 5 Mar 2018 12:01:22 +0100
Subject: [PATCH 29/39] - design issue

---
 index.html | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/index.html b/index.html
index 8a15ddd..aea2dad 100644
--- a/index.html
+++ b/index.html
@@ -27,10 +27,9 @@
                 <div id="navbar" class="navbar-collapse collapse">
                     <ul class="nav navbar-nav navbar-right">
                         <li><a href="#">About</a></li>
-                        <li>↪Big thank you is due to lautr3k! (project core dev - see <a href="https://github.com/lautr3k/SLAcer.js">GitHub</a>)</li>
                         <li><a href="https://www.thingiverse.com/groups/sparkmaker/forums/gadgets/topic:28168">Thingiverse</a></li>
                         <li><a href="https://github.com/n0sr3v/SLAcer.js">GitHub (Fork)</a></li>
-                        <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub</a></li>
+                        <li><a href="https://github.com/lautr3k/SLAcer.js">GitHub (↪thank you to lautr3k)</a></li>
                     </ul>
                 </div>
             </div>

From be9568566e920d3518fd8cce39877869426cbfee Mon Sep 17 00:00:00 2001
From: Kieran David Evans <keyz182@gmail.com>
Date: Mon, 5 Mar 2018 14:00:26 +0000
Subject: [PATCH 30/39] Serivce worker and manifest to allow offline usage

---
 .idea/vcs.xml |  6 +++++
 index.html    | 14 +++++++++++-
 manifest.json |  8 +++++++
 sw.js         | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+), 1 deletion(-)
 create mode 100644 .idea/vcs.xml
 create mode 100644 manifest.json
 create mode 100644 sw.js

diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/index.html b/index.html
index aea2dad..1120cb5 100644
--- a/index.html
+++ b/index.html
@@ -11,6 +11,8 @@
         <link rel="stylesheet" type="text/css" href="vendor/bootstrap-slider/css/bootstrap-slider.min.css" />
         <link rel="stylesheet" type="text/css" href="vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css" />
         <link rel="stylesheet" type="text/css" href="css/main.css" />
+        <link rel="manifest" href="./manifest.json">
+
     </head>
     <body>
         <nav class="navbar navbar-inverse navbar-fixed-top">
@@ -366,7 +368,17 @@ <h3 class="panel-title">Colors</h3>
             <!-- <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button> -->
             <p class="message">Alert message empty...</p>
         </div>
-
+        <script type="text/javascript">
+            if (navigator.serviceWorker) {
+                navigator.serviceWorker.register('sw.js', {scope: '/'}).then(function(reg) {
+                    // registration worked
+                    console.log('Registration succeeded. Scope is ' + reg.scope);
+                }).catch(function(error) {
+                    // registration failed
+                    console.log('Registration failed with ' + error);
+                });
+            }
+        </script>
         <script src="vendor/jquery-2.1.4.min.js" type="text/javascript"></script>
         <script src="vendor/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
         <script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..f0d0ca7
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,8 @@
+{
+  "short_name": "SLAcer.js",
+  "name": "SLAcer.js (bêta)",
+  "description": "SLAcer.js (bêta)",
+  "start_url": "./index.html",
+  "display": "standalone",
+  "orientation": "landscape"
+}
\ No newline at end of file
diff --git a/sw.js b/sw.js
new file mode 100644
index 0000000..50995c8
--- /dev/null
+++ b/sw.js
@@ -0,0 +1,61 @@
+// Use a cacheName for cache versioning
+var cacheName = 'v1:static';
+var cacheFiles = [
+    './',
+    'index.html',
+    './index.html',
+    './css/main.css',
+    './js/main.js',
+    './js/loader/stl.js',
+    './js/slacer/mesh.js',
+    './js/slacer/settings.js',
+    './js/slacer/slicer.js',
+    './js/slacer/viewer.js',
+    './js/slacer/viewcontrols.js',
+    './js/slacer/viewer2d.js',
+    './js/slacer/viewer3d.js',
+    './vendor/jquery-ui/jquery-ui.min.css',
+    './vendor/bootstrap/css/bootstrap.min.css',
+    './vendor/bootstrap-slider/css/bootstrap-slider.min.css',
+    './vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css',
+    './vendor/jquery-2.1.4.min.js',
+    './vendor/jquery-ui/jquery-ui.min.js',
+    './vendor/bootstrap/js/bootstrap.min.js',
+    './vendor/bootstrap-slider/bootstrap-slider.min.js',
+    './vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js',
+    './vendor/lodash.min.js',
+    './vendor/three.min.js',
+    './vendor/earcut.js',
+    './vendor/triangulation.js',
+    './vendor/OrbitControls.js',
+    './vendor/FileSaver.min.js',
+    './vendor/jszip.min.js'
+];
+
+// During the installation phase, you'll usually want to cache static assets.
+self.addEventListener('install', function(e) {
+    // Once the service worker is installed, go ahead and fetch the resources to make this work offline.
+    console.log('install');
+    e.waitUntil(
+        caches.open(cacheName).then(function(cache) {
+            return cache.addAll(cacheFiles).then(function() {
+                self.skipWaiting();
+            });
+        })
+    );
+});
+
+// when the browser fetches a URL…
+self.addEventListener('fetch', function(event) {
+    // … either respond with the cached object or go ahead and fetch the actual URL
+    event.respondWith(
+        caches.match(event.request).then(function(resp) {
+            return resp || fetch(event.request).then(function(response) {
+                return caches.open(cacheName).then(function(cache) {
+                    cache.put(event.request, response.clone());
+                    return response;
+                });
+            });
+        })
+    );
+});
\ No newline at end of file

From c871a55721b8a615788dd0e861588c8276c8f18b Mon Sep 17 00:00:00 2001
From: Fabian <fabian.neumann@ima-zlw-ifu.rwth-aachen.de>
Date: Thu, 8 Mar 2018 15:06:38 +0100
Subject: [PATCH 31/39] - fixed 0 layer bug (due geometry flip) - removed debug

---
 js/main.js | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 998f77b..281e8a3 100644
--- a/js/main.js
+++ b/js/main.js
@@ -134,15 +134,20 @@ function getSlice(layerNumber) {
     removeSlices();
     removeShapes();
 
+    // debug
+    // console.log("layerNumber", layerNumber)
+
     // ...
     $slicerLayerValue.html(layerNumber);
 
+
     if (layerNumber < 1) {
         viewer2d.render();
         viewer3d.render();
         return;
     }
 
+
     if (transformations.update) {
         throw 'transformations not applyed...';
     }
@@ -479,8 +484,8 @@ function updateSliderUI() {
     var layersHeight = settings.get('slicer.layers.height') / 1000;
     var layersNumber = Math.floor(slicer.mesh.getSize().z / layersHeight);
 
-    console.log("layersHeight", layersHeight);
-    console.log("layersNumber", layersNumber);
+    // console.log("layersHeight", layersHeight);
+    // console.log("layersNumber", layersNumber);
 
     $sliderInput.slider('setAttribute', 'max', layersNumber);
     $sliderMaxValue.html(layersNumber);
@@ -495,6 +500,7 @@ function calcPrintTime(layersHeight, layersNumber){
     var downlift_time = (settings.get('slicer.lifting.height')-layersHeight)/settings.get('slicer.lifting.decline')*60*1000
     result = layersNumber*(parseInt(settings.get('slicer.light.on'))+uplift_time+downlift_time)+
         settings.get('slicer.layers.bottom')*(settings.get('slicer.light.bottom')-settings.get('slicer.light.on'))
+    /*
     console.log("slicer.light.on (ms)", settings.get('slicer.light.on'));
     console.log("slicer.layers.bottom)", settings.get('slicer.layers.bottom'));
     console.log("slicer.light.bottom)", settings.get('slicer.light.bottom'));
@@ -504,6 +510,7 @@ function calcPrintTime(layersHeight, layersNumber){
     console.log("tmp 1 (ms)", layersNumber*(parseInt(settings.get('slicer.light.on'))+uplift_time+downlift_time));
     console.log("tmp 2 (ms)", settings.get('slicer.layers.bottom')*(settings.get('slicer.light.bottom')-settings.get('slicer.light.on')));
     console.log("result (ms)", result);
+    */
 
     return result;
 }
@@ -742,6 +749,8 @@ function slice() {
         return endSlicing();
     }
 
+    // debug
+    // console.log("currentSliceNumber", currentSliceNumber)
 
     getSlice(currentSliceNumber);
 
@@ -828,18 +837,23 @@ function startSlicing() {
 
     if(WOWExport){// GCode logic
 
+        // hotfix for first layer bug - before flip geometry!
+        $sliderInput.slider('setValue', currentSliceNumber);
+
         // hotfix for mirror bug
         flipGeometry();
 
         wowFile = "";
 
         // Tests
+        /*
         var array = new Uint8Array(2);
         array[1]=255;
         console.log(array);
         var textDecoder = new TextDecoder("utf-8");
         var binary_layer = textDecoder.decode(array);
         console.log(binary_layer);
+        */
         //console.log(textDecoder.encode(binary_layer));
 
         wowFile += "G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n"
@@ -848,6 +862,15 @@ function startSlicing() {
     slicesNumber && slice();
 }
 
+function waitForZeroLayer(callback){
+    if(currentSliceNumber === 0){
+        callback();
+    }
+    else{
+        setTimeout(waitForZeroLayer(callback), 250);
+    }
+}
+
 $zipButton.on('click', function(e) {
     if (zipFile) {
         var name = 'SLAcer';

From c818e7618e5afe32b66f6da0c73762fe6a61b743 Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Fri, 7 Sep 2018 18:15:23 -0400
Subject: [PATCH 32/39] UI Panel for GCode

---
 index.html | 19 +++++++++++++++++++
 js/main.js | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/index.html b/index.html
index aea2dad..37e2064 100644
--- a/index.html
+++ b/index.html
@@ -341,6 +341,25 @@ <h3 class="panel-title">Colors</h3>
                     </div>
                 </div><!-- #colors -->
 
+                <div id="gcode" class="panel panel-default">
+                    <div class="panel-heading">
+                        <button class="panel-toggle btn btn-default btn-xs pull-right" type="button" data-toggle="collapse" data-target="#gcode-body">
+                            <span class="glyphicon glyphicon-menu-down"></span>
+                        </button>
+                        <h3 class="panel-title">GCode</h3>
+                    </div>
+                    <div id="gcode-body" class="panel-body collapse">
+                        <div class="form-group">
+                            <label for="start" style="width: 100%; float: none;" >Start</label>
+                            <textarea id="start" class="form-control" rows="5" style="width: 100%; float: none;" ></textarea>
+                        </div>
+                        <div class="form-group">
+                            <label for="end" style="width: 100%; float: none;" >End</label>
+                            <textarea id="end" class="form-control" rows="5" style="width: 100%; float: none;" ></textarea>
+                        </div>
+                    </div>
+                </div><!-- #gcode -->
+
             </div><!-- #sidebar -->
 
             <div id="main">
diff --git a/js/main.js b/js/main.js
index 281e8a3..339e824 100644
--- a/js/main.js
+++ b/js/main.js
@@ -85,6 +85,14 @@ var settings = new SLAcer.Settings({
             position : 7
         }
     },
+    gcode: {
+        start : 'G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n',
+        end: 'M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;',
+        panel: {
+            collapsed: true,
+            position : 8
+        }
+    },
     viewer3d: {
         color: 0xffffff
     }
@@ -1072,6 +1080,33 @@ $sliceColor.colorpicker().on('changeColor.colorpicker', function(e) {
     }
 });
 
+// gcode
+var $gcodeBody = initPanel('gcode');
+var $gcodeStart = $gcodeBody.find('#start');
+var $gcodeEnd = $gcodeBody.find('#end');
+
+function updateGcodeUI() {
+    var gcode = settings.get('gcode');
+
+    $gcodeStart.val(gcode.start);
+    $gcodeEnd.val(gcode.end);
+}
+
+function updateGcodeSettings() {
+    var startText = $gcodeStart.val();
+    var endText = $gcodeEnd.val();
+
+    settings.set('gcode', {
+        start   : $gcodeStart.val(),
+        end     : $gcodeEnd.val(),
+    });
+}
+
+$gcodeStart.on('change', updateGcodeSettings);
+$gcodeEnd.on('change', updateGcodeSettings);
+
+updateGcodeUI();
+
 // Alert
 var $alertPanel   = $('#alert');
 var $alertMessage = $alertPanel.find('.message');

From c648543123143c318caa3fc8281562383c9b7150 Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Fri, 7 Sep 2018 18:26:41 -0400
Subject: [PATCH 33/39] use settings when generating GCode

now uses gcode.start for beginning of generated gcode and gcode.end at the end
---
 js/main.js | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 339e824..18465d2 100644
--- a/js/main.js
+++ b/js/main.js
@@ -778,7 +778,9 @@ function slice() {
 function endSlicing() {
 
     if(WOWExport) {// GCode & export logic
-        wowFile += "M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;"
+        // add gcode footer from settings
+        var gcode = settings.get('gcode');
+        wowFile += gcode.end;
 
         zipFile.file("print.wow", wowFile, {binary: true});
 
@@ -864,7 +866,9 @@ function startSlicing() {
         */
         //console.log(textDecoder.encode(binary_layer));
 
-        wowFile += "G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n"
+        // use gcode header from settings
+        var gcode = settings.get('gcode');
+        wowFile += gcode.start;
     }
 
     slicesNumber && slice();

From 7b304172eacb1cf70f731d7c720fecf9d8502d25 Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Fri, 7 Sep 2018 19:02:08 -0400
Subject: [PATCH 34/39] reset to default option for gcode

a button for resetting gcode to default seemed wise after some testing
---
 css/main.css |  3 ++-
 index.html   |  6 ++++--
 js/main.js   | 26 ++++++++++++++++++++++++--
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/css/main.css b/css/main.css
index ee1457a..9e65683 100644
--- a/css/main.css
+++ b/css/main.css
@@ -54,7 +54,8 @@
 }
 
 #sidebar .info-value,
-#sidebar .form-control {
+#sidebar .form-control,
+#sidebar .btn-reset {
     width: 40%;
     float: left;
 }
diff --git a/index.html b/index.html
index 37e2064..519c619 100644
--- a/index.html
+++ b/index.html
@@ -350,11 +350,13 @@ <h3 class="panel-title">GCode</h3>
                     </div>
                     <div id="gcode-body" class="panel-body collapse">
                         <div class="form-group">
-                            <label for="start" style="width: 100%; float: none;" >Start</label>
+                            <label for="resetStart" >Start</label>
+                            <span class="btn btn-default btn-xs btn-reset" id="resetStart" title="Reset to default Start GCode" >Reset</span>
                             <textarea id="start" class="form-control" rows="5" style="width: 100%; float: none;" ></textarea>
                         </div>
                         <div class="form-group">
-                            <label for="end" style="width: 100%; float: none;" >End</label>
+                            <label for="resetEnd" >End</label>
+                            <span class="btn btn-default btn-xs btn-reset" id="resetEnd" title="Reset to default End GCode" >Reset</span>
                             <textarea id="end" class="form-control" rows="5" style="width: 100%; float: none;" ></textarea>
                         </div>
                     </div>
diff --git a/js/main.js b/js/main.js
index 18465d2..379e6f1 100644
--- a/js/main.js
+++ b/js/main.js
@@ -86,8 +86,8 @@ var settings = new SLAcer.Settings({
         }
     },
     gcode: {
-        start : 'G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n',
-        end: 'M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;',
+        start : getDefaultGcodeStart(),
+        end: getDefaultGcodeEnd(),
         panel: {
             collapsed: true,
             position : 8
@@ -1088,6 +1088,8 @@ $sliceColor.colorpicker().on('changeColor.colorpicker', function(e) {
 var $gcodeBody = initPanel('gcode');
 var $gcodeStart = $gcodeBody.find('#start');
 var $gcodeEnd = $gcodeBody.find('#end');
+var $gcodeResetStart = $gcodeBody.find('#resetStart');
+var $gcodeResetEnd = $gcodeBody.find('#resetEnd');
 
 function updateGcodeUI() {
     var gcode = settings.get('gcode');
@@ -1106,8 +1108,28 @@ function updateGcodeSettings() {
     });
 }
 
+function resetGcodeStart() {
+    $gcodeStart.val(getDefaultGcodeStart());
+    updateGcodeSettings();
+}
+
+function resetGcodeEnd() {
+    $gcodeEnd.val(getDefaultGcodeEnd());
+    updateGcodeSettings();
+}
+
+function getDefaultGcodeStart() {
+    return 'G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n';
+}
+
+function getDefaultGcodeEnd() {
+    return 'M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;';
+}
+
 $gcodeStart.on('change', updateGcodeSettings);
 $gcodeEnd.on('change', updateGcodeSettings);
+$gcodeResetStart.on('click', resetGcodeStart);
+$gcodeResetEnd.on('click', resetGcodeEnd);
 
 updateGcodeUI();
 

From be9c74a850e31cb0de790b29068d2dfaf4146b9f Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Fri, 7 Sep 2018 19:10:37 -0400
Subject: [PATCH 35/39] comments

was double-checking that I have the right start and end gcode defaults and added links to documentation in comments
---
 js/main.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/main.js b/js/main.js
index 379e6f1..532648c 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1119,11 +1119,11 @@ function resetGcodeEnd() {
 }
 
 function getDefaultGcodeStart() {
-    return 'G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n';
+    return 'G21;\nG91;\nM17;\nM106 S0;\nG28 Z0;\n;W:480;\n;H:854;\n'; // see https://github.com/bastirichter/Sparkmaker/blob/master/file_format.md for details
 }
 
 function getDefaultGcodeEnd() {
-    return 'M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;';
+    return 'M106 S0;\nG1 Z20.0;\nG4 S300;\nM18;'; // see https://github.com/bastirichter/Sparkmaker/blob/master/file_format.md for details
 }
 
 $gcodeStart.on('change', updateGcodeSettings);

From 1e639af20d1681bc8b3e518a6b5064ab22132ada Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Sat, 22 Sep 2018 20:47:47 -0400
Subject: [PATCH 36/39] export SM FHD format

experimental option to export in SparkMaker FHD file format
---
 index.html |  1 +
 js/main.js | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/index.html b/index.html
index 519c619..85cdbd4 100644
--- a/index.html
+++ b/index.html
@@ -212,6 +212,7 @@ <h3 class="panel-title">Slicer</h3>
                             <input type="radio" name="slicer-image-extension" id="slicer-image-extension-png" value="png" /> png
                             <input type="radio" name="slicer-image-extension" id="slicer-image-extension-svg" value="svg" /> svg
                             <input type="radio" name="slicer-image-extension" id="slicer-image-extension-wow" value="wow" checked="checked" /> wow
+                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-fhd" value="fhd" checked="checked" /> FHD
                         </div>
 
                         <hr />
diff --git a/js/main.js b/js/main.js
index 532648c..e06c57c 100644
--- a/js/main.js
+++ b/js/main.js
@@ -208,6 +208,28 @@ function getSlice(layerNumber) {
             if (settings.get('slicer.folder')) {
                 zipFolder.file(fileName, imgData, {base64: true});
             }
+        } else if (FHDExport) {
+            // image file
+            var fileName = 'slice (' + layerNumber + ').png';
+            var imgData  = dataURL.substr(dataURL.indexOf(',') + 1);
+            zipFolder.file(fileName, imgData, {base64: true});
+
+            // gcode
+            wowFile += "M106 S0;\n"; // UV lights off
+            wowFile += "G1 Z" + settings.get('slicer.lifting.height') + " F" + settings.get('slicer.lifting.speed') + ";\n"; // raise bed up specified height and speed
+            wowFile += "G1 Z-" + (settings.get('slicer.lifting.height') - settings.get('slicer.layers.height') / 1000) + " F" + settings.get('slicer.lifting.decline') + ";\n"; // lower bed down specified height and speed
+
+            //bottom layer
+            var exposure_time;
+            if(layerNumber<=settings.get('slicer.layers.bottom')){
+                exposure_time = settings.get('slicer.light.bottom');
+            }else{
+                exposure_time = settings.get('slicer.light.on');
+            }
+
+            wowFile += "{" + fileName + "};\n"; // link to layer image
+            wowFile += "M106 S"+settings.get('slicer.light.strength')+";\n"; // UV lights on specified strength
+            wowFile += "G4 S" + exposure_time / 1000 + ";\n"; // wait specified layer cure time
         }else if (WOWExport) {
             //console.log('layer number:', layerNumber);
             //console.log('z position :', zPosition);
@@ -666,6 +688,7 @@ var $slicerLiftingHeight = $slicerBody.find('#slicer-lifting-height');
 var $slicerExportPNG = $slicerBody.find('#slicer-image-extension-png');
 var $slicerExportSVG = $slicerBody.find('#slicer-image-extension-svg');
 var $slicerExportWOW = $slicerBody.find('#slicer-image-extension-wow');
+var $slicerExportFHD = $slicerBody.find('#slicer-image-extension-fhd');
 
 var $slicerSpeedYes    = $slicerBody.find('#slicer-speed-yes');
 var $slicerSpeedNo     = $slicerBody.find('#slicer-speed-no');
@@ -715,6 +738,7 @@ function updateSlicerSettings() {
     settings.set('slicer.png', $slicerExportPNG[0].checked);
     settings.set('slicer.svg', $slicerExportSVG[0].checked);
     settings.set('slicer.wow', $slicerExportWOW[0].checked);
+    settings.set('slicer.fhd', $slicerExportFHD[0].checked);
 
     settings.set('slicer.zip', $slicerMakeZipYes[0].checked);
 
@@ -738,6 +762,7 @@ var zipFolder;
 var wowFile;
 
 var WOWExport;
+var FHDExport;
 var SVGExport;
 var PNGExport;
 
@@ -784,6 +809,15 @@ function endSlicing() {
 
         zipFile.file("print.wow", wowFile, {binary: true});
 
+        // hotfix for mirror bug
+        flipGeometry();
+    } else if (FHDExport) {
+        // add gcode footer from settings
+        var gcode = settings.get('gcode'); // I believe same end gcode is valid for FHD as for standard sparkmaker - Adam
+        wowFile += gcode.end;
+
+        zipFolder.file("print.wow", wowFile, {binary: true}); // probably don't need binary, but doesn't seem to hurt
+
         // hotfix for mirror bug
         flipGeometry();
     }
@@ -814,6 +848,7 @@ function startSlicing() {
     zipFolder = null;
     wowFile   = null;
     WOWExport = null;
+    FHDExport = null;
     SVGExport = null;
     PNGExport = null;
 
@@ -840,9 +875,13 @@ function startSlicing() {
             declineSpeed  : parseInt(settings.get('slicer.lifting.decline')),  // mm/min
             liftingHeight : parseInt(settings.get('slicer.lifting.height'))  // mm
         }, null, 2));
-        WOWExport = settings.get('slicer.wow')
+        WOWExport = settings.get('slicer.wow');
+        FHDExport = settings.get('slicer.fhd');
         SVGExport = settings.get('slicer.svg');
         PNGExport = settings.get('slicer.png');
+        if (FHDExport) {
+            zipFolder = zipFile.folder('print-FHD');
+        }
     }
 
     if(WOWExport){// GCode logic
@@ -869,6 +908,18 @@ function startSlicing() {
         // use gcode header from settings
         var gcode = settings.get('gcode');
         wowFile += gcode.start;
+    } else if (FHDExport) {
+        // hotfix for first layer bug - before flip geometry!
+        $sliderInput.slider('setValue', currentSliceNumber);
+
+        // hotfix for mirror bug
+        flipGeometry();
+
+        wowFile = "";
+
+        // use gcode header from settings
+        var gcode = settings.get('gcode'); // I believe same start gcode is valid for FHD as for standard sparkmaker - Adam
+        wowFile += gcode.start;
     }
 
     slicesNumber && slice();

From 6dde259d440d820580a69e2859f446b7b196b187 Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Sat, 22 Sep 2018 21:20:23 -0400
Subject: [PATCH 37/39] update UI for slicer output type

use dropdown select control instead of radio buttons for slicer output type
---
 index.html | 12 +++++++-----
 js/main.js | 35 ++++++++++++++++++-----------------
 2 files changed, 25 insertions(+), 22 deletions(-)

diff --git a/index.html b/index.html
index 85cdbd4..27a39f8 100644
--- a/index.html
+++ b/index.html
@@ -208,11 +208,13 @@ <h3 class="panel-title">Slicer</h3>
                         <hr />
 
                         <div class="form-group">
-                            <label for="slicer-image-extension">Output type</label>
-                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-png" value="png" /> png
-                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-svg" value="svg" /> svg
-                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-wow" value="wow" checked="checked" /> wow
-                            <input type="radio" name="slicer-image-extension" id="slicer-image-extension-fhd" value="fhd" checked="checked" /> FHD
+                            <label for="output-type">Output type</label>
+                            <select id="output-type" class="form-control input-sm">
+                                <option>png</option>
+                                <option>svg</option>
+                                <option>wow</option>
+                                <option>fhd</option>
+                            </select>
                         </div>
 
                         <hr />
diff --git a/js/main.js b/js/main.js
index e06c57c..b346bac 100644
--- a/js/main.js
+++ b/js/main.js
@@ -22,9 +22,7 @@ var settings = new SLAcer.Settings({
         },
         zip: true,
         folder: false,
-        wow: true,
-        svg: false,
-        png: false,
+        output: 'wow',
         speed: true,
         speedDelay: 10, // ms
         panel: {
@@ -685,10 +683,7 @@ var $printTimeValue  = $slicerBody.find('#print-time');
 var $slicerLiftingSpeed  = $slicerBody.find('#slicer-lifting-speed');
 var $slicerLiftingHeight = $slicerBody.find('#slicer-lifting-height');
 
-var $slicerExportPNG = $slicerBody.find('#slicer-image-extension-png');
-var $slicerExportSVG = $slicerBody.find('#slicer-image-extension-svg');
-var $slicerExportWOW = $slicerBody.find('#slicer-image-extension-wow');
-var $slicerExportFHD = $slicerBody.find('#slicer-image-extension-fhd');
+var $outputType = $slicerBody.find('#output-type');
 
 var $slicerSpeedYes    = $slicerBody.find('#slicer-speed-yes');
 var $slicerSpeedNo     = $slicerBody.find('#slicer-speed-no');
@@ -735,10 +730,7 @@ function updateSlicerSettings() {
     settings.set('slicer.lifting.speed', $slicerLiftingSpeed.val());
     settings.set('slicer.lifting.height', $slicerLiftingHeight.val());
 
-    settings.set('slicer.png', $slicerExportPNG[0].checked);
-    settings.set('slicer.svg', $slicerExportSVG[0].checked);
-    settings.set('slicer.wow', $slicerExportWOW[0].checked);
-    settings.set('slicer.fhd', $slicerExportFHD[0].checked);
+    settings.set('slicer.output', $outputType.val());
 
     settings.set('slicer.zip', $slicerMakeZipYes[0].checked);
 
@@ -859,7 +851,7 @@ function startSlicing() {
         }
         zipFile.file("README.txt", 'Generated by SLAcer.js for SparkMaker\r\nhttps://n0sr3v.github.io/SLAcer.js/\r\n\r\nProject based on: \r\nhttps://github.com/lautr3k/SLAcer.js\r\nAppreciate this work!\r\n');
         zipFile.file("slacer.json", JSON.stringify({
-            imageExtension: settings.get('slicer.png') ? 'png' : settings.get('slicer.svg') ? 'svg' : 'wow',
+            imageExtension: settings.get('slicer.output'),
             imageDirectoryCreated: settings.get('slicer.folder') ? 'false' : 'true',
             imageDirectory: !settings.get('slicer.folder') ? '' : 'slices',
             screenWidth   : settings.get('screen.width'),
@@ -875,10 +867,18 @@ function startSlicing() {
             declineSpeed  : parseInt(settings.get('slicer.lifting.decline')),  // mm/min
             liftingHeight : parseInt(settings.get('slicer.lifting.height'))  // mm
         }, null, 2));
-        WOWExport = settings.get('slicer.wow');
-        FHDExport = settings.get('slicer.fhd');
-        SVGExport = settings.get('slicer.svg');
-        PNGExport = settings.get('slicer.png');
+        if ($outputType.val() == 'wow') {
+            WOWExport = true;
+        }
+        else if ($outputType.val() == 'fhd') {
+            FHDExport = true;
+        }
+        else if ($outputType.val() == 'svg') {
+            SVGExport = true;
+        }
+        else if ($outputType.val() == 'png') {
+            PNGExport = true;
+        }
         if (FHDExport) {
             zipFolder = zipFile.folder('print-FHD');
         }
@@ -960,7 +960,7 @@ $abortButton.on('click', function(e) {
     endSlicing();
 });
 
-$('#slicer-image-extension-' + (settings.get('slicer.png') ? 'png' : settings.get('slicer.svg') ? 'svg' : 'wow')).prop('checked', true);
+$outputType.val(settings.get('slicer.output'));
 $('#slicer-make-zip-' + (settings.get('slicer.zip') ? 'yes' : 'no')).prop('checked', true);
 
 //new
@@ -968,6 +968,7 @@ $('#slicer-make-folder-' + (settings.get('slicer.folder') ? 'yes' : 'no')).prop(
 
 $('#slicer-speed-' + (settings.get('slicer.speed') ? 'yes' : 'no')).prop('checked', true);
 $('#slicer input').on('input, change', updateSlicerSettings);
+$('#slicer select').on('change', updateSlicerSettings);
 updateSlicerUI();
 
 // Build volume panel

From 36c1ed877be87f105e89e7adb51214002996f5d6 Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Wed, 3 Oct 2018 21:46:37 -0400
Subject: [PATCH 38/39] presets for sparkmaker and FHD

Added presets to make it easier to switch between original sparkmaker and sparkmaker FHD settings. Custom settings are supported as well
---
 index.html |  10 +++++
 js/main.js | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/index.html b/index.html
index 27a39f8..843dcb4 100644
--- a/index.html
+++ b/index.html
@@ -108,6 +108,14 @@ <h3 class="panel-title">File</h3>
                             </span>
                             <small>Or drop an STL file anywhere.<br>In case of error check your model <a href="https://service.netfabb.com/service.php">here</a>!</small>
                         </div>
+                        <div class="form-group">
+                            <label for="printer-type" style="width: 25%;">Printer</label>
+                            <select id="printer-type" class="form-control input-sm" style="width: 75%;">
+                                <option>Sparkmaker</option>
+                                <option>Sparkmaker FHD</option>
+                                <option>Custom</option>
+                            </select>
+                        </div>
                     </div>
                 </div><!-- #file -->
 
@@ -391,6 +399,8 @@ <h3 class="panel-title">GCode</h3>
             <p class="message">Alert message empty...</p>
         </div>
 
+        <div id="dialog-confirm"></div>
+
         <script src="vendor/jquery-2.1.4.min.js" type="text/javascript"></script>
         <script src="vendor/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
         <script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
diff --git a/js/main.js b/js/main.js
index b346bac..3fc1cc7 100644
--- a/js/main.js
+++ b/js/main.js
@@ -7,7 +7,8 @@ var settings = new SLAcer.Settings({
         panel: {
             collapsed: false,
             position : 0
-        }
+        },
+        printer: 'Custom'
     },
     slicer: {
         layers: {
@@ -615,6 +616,7 @@ function parseUnit(value, unit) {
 // File panel
 var $fileBody  = initPanel('file');
 var $fileInput = $fileBody.find('#file-input');
+var $printerType = $fileBody.find('#printer-type');
 var loadedFile = null;
 
 $fileInput.on('change', function(e) {
@@ -623,6 +625,115 @@ $fileInput.on('change', function(e) {
     loader.loadFile(loadedFile);
 });
 
+$printerType.on('change', function(e) {
+    newPrinterType = $printerType.val();
+
+    if (newPrinterType == 'Custom') {
+        // update printerType setting only
+        settings.set('file.printer', newPrinterType);
+    }
+    else {
+        // TODO: need to fix slider errors when using jquery-ui full (as opposed to .min). Then we can use this confirm dialog
+//        // make sure user is willing to update screen, build volume, and outputType settings
+//        $("#dialog-confirm").html("Are you sure you want to replace screen, build volume, gcode, and outputType settings with \"" + newPrinterType + "\" defaults?");
+//        $("#dialog-confirm").dialog({
+//            resizable: false,
+//            modal: true,
+//            title: "Update Settings?",
+//            height: 250,
+//            width: 400,
+//            buttons: {
+//                "Yes": function () {
+//                    $(this).dialog('close');
+                    // update settings
+                    settings.set('file.printer', newPrinterType);
+                    printerDefaults(newPrinterType);
+//                },
+//                "No": function () {
+//                    $(this).dialog('close');
+//                    // revert printerType input to the old printer-type value from settings
+//                    $printerType.val(settings.get('file.printer'));
+//                }
+//            }
+//        });
+    }
+});
+
+function printerDefaults(printerType) {
+    // update settings and UI
+    if (printerType == 'Sparkmaker') {
+        // screen
+        settings.set('screen', {
+            width   : 854,
+            height  : 480,
+            diagonal: {
+                size: 4.6,
+                unit: 'in'
+            }
+        });
+        $('#screen-diagonal-unit-' + settings.get('screen.diagonal.unit')).prop('checked', true);
+        updateScreenUI();
+
+        // build volume x,y,z,unit
+        settings.set('buildVolume', {
+            size: {
+                x: 102,
+                y: 56,
+                z: 125
+            },
+            unit: 'mm'
+        });
+        $('#build-volume-unit-' + settings.get('buildVolume.unit')).prop('checked', true);
+        updateBuildVolumeUI()
+
+        // outputType
+        settings.set('slicer.output', 'wow');
+        $outputType.val(settings.get('slicer.output'));
+
+        // gcode
+        resetGcodeStart(); // gcode prefix and suffix are the same for both Sparkmaker and Sparkmaker FHD for now
+        resetGcodeEnd();
+    }
+    else if (printerType == 'Sparkmaker FHD') {
+        // screen
+        settings.set('screen', {
+            width   : 1920,
+            height  : 1080,
+            diagonal: {
+                size: 4.9686,
+                unit: 'in'
+            }
+        });
+        $('#screen-diagonal-unit-' + settings.get('screen.diagonal.unit')).prop('checked', true);
+        updateScreenUI();
+
+        // build volume
+        settings.set('buildVolume', {
+            size: {
+                x: 110.016,
+                y: 61.8357,
+                z: 125
+            },
+            unit: 'mm'
+        });
+        $('#build-volume-unit-' + settings.get('buildVolume.unit')).prop('checked', true);
+        updateBuildVolumeUI()
+
+        // outputType
+        settings.set('slicer.output', 'fhd');
+        $outputType.val(settings.get('slicer.output'));
+
+        // gcode
+        resetGcodeStart(); // gcode prefix and suffix are the same for both Sparkmaker and Sparkmaker FHD for now
+        resetGcodeEnd();
+    }
+
+    // reload 3d view with new screen and build-volume settings
+    updateBuildVolumeSettings();
+    updateScreenSettings();
+}
+
+
 // Mesh panel
 var $meshBody     = initPanel('mesh');
 var $meshFaces    = $meshBody.find('#mesh-faces');

From f17923719bfa5dcbcd48c76a88905c3937475e33 Mon Sep 17 00:00:00 2001
From: Adukra <43076626+Adukra@users.noreply.github.com>
Date: Mon, 8 Oct 2018 21:36:49 -0400
Subject: [PATCH 39/39] init printer field to settings value

init printer field to settings value
---
 js/main.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/js/main.js b/js/main.js
index 3fc1cc7..76e356d 100644
--- a/js/main.js
+++ b/js/main.js
@@ -659,6 +659,8 @@ $printerType.on('change', function(e) {
     }
 });
 
+$printerType.val(settings.get('file.printer'));
+
 function printerDefaults(printerType) {
     // update settings and UI
     if (printerType == 'Sparkmaker') {
