mirror of
https://github.com/Doodle3D/doodle3d-client.git
synced 2024-12-22 13:13:48 +01:00
added working prev/next/save functionality
This commit is contained in:
parent
8745e037a4
commit
0b5cf1a5f4
@ -32,7 +32,8 @@ module.exports = function(grunt) {
|
||||
'js_src/utils.js',
|
||||
'js_src/sidebar.js',
|
||||
'js_src/Message.js',
|
||||
'js_src/main.js'
|
||||
'js_src/main.js',
|
||||
'js_src/sketches.js'
|
||||
],
|
||||
dest: 'www/js/<%= pkg.name %>.js'
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ function initButtonBehavior() {
|
||||
btnNew.on('touchstart mousedown', clearDoodle);
|
||||
btnPrint.on('touchstart mousedown', print);
|
||||
|
||||
getSavedSketchStatus();
|
||||
setSketchModified(false);
|
||||
//updatePrevNextButtonStateOnClear();
|
||||
|
||||
// btnClear.click(function(e) {
|
||||
// e.preventDefault();
|
||||
// // console.log("clear");
|
||||
@ -191,13 +195,13 @@ function stopPrint() {
|
||||
}
|
||||
|
||||
|
||||
function prevDoodle(e) {
|
||||
console.log("f:prevDoodle()");
|
||||
console.log("f:prevDoodle()");
|
||||
}
|
||||
function nextDoodle(e) {
|
||||
console.log("f:nextDoodle()");
|
||||
}
|
||||
// function prevDoodle(e) {
|
||||
// console.log("f:prevDoodle()");
|
||||
// console.log("f:prevDoodle()");
|
||||
// }
|
||||
// function nextDoodle(e) {
|
||||
// console.log("f:nextDoodle()");
|
||||
// }
|
||||
|
||||
function print(e) {
|
||||
console.log("f:print() >> sendPrintCommands = " + sendPrintCommands);
|
||||
@ -285,6 +289,8 @@ function previewUp(redrawLess) {
|
||||
if (numLayers < maxNumLayers) {
|
||||
numLayers++;
|
||||
}
|
||||
setSketchModified(true);
|
||||
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
@ -293,6 +299,7 @@ function previewDown(redrawLess) {
|
||||
if (numLayers > minNumLayers) {
|
||||
numLayers--;
|
||||
}
|
||||
setSketchModified(true);
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
@ -302,12 +309,14 @@ function previewTwistLeft(redrawLess) {
|
||||
if (rStep > -previewRotationLimit) rStep -= twistIncrement;
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
setSketchModified(true);
|
||||
}
|
||||
function previewTwistRight(redrawLess) {
|
||||
// console.log("f:previewTwistRight()");
|
||||
if (rStep < previewRotationLimit) rStep += twistIncrement;
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
setSketchModified(true);
|
||||
}
|
||||
|
||||
|
||||
@ -390,20 +399,14 @@ function setState(newState,newHasControl) {
|
||||
|
||||
/* save, next and prev buttons */
|
||||
switch(newState) {
|
||||
/*case Printer.WIFIBOX_DISCONNECTED_STATE:
|
||||
case Printer.WIFIBOX_DISCONNECTED_STATE:
|
||||
disableButton(btnPrevious);
|
||||
disableButton(btnNext);
|
||||
disableButton(btnSave);
|
||||
break;
|
||||
default:
|
||||
enableButton(btnPrevious, null);
|
||||
enableButton(btnNext, null);
|
||||
enableButton(btnSave, null);
|
||||
break;*/
|
||||
default:
|
||||
disableButton(btnPrevious);
|
||||
disableButton(btnNext);
|
||||
disableButton(btnSave);
|
||||
updatePrevNextButtonState();
|
||||
if (isModified) enableButton(btnSave, saveSketch);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ var movementCounter = 0;
|
||||
var drawVariableLineWeight = false; // set to true to have the momentum of the mouse/touch movement result in larger/smaller strokes
|
||||
var lineweight = 2;
|
||||
|
||||
var isModified = false;
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* INIT
|
||||
@ -146,6 +148,8 @@ function draw(_x, _y, _width) {
|
||||
function clearDoodle() {
|
||||
console.log("f:clearDoodle");
|
||||
|
||||
updatePrevNextButtonStateOnClear();
|
||||
|
||||
_points = [];
|
||||
|
||||
prevX = 0;
|
||||
@ -162,6 +166,8 @@ function clearDoodle() {
|
||||
clearMainView();
|
||||
resetPreview();
|
||||
resetVerticalShapes();
|
||||
|
||||
setSketchModified(false);
|
||||
}
|
||||
|
||||
function redrawDoodle(recalcBoundsAndTransforms) {
|
||||
@ -258,6 +264,8 @@ function adjustPreviewTransformation() {
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function onCanvasMouseDown(e) {
|
||||
setSketchModified(true);
|
||||
|
||||
// console.log("f:onCanvasMouseDown()");
|
||||
// console.log("onCanvasMouseDown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY);
|
||||
// console.log("onCanvasMouseDown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY);
|
||||
@ -285,8 +293,12 @@ function onCanvasMouseDown(e) {
|
||||
|
||||
var prevPoint = {x:-1, y:-1};
|
||||
function onCanvasMouseMove(e) {
|
||||
|
||||
// console.log("f:onCanvasMouseMove()");
|
||||
if (!dragging) return;
|
||||
|
||||
setSketchModified(true);
|
||||
|
||||
// console.log("onmousemove");
|
||||
|
||||
var x, y;
|
||||
@ -360,6 +372,8 @@ function onCanvasMouseUp(e) {
|
||||
}
|
||||
|
||||
function onCanvasTouchDown(e) {
|
||||
setSketchModified(true);
|
||||
|
||||
e.preventDefault();
|
||||
console.log("f:onCanvasTouchDown >> e: " , e);
|
||||
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
||||
@ -382,6 +396,8 @@ function onCanvasTouchDown(e) {
|
||||
}
|
||||
|
||||
function onCanvasTouchMove(e) {
|
||||
setSketchModified(true);
|
||||
|
||||
e.preventDefault();
|
||||
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
||||
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
||||
@ -458,4 +474,139 @@ function onCanvasTouchEnd(e) {
|
||||
|
||||
function prevent(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
|
156
js_src/sketches.js
Normal file
156
js_src/sketches.js
Normal file
@ -0,0 +1,156 @@
|
||||
var currentSketchId = 0;
|
||||
var numSavedSketches = 0;
|
||||
|
||||
function getSavedSketchStatus() {
|
||||
$.ajax({
|
||||
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: ", response);
|
||||
});
|
||||
}
|
||||
|
||||
function setSketchModified(_isModified, doNotClearCurrent) {
|
||||
isModified = _isModified;
|
||||
|
||||
// alert("isModified: " + isModified);
|
||||
//console.log("setModified: " + isModified + (typeof(doNotClearCurrent) !== 'undefined' ? " (doNotClearCurrent: "+doNotClearCurrent+")" : "")); //TEMP
|
||||
|
||||
if (isModified) enableButton(btnSave, saveSketch);
|
||||
else disableButton(btnSave);
|
||||
|
||||
//if (typeof(doNotClearCurrent) !== 'undefined' && !doNotClearCurrent) setCurrentSketchId(-1);
|
||||
|
||||
|
||||
//sketchModified = isModified; /// ERROR?
|
||||
}
|
||||
|
||||
function setCurrentSketchId(sId) {
|
||||
console.log("setCurrentSketchId: " + sId + " / " + numSavedSketches);
|
||||
// var enablePrev = false;
|
||||
// var enableNext = false;
|
||||
|
||||
currentSketchId = sId;
|
||||
|
||||
//clamp
|
||||
if (currentSketchId > numSavedSketches) currentSketchId = numSavedSketches;
|
||||
if (currentSketchId < 1) currentSketchId = 1;
|
||||
|
||||
//update textbox
|
||||
//$("#txtSketch").val(currentSketchId);
|
||||
|
||||
updatePrevNextButtonState();
|
||||
}
|
||||
|
||||
function updatePrevNextButtonStateOnClear() {
|
||||
enableButton(btnPrevious, prevDoodle);
|
||||
disableButton(btnNext);
|
||||
currentSketchId = numSavedSketches+1; //after the end of the list
|
||||
disableButton(btnSave);
|
||||
}
|
||||
|
||||
function updatePrevNextButtonState() {
|
||||
|
||||
//btnPrevious state
|
||||
if (numSavedSketches==0 || currentSketchId < 2) {
|
||||
disableButton(btnPrevious);
|
||||
} else {
|
||||
enableButton(btnPrevious, prevDoodle);
|
||||
}
|
||||
|
||||
//btnNext state
|
||||
if (numSavedSketches==0 || currentSketchId >= numSavedSketches) {
|
||||
disableButton(btnNext);
|
||||
} else {
|
||||
enableButton(btnNext, nextDoodle);
|
||||
}
|
||||
}
|
||||
|
||||
function loadSketch(sketchId) {
|
||||
|
||||
$.ajax({
|
||||
url: wifiboxURL + "/sketch/" + sketchId,
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
// timeout: this.timeoutTime,
|
||||
success: function(response) {
|
||||
if (response.status == 'error' || response.status == 'fail') {
|
||||
console.log("loadSketch fail/error: " + response.msg + " -- ", response);
|
||||
} else {
|
||||
console.log("loadSketch success: loaded id #" + response.data.id, response);
|
||||
//console.log("sketch content:\n" + response.data.data);
|
||||
if (loadFromSvg(response.data.data)) {
|
||||
setSketchModified(false, true);
|
||||
setCurrentSketchId(response.data.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("loadSketch failed: ", response);
|
||||
});
|
||||
}
|
||||
|
||||
//btnSave.mouseup(saveSketch);
|
||||
function saveSketch() {
|
||||
svg = saveToSvg();
|
||||
console.log("generated SVG [" + _points.length + " points, " + svg.length + " bytes]:\n" + svg);
|
||||
|
||||
$.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);
|
||||
//}
|
||||
}
|
@ -31,9 +31,10 @@
|
||||
<div class="leftpanel shadowright">
|
||||
<div class='sidebutton shadowright'></div>
|
||||
<img class="btnNew btn" src="img/buttons/btnNew.png" /><br/>
|
||||
<div class="btnsPrevNext">
|
||||
<div class="btnsPrevNext" style="text-align:center">
|
||||
<img class="btnPrevious btn" src="img/buttons/btnLeft.png">
|
||||
<img class="btnNext btn" src="img/buttons/btnRight.png">
|
||||
<!-- <div id="txtSketch"></div> -->
|
||||
</div>
|
||||
<img class="btnSave btn" src="img/buttons/btnSave.png" /><br/>
|
||||
<img class="btnOops btn" src="img/buttons/btnOops.png" /><br/>
|
||||
|
Loading…
Reference in New Issue
Block a user