add cam origin selector. fix wasm newpoly

This commit is contained in:
Stewart Allen 2025-07-10 16:54:02 -04:00
commit 5532cf28e4
12 changed files with 277 additions and 132 deletions

View file

@ -95,6 +95,7 @@ export function createPopOp(type, map) {
return op.rec === rec;
},
bind: (ev) => {
console.log({ bind: type, map, op });
api.util.ui2rec(op.rec, op.inputs);
const settings = conf.get();

View file

@ -0,0 +1,114 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { api } from '../../core/api.js';
import { env, clearPops } from './client.js';
import { CAM } from './driver-fe.js';
import { config } from '../../../geo/base.js';
import { addbox, delbox } from '../../core/boxes.js';
export let originSelectOn = false;
let { world } = api.SPACE;
let alert, lastHover, lastPoints;
export function originSelect() {
if (originSelectOn) {
return originSelectDone();
}
clearPops();
alert = api.show.alert("analyzing parts...", 1000);
originSelectOn = true;
api.feature.hover = true;
api.feature.hoverAdds = true;
env.hover = pointHover;
env.hoverUp = pointHoverUp;
CAM.traces((ids) => {
api.hide.alert(alert);
alert = api.show.alert("select origin<br>[esc] to cancel", 1000);
let points = {};
let color = new THREE.Color( 0xff0000 );
api.widgets.for(widget => {
let { pos, tzoff } = widget.track;
let { adds, traces } = widget;
let polys = traces.map(trace => {
return trace.fixClosed().clone().move(pos).move({ x:0, y:0, z: -tzoff });
});
for (let poly of polys) {
if (poly.circularity() >= config.hint_min_circ) {
let center = poly.calcCircleCenter();
if (points[center.key]) {
continue;
}
let box = addbox(center, color, center.key, undefined, { opacity: 1 });
adds.push(box);
world.add(box);
box._origin = center;
points[center.key] = { box, center };
}
}
});
lastPoints = Object.values(points);
});
}
export function originSelectDone() {
if (!originSelectOn) {
return;
}
api.hide.alert(alert);
api.feature.hover = false;
api.feature.hoverAdds = false;
api.widgets.for(widget => {
for (let box of widget.adds) {
world.remove(box);
}
widget.adds.length = 0;
});
originSelectOn = false;
}
function pointHover(data) {
if (lastHover) {
let { color, colorSave } = lastHover.material[0] || lastHover.material;
color.r = colorSave.r;
color.g = colorSave.g;
color.b = colorSave.b;
}
lastHover = null;
if (data.type === 'platform') {
return;
}
if (!data.int.object._origin) {
return;
}
lastHover = data.int.object;
let material = lastHover.material[0] || lastHover.material;
let color = material.color;
material.colorSave = color.clone();
color.setHex(0x00ff00);
}
function pointHoverUp(int, ev) {
if (!int?.object?._origin) return;
let { _origin } = int.object;
let { process, stock } = api.conf.get();
let { x, y, z } = _origin;
let { camOriginTop, camOriginCenter } = process;
if (camOriginTop) {
z = z - stock.z;
}
if (!camOriginCenter) {
x += stock.x / 2;
y += stock.y / 2;
}
process.camOriginOffX = x;
process.camOriginOffY = y;
process.camOriginOffZ = z;
api.settings.update_fields();
api.platform.update_origin();
originSelectDone();
}

View file

@ -1,7 +1,7 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { api } from '../../core/api.js';
import { env, clearPops } from './client.js';
import { env, clearPops, isDark } from './client.js';
import { CAM } from './driver-fe.js';
import { Layers } from '../../core/layers.js';
import { Stack } from '../../core/stack.js';
@ -123,7 +123,7 @@ export function traceHover(data) {
let material = lastTrace.material[0] || lastTrace.material;
let color = material.color;
material.colorSave = color.clone();
color.setHex(env.isDark() ? 0x0066ff : 0x0000ff);
color.setHex(isDark() ? 0x0066ff : 0x0000ff);
}
export function traceHoverUp(int, ev) {
@ -157,7 +157,7 @@ export function traceToggle(obj, skip) {
colorSave = material.colorSave = color.clone();
}
if (obj.selected) {
color.setHex(env.isDark() ? 0xdd0011 : 0xff0033);
color.setHex(isDark() ? 0xdd0011 : 0xff0033);
colorSave.r = color.r;
colorSave.g = color.g;
colorSave.b = color.b;

View file

@ -1,6 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { $, h } from '../../../moto/webui.js';
import { $ } from '../../../moto/webui.js';
import { api } from '../../core/api.js';
import { load } from '../../../load/file.js';
import { animate as anim_2d, animate_clear as anim_2d_clear } from './anim-2d-fe.js';
@ -14,13 +14,14 @@ import { tabAdd, tabDone, tabClear, restoreTabs, updateTabs } from './cl-tab.js'
import { traceOn, traceDone, unselectTraces } from './cl-trace.js';
import { holeSelOn, selectHolesDone, clearHolesRec } from './cl-hole.js';
import { surfaceOn, surfaceDone } from './cl-surface.js';
import { originSelectDone } from './cl-origin.js';
const DEG2RAD = Math.PI / 180;
const RAD2DEG = 180 / Math.PI;
const hasSharedArrays = self.SharedArrayBuffer ? true : false;
const { VIEWS, STACKS } = api.const;
const { noop, space } = api;
const { noop } = api;
const { ui: UI, uc: UC } = api;
const { widgets: WIDGETS } = api;
@ -54,10 +55,11 @@ export function isDark() {
export function clearPops() {
if (env.func.unpop) env.func.unpop();
originSelectDone();
selectHolesDone();
surfaceDone();
tabDone();
traceDone();
surfaceDone();
selectHolesDone();
}
function animFn() {

View file

@ -0,0 +1,92 @@
import { api } from '../../core/api.js';
import { originSelect } from './cl-origin.js';
let LANG = api.language.current;
let { CAM } = api.const.MODES,
{ $ } = api.web,
{ uc, ui } = api,
{ bound, toInt, toFloat } = uc,
{ newBlank, newButton, newBoolean, newGroup, newInput } = uc,
{ newSelect, newLabel, newValue, newRow, newGCode, newDiv } = uc,
driven = true,
separator = true,
trigger = true,
units = true
;
function onBooleanClick(el) {
api.event.emit('click.boolean', el);
}
function onButtonClick(el) {
api.event.emit('click.button', el);
}
function zAnchorSave() {
api.conf.update();
api.platform.update_top_z();
}
export function menu() {
return {
_____: newGroup(LANG.ct_menu, $('cam-tabs'), { modes:CAM, marker:true, driven, separator }),
camTabsWidth: newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:toFloat, bound:bound(0.005,100), units}),
camTabsHeight: newInput(LANG.ct_hght_s, {title:LANG.ct_hght_l, convert:toFloat, bound:bound(0.005,100), units}),
camTabsDepth: newInput(LANG.ct_dpth_s, {title:LANG.ct_dpth_l, convert:toFloat, bound:bound(0.005,100), units}),
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>'}))
], {class:"ext-buttons f-row"}),
_____: newGroup(LANG.cs_menu, $('cam-stock'), { modes:CAM, driven, separator }),
camStockX: newInput(LANG.cs_wdth_s, {title:LANG.cs_wdth_l, convert:toFloat, bound:bound(0,9999), units}),
camStockY: newInput(LANG.cs_dpth_s, {title:LANG.cs_dpth_l, convert:toFloat, bound:bound(0,9999), units}),
camStockZ: newInput(LANG.cs_hght_s, {title:LANG.cs_hght_l, convert:toFloat, bound:bound(0,9999), units}),
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}),
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units}),
camZTop: newInput(LANG.ou_ztop_s, {title:LANG.ou_ztop_l, convert:toFloat, units, trigger}),
camZBottom: newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:toFloat, units, trigger}),
camZThru: newInput(LANG.ou_ztru_s, {title:LANG.ou_ztru_l, convert:toFloat, bound:bound(0.0,100), units }),
camZClearance: newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:toFloat, bound:bound(0.01,100), units }),
camFastFeedZ: newInput(LANG.cc_rzpd_s, {title:LANG.cc_rzpd_l, convert:toFloat, units}),
camFastFeed: newInput(LANG.cc_rapd_s, {title:LANG.cc_rapd_l, convert:toFloat, units}),
_____: newGroup(LANG.ou_menu, $('cam-output'), { modes:CAM, driven, separator, group:"cam-output" }),
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}),
separator: newBlank({ class:"set-sep", driven }),
camFirstZMax: newBoolean(LANG.ou_z1st_s, onBooleanClick, {title:LANG.ou_z1st_l}),
camForceZMax: newBoolean(LANG.ou_forz_s, onBooleanClick, {title:LANG.ou_forz_l}),
separator: newBlank({ class:"set-sep", driven }),
camEaseAngle: newInput(LANG.ou_eang_s, {title:LANG.ou_eang_l, convert:toFloat, bound:bound(0.1,85), show:() => ui.camEaseDown.checked}),
camFullEngage: newInput(LANG.ou_feng_s, {title:LANG.ou_feng_l, convert:toFloat, bound:bound(0.1,1.0)}),
_____: newGroup(LANG.co_menu, $('cam-origin'), { modes:CAM, driven, separator }),
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 }),
camOriginOffX: newInput(LANG.co_offx_s, {title:LANG.co_offx_l, convert:toFloat, units}),
camOriginOffY: newInput(LANG.co_offy_s, {title:LANG.co_offy_l, convert:toFloat, units}),
camOriginOffZ: newInput(LANG.co_offz_s, {title:LANG.co_offz_l, convert:toFloat, units}),
separator: newBlank({ class:"set-sep", driven }),
camOriginSelect: newRow([ newButton("select", originSelect)], { class: "ext-buttons f-row" }),
_____: newGroup(LANG.op_xprt_s, $('cam-expert'), { group:"cam_expert", modes:CAM, marker: false, driven, separator }),
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 }),
separator: newBlank({ class:"set-sep", driven }),
camArcTolerance: newInput(LANG.cx_arct_s, {title:LANG.cx_arct_l, convert:toFloat, units, bound:bound(0,100)}),
camArcResolution: newInput(LANG.cx_arcr_s, {title:LANG.cx_arcr_l, convert:toFloat, bound:bound(0,180), show:() => ui.camArcTolerance.value > 0}),
};
};

View file

@ -398,7 +398,7 @@ export function addDogbones(poly, dist, reverse) {
}
};
export async function traces(settings, widget, single) {
export async function traces(settings, widget) {
if (widget.traces) {
return false;
}
@ -534,7 +534,6 @@ export async function holes(settings, widget, individual, rec, onProgress) {
// keeps the z bottom relative to the part when z align changes
zBottom = isIndexed ? camZBottom : camZBottom - zbOff;
let slicerOpts = { flatoff: 0.001 }
let slicer = new cam_slicer(widget, slicerOpts);
let zFlats = Object.keys(slicer.zFlat).map(Number).map(z => [z, z - 0.002]).flat()