0
0
mirror of https://github.com/Doodle3D/doodle3d-client.git synced 2024-06-01 20:34:31 +02:00

Compare commits

...

56 Commits

Author SHA1 Message Date
peteruithoven
f8032d7411 Merge branch 'develop' 2017-06-23 12:36:16 +02:00
peteruithoven
2acb06c3ed Adding forgotten grunt task to make file: template
@companje This would add build info, create main.js.out which was used in later concat tasks. Without this task the final code would lack the main.js code.
2017-06-23 12:28:35 +02:00
peteruithoven
daed62937c Merged master into develop 2016-07-26 15:24:38 +02:00
peteruithoven
058fff8b34 Handle multiple tags in buildinfo 2016-06-15 14:50:09 +02:00
peteruithoven
28808078ad Enable using common npm start script 2016-06-15 14:49:46 +02:00
peteruithoven
4e18fa0f56 Execute new gitinfo in OpenWRT build 2016-05-11 13:28:44 +02:00
peteruithoven
225a173da7 Altered Build/Compile to run from shared folder
so grunt can access git info
2016-05-11 13:28:15 +02:00
peteruithoven
d2bc62b092 Fix stopping while sending
Fixes https://github.com/Doodle3D/WiFi-Box/issues/9
2016-05-11 12:22:54 +02:00
peteruithoven
28ce8ff479 OpenWRT Build/Prepare fix
Copy js files to build dir so grunt can use them
Relevant for #307
2016-05-10 16:06:27 +02:00
peteruithoven
fbcdaad54a Fix OpenWRT makefile Build/Compile step
Fixes #307
2016-05-10 15:21:49 +02:00
Wouter R
4a3da30ebd Log git/version information in web console (#305).
The information is dynamically inserted when grunt is run.
2016-04-23 17:36:35 +02:00
Wouter R
533968bb04 Stability fixes on unstable network (#304):
- when a sequence number mismatch is received and the wifibox expects the chunk immediately following the current one, skip ahead; this often happens after a network disconnect.
- retry sending a print part when the wifibox was disconnected (i.e. checkStatus failed and set state to WIFIBOX_DISCONNECTED_STATE).
2016-04-19 18:03:52 +02:00
Wouter R
0a9ceee49a Log statement fixes. 2016-04-19 18:03:17 +02:00
Wouter R
50d964e611 Change several log statements for Safari to print on one line instead of multiple. 2016-04-19 00:28:55 +02:00
Wouter R
656e37670e Log more information on AJAX failure and explicitly log when buffer is full. 2016-03-11 15:49:32 +01:00
Wouter R
4752199cfb Remove outdated comment. 2016-02-17 18:52:17 +01:00
Wouter R
c742740078 Include sequence numbers in console.log message when sending print. 2016-02-14 17:29:23 +01:00
Wouter R
578fba4f63 Sequence numbering + stop button:
- send sequence numbers along with gcode to wifibox;
- remove 'disable stop button hack';
- show error to user in case of sequencing errors, except when in stopping state.

Should fix #226.
2016-02-14 17:13:13 +01:00
Wouter R
bca548def5 js/Printer.js: partly clean up sendPrinterPart. 2016-02-14 16:42:21 +01:00
Wouter R
a5d3e88f0a js/Printer.js:
- change this.sendLength to Printer.MAX_LINES_PER_POST;
- re-order object variable declarations.
2016-02-14 16:21:52 +01:00
Wouter R
456531b15f Change 'first' parameter of printer/print call to 'clear'. 2016-02-14 00:37:17 +01:00
Wouter R
4f5e1143b4 Send total number of lines to be printed along with every gcode chunk. 2016-02-13 23:45:48 +01:00
Wouter R
a9f7fe1c78 Use bufferSize and maxBufferSize from printer progress to wait until buffer load drops below given ratio after buffer_full has been received. 2016-02-12 17:34:05 +01:00
Wouter R
8f0943a53b Update license-spec.lua for changed directory structure. 2016-02-12 17:06:03 +01:00
Wouter R
5c07947fe5 Code refactoring. 2016-01-06 20:35:19 +01:00
Wouter R
d48944e448 Add checkbox for new setting 'printer.bottomEnableTraveling'.
Implement bottom layer traveling in GCode generation as well as sketch rendering.
2016-01-06 19:26:07 +01:00
Wouter R
46bcd54a1a Only show warning about verbose logging when level is set to verbose or bulk.
Small improvements to when log level warnings are shown.
2016-01-06 16:38:59 +01:00
peteruithoven
25c51c3e5c settings log level layout 2016-01-06 16:11:34 +01:00
Wouter R
c2f5f890c7 Add dropdown menu to settings window for log level selection with appropriate warnings. 2016-01-06 14:25:17 +01:00
peteruithoven
09fcdbea31 Month fix #294 2015-09-15 10:42:45 +02:00
peteruithoven
969178b096 Merge branch 'develop' 2015-06-17 14:27:28 +02:00
peteruithoven
58ad430e13 404 responsive 2015-06-15 17:47:00 +02:00
Arne Boon
a7d253203a wanhao duplicator 4 printer type r2x heated bed support 2015-06-10 17:46:00 +02:00
Arne Boon
38b43e5263 add filament thickness to printer settings panel to make it configurable per printer type 2015-06-09 17:13:36 +02:00
peteruithoven
9a24230112 404 page fixes 2015-06-05 14:19:10 +02:00
peteruithoven
a823c4cc25 Removed Scan & Trace button
Doesn’t seem to be used, there is already a Photo Guide button.
2015-06-03 12:05:59 +02:00
peteruithoven
6835a7056c Merge branch 'master' into develop 2015-06-03 12:04:16 +02:00
Rick Companje
8d2d4a9f57 makefile & logo click url 2014-12-19 21:13:22 +01:00
Rick Companje
2fba2b34a1 filemanager refresh 2014-12-17 10:02:46 +01:00
Rick Companje
95f5ce97b5 manage sketches and file manager 2014-12-17 09:45:40 +01:00
Rick Companje
31b16b2a3f finished viewer 2014-12-10 15:21:17 +01:00
Rick Companje
18d1aacc71 fixed issue #261 (scroll overflow) 2014-12-10 08:55:31 +01:00
Rick Companje
58b930cefa started with file manager / viewer 2014-12-09 21:13:39 +01:00
Rick Companje
c6b6a3c448 fixed aspect-ratio bug for photo guide 2014-12-05 16:16:54 +01:00
Rick Companje
3d99c146a0 added a button for importing photos for tracing by hand 2014-10-09 16:24:24 +02:00
Wouter R
27e794876b Merge branch 'develop' of github.com:Doodle3D/doodle3d-client into develop 2014-06-05 19:53:07 +02:00
peteruithoven
6202f9febd Merge branch 'develop' 2014-05-28 17:49:35 +02:00
peteruithoven
53843f499c Fix #246. Assume ap created when empty network status 2014-05-22 13:58:24 +02:00
peteruithoven
953d50e5fc 404 style fixes 2014-05-14 17:49:05 +02:00
peteruithoven
72d2e859f7 iOS Captive portal fix 2 2014-05-14 17:28:51 +02:00
peteruithoven
248de728c6 iOS Captive portal fix 2014-05-14 17:28:09 +02:00
Rick Companje
4d986a3528 Update README.md 2014-04-22 21:06:38 +02:00
Rick Companje
c4593a4dc3 Update README.md 2014-04-22 21:05:10 +02:00
Rick Companje
7441b848f3 Update README.md 2014-04-22 21:04:56 +02:00
Rick Companje
d2ab7fc08b Update README.md 2014-04-22 21:03:25 +02:00
Wouter R
494aca34bc Eclipse-related files. 2014-03-20 21:48:00 +01:00
42 changed files with 1032 additions and 339 deletions

9
.gitignore vendored
View File

@ -18,18 +18,11 @@ img/logo/logo_smaller.png
img/logo/logo_smaller_8bit.png img/logo/logo_smaller_8bit.png
img/logo/logo_smaller_wide_8bit.png img/logo/logo_smaller_wide_8bit.png
img/logo/logo_smallest.png img/logo/logo_smallest.png
css/_backup20131010/*
css/_backup20131011/*
d3d_btns.css d3d_btns.css
index.html.orig
js/Thermometer.js.orig
js/buttonbehaviors.js.orig
js/gcodeGenerating_v01.js.orig
js/init_layout backup20130918.js
js/main.js.orig js/main.js.orig
js/previewRendering_v02.js.orig
less/verticalshapes.css less/verticalshapes.css
less/verticalshapes_backup.css less/verticalshapes_backup.css
__settings.html __settings.html
css/_settings.css css/_settings.css
node_modules/* node_modules/*
js/main.js.out

16
.settings/.jsdtscope Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="node_modules/|www/" kind="src" path="">
<attributes>
<attribute name="provider" value="org.eclipse.wst.jsdt.web.core.internal.project.ModuleSourcePathProvider"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path=""/>
</classpath>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
included=//*.js

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>

View File

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@ -0,0 +1 @@
Window

View File

@ -10,6 +10,32 @@ module.exports = function(grunt) {
'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
gitinfo: {
options: {},
commands: { 'tag': ['tag', '--points-at', 'HEAD'] }
},
template: {
'add_build_info': {
options: {
data: function() {
grunt.task.requires('gitinfo');
var gi = grunt.config('gitinfo');
var lbc = gi.local.branch.current;
var tags = (gi.tag == '') ? 'no_tag' : gi.tag;
tags = tags.split('\n').join(',');
var commitMsg = lbc.lastCommitMessage.slice(1, -1).split('\n')[0].replace(/"/g, '\\\"');
var buildInfo = lbc.shortSHA + "/" + lbc.name + "/" + tags +
" (" + lbc.lastCommitTime.slice(1, -1) + "; \'" + commitMsg + "'";
return { 'build_info': buildInfo };
}
},
files: {
'js/main.js.out': ['js/main.js']
}
}
},
concat: { concat: {
options: { options: {
// separator: ';' // separator: ';'
@ -22,7 +48,8 @@ module.exports = function(grunt) {
'js/*.js', 'js/*.js',
// make sure we put main.js last // make sure we put main.js last
'!js/main.js', '!js/main.js',
'js/main.js', ], 'js/main.js.out'
],
dest: 'www/js/<%= pkg.name %>.js' dest: 'www/js/<%= pkg.name %>.js'
} }
}, },
@ -129,6 +156,8 @@ module.exports = function(grunt) {
}); });
// These plugins provide necessary tasks. // These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-gitinfo');
grunt.loadNpmTasks('grunt-template');
grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-uglify');
@ -139,6 +168,8 @@ module.exports = function(grunt) {
// Default task. // Default task.
grunt.registerTask('default', [ grunt.registerTask('default', [
'gitinfo',
'template',
'less', 'less',
'autoprefixer', 'autoprefixer',
'cssmin', 'cssmin',

View File

@ -34,6 +34,7 @@ endef
define Build/Prepare define Build/Prepare
mkdir -p $(PKG_BUILD_DIR) mkdir -p $(PKG_BUILD_DIR)
$(CP) js $(PKG_BUILD_DIR)/
$(CP) less $(PKG_BUILD_DIR)/ $(CP) less $(PKG_BUILD_DIR)/
$(CP) www $(PKG_BUILD_DIR)/ $(CP) www $(PKG_BUILD_DIR)/
$(CP) Gruntfile.js $(PKG_BUILD_DIR)/ $(CP) Gruntfile.js $(PKG_BUILD_DIR)/
@ -43,16 +44,22 @@ define Build/Prepare
endef endef
define Build/Compile define Build/Compile
# We're running grunt in the shared folder, so
# grunt can access git info
npm install npm install
ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y) ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y)
grunt less autoprefixer cssmin concat uglify grunt gitinfo template less autoprefixer cssmin concat uglify
else else
grunt less autoprefixer cssmin concat grunt gitinfo template less autoprefixer cssmin concat
endif endif
# Copy compiled files to build dir
$(CP) www $(PKG_BUILD_DIR)/
endef endef
define Package/doodle3d-client/install define Package/doodle3d-client/install
$(INSTALL_DIR) $(1)/www $(INSTALL_DIR) $(1)/www
$(INSTALL_DIR) $(1)/www/filemanager
$(INSTALL_DIR) $(1)/www/css $(INSTALL_DIR) $(1)/www/css
$(INSTALL_DIR) $(1)/www/img $(INSTALL_DIR) $(1)/www/img
#$(INSTALL_DIR) $(1)/www/js #$(INSTALL_DIR) $(1)/www/js
@ -63,12 +70,14 @@ define Package/doodle3d-client/install
$(CP) $(PKG_BUILD_DIR)/www/settings.html $(1)/www/ $(CP) $(PKG_BUILD_DIR)/www/settings.html $(1)/www/
$(CP) $(PKG_BUILD_DIR)/www/helpcontent.html $(1)/www/ $(CP) $(PKG_BUILD_DIR)/www/helpcontent.html $(1)/www/
$(CP) $(PKG_BUILD_DIR)/www/redirect.html $(1)/www/ $(CP) $(PKG_BUILD_DIR)/www/redirect.html $(1)/www/
$(CP) $(PKG_BUILD_DIR)/www/404.html $(1)/www/
$(CP) $(PKG_BUILD_DIR)/www/css/debug.min.css $(1)/www/css/ $(CP) $(PKG_BUILD_DIR)/www/css/debug.min.css $(1)/www/css/
$(CP) $(PKG_BUILD_DIR)/www/css/settings.min.css $(1)/www/css/ $(CP) $(PKG_BUILD_DIR)/www/css/settings.min.css $(1)/www/css/
$(CP) $(PKG_BUILD_DIR)/www/css/styles.min.css $(1)/www/css/ $(CP) $(PKG_BUILD_DIR)/www/css/styles.min.css $(1)/www/css/
$(CP) $(PKG_BUILD_DIR)/www/img/* $(1)/www/img/ $(CP) $(PKG_BUILD_DIR)/www/img/* $(1)/www/img/
$(CP) $(PKG_BUILD_DIR)/www/filemanager/* $(1)/www/filemanager/
ifeq ($(CONFIG_DOODLE3D_CLIENT_MINIFY_JS),y) 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/

View File

@ -5,9 +5,10 @@ Doodle3D client app
# How to build # How to build
## Prerequisites ## Prerequisites
- get `npm`, the Node.js package manager, for instance using macports on OSX. - install npm, the Node.js package manager: `sudo port install npm`
- (prerequisite) install Grunt: `sudo pm install -g grunt-cli`. - install Grunt: `sudo npm install -g grunt-cli`
- run `npm install` in the project root to install project dependencies - run `npm install` in the **project root** to install project dependencies
Finally run grunt to build minified css and js files. By default, it will keep ## Build
- run `grunt` in the project root to to build minified css and js files. By default, it will keep
running to automatically rebuild when source files are changed. running to automatically rebuild when source files are changed.

41
js/AddScanDialog.js Normal file
View File

@ -0,0 +1,41 @@
//var shapeResolution=3;
var shapePopup;
function initScanDialog() {
scanPopup = new Popup($("#popupScan"), $("#popupMask"));
$("#btnScanOk").on("onButtonClick", onBtnScanOk);
$("#btnCloseScan").on("onButtonClick", onBtnCloseScan);
}
function onBtnCloseScan() {
$('#imgGuide').hide();
$('#btnCloseScan').hide();
}
function onBtnScanOk() {
scanPopup.commit();
}
function showScanDialog() {
scanPopup.open();
}
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imgGuide').attr('src', e.target.result);
$('#imgGuide').show();
$('#btnCloseScan').show();
scanPopup.commit();
}
reader.readAsDataURL(input.files[0]);
}
}
$("#fileScan").change(function(){
readURL(this);
});

View File

@ -49,8 +49,8 @@ function initKeyboard() {
var ch = String.fromCharCode(event.which); var ch = String.fromCharCode(event.which);
switch (ch) { switch (ch) {
case 'c': clearDoodle(); break; case 'c': newSketch(); break;
case 'n': clearDoodle(); break; case 'n': newSketch(); break;
case 'p': print(); break; case 'p': print(); break;
case 'u': oopsUndo(); break; case 'u': oopsUndo(); break;
case 'g': settingsWindow.downloadGcode(); break; case 'g': settingsWindow.downloadGcode(); break;
@ -59,13 +59,14 @@ function initKeyboard() {
case 'h': previewUp(true); break; case 'h': previewUp(true); break;
case 'H': previewDown(true); break; case 'H': previewDown(true); break;
case 's': saveSketch(); break; case 's': saveSketch(); break;
case 'L': nextDoodle(); break; case 'L': nextSketch(); break;
case 'l': prevDoodle(); break; case 'l': prevSketch(); break;
case '[': previewTwistLeft(); break; case '[': previewTwistLeft(); break;
case ']': previewTwistRight(); break; case ']': previewTwistRight(); break;
case '|': resetTwist(); break; case '|': resetTwist(); break;
case 't': showWordArtDialog(); break; case 't': showWordArtDialog(); break;
case 'i': showShapeDialog(); break; case 'i': showShapeDialog(); break;
case 'T': showScanDialog(); break;
case ';': moveShape(-5,0); break; case ';': moveShape(-5,0); break;
case '\'': moveShape(5,0); break; case '\'': moveShape(5,0); break;

View File

@ -25,7 +25,7 @@ function Message() {
this.$element = $element; this.$element = $element;
} }
this.set = function(contents,mode,autoHide,disableEffect) { this.set = function(contents,mode,autoHide,disableEffect) {
console.log("Message:set: ",contents,mode,autoHide,disableEffect); //console.log("Message:set: ",contents,mode,autoHide,disableEffect);
if(disableEffect) { if(disableEffect) {
self.fill(contents,mode,autoHide) self.fill(contents,mode,autoHide)
} else{ } else{

View File

@ -19,6 +19,7 @@ function setPrintprogress(val) {
//*/ //*/
function Printer() { function Printer() {
/* CONSTANTS */
Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected"; Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected";
Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet
@ -32,11 +33,29 @@ function Printer() {
Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being sent to the printer, leaving will result in a incomplete 3D print"; Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being sent to the printer, leaving will result in a incomplete 3D print";
//after buffer full message has been received, wait until the buffer load is below this ratio before sending new data
Printer.GCODE_BUFFER_WAIT_LOAD_RATIO = 0.75;
Printer.BUFFER_SPACE_WAIT_TIMEOUT = 30000; // how often to recheck buffer load
//time to wait when wifibox connection is lost while printing
Printer.DISCONNECTED_RETRY_DELAY = 5000;
Printer.MAX_LINES_PER_POST = 500; // max amount of gcode lines per post (limited because WiFi box can't handle too much)
Printer.MAX_GCODE_SIZE = 10; // max size of gcode in MB's (estimation)
// Events
Printer.UPDATE = "update";
/* MEMBER VARIABLES */
this.temperature = 0; this.temperature = 0;
this.targetTemperature = 0; this.targetTemperature = 0;
this.currentLine = 0; this.currentLine = 0;
this.totalLines = 0; this.totalLines = 0;
this.bufferedLines = 0; this.bufferedLines = 0;
this.bufferSize = 0;
this.maxBufferSize = 0;
this.state = Printer.UNKNOWN_STATE; this.state = Printer.UNKNOWN_STATE;
this.hasControl = true; // whether this client has control access this.hasControl = true; // whether this client has control access
@ -47,8 +66,8 @@ function Printer() {
this.timeoutTime = 3000; this.timeoutTime = 3000;
this.sendPrintPartTimeoutTime = 5000; this.sendPrintPartTimeoutTime = 5000;
this.gcode; // gcode to be printed this.gcode = []; // gcode to be printed
this.sendLength = 500; // max amount of gcode lines per post (limited because WiFi box can't handle too much) this.gcodeNumChunks = 0; //number of chunks to be sent (used for sequence numbering)
this.retryDelay = 2000; // retry setTimout delay this.retryDelay = 2000; // retry setTimout delay
this.retrySendPrintPartDelay; // retry setTimout instance this.retrySendPrintPartDelay; // retry setTimout instance
@ -56,12 +75,10 @@ function Printer() {
this.retryStopDelay; // retry setTimout instance this.retryStopDelay; // retry setTimout instance
this.retryPreheatDelay; // retry setTimout instance this.retryPreheatDelay; // retry setTimout instance
Printer.MAX_GCODE_SIZE = 10; // max size of gcode in MB's (estimation)
this.stateOverruled = false; this.stateOverruled = false;
// Events
Printer.UPDATE = "update"; /* FUNCTIONS */
var self = this; var self = this;
@ -120,6 +137,7 @@ function Printer() {
this.sendIndex = 0; this.sendIndex = 0;
this.gcode = gcode; this.gcode = gcode;
this.gcodeNumChunks = Math.ceil(this.gcode.length / Printer.MAX_LINES_PER_POST);
//console.log(" gcode[20]: ",gcode[20]); //console.log(" gcode[20]: ",gcode[20]);
var gcodeLineSize = this.byteSize(gcode[20]); var gcodeLineSize = this.byteSize(gcode[20]);
@ -142,7 +160,7 @@ function Printer() {
//this.targetTemperature = settings["printer.temperature"]; // slight hack //this.targetTemperature = settings["printer.temperature"]; // slight hack
this.sendPrintPart(this.sendIndex, this.sendLength); this.sendPrintPart(this.sendIndex, Printer.MAX_LINES_PER_POST);
} }
this.byteSize = function(s){ this.byteSize = function(s){
@ -150,26 +168,43 @@ function Printer() {
} }
this.sendPrintPart = function(sendIndex,sendLength) { this.sendPrintPart = function(sendIndex,sendLength) {
console.log("Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this.gcode.length + ", sendLength: " + sendLength); var self = this;
// Abort if stopping
// sendPrintPart can be called by delayed retry after request timeout for example
var sendPercentage = Math.round(sendIndex/this.gcode.length*100); if (self.state === Printer.STOPPING_STATE) return;
message.set("Sending doodle to printer: "+sendPercentage+"%",Message.NOTICE,false,true);
var firstOne = (sendIndex == 0)? true : false;
var start = firstOne; // start printing right away
var completed = false; var completed = false;
if (this.gcode.length < (sendIndex + sendLength)) { if (this.gcode.length < (sendIndex + sendLength)) {
console.log(" sending less than max sendLength (and last)");
sendLength = this.gcode.length - sendIndex; sendLength = this.gcode.length - sendIndex;
//lastOne = true;
completed = true; completed = true;
} }
var gcodePart = this.gcode.slice(sendIndex, sendIndex+sendLength);
var postData = { gcode: gcodePart.join("\n"), first: firstOne, start: start};
var self = this; /* prepare post data */
var gcodePart = this.gcode.slice(sendIndex, sendIndex + sendLength);
var firstOne = (sendIndex == 0) ? true : false;
var start = firstOne; // start printing right away
var seqNum = Math.floor(sendIndex / Printer.MAX_LINES_PER_POST);
var postData = {
gcode: gcodePart.join("\n"), total_lines: this.gcode.length,
clear: firstOne, start: start,
seq_number: seqNum, seq_total: this.gcodeNumChunks
};
/* inform user what's going on */
var lessThanMaxText = completed ? " (last one, max=" + Printer.MAX_LINES_PER_POST + ")" : "";
console.log("Printer:sendPrintPart: sendIndex=" + sendIndex + "/" + this.gcode.length +
", sendLength=" + sendLength + lessThanMaxText +
", sequence numbers: " + seqNum + "/" + this.gcodeNumChunks);
var sendPercentage = Math.round(sendIndex / this.gcode.length * 100);
message.set("Sending doodle to printer: " + sendPercentage + "%", Message.NOTICE, false, true);
/* send data */
if (communicateWithWifibox) { if (communicateWithWifibox) {
$.ajax({ $.ajax({
url: this.wifiboxURL + "/printer/print", url: this.wifiboxURL + "/printer/print",
@ -178,13 +213,13 @@ function Printer() {
dataType: 'json', dataType: 'json',
timeout: this.sendPrintPartTimeoutTime, timeout: this.sendPrintPartTimeoutTime,
success: function(data){ success: function(data){
console.log("Printer:sendPrintPart response: ",data); //console.log("Printer:sendPrintPart success response: ", data);
if(data.status == "success") { if(data.status == "success") {
if (completed) { if (completed) {
console.log("Printer:sendPrintPart:gcode sending completed"); console.log("Printer:sendPrintPart: gcode sending completed");
this.gcode = []; this.gcode = [];
btnStop.css("display","block"); // hack this.gcodeNumChunks = 0;
self.removeLeaveWarning(); self.removeLeaveWarning();
message.set("Doodle has been sent to printer...",Message.INFO,true); message.set("Doodle has been sent to printer...",Message.INFO,true);
//self.targetTemperature = settings["printer.temperature"]; // slight hack //self.targetTemperature = settings["printer.temperature"]; // slight hack
@ -195,23 +230,48 @@ function Printer() {
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) { if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
//console.log("Printer:sendPrintPart:sending next part"); //console.log("Printer:sendPrintPart:sending next part");
self.sendPrintPart(sendIndex + sendLength, sendLength); self.sendPrintPart(sendIndex + sendLength, sendLength);
} else if (Printer.WIFIBOX_DISCONNECTED_STATE) {
console.warn("Printer:sendPrintPart: wifibox connection lost while printing, retrying in " + (Printer.DISCONNECTED_RETRY_DELAY / 1000) + " seconds");
clearTimeout(self.retrySendPrintPartDelay);
self.retrySendPrintPartDelay = setTimeout(function() {
console.log("Printer:sendPrintPart: retrying after wifibox disconnect was detected");
self.sendPrintPart(sendIndex, sendLength);
}, Printer.DISCONNECTED_RETRY_DELAY);
} }
} }
} else if (data.status == "fail") {
if (data.data.status == "buffer_full") {
console.log("Printer:sendPrintPart: print server reported buffer full, pausing data transmission");
//this will wait in a setTimeout loop until enough room is available and then call sendPrintPart again.
self.waitForBufferSpace(sendIndex, sendLength);
} else if (data.data.status == "seq_num_mismatch" && data.data.seq_number == seqNum) {
console.warn("Printer:sendPrintPart: received sequence error, server is one chunk ahead. Proceeding with next chunk...");
self.sendPrintPart(sendIndex + sendLength, sendLength);
} else {
console.error("Printer:sendPrintPart: unexpected failure response for API endpoint printer/print (" +
data.data.status + ", current server seq. info: " + data.data.seq_number + "/" + data.data.seq_total + ")");
//sequence errors should not occur, except perhaps when 'stop' was clicked while still sending (https://github.com/Doodle3D/doodle3d-client/issues/226).
if (self.state != Printer.STOPPING_STATE) {
message.set("Unexpected error sending doodle to printer (" + data.data.status + "), please retry", Message.ERROR, false, true);
}
}
} }
// after we know the first gcode packed has bin received or failed
// after we know the first gcode part has been received or failed
// (and the driver had time to update the printer.state) // (and the driver had time to update the printer.state)
// we start checking the status again // we start checking the status again
if(sendIndex == 0) { if(sendIndex == 0) {
self.startStatusCheckInterval(); self.startStatusCheckInterval();
} }
} }
}).fail(function() { }).fail(function(jqXHr, textStatus, errorThrown) {
console.log("Printer:sendPrintPart: failed"); console.error("Printer:sendPrintPart: failed (AJAX status: '" + textStatus + "') AJAX exception (if any):", errorThrown);
console.warn("Printer:sendPrintPart: retrying in " + (Printer.DISCONNECTED_RETRY_DELAY / 1000) + " seconds");
clearTimeout(self.retrySendPrintPartDelay); clearTimeout(self.retrySendPrintPartDelay);
self.retrySendPrintPartDelay = setTimeout(function() { self.retrySendPrintPartDelay = setTimeout(function() {
console.log("request printer:sendPrintPart failed retry"); console.log("Printer:sendPrintPart: retrying after AJAX failure");
self.sendPrintPart(sendIndex, sendLength) self.sendPrintPart(sendIndex, sendLength)
},self.retryDelay); // retry after delay }, Printer.DISCONNECTED_RETRY_DELAY);
// after we know the gcode packed has bin received or failed // after we know the gcode packed has bin received or failed
// (and the driver had time to update the printer.state) // (and the driver had time to update the printer.state)
@ -222,13 +282,47 @@ function Printer() {
console.log ("Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function"); console.log ("Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function");
} }
} }
/*
* Called by sendPrintPart when a buffer_full fail response is received.
* This function keeps calling itself until the GCodeBuffer's load ratio
* drops below a predefined value and then calls sendPrintPart again.
*/
this.waitForBufferSpace = function(sendIndex,sendLength) {
var fillRatio = this.bufferSize / this.maxBufferSize;
var self = this;
//console.log("buffer fill state: " + self.bufferSize + "/" + self.maxBufferSize + " (" + fillPercent + "%)");
if (fillRatio >= Printer.GCODE_BUFFER_WAIT_LOAD_RATIO) {
var fillPercent = (fillRatio * 100).toFixed(2);
console.log("Printer:waitForBufferSpace: waiting until gcode buffer load ratio is below " +
(Printer.GCODE_BUFFER_WAIT_LOAD_RATIO * 100) + "% (current: " + fillPercent + "% of " +
(self.maxBufferSize / 1024) + "KiB)");
self.waitForBufferSpaceDelay = setTimeout(function() { self.waitForBufferSpace(sendIndex, sendLength); }, Printer.BUFFER_SPACE_WAIT_TIMEOUT);
} else {
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
console.log("Printer:waitForBufferSpace: load ratio dropped below " + (Printer.GCODE_BUFFER_WAIT_LOAD_RATIO * 100) + "%, calling sendPrintPart...");
self.sendPrintPart(sendIndex, sendLength);
} else {
console.log("Printer:waitForBufferSpace: load ratio dropped far enough but printer state is not printing or buffering anymore, not resuming.");
}
}
}
this.stop = function() { this.stop = function() {
console.log("Printer:stop"); console.log("Printer:stop");
var self = this;
if (self.retrySendPrintPartDelay !== undefined) {
clearTimeout(self.retrySendPrintPartDelay);
}
if (self.waitForBufferSpaceDelay !== undefined) {
clearTimeout(self.waitForBufferSpaceDelay);
}
endCode = generateEndCode(); endCode = generateEndCode();
console.log(" endCode: ",endCode); console.log(" endCode: ",endCode);
var postData = { gcode: endCode.join("\n")}; var postData = { gcode: endCode.join("\n")};
var self = this;
if (communicateWithWifibox) { if (communicateWithWifibox) {
$.ajax({ $.ajax({
url: this.wifiboxURL + "/printer/stop", url: this.wifiboxURL + "/printer/stop",
@ -325,7 +419,9 @@ function Printer() {
// progress // progress
self.currentLine = data.current_line; self.currentLine = data.current_line;
self.totalLines = data.total_lines; self.totalLines = data.total_lines;
self.bufferedLines = data.buffered_lines self.bufferedLines = data.buffered_lines;
self.bufferSize = data.buffer_size;
self.maxBufferSize = data.max_buffer_size;
// access // access
self.hasControl = data.has_control; self.hasControl = data.has_control;

View File

@ -25,7 +25,7 @@ function shapeMoveTo(x,y) {
_points.push([x, y, true]); _points.push([x, y, true]);
adjustBounds(x, y); adjustBounds(x, y);
adjustPreviewTransformation(); adjustPreviewTransformation();
draw(x, y, .5); draw(x, y, -1);
} }
function shapeLineTo(x,y) { function shapeLineTo(x,y) {

View File

@ -56,6 +56,8 @@ function loadFromSvg(svgData) {
clearDoodle(); clearDoodle();
svgData = svgData.replace("M0,0 ",""); //RC: hack
var p = svgData.indexOf("<path"); var p = svgData.indexOf("<path");
if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; } if (p == -1) { console.log("loadFromSvg: could not find parsing start point"); return false; }
p = svgData.indexOf('d="', p); p = svgData.indexOf('d="', p);
@ -73,7 +75,17 @@ function loadFromSvg(svgData) {
return true; return true;
} else { //something else, must be a pair of coordinates... } else { //something else, must be a pair of coordinates...
var tx = 0, ty = 0, numberEnd = 0, len = 0; var tx = 0, ty = 0, numberEnd = 0, len = 0;
// var firstComma = svgData.indexOf(',', p);
// var firstSpace = svgData.indexOf(' ', p);
numberEnd = svgData.indexOf(',', p); numberEnd = svgData.indexOf(',', p);
////// RC: if instead of a comma a space is used between a pair use that as a separator
var firstSpace = svgData.indexOf(' ', p);
if (firstSpace<numberEnd) numberEnd=firstSpace;
//console.log('numberEnd',numberEnd,firstSpace);
////////////////
if (numberEnd == -1) { console.log("could not find comma in coordinate pair"); return false; } if (numberEnd == -1) { console.log("could not find comma in coordinate pair"); return false; }
len = numberEnd - p; len = numberEnd - p;
tx = parseFloat(svgData.substr(p, len)); tx = parseFloat(svgData.substr(p, len));
@ -104,7 +116,7 @@ function loadFromSvg(svgData) {
adjustBounds(x, y); adjustBounds(x, y);
adjustPreviewTransformation(); adjustPreviewTransformation();
if (isMove) draw(x, y, .5); if (isMove) draw(x, y, -1);
else draw(x, y); else draw(x, y);
} }
p++; p++;

View File

@ -13,6 +13,7 @@ var btnSettings, btnWordArt;
var btnToggleEdit, buttonGroupEdit, btnZoom, btnMove, btnRotate; var btnToggleEdit, buttonGroupEdit, btnZoom, btnMove, btnRotate;
var btnToggleVerticalShapes, btnHeight, btnTwist, btnShape, btnConv, btnStraight, btnSine, btnDiv; var btnToggleVerticalShapes, btnHeight, btnTwist, btnShape, btnConv, btnStraight, btnSine, btnDiv;
var buttonGroupAdd, popupWordArt; var buttonGroupAdd, popupWordArt;
var btnScan, popupScan;
var state; var state;
var prevState; var prevState;
@ -43,8 +44,10 @@ function initButtonBehavior() {
buttonGroupAdd = $("#buttonGroupAdd"); buttonGroupAdd = $("#buttonGroupAdd");
btnShape = new Button("#btnShape"); btnShape = new Button("#btnShape");
btnWordArt = new Button("#btnWordArt"); btnWordArt = new Button("#btnWordArt");
btnScan = new Button("#btnScan");
popupWordArt = $("#popupWordArt"); popupWordArt = $("#popupWordArt");
popupShape = $("#popupShape"); popupShape = $("#popupShape");
popupScan = $("#popupScan");
popupMask = $("#popupMask"); popupMask = $("#popupMask");
logoPanel = $("#logopanel"); logoPanel = $("#logopanel");
btnToggleEdit = new Button("#btnToggleEdit"); btnToggleEdit = new Button("#btnToggleEdit");
@ -69,11 +72,12 @@ function initButtonBehavior() {
btnAdd.on("onButtonClick", onBtnAdd); btnAdd.on("onButtonClick", onBtnAdd);
btnWordArt.on("onButtonClick", onBtnWordArt); btnWordArt.on("onButtonClick", onBtnWordArt);
btnShape.on("onButtonClick", onBtnShape); btnShape.on("onButtonClick", onBtnShape);
btnScan.on("onButtonClick", onBtnScan);
btnPrint.on("onButtonClick", print); btnPrint.on("onButtonClick", print);
btnStop.on("onButtonClick", stopPrint); btnStop.on("onButtonClick", stopPrint);
btnSave.on("onButtonClick", saveSketch); btnSave.on("onButtonClick", saveSketch);
btnPrevious.on("onButtonClick", prevDoodle); btnPrevious.on("onButtonClick", previousSketch);
btnNext.on("onButtonClick", nextDoodle); btnNext.on("onButtonClick", nextSketch);
btnOops.on("onButtonHold", onBtnOops); btnOops.on("onButtonHold", onBtnOops);
// vertical shape buttons // vertical shape buttons
btnToggleVerticalShapes.on("onButtonClick", onBtnToggleVerticalShapes); btnToggleVerticalShapes.on("onButtonClick", onBtnToggleVerticalShapes);
@ -89,8 +93,10 @@ function initButtonBehavior() {
btnZoom.on("onButtonHold", onBtnZoom); btnZoom.on("onButtonHold", onBtnZoom);
btnRotate.on("onButtonHold", onBtnRotate); btnRotate.on("onButtonHold", onBtnRotate);
getSavedSketchStatus(); //getSavedSketchStatus();
setSketchModified(false); listSketches();
// setSketchModified(false);
// updateSketchButtonStates();
function onBtnToggleVerticalShapes() { function onBtnToggleVerticalShapes() {
var btnImg; var btnImg;
@ -179,7 +185,7 @@ function initButtonBehavior() {
} }
function onBtnNew(e) { function onBtnNew(e) {
clearDoodle(); newSketch();
} }
function onBtnWordArt(e) { function onBtnWordArt(e) {
@ -191,6 +197,11 @@ function initButtonBehavior() {
buttonGroupAdd.fadeOut(); buttonGroupAdd.fadeOut();
} }
function onBtnScan(e) {
showScanDialog();
buttonGroupAdd.fadeOut();
}
btnSettings.on("onButtonClick", openSettingsWindow); btnSettings.on("onButtonClick", openSettingsWindow);
// 29-okt-2013 - we're not doing help for smartphones at the moment // 29-okt-2013 - we're not doing help for smartphones at the moment
@ -221,8 +232,6 @@ function print(e) {
//setState(Printer.BUFFERING_STATE,printer.hasControl); //setState(Printer.BUFFERING_STATE,printer.hasControl);
printer.overruleState(Printer.BUFFERING_STATE); printer.overruleState(Printer.BUFFERING_STATE);
btnStop.css("display","none"); // hack
// we put the gcode generation in a little delay // we put the gcode generation in a little delay
// so that for example the print button is disabled right away // so that for example the print button is disabled right away
clearTimeout(gcodeGenerateDelayer); clearTimeout(gcodeGenerateDelayer);
@ -347,7 +356,7 @@ function setState(newState,newHasControl) {
prevState = state; prevState = state;
console.log("setState: ",prevState," > ",newState," ( ",newHasControl,")"); console.log("setState: " + prevState + " > " + newState + " ( " + newHasControl + ")");
setDebugText("State: "+newState); setDebugText("State: "+newState);
// print button // print button
@ -414,8 +423,9 @@ function setState(newState,newHasControl) {
btnSave.disable(); btnSave.disable();
break; break;
default: default:
updatePrevNextButtonState(); // updatePrevNextButtonState();
if (isModified) btnSave.enable(); updateSketchButtonStates();
if (isModified) btnSave.enable();
break; break;
} }

View File

@ -97,52 +97,66 @@ function initDoodleDrawing() {
* CANVAS DRAWING FUNCTION * CANVAS DRAWING FUNCTION
* *
* * * * * * * * * */ * * * * * * * * * */
function draw(_x, _y, _width) {
//console.log("canvasDrawing:draw");
// console.log("f:draw() >> _width: " + _width);
if (prevX == 0 && prevY ==0) { //If _width is not specified, it is calculated from the distance between this and the previous point.
//If _width is negative, the path is 'floating', and only drawn if the setting printer.bottomEnableTraveling is true.
function draw(_x, _y, _width) {
//console.log("canvasDrawing:draw");
//console.log("f:draw() >> _width: " + _width);
if (prevX == 0 && prevY == 0) {
prevX = _x; prevX = _x;
prevY = _y; prevY = _y;
} }
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(prevX, prevY); ctx.moveTo(prevX, prevY);
ctx.lineTo(_x, _y);
if (_width != undefined) { var lineWeight = null;
ctx.lineWidth = _width; if (_width != undefined && _width < 0) {
} else { if (settings['printer.bottomEnableTraveling']) {
if (drawVariableLineWeight) { ctx.moveTo(_x, _y);
var dist = Math.sqrt(Math.pow((prevX - _x), 2) + Math.pow((prevY - _y), 2));
if (dist < 10) {
lineweight += .25;
} else if (dist < 20) {
lineweight += .5;
} else if (dist < 30) {
lineweight += .75;
} else if (dist < 50) {
lineweight += 1;
} else if (dist < 80) {
lineweight += 1.5;
} else if (dist < 120) {
lineweight += 2.25;
} else if (dist < 170) {
lineweight += 3.5;
} else {
lineweight += 2;
}
lineweight = Math.min(lineweight, 30);
lineweight *= 0.90;
lineweight = Math.max(lineweight, 1.0);
} else { } else {
lineweight = 2; lineWeight = 0.5;
}
} else {
if (_width != undefined) {
lineWeight = _width;
} else {
if (drawVariableLineWeight) {
var dist = Math.sqrt(Math.pow((prevX - _x), 2) + Math.pow((prevY - _y), 2));
if (dist < 10) {
lineWeight += .25;
} else if (dist < 20) {
lineWeight += .5;
} else if (dist < 30) {
lineWeight += .75;
} else if (dist < 50) {
lineWeight += 1;
} else if (dist < 80) {
lineWeight += 1.5;
} else if (dist < 120) {
lineWeight += 2.25;
} else if (dist < 170) {
lineWeight += 3.5;
} else {
lineWeight += 2;
}
lineWeight = Math.min(lineWeight, 30);
lineWeight *= 0.90;
lineWeight = Math.max(lineWeight, 1.0);
} else {
lineWeight = 2;
}
} }
ctx.lineWidth = lineweight;
} }
ctx.lineCap = 'round';
ctx.stroke(); if (lineWeight != null) {
ctx.lineCap = 'round';
ctx.lineWidth = lineWeight;
ctx.lineTo(_x, _y);
ctx.stroke();
}
prevX = _x; prevX = _x;
prevY = _y; prevY = _y;
@ -157,7 +171,7 @@ function draw(_x, _y, _width) {
function clearDoodle() { function clearDoodle() {
//console.log("f:clearDoodle"); //console.log("f:clearDoodle");
updatePrevNextButtonStateOnClear(); //updatePrevNextButtonStateOnClear();
_points = []; _points = [];
@ -177,6 +191,7 @@ function clearDoodle() {
resetVerticalShapes(); resetVerticalShapes();
setSketchModified(false); setSketchModified(false);
// updateSketchButtonStates();
} }
function redrawDoodle(recalcBoundsAndTransforms) { function redrawDoodle(recalcBoundsAndTransforms) {
@ -201,7 +216,7 @@ function redrawDoodle(recalcBoundsAndTransforms) {
for (var i = 0; i < _points.length; i++) { for (var i = 0; i < _points.length; i++) {
// console.log(" drawing points " + _points[i]); // console.log(" drawing points " + _points[i]);
if (_points[i][2] == true) { if (_points[i][2] == true) {
draw(_points[i][0], _points[i][1], 0.5); draw(_points[i][0], _points[i][1], -1);
} else { } else {
draw(_points[i][0], _points[i][1]); draw(_points[i][0], _points[i][1]);
} }
@ -300,7 +315,7 @@ function onCanvasMouseDown(e) {
_points.push([x, y, true]); _points.push([x, y, true]);
adjustBounds(x, y); adjustBounds(x, y);
adjustPreviewTransformation(); adjustPreviewTransformation();
draw(x, y, 0.5); draw(x, y, -1);
} }
var prevPoint = {x:-1, y:-1}; var prevPoint = {x:-1, y:-1};
@ -322,18 +337,9 @@ function onCanvasMouseMove(e) {
y = e.layerY; y = e.layerY;
} }
if (prevPoint.x != -1 || prevPoint.y != -1) { var prevPresent = prevPoint.x != -1 || prevPoint.y != -1;
var dist = Math.sqrt(((prevPoint.x - x) * (prevPoint.x - x)) + ((prevPoint.y - y) * (prevPoint.y - y))); var dist = prevPresent ? Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2)) : undefined;
if (dist > 5) { // replace by setting: doodle3d.simplify.minDistance if (!prevPresent || dist > 5) { // replace dist check by setting: doodle3d.simplify.minDistance
_points.push([x, y, false]);
adjustBounds(x, y);
adjustPreviewTransformation();
draw(x, y);
prevPoint.x = x;
prevPoint.y = y;
}
} else {
// this is called once, every time you start to draw a line
_points.push([x, y, false]); _points.push([x, y, false]);
adjustBounds(x, y); adjustBounds(x, y);
adjustPreviewTransformation(); adjustPreviewTransformation();
@ -341,7 +347,7 @@ function onCanvasMouseMove(e) {
prevPoint.x = x; prevPoint.x = x;
prevPoint.y = y; prevPoint.y = y;
} }
// DEBUG // DEBUG
// $("#textdump").text(""); // $("#textdump").text("");
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n"); // $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
@ -400,7 +406,7 @@ function onCanvasTouchDown(e) {
_points.push([x, y, true]); _points.push([x, y, true]);
adjustBounds(x, y); adjustBounds(x, y);
adjustPreviewTransformation(); adjustPreviewTransformation();
draw(x, y, .5); draw(x, y, -1);
movementCounter = 0; movementCounter = 0;
@ -423,19 +429,11 @@ function onCanvasTouchMove(e) {
//console.log("f:onCanvasTouchMove >> x,y = "+x+","+y+" , e: " , e); //console.log("f:onCanvasTouchMove >> x,y = "+x+","+y+" , e: " , e);
if (prevPoint.x != -1 || prevPoint.y != -1) { var prevPresent = prevPoint.x != -1 || prevPoint.y != -1;
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2)); var dist = prevPresent ? Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2)) : undefined;
if (dist > 5) { if (!prevPresent || dist > 5) { // replace dist check by setting: doodle3d.simplify.minDistance
_points.push([x, y, false]);
adjustBounds(x, y)
adjustPreviewTransformation();
draw(x, y);
prevPoint.x = x;
prevPoint.y = y;
}
} else {
_points.push([x, y, false]); _points.push([x, y, false]);
adjustBounds(x, y) adjustBounds(x, y);
adjustPreviewTransformation(); adjustPreviewTransformation();
draw(x, y); draw(x, y);
prevPoint.x = x; prevPoint.x = x;
@ -488,8 +486,3 @@ function onCanvasTouchEnd(e) {
function prevent(e) { function prevent(e) {
e.preventDefault(); e.preventDefault();
} }

View File

@ -20,6 +20,7 @@ function generate_gcode() {
var bottomSpeed = settings["printer.bottomLayerSpeed"]; var bottomSpeed = settings["printer.bottomLayerSpeed"];
var firstLayerSlow = settings["printer.firstLayerSlow"]; var firstLayerSlow = settings["printer.firstLayerSlow"];
var bottomFlowRate = settings["printer.bottomFlowRate"]; var bottomFlowRate = settings["printer.bottomFlowRate"];
var bottomEnableTraveling = settings["printer.bottomEnableTraveling"];
var travelSpeed = settings["printer.travelSpeed"] var travelSpeed = settings["printer.travelSpeed"]
var filamentThickness = settings["printer.filamentThickness"]; var filamentThickness = settings["printer.filamentThickness"];
var wallThickness = settings["printer.wallThickness"]; var wallThickness = settings["printer.wallThickness"];
@ -159,8 +160,10 @@ function generate_gcode() {
var isTraveling = !isLoop && i==0; var isTraveling = !isLoop && i==0;
var doRetract = retractionEnabled && prev.distance(to) > retractionminDistance; var doRetract = retractionEnabled && prev.distance(to) > retractionminDistance;
//Always travel to first point, then optionally disable traveling for first two layers and use settings for remainder of print.
var firstPointEver = (layer == 0 && i == 0 && j == 0); var firstPointEver = (layer == 0 && i == 0 && j == 0);
if (firstPointEver || layer > 2 && enableTraveling && isTraveling) { //always travel to first point, then disable traveling for first two layers and use settings for remainder of print var travelingAllowed = firstPointEver || bottomEnableTraveling || layer > 2;
if (travelingAllowed && enableTraveling && isTraveling) {
if (!firstPointEver && doRetract) gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); //retract if (!firstPointEver && 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 (!firstPointEver && doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal if (!firstPointEver && doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal
@ -218,6 +221,8 @@ function subsituteVariables(gcode) {
case "makerbot_replicator2x": printerType = "r2x"; 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; case "makerbot_generic": printerType = "r2"; break;
case "wanhao_duplicator4": printerType = "r2x"; break;
case "_3Dison_plus": printerType = "r2"; break;
} }
var heatedBedReplacement = (heatedbed)? "" : ";"; var heatedBedReplacement = (heatedbed)? "" : ";";

View File

@ -34,7 +34,8 @@ var POPUP_SHOW_DURATION = 175;
var BUTTON_GROUP_SHOW_DURATION = 80; var BUTTON_GROUP_SHOW_DURATION = 80;
$(function() { $(function() {
console.log("ready"); console.log("Doodle3D client ready");
console.log("Build information - <%= build_info %>)");
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");
@ -42,15 +43,26 @@ $(function() {
if (getURLParameter("r") != "null") wifiboxIsRemote = (getURLParameter("r") == "1"); if (getURLParameter("r") != "null") wifiboxIsRemote = (getURLParameter("r") == "1");
if (getURLParameter("u") != "null") autoUpdate = (getURLParameter("u") == "1"); if (getURLParameter("u") != "null") autoUpdate = (getURLParameter("u") == "1");
if (wifiboxIsRemote) { var hostname;
// var hostname = "http://10.0.0.45"; if (wifiboxIsRemote) hostname = 'http://192.168.5.1';
var hostname = "http://192.168.5.1"; if (getURLParameter("wifiboxURL") != "null") hostname = getURLParameter("wifiboxURL");
wifiboxURL = hostname+"/d3dapi"; if (!hostname) hostname = "http://" + window.location.host;
wifiboxCGIBinURL = hostname+"/cgi-bin/d3dapi";
} else { wifiboxURL = hostname+"/d3dapi";
wifiboxURL = "http://" + window.location.host + "/d3dapi"; wifiboxCGIBinURL = hostname+"/cgi-bin/d3dapi";
wifiboxCGIBinURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
}
//var api = wifiboxURL+'/d3dapi/sketch/';
// if (wifiboxIsRemote) {
// // var hostname = "http://10.0.0.45";
// var hostname = "http://192.168.5.1";
// wifiboxURL = hostname+"/d3dapi";
// wifiboxCGIBinURL = hostname+"/cgi-bin/d3dapi";
// } else {
// wifiboxURL = "http://" + window.location.host + "/d3dapi";
// wifiboxCGIBinURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
// }
if (!communicateWithWifibox) { if (!communicateWithWifibox) {
sendPrintCommands = false; // 'communicateWithWifibox = false' implies this sendPrintCommands = false; // 'communicateWithWifibox = false' implies this
@ -74,6 +86,7 @@ $(function() {
// initVerticalShapes(); // initVerticalShapes();
initWordArt(); initWordArt();
initShapeDialog(); initShapeDialog();
initScanDialog();
disableDragging(); disableDragging();

View File

@ -145,6 +145,9 @@ function NetworkPanel() {
this.retrieveNetworkStatus = function(connecting) { this.retrieveNetworkStatus = function(connecting) {
//console.log("NetworkPanel:retrieveNetworkStatus"); //console.log("NetworkPanel:retrieveNetworkStatus");
_api.status(function(data) { _api.status(function(data) {
if(data.status === "") {
data.status = NetworkAPI.STATUS.CREATED.toString();
}
if(typeof data.status === 'string') { if(typeof data.status === 'string') {
data.status = parseInt(data.status); data.status = parseInt(data.status);
} }

View File

@ -34,7 +34,8 @@ function SettingsWindow() {
var _networkPanel = new NetworkPanel(); var _networkPanel = new NetworkPanel();
var _networkAPI = new NetworkAPI(); var _networkAPI = new NetworkAPI();
var _restoreStateField var _restoreStateField;
var _initialLogLevel = undefined;
var self = this; var self = this;
@ -115,6 +116,10 @@ function SettingsWindow() {
settingsPopup.close(); settingsPopup.close();
self.signin(); self.signin();
} }
//FIXME: instead of this rather ugly call, implement events for changes to settings so we can keep code decoupled
redrawDoodle(false);
_btnOK.removeAttr("disabled"); _btnOK.removeAttr("disabled");
}); });
}; };
@ -123,6 +128,12 @@ function SettingsWindow() {
_form.loadAllSettings(function(loadedSettings){ _form.loadAllSettings(function(loadedSettings){
console.log("Settings:loaded settings: ",loadedSettings); console.log("Settings:loaded settings: ",loadedSettings);
settings = loadedSettings; settings = loadedSettings;
//only set the initial level once, to make behaviour of restart warning as correctly as possible
if (_initialLogLevel == undefined)
_initialLogLevel = loadedSettings['system.log.level'];
updateLogLevelWarningsVisibility();
_form.fillForm(settings); _form.fillForm(settings);
$(document).trigger(SettingsWindow.SETTINGS_LOADED); $(document).trigger(SettingsWindow.SETTINGS_LOADED);
if(complete) complete(); if(complete) complete();
@ -176,6 +187,35 @@ function SettingsWindow() {
saveAs(blob, "doodle3d.svg"); saveAs(blob, "doodle3d.svg");
} }
}; };
this.openFileManager = function() {
location.href = "filemanager/"+location.search;
}
this.logLevelChanged = function() {
updateLogLevelWarningsVisibility();
}
/***** LOCAL FUNCTIONS *****/
function updateLogLevelWarningsVisibility() {
var showHideAnimDuration = 100;
newLevel = $('#logLevel').val();
if (_initialLogLevel != newLevel) {
$('#logging-restart-warning').show(showHideAnimDuration);
} else {
$('#logging-restart-warning').hide(showHideAnimDuration);
}
switch (newLevel) {
case "verbose": case "bulk":
$('#logging-verbose-warning').show(showHideAnimDuration);
break;
default:
$('#logging-verbose-warning').hide(showHideAnimDuration);
}
}
} }
/************************* /*************************

View File

@ -204,7 +204,7 @@ function UpdatePanel() {
this.setState = function(newState,refresh) { this.setState = function(newState,refresh) {
//console.log("UpdatePanel:setState"); //console.log("UpdatePanel:setState");
if(!refresh && this.state == newState) return; if(!refresh && this.state == newState) return;
console.log("UpdatePanel:setState: ",this.state," > ",newState,"(",this.stateText,") (in Access Point Mode: ",_inAccessPointMode,") (newestVersion: ",self.newestVersion,") (refresh: ",refresh,")"); console.log("UpdatePanel:setState: " + this.state + " > " + newState + "(" + this.stateText + ") (in Access Point Mode: " + _inAccessPointMode + ") (newestVersion: " + self.newestVersion + ") (refresh: " + refresh + ")");
this.state = newState; this.state = newState;
// should personal sketches and settings be retained over update? // should personal sketches and settings be retained over update?
@ -314,7 +314,7 @@ function UpdatePanel() {
var fields = [ ts.substr(0, 4), ts.substr(4, 2), ts.substr(6, 2) ]; var fields = [ ts.substr(0, 4), ts.substr(4, 2), ts.substr(6, 2) ];
if (!fields || fields.length != 3 || fields[1] > 12) return null; if (!fields || fields.length != 3 || fields[1] > 12) return null;
var abbrMonths = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Sep', 'Aug', 'Oct', 'Nov', 'Dec' ]; var abbrMonths = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
return abbrMonths[fields[1] - 1] + " " + fields[2] + ", " + fields[0]; return abbrMonths[fields[1] - 1] + " " + fields[2] + ", " + fields[0];
} }

View File

@ -6,158 +6,95 @@
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details. * See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/ */
var currentSketchId = 0; var curSketch = 0;
var numSavedSketches = 0; var sketches = []; //contains fileIDs
function getSavedSketchStatus() { function previousSketch(e) {
$.ajax({ loadSketch(curSketch-1);
url: wifiboxURL + "/sketch/status",
dataType: 'json',
type: 'GET',
//timeout: this.timeoutTime,
success: function(response) {
if (response.status == 'error' || response.status == 'fail') {
console.log("getSavedSketchStatus fail/error: " + response.msg + " -- ", response);
} else {
console.log("getSavedSketchStatus success: num. saved: " + response.data.number_of_sketches + ", space available: " + response.data.available);
numSavedSketches = response.data.number_of_sketches;
updatePrevNextButtonStateOnClear();
}
}
}).fail(function() {
console.log("getSavedSketchStatus failed");
});
} }
function setSketchModified(_isModified, doNotClearCurrent) { function nextSketch(e) {
loadSketch(curSketch+1);
}
function newSketch(e) {
clearDoodle();
curSketch = sketches.length; //index of the last item + 1
updateSketchButtonStates();
}
function listSketches() {
console.log('listSketches')
$.get(wifiboxURL + "/sketch/list", function(data) {
if (data.status=='success') {
sketches = data.data.list;
curSketch = sketches.length-1;
setSketchModified(false);
updateSketchButtonStates();
}
})
}
function setSketchModified(_isModified) {
isModified = _isModified; isModified = _isModified;
updateSketchButtonStates();
// alert("isModified: " + isModified);
//console.log("setModified: " + isModified + (typeof(doNotClearCurrent) !== 'undefined' ? " (doNotClearCurrent: "+doNotClearCurrent+")" : "")); //TEMP
if (isModified) btnSave.enable();
else btnSave.disable();
//if (typeof(doNotClearCurrent) !== 'undefined' && !doNotClearCurrent) setCurrentSketchId(-1);
//sketchModified = isModified; /// ERROR?
} }
function setCurrentSketchId(sId) { function updateSketchButtonStates() {
console.log("setCurrentSketchId: " + sId + " / " + numSavedSketches); console.log('sketch: isModified: ' + isModified + ', curSketch: ' + curSketch + ', sketches.length: ' + sketches.length);
// var enablePrev = false;
// var enableNext = false;
currentSketchId = sId; if (isModified) {
btnSave.enable();
//clamp }
if (currentSketchId > numSavedSketches) currentSketchId = numSavedSketches; else {
if (currentSketchId < 1) currentSketchId = 1; btnSave.disable();
//update textbox
//$("#txtSketch").val(currentSketchId);
updatePrevNextButtonState();
}
function updatePrevNextButtonStateOnClear() {
if (numSavedSketches > 0) btnPrevious.enable();
btnNext.disable();
currentSketchId = numSavedSketches+1; //after the end of the list
btnSave.disable();
}
function updatePrevNextButtonState() {
//btnPrevious state
if (numSavedSketches==0 || currentSketchId < 2) {
btnPrevious.disable();
} else {
btnPrevious.enable();
} }
//btnNext state if (curSketch<sketches.length-1) {
if (numSavedSketches==0 || currentSketchId >= numSavedSketches) {
btnNext.disable();
} else {
btnNext.enable(); btnNext.enable();
} else {
btnNext.disable();
} }
if (curSketch>0) {
btnPrevious.enable();
} else {
btnPrevious.disable();
}
} }
function loadSketch(sketchId) { function loadSketch(_curSketch) {
curSketch = _curSketch;
$.ajax({ if (curSketch<0) curSketch=0;
url: wifiboxURL + "/sketch/" + sketchId, if (curSketch>sketches.length-1) curSketch=sketches.length-1;
dataType: 'json',
type: 'GET', var id = sketches[curSketch];
// timeout: this.timeoutTime,
success: function(response) { console.log('sketch: loadSketch curSketch:' + curSketch + ', id: ' + id);
if (response.status == 'error' || response.status == 'fail') {
console.log("loadSketch fail/error: " + response.msg + " -- ", response); $.get(wifiboxURL + "/sketch", {id:id}, function(response) {
} else { if (response.status=='success') {
console.log("loadSketch success: loaded id #" + response.data.id, response); console.log('sketch: loaded',response);
//console.log("sketch content:\n" + response.data.data); var svgData = response.data.data;
if (loadFromSvg(response.data.data)) { loadFromSvg(svgData);
setSketchModified(false, true); setSketchModified(false);
setCurrentSketchId(response.data.id); } else {
} console.log('error loading sketch: ',response);
} listSketches();
} }
}).fail(function() {
console.log("loadSketch failed: ", response); })
});
} }
function saveSketch() { function saveSketch() {
svg = saveToSvg(); console.log("sketch: saveSketch");
console.log("generated SVG [" + _points.length + " points, " + svg.length + " bytes]:\n" + svg); var svgData = saveToSvg();
$.post(wifiboxURL + "/sketch", {data: svgData}, function(response) {
console.log("sketch: saveSketch: response",response);
listSketches();
})
$.ajax({
url: wifiboxURL + "/sketch",
dataType: 'json',
type: 'POST',
data: { data: svg },
//timeout: this.timeoutTime,
success: function(response) {
if (response.status == 'error' || response.status == 'fail') {
console.log("saveSketch fail/error: " + response.msg + " -- ", response);
} else {
console.log("saveSketch success: saved with id #" + response.data.id, response);
setSketchModified(false, true);
numSavedSketches = response.data.id;
setCurrentSketchId(response.data.id);
}
}
}).fail(function() {
console.log("saveSketch failed: ", response);
});
}
function prevDoodle(e) {
console.log("f:prevDoodle(): " + currentSketchId + " / " + numSavedSketches);
//alert('prev ' + numSavedSketches);
//return;
//TODO: if (enabled) {
var sketchId = (currentSketchId > 0) ? currentSketchId : numSavedSketches;
if (sketchId > 1) sketchId--;
//alert(sketchId);
loadSketch(sketchId);
//}
}
function nextDoodle(e) {
console.log("f:nextDoodle()");
//alert('next ' + numSavedSketches);
//return;
//TODO: if (enabled) {
var sketchId = (currentSketchId > 0) ? currentSketchId : numSavedSketches;
if (sketchId < numSavedSketches) sketchId++;
loadSketch(sketchId);
//}
} }

View File

@ -6,9 +6,35 @@
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
height: 250px; height: 200px;
width: 500px; width: 30em;
margin: -125px 0 0 -250px; margin: -85px 0px 0px -16em;
background-color: #FCFCFC;
padding: 0px 1em;
}
}
@media screen and (max-width: 485px) {
#page404 {
overflow-y: auto;
#message404 {
position: relative;
left: 0px;
top: 0px;
margin: 10% 0;
padding: 0;
width: 100%;
height: auto;
p, ul {
margin: 1em;
}
}
#landscape {
box-shadow: none;
.bgContainer {
display: none;
}
}
} }
} }

View File

@ -47,18 +47,20 @@ body {
left: 0px; left: 0px;
//z-index: -5; //z-index: -5;
} }
#bgTop { #bgTop {
top: 0px; top: 0px;
} }
#bgMiddle { #bgMiddle {
top: 30%; top: 30%;
} }
#bgBottom { #bgBottom {
bottom: 0px; bottom: 0px;
} }
@media only screen and (max-height: 700px) {
#bgMiddle {
display: none;
}
}
@import "base_centerpanel.less"; @import "base_centerpanel.less";
@import "base_leftpanel.less"; @import "base_leftpanel.less";

View File

@ -57,6 +57,7 @@
left: 0; left: 0;
width: 78%; width: 78%;
height: 100%; height: 100%;
text-align: center;
} }
#mycanvas { #mycanvas {
@ -127,4 +128,24 @@
} }
#mycanvas {
position: absolute;
left: 0px;
top: 0px;
}
#imgGuide {
// z-index: -1000;
// position: absolute;
// -webkit-filter: contrast(400%);
//-webkit-filter: brightness(100%);
// opacity: 50%;
opacity: 0.4;
filter: alpha(opacity=40);
pointer-events:none;
max-width: 100%;
max-height: 100%;
height: auto;
margin-left: auto;
}

View File

@ -130,6 +130,16 @@
left: 4px; left: 4px;
position: absolute; position: absolute;
} }
#btnCloseScan {
top: 4px;
right: 8px;
position: absolute;
display: none;
opacity: 0.7;
filter: alpha(opacity=70);
}
#buttonGroupEdit { #buttonGroupEdit {
position: absolute; position: absolute;
top: 5px; top: 5px;
@ -163,10 +173,10 @@
margin-top: -60%; margin-top: -60%;
margin-left: 70%; margin-left: 70%;
width: 200%; width: 200%;
max-width: 140px; /*fixme: can this grow based on it's content?*/ max-width: 240px; /*fixme: can this grow based on it's content?*/
padding: 5% 0 5% 5%; padding: 5% 0 5% 5%;
#btnWordArt, #btnShape { #btnWordArt, #btnShape, #btnScan {
width: 45%; width: 30%;
} }
} }

View File

@ -47,6 +47,21 @@
} }
} }
#popupScan {
width: 330px;
height:210px;
margin-left: -165px;
margin-top: -105px;
input[type="file"] {
width: 98%;
}
#btnScanOk {
float: right;
margin: 15px 0 0 0;
}
}
#popupShape { #popupShape {
width: 310px; width: 310px;
margin-left: -155px; margin-left: -155px;

View File

@ -3,6 +3,16 @@
SETTINGS POPUP SETTINGS POPUP
*/ */
.warn-box {
color: #bb0;
border: 1px solid #bb0;
width: 99%;
border-radius: 5px;
margin: 7px 0;
padding: 2px;
display: none;
}
#popupSettings { #popupSettings {
top: 0; top: 0;
left: 0; left: 0;

View File

@ -1,8 +1,10 @@
local M = { local M = {
BASE_PATH = 'js_src', BASE_PATH = 'js',
EXCLUDE_FILES = {}, EXCLUDE_FILES = {},
PROCESS_FILES = { PROCESS_FILES = {
['js_src/[^/]*%.js'] = 'cstyle' ['js/[^/]*%.js'] = 'cstyle',
['js/api/[^/]*%.js'] = 'cstyle',
['js/settings/[^/]*%.js'] = 'cstyle'
}, },
IGNORE_GIT_CHANGED = false IGNORE_GIT_CHANGED = false
} }

View File

@ -9,7 +9,7 @@
"author": "Peter Uithoven, Adriaan Wormgoor, Rick Companje, Wouter Reckman", "author": "Peter Uithoven, Adriaan Wormgoor, Rick Companje, Wouter Reckman",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"devDependencies": { "devDependencies": {
"grunt": "~0.4.1", "grunt": "~0.4.5",
"grunt-cli": "~0.1.9", "grunt-cli": "~0.1.9",
"grunt-contrib-less": "~0.7.0", "grunt-contrib-less": "~0.7.0",
"grunt-contrib-watch": "~0.5.3", "grunt-contrib-watch": "~0.5.3",
@ -17,6 +17,11 @@
"grunt-contrib-jshint": "~0.6.4", "grunt-contrib-jshint": "~0.6.4",
"grunt-autoprefixer": "~0.4.0", "grunt-autoprefixer": "~0.4.0",
"grunt-contrib-cssmin": "~0.6.2", "grunt-contrib-cssmin": "~0.6.2",
"grunt-contrib-concat": "~0.3.0" "grunt-contrib-concat": "~0.3.0",
"grunt-gitinfo": "~0.1.7",
"grunt-template": "~0.2.3"
},
"scripts": {
"start": "grunt"
} }
} }

30
www/404.html Normal file
View File

@ -0,0 +1,30 @@
<div id="landscape" class="clearfix">
<!-- background images -->
<div class="bgContainer">
<img id="bgTop" src="img/bg_top.png" />
<img id="bgMiddle" src="img/bg_middle.png" />
<img id="bgBottom" src="img/bg_bottom.png" />
</div>
<!-- center panel -->
<div id="centerpanel">
<div id="logopanel" class="btn">
<img id="pencil" src="img/logo/pencil.png"/>
<img id="logo" src="img/logo/doodle3d.png"/>
</div>
</div>
<div id="message404">
<p>
You're probably trying to go to a website on the internet, but you're currently only connected to the Doodle3D WiFi box, which means you're not connected to the internet.<br/>
You could:
<ul>
<li>Reconnect to the WiFi you normally use.</li>
<li>Configure the WiFi box to connect to that WiFi in client mode. You can do this trough the settings screen.</li>
</ul>
</p>
</div>
</div>
<div id="portrait">
<img id="vertImage" src="img/bg_vertical.png"/>
</div>

View File

@ -17,6 +17,7 @@ body,th,td {
/*min-width: 370px;*/ /*min-width: 370px;*/
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: scroll;
} }
/*form#settingsForm {*/ /*form#settingsForm {*/
/*width: 100% auto;*/ /*width: 100% auto;*/
@ -75,6 +76,10 @@ form fieldset.collapsed legend {
center left; center left;
} }
#debugPanel label {
min-width: 59px;
}
form label { form label {
min-width: 150px; min-width: 150px;
display: block; display: block;

View File

@ -0,0 +1,49 @@
body {
font-family: Helvetica, Abel, Arial;
font-size: 1em;
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
-moz-user-select: none; /* mozilla browsers */
-khtml-user-select: none; /* webkit (konqueror) browsers */
-ms-user-select: none; /* IE10+ */
}
button {
font-size: 1em;
}
div.item {
width:150px;
height:130px;
border:1px solid black;
display: inline-block;
overflow: hidden;
background-color: white;
margin-right: 5px;
}
div.item.selected {
background-color: #7cf;
}
div.item input[type='checkbox'] {
position: absolute;
}
#frmUpload {
display: inline;
}
input[type='file'] {
width: 1px;
opacity:0
}
#txtInfo {
float: right;
/*display: inline-block;*/
}
img#logo {
cursor: pointer;
}

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>Doodle3D</title>
<link href="css/style.css" rel="stylesheet" media="screen">
</head>
<body>
<img id="logo" src="../img/logo/doodle3d.png" height="25">
<hr>
<button id="btnSelectAll">Select all</button>
<button id="btnDeselectAll">Deselect all</button>
<button id="btnDelete">Delete</button>
<button id="btnDownload">Download</button> <!-- <a id="link" href="#">Download</a> -->
<form id="frmUpload"><button id="btnUpload">Upload</button><input id="uploads" type="file" accept="image/svg+xml" multiple/></form>
<span id="txtInfo"></span>
<hr>
<form>
<div id="svgContainer"></div>
</form>
<script src="../js/libs/jquery-1-9-1.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>

267
www/filemanager/js/main.js Normal file
View File

@ -0,0 +1,267 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2014, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
// http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery
function getURLParameter(name) {
return decodeURI((new RegExp('[&?]'+name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]);
}
var wifiboxURL = "";
if (getURLParameter("r") != "null") wifiboxURL = 'http://192.168.5.1';
if (getURLParameter("wifiboxURL") != "null") wifiboxURL = getURLParameter("wifiboxURL");
var api = wifiboxURL+'/d3dapi/sketch/';
$("#logo").click(onLogoClick)
$("#btnDelete").click(deleteSelectedSketches);
$("#btnSelectAll").click(selectAll);
$("#btnDeselectAll").click(deselectAll);
$("#uploads").change(upload);
$("#btnDownload").click(download);
$("#btnUpload").click(function(e) {
e.preventDefault();
$("#uploads").trigger('click');
});
var isBusy = true;
updateButtonStates();
$.get(api+'list', function(data) { //?id=00003
if (data.status=='success') {
var list = data.data.list;
// list.reverse();
isBusy = true;
updateButtonStates();
updateStatusMessage('loading '+list.length+' sketches...');
loadSketch(list, function() {
console.log('done');
isBusy = false;
updateFreeSpace();
updateButtonStates();
});
} else {
console.log('failure',data)
}
}).fail(function(status) {
alert("Error ("+status.status+") connecting to "+api+'list');
console.log(status);
});
function onLogoClick() {
location.href='/'+location.search;
}
function loadSketch(list,cb) {
var id = list.pop();
$.get(api+'?id='+id, function(data) {
if (data.status=='success') {
addItem(id,data.data.data);
}
updateStatusMessage('loading '+list.length+' sketches...');
if (list.length>0) {
loadSketch(list,function() {
cb();
})
} else {
cb();
}
});
}
function addItem(id,svgData,doPrepend) {
var path;
if (!svgData) path = "";
else if (typeof(svgData)!='string') path = "";
else if (svgData.indexOf("CDATA")==-1) path = "";
else path = svgData.split('d="')[1].split('"')[0];
var item = $('<div class="item" data="'+id+'" title="'+id+'">');
var svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 640 540"><path fill="none" stroke="black" stroke-width="2" d="'+path+'"></path></svg>';
item.click(function() {
$(this).toggleClass('selected');
console.log($(this).attr("data"));
updateButtonStates();
})
item.append(svg);
if (doPrepend) $('#svgContainer').prepend(item);
else $('#svgContainer').append(item);
item.hide().fadeIn();
updateButtonStates();
}
function deleteSketches(list,cb) {
var id = list.pop();
$.post(api+'delete', {id:id}, function(data) {
$('.item[data='+id+']').fadeOut('slow',function() {
$(this).remove(); //remove when effect is finished
});
updateStatusMessage("Deleting " + list.length + ' sketches...');
if (list.length>0) {
deleteSketches(list,cb);
} else {
cb();
}
});
}
function deleteSelectedSketches() {
if (confirm('Do you want to delete '+$('.item.selected').length+' drawings?')) {
var ids = [];
$('.item.selected').map(function(){
ids.push($(this).attr('data'));
});
isBusy = true;
updateButtonStates();
deleteSketches(ids,function() {
console.log('done deleting sketches');
isBusy = false;
updateButtonStates();
updateFreeSpace();
});
deselectAll();
updateButtonStates();
}
}
function selectAll() {
$('.item').addClass('selected');
updateButtonStates();
}
function deselectAll() {
$('.item').removeClass('selected');
updateButtonStates();
}
function updateButtonStates() {
var numItems = $('.item').length;
var numSelected = $('.item.selected').length;
var noSelection = numSelected==0;
$("#btnDelete").attr("disabled",isBusy || noSelection);
$("#btnDownload").attr("disabled",isBusy || noSelection);
$("#btnDeselectAll").attr("disabled",isBusy || noSelection);
$("#btnSelectAll").attr("disabled",isBusy || numItems==0);
$("#btnUpload").attr("disabled",isBusy || !noSelection);
$("#btnDelete").text("Delete" + (noSelection ? "" : " ("+numSelected+")"));
$("#btnDownload").text("Download" + (noSelection ? "" : " ("+numSelected+")"));
}
function uploadFile(files, index, next) {
var reader = new FileReader();
reader.readAsText(files[index], "UTF-8");
reader.onload = function (evt) {
console.log("onload",index); //,files[index],evt.target);
//process file
var svg = convertSvg(evt.target.result);
$.post(api, {data:svg}, function(data) {
if (data.status=='success') {
var id = data.data.id;
addItem(id,svg,true);
updateStatusMessage('uploading '+(files.length-index)+' sketches...');
if (index<files.length-1) {
uploadFile(files, index+1, next);
} else {
next(); //no more files, call back
}
}
});
}
reader.onerror = function (evt) {
console.log("onerror");
next(); //stop processing file(s), call back/
}
}
function upload() {
var files = $("#uploads")[0].files
var reader = new FileReader();
var cur = 0;
isBusy = true;
updateButtonStates();
updateStatusMessage("Uploading " + files.length + " files");
uploadFile(files, cur, function() {
console.log("done");
isBusy = false;
updateButtonStates();
updateFreeSpace();
$("#frmUpload")[0].reset();
})
}
function updateFreeSpace() {
$.get(api+'status', function(data) { //?id=00003
if (data.status=='success') {
var numSketches = data.data.number_of_sketches;
var freeKb = Math.round(data.data.available/1024);
updateStatusMessage(numSketches+" sketches, "+freeKb+"k bytes free");
}
});
}
function updateStatusMessage(msg) {
$("#txtInfo").text(msg);
}
function convertSvg(svg) {
if (!svg) return "";
if (typeof(svg)!='string') return "";
if (svg.indexOf("CDATA")>-1) return svg; //assume this SVG is already ok
//this fixes SVG's created by the kunstcentraal app
var re = /([a-zA-Z])\s?([0-9]{1,}) ([0-9]{1,})/g;
svg = svg.replace(re,"$1$2,$3");
re = /<\/svg>/g;
svg = svg.replace(re,"<!--<![CDATA[d3d-keys {\"height\":5,\"outlineShape\":\"none\",\"twist\":0}]]>-->\n</svg>");
svg = svg.replace("M0,0 ",""); //RC: hack
return svg;
}
function download() {
$('.item.selected').each(function() {
var id = $(this).attr('data');
var svgData = $(this).html();
console.log('downloading',id);
$('<a target="_blank" href="data:image/svg+xml,'+encodeURIComponent(svgData)+'" download="'+id+'.svg">')[0].click();
});
}

View File

@ -22,7 +22,7 @@
</li> </li>
<li data-id="btnsPrevNext" data-button="Next" data-options="tipLocation:right;tipAdjustmentY:-25"> <li data-id="btnsPrevNext" data-button="Next" data-options="tipLocation:right;tipAdjustmentY:-25">
<h2>View saved doodles</h2> <h2>View saved doodles</h2>
<p>Use the buttons '<' and '>' to flip through all the saved doodles on your Wi-Fi box.</p> <p>Use the buttons '&lt;' and '&gt;' to flip through all the saved doodles on your Wi-Fi box.</p>
</li> </li>
<li data-id="btnOops" data-button="Next" data-options="tipLocation:right"> <li data-id="btnOops" data-button="Next" data-options="tipLocation:right">
<h2>Oops</h2> <h2>Oops</h2>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -40,6 +40,7 @@
<div id="buttonGroupAdd" class="buttonGroup"> <div id="buttonGroupAdd" class="buttonGroup">
<img id="btnWordArt" class="btn" src="img/buttons/btnWordArt.png" /> <img id="btnWordArt" class="btn" src="img/buttons/btnWordArt.png" />
<img id="btnShape" class="btn" src="img/buttons/btnShape.png" /> <img id="btnShape" class="btn" src="img/buttons/btnShape.png" />
<img id="btnScan" class="btn" src="img/buttons/btnGuide.png" />
</div> </div>
</div> </div>
@ -75,10 +76,12 @@
</div> </div>
<div id="drawareacontainer"> <div id="drawareacontainer">
<div id="canvasContainers"> <div id="canvasContainers">
<div id="mycanvasContainer"> <div id="mycanvasContainer">
<img id="imgGuide">
<canvas id="mycanvas"></canvas> <canvas id="mycanvas"></canvas>
<img id="btnCloseScan" class="btn" src="img/buttons/btnClose.png" />
</div> </div>
<div id="previewContainer"> <div id="previewContainer">
@ -125,6 +128,15 @@
<img id="btnWordArtOk" class="btn" src="img/buttons/btnOk.png"> <img id="btnWordArtOk" class="btn" src="img/buttons/btnOk.png">
</div> </div>
</div> </div>
<div class="popup" id="popupScan">
<div class="content">
<h1>Use photo as a guide</h1>
<input id="fileScan" type="file"/>
<!-- <input id="txtDummy" type="text"/> -->
<img id="btnScanOk" class="btn" src="img/buttons/btnOk.png">
</div>
</div>
<div class="popup" id="popupShape"> <div class="popup" id="popupShape">
<div class="content"> <div class="content">

View File

@ -1,50 +1,29 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Doodle3D 404</title> <title>Success</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="icon" type="image/ico" href="favicon_alt.ico"/> <meta name="mobile-web-app-capable" content="yes" />
<link href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png" rel="apple-touch-icon-precomposed" sizes="144x144" /> <meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,minimal-ui">
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="icon" type="image/ico" href="./favicon_alt.ico"/>
<link rel="apple-touch-icon-precomposed" href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png"/>
<link rel="apple-touch-icon-precomposed" href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png" sizes="144x144" />
<link href="css/styles.min.css" rel="stylesheet" media="screen"> <link href="css/styles.min.css" rel="stylesheet" media="screen">
<link href="css/debug.min.css" rel="stylesheet" media="screen"> <link href="css/debug.min.css" rel="stylesheet" media="screen">
</head> </head>
<body id="page404"> <body id="page404">
Success
<div id="landscape" class="clearfix"> <script src="js/libs/jquery-1-9-1.min.js"></script>
<script>
<!-- background images --> $(document.body).load("404.html");
<div class="bgContainer"> document.title = "Doodle3D 404"
<img class="bgTop" src="img/bg_top.png" /> </script>
<img class="bgMiddle" src="img/bg_middle.png" />
<img class="bgBottom" src="img/bg_bottom.png" />
</div>
<!-- center panel -->
<div class="centerpanel">
<div class="logopanel">
<div class="d3dlogo" onclick="location.reload()"></div>
</div>
</div>
<div id="message404">
<p>
You're probably trying to go to a website on the internet, but you're currently only connected to the Doodle3D WiFi box, which means you're not connected to the internet.<br/>
You could:
<ul>
<li>Reconnect to the WiFi you normally use.</li>
<li>Configure the WiFi box to connect to that WiFi in client mode. You can do this trough the settings screen.</li>
</ul>
</p>
</div>
</div>
<div id="portrait">
<img class="vertImage" src="img/bg_vertical.png"/>
</div>
</body> </body>
</html> </html>

View File

@ -60,6 +60,7 @@
<label for="printerDimensionsZ"></label> <label for="printerDimensionsZ"></label>
z:<input id="printerDimensionsZ" type="number" class="small" name="printer.dimensions.z" placeholder="z">mm<br> z:<input id="printerDimensionsZ" type="number" class="small" name="printer.dimensions.z" placeholder="z">mm<br>
<label for="heatedBed">Heated bed:</label><input id="heatedBed" type="checkbox" name="printer.heatedbed" value="heatedbed"><br> <label for="heatedBed">Heated bed:</label><input id="heatedBed" type="checkbox" name="printer.heatedbed" value="heatedbed"><br>
<label for="filamentThickness">Filament thickness:</label><input id="filamentThickness" step="0.01" type="number" class="small" name="printer.filamentThickness">mm<br>
<fieldset id="gcodePanel"> <fieldset id="gcodePanel">
<legend>GCODE settings</legend> <legend>GCODE settings</legend>
<div> <div>
@ -91,7 +92,6 @@
<legend>Print settings</legend> <legend>Print settings</legend>
<label for="layerHeight">Layer height:</label><input id="layerHeight" type="number" step="0.01" class="small" name="printer.layerHeight">mm<br> <label for="layerHeight">Layer height:</label><input id="layerHeight" type="number" step="0.01" class="small" name="printer.layerHeight">mm<br>
<label for="wallThickness">Wall thickness:</label><input id="wallThickness" type="number" step="0.1" class="small" name="printer.wallThickness">mm<br> <label for="wallThickness">Wall thickness:</label><input id="wallThickness" type="number" step="0.1" class="small" name="printer.wallThickness">mm<br>
<label for="filamentThickness">Filament thickness:</label><input id="filamentThickness" step="0.01" type="number" class="small" name="printer.filamentThickness">mm<br>
<label for="temperature">Temperature:</label><input id="temperature" type="number" class="small" name="printer.temperature">degrees C<br> <label for="temperature">Temperature:</label><input id="temperature" type="number" class="small" name="printer.temperature">degrees C<br>
<label for="bedTemperature">Bed temperature:</label><input id="bedTemperature" type="number" class="small" name="printer.bed.temperature">degrees C<br> <label for="bedTemperature">Bed temperature:</label><input id="bedTemperature" type="number" class="small" name="printer.bed.temperature">degrees C<br>
<br> <br>
@ -99,6 +99,7 @@
<label for="bottomLayerSpeed">Bottom layer speed:</label><input id="bottomLayerSpeed" type="number" name="printer.bottomLayerSpeed" class="small">mm/s<br> <label for="bottomLayerSpeed">Bottom layer speed:</label><input id="bottomLayerSpeed" type="number" name="printer.bottomLayerSpeed" class="small">mm/s<br>
<label for="travelSpeed">Travel speed:</label><input id="travelSpeed" type="number" name="printer.travelSpeed" class="small">mm/s<br> <label for="travelSpeed">Travel speed:</label><input id="travelSpeed" type="number" name="printer.travelSpeed" class="small">mm/s<br>
<label for="enableTraveling">Enable traveling:</label><input id="enableTraveling" type="checkbox" name="printer.enableTraveling" value="enableTraveling"><br> <label for="enableTraveling">Enable traveling:</label><input id="enableTraveling" type="checkbox" name="printer.enableTraveling" value="enableTraveling"><br>
<label for="bottomEnableTraveling">Bottom layers traveling:</label><input id="bottomEnableTraveling" type="checkbox" name="printer.bottomEnableTraveling" value="bottomEnableTraveling"><br>
<label for="firstLayerSlow">Bottom layers slow:</label><input id="firstLayerSlow" type="checkbox" name="printer.firstLayerSlow" value="firstLayerSlow"><br> <label for="firstLayerSlow">Bottom layers slow:</label><input id="firstLayerSlow" type="checkbox" name="printer.firstLayerSlow" value="firstLayerSlow"><br>
<label for="bottomFlowRate">Bottom layers flow rate*:</label><input id="bottomFlowRate" type="number" name="printer.bottomFlowRate" class="small"><br> <label for="bottomFlowRate">Bottom layers flow rate*:</label><input id="bottomFlowRate" type="number" name="printer.bottomFlowRate" class="small"><br>
<small>* Multiplier for extrusion rate in first few layers</small> <small>* Multiplier for extrusion rate in first few layers</small>
@ -173,14 +174,36 @@
<small id="updateInfo"></small> <small id="updateInfo"></small>
</fieldset> </fieldset>
<fieldset id="debugPanel"> <fieldset id="extraPanel">
<legend>Debug</legend> <legend>Sketches</legend>
<input type="button" onclick="settingsWindow.downloadlogs()" name="downloadlogs" value="Download logs" class="button" id="downloadlogs"/> <input type="button" onclick="settingsWindow.openFileManager()" name="btnFileMgr" value="Open FileManager" class="button" id="btnFileMgr"/>
<input type="button" onclick="settingsWindow.downloadGcode()" name="downloadGcode" value="Download GCODE" class="button" id="downloadGcode"/> <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"/> <input type="button" onclick="settingsWindow.downloadSvg()" name="downloadSvg" value="Download SVG" class="button" id="downloadSvg"/>
</fieldset> </fieldset>
<fieldset id="restorePanel"> <fieldset id="debugPanel">
<legend>Debug</legend>
<label for="logLevel">Log level:</label>
<select id="logLevel" name="system.log.level" onchange="settingsWindow.logLevelChanged()">
<option value="" disabled="disabled" selected="selected">Please choose a log level</option>
<option value="quiet">Quiet</option>
<option value="error">Error</option>
<option value="warning">Warning</option>
<option value="info">Info</option>
<option value="verbose">Verbose</option>
<option value="bulk">Bulk</option>
</select><br/>
<div id="logging-restart-warning" class="warn-box">
Restart the wifibox for the new log level to take effect.
</div>
<div id="logging-verbose-warning" class="warn-box">
<em>Be careful</em>: when setting a log level higher than info, the Wifibox may quickly run out of memory, causing crashes and other unwanted behaviour.
</div>
<br/>
<input type="button" onclick="settingsWindow.downloadlogs()" name="downloadlogs" value="Download logs" class="button" id="downloadlogs"/>
</fieldset>
<fieldset id="restorePanel">
<legend>Restore</legend> <legend>Restore</legend>
<input type="button" name="restoresettings" value="Restore settings to defaults" class="button" id="restoreSettings"/> <input type="button" name="restoresettings" value="Restore settings to defaults" class="button" id="restoreSettings"/>
<span id="restoreState"></span> <span id="restoreState"></span>