2013-10-22 12:04:46 +02:00
//these settings are defined in the firmware (conf_defaults.lua) and will be initialized in loadSettings()
var settings = {
"network.ap.ssid" : "d3d-ap-%%MAC_ADDR_TAIL%%" ,
"network.ap.address" : "192.168.10.1" ,
"network.ap.netmask" : "255.255.255.0" ,
"printer.temperature" : 220 ,
"printer.maxObjectHeight" : 150 ,
"printer.layerHeight" : 0.2 ,
"printer.wallThickness" : 0.7 ,
"printer.screenToMillimeterScale" : 0.3 ,
"printer.speed" : 50 ,
"printer.travelSpeed" : 200 ,
"printer.filamentThickness" : 2.85 ,
"printer.enableTraveling" : true ,
"printer.useSubLayers" : true ,
"printer.firstLayerSlow" : true ,
"printer.autoWarmUp" : true ,
"printer.simplify.iterations" : 10 ,
"printer.simplify.minNumPoints" : 15 ,
"printer.simplify.minDistance" : 3 ,
"printer.retraction.enabled" : true ,
"printer.retraction.speed" : 50 ,
"printer.retraction.minDistance" : 1 ,
"printer.retraction.amount" : 5 ,
"printer.autoWarmUpCommand" : "M104 S220 (hardcoded temperature)"
}
function SettingsWindow ( ) {
this . wifiboxURL ;
this . wifiboxCGIBinURL
this . window ;
this . form ;
this . timeoutTime = 3000 ;
this . retryDelay = 2000 ; // retry setTimout delay
this . retryRetrieveNetworkStatusDelayTime = 1000 ; // retry setTimout delay
this . retryLoadSettingsDelay ; // retry setTimout instance
this . retrySaveSettingsDelay ; // retry setTimout instance
this . retryRetrieveNetworkStatusDelay ; // retry setTimout instance
this . apFieldSet ;
this . clientFieldSet ;
this . networks ;
this . currentNetwork ; // the ssid of the network the box is on
this . selectedNetwork ; // the ssid of the selected network in the client mode settings
this . currentLocalIP = "" ;
this . clientModeState = SettingsWindow . NOT _CONNECTED ;
this . currentAP ;
this . apModeState = SettingsWindow . NO _AP ;
// after switching wifi network or creating a access point we delay the status retrieval
// because the webserver needs time to switch
this . retrieveNetworkStatusDelay ; // setTimout delay
this . retrieveNetworkStatusDelayTime = 1000 ;
// Events
SettingsWindow . SETTINGS _LOADED = "settingsLoaded" ;
// network client mode states
SettingsWindow . NOT _CONNECTED = "not connected" ; // also used as first item in networks list
SettingsWindow . CONNECTED = "connected" ;
SettingsWindow . CONNECTING = "connecting" ;
SettingsWindow . CONNECTING _FAILED = "connecting failed"
// network access point mode states
SettingsWindow . NO _AP = "no ap" ;
SettingsWindow . AP = "ap" ;
SettingsWindow . CREATING _AP = "creating ap" ;
SettingsWindow . API _CONNECTING _FAILED = - 1
SettingsWindow . API _NOT _CONNECTED = 0
SettingsWindow . API _CONNECTING = 1
SettingsWindow . API _CONNECTED = 2
SettingsWindow . API _CREATING = 3
SettingsWindow . API _CREATED = 4
// network mode
SettingsWindow . NETWORK _MODE _NEITHER = "neither" ;
SettingsWindow . NETWORK _MODE _CLIENT = "clientMode" ;
SettingsWindow . NETWORK _MODE _ACCESS _POINT = "accessPointMode" ;
this . networkMode = SettingsWindow . NETWORK _MODE _NEITHER ;
this . updatePanel = new UpdatePanel ( ) ;
var self = this ;
this . init = function ( wifiboxURL , wifiboxCGIBinURL ) {
this . wifiboxURL = wifiboxURL ;
this . wifiboxCGIBinURL = wifiboxCGIBinURL ;
this . window = $ ( "#settings" ) ;
this . window . find ( ".btnOK" ) . click ( this . submitwindow ) ;
this . window . find ( ".settingsContainer" ) . load ( "settings.html" , function ( ) {
console . log ( "Settings:finished loading settings.html, now loading settings..." ) ;
self . form = self . window . find ( "form" ) ;
self . form . submit ( function ( e ) { self . submitwindow ( e ) } ) ;
self . loadSettings ( ) ;
var btnAP = self . form . find ( "label[for='ap']" ) ;
var btnClient = self . form . find ( "label[for='client']" ) ;
var btnRefresh = self . form . find ( "#refreshNetworks" ) ;
var btnConnect = self . form . find ( "#connectToNetwork" ) ;
var btnCreate = self . form . find ( "#createAP" ) ;
var networkSelector = self . form . find ( "#network" ) ;
self . apFieldSet = self . form . find ( "#apSettings" ) ;
self . clientFieldSet = self . form . find ( "#clientSettings" ) ;
btnAP . on ( 'touchstart mousedown' , self . showAPSettings ) ;
btnClient . on ( 'touchstart mousedown' , self . showClientSettings ) ;
btnRefresh . on ( 'touchstart mousedown' , self . refreshNetworks ) ;
btnConnect . on ( 'touchstart mousedown' , self . connectToNetwork ) ;
btnCreate . on ( 'touchstart mousedown' , self . createAP ) ;
networkSelector . change ( self . networkSelectorChanged ) ;
// update panel
var $updatePanelElement = self . form . find ( "#updatePanel" ) ;
self . updatePanel . init ( wifiboxURL , $updatePanelElement ) ;
} ) ;
}
this . submitwindow = function ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
self . saveSettings ( self . readForm ( ) , function ( ) {
self . hideSettings ( ) ;
} ) ;
clearTimeout ( self . retryRetrieveNetworkStatusDelay ) ;
}
this . showSettings = function ( ) {
console . log ( "f:showSettings()" ) ;
this . loadSettings ( ) ; // reload settings
// this.window.css("display","table");
$ ( "#contentOverlay" ) . fadeIn ( 375 , function ( ) {
document . body . removeEventListener ( 'touchmove' , prevent , false ) ;
} ) ;
}
this . hideSettings = function ( ) {
$ ( "#contentOverlay" ) . fadeOut ( 375 , function ( ) {
document . body . addEventListener ( 'touchmove' , prevent , false ) ;
// self.window.css("display","none");
} ) ;
}
this . loadSettings = function ( ) {
if ( ! communicateWithWifibox ) {
console . log ( " communicateWithWifibox is false: settings aren't being loaded from wifibox..." )
return ;
}
console . log ( "Settings:loadSettings() >> getting new data..." ) ;
$ . ajax ( {
url : this . wifiboxURL + "/config/all" ,
dataType : 'json' ,
timeout : this . timeoutTime ,
success : function ( response ) {
console . log ( "Settings:loadSettings response: " , response ) ;
settings = response . data ;
console . log ( " settings: " , settings ) ;
self . fillForm ( ) ;
$ ( document ) . trigger ( SettingsWindow . SETTINGS _LOADED ) ;
}
} ) . fail ( function ( ) {
console . log ( "Settings:loadSettings: failed" ) ;
clearTimeout ( self . retryLoadSettingsDelay ) ;
self . retryLoadSettingsDelay = setTimeout ( function ( ) { self . loadSettings ( ) } , self . retryDelay ) ; // retry after delay
} ) ;
this . refreshNetworks ( ) ;
this . retrieveNetworkStatus ( false ) ;
}
this . fillForm = function ( ) {
console . log ( "SettingsWindow:fillForm" ) ;
//fill form with loaded settings
var selects = this . form . find ( "select" ) ;
selects . each ( function ( index , element ) {
var element = $ ( element ) ;
element . val ( settings [ element . attr ( 'name' ) ] ) ;
} ) ;
var inputs = this . form . find ( "input" ) ;
inputs . each ( function ( index , element ) {
var element = $ ( element ) ;
//console.log("printer setting input: ",index,element.attr("type"),element.attr('name')); //,element);
switch ( element . attr ( "type" ) ) {
case "text" :
case "number" :
element . val ( settings [ element . attr ( 'name' ) ] ) ;
break ;
case "checkbox" :
element . prop ( 'checked' , settings [ element . attr ( 'name' ) ] ) ;
break ;
}
} ) ;
var textareas = this . form . find ( "textarea" ) ;
textareas . each ( function ( index , element ) {
var element = $ ( element ) ;
var value = settings [ element . attr ( 'name' ) ] ;
element . val ( value ) ;
} ) ;
}
this . saveSettings = function ( newSettings , complete ) {
settings = newSettings ; // store new settings in global settings
if ( communicateWithWifibox ) {
$ . ajax ( {
url : this . wifiboxURL + "/config" ,
type : "POST" ,
data : newSettings ,
dataType : 'json' ,
timeout : this . timeoutTime ,
success : function ( response ) {
console . log ( "Settings:saveSettings response: " , response ) ;
if ( response . status == "error" ) {
clearTimeout ( self . retrySaveSettingsDelay ) ;
self . retrySaveSettingsDelay = setTimeout ( function ( ) { self . saveSettings ( settings ) } , self . retryDelay ) ; // retry after delay
} else {
var data = response . data ;
var validation = data . validation ;
self . clearValidationErrors ( ) ;
var validated = true ;
$ . each ( validation , function ( key , val ) {
if ( val != "ok" ) {
console . log ( "ERROR: setting '" + key + "' not successfully set. Message: " + val ) ;
self . displayValidationError ( key , val ) ;
validated = false ;
}
} ) ;
settings . substituted _ssid = data . substituted _ssid ;
if ( complete && validated ) complete ( ) ;
}
}
} ) . fail ( function ( ) {
console . log ( "Settings:saveSettings: failed" ) ;
clearTimeout ( self . retrySaveSettingsDelay ) ;
self . retrySaveSettingsDelay = setTimeout ( function ( ) { self . saveSettings ( settings ) } , self . retryDelay ) ; // retry after delay
} ) ;
}
}
this . displayValidationError = function ( key , msg ) {
var formElement = self . form . find ( "[name|='" + key + "']" ) ;
console . log ( "formElement: " , formElement ) ;
formElement . addClass ( "error" ) ;
var errorMsg = "<p class='errorMsg'>" + msg + "</p>"
formElement . after ( errorMsg ) ;
}
this . clearValidationErrors = function ( ) {
var formElements = self . form . find ( ".error" ) ;
formElements . each ( function ( index , element ) {
$ ( element ) . removeClass ( "error" ) ;
} ) ;
}
this . readForm = function ( ) {
//console.log("SettingsWindow:readForm");
var settings = { } ;
var selects = self . form . find ( "select" ) ;
selects . each ( function ( index , element ) {
var element = $ ( element ) ;
if ( element . attr ( 'name' ) != "network.client.network" ) {
settings [ element . attr ( 'name' ) ] = element . val ( ) ;
}
} ) ;
var inputs = self . form . find ( "input" ) ;
inputs . each ( function ( index , element ) {
var element = $ ( element ) ;
switch ( element . attr ( "type" ) ) {
case "text" :
case "number" :
settings [ element . attr ( 'name' ) ] = element . val ( ) ;
break ;
case "checkbox" :
settings [ element . attr ( 'name' ) ] = element . prop ( 'checked' )
break ;
}
} ) ;
var textareas = self . form . find ( "textarea" ) ;
textareas . each ( function ( index , element ) {
var element = $ ( element ) ;
settings [ element . attr ( 'name' ) ] = element . val ( ) ;
} ) ;
//console.log(settings);
return settings ;
}
/ *
* Networks ui
* /
this . showAPSettings = function ( ) {
self . apFieldSet . show ( ) ;
self . clientFieldSet . hide ( ) ;
}
this . showClientSettings = function ( ) {
self . clientFieldSet . show ( ) ;
self . apFieldSet . hide ( ) ;
}
this . refreshNetworks = function ( ) {
console . log ( "Settings:refreshNetworks" ) ;
if ( communicateWithWifibox ) {
$ . ajax ( {
url : self . wifiboxURL + "/network/scan" ,
type : "GET" ,
dataType : 'json' ,
timeout : self . timeoutTime ,
success : function ( response ) {
console . log ( "Settings:refreshNetworks response: " , response ) ;
if ( response . status == "error" ) {
//clearTimeout(self.retrySaveSettingsDelay);
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
} else {
var networks = response . data . networks
self . networks = { } ;
var foundCurrentNetwork = false ;
var networkSelector = self . form . find ( "#network" ) ;
networkSelector . empty ( ) ;
networkSelector . append (
$ ( "<option></option>" ) . val ( SettingsWindow . NOT _CONNECTED ) . html ( "not connected" )
) ;
$ . each ( networks , function ( index , element ) {
if ( element . ssid == self . currentNetwork ) {
foundCurrentNetwork = true ;
}
networkSelector . append (
$ ( "<option></option>" ) . val ( element . ssid ) . html ( element . ssid )
) ;
self . networks [ element . ssid ] = element ;
} ) ;
if ( foundCurrentNetwork ) {
networkSelector . val ( self . currentNetwork ) ;
self . selectNetwork ( self . currentNetwork ) ;
}
}
}
} ) . fail ( function ( ) {
} ) ;
}
}
this . retrieveNetworkStatus = function ( connecting ) {
//console.log("Settings:retrieveNetworkStatus");
if ( communicateWithWifibox ) {
$ . ajax ( {
url : self . wifiboxURL + "/network/status" ,
type : "GET" ,
dataType : 'json' ,
timeout : self . timeoutTime ,
success : function ( response ) {
console . log ( "Settings:retrieveNetworkStatus response: " , response ) ;
if ( response . status == "error" ) {
} else {
var data = response . data ;
if ( typeof data . status === 'string' ) {
data . status = parseInt ( data . status ) ;
}
//console.log(" data.status: ",data.status,data.statusMessage);
// Determine which network settings to show
switch ( data . status ) {
case SettingsWindow . API _NOT _CONNECTED :
//console.log(" not connected & not a access point");
self . apFieldSet . show ( ) ;
self . clientFieldSet . show ( ) ;
self . networkMode = SettingsWindow . NETWORK _MODE _NEITHER ;
break ;
case SettingsWindow . API _CONNECTING _FAILED :
case SettingsWindow . API _CONNECTING :
case SettingsWindow . API _CONNECTED :
//console.log(" client mode");
self . form . find ( "#client" ) . prop ( 'checked' , true ) ;
self . apFieldSet . hide ( ) ;
self . clientFieldSet . show ( ) ;
if ( data . status == SettingsWindow . API _CONNECTED ) {
var networkSelector = self . form . find ( "#network" ) ;
networkSelector . val ( data . ssid ) ;
self . currentNetwork = data . ssid ;
self . currentLocalIP = data . localip ;
self . selectNetwork ( data . ssid ) ;
} else {
self . currentLocalIP = ""
}
self . networkMode = SettingsWindow . NETWORK _MODE _CLIENT ;
break ;
case SettingsWindow . API _CREATING :
case SettingsWindow . API _CREATED :
//console.log(" access point mode");
self . form . find ( "#ap" ) . prop ( 'checked' , true ) ;
self . apFieldSet . show ( ) ;
self . clientFieldSet . hide ( ) ;
self . currentNetwork = undefined ;
self . selectNetwork ( SettingsWindow . NOT _CONNECTED ) ;
var networkSelector = self . form . find ( "#network" ) ;
networkSelector . val ( SettingsWindow . NOT _CONNECTED ) ;
if ( data . ssid && data . status == SettingsWindow . API _CREATED ) {
self . currentAP = data . ssid ;
}
self . networkMode = SettingsWindow . NETWORK _MODE _ACCESS _POINT ;
break ;
}
self . updatePanel . setNetworkMode ( self . networkMode ) ;
// update status message
switch ( data . status ) {
case SettingsWindow . API _CONNECTING _FAILED :
self . setClientModeState ( SettingsWindow . CONNECTING _FAILED , data . statusMessage ) ;
self . setAPModeState ( SettingsWindow . NO _AP , "" ) ;
break ;
case SettingsWindow . API _NOT _CONNECTED :
self . setClientModeState ( SettingsWindow . NOT _CONNECTED , "" ) ;
self . setAPModeState ( SettingsWindow . NO _AP , "" ) ;
break ;
case SettingsWindow . API _CONNECTING :
self . setClientModeState ( SettingsWindow . CONNECTING , "" ) ;
self . setAPModeState ( SettingsWindow . NO _AP , "" ) ;
break ;
case SettingsWindow . API _CONNECTED :
self . setClientModeState ( SettingsWindow . CONNECTED , "" ) ;
self . setAPModeState ( SettingsWindow . NO _AP , "" ) ;
break ;
case SettingsWindow . API _CREATING :
self . setClientModeState ( SettingsWindow . NOT _CONNECTED , "" ) ;
self . setAPModeState ( SettingsWindow . CREATING _AP , "" ) ;
break ;
case SettingsWindow . API _CREATED :
self . setClientModeState ( SettingsWindow . NOT _CONNECTED , "" ) ;
self . setAPModeState ( SettingsWindow . AP , "" ) ;
break ;
}
// Keep checking for updates?
if ( connecting ) {
switch ( data . status ) {
case SettingsWindow . API _CONNECTING :
case SettingsWindow . API _CREATING :
clearTimeout ( self . retryRetrieveNetworkStatusDelay ) ;
self . retryRetrieveNetworkStatusDelay = setTimeout ( function ( ) { self . retrieveNetworkStatus ( connecting ) } , self . retryRetrieveNetworkStatusDelayTime ) ; // retry after delay
break ;
}
}
}
}
} ) . fail ( function ( ) {
console . log ( "Settings:retrieveNetworkStatus: failed" ) ;
clearTimeout ( self . retryRetrieveNetworkStatusDelay ) ;
self . retryRetrieveNetworkStatusDelay = setTimeout ( function ( ) { self . retrieveNetworkStatus ( connecting ) } , self . retryDelay ) ; // retry after delay
} ) ;
}
}
this . networkSelectorChanged = function ( e ) {
var selectedOption = $ ( this ) . find ( "option:selected" ) ;
self . selectNetwork ( selectedOption . val ( ) ) ;
}
this . selectNetwork = function ( ssid ) {
console . log ( "select network: " , ssid ) ;
if ( ssid == "" ) return ;
console . log ( " checked" ) ;
this . selectedNetwork = ssid ;
if ( this . networks == undefined || ssid == SettingsWindow . NOT _CONNECTED ) {
this . hideWiFiPassword ( ) ;
} else {
var network = this . networks [ ssid ] ;
if ( network . encryption == "none" ) {
this . hideWiFiPassword ( ) ;
} else {
this . showWiFiPassword ( ) ;
}
this . form . find ( "#password" ) . val ( "" ) ;
}
}
this . showWiFiPassword = function ( ) {
this . form . find ( "#passwordLabel" ) . show ( ) ;
this . form . find ( "#password" ) . show ( ) ;
}
this . hideWiFiPassword = function ( ) {
this . form . find ( "#passwordLabel" ) . hide ( ) ;
this . form . find ( "#password" ) . hide ( ) ;
}
this . setClientModeState = function ( state , msg ) {
var field = this . form . find ( "#clientModeState" ) ;
var btnConnect = self . form . find ( "#connectToNetwork" ) ;
switch ( state ) {
case SettingsWindow . NOT _CONNECTED :
btnConnect . removeAttr ( "disabled" ) ;
field . html ( "Not connected" ) ;
break ;
case SettingsWindow . CONNECTED :
btnConnect . removeAttr ( "disabled" ) ;
var fieldText = "Connected to: <b>" + this . currentNetwork + "</b>." ;
if ( this . currentLocalIP != undefined && this . currentLocalIP != "" ) {
var a = "<a href='http://" + this . currentLocalIP + "' target='_black'>" + this . currentLocalIP + "</a>" ;
fieldText += " (IP: " + a + ")" ;
}
field . html ( fieldText ) ;
break ;
case SettingsWindow . CONNECTING :
btnConnect . attr ( "disabled" , true ) ;
field . html ( "Connecting... Reconnect by connecting your device to <b>" + this . selectedNetwork + "</b> and going to <a href='http://connect.doodle3d.com'>connect.doodle3d.com</a>" ) ;
break ;
case SettingsWindow . CONNECTING _FAILED :
btnConnect . removeAttr ( "disabled" ) ;
field . html ( msg ) ;
break ;
}
this . clientModeState = state ;
}
this . setAPModeState = function ( state , msg ) {
var field = this . form . find ( "#apModeState" ) ;
var btnCreate = this . form . find ( "#createAP" ) ;
switch ( state ) {
case SettingsWindow . NO _AP :
btnCreate . removeAttr ( "disabled" ) ;
field . html ( "Not currently a access point" ) ;
break ;
case SettingsWindow . AP :
btnCreate . removeAttr ( "disabled" ) ;
field . html ( "Is access point: <b>" + this . currentAP + "</b>" ) ;
break ;
case SettingsWindow . CREATING _AP :
btnCreate . attr ( "disabled" , true ) ;
field . html ( "Creating access point... Reconnect by connecting your device to <b>" + settings . substituted _ssid + "</b> and going to <a href='http://draw.doodle3d.com'>draw.doodle3d.com</a>" ) ;
break ;
}
this . apModeState = state ;
}
this . connectToNetwork = function ( ) {
console . log ( "connectToNetwork" ) ;
if ( self . selectedNetwork == undefined ) return ;
var postData = {
ssid : self . selectedNetwork ,
phrase : self . form . find ( "#password" ) . val ( ) ,
recreate : true
}
console . log ( " postData: " , postData ) ;
if ( communicateWithWifibox ) {
// save network related settings and on complete, connect to network
self . saveSettings ( self . readForm ( ) , function ( ) {
$ . ajax ( {
url : self . wifiboxCGIBinURL + "/network/associate" ,
type : "POST" ,
data : postData ,
dataType : 'json' ,
timeout : self . timeoutTime ,
success : function ( response ) {
console . log ( "Settings:connectToNetwork response: " , response ) ;
}
} ) . fail ( function ( ) {
console . log ( "Settings:connectToNetwork: timeout (normal behavior)" ) ;
//clearTimeout(self.retrySaveSettingsDelay);
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
} ) ;
} ) ;
}
self . setClientModeState ( SettingsWindow . CONNECTING , "" ) ;
// after switching wifi network or creating a access point we delay the status retrieval
// because the webserver needs time to switch
clearTimeout ( self . retrieveNetworkStatusDelay ) ;
self . retrieveNetworkStatusDelay = setTimeout ( function ( ) { self . retrieveNetworkStatus ( true ) } , self . retrieveNetworkStatusDelayTime ) ;
}
this . createAP = function ( ) {
console . log ( "createAP" ) ;
if ( communicateWithWifibox ) {
// save network related settings and on complete, create access point
self . saveSettings ( self . readForm ( ) , function ( ) {
self . setAPModeState ( SettingsWindow . CREATING _AP ) ; // get latest substituted ssid
$ . ajax ( {
url : self . wifiboxCGIBinURL + "/network/openap" ,
type : "POST" ,
dataType : 'json' ,
timeout : self . timeoutTime ,
success : function ( response ) {
console . log ( "Settings:createAP response: " , response ) ;
}
} ) . fail ( function ( ) {
console . log ( "Settings:createAP: timeout (normal behavior)" ) ;
//clearTimeout(self.retrySaveSettingsDelay);
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
} ) ;
self . setAPModeState ( SettingsWindow . CREATING _AP , "" ) ;
// after switching wifi network or creating a access point we delay the status retrieval
// because the webserver needs time to switch
clearTimeout ( self . retrieveNetworkStatusDelay ) ;
self . retrieveNetworkStatusDelay = setTimeout ( function ( ) { self . retrieveNetworkStatus ( true ) } , self . retrieveNetworkStatusDelayTime ) ;
} ) ;
}
}
}
/ * * * * * * * * * * * * * * * * * * * * * * * * *
*
*
* FROM DOODLE3D . INI
*
* /
//TODO: find all references to these variables, replace them and finally remove these.
var objectHeight = 20 ;
var layerHeight = . 2 ;
//var wallThickness = .5;
//var hop = 0;
//var speed = 70;
//var travelSpeed = 200;
var enableTraveling = true ;
//var filamentThickness = 2.89;
var minScale = . 3 ;
var maxScale = 1 ;
var shape = "%" ;
var twists = 0 ;
//var useSubLayers = true;
//var debug = false; // debug moved to main.js
var loglevel = 2 ;
//var zOffset = 0;
var serverport = 8888 ;
var autoLoadImage = "hand.txt" ;
var loadOffset = [ 0 , 0 ] ; // x en y ?
var showWarmUp = true ;
var loopAlways = false ;
var firstLayerSlow = true ;
var useSubpathColors = false ;
var autoWarmUp = true ;
//var maxObjectHeight = 150;
var maxScaleDifference = . 1 ;
var frameRate = 60 ;
var quitOnEscape = true ;
var screenToMillimeterScale = . 3 ; // 0.3
//var targetTemperature = 220;
//var simplifyiterations = 10;
//var simplifyminNumPoints = 15;
//var simplifyminDistance = 3;
//var retractionspeed = 50;
//var retractionminDistance = 5;
//var retractionamount = 3;
var sideis3D = true ;
var sidevisible = true ;
var sidebounds = [ 900 , 210 , 131 , 390 ] ;
var sideborder = [ 880 , 169 , 2 , 471 ] ;
var windowbounds = [ 0 , 0 , 800 , 500 ] ;
var windowcenter = true ;
var windowfullscreen = false ;
var autoWarmUpCommand = "M104 S230" ;
//var checkTemperatureInterval = 3;
var autoWarmUpDelay = 3 ;
function UpdatePanel ( ) {
this . wifiboxURL ;
this . element ;
this . statusCheckInterval = 1000 ;
this . statusCheckDelayer ; // setTimout instance
this . installedDelay = 60 * 1000 ; // Since we can't retrieve status during installation we show the installed text after a fixed delay
this . installedDelayer ; // setTimout instance
this . retryDelay = 1000 ;
this . retryDelayer ; // setTimout instance
//this.timeoutTime = 3000;
this . canUpdate = false ;
this . currentVersion = "" ;
this . newestVersion ;
this . progress ;
this . imageSize ;
// states from api, see Doodle3D firmware src/script/d3d-updater.lua
UpdatePanel . NONE = 1 ; // default state
UpdatePanel . DOWNLOADING = 2 ;
UpdatePanel . DOWNLOAD _FAILED = 3 ;
UpdatePanel . IMAGE _READY = 4 ; // download successfull and checked
UpdatePanel . INSTALLING = 5 ;
UpdatePanel . INSTALLED = 6 ;
UpdatePanel . INSTALL _FAILED = 7 ;
this . state ; // update state from api
this . stateText = "" ; // update state text from api
this . networkMode ; // network modes from SettingsWindow
var self = this ;
this . init = function ( wifiboxURL , updatePanelElement ) {
this . wifiboxURL = wifiboxURL ;
this . element = updatePanelElement ;
this . btnUpdate = this . element . find ( "#update" ) ;
this . statusDisplay = this . element . find ( "#updateState" ) ;
this . infoDisplay = this . element . find ( "#updateInfo" ) ;
this . btnUpdate . click ( this . update ) ;
this . checkStatus ( false ) ;
}
this . update = function ( ) {
console . log ( "UpdatePanel:update" ) ;
self . downloadUpdate ( ) ;
}
this . downloadUpdate = function ( ) {
console . log ( "UpdatePanel:downloadUpdate" ) ;
$ . ajax ( {
url : self . wifiboxURL + "/update/download" ,
type : "POST" ,
dataType : 'json' ,
success : function ( response ) {
console . log ( "UpdatePanel:downloadUpdate response: " , response ) ;
}
} ) . fail ( function ( ) {
console . log ( "UpdatePanel:downloadUpdate: failed" ) ;
} ) ;
self . setState ( UpdatePanel . DOWNLOADING ) ;
self . startCheckingStatus ( ) ;
}
this . installUpdate = function ( ) {
console . log ( "UpdatePanel:installUpdate" ) ;
self . stopCheckingStatus ( ) ;
$ . ajax ( {
url : self . wifiboxURL + "/update/install" ,
type : "POST" ,
dataType : 'json' ,
success : function ( response ) {
console . log ( "UpdatePanel:installUpdate response: " , response ) ;
}
} ) . fail ( function ( ) {
console . log ( "UpdatePanel:installUpdate: no respons (there shouldn't be)" ) ;
} ) ;
self . setState ( UpdatePanel . INSTALLING ) ;
clearTimeout ( self . installedDelayer ) ;
self . installedDelayer = setTimeout ( function ( ) { self . setState ( UpdatePanel . INSTALLED ) } , self . installedDelay ) ;
}
this . startCheckingStatus = function ( ) {
clearTimeout ( self . statusCheckDelayer ) ;
clearTimeout ( self . retryDelayer ) ;
self . statusCheckDelayer = setTimeout ( function ( ) { self . checkStatus ( true ) } , self . statusCheckInterval ) ;
}
this . stopCheckingStatus = function ( ) {
clearTimeout ( self . statusCheckDelayer ) ;
clearTimeout ( self . retryDelayer ) ;
}
this . checkStatus = function ( keepChecking ) {
if ( ! communicateWithWifibox ) return ;
$ . ajax ( {
url : self . wifiboxURL + "/update/status" ,
type : "GET" ,
dataType : 'json' ,
//timeout: self.timeoutTime,
success : function ( response ) {
console . log ( "UpdatePanel:checkStatus response: " , response ) ;
// Keep checking ?
if ( keepChecking ) {
switch ( self . state ) {
case UpdatePanel . DOWNLOADING :
case UpdatePanel . INSTALLING :
clearTimeout ( self . statusCheckDelayer ) ;
self . statusCheckDelayer = setTimeout ( function ( ) { self . checkStatus ( keepChecking ) } , self . statusCheckInterval ) ;
break ;
}
}
if ( response . status != "error" ) {
var data = response . data ;
self . handleStatusData ( data ) ;
}
}
} ) . fail ( function ( ) {
//console.log("UpdatePanel:checkStatus: failed");
if ( keepChecking ) {
clearTimeout ( self . retryDelayer ) ;
self . retryDelayer = setTimeout ( function ( ) { self . checkStatus ( keepChecking ) } , self . retryDelay ) ; // retry after delay
}
} ) ;
}
this . handleStatusData = function ( data ) {
//console.log("UpdatePanel:handleStatusData");
self . canUpdate = data . can _update ;
if ( self . currentVersion != data . current _version || self . newestVersion != data . newest _version ) {
self . currentVersion = data . current _version ;
self . newestVersion = data . newest _version ;
self . updateInfoDisplay ( ) ;
}
self . stateText = data . state _text ;
self . progress = data . progress ; // not always available
self . imageSize = data . image _size ; // not always available
self . setState ( data . state _code ) ;
switch ( this . state ) {
case UpdatePanel . IMAGE _READY :
self . installUpdate ( ) ;
break ;
}
}
this . setState = function ( newState ) {
if ( this . state == newState ) return ;
console . log ( "UpdatePanel:setState: " , this . state , " > " , newState , "(" , this . stateText , ") (networkMode: " , self . networkMode , ") (newestVersion: " , self . newestVersion , ")" ) ;
this . state = newState ;
// download button
// if there isn't newestVersion data something went wrong,
// probably accessing the internet
if ( self . newestVersion != undefined ) {
switch ( this . state ) {
case UpdatePanel . NONE :
case UpdatePanel . DOWNLOAD _FAILED :
case UpdatePanel . INSTALL _FAILED :
if ( self . canUpdate ) {
self . btnUpdate . removeAttr ( "disabled" ) ;
} else {
self . btnUpdate . attr ( "disabled" , true ) ;
}
break ;
default :
self . btnUpdate . attr ( "disabled" , true ) ;
break ;
}
} else {
self . btnUpdate . attr ( "disabled" , true ) ;
}
this . updateStatusDisplay ( ) ;
}
this . updateStatusDisplay = function ( ) {
var text = "" ;
if ( self . newestVersion != undefined ) {
switch ( this . state ) {
case UpdatePanel . NONE :
if ( self . canUpdate ) {
text = "Update(s) available." ;
} else {
text = "You're up to date." ;
}
break ;
case UpdatePanel . DOWNLOADING :
text = "Downloading update..." ;
break ;
case UpdatePanel . DOWNLOAD _FAILED :
text = "Downloading update failed." ;
break ;
case UpdatePanel . IMAGE _READY :
text = "Update downloaded." ;
break ;
case UpdatePanel . INSTALLING :
text = "Installing update... (will take a minute)" ;
break ;
case UpdatePanel . INSTALLED :
text = "Update complete, please <a href='javascript:location.reload(true);'>refresh Page</a>." ;
break ;
case UpdatePanel . INSTALL _FAILED :
text = "Installing update failed." ;
break ;
}
} else {
if ( self . networkMode == SettingsWindow . NETWORK _MODE _ACCESS _POINT ) {
text = "Can't access internet in access point mode." ;
} else {
text = "Can't access internet." ;
}
}
this . statusDisplay . html ( text ) ;
}
this . updateInfoDisplay = function ( ) {
var text = "Current version: " + self . currentVersion + ". " ;
if ( self . canUpdate ) {
text += "Latest version: " + self . newestVersion + "." ;
}
self . infoDisplay . text ( text ) ;
}
this . setNetworkMode = function ( networkMode ) {
self . networkMode = networkMode ;
}
}
function setTemperature ( callback ) {
if ( callback != undefined ) callback ( ) ;
}
function setTemperature ( callback ) {
if ( callback != undefined ) callback ( ) ;
}
var VERTICALSHAPE ;
var verticalShapes = {
"NONE" : 'none' ,
"DIVERGING" : 'diverging' ,
"CONVERGING" : 'converging' ,
"SINUS" : 'sinus'
} ;
function initVerticalShapes ( ) {
// TODO give these vertical shapes a better spot
VERTICALSHAPE = verticalShapes . NONE ;
$ ( ".verticalShapes, .straight" ) . on ( 'mouseup touchend' , function ( e ) {
e . preventDefault ( ) ;
console . log ( "diverging" ) ;
VERTICALSHAPE = verticalShapes . NONE ;
redrawRenderedPreview ( ) ;
} )
$ ( ".verticalShapes, .diverging" ) . on ( 'mouseup touchend' , function ( e ) {
e . preventDefault ( ) ;
console . log ( "diverging" ) ;
VERTICALSHAPE = verticalShapes . DIVERGING ;
redrawRenderedPreview ( ) ;
} )
$ ( ".verticalShapes, .converging" ) . on ( 'mouseup touchend' , function ( e ) {
e . preventDefault ( ) ;
console . log ( "converging" ) ;
VERTICALSHAPE = verticalShapes . CONVERGING ;
redrawRenderedPreview ( ) ;
} )
$ ( ".verticalShapes, .sinus" ) . on ( 'mouseup touchend' , function ( e ) {
e . preventDefault ( ) ;
console . log ( "sinus" ) ;
VERTICALSHAPE = verticalShapes . SINUS ;
redrawRenderedPreview ( ) ;
} )
}
function resetVerticalShapes ( ) {
VERTICALSHAPE = verticalShapes . NONE ;
}
var btnMoveUpInterval ;
var btnMoveDownInterval ;
var btnTwistLeftInterval ;
var btnTwistRightInterval ;
var twistIncrement = Math . PI / 1800 ;
var btnOopsInterval ;
var btnNew , btnPrevious , btnNext ;
var btnOops , btnStop , btnClear ;
var btnMoveUp , btnMoveDown , btnTwistLeft , btnTwistRight ;
var btnInfo , btnSettings ;
//var btnDebug; // debug
var state ;
var prevState ;
var hasControl ;
var gcodeGenerateDelayer ;
var gcodeGenerateDelay = 50 ;
function initButtonBehavior ( ) {
console . log ( "f:initButtonBehavior" ) ;
// btnClear= $(".btnClear");
btnOops = $ ( ".btnOops" ) ;
btnMoveUp = $ ( "#btnMoveUp" ) ;
btnMoveDown = $ ( "#btnMoveDown" ) ;
btnTwistLeft = $ ( "#btnTwistLeft" ) ;
btnTwistRight = $ ( "#btnTwistRight" ) ;
btnInfo = $ ( ".btnInfo" ) ;
btnSettings = $ ( ".btnSettings" ) ;
btnNew = $ ( ".btnNew" ) ;
btnPrint = $ ( ".btnPrint" ) ;
btnStop = $ ( ".btnStop" ) ;
btnPrevious = $ ( ".btnPrevious" ) ;
btnNext = $ ( ".btnNext" ) ;
//debug
//btnDebug = $(".debugBtn");
btnNew . on ( 'touchstart mousedown' , clearDoodle ) ;
btnPrint . on ( 'touchstart mousedown' , print ) ;
// not using these at the moment
$ ( "#btnPrevious" ) . css ( "opacity" , "0.3" ) ;
btnNext . css ( "opacity" , "0.3" ) ;
$ ( "#btnSave" ) . css ( "opacity" , "0.3" ) ;
btnInfo . css ( "opacity" , "0.3" ) ;
// btnClear.click(function(e) {
// e.preventDefault();
// // console.log("clear");
//
// clearDoodle();
// });
function startOops ( e ) {
// console.log("btnOops mouse down");
e . preventDefault ( ) ;
btnOopsInterval = setInterval ( function ( ) {
oopsUndo ( ) ;
} , 1000 / 50 ) ;
}
function stopOops ( e ) {
// console.log("btnOops mouse up");
e . preventDefault ( ) ;
clearInterval ( btnOopsInterval ) ;
}
btnOops . on ( 'touchstart' , function ( e ) { startOops ( e ) ; } ) ;
btnOops . on ( 'touchend' , function ( e ) { stopOops ( e ) ; } ) ;
btnOops . mousedown ( function ( e ) { startOops ( e ) ; } ) ;
btnOops . mouseup ( function ( e ) { stopOops ( e ) ; } ) ;
function startMoveUp ( e ) {
e . preventDefault ( ) ;
// console.log("btnMoveUp mouse down");
previewUp ( true ) ;
clearInterval ( btnMoveUpInterval ) ;
btnMoveUpInterval = setInterval ( function ( ) {
previewUp ( true ) ;
} , 1000 / 30 ) ;
}
function stopMoveUp ( e ) {
e . preventDefault ( ) ;
console . log ( "btnMoveUp mouse up" ) ;
clearInterval ( btnMoveUpInterval ) ;
previewUp ( ) ;
}
btnMoveUp . mousedown ( function ( e ) { startMoveUp ( e ) } ) ;
btnMoveUp . mouseup ( function ( e ) { stopMoveUp ( e ) } ) ;
btnMoveUp . on ( 'touchstart' , function ( e ) { startMoveUp ( e ) } ) ;
btnMoveUp . on ( 'touchend' , function ( e ) { stopMoveUp ( e ) } ) ;
function startMoveDown ( e ) {
e . preventDefault ( ) ;
// console.log("btnMoveDown mouse down");
previewDown ( true ) ;
clearInterval ( btnMoveDownInterval ) ;
btnMoveDownInterval = setInterval ( function ( ) {
previewDown ( true ) ;
} , 1000 / 30 ) ;
}
function stopMoveDown ( e ) {
e . preventDefault ( ) ;
console . log ( "btnMoveDown mouse up" ) ;
clearInterval ( btnMoveDownInterval ) ;
previewDown ( ) ;
}
btnMoveDown . mousedown ( function ( e ) { startMoveDown ( e ) } ) ;
btnMoveDown . mouseup ( function ( e ) { stopMoveDown ( e ) } ) ;
btnMoveDown . on ( 'touchstart' , function ( e ) { startMoveDown ( e ) } ) ;
btnMoveDown . on ( 'touchend' , function ( e ) { stopMoveDown ( e ) } ) ;
function startTwistLeft ( e ) {
e . preventDefault ( ) ;
// console.log("btnTwistLeft mouse down");
previewTwistLeft ( true ) ;
clearInterval ( btnTwistLeftInterval ) ;
btnTwistLeftInterval = setInterval ( function ( ) {
previewTwistLeft ( true ) ;
} , 1000 / 30 ) ;
}
function stopTwistLeft ( e ) {
e . preventDefault ( ) ;
// console.log("btnTwistLeft mouse up");
clearInterval ( btnTwistLeftInterval ) ;
previewTwistLeft ( ) ;
}
btnTwistLeft . mousedown ( function ( e ) { startTwistLeft ( e ) } ) ;
btnTwistLeft . mouseup ( function ( e ) { stopTwistLeft ( e ) } ) ;
btnTwistLeft . on ( 'touchstart' , function ( e ) { startTwistLeft ( e ) } ) ;
btnTwistLeft . on ( 'touchend' , function ( e ) { stopTwistLeft ( e ) } ) ;
function startTwistRight ( e ) {
e . preventDefault ( ) ;
// console.log("btnTwistRight mouse down");
previewTwistRight ( true ) ;
clearInterval ( btnTwistRightInterval ) ;
btnTwistRightInterval = setInterval ( function ( ) {
previewTwistRight ( true ) ;
} , 1000 / 30 ) ;
}
function stopTwistRight ( e ) {
e . preventDefault ( ) ;
// console.log("btnTwistRight mouse up");
clearInterval ( btnTwistRightInterval ) ;
previewTwistRight ( ) ;
}
btnTwistRight . mousedown ( function ( e ) { startTwistRight ( e ) } ) ;
btnTwistRight . mouseup ( function ( e ) { stopTwistRight ( e ) } ) ;
btnTwistRight . on ( 'touchstart' , function ( e ) { startTwistRight ( e ) } ) ;
btnTwistRight . on ( 'touchend' , function ( e ) { stopTwistRight ( e ) } ) ;
/ * f u n c t i o n o p e n S e t t i n g s ( ) {
console . log ( "f:openSettings()" ) ;
$ ( "#contentOverlay" ) . fadeIn ( 1000 , function ( ) {
loadSettings ( ) ;
} ) ;
} * /
btnSettings . bind ( 'touchstart mousedown' , function ( ) {
//e.preventDefault();
//console.log("btnSettings clicked");
settingsWindow . showSettings ( ) ;
} ) ;
// btnSettings.on('touchend', function(e) {
// e.preventDefault();
// console.log("btnSettings touchend");
// });
btnInfo . mouseup ( function ( e ) {
e . preventDefault ( ) ;
console . log ( "btnInfo mouse up" ) ;
} ) ;
// DEBUG
/ *
// $(".agentInfo").css("display", "none");
btnDebug . click ( function ( e ) {
console . log ( "debugClick" ) ;
$ ( ".agentInfo" ) . toggleClass ( "agentInfoToggle" ) ;
e . preventDefault ( ) ;
} )
//*/
//btnStop.on('touchstart mousedown',stopPrint);
}
function stopPrint ( ) {
console . log ( "f:stopPrint() >> sendPrintCommands = " + sendPrintCommands ) ;
//if (!confirm("Weet je zeker dat je huidige print wilt stoppen?")) return;
if ( sendPrintCommands ) printer . stop ( ) ;
//setState(Printer.STOPPING_STATE,printer.hasControl);
printer . overruleState ( Printer . STOPPING _STATE ) ;
}
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 ) ;
//$(".btnPrint").css("display","none");
if ( _points . length > 2 ) {
//setState(Printer.BUFFERING_STATE,printer.hasControl);
printer . overruleState ( Printer . BUFFERING _STATE ) ;
btnStop . css ( "display" , "none" ) ; // hack
// we put the gcode generation in a little delay
// so that for example the print button is disabled right away
clearTimeout ( gcodeGenerateDelayer ) ;
gcodeGenerateDelayer = setTimeout ( function ( ) {
var gcode = generate _gcode ( ) ;
if ( sendPrintCommands ) {
if ( gcode . length > 0 ) {
printer . print ( gcode ) ;
} else {
printer . overruleState ( Printer . IDLE _STATE ) ;
printer . startStatusCheckInterval ( ) ;
}
} else {
console . log ( "sendPrintCommands is false: not sending print command to 3dprinter" ) ;
}
if ( debugMode ) {
$ ( "#textdump" ) . text ( "" ) ;
$ ( "#textdump" ) . text ( gcode . join ( "\n" ) ) ;
}
} , gcodeGenerateDelay ) ;
} else {
console . log ( "f:print >> not enough points!" ) ;
}
//alert("Je tekening zal nu geprint worden");
//$(".btnPrint").css("display","block");
// $.post("/doodle3d.of", { data:output }, function(data) {
// btnPrint.disabled = false;
// });
}
function clearMainView ( ) {
// console.log("f:clearMainView()");
ctx . save ( ) ;
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
ctx . restore ( ) ;
}
function resetPreview ( ) {
// console.log("f:resetPreview()");
// clear preview canvas
previewCtx . save ( ) ;
previewCtx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
previewCtx . restore ( ) ;
// reset height and rotation to default values
numLayers = previewDefaults . numLayers ; // current number of preview layers
rStep = previewDefaults . rotation ; // Math.PI/180; //Math.PI/40; //
}
function oopsUndo ( ) {
// console.log("f:oopsUndo()");
_points . pop ( ) ;
redrawDoodle ( ) ;
redrawPreview ( ) ;
}
function previewUp ( redrawLess ) {
// console.log("f:previewUp()");
if ( numLayers < maxNumLayers ) {
numLayers ++ ;
}
// redrawPreview(redrawLess);
redrawRenderedPreview ( redrawLess ) ;
}
function previewDown ( redrawLess ) {
// console.log("f:previewDown()");
if ( numLayers > minNumLayers ) {
numLayers -- ;
}
// redrawPreview(redrawLess);
redrawRenderedPreview ( redrawLess ) ;
}
function previewTwistLeft ( redrawLess ) {
if ( redrawLess == undefined ) redrawLess = false ;
// console.log("f:previewTwistLeft()");
if ( rStep > - previewRotationLimit ) rStep -= twistIncrement ;
// redrawPreview(redrawLess);
redrawRenderedPreview ( redrawLess ) ;
}
function previewTwistRight ( redrawLess ) {
// console.log("f:previewTwistRight()");
if ( rStep < previewRotationLimit ) rStep += twistIncrement ;
// redrawPreview(redrawLess);
redrawRenderedPreview ( redrawLess ) ;
}
function update ( ) {
setState ( printer . state , printer . hasControl ) ;
thermometer . update ( printer . temperature , printer . targetTemperature ) ;
progressbar . update ( printer . currentLine , printer . totalLines ) ;
}
function setState ( newState , newHasControl ) {
if ( newState == state && newHasControl == hasControl ) return ;
prevState = state ;
console . log ( "setState: " , prevState , " > " , newState , " ( " , newHasControl , ")" ) ;
setDebugText ( "State: " + newState ) ;
// print button
var printEnabled = ( newState == Printer . IDLE _STATE && newHasControl ) ;
if ( printEnabled ) {
btnPrint . removeClass ( "disabled" ) ; // enable print button
btnPrint . unbind ( 'touchstart mousedown' ) ;
btnPrint . bind ( 'touchstart mousedown' , print ) ;
} else {
btnPrint . addClass ( "disabled" ) ; // disable print button
btnPrint . unbind ( 'touchstart mousedown' ) ;
}
// stop button
var stopEnabled = ( ( newState == Printer . PRINTING _STATE || newState == Printer . BUFFERING _STATE ) && newHasControl ) ;
if ( stopEnabled ) {
btnStop . removeClass ( "disabled" ) ;
btnStop . unbind ( 'touchstart mousedown' ) ;
btnStop . bind ( 'touchstart mousedown' , stopPrint ) ;
} else {
btnStop . addClass ( "disabled" ) ;
btnStop . unbind ( 'touchstart mousedown' ) ;
}
// thermometer
switch ( newState ) {
case Printer . IDLE _STATE :
case Printer . BUFFERING _STATE :
case Printer . PRINTING _STATE :
case Printer . STOPPING _STATE :
thermometer . show ( ) ;
break ;
default :
thermometer . hide ( ) ;
break ;
}
// progress indicator
switch ( newState ) {
case Printer . PRINTING _STATE :
progressbar . show ( ) ;
break ;
default :
progressbar . hide ( ) ;
break ;
}
if ( newState == Printer . WIFIBOX _DISCONNECTED _STATE ) {
message . set ( "Lost connection to WiFi box" , Message . ERROR ) ;
} else if ( prevState == Printer . WIFIBOX _DISCONNECTED _STATE ) {
message . set ( "Connected to WiFi box" , Message . INFO , true ) ;
} else if ( newState == Printer . DISCONNECTED _STATE ) {
message . set ( "Printer disconnected" , Message . WARNING , true ) ;
} else if ( prevState == Printer . DISCONNECTED _STATE && newState == Printer . IDLE _STATE ||
prevState == Printer . UNKNOWN _STATE && newState == Printer . IDLE _STATE ) {
message . set ( "Printer connected" , Message . INFO , true ) ;
}
state = newState ;
hasControl = newHasControl ;
}
/ * * * * * * * * * *
*
* VARS
*
* * * * * * * * * * /
var preview ;
var previewCtx ;
var svgPathRegExp = /[LM]\d* \d*/ig ;
var svgPathParamsRegExp = /([LM])(\d*) (\d*)/ ;
var dragging = false ;
var $canvas , canvas , ctx ;
var canvasWidth , canvasHeight ;
var drawCanvas ;
var drawCanvasTopLeftCoords = [ 0 , 0 ] ;
var doodleBounds = [ - 1 , - 1 , - 1 , - 1 ] ; // left, top, right, bottom
// var doodleScaleVals = [[0, 0], [1.0, 1.0]]; // [ [x, y], [scaleX, scaleY] ]
var doodleTransform = [ 0 , 0 , 1.0 , 1.0 ] ; // [ x, y, scaleX, scaleY ]
var _points = [ ] ;
var prevCountingTime = 0 ;
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 ;
/ * * * * * * * * * *
*
* INIT
*
* * * * * * * * * * /
function initDoodleDrawing ( ) {
console . log ( "f:initDoodleDrawing()" ) ;
$canvas = $ ( "#mycanvas" ) ;
canvas = $canvas [ 0 ] ;
ctx = canvas . getContext ( '2d' ) ;
canvasWidth = canvas . width ;
canvasHeight = canvas . height ;
//*
//TODO make these jquery eventhandlers (works for all)
if ( ! canvas . addEventListener ) {
canvas . attachEvent ( 'onmousedown' , onCanvasMouseDown ) ;
canvas . attachEvent ( 'onmousemove' , onCanvasMouseMove ) ;
canvas . attachEvent ( 'onmouseup' , onCanvasMouseUp ) ;
canvas . attachEvent ( 'ontouchstart' , onCanvasTouchDown ) ;
canvas . attachEvent ( 'ontouchmove' , onCanvasTouchMove ) ;
canvas . attachEvent ( 'ontouchend' , onCanvasTouchEnd ) ;
document . body . attachEvent ( 'ontouchmove' , prevent ) ;
} else {
canvas . addEventListener ( 'mousedown' , onCanvasMouseDown , false ) ;
canvas . addEventListener ( 'mousemove' , onCanvasMouseMove , false ) ;
canvas . addEventListener ( 'mouseup' , onCanvasMouseUp , false ) ;
canvas . addEventListener ( 'touchstart' , onCanvasTouchDown , false ) ;
canvas . addEventListener ( 'touchmove' , onCanvasTouchMove , false ) ;
canvas . addEventListener ( 'touchend' , onCanvasTouchEnd , false ) ;
if ( ! debugMode ) document . body . addEventListener ( 'touchmove' , prevent , false ) ;
}
//*/
// drawCanvas = $(".drawareacontainer");
drawCanvas = $ ( "#mycanvasContainer" ) ; // $("#drawAreaContainer")
console . log ( "drawCanvasTopLeftCoords: " + drawCanvasTopLeftCoords ) ;
// drawCanvasTopLeftCoords[0] = drawCanvas.css("left").match(/[0-9]/g).join("");
// drawCanvasTopLeftCoords[1] = drawCanvas.css("top").match(/[0-9]/g).join("");
drawCanvasTopLeftCoords [ 0 ] = drawCanvas . offset ( ) . left ;
drawCanvasTopLeftCoords [ 1 ] = drawCanvas . offset ( ) . top ;
// drawCanvasTopLeftCoords[0] = drawCanvas[0].offsetParent.offsetLeft;
// drawCanvasTopLeftCoords[1] = drawCanvas[0].offsetParent.offsetTop;
console . log ( "f:initDoodleDrawing() >> canvasWidth: " + canvasWidth ) ;
console . log ( "f:initDoodleDrawing() >> canvasHeight: " + canvasHeight ) ;
}
/ * * * * * * * * * *
*
* CANVAS DRAWING FUNCTION
*
* * * * * * * * * * /
function draw ( _x , _y , _width ) {
// console.log("f:draw() >> _width: " + _width);
if ( prevX == 0 && prevY == 0 ) {
prevX = _x ;
prevY = _y ;
}
ctx . beginPath ( ) ;
ctx . moveTo ( prevX , prevY ) ;
ctx . lineTo ( _x , _y ) ;
if ( _width != undefined ) {
ctx . lineWidth = _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 ( ) ;
prevX = _x ;
prevY = _y ;
}
/ * * * * * * * * * *
*
* SUPPORTING FUNCTIONS
*
* * * * * * * * * * /
function clearDoodle ( ) {
console . log ( "f:clearDoodle" ) ;
_points = [ ] ;
prevX = 0 ;
prevY = 0 ;
updatePrevX = - 1 ;
updatePrevY = - 1 ;
doodleBounds = [ - 1 , - 1 , - 1 , - 1 ] ; // left, top, right, bottom
doodleTransform = [ 0 , 0 , 1.0 , 1.0 ] ; // [ x, y, scaleX, scaleY ]
dragging = false ;
clearMainView ( ) ;
resetPreview ( ) ;
resetVerticalShapes ( ) ;
}
function redrawDoodle ( ) {
console . log ( "f:redrawDoodle()" ) ;
clearMainView ( ) ;
prevX = 0 ;
prevY = 0 ;
for ( var i = 0 ; i < _points . length ; i ++ ) {
// console.log(" drawing points " + _points[i]);
if ( _points [ i ] [ 2 ] == true ) {
draw ( _points [ i ] [ 0 ] , _points [ i ] [ 1 ] , 0.5 ) ;
} else {
draw ( _points [ i ] [ 0 ] , _points [ i ] [ 1 ] ) ;
}
}
}
function adjustBounds ( x , y ) {
var newPointsOutsideOfCurrentBounds = false ;
console . log ( "f:adjustBounds(" + x + "," + y + ")" ) ;
if ( doodleBounds [ 0 ] == - 1 ) {
// if doodleBounds[0] is -1 then it isn't initted yet, so x and y are both the min and max vals
doodleBounds [ 0 ] = x ;
doodleBounds [ 1 ] = y ;
doodleBounds [ 2 ] = x ;
doodleBounds [ 3 ] = y ;
return ;
}
if ( x < doodleBounds [ 0 ] ) {
doodleBounds [ 0 ] = x ;
newPointsOutsideOfCurrentBounds = true ;
}
if ( x > doodleBounds [ 2 ] ) {
doodleBounds [ 2 ] = x ;
newPointsOutsideOfCurrentBounds = true ;
}
if ( y < doodleBounds [ 1 ] ) {
doodleBounds [ 1 ] = y ;
newPointsOutsideOfCurrentBounds = true ;
}
if ( y > doodleBounds [ 3 ] ) {
doodleBounds [ 3 ] = y ;
newPointsOutsideOfCurrentBounds = true ;
}
// doodleBounds[0] = Math.min(doodleBounds[0], x); // left
// doodleBounds[2] = Math.max(doodleBounds[2], x); // right
//
// doodleBounds[1] = Math.min(doodleBounds[1], y); // top
// doodleBounds[3] = Math.max(doodleBounds[3], y); // bottom
// draw the bounding rect (DEBUG)
/ *
ctx . beginPath ( ) ;
ctx . rect ( doodleBounds [ 0 ] , doodleBounds [ 1 ] , doodleBounds [ 2 ] - doodleBounds [ 0 ] , doodleBounds [ 3 ] - doodleBounds [ 1 ] ) ;
ctx . lineWidth = . 2 ;
ctx . strokeStyle = "#333"
ctx . stroke ( ) ;
ctx . closePath ( ) ;
//*/
// console.log(" new bounds: " + doodleBounds);
return newPointsOutsideOfCurrentBounds ;
}
// does what exactly?
function adjustPreviewTransformation ( ) {
// console.log("f:adjustPreviewTransformation()");
// doodleTransform[0] = doodleBounds[0] - (doodleBounds[2] - doodleBounds[0]) / 2;
// doodleTransform[1] = doodleBounds[1] - (doodleBounds[3] - doodleBounds[1]) / 2;
// doodleTransform[0] = doodleBounds[0] - ((doodleBounds[2] - doodleBounds[0]) / 2);
// doodleTransform[1] = doodleBounds[1] - ((doodleBounds[3] - doodleBounds[1]) / 2);
doodleTransform [ 0 ] = doodleBounds [ 0 ] ;
doodleTransform [ 1 ] = doodleBounds [ 1 ] ;
var sclX , sclY , finalScl ;
if ( _points . length < 2 ) {
// console.log(_points);
sclX = 1.0 ;
sclY = 1.0 ;
finalScl = Math . min ( sclX , sclY ) ;
} else {
sclX = canvasWidth / ( doodleBounds [ 2 ] - doodleBounds [ 0 ] ) ;
sclY = canvasHeight / ( doodleBounds [ 3 ] - doodleBounds [ 1 ] ) ;
// TODO this shouldn't be a matter if choosing the smallest but should probably involve maintaining aspect ratio??
finalScl = Math . min ( sclX , sclY ) ;
}
doodleTransform [ 2 ] = finalScl ;
doodleTransform [ 3 ] = finalScl ;
}
/ * * * * * * * * * *
*
* MOUSE / TOUCH EVENTHANDLERS
*
* * * * * * * * * * /
function onCanvasMouseDown ( e ) {
// console.log("onmousedown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY);
// console.log("onmousedown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY);
// console.log("onmousedown >> e: " + e);
// console.log(e);
// console.log("f:onCanvasMouseDown()");
dragging = true ;
prevCountingTime = new Date ( ) . getTime ( ) ;
movementCounter = 0
// _points.push([e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, true]);
// adjustBounds(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
// adjustPreviewTransformation();
// draw(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, 0.5);
var x , y ;
if ( e . offsetX != undefined ) {
x = e . offsetX ;
y = e . offsetY ;
} else {
x = e . layerX ;
y = e . layerY ;
}
// console.log(" x: " + x + ", y: " + y);
_points . push ( [ x , y , true ] ) ;
adjustBounds ( x , y ) ;
adjustPreviewTransformation ( ) ;
draw ( x , y , 0.5 ) ;
}
var prevPoint = { x : - 1 , y : - 1 } ;
function onCanvasMouseMove ( e ) {
// console.log("f:onCanvasMouseMove()");
if ( ! dragging ) return ;
// console.log("onmousemove");
var x , y ;
if ( e . offsetX != undefined ) {
x = e . offsetX ;
y = e . offsetY ;
} else {
x = e . layerX ;
y = e . layerY ;
}
if ( prevPoint . x != - 1 || prevPoint . y != - 1 ) {
var dist = Math . sqrt ( Math . pow ( ( prevPoint . x - x ) , 2 ) + Math . pow ( ( prevPoint . y - y ) , 2 ) ) ;
if ( dist > 5 ) { // replace 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 ] ) ;
adjustBounds ( x , y )
adjustPreviewTransformation ( ) ;
draw ( x , y ) ;
prevPoint . x = x ;
prevPoint . y = y ;
}
// DEBUG
// $("#textdump").text("");
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
// $("#textdump").append("doodletransform:" + doodleTransform + "\n");
if ( new Date ( ) . getTime ( ) - prevRedrawTime > redrawInterval ) {
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
prevRedrawTime = new Date ( ) . getTime ( ) ;
if ( _points . length < 50 ) {
redrawPreview ( ) ;
} else {
updatePreview ( x , y , true ) ;
/ *
if ( _points . length - prevUpdateFullPreview > prevUpdateFullPreviewInterval ) {
console . log ( "f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview" ) ;
redrawPreview ( ) ;
prevUpdateFullPreview = _points . length ;
} else {
updatePreview ( x , y , true ) ;
}
//*/
// redrawPreview();
}
}
}
prevUpdateFullPreview = 0 ; // 0 is not a timeframe but refers to the _points array
prevUpdateFullPreviewInterval = 25 ; // refers to number of points, not a timeframe
function onCanvasMouseUp ( e ) {
// console.log("f:onCanvasMouseUp()");
// console.log("onmouseup");
dragging = false ;
console . log ( "doodleBounds: " + doodleBounds ) ;
console . log ( "doodleTransform: " + doodleTransform ) ;
// ctx.stroke();
console . log ( "_points.length :" + _points . length ) ;
// console.log(_points);
// DEBUG
// $("#textdump").text("");
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
// $("#textdump").append("doodletransform:" + doodleTransform + "\n");
// redrawPreview();
renderToImageDataPreview ( ) ;
}
function onCanvasTouchDown ( e ) {
e . preventDefault ( ) ;
console . log ( "f:onCanvasTouchDown >> e: " , e ) ;
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
var x = e . touches [ 0 ] . pageX - drawCanvasTopLeftCoords [ 0 ] ;
var y = e . touches [ 0 ] . pageY - drawCanvasTopLeftCoords [ 1 ] ;
// var x = e.touches[0].pageX;
// var y = e.touches[0].pageY;
// var x = e.touches[0].layerX;
// var y = e.touches[0].layerY;
_points . push ( [ x , y , true ] ) ;
adjustBounds ( x , y ) ;
adjustPreviewTransformation ( ) ;
draw ( x , y , . 5 ) ;
movementCounter = 0 ;
prevRedrawTime = new Date ( ) . getTime ( ) ;
}
function onCanvasTouchMove ( e ) {
e . preventDefault ( ) ;
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
var x = e . touches [ 0 ] . pageX - drawCanvasTopLeftCoords [ 0 ] ;
var y = e . touches [ 0 ] . pageY - drawCanvasTopLeftCoords [ 1 ] ;
// var x = e.touches[0].layerX;
// var y = e.touches[0].layerY;
// var x = e.touches[0].layerX;
// var y = e.touches[0].layerY;
console . log ( "f:onCanvasTouchMove >> x,y = " + x + "," + y + " , e: " , e ) ;
if ( prevPoint . x != - 1 || prevPoint . y != - 1 ) {
var dist = Math . sqrt ( Math . pow ( ( prevPoint . x - x ) , 2 ) + Math . pow ( ( prevPoint . y - y ) , 2 ) ) ;
if ( dist > 5 ) {
_points . push ( [ x , y , false ] ) ;
adjustBounds ( x , y )
adjustPreviewTransformation ( ) ;
draw ( x , y ) ;
prevPoint . x = x ;
prevPoint . y = y ;
}
} else {
_points . push ( [ x , y , false ] ) ;
adjustBounds ( x , y )
adjustPreviewTransformation ( ) ;
draw ( x , y ) ;
prevPoint . x = x ;
prevPoint . y = y ;
}
// update counter -> this was for getting a handle on how often the Canvas fires a move-event
/ *
movementCounter ++ ;
if ( new Date ( ) . getTime ( ) - prevCountingTime > 1000 ) {
// console.log("number of moves in 1sec: " + movementCounter)
prevCountingTime = new Date ( ) . getTime ( ) ;
$ ( "#numtimes" ) . text ( movementCounter + " times" ) ;
movementCounter = 0 ;
}
//*/
if ( new Date ( ) . getTime ( ) - prevRedrawTime > redrawInterval ) {
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
if ( _points . length < 50 ) {
redrawPreview ( ) ;
} else {
updatePreview ( x , y , true ) ;
/ *
if ( _points . length - prevUpdateFullPreview > prevUpdateFullPreviewInterval ) {
console . log ( "f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview" ) ;
redrawPreview ( ) ;
prevUpdateFullPreview = _points . length ;
} else {
updatePreview ( x , y , true ) ;
}
//*/
}
prevRedrawTime = new Date ( ) . getTime ( ) ;
}
}
function onCanvasTouchEnd ( e ) {
console . log ( "f:onCanvasTouchEnd()" ) ;
console . log ( "doodleBounds: " + doodleBounds ) ;
console . log ( "doodleTransform: " + doodleTransform ) ;
// ctx.stroke();
console . log ( "_points.length :" + _points . length ) ;
// redrawPreview();
renderToImageDataPreview ( ) ;
}
function prevent ( e ) {
e . preventDefault ( ) ;
}
//*
var $preview ;
var preview ;
var previewCtx ;
var preview _tmp ;
var previewCtx _tmp ;
var previewDefaults = {
rotation : Math . PI / 90 ,
numLayers : 10
}
var svgPathRegExp = /[LM]\d* \d*/ig ;
var svgPathParamsRegExp = /([LM])(\d*) (\d*)/ ;
var prevRedrawTime = new Date ( ) . getTime ( ) ;
var redrawInterval = 1000 / 30 ; // ms
function initPreviewRendering ( ) {
console . log ( "f:initPreviewRendering()" ) ;
$preview = $ ( "#preview" ) ;
preview = $preview [ 0 ] ;
previewCtx = preview . getContext ( '2d' ) ;
// DEBUG --> mbt preview_tmp (voor de toImageData truc)
var _ratio = preview . width / canvas . width ;
preview _tmp = document . getElementById ( 'preview_tmp' ) ;
preview _tmp . width = preview . width ;
preview _tmp . height = canvas . height * _ratio ;
$ ( "#preview_tmp" ) . css ( "top" , - preview _tmp . height ) ;
previewCtx _tmp = preview _tmp . getContext ( '2d' ) ;
calcPreviewCanvasProperties ( ) ;
redrawPreview ( ) ;
}
function calcPreviewCanvasProperties ( ) {
console . log ( "f:calcPreviewCanvasProperties()" ) ;
globalScale = preview . width / canvasWidth ;
layerCX = ( canvasWidth / 2 ) * globalScale ; // defined in canvasDrawing_v01.js
layerCY = ( canvasHeight / 2 ) * globalScale ; // defined in canvasDrawing_v01.js
// layerOffsetY = preview.height - 1.75 * layerCY;
layerOffsetY = preview . height * ( 1 - previewVerticalPadding . bottom ) ;
yStep = ( preview . height - ( preview . height * ( previewVerticalPadding . top + previewVerticalPadding . bottom ) ) ) / maxNumLayers ;
}
// TODO (perhaps) : make the twist limit dynamic, depending on what's printable (w.r.t. overlapping)
var previewRotationLimit = Math . PI / 30 ; // rough estimate
var numLayers = previewDefaults . numLayers ; // current number of preview layers
var maxNumLayers = 100 ; // maximum number of preview layers
var minNumLayers = 2 ; // minimum number of preview layers
var globalScale = 0.3 ; // global scale of preview (width preview / width canvas)
var globalAlpha = 0.20 ; // global alpha of preview
var scaleY = 0.4 ; // additional vertical scale per path for 3d effect
var viewerScale = 0.65 ; // additional scale to fit into preview nicely (otherwise is fills out totally)
var previewVerticalPadding = { "top" : . 15 , "bottom" : 0.12 } ; // %
var strokeWidth = 2 ; //4;
//var rStep = Math.PI/40; //Math.PI/40; //
var rStep = previewDefaults . rotation ; // Math.PI/180; //Math.PI/40; //
var yStep ; // = preview.height / 150; // 3; //6;
//var svgWidth = 500; // 650 //parseInt($(svg).css("width"));
//var svgHeight = 450; //450; //parseInt($(svg).css("height"));
var layerCX , layerCY ;
//var layerCX = (canvasWidth / 2) * globalScale; // defined in canvasDrawing_v01.js
//var layerCY = (canvasHeight / 2) * globalScale; // defined in canvasDrawing_v01.js
var layerOffsetY ; //= preview.height - 1.75 * layerCY; // 330; // previewHeight - 120
var prevX = 0 ;
var prevY = 0 ;
var highlight = true ; //highlight bottom, middle and top layers
var linesRaw = "" ;
var debug _redrawSimplification = 6 ;
function redrawPreview ( redrawLess ) {
if ( redrawLess == undefined ) redrawLess = false ;
if ( _points . length < 2 ) return ;
if ( ! redrawLess ) {
//debug_redrawSimplification = Math.round(_points.length / 65);
//*
if ( _points . length < 100 ) {
debug _redrawSimplification = 6 ;
} else if ( _points . length < 250 ) {
debug _redrawSimplification = 7 ;
} else if ( _points . length < 400 ) {
debug _redrawSimplification = 8 ;
} else if ( _points . length < 550 ) {
debug _redrawSimplification = 9 ;
} else if ( _points . length < 700 ) {
debug _redrawSimplification = 10 ;
} else {
debug _redrawSimplification = 11 ;
}
//*/
// console.log("debug_redrawSimplification: " + debug_redrawSimplification);
}
var y = 0 ;
var r = 0 ;
//preview.width = preview.width;
previewCtx . clearRect ( 0 , 0 , preview . width , preview . height ) ;
previewCtx . lineWidth = strokeWidth ;
previewCtx . strokeStyle = '#f00' ; //"rgba(255,255,0,0)";
for ( var i = 0 ; i < numLayers ; i ++ ) {
var verticalScaleFactor = scaleFunction ( i / maxNumLayers ) ;
if ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) {
previewCtx . globalAlpha = 1 ;
} else {
previewCtx . globalAlpha = globalAlpha ;
}
if ( redrawLess && i % debug _redrawSimplification != 0 && ! ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) ) {
y -= yStep ;
r += rStep ;
continue ;
}
previewCtx . save ( ) ;
// previewCtx.translate(layerCX, layerOffsetY + layerCY + y);
previewCtx . translate ( layerCX , layerOffsetY + y ) ;
// previewCtx.setTransform(1, 0, 0, scaleY, layerCX, layerOffsetY+layerCY+y);
previewCtx . scale ( viewerScale * verticalScaleFactor , scaleY * viewerScale * verticalScaleFactor ) ;
previewCtx . rotate ( r ) ;
previewCtx . translate ( ( - doodleTransform [ 0 ] ) * ( globalScale * doodleTransform [ 2 ] ) , ( - doodleTransform [ 1 ] ) * ( globalScale * doodleTransform [ 3 ] ) ) ;
var adjustedDoodlePoint = centeredAndScaledDoodlePoint ( _points [ 0 ] ) ;
previewCtx . beginPath ( ) ;
previewCtx . moveTo ( adjustedDoodlePoint . x , adjustedDoodlePoint . y ) ;
for ( var j = 1 ; j < _points . length ; j ++ ) {
adjustedDoodlePoint = centeredAndScaledDoodlePoint ( _points [ j ] )
if ( redrawLess && j % debug _redrawSimplification != 0 ) continue ;
previewCtx . lineTo ( adjustedDoodlePoint . x , adjustedDoodlePoint . y ) ;
}
previewCtx . stroke ( ) ;
y -= yStep ;
r += rStep ;
previewCtx . restore ( ) ;
}
previewCtx . globalAlpha = globalAlpha ;
}
function renderToImageDataPreview ( ) {
console . log ( "f:renderToImageDataPreview()" ) ;
if ( _points . length < 2 ) return ;
//*
// the first step
previewCtx _tmp . clearRect ( 0 , 0 , preview . width , preview . height ) ;
previewCtx _tmp . lineWidth = strokeWidth ;
previewCtx _tmp . strokeStyle = '#f00' ; //"rgba(255,255,0,0)";
previewCtx _tmp . save ( ) ;
previewCtx _tmp . translate ( layerCX , layerCY ) ;
previewCtx _tmp . scale ( viewerScale , viewerScale ) ;
previewCtx _tmp . translate ( ( - doodleTransform [ 0 ] ) * ( globalScale * doodleTransform [ 2 ] ) , ( - doodleTransform [ 1 ] ) * ( globalScale * doodleTransform [ 3 ] ) ) ;
var adjustedDoodlePt = centeredAndScaledDoodlePoint ( _points [ 0 ] ) ;
previewCtx _tmp . beginPath ( ) ;
previewCtx _tmp . moveTo ( adjustedDoodlePt . x , adjustedDoodlePt . y ) ;
for ( var j = 1 ; j < _points . length ; j ++ ) {
adjustedDoodlePt = centeredAndScaledDoodlePoint ( _points [ j ] )
previewCtx _tmp . lineTo ( adjustedDoodlePt . x , adjustedDoodlePt . y ) ;
}
previewCtx _tmp . stroke ( ) ;
previewCtx _tmp . closePath ( ) ;
previewCtx _tmp . restore ( ) ;
//*/
// var saved_rect = previewCtx_tmp.getImageData(0, 0, layerCX*2, layerCY*2);
var saved _rect _todataurl = preview _tmp . toDataURL ( ) ;
doodleImageCapture = new Image ( ) ;
doodleImageCapture . onload = function ( ) {
previewCtx . clearRect ( 0 , 0 , preview . width , preview . height ) ;
previewCtx . lineWidth = strokeWidth ;
previewCtx . strokeStyle = '#f00' ; //"rgba(255,255,0,0)";
var y = 0 ;
var r = 0 ;
for ( var i = 0 ; i < numLayers ; i ++ ) {
var verticalScaleFactor = scaleFunction ( i / maxNumLayers ) ;
if ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) {
previewCtx . globalAlpha = 1 ;
} else {
previewCtx . globalAlpha = globalAlpha ;
}
previewCtx . save ( ) ;
previewCtx . translate ( layerCX , layerOffsetY + y ) ;
// previewCtx.scale(1, scaleY)
previewCtx . scale ( verticalScaleFactor , scaleY * verticalScaleFactor )
previewCtx . rotate ( r ) ;
previewCtx . translate ( - layerCX , - layerCY ) ;
previewCtx . drawImage ( doodleImageCapture , 0 , 0 ) ;
y -= yStep ;
r += rStep ;
previewCtx . restore ( ) ;
}
} ;
doodleImageCapture . src = saved _rect _todataurl ;
previewCtx . globalAlpha = globalAlpha ;
}
// called by the move up/down or twist left/right buttons
// it is assumed that the preview has been rendered to an Image object, which will be used to draw the preview with (much better performance)
function redrawRenderedPreview ( redrawLess ) {
if ( redrawLess == undefined ) redrawLess = false ;
console . log ( "f:redrawRenderedPreview()" ) ;
previewCtx . clearRect ( 0 , 0 , preview . width , preview . height ) ;
previewCtx . lineWidth = strokeWidth ;
previewCtx . strokeStyle = '#f00' ; //"rgba(255,255,0,0)";
var y = 0 ;
var r = 0 ;
for ( var i = 0 ; i < numLayers ; i ++ ) {
var verticalScaleFactor = scaleFunction ( i / maxNumLayers ) ;
if ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) {
previewCtx . globalAlpha = 1 ;
} else {
previewCtx . globalAlpha = globalAlpha ;
}
if ( redrawLess && i % 2 != 0 && ! ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) ) {
y -= yStep ;
r += rStep ;
continue ;
}
previewCtx . save ( ) ;
previewCtx . translate ( layerCX , layerOffsetY + y ) ;
// previewCtx.scale(1, scaleY)
previewCtx . scale ( verticalScaleFactor , scaleY * verticalScaleFactor ) ;
previewCtx . rotate ( r ) ;
previewCtx . translate ( - layerCX , - layerCY ) ;
previewCtx . drawImage ( doodleImageCapture , 0 , 0 ) ;
y -= yStep ;
r += rStep ;
previewCtx . restore ( ) ;
}
}
function centeredAndScaledDoodlePoint ( p ) {
var obj = { x : 0 , y : 0 } ;
obj . x = ( p [ 0 ] - ( ( doodleBounds [ 2 ] - doodleBounds [ 0 ] ) / 2 ) ) * ( globalScale * doodleTransform [ 2 ] ) ;
obj . y = ( p [ 1 ] - ( ( doodleBounds [ 3 ] - doodleBounds [ 1 ] ) / 2 ) ) * ( globalScale * doodleTransform [ 3 ] ) ;
// obj.x = (p[0] - (doodleBounds[2] - doodleBounds[0])) * (globalScale * doodleTransform[2]);
// obj.y = (p[1] - (doodleBounds[3] - doodleBounds[1])) * (globalScale * doodleTransform[3]);
// obj.x = (p[0] - doodleTransform[0]) * (globalScale * doodleTransform[2]);
// obj.y = (p[1] - doodleTransform[1]) * (globalScale * doodleTransform[3]);
return obj ;
}
//*
var updatePrevX = - 1 ;
var updatePrevY = - 1 ;
function updatePreview ( _x , _y , redrawLess ) {
if ( redrawLess == undefined ) redrawLess = false ;
redrawLess = false ;
if ( _points . length < 2 ) return ;
if ( updatePrevX == - 1 || updatePrevY == - 1 ) {
updatePrevX = _x ;
updatePrevY = _y ;
return ;
}
// if (_points.length < 16 && Math.sqrt(Math.pow((updatePrevX - _x), 2) + Math.pow((updatePrevY - _y), 2)) < 8) return;
var y = 0 ;
var r = 0 ;
previewCtx . lineWidth = strokeWidth ;
previewCtx . strokeStyle = '#f00' ; //"rgba(255,255,0,0)";
for ( var i = 0 ; i < numLayers ; i ++ ) {
if ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) {
previewCtx . globalAlpha = 1 ;
} else {
previewCtx . globalAlpha = globalAlpha ;
}
if ( redrawLess && i % debug _redrawSimplification != 0 && ! ( i == 0 || i == Math . floor ( numLayers / 2 ) || i == numLayers - 1 ) ) {
y -= yStep ;
r += rStep ;
continue ;
}
previewCtx . save ( ) ;
// previewCtx.translate(layerCX, layerOffsetY + layerCY + y);
previewCtx . translate ( layerCX , layerOffsetY + y ) ;
previewCtx . scale ( viewerScale , scaleY * viewerScale ) ;
previewCtx . rotate ( r ) ;
previewCtx . translate ( ( - doodleTransform [ 0 ] ) * ( globalScale * doodleTransform [ 2 ] ) , ( - doodleTransform [ 1 ] ) * ( globalScale * doodleTransform [ 3 ] ) ) ;
previewCtx . beginPath ( ) ;
var prevPoint = centeredAndScaledDoodlePoint ( [ updatePrevX , updatePrevY ] ) ;
previewCtx . moveTo ( prevPoint . x , prevPoint . y ) ;
var adjustedDoodlePoint = centeredAndScaledDoodlePoint ( [ _x , _y ] ) ;
previewCtx . lineTo ( adjustedDoodlePoint . x , adjustedDoodlePoint . y ) ;
previewCtx . stroke ( ) ;
y -= yStep ;
r += rStep ;
previewCtx . restore ( ) ;
}
previewCtx . globalAlpha = globalAlpha ;
updatePrevX = _x ;
updatePrevY = _y ;
}
//*/
/ * v a r g c o d e S t a r t = [ ] ;
gcodeStart . push ( ";Generated with Doodle3D" ) ;
gcodeStart . push ( "G21" ) ; // metric values
gcodeStart . push ( "G91" ) ; // relative positioning
gcodeStart . push ( "M107" ) ; // start with the fan off
gcodeStart . push ( "G28 X0 Y0" ) ; // move X/Y to min endstops
gcodeStart . push ( "G28 Z0" ) ; // move Z to min endstops
gcodeStart . push ( "G1 Z15 F9000" ) ; // move the platform down 15mm
gcodeStart . push ( "G92 E0" ) ; // zero the extruded length
gcodeStart . push ( "G1 F200 E10" ) ; // extrude 10mm of feed stock
gcodeStart . push ( "G92 E0" ) ; // zero the extruded length again
//gcodeStart.push("G92 X-100 Y-100 E0"); // zero the extruded length again and make center the start position
gcodeStart . push ( "G1 F9000" ) ;
gcodeStart . push ( "G90" ) ; // absolute positioning
gcodeStart . push ( "M117 Printing Doodle... " ) ; // display message (20 characters to clear whole screen)
var gcodeEnd = [ ] ;
gcodeEnd . push ( "M107" ) ; // fan off
gcodeEnd . push ( "G91" ) ; // relative positioning
gcodeEnd . push ( "G1 E-1 F300" ) ; // retract the filament a bit before lifting the nozzle, to release some of the pressure
gcodeEnd . push ( "G1 Z+0.5 E-5 X-20 Y-20 F9000" ) ; // move Z up a bit and retract filament even more
gcodeEnd . push ( "G28 X0 Y0" ) ; // move X/Y to min endstops, so the head is out of the way
gcodeEnd . push ( "M84" ) ; // disable axes / steppers
gcodeEnd . push ( "G90" ) ; // absolute positioning
gcodeEnd . push ( "M117 Done " ) ; // display message (20 characters to clear whole screen)*/
var MAX _POINTS _TO _PRINT = 400000 ; //80000; //40000;
var gcode = [ ] ;
function generate _gcode ( ) {
console . log ( "f:generategcode()" ) ;
// TODO 2013-09-18 evaluate if this should stay here
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
var gCodeOffsetX = 110 ; // mm
var gCodeOffsetY = 110 ; // mm
gcode = [ ] ;
console . log ( "settings: " , settings ) ;
var speed = settings [ "printer.speed" ]
var normalSpeed = speed ;
var bottomSpeed = speed * 0.5 ;
var travelSpeed = settings [ "printer.travelSpeed" ]
var filamentThickness = settings [ "printer.filamentThickness" ] ;
var wallThickness = settings [ "printer.wallThickness" ] ;
var screenToMillimeterScale = settings [ "printer.screenToMillimeterScale" ] ;
var layerHeight = settings [ "printer.layerHeight" ] ;
var maxObjectHeight = settings [ "printer.maxObjectHeight" ] ;
var temperature = settings [ "printer.temperature" ] ;
2013-10-22 15:33:08 +02:00
var bedTemperature = settings [ "printer.bed.temperature" ] ;
2013-10-22 12:04:46 +02:00
var useSubLayers = settings [ "printer.useSubLayers" ] ;
var enableTraveling = settings [ "printer.enableTraveling" ] ;
var retractionEnabled = settings [ "printer.retraction.enabled" ] ;
var retractionspeed = settings [ "printer.retraction.speed" ] ;
var retractionminDistance = settings [ "printer.retraction.minDistance" ] ;
var retractionamount = settings [ "printer.retraction.amount" ] ;
var preheatTemperature = settings [ "printer.heatup.temperature" ] ;
2013-10-22 15:33:08 +02:00
var preheatBedTemperature = settings [ "printer.heatup.bed.temperature" ] ;
2013-10-22 12:04:46 +02:00
var startGcode = settings [ "printer.startgcode" ] ;
2013-10-22 15:33:08 +02:00
startGcode = subsituteVariables ( startGcode , temperature , bedTemperature , preheatTemperature , preheatBedTemperature ) ;
2013-10-22 12:04:46 +02:00
startGcode = startGcode . split ( "\n" ) ;
var endGcode = settings [ "printer.endgcode" ] ;
2013-10-22 15:33:08 +02:00
endGcode = subsituteVariables ( endGcode , temperature , bedTemperature , preheatTemperature , preheatBedTemperature ) ;
2013-10-22 12:04:46 +02:00
endGcode = endGcode . split ( "\n" ) ;
/ *
console . log ( "f:generate_gcode >> EFFE CHECKEN:" ) ;
console . log ( " speed: " + speed ) ;
console . log ( " travelSpeed: " + travelSpeed ) ;
console . log ( " filamentThickness: " + filamentThickness ) ;
console . log ( " wallThickness: " + wallThickness ) ;
console . log ( " screenToMillimeterScale: " + screenToMillimeterScale ) ;
console . log ( " layerHeight: " + layerHeight ) ;
console . log ( " objectHeight: " + objectHeight ) ;
console . log ( " maxObjectHeight: " + maxObjectHeight ) ;
console . log ( " temperature: " + temperature ) ;
console . log ( " maxObjectHeight: " + maxObjectHeight ) ;
console . log ( " useSubLayers: " + useSubLayers ) ;
console . log ( " enableTraveling: " + enableTraveling ) ;
console . log ( " retractionspeed: " + retractionspeed ) ;
console . log ( " retractionminDistance: " + retractionminDistance ) ;
console . log ( " retractionamount: " + retractionamount ) ;
console . log ( "" ) ;
//*/
// max amount of real world layers
var layers = maxObjectHeight / layerHeight ; //maxObjectHeight instead of objectHeight
// translate numLayers in preview to objectHeight in real world
//objectHeight = Math.ceil(numLayers / 5); // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
//objectHeight = numLayers; // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
objectHeight = Math . round ( numLayers / maxNumLayers * maxObjectHeight ) ;
// translate preview rotation (per layer) to real world rotation
var rStepGCode = rStep * maxNumLayers / layers ; ///maxNumLayers*maxObjectHeight;
// correct direction
rStepGCode = - rStepGCode ;
// todo hier een array van PATHS maken wat de losse paths zijn
// copy array without reference -> http://stackoverflow.com/questions/9885821/copying-of-an-array-of-objects-to-another-array-without-object-reference-in-java
var points = JSON . parse ( JSON . stringify ( _points ) ) ;
// console.log("f:generategcode() >> paths: " + paths.toString());
// console.log("paths.toString(): " + paths.toString());
// return;
//gcode.push("M104 S" + temperature); // set target temperature and do not wait for the extruder to reach it
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
// add gcode begin commands
gcode = gcode . concat ( startGcode ) ;
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
var layers = maxObjectHeight / layerHeight ; //maxObjectHeight instead of objectHeight
var extruder = 0.0 ;
var prev = new Point ( ) ; prev . set ( 0 , 0 ) ;
// replacement (and improvement) for ofxGetCenterofMass
var centerOfDoodle = {
x : doodleBounds [ 0 ] + ( doodleBounds [ 2 ] - doodleBounds [ 0 ] ) / 2 ,
y : doodleBounds [ 1 ] + ( doodleBounds [ 3 ] - doodleBounds [ 1 ] ) / 2
// x: doodleBounds[0],
// y: doodleBounds[1]
}
console . log ( "f:generategcode() >> layers: " + layers ) ;
if ( layers == Infinity ) return ;
// check feasibility of design
var pointsToPrint = points . length * layers * ( objectHeight / maxObjectHeight )
//console.log(" points.length: ",points.length);
//console.log(" numLayers: ",(layers*(objectHeight/maxObjectHeight)));
//console.log(" pointsToPrint: ",pointsToPrint);
//console.log(" MAX_POINTS_TO_PRINT: ",MAX_POINTS_TO_PRINT);
if ( pointsToPrint > MAX _POINTS _TO _PRINT ) {
alert ( "Sorry, your doodle to to complex and / or to high" ) ;
console . log ( "WARNING: to many points to convert to gcode" ) ;
return [ ] ;
}
for ( var layer = 0 ; layer < layers ; layer ++ ) {
var p = JSON . parse ( JSON . stringify ( points ) ) ; // [].concat(points);
if ( p . length < 2 ) return ;
var even = ( layer % 2 == 0 ) ;
var progress = layer / layers ;
// float layerScale = scaleFunction(float(layer)/layers); // scaleFactor van de layer -> lookup naar vfunc[] voor die scaleVals
// var layerScale = 1.0;
var layerScale = scaleFunction ( progress ) ;
// if begin point this row and end point last row are close enough, isLoop is true
var isLoop = lineLength ( points [ 0 ] [ 0 ] , points [ 0 ] [ 1 ] , points [ points . length - 1 ] [ 0 ] , points [ points . length - 1 ] [ 1 ] ) < 3 ;
// set center of doodle as middle (ie subtract to that)
pointsTranslate ( p , - centerOfDoodle . x , - centerOfDoodle . y ) ;
pointsScale ( p , screenToMillimeterScale , - screenToMillimeterScale ) ;
pointsScale ( p , layerScale , layerScale ) ;
// sort-of in de buurt van (360/2.5)
// // -> aight.. er zijn 750 lines vs 1000 in de d3d app. 135 = .75 * 180... dit kan je nog rechttrekken als je NET wat slimmer nadenkt :)
// update: NEE, het is niet .75 * 180 want 135 was niet de beste value.
//pointsRotate(p, rStep * progress * 139);
pointsRotate ( p , rStepGCode * layer ) ;
if ( layer == 0 ) {
//gcode.push("M107"); //fan off
if ( firstLayerSlow ) {
//gcode.push("M220 S20"); //slow speed
speed = bottomSpeed ;
//console.log("> speed: ",speed);
}
} else if ( layer == 2 ) { ////////LET OP, pas bij layer 2 weer op normale snelheid ipv layer 1
gcode . push ( "M106" ) ; //fan on
//gcode.push("M220 S100"); //normal speed
speed = normalSpeed ;
//console.log("> speed: ",speed);
}
var curLayerCommand = 0 ;
var totalLayerCommands = p . length ;
var layerProgress = 0 ;
var paths = [ ] ;
var pathCounter = - 1 ;
// var points = [];
for ( var i = 0 ; i < p . length ; i ++ ) {
if ( p [ i ] [ 2 ] == true ) {
pathCounter ++ ;
paths . push ( [ ] ) ;
paths [ pathCounter ] . push ( [ p [ i ] [ 0 ] , p [ i ] [ 1 ] ] ) ;
} else {
paths [ pathCounter ] . push ( [ p [ i ] [ 0 ] , p [ i ] [ 1 ] ] ) ;
}
}
// console.log("f:generategcode() >> paths.length: " + paths.length);
// loop over the subpaths (the separately drawn lines)
for ( var j = 0 ; j < paths . length ; j ++ ) { // TODO paths > subpaths
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
// vector<ofSubPath::Command> &commands = subpaths[even ? j : subpaths.size()-1-j].getCommands();
var commands = paths [ j ] ; //commands zijn alle points uit subpath j // TODO commands > subpathPoints
// loop over the coordinates of the subpath
for ( var i = 0 ; i < commands . length ; i ++ ) {
var last = commands . length - 1 ;
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
// ofPoint to = commands[(even || isLoop || loopAlways) ? i : last-i].to;
var to = new Point ( ) ; to . set ( commands [ i ] [ 0 ] , commands [ i ] [ 1 ] ) ;
// TODO 2013-09-18 evaluate if this should stay..
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
to . x += gCodeOffsetX ;
to . y += gCodeOffsetY ;
var sublayer = ( layer == 0 ) ? 0.0 : layer + ( useSubLayers ? ( curLayerCommand / totalLayerCommands ) : 0 ) ;
var z = ( sublayer + 1 ) * layerHeight ; // 2013-09-06 removed zOffset (seemed to be useless)
var isTraveling = ! isLoop && i == 0 ;
var doRetract = retractionEnabled && prev . distance ( to ) > retractionminDistance ;
if ( enableTraveling && isTraveling ) {
// console.log("enableTraveling && isTraveling >> doRetract: " + doRetract + ", retractionspeed: " + retractionspeed);
if ( doRetract ) gcode . push ( "G0 E" + ( extruder - retractionamount ) . toFixed ( 3 ) + " F" + ( retractionspeed * 60 ) . toFixed ( 3 ) ) ; //retract
gcode . push ( "G0 X" + to . x . toFixed ( 3 ) + " Y" + to . y . toFixed ( 3 ) + " Z" + z . toFixed ( 3 ) + " F" + ( travelSpeed * 60 ) . toFixed ( 3 ) ) ;
if ( doRetract ) gcode . push ( "G0 E" + extruder . toFixed ( 3 ) + " F" + ( retractionspeed * 60 ) . toFixed ( 3 ) ) ; // return to normal
} else {
// console.log(" else");
//extruder += prev.distance(to) * wallThickness * layerHeight / filamentThickness;
extruder += prev . distance ( to ) * wallThickness * layerHeight / ( Math . pow ( ( filamentThickness / 2 ) , 2 ) * Math . PI ) ;
gcode . push ( "G1 X" + to . x . toFixed ( 3 ) + " Y" + to . y . toFixed ( 3 ) + " Z" + z . toFixed ( 3 ) + " F" + ( speed * 60 ) . toFixed ( 3 ) + " E" + extruder . toFixed ( 3 ) ) ;
}
curLayerCommand ++ ;
layerProgress = curLayerCommand / totalLayerCommands ;
prev = to ;
}
}
if ( ( layer / layers ) > ( objectHeight / maxObjectHeight ) ) {
console . log ( "f:generategcode() >> (layer/layers) > (objectHeight/maxObjectHeight) is true -> breaking at layer " + ( layer + 1 ) ) ;
break ;
}
}
// add gcode end commands
gcode = gcode . concat ( endGcode ) ;
return gcode ;
}
2013-10-22 15:33:08 +02:00
function subsituteVariables ( gcode , temperature , bedTemperature , preheatTemperature , preheatBedTemperature ) {
gcode = gcode . replace ( /{printingTemp}/gi , temperature ) ;
gcode = gcode . replace ( /{printingBedTemp}/gi , bedTemperature ) ;
gcode = gcode . replace ( /{preheatTemp}/gi , preheatTemperature ) ;
gcode = gcode . replace ( /{preheatBedTemp}/gi , preheatBedTemperature ) ;
return gcode ;
}
2013-10-22 12:04:46 +02:00
function scaleFunction ( percent ) {
var r = 1.0 ;
switch ( VERTICALSHAPE ) {
case verticalShapes . NONE :
r = 1.0 ;
break ;
case verticalShapes . DIVERGING :
r = . 5 + ( percent * . 5 ) ;
break ;
case verticalShapes . CONVERGING :
r = 1.0 - ( percent * . 8 ) ;
break ;
case verticalShapes . SINUS :
r = ( Math . cos ( percent * Math . PI * 4 ) * . 25 ) + . 75 ;
break ;
}
// return 1.0 - (percent *.8);
return r ;
}
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 ;
}
}
// rotates around point 0,0 (origin).
// Not the prettiest kind of rotation solution but in our case we're assuming that the points have just been translated to origin
pointsRotate = function ( p , ang ) {
var _ang , dist ;
for ( var i = 0 ; i < p . length ; i ++ ) {
dist = Math . sqrt ( p [ i ] [ 0 ] * p [ i ] [ 0 ] + p [ i ] [ 1 ] * p [ i ] [ 1 ] ) ;
_ang = Math . atan2 ( p [ i ] [ 1 ] , p [ i ] [ 0 ] ) ;
p [ i ] [ 0 ] = Math . cos ( _ang + ang ) * dist ;
p [ i ] [ 1 ] = Math . sin ( _ang + ang ) * dist ;
}
}
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/math/line-length [rev. #1]
lineLength = function ( x , y , x0 , y0 ) {
return Math . sqrt ( ( x -= x0 ) * x + ( y -= y0 ) * y ) ;
} ;
var Point = function ( ) { } ;
Point . prototype = {
x : 0 ,
y : 0 ,
set : function ( _x , _y ) {
this . x = _x ;
this . y = _y ;
} ,
distance : function ( p ) {
var d = - 1 ;
if ( p instanceof Point ) {
d = Math . sqrt ( ( p . x - this . x ) * ( p . x - this . x ) + ( p . y - this . y ) * ( p . y - this . y ) ) ;
}
return d ;
} ,
toString : function ( ) {
console . log ( "x:" + this . x + ", y:" + this . y ) ;
}
}
// TODO refactor this stuff, there's much to wipe
var drawAreaContainerMinHeight = 300 ;
var drawAreaContainerMaxHeight = 450 ;
function doOnResize ( ) {
// console.log("doOnResize() >> " + new Date().getTime());
canvas . width = $canvas . width ( ) ;
canvas . height = $canvas . height ( ) ; // canvas.clientHeight;
preview . width = $preview . width ( ) ;
preview . height = $drawAreaContainer . height ( ) ;
canvasWidth = canvas . width ;
canvasHeight = canvas . height ;
console . log ( " preview.width: " + preview . width + ", $preview.width(): " + $preview . width ( ) ) ;
calcPreviewCanvasProperties ( ) ;
drawCanvasTopLeftCoords [ 0 ] = drawCanvas . offset ( ) . left ;
drawCanvasTopLeftCoords [ 1 ] = drawCanvas . offset ( ) . top ;
redrawDoodle ( ) ;
redrawPreview ( ) ;
}
function initLayouting ( ) {
console . log ( "f:initLayouting()" ) ;
$drawAreaContainer = $ ( ".drawareacontainer" ) ;
canvas . width = $canvas . width ( ) ;
canvas . height = $canvas . height ( ) ; // canvas.clientHeight;
preview . width = $preview . width ( ) ;
preview . height = $drawAreaContainer . height ( ) ;
canvasWidth = canvas . width ;
canvasHeight = canvas . height ;
$drawAreaContainer . show ( ) ;
// window.innerHeight
console . log ( "window.innerHeight: " + window . innerHeight ) ;
console . log ( "window.innerWidth: " + window . innerWidth ) ;
console . log ( "$drawAreaContainer.innerHeight(): " + $drawAreaContainer . innerHeight ( ) ) ;
console . log ( "$drawAreaContainer.offset().top: " + $drawAreaContainer . offset ( ) . top ) ;
// timeout because it SEEMS to be beneficial for initting the layout
// 2013-09-18 seems beneficial since when?
setTimeout ( _startOrientationAndChangeEventListening , 1000 ) ;
}
function _startOrientationAndChangeEventListening ( ) {
// Initial execution if needed
$ ( window ) . on ( 'resize' , doOnResize ) ;
// is it necessary to call these? Aren't they called by the above eventhandlers?
doOnResize ( ) ;
}
/ * n o t u s i n g t h i s n o w
var $printProgressContainer = $ ( "#printProgressContainer" ) ;
var $progressbar = $ ( "#progressbar" ) ;
var $progressAmount = $ ( ".progressAmount" ) ;
function setPrintprogress ( val ) {
if ( isNaN ( val ) ) return ;
// console.log("f:setPrintprogress() >> val " + val);
$progressbar . css ( "width" , val * 100 + "%" ) ;
$progressAmount . text ( Math . floor ( val * 100 ) + "%" ) ;
}
//*/
function Printer ( ) {
Printer . WIFIBOX _DISCONNECTED _STATE = "wifibox disconnected" ;
Printer . UNKNOWN _STATE = "unknown" ; // happens when a printer is connection but there isn't communication yet
Printer . DISCONNECTED _STATE = "disconnected" ; // printer disconnected
Printer . IDLE _STATE = "idle" ; // printer found, but idle
Printer . BUFFERING _STATE = "buffering" ; // printer is buffering (recieving) data, but not yet printing
Printer . PRINTING _STATE = "printing" ;
Printer . STOPPING _STATE = "stopping" ; // when you stop (abort) a print it prints the endcode
Printer . ON _BEFORE _UNLOAD _MESSAGE = "You're doodle is still being send to the printer, leaving will result in a incomplete 3D print" ;
this . temperature = 0 ;
this . targetTemperature = 0 ;
this . currentLine = 0 ;
this . totalLines = 0 ;
this . bufferedLines = 0 ;
this . state = Printer . UNKNOWN _STATE ;
this . hasControl = true ; // whether this client has control access
this . wifiboxURL ;
this . checkStatusInterval = 3000 ;
this . checkStatusDelay ;
this . timeoutTime = 3000 ;
this . sendPrintPartTimeoutTime = 5000 ;
this . gcode ; // gcode to be printed
this . sendLength = 1500 ; // max amount of gcode lines per post (limited because WiFi box can't handle to much)
this . retryDelay = 2000 ; // retry setTimout delay
this . retrySendPrintPartDelay ; // retry setTimout instance
this . retryCheckStatusDelay ; // retry setTimout instance
this . retryStopDelay ; // retry setTimout instance
this . retryPreheatDelay ; // retry setTimout instance
this . maxGCodeSize = 10 ; // max size of gcode in MB's (estimation)
this . stateOverruled = false ;
// Events
Printer . UPDATE = "update" ;
var self = this ;
this . init = function ( ) {
console . log ( "Printer:init" ) ;
//this.wifiboxURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
//this.wifiboxURL = "http://192.168.5.1/cgi-bin/d3dapi";
this . wifiboxURL = wifiboxURL ;
//this.wifiboxURL = "proxy5.php";
console . log ( " wifiboxURL: " , this . wifiboxURL ) ;
if ( autoUpdate ) {
this . startStatusCheckInterval ( ) ;
}
}
this . preheat = function ( ) {
console . log ( "Printer:preheat" ) ;
var self = this ;
if ( communicateWithWifibox ) {
$ . ajax ( {
url : this . wifiboxURL + "/printer/heatup" ,
type : "POST" ,
dataType : 'json' ,
timeout : this . timeoutTime ,
success : function ( data ) {
console . log ( "Printer:preheat response: " , data ) ;
if ( data . status == "error" ) {
clearTimeout ( self . retryPreheatDelay ) ;
self . retryPreheatDelay = setTimeout ( function ( ) { self . preheat ( ) } , self . retryDelay ) ; // retry after delay
}
}
} ) . fail ( function ( ) {
console . log ( "Printer:preheat: failed" ) ;
clearTimeout ( self . retryPreheatDelay ) ;
self . retryPreheatDelay = setTimeout ( function ( ) { self . preheat ( ) } , self . retryDelay ) ; // retry after delay
} ) ;
} else {
console . log ( "Printer >> f:preheat() >> communicateWithWifibox is false, so not executing this function" ) ;
}
}
this . print = function ( gcode ) {
console . log ( "Printer:print" ) ;
console . log ( " gcode total # of lines: " + gcode . length ) ;
message . set ( "Sending doodle to printer..." , Message . NOTICE ) ;
self . addLeaveWarning ( ) ;
/ * f o r ( i = 0 ; i < g c o d e . l e n g t h ; i + + ) {
gcode [ i ] += " (" + i + ")" ;
} * /
this . sendIndex = 0 ;
this . gcode = gcode ;
//console.log(" gcode[20]: ",gcode[20]);
var gcodeLineSize = this . byteSize ( gcode [ 20 ] ) ;
//console.log(" gcodeLineSize: ",gcodeLineSize);
var gcodeSize = gcodeLineSize * gcode . length / 1024 / 1024 ; // estimate gcode size in MB's
console . log ( " gcodeSize: " , gcodeSize ) ;
if ( gcodeSize > this . maxGCodeSize ) {
console . log ( "Error: Printer:print: gcode file is probably to big (" + gcodeSize + "MB) (max: " + this . maxGCodeSize + "MB)" ) ;
return ;
}
//this.targetTemperature = settings["printer.temperature"]; // slight hack
this . sendPrintPart ( this . sendIndex , this . sendLength ) ;
}
this . byteSize = function ( s ) {
return ~ - encodeURI ( s ) . split ( /%..|./ ) . length ;
}
this . sendPrintPart = function ( sendIndex , sendLength ) {
console . log ( "Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this . gcode . length + ", sendLength: " + sendLength ) ;
var firstOne = ( sendIndex == 0 ) ? true : false ;
var start = firstOne ; // start printing right away
var completed = false ;
if ( this . gcode . length < ( sendIndex + sendLength ) ) {
console . log ( " sending less than max sendLength (and last)" ) ;
sendLength = this . gcode . length - sendIndex ;
//lastOne = true;
completed = true ;
}
var gcodePart = this . gcode . slice ( sendIndex , sendIndex + sendLength ) ;
var postData = { gcode : gcodePart . join ( "\n" ) , first : firstOne , start : start } ;
var self = this ;
if ( communicateWithWifibox ) {
$ . ajax ( {
url : this . wifiboxURL + "/printer/print" ,
type : "POST" ,
data : postData ,
dataType : 'json' ,
timeout : this . sendPrintPartTimeoutTime ,
success : function ( data ) {
console . log ( "Printer:sendPrintPart response: " , data ) ;
if ( data . status == "success" ) {
if ( completed ) {
console . log ( "Printer:sendPrintPart:gcode sending completed" ) ;
this . gcode = [ ] ;
btnStop . css ( "display" , "block" ) ; // hack
self . removeLeaveWarning ( ) ;
message . set ( "Doodle is send to printer..." , Message . INFO , true ) ;
//self.targetTemperature = settings["printer.temperature"]; // slight hack
} else {
// only if the state hasn't bin changed (by for example pressing stop) we send more gcode
console . log ( "Printer:sendPrintPart:gcode part received (state: " , self . state , ")" ) ;
if ( self . state == Printer . PRINTING _STATE || self . state == Printer . BUFFERING _STATE ) {
console . log ( "Printer:sendPrintPart:sending next part" ) ;
self . sendPrintPart ( sendIndex + sendLength , sendLength ) ;
}
}
}
// after we know the first gcode packed has bin received or failed
// (and the driver had time to update the printer.state)
// we start checking the status again
if ( sendIndex == 0 ) {
self . startStatusCheckInterval ( ) ;
}
}
} ) . fail ( function ( ) {
console . log ( "Printer:sendPrintPart: failed" ) ;
clearTimeout ( self . retrySendPrintPartDelay ) ;
self . retrySendPrintPartDelay = setTimeout ( function ( ) {
console . log ( "request printer:sendPrintPart failed retry" ) ;
self . sendPrintPart ( sendIndex , sendLength )
} , self . retryDelay ) ; // retry after delay
// after we know the gcode packed has bin received or failed
// (and the driver had time to update the printer.state)
// we start checking the status again
self . startStatusCheckInterval ( ) ;
} ) ;
} else {
console . log ( "Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function" ) ;
}
}
this . stop = function ( ) {
console . log ( "Printer:stop" ) ;
var self = this ;
if ( communicateWithWifibox ) {
$ . ajax ( {
url : this . wifiboxURL + "/printer/stop" ,
type : "POST" ,
dataType : 'json' ,
timeout : this . timeoutTime ,
success : function ( data ) {
console . log ( "Printer:stop response: " , data ) ;
// after we know the stop has bin received or failed
// (and the driver had time to update the printer.state)
// we start checking the status again
self . startStatusCheckInterval ( ) ;
}
} ) . fail ( function ( ) {
console . log ( "Printer:stop: failed" ) ;
clearTimeout ( self . retryStopDelay ) ;
self . retryStopDelay = setTimeout ( function ( ) { self . stop ( ) } , self . retryDelay ) ; // retry after delay
// after we know the stop has bin received or failed
// (and the driver had time to update the printer.state)
// we start checking the status again
self . startStatusCheckInterval ( ) ;
} ) ;
} else {
console . log ( "Printer >> f:communicateWithWifibox() >> communicateWithWifibox is false, so not executing this function" ) ;
}
}
this . startStatusCheckInterval = function ( ) {
console . log ( "Printer:startStatusCheckInterval" ) ;
self . checkStatus ( ) ;
clearTimeout ( self . checkStatusDelay ) ;
clearTimeout ( self . retryCheckStatusDelay ) ;
self . checkStatusDelay = setTimeout ( function ( ) { self . checkStatus ( ) } , self . checkStatusInterval ) ;
}
this . stopStatusCheckInterval = function ( ) {
console . log ( "Printer:stopStatusCheckInterval" ) ;
clearTimeout ( self . checkStatusDelay ) ;
clearTimeout ( self . retryCheckStatusDelay ) ;
}
this . checkStatus = function ( ) {
console . log ( "Printer:checkStatus" ) ;
this . stateOverruled = false ;
//console.log(" stateOverruled: ",this.stateOverruled);
var self = this ;
if ( communicateWithWifibox ) {
$ . ajax ( {
url : this . wifiboxURL + "/info/status" ,
dataType : 'json' ,
timeout : this . timeoutTime ,
success : function ( response ) {
//console.log(" Printer:status: ",response.data.state); //," response: ",response);
self . handleStatusUpdate ( response ) ;
clearTimeout ( self . checkStatusDelay ) ;
clearTimeout ( self . retryCheckStatusDelay ) ;
self . checkStatusDelay = setTimeout ( function ( ) { self . checkStatus ( ) } , self . checkStatusInterval ) ;
}
} ) . fail ( function ( ) {
console . log ( "Printer:checkStatus: failed" ) ;
self . state = Printer . WIFIBOX _DISCONNECTED _STATE ;
clearTimeout ( self . checkStatusDelay ) ;
clearTimeout ( self . retryCheckStatusDelay ) ;
self . retryCheckStatusDelay = setTimeout ( function ( ) { self . checkStatus ( ) } , self . retryDelay ) ; // retry after delay
$ ( document ) . trigger ( Printer . UPDATE ) ;
} ) ;
} else {
console . log ( "Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function" ) ;
}
}
this . handleStatusUpdate = function ( response ) {
console . log ( "Printer:handleStatusUpdate response: " , response ) ;
var data = response . data ;
if ( response . status != "success" ) {
self . state = Printer . UNKNOWN _STATE ;
} else {
// state
//console.log(" stateOverruled: ",this.stateOverruled);
if ( ! this . stateOverruled ) {
self . state = data . state ;
//console.log(" state > ",self.state);
}
// temperature
self . temperature = data . hotend ;
self . targetTemperature = data . hotend _target ;
// progress
self . currentLine = data . current _line ;
self . totalLines = data . total _lines ;
self . bufferedLines = data . buffered _lines
// access
self . hasControl = data . has _control ;
if ( self . state == Printer . PRINTING _STATE || self . state == Printer . STOPPING _STATE ) {
console . log ( "progress: " , self . currentLine + "/" + self . totalLines + " (" + self . bufferedLines + ") (" + self . state + ")" ) ;
}
}
$ ( document ) . trigger ( Printer . UPDATE ) ;
}
this . overruleState = function ( newState ) {
this . stateOverruled = true ;
console . log ( " stateOverruled: " , this . stateOverruled ) ;
self . state = newState ;
$ ( document ) . trigger ( Printer . UPDATE ) ;
this . stopStatusCheckInterval ( ) ;
}
this . removeLeaveWarning = function ( ) {
window . onbeforeunload = null ;
}
this . addLeaveWarning = function ( ) {
window . onbeforeunload = function ( ) {
return Printer . ON _BEFORE _UNLOAD _MESSAGE ;
} ;
}
}
function Progressbar ( ) {
this . currProgress = 0 ; // default val
this . progressbarFGImg = new Image ( ) ;
this . progressbarFGImgSrc = "img/progress_fg.png" ;
this . progressbarBGImg = new Image ( ) ;
this . progressbarBGImgSrc = "img/progress_bg.png" ;
this . progressWidth = 93 ;
this . progressHeight = 82 ;
this . quartPI = . 5 * Math . PI ;
this . twoPI = 2 * Math . PI ;
this . $canvas ;
this . canvas ;
this . context ;
this . $container ;
this . isInitted = false ;
this . enabled = true ;
this . init = function ( targCanvas , targCanvasContainer ) {
console . log ( "Thermometer.init()" ) ;
this . $container = targCanvasContainer ;
this . $canvas = targCanvas ;
this . canvas = this . $canvas [ 0 ] ;
this . context = this . canvas . getContext ( '2d' ) ;
var self = this ;
this . progressbarBGImg . onload = function ( ) {
console . log ( "progressbarBGImg img loaded" ) ;
// self.isInitted = true;
// self.update(self.currentTemperature, self.targetTemperature);
self . progressbarFGImg . onload = function ( ) {
console . log ( "progressbarFGImg img loaded" ) ;
self . isInitted = true ;
self . update ( 0 , 100 ) ;
} ;
self . progressbarFGImg . src = self . progressbarFGImgSrc ;
} ;
this . progressbarBGImg . src = this . progressbarBGImgSrc ;
}
this . update = function ( part , total ) {
//console.log("Progressbar.update(" + part + "," + total + ")");
var pct = part / total ;
if ( this . isInitted ) {
if ( part == undefined ) part = 0 ;
if ( total == undefined ) total = 100 ; // prevent divide by zero
var progress = part / total ;
progress = Math . min ( progress , 1.0 ) ;
progress = Math . max ( progress , 0 ) ;
//console.log("progressbar >> f:update() >> progress: " + progress);
// clear
this . context . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
this . context . drawImage ( this . progressbarBGImg , 0 , 0 ) ;
this . context . font = "7pt sans-serif" ;
// draw the progressbar foreground's clipping path
this . context . save ( ) ;
this . context . beginPath ( ) ;
this . context . moveTo ( 45 , 45 ) ;
this . context . lineTo ( 45 , 0 ) ;
this . context . arc ( 45 , 45 , 45 , - this . quartPI , - this . quartPI + ( progress * ( this . twoPI ) ) , false ) ; // circle bottom of thermometer
this . context . lineTo ( 45 , 45 ) ;
this . context . clip ( ) ;
this . context . drawImage ( this . progressbarFGImg , 0 , 0 ) ;
this . context . restore ( ) ;
if ( debugMode ) {
this . context . fillStyle = '#222' ;
this . context . strokeStyle = '#fff' ;
this . context . lineWidth = 3 ;
this . context . textAlign = "center" ;
this . context . strokeText ( part + " / " + total , 45 , 45 , 90 ) ;
this . context . fillText ( part + " / " + total , 45 , 45 , 90 ) ;
}
} else {
console . log ( "Progressbar.setTemperature() -> thermometer not initialized!" ) ;
}
}
this . show = function ( ) {
this . $container . addClass ( "progressbarAppear" ) ;
// this.$container.show();
this . enabled = true ;
}
this . hide = function ( ) {
this . $container . removeClass ( "progressbarAppear" ) ;
// this.$container.hide();
this . enabled = false ;
}
}
// TODO assess if this var is still necessary
var $displayThermometer = $ ( "#thermometerContainer" ) ;
//TODO 2013-09-18 allow displaying temperatures HIGHER than the targTemp (it's now being capped at targTemp).
function Thermometer ( ) {
this . currentTemperature = 0 ; // default val
this . targetTemperature = 0 ; // default val
this . thermoOverlayImg = new Image ( ) ;
this . thermoOverlayImgSrc = "img/thermometer_fg_overlay.png" ; // ../img/thermometer_fg_overlay.png
this . thermoWidth = 40 ;
this . thermoHeight = 100 ;
this . $canvas ;
this . canvas ;
this . context ;
this . $container ;
this . isInitted = false ;
this . enabled = true ;
this . thermoColors = [
[ 50 , 200 , 244 ] , // 'cold'
[ 244 , 190 , 10 ] , // 'warming up'
[ 244 , 50 , 50 ] // 'ready / hot'
] ;
this . init = function ( targCanvas , targCanvasContainer ) {
console . log ( "Thermometer.init()" ) ;
this . $container = targCanvasContainer ;
this . $canvas = targCanvas ;
this . canvas = this . $canvas [ 0 ] ;
this . context = this . canvas . getContext ( '2d' ) ;
var self = this ;
this . thermoOverlayImg . onload = function ( ) {
console . log ( "canvasThermoOverlay img loaded" ) ;
self . isInitted = true ;
self . update ( self . currentTemperature , self . targetTemperature ) ;
} ;
this . thermoOverlayImg . src = this . thermoOverlayImgSrc ;
}
this . update = function ( curr , targ ) {
// console.log("Thermometer.update(" + curr + "," + targ + ")");
if ( this . isInitted ) {
if ( ! this . enabled ) return ;
if ( curr == undefined ) curr = 0 ;
if ( targ == undefined ) targ = 180 ; // prevent divide by zero
var progress = curr / targ ;
progress = Math . min ( progress , 1.0 ) ;
progress = Math . max ( progress , 0 ) ;
var h = this . thermoHeight ; // 94 // px
var paddingUnder = 15 ; // how far is beginpoint from bottom of thermometer
var paddingAbove = 25 ; // how far is endpoint from top of thermometer
var endPoint = h * . 8 ;
var p = Math . floor ( ( h - paddingUnder - paddingAbove ) * progress ) ; // %
// var tempHeight =
var currColor = this . thermoColors [ 0 ] ;
if ( progress > 0.98 ) {
currColor = this . thermoColors [ 2 ] ;
} else if ( progress > 0.25 ) {
currColor = this . thermoColors [ 1 ] ;
}
// clear
this . context . clearRect ( 0 , 0 , this . canvas . width , this . canvas . height ) ;
this . context . font = "10pt sans-serif" ;
// draw the thermometer clipping path
this . context . save ( ) ;
this . context . beginPath ( ) ;
this . context . arc ( 40 , 80 , 16 , 0 , 2 * Math . PI , false ) ; // circle bottom of thermometer
this . context . arc ( 40 , 10 , 4 , 0 , 2 * Math . PI , false ) ; // circle at top of thermometer tube
this . context . rect ( 36 , 11 , 8 , 70 ) ; // thermometer tube
this . context . fillStyle = '#fff' ;
this . context . fill ( ) ;
this . context . clip ( ) ;
// draw rectangle which represents temperature
// rect will be clipped by the thermometer outlines
this . context . beginPath ( ) ;
this . context . rect ( 20 , h - paddingUnder - p , 60 , p + paddingUnder ) ;
//console.log(" currColor: " + currColor);
//todo Math.floor??
this . context . fillStyle = "rgb(" + currColor [ 0 ] + "," + currColor [ 1 ] + "," + currColor [ 2 ] + ")" ;
this . context . fill ( ) ;
this . context . restore ( ) ;
// additional text labels
this . context . save ( ) ;
this . context . beginPath ( ) ;
this . context . moveTo ( 32 , paddingAbove ) ;
this . context . lineTo ( 52 , paddingAbove ) ;
this . context . lineWidth = 2 ;
this . context . strokeStyle = '#000' ;
this . context . stroke ( ) ;
this . context . fillStyle = '#000' ;
this . context . textAlign = "left" ;
this . context . textBaseline = "middle" ;
this . context . fillText ( targ + "°" , 55 , paddingAbove ) ;
this . context . restore ( ) ;
// the thermometer outline png
this . context . drawImage ( this . thermoOverlayImg , 20 , 0 ) ;
// text
this . context . fillStyle = '#000' ;
this . context . textAlign = "center" ;
this . context . fillText ( curr + "°" , 40 , h + paddingUnder ) ;
} else {
console . log ( "Thermometer.setTemperature() -> thermometer not initialized!" ) ;
}
}
this . show = function ( ) {
this . $container . addClass ( "thermometerAppear" ) ;
// $("#progressbarCanvasContainer").addClass("thermometerAppear");
// this.$container.show();
this . enabled = true ;
}
this . hide = function ( ) {
this . $container . removeClass ( "thermometerAppear" ) ;
// $("#progressbarCanvasContainer").removeClass("thermometerAppear");
// this.$container.hide();
this . enabled = false ;
}
}
// http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery
function getURLParameter ( name ) {
return decodeURI (
( new RegExp ( '[&?]' + name + '=' + '(.+?)(&|$)' ) . exec ( location . search ) || [ , null ] ) [ 1 ]
) ;
}
var sidebarLeft ;
var sidebarRight ;
function initSidebars ( ) {
console . log ( "f:initSidebars()" ) ;
sidebarLeft = new SideBar ( ) ;
sidebarLeft . init ( ".leftpanel" , "hideleft" , function ( ) {
$ ( ".leftpanel" ) . show ( ) ;
} ) ;
sidebarRight = new SideBar ( ) ;
sidebarRight . init ( ".rightpanel" , "hideright" , function ( ) {
$ ( ".rightpanel" ) . show ( ) ;
} ) ;
}
function SideBar ( ) {
this . initted = false ;
this . $contentTarg = undefined ;
this . $sideBtn = undefined ;
this . contentHidden = false ;
this . hideClass = "" ;
this . init = function ( targ , hideClass , callback ) {
console . log ( "SideBar >> f:init >> targ: " , $ ( targ ) , ", hideClass: " + hideClass ) ;
this . $contentTarg = $ ( targ ) ;
this . hideClass = hideClass ;
this . $contentTarg . addClass ( this . hideClass ) ;
this . contentHidden = true ;
this . $contentTarg . append ( "<div class='sidebutton'></div>" ) ;
this . $sideBtn = $ ( targ + " .sidebutton" ) ;
var self = this ;
this . $sideBtn . on ( 'click' , function ( e ) {
console . log ( "sidebutton" ) ;
self . toggleShowHide ( ) ;
} ) ;
this . initted = true ;
callback ( ) ;
}
this . toggleShowHide = function ( ) {
if ( this . contentHidden ) {
this . contentHidden = false ;
this . $contentTarg . removeClass ( this . hideClass ) ;
// self.$sideBtn.addClass("sidebuttonin");
this . $sideBtn . addClass ( "sidebuttonin" ) ;
} else {
this . contentHidden = true ;
this . $contentTarg . addClass ( this . hideClass ) ;
// self.$sideBtn.removeClass("sidebuttonin");
this . $sideBtn . removeClass ( "sidebuttonin" ) ;
}
}
}
function Message ( ) {
Message . ERROR = "error" ;
Message . WARNING = "warning" ;
Message . NOTICE = "notice" ;
Message . INFO = "info" ;
this . mode = "" ;
this . $element ;
var self = this ;
var autoHideDelay = 2000 ;
var autohideTimeout ;
this . init = function ( $element ) {
console . log ( "Message:init" ) ;
this . $element = $element ;
console . log ( "$element: " , $element ) ;
}
this . set = function ( text , mode , autoHide ) {
console . log ( "Message:set: " , text , mode , autoHide ) ;
self . hide ( function ( ) {
self . show ( ) ;
self . clear ( ) ;
self . $element . text ( text ) ;
self . $element . addClass ( mode ) ;
self . show ( ) ;
self . mode = mode ;
clearTimeout ( autohideTimeout ) ;
if ( autoHide ) {
autohideTimeout = setTimeout ( function ( ) { self . hide ( ) } , autoHideDelay ) ;
}
} ) ;
}
this . clear = function ( $element ) {
this . $element . text ( "" ) ;
this . $element . removeClass ( this . mode ) ;
}
this . show = function ( ) {
this . $element . fadeIn ( 200 ) ;
}
this . hide = function ( complete ) {
this . $element . fadeOut ( 200 , complete ) ;
}
}
var debugMode = false ; // debug mode
var sendPrintCommands = true ; // if Doodle3d should send print commands to the 3d printer
var communicateWithWifibox = true ; // if Doodle3d should try interfacing with the wifibox (in case one is not connected)
var wifiboxIsRemote = false ; // when you want to run the client on a computer and have it remotely connect to the wifibox
var autoUpdate = true ; // auto retrieve updates about temperature and progress from printer
var printer = new Printer ( ) ;
var progressbar = new Progressbar ( ) ;
var thermometer = new Thermometer ( ) ;
var settingsWindow = new SettingsWindow ( ) ;
var message = new Message ( ) ;
var firstTimeSettingsLoaded = true ;
var wifiboxURL ; // Using the uhttpd lua handler as default, because of better performance
var wifiboxCGIBinURL ; // CGI-bin, for some network stuff, where it needs to restart the webserver for example
var $drawAreaContainer , $doodleCanvas , doodleCanvas , doodleCanvasContext , $previewContainer ;
var showhideInterval ;
var showOrHide = false ;
$ ( 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" ) ;
if ( getURLParameter ( "r" ) != "null" ) wifiboxIsRemote = ( getURLParameter ( "r" ) == "1" ) ;
if ( getURLParameter ( "u" ) != "null" ) autoUpdate = ( getURLParameter ( "u" ) == "1" ) ;
if ( wifiboxIsRemote ) {
wifiboxURL = "http://192.168.5.1/d3dapi" ;
wifiboxCGIBinURL = "http://192.168.5.1/cgi-bin/d3dapi" ;
} else {
wifiboxURL = "http://" + window . location . host + "/d3dapi" ;
wifiboxCGIBinURL = "http://" + window . location . host + "/cgi-bin/d3dapi" ;
}
if ( ! communicateWithWifibox ) {
sendPrintCommands = false ; // 'communicateWithWifibox = false' implies this
}
console . log ( "debugMode: " + debugMode ) ;
console . log ( "sendPrintCommands: " + sendPrintCommands ) ;
console . log ( "communicateWithWifibox: " + communicateWithWifibox ) ;
console . log ( "wifiboxIsRemote: " + wifiboxIsRemote ) ;
console . log ( "wifibox URL: " + wifiboxURL ) ;
initDoodleDrawing ( ) ;
initPreviewRendering ( ) ;
initLayouting ( ) ;
initSidebars ( ) ;
initButtonBehavior ( ) ;
initVerticalShapes ( ) ;
thermometer . init ( $ ( "#thermometerCanvas" ) , $ ( "#thermometerContainer" ) ) ;
progressbar . init ( $ ( "#progressbarCanvas" ) , $ ( "#progressbarCanvasContainer" ) ) ;
message . init ( $ ( "#message" ) ) ;
printer . init ( ) ;
$ ( document ) . on ( Printer . UPDATE , update ) ;
settingsWindow . init ( wifiboxURL , wifiboxCGIBinURL ) ;
$ ( document ) . on ( SettingsWindow . SETTINGS _LOADED , settingsLoaded ) ;
if ( debugMode ) {
console . log ( "debug mode is true" ) ;
$ ( "body" ) . css ( "overflow" , "auto" ) ;
$ ( "#debug_textArea" ) . css ( "display" , "block" ) ;
$ ( "#preview_tmp" ) . css ( "display" , "block" ) ;
$ ( "#debug_display" ) . css ( "display" , "block" ) ;
// show and hide the progressguage and thermometer
2013-10-22 15:33:08 +02:00
//showhideInterval = setInterval(showOrHideThermo, 2500);
2013-10-22 12:04:46 +02:00
// $("#debugContainer").css("display", "block");
/* TEMP CODE!! -> artificially populates the startgcode and endgcode textareas in the settings window */
// todo remove this temporary code...
/ *
setTimeout ( function ( ) {
$ ( "#startgcode" ) . text ( "" ) ;
$ ( "#startgcode" ) . append ( "G21 (mm) \n" ) ;
$ ( "#startgcode" ) . append ( "G91 (relative) \n" ) ;
$ ( "#startgcode" ) . append ( "G28 X0 Y0 Z0 (physical home) \n" ) ;
$ ( "#startgcode" ) . append ( "M104 S230 (temperature) \n" ) ;
$ ( "#startgcode" ) . append ( "G1 E10 F250 (flow) \n" ) ;
$ ( "#startgcode" ) . append ( "G92 X-100 Y-100 Z0 E10 \n" ) ;
$ ( "#startgcode" ) . append ( "G1 Z3 F5000 (prevent diagonal line) \n" ) ;
$ ( "#startgcode" ) . append ( "G90 (absolute) \n" ) ;
$ ( "#startgcode" ) . append ( "M106 (fan on)" ) ;
console . log ( "$('#startgcode'): " + $ ( "#startgcode" ) . val ( ) ) ;
$ ( "#endgcode" ) . text ( "" ) ;
$ ( "#endgcode" ) . append ( "G1 X-100 Y-100 F15000 (fast homing) \n" ) ;
$ ( "#endgcode" ) . append ( "M107 \n" ) ;
$ ( "#endgcode" ) . append ( "M84 (disable axes) \n" ) ;
console . log ( "$('#endgcode'): " + $ ( "#endgcode" ) . val ( ) ) ;
} , 1000 ) ;
//*/
}
} ) ;
function showOrHideThermo ( ) {
console . log ( "f:showOrHideThermo()" ) ;
if ( showOrHide ) {
thermometer . hide ( ) ;
progressbar . hide ( ) ;
} else {
thermometer . show ( ) ;
progressbar . show ( ) ;
}
showOrHide = ! showOrHide ;
}
function settingsLoaded ( ) {
console . log ( "settingsLoaded" ) ;
console . log ( "autoHeatup: " , settings [ "printer.heatup.enabled" ] ) ;
if ( settings [ "printer.heatup.enabled" ] ) {
if ( firstTimeSettingsLoaded ) {
printer . preheat ( ) ;
firstTimeSettingsLoaded = false ;
}
}
}
function setDebugText ( text ) {
$ ( "#debug_display" ) . text ( text ) ;
}