2020-06-03 22:39:30 -04:00
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
2020-03-09 11:02:09 -04:00
"use strict" ;
2022-02-20 22:47:04 -05:00
// dep: geo.base
// dep: kiri.api
2022-02-22 00:05:29 -05:00
// dep: kiri.main
// dep: kiri.lang
2022-02-20 22:47:04 -05:00
// dep: kiri.stats
// dep: kiri.consts
// dep: kiri.platform
// dep: kiri.selection
2022-02-24 23:29:53 -05:00
// use: kiri.tools
2022-02-22 00:05:29 -05:00
// use: kiri.pack
2022-02-20 22:47:04 -05:00
gapp . register ( "kiri.init" , [ ] , ( root , exports ) => {
const { base , kiri } = root ;
2022-02-17 17:55:26 -05:00
const { api , catalog , conf , consts , space } = kiri ;
const { sdb , stats , js2o , o2js , platform , selection , ui , uc } = api ;
const { VIEWS , MODES , SEED } = consts ;
const { LANG , LOCAL , SETUP } = api . const ;
const WIN = self . window ,
2020-03-09 11:02:09 -04:00
DOC = self . document ,
2024-06-09 11:00:53 -07:00
DEG2RAD = Math . PI / 180 ,
2020-03-09 11:02:09 -04:00
STARTMODE = SETUP . sm && SETUP . sm . length === 1 ? SETUP . sm [ 0 ] : null ,
2024-06-09 11:00:53 -07:00
{ CAM , SLA , FDM , LASER , DRAG , WJET , WEDM } = MODES ,
TWOD = [ LASER , DRAG , WJET , WEDM ] ,
2024-06-11 13:16:02 -07:00
TWONED = [ LASER , DRAG , WJET ] ,
2024-06-09 11:00:53 -07:00
THREED = [ FDM , CAM , SLA ] ,
GCODE = [ FDM , CAM , ... TWOD ] ,
CAM _LZR = [ CAM , ... TWOD ] ,
FDM _LZR = [ FDM , ... TWOD ] ,
2024-06-11 13:16:02 -07:00
FDM _LZN = [ FDM , ... TWONED ] ,
NO _WEDM = [ FDM , CAM , SLA , LASER , DRAG , WJET ] ,
2024-06-09 11:00:53 -07:00
FDM _CAM = [ FDM , CAM ] ,
2020-12-13 09:55:30 -05:00
proto = location . protocol ,
2024-05-26 22:51:44 -04:00
ver = Date . now ( ) . toString ( 36 ) ,
2024-05-28 18:02:52 -04:00
separator = true ,
2024-05-26 22:51:44 -04:00
driven = true ;
2020-06-03 22:39:30 -04:00
2020-11-29 00:10:41 -05:00
let currentDevice = null ,
deviceURL = null ,
deviceTexture = null ,
2020-12-20 14:15:35 -05:00
deviceFilter = null ,
2020-11-28 13:12:07 -05:00
deviceImage = null ,
2020-03-09 11:02:09 -04:00
selectedTool = null ,
2020-03-12 11:09:29 -04:00
editTools = null ,
2020-04-22 00:24:06 -04:00
maxTool = 0 ,
2021-02-11 11:02:18 -05:00
platformColor ,
contextInt ;
2020-03-09 11:02:09 -04:00
2020-03-17 16:32:43 -04:00
// extend KIRI API with local functions
2022-02-17 17:55:26 -05:00
api . show . devices = showDevices ;
api . device . set = selectDevice ;
api . device . clone = cloneDevice ;
2020-03-17 16:32:43 -04:00
2020-03-09 11:02:09 -04:00
function settings ( ) {
2022-02-17 17:55:26 -05:00
return api . conf . get ( ) ;
2020-03-09 11:02:09 -04:00
}
2020-03-16 23:57:14 -04:00
function checkSeed ( then ) {
// skip sample object load in onshape (or any script postload)
2022-02-17 17:55:26 -05:00
if ( ! sdb [ SEED ] ) {
sdb [ SEED ] = new Date ( ) . getTime ( ) ;
if ( ! SETUP . s && api . feature . seed ) {
2021-03-31 17:56:24 -04:00
if ( SETUP . debug ) {
return then ( ) ;
}
2020-03-16 23:57:14 -04:00
platform . load _stl ( "/obj/cube.stl" , function ( vert ) {
2022-02-17 17:55:26 -05:00
catalog . putFile ( "sample cube.stl" , vert ) ;
2022-11-04 12:46:06 -04:00
platform . update _bounds ( ) ;
2022-02-17 17:55:26 -05:00
space . view . home ( ) ;
setTimeout ( ( ) => { api . space . save ( true ) } , 500 ) ;
2020-03-16 23:57:14 -04:00
then ( ) ;
2022-02-17 17:55:26 -05:00
api . help . show ( ) ;
2020-03-16 23:57:14 -04:00
} ) ;
return true ;
}
}
return false ;
}
2020-06-13 11:23:52 -04:00
function unitsSave ( ) {
2022-02-19 12:43:42 -05:00
api . conf . update ( { controller : true } ) ;
2020-06-13 11:23:52 -04:00
platform . update _size ( ) ;
}
2020-11-24 19:46:15 -05:00
function aniMeshSave ( ) {
2022-02-19 12:43:42 -05:00
api . conf . update ( { controller : true } ) ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2020-11-24 19:46:15 -05:00
}
2020-11-12 12:15:39 -05:00
function lineTypeSave ( ) {
2022-02-17 17:55:26 -05:00
const sel = ui . lineType . options [ ui . lineType . selectedIndex ] ;
2020-11-12 12:15:39 -05:00
if ( sel ) {
settings ( ) . controller . lineType = sel . value ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2020-11-12 12:15:39 -05:00
}
}
2021-11-10 11:40:34 -05:00
function filamentSourceEditUpdate ( ) {
2022-02-17 17:55:26 -05:00
if ( ui . filamentSource && ui . filamentSourceEdit ) {
api . event . emit ( "filament.source" ) ;
const sel = ui . filamentSource . options [ ui . filamentSource . selectedIndex ] ;
2021-11-10 11:40:34 -05:00
if ( sel ) {
2022-02-17 17:55:26 -05:00
ui . filamentSourceEdit . style . display = sel . value === 'palette3' ? '' : 'none' ;
2021-11-10 11:40:34 -05:00
}
}
}
2021-11-09 22:17:18 -05:00
function filamentSourceSave ( ) {
2022-02-17 17:55:26 -05:00
const sel = ui . filamentSource . options [ ui . filamentSource . selectedIndex ] ;
2021-11-09 22:17:18 -05:00
if ( sel ) {
settings ( ) . device . filamentSource = sel . value ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2021-11-09 22:17:18 -05:00
}
2021-11-10 11:40:34 -05:00
filamentSourceEditUpdate ( ) ;
}
2022-02-23 16:17:52 -05:00
function thinWallSave ( ) {
let opt = ui . sliceDetectThin ;
let level = opt . options [ opt . selectedIndex ] ;
if ( level ) {
settings ( ) . process . sliceDetectThin = level . value ;
api . conf . save ( ) ;
}
}
2020-11-06 10:47:49 -05:00
function detailSave ( ) {
2022-02-17 17:55:26 -05:00
let level = ui . detail . options [ ui . detail . selectedIndex ] ;
2020-11-06 10:47:49 -05:00
if ( level ) {
level = level . value ;
2022-02-17 17:55:26 -05:00
let rez = base . config . clipperClean ;
2020-11-06 10:47:49 -05:00
switch ( level ) {
2021-06-20 22:15:46 -04:00
case '100' : rez = 50 ; break ;
2022-02-17 17:55:26 -05:00
case '75' : rez = base . config . clipperClean ; break ;
2021-06-20 22:15:46 -04:00
case '50' : rez = 500 ; break ;
2021-06-21 15:15:05 -04:00
case '25' : rez = 1000 ; break ;
2020-11-06 10:47:49 -05:00
}
2022-02-17 17:55:26 -05:00
kiri . client . config ( {
2020-11-06 10:47:49 -05:00
base : { clipperClean : rez }
} ) ;
settings ( ) . controller . detail = level ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2020-11-06 10:47:49 -05:00
}
}
2020-11-10 21:48:04 -05:00
function speedSave ( ) {
2022-02-17 17:55:26 -05:00
settings ( ) . controller . showSpeeds = ui . showSpeeds . checked ;
2024-05-19 22:31:25 -04:00
api . view . update _speeds ( ) ;
2020-11-10 21:48:04 -05:00
}
2020-12-22 15:05:50 -05:00
function zAnchorSave ( ) {
2022-02-17 17:55:26 -05:00
api . conf . update ( ) ;
api . platform . update _top _z ( ) ;
2020-12-22 15:05:50 -05:00
}
2022-02-24 13:47:26 -05:00
function setThreaded ( bool ) {
if ( bool ) {
kiri . client . pool . start ( ) ;
} else {
kiri . client . pool . stop ( ) ;
}
return bool ;
}
2022-03-03 13:10:32 -05:00
api . event . on ( "set.threaded" , bool => setThreaded ( bool ) ) ;
2020-03-16 23:57:14 -04:00
function booleanSave ( ) {
2020-04-08 09:38:32 -04:00
let control = settings ( ) . controller ;
2022-02-17 17:55:26 -05:00
let doAlert = ui . ortho . checked !== control . ortho ;
if ( control . assembly != ui . assembly . checked ) {
kiri . client . wasm ( ui . assembly . checked ) ;
}
if ( control . antiAlias != ui . antiAlias . checked ) {
api . show . alert ( 'Page Reload Required to Change Aliasing' ) ;
}
2022-09-16 10:43:53 -04:00
control . shiny = ui . shiny . checked ;
2022-02-17 17:55:26 -05:00
control . decals = ui . decals . checked ;
2024-06-02 18:55:20 -04:00
control . drawer = ui . drawer . checked ;
2024-06-02 19:05:10 -04:00
control . scrolls = ui . scrolls . checked ;
2022-02-17 17:55:26 -05:00
control . showOrigin = ui . showOrigin . checked ;
control . showRulers = ui . showRulers . checked ;
control . autoLayout = ui . autoLayout . checked ;
control . freeLayout = ui . freeLayout . checked ;
control . spaceRandoX = ui . spaceRandoX . checked ;
control . autoSave = ui . autoSave . checked ;
control . antiAlias = ui . antiAlias . checked ;
control . reverseZoom = ui . reverseZoom . checked ;
control . dark = ui . dark . checked ;
control . exportOcto = ui . exportOcto . checked ;
control . exportGhost = ui . exportGhost . checked ;
control . exportLocal = ui . exportLocal . checked ;
control . exportThumb = ui . exportThumb . checked ;
control . exportPreview = ui . exportPreview . checked ;
control . healMesh = ui . healMesh . checked ;
2022-02-24 13:47:26 -05:00
control . threaded = setThreaded ( ui . threaded . checked ) ;
2022-02-17 17:55:26 -05:00
control . assembly = ui . assembly . checked ;
control . ortho = ui . ortho . checked ;
control . devel = ui . devel . checked ;
space . view . setZoom ( control . reverseZoom , control . zoomSpeed ) ;
2021-02-07 17:53:16 -05:00
// platform.layout();
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
api . platform . update _size ( ) ;
2022-01-28 16:54:53 -05:00
updateStats ( ) ;
2024-06-02 18:55:20 -04:00
updateDrawer ( ) ;
2022-01-18 13:41:11 -05:00
if ( control . decals && ! control . dark ) {
// disable decals in dark mode
2020-11-29 00:10:41 -05:00
loadDeviceTexture ( currentDevice , deviceTexture ) ;
} else {
clearDeviceTexture ( ) ;
}
2022-02-17 17:55:26 -05:00
api . event . emit ( 'boolean.update' ) ;
2021-03-04 13:22:53 -05:00
if ( doAlert ) {
2022-02-17 17:55:26 -05:00
api . show . alert ( "change requires page refresh" ) ;
2021-03-04 13:22:53 -05:00
}
2020-11-12 20:02:06 -05:00
}
2024-06-02 18:55:20 -04:00
function updateDrawer ( ) {
2024-06-02 19:05:10 -04:00
const { drawer , scrolls } = settings ( ) . controller ;
$c ( 'app' , drawer ? 'slideshow' : '' , drawer ? '' : 'slideshow' ) ;
$c ( 'app' , scrolls ? '' : 'hide-scroll' , scrolls ? 'hide-scroll' : '' ) ;
2024-06-02 18:55:20 -04:00
}
2022-01-28 16:54:53 -05:00
function updateStats ( ) {
if ( self . debug !== true ) {
return ;
}
2022-02-17 17:55:26 -05:00
let { div , fps , rms , rnfo } = ui . stats ;
2022-01-28 16:54:53 -05:00
div . style . display = 'flex' ;
2020-12-27 14:36:17 -05:00
setInterval ( ( ) => {
2022-10-04 16:43:33 -04:00
const nrms = space . view . getRMS ( ) . toFixed ( 1 ) ;
const nfps = space . view . getFPS ( ) . toFixed ( 1 ) ;
2022-02-17 17:55:26 -05:00
const rend = space . renderInfo ( ) ;
2022-01-31 15:20:34 -05:00
const { memory , render } = rend ;
2022-01-28 16:54:53 -05:00
if ( nfps !== fps . innerText ) {
fps . innerText = nfps ;
}
if ( nrms !== rms . innerText ) {
rms . innerText = nrms ;
2020-12-27 14:36:17 -05:00
}
2022-01-31 15:20:34 -05:00
if ( rnfo . offsetParent !== null ) {
2022-10-04 16:46:28 -04:00
rnfo . innerHTML = Object . entries ( { ... memory , ... render , render _ms : nrms , frames _sec : nfps } ) . map ( row => {
2022-10-04 16:43:33 -04:00
return ` <div> ${ row [ 0 ] } </div><label> ${ base . util . comma ( row [ 1 ] ) } </label> `
} ) . join ( '' ) ;
2022-01-31 15:20:34 -05:00
}
2020-12-27 14:36:17 -05:00
} , 100 ) ;
2020-03-16 23:57:14 -04:00
}
2021-10-08 11:07:38 -04:00
function parentWithClass ( el , classname ) {
while ( el ) {
if ( el . classList . contains ( classname ) ) {
return el ;
}
el = el . parentNode ;
}
return el ;
2020-03-16 23:57:14 -04:00
}
2022-10-30 17:04:16 -04:00
function onBooleanClick ( el ) {
uc . refresh ( ) ;
2022-02-17 17:55:26 -05:00
api . conf . update ( ) ;
2020-03-16 23:57:14 -04:00
DOC . activeElement . blur ( ) ;
2022-02-17 17:55:26 -05:00
api . event . emit ( "boolean.click" ) ;
2022-10-18 10:36:41 -04:00
updateLaserState ( ) ;
2022-10-30 17:04:16 -04:00
if ( el === ui . camStockIndexed ) {
api . space . set _focus ( ) ;
}
2020-03-16 23:57:14 -04:00
}
2020-11-22 12:57:25 -05:00
function onButtonClick ( ev ) {
let target = ev . target ;
while ( target && target . tagName !== 'BUTTON' ) {
target = target . parentNode ;
}
2022-02-17 17:55:26 -05:00
api . event . emit ( "button.click" , target ) ;
2020-11-22 12:57:25 -05:00
}
2020-03-16 23:57:14 -04:00
function inputHasFocus ( ) {
let active = DOC . activeElement ;
return active && ( active . nodeName === "INPUT" || active . nodeName === "TEXTAREA" ) ;
}
function cca ( c ) {
return c . charCodeAt ( 0 ) ;
}
function keyUpHandler ( evt ) {
2022-02-17 17:55:26 -05:00
if ( api . feature . on _key ) {
if ( api . feature . on _key ( { up : evt } ) ) return ;
2020-04-12 14:35:24 -04:00
}
2020-03-16 23:57:14 -04:00
switch ( evt . keyCode ) {
// escape
case 27 :
// blur text input focus
DOC . activeElement . blur ( ) ;
// dismiss modals
2022-02-17 17:55:26 -05:00
api . modal . hide ( ) ;
2020-03-16 23:57:14 -04:00
// deselect widgets
platform . deselect ( ) ;
// hide all dialogs
2022-02-17 17:55:26 -05:00
api . dialog . hide ( ) ;
2020-03-16 23:57:14 -04:00
// cancel slicing
2022-02-17 17:55:26 -05:00
api . function . cancel ( ) ;
2020-11-22 12:57:25 -05:00
// and send an event (used by FDM client)
2022-02-17 17:55:26 -05:00
api . event . emit ( "key.esc" ) ;
2020-03-16 23:57:14 -04:00
break ;
}
return false ;
}
function keyDownHandler ( evt ) {
2022-02-17 17:55:26 -05:00
if ( api . modal . visible ( ) ) {
2020-03-16 23:57:14 -04:00
return false ;
}
2022-02-17 17:55:26 -05:00
if ( api . feature . on _key ) {
if ( api . feature . on _key ( { down : evt } ) ) return ;
2020-04-12 14:35:24 -04:00
}
2020-03-16 23:57:14 -04:00
let move = evt . altKey ? 5 : 0 ,
deg = move ? 0 : - Math . PI / ( evt . shiftKey ? 36 : 2 ) ;
switch ( evt . keyCode ) {
case 8 : // apple: delete/backspace
case 46 : // others: delete
if ( inputHasFocus ( ) ) return false ;
2022-02-17 17:55:26 -05:00
platform . delete ( api . selection . meshes ( ) ) ;
2020-03-16 23:57:14 -04:00
evt . preventDefault ( ) ;
break ;
case 37 : // left arrow
if ( inputHasFocus ( ) ) return false ;
2022-02-17 17:55:26 -05:00
if ( deg ) api . selection . rotate ( 0 , 0 , - deg ) ;
if ( move > 0 ) api . selection . move ( - move , 0 , 0 ) ;
2020-03-16 23:57:14 -04:00
evt . preventDefault ( ) ;
break ;
case 39 : // right arrow
if ( inputHasFocus ( ) ) return false ;
2022-02-17 17:55:26 -05:00
if ( deg ) api . selection . rotate ( 0 , 0 , deg ) ;
if ( move > 0 ) api . selection . move ( move , 0 , 0 ) ;
2020-03-16 23:57:14 -04:00
evt . preventDefault ( ) ;
break ;
case 38 : // up arrow
if ( inputHasFocus ( ) ) return false ;
2022-02-17 17:55:26 -05:00
if ( evt . metaKey ) return api . show . layer ( api . var . layer _at + 1 ) ;
if ( deg ) api . selection . rotate ( deg , 0 , 0 ) ;
if ( move > 0 ) api . selection . move ( 0 , move , 0 ) ;
2020-03-16 23:57:14 -04:00
evt . preventDefault ( ) ;
break ;
case 40 : // down arrow
if ( inputHasFocus ( ) ) return false ;
2022-02-17 17:55:26 -05:00
if ( evt . metaKey ) return api . show . layer ( api . var . layer _at - 1 ) ;
if ( deg ) api . selection . rotate ( - deg , 0 , 0 ) ;
if ( move > 0 ) api . selection . move ( 0 , - move , 0 ) ;
2020-03-16 23:57:14 -04:00
evt . preventDefault ( ) ;
break ;
case 65 : // 'a' for select all
2020-10-25 00:33:11 +03:00
if ( evt . metaKey || evt . ctrlKey ) {
2020-03-16 23:57:14 -04:00
if ( inputHasFocus ( ) ) return false ;
evt . preventDefault ( ) ;
platform . deselect ( ) ;
platform . select _all ( ) ;
}
break ;
case 83 : // 's' for save workspace
if ( evt . ctrlKey ) {
evt . preventDefault ( ) ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2020-09-26 08:10:49 -04:00
console . log ( "settings saved" ) ;
2020-03-16 23:57:14 -04:00
} else
if ( evt . metaKey ) {
evt . preventDefault ( ) ;
2022-02-17 17:55:26 -05:00
api . space . save ( ) ;
2020-03-16 23:57:14 -04:00
}
break ;
case 76 : // 'l' for restore workspace
if ( evt . metaKey ) {
evt . preventDefault ( ) ;
2022-02-17 17:55:26 -05:00
api . space . restore ( ) ;
2020-03-16 23:57:14 -04:00
}
break ;
}
}
function keyHandler ( evt ) {
2021-02-11 11:02:18 -05:00
let handled = true ;
2022-02-17 17:55:26 -05:00
if ( api . modal . visible ( ) || inputHasFocus ( ) ) {
2020-03-16 23:57:14 -04:00
return false ;
}
2022-02-17 17:55:26 -05:00
if ( api . feature . on _key ) {
if ( api . feature . on _key ( { key : evt } ) ) return ;
2020-04-12 14:35:24 -04:00
}
2021-03-01 00:22:07 -05:00
if ( evt . ctrlKey ) {
switch ( evt . key ) {
2022-02-17 17:55:26 -05:00
case 'g' : return api . group . merge ( ) ;
case 'u' : return api . group . split ( ) ;
2021-03-01 00:22:07 -05:00
}
}
2020-03-16 23:57:14 -04:00
switch ( evt . charCode ) {
2022-02-17 17:55:26 -05:00
case cca ( '`' ) : api . show . slices ( 0 ) ; break ;
case cca ( '0' ) : api . show . slices ( api . var . layer _max ) ; break ;
case cca ( '1' ) : api . show . slices ( api . var . layer _max / 10 ) ; break ;
case cca ( '2' ) : api . show . slices ( api . var . layer _max * 2 / 10 ) ; break ;
case cca ( '3' ) : api . show . slices ( api . var . layer _max * 3 / 10 ) ; break ;
case cca ( '4' ) : api . show . slices ( api . var . layer _max * 4 / 10 ) ; break ;
case cca ( '5' ) : api . show . slices ( api . var . layer _max * 5 / 10 ) ; break ;
case cca ( '6' ) : api . show . slices ( api . var . layer _max * 6 / 10 ) ; break ;
case cca ( '7' ) : api . show . slices ( api . var . layer _max * 7 / 10 ) ; break ;
case cca ( '8' ) : api . show . slices ( api . var . layer _max * 8 / 10 ) ; break ;
case cca ( '9' ) : api . show . slices ( api . var . layer _max * 9 / 10 ) ; break ;
2020-03-16 23:57:14 -04:00
case cca ( '?' ) :
2022-02-17 17:55:26 -05:00
api . help . show ( ) ;
2020-03-16 23:57:14 -04:00
break ;
case cca ( 'Z' ) : // reset stored state
2022-02-17 17:55:26 -05:00
uc . confirm ( 'clear all settings and preferences?' ) . then ( yes => {
if ( yes ) sdb . clear ( ) ;
2020-06-19 19:23:09 -04:00
} ) ;
2020-03-16 23:57:14 -04:00
break ;
case cca ( 'C' ) : // refresh catalog
2022-02-17 17:55:26 -05:00
catalog . refresh ( ) ;
2020-03-16 23:57:14 -04:00
break ;
2020-06-09 20:22:11 -04:00
case cca ( 'i' ) : // file import
2022-02-17 17:55:26 -05:00
api . event . import ( ) ;
2020-03-16 23:57:14 -04:00
break ;
2020-12-05 16:11:40 -05:00
case cca ( 'S' ) : // slice
case cca ( 's' ) : // slice
if ( evt . shiftKey ) {
2022-02-17 17:55:26 -05:00
api . show . alert ( 'CAPS lock on?' ) ;
2020-12-05 16:11:40 -05:00
}
2022-02-17 17:55:26 -05:00
api . function . slice ( ) ;
2020-03-16 23:57:14 -04:00
break ;
2020-12-05 16:11:40 -05:00
case cca ( 'P' ) : // prepare
case cca ( 'p' ) : // prepare
if ( evt . shiftKey ) {
2022-02-17 17:55:26 -05:00
api . show . alert ( 'CAPS lock on?' ) ;
2020-12-05 16:11:40 -05:00
}
2022-02-17 17:55:26 -05:00
if ( api . mode . get ( ) !== 'SLA' ) {
2020-04-26 09:53:22 -04:00
// hidden in SLA mode
2022-02-17 17:55:26 -05:00
api . function . print ( ) ;
2020-04-26 09:53:22 -04:00
}
2020-03-16 23:57:14 -04:00
break ;
2020-12-05 16:11:40 -05:00
case cca ( 'X' ) : // export
case cca ( 'x' ) : // export
if ( evt . shiftKey ) {
2022-02-17 17:55:26 -05:00
api . show . alert ( 'CAPS lock on?' ) ;
2020-12-05 16:11:40 -05:00
}
2022-02-17 17:55:26 -05:00
api . function . export ( ) ;
2020-03-16 23:57:14 -04:00
break ;
2020-12-06 11:17:33 -05:00
case cca ( 'g' ) : // CAM animate
2022-02-17 17:55:26 -05:00
api . function . animate ( ) ;
2020-12-06 11:17:33 -05:00
break ;
2020-12-08 23:27:34 -05:00
case cca ( 'O' ) : // manual rotation
2020-03-16 23:57:14 -04:00
rotateInputSelection ( ) ;
break ;
2020-12-05 16:11:40 -05:00
case cca ( 'r' ) : // recent files
2022-02-17 17:55:26 -05:00
api . modal . show ( 'files' ) ;
2020-03-16 23:57:14 -04:00
break ;
2020-06-09 20:22:11 -04:00
case cca ( 'q' ) : // preferences
2022-02-17 17:55:26 -05:00
api . modal . show ( 'prefs' ) ;
2020-06-09 20:22:11 -04:00
break ;
2020-06-09 23:19:51 -04:00
case cca ( 'l' ) : // device
settingsLoad ( ) ;
break ;
2020-06-09 20:22:11 -04:00
case cca ( 'e' ) : // device
2020-03-16 23:57:14 -04:00
showDevices ( ) ;
break ;
2024-06-05 12:10:33 -07:00
// case cca('w'): // scale
// api.event.emit("tool.next");
// break;
2020-03-16 23:57:14 -04:00
case cca ( 'o' ) : // tools
showTools ( ) ;
break ;
case cca ( 'c' ) : // local devices
2022-02-17 17:55:26 -05:00
api . show . local ( ) ;
2020-03-16 23:57:14 -04:00
break ;
case cca ( 'v' ) : // toggle single slice view mode
2022-02-17 17:55:26 -05:00
if ( api . view . get ( ) === VIEWS . ARRANGE ) {
api . space . set _focus ( api . selection . widgets ( ) ) ;
2021-01-22 10:41:04 -05:00
}
2022-02-17 17:55:26 -05:00
if ( api . var . layer _hi == api . var . layer _lo ) {
api . var . layer _lo = 0 ;
2020-06-08 12:23:35 -04:00
} else {
2022-02-17 17:55:26 -05:00
api . var . layer _lo = api . var . layer _hi ;
2020-06-08 12:23:35 -04:00
}
2022-02-17 17:55:26 -05:00
api . show . slices ( ) ;
2020-03-16 23:57:14 -04:00
break ;
case cca ( 'd' ) : // duplicate object
2021-02-11 11:02:18 -05:00
duplicateSelection ( ) ;
2020-03-16 23:57:14 -04:00
break ;
case cca ( 'm' ) : // mirror object
2021-02-11 11:02:18 -05:00
mirrorSelection ( ) ;
2020-03-16 23:57:14 -04:00
break ;
2021-01-25 08:49:42 -05:00
case cca ( 'a' ) :
2022-02-17 17:55:26 -05:00
if ( api . view . get ( ) === VIEWS . ARRANGE ) {
2021-01-25 08:49:42 -05:00
// auto arrange items on platform
platform . layout ( ) ;
2022-02-17 17:55:26 -05:00
if ( ! api . conf . get ( ) . controller . spaceRandoX ) {
api . space . set _focus ( api . selection . widgets ( ) ) ;
2022-02-08 23:54:20 -05:00
}
2021-01-25 08:49:42 -05:00
} else {
// go to arrange view
2022-02-17 17:55:26 -05:00
api . view . set ( VIEWS . ARRANGE ) ;
2021-01-25 08:49:42 -05:00
}
2020-03-16 23:57:14 -04:00
break ;
default :
2022-02-17 17:55:26 -05:00
api . event . emit ( 'keypress' , evt ) ;
2020-03-16 23:57:14 -04:00
handled = false ;
break ;
}
2021-02-11 11:02:18 -05:00
if ( handled ) {
evt . preventDefault ( ) ;
evt . stopPropagation ( ) ;
}
2020-03-16 23:57:14 -04:00
return false ;
}
2021-02-11 11:02:18 -05:00
function duplicateSelection ( ) {
2022-02-17 17:55:26 -05:00
api . selection . duplicate ( ) ;
2021-02-11 11:02:18 -05:00
}
function mirrorSelection ( ) {
2022-02-17 17:55:26 -05:00
api . selection . mirror ( ) ;
2021-02-11 11:02:18 -05:00
}
2020-03-16 23:57:14 -04:00
function keys ( o ) {
let key , list = [ ] ;
for ( key in o ) { if ( o . hasOwnProperty ( key ) ) list . push ( key ) }
return list . sort ( ) ;
}
function clearSelected ( children ) {
for ( let i = 0 ; i < children . length ; i ++ ) {
children [ i ] . setAttribute ( 'class' , '' ) ;
}
}
function rotateInputSelection ( ) {
2022-02-17 17:55:26 -05:00
if ( api . selection . meshes ( ) . length === 0 ) {
api . show . alert ( "select object to rotate" ) ;
2020-03-16 23:57:14 -04:00
return ;
}
2020-06-09 19:23:03 -04:00
let coord = ( prompt ( "Enter X,Y,Z degrees of rotation" ) || '' ) . split ( ',' ) ,
2020-03-30 14:10:36 -04:00
prod = Math . PI / 180 ,
2020-03-16 23:57:14 -04:00
x = parseFloat ( coord [ 0 ] || 0.0 ) * prod ,
y = parseFloat ( coord [ 1 ] || 0.0 ) * prod ,
z = parseFloat ( coord [ 2 ] || 0.0 ) * prod ;
2022-02-17 17:55:26 -05:00
api . selection . rotate ( x , y , z ) ;
2020-03-16 23:57:14 -04:00
}
function positionSelection ( ) {
2022-02-17 17:55:26 -05:00
if ( api . selection . meshes ( ) . length === 0 ) {
api . show . alert ( "select object to position" ) ;
2020-03-16 23:57:14 -04:00
return ;
}
let current = settings ( ) ,
2023-01-06 22:25:37 -05:00
{ device , process } = current ,
2024-06-09 15:33:30 -07:00
center = process . ctOriginCenter || process . camOriginCenter || device . bedRound || device . originCenter ,
2020-03-16 23:57:14 -04:00
bounds = boundsSelection ( ) ,
coord = prompt ( "Enter X,Y coordinates for selection" ) . split ( ',' ) ,
x = parseFloat ( coord [ 0 ] || 0.0 ) ,
y = parseFloat ( coord [ 1 ] || 0.0 ) ,
z = parseFloat ( coord [ 2 ] || 0.0 ) ;
if ( ! center ) {
2023-01-06 22:25:37 -05:00
x = x - device . bedWidth / 2 + ( bounds . max . x - bounds . min . x ) / 2 ;
y = y - device . bedDepth / 2 + ( bounds . max . y - bounds . min . y ) / 2
2020-03-16 23:57:14 -04:00
}
2022-02-17 17:55:26 -05:00
api . selection . move ( x , y , z , true ) ;
2020-03-16 23:57:14 -04:00
}
2020-09-24 08:52:59 -04:00
function deviceExport ( exp , name ) {
2020-11-19 21:33:47 -05:00
name = ( name || "device" )
2020-09-24 08:52:59 -04:00
. toLowerCase ( )
. replace ( / /g , '_' )
. replace ( /\./g , '_' ) ;
2022-02-17 17:55:26 -05:00
uc . prompt ( "Export Device Filename" , name ) . then ( name => {
2020-09-24 08:52:59 -04:00
if ( name ) {
2022-02-17 17:55:26 -05:00
api . util . download ( exp , ` ${ name } .km ` ) ;
2020-09-24 08:52:59 -04:00
}
} ) ;
}
2021-10-08 21:15:54 -04:00
function objectsExport ( format = "stl" ) {
2022-02-17 17:55:26 -05:00
// return api.selection.export();
uc . confirm ( "Export Filename" , { ok : true , cancel : false } , ` selected. ${ format } ` ) . then ( name => {
2020-12-06 21:25:31 -05:00
if ( ! name ) return ;
2021-10-08 21:15:54 -04:00
if ( name . toLowerCase ( ) . indexOf ( ` . ${ format } ` ) < 0 ) {
name = ` ${ name } . ${ format } ` ;
2020-12-06 21:25:31 -05:00
}
2022-02-17 17:55:26 -05:00
api . util . download ( api . selection . export ( format ) , name ) ;
2020-12-06 21:25:31 -05:00
} ) ;
}
2024-05-31 13:42:24 -04:00
function profileExport ( ) {
2020-11-16 09:17:02 -05:00
const opt = { pre : [
2024-05-31 13:42:24 -04:00
"<div class='f-col a-center gap5 mlr10'>" ,
" <h3>Workspace Export</h3>" ,
" <label>This will create a backup of your</label>" ,
" <label>workspace, devices, and settings</label>" ,
" <span class='mt10'><input id='excwork' type='checkbox'> Exclude meshes</span>" ,
2020-11-16 09:17:02 -05:00
"</div>"
] } ;
2024-05-31 13:42:24 -04:00
let suggestion = "workspace" ;
let file = api . widgets . all ( ) [ 0 ] ? . meta . file || '' ;
if ( file ) {
suggestion = ` ${ suggestion } _ ${ file . split ( '.' ) [ 0 ] } ` . replaceAll ( ' ' , '_' ) ;
} ;
uc . confirm ( "Filename" , { ok : true , cancel : false } , suggestion , opt ) . then ( name => {
if ( ! name ) return ;
let work = ! $ ( 'excwork' ) . checked ;
let json = api . conf . export ( { work , clear : true } ) ;
kiri . client . zip ( [
{ name : "workspace.json" , data : JSON . stringify ( json ) }
] , progress => {
api . show . progress ( progress . percent / 100 , "compressing workspace" ) ;
} , output => {
api . show . progress ( 0 ) ;
api . util . download ( output , ` ${ name } .kmz ` ) ;
} ) ;
2020-06-19 19:23:09 -04:00
} ) ;
2020-04-07 21:45:21 -04:00
}
2021-03-31 10:41:28 -04:00
function settingsSave ( ev , name ) {
2020-06-13 18:27:31 -04:00
if ( ev ) {
ev . stopPropagation ( ) ;
ev . preventDefault ( ) ;
}
2020-06-19 19:23:09 -04:00
2022-02-17 17:55:26 -05:00
api . dialog . hide ( ) ;
let mode = api . mode . get ( ) ,
2020-03-16 23:57:14 -04:00
s = settings ( ) ,
def = "default" ,
cp = s . process ,
2020-11-20 09:46:10 -05:00
pl = s . sproc [ mode ] ,
2021-03-31 10:41:28 -04:00
lp = s . cproc [ mode ] ,
saveAs = ( name ) => {
if ( ! name ) {
return ;
}
2020-06-19 19:23:09 -04:00
let np = pl [ name ] = { } ;
cp . processName = name ;
2021-01-29 13:12:35 -05:00
pl [ name ] = Object . clone ( cp ) ;
2020-06-19 19:23:09 -04:00
for ( let k in cp ) {
if ( ! cp . hasOwnProperty ( k ) ) continue ;
np [ k ] = cp [ k ] ;
}
2021-01-29 13:12:35 -05:00
s . cproc [ mode ] = name ;
2020-11-15 22:12:45 -05:00
s . devproc [ s . device . deviceName ] = name ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
api . conf . update ( ) ;
api . event . settings ( ) ;
2024-05-16 18:18:09 -04:00
sync _put ( ) ;
2021-03-31 10:41:28 -04:00
} ;
if ( name ) {
saveAs ( name ) ;
} else {
2022-02-17 17:55:26 -05:00
uc . prompt ( "Save Settings As" , cp ? lp || def : def ) . then ( saveAs ) ;
2021-03-31 10:41:28 -04:00
}
2020-03-16 23:57:14 -04:00
}
function settingsLoad ( ) {
2022-02-17 17:55:26 -05:00
api . conf . show ( ) ;
2020-03-16 23:57:14 -04:00
}
2020-04-09 14:52:43 -04:00
function putLocalDevice ( devicename , obj ) {
settings ( ) . devices [ devicename ] = obj ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2020-03-16 23:57:14 -04:00
}
function removeLocalDevice ( devicename ) {
delete settings ( ) . devices [ devicename ] ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2024-05-16 18:18:09 -04:00
sync _put ( ) ;
2020-03-16 23:57:14 -04:00
}
function isLocalDevice ( devicename ) {
return settings ( ) . devices [ devicename ] ? true : false ;
}
function getSelectedDevice ( ) {
2022-02-17 17:55:26 -05:00
return api . device . get ( ) ;
2020-03-16 23:57:14 -04:00
}
2020-12-15 14:15:39 -05:00
function selectDevice ( devicename ) {
2020-03-16 23:57:14 -04:00
if ( isLocalDevice ( devicename ) ) {
setDeviceCode ( settings ( ) . devices [ devicename ] , devicename ) ;
} else {
2022-02-17 17:55:26 -05:00
let code = devices [ api . mode . get _lower ( ) ] [ devicename ] ;
2020-12-15 14:15:39 -05:00
if ( code ) {
setDeviceCode ( code , devicename ) ;
}
2020-03-16 23:57:14 -04:00
}
}
// only for local filters
2020-04-09 14:52:43 -04:00
function cloneDevice ( ) {
2022-03-06 17:15:28 -05:00
let name = ` ${ getSelectedDevice ( ) . replace ( /\./g , ' ' ) } ` ;
2022-02-17 17:55:26 -05:00
let code = api . clone ( settings ( ) . device ) ;
code . mode = api . mode . get ( ) ;
2022-03-06 17:15:28 -05:00
if ( name . toLowerCase ( ) . indexOf ( 'my ' ) >= 0 ) {
name = ` ${ name } copy ` ;
} else {
name = ` My ${ name } ` ;
}
2020-04-09 14:52:43 -04:00
putLocalDevice ( name , code ) ;
setDeviceCode ( code , name ) ;
2024-05-16 18:18:09 -04:00
sync _put ( ) ;
2020-03-16 23:57:14 -04:00
}
2022-10-18 10:36:41 -04:00
function updateLaserState ( ) {
const dev = settings ( ) . device ;
$ ( 'laser-on' ) . style . display = dev . useLaser ? 'flex' : 'none' ;
$ ( 'laser-off' ) . style . display = dev . useLaser ? 'flex' : 'none' ;
}
2020-03-16 23:57:14 -04:00
function setDeviceCode ( code , devicename ) {
2022-02-17 17:55:26 -05:00
api . event . emit ( 'device.select' , { devicename , code } ) ;
2020-03-16 23:57:14 -04:00
try {
if ( typeof ( code ) === 'string' ) code = js2o ( code ) || { } ;
2022-02-17 17:55:26 -05:00
api . event . emit ( 'device.set' , devicename ) ;
2020-04-18 11:34:54 -04:00
2022-02-17 17:55:26 -05:00
let mode = api . mode . get ( ) ,
2022-05-08 13:41:12 -04:00
lmode = mode . toLowerCase ( ) ,
2020-03-16 23:57:14 -04:00
current = settings ( ) ,
2020-04-09 14:52:43 -04:00
local = isLocalDevice ( devicename ) ,
2022-02-17 17:55:26 -05:00
dev = current . device = conf . device _from _code ( code , mode ) ,
2021-02-15 11:05:47 -05:00
dproc = current . devproc [ devicename ] , // last process name for this device
2021-01-22 22:09:29 -05:00
newdev = dproc === undefined , // first time device is selected
predev = current . filter [ mode ] , // previous device selection
chgdev = predev !== devicename ; // device is changing
2020-03-16 23:57:14 -04:00
2022-05-08 13:41:12 -04:00
// fill missing device fields
conf . fill _cull _once ( dev , conf . defaults [ lmode ] . d ) ;
2021-01-16 21:51:09 -05:00
// first time device use, add any print profiles and set to default if present
2021-01-22 22:09:29 -05:00
if ( code . profiles ) {
for ( let profile of code . profiles ) {
let profname = profile . processName ;
2021-02-15 11:05:47 -05:00
// if no saved profile by that name for this mode...
2021-01-22 22:09:29 -05:00
if ( ! current . sproc [ mode ] [ profname ] ) {
console . log ( 'adding profile' , profname , 'to' , mode ) ;
current . sproc [ mode ] [ profname ] = profile ;
}
2021-02-15 11:05:47 -05:00
// if it's a new device, seed the new profile name as last profile
2021-01-22 22:09:29 -05:00
if ( newdev && ! current . devproc [ devicename ] ) {
console . log ( 'setting default profile for new device' , devicename , 'to' , profname ) ;
current . devproc [ devicename ] = dproc = profname ;
2021-01-16 21:51:09 -05:00
}
}
2021-01-22 22:09:29 -05:00
}
2021-01-16 21:51:09 -05:00
2020-04-16 22:33:09 -04:00
dev . new = false ;
2020-04-16 18:27:28 -04:00
dev . deviceName = devicename ;
2024-06-01 16:49:26 -04:00
// ui.deviceName.value = devicename;
2022-02-17 17:55:26 -05:00
ui . deviceBelt . checked = dev . bedBelt ;
ui . deviceRound . checked = dev . bedRound ;
2024-06-09 15:33:30 -07:00
ui . deviceOrigin . checked = dev . ctOriginCenter || dev . originCenter || dev . bedRound ;
2022-02-17 17:55:26 -05:00
ui . fwRetract . checked = dev . fwRetract ;
if ( ! dev . filamentSource ) ui . filamentSource . selectedIndex = 0 ;
2020-04-09 14:52:43 -04:00
2024-05-29 23:11:44 -04:00
// add extruder selection buttons
if ( dev . extruders ) {
let ext = api . lists . extruders = [ ] ;
dev . internal = 0 ;
for ( let i = 0 ; i < dev . extruders . length ; i ++ ) {
ext . push ( { id : i , name : i } ) ;
}
}
2020-03-16 23:57:14 -04:00
// disable editing for non-local devices
[
2024-06-01 16:49:26 -04:00
// ui.deviceName,
2022-02-17 17:55:26 -05:00
ui . gcodePre ,
ui . gcodePost ,
ui . bedDepth ,
ui . bedWidth ,
ui . maxHeight ,
2022-10-18 10:27:41 -04:00
ui . useLaser ,
2022-02-17 17:55:26 -05:00
ui . resolutionX ,
ui . resolutionY ,
ui . deviceOrigin ,
ui . deviceRound ,
ui . deviceBelt ,
ui . fwRetract ,
ui . filamentSource ,
ui . deviceZMax ,
2022-05-11 21:17:42 -04:00
ui . gcodeTime ,
2022-02-17 17:55:26 -05:00
ui . gcodeFan ,
2022-05-08 13:41:12 -04:00
ui . gcodeFeature ,
2022-02-17 17:55:26 -05:00
ui . gcodeTrack ,
ui . gcodeLayer ,
ui . extFilament ,
ui . extNozzle ,
ui . spindleMax ,
ui . gcodeSpindle ,
ui . gcodeDwell ,
ui . gcodeChange ,
ui . gcodeFExt ,
ui . gcodeSpace ,
ui . gcodeStrip ,
ui . gcodeLaserOn ,
ui . gcodeLaserOff ,
ui . extPrev ,
ui . extNext ,
ui . extAdd ,
ui . extDel ,
ui . extOffsetX ,
ui . extOffsetY ,
ui . extSelect ,
ui . extDeselect
2020-03-16 23:57:14 -04:00
] . forEach ( function ( e ) {
e . disabled = ! local ;
} ) ;
2022-02-17 17:55:26 -05:00
ui . deviceSave . disabled = ! local ;
ui . deviceDelete . disabled = ! local ;
2024-06-01 16:49:26 -04:00
ui . deviceRename . disabled = ! local ;
2022-02-17 17:55:26 -05:00
ui . deviceExport . disabled = ! local ;
2024-06-01 16:49:26 -04:00
ui . deviceAdd . style . display = mode === 'SLA' ? 'none' : '' ;
2020-12-13 23:58:03 -05:00
if ( local ) {
2022-02-17 17:55:26 -05:00
ui . deviceAdd . innerText = "copy" ;
ui . deviceDelete . style . display = '' ;
2024-06-01 16:49:26 -04:00
ui . deviceRename . style . display = '' ;
2022-02-17 17:55:26 -05:00
ui . deviceExport . style . display = '' ;
2020-12-13 23:58:03 -05:00
} else {
2022-02-17 17:55:26 -05:00
ui . deviceAdd . innerText = "customize" ;
ui . deviceDelete . style . display = 'none' ;
2024-06-01 16:49:26 -04:00
ui . deviceRename . style . display = 'none' ;
2022-02-17 17:55:26 -05:00
ui . deviceExport . style . display = 'none' ;
2020-12-13 23:58:03 -05:00
}
2022-02-17 17:55:26 -05:00
ui . deviceAdd . disabled = dev . noclone ;
2020-03-16 23:57:14 -04:00
2022-02-19 12:43:42 -05:00
api . conf . update _fields ( ) ;
2022-10-12 17:38:55 -04:00
space . platform . setBelt ( isBelt ( ) ) ;
2020-03-16 23:57:14 -04:00
platform . update _size ( ) ;
2021-02-16 21:16:55 -05:00
platform . update _origin ( ) ;
platform . update ( ) ;
2022-10-18 10:36:41 -04:00
updateLaserState ( ) ;
2020-03-16 23:57:14 -04:00
2021-02-15 11:05:47 -05:00
// store current device name for this mode
2020-03-16 23:57:14 -04:00
current . filter [ mode ] = devicename ;
2021-02-15 11:05:47 -05:00
// cache device record for this mode (restored in setMode)
2020-11-29 00:10:41 -05:00
current . cdev [ mode ] = currentDevice = dev ;
2020-03-16 23:57:14 -04:00
2020-06-20 23:05:29 -04:00
if ( dproc ) {
// restore last process associated with this device
2022-02-17 17:55:26 -05:00
api . conf . load ( null , dproc ) ;
2020-06-20 23:05:29 -04:00
} else {
2022-02-17 17:55:26 -05:00
api . conf . update ( ) ;
2020-06-20 23:05:29 -04:00
}
2020-03-16 23:57:14 -04:00
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2021-01-22 22:09:29 -05:00
2021-11-28 12:03:50 -05:00
if ( isBelt ( ) ) {
2022-02-17 17:55:26 -05:00
// space.view.setHome(dev.bedBelt ? Math.PI/2 : 0, Math.PI / 2.5);
space . view . setHome ( 0 , Math . PI / 2.5 ) ;
2021-11-28 12:03:50 -05:00
} else {
2022-02-17 17:55:26 -05:00
space . view . setHome ( 0 ) ;
2021-11-28 12:03:50 -05:00
}
2021-01-22 22:09:29 -05:00
// when changing devices, update focus on widgets
if ( chgdev ) {
2022-02-17 17:55:26 -05:00
setTimeout ( api . space . set _focus , 0 ) ;
2021-01-22 22:09:29 -05:00
}
2022-10-18 20:12:42 -04:00
uc . refresh ( 1 ) ;
2021-11-10 11:40:34 -05:00
filamentSourceEditUpdate ( ) ;
2020-11-28 12:44:41 -05:00
2020-11-28 13:12:07 -05:00
if ( dev . imageURL ) {
if ( dev . imageURL !== deviceURL ) {
deviceURL = dev . imageURL ;
loadDeviceImage ( dev ) ;
}
2020-11-28 19:02:28 -05:00
} else {
clearDeviceTexture ( ) ;
2020-11-28 12:44:41 -05:00
}
2020-03-16 23:57:14 -04:00
} catch ( e ) {
2020-03-17 16:32:43 -04:00
console . log ( { error : e , device : code , devicename } ) ;
2022-02-17 17:55:26 -05:00
api . show . alert ( ` invalid or deprecated device: " ${ devicename } " ` , 10 ) ;
api . show . alert ( ` please select a new device ` , 10 ) ;
2020-04-13 17:42:40 -04:00
throw e ;
2020-04-09 15:29:34 -04:00
showDevices ( ) ;
2020-03-16 23:57:14 -04:00
}
2022-02-17 17:55:26 -05:00
api . function . clear ( ) ;
api . event . settings ( ) ;
2020-03-16 23:57:14 -04:00
}
2020-11-28 19:02:28 -05:00
function clearDeviceTexture ( ) {
if ( deviceImage ) {
2022-02-17 17:55:26 -05:00
space . world . remove ( deviceImage ) ;
2020-11-28 19:02:28 -05:00
deviceImage = null ;
2020-11-28 19:28:49 -05:00
deviceURL = null ;
2020-11-28 19:02:28 -05:00
}
}
function loadDeviceImage ( dev , url ) {
2021-01-27 23:47:06 -05:00
let turl = url || dev . imageURL ;
if ( ! turl ) return ;
new THREE . TextureLoader ( ) . load ( turl , texture => {
2020-11-28 19:02:28 -05:00
loadDeviceTexture ( dev , texture ) ;
} , inc => {
console . log ( { load _inc : inc } ) ;
} , error => {
2021-01-27 23:47:06 -05:00
console . log ( { load _error : error , turl } ) ;
2021-01-11 22:59:32 -05:00
clearDeviceTexture ( ) ;
2020-11-28 13:12:07 -05:00
} ) ;
}
2020-11-28 19:02:28 -05:00
function loadDeviceTexture ( dev , texture ) {
clearDeviceTexture ( ) ;
2020-11-29 00:10:41 -05:00
deviceTexture = texture ;
2022-02-17 17:55:26 -05:00
let { decals , dark } = api . conf . get ( ) . controller ;
2022-01-18 13:41:11 -05:00
// disable decals in dark mode
if ( ! ( texture && decals && ! dark ) ) {
2020-11-28 19:02:28 -05:00
return ;
}
let { width , height } = texture . image ;
let { bedWidth , bedDepth , bedHeight } = dev ;
let scale = dev . imageScale || 0.75 ;
let img _ratio = width / height ;
if ( scale <= 1 ) {
let dev _ratio = bedWidth / bedDepth ;
if ( dev _ratio > img _ratio ) {
scale *= bedDepth / height ;
} else {
scale *= bedWidth / width ;
}
} else if ( scale > 1 ) {
scale = ( scale / Math . max ( width , height ) ) ;
}
width *= scale ;
height *= scale ;
let pos = null ;
if ( true ) switch ( dev . imageAnchor ) {
case 1 : pos = { x : - ( bedWidth - width ) / 2 , y : ( bedDepth - height ) / 2 } ; break ;
case 2 : pos = { x : 0 , y : ( bedDepth - height ) / 2 } ; break ;
case 3 : pos = { x : ( bedWidth - width ) / 2 , y : ( bedDepth - height ) / 2 } ; break ;
case 4 : pos = { x : - ( bedWidth - width ) / 2 , y : 0 } ; break ;
case 5 : pos = { x : ( bedWidth - width ) / 2 , y : 0 } ; break ;
case 6 : pos = { x : - ( bedWidth - width ) / 2 , y : - ( bedDepth - height ) / 2 } ; break ;
case 7 : pos = { x : 0 , y : - ( bedDepth - height ) / 2 } ; break ;
case 8 : pos = { x : ( bedWidth - width ) / 2 , y : - ( bedDepth - height ) / 2 } ; break ;
}
2022-09-28 00:20:17 -04:00
let geometry = new THREE . PlaneGeometry ( width , height , 1 ) ,
2020-11-28 19:02:28 -05:00
material = new THREE . MeshBasicMaterial ( { map : texture , transparent : true } ) ,
mesh = new THREE . Mesh ( geometry , material ) ;
mesh . position . z = - bedHeight ;
mesh . renderOrder = - 1 ;
if ( pos ) {
mesh . position . x = pos . x ;
mesh . position . y = pos . y ;
}
2022-02-17 17:55:26 -05:00
space . world . add ( deviceImage = mesh ) ;
2020-11-28 19:02:28 -05:00
}
2024-06-01 16:49:26 -04:00
function updateDeviceName ( newname ) {
let selected = api . device . get ( ) ,
2020-04-16 20:39:00 -04:00
devs = settings ( ) . devices ;
if ( newname !== selected ) {
devs [ newname ] = devs [ selected ] ;
delete devs [ selected ] ;
selectDevice ( newname ) ;
2020-06-20 23:05:29 -04:00
updateDeviceList ( ) ;
2020-04-16 20:39:00 -04:00
}
}
2022-03-07 11:58:58 -05:00
function updateDeviceSize ( ) {
api . conf . update ( ) ;
platform . update _size ( ) ;
platform . update _origin ( ) ;
}
2020-03-16 23:57:14 -04:00
function renderDevices ( devices ) {
2024-06-01 16:49:26 -04:00
let selected = api . device . get ( ) || devices [ 0 ] ,
2022-02-17 17:55:26 -05:00
features = api . feature ,
2021-09-09 15:16:44 -04:00
devs = settings ( ) . devices ,
dfilter = typeof ( features . device _filter ) === 'function' ? features . device _filter : undefined ;
2020-03-16 23:57:14 -04:00
for ( let local in devs ) {
if ( ! ( devs . hasOwnProperty ( local ) && devs [ local ] ) ) {
continue ;
}
let dev = devs [ local ] ,
fdmCode = dev . cmd ,
2022-02-17 17:55:26 -05:00
fdmMode = ( api . mode . get ( ) === 'FDM' ) ;
2020-03-16 23:57:14 -04:00
2022-02-17 17:55:26 -05:00
if ( dev . mode ? ( dev . mode === api . mode . get ( ) ) : ( fdmCode ? fdmMode : ! fdmMode ) ) {
2020-03-16 23:57:14 -04:00
devices . push ( local ) ;
}
} ;
devices = devices . sort ( ) ;
2022-02-17 17:55:26 -05:00
api . event . emit ( 'devices.render' , devices ) ;
2021-11-15 14:10:15 -05:00
2022-02-17 17:55:26 -05:00
ui . deviceSave . onclick = function ( ) {
api . event . emit ( 'device.save' ) ;
api . function . clear ( ) ;
api . conf . save ( ) ;
2024-05-16 18:18:09 -04:00
sync _put ( ) ;
2020-03-16 23:57:14 -04:00
showDevices ( ) ;
2022-02-17 17:55:26 -05:00
api . modal . hide ( ) ;
2020-03-16 23:57:14 -04:00
} ;
2022-02-17 17:55:26 -05:00
ui . deviceAdd . onclick = function ( ) {
api . function . clear ( ) ;
2020-04-09 14:52:43 -04:00
cloneDevice ( ) ;
2020-03-16 23:57:14 -04:00
showDevices ( ) ;
} ;
2022-02-17 17:55:26 -05:00
ui . deviceDelete . onclick = function ( ) {
api . function . clear ( ) ;
2020-03-16 23:57:14 -04:00
removeLocalDevice ( getSelectedDevice ( ) ) ;
2024-06-01 16:49:26 -04:00
selectDevice ( getModeDevices ( ) [ 0 ] ) ;
2020-03-16 23:57:14 -04:00
showDevices ( ) ;
} ;
2024-06-01 16:49:26 -04:00
ui . deviceRename . onclick = function ( ) {
const newname = prompt ( ` Rename " ${ selected } ` , selected ) ;
if ( newname ) updateDeviceName ( newname ) ;
} ;
2022-02-24 19:53:22 -05:00
ui . deviceExport . onclick = function ( event ) {
const record = {
2022-02-17 17:55:26 -05:00
version : kiri . version ,
2020-09-24 08:52:59 -04:00
device : selected ,
2022-02-17 17:55:26 -05:00
process : api . process . code ( ) ,
2024-05-12 07:58:14 -04:00
profiles : event . altKey ? api . settings . prof ( ) : undefined ,
2020-09-24 08:52:59 -04:00
code : devs [ selected ] ,
time : Date . now ( )
2022-02-24 19:53:22 -05:00
} ;
let exp = api . util . b64enc ( record ) ;
api . device . export ( exp , selected , { event , record } ) ;
2020-09-24 08:52:59 -04:00
} ;
2020-03-16 23:57:14 -04:00
2020-12-13 23:58:03 -05:00
let dedup = { } ;
2024-06-01 16:49:26 -04:00
let list _cdev = [ ] ;
let list _mdev = [ ] ;
2020-03-16 23:57:14 -04:00
devices . forEach ( function ( device , index ) {
2020-12-13 23:58:03 -05:00
// prevent device from appearing twice
// such as local name = standard device name
if ( dedup [ device ] ) {
2020-03-16 23:57:14 -04:00
return ;
}
2020-12-13 23:58:03 -05:00
dedup [ device ] = device ;
let loc = isLocalDevice ( device ) ;
2021-09-09 15:16:44 -04:00
if ( dfilter && dfilter ( device ) === false ) {
return ;
}
2020-12-13 23:58:03 -05:00
if ( loc ) {
2024-06-01 16:49:26 -04:00
list _mdev . push ( h . option ( device ) ) ;
2020-12-13 23:58:03 -05:00
} else {
2024-06-01 16:49:26 -04:00
list _cdev . push ( h . option ( device ) ) ;
2020-03-16 23:57:14 -04:00
}
} ) ;
2024-06-01 16:49:26 -04:00
let dev _list = $ ( 'dev-list' ) ;
h . bind ( dev _list , [
h . option ( { _ : '-- My Devices --' , disabled : true } ) ,
... list _mdev ,
h . option ( { _ : '-- Stock Devices --' , disabled : true } ) ,
... list _cdev
] ) ;
let dev _opts = [ ... dev _list . options ] . map ( o => o . label ) ;
dev _list . selectedIndex = dev _opts . indexOf ( selected ) ;
dev _list . onchange = ev => {
const seldev = dev _list . options [ dev _list . selectedIndex ] ;
selectDevice ( seldev . label ) ;
api . platform . layout ( ) ;
2020-03-16 23:57:14 -04:00
}
2024-06-01 16:49:26 -04:00
selectDevice ( selected ) ;
2020-03-16 23:57:14 -04:00
}
function renderTools ( ) {
2022-02-17 17:55:26 -05:00
ui . toolSelect . innerHTML = '' ;
2020-03-16 23:57:14 -04:00
maxTool = 0 ;
editTools . forEach ( function ( tool , index ) {
maxTool = Math . max ( maxTool , tool . number ) ;
tool . order = index ;
let opt = DOC . createElement ( 'option' ) ;
opt . appendChild ( DOC . createTextNode ( tool . name ) ) ;
opt . onclick = function ( ) { selectTool ( tool ) } ;
2022-02-17 17:55:26 -05:00
ui . toolSelect . appendChild ( opt ) ;
2020-03-16 23:57:14 -04:00
} ) ;
}
function selectTool ( tool ) {
selectedTool = tool ;
2022-02-17 17:55:26 -05:00
ui . toolName . value = tool . name ;
ui . toolNum . value = tool . number ;
ui . toolFluteDiam . value = tool . flute _diam ;
ui . toolFluteLen . value = tool . flute _len ;
ui . toolShaftDiam . value = tool . shaft _diam ;
ui . toolShaftLen . value = tool . shaft _len ;
ui . toolTaperTip . value = tool . taper _tip || 0 ;
ui . toolMetric . checked = tool . metric ;
ui . toolType . selectedIndex = [ 'endmill' , 'ballmill' , 'tapermill' ] . indexOf ( tool . type ) ;
2023-02-17 11:34:51 -05:00
if ( tool . type === 'tapermill' ) {
ui . toolTaperAngle . value = kiri . driver . CAM . calcTaperAngle (
( tool . flute _diam - tool . taper _tip ) / 2 , tool . flute _len
2023-02-19 08:35:10 -05:00
) . round ( 1 ) ;
2023-02-17 11:34:51 -05:00
} else {
ui . toolTaperAngle . value = 0 ;
}
2020-03-16 23:57:14 -04:00
renderTool ( tool ) ;
}
function otag ( o ) {
if ( Array . isArray ( o ) ) {
let out = [ ]
o . forEach ( oe => out . push ( otag ( oe ) ) ) ;
return out . join ( '' ) ;
}
let tags = [ ] ;
Object . keys ( o ) . forEach ( key => {
let val = o [ key ] ;
let att = [ ] ;
Object . keys ( val ) . forEach ( tk => {
let tv = val [ tk ] ;
att . push ( ` ${ tk . replace ( /_/g , '-' ) } =" ${ tv } " ` ) ;
} ) ;
tags . push ( ` < ${ key } ${ att . join ( ' ' ) } ></ ${ key } > ` ) ;
} ) ;
return tags . join ( '' ) ;
}
function renderTool ( tool ) {
let type = selectedTool . type ;
let taper = type === 'tapermill' ;
2023-02-17 11:34:51 -05:00
ui . toolTaperAngle . disabled = taper ? undefined : 'true' ;
2022-02-17 17:55:26 -05:00
ui . toolTaperTip . disabled = taper ? undefined : 'true' ;
2020-03-16 23:57:14 -04:00
$ ( 'tool-view' ) . innerHTML = '<svg id="tool-svg" width="100%" height="100%"></svg>' ;
setTimeout ( ( ) => {
let svg = $ ( 'tool-svg' ) ;
let pad = 10 ;
let dim = { w : svg . clientWidth , h : svg . clientHeight }
let max = { w : dim . w - pad * 2 , h : dim . h - pad * 2 } ;
let off = { x : pad , y : pad } ;
let shaft _fill = "#cccccc" ;
let flute _fill = "#dddddd" ;
let stroke = "#777777" ;
let stroke _width = 3 ;
2020-12-09 16:01:18 -05:00
let stroke _thin = stroke _width / 2 ;
2020-03-16 23:57:14 -04:00
let shaft = tool . shaft _len || 1 ;
let flute = tool . flute _len || 1 ;
let tip _len = type === "ballmill" ? tool . flute _diam / 2 : 0 ;
let total _len = shaft + flute + tip _len ;
2020-12-09 16:01:18 -05:00
let units = dim . h / total _len ;
2020-03-16 23:57:14 -04:00
let shaft _len = ( shaft / total _len ) * max . h ;
let flute _len = ( flute / total _len ) * max . h ;
2020-12-09 16:01:18 -05:00
let total _wid = Math . max ( tool . flute _diam , tool . shaft _diam ) ;
let shaft _off = ( max . w - tool . shaft _diam * units ) / 2 ;
let flute _off = ( max . w - tool . flute _diam * units ) / 2 ;
let taper _off = ( max . w - ( tool . taper _tip || 0 ) * units ) / 2 ;
2020-03-16 23:57:14 -04:00
let parts = [
{ rect : {
x : off . x + shaft _off , y : off . y ,
width : max . w - shaft _off * 2 , height : shaft _len ,
stroke , fill : shaft _fill , stroke _width
} }
] ;
if ( type === "tapermill" ) {
let yoff = off . y + shaft _len ;
let mid = dim . w / 2 ;
parts . push ( { path : { stroke _width , stroke , fill : flute _fill , d : [
` M ${ off . x + flute _off } ${ yoff } ` ,
` L ${ off . x + taper _off } ${ yoff + flute _len } ` ,
` L ${ dim . w - off . x - taper _off } ${ yoff + flute _len } ` ,
` L ${ dim . w - off . x - flute _off } ${ yoff } ` ,
` z `
] . join ( '\n' ) } } ) ;
} else {
2020-12-09 16:01:18 -05:00
let x1 = off . x + flute _off ;
let y1 = off . y + shaft _len ;
let x2 = x1 + max . w - flute _off * 2 ;
let y2 = y1 + flute _len ;
2020-03-16 23:57:14 -04:00
parts . push ( { rect : {
x : off . x + flute _off , y : off . y + shaft _len ,
width : max . w - flute _off * 2 , height : flute _len ,
stroke , fill : flute _fill , stroke _width
} } ) ;
2020-12-09 16:01:18 -05:00
parts . push ( { line : { x1 , y1 , x2 , y2 , stroke , stroke _width : stroke _thin } } ) ;
parts . push ( { line : {
x1 : ( x1 + x2 ) / 2 , y1 , x2 , y2 : ( y1 + y2 ) / 2 ,
stroke , stroke _width : stroke _thin
} } ) ;
parts . push ( { line : {
x1 , y1 : ( y1 + y2 ) / 2 , x2 : ( x1 + x2 ) / 2 , y2 ,
stroke , stroke _width : stroke _thin
} } ) ;
2020-03-16 23:57:14 -04:00
}
if ( type === "ballmill" ) {
let rad = ( max . w - flute _off * 2 ) / 2 ;
let xend = dim . w - off . x - flute _off ;
let yoff = off . y + shaft _len + flute _len + stroke _width / 2 ;
parts . push ( { path : { stroke _width , stroke , fill : flute _fill , d : [
` M ${ off . x + flute _off } ${ yoff } ` ,
` A ${ rad } ${ rad } 0 0 0 ${ xend } ${ yoff } ` ,
// `L ${off.x + flute_off} ${yoff}`
] . join ( '\n' ) } } )
}
svg . innerHTML = otag ( parts ) ;
} , 10 ) ;
}
2023-02-17 11:34:51 -05:00
function updateTool ( ev ) {
2022-02-17 17:55:26 -05:00
selectedTool . name = ui . toolName . value ;
selectedTool . number = parseInt ( ui . toolNum . value ) ;
selectedTool . flute _diam = parseFloat ( ui . toolFluteDiam . value ) ;
selectedTool . flute _len = parseFloat ( ui . toolFluteLen . value ) ;
selectedTool . shaft _diam = parseFloat ( ui . toolShaftDiam . value ) ;
selectedTool . shaft _len = parseFloat ( ui . toolShaftLen . value ) ;
selectedTool . taper _tip = parseFloat ( ui . toolTaperTip . value ) ;
selectedTool . metric = ui . toolMetric . checked ;
selectedTool . type = [ 'endmill' , 'ballmill' , 'tapermill' ] [ ui . toolType . selectedIndex ] ;
2023-02-17 11:34:51 -05:00
if ( selectedTool . type === 'tapermill' ) {
const CAM = kiri . driver . CAM ;
const rad = ( selectedTool . flute _diam - selectedTool . taper _tip ) / 2 ;
if ( ev && ev . target === ui . toolTaperAngle ) {
const angle = parseFloat ( ev . target . value ) ;
const len = CAM . calcTaperLength ( rad , angle * DEG2RAD ) ;
selectedTool . flute _len = len ;
2023-02-19 08:35:10 -05:00
ui . toolTaperAngle . value = angle . round ( 1 ) ;
2023-02-17 11:34:51 -05:00
ui . toolFluteLen . value = selectedTool . flute _len . round ( 4 ) ;
} else {
2023-02-19 08:35:10 -05:00
ui . toolTaperAngle . value = CAM . calcTaperAngle ( rad , selectedTool . flute _len ) . round ( 1 ) ;
2023-02-17 11:34:51 -05:00
}
} else {
ui . toolTaperAngle . value = 0 ;
}
2020-03-16 23:57:14 -04:00
renderTools ( ) ;
2022-02-17 17:55:26 -05:00
ui . toolSelect . selectedIndex = selectedTool . order ;
2020-03-16 23:57:14 -04:00
setToolChanged ( true ) ;
renderTool ( selectedTool ) ;
}
function setToolChanged ( changed ) {
editTools . changed = changed ;
2022-02-17 17:55:26 -05:00
ui . toolsSave . disabled = ! changed ;
2020-03-16 23:57:14 -04:00
}
function showTools ( ) {
2022-02-17 17:55:26 -05:00
if ( api . mode . get _id ( ) !== MODES . CAM ) return ;
2024-05-16 18:18:09 -04:00
sync _get ( ) . then ( _showTools ) ;
}
function _showTools ( ) {
2020-03-16 23:57:14 -04:00
let selectedIndex = null ;
editTools = settings ( ) . tools . slice ( ) . sort ( ( a , b ) => {
return a . name > b . name ? 1 : - 1 ;
} ) ;
setToolChanged ( false ) ;
2022-02-17 17:55:26 -05:00
ui . toolsClose . onclick = function ( ) {
2020-03-16 23:57:14 -04:00
if ( editTools . changed && ! confirm ( "abandon changes?" ) ) return ;
2022-02-17 17:55:26 -05:00
api . dialog . hide ( ) ;
2020-03-16 23:57:14 -04:00
} ;
2022-02-17 17:55:26 -05:00
ui . toolAdd . onclick = function ( ) {
2020-03-16 23:57:14 -04:00
editTools . push ( {
id : Date . now ( ) ,
number : maxTool + 1 ,
name : "new" ,
type : "endmill" ,
shaft _diam : 0.25 ,
shaft _len : 1 ,
flute _diam : 0.25 ,
flute _len : 2 ,
// taper_angle: 70,
taper _tip : 0 ,
metric : false
} ) ;
setToolChanged ( true ) ;
renderTools ( ) ;
2022-02-17 17:55:26 -05:00
ui . toolSelect . selectedIndex = editTools . length - 1 ;
2020-03-16 23:57:14 -04:00
selectTool ( editTools [ editTools . length - 1 ] ) ;
} ;
2022-02-17 17:55:26 -05:00
ui . toolDelete . onclick = function ( ) {
2020-03-16 23:57:14 -04:00
editTools . remove ( selectedTool ) ;
setToolChanged ( true ) ;
renderTools ( ) ;
} ;
2022-02-17 17:55:26 -05:00
ui . toolsSave . onclick = function ( ) {
2020-03-16 23:57:14 -04:00
if ( selectedTool ) updateTool ( ) ;
settings ( ) . tools = editTools . sort ( ( a , b ) => {
return a . name < b . name ? - 1 : 1 ;
} ) ;
setToolChanged ( false ) ;
2022-02-17 17:55:26 -05:00
api . conf . save ( ) ;
2022-02-19 12:43:42 -05:00
api . conf . update _fields ( ) ;
2022-02-17 17:55:26 -05:00
api . event . settings ( ) ;
2024-05-16 18:18:09 -04:00
sync _put ( ) ;
2020-03-16 23:57:14 -04:00
} ;
2022-10-30 00:33:10 -04:00
ui . toolsExport . onclick = ( ) => {
uc . prompt ( "Export Tools Filename" , "tools" ) . then ( name => {
if ( ! name ) {
return ;
}
const record = {
version : kiri . version ,
tools : api . conf . get ( ) . tools ,
time : Date . now ( )
} ;
api . util . download ( api . util . b64enc ( record ) , ` ${ name } .km ` ) ;
} ) ;
} ;
2020-03-16 23:57:14 -04:00
renderTools ( ) ;
if ( editTools . length > 0 ) {
selectTool ( editTools [ 0 ] ) ;
2022-02-17 17:55:26 -05:00
ui . toolSelect . selectedIndex = 0 ;
2020-03-16 23:57:14 -04:00
} else {
2022-02-17 17:55:26 -05:00
ui . toolAdd . onclick ( ) ;
2020-03-16 23:57:14 -04:00
}
2022-02-17 17:55:26 -05:00
api . dialog . show ( 'tools' ) ;
ui . toolSelect . focus ( ) ;
2020-03-16 23:57:14 -04:00
}
2022-10-30 00:33:10 -04:00
// not the best way to do this, but main decl of api.show is broken
api . show . tools = showTools ;
2024-06-01 16:49:26 -04:00
function getModeDevices ( ) {
2024-06-09 11:00:53 -07:00
// devices are injected into self scope by
// app.js generateDevices()
2024-06-01 16:49:26 -04:00
return Object . keys ( devices [ api . mode . get _lower ( ) ] ) . sort ( ) ;
}
2020-06-06 20:05:21 -04:00
function updateDeviceList ( ) {
2024-06-01 16:49:26 -04:00
renderDevices ( getModeDevices ( ) ) ;
2020-06-06 20:05:21 -04:00
}
2024-05-16 18:18:09 -04:00
async function sync _get ( ) {
2024-05-16 18:53:38 -04:00
await api . settings . sync . get ( ) ;
2024-05-16 18:18:09 -04:00
}
async function sync _put ( ) {
2024-05-16 18:53:38 -04:00
await api . settings . sync . put ( ) ;
2024-05-16 18:18:09 -04:00
}
2020-03-16 23:57:14 -04:00
function showDevices ( ) {
2024-05-16 18:18:09 -04:00
sync _get ( ) . then ( _showDevices ) ;
}
function _showDevices ( ) {
2024-06-01 16:49:26 -04:00
updateDeviceList ( ) ;
2022-02-17 17:55:26 -05:00
api . modal . show ( 'setup' ) ;
2020-03-16 23:57:14 -04:00
}
function dragOverHandler ( evt ) {
evt . stopPropagation ( ) ;
evt . preventDefault ( ) ;
2021-02-24 12:28:17 -05:00
// prevent drop actions when a dialog is open
2022-02-17 17:55:26 -05:00
if ( api . modal . visible ( ) ) {
2021-02-24 12:28:17 -05:00
return ;
}
2020-03-16 23:57:14 -04:00
evt . dataTransfer . dropEffect = 'copy' ;
2022-02-17 17:55:26 -05:00
let oldcolor = space . platform . setColor ( 0x00ff00 ) ;
2020-04-22 00:24:06 -04:00
if ( oldcolor !== 0x00ff00 ) platformColor = oldcolor ;
2020-03-16 23:57:14 -04:00
}
function dragLeave ( ) {
2022-02-17 17:55:26 -05:00
space . platform . setColor ( platformColor ) ;
2020-03-16 23:57:14 -04:00
}
function dropHandler ( evt ) {
evt . stopPropagation ( ) ;
evt . preventDefault ( ) ;
2021-02-24 12:28:17 -05:00
// prevent drop actions when a dialog is open
2022-02-17 17:55:26 -05:00
if ( api . modal . visible ( ) ) {
2021-02-24 12:28:17 -05:00
return ;
}
2022-02-17 17:55:26 -05:00
space . platform . setColor ( platformColor ) ;
2020-03-16 23:57:14 -04:00
2020-06-19 19:23:09 -04:00
let files = evt . dataTransfer . files ;
2022-02-17 17:55:26 -05:00
switch ( api . feature . drop _group ) {
2020-07-09 09:51:42 -04:00
case true :
2022-02-17 17:55:26 -05:00
return api . platform . load _files ( files , [ ] ) ;
2020-07-09 09:51:42 -04:00
case false :
2022-02-17 17:55:26 -05:00
return api . platform . load _files ( files , undefined ) ;
2020-07-09 09:51:42 -04:00
}
2021-12-07 18:28:49 -05:00
if ( files . length === 1 ) {
2022-02-17 17:55:26 -05:00
api . platform . load _files ( files ) ;
2020-06-19 19:23:09 -04:00
} else {
2022-02-17 17:55:26 -05:00
uc . confirm ( ` group ${ files . length } files? ` ) . then ( yes => {
api . platform . load _files ( files , yes ? [ ] : undefined ) ;
2021-12-07 18:28:49 -05:00
} ) ;
2020-06-19 19:23:09 -04:00
}
2020-03-16 23:57:14 -04:00
}
function loadCatalogFile ( e ) {
2022-02-17 17:55:26 -05:00
api . widgets . load ( e . target . getAttribute ( 'load' ) , function ( widget ) {
2020-03-16 23:57:14 -04:00
platform . add ( widget ) ;
2022-02-17 17:55:26 -05:00
api . dialog . hide ( ) ;
2020-03-16 23:57:14 -04:00
} ) ;
}
function updateCatalog ( files ) {
2022-02-17 17:55:26 -05:00
let table = ui . catalogList ,
2020-03-16 23:57:14 -04:00
list = [ ] ;
table . innerHTML = '' ;
for ( let name in files ) {
list . push ( { n : name , ln : name . toLowerCase ( ) , v : files [ name ] . vertices , t : files [ name ] . updated } ) ;
}
list . sort ( function ( a , b ) {
return a . ln < b . ln ? - 1 : 1 ;
} ) ;
for ( let i = 0 ; i < list . length ; i ++ ) {
let row = DOC . createElement ( 'div' ) ,
2020-06-09 19:23:03 -04:00
renm = DOC . createElement ( 'button' ) ,
2020-03-16 23:57:14 -04:00
load = DOC . createElement ( 'button' ) ,
2020-06-09 19:23:03 -04:00
size = DOC . createElement ( 'button' ) ,
2020-03-16 23:57:14 -04:00
del = DOC . createElement ( 'button' ) ,
file = list [ i ] ,
2020-06-09 19:23:03 -04:00
name = file . n ,
2020-06-09 20:22:11 -04:00
date = new Date ( file . t ) ,
2020-06-09 19:23:03 -04:00
split = name . split ( '.' ) ,
short = split [ 0 ] ,
ext = split [ 1 ] ? ` . ${ split [ 1 ] } ` : '' ;
renm . setAttribute ( 'class' , 'rename' ) ;
renm . setAttribute ( 'title' , 'rename file' ) ;
2020-11-20 09:46:10 -05:00
renm . innerHTML = '<i class="far fa-edit"></i>' ;
2020-06-09 19:23:03 -04:00
renm . onclick = ( ) => {
let newname = prompt ( ` rename file ` , short ) ;
if ( newname && newname !== short ) {
2022-02-17 17:55:26 -05:00
catalog . rename ( name , ` ${ newname } ${ ext } ` , then => {
catalog . refresh ( ) ;
2020-06-09 19:23:03 -04:00
} ) ;
}
} ;
2020-03-16 23:57:14 -04:00
load . setAttribute ( 'load' , name ) ;
2020-06-09 20:22:11 -04:00
load . setAttribute ( 'title' , ` file: ${ name } \n vertices: ${ file . v } \n date: ${ date } ` ) ;
2020-03-16 23:57:14 -04:00
load . onclick = loadCatalogFile ;
2020-06-09 19:23:03 -04:00
load . appendChild ( DOC . createTextNode ( short ) ) ;
2020-03-16 23:57:14 -04:00
del . setAttribute ( 'del' , name ) ;
del . setAttribute ( 'title' , "remove '" + name + "'" ) ;
2022-02-17 17:55:26 -05:00
del . onclick = ( ) => { catalog . deleteFile ( name ) } ;
2020-11-20 09:46:10 -05:00
del . innerHTML = '<i class="far fa-trash-alt"></i>' ;
2020-03-16 23:57:14 -04:00
2020-06-09 19:23:03 -04:00
size . setAttribute ( "disabled" , true ) ;
size . setAttribute ( "class" , "label" ) ;
2022-02-17 17:55:26 -05:00
size . appendChild ( DOC . createTextNode ( base . util . comma ( file . v ) ) ) ;
2020-06-09 19:23:03 -04:00
2020-07-01 17:26:39 -04:00
row . setAttribute ( "class" , "f-row a-center" ) ;
2020-06-09 19:23:03 -04:00
row . appendChild ( renm ) ;
2020-03-16 23:57:14 -04:00
row . appendChild ( load ) ;
2020-06-09 19:23:03 -04:00
row . appendChild ( size ) ;
2020-03-16 23:57:14 -04:00
row . appendChild ( del ) ;
table . appendChild ( row ) ;
}
}
2021-03-31 17:56:24 -04:00
function isMultiHead ( ) {
2022-02-17 17:55:26 -05:00
let dev = api . conf . get ( ) . device ;
2021-04-11 19:59:03 -04:00
return isNotBelt ( ) && dev . extruders && dev . extruders . length > 1 ;
2021-03-31 17:56:24 -04:00
}
2021-01-16 13:08:44 -05:00
function isBelt ( ) {
2022-02-17 17:55:26 -05:00
return ui . deviceBelt . checked ;
2021-01-16 13:08:44 -05:00
}
function isNotBelt ( ) {
return ! isBelt ( ) ;
}
2020-03-16 23:57:14 -04:00
// MAIN INITIALIZATION FUNCTION
function init _one ( ) {
2023-03-12 12:22:35 -04:00
let { event , conf , view , show } = api ;
2024-05-27 13:53:16 -04:00
let { bound , toInt , toFloat } = uc ;
let { newBlank , newButton , newBoolean , newGroup , newInput } = uc ;
2024-06-02 14:10:16 -04:00
let { newSelect , newText , newRow , newGCode , newDiv } = uc ;
2023-02-07 14:54:55 -05:00
2021-12-09 23:12:35 -05:00
event . emit ( 'init.one' ) ;
2020-04-20 17:50:23 -04:00
2020-03-29 20:23:48 -04:00
// ensure we have settings from last session
2021-12-09 23:12:35 -05:00
conf . restore ( ) ;
2020-03-29 20:23:48 -04:00
2020-06-07 23:02:05 -04:00
let container = $ ( 'container' ) ,
2020-04-08 09:38:32 -04:00
welcome = $ ( 'welcome' ) ,
2020-06-06 23:21:42 -04:00
gcode = $ ( 'dev-gcode' ) ,
2020-06-07 23:02:05 -04:00
tracker = $ ( 'tracker' ) ,
2020-10-27 21:09:28 -04:00
controller = settings ( ) . controller ;
2020-06-09 00:25:11 -04:00
WIN . addEventListener ( "resize" , ( ) => {
2021-12-09 23:12:35 -05:00
event . emit ( 'resize' ) ;
2020-06-09 00:25:11 -04:00
} ) ;
2021-12-09 23:12:35 -05:00
event . on ( 'resize' , ( ) => {
2020-06-09 00:25:11 -04:00
if ( WIN . innerHeight < 800 ) {
2022-02-17 17:55:26 -05:00
ui . modalBox . classList . add ( 'mh85' ) ;
2020-06-09 00:25:11 -04:00
} else {
2022-02-17 17:55:26 -05:00
ui . modalBox . classList . remove ( 'mh85' ) ;
2020-06-09 00:25:11 -04:00
}
2021-12-09 23:12:35 -05:00
view . update _slider ( ) ;
2020-06-09 00:25:11 -04:00
} ) ;
2020-03-09 11:02:09 -04:00
2022-02-17 17:55:26 -05:00
space . sky . showGrid ( false ) ;
space . sky . setColor ( controller . dark ? 0 : 0xffffff ) ;
space . setAntiAlias ( controller . antiAlias ) ;
space . init ( container , function ( delta ) {
let vars = api . var ;
2021-12-09 23:12:35 -05:00
if ( vars . layer _max === 0 || ! delta ) return ;
2021-03-04 13:22:53 -05:00
if ( controller . reverseZoom ) delta = - delta ;
2021-12-09 23:12:35 -05:00
let same = vars . layer _hi === vars . layer _lo ;
let track = vars . layer _lo > 0 ;
2020-06-14 19:13:46 -04:00
if ( delta > 0 ) {
2021-12-09 23:12:35 -05:00
vars . layer _hi = Math . max ( same ? 0 : vars . layer _lo , vars . layer _hi - 1 ) ;
2020-06-14 19:13:46 -04:00
if ( track ) {
2021-12-09 23:12:35 -05:00
vars . layer _lo = Math . max ( 0 , vars . layer _lo - 1 ) ;
2020-06-14 19:13:46 -04:00
}
} else if ( delta < 0 ) {
2021-12-09 23:12:35 -05:00
vars . layer _hi = Math . min ( vars . layer _max , vars . layer _hi + 1 ) ;
2020-06-14 19:13:46 -04:00
if ( track ) {
2021-12-09 23:12:35 -05:00
vars . layer _lo = Math . min ( vars . layer _hi , vars . layer _lo + 1 ) ;
2020-06-14 19:13:46 -04:00
}
}
if ( same ) {
2021-12-09 23:12:35 -05:00
vars . layer _lo = vars . layer _hi ;
2020-06-14 19:13:46 -04:00
}
2021-12-09 23:12:35 -05:00
view . update _slider ( ) ;
show . slices ( ) ;
2021-03-04 13:22:53 -05:00
} , controller . ortho ) ;
2022-02-17 17:55:26 -05:00
space . platform . onMove ( conf . save ) ;
space . platform . setRound ( true ) ;
space . useDefaultKeys ( api . feature . on _key === undefined || api . feature . on _key _defaults ) ;
2024-06-02 18:55:20 -04:00
updateDrawer ( ) ;
2020-03-09 11:02:09 -04:00
2022-02-24 19:53:22 -05:00
// api augmentation with local functions
api . device . export = deviceExport ;
2022-02-17 17:55:26 -05:00
Object . assign ( ui , {
2020-12-16 21:25:45 -05:00
tracker : tracker ,
container : container ,
2020-03-09 11:02:09 -04:00
alert : {
2020-03-16 13:11:02 -04:00
dialog : $ ( 'alert-area' ) ,
text : $ ( 'alert-text' )
2020-03-09 11:02:09 -04:00
} ,
2020-11-16 11:00:52 -05:00
func : {
2020-06-09 18:12:59 -04:00
slice : $ ( 'act-slice' ) ,
preview : $ ( 'act-preview' ) ,
2020-12-02 10:00:41 -05:00
animate : $ ( 'act-animate' ) ,
2020-06-09 18:12:59 -04:00
export : $ ( 'act-export' )
} ,
2020-12-06 11:52:37 -05:00
label : {
slice : $ ( 'label-slice' ) ,
preview : $ ( 'label-preview' ) ,
animate : $ ( 'label-animate' ) ,
2020-12-06 21:25:31 -05:00
export : $ ( 'label-export' ) ,
2020-12-06 11:52:37 -05:00
} ,
2020-11-16 11:00:52 -05:00
acct : {
2024-05-19 22:31:25 -04:00
help : $ ( 'app-help' ) ,
export : $ ( 'app-export' )
2020-11-16 11:00:52 -05:00
} ,
2020-12-20 14:15:35 -05:00
dev : {
2022-02-24 20:06:57 -05:00
header : $ ( 'dev-header' ) ,
2020-12-20 14:15:35 -05:00
search : $ ( 'dev-search' ) ,
filter : $ ( 'dev-filter' )
} ,
2021-10-08 21:15:54 -04:00
mesh : {
name : $ ( 'mesh-name' ) ,
points : $ ( 'mesh-points' ) ,
faces : $ ( 'mesh-faces' ) ,
} ,
2020-11-16 11:00:52 -05:00
2022-01-28 16:54:53 -05:00
stats : {
fps : $ ( 'fps' ) ,
rms : $ ( 'rms' ) ,
div : $ ( 'stats' ) ,
2022-01-31 15:20:34 -05:00
rnfo : $ ( 'rnfo' ) ,
2022-01-28 16:54:53 -05:00
} ,
2020-06-08 00:08:19 -04:00
load : $ ( 'load-file' ) ,
2020-11-10 21:48:04 -05:00
speeds : $ ( 'speeds' ) ,
speedbar : $ ( 'speedbar' ) ,
2020-12-06 21:25:31 -05:00
context : $ ( 'context-menu' ) ,
2020-06-08 00:08:19 -04:00
2021-01-27 17:58:04 -05:00
ltsetup : $ ( 'lt-setup' ) ,
ltfile : $ ( 'lt-file' ) ,
ltview : $ ( 'lt-view' ) ,
2022-10-17 00:59:27 -04:00
ltact : $ ( 'lt-start' ) ,
2021-10-07 22:59:05 -04:00
edit : $ ( 'lt-tools' ) ,
2024-05-19 22:31:25 -04:00
nozzle : $ ( 'menu-nozzle' ) ,
2020-06-06 11:17:04 -04:00
2020-03-16 13:11:02 -04:00
modal : $ ( 'modal' ) ,
2020-06-09 00:25:11 -04:00
modalBox : $ ( 'modal-box' ) ,
2020-06-06 11:17:04 -04:00
help : $ ( 'mod-help' ) ,
2020-06-06 20:05:21 -04:00
setup : $ ( 'mod-setup' ) ,
prefs : $ ( 'mod-prefs' ) ,
files : $ ( 'mod-files' ) ,
2020-06-07 23:02:05 -04:00
saves : $ ( 'mod-saves' ) ,
2021-10-08 14:55:46 -04:00
tools : $ ( 'mod-tools' ) ,
2020-06-06 11:17:04 -04:00
print : $ ( 'mod-print' ) ,
local : $ ( 'mod-local' ) ,
2020-06-12 20:39:59 -04:00
any : $ ( 'mod-any' ) ,
2020-06-06 20:05:21 -04:00
2020-06-06 11:17:04 -04:00
catalogBody : $ ( 'catalogBody' ) ,
catalogList : $ ( 'catalogList' ) ,
2020-03-16 13:11:02 -04:00
devices : $ ( 'devices' ) ,
deviceAdd : $ ( 'device-add' ) ,
deviceDelete : $ ( 'device-del' ) ,
2024-06-01 16:49:26 -04:00
deviceRename : $ ( 'device-ren' ) ,
2020-09-24 08:52:59 -04:00
deviceExport : $ ( 'device-exp' ) ,
2020-03-16 13:11:02 -04:00
deviceSave : $ ( 'device-save' ) ,
2020-06-06 23:21:42 -04:00
2020-03-16 13:11:02 -04:00
toolsSave : $ ( 'tools-save' ) ,
toolsClose : $ ( 'tools-close' ) ,
2022-10-30 00:33:10 -04:00
toolsExport : $ ( 'tools-export' ) ,
2020-03-16 13:11:02 -04:00
toolSelect : $ ( 'tool-select' ) ,
toolAdd : $ ( 'tool-add' ) ,
toolDelete : $ ( 'tool-del' ) ,
toolType : $ ( 'tool-type' ) ,
toolName : $ ( 'tool-name' ) ,
toolNum : $ ( 'tool-num' ) ,
toolFluteDiam : $ ( 'tool-fdiam' ) ,
toolFluteLen : $ ( 'tool-flen' ) ,
toolShaftDiam : $ ( 'tool-sdiam' ) ,
toolShaftLen : $ ( 'tool-slen' ) ,
2023-02-17 11:34:51 -05:00
toolTaperAngle : $ ( 'tool-tangle' ) ,
2020-03-16 13:11:02 -04:00
toolTaperTip : $ ( 'tool-ttip' ) ,
toolMetric : $ ( 'tool-metric' ) ,
2020-06-06 23:21:42 -04:00
2020-06-07 23:02:05 -04:00
setMenu : $ ( 'set-menu' ) ,
2020-03-16 13:11:02 -04:00
settings : $ ( 'settings' ) ,
settingsBody : $ ( 'settingsBody' ) ,
settingsList : $ ( 'settingsList' ) ,
2020-06-06 23:21:42 -04:00
2020-06-07 23:02:05 -04:00
slider : $ ( 'slider' ) ,
sliderMax : $ ( 'slider-max' ) ,
2020-06-08 21:46:53 -04:00
sliderMin : $ ( 'slider-zero' ) ,
2020-06-07 23:02:05 -04:00
sliderLo : $ ( 'slider-lo' ) ,
sliderMid : $ ( 'slider-mid' ) ,
sliderHi : $ ( 'slider-hi' ) ,
sliderHold : $ ( 'slider-hold' ) ,
sliderRange : $ ( 'slider-center' ) ,
2020-06-06 23:21:42 -04:00
2020-06-05 23:21:53 -04:00
loading : $ ( 'progress' ) . style ,
progress : $ ( 'progbar' ) . style ,
prostatus : $ ( 'progtxt' ) ,
2020-06-06 23:21:42 -04:00
2020-03-16 13:11:02 -04:00
selection : $ ( 'selection' ) ,
2020-04-11 09:22:37 -04:00
sizeX : $ ( 'size_x' ) ,
sizeY : $ ( 'size_y' ) ,
sizeZ : $ ( 'size_z' ) ,
2020-03-16 13:11:02 -04:00
scaleX : $ ( 'scale_x' ) ,
scaleY : $ ( 'scale_y' ) ,
scaleZ : $ ( 'scale_z' ) ,
2020-04-11 09:22:37 -04:00
lockX : $ ( 'lock_x' ) ,
lockY : $ ( 'lock_y' ) ,
lockZ : $ ( 'lock_z' ) ,
2020-03-16 13:11:02 -04:00
stock : $ ( 'stock' ) ,
stockWidth : $ ( 'stock-width' ) ,
stockDepth : $ ( 'stock-width' ) ,
stockHeight : $ ( 'stock-width' ) ,
2020-03-16 12:11:30 -04:00
2024-05-26 22:51:44 -04:00
/** Device Browser / Editor */
2024-06-02 14:10:16 -04:00
_ _ _ _ _ : newDiv ( { class : "f-col t-body t-inset" , addto : $ ( 'dev-config' ) , set : true } ) ,
2024-06-01 16:49:26 -04:00
device : newGroup ( LANG . dv _gr _dev , null , { group : "ddev" , inline : true , class : "noshow" } ) ,
_ _ _ _ _ : newGroup ( "workspace" , null , { group : "dext" , inline : true } ) ,
bedWidth : newInput ( 'X (width)' , { title : LANG . dv _bedw _l , convert : toFloat , size : 6 , units : true , round : 2 , action : updateDeviceSize } ) ,
bedDepth : newInput ( 'Y (depth)' , { title : LANG . dv _bedw _l , convert : toFloat , size : 6 , units : true , round : 2 , action : updateDeviceSize } ) ,
maxHeight : newInput ( 'Z (height)' , { title : LANG . dv _bedw _l , convert : toFloat , size : 6 , units : true , round : 2 , action : updateDeviceSize } ) ,
resolutionX : newInput ( LANG . dv _rezx _s , { title : LANG . dv _rezx _l , convert : toInt , size : 6 , modes : SLA } ) ,
resolutionY : newInput ( LANG . dv _rezy _s , { title : LANG . dv _rezy _l , convert : toInt , size : 6 , modes : SLA } ) ,
2024-06-11 13:16:02 -07:00
_ _ _ _ _ : newDiv ( { class : "f-col t-body t-inset" , addto : $ ( 'dev-config' ) , set : true , modes : NO _WEDM } ) ,
_ _ _ _ _ : newGroup ( "firmware" , null , { group : "dext" , inline : true , modes : NO _WEDM } ) ,
2024-06-01 16:49:26 -04:00
fwRetract : newBoolean ( LANG . dv _retr _s , onBooleanClick , { title : LANG . dv _retr _l , modes : FDM } ) ,
2024-06-11 13:16:02 -07:00
deviceOrigin : newBoolean ( LANG . dv _orgc _s , onBooleanClick , { title : LANG . dv _orgc _l , modes : FDM _LZN , show : ( ) => ! ui . deviceRound . checked } ) ,
2024-06-01 16:49:26 -04:00
deviceRound : newBoolean ( LANG . dv _bedc _s , onBooleanClick , { title : LANG . dv _bedc _l , modes : FDM , trigger : true , show : isNotBelt } ) ,
deviceBelt : newBoolean ( LANG . dv _belt _s , onBooleanClick , { title : LANG . dv _belt _l , modes : FDM , trigger : true , show : ( ) => ! ui . deviceRound . checked } ) ,
separator : newBlank ( { class : "pop-sep" , modes : FDM , driven : true } ) ,
2024-05-27 13:53:16 -04:00
spindleMax : newInput ( LANG . dv _spmx _s , { title : LANG . dv _spmx _l , convert : toInt , size : 5 , modes : CAM , trigger : 1 } ) ,
deviceZMax : newInput ( LANG . dv _zmax _s , { title : LANG . dv _zmax _l , convert : toInt , size : 5 , modes : FDM } ) ,
gcodeTime : newInput ( LANG . dv _time _s , { title : LANG . dv _time _l , convert : toFloat , size : 5 , modes : FDM } ) ,
2024-06-01 16:49:26 -04:00
filamentSource : newSelect ( LANG . dv _fsrc _s , { title : LANG . dv _fsrc _l , action : filamentSourceSave , modes : FDM , show : ( ) => false } , "filasrc" ) ,
2024-06-02 14:10:16 -04:00
_ _ _ _ _ : newDiv ( { class : "f-col t-body t-inset" , addto : $ ( 'dev-config' ) , set : true , modes : FDM } ) ,
2024-06-01 16:49:26 -04:00
extruder : newGroup ( LANG . dv _gr _ext , null , { group : "dext" , inline : true } ) ,
2024-05-27 13:53:16 -04:00
extFilament : newInput ( LANG . dv _fila _s , { title : LANG . dv _fila _l , convert : toFloat , modes : FDM } ) ,
extNozzle : newInput ( LANG . dv _nozl _s , { title : LANG . dv _nozl _l , convert : toFloat , modes : FDM } ) ,
extOffsetX : newInput ( LANG . dv _exox _s , { title : LANG . dv _exox _l , convert : toFloat , modes : FDM } ) ,
extOffsetY : newInput ( LANG . dv _exoy _s , { title : LANG . dv _exoy _l , convert : toFloat , modes : FDM } ) ,
2024-06-08 15:18:19 -07:00
_ _ _ _ _ : newDiv ( { class : "f-col t-body t-inset" , addto : $ ( 'dev-config' ) , set : true , modes : FDM _CAM } ) ,
2024-06-01 16:49:26 -04:00
_ _ _ _ _ : newGroup ( LANG . dv _gr _too , null , { group : "dext" , inline : true } ) ,
2024-06-08 15:18:19 -07:00
extSelect : newText ( LANG . dv _exts _s , { title : LANG . dv _exts _l , size : 14 , height : 3 , area : gcode } ) ,
extDeselect : newText ( LANG . dv _dext _s , { title : LANG . dv _dext _l , size : 14 , height : 3 , area : gcode } ) ,
2024-05-27 13:53:16 -04:00
extPad : newBlank ( { class : "grow" , modes : FDM } ) ,
extActions : newRow ( [
ui . extPrev = newButton ( undefined , undefined , { icon : '<i class="fas fa-less-than"></i>' } ) ,
2024-05-27 14:06:24 -04:00
ui . extAdd = newButton ( undefined , undefined , { icon : '<i class="fas fa-plus"></i>' } ) ,
ui . extDel = newButton ( undefined , undefined , { icon : '<i class="fas fa-minus"></i>' } ) ,
2024-05-27 13:53:16 -04:00
ui . extNext = newButton ( undefined , undefined , { icon : '<i class="fas fa-greater-than"></i>' } )
2024-05-31 23:35:42 -04:00
] , { class : "dev-buttons ext-buttons" , modes : FDM } ) ,
2024-06-02 14:10:16 -04:00
_ _ _ _ _ : newDiv ( { class : "f-col t-body t-inset" , addto : $ ( 'dev-config' ) , set : true , modes : FDM , show : ( ) => false && ui . filamentSource . selectedOptions [ 0 ] . value === 'palette3' } ) ,
2024-06-01 16:49:26 -04:00
palette : newGroup ( LANG . dv _gr _pal , null , { group : "dext2" , inline : true , modes : FDM } ) ,
2024-05-27 13:53:16 -04:00
paletteId : newInput ( LANG . dv _paid _s , { title : LANG . dv _paid _l , modes : FDM , size : 15 , text : true } ) ,
palettePing : newInput ( LANG . dv _paps _s , { title : LANG . dv _paps _l , modes : FDM , convert : toInt } ) ,
paletteFeed : newInput ( LANG . dv _pafe _s , { title : LANG . dv _pafe _l , modes : FDM , convert : toInt } ) ,
palettePush : newInput ( LANG . dv _papl _s , { title : LANG . dv _papl _l , modes : FDM , convert : toInt } ) ,
paletteOffset : newInput ( LANG . dv _paof _s , { title : LANG . dv _paof _l , modes : FDM , convert : toInt } ) ,
paletteSep : newBlank ( { class : "pop-sep" , modes : FDM } ) ,
paletteHeat : newInput ( LANG . dv _pahe _s , { title : LANG . dv _pahe _l , modes : FDM , convert : toInt } ) ,
paletteCool : newInput ( LANG . dv _paco _s , { title : LANG . dv _paco _l , modes : FDM , convert : toInt } ) ,
palettePress : newInput ( LANG . dv _pacm _s , { title : LANG . dv _pacm _l , modes : FDM , convert : toInt } ) ,
2024-06-02 14:10:16 -04:00
_ _ _ _ _ : newDiv ( { class : "f-col t-body t-inset" , addto : $ ( 'dev-config' ) , set : true , modes : CAM _LZR } ) ,
2024-06-01 16:49:26 -04:00
_ _ _ _ _ : newGroup ( LANG . dv _gr _out , null , { group : "dgco" , inline : true } ) ,
2024-05-27 13:53:16 -04:00
gcodeStrip : newBoolean ( LANG . dv _strc _s , onBooleanClick , { title : LANG . dv _strc _l , modes : CAM } ) ,
gcodeSpace : newBoolean ( LANG . dv _tksp _s , onBooleanClick , { title : LANG . dv _tksp _l , modes : CAM _LZR } ) ,
useLaser : newBoolean ( LANG . dv _lazr _s , onBooleanClick , { title : LANG . dv _lazr _l , modes : CAM } ) ,
gcodeFExt : newInput ( LANG . dv _fext _s , { title : LANG . dv _fext _l , modes : CAM _LZR , size : 7 , text : true } ) ,
gcodeEd : newGroup ( LANG . dv _gr _gco , $ ( 'dg' ) , { group : "dgcp" , inline : true , modes : GCODE } ) ,
gcodeMacros : newRow ( [
2024-05-27 14:06:24 -04:00
( ui . gcodePre = newGCode ( LANG . dv _head _s , { title : LANG . dv _head _l , modes : GCODE , area : gcode } ) ) . button ,
( ui . gcodePost = newGCode ( LANG . dv _foot _s , { title : LANG . dv _foot _l , modes : GCODE , area : gcode } ) ) . button ,
( ui . gcodeLayer = newGCode ( LANG . dv _layr _s , { title : LANG . dv _layr _l , modes : FDM , area : gcode } ) ) . button ,
( ui . gcodeTrack = newGCode ( LANG . dv _prog _s , { title : LANG . dv _prog _l , modes : FDM , area : gcode } ) ) . button ,
( ui . gcodeFan = newGCode ( LANG . dv _fanp _s , { title : LANG . dv _fanp _l , modes : FDM , area : gcode } ) ) . button ,
( ui . gcodeFeature = newGCode ( LANG . dv _feat _s , { title : LANG . dv _feat _l , modes : FDM , area : gcode } ) ) . button ,
( ui . gcodeLaserOn = newGCode ( LANG . dv _lzon _s , { title : LANG . dv _lzon _l , modes : LASER , area : gcode } ) ) . button ,
2024-05-27 13:53:16 -04:00
( ui . gcodeLaserOff = newGCode ( LANG . dv _lzof _s , { title : LANG . dv _lzof _l , modes : LASER , area : gcode } ) ) . button ,
2024-06-13 23:42:28 -04:00
( ui . gcodeWaterOn = newGCode ( LANG . dv _waon _s , { title : LANG . dv _waon _l , modes : WJET , area : gcode } ) ) . button ,
( ui . gcodeWaterOff = newGCode ( LANG . dv _waof _s , { title : LANG . dv _waof _l , modes : WJET , area : gcode } ) ) . button ,
( ui . gcodeKnifeDn = newGCode ( LANG . dv _dkon _s , { title : LANG . dv _dkon _l , modes : DRAG , area : gcode } ) ) . button ,
( ui . gcodeKnifeUp = newGCode ( LANG . dv _dkof _s , { title : LANG . dv _dkof _l , modes : DRAG , area : gcode } ) ) . button ,
2024-05-27 14:06:24 -04:00
( ui . gcodeChange = newGCode ( LANG . dv _tool _s , { title : LANG . dv _tool _l , modes : CAM , area : gcode } ) ) . button ,
( ui . gcodeDwell = newGCode ( LANG . dv _dwll _s , { title : LANG . dv _dwll _l , modes : CAM , area : gcode } ) ) . button ,
( ui . gcodeSpindle = newGCode ( LANG . dv _sspd _s , { title : LANG . dv _sspd _l , modes : CAM , area : gcode , show : ( ) => ui . spindleMax . value > 0 } ) ) . button
2021-05-02 19:29:46 -04:00
] , { class : "ext-buttons f-row gcode-macros" } ) ,
2020-06-06 23:21:42 -04:00
2024-05-26 22:51:44 -04:00
/** Preferences Menu */
2024-05-31 23:35:42 -04:00
_ _ _ _ _ : newGroup ( LANG . op _menu , $ ( 'prefs-gen1' ) , { inline : true } ) ,
2024-05-27 13:53:16 -04:00
antiAlias : newBoolean ( LANG . op _anta _s , booleanSave , { title : LANG . op _anta _l } ) ,
reverseZoom : newBoolean ( LANG . op _invr _s , booleanSave , { title : LANG . op _invr _l } ) ,
ortho : newBoolean ( LANG . op _orth _s , booleanSave , { title : LANG . op _orth _l } ) ,
dark : newBoolean ( LANG . op _dark _s , booleanSave , { title : LANG . op _dark _l } ) ,
2024-06-02 18:55:20 -04:00
drawer : newBoolean ( 'slide out' , booleanSave , { title : 'slide out settings drawer' } ) ,
2024-06-02 19:05:10 -04:00
scrolls : newBoolean ( 'scrollbars' , booleanSave , { title : 'show scrollbars' } ) ,
2024-05-27 13:53:16 -04:00
devel : newBoolean ( LANG . op _devl _s , booleanSave , { title : LANG . op _devl _l } ) ,
2024-05-31 23:35:42 -04:00
_ _ _ _ _ : newGroup ( LANG . op _disp , $ ( 'prefs-gen2' ) , { inline : true } ) ,
2024-05-27 13:53:16 -04:00
showOrigin : newBoolean ( LANG . op _shor _s , booleanSave , { title : LANG . op _shor _l } ) ,
showRulers : newBoolean ( LANG . op _shru _s , booleanSave , { title : LANG . op _shru _l } ) ,
showSpeeds : newBoolean ( LANG . op _sped _s , speedSave , { title : LANG . op _sped _l } ) ,
decals : newBoolean ( LANG . op _decl _s , booleanSave , { title : LANG . op _decl _s } ) ,
shiny : newBoolean ( LANG . op _shny _s , booleanSave , { title : LANG . op _shny _l , modes : FDM } ) ,
lineType : newSelect ( LANG . op _line _s , { title : LANG . op _line _l , action : lineTypeSave , modes : FDM } , "linetype" ) ,
animesh : newSelect ( LANG . op _anim _s , { title : LANG . op _anim _l , action : aniMeshSave , modes : CAM } , "animesh" ) ,
2024-06-01 16:49:26 -04:00
units : newSelect ( LANG . op _unit _s , { title : LANG . op _unit _l , action : unitsSave , modes : CAM } , "units" ) ,
2024-05-31 23:35:42 -04:00
_ _ _ _ _ : newGroup ( LANG . lo _menu , $ ( 'prefs-lay' ) , { inline : true } ) ,
2024-05-27 13:53:16 -04:00
autoSave : newBoolean ( LANG . op _save _s , booleanSave , { title : LANG . op _save _l } ) ,
autoLayout : newBoolean ( LANG . op _auto _s , booleanSave , { title : LANG . op _auto _l } ) ,
freeLayout : newBoolean ( LANG . op _free _s , booleanSave , { title : LANG . op _free _l } ) ,
spaceRandoX : newBoolean ( LANG . op _spcx _s , booleanSave , { title : LANG . op _spcx _l , show : isBelt } ) ,
spaceLayout : newInput ( LANG . op _spcr _s , { title : LANG . op _spcr _l , convert : toFloat , size : 3 , units : true } ) ,
2024-05-31 23:35:42 -04:00
_ _ _ _ _ : newGroup ( LANG . xp _menu , $ ( 'prefs-xpo' ) , { inline : true } ) ,
2024-05-27 13:53:16 -04:00
exportLocal : newBoolean ( ` Grid:Local ` , booleanSave , { title : LANG . op _exgl _l } ) ,
exportGhost : newBoolean ( ` Grid:Host ` , booleanSave , { title : LANG . op _exgh _l } ) ,
exportOcto : newBoolean ( ` OctoPrint ` , booleanSave , { title : LANG . op _exop _l } ) ,
exportThumb : newBoolean ( ` Thumbnail ` , booleanSave , { modes : FDM } ) ,
exportPreview : newBoolean ( ` Code Preview ` , booleanSave ) ,
2024-05-31 23:35:42 -04:00
_ _ _ _ _ : newGroup ( LANG . pt _menu , $ ( 'prefs-prt' ) , { inline : true } ) ,
2024-05-27 13:53:16 -04:00
detail : newSelect ( LANG . pt _qual _s , { title : LANG . pt _qual _l , action : detailSave } , "detail" ) ,
healMesh : newBoolean ( LANG . pt _heal _s , booleanSave , { title : LANG . pt _heal _l } ) ,
2024-06-09 11:00:53 -07:00
threaded : newBoolean ( LANG . pt _thrd _s , booleanSave , { title : LANG . pt _thrd _l , modes : THREED } ) ,
assembly : newBoolean ( LANG . pt _assy _s , booleanSave , { title : LANG . pt _assy _l , modes : THREED } ) ,
2022-02-17 17:55:26 -05:00
prefadd : uc . checkpoint ( $ ( 'prefs-add' ) ) ,
2024-05-26 22:51:44 -04:00
/** FDM Settings */
2024-05-29 08:52:16 -04:00
_ _ _ _ _ : newGroup ( LANG . sl _menu , $ ( 'fdm-layers' ) , { modes : FDM , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
sliceHeight : newInput ( LANG . sl _lahi _s , { title : LANG . sl _lahi _l , convert : toFloat } ) ,
2024-05-29 20:08:37 -04:00
sliceMinHeight : newInput ( LANG . ad _minl _s , { title : LANG . ad _minl _l , convert : toFloat , bound : bound ( 0 , 3.0 ) , show : ( ) => ui . sliceAdaptive . checked } ) ,
2024-05-27 13:53:16 -04:00
sliceTopLayers : newInput ( LANG . sl _ltop _s , { title : LANG . sl _ltop _l , convert : toInt } ) ,
sliceBottomLayers : newInput ( LANG . sl _lbot _s , { title : LANG . sl _lbot _l , convert : toInt } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-29 17:55:34 -04:00
sliceAdaptive : newBoolean ( LANG . ad _adap _s , onBooleanClick , { title : LANG . ad _adap _l } ) ,
2024-05-29 08:52:16 -04:00
_ _ _ _ _ : newGroup ( LANG . sw _menu , $ ( 'fdm-walls' ) , { modes : FDM , driven , separator } ) ,
sliceShells : newInput ( LANG . sl _shel _s , { title : LANG . sl _shel _l , convert : toFloat } ) ,
sliceLineWidth : newInput ( LANG . sl _line _s , { title : LANG . sl _line _l , convert : toFloat , bound : bound ( 0 , 5 ) } ) ,
2024-05-29 16:00:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
sliceShellOrder : newSelect ( LANG . sl _ordr _s , { title : LANG . sl _ordr _l } , "shell" ) ,
2024-05-29 08:52:16 -04:00
sliceDetectThin : newSelect ( LANG . ad _thin _s , { title : LANG . ad _thin _l , action : thinWallSave } , "thin" ) ,
outputAlternating : newBoolean ( LANG . ad _altr _s , onBooleanClick , { title : LANG . ad _altr _l } ) ,
_ _ _ _ _ : newGroup ( LANG . fi _menu , $ ( 'fdm-fill' ) , { modes : FDM , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
sliceFillType : newSelect ( LANG . fi _type , { trigger : true } , "infill" ) ,
sliceFillSparse : newInput ( LANG . fi _pcnt _s , { title : LANG . fi _pcnt _l , convert : toFloat , bound : bound ( 0.0 , 1.0 ) } ) ,
2024-05-29 16:00:16 -04:00
sliceFillRepeat : newInput ( LANG . fi _rept _s , { title : LANG . fi _rept _l , convert : toInt , bound : bound ( 1 , 10 ) , show : fillShow } ) ,
2024-05-27 13:53:16 -04:00
sliceFillOverlap : newInput ( LANG . fi _over _s , { title : LANG . fi _over _l , convert : toFloat , bound : bound ( 0.0 , 2.0 ) } ) ,
2024-05-29 16:00:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-27 14:06:24 -04:00
sliceFillRate : newInput ( LANG . ou _feed _s , { title : LANG . ou _feed _l , convert : toInt , bound : bound ( 0 , 500 ) } ) ,
sliceSolidRate : newInput ( LANG . ou _fini _s , { title : LANG . ou _fini _l , convert : toInt , bound : bound ( 0 , 500 ) } ) ,
2024-05-29 16:00:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-27 13:53:16 -04:00
sliceFillGrow : newInput ( LANG . fi _grow _s , { title : LANG . fi _grow _l , convert : toFloat } ) ,
sliceFillAngle : newInput ( LANG . fi _angl _s , { title : LANG . fi _angl _l , convert : toFloat } ) ,
2024-05-29 08:52:16 -04:00
_ _ _ _ _ : newGroup ( LANG . fh _menu , $ ( 'fdm-heat' ) , { modes : FDM , driven , separator } ) ,
outputTemp : newInput ( LANG . ou _nozl _s , { title : LANG . ou _nozl _l , convert : toInt } ) ,
outputBedTemp : newInput ( LANG . ou _bedd _s , { title : LANG . ou _bedd _l , convert : toInt } ) ,
_ _ _ _ _ : newGroup ( LANG . fc _menu , $ ( 'fdm-cool' ) , { modes : FDM , driven , separator } ) ,
outputFanLayer : newInput ( LANG . ou _fanl _s , { title : LANG . ou _fanl _l , convert : toInt , bound : bound ( 0 , 255 ) } ) ,
outputFanSpeed : newInput ( LANG . ou _fans _s , { title : LANG . ou _fans _l , convert : toInt , bound : bound ( 0 , 255 ) } ) ,
_ _ _ _ _ : newGroup ( LANG . sp _menu , $ ( 'fdm-support' ) , { modes : FDM , marker : false , driven , separator } ) ,
2024-05-29 21:01:56 -04:00
sliceSupportNozzle : newSelect ( LANG . sp _nozl _s , { title : LANG . sp _nozl _l , show : isMultiHead } , "extruders" ) ,
2024-05-27 13:53:16 -04:00
sliceSupportDensity : newInput ( LANG . sp _dens _s , { title : LANG . sp _dens _l , convert : toFloat , bound : bound ( 0.0 , 1.0 ) } ) ,
2024-05-27 14:06:24 -04:00
sliceSupportSize : newInput ( LANG . sp _size _s , { title : LANG . sp _size _l , convert : toFloat , bound : bound ( 1.0 , 200.0 ) } ) ,
sliceSupportOffset : newInput ( LANG . sp _offs _s , { title : LANG . sp _offs _l , convert : toFloat , bound : bound ( 0.0 , 200.0 ) } ) ,
sliceSupportGap : newInput ( LANG . sp _gaps _s , { title : LANG . sp _gaps _l , convert : toInt , bound : bound ( 0 , 5 ) } ) ,
sliceSupportArea : newInput ( LANG . sp _area _s , { title : LANG . sp _area _l , convert : toFloat , bound : bound ( 0.0 , 200.0 ) } ) ,
sliceSupportExtra : newInput ( LANG . sp _xpnd _s , { title : LANG . sp _xpnd _l , convert : toFloat , bound : bound ( 0.0 , 10.0 ) } ) ,
sliceSupportGrow : newInput ( LANG . sp _grow _s , { title : LANG . sp _grow _l , convert : toFloat , bound : bound ( 0.0 , 10.0 ) } ) ,
sliceSupportAngle : newInput ( LANG . sp _angl _s , { title : LANG . sp _angl _l , convert : toFloat , bound : bound ( 0.0 , 90.0 ) } ) ,
2024-05-29 20:08:37 -04:00
sliceSupportSpan : newInput ( LANG . sp _span _s , { title : LANG . sp _span _l , convert : toFloat , bound : bound ( 0.0 , 200.0 ) , show : ( ) => ui . sliceSupportEnable . checked } ) ,
2024-05-27 13:53:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
sliceSupportEnable : newBoolean ( LANG . sp _auto _s , onBooleanClick , { title : LANG . sp _auto _l , show : isNotBelt } ) ,
sliceSupportOutline : newBoolean ( LANG . sp _outl _s , onBooleanClick , { title : LANG . sp _outl _l } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
sliceSupportGen : newRow ( [
ui . ssaGen = newButton ( LANG . sp _detect , onButtonClick , { class : "f-col grow a-center" } )
2021-03-12 13:19:57 -05:00
] , { modes : FDM , class : "ext-buttons f-row grow" } ) ,
2024-05-29 16:00:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-27 13:53:16 -04:00
sliceSupportManual : newRow ( [
( ui . ssmAdd = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-plus"></i>' } ) ) ,
( ui . ssmDun = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-check"></i>' } ) ) ,
( ui . ssmClr = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-trash-alt"></i>' } ) )
2024-05-26 22:51:44 -04:00
] , { class : "ext-buttons f-row" } ) ,
2024-05-29 16:00:16 -04:00
_ _ _ _ _ : newGroup ( LANG . fl _menu , $ ( 'fdm-base' ) , { modes : FDM , driven , separator } ) ,
firstSliceHeight : newInput ( LANG . fl _lahi _s , { title : LANG . fl _lahi _l , convert : toFloat , show : isNotBelt } ) ,
firstLayerNozzleTemp : newInput ( LANG . fl _nozl _s , { title : LANG . fl _nozl _l , convert : toInt , show : isNotBelt } ) ,
firstLayerBedTemp : newInput ( LANG . fl _bedd _s , { title : LANG . fl _bedd _l , convert : toInt , show : isNotBelt } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
firstLayerFanSpeed : newInput ( LANG . ou _fans _s , { title : LANG . ou _fans _l , convert : toInt , bound : bound ( 0 , 255 ) , show : isBelt } ) ,
firstLayerYOffset : newInput ( LANG . fl _zoff _s , { title : LANG . fl _zoff _l , convert : toFloat , show : isBelt } ) ,
firstLayerFlatten : newInput ( LANG . fl _flat _s , { title : LANG . fl _flat _l , convert : toFloat , show : isBelt } ) ,
firstLayerRate : newInput ( LANG . fl _rate _s , { title : LANG . fl _rate _l , convert : toFloat } ) ,
firstLayerFillRate : newInput ( LANG . fl _frat _s , { title : LANG . fl _frat _l , convert : toFloat , show : isNotBelt } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
firstLayerLineMult : newInput ( LANG . fl _sfac _s , { title : LANG . fl _sfac _l , convert : toFloat , bound : bound ( 0.5 , 2 ) , show : isNotBelt } ) ,
firstLayerPrintMult : newInput ( LANG . fl _mult _s , { title : LANG . fl _mult _l , convert : toFloat } ) ,
firstLayerBrim : newInput ( LANG . fl _brim _s , { title : LANG . fl _brim _l , convert : toInt , show : isBelt } ) ,
firstLayerBrimIn : newInput ( LANG . fl _brin _s , { title : LANG . fl _brin _l , convert : toInt , show : isBelt } ) ,
firstLayerBrimTrig : newInput ( LANG . fl _brmn _s , { title : LANG . fl _brmn _l , convert : toInt , show : isBelt } ) ,
firstLayerBrimGap : newInput ( LANG . fl _brgp _s , { title : LANG . fl _brgp _l , convert : toFloat , show : isBelt } ) ,
firstLayerBeltLead : newInput ( LANG . fl _bled _s , { title : LANG . fl _bled _l , convert : toFloat , show : isBelt } ) ,
firstLayerBeltBump : newInput ( LANG . fl _blmp _s , { title : LANG . fl _blmp _l , convert : toFloat , bound : bound ( 0 , 10 ) , show : isBelt } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
outputBrimCount : newInput ( LANG . fl _skrt _s , { title : LANG . fl _skrt _l , convert : toInt , show : isNotBelt } ) ,
outputBrimOffset : newInput ( LANG . fl _skro _s , { title : LANG . fl _skro _l , convert : toFloat , show : isNotBelt } ) ,
outputRaftSpacing : newInput ( LANG . fr _spac _s , { title : LANG . fr _spac _l , convert : toFloat , bound : bound ( 0.0 , 3.0 ) , show : ( ) => ui . outputRaft . checked && isNotBelt ( ) } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
outputRaft : newBoolean ( LANG . fr _nabl _s , onBooleanClick , { title : LANG . fr _nabl _l , trigger : true , show : ( ) => isNotBelt ( ) } ) ,
outputDraftShield : newBoolean ( LANG . fr _draf _s , onBooleanClick , { title : LANG . fr _draf _l , trigger : true , show : ( ) => isNotBelt ( ) } ) ,
2024-05-29 08:52:16 -04:00
_ _ _ _ _ : newGroup ( LANG . ou _menu , $ ( 'fdm-output' ) , { modes : FDM , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
outputFeedrate : newInput ( LANG . ou _feed _s , { title : LANG . ou _feed _l , convert : toInt } ) ,
outputFinishrate : newInput ( LANG . ou _fini _s , { title : LANG . ou _fini _l , convert : toInt } ) ,
outputSeekrate : newInput ( LANG . ou _move _s , { title : LANG . ou _move _l , convert : toInt } ) ,
2024-05-29 16:00:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-27 13:53:16 -04:00
outputShellMult : newInput ( LANG . ou _shml _s , { title : LANG . ou _exml _l , convert : toFloat , bound : bound ( 0.0 , 2.0 ) } ) ,
outputFillMult : newInput ( LANG . ou _flml _s , { title : LANG . ou _exml _l , convert : toFloat , bound : bound ( 0.0 , 2.0 ) } ) ,
outputSparseMult : newInput ( LANG . ou _spml _s , { title : LANG . ou _exml _l , convert : toFloat , bound : bound ( 0.0 , 2.0 ) } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-29 16:00:16 -04:00
outputRetractDist : newInput ( LANG . ad _rdst _s , { title : LANG . ad _rdst _l , convert : toFloat } ) ,
outputRetractSpeed : newInput ( LANG . ad _rrat _s , { title : LANG . ad _rrat _l , convert : toInt } ) ,
outputRetractWipe : newInput ( LANG . ad _wpln _s , { title : LANG . ad _wpln _l , convert : toFloat , bound : bound ( 0.0 , 10 ) } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
sliceLayerStart : newSelect ( LANG . sl _strt _s , { title : LANG . sl _strt _l } , "start" ) ,
2024-05-27 13:53:16 -04:00
outputLayerRetract : newBoolean ( LANG . ad _lret _s , onBooleanClick , { title : LANG . ad _lret _l } ) ,
outputAvoidGaps : newBoolean ( LANG . ad _agap _s , onBooleanClick , { title : LANG . ad _agap _l } ) ,
2024-05-29 21:01:56 -04:00
separator : newBlank ( { class : "set-sep" , driven , show : isMultiHead } ) ,
2024-05-27 13:53:16 -04:00
outputBeltFirst : newBoolean ( LANG . ad _lbir _s , onBooleanClick , { title : LANG . ad _lbir _l , show : isBelt } ) ,
2024-05-29 21:01:56 -04:00
outputNozzle : newSelect ( LANG . sp _nozl _s , { title : LANG . sp _nozl _l , show : isMultiHead } , "extruders" ) ,
2024-05-29 08:52:16 -04:00
_ _ _ _ _ : newGroup ( LANG . ad _menu , $ ( 'fdm-expert' ) , { modes : FDM , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
outputRetractDwell : newInput ( LANG . ad _rdwl _s , { title : LANG . ad _rdwl _l , convert : toInt } ) ,
sliceSolidMinArea : newInput ( LANG . ad _msol _s , { title : LANG . ad _msol _l , convert : toFloat } ) ,
2024-05-27 14:06:24 -04:00
outputMinSpeed : newInput ( LANG . ad _mins _s , { title : LANG . ad _mins _l , convert : toFloat , bound : bound ( 1 , 200 ) } ) ,
outputShortPoly : newInput ( LANG . ad _spol _s , { title : LANG . ad _spol _l , convert : toFloat , bound : bound ( 0 , 10000 ) } ) ,
outputCoastDist : newInput ( LANG . ad _scst _s , { title : LANG . ad _scst _l , convert : toFloat , bound : bound ( 0.0 , 10 ) } ) ,
zHopDistance : newInput ( LANG . ad _zhop _s , { title : LANG . ad _zhop _l , convert : toFloat , bound : bound ( 0 , 3.0 ) } ) ,
arcTolerance : newInput ( LANG . ad _arct _s , { title : LANG . ad _arct _l , convert : toFloat , bound : bound ( 0 , 1.0 ) , show : ( ) => { return isNotBelt ( ) } } ) ,
antiBacklash : newInput ( LANG . ad _abkl _s , { title : LANG . ad _abkl _l , convert : toInt , bound : bound ( 0 , 3 ) } ) ,
outputLoops : newInput ( LANG . ag _loop _s , { title : LANG . ag _loop _l , convert : toInt , bound : bound ( - 1 , 1000 ) , show : isBelt } ) ,
outputPurgeTower : newInput ( LANG . ad _purg _s , { title : LANG . ad _purg _l , convert : toInt , bound : bound ( 0 , 1000 ) } ) ,
2024-05-26 22:51:44 -04:00
fdmRanges : $ ( 'fdm-ranges' ) ,
/** CAM Settings */
2024-05-28 18:02:52 -04:00
camTabs : newGroup ( LANG . ct _menu , $ ( 'cam-tabs' ) , { modes : CAM , marker : true , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
camTabsWidth : newInput ( LANG . ct _wdth _s , { title : LANG . ct _wdth _l , convert : toFloat , bound : bound ( 0.005 , 100 ) , units : true } ) ,
camTabsHeight : newInput ( LANG . ct _hght _s , { title : LANG . ct _hght _l , convert : toFloat , bound : bound ( 0.005 , 100 ) , units : true } ) ,
camTabsDepth : newInput ( LANG . ct _dpth _s , { title : LANG . ct _dpth _l , convert : toFloat , bound : bound ( 0.005 , 100 ) , units : true } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
camTabsMidline : newBoolean ( LANG . ct _midl _s , onBooleanClick , { title : LANG . ct _midl _l } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
camTabsManual : newRow ( [
( ui . tabAdd = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-plus"></i>' } ) ) ,
( ui . tabDun = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-check"></i>' } ) ) ,
( ui . tabClr = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-trash-alt"></i>' } ) )
2024-05-26 22:51:44 -04:00
] , { class : "ext-buttons f-row" } ) ,
2024-05-28 18:02:52 -04:00
camStock : newGroup ( LANG . cs _menu , $ ( 'cam-stock' ) , { modes : CAM , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
camStockX : newInput ( LANG . cs _wdth _s , { title : LANG . cs _wdth _l , convert : toFloat , bound : bound ( 0 , 9999 ) , units : true } ) ,
camStockY : newInput ( LANG . cs _dpth _s , { title : LANG . cs _dpth _l , convert : toFloat , bound : bound ( 0 , 9999 ) , units : true } ) ,
camStockZ : newInput ( LANG . cs _hght _s , { title : LANG . cs _hght _l , convert : toFloat , bound : bound ( 0 , 9999 ) , units : true } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
camStockOffset : newBoolean ( LANG . cs _offs _s , onBooleanClick , { title : LANG . cs _offs _l } ) ,
camStockClipTo : newBoolean ( LANG . cs _clip _s , onBooleanClick , { title : LANG . cs _clip _l } ) ,
camStockIndexed : newBoolean ( LANG . cs _indx _s , onBooleanClick , { title : LANG . cs _indx _l } ) ,
camStockIndexGrid : newBoolean ( LANG . cs _ishg _s , onBooleanClick , { title : LANG . cs _ishg _l , show : ( ) => ui . camStockIndexed . checked } ) ,
2024-05-28 18:02:52 -04:00
camLimits : newGroup ( LANG . cc _menu , $ ( 'cam-limits' ) , { modes : CAM , driven , separator } ) ,
2024-06-01 16:49:26 -04:00
camZAnchor : newSelect ( LANG . ou _zanc _s , { title : LANG . ou _zanc _l , action : zAnchorSave , show : ( ) => ! ui . camStockIndexed . checked } , "zanchor" ) ,
2024-05-27 13:53:16 -04:00
camZOffset : newInput ( LANG . ou _ztof _s , { title : LANG . ou _ztof _l , convert : toFloat , units : true } ) ,
camZBottom : newInput ( LANG . ou _zbot _s , { title : LANG . ou _zbot _l , convert : toFloat , units : true , trigger : true } ) ,
camZThru : newInput ( LANG . ou _ztru _s , { title : LANG . ou _ztru _l , convert : toFloat , bound : bound ( 0.0 , 100 ) , units : true , show : ( ) => { return ui . camZBottom . value == 0 } } ) ,
camZClearance : newInput ( LANG . ou _zclr _s , { title : LANG . ou _zclr _l , convert : toFloat , bound : bound ( 0.01 , 100 ) , units : true } ) ,
camFastFeedZ : newInput ( LANG . cc _rzpd _s , { title : LANG . cc _rzpd _l , convert : toFloat , units : true } ) ,
camFastFeed : newInput ( LANG . cc _rapd _s , { title : LANG . cc _rapd _l , convert : toFloat , units : true } ) ,
2024-05-28 18:02:52 -04:00
camOutput : newGroup ( LANG . ou _menu , $ ( 'cam-output' ) , { modes : CAM , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
camConventional : newBoolean ( LANG . ou _conv _s , onBooleanClick , { title : LANG . ou _conv _l } ) ,
camEaseDown : newBoolean ( LANG . cr _ease _s , onBooleanClick , { title : LANG . cr _ease _l } ) ,
camDepthFirst : newBoolean ( LANG . ou _depf _s , onBooleanClick , { title : LANG . ou _depf _l } ) ,
camToolInit : newBoolean ( LANG . ou _toin _s , onBooleanClick , { title : LANG . ou _toin _l } ) ,
camFirstZMax : newBoolean ( LANG . ou _z1st _s , onBooleanClick , { title : LANG . ou _z1st _l } ) ,
camForceZMax : newBoolean ( LANG . ou _forz _s , onBooleanClick , { title : LANG . ou _forz _l } ) ,
2024-05-28 18:02:52 -04:00
camOrigin : newGroup ( LANG . co _menu , $ ( 'cam-origin' ) , { modes : CAM , driven , separator } ) ,
2024-06-05 12:10:33 -07:00
camOriginTop : newBoolean ( LANG . or _topp _s , onBooleanClick , { title : LANG . or _topp _l } ) ,
camOriginCenter : newBoolean ( LANG . or _cntr _s , onBooleanClick , { title : LANG . or _cntr _l } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-05-27 13:53:16 -04:00
camOriginOffX : newInput ( LANG . co _offx _s , { title : LANG . co _offx _l , convert : toFloat , units : true } ) ,
camOriginOffY : newInput ( LANG . co _offy _s , { title : LANG . co _offy _l , convert : toFloat , units : true } ) ,
camOriginOffZ : newInput ( LANG . co _offz _s , { title : LANG . co _offz _l , convert : toFloat , units : true } ) ,
2024-05-28 18:02:52 -04:00
camExpert : newGroup ( LANG . op _xprt _s , $ ( 'cam-expert' ) , { group : "cam_expert" , modes : CAM , marker : false , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
camExpertFast : newBoolean ( LANG . cx _fast _s , onBooleanClick , { title : LANG . cx _fast _l , show : ( ) => ! ui . camTrueShadow . checked } ) ,
camTrueShadow : newBoolean ( LANG . cx _true _s , onBooleanClick , { title : LANG . cx _true _l , show : ( ) => ! ui . camExpertFast . checked } ) ,
2024-05-26 22:51:44 -04:00
2024-06-09 15:33:30 -07:00
/** LASER/DRAG/WJET/WEDM cut tool Settings */
2024-05-26 22:51:44 -04:00
2024-06-09 15:33:30 -07:00
_ _ _ _ _ : newGroup ( LANG . sl _menu , $ ( 'lzr-slice' ) , { modes : TWOD , driven , separator } ) ,
ctSliceKerf : newInput ( LANG . ls _offs _s , { title : LANG . ls _offs _l , convert : toFloat } ) ,
2024-06-11 13:16:02 -07:00
ctSliceHeight : newInput ( LANG . ls _lahi _s , { title : LANG . ls _lahi _l , convert : toFloat , trigger : true } ) ,
ctSliceHeightMin : newInput ( LANG . ls _lahm _s , { title : LANG . ls _lahm _l , convert : toFloat , show : ( ) => ui . ctSliceHeight . value == 0 && ! ui . ctSliceSingle . checked } ) ,
separator : newBlank ( { class : "set-sep" , driven } ) ,
ctSliceSingle : newBoolean ( LANG . ls _sngl _s , onBooleanClick , { title : LANG . ls _sngl _l } ) ,
ctOmitInner : newBoolean ( LANG . we _omit _s , onBooleanClick , { title : LANG . we _omit _l , modes : WEDM } ) ,
_ _ _ _ _ : newGroup ( 'surfaces' , $ ( 'lzr-surface' ) , { modes : [ - 1 ] , driven , separator } ) ,
2024-06-10 21:54:25 -07:00
ctSurfaces : newRow ( [
( ui . faceAdd = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-plus"></i>' } ) ) ,
( ui . faceDun = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-check"></i>' } ) ) ,
( ui . faceClr = newButton ( undefined , onButtonClick , { icon : '<i class="fas fa-trash-alt"></i>' } ) )
] , { class : "ext-buttons f-row" , modes : WEDM } ) ,
_ _ _ _ _ : newGroup ( LANG . dk _menu , $ ( 'lzr-knife' ) , { modes : DRAG , marker : true , driven , separator } ) ,
2024-06-09 15:33:30 -07:00
ctOutKnifeDepth : newInput ( LANG . dk _dpth _s , { title : LANG . dk _dpth _l , convert : toFloat , bound : bound ( 0.0 , 5.0 ) } ) ,
ctOutKnifePasses : newInput ( LANG . dk _pass _s , { title : LANG . dk _pass _l , convert : toInt , bound : bound ( 0 , 5 ) } ) ,
ctOutKnifeTip : newInput ( LANG . dk _offs _s , { title : LANG . dk _offs _l , convert : toFloat , bound : bound ( 0.0 , 10.0 ) } ) ,
2024-06-11 13:16:02 -07:00
_ _ _ _ _ : newGroup ( LANG . lo _menu , $ ( 'lzr-layout' ) , { modes : TWOD , driven , separator } ) ,
2024-06-09 15:33:30 -07:00
ctOutTileSpacing : newInput ( LANG . ou _spac _s , { title : LANG . ou _spac _l , convert : toInt } ) ,
2024-06-11 13:16:02 -07:00
ctOutMerged : newBoolean ( LANG . ou _mrgd _s , onBooleanClick , { title : LANG . ou _mrgd _l , modes : TWONED } ) ,
2024-06-09 15:33:30 -07:00
ctOutGroup : newBoolean ( LANG . ou _grpd _s , onBooleanClick , { title : LANG . ou _grpd _l , show : ( ) => ! ui . ctOutStack . checked } ) ,
2024-06-10 21:54:25 -07:00
_ _ _ _ _ : newGroup ( LANG . ou _menu , $ ( 'lzr-output' ) , { modes : TWOD , driven , separator } ) ,
2024-06-11 13:16:02 -07:00
ctOutPower : newInput ( LANG . ou _powr _s , { title : LANG . ou _powr _l , convert : toInt , bound : bound ( 1 , 100 ) , modes : TWONED } ) ,
2024-06-09 15:33:30 -07:00
ctOutSpeed : newInput ( LANG . ou _sped _s , { title : LANG . ou _sped _l , convert : toInt } ) ,
2024-06-11 13:16:02 -07:00
ctAdaptive : newBoolean ( 'adaptive speed' , onBooleanClick , { modes : WEDM , title : 'controller determines best cutting speed based on material feedback at runtime' } ) ,
2024-05-27 13:53:16 -04:00
separator : newBlank ( { class : "set-sep" , driven } ) ,
2024-06-13 22:13:03 -04:00
ctOriginBounds : newBoolean ( LANG . or _bnds _s , onBooleanClick , { title : LANG . or _bnds _l , show : ( ) => ! ui . ctOriginCenter . checked } ) ,
ctOriginCenter : newBoolean ( LANG . or _cntr _s , onBooleanClick , { title : LANG . or _cntr _l , show : ( ) => ! ui . ctOriginBounds . checked } ) ,
2024-06-13 22:31:59 -04:00
separator : newBlank ( { class : "set-sep" , driven , modes : WEDM , show : ( ) => ui . ctOriginBounds . checked } ) ,
ctOriginOffX : newInput ( LANG . or _offx _s , { title : LANG . or _offx _l , convert : toFloat , modes : WEDM , show : ( ) => ui . ctOriginBounds . checked } ) ,
ctOriginOffY : newInput ( LANG . or _offy _s , { title : LANG . or _offy _l , convert : toFloat , modes : WEDM , show : ( ) => ui . ctOriginBounds . checked } ) ,
2024-06-10 21:54:25 -07:00
separator : newBlank ( { class : "set-sep" , driven , modes : TWONED } ) ,
ctOutZColor : newBoolean ( LANG . ou _layo _s , onBooleanClick , { title : LANG . ou _layo _l , modes : TWONED , show : ( ) => { return ui . ctOutMerged . checked === false } } ) ,
ctOutLayer : newBoolean ( LANG . ou _layr _s , onBooleanClick , { title : LANG . ou _layr _l , modes : TWONED } ) ,
ctOutStack : newBoolean ( LANG . ou _lays _s , onBooleanClick , { title : LANG . ou _lays _l , modes : TWONED } ) ,
2024-05-26 22:51:44 -04:00
/** SLA SETTINGS */
2024-05-27 13:53:16 -04:00
2024-05-28 18:02:52 -04:00
slaProc : newGroup ( LANG . sa _menu , $ ( 'sla-slice' ) , { modes : SLA , group : "sla-slice" , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
slaSlice : newInput ( LANG . sa _lahe _s , { title : LANG . sa _lahe _l , convert : toFloat } ) ,
slaShell : newInput ( LANG . sa _shel _s , { title : LANG . sa _shel _l , convert : toFloat } ) ,
slaOpenTop : newBoolean ( LANG . sa _otop _s , onBooleanClick , { title : LANG . sa _otop _l } ) ,
slaOpenBase : newBoolean ( LANG . sa _obas _s , onBooleanClick , { title : LANG . sa _obas _l } ) ,
2024-05-28 18:02:52 -04:00
slaLayers : newGroup ( LANG . sa _layr _m , $ ( 'sla-layers' ) , { modes : SLA , group : "sla-layers" , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
slaLayerOn : newInput ( LANG . sa _lton _s , { title : LANG . sa _lton _l , convert : toFloat } ) ,
slaLayerOff : newInput ( LANG . sa _ltof _s , { title : LANG . sa _ltof _l , convert : toFloat } ) ,
slaPeelDist : newInput ( LANG . sa _pldi _s , { title : LANG . sa _pldi _l , convert : toFloat } ) ,
slaPeelLiftRate : newInput ( LANG . sa _pllr _s , { title : LANG . sa _pllr _l , convert : toFloat } ) ,
slaPeelDropRate : newInput ( LANG . sa _pldr _s , { title : LANG . sa _pldr _l , convert : toFloat } ) ,
2024-05-28 18:02:52 -04:00
slaBase : newGroup ( LANG . sa _base _m , $ ( 'sla-base' ) , { modes : SLA , group : "sla-base" , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
slaBaseLayers : newInput ( LANG . sa _balc _s , { title : LANG . sa _balc _l , convert : toInt } ) ,
slaBaseOn : newInput ( LANG . sa _lton _s , { title : LANG . sa _bltn _l , convert : toFloat } ) ,
slaBaseOff : newInput ( LANG . sa _ltof _s , { title : LANG . sa _bltf _l , convert : toFloat } ) ,
slaBasePeelDist : newInput ( LANG . sa _pldi _s , { title : LANG . sa _pldi _l , convert : toFloat } ) ,
slaBasePeelLiftRate : newInput ( LANG . sa _pllr _s , { title : LANG . sa _pllr _l , convert : toFloat } ) ,
2024-05-28 18:02:52 -04:00
slaFill : newGroup ( LANG . sa _infl _m , $ ( 'sla-fill' ) , { modes : SLA , group : "sla-infill" , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
slaFillDensity : newInput ( LANG . sa _ifdn _s , { title : LANG . sa _ifdn _l , convert : toFloat , bound : bound ( 0 , 1 ) } ) ,
slaFillLine : newInput ( LANG . sa _iflw _s , { title : LANG . sa _iflw _l , convert : toFloat , bound : bound ( 0 , 5 ) } ) ,
2024-05-28 18:02:52 -04:00
slaSupport : newGroup ( LANG . sa _supp _m , $ ( 'sla-support' ) , { modes : SLA , group : "sla-support" , driven , separator } ) ,
2024-05-27 14:06:24 -04:00
slaSupportLayers : newInput ( LANG . sa _slyr _s , { title : LANG . sa _slyr _l , convert : toInt , bound : bound ( 5 , 100 ) } ) ,
slaSupportGap : newInput ( LANG . sa _slgp _s , { title : LANG . sa _slgp _l , convert : toInt , bound : bound ( 3 , 30 ) } ) ,
2024-05-27 13:53:16 -04:00
slaSupportDensity : newInput ( LANG . sa _sldn _s , { title : LANG . sa _sldn _l , convert : toFloat , bound : bound ( 0.01 , 0.9 ) } ) ,
slaSupportSize : newInput ( LANG . sa _slsz _s , { title : LANG . sa _slsz _l , convert : toFloat , bound : bound ( 0.1 , 1 ) } ) ,
2024-05-27 14:06:24 -04:00
slaSupportPoints : newInput ( LANG . sa _slpt _s , { title : LANG . sa _slpt _l , convert : toInt , bound : bound ( 3 , 10 ) } ) ,
2024-05-27 13:53:16 -04:00
slaSupportEnable : newBoolean ( LANG . enable , onBooleanClick , { title : LANG . sl _slen _l } ) ,
2024-05-28 18:02:52 -04:00
slaOutput : newGroup ( LANG . sa _outp _m , $ ( 'sla-output' ) , { modes : SLA , group : "sla-first" , driven , separator } ) ,
2024-05-27 13:53:16 -04:00
slaFirstOffset : newInput ( LANG . sa _opzo _s , { title : LANG . sa _opzo _l , convert : toFloat , bound : bound ( 0 , 1 ) } ) ,
slaAntiAlias : newSelect ( LANG . sa _opaa _s , { title : LANG . sa _opaa _l } , "antialias" ) ,
2020-06-06 00:38:46 -04:00
2024-05-27 14:10:16 -04:00
layers : uc . setGroup ( $ ( "layers" ) ) ,
settingsName : $ ( 'settingsName' ) ,
settingsSave : $ ( 'settingsSave' ) ,
2020-03-09 11:02:09 -04:00
} ) ;
2021-03-31 10:41:28 -04:00
// override old style settings two-button menu
2024-05-27 14:10:16 -04:00
ui . settingsSave . onclick = ( ) => {
settingsSave ( undefined , ui . settingsName . value ) ;
2021-03-31 10:41:28 -04:00
} ;
2021-05-05 11:03:00 -04:00
function optSelected ( sel ) {
2021-05-05 13:58:13 -04:00
let opt = sel . options [ sel . selectedIndex ] ;
return opt ? opt . value : undefined ;
2021-05-05 11:03:00 -04:00
}
function fillShow ( ) {
2022-02-17 17:55:26 -05:00
return optSelected ( ui . sliceFillType ) === 'linear' ;
2021-05-05 11:03:00 -04:00
}
2020-06-29 08:11:49 -04:00
function spindleShow ( ) {
return settings ( ) . device . spindleMax > 0 ;
}
2020-06-07 23:02:05 -04:00
// slider setup
2022-10-17 10:48:12 -04:00
const mobile = moto . space . info . mob ;
const slbar = mobile ? 80 : 30 ;
2020-06-15 12:07:16 -04:00
const slbar2 = slbar * 2 ;
2022-02-17 17:55:26 -05:00
const slider = ui . sliderRange ;
2020-06-07 23:02:05 -04:00
const drag = { } ;
2020-06-08 21:46:53 -04:00
2022-10-17 10:48:12 -04:00
if ( mobile ) {
ui . slider . classList . add ( 'slider-mobile' ) ;
ui . sliderLo . classList . add ( 'slider-mobile' ) ;
ui . sliderHi . classList . add ( 'slider-mobile' ) ;
2022-10-18 00:44:39 -04:00
// add css style for mobile devices
DOC . body . classList . add ( 'mobile' ) ;
2022-10-17 10:48:12 -04:00
}
2020-06-07 23:02:05 -04:00
function pxToInt ( txt ) {
return txt ? parseInt ( txt . substring ( 0 , txt . length - 2 ) ) : 0 ;
}
2020-06-08 21:46:53 -04:00
2020-06-07 23:02:05 -04:00
function sliderUpdate ( ) {
2020-06-21 22:37:11 -04:00
let start = drag . low / drag . maxval ;
let end = ( drag . low + drag . mid - slbar ) / drag . maxval ;
2022-02-17 17:55:26 -05:00
api . event . emit ( 'slider.pos' , { start , end } ) ;
api . var . layer _lo = Math . round ( start * api . var . layer _max ) ;
api . var . layer _hi = Math . round ( end * api . var . layer _max ) ;
api . show . layer ( ) ;
space . scene . active ( ) ;
2020-06-07 23:02:05 -04:00
}
2020-06-08 21:46:53 -04:00
2020-06-07 23:02:05 -04:00
function dragit ( el , delta ) {
2022-10-16 23:35:09 -04:00
el . ontouchstart = el . onmousedown = ( ev ) => {
2022-10-18 00:44:39 -04:00
// el.classList.add('sli-drag-el');
2020-06-07 23:02:05 -04:00
tracker . style . display = 'block' ;
ev . stopPropagation ( ) ;
2022-10-16 23:35:09 -04:00
let obj = ( ev . touches ? ev . touches [ 0 ] : ev ) ;
2020-06-21 22:37:11 -04:00
drag . width = slider . clientWidth ;
drag . maxval = drag . width - slbar2 ;
2022-10-16 23:35:09 -04:00
drag . start = obj . screenX ;
2022-02-17 17:55:26 -05:00
drag . loat = drag . low = pxToInt ( ui . sliderHold . style . marginLeft ) ;
drag . mdat = drag . mid = ui . sliderMid . clientWidth ;
drag . hiat = pxToInt ( ui . sliderHold . style . marginRight ) ;
2020-06-21 22:37:11 -04:00
drag . mdmax = drag . width - slbar - drag . loat ;
drag . himax = drag . width - slbar - drag . mdat ;
2022-10-17 10:48:12 -04:00
let cancel _drag = tracker . ontouchend = tracker . onmouseup = ( ev ) => {
2022-10-18 00:44:39 -04:00
// el.classList.remove('sli-drag-el');
2020-06-08 14:21:10 -04:00
if ( ev ) {
ev . stopPropagation ( ) ;
ev . preventDefault ( ) ;
}
slider . onmousemove = undefined ;
tracker . style . display = 'none' ;
} ;
2022-10-18 00:44:39 -04:00
el . ontouchend = cancel _drag ;
el . ontouchmove = tracker . ontouchmove = tracker . onmousemove = ( ev ) => {
2020-06-07 23:02:05 -04:00
ev . stopPropagation ( ) ;
2020-06-08 14:21:10 -04:00
ev . preventDefault ( ) ;
if ( ev . buttons === 0 ) {
return cancel _drag ( ) ;
}
2022-10-16 23:35:09 -04:00
if ( delta ) {
let obj = ( ev . touches ? ev . touches [ 0 ] : ev ) ;
delta ( obj . screenX - drag . start ) ;
}
2020-06-07 23:02:05 -04:00
} ;
} ;
}
2022-02-17 17:55:26 -05:00
dragit ( ui . sliderLo , ( delta ) => {
2020-06-07 23:02:05 -04:00
let midval = drag . mdat - delta ;
2020-06-21 22:37:11 -04:00
let lowval = drag . loat + delta ;
if ( midval < slbar || lowval < 0 ) {
2020-06-07 23:02:05 -04:00
return ;
}
2022-02-17 17:55:26 -05:00
ui . sliderHold . style . marginLeft = ` ${ lowval } px ` ;
ui . sliderMid . style . width = ` ${ midval } px ` ;
2020-06-21 22:37:11 -04:00
drag . low = lowval ;
2020-06-07 23:02:05 -04:00
drag . mid = midval ;
sliderUpdate ( ) ;
} ) ;
2022-02-17 17:55:26 -05:00
dragit ( ui . sliderMid , ( delta ) => {
2020-06-21 22:37:11 -04:00
let loval = drag . loat + delta ;
let hival = drag . hiat - delta ;
if ( loval < 0 || hival < 0 ) return ;
2022-02-17 17:55:26 -05:00
ui . sliderHold . style . marginLeft = ` ${ loval } px ` ;
ui . sliderHold . style . marginRight = ` ${ hival } px ` ;
2020-06-21 22:37:11 -04:00
drag . low = loval ;
2020-06-07 23:02:05 -04:00
sliderUpdate ( ) ;
} ) ;
2022-02-17 17:55:26 -05:00
dragit ( ui . sliderHi , ( delta ) => {
2020-06-21 22:37:11 -04:00
let midval = drag . mdat + delta ;
let hival = drag . hiat - delta ;
if ( midval < slbar || midval > drag . mdmax || hival < 0 ) return ;
2022-02-17 17:55:26 -05:00
ui . sliderMid . style . width = ` ${ midval } px ` ;
ui . sliderHold . style . marginRight = ` ${ hival } px ` ;
2020-06-21 22:37:11 -04:00
drag . mid = midval ;
2020-06-07 23:02:05 -04:00
sliderUpdate ( ) ;
} ) ;
2022-10-26 21:47:31 -04:00
ui . load . onchange = function ( event ) {
api . platform . load _files ( event . target . files ) ;
2023-01-14 10:57:32 -05:00
ui . load . value = '' ; // reset so you can re-import the same filee
2022-10-26 21:47:31 -04:00
} ;
2022-02-17 17:55:26 -05:00
ui . sliderMin . onclick = ( ) => {
api . show . layer ( 0 , 0 ) ;
2020-06-08 21:46:53 -04:00
}
2022-02-17 17:55:26 -05:00
ui . sliderMax . onclick = ( ) => {
api . show . layer ( api . var . layer _max , 0 ) ;
2020-03-20 20:56:24 -04:00
}
2022-02-17 17:55:26 -05:00
ui . slider . onmouseover = ( ev ) => {
api . event . emit ( 'slider.label' ) ;
2020-06-08 21:46:53 -04:00
} ;
2022-02-17 17:55:26 -05:00
ui . slider . onmouseleave = ( ev ) => {
if ( ! ev . buttons ) api . event . emit ( 'slider.unlabel' ) ;
2020-06-08 21:46:53 -04:00
} ;
2022-02-17 17:55:26 -05:00
api . event . on ( 'slider.unlabel' , ( values ) => {
2020-06-08 21:46:53 -04:00
} ) ;
2022-02-17 17:55:26 -05:00
api . event . on ( 'slider.label' , ( values ) => {
let digits = api . var . layer _max . toString ( ) . length ;
2020-06-21 22:37:11 -04:00
$ ( 'slider-zero' ) . style . width = ` ${ digits } em ` ;
$ ( 'slider-max' ) . style . width = ` ${ digits } em ` ;
2022-02-17 17:55:26 -05:00
$ ( 'slider-zero' ) . innerText = api . var . layer _lo ;
$ ( 'slider-max' ) . innerText = api . var . layer _hi ;
2020-06-08 21:46:53 -04:00
} ) ;
2022-02-17 17:55:26 -05:00
api . event . on ( 'slider.set' , ( values ) => {
2020-06-21 22:37:11 -04:00
let width = slider . clientWidth ;
let maxval = width - slbar2 ;
2020-06-07 23:02:05 -04:00
let start = Math . max ( 0 , Math . min ( 1 , values . start ) ) ;
let end = Math . max ( start , Math . min ( 1 , values . end ) ) ;
2020-06-21 22:37:11 -04:00
let lowval = start * maxval ;
2020-06-15 12:07:16 -04:00
let midval = ( ( end - start ) * maxval ) + slbar ;
2020-06-21 22:37:11 -04:00
let hival = maxval - end * maxval ;
2022-02-17 17:55:26 -05:00
ui . sliderHold . style . marginLeft = ` ${ lowval } px ` ;
ui . sliderMid . style . width = ` ${ midval } px ` ;
ui . sliderHold . style . marginRight = ` ${ hival } px ` ;
2020-06-07 23:02:05 -04:00
} ) ;
2021-02-07 19:25:30 -05:00
// store layer preferences
2022-02-17 17:55:26 -05:00
api . event . on ( 'stack.show' , label => {
let mode = api . mode . get ( ) ;
let view = api . view . get ( ) ;
api . conf . get ( ) . labels [ ` ${ mode } - ${ view } - ${ label } ` ] = true ;
2021-02-07 19:25:30 -05:00
} ) ;
2022-02-17 17:55:26 -05:00
api . event . on ( 'stack.hide' , label => {
let mode = api . mode . get ( ) ;
let view = api . view . get ( ) ;
api . conf . get ( ) . labels [ ` ${ mode } - ${ view } - ${ label } ` ] = false ;
2021-02-07 19:25:30 -05:00
} ) ;
2020-06-06 20:05:21 -04:00
// bind language choices
$ ( 'lset-en' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'en-us' ) ;
api . space . reload ( ) ;
2020-04-02 17:06:38 -04:00
} ;
2021-01-16 10:08:11 -05:00
$ ( 'lset-da' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'da-dk' ) ;
api . space . reload ( ) ;
2021-01-16 10:08:11 -05:00
} ;
2021-02-27 11:27:46 -05:00
$ ( 'lset-de' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'de-de' ) ;
api . space . reload ( ) ;
2021-02-27 11:27:46 -05:00
} ;
$ ( 'lset-fr' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'fr-fr' ) ;
api . space . reload ( ) ;
2021-02-27 11:27:46 -05:00
} ;
2021-03-06 12:21:25 -05:00
$ ( 'lset-pl' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'pl-pl' ) ;
api . space . reload ( ) ;
2021-03-06 12:21:25 -05:00
} ;
2021-03-27 18:57:37 -04:00
$ ( 'lset-pt' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'pt-pt' ) ;
api . space . reload ( ) ;
2021-03-27 18:57:37 -04:00
} ;
2021-03-25 09:32:54 -04:00
$ ( 'lset-es' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'es-es' ) ;
api . space . reload ( ) ;
2021-03-25 09:32:54 -04:00
} ;
2021-03-29 15:09:59 -04:00
$ ( 'lset-zh' ) . onclick = function ( ) {
2022-02-17 17:55:26 -05:00
sdb . setItem ( 'kiri-lang' , 'zh' ) ;
api . space . reload ( ) ;
2021-03-29 15:09:59 -04:00
} ;
2020-04-02 17:06:38 -04:00
2022-02-17 17:55:26 -05:00
space . event . addHandlers ( self , [
2020-03-09 11:02:09 -04:00
'keyup' , keyUpHandler ,
'keydown' , keyDownHandler ,
'keypress' , keyHandler ,
'dragover' , dragOverHandler ,
'dragleave' , dragLeave ,
'drop' , dropHandler
] ) ;
2020-04-11 09:22:37 -04:00
function selectionSize ( e ) {
let dv = parseFloat ( e . target . value || 1 ) ,
pv = parseFloat ( e . target . was || 1 ) ,
ra = dv / pv ,
2024-06-05 17:36:35 -07:00
xv = parseFloat ( ui . sizeX . was ? ? ui . scaleX . value ) || 1 ,
yv = parseFloat ( ui . sizeY . was ? ? ui . scaleY . value ) || 1 ,
zv = parseFloat ( ui . sizeZ . was ? ? ui . scaleZ . value ) || 1 ,
2021-01-27 11:23:39 -05:00
ta = e . target ,
2022-02-17 17:55:26 -05:00
xc = ui . lockX . checked ,
yc = ui . lockY . checked ,
zc = ui . lockZ . checked ,
xt = ta === ui . sizeX ,
yt = ta === ui . sizeY ,
zt = ta === ui . sizeZ ,
2021-01-27 11:23:39 -05:00
tl = ( xt && xc ) || ( yt && yc ) || ( zt && zc ) ,
xr = ( ( tl && xc ) || ( ! tl && xt ) ? ra : 1 ) ,
yr = ( ( tl && yc ) || ( ! tl && yt ) ? ra : 1 ) ,
zr = ( ( tl && zc ) || ( ! tl && zt ) ? ra : 1 ) ;
2021-10-08 14:55:46 -04:00
// prevent null scale
if ( xr * yr * zr === 0 ) {
return ;
}
2022-02-17 17:55:26 -05:00
api . selection . scale ( xr , yr , zr ) ;
ui . sizeX . was = ui . sizeX . value = xv * xr ;
ui . sizeY . was = ui . sizeY . value = yv * yr ;
ui . sizeZ . was = ui . sizeZ . value = zv * zr ;
2020-04-11 09:22:37 -04:00
}
function selectionScale ( e ) {
let dv = parseFloat ( e . target . value || 1 ) ,
pv = parseFloat ( e . target . was || 1 ) ,
ra = dv / pv ,
2024-06-05 17:36:35 -07:00
xv = parseFloat ( ui . scaleX . was ? ? ui . scaleX . value ) || 1 ,
yv = parseFloat ( ui . scaleY . was ? ? ui . scaleY . value ) || 1 ,
zv = parseFloat ( ui . scaleZ . was ? ? ui . scaleY . value ) || 1 ,
2021-01-27 11:23:39 -05:00
ta = e . target ,
2022-02-17 17:55:26 -05:00
xc = ui . lockX . checked ,
yc = ui . lockY . checked ,
zc = ui . lockZ . checked ,
xt = ta === ui . scaleX ,
yt = ta === ui . scaleY ,
zt = ta === ui . scaleZ ,
2021-01-27 11:23:39 -05:00
tl = ( xt && xc ) || ( yt && yc ) || ( zt && zc ) ,
xr = ( ( tl && xc ) || ( ! tl && xt ) ? ra : 1 ) ,
yr = ( ( tl && yc ) || ( ! tl && yt ) ? ra : 1 ) ,
zr = ( ( tl && zc ) || ( ! tl && zt ) ? ra : 1 ) ;
2024-06-05 17:36:35 -07:00
2022-02-17 17:55:26 -05:00
api . selection . scale ( xr , yr , zr ) ;
ui . scaleX . was = ui . scaleX . value = xv * xr ;
ui . scaleY . was = ui . scaleY . value = yv * yr ;
ui . scaleZ . was = ui . scaleZ . value = zv * zr ;
2020-04-11 09:22:37 -04:00
}
function selectionRotate ( e ) {
2024-06-05 17:36:35 -07:00
let val = parseFloat ( e . target . value ) || 0 ;
// let deg = val * DEG2RAD;
e . target . value = val ;
2020-04-11 09:22:37 -04:00
}
2022-02-17 17:55:26 -05:00
space . event . onEnterKey ( [
ui . scaleX , selectionScale ,
ui . scaleY , selectionScale ,
ui . scaleZ , selectionScale ,
ui . sizeX , selectionSize ,
ui . sizeY , selectionSize ,
ui . sizeZ , selectionSize ,
ui . toolName , updateTool ,
ui . toolNum , updateTool ,
ui . toolFluteDiam , updateTool ,
ui . toolFluteLen , updateTool ,
ui . toolShaftDiam , updateTool ,
ui . toolShaftLen , updateTool ,
ui . toolTaperTip , updateTool ,
2023-02-17 11:34:51 -05:00
ui . toolTaperAngle , updateTool ,
2020-04-11 09:22:37 -04:00
$ ( 'rot_x' ) , selectionRotate ,
$ ( 'rot_y' ) , selectionRotate ,
$ ( 'rot_z' ) , selectionRotate
2021-04-07 22:14:53 -04:00
] , true ) ;
2020-03-09 11:02:09 -04:00
2021-01-27 11:23:39 -05:00
$ ( 'lab-axis' ) . onclick = ( ) => {
2022-02-17 17:55:26 -05:00
ui . lockX . checked =
ui . lockY . checked =
ui . lockZ . checked = ! (
ui . lockX . checked ||
ui . lockY . checked ||
ui . lockZ . checked
2021-01-27 11:23:39 -05:00
) ;
} ;
2021-10-08 14:55:46 -04:00
$ ( 'scale-reset' ) . onclick = $ ( 'lab-scale' ) . onclick = ( ) => {
2022-02-17 17:55:26 -05:00
api . selection . scale ( 1 / ui . scaleX . was , 1 / ui . scaleY . was , 1 / ui . scaleZ . was ) ;
ui . scaleX . value = ui . scaleY . value = ui . scaleZ . value =
ui . scaleX . was = ui . scaleY . was = ui . scaleZ . was = 1 ;
2021-01-27 11:23:39 -05:00
} ;
2022-10-17 22:24:19 -04:00
$ ( 'app-xpnd' ) . onclick = ( ) => {
2022-10-19 23:57:53 -04:00
try {
DOC . body . requestFullscreen ( ) ;
} catch ( e ) {
event . emit ( 'resize' ) ;
moto . space . event . onResize ( ) ;
}
2022-10-17 22:24:19 -04:00
} ;
2024-05-19 22:31:25 -04:00
if ( ! DOC . body . requestFullscreen ) {
$ ( 'app-xpnd' ) . style . display = 'none' ;
2023-02-05 17:01:21 -05:00
}
2022-02-17 17:55:26 -05:00
uc . onBlur ( [
ui . toolName ,
ui . toolNum ,
ui . toolFluteDiam ,
ui . toolFluteLen ,
ui . toolShaftDiam ,
ui . toolShaftLen ,
ui . toolTaperTip ,
2021-01-04 20:47:55 -05:00
] , updateTool ) ;
2022-02-17 17:55:26 -05:00
ui . toolMetric . onclick = updateTool ;
ui . toolType . onchange = updateTool ;
2020-12-13 23:58:03 -05:00
// default show gcode pre
2022-02-17 17:55:26 -05:00
ui . gcodePre . button . click ( ) ;
2020-03-09 11:02:09 -04:00
2020-06-06 20:05:21 -04:00
function mksvg ( src ) {
let svg = DOC . createElement ( 'svg' ) ;
svg . innerHTML = src ;
return svg ;
}
2020-06-27 23:28:09 -04:00
function mklbl ( src ) {
let lbl = DOC . createElement ( 'label' ) ;
lbl . innerText = src ;
return lbl ;
}
2022-02-17 17:55:26 -05:00
api . platform . update _size ( ) ;
2020-03-09 11:02:09 -04:00
2022-02-24 23:29:53 -05:00
function mouseOnHover ( int , event , ints ) {
2022-02-17 17:55:26 -05:00
if ( ! api . feature . hover ) return ;
if ( ! int ) return api . feature . hovers || api . widgets . meshes ( ) ;
api . event . emit ( 'mouse.hover' , { int , ints , event , point : int . point , type : 'widget' } ) ;
2022-02-24 23:29:53 -05:00
}
2020-11-22 12:12:23 -05:00
2022-02-24 23:29:53 -05:00
function platformOnHover ( int , event ) {
2022-02-17 17:55:26 -05:00
if ( ! api . feature . hover ) return ;
if ( int ) api . event . emit ( 'mouse.hover' , { point : int , event , type : 'platform' } ) ;
2022-02-24 23:29:53 -05:00
}
api . event . on ( "feature.hover" , enable => {
space . mouse . onHover ( enable ? mouseOnHover : undefined ) ;
space . platform . onHover ( enable ? platformOnHover : undefined ) ;
2020-11-22 12:12:23 -05:00
} ) ;
2021-02-11 11:02:18 -05:00
// block standard browser context menu
DOC . oncontextmenu = ( event ) => {
2021-03-27 11:18:14 -04:00
let et = event . target ;
2021-05-03 14:48:03 -04:00
if ( et . tagName === 'CANVAS' || et . id === 'context-menu' || et . classList . contains ( 'draggable' ) ) {
2021-02-27 11:27:46 -05:00
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
return false ;
}
2021-02-11 11:02:18 -05:00
} ;
2022-04-04 21:37:15 -04:00
space . mouse . downSelect ( ( int , event ) => {
if ( api . feature . on _mouse _down ) {
2020-11-22 13:15:27 -05:00
if ( int ) {
2022-04-04 21:37:15 -04:00
api . feature . on _mouse _down ( int , event ) ;
2020-11-22 13:35:01 -05:00
return ;
2020-11-22 13:15:27 -05:00
}
2022-04-04 21:37:15 -04:00
}
if ( api . feature . hover ) {
if ( int ) {
return api . event . emit ( 'mouse.hover.down' , { int , point : int . point } ) ;
} else {
return api . selection . meshes ( ) ;
}
2020-11-22 13:15:27 -05:00
}
2020-03-30 14:10:36 -04:00
// lay flat with meta or ctrl clicking a selected face
2022-02-17 17:55:26 -05:00
if ( int && ( event . ctrlKey || event . metaKey || api . feature . on _face _select ) ) {
2020-03-30 14:10:36 -04:00
let q = new THREE . Quaternion ( ) ;
2020-11-22 12:12:23 -05:00
// find intersecting point, look "up" on Z and rotate to face that
2020-11-22 17:01:36 -05:00
q . setFromUnitVectors ( int . face . normal , new THREE . Vector3 ( 0 , 0 , - 1 ) ) ;
2022-02-17 17:55:26 -05:00
api . selection . rotate ( q ) ;
2020-03-30 14:10:36 -04:00
}
2022-02-17 17:55:26 -05:00
if ( api . view . get ( ) !== VIEWS . ARRANGE ) {
2020-11-22 12:12:23 -05:00
// return no selection in modes other than arrange
return null ;
} else {
// return selected meshes for further mouse processing
2022-02-17 17:55:26 -05:00
return api . feature . hovers || api . selection . meshes ( ) ;
2020-11-22 12:12:23 -05:00
}
2020-03-09 11:02:09 -04:00
} ) ;
2022-04-04 21:37:15 -04:00
space . mouse . upSelect ( ( object , event ) => {
if ( api . feature . on _mouse _up ) {
if ( event && object ) {
return api . feature . on _mouse _up ( object , event ) ;
} else {
return api . widgets . meshes ( ) ;
}
}
2022-02-17 17:55:26 -05:00
if ( event && api . feature . hover ) {
api . event . emit ( 'mouse.hover.up' , { object , event } ) ;
2020-11-22 13:15:27 -05:00
return ;
}
2020-03-09 11:02:09 -04:00
if ( event && event . target . nodeName === "CANVAS" ) {
2020-12-27 19:23:40 -05:00
if ( object && object . object ) {
if ( object . object . widget ) {
2021-11-08 20:23:56 -05:00
platform . select ( object . object . widget , event . shiftKey , false ) ;
2020-11-23 18:16:45 -05:00
}
2020-03-09 11:02:09 -04:00
} else {
platform . deselect ( ) ;
}
} else {
2022-02-17 17:55:26 -05:00
return api . feature . hovers || api . widgets . meshes ( ) ;
2020-03-09 11:02:09 -04:00
}
} ) ;
2022-02-17 17:55:26 -05:00
space . mouse . onDrag ( function ( delta , offset , up = false ) {
if ( api . feature . hover ) {
2020-11-22 14:53:17 -05:00
return ;
}
2021-10-19 21:58:06 -04:00
if ( up ) {
2022-02-17 17:55:26 -05:00
api . event . emit ( 'mouse.drag.done' , offset ) ;
2021-10-19 21:58:06 -04:00
}
2022-02-17 17:55:26 -05:00
if ( delta && ui . freeLayout . checked ) {
2020-05-01 10:29:50 -04:00
let set = settings ( ) ;
let dev = set . device ;
2020-11-20 10:32:58 -05:00
let bound = set . bounds _sel ;
2020-05-01 10:29:50 -04:00
let width = dev . bedWidth / 2 ;
let depth = dev . bedDepth / 2 ;
2020-11-20 10:32:58 -05:00
let isout = (
bound . min . x <= - width ||
bound . min . y <= - depth ||
bound . max . x >= width ||
bound . max . y >= depth
) ;
if ( ! isout ) {
if ( bound . min . x + delta . x <= - width ) return ;
if ( bound . min . y + delta . y <= - depth ) return ;
if ( bound . max . x + delta . x >= width ) return ;
if ( bound . max . y + delta . y >= depth ) return ;
}
2022-02-17 17:55:26 -05:00
api . selection . move ( delta . x , delta . y , 0 ) ;
api . event . emit ( 'selection.drag' , delta ) ;
2020-03-09 11:02:09 -04:00
} else {
2022-02-17 17:55:26 -05:00
return api . selection . meshes ( ) . length > 0 ;
2020-03-09 11:02:09 -04:00
}
} ) ;
2022-02-17 17:55:26 -05:00
api . space . restore ( init _two ) || checkSeed ( init _two ) || init _two ( ) ;
2020-03-16 23:57:14 -04:00
} ;
2020-03-09 11:02:09 -04:00
2020-03-16 23:57:14 -04:00
// SECOND STAGE INIT AFTER UI RESTORED
function init _two ( ) {
2022-02-17 17:55:26 -05:00
api . event . emit ( 'init.two' ) ;
2020-04-20 17:50:23 -04:00
2020-06-11 22:11:19 -04:00
// call driver initializations, if present
2022-02-17 17:55:26 -05:00
Object . values ( kiri . driver ) . forEach ( driver => {
2020-06-11 22:11:19 -04:00
if ( driver . init ) try {
2024-06-10 21:54:25 -07:00
driver . init ( kiri , api , driver ) ;
2020-06-11 22:11:19 -04:00
} catch ( error ) {
console . log ( { driver _init _fail : driver , error } )
}
} ) ;
2020-03-16 23:57:14 -04:00
// load script extensions
if ( SETUP . s ) SETUP . s . forEach ( function ( lib ) {
let scr = DOC . createElement ( 'script' ) ;
2020-03-17 12:16:35 -04:00
scr . setAttribute ( 'defer' , true ) ;
2022-02-17 17:55:26 -05:00
scr . setAttribute ( 'src' , ` /code/ ${ lib } .js? ${ kiri . version } ` ) ;
2020-03-16 23:57:14 -04:00
DOC . body . appendChild ( scr ) ;
2022-02-17 17:55:26 -05:00
stats . add ( 'load_' + lib ) ;
api . event . emit ( 'load.lib' , lib ) ;
2020-03-16 23:57:14 -04:00
} ) ;
2020-03-09 11:02:09 -04:00
2020-03-16 23:57:14 -04:00
// load CSS extensions
if ( SETUP . ss ) SETUP . ss . forEach ( function ( style ) {
style = style . charAt ( 0 ) === '/' ? style : ` /kiri/style- ${ style } ` ;
let ss = DOC . createElement ( 'link' ) ;
ss . setAttribute ( "type" , "text/css" ) ;
ss . setAttribute ( "rel" , "stylesheet" ) ;
2022-02-17 17:55:26 -05:00
ss . setAttribute ( "href" , ` ${ style } .css? ${ kiri . version } ` ) ;
2020-03-16 23:57:14 -04:00
DOC . body . appendChild ( ss ) ;
} ) ;
2020-03-09 11:02:09 -04:00
2020-03-16 23:57:14 -04:00
// override stored settings
if ( SETUP . v ) SETUP . v . forEach ( function ( kv ) {
kv = kv . split ( '=' ) ;
2022-02-17 17:55:26 -05:00
sdb . setItem ( kv [ 0 ] , kv [ 1 ] ) ;
2020-03-16 23:57:14 -04:00
} ) ;
2020-03-09 11:02:09 -04:00
2020-03-16 23:57:14 -04:00
// import octoprint settings
if ( SETUP . ophost ) {
2022-02-17 17:55:26 -05:00
let ohost = api . const . OCTO = {
2020-03-16 23:57:14 -04:00
host : SETUP . ophost [ 0 ] ,
apik : SETUP . opkey ? SETUP . opkey [ 0 ] : ''
} ;
2022-02-17 17:55:26 -05:00
sdb [ 'octo-host' ] = ohost . host ;
sdb [ 'octo-apik' ] = ohost . apik ;
2020-03-16 23:57:14 -04:00
console . log ( { octoprint : ohost } ) ;
}
2020-03-09 11:02:09 -04:00
2022-02-20 00:56:08 -05:00
// load workspace from url
if ( SETUP . wrk ) {
2022-08-04 12:37:42 -04:00
api . settings . import _url ( ` ${ proto } // ${ SETUP . wrk [ 0 ] } ` , false ) ;
2022-02-20 00:56:08 -05:00
}
2020-11-15 22:12:45 -05:00
// bind this to UI so main can call it on settings import
2022-02-17 17:55:26 -05:00
ui . sync = function ( ) {
2020-11-15 22:12:45 -05:00
const current = settings ( ) ;
const control = current . controller ;
const process = settings . process ;
platform . deselect ( ) ;
2022-02-17 17:55:26 -05:00
catalog . addFileListener ( updateCatalog ) ;
space . view . setZoom ( control . reverseZoom , control . zoomSpeed ) ;
space . platform . setGridZOff ( undefined ) ;
space . platform . setZOff ( 0.05 ) ;
2020-11-15 22:12:45 -05:00
// restore UI state from settings
2022-02-17 17:55:26 -05:00
ui . showOrigin . checked = control . showOrigin ;
ui . showRulers . checked = control . showRulers ;
ui . showSpeeds . checked = control . showSpeeds ;
ui . freeLayout . checked = control . freeLayout ;
ui . autoLayout . checked = control . autoLayout ;
ui . spaceRandoX . checked = control . spaceRandoX ;
ui . antiAlias . checked = control . antiAlias ;
ui . reverseZoom . checked = control . reverseZoom ;
ui . autoSave . checked = control . autoSave ;
ui . healMesh . checked = control . healMesh ;
2022-02-24 13:47:26 -05:00
ui . threaded . checked = setThreaded ( control . threaded ) ;
2022-02-17 17:55:26 -05:00
ui . assembly . checked = control . assembly ;
ui . ortho . checked = control . ortho ;
ui . devel . checked = control . devel ;
2020-11-15 22:12:45 -05:00
lineTypeSave ( ) ;
detailSave ( ) ;
2022-01-28 16:54:53 -05:00
updateStats ( ) ;
2020-11-15 22:12:45 -05:00
// optional set-and-lock mode (hides mode menu)
let SETMODE = SETUP . mode ? SETUP . mode [ 0 ] : null ;
// optional set-and-lock device (hides device menu)
let DEVNAME = SETUP . dev ? SETUP . dev [ 0 ] : null ;
// setup default mode and enable mode locking, if set
2022-02-17 17:55:26 -05:00
api . mode . set ( SETMODE || STARTMODE || current . mode , SETMODE ) ;
2020-11-15 22:12:45 -05:00
// fill device list
updateDeviceList ( ) ;
2020-03-09 11:02:09 -04:00
2020-11-15 22:12:45 -05:00
// update ui fields from settings
2022-02-19 12:43:42 -05:00
api . conf . update _fields ( ) ;
2020-03-09 11:02:09 -04:00
2020-11-15 22:12:45 -05:00
// default to ARRANGE view mode
2022-02-17 17:55:26 -05:00
api . view . set ( VIEWS . ARRANGE ) ;
2020-03-09 11:02:09 -04:00
2020-11-15 22:12:45 -05:00
// add ability to override
2022-02-17 17:55:26 -05:00
api . show . controls ( api . feature . controls ) ;
2020-06-06 20:05:21 -04:00
2020-11-15 22:12:45 -05:00
// update everything dependent on the platform size
platform . update _size ( ) ;
2021-07-07 21:09:34 -04:00
// load wasm if indicated
2022-02-17 17:55:26 -05:00
kiri . client . wasm ( control . assembly === true ) ;
2020-11-15 22:12:45 -05:00
} ;
2020-03-09 11:02:09 -04:00
2022-02-17 17:55:26 -05:00
ui . sync ( ) ;
2020-03-09 11:02:09 -04:00
2020-03-16 23:57:14 -04:00
// clear alerts as they build up
2022-02-17 17:55:26 -05:00
setInterval ( api . event . alerts , 1000 ) ;
2020-03-10 14:23:42 -04:00
2020-03-17 16:32:43 -04:00
// add hide-alerts-on-alert-click
2022-02-17 17:55:26 -05:00
ui . alert . dialog . onclick = function ( ) {
api . event . alerts ( true ) ;
2020-03-16 23:57:14 -04:00
} ;
2020-03-09 11:02:09 -04:00
2020-06-06 11:17:04 -04:00
// enable modal hiding
2022-02-17 17:55:26 -05:00
$ ( 'mod-x' ) . onclick = api . modal . hide ;
2020-03-17 16:32:43 -04:00
2022-02-17 17:55:26 -05:00
if ( ! SETUP . s ) console . log ( ` kiri | init main | ${ kiri . version } ` ) ;
2020-03-17 18:32:16 -04:00
// send init-done event
2022-02-17 17:55:26 -05:00
api . event . emit ( 'init-done' , stats ) ;
2020-04-15 15:20:02 -04:00
2020-06-13 22:01:43 -04:00
// show gdpr if it's never been seen and we're not iframed
2023-02-14 22:23:30 -05:00
if ( ! sdb . gdpr && WIN . self === WIN . top && ! SETUP . debug && ! api . const . LOCAL ) {
2020-06-13 20:04:39 -04:00
$ ( 'gdpr' ) . style . display = 'flex' ;
}
2023-03-12 12:22:35 -04:00
// warn of degraded functionality when SharedArrayBuffers are missing
if ( api . feature . work _alerts && ! window . SharedArrayBuffer ) {
api . alerts . show ( "The security context of this" , 10 ) ;
2024-06-13 22:17:20 -04:00
api . alerts . show ( "Window blocks important functionality." , 10 ) ;
api . alerts . show ( "Try a Chromium-base Browser instead" , 10 ) ;
2023-03-12 12:22:35 -04:00
}
2020-06-15 18:07:31 -04:00
// add keyboard focus handler (must use for iframes)
WIN . addEventListener ( 'load' , function ( ) {
WIN . focus ( ) ;
DOC . body . addEventListener ( 'click' , function ( ) {
WIN . focus ( ) ;
} , false ) ;
} ) ;
2020-06-13 20:04:39 -04:00
// dismiss gdpr alert
$ ( 'gotit' ) . onclick = ( ) => {
$ ( 'gdpr' ) . style . display = 'none' ;
2022-02-17 17:55:26 -05:00
sdb . gdpr = Date . now ( ) ;
2020-06-13 20:04:39 -04:00
} ;
2020-06-06 16:02:04 -04:00
// lift curtain
$ ( 'curtain' ) . style . display = 'none' ;
2020-06-08 00:08:19 -04:00
// bind interface action elements
2022-02-17 17:55:26 -05:00
$ ( 'app-name' ) . onclick = api . help . show ;
2024-06-01 16:51:46 -04:00
$ ( 'mode-device' ) . onclick = showDevices ;
$ ( 'mode-profile' ) . onclick = settingsLoad ;
2024-05-31 02:17:16 -04:00
$ ( 'mode-fdm' ) . onclick = ( ) => api . mode . set ( 'FDM' ) ;
$ ( 'mode-cam' ) . onclick = ( ) => api . mode . set ( 'CAM' ) ;
$ ( 'mode-sla' ) . onclick = ( ) => api . mode . set ( 'SLA' ) ;
$ ( 'mode-laser' ) . onclick = ( ) => api . mode . set ( 'LASER' ) ;
2024-06-09 11:00:53 -07:00
$ ( 'mode-drag' ) . onclick = ( ) => api . mode . set ( 'DRAG' ) ;
2024-06-09 14:03:16 -07:00
$ ( 'mode-wjet' ) . onclick = ( ) => api . mode . set ( 'WJET' ) ;
$ ( 'mode-wedm' ) . onclick = ( ) => api . mode . set ( 'WEDM' ) ;
2021-12-04 13:34:00 -05:00
$ ( 'set-device' ) . onclick = ( ev ) => { ev . stopPropagation ( ) ; showDevices ( ) } ;
2024-05-20 22:06:33 -04:00
$ ( 'set-profs' ) . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . conf . show ( ) } ;
2020-06-08 00:08:19 -04:00
$ ( 'set-tools' ) . onclick = ( ev ) => { ev . stopPropagation ( ) ; showTools ( ) } ;
2022-02-17 17:55:26 -05:00
$ ( 'set-prefs' ) . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . modal . show ( 'prefs' ) } ;
ui . acct . help . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . help . show ( ) } ;
ui . acct . export . onclick = ( ev ) => { ev . stopPropagation ( ) ; profileExport ( ) } ;
ui . acct . export . title = LANG . acct _xpo ;
$ ( 'file-recent' ) . onclick = ( ) => { api . modal . show ( 'files' ) } ;
2022-10-26 21:47:31 -04:00
$ ( 'file-import' ) . onclick = ( ev ) => { api . event . import ( ev ) ; } ;
2022-02-17 17:55:26 -05:00
ui . func . slice . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . function . slice ( ) } ;
ui . func . preview . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . function . print ( ) } ;
ui . func . animate . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . function . animate ( ) } ;
ui . func . export . onclick = ( ev ) => { ev . stopPropagation ( ) ; api . function . export ( ) } ;
$ ( 'view-arrange' ) . onclick = api . platform . layout ;
$ ( 'view-top' ) . onclick = space . view . top ;
$ ( 'view-home' ) . onclick = space . view . home ;
2024-05-20 22:20:20 -04:00
$ ( 'view-front' ) . onclick = space . view . front ;
$ ( 'view-back' ) . onclick = space . view . back ;
$ ( 'view-left' ) . onclick = space . view . left ;
$ ( 'view-right' ) . onclick = space . view . right ;
2021-10-09 17:28:49 -04:00
$ ( 'unrotate' ) . onclick = ( ) => {
2022-02-17 17:55:26 -05:00
api . widgets . for ( w => w . unrotate ( ) ) ;
api . selection . update _info ( ) ;
2021-10-09 17:28:49 -04:00
} ;
2020-06-15 09:47:12 -04:00
// rotation buttons
2024-06-05 17:36:35 -07:00
let d = ( Math . PI / 180 ) ;
$ ( 'rot_x_lt' ) . onclick = ( ) => { api . selection . rotate ( - d * $ ( 'rot_x' ) . value , 0 , 0 ) } ;
$ ( 'rot_x_gt' ) . onclick = ( ) => { api . selection . rotate ( d * $ ( 'rot_x' ) . value , 0 , 0 ) } ;
$ ( 'rot_y_lt' ) . onclick = ( ) => { api . selection . rotate ( 0 , - d * $ ( 'rot_y' ) . value , 0 ) } ;
$ ( 'rot_y_gt' ) . onclick = ( ) => { api . selection . rotate ( 0 , d * $ ( 'rot_y' ) . value , 0 ) } ;
$ ( 'rot_z_lt' ) . onclick = ( ) => { api . selection . rotate ( 0 , 0 , d * $ ( 'rot_z' ) . value ) } ;
$ ( 'rot_z_gt' ) . onclick = ( ) => { api . selection . rotate ( 0 , 0 , - d * $ ( 'rot_z' ) . value ) } ;
2020-11-08 16:44:32 -05:00
// rendering options
2022-02-17 17:55:26 -05:00
$ ( 'render-ghost' ) . onclick = ( ) => { api . view . wireframe ( false , 0 , api . view . is _arrange ( ) ? 0.4 : 0.25 ) ; } ;
$ ( 'render-wire' ) . onclick = ( ) => { api . view . wireframe ( true , 0 , api . space . is _dark ( ) ? 0.25 : 0.5 ) ; } ;
$ ( 'render-solid' ) . onclick = ( ) => { api . view . wireframe ( false , 0 , 1 ) ; } ;
2021-10-08 21:15:54 -04:00
// mesh buttons
2024-06-07 09:51:09 -07:00
// $('mesh-swap').onclick = () => { api.widgets.replace() };
// $('mesh-enable').onclick = () => { api.selection.enable() };
// $('mesh-disable').onclick = () => { api.selection.disable() };
// $('mesh-rename').onclick = () => { api.widgets.rename() };
2021-10-08 21:15:54 -04:00
$ ( 'mesh-export-stl' ) . onclick = ( ) => { objectsExport ( 'stl' ) } ;
$ ( 'mesh-export-obj' ) . onclick = ( ) => { objectsExport ( 'obj' ) } ;
2021-02-11 11:02:18 -05:00
$ ( 'context-duplicate' ) . onclick = duplicateSelection ;
$ ( 'context-mirror' ) . onclick = mirrorSelection ;
2024-06-02 11:00:37 -04:00
$ ( 'context-layflat' ) . onclick = ( ) => { api . event . emit ( "tool.mesh.lay-flat" ) } ;
2024-06-05 12:10:33 -07:00
$ ( 'context-setfocus' ) . onclick = ( ) => {
api . event . emit (
"tool.camera.focus" ,
ev => api . space . set _focus ( undefined , ev . object . point )
) ;
} ;
2020-06-08 11:54:57 -04:00
2022-02-17 17:55:26 -05:00
ui . modal . onclick = api . modal . hide ;
ui . modalBox . onclick = ( ev ) => { ev . stopPropagation ( ) } ;
2020-06-17 15:02:46 -04:00
2020-06-08 12:01:56 -04:00
// add app name hover info
2022-02-17 17:55:26 -05:00
$ ( 'app-info' ) . innerText = kiri . version ;
2024-06-02 14:10:16 -04:00
2020-06-08 12:01:56 -04:00
// show topline separator when iframed
2024-06-02 14:10:16 -04:00
try { if ( WIN . self !== WIN . top ) $ ( 'top-sep' ) . style . display = 'flex' } catch ( e ) { console . log ( e ) }
2020-11-16 22:19:14 -05:00
// warn users they are running a beta release
2022-02-17 17:55:26 -05:00
if ( kiri . beta && kiri . beta > 0 && sdb . kiri _beta != kiri . beta ) {
api . show . alert ( "this is a beta / development release" ) ;
sdb . kiri _beta = kiri . beta ;
2020-11-16 22:19:14 -05:00
}
2021-11-10 11:40:34 -05:00
// add palette3 edit button after filament source selector
{
2021-11-28 12:03:50 -05:00
let randomId = Math . round ( Math . random ( ) * 0xffffffffffff ) . toString ( 16 ) ;
2022-02-17 17:55:26 -05:00
let fsp = ui . filamentSource . parentNode ;
let btn = ui . filamentSourceEdit = DOC . createElement ( 'button' ) ;
2021-11-10 11:40:34 -05:00
btn . setAttribute ( 'id' , 'fs-edit' ) ;
btn . appendChild ( DOC . createTextNode ( 'edit' ) ) ;
2022-02-17 17:55:26 -05:00
fsp . insertBefore ( btn , ui . filamentSource ) ;
2021-11-19 23:52:49 -05:00
let editDone = ( ) => {
2022-02-17 17:55:26 -05:00
let device = api . conf . get ( ) . device ;
2021-11-19 23:52:49 -05:00
let extra = device . extras = device . extras || { } ;
btn . onclick = edit ;
btn . innerText = 'edit' ;
2022-02-17 17:55:26 -05:00
ui . extruder . parentNode . style . display = 'flex' ;
ui . palette . parentNode . style . display = 'none' ;
2021-11-19 23:52:49 -05:00
// save settings
extra . palette = {
2022-02-17 17:55:26 -05:00
printer : ui . paletteId . value || randomId ,
ping : ui . palettePing . convert ( ) ,
feed : ui . paletteFeed . convert ( ) ,
push : ui . palettePush . convert ( ) ,
offset : ui . paletteOffset . convert ( ) ,
heat : ui . paletteHeat . convert ( ) ,
cool : ui . paletteCool . convert ( ) ,
press : ui . palettePress . convert ( )
2021-11-19 23:52:49 -05:00
} ;
} ;
2021-11-15 14:10:15 -05:00
let edit = btn . onclick = ( ) => {
2022-02-17 17:55:26 -05:00
let device = api . conf . get ( ) . device ;
2021-11-15 14:10:15 -05:00
let extra = device . extras = device . extras || { } ;
let pinfo = extra . palette ;
if ( ! pinfo ) {
pinfo = extra . palette = {
2021-11-28 12:03:50 -05:00
printer : randomId ,
2021-11-15 14:10:15 -05:00
feed : 570 ,
push : 600 ,
heat : 0 ,
cool : 0 ,
press : 0
} ;
}
2022-02-17 17:55:26 -05:00
ui . paletteId . value = pinfo . printer ;
ui . palettePing . value = pinfo . ping || 0 ;
ui . paletteFeed . value = pinfo . feed || 0 ;
ui . palettePush . value = pinfo . push || 0 ;
ui . paletteOffset . value = pinfo . offset || 0 ;
ui . paletteHeat . value = pinfo . heat || 0 ;
ui . paletteCool . value = pinfo . cool || 0 ;
ui . palettePress . value = pinfo . press || 0 ;
ui . extruder . parentNode . style . display = 'none' ;
ui . palette . parentNode . style . display = 'flex' ;
2021-11-15 14:10:15 -05:00
btn . innerText = 'done' ;
2021-11-19 23:52:49 -05:00
btn . onclick = editDone ;
2021-11-15 14:10:15 -05:00
} ;
2022-02-17 17:55:26 -05:00
api . event . on ( [ "device.select" , "filament.source" ] , ( ) => {
ui . extruder . parentNode . style . display = 'flex' ;
ui . palette . parentNode . style . display = 'none' ;
2021-11-15 14:10:15 -05:00
btn . innerText = 'edit' ;
btn . onclick = edit ;
} ) ;
2022-02-17 17:55:26 -05:00
api . event . on ( "device.save" , editDone ) ;
2021-11-10 11:40:34 -05:00
}
2020-03-17 18:32:16 -04:00
}
2021-02-26 07:52:43 -05:00
// update static html elements with language overrides
2022-02-17 17:55:26 -05:00
ui . lang = function ( ) {
2021-10-07 22:59:05 -04:00
// lk attribute causes inner text to be replaced with lang value
2021-02-26 07:52:43 -05:00
for ( let el of [ ... DOC . querySelectorAll ( "[lk]" ) ] ) {
let key = el . getAttribute ( 'lk' ) ;
let val = LANG [ key ] ;
if ( val ) {
el . innerText = val ;
} else {
console . log ( { missing _ln : key } ) ;
}
}
2021-10-07 22:59:05 -04:00
// lkt attribute causes a title attribute to be set from lang value
for ( let el of [ ... DOC . querySelectorAll ( "[lkt]" ) ] ) {
let key = el . getAttribute ( 'lkt' ) ;
let val = LANG [ key ] ;
if ( val ) {
el . setAttribute ( "title" , val ) ;
} else {
console . log ( { missing _ln : key } ) ;
}
}
2021-10-09 18:29:20 -04:00
}
// init lang must happen before all other init functions
function init _lang ( ) {
// if a language needs to load, the script is injected and loaded
// first. once this loads, or doesn't, the initialization begins
2022-02-17 17:55:26 -05:00
let lang = SETUP . ln ? SETUP . ln [ 0 ] : sdb . getItem ( 'kiri-lang' ) || kiri . lang . get ( ) ;
2021-10-09 18:29:20 -04:00
// inject language script if not english
if ( lang && lang !== 'en' && lang !== 'en-us' ) {
2022-02-17 17:55:26 -05:00
let map = kiri . lang . map ( lang ) ;
2021-10-09 18:29:20 -04:00
let scr = DOC . createElement ( 'script' ) ;
// scr.setAttribute('defer',true);
2022-02-17 17:55:26 -05:00
scr . setAttribute ( 'src' , ` /kiri/lang/ ${ map } .js? ${ kiri . version } ` ) ;
2021-10-09 18:29:20 -04:00
( DOC . body || DOC . head ) . appendChild ( scr ) ;
2022-02-17 17:55:26 -05:00
stats . set ( 'll' , lang ) ;
2021-10-09 18:29:20 -04:00
scr . onload = function ( ) {
2022-02-17 17:55:26 -05:00
kiri . lang . set ( map ) ;
ui . lang ( ) ;
2021-10-09 18:29:20 -04:00
init _one ( ) ;
} ;
scr . onerror = function ( err ) {
console . log ( { language _load _error : err , lang } )
2022-02-17 17:55:26 -05:00
kiri . lang . set ( ) ;
ui . lang ( ) ;
2021-10-09 18:29:20 -04:00
init _one ( ) ;
}
2021-10-09 19:33:49 -04:00
} else {
// set to browser default which will be overridden
// by any future script loads (above)
2022-02-17 17:55:26 -05:00
kiri . lang . set ( ) ;
ui . lang ( ) ;
2020-03-18 18:22:57 -04:00
init _one ( ) ;
2020-03-17 18:32:16 -04:00
}
2020-03-16 23:57:14 -04:00
}
2020-03-09 11:02:09 -04:00
2021-12-27 10:18:13 -05:00
// setup init() trigger when dom + scripts complete
DOC . onreadystatechange = function ( ) {
if ( DOC . readyState === 'complete' ) {
init _lang ( ) ;
}
2020-03-17 18:32:16 -04:00
}
2020-03-09 11:02:09 -04:00
2022-02-20 22:47:04 -05:00
} ) ;