grid-apps-cmms/src/kiri/mode/cam/cl-trace.js
2025-11-21 20:12:55 -05:00

181 lines
5.7 KiB
JavaScript

/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { api } from '../../core/api.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';
export let traceOn = false;
export let lastTrace;
export function setLastTrace(trace) {
lastTrace = trace;
}
export function traceAdd(ev) {
if (traceOn) {
return traceDone();
}
clearPops();
alert = api.show.alert("analyzing parts...", 1000);
traceOn = env.hoveredOp;
traceOn.classList.add("editing");
api.feature.hover = true;
api.feature.hoverAdds = true;
env.hover = traceHover;
env.hoverUp = traceHoverUp;
CAM.traces((ids) => {
api.hide.alert(alert);
alert = api.show.alert("[esc] cancels trace editing");
api.widgets.for(widget => {
if (ids.indexOf(widget.id) >= 0) {
unselectTraces(widget, true);
widget.trace_stack = null;
}
if (widget.trace_stack) {
widget.adds.appendAll(widget.trace_stack.meshes);
widget.trace_stack.show();
return;
}
let areas = (env.poppedRec.areas[widget.id] || []);
let stack = new Stack(widget.mesh);
widget.trace_stack = stack;
widget.traces?.forEach(poly => {
let match = areas.filter(arr => poly.matches(arr));
let layers = new Layers();
layers.setLayer("trace", { line: 0xaaaa55, fat: 4, order: -10 }, false).addPoly(poly);
stack.addLayers(layers);
stack.new_meshes.forEach(mesh => {
mesh.trace = { widget, poly };
// ensure trace poly singleton from matches
if (match.length > 0) {
poly._trace = match[0];
} else {
poly._trace = poly.toArray();
}
});
widget.adds.appendAll(stack.new_meshes);
// console.log(widget)
});
});
// ensure appropriate traces are toggled matching current record
api.widgets.for(widget => {
widget.setVisualState({ opacity: 0.25 });
let areas = (env.poppedRec.areas[widget.id] || []);
let stack = widget.trace_stack;
stack.meshes.forEach(mesh => {
let { poly } = mesh.trace;
let match = areas.filter(arr => poly.matches(arr));
if (match.length > 0) {
if (!mesh.selected) {
traceToggle(mesh, true);
}
} else if (mesh.selected) {
traceToggle(mesh, true);
}
});
});
}, env.poppedRec.select === 'lines');
}
export function traceDone() {
if (!traceOn) {
return;
}
env.func.unpop();
traceOn.classList.remove("editing");
traceOn = false;
api.widgets.opacity(1);
api.hide.alert(alert);
api.feature.hover = false;
api.feature.hoverAdds = false;
api.widgets.for(widget => {
widget.restoreVisualState();
if (widget.trace_stack) {
widget.trace_stack.hide();
widget.adds.removeAll(widget.trace_stack.meshes);
}
});
}
export function traceHover(data) {
if (lastTrace) {
let { color, colorSave } = lastTrace.material[0] || lastTrace.material;
color.r = colorSave.r;
color.g = colorSave.g;
color.b = colorSave.b;
}
lastTrace = null;
if (data.type === 'platform') {
return;
}
if (!data.int.object.trace) {
return;
}
lastTrace = data.int.object;
if (lastTrace.selected) {
let event = data.event;
let target = event.target;
let { clientX, clientY } = event;
let { offsetWidth, offsetHeight } = target;
}
let material = lastTrace.material[0] || lastTrace.material;
let color = material.color;
material.colorSave = color.clone();
color.setHex(isDark() ? 0x0066ff : 0x0000ff);
}
export function traceHoverUp(int, ev) {
if (!int) return;
let { object } = int;
traceToggle(object);
if (ev.metaKey || ev.ctrlKey) {
let { selected } = object;
let { widget, poly } = object.trace;
let avgZ = poly.avgZ();
for (let add of widget.adds) {
if (add.trace && add.selected !== selected && add.trace.poly.onZ(avgZ)) {
traceToggle(add);
}
}
}
}
export function traceToggle(obj, skip) {
let material = obj.material[0] || obj.material;
if (!(material && obj.trace)) return;
let { color, colorSave } = material;
let { widget, poly } = obj.trace;
let areas = env.poppedRec.areas;
if (!areas) {
return;
}
let wlist = areas[widget.id] = areas[widget.id] || [];
obj.selected = !obj.selected;
if (!colorSave) {
colorSave = material.colorSave = color.clone();
}
if (obj.selected) {
color.setHex(isDark() ? 0xdd0011 : 0xff0033);
colorSave.r = color.r;
colorSave.g = color.g;
colorSave.b = color.b;
if (!skip) wlist.push(poly._trace);
} else {
color.setHex(0xaaaa55);
colorSave.setHex(0xaaaa55);
if (!skip) wlist.remove(poly._trace);
}
api.conf.save();
}
export function unselectTraces(widget, skip) {
if (widget.trace_stack) {
widget.trace_stack.meshes.forEach(mesh => {
if (mesh.selected) {
traceToggle(mesh, skip);
}
});
}
}