2014-12-17 09:45:40 +01:00
/ *
* 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/' ;
2014-12-09 21:13:39 +01:00
2014-12-17 10:02:46 +01:00
$ ( "#logo" ) . click ( onLogoClick )
2014-12-10 15:21:17 +01:00
$ ( "#btnDelete" ) . click ( deleteSelectedSketches ) ;
$ ( "#btnSelectAll" ) . click ( selectAll ) ;
$ ( "#btnDeselectAll" ) . click ( deselectAll ) ;
$ ( "#uploads" ) . change ( upload ) ;
$ ( "#btnDownload" ) . click ( download ) ;
2017-05-23 23:08:26 +02:00
$ ( "#btnPancake" ) . click ( pancake ) ;
2014-12-10 15:21:17 +01:00
2014-12-17 09:45:40 +01:00
$ ( "#btnUpload" ) . click ( function ( e ) {
e . preventDefault ( ) ;
2014-12-10 15:21:17 +01:00
$ ( "#uploads" ) . trigger ( 'click' ) ;
} ) ;
var isBusy = true ;
updateButtonStates ( ) ;
2014-12-09 21:13:39 +01:00
$ . get ( api + 'list' , function ( data ) { //?id=00003
2014-12-17 09:45:40 +01:00
2014-12-09 21:13:39 +01:00
if ( data . status == 'success' ) {
var list = data . data . list ;
2014-12-10 15:21:17 +01:00
// list.reverse();
isBusy = true ;
updateButtonStates ( ) ;
updateStatusMessage ( 'loading ' + list . length + ' sketches...' ) ;
2014-12-09 21:13:39 +01:00
loadSketch ( list , function ( ) {
console . log ( 'done' ) ;
2014-12-10 15:21:17 +01:00
isBusy = false ;
updateFreeSpace ( ) ;
updateButtonStates ( ) ;
2014-12-09 21:13:39 +01:00
} ) ;
2014-12-10 15:21:17 +01:00
} else {
console . log ( 'failure' , data )
}
2014-12-09 21:13:39 +01:00
2014-12-17 09:45:40 +01:00
} ) . fail ( function ( status ) {
alert ( "Error (" + status . status + ") connecting to " + api + 'list' ) ;
console . log ( status ) ;
2014-12-09 21:13:39 +01:00
} ) ;
2014-12-17 10:02:46 +01:00
function onLogoClick ( ) {
2014-12-19 21:13:22 +01:00
location . href = '/' + location . search ;
2014-12-17 10:02:46 +01:00
}
2014-12-09 21:13:39 +01:00
function loadSketch ( list , cb ) {
2014-12-10 15:21:17 +01:00
var id = list . pop ( ) ;
$ . get ( api + '?id=' + id , function ( data ) {
2014-12-09 21:13:39 +01:00
2014-12-10 15:21:17 +01:00
if ( data . status == 'success' ) {
addItem ( id , data . data . data ) ;
}
2014-12-09 21:13:39 +01:00
2014-12-10 15:21:17 +01:00
updateStatusMessage ( 'loading ' + list . length + ' sketches...' ) ;
2014-12-09 21:13:39 +01:00
2014-12-10 15:21:17 +01:00
if ( list . length > 0 ) {
loadSketch ( list , function ( ) {
cb ( ) ;
} )
} else {
cb ( ) ;
}
} ) ;
2014-12-09 21:13:39 +01:00
}
2014-12-10 15:21:17 +01:00
function addItem ( id , svgData , doPrepend ) {
var path ;
2017-05-23 23:08:26 +02:00
// console.log($getBoundingClientRect().width);
2014-12-10 15:21:17 +01:00
if ( ! svgData ) path = "" ;
else if ( typeof ( svgData ) != 'string' ) path = "" ;
else if ( svgData . indexOf ( "CDATA" ) == - 1 ) path = "" ;
else path = svgData . split ( 'd="' ) [ 1 ] . split ( '"' ) [ 0 ] ;
2017-05-23 23:08:26 +02:00
svgWidth = svgData . split ( "width=\"" ) [ 1 ] . split ( "\"" ) [ 0 ] ;
2014-12-17 09:45:40 +01:00
var item = $ ( '<div class="item" data="' + id + '" title="' + id + '">' ) ;
2017-05-23 23:08:26 +02:00
item . attr ( "data-width" , svgWidth ) ;
2014-12-10 15:21:17 +01:00
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>' ;
2014-12-09 21:13:39 +01:00
item . click ( function ( ) {
$ ( this ) . toggleClass ( 'selected' ) ;
2014-12-10 15:21:17 +01:00
console . log ( $ ( this ) . attr ( "data" ) ) ;
updateButtonStates ( ) ;
2014-12-09 21:13:39 +01:00
} )
item . append ( svg ) ;
2014-12-10 15:21:17 +01:00
if ( doPrepend ) $ ( '#svgContainer' ) . prepend ( item ) ;
else $ ( '#svgContainer' ) . append ( item ) ;
item . hide ( ) . fadeIn ( ) ;
2014-12-09 21:13:39 +01:00
2014-12-10 15:21:17 +01:00
updateButtonStates ( ) ;
2014-12-09 21:13:39 +01:00
}
2014-12-10 15:21:17 +01:00
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 ( ) ;
}
} ) ;
}
2014-12-09 21:13:39 +01:00
function deleteSelectedSketches ( ) {
if ( confirm ( 'Do you want to delete ' + $ ( '.item.selected' ) . length + ' drawings?' ) ) {
2014-12-10 15:21:17 +01:00
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 ( ) ;
}
2014-12-09 21:13:39 +01:00
}
function selectAll ( ) {
$ ( '.item' ) . addClass ( 'selected' ) ;
2014-12-10 15:21:17 +01:00
updateButtonStates ( ) ;
2014-12-09 21:13:39 +01:00
}
function deselectAll ( ) {
$ ( '.item' ) . removeClass ( 'selected' ) ;
2014-12-10 15:21:17 +01:00
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 + ")" ) ) ;
2014-12-09 21:13:39 +01:00
}
2014-12-10 15:21:17 +01:00
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 ;
2014-12-17 09:45:40 +01:00
svg = svg . replace ( re , "<!--<![CDATA[d3d-keys {\"height\":5,\"outlineShape\":\"none\",\"twist\":0}]]>-->\n</svg>" ) ;
svg = svg . replace ( "M0,0 " , "" ) ; //RC: hack
return svg ;
2014-12-10 15:21:17 +01:00
}
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 ( ) ;
} ) ;
}
2014-12-09 21:13:39 +01:00
2017-05-23 23:08:26 +02:00
function pointsToGCode ( points ) {
var gcode = "" ;
var wasMove = false ;
for ( var i = 0 ; i < points . length ; i ++ ) {
var x = points [ i ] [ 0 ] ;
var y = points [ i ] [ 1 ] ;
var isMove = points [ i ] [ 2 ] ;
if ( ! wasMove && isMove ) gcode += "M107 ; pump off\n" ;
if ( wasMove && ! isMove ) gcode += "M106 ; pump on\nG4 P450\n" ;
gcode += "G0 X" + x + " Y" + y + "\n" ;
wasMove = isMove ;
}
return gcode ;
}
//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 _points = [ ] ;
var mode = '' , x = 0 , y = 0 ;
console . log ( "loading " + svgData . length + " bytes of data..." ) ;
// clearDoodle();
svgData = svgData . replace ( "M0,0 " , "" ) ; //RC: hack
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' || 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 ;
// var firstComma = svgData.indexOf(',', p);
// var firstSpace = 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 ; }
len = numberEnd - p ;
tx = parseFloat ( 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 = parseFloat ( 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, -1);
// else draw(x, y);
}
p ++ ;
}
return true ;
} ;
parseCommand ( ) ; //depends on value of p, so don't move this without taking that into consideration
return _points ;
}
getMinX = function ( p ) {
var minX = 9999 ;
for ( var i = 0 ; i < p . length ; i ++ ) {
minX = Math . min ( minX , p [ i ] [ 0 ] ) ;
}
return minX ;
}
getMaxX = function ( p ) {
var maxX = - 9999 ;
for ( var i = 0 ; i < p . length ; i ++ ) {
maxX = Math . max ( maxX , p [ i ] [ 0 ] ) ;
}
return maxX ;
}
getMinY = function ( p ) {
var minY = 9999 ;
for ( var i = 0 ; i < p . length ; i ++ ) {
minY = Math . min ( minY , p [ i ] [ 1 ] ) ;
}
return minY ;
}
getMaxY = function ( p ) {
var maxY = - 9999 ;
for ( var i = 0 ; i < p . length ; i ++ ) {
maxY = Math . max ( maxY , p [ i ] [ 1 ] ) ;
}
return maxY ;
}
alignLeft = function ( p ) {
var minX = getMinX ( p ) ;
//apply
for ( var i = 0 ; i < p . length ; i ++ ) {
p [ i ] [ 0 ] -= minX ;
}
}
alignTop = function ( p ) {
var minY = getMinY ( p ) ;
//apply
for ( var i = 0 ; i < p . length ; i ++ ) {
p [ i ] [ 1 ] -= minY ;
}
}
getWidth = function ( p ) {
return getMaxX ( p ) - getMinX ( p ) ;
}
pointsTranslate = function ( p , x , y ) {
for ( var i = 0 ; i < p . length ; i ++ ) {
p [ i ] [ 0 ] += x ;
p [ i ] [ 1 ] += y ;
}
}
pointsScale = function ( p , sx , sy ) {
for ( var i = 0 ; i < p . length ; i ++ ) {
p [ i ] [ 0 ] *= sx ;
p [ i ] [ 1 ] *= sy ;
}
}
function pancake ( ) {
var startGcode = "W1 X42 Y210 L485 T0 ;Define Workspace of this file\nG21 ;Set units to MM\nG1 F5600 ;Set Speed\nM107 ;Pump off\nG4 P1000 ;Pause for 1000 milliseconds\nM84 ;Motors off\nG28 X0 Y0 ;Home All Axis\n" ;
var endGcode = "G4 P1000\nG28 X0 Y0\nM84" ;
var allGcode = startGcode ;
var offsetX = 0 ;
$ ( '.item.selected' ) . each ( function ( ) {
var id = $ ( this ) . attr ( 'data' ) ;
var svgData = $ ( this ) . html ( ) ;
var points = loadFromSvg ( svgData ) ;
pointsScale ( points , . 2 , - . 2 ) ;
alignLeft ( points ) ;
alignTop ( points ) ;
pointsTranslate ( points , offsetX , 0 ) ;
offsetX += getWidth ( points ) ;
var gcode = pointsToGCode ( points ) ;
allGcode += gcode ;
} ) ;
allGcode += endGcode ;
$ ( '<a target="_blank" href="data:application/x-gcode,' + encodeURIComponent ( allGcode ) + '" download="doodle.gcode">' ) [ 0 ] . click ( ) ;
}