mirror of
https://github.com/Doodle3D/doodle3d-client.git
synced 2024-11-22 17:27:57 +01:00
Merge branch 'develop'
This commit is contained in:
commit
457cb756ad
@ -16,8 +16,12 @@ module.exports = function(grunt) {
|
|||||||
},
|
},
|
||||||
js: {
|
js: {
|
||||||
src: [
|
src: [
|
||||||
|
'js_src/Shape.js',
|
||||||
|
'js_src/Svg.js',
|
||||||
|
'js_src/Keyboard.js',
|
||||||
'js_src/SettingsWindow.js',
|
'js_src/SettingsWindow.js',
|
||||||
'js_src/UpdatePanel.js',
|
'js_src/UpdatePanel.js',
|
||||||
|
'js_src/PrinterPanel.js',
|
||||||
'js_src/Help.js',
|
'js_src/Help.js',
|
||||||
'js_src/d3dServerInterfacing.js',
|
'js_src/d3dServerInterfacing.js',
|
||||||
'js_src/verticalShapes.js',
|
'js_src/verticalShapes.js',
|
||||||
|
25
Makefile
25
Makefile
@ -4,7 +4,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME := doodle3d-client
|
PKG_NAME := doodle3d-client
|
||||||
PKG_VERSION := 0.9.0
|
PKG_VERSION := 0.9.2
|
||||||
PKG_RELEASE := 1
|
PKG_RELEASE := 1
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
@ -22,6 +22,16 @@ define Package/doodle3d-client/description
|
|||||||
This package provides the Doodle3D web client, which interacts with the wifibox package using a REST API.
|
This package provides the Doodle3D web client, which interacts with the wifibox package using a REST API.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define Package/doodle3d-client/config
|
||||||
|
config DOODLE3D_CLIENT_MINIFY_JS
|
||||||
|
depends on PACKAGE_doodle3d-client
|
||||||
|
bool "Minify javascript"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
All javascript files are concatenated into one file; this file enables minification
|
||||||
|
of that file. Disable this to make on-the-fly modifications easier.
|
||||||
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
mkdir -p $(PKG_BUILD_DIR)
|
mkdir -p $(PKG_BUILD_DIR)
|
||||||
$(CP) less $(PKG_BUILD_DIR)/
|
$(CP) less $(PKG_BUILD_DIR)/
|
||||||
@ -35,7 +45,11 @@ endef
|
|||||||
|
|
||||||
define Build/Compile
|
define Build/Compile
|
||||||
npm install
|
npm install
|
||||||
|
ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y)
|
||||||
grunt less autoprefixer cssmin concat uglify
|
grunt less autoprefixer cssmin concat uglify
|
||||||
|
else
|
||||||
|
grunt less autoprefixer cssmin concat
|
||||||
|
endif
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/doodle3d-client/install
|
define Package/doodle3d-client/install
|
||||||
@ -56,7 +70,16 @@ define Package/doodle3d-client/install
|
|||||||
|
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/img/* $(1)/www/img/
|
$(CP) $(PKG_BUILD_DIR)/www/img/* $(1)/www/img/
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y)
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/js/doodle3d-client.min.js $(1)/www/js/
|
$(CP) $(PKG_BUILD_DIR)/www/js/doodle3d-client.min.js $(1)/www/js/
|
||||||
|
else
|
||||||
|
#NOTE: if using a symlink here installation with openwrt make fails
|
||||||
|
# when trying to build with minification after package has been built
|
||||||
|
# without minification (dangling symlink breaks openwrt's final copy command)
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/www/js/doodle3d-client.js $(1)/www/js/doodle3d-client.min.js
|
||||||
|
#$(LN) -s /www/js/doodle3d-client.js $(1)/www/js/doodle3d-client.min.js
|
||||||
|
endif
|
||||||
|
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/js/libs/* $(1)/www/js/libs/
|
$(CP) $(PKG_BUILD_DIR)/www/js/libs/* $(1)/www/js/libs/
|
||||||
|
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/library $(1)/www/
|
$(CP) $(PKG_BUILD_DIR)/www/library $(1)/www/
|
||||||
|
34
js_src/Keyboard.js
Normal file
34
js_src/Keyboard.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
var keyboardShortcutsEnabled = true;
|
||||||
|
|
||||||
|
function initKeyboard() {
|
||||||
|
|
||||||
|
$(document).keypress(function(event) {
|
||||||
|
|
||||||
|
if (!keyboardShortcutsEnabled) return;
|
||||||
|
|
||||||
|
var ch = String.fromCharCode(event.which);
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case 'c': clearDoodle(); break;
|
||||||
|
case 'n': clearDoodle(); break;
|
||||||
|
case 'p': print(); break;
|
||||||
|
case 'u': oopsUndo(); break;
|
||||||
|
case 'e': settingsWindow.downloadGcode(); break;
|
||||||
|
case 'q': stopPrint(); break;
|
||||||
|
case ',': openSettingsWindow(); break;
|
||||||
|
case 'C': drawCircle(250,180,80,64); break; //x,y,r,res
|
||||||
|
case 'T': drawCircle(250,180,80,3); break; //triangle
|
||||||
|
case 'X': drawCircle(250,180,80,6); break; //hexagon
|
||||||
|
case 'h': previewUp(true); break;
|
||||||
|
case 'H': previewDown(true); break;
|
||||||
|
case 's': saveSketch(); break;
|
||||||
|
case 'L': nextDoodle(); break;
|
||||||
|
case 'l': prevDoodle(); break;
|
||||||
|
case '[': previewTwistLeft(); break;
|
||||||
|
case ']': previewTwistRight(); break;
|
||||||
|
case '\'': resetTwist(); break;
|
||||||
|
default: console.log("Key: '" + ch + "' (" + event.which + ")");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
@ -38,7 +38,7 @@ function Printer() {
|
|||||||
this.sendPrintPartTimeoutTime = 5000;
|
this.sendPrintPartTimeoutTime = 5000;
|
||||||
|
|
||||||
this.gcode; // gcode to be printed
|
this.gcode; // gcode to be printed
|
||||||
this.sendLength = 1500; // max amount of gcode lines per post (limited because WiFi box can't handle to much)
|
this.sendLength = 500; // max amount of gcode lines per post (limited because WiFi box can't handle to much)
|
||||||
|
|
||||||
this.retryDelay = 2000; // retry setTimout delay
|
this.retryDelay = 2000; // retry setTimout delay
|
||||||
this.retrySendPrintPartDelay; // retry setTimout instance
|
this.retrySendPrintPartDelay; // retry setTimout instance
|
||||||
|
76
js_src/PrinterPanel.js
Normal file
76
js_src/PrinterPanel.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
function PrinterPanel() {
|
||||||
|
this.wifiboxURL;
|
||||||
|
this.element;
|
||||||
|
|
||||||
|
this.retryDelay = 1000;
|
||||||
|
this.retryDelayer; // setTimout instance
|
||||||
|
//this.timeoutTime = 3000;
|
||||||
|
|
||||||
|
this.printerType;
|
||||||
|
this.printerSettingsNames;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.init = function(wifiboxURL,element) {
|
||||||
|
self.wifiboxURL = wifiboxURL;
|
||||||
|
self.element = element;
|
||||||
|
|
||||||
|
self.printerSelector = element.find("#printerType");
|
||||||
|
self.printerSelector.change(self.printerSelectorChanged);
|
||||||
|
|
||||||
|
var formElements = element.find("[name]");
|
||||||
|
self.printerSettingsNames = [];
|
||||||
|
formElements.each( function(index,element) {
|
||||||
|
self.printerSettingsNames.push(element.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
var gcodePanel = element.find("#gcodePanel");
|
||||||
|
gcodePanel.coolfieldset({collapsed:true});
|
||||||
|
}
|
||||||
|
this.printerSelectorChanged = function(e) {
|
||||||
|
console.log("PrinterPanel:printerSelectorChanged");
|
||||||
|
console.log("self: ", self);
|
||||||
|
self.printerType = self.printerSelector.find("option:selected").val();
|
||||||
|
self.savePrinterType(self.loadPrinterSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.savePrinterType = function(complete) {
|
||||||
|
console.log("PrinterPanel:savePrinterType");
|
||||||
|
var postData = {};
|
||||||
|
postData[self.printerSelector.attr("name")] = self.printerType;
|
||||||
|
console.log("postData: ",postData);
|
||||||
|
$.ajax({
|
||||||
|
url: self.wifiboxURL + "/config/",
|
||||||
|
type: "POST",
|
||||||
|
dataType: 'json',
|
||||||
|
data: postData,
|
||||||
|
success: function(response){
|
||||||
|
console.log("PrinterPanel:savePrinterType response: ",response);
|
||||||
|
if(complete) complete();
|
||||||
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
console.log("PrinterPanel:savePrinterType: failed");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.loadPrinterSettings = function() {
|
||||||
|
console.log("PrinterPanel:loadPrinterSettings");
|
||||||
|
console.log(" self.printerSettingsNames: ",self.printerSettingsNames);
|
||||||
|
var getData = {};
|
||||||
|
$.each(self.printerSettingsNames, function(key, val) {
|
||||||
|
getData[val] = "";
|
||||||
|
});
|
||||||
|
console.log("getData: ",getData);
|
||||||
|
$.ajax({
|
||||||
|
url: self.wifiboxURL + "/config/",
|
||||||
|
dataType: 'json',
|
||||||
|
data: getData,
|
||||||
|
success: function(response){
|
||||||
|
console.log("PrinterPanel:loadPrinterSettings response: ",response);
|
||||||
|
|
||||||
|
self.fillForm(response.data,self.element);
|
||||||
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
console.log("PrinterPanel:loadPrinterSettings: failed");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +1,5 @@
|
|||||||
//these settings are defined in the firmware (conf_defaults.lua) and will be initialized in loadSettings()
|
//these settings are defined in the firmware (conf_defaults.lua) and will be initialized in loadSettings()
|
||||||
var settings = {
|
var settings = { }
|
||||||
"network.ap.ssid": "d3d-ap-%%MAC_ADDR_TAIL%%",
|
|
||||||
"network.ap.address": "192.168.10.1",
|
|
||||||
"network.ap.netmask": "255.255.255.0",
|
|
||||||
"printer.temperature": 220,
|
|
||||||
"printer.maxObjectHeight": 150,
|
|
||||||
"printer.layerHeight": 0.2,
|
|
||||||
"printer.wallThickness": 0.7,
|
|
||||||
"printer.screenToMillimeterScale": 0.3,
|
|
||||||
"printer.speed": 50,
|
|
||||||
"printer.travelSpeed": 200,
|
|
||||||
"printer.filamentThickness": 2.85,
|
|
||||||
"printer.enableTraveling": true,
|
|
||||||
"printer.useSubLayers": true,
|
|
||||||
"printer.firstLayerSlow": true,
|
|
||||||
"printer.autoWarmUp": true,
|
|
||||||
"printer.simplify.iterations": 10,
|
|
||||||
"printer.simplify.minNumPoints": 15,
|
|
||||||
"printer.simplify.minDistance": 3,
|
|
||||||
"printer.retraction.enabled": true,
|
|
||||||
"printer.retraction.speed": 50,
|
|
||||||
"printer.retraction.minDistance": 1,
|
|
||||||
"printer.retraction.amount": 5,
|
|
||||||
"printer.autoWarmUpCommand": "M104 S220 (hardcoded temperature)"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//wrapper to prevent scoping issues in showSettings()
|
//wrapper to prevent scoping issues in showSettings()
|
||||||
function openSettingsWindow() {
|
function openSettingsWindow() {
|
||||||
@ -90,6 +65,7 @@ function SettingsWindow() {
|
|||||||
this.networkMode = SettingsWindow.NETWORK_MODE_NEITHER;
|
this.networkMode = SettingsWindow.NETWORK_MODE_NEITHER;
|
||||||
|
|
||||||
this.updatePanel = new UpdatePanel();
|
this.updatePanel = new UpdatePanel();
|
||||||
|
this.printerPanel = new PrinterPanel();
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -107,9 +83,20 @@ function SettingsWindow() {
|
|||||||
self.form = self.window.find("form");
|
self.form = self.window.find("form");
|
||||||
self.form.submit(function (e) { self.submitwindow(e) });
|
self.form.submit(function (e) { self.submitwindow(e) });
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: self.wifiboxURL + "/printer/listall",
|
||||||
|
dataType: 'json',
|
||||||
|
timeout: self.timeoutTime,
|
||||||
|
success: function(response) {
|
||||||
|
console.log("Settings:printer/listall response: ",response.data.printers);
|
||||||
|
|
||||||
|
$.each(response.data.printers, function(key, value) {
|
||||||
|
// console.log(key,value);
|
||||||
|
$('#printerType').append($('<option>').text(value).attr('value', key));
|
||||||
|
});
|
||||||
|
|
||||||
self.loadSettings();
|
self.loadSettings();
|
||||||
|
|
||||||
self.printerSelector = self.form.find("#printerType");
|
|
||||||
var btnAP = self.form.find("label[for='ap']");
|
var btnAP = self.form.find("label[for='ap']");
|
||||||
var btnClient = self.form.find("label[for='client']");
|
var btnClient = self.form.find("label[for='client']");
|
||||||
var btnRefresh = self.form.find("#refreshNetworks");
|
var btnRefresh = self.form.find("#refreshNetworks");
|
||||||
@ -118,8 +105,6 @@ function SettingsWindow() {
|
|||||||
var networkSelector = self.form.find("#network");
|
var networkSelector = self.form.find("#network");
|
||||||
self.apFieldSet = self.form.find("#apSettings");
|
self.apFieldSet = self.form.find("#apSettings");
|
||||||
self.clientFieldSet = self.form.find("#clientSettings");
|
self.clientFieldSet = self.form.find("#clientSettings");
|
||||||
self.gcodeSettings = self.form.find("#gcodeSettings");
|
|
||||||
self.x3gSettings = self.form.find("#x3gSettings");
|
|
||||||
self.btnRestoreSettings = self.form.find("#restoreSettings");
|
self.btnRestoreSettings = self.form.find("#restoreSettings");
|
||||||
|
|
||||||
btnAP.on('touchstart mousedown',self.showAPSettings);
|
btnAP.on('touchstart mousedown',self.showAPSettings);
|
||||||
@ -127,16 +112,25 @@ function SettingsWindow() {
|
|||||||
btnRefresh.on('touchstart mousedown',self.refreshNetworks);
|
btnRefresh.on('touchstart mousedown',self.refreshNetworks);
|
||||||
btnConnect.on('touchstart mousedown',self.connectToNetwork);
|
btnConnect.on('touchstart mousedown',self.connectToNetwork);
|
||||||
btnCreate.on('touchstart mousedown',self.createAP);
|
btnCreate.on('touchstart mousedown',self.createAP);
|
||||||
self.printerSelector.change(self.printerSelectorChanged);
|
|
||||||
networkSelector.change(self.networkSelectorChanged);
|
networkSelector.change(self.networkSelectorChanged);
|
||||||
self.btnRestoreSettings.on('touchstart mousedown',self.resetSettings);
|
self.btnRestoreSettings.on('touchstart mousedown',self.resetSettings);
|
||||||
|
|
||||||
|
|
||||||
// update panel
|
// update panel
|
||||||
var $updatePanelElement = self.form.find("#updatePanel");
|
var $updatePanelElement = self.form.find("#updatePanel");
|
||||||
self.updatePanel.init(wifiboxURL,$updatePanelElement);
|
self.updatePanel.init(wifiboxURL,$updatePanelElement);
|
||||||
});
|
|
||||||
|
// printer panel
|
||||||
|
var $printerPanelElement = self.form.find("#printerPanel");
|
||||||
|
self.printerPanel.init(wifiboxURL,$printerPanelElement);
|
||||||
|
self.printerPanel.fillForm = self.fillForm;
|
||||||
}
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
console.log("FATAL ERROR: Settings:printer/listall failed");
|
||||||
|
});
|
||||||
|
}); //this.window.find
|
||||||
|
|
||||||
|
} //this.init
|
||||||
|
|
||||||
this.submitwindow = function(e) {
|
this.submitwindow = function(e) {
|
||||||
disableButton(self.btnOK,self.submitwindow);
|
disableButton(self.btnOK,self.submitwindow);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -156,14 +150,16 @@ function SettingsWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.showSettings = function() {
|
this.showSettings = function() {
|
||||||
|
keyboardShortcutsEnabled = false;
|
||||||
this.loadSettings(function() { // reload settings
|
this.loadSettings(function() { // reload settings
|
||||||
$("#contentOverlay").fadeIn(375, function() {
|
$("#contentOverlay").fadeIn(175, function() {
|
||||||
document.body.removeEventListener('touchmove',prevent,false);
|
document.body.removeEventListener('touchmove',prevent,false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.hideSettings = function(complete) {
|
this.hideSettings = function(complete) {
|
||||||
$("#contentOverlay").fadeOut(375, function() {
|
keyboardShortcutsEnabled = true;
|
||||||
|
$("#contentOverlay").fadeOut(175, function() {
|
||||||
document.body.addEventListener('touchmove',prevent,false);
|
document.body.addEventListener('touchmove',prevent,false);
|
||||||
// self.window.css("display","none");
|
// self.window.css("display","none");
|
||||||
complete();
|
complete();
|
||||||
@ -185,7 +181,7 @@ function SettingsWindow() {
|
|||||||
console.log("Settings:loadSettings response: ",response);
|
console.log("Settings:loadSettings response: ",response);
|
||||||
settings = response.data;
|
settings = response.data;
|
||||||
console.log(" settings: ",settings);
|
console.log(" settings: ",settings);
|
||||||
self.fillForm();
|
self.fillForm(settings);
|
||||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||||
if(complete) complete();
|
if(complete) complete();
|
||||||
}
|
}
|
||||||
@ -198,16 +194,16 @@ function SettingsWindow() {
|
|||||||
this.refreshNetworks();
|
this.refreshNetworks();
|
||||||
this.retrieveNetworkStatus(false);
|
this.retrieveNetworkStatus(false);
|
||||||
}
|
}
|
||||||
this.fillForm = function() {
|
this.fillForm = function(settings,form) {
|
||||||
console.log("SettingsWindow:fillForm");
|
if(!form) form = this.form; // if no form specified, fill whole form
|
||||||
|
|
||||||
//fill form with loaded settings
|
//fill form with loaded settings
|
||||||
var selects = this.form.find("select");
|
var selects = form.find("select");
|
||||||
selects.each( function(index,element) {
|
selects.each( function(index,element) {
|
||||||
var element = $(element);
|
var element = $(element);
|
||||||
element.val(settings[element.attr('name')]);
|
element.val(settings[element.attr('name')]);
|
||||||
});
|
});
|
||||||
var inputs = this.form.find("input");
|
var inputs = form.find("input");
|
||||||
inputs.each( function(index,element) {
|
inputs.each( function(index,element) {
|
||||||
var element = $(element);
|
var element = $(element);
|
||||||
//console.log("printer setting input: ",index,element.attr("type"),element.attr('name')); //,element);
|
//console.log("printer setting input: ",index,element.attr("type"),element.attr('name')); //,element);
|
||||||
@ -221,13 +217,12 @@ function SettingsWindow() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var textareas = this.form.find("textarea");
|
var textareas = form.find("textarea");
|
||||||
textareas.each( function(index,element) {
|
textareas.each( function(index,element) {
|
||||||
var element = $(element);
|
var element = $(element);
|
||||||
var value = settings[element.attr('name')];
|
var value = settings[element.attr('name')];
|
||||||
element.val(value);
|
element.val(value);
|
||||||
});
|
});
|
||||||
self.printerSelectorChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.saveSettings = function(newSettings,complete) {
|
this.saveSettings = function(newSettings,complete) {
|
||||||
@ -288,7 +283,7 @@ function SettingsWindow() {
|
|||||||
} else {
|
} else {
|
||||||
settings = response.data;
|
settings = response.data;
|
||||||
console.log(" settings: ",settings);
|
console.log(" settings: ",settings);
|
||||||
self.fillForm();
|
self.fillForm(settings);
|
||||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||||
|
|
||||||
self.btnRestoreSettings.removeAttr("disabled");
|
self.btnRestoreSettings.removeAttr("disabled");
|
||||||
@ -346,30 +341,6 @@ function SettingsWindow() {
|
|||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.printerSelectorChanged = function(e) {
|
|
||||||
var selectedOption = self.printerSelector.find("option:selected");
|
|
||||||
if(self.isMarlinPrinter(selectedOption.val())) {
|
|
||||||
self.x3gSettings.hide();
|
|
||||||
self.gcodeSettings.show();
|
|
||||||
} else {
|
|
||||||
self.gcodeSettings.hide();
|
|
||||||
self.x3gSettings.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isMarlinPrinter = function(printer) {
|
|
||||||
switch(printer) {
|
|
||||||
case "makerbot_generic":
|
|
||||||
case "makerbot_replicator2":
|
|
||||||
case "makerbot_thingomatic":
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.signin = function() {
|
this.signin = function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: self.wifiboxCGIBinURL + "/network/signin",
|
url: self.wifiboxCGIBinURL + "/network/signin",
|
||||||
@ -388,6 +359,22 @@ function SettingsWindow() {
|
|||||||
window.location.href = self.wifiboxURL + "/info/logfiles"
|
window.location.href = self.wifiboxURL + "/info/logfiles"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.downloadGcode = function() {
|
||||||
|
var gcode = generate_gcode();
|
||||||
|
if (gcode!=undefined) {
|
||||||
|
var blob = new Blob([gcode.join("\n")], {type: "text/plain;charset=utf-8"});
|
||||||
|
saveAs(blob, "doodle3d.gcode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.downloadSvg = function() {
|
||||||
|
var svg = saveToSvg();
|
||||||
|
if (svg!=undefined) {
|
||||||
|
var blob = new Blob([svg], {type: "text/plain;charset=utf-8"});
|
||||||
|
saveAs(blob, "doodle3d.svg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Networks ui
|
* Networks ui
|
||||||
*/
|
*/
|
||||||
|
34
js_src/Shape.js
Normal file
34
js_src/Shape.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
function drawCircle(x0,y0,r,res) {
|
||||||
|
if (res==undefined) res = 50; //circle resolution
|
||||||
|
beginShape();
|
||||||
|
var step=Math.PI * 2.0 / res;
|
||||||
|
for (var a=0; a<=Math.PI*2; a+=step) {
|
||||||
|
var x = Math.sin(a) * r + x0;
|
||||||
|
var y = Math.cos(a) * r + y0;
|
||||||
|
if (a==0) shapeMoveTo(x,y);
|
||||||
|
else shapeLineTo(x,y);
|
||||||
|
}
|
||||||
|
endShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
function beginShape(x,y) {
|
||||||
|
setSketchModified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shapeMoveTo(x,y) {
|
||||||
|
_points.push([x, y, true]);
|
||||||
|
adjustBounds(x, y)
|
||||||
|
adjustPreviewTransformation();
|
||||||
|
draw(x, y, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shapeLineTo(x,y) {
|
||||||
|
_points.push([x, y, false]);
|
||||||
|
adjustBounds(x, y)
|
||||||
|
adjustPreviewTransformation();
|
||||||
|
draw(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
function endShape() {
|
||||||
|
renderToImageDataPreview();
|
||||||
|
}
|
132
js_src/Svg.js
Normal file
132
js_src/Svg.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
//SVG validator: http://validator.w3.org/
|
||||||
|
//SVG viewer: http://svg-edit.googlecode.com/svn/branches/2.6/editor/svg-editor.html
|
||||||
|
function saveToSvg() {
|
||||||
|
var lastX = 0, lastY = 0, lastIsMove;
|
||||||
|
var svg = '';
|
||||||
|
|
||||||
|
var boundsWidth = doodleBounds[2] - doodleBounds[0];
|
||||||
|
var boundsHeight = doodleBounds[3] - doodleBounds[1];
|
||||||
|
|
||||||
|
svg += '<?xml version="1.0" standalone="no"?>\n';
|
||||||
|
svg += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
|
||||||
|
svg += '<svg width="' + boundsWidth + '" height="' + boundsHeight + '" version="1.1" xmlns="http://www.w3.org/2000/svg">\n';
|
||||||
|
svg += '\t<desc>Doodle 3D sketch</desc>\n';
|
||||||
|
|
||||||
|
var data = '';
|
||||||
|
for (var i = 0; i < _points.length; ++i) {
|
||||||
|
var x = _points[i][0], y = _points[i][1], isMove = _points[i][2];
|
||||||
|
var dx = x - lastX, dy = y - lastY;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
data += 'M'; //emit absolute move on first pair of coordinates
|
||||||
|
else if (isMove != lastIsMove)
|
||||||
|
data += isMove ? 'm' : 'l';
|
||||||
|
|
||||||
|
data += dx + ',' + dy + ' ';
|
||||||
|
|
||||||
|
lastX = x;
|
||||||
|
lastY = y;
|
||||||
|
lastIsMove = isMove;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg += '\t<path transform="translate(' + -doodleBounds[0] + ',' + -doodleBounds[1] + ')" d="' + data + '" fill="none" stroke="black" stroke-width="2" />\n';
|
||||||
|
|
||||||
|
var fields = JSON.stringify({'height': numLayers, 'outlineShape': VERTICALSHAPE, 'twist': rStep});
|
||||||
|
svg += '\t<!--<![CDATA[d3d-keys ' + fields + ']]>-->\n';
|
||||||
|
|
||||||
|
svg += '</svg>\n';
|
||||||
|
|
||||||
|
return svg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: use local variables instead of _points,numLayers,VERTICALSHAPE and rStep so we can leave a current doodle in tact if an error occurs while parsing
|
||||||
|
function loadFromSvg(svgData) {
|
||||||
|
var mode = '', x = 0, y = 0;
|
||||||
|
|
||||||
|
console.log("loading " + svgData.length + " bytes of data...");
|
||||||
|
|
||||||
|
clearDoodle();
|
||||||
|
|
||||||
|
var p = svgData.indexOf("<path");
|
||||||
|
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
|
||||||
|
p = svgData.indexOf('d="', p);
|
||||||
|
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
|
||||||
|
p += 3; //skip 'd="'
|
||||||
|
|
||||||
|
var skipSpace = function() { while (svgData.charAt(p) == ' ') p++; }
|
||||||
|
var parseCommand = function() {
|
||||||
|
while (true) {
|
||||||
|
skipSpace();
|
||||||
|
var c = svgData.charAt(p);
|
||||||
|
if (c == 'M' || c == 'm' || c == 'l') { //new command letter
|
||||||
|
mode = c;
|
||||||
|
} else if (c == '"') { //end of command chain
|
||||||
|
return true;
|
||||||
|
} else { //something else, must be a pair of coordinates...
|
||||||
|
var tx = 0, ty = 0, numberEnd = 0, len = 0;
|
||||||
|
numberEnd = svgData.indexOf(',', p);
|
||||||
|
if (numberEnd == -1) { console.log("could not find comma in coordinate pair"); return false; }
|
||||||
|
len = numberEnd - p;
|
||||||
|
tx = parseInt(svgData.substr(p, len));
|
||||||
|
p += len + 1;
|
||||||
|
skipSpace();
|
||||||
|
numberEnd = svgData.indexOf(' ', p);
|
||||||
|
if (numberEnd == -1) { console.log("could not find space after coordinate pair"); return false; }
|
||||||
|
len = numberEnd - p;
|
||||||
|
ty = parseInt(svgData.substr(p, len));
|
||||||
|
p += len;
|
||||||
|
|
||||||
|
if (mode == 'M' || mode == 'L') {
|
||||||
|
x = tx; y = ty;
|
||||||
|
} else if (mode == 'm' || mode == 'l') {
|
||||||
|
x += tx; y += ty;
|
||||||
|
} else {
|
||||||
|
console.log("loadFromSvg: found coordinate pair but mode was never set");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isMove = mode == 'm' || mode == 'M';
|
||||||
|
|
||||||
|
//TODO: create script-wide function for adding points?
|
||||||
|
//console.log("inserting "+x+","+y+" ",isMove);
|
||||||
|
updatePrevX = x;
|
||||||
|
updatePrevY = y;
|
||||||
|
_points.push([x, y, isMove]);
|
||||||
|
adjustBounds(x, y);
|
||||||
|
adjustPreviewTransformation();
|
||||||
|
|
||||||
|
if (isMove) draw(x, y, .5);
|
||||||
|
else draw(x, y);
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
parseCommand(); //depends on value of p, so don't move this without taking that into consideration
|
||||||
|
|
||||||
|
const fieldDefMarker = "<!--<![CDATA[d3d-keys";
|
||||||
|
p = svgData.indexOf(fieldDefMarker);
|
||||||
|
if (p == -1) { console.log("loadFromSvg: could not find metadata marker"); return false; }
|
||||||
|
p += fieldDefMarker.length;
|
||||||
|
skipSpace();
|
||||||
|
|
||||||
|
var endP = svgData.indexOf("]]>-->", p);
|
||||||
|
if (endP == -1) { console.log("loadFromSvg: could not find metadata end-marker"); return false; }
|
||||||
|
var metaFields = JSON.parse(svgData.substr(p, endP - p));
|
||||||
|
//TODO: log error and return false if parsing failed
|
||||||
|
for (var k in metaFields) {
|
||||||
|
var v = metaFields[k];
|
||||||
|
switch (k) {
|
||||||
|
case "height": numLayers = v; break;
|
||||||
|
case "outlineShape": VERTICALSHAPE = v; break;
|
||||||
|
case "twist": rStep = v; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderToImageDataPreview();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -246,10 +246,10 @@ function print(e) {
|
|||||||
console.log("sendPrintCommands is false: not sending print command to 3dprinter");
|
console.log("sendPrintCommands is false: not sending print command to 3dprinter");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugMode) {
|
// if (debugMode) {
|
||||||
$("#textdump").text("");
|
// $("#textdump").text("");
|
||||||
$("#textdump").text(gcode.join("\n"));
|
// $("#textdump").text(gcode.join("\n"));
|
||||||
}
|
// }
|
||||||
|
|
||||||
}, gcodeGenerateDelay);
|
}, gcodeGenerateDelay);
|
||||||
} else {
|
} else {
|
||||||
@ -336,7 +336,11 @@ function previewTwistRight(redrawLess) {
|
|||||||
setSketchModified(true);
|
setSketchModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetTwist() {
|
||||||
|
rStep = 0;
|
||||||
|
redrawRenderedPreview();
|
||||||
|
setSketchModified(true);
|
||||||
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
setState(printer.state,printer.hasControl);
|
setState(printer.state,printer.hasControl);
|
||||||
|
@ -477,136 +477,6 @@ function prevent(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//SVG validator: http://validator.w3.org/
|
|
||||||
//SVG viewer: http://svg-edit.googlecode.com/svn/branches/2.6/editor/svg-editor.html
|
|
||||||
function saveToSvg() {
|
|
||||||
var lastX = 0, lastY = 0, lastIsMove;
|
|
||||||
var svg = '';
|
|
||||||
|
|
||||||
var boundsWidth = doodleBounds[2] - doodleBounds[0];
|
|
||||||
var boundsHeight = doodleBounds[3] - doodleBounds[1];
|
|
||||||
|
|
||||||
svg += '<?xml version="1.0" standalone="no"?>\n';
|
|
||||||
svg += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
|
|
||||||
svg += '<svg width="' + boundsWidth + '" height="' + boundsHeight + '" version="1.1" xmlns="http://www.w3.org/2000/svg">\n';
|
|
||||||
svg += '\t<desc>Doodle 3D sketch</desc>\n';
|
|
||||||
|
|
||||||
var data = '';
|
|
||||||
for (var i = 0; i < _points.length; ++i) {
|
|
||||||
var x = _points[i][0], y = _points[i][1], isMove = _points[i][2];
|
|
||||||
var dx = x - lastX, dy = y - lastY;
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
data += 'M'; //emit absolute move on first pair of coordinates
|
|
||||||
else if (isMove != lastIsMove)
|
|
||||||
data += isMove ? 'm' : 'l';
|
|
||||||
|
|
||||||
data += dx + ',' + dy + ' ';
|
|
||||||
|
|
||||||
lastX = x;
|
|
||||||
lastY = y;
|
|
||||||
lastIsMove = isMove;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg += '\t<path transform="translate(' + -doodleBounds[0] + ',' + -doodleBounds[1] + ')" d="' + data + '" fill="none" stroke="black" stroke-width="2" />\n';
|
|
||||||
|
|
||||||
var fields = JSON.stringify({'height': numLayers, 'outlineShape': VERTICALSHAPE, 'twist': rStep});
|
|
||||||
svg += '\t<!--<![CDATA[d3d-keys ' + fields + ']]>-->\n';
|
|
||||||
|
|
||||||
svg += '</svg>\n';
|
|
||||||
|
|
||||||
return svg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: use local variables instead of _points,numLayers,VERTICALSHAPE and rStep so we can leave a current doodle in tact if an error occurs while parsing
|
|
||||||
function loadFromSvg(svgData) {
|
|
||||||
var mode = '', x = 0, y = 0;
|
|
||||||
|
|
||||||
console.log("loading " + svgData.length + " bytes of data...");
|
|
||||||
|
|
||||||
clearDoodle();
|
|
||||||
|
|
||||||
var p = svgData.indexOf("<path");
|
|
||||||
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
|
|
||||||
p = svgData.indexOf('d="', p);
|
|
||||||
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
|
|
||||||
p += 3; //skip 'd="'
|
|
||||||
|
|
||||||
var skipSpace = function() { while (svgData.charAt(p) == ' ') p++; }
|
|
||||||
var parseCommand = function() {
|
|
||||||
while (true) {
|
|
||||||
skipSpace();
|
|
||||||
var c = svgData.charAt(p);
|
|
||||||
if (c == 'M' || c == 'm' || c == 'l') { //new command letter
|
|
||||||
mode = c;
|
|
||||||
} else if (c == '"') { //end of command chain
|
|
||||||
return true;
|
|
||||||
} else { //something else, must be a pair of coordinates...
|
|
||||||
var tx = 0, ty = 0, numberEnd = 0, len = 0;
|
|
||||||
numberEnd = svgData.indexOf(',', p);
|
|
||||||
if (numberEnd == -1) { console.log("could not find comma in coordinate pair"); return false; }
|
|
||||||
len = numberEnd - p;
|
|
||||||
tx = parseInt(svgData.substr(p, len));
|
|
||||||
p += len + 1;
|
|
||||||
skipSpace();
|
|
||||||
numberEnd = svgData.indexOf(' ', p);
|
|
||||||
if (numberEnd == -1) { console.log("could not find space after coordinate pair"); return false; }
|
|
||||||
len = numberEnd - p;
|
|
||||||
ty = parseInt(svgData.substr(p, len));
|
|
||||||
p += len;
|
|
||||||
|
|
||||||
if (mode == 'M' || mode == 'L') {
|
|
||||||
x = tx; y = ty;
|
|
||||||
} else if (mode == 'm' || mode == 'l') {
|
|
||||||
x += tx; y += ty;
|
|
||||||
} else {
|
|
||||||
console.log("loadFromSvg: found coordinate pair but mode was never set");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isMove = mode == 'm' || mode == 'M';
|
|
||||||
|
|
||||||
//TODO: create script-wide function for adding points?
|
|
||||||
//console.log("inserting "+x+","+y+" ",isMove);
|
|
||||||
updatePrevX = x;
|
|
||||||
updatePrevY = y;
|
|
||||||
_points.push([x, y, isMove]);
|
|
||||||
adjustBounds(x, y);
|
|
||||||
adjustPreviewTransformation();
|
|
||||||
|
|
||||||
if (isMove) draw(x, y, .5);
|
|
||||||
else draw(x, y);
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
parseCommand(); //depends on value of p, so don't move this without taking that into consideration
|
|
||||||
|
|
||||||
const fieldDefMarker = "<!--<![CDATA[d3d-keys";
|
|
||||||
p = svgData.indexOf(fieldDefMarker);
|
|
||||||
if (p == -1) { console.log("loadFromSvg: could not find metadata marker"); return false; }
|
|
||||||
p += fieldDefMarker.length;
|
|
||||||
skipSpace();
|
|
||||||
|
|
||||||
var endP = svgData.indexOf("]]>-->", p);
|
|
||||||
if (endP == -1) { console.log("loadFromSvg: could not find metadata end-marker"); return false; }
|
|
||||||
var metaFields = JSON.parse(svgData.substr(p, endP - p));
|
|
||||||
//TODO: log error and return false if parsing failed
|
|
||||||
for (var k in metaFields) {
|
|
||||||
var v = metaFields[k];
|
|
||||||
switch (k) {
|
|
||||||
case "height": numLayers = v; break;
|
|
||||||
case "outlineShape": VERTICALSHAPE = v; break;
|
|
||||||
case "twist": rStep = v; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderToImageDataPreview();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,37 +1,10 @@
|
|||||||
/*var gcodeStart = [];
|
|
||||||
gcodeStart.push(";Generated with Doodle3D");
|
|
||||||
gcodeStart.push("G21"); // metric values
|
|
||||||
gcodeStart.push("G91"); // relative positioning
|
|
||||||
gcodeStart.push("M107"); // start with the fan off
|
|
||||||
gcodeStart.push("G28 X0 Y0"); // move X/Y to min endstops
|
|
||||||
gcodeStart.push("G28 Z0"); // move Z to min endstops
|
|
||||||
gcodeStart.push("G1 Z15 F9000"); // move the platform down 15mm
|
|
||||||
gcodeStart.push("G92 E0"); // zero the extruded length
|
|
||||||
gcodeStart.push("G1 F200 E10"); // extrude 10mm of feed stock
|
|
||||||
gcodeStart.push("G92 E0"); // zero the extruded length again
|
|
||||||
//gcodeStart.push("G92 X-100 Y-100 E0"); // zero the extruded length again and make center the start position
|
|
||||||
gcodeStart.push("G1 F9000");
|
|
||||||
gcodeStart.push("G90"); // absolute positioning
|
|
||||||
gcodeStart.push("M117 Printing Doodle... "); // display message (20 characters to clear whole screen)
|
|
||||||
|
|
||||||
var gcodeEnd= [];
|
var MAX_POINTS_TO_PRINT = 200000
|
||||||
gcodeEnd.push("M107"); // fan off
|
|
||||||
gcodeEnd.push("G91"); // relative positioning
|
|
||||||
gcodeEnd.push("G1 E-1 F300"); // retract the filament a bit before lifting the nozzle, to release some of the pressure
|
|
||||||
gcodeEnd.push("G1 Z+0.5 E-5 X-20 Y-20 F9000"); // move Z up a bit and retract filament even more
|
|
||||||
gcodeEnd.push("G28 X0 Y0"); // move X/Y to min endstops, so the head is out of the way
|
|
||||||
gcodeEnd.push("M84"); // disable axes / steppers
|
|
||||||
gcodeEnd.push("G90"); // absolute positioning
|
|
||||||
gcodeEnd.push("M117 Done "); // display message (20 characters to clear whole screen)*/
|
|
||||||
|
|
||||||
|
|
||||||
var MAX_POINTS_TO_PRINT = 200000; //400000; //80000; //40000;
|
|
||||||
var gcode = [];
|
var gcode = [];
|
||||||
|
|
||||||
function generate_gcode() {
|
function generate_gcode() {
|
||||||
console.log("f:generategcode()");
|
console.log("f:generategcode()");
|
||||||
|
|
||||||
|
|
||||||
gcode = [];
|
gcode = [];
|
||||||
|
|
||||||
console.log("settings: ",settings);
|
console.log("settings: ",settings);
|
||||||
@ -43,7 +16,6 @@ function generate_gcode() {
|
|||||||
var wallThickness = settings["printer.wallThickness"];
|
var wallThickness = settings["printer.wallThickness"];
|
||||||
var screenToMillimeterScale = settings["printer.screenToMillimeterScale"];
|
var screenToMillimeterScale = settings["printer.screenToMillimeterScale"];
|
||||||
var layerHeight = settings["printer.layerHeight"];
|
var layerHeight = settings["printer.layerHeight"];
|
||||||
var maxObjectHeight = settings["printer.maxObjectHeight"];
|
|
||||||
var temperature = settings["printer.temperature"];
|
var temperature = settings["printer.temperature"];
|
||||||
var bedTemperature = settings["printer.bed.temperature"];
|
var bedTemperature = settings["printer.bed.temperature"];
|
||||||
var useSubLayers = settings["printer.useSubLayers"];
|
var useSubLayers = settings["printer.useSubLayers"];
|
||||||
@ -54,66 +26,35 @@ function generate_gcode() {
|
|||||||
var retractionamount = settings["printer.retraction.amount"];
|
var retractionamount = settings["printer.retraction.amount"];
|
||||||
var preheatTemperature = settings["printer.heatup.temperature"];
|
var preheatTemperature = settings["printer.heatup.temperature"];
|
||||||
var preheatBedTemperature = settings["printer.heatup.bed.temperature"];
|
var preheatBedTemperature = settings["printer.heatup.bed.temperature"];
|
||||||
var printerBedWidth = settings["printer.bed.width"];
|
var printerDimensionsX = settings["printer.dimensions.x"];
|
||||||
var printerBedHeight = settings["printer.bed.height"];
|
var printerDimensionsY = settings["printer.dimensions.y"];
|
||||||
|
var printerDimensionsZ = settings["printer.dimensions.z"];
|
||||||
|
|
||||||
var gCodeOffsetX = printerBedWidth/2; //110; // mm
|
var gCodeOffsetX = printerDimensionsX/2;
|
||||||
var gCodeOffsetY = printerBedHeight/2; //110; // mm
|
var gCodeOffsetY = printerDimensionsY/2;
|
||||||
|
|
||||||
var startCode = generateStartCode();
|
var startCode = generateStartCode();
|
||||||
var endCode = generateEndCode();
|
var endCode = generateEndCode();
|
||||||
|
|
||||||
/*
|
|
||||||
console.log("f:generate_gcode >> EFFE CHECKEN:");
|
|
||||||
console.log(" speed: " + speed);
|
|
||||||
console.log(" travelSpeed: " + travelSpeed);
|
|
||||||
console.log(" filamentThickness: " + filamentThickness);
|
|
||||||
console.log(" wallThickness: " + wallThickness);
|
|
||||||
console.log(" screenToMillimeterScale: " + screenToMillimeterScale);
|
|
||||||
console.log(" layerHeight: " + layerHeight);
|
|
||||||
console.log(" objectHeight: " + objectHeight);
|
|
||||||
console.log(" maxObjectHeight: " + maxObjectHeight);
|
|
||||||
console.log(" temperature: " + temperature);
|
|
||||||
console.log(" maxObjectHeight: " + maxObjectHeight);
|
|
||||||
console.log(" useSubLayers: " + useSubLayers);
|
|
||||||
console.log(" enableTraveling: " + enableTraveling);
|
|
||||||
console.log(" retractionspeed: " + retractionspeed);
|
|
||||||
console.log(" retractionminDistance: " + retractionminDistance);
|
|
||||||
console.log(" retractionamount: " + retractionamount);
|
|
||||||
console.log("");
|
|
||||||
//*/
|
|
||||||
|
|
||||||
// max amount of real world layers
|
// max amount of real world layers
|
||||||
var layers = maxObjectHeight / layerHeight; //maxObjectHeight instead of objectHeight
|
var layers = printerDimensionsZ / layerHeight; //maxObjectHeight instead of objectHeight
|
||||||
|
|
||||||
// translate numLayers in preview to objectHeight in real world
|
// translate numLayers in preview to objectHeight in real world
|
||||||
//objectHeight = Math.ceil(numLayers / 5); // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
|
objectHeight = Math.round(numLayers/maxNumLayers*printerDimensionsZ);
|
||||||
//objectHeight = numLayers; // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
|
|
||||||
objectHeight = Math.round(numLayers/maxNumLayers*maxObjectHeight);
|
|
||||||
|
|
||||||
// translate preview rotation (per layer) to real world rotation
|
// translate preview rotation (per layer) to real world rotation
|
||||||
var rStepGCode = rStep * maxNumLayers/layers; ///maxNumLayers*maxObjectHeight;
|
var rStepGCode = rStep * maxNumLayers/layers; ///maxNumLayers*maxObjectHeight;
|
||||||
|
|
||||||
// correct direction
|
// correct direction
|
||||||
rStepGCode = -rStepGCode;
|
rStepGCode = -rStepGCode;
|
||||||
|
|
||||||
// todo hier een array van PATHS maken wat de losse paths zijn
|
|
||||||
|
|
||||||
// copy array without reference -> http://stackoverflow.com/questions/9885821/copying-of-an-array-of-objects-to-another-array-without-object-reference-in-java
|
// copy array without reference -> http://stackoverflow.com/questions/9885821/copying-of-an-array-of-objects-to-another-array-without-object-reference-in-java
|
||||||
var points = JSON.parse(JSON.stringify(_points));
|
var points = JSON.parse(JSON.stringify(_points));
|
||||||
|
|
||||||
// console.log("f:generategcode() >> paths: " + paths.toString());
|
|
||||||
// console.log("paths.toString(): " + paths.toString());
|
|
||||||
// return;
|
|
||||||
|
|
||||||
//gcode.push("M104 S" + temperature); // set target temperature and do not wait for the extruder to reach it
|
|
||||||
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
|
||||||
|
|
||||||
// add gcode begin commands
|
// add gcode begin commands
|
||||||
gcode = gcode.concat(startCode);
|
gcode = gcode.concat(startCode);
|
||||||
|
|
||||||
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
var layers = printerDimensionsZ / layerHeight; //maxObjectHeight instead of objectHeight
|
||||||
|
|
||||||
var layers = maxObjectHeight / layerHeight; //maxObjectHeight instead of objectHeight
|
|
||||||
var extruder = 0.0;
|
var extruder = 0.0;
|
||||||
var prev = new Point(); prev.set(0, 0);
|
var prev = new Point(); prev.set(0, 0);
|
||||||
|
|
||||||
@ -121,19 +62,13 @@ function generate_gcode() {
|
|||||||
var centerOfDoodle = {
|
var centerOfDoodle = {
|
||||||
x: doodleBounds[0] + (doodleBounds[2]- doodleBounds[0])/2,
|
x: doodleBounds[0] + (doodleBounds[2]- doodleBounds[0])/2,
|
||||||
y: doodleBounds[1] + (doodleBounds[3] - doodleBounds[1])/2
|
y: doodleBounds[1] + (doodleBounds[3] - doodleBounds[1])/2
|
||||||
// x: doodleBounds[0],
|
|
||||||
// y: doodleBounds[1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("f:generategcode() >> layers: " + layers);
|
console.log("f:generategcode() >> layers: " + layers);
|
||||||
if (layers == Infinity) return;
|
if (layers == Infinity) return;
|
||||||
|
|
||||||
// check feasibility of design
|
// check feasibility of design
|
||||||
var pointsToPrint = points.length * layers*(objectHeight/maxObjectHeight)
|
var pointsToPrint = points.length * layers*(objectHeight/printerDimensionsZ)
|
||||||
//console.log(" points.length: ",points.length);
|
|
||||||
//console.log(" numLayers: ",(layers*(objectHeight/maxObjectHeight)));
|
|
||||||
//console.log(" pointsToPrint: ",pointsToPrint);
|
|
||||||
//console.log(" MAX_POINTS_TO_PRINT: ",MAX_POINTS_TO_PRINT);
|
|
||||||
|
|
||||||
console.log("pointsToPrint: ",pointsToPrint);
|
console.log("pointsToPrint: ",pointsToPrint);
|
||||||
|
|
||||||
@ -145,14 +80,14 @@ function generate_gcode() {
|
|||||||
|
|
||||||
for (var layer = 0; layer < layers; layer++) {
|
for (var layer = 0; layer < layers; layer++) {
|
||||||
|
|
||||||
|
//gcode.push(";LAYER:"+layer); //this will be added in a next release to support GCODE previewing in CURA
|
||||||
|
|
||||||
var p = JSON.parse(JSON.stringify(points)); // [].concat(points);
|
var p = JSON.parse(JSON.stringify(points)); // [].concat(points);
|
||||||
|
|
||||||
if (p.length < 2) return;
|
if (p.length < 2) return;
|
||||||
var even = (layer % 2 == 0);
|
var even = (layer % 2 == 0);
|
||||||
var progress = layer / layers;
|
var progress = layer / layers;
|
||||||
|
|
||||||
// float layerScale = scaleFunction(float(layer)/layers); // scaleFactor van de layer -> lookup naar vfunc[] voor die scaleVals
|
|
||||||
// var layerScale = 1.0;
|
|
||||||
var layerScale = scaleFunction(progress);
|
var layerScale = scaleFunction(progress);
|
||||||
|
|
||||||
// if begin point this row and end point last row are close enough, isLoop is true
|
// if begin point this row and end point last row are close enough, isLoop is true
|
||||||
@ -162,11 +97,6 @@ function generate_gcode() {
|
|||||||
pointsTranslate(p, -centerOfDoodle.x, -centerOfDoodle.y);
|
pointsTranslate(p, -centerOfDoodle.x, -centerOfDoodle.y);
|
||||||
pointsScale(p, screenToMillimeterScale,-screenToMillimeterScale);
|
pointsScale(p, screenToMillimeterScale,-screenToMillimeterScale);
|
||||||
pointsScale(p, layerScale, layerScale);
|
pointsScale(p, layerScale, layerScale);
|
||||||
|
|
||||||
// sort-of in de buurt van (360/2.5)
|
|
||||||
// // -> aight.. er zijn 750 lines vs 1000 in de d3d app. 135 = .75 * 180... dit kan je nog rechttrekken als je NET wat slimmer nadenkt :)
|
|
||||||
// update: NEE, het is niet .75 * 180 want 135 was niet de beste value.
|
|
||||||
//pointsRotate(p, rStep * progress * 139);
|
|
||||||
pointsRotate(p, rStepGCode * layer);
|
pointsRotate(p, rStepGCode * layer);
|
||||||
|
|
||||||
if (layer == 0) {
|
if (layer == 0) {
|
||||||
@ -200,24 +130,17 @@ function generate_gcode() {
|
|||||||
paths[pathCounter].push([p[i][0], p[i][1]]);
|
paths[pathCounter].push([p[i][0], p[i][1]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log("f:generategcode() >> paths.length: " + paths.length);
|
|
||||||
|
|
||||||
// loop over the subpaths (the separately drawn lines)
|
// loop over the subpaths (the separately drawn lines)
|
||||||
for (var j = 0; j < paths.length; j++) { // TODO paths > subpaths
|
for (var j = 0; j < paths.length; j++) { // TODO paths > subpaths
|
||||||
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
|
var commands = paths[j];
|
||||||
// vector<ofSubPath::Command> &commands = subpaths[even ? j : subpaths.size()-1-j].getCommands();
|
|
||||||
var commands = paths[j]; //commands zijn alle points uit subpath j // TODO commands > subpathPoints
|
|
||||||
|
|
||||||
// loop over the coordinates of the subpath
|
// loop over the coordinates of the subpath
|
||||||
for (var i = 0; i < commands.length; i++) {
|
for (var i = 0; i < commands.length; i++) {
|
||||||
var last = commands.length - 1;
|
var last = commands.length - 1;
|
||||||
|
|
||||||
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
|
|
||||||
// ofPoint to = commands[(even || isLoop || loopAlways) ? i : last-i].to;
|
|
||||||
var to = new Point(); to.set(commands[i][0], commands[i][1]);
|
var to = new Point(); to.set(commands[i][0], commands[i][1]);
|
||||||
|
|
||||||
// TODO 2013-09-18 evaluate if this should stay..
|
|
||||||
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
|
||||||
to.x += gCodeOffsetX;
|
to.x += gCodeOffsetX;
|
||||||
to.y += gCodeOffsetY;
|
to.y += gCodeOffsetY;
|
||||||
|
|
||||||
@ -228,13 +151,10 @@ function generate_gcode() {
|
|||||||
var doRetract = retractionEnabled && prev.distance(to) > retractionminDistance;
|
var doRetract = retractionEnabled && prev.distance(to) > retractionminDistance;
|
||||||
|
|
||||||
if (enableTraveling && isTraveling) {
|
if (enableTraveling && isTraveling) {
|
||||||
// console.log("enableTraveling && isTraveling >> doRetract: " + doRetract + ", retractionspeed: " + retractionspeed);
|
|
||||||
if (doRetract) gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); //retract
|
if (doRetract) gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); //retract
|
||||||
gcode.push("G0 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (travelSpeed * 60).toFixed(3));
|
gcode.push("G0 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (travelSpeed * 60).toFixed(3));
|
||||||
if (doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal
|
if (doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal
|
||||||
} else {
|
} else {
|
||||||
// console.log(" else");
|
|
||||||
//extruder += prev.distance(to) * wallThickness * layerHeight / filamentThickness;
|
|
||||||
extruder += prev.distance(to) * wallThickness * layerHeight / (Math.pow((filamentThickness/2), 2) * Math.PI);
|
extruder += prev.distance(to) * wallThickness * layerHeight / (Math.pow((filamentThickness/2), 2) * Math.PI);
|
||||||
gcode.push("G1 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (speed * 60).toFixed(3) + " E" + extruder.toFixed(3));
|
gcode.push("G1 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (speed * 60).toFixed(3) + " E" + extruder.toFixed(3));
|
||||||
}
|
}
|
||||||
@ -247,8 +167,8 @@ function generate_gcode() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((layer/layers) > (objectHeight/maxObjectHeight)) {
|
if ((layer/layers) > (objectHeight/printerDimensionsZ)) {
|
||||||
console.log("f:generategcode() >> (layer/layers) > (objectHeight/maxObjectHeight) is true -> breaking at layer " + (layer + 1));
|
console.log("f:generategcode() >> (layer/layers) > (objectHeight/printerDimensionsZ) is true -> breaking at layer " + (layer + 1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,26 +180,14 @@ function generate_gcode() {
|
|||||||
|
|
||||||
function generateStartCode() {
|
function generateStartCode() {
|
||||||
var printerType = settings["printer.type"];
|
var printerType = settings["printer.type"];
|
||||||
|
var startCode = settings["printer.startcode"];
|
||||||
var startCode = "";
|
|
||||||
if(settingsWindow.isMarlinPrinter(printerType)) {
|
|
||||||
startCode = settings["printer.startcode.marlin"];
|
|
||||||
} else {
|
|
||||||
startCode = settings["printer.startcode.x3g"];
|
|
||||||
}
|
|
||||||
startCode = subsituteVariables(startCode);
|
startCode = subsituteVariables(startCode);
|
||||||
startCode = startCode.split("\n");
|
startCode = startCode.split("\n");
|
||||||
return startCode;
|
return startCode;
|
||||||
}
|
}
|
||||||
function generateEndCode() {
|
function generateEndCode() {
|
||||||
var printerType = settings["printer.type"];
|
var printerType = settings["printer.type"];
|
||||||
|
var endCode = settings["printer.endcode"];
|
||||||
var endCode = "";
|
|
||||||
if(settingsWindow.isMarlinPrinter(printerType)) {
|
|
||||||
endCode = settings["printer.endcode.marlin"];
|
|
||||||
} else {
|
|
||||||
endCode = settings["printer.endcode.x3g"];
|
|
||||||
}
|
|
||||||
endCode = subsituteVariables(endCode);
|
endCode = subsituteVariables(endCode);
|
||||||
endCode = endCode.split("\n");
|
endCode = endCode.split("\n");
|
||||||
return endCode;
|
return endCode;
|
||||||
@ -294,8 +202,10 @@ function subsituteVariables(gcode) {
|
|||||||
var printerType = settings["printer.type"];
|
var printerType = settings["printer.type"];
|
||||||
|
|
||||||
switch (printerType) {
|
switch (printerType) {
|
||||||
case "makerbot_replicator2": printerType = "r2x"; break;
|
case "makerbot_replicator2": printerType = "r2"; break;
|
||||||
|
case "makerbot_replicator2x": printerType = "r2x"; break;
|
||||||
case "makerbot_thingomatic": printerType = "t6"; break;
|
case "makerbot_thingomatic": printerType = "t6"; break;
|
||||||
|
case "makerbot_generic": printerType = "r2"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcode = gcode.replace(/{printingTemp}/gi ,temperature);
|
gcode = gcode.replace(/{printingTemp}/gi ,temperature);
|
||||||
|
232
js_src/libs/FileSaver.js
Normal file
232
js_src/libs/FileSaver.js
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
/* FileSaver.js
|
||||||
|
* A saveAs() FileSaver implementation.
|
||||||
|
* 2013-10-21
|
||||||
|
*
|
||||||
|
* By Eli Grey, http://eligrey.com
|
||||||
|
* License: X11/MIT
|
||||||
|
* See LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*global self */
|
||||||
|
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
||||||
|
plusplus: true */
|
||||||
|
|
||||||
|
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
|
||||||
|
|
||||||
|
var saveAs = saveAs
|
||||||
|
|| (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
|
||||||
|
|| (function(view) {
|
||||||
|
"use strict";
|
||||||
|
var
|
||||||
|
doc = view.document
|
||||||
|
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
|
||||||
|
, get_URL = function() {
|
||||||
|
return view.URL || view.webkitURL || view;
|
||||||
|
}
|
||||||
|
, URL = view.URL || view.webkitURL || view
|
||||||
|
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||||
|
, can_use_save_link = !view.externalHost && "download" in save_link
|
||||||
|
, click = function(node) {
|
||||||
|
var event = doc.createEvent("MouseEvents");
|
||||||
|
event.initMouseEvent(
|
||||||
|
"click", true, false, view, 0, 0, 0, 0, 0
|
||||||
|
, false, false, false, false, 0, null
|
||||||
|
);
|
||||||
|
node.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
, webkit_req_fs = view.webkitRequestFileSystem
|
||||||
|
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
|
||||||
|
, throw_outside = function (ex) {
|
||||||
|
(view.setImmediate || view.setTimeout)(function() {
|
||||||
|
throw ex;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
, force_saveable_type = "application/octet-stream"
|
||||||
|
, fs_min_size = 0
|
||||||
|
, deletion_queue = []
|
||||||
|
, process_deletion_queue = function() {
|
||||||
|
var i = deletion_queue.length;
|
||||||
|
while (i--) {
|
||||||
|
var file = deletion_queue[i];
|
||||||
|
if (typeof file === "string") { // file is an object URL
|
||||||
|
URL.revokeObjectURL(file);
|
||||||
|
} else { // file is a File
|
||||||
|
file.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deletion_queue.length = 0; // clear queue
|
||||||
|
}
|
||||||
|
, dispatch = function(filesaver, event_types, event) {
|
||||||
|
event_types = [].concat(event_types);
|
||||||
|
var i = event_types.length;
|
||||||
|
while (i--) {
|
||||||
|
var listener = filesaver["on" + event_types[i]];
|
||||||
|
if (typeof listener === "function") {
|
||||||
|
try {
|
||||||
|
listener.call(filesaver, event || filesaver);
|
||||||
|
} catch (ex) {
|
||||||
|
throw_outside(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, FileSaver = function(blob, name) {
|
||||||
|
// First try a.download, then web filesystem, then object URLs
|
||||||
|
var
|
||||||
|
filesaver = this
|
||||||
|
, type = blob.type
|
||||||
|
, blob_changed = false
|
||||||
|
, object_url
|
||||||
|
, target_view
|
||||||
|
, get_object_url = function() {
|
||||||
|
var object_url = get_URL().createObjectURL(blob);
|
||||||
|
deletion_queue.push(object_url);
|
||||||
|
return object_url;
|
||||||
|
}
|
||||||
|
, dispatch_all = function() {
|
||||||
|
dispatch(filesaver, "writestart progress write writeend".split(" "));
|
||||||
|
}
|
||||||
|
// on any filesys errors revert to saving with object URLs
|
||||||
|
, fs_error = function() {
|
||||||
|
// don't create more object URLs than needed
|
||||||
|
if (blob_changed || !object_url) {
|
||||||
|
object_url = get_object_url(blob);
|
||||||
|
}
|
||||||
|
if (target_view) {
|
||||||
|
target_view.location.href = object_url;
|
||||||
|
} else {
|
||||||
|
window.open(object_url, "_blank");
|
||||||
|
}
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch_all();
|
||||||
|
}
|
||||||
|
, abortable = function(func) {
|
||||||
|
return function() {
|
||||||
|
if (filesaver.readyState !== filesaver.DONE) {
|
||||||
|
return func.apply(this, arguments);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
, create_if_not_found = {create: true, exclusive: false}
|
||||||
|
, slice
|
||||||
|
;
|
||||||
|
filesaver.readyState = filesaver.INIT;
|
||||||
|
if (!name) {
|
||||||
|
name = "download";
|
||||||
|
}
|
||||||
|
if (can_use_save_link) {
|
||||||
|
object_url = get_object_url(blob);
|
||||||
|
// FF for Android has a nasty garbage collection mechanism
|
||||||
|
// that turns all objects that are not pure javascript into 'deadObject'
|
||||||
|
// this means `doc` and `save_link` are unusable and need to be recreated
|
||||||
|
// `view` is usable though:
|
||||||
|
doc = view.document;
|
||||||
|
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
|
||||||
|
save_link.href = object_url;
|
||||||
|
save_link.download = name;
|
||||||
|
var event = doc.createEvent("MouseEvents");
|
||||||
|
event.initMouseEvent(
|
||||||
|
"click", true, false, view, 0, 0, 0, 0, 0
|
||||||
|
, false, false, false, false, 0, null
|
||||||
|
);
|
||||||
|
save_link.dispatchEvent(event);
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch_all();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Object and web filesystem URLs have a problem saving in Google Chrome when
|
||||||
|
// viewed in a tab, so I force save with application/octet-stream
|
||||||
|
// http://code.google.com/p/chromium/issues/detail?id=91158
|
||||||
|
if (view.chrome && type && type !== force_saveable_type) {
|
||||||
|
slice = blob.slice || blob.webkitSlice;
|
||||||
|
blob = slice.call(blob, 0, blob.size, force_saveable_type);
|
||||||
|
blob_changed = true;
|
||||||
|
}
|
||||||
|
// Since I can't be sure that the guessed media type will trigger a download
|
||||||
|
// in WebKit, I append .download to the filename.
|
||||||
|
// https://bugs.webkit.org/show_bug.cgi?id=65440
|
||||||
|
if (webkit_req_fs && name !== "download") {
|
||||||
|
name += ".download";
|
||||||
|
}
|
||||||
|
if (type === force_saveable_type || webkit_req_fs) {
|
||||||
|
target_view = view;
|
||||||
|
}
|
||||||
|
if (!req_fs) {
|
||||||
|
fs_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs_min_size += blob.size;
|
||||||
|
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
|
||||||
|
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
|
||||||
|
var save = function() {
|
||||||
|
dir.getFile(name, create_if_not_found, abortable(function(file) {
|
||||||
|
file.createWriter(abortable(function(writer) {
|
||||||
|
writer.onwriteend = function(event) {
|
||||||
|
target_view.location.href = file.toURL();
|
||||||
|
deletion_queue.push(file);
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch(filesaver, "writeend", event);
|
||||||
|
};
|
||||||
|
writer.onerror = function() {
|
||||||
|
var error = writer.error;
|
||||||
|
if (error.code !== error.ABORT_ERR) {
|
||||||
|
fs_error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
"writestart progress write abort".split(" ").forEach(function(event) {
|
||||||
|
writer["on" + event] = filesaver["on" + event];
|
||||||
|
});
|
||||||
|
writer.write(blob);
|
||||||
|
filesaver.abort = function() {
|
||||||
|
writer.abort();
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
};
|
||||||
|
filesaver.readyState = filesaver.WRITING;
|
||||||
|
}), fs_error);
|
||||||
|
}), fs_error);
|
||||||
|
};
|
||||||
|
dir.getFile(name, {create: false}, abortable(function(file) {
|
||||||
|
// delete file if it already exists
|
||||||
|
file.remove();
|
||||||
|
save();
|
||||||
|
}), abortable(function(ex) {
|
||||||
|
if (ex.code === ex.NOT_FOUND_ERR) {
|
||||||
|
save();
|
||||||
|
} else {
|
||||||
|
fs_error();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}), fs_error);
|
||||||
|
}), fs_error);
|
||||||
|
}
|
||||||
|
, FS_proto = FileSaver.prototype
|
||||||
|
, saveAs = function(blob, name) {
|
||||||
|
return new FileSaver(blob, name);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
FS_proto.abort = function() {
|
||||||
|
var filesaver = this;
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch(filesaver, "abort");
|
||||||
|
};
|
||||||
|
FS_proto.readyState = FS_proto.INIT = 0;
|
||||||
|
FS_proto.WRITING = 1;
|
||||||
|
FS_proto.DONE = 2;
|
||||||
|
|
||||||
|
FS_proto.error =
|
||||||
|
FS_proto.onwritestart =
|
||||||
|
FS_proto.onprogress =
|
||||||
|
FS_proto.onwrite =
|
||||||
|
FS_proto.onabort =
|
||||||
|
FS_proto.onerror =
|
||||||
|
FS_proto.onwriteend =
|
||||||
|
null;
|
||||||
|
|
||||||
|
view.addEventListener("unload", process_deletion_queue, false);
|
||||||
|
return saveAs;
|
||||||
|
}(this.self || this.window || this.content));
|
||||||
|
// `self` is undefined in Firefox for Android content script context
|
||||||
|
// while `this` is nsIContentFrameMessageManager
|
||||||
|
// with an attribute `content` that corresponds to the window
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') module.exports = saveAs;
|
58
js_src/libs/jquery-coolfieldset.js
vendored
Normal file
58
js_src/libs/jquery-coolfieldset.js
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* jQuery Plugin for creating collapsible fieldset
|
||||||
|
* @requires jQuery 1.2 or later
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Lucky <bogeyman2007@gmail.com>
|
||||||
|
* Licensed under the GPL license:
|
||||||
|
* http://www.gnu.org/licenses/gpl.html
|
||||||
|
*
|
||||||
|
* "animation" and "speed" options are added by Mitch Kuppinger <dpneumo@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
function hideFieldsetContent(obj, options){
|
||||||
|
if(options.animation==true)
|
||||||
|
obj.find('div').slideUp(options.speed);
|
||||||
|
else
|
||||||
|
obj.find('div').hide();
|
||||||
|
|
||||||
|
obj.removeClass("expanded");
|
||||||
|
obj.addClass("collapsed");
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFieldsetContent(obj, options){
|
||||||
|
if(options.animation==true)
|
||||||
|
obj.find('div').slideDown(options.speed);
|
||||||
|
else
|
||||||
|
obj.find('div').show();
|
||||||
|
|
||||||
|
obj.removeClass("collapsed");
|
||||||
|
obj.addClass("expanded");
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.coolfieldset = function(options){
|
||||||
|
var setting={collapsed:false, animation:true, speed:'medium'};
|
||||||
|
$.extend(setting, options);
|
||||||
|
|
||||||
|
this.each(function(){
|
||||||
|
var fieldset=$(this);
|
||||||
|
fieldset.addClass("collapsible");
|
||||||
|
var legend=fieldset.children('legend');
|
||||||
|
|
||||||
|
if(setting.collapsed==true){
|
||||||
|
hideFieldsetContent(fieldset, setting);
|
||||||
|
} else {
|
||||||
|
showFieldsetContent(fieldset, setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
// legend.bind('touchstart mousedown', function() {
|
||||||
|
legend.bind('click', function() {
|
||||||
|
if(fieldset.hasClass("collapsed")) {
|
||||||
|
showFieldsetContent(fieldset, setting);
|
||||||
|
} else {
|
||||||
|
hideFieldsetContent(fieldset, setting);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})(jQuery);
|
@ -25,8 +25,6 @@ var clientInfo = {};
|
|||||||
$(function() {
|
$(function() {
|
||||||
console.log("ready");
|
console.log("ready");
|
||||||
|
|
||||||
//TODO give this a more logical place in code
|
|
||||||
|
|
||||||
if (getURLParameter("d") != "null") debugMode = (getURLParameter("d") == "1");
|
if (getURLParameter("d") != "null") debugMode = (getURLParameter("d") == "1");
|
||||||
if (getURLParameter("p") != "null") sendPrintCommands = (getURLParameter("p") == "1");
|
if (getURLParameter("p") != "null") sendPrintCommands = (getURLParameter("p") == "1");
|
||||||
if (getURLParameter("c") != "null") communicateWithWifibox = (getURLParameter("c") == "1");
|
if (getURLParameter("c") != "null") communicateWithWifibox = (getURLParameter("c") == "1");
|
||||||
@ -34,8 +32,10 @@ $(function() {
|
|||||||
if (getURLParameter("u") != "null") autoUpdate = (getURLParameter("u") == "1");
|
if (getURLParameter("u") != "null") autoUpdate = (getURLParameter("u") == "1");
|
||||||
|
|
||||||
if (wifiboxIsRemote) {
|
if (wifiboxIsRemote) {
|
||||||
wifiboxURL = "http://192.168.5.1/d3dapi";
|
// var hostname = "http://10.0.0.45";
|
||||||
wifiboxCGIBinURL = "http://192.168.5.1/cgi-bin/d3dapi";
|
var hostname = "http://192.168.5.1";
|
||||||
|
wifiboxURL = hostname+"/d3dapi";
|
||||||
|
wifiboxCGIBinURL = hostname+"/cgi-bin/d3dapi";
|
||||||
} else {
|
} else {
|
||||||
wifiboxURL = "http://" + window.location.host + "/d3dapi";
|
wifiboxURL = "http://" + window.location.host + "/d3dapi";
|
||||||
wifiboxCGIBinURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
|
wifiboxCGIBinURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
|
||||||
@ -59,6 +59,7 @@ $(function() {
|
|||||||
initLayouting();
|
initLayouting();
|
||||||
initSidebars();
|
initSidebars();
|
||||||
initButtonBehavior();
|
initButtonBehavior();
|
||||||
|
initKeyboard();
|
||||||
initVerticalShapes();
|
initVerticalShapes();
|
||||||
if (!clientInfo.isSmartphone) initHelp();
|
if (!clientInfo.isSmartphone) initHelp();
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ $(function() {
|
|||||||
console.log("debug mode is true");
|
console.log("debug mode is true");
|
||||||
$("body").css("overflow", "auto");
|
$("body").css("overflow", "auto");
|
||||||
$("#debug_textArea").css("display", "block");
|
$("#debug_textArea").css("display", "block");
|
||||||
$("#preview_tmp").css("display", "block");
|
//$("#preview_tmp").css("display", "block");
|
||||||
|
|
||||||
$("#debug_display").css("display", "block");
|
$("#debug_display").css("display", "block");
|
||||||
|
|
||||||
@ -115,14 +116,14 @@ $(function() {
|
|||||||
function enableButton(elem, handler) {
|
function enableButton(elem, handler) {
|
||||||
//var elem = $('#'+domId);
|
//var elem = $('#'+domId);
|
||||||
elem.removeClass("disabled");
|
elem.removeClass("disabled");
|
||||||
elem.unbind('touchstart mousedown');
|
elem.unbind('click');
|
||||||
elem.bind('touchstart mousedown', handler);
|
elem.bind('click', handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableButton(elem) {
|
function disableButton(elem) {
|
||||||
//var elem = $('#'+domId);
|
//var elem = $('#'+domId);
|
||||||
elem.addClass("disabled");
|
elem.addClass("disabled");
|
||||||
elem.unbind('touchstart mousedown');
|
elem.unbind('click');
|
||||||
}
|
}
|
||||||
|
|
||||||
function showOrHideThermo() {
|
function showOrHideThermo() {
|
||||||
|
@ -7,7 +7,7 @@ var preview_tmp;
|
|||||||
var previewCtx_tmp;
|
var previewCtx_tmp;
|
||||||
|
|
||||||
var previewDefaults = {
|
var previewDefaults = {
|
||||||
rotation: Math.PI/90,
|
rotation: 0, //Math.PI/90,
|
||||||
numLayers: 10
|
numLayers: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +35,34 @@ form fieldset fieldset{
|
|||||||
clear: left;
|
clear: left;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
form fieldset.collapsed {
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
float:none;
|
||||||
|
}
|
||||||
|
form fieldset.collapsible {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
form fieldset.collapsible div{
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
form fieldset legend {
|
form fieldset legend {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
form fieldset.collapsible legend {
|
||||||
|
padding-left: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
form fieldset.expanded legend {
|
||||||
|
background: transparent url(../img/buttons/expanded.gif) no-repeat center left;
|
||||||
|
}
|
||||||
|
form fieldset.collapsed legend {
|
||||||
|
background: transparent url(../img/buttons/collapsed.gif) no-repeat center left;
|
||||||
|
}
|
||||||
|
|
||||||
form label {
|
form label {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
display: block;
|
display: block;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB |
BIN
www/img/buttons/collapsed.gif
Normal file
BIN
www/img/buttons/collapsed.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 B |
BIN
www/img/buttons/expanded.gif
Normal file
BIN
www/img/buttons/expanded.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 107 B |
@ -33,8 +33,8 @@
|
|||||||
<div class='sidebutton shadowright'></div>
|
<div class='sidebutton shadowright'></div>
|
||||||
<img class="btnNew btn" src="img/buttons/btnNew.png" /><br/>
|
<img class="btnNew btn" src="img/buttons/btnNew.png" /><br/>
|
||||||
<div class="btnsPrevNext" style="text-align:center">
|
<div class="btnsPrevNext" style="text-align:center">
|
||||||
<img class="btnPrevious btn" src="img/buttons/btnLeft.png">
|
<img class="btnPrevious btn disabled" src="img/buttons/btnLeft.png">
|
||||||
<img class="btnNext btn" src="img/buttons/btnRight.png">
|
<img class="btnNext btn disabled" src="img/buttons/btnRight.png">
|
||||||
<!-- <div id="txtSketch"></div> -->
|
<!-- <div id="txtSketch"></div> -->
|
||||||
</div>
|
</div>
|
||||||
<img class="btnSave btn" src="img/buttons/btnSave.png" /><br/>
|
<img class="btnSave btn" src="img/buttons/btnSave.png" /><br/>
|
||||||
@ -102,7 +102,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="debug_textArea">
|
<div id="debug_textArea">
|
||||||
<textarea rows="5" cols="60" id="textdump"></textarea>
|
<!-- <textarea rows="5" cols="60" id="textdump"></textarea> -->
|
||||||
|
<button onclick="settingsWindow.downloadGcode()">Download gcode</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="debug_display">
|
<div id="debug_display">
|
||||||
</div>
|
</div>
|
||||||
@ -117,7 +118,7 @@
|
|||||||
<div class="settingsContainer"></div>
|
<div class="settingsContainer"></div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="btnContainer">
|
<div class="btnContainer">
|
||||||
<img src="img/buttons/btnOk_settings.png" class="btn btnOK" alt="save"/>
|
<img src="img/buttons/btnOk.png" class="btn btnOK" alt="save"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -134,6 +135,8 @@
|
|||||||
<!--<script src="js/libs/imagesloaded-pkgd.min.js"></script>-->
|
<!--<script src="js/libs/imagesloaded-pkgd.min.js"></script>-->
|
||||||
<!--<script src="../js_src/libs/jquery-joyride-2-1.js"></script>-->
|
<!--<script src="../js_src/libs/jquery-joyride-2-1.js"></script>-->
|
||||||
<script src="js/libs/jquery-joyride-2-1.min.js"></script>
|
<script src="js/libs/jquery-joyride-2-1.min.js"></script>
|
||||||
|
<script src="js/libs/jquery-coolfieldset.min.js"></script>
|
||||||
|
<script src="js/libs/FileSaver.min.js"></script>
|
||||||
<!--<script src="js/doodle3d-client.js"></script>-->
|
<!--<script src="js/doodle3d-client.js"></script>-->
|
||||||
<script src="js/doodle3d-client.min.js"></script>
|
<script src="js/doodle3d-client.min.js"></script>
|
||||||
|
|
||||||
@ -152,6 +155,8 @@
|
|||||||
<script src="../js_src/Progressbar.js"></script>
|
<script src="../js_src/Progressbar.js"></script>
|
||||||
<script src="../js_src/Thermometer.js"></script>
|
<script src="../js_src/Thermometer.js"></script>
|
||||||
<script src="../js_src/utils.js"></script>
|
<script src="../js_src/utils.js"></script>
|
||||||
|
<script src="../js_src/sketches.js"></script>
|
||||||
|
<script src="../js_src/Help.js"></script>
|
||||||
<script src="../js_src/sidebar.js"></script>
|
<script src="../js_src/sidebar.js"></script>
|
||||||
<script src="../js_src/Message.js"></script>
|
<script src="../js_src/Message.js"></script>
|
||||||
<script src="../js_src/main.js"></script>
|
<script src="../js_src/main.js"></script>
|
||||||
|
@ -12,13 +12,15 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="settingsContainer">
|
<div class="settingsContainer">
|
||||||
<form id="settingsForm">
|
<form id="settingsForm">
|
||||||
<fieldset>
|
<fieldset id="printerPanel">
|
||||||
<legend>3D printer</legend>
|
<legend>3D printer</legend>
|
||||||
<label for="printerType">Type:</label>
|
<label for="printerType">Type:</label>
|
||||||
<select id="printerType" name="printer.type">
|
<select id="printerType" name="printer.type"></select>
|
||||||
<option value="rigidbot">Rigidbot</option>
|
<!-- <option value="rigidbot">Rigidbot</option>
|
||||||
<option value="ultimaker">Ultimaker</option>
|
<option value="ultimaker">Ultimaker</option>
|
||||||
|
<option value="ultimaker2">Ultimaker2</option>
|
||||||
<option value="makerbot_replicator2">MakerBot Replicator2</option>
|
<option value="makerbot_replicator2">MakerBot Replicator2</option>
|
||||||
|
<option value="makerbot_replicator2x">MakerBot Replicator2x</option>
|
||||||
<option value="makerbot_thingomatic">MakerBot Thing-o-matic</option>
|
<option value="makerbot_thingomatic">MakerBot Thing-o-matic</option>
|
||||||
<option value="printrbot">Printrbot</option>
|
<option value="printrbot">Printrbot</option>
|
||||||
<option value="bukobot">Bukobot</option>
|
<option value="bukobot">Bukobot</option>
|
||||||
@ -49,9 +51,38 @@
|
|||||||
<option value="vision_3d_printer">Vision 3D Printer</option>
|
<option value="vision_3d_printer">Vision 3D Printer</option>
|
||||||
<option value="marlin_generic">Generic Marlin Printer</option>
|
<option value="marlin_generic">Generic Marlin Printer</option>
|
||||||
<option value="makerbot_generic">Generic Makerbot Printer</option>
|
<option value="makerbot_generic">Generic Makerbot Printer</option>
|
||||||
</select><br/>
|
</select> --><br/>
|
||||||
<label for="printerBedWidth">Bed width:</label><input id="printerBedWidth" type="number" class="small" name="printer.bed.width">mm<br>
|
|
||||||
<label for="printerBedHeight">Bed height:</label><input id="printerBedHeight" type="number" class="small" name="printer.bed.height">mm<br>
|
<label for="printerDimensionsX">Dimensions:</label>
|
||||||
|
x:<input id="printerDimensionsX" type="number" class="small" name="printer.dimensions.x" placeholder="x">mm<br>
|
||||||
|
<label for="printerDimensionsY"></label>
|
||||||
|
y:<input id="printerDimensionsY" type="number" class="small" name="printer.dimensions.y" placeholder="y">mm<br>
|
||||||
|
<label for="printerDimensionsZ"></label>
|
||||||
|
z:<input id="printerDimensionsZ" type="number" class="small" name="printer.dimensions.z" placeholder="z">mm<br>
|
||||||
|
|
||||||
|
<fieldset id="gcodePanel">
|
||||||
|
<legend>GCODE settings</legend>
|
||||||
|
<div>
|
||||||
|
<div class="startgcode_left">
|
||||||
|
<label for="startgcode">Start:</label><br/>
|
||||||
|
<textarea id="startgcode" class="gcode" name="printer.startcode"></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="endgcode">End:</label><br/>
|
||||||
|
<textarea id="endgcode" class="gcode" name="printer.endcode"></textarea>
|
||||||
|
</div>
|
||||||
|
<small>
|
||||||
|
The following texts are replaced:
|
||||||
|
<dl>
|
||||||
|
<dt>{printingTemp}</dt><dd>Printing temperature</dd>
|
||||||
|
<dt>{printingBedTemp}</dt><dd>Printing bed temperature</dd>
|
||||||
|
<dt>{preheatTemp}</dt><dd>Preheat temperature</dd>
|
||||||
|
<dt>{preheatBedTemp}</dt><dd>Preheat bed temperature</dd>
|
||||||
|
<dt>{printerType}</dt><dd>Printer type</dd>
|
||||||
|
</dl>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset id="printersettings">
|
<fieldset id="printersettings">
|
||||||
@ -82,7 +113,7 @@
|
|||||||
<fieldset id="doodlesettings">
|
<fieldset id="doodlesettings">
|
||||||
<legend>Doodle3D settings</legend>
|
<legend>Doodle3D settings</legend>
|
||||||
<label for="simplifyMinDistance">Minimal line distance:</label><input id="simplifyMinDistance" type="number" class="small" name="doodle3d.simplify.minDistance">px<br>
|
<label for="simplifyMinDistance">Minimal line distance:</label><input id="simplifyMinDistance" type="number" class="small" name="doodle3d.simplify.minDistance">px<br>
|
||||||
<label for="maxObjectHeight">Max object height:</label><input id="maxObjectHeight" type="number" class="small" name="printer.maxObjectHeight">mm<br>
|
<!-- <label for="maxObjectHeight">Max object height:</label><input id="maxObjectHeight" type="number" class="small" name="printer.maxObjectHeight">mm<br> -->
|
||||||
<label for="screenToMillimeterScale">Pixels to mm scale:</label><input id="screenToMillimeterScale" type="number" step="0.1" class="small" name="printer.screenToMillimeterScale"><br>
|
<label for="screenToMillimeterScale">Pixels to mm scale:</label><input id="screenToMillimeterScale" type="number" step="0.1" class="small" name="printer.screenToMillimeterScale"><br>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@ -133,52 +164,11 @@
|
|||||||
<small id="updateInfo"></small>
|
<small id="updateInfo"></small>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset id="gcodeSettings">
|
|
||||||
<legend>GCODE settings</legend>
|
|
||||||
<small class="intro">GCode settings for all printers that use Marlin firmware</small>
|
|
||||||
<div class="startgcode_left">
|
|
||||||
<label for="startgcodeMarlin">Start:</label><br/>
|
|
||||||
<textarea id="startgcodeMarlin" class="gcode" name="printer.startcode.marlin"></textarea>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="endgcodeMarlin">End:</label><br/>
|
|
||||||
<textarea id="endcodeMarlin" class="gcode" name="printer.endcode.marlin"></textarea>
|
|
||||||
</div>
|
|
||||||
<small>
|
|
||||||
The following texts are replaced:
|
|
||||||
<dl>
|
|
||||||
<dt>{printingTemp}</dt><dd>Printing temperature</dd>
|
|
||||||
<dt>{printingBedTemp}</dt><dd>Printing bed temperature</dd>
|
|
||||||
<dt>{preheatTemp}</dt><dd>Preheat temperature</dd>
|
|
||||||
<dt>{preheatBedTemp}</dt><dd>Preheat bed temperature</dd>
|
|
||||||
</dl>
|
|
||||||
</small>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset id="x3gSettings">
|
|
||||||
<legend>GCODE settings</legend>
|
|
||||||
<small class="intro">GCODE settings for Makerbots.</small>
|
|
||||||
<div class="startgcode_left">
|
|
||||||
<label for="startgcodeX3G">Start:</label><br/>
|
|
||||||
<textarea id="startcodeX3G" class="gcode" name="printer.startcode.x3g"></textarea>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="endgcodeX3G">End:</label><br/>
|
|
||||||
<textarea id="endcodeX3G" class="gcode" name="printer.endcode.x3g"></textarea>
|
|
||||||
</div>
|
|
||||||
<small>
|
|
||||||
The following texts are replaced:
|
|
||||||
<dl>
|
|
||||||
<dt>{printingTemp}</dt><dd>Printing temperature</dd>
|
|
||||||
<dt>{printingBedTemp}</dt><dd>Printing bed temperature</dd>
|
|
||||||
<dt>{preheatTemp}</dt><dd>Preheat temperature</dd>
|
|
||||||
<dt>{preheatBedTemp}</dt><dd>Preheat bed temperature</dd>
|
|
||||||
<dt>{printerType}</dt><dd>Printer type</dd>
|
|
||||||
</dl>
|
|
||||||
</small>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset id="debugPanel">
|
<fieldset id="debugPanel">
|
||||||
<legend>Debug</legend>
|
<legend>Debug</legend>
|
||||||
<input type="button" onclick="settingsWindow.downloadlogs()" name="downloadlogs" value="Download logs" class="button" id="downloadlogs"/>
|
<input type="button" onclick="settingsWindow.downloadlogs()" name="downloadlogs" value="Download logs" class="button" id="downloadlogs"/>
|
||||||
|
<input type="button" onclick="settingsWindow.downloadGcode()" name="downloadGcode" value="Download GCODE" class="button" id="downloadGcode"/>
|
||||||
|
<input type="button" onclick="settingsWindow.downloadSvg()" name="downloadSvg" value="Download SVG" class="button" id="downloadSvg"/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset id="restorePanel">
|
<fieldset id="restorePanel">
|
||||||
<legend>Restore</legend>
|
<legend>Restore</legend>
|
||||||
|
Loading…
Reference in New Issue
Block a user