0
0
mirror of https://github.com/Doodle3D/doodle3d-client.git synced 2024-12-22 13:13:48 +01:00

Added download GCODE feature, added keyboard shortcuts and added some basic Shapes

This commit is contained in:
Rick Companje 2013-12-05 11:14:12 +01:00
parent dd6c1d8034
commit b85d3244c9
11 changed files with 224 additions and 139 deletions

View File

@ -16,6 +16,9 @@ module.exports = function(grunt) {
},
js: {
src: [
'js_src/Shape.js',
'js_src/Svg.js',
'js_src/Keyboard.js',
'js_src/SettingsWindow.js',
'js_src/UpdatePanel.js',
'js_src/PrinterPanel.js',

30
js_src/Keyboard.js Normal file
View File

@ -0,0 +1,30 @@
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 '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 '[': previewTwistLeft(); break;
case ']': previewTwistRight(); break;
case '\'': resetTwist(); break;
default: console.log("Key: '" + ch + "' (" + event.which + ")");
}
})
}

View File

@ -159,6 +159,7 @@ function SettingsWindow() {
}
this.showSettings = function() {
keyboardShortcutsEnabled = false;
this.loadSettings(function() { // reload settings
$("#contentOverlay").fadeIn(375, function() {
document.body.removeEventListener('touchmove',prevent,false);
@ -166,6 +167,7 @@ function SettingsWindow() {
});
}
this.hideSettings = function(complete) {
keyboardShortcutsEnabled = true;
$("#contentOverlay").fadeOut(375, function() {
document.body.addEventListener('touchmove',prevent,false);
// self.window.css("display","none");
@ -365,6 +367,14 @@ function SettingsWindow() {
this.downloadlogs = function() {
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");
}
}
/*
* Networks ui

34
js_src/Shape.js Normal file
View 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
View 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;
}

View File

@ -246,10 +246,10 @@ function print(e) {
console.log("sendPrintCommands is false: not sending print command to 3dprinter");
}
if (debugMode) {
$("#textdump").text("");
$("#textdump").text(gcode.join("\n"));
}
// if (debugMode) {
// $("#textdump").text("");
// $("#textdump").text(gcode.join("\n"));
// }
}, gcodeGenerateDelay);
} else {
@ -336,7 +336,11 @@ function previewTwistRight(redrawLess) {
setSketchModified(true);
}
function resetTwist() {
rStep = 0;
redrawRenderedPreview();
setSketchModified(true);
}
function update() {
setState(printer.state,printer.hasControl);

View File

@ -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;
}

View File

@ -25,8 +25,6 @@ var clientInfo = {};
$(function() {
console.log("ready");
//TODO give this a more logical place in code
if (getURLParameter("d") != "null") debugMode = (getURLParameter("d") == "1");
if (getURLParameter("p") != "null") sendPrintCommands = (getURLParameter("p") == "1");
if (getURLParameter("c") != "null") communicateWithWifibox = (getURLParameter("c") == "1");
@ -59,6 +57,7 @@ $(function() {
initLayouting();
initSidebars();
initButtonBehavior();
initKeyboard();
initVerticalShapes();
if (!clientInfo.isSmartphone) initHelp();

View File

@ -7,7 +7,7 @@ var preview_tmp;
var previewCtx_tmp;
var previewDefaults = {
rotation: Math.PI/90,
rotation: 0, //Math.PI/90,
numLayers: 10
}

View File

@ -102,7 +102,8 @@
</div>
</div>
<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 id="debug_display">
</div>
@ -135,6 +136,7 @@
<!--<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-coolfieldset.min.js"></script>
<script src="js/libs/FileSaver.js"></script>
<!--<script src="js/doodle3d-client.js"></script>-->
<script src="js/doodle3d-client.min.js"></script>

View File

@ -160,6 +160,7 @@
<fieldset id="debugPanel">
<legend>Debug</legend>
<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"/>
</fieldset>
<fieldset id="restorePanel">
<legend>Restore</legend>