kiri/app renames and reorgs
This commit is contained in:
parent
d8ddb45bcb
commit
5bd67545dc
23 changed files with 486 additions and 499 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,5 +1,7 @@
|
|||
*.pem
|
||||
.DS_Store
|
||||
.bache
|
||||
.bcache
|
||||
.claude
|
||||
.docusaurus
|
||||
.env
|
||||
alt
|
||||
|
|
@ -16,4 +18,5 @@ src/ext/jszip-esm.js
|
|||
src/ext/quickjs.js
|
||||
src/ext/three.js
|
||||
tmp
|
||||
tmp_*/
|
||||
web/boot/bundle*
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import web from '../../moto/webui.js';
|
|||
|
||||
import { beta, version } from '../../moto/license.js';
|
||||
import { broker } from '../../moto/broker.js';
|
||||
import { client as work } from './client.js';
|
||||
import { client as workers } from './workers.js';
|
||||
import { consts, COLOR as color, LISTS as lists } from '../core/consts.js';
|
||||
import { device, devices } from './devices.js';
|
||||
import { functions } from './function.js';
|
||||
|
|
@ -17,8 +17,8 @@ import { group as groupModule } from './groups.js';
|
|||
import { help as helpModule } from './help.js';
|
||||
import { image as imageModule } from './image.js';
|
||||
import { Index } from '../../data/index.js';
|
||||
import { LANG } from './lang.js';
|
||||
import { local } from './local-storage.js';
|
||||
import { LANG } from './language.js';
|
||||
import { local } from './local.js';
|
||||
import { local as dataLocal } from '../../data/local.js';
|
||||
import { modal } from './modal.js';
|
||||
import { mode as modeModule, process as processModule } from './mode.js';
|
||||
|
|
@ -26,17 +26,17 @@ import { newWidget } from '../core/widget.js';
|
|||
import { noop, ajax, o2js, js2o, utils } from '../core/utils.js';
|
||||
import { openFiles } from './files.js';
|
||||
import { platform } from './platform.js';
|
||||
import { selection } from './select.js';
|
||||
import { selection } from './selected.js';
|
||||
import { settingsUI } from './config/dialog.js';
|
||||
import { showDevices } from './devices.js';
|
||||
import { showTools } from '../mode/cam/tools.js';
|
||||
import { space as SPACE } from '../../moto/space.js';
|
||||
import { stats } from './stats.js';
|
||||
import { types as load } from '../../load/file.js';
|
||||
import { UI } from './component.js';
|
||||
import { UI } from './inputs.js';
|
||||
import { updateTool } from '../mode/cam/tools.js';
|
||||
import { util as utilModule } from './util.js';
|
||||
import { view as viewModule } from './view-state.js';
|
||||
import { view as viewModule } from './viewmode.js';
|
||||
import { visuals } from './visuals.js';
|
||||
import { widgets } from '../core/widgets.js';
|
||||
import { workspace } from './workspace.js';
|
||||
|
|
@ -74,7 +74,7 @@ export const api = {
|
|||
dec() { api.event.emit("busy", --busyVal) }
|
||||
},
|
||||
catalog: FILES,
|
||||
client: work,
|
||||
client: workers,
|
||||
clip(text) {
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
|
|
@ -219,7 +219,7 @@ export const api = {
|
|||
visuals,
|
||||
web,
|
||||
widgets,
|
||||
work,
|
||||
work: workers,
|
||||
};
|
||||
|
||||
// allow widget to straddle client / worker FOR NOW
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
import { settings as set_ctrl } from './config/manager.js';
|
||||
import { $ } from '../../../moto/webui.js';
|
||||
import { api } from '../api.js';
|
||||
import { settings as set_ctrl } from './manager.js';
|
||||
|
||||
function settings() {
|
||||
return api.conf.get();
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
import { client } from './client.js';
|
||||
import { client } from './workers.js';
|
||||
import { local } from '../../data/local.js';
|
||||
import { util } from '../../geo/base.js';
|
||||
import { MODES } from '../core/consts.js';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { api } from './api.js';
|
||||
import { client } from './client.js';
|
||||
import { client } from './workers.js';
|
||||
import { codec } from '../core/codec.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { COLOR, PMODES } from '../core/consts.js';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { selection } from './select.js';
|
||||
import { selection } from './selected.js';
|
||||
import { Widget } from '../core/widget.js';
|
||||
|
||||
function groupMerge() {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { init as initLaser } from '../mode/laser/init-ui.js';
|
|||
import { init as initSLA } from '../mode/sla/init-ui.js';
|
||||
import { init as initWEDM } from '../mode/wedm/init-ui.js';
|
||||
import { init as initWJET } from '../mode/wjet/init-ui.js';
|
||||
import { interact } from './interact.js';
|
||||
import { interact } from './mouse.js';
|
||||
import { keyboard } from './keyboard.js';
|
||||
import { local as sdb } from '../../data/local.js';
|
||||
import { menu as menuCAM } from '../mode/cam/init-menu.js';
|
||||
|
|
@ -20,9 +20,8 @@ import { menu as menuLaser } from '../mode/laser/init-menu.js';
|
|||
import { menu as menuSLA } from '../mode/sla/init-menu.js';
|
||||
import { modal } from './modal.js';
|
||||
import { preferences } from './preferences.js';
|
||||
import { selectionTools } from './selection-tools.js';
|
||||
import { settings as set_ctrl } from './config/manager.js';
|
||||
import { settingsOps } from './settings-ops.js';
|
||||
import { settingsOps } from './config/settings.js';
|
||||
import { slider } from './slider.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { VIEWS, MODES, SEED } from '../core/consts.js';
|
||||
|
|
@ -32,6 +31,7 @@ import STACKS from './stacks.js';
|
|||
let { SETUP } = api.const,
|
||||
{ CAM, SLA, FDM, LASER, DRAG, WJET, WEDM } = MODES,
|
||||
{ catalog, platform, selection, stats } = api,
|
||||
{ input_binding, input_position, input_rotate } = selection,
|
||||
DOC = self.document,
|
||||
WIN = self.window,
|
||||
LANG = api.language.current,
|
||||
|
|
@ -516,7 +516,7 @@ function init_one() {
|
|||
VIEWS,
|
||||
DOC,
|
||||
WIN,
|
||||
rotateInputSelection: selectionTools.rotateInputSelection,
|
||||
rotateInputSelection: input_rotate,
|
||||
settingsLoad: settingsOps.settingsLoad
|
||||
});
|
||||
|
||||
|
|
@ -587,7 +587,7 @@ function init_one() {
|
|||
]);
|
||||
|
||||
// Setup selection transformation bindings
|
||||
selectionTools.setupSelectionBindings(ui);
|
||||
input_binding(ui);
|
||||
|
||||
$('lab-axis').onclick = () => {
|
||||
ui.lockX.checked =
|
||||
|
|
@ -684,4 +684,4 @@ function init_one() {
|
|||
});
|
||||
};
|
||||
|
||||
export { onBooleanClick, updateTool, init_one };
|
||||
export { onBooleanClick, init_one as init_input };
|
||||
292
src/kiri/app/init-sync.js
Normal file
292
src/kiri/app/init-sync.js
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
import { beta, version } from '../../moto/license.js';
|
||||
import { fileOps } from './file-ops.js';
|
||||
import { local as sdb } from '../../data/local.js';
|
||||
import { preferences } from './preferences.js';
|
||||
import { settings as set_ctrl } from './config/manager.js';
|
||||
import { settingsOps } from './config/settings.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { VIEWS } from '../core/consts.js';
|
||||
|
||||
const DOC = self.document;
|
||||
const WIN = self.window;
|
||||
const proto = location.protocol;
|
||||
const { SETUP, LOCAL } = api.const;
|
||||
const { platform, client, catalog, stats } = api;
|
||||
const LANG = api.language.current;
|
||||
const ui = api.ui;
|
||||
const STARTMODE = SETUP.sm && SETUP.sm.length === 1 ? SETUP.sm[0] : null;
|
||||
|
||||
function settings() {
|
||||
return api.conf.get();
|
||||
}
|
||||
|
||||
// SECOND STAGE INIT AFTER UI RESTORED
|
||||
export async function init_sync() {
|
||||
api.event.emit('init.two');
|
||||
|
||||
// load script extensions
|
||||
if (SETUP.s) SETUP.s.forEach(function(lib) {
|
||||
let scr = DOC.createElement('script');
|
||||
scr.setAttribute('async', true);
|
||||
scr.setAttribute('defer', true);
|
||||
scr.setAttribute('src',`/code/${lib}.js`);
|
||||
DOC.body.appendChild(scr);
|
||||
stats.add('load_'+lib);
|
||||
api.event.emit('load.lib', lib);
|
||||
});
|
||||
|
||||
// override stored settings
|
||||
if (SETUP.v) SETUP.v.forEach(function(kv) {
|
||||
kv = kv.split('=');
|
||||
sdb.setItem(kv[0],kv[1]);
|
||||
});
|
||||
|
||||
// import octoprint settings
|
||||
if (SETUP.ophost) {
|
||||
let ohost = api.const.OCTO = {
|
||||
host: SETUP.ophost[0],
|
||||
apik: SETUP.opkey ? SETUP.opkey[0] : ''
|
||||
};
|
||||
sdb['octo-host'] = ohost.host;
|
||||
sdb['octo-apik'] = ohost.apik;
|
||||
console.log({octoprint:ohost});
|
||||
}
|
||||
|
||||
// load workspace from url
|
||||
if (SETUP.wrk) {
|
||||
set_ctrl.import_url(`${proto}//${SETUP.wrk[0]}`, false);
|
||||
}
|
||||
|
||||
// load an object from url
|
||||
if (SETUP.load) {
|
||||
console.log({load:SETUP});
|
||||
api.platform.load_url(`${proto}//${SETUP.load[0]}`);
|
||||
}
|
||||
|
||||
// bind this to UI so main can call it on settings import
|
||||
ui.sync = ui_sync;
|
||||
ui_sync();
|
||||
|
||||
// clear alerts as they build up
|
||||
setInterval(api.event.alerts, 1000);
|
||||
|
||||
// add hide-alerts-on-alert-click
|
||||
ui.alert.dialog.onclick = function() {
|
||||
api.event.alerts(true);
|
||||
};
|
||||
|
||||
// enable modal hiding
|
||||
$('mod-x').onclick = api.modal.hide;
|
||||
|
||||
if (!SETUP.s) console.log(`kiri | init main | ${version}`);
|
||||
|
||||
// send init-done event
|
||||
api.event.emit('init-done', stats);
|
||||
|
||||
// show gdpr if it's never been seen and we're not iframed
|
||||
const isLocal = LOCAL || WIN.location.host.split(':')[0] === 'localhost';
|
||||
if (!sdb.gdpr && WIN.self === WIN.top && !SETUP.debug && !isLocal) {
|
||||
$('gdpr').style.display = 'flex';
|
||||
}
|
||||
|
||||
// warn of degraded functionality when SharedArrayBuffers are missing
|
||||
if (api.feature.work_alerts && !window.SharedArrayBuffer) {
|
||||
api.alerts.show("The security context of this", 10);
|
||||
api.alerts.show("Window blocks important functionality.", 10);
|
||||
api.alerts.show("Try a Chromium-base Browser instead", 10);
|
||||
}
|
||||
|
||||
// add keyboard focus handler (must use for iframes)
|
||||
WIN.addEventListener('load', function () {
|
||||
WIN.focus();
|
||||
DOC.body.addEventListener('click', function() {
|
||||
WIN.focus();
|
||||
},false);
|
||||
});
|
||||
|
||||
// dismiss gdpr alert
|
||||
$('gotit').onclick = () => {
|
||||
$('gdpr').style.display = 'none';
|
||||
sdb.gdpr = Date.now();
|
||||
};
|
||||
|
||||
// Setup navigation button bindings
|
||||
setup_keybd_nav(ui, WIN, LANG);
|
||||
|
||||
// ui.modal.onclick = api.modal.hide;
|
||||
ui.modalBox.onclick = (ev) => { ev.stopPropagation() };
|
||||
|
||||
// add app name hover info
|
||||
$('app-info').innerText = version;
|
||||
|
||||
// show topline separator when iframed
|
||||
try { if (WIN.self !== WIN.top) $('top-sep').style.display = 'flex' } catch (e) { console.log(e) }
|
||||
|
||||
// warn users they are running a beta release
|
||||
if (beta && beta > 0 && sdb.kiri_beta != beta) {
|
||||
api.show.alert("CAUTION");
|
||||
api.show.alert("this is a development release");
|
||||
api.show.alert("and may not function properly");
|
||||
sdb.kiri_beta = beta;
|
||||
}
|
||||
|
||||
// hide url params but preserve version root (when present)
|
||||
let wlp = WIN.location.pathname;
|
||||
let kio = wlp.indexOf('/kiri/');
|
||||
if (kio >= 0) {
|
||||
history.replaceState({}, '', wlp.substring(0,kio + 6));
|
||||
}
|
||||
|
||||
// lift curtain
|
||||
$('curtain').style.display = 'none';
|
||||
}
|
||||
|
||||
function ui_sync() {
|
||||
const current = settings();
|
||||
const control = current.controller;
|
||||
|
||||
if (!control.devel) {
|
||||
// TODO: hide thin type 3 during development
|
||||
api.const.LISTS.thin.length = 3;
|
||||
}
|
||||
|
||||
platform.deselect();
|
||||
catalog.addFileListener(fileOps.updateCatalog);
|
||||
space.view.setZoom(control.reverseZoom, control.zoomSpeed);
|
||||
space.platform.setGridZOff(undefined);
|
||||
space.platform.setZOff(0.05);
|
||||
space.view.setProjection(control.ortho ? 'orthographic' : 'perspective');
|
||||
|
||||
// restore UI state from settings
|
||||
ui.antiAlias.checked = control.antiAlias;
|
||||
ui.assembly.checked = control.assembly;
|
||||
ui.autoLayout.checked = control.autoLayout;
|
||||
ui.autoSave.checked = control.autoSave;
|
||||
ui.devel.checked = control.devel;
|
||||
ui.freeLayout.checked = control.freeLayout;
|
||||
ui.healMesh.checked = control.healMesh;
|
||||
ui.manifold.checked = control.manifold;
|
||||
ui.ortho.checked = control.ortho;
|
||||
ui.reverseZoom.checked = control.reverseZoom;
|
||||
ui.showOrigin.checked = control.showOrigin;
|
||||
ui.showRulers.checked = control.showRulers;
|
||||
ui.showSpeeds.checked = control.showSpeeds;
|
||||
ui.spaceRandoX.checked = control.spaceRandoX;
|
||||
// ui.threaded.checked = setThreaded(control.threaded);
|
||||
ui.webGPU.checked = control.webGPU;
|
||||
|
||||
preferences.setThreaded(true);
|
||||
preferences.lineTypeSave();
|
||||
preferences.detailSave();
|
||||
preferences.updateStats();
|
||||
|
||||
// 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
|
||||
api.mode.set(SETMODE || STARTMODE || current.mode, SETMODE);
|
||||
|
||||
// fill device list
|
||||
api.devices.refresh();
|
||||
|
||||
// update ui fields from settings
|
||||
api.conf.update_fields();
|
||||
|
||||
// default to ARRANGE view mode
|
||||
api.view.set(VIEWS.ARRANGE);
|
||||
|
||||
// add ability to override (todo: restore?)
|
||||
// api.show.controls(api.feature.controls);
|
||||
|
||||
// update everything dependent on the platform size
|
||||
platform.update_size();
|
||||
|
||||
// load wasm if indicated
|
||||
client.wasm(control.assembly === true);
|
||||
}
|
||||
|
||||
function setup_keybd_nav(ui, WIN, LANG) {
|
||||
const { selection } = api;
|
||||
|
||||
// bind interface action elements
|
||||
$('export-support-a').onclick = (ev) => { ev.stopPropagation(); api.modal.show('don8') };
|
||||
$('mode-device').onclick = api.show.devices;
|
||||
$('mode-profile').onclick = settingsOps.settingsLoad;
|
||||
$('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');
|
||||
$('mode-drag').onclick = () => api.mode.set('DRAG');
|
||||
$('mode-wjet').onclick = () => api.mode.set('WJET');
|
||||
$('mode-wedm').onclick = () => api.mode.set('WEDM');
|
||||
$('set-device').onclick = (ev) => { ev.stopPropagation(); api.show.devices() };
|
||||
$('set-profs').onclick = (ev) => { ev.stopPropagation(); api.conf.show() };
|
||||
$('set-tools').onclick = (ev) => { ev.stopPropagation(); api.show.tools() };
|
||||
$('set-prefs').onclick = (ev) => { ev.stopPropagation(); api.modal.show('prefs') };
|
||||
ui.acct.help.onclick = (ev) => { ev.stopPropagation(); api.help.show() };
|
||||
ui.acct.don8.onclick = (ev) => { ev.stopPropagation(); api.modal.show('don8') };
|
||||
ui.acct.mesh.onclick = (ev) => { ev.stopPropagation(); WIN.location = "/mesh" };
|
||||
ui.acct.export.onclick = (ev) => { ev.stopPropagation(); settingsOps.profileExport() };
|
||||
ui.acct.export.title = LANG.acct_xpo;
|
||||
$('file-new').onclick = (ev) => { ev.stopPropagation(); settingsOps.workspaceNew() };
|
||||
$('file-recent').onclick = () => { api.modal.show('files') };
|
||||
$('file-import').onclick = (ev) => { api.event.import(ev); };
|
||||
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;
|
||||
$('view-front').onclick = space.view.front;
|
||||
$('view-back').onclick = space.view.back;
|
||||
$('view-left').onclick = space.view.left;
|
||||
$('view-right').onclick = space.view.right;
|
||||
$('unrotate').onclick = () => {
|
||||
api.widgets.for(w => w.unrotate());
|
||||
selection.update_info();
|
||||
};
|
||||
// attach button handlers to support targets
|
||||
for (let btn of ["don8pt","don8gh","don8pp"]) {
|
||||
$(btn).onclick = (ev) => {
|
||||
window.open(ev.target.children[0].href);
|
||||
}
|
||||
}
|
||||
// rotation buttons
|
||||
let d = (Math.PI / 180);
|
||||
$('rot_x_lt').onclick = () => { selection.rotate(-d * $('rot_x').value,0,0) };
|
||||
$('rot_x_gt').onclick = () => { selection.rotate( d * $('rot_x').value,0,0) };
|
||||
$('rot_y_lt').onclick = () => { selection.rotate(0,-d * $('rot_y').value,0) };
|
||||
$('rot_y_gt').onclick = () => { selection.rotate(0, d * $('rot_y').value,0) };
|
||||
$('rot_z_lt').onclick = () => { selection.rotate(0,0, d * $('rot_z').value) };
|
||||
$('rot_z_gt').onclick = () => { selection.rotate(0,0,-d * $('rot_z').value) };
|
||||
// rendering options
|
||||
$('render-edges').onclick = () => { api.view.edges({ toggle: true }); api.conf.save() };
|
||||
$('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); };
|
||||
$('mesh-export-stl').onclick = () => { settingsOps.objectsExport('stl') };
|
||||
$('mesh-export-obj').onclick = () => { settingsOps.objectsExport('obj') };
|
||||
$('mesh-merge').onclick = selection.merge;
|
||||
$('mesh-split').onclick = selection.isolateBodies;
|
||||
$('context-duplicate').onclick = selection.duplicate;
|
||||
$('context-mirror').onclick = selection.mirror;
|
||||
$('context-layflat').onclick = () => { api.event.emit("tool.mesh.lay-flat") };
|
||||
$('context-lefty').onclick = () => { api.event.emit("tool.mesh.lefty") };
|
||||
$('context-setfocus').onclick = () => {
|
||||
api.event.emit(
|
||||
"tool.camera.focus",
|
||||
ev => api.space.set_focus(undefined, ev.object.point)
|
||||
);
|
||||
};
|
||||
$('context-contents').onclick = () => { api.SPACE.view.fit() };
|
||||
$('view-fit').onclick = () => { api.SPACE.view.fit() };
|
||||
$('wassup').onmouseover = () => { $('suppopp').classList.remove('hide') };
|
||||
}
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
import { beta, version } from '../../moto/license.js';
|
||||
import { fileOps } from './file-ops.js';
|
||||
import { local as sdb } from '../../data/local.js';
|
||||
import { navigation } from './navigation.js';
|
||||
import { preferences } from './preferences.js';
|
||||
import { settings as set_ctrl } from './config/manager.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { VIEWS } from '../core/consts.js';
|
||||
|
||||
const DOC = self.document;
|
||||
const WIN = self.window;
|
||||
const proto = location.protocol;
|
||||
const { SETUP, LOCAL } = api.const;
|
||||
const { platform, client, catalog, stats } = api;
|
||||
const LANG = api.language.current;
|
||||
const ui = api.ui;
|
||||
const STARTMODE = SETUP.sm && SETUP.sm.length === 1 ? SETUP.sm[0] : null;
|
||||
|
||||
function settings() {
|
||||
return api.conf.get();
|
||||
}
|
||||
|
||||
// SECOND STAGE INIT AFTER UI RESTORED
|
||||
export async function init_two() {
|
||||
api.event.emit('init.two');
|
||||
|
||||
// load script extensions
|
||||
if (SETUP.s) SETUP.s.forEach(function(lib) {
|
||||
let scr = DOC.createElement('script');
|
||||
scr.setAttribute('async', true);
|
||||
scr.setAttribute('defer', true);
|
||||
scr.setAttribute('src',`/code/${lib}.js`);
|
||||
DOC.body.appendChild(scr);
|
||||
stats.add('load_'+lib);
|
||||
api.event.emit('load.lib', lib);
|
||||
});
|
||||
|
||||
// override stored settings
|
||||
if (SETUP.v) SETUP.v.forEach(function(kv) {
|
||||
kv = kv.split('=');
|
||||
sdb.setItem(kv[0],kv[1]);
|
||||
});
|
||||
|
||||
// import octoprint settings
|
||||
if (SETUP.ophost) {
|
||||
let ohost = api.const.OCTO = {
|
||||
host: SETUP.ophost[0],
|
||||
apik: SETUP.opkey ? SETUP.opkey[0] : ''
|
||||
};
|
||||
sdb['octo-host'] = ohost.host;
|
||||
sdb['octo-apik'] = ohost.apik;
|
||||
console.log({octoprint:ohost});
|
||||
}
|
||||
|
||||
// load workspace from url
|
||||
if (SETUP.wrk) {
|
||||
set_ctrl.import_url(`${proto}//${SETUP.wrk[0]}`, false);
|
||||
}
|
||||
|
||||
// load an object from url
|
||||
if (SETUP.load) {
|
||||
console.log({load:SETUP});
|
||||
api.platform.load_url(`${proto}//${SETUP.load[0]}`);
|
||||
}
|
||||
|
||||
// bind this to UI so main can call it on settings import
|
||||
ui.sync = function() {
|
||||
const current = settings();
|
||||
const control = current.controller;
|
||||
|
||||
if (!control.devel) {
|
||||
// TODO: hide thin type 3 during development
|
||||
api.const.LISTS.thin.length = 3;
|
||||
}
|
||||
|
||||
platform.deselect();
|
||||
catalog.addFileListener(fileOps.updateCatalog);
|
||||
space.view.setZoom(control.reverseZoom, control.zoomSpeed);
|
||||
space.platform.setGridZOff(undefined);
|
||||
space.platform.setZOff(0.05);
|
||||
space.view.setProjection(control.ortho ? 'orthographic' : 'perspective');
|
||||
|
||||
// restore UI state from settings
|
||||
ui.antiAlias.checked = control.antiAlias;
|
||||
ui.assembly.checked = control.assembly;
|
||||
ui.autoLayout.checked = control.autoLayout;
|
||||
ui.autoSave.checked = control.autoSave;
|
||||
ui.devel.checked = control.devel;
|
||||
ui.freeLayout.checked = control.freeLayout;
|
||||
ui.healMesh.checked = control.healMesh;
|
||||
ui.manifold.checked = control.manifold;
|
||||
ui.ortho.checked = control.ortho;
|
||||
ui.reverseZoom.checked = control.reverseZoom;
|
||||
ui.showOrigin.checked = control.showOrigin;
|
||||
ui.showRulers.checked = control.showRulers;
|
||||
ui.showSpeeds.checked = control.showSpeeds;
|
||||
ui.spaceRandoX.checked = control.spaceRandoX;
|
||||
// ui.threaded.checked = setThreaded(control.threaded);
|
||||
ui.webGPU.checked = control.webGPU;
|
||||
|
||||
preferences.setThreaded(true);
|
||||
preferences.lineTypeSave();
|
||||
preferences.detailSave();
|
||||
preferences.updateStats();
|
||||
|
||||
// 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
|
||||
api.mode.set(SETMODE || STARTMODE || current.mode, SETMODE);
|
||||
|
||||
// fill device list
|
||||
api.devices.refresh();
|
||||
|
||||
// update ui fields from settings
|
||||
api.conf.update_fields();
|
||||
|
||||
// default to ARRANGE view mode
|
||||
api.view.set(VIEWS.ARRANGE);
|
||||
|
||||
// add ability to override (todo: restore?)
|
||||
// api.show.controls(api.feature.controls);
|
||||
|
||||
// update everything dependent on the platform size
|
||||
platform.update_size();
|
||||
|
||||
// load wasm if indicated
|
||||
client.wasm(control.assembly === true);
|
||||
};
|
||||
|
||||
ui.sync();
|
||||
|
||||
// clear alerts as they build up
|
||||
setInterval(api.event.alerts, 1000);
|
||||
|
||||
// add hide-alerts-on-alert-click
|
||||
ui.alert.dialog.onclick = function() {
|
||||
api.event.alerts(true);
|
||||
};
|
||||
|
||||
// enable modal hiding
|
||||
$('mod-x').onclick = api.modal.hide;
|
||||
|
||||
if (!SETUP.s) console.log(`kiri | init main | ${version}`);
|
||||
|
||||
// send init-done event
|
||||
api.event.emit('init-done', stats);
|
||||
|
||||
// show gdpr if it's never been seen and we're not iframed
|
||||
const isLocal = LOCAL || WIN.location.host.split(':')[0] === 'localhost';
|
||||
if (!sdb.gdpr && WIN.self === WIN.top && !SETUP.debug && !isLocal) {
|
||||
$('gdpr').style.display = 'flex';
|
||||
}
|
||||
|
||||
// warn of degraded functionality when SharedArrayBuffers are missing
|
||||
if (api.feature.work_alerts && !window.SharedArrayBuffer) {
|
||||
api.alerts.show("The security context of this", 10);
|
||||
api.alerts.show("Window blocks important functionality.", 10);
|
||||
api.alerts.show("Try a Chromium-base Browser instead", 10);
|
||||
}
|
||||
|
||||
// add keyboard focus handler (must use for iframes)
|
||||
WIN.addEventListener('load', function () {
|
||||
WIN.focus();
|
||||
DOC.body.addEventListener('click', function() {
|
||||
WIN.focus();
|
||||
},false);
|
||||
});
|
||||
|
||||
// dismiss gdpr alert
|
||||
$('gotit').onclick = () => {
|
||||
$('gdpr').style.display = 'none';
|
||||
sdb.gdpr = Date.now();
|
||||
};
|
||||
|
||||
// Setup navigation button bindings
|
||||
navigation.setupNavigation(ui, WIN, LANG);
|
||||
|
||||
// ui.modal.onclick = api.modal.hide;
|
||||
ui.modalBox.onclick = (ev) => { ev.stopPropagation() };
|
||||
|
||||
// add app name hover info
|
||||
$('app-info').innerText = version;
|
||||
|
||||
// show topline separator when iframed
|
||||
try { if (WIN.self !== WIN.top) $('top-sep').style.display = 'flex' } catch (e) { console.log(e) }
|
||||
|
||||
// warn users they are running a beta release
|
||||
if (beta && beta > 0 && sdb.kiri_beta != beta) {
|
||||
api.show.alert("CAUTION");
|
||||
api.show.alert("this is a development release");
|
||||
api.show.alert("and may not function properly");
|
||||
sdb.kiri_beta = beta;
|
||||
}
|
||||
|
||||
// hide url params but preserve version root (when present)
|
||||
let wlp = WIN.location.pathname;
|
||||
let kio = wlp.indexOf('/kiri/');
|
||||
if (kio >= 0) {
|
||||
history.replaceState({}, '', wlp.substring(0,kio + 6));
|
||||
}
|
||||
|
||||
// lift curtain
|
||||
$('curtain').style.display = 'none';
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import { api } from './api.js';
|
|||
import { consts } from '../core/consts.js';
|
||||
import { modal } from './modal.js';
|
||||
import { platform } from './platform.js';
|
||||
import { selection } from './select.js';
|
||||
import { selection } from './selected.js';
|
||||
import { settings } from './config/manager.js';
|
||||
|
||||
const { MODES, VIEWS } = consts;
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { settingsOps } from './settings-ops.js';
|
||||
|
||||
const { selection } = api;
|
||||
|
||||
function setupNavigation(ui, WIN, LANG) {
|
||||
// bind interface action elements
|
||||
$('export-support-a').onclick = (ev) => { ev.stopPropagation(); api.modal.show('don8') };
|
||||
$('mode-device').onclick = api.show.devices;
|
||||
$('mode-profile').onclick = settingsOps.settingsLoad;
|
||||
$('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');
|
||||
$('mode-drag').onclick = () => api.mode.set('DRAG');
|
||||
$('mode-wjet').onclick = () => api.mode.set('WJET');
|
||||
$('mode-wedm').onclick = () => api.mode.set('WEDM');
|
||||
$('set-device').onclick = (ev) => { ev.stopPropagation(); api.show.devices() };
|
||||
$('set-profs').onclick = (ev) => { ev.stopPropagation(); api.conf.show() };
|
||||
$('set-tools').onclick = (ev) => { ev.stopPropagation(); api.show.tools() };
|
||||
$('set-prefs').onclick = (ev) => { ev.stopPropagation(); api.modal.show('prefs') };
|
||||
ui.acct.help.onclick = (ev) => { ev.stopPropagation(); api.help.show() };
|
||||
ui.acct.don8.onclick = (ev) => { ev.stopPropagation(); api.modal.show('don8') };
|
||||
ui.acct.mesh.onclick = (ev) => { ev.stopPropagation(); WIN.location = "/mesh" };
|
||||
ui.acct.export.onclick = (ev) => { ev.stopPropagation(); settingsOps.profileExport() };
|
||||
ui.acct.export.title = LANG.acct_xpo;
|
||||
$('file-new').onclick = (ev) => { ev.stopPropagation(); settingsOps.workspaceNew() };
|
||||
$('file-recent').onclick = () => { api.modal.show('files') };
|
||||
$('file-import').onclick = (ev) => { api.event.import(ev); };
|
||||
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;
|
||||
$('view-front').onclick = space.view.front;
|
||||
$('view-back').onclick = space.view.back;
|
||||
$('view-left').onclick = space.view.left;
|
||||
$('view-right').onclick = space.view.right;
|
||||
$('unrotate').onclick = () => {
|
||||
api.widgets.for(w => w.unrotate());
|
||||
selection.update_info();
|
||||
};
|
||||
// attach button handlers to support targets
|
||||
for (let btn of ["don8pt","don8gh","don8pp"]) {
|
||||
$(btn).onclick = (ev) => {
|
||||
window.open(ev.target.children[0].href);
|
||||
}
|
||||
}
|
||||
// rotation buttons
|
||||
let d = (Math.PI / 180);
|
||||
$('rot_x_lt').onclick = () => { selection.rotate(-d * $('rot_x').value,0,0) };
|
||||
$('rot_x_gt').onclick = () => { selection.rotate( d * $('rot_x').value,0,0) };
|
||||
$('rot_y_lt').onclick = () => { selection.rotate(0,-d * $('rot_y').value,0) };
|
||||
$('rot_y_gt').onclick = () => { selection.rotate(0, d * $('rot_y').value,0) };
|
||||
$('rot_z_lt').onclick = () => { selection.rotate(0,0, d * $('rot_z').value) };
|
||||
$('rot_z_gt').onclick = () => { selection.rotate(0,0,-d * $('rot_z').value) };
|
||||
// rendering options
|
||||
$('render-edges').onclick = () => { api.view.edges({ toggle: true }); api.conf.save() };
|
||||
$('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); };
|
||||
$('mesh-export-stl').onclick = () => { settingsOps.objectsExport('stl') };
|
||||
$('mesh-export-obj').onclick = () => { settingsOps.objectsExport('obj') };
|
||||
$('mesh-merge').onclick = selection.merge;
|
||||
$('mesh-split').onclick = selection.isolateBodies;
|
||||
$('context-duplicate').onclick = selection.duplicate;
|
||||
$('context-mirror').onclick = selection.mirror;
|
||||
$('context-layflat').onclick = () => { api.event.emit("tool.mesh.lay-flat") };
|
||||
$('context-lefty').onclick = () => { api.event.emit("tool.mesh.lefty") };
|
||||
$('context-setfocus').onclick = () => {
|
||||
api.event.emit(
|
||||
"tool.camera.focus",
|
||||
ev => api.space.set_focus(undefined, ev.object.point)
|
||||
);
|
||||
};
|
||||
$('context-contents').onclick = () => { api.SPACE.view.fit() };
|
||||
$('view-fit').onclick = () => { api.SPACE.view.fit() };
|
||||
$('wassup').onmouseover = () => { $('suppopp').classList.remove('hide') };
|
||||
}
|
||||
|
||||
export const navigation = {
|
||||
setupNavigation
|
||||
};
|
||||
|
|
@ -9,6 +9,10 @@ import { encode as stlEncode } from '../../load/stl.js';
|
|||
|
||||
const selectedMeshes = [];
|
||||
|
||||
function updateTool(ev) {
|
||||
api.tool.update(ev);
|
||||
}
|
||||
|
||||
function for_groups(fn) {
|
||||
let groups = widgets(true).map(w => w.group).uniq();
|
||||
for (let group of groups) {
|
||||
|
|
@ -47,6 +51,20 @@ function move(x, y, z, abs) {
|
|||
api.space.auto_save();
|
||||
}
|
||||
|
||||
function get_bounds() {
|
||||
// Helper to compute bounds of selected meshes
|
||||
const THREE = self.THREE;
|
||||
let bounds = new THREE.Box3();
|
||||
selection.for_meshes(mesh => {
|
||||
let box = mesh.getBoundingBox().clone();
|
||||
let pos = mesh.widget.mesh.position;
|
||||
box.min.add(pos);
|
||||
box.max.add(pos);
|
||||
bounds = bounds.union(box);
|
||||
});
|
||||
return bounds;
|
||||
}
|
||||
|
||||
function update_info() {
|
||||
const ui = api.ui;
|
||||
let bounds = new THREE.Box3(), track;
|
||||
|
|
@ -299,19 +317,155 @@ function setDisabled(bool) {
|
|||
api.platform.update_selected();
|
||||
}
|
||||
|
||||
function settings() {
|
||||
return api.conf.get();
|
||||
}
|
||||
|
||||
function input_rotate() {
|
||||
if (selection.meshes().length === 0) {
|
||||
api.show.alert("select object to rotate");
|
||||
return;
|
||||
}
|
||||
api.uc.prompt("Enter X,Y,Z degrees of rotation","").then(coord => {
|
||||
coord = (coord || '').split(',');
|
||||
let prod = Math.PI / 180,
|
||||
x = parseFloat(coord[0] || 0.0) * prod,
|
||||
y = parseFloat(coord[1] || 0.0) * prod,
|
||||
z = parseFloat(coord[2] || 0.0) * prod;
|
||||
selection.rotate(x, y, z);
|
||||
});
|
||||
}
|
||||
|
||||
function input_position() {
|
||||
if (selection.meshes().length === 0) {
|
||||
api.show.alert("select object to position");
|
||||
return;
|
||||
}
|
||||
let current = settings(),
|
||||
{ device, process} = current,
|
||||
center = process.ctOriginCenter || process.camOriginCenter || device.bedRound || device.originCenter,
|
||||
bounds = selection.get_bounds();
|
||||
|
||||
api.uc.prompt("Enter X,Y coordinates for selection","").then(coord => {
|
||||
coord = (coord || '').split(',');
|
||||
let x = parseFloat(coord[0] || 0.0),
|
||||
y = parseFloat(coord[1] || 0.0),
|
||||
z = parseFloat(coord[2] || 0.0);
|
||||
|
||||
if (!center) {
|
||||
x = x - device.bedWidth/2 + (bounds.max.x - bounds.min.x)/2;
|
||||
y = y - device.bedDepth/2 + (bounds.max.y - bounds.min.y)/2
|
||||
}
|
||||
|
||||
selection.move(x, y, z, true);
|
||||
});
|
||||
}
|
||||
|
||||
function input_resize(e, ui) {
|
||||
let dv = parseFloat(e.target.value || 1),
|
||||
pv = parseFloat(e.target.was || 1),
|
||||
ra = dv / pv,
|
||||
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,
|
||||
ta = e.target,
|
||||
xc = ui.lockX.checked,
|
||||
yc = ui.lockY.checked,
|
||||
zc = ui.lockZ.checked,
|
||||
xt = ta === ui.sizeX,
|
||||
yt = ta === ui.sizeY,
|
||||
zt = ta === ui.sizeZ,
|
||||
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);
|
||||
// prevent null scale
|
||||
if (xv * xr < 0.1 || yv * yr < 0.1 || zv * zr < 0.1) {
|
||||
api.alerts.show('invalid scale value');
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
function input_scale(e, ui) {
|
||||
let dv = parseFloat(e.target.value || 1),
|
||||
pv = parseFloat(e.target.was || 1),
|
||||
ra = dv / pv,
|
||||
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,
|
||||
ta = e.target,
|
||||
xc = ui.lockX.checked,
|
||||
yc = ui.lockY.checked,
|
||||
zc = ui.lockZ.checked,
|
||||
xt = ta === ui.scaleX,
|
||||
yt = ta === ui.scaleY,
|
||||
zt = ta === ui.scaleZ,
|
||||
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);
|
||||
// prevent null scale
|
||||
if (xv * xr < 0.1 || yv * yr < 0.1 || zv * zr < 0.1) {
|
||||
api.alerts.show('invalid scale value');
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
function parse_as_float(e) {
|
||||
e.target.value = parseFloat(e.target.value) || 0;
|
||||
}
|
||||
|
||||
function input_binding(ui) {
|
||||
// on enter but not on blur
|
||||
space.event.onEnterKey([
|
||||
ui.scaleX, (e) => input_scale(e, ui),
|
||||
ui.scaleY, (e) => input_scale(e, ui),
|
||||
ui.scaleZ, (e) => input_scale(e, ui),
|
||||
ui.sizeX, (e) => input_resize(e, ui),
|
||||
ui.sizeY, (e) => input_resize(e, ui),
|
||||
ui.sizeZ, (e) => input_resize(e, ui),
|
||||
]);
|
||||
// on enter and blur
|
||||
space.event.onEnterKey([
|
||||
ui.toolName, updateTool,
|
||||
ui.toolNum, updateTool,
|
||||
ui.toolFluteDiam, updateTool,
|
||||
ui.toolFluteLen, updateTool,
|
||||
ui.toolShaftDiam, updateTool,
|
||||
ui.toolShaftLen, updateTool,
|
||||
ui.toolTaperTip, updateTool,
|
||||
ui.toolTaperAngle, updateTool,
|
||||
$('rot_x'), parse_as_float,
|
||||
$('rot_y'), parse_as_float,
|
||||
$('rot_z'), parse_as_float
|
||||
], true);
|
||||
}
|
||||
|
||||
// extend API (api.selection)
|
||||
export const selection = {
|
||||
move,
|
||||
merge,
|
||||
isolateBodies,
|
||||
scale,
|
||||
rotate,
|
||||
mirror,
|
||||
duplicate,
|
||||
for_groups,
|
||||
for_meshes,
|
||||
for_status,
|
||||
for_widgets,
|
||||
get_bounds,
|
||||
input_binding,
|
||||
input_position,
|
||||
input_rotate,
|
||||
isolateBodies,
|
||||
merge,
|
||||
mirror,
|
||||
move,
|
||||
rotate,
|
||||
scale,
|
||||
update_bounds,
|
||||
update_info,
|
||||
widgets,
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { updateTool } from '../mode/cam/tools.js';
|
||||
|
||||
const { selection } = api;
|
||||
|
||||
function settings() {
|
||||
return api.conf.get();
|
||||
}
|
||||
|
||||
function boundsSelection() {
|
||||
// Helper to compute bounds of selected meshes
|
||||
const THREE = self.THREE;
|
||||
let bounds = new THREE.Box3();
|
||||
selection.for_meshes(mesh => {
|
||||
let box = mesh.getBoundingBox().clone();
|
||||
let pos = mesh.widget.mesh.position;
|
||||
box.min.add(pos);
|
||||
box.max.add(pos);
|
||||
bounds = bounds.union(box);
|
||||
});
|
||||
return bounds;
|
||||
}
|
||||
|
||||
function rotateInputSelection() {
|
||||
if (selection.meshes().length === 0) {
|
||||
api.show.alert("select object to rotate");
|
||||
return;
|
||||
}
|
||||
api.uc.prompt("Enter X,Y,Z degrees of rotation","").then(coord => {
|
||||
coord = (coord || '').split(',');
|
||||
let prod = Math.PI / 180,
|
||||
x = parseFloat(coord[0] || 0.0) * prod,
|
||||
y = parseFloat(coord[1] || 0.0) * prod,
|
||||
z = parseFloat(coord[2] || 0.0) * prod;
|
||||
selection.rotate(x, y, z);
|
||||
});
|
||||
}
|
||||
|
||||
function positionSelection() {
|
||||
if (selection.meshes().length === 0) {
|
||||
api.show.alert("select object to position");
|
||||
return;
|
||||
}
|
||||
let current = settings(),
|
||||
{ device, process} = current,
|
||||
center = process.ctOriginCenter || process.camOriginCenter || device.bedRound || device.originCenter,
|
||||
bounds = boundsSelection();
|
||||
|
||||
api.uc.prompt("Enter X,Y coordinates for selection","").then(coord => {
|
||||
coord = (coord || '').split(',');
|
||||
let x = parseFloat(coord[0] || 0.0),
|
||||
y = parseFloat(coord[1] || 0.0),
|
||||
z = parseFloat(coord[2] || 0.0);
|
||||
|
||||
if (!center) {
|
||||
x = x - device.bedWidth/2 + (bounds.max.x - bounds.min.x)/2;
|
||||
y = y - device.bedDepth/2 + (bounds.max.y - bounds.min.y)/2
|
||||
}
|
||||
|
||||
selection.move(x, y, z, true);
|
||||
});
|
||||
}
|
||||
|
||||
function selectionSize(e, ui) {
|
||||
let dv = parseFloat(e.target.value || 1),
|
||||
pv = parseFloat(e.target.was || 1),
|
||||
ra = dv / pv,
|
||||
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,
|
||||
ta = e.target,
|
||||
xc = ui.lockX.checked,
|
||||
yc = ui.lockY.checked,
|
||||
zc = ui.lockZ.checked,
|
||||
xt = ta === ui.sizeX,
|
||||
yt = ta === ui.sizeY,
|
||||
zt = ta === ui.sizeZ,
|
||||
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);
|
||||
// prevent null scale
|
||||
if (xv * xr < 0.1 || yv * yr < 0.1 || zv * zr < 0.1) {
|
||||
api.alerts.show('invalid scale value');
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
function selectionScale(e, ui) {
|
||||
let dv = parseFloat(e.target.value || 1),
|
||||
pv = parseFloat(e.target.was || 1),
|
||||
ra = dv / pv,
|
||||
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,
|
||||
ta = e.target,
|
||||
xc = ui.lockX.checked,
|
||||
yc = ui.lockY.checked,
|
||||
zc = ui.lockZ.checked,
|
||||
xt = ta === ui.scaleX,
|
||||
yt = ta === ui.scaleY,
|
||||
zt = ta === ui.scaleZ,
|
||||
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);
|
||||
// prevent null scale
|
||||
if (xv * xr < 0.1 || yv * yr < 0.1 || zv * zr < 0.1) {
|
||||
api.alerts.show('invalid scale value');
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
function selectionRotate(e) {
|
||||
let val = parseFloat(e.target.value) || 0;
|
||||
e.target.value = val;
|
||||
}
|
||||
|
||||
function setupSelectionBindings(ui) {
|
||||
// on enter but not on blur
|
||||
space.event.onEnterKey([
|
||||
ui.scaleX, (e) => selectionScale(e, ui),
|
||||
ui.scaleY, (e) => selectionScale(e, ui),
|
||||
ui.scaleZ, (e) => selectionScale(e, ui),
|
||||
ui.sizeX, (e) => selectionSize(e, ui),
|
||||
ui.sizeY, (e) => selectionSize(e, ui),
|
||||
ui.sizeZ, (e) => selectionSize(e, ui),
|
||||
]);
|
||||
// on enter and blur
|
||||
space.event.onEnterKey([
|
||||
ui.toolName, updateTool,
|
||||
ui.toolNum, updateTool,
|
||||
ui.toolFluteDiam, updateTool,
|
||||
ui.toolFluteLen, updateTool,
|
||||
ui.toolShaftDiam, updateTool,
|
||||
ui.toolShaftLen, updateTool,
|
||||
ui.toolTaperTip, updateTool,
|
||||
ui.toolTaperAngle, updateTool,
|
||||
$('rot_x'), selectionRotate,
|
||||
$('rot_y'), selectionRotate,
|
||||
$('rot_z'), selectionRotate
|
||||
], true);
|
||||
}
|
||||
|
||||
export const selectionTools = {
|
||||
rotateInputSelection,
|
||||
positionSelection,
|
||||
setupSelectionBindings
|
||||
};
|
||||
|
|
@ -4,7 +4,7 @@ import { $ } from '../../moto/webui.js';
|
|||
import { api } from './api.js';
|
||||
import { consts } from '../core/consts.js';
|
||||
import { platform } from './platform.js';
|
||||
import { selection } from './select.js';
|
||||
import { selection } from './selected.js';
|
||||
import { settings } from './config/manager.js';
|
||||
import STACKS from './stacks.js';
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ import { api } from './api.js';
|
|||
import { local as SDB } from '../../data/local.js';
|
||||
import { openFiles } from './files.js';
|
||||
import { platform } from './platform.js';
|
||||
import { selection } from './select.js';
|
||||
import { selection } from './selected.js';
|
||||
import { settings } from './config/manager.js';
|
||||
import { space as SPACE } from '../../moto/space.js';
|
||||
import { utils } from '../core/utils.js';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { $ } from '../../../moto/webui.js';
|
|||
import { api } from '../../app/api.js';
|
||||
import { conf } from '../../app/config/defaults.js';
|
||||
import { util } from '../../../geo/base.js';
|
||||
import { client } from '../../app/client.js';
|
||||
import { client } from '../../app/workers.js';
|
||||
import { addbox, delbox, getlastbox } from '../../core/boxes.js';
|
||||
import { Layers } from '../../app/layers.js';
|
||||
import { Stack } from '../../app/stack.js';
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import '../../add/class.js';
|
|||
import '../../add/three.js';
|
||||
import { api } from '../app/api.js';
|
||||
import { conf } from '../app/config/defaults.js';
|
||||
import { client } from '../app/client.js';
|
||||
import { client } from '../app/workers.js';
|
||||
import { load } from '../../load/file.js';
|
||||
import { newWidget } from '../core/widget.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
import '../add/array.js';
|
||||
import '../add/class.js';
|
||||
import '../add/three.js';
|
||||
import '../kiri/app/lang.js';
|
||||
import '../kiri/app/language.js';
|
||||
import '../kiri/core/lang-en.js';
|
||||
|
||||
import { api } from '../kiri/app/api.js';
|
||||
import { init_lang } from '../kiri/app/init-lang.js';
|
||||
import { init_one } from '../kiri/app/init-one.js';
|
||||
import { init_two } from '../kiri/app/init-two.js';
|
||||
import { init_input } from '../kiri/app/init-input.js';
|
||||
import { init_sync } from '../kiri/app/init-sync.js';
|
||||
|
||||
let traceload = location.search.indexOf('traceload') > 0;
|
||||
let load = [];
|
||||
|
|
@ -34,8 +34,8 @@ async function checkReady() {
|
|||
{
|
||||
api.client.start();
|
||||
await init_lang();
|
||||
await init_one();
|
||||
await init_two();
|
||||
await init_input();
|
||||
await init_sync();
|
||||
}
|
||||
for (let fn of load) {
|
||||
safeExec(fn);
|
||||
|
|
|
|||
Loading…
Reference in a new issue