splitting cam client into modules
This commit is contained in:
parent
f4957698c0
commit
37e081ed8e
8 changed files with 1493 additions and 1432 deletions
82
src2/kiri-mode/cam/cl-flip.js
Normal file
82
src2/kiri-mode/cam/cl-flip.js
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { api } from '../../kiri/api.js';
|
||||||
|
import { env } from './client.js';
|
||||||
|
import { CAM } from './driver-fe.js';
|
||||||
|
|
||||||
|
export function opFlip() {
|
||||||
|
api.view.set_arrange();
|
||||||
|
let widgets = api.widgets.all();
|
||||||
|
let { process } = env.current;
|
||||||
|
let { ops, op2 } = process;
|
||||||
|
// add flip singleton to b-side
|
||||||
|
let add2 = op2.length === 0;
|
||||||
|
let axis = env.poppedRec.axis;
|
||||||
|
env.flipping = true;
|
||||||
|
process.camZAnchor = {
|
||||||
|
top: "bottom",
|
||||||
|
bottom: "top",
|
||||||
|
middle: "middle"
|
||||||
|
}[process.camZAnchor];
|
||||||
|
// flip tabs
|
||||||
|
for (let widget of widgets) {
|
||||||
|
let anno = api.widgets.annotate(widget.id).tab || [];
|
||||||
|
let wbm = widget.bounds.max.z;
|
||||||
|
for (let tab of anno) {
|
||||||
|
let box = widget.tabs[tab.id].box;s
|
||||||
|
let bpo = box.position;
|
||||||
|
let xr = 0, yr = 0;
|
||||||
|
let flz = wbm - bpo.z;
|
||||||
|
if (axis === 'X') {
|
||||||
|
tab.pos.y = -tab.pos.y;
|
||||||
|
bpo.y = -bpo.y;
|
||||||
|
xr = Math.PI / 2;
|
||||||
|
}
|
||||||
|
if (axis === 'Y') {
|
||||||
|
tab.pos.x = -tab.pos.x;
|
||||||
|
bpo.x = -bpo.x;
|
||||||
|
yr = Math.PI / 2;
|
||||||
|
}
|
||||||
|
tab.pos.z = bpo.z = flz;
|
||||||
|
let [rx, ry, rz, rw] = tab.rot;
|
||||||
|
let qat = new THREE.Quaternion(rx, ry, rz, rw);
|
||||||
|
let eul = new THREE.Euler().setFromQuaternion(qat);
|
||||||
|
eul._z = -eul._z;
|
||||||
|
tab.rot = new THREE.Quaternion().setFromEuler(eul);
|
||||||
|
}
|
||||||
|
clearTabs(widget, true);
|
||||||
|
restoreTabs([widget]);
|
||||||
|
}
|
||||||
|
// flip widget
|
||||||
|
if (axis === 'X') {
|
||||||
|
api.selection.rotate(Math.PI, 0, 0);
|
||||||
|
}
|
||||||
|
if (axis === 'Y') {
|
||||||
|
api.selection.rotate(0, Math.PI, 0);
|
||||||
|
}
|
||||||
|
// clear traces cache
|
||||||
|
CAM.traces_clear();
|
||||||
|
api.client.clear();
|
||||||
|
env.flipping = false;
|
||||||
|
process.ops = op2;
|
||||||
|
process.op2 = ops;
|
||||||
|
// flip camZBottom
|
||||||
|
if (env.poppedRec.invert && process.camZBottom && env.camZBottom) {
|
||||||
|
const maxZ = env.camZBottom._max.z
|
||||||
|
process.camZBottom = maxZ - process.camZBottom;
|
||||||
|
api.util.rec2ui(process);
|
||||||
|
updateStock();
|
||||||
|
}
|
||||||
|
// keep flip operations in sync
|
||||||
|
for (let op of op2) {
|
||||||
|
if (op.type === 'flip') {
|
||||||
|
op.axis = env.poppedRec.axis;
|
||||||
|
op.invert = env.poppedRec.invert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (add2) {
|
||||||
|
opAdd(env.poppedRec);
|
||||||
|
} else {
|
||||||
|
opRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
216
src2/kiri-mode/cam/cl-hole.js
Normal file
216
src2/kiri-mode/cam/cl-hole.js
Normal file
|
|
@ -0,0 +1,216 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { api } from '../../kiri/api.js';
|
||||||
|
import { env } from './client.js';
|
||||||
|
import { lastTrace, setLastTrace } from './cl-trace.js';
|
||||||
|
|
||||||
|
export let holeSelOn = false, lastSelHoles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client side function to select holes in widgets for CAM operations.
|
||||||
|
* If holes have already been analyzed, they are displayed immediately.
|
||||||
|
* Otherwise, the CAM server is queried and the results are cached.
|
||||||
|
* @param {boolean} individual - select all holes, false to only select
|
||||||
|
* holes of tool diameter.
|
||||||
|
*/
|
||||||
|
export async function selectHoles(individual) {
|
||||||
|
// console.log("client individual selected",individual)
|
||||||
|
if (holeSelOn) {
|
||||||
|
return selectHolesDone();
|
||||||
|
}
|
||||||
|
env.clearPops();
|
||||||
|
let alert = api.show.alert("analyzing parts...");
|
||||||
|
holeSelOn = env.hoveredOp;
|
||||||
|
holeSelOn.classList.add("editing");
|
||||||
|
api.feature.hover = true;
|
||||||
|
api.feature.hoverAdds = true;
|
||||||
|
env.hover = selectHolesHover;
|
||||||
|
env.hoverUp = selectHolesHoverUp;
|
||||||
|
|
||||||
|
const widgets = api.widgets.all()
|
||||||
|
/**
|
||||||
|
* creates a mesh for a hole and adds it to a widget
|
||||||
|
* @param {Object3D} widget - widget to add the hole mesh to
|
||||||
|
* @param {Object} drill - {depth,selected} object of the hole
|
||||||
|
* @returns {Mesh} the created mesh
|
||||||
|
*/
|
||||||
|
function createHoleMesh(widget, drill) {
|
||||||
|
let { depth, selected, diam } = drill
|
||||||
|
let color = selected ? 0xFF0000 : 0x39e366
|
||||||
|
let geo = new THREE.CylinderGeometry(diam / 2, diam / 2, depth, 20);
|
||||||
|
const material = new THREE.MeshPhongMaterial({ color });
|
||||||
|
let mesh = new THREE.Mesh(geo, material);
|
||||||
|
mesh.position.copy(drill)
|
||||||
|
mesh.position.z -= depth / 2
|
||||||
|
mesh.rotation.x = Math.PI / 2
|
||||||
|
drill.widgetID = widget.id
|
||||||
|
drill.meshId = mesh.id; // add pointers to both objects
|
||||||
|
mesh.hole = drill;
|
||||||
|
mesh.parent = widget.mesh;
|
||||||
|
widget.mesh.add(mesh);
|
||||||
|
widget.adds.push(mesh); // for click detection
|
||||||
|
return mesh
|
||||||
|
}
|
||||||
|
let meshesCached = widgets.every(widget => env.poppedRec.drills[widget.id] != undefined)
|
||||||
|
if (individual && meshesCached) {
|
||||||
|
// if any widget already has cached holes
|
||||||
|
// console.log("already has cached holes",env.poppedRec.drills)
|
||||||
|
api.hide.alert(alert);
|
||||||
|
api.widgets.for(widget => {
|
||||||
|
if (widget.adds) {
|
||||||
|
let drills = env.poppedRec.drills[widget.id];
|
||||||
|
let ids = drills.map(hole => hole.meshId);
|
||||||
|
if (false && widget.adds.includes(mesh)) {
|
||||||
|
// mesh in the old code was a dead artifact
|
||||||
|
// so this code branch never actually ran
|
||||||
|
widget.adds.forEach(add => {
|
||||||
|
if (ids.includes(add.id)) {
|
||||||
|
add.visible = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
drills.forEach(drill => {
|
||||||
|
createHoleMesh(widget, drill);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// if no widget has cached holes
|
||||||
|
let alert2 = api.show.alert("");
|
||||||
|
let found = await CAM.holes(
|
||||||
|
individual,
|
||||||
|
env.poppedRec,
|
||||||
|
(progress, msg) => {
|
||||||
|
alert2[0] = msg;
|
||||||
|
api.show.progress(progress, msg);
|
||||||
|
api.alerts.update();
|
||||||
|
},
|
||||||
|
async centers => {
|
||||||
|
api.show.progress(0);
|
||||||
|
if (!Array.isArray(centers)) {
|
||||||
|
console.log("worker returned a malformed drills response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (centers.length === 0) {
|
||||||
|
console.log("no drill holes found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let shadow = centers.some(c => c.shadowed);
|
||||||
|
api.hide.alert(alert2);
|
||||||
|
if (shadow) {
|
||||||
|
alert2 = api.show.alert("Some holes are shadowed by part and are not shown.");
|
||||||
|
}
|
||||||
|
centers = centers ?? [];
|
||||||
|
// list of all hole centers and if they are selected
|
||||||
|
api.widgets.for(widget => {
|
||||||
|
const { holes } = centers.find(center => center.id == widget.id);
|
||||||
|
// console.log(holes)
|
||||||
|
if (!holes.length) unselectHoles(holes);
|
||||||
|
holes.forEach(hole => {
|
||||||
|
createHoleMesh(widget, hole);
|
||||||
|
});
|
||||||
|
//add hole data to record
|
||||||
|
env.poppedRec.drills = env.poppedRec.drills ?? {};
|
||||||
|
env.poppedRec.drills[widget.id] = holes;
|
||||||
|
//give widget access to an array of drill records that refrence it
|
||||||
|
//so that it can be cleared when widget is rotated or mirrored etc.
|
||||||
|
if (!widget.drills) { widget.drills = [] };
|
||||||
|
widget.drills.push(holes);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!found || found.length === 0) {
|
||||||
|
api.hide.alert(alert);
|
||||||
|
api.hide.alert(alert2);
|
||||||
|
api.show.alert("no drill holes found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//hide the alert once hole meshes are calculated on the worker, and then added to the scene
|
||||||
|
// api.hide.alert(alert);
|
||||||
|
let escAlert = api.show.alert("[esc] cancels drill editing", 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
api.hide.alert(escAlert);
|
||||||
|
}, 5000);
|
||||||
|
api.widgets.opacity(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectHolesHover(data) {
|
||||||
|
//not used right now. may be useful in the future
|
||||||
|
if (lastTrace) {
|
||||||
|
let { color, colorSave } = lastTrace.material[0] || lastTrace.material;
|
||||||
|
color.r = colorSave.r;
|
||||||
|
color.g = colorSave.g;
|
||||||
|
color.b = colorSave.b;
|
||||||
|
lastTrace.position.z -= 0.01;
|
||||||
|
}
|
||||||
|
if (data.type === 'platform') {
|
||||||
|
setLastTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectHolesHoverUp(int, ev) {
|
||||||
|
if (!int) return; //if not a hole mesh return
|
||||||
|
let { object } = int;
|
||||||
|
selectHoleToggle(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the selection of a hole mesh and update its color
|
||||||
|
* @param {Object3D} mesh - the hole mesh to toggle
|
||||||
|
*/
|
||||||
|
export function selectHoleToggle(mesh) {
|
||||||
|
let { hole } = mesh
|
||||||
|
if (!hole) return
|
||||||
|
hole.selected = !hole.selected;
|
||||||
|
mesh.material.color.setHex(hole.selected ? 0xFF0000 : 0x39e366);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the recorded holes in the widget (widget.drills array)
|
||||||
|
* and also clears the widget.adds array.
|
||||||
|
* @param {Object} widget - the widget with the drills array to clear
|
||||||
|
*/
|
||||||
|
export function clearHolesRec(widget) {
|
||||||
|
if (widget.drills) {
|
||||||
|
widget.drills.forEach(rec => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (widget.adds) {
|
||||||
|
widget.adds.length = 0 //clear adds array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup function for selectHoles.
|
||||||
|
* Removes all adds from the scene, hides the alert, and resets the opacity of the widgets.
|
||||||
|
* Also resets the hover features and the editing class on the holeSelOn html element.
|
||||||
|
*/
|
||||||
|
export function selectHolesDone() {
|
||||||
|
if (!holeSelOn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
env.func.unpop();
|
||||||
|
holeSelOn.classList.remove("editing");
|
||||||
|
holeSelOn = false;
|
||||||
|
api.widgets.opacity(1);
|
||||||
|
api.hide.alert(alert);
|
||||||
|
api.feature.hover = false;
|
||||||
|
api.feature.hoverAdds = false;
|
||||||
|
|
||||||
|
api.widgets.for(widget => {
|
||||||
|
for (let add of widget.adds) {
|
||||||
|
add.visible = false
|
||||||
|
widget.mesh.remove(add);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unselectHoles(widget) {
|
||||||
|
if (!widget.holes) return
|
||||||
|
widget.holes.forEach(hole => {
|
||||||
|
hole.selected = false
|
||||||
|
})
|
||||||
|
}
|
||||||
598
src2/kiri-mode/cam/cl-ops.js
Normal file
598
src2/kiri-mode/cam/cl-ops.js
Normal file
|
|
@ -0,0 +1,598 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { $, h } from '../../moto/webui.js';
|
||||||
|
import { api } from '../../kiri/api.js';
|
||||||
|
import { env } from './client.js';
|
||||||
|
import { Tool } from './tool.js';
|
||||||
|
import { opFlip } from './cl-flip.js';
|
||||||
|
import { selectHoles } from './cl-hole.js';
|
||||||
|
import { surfaceAdd } from './cl-surface.js';
|
||||||
|
import { traceAdd } from './cl-trace.js';
|
||||||
|
|
||||||
|
const { MODES } = api.const;
|
||||||
|
const { uc: UC } = api;
|
||||||
|
const { alerts, conf } = api;
|
||||||
|
const { current: LANG } = api.language;
|
||||||
|
|
||||||
|
let seed = Date.now();
|
||||||
|
|
||||||
|
function hasIndexing() {
|
||||||
|
return env.isIndexed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasSpindle() {
|
||||||
|
return env.current.device.spindleMax > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function zTop() {
|
||||||
|
return api.conf.get().process.camZTop > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function zBottom() {
|
||||||
|
return api.conf.get().process.camZBottom > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create custom gcode editor function
|
||||||
|
function gcodeEditor(label, field) {
|
||||||
|
return function () {
|
||||||
|
opGCode(label, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function opGCode(label, field = 'gcode') {
|
||||||
|
api.dialog.show('any');
|
||||||
|
const { c_gcode } = h.bind(
|
||||||
|
$('mod-any'), h.div({ id: "camop_dialog" }, [
|
||||||
|
h.label(label || 'custom gcode operation'),
|
||||||
|
h.textarea({ id: "c_gcode", rows: 15, cols: 50 }),
|
||||||
|
h.button({
|
||||||
|
_: 'done', onclick: () => {
|
||||||
|
api.dialog.hide();
|
||||||
|
api.conf.save();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
])
|
||||||
|
);
|
||||||
|
let av = env.poppedRec[field] || [];
|
||||||
|
c_gcode.value = typeof (av) === 'string' ? av : av.join('\n');
|
||||||
|
c_gcode.onkeyup = (el) => {
|
||||||
|
env.poppedRec[field] = c_gcode.value.trim().split('\n');
|
||||||
|
};
|
||||||
|
c_gcode.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new popup operation (popOp) for a given type.
|
||||||
|
* @param {string} type - the name of the popOp to create
|
||||||
|
* @param {object} map - an object mapping popOp keys to either a string
|
||||||
|
* (representing a key in current.process) or a value (to be used as the default).
|
||||||
|
* @returns {object} the newly created popOp.
|
||||||
|
*/
|
||||||
|
export function createPopOp(type, map) {
|
||||||
|
let op = env.popOp[type] = {
|
||||||
|
div: UC.newElement('div', { id: `${type}-op`, class: "cam-pop-op" }),
|
||||||
|
use: (rec) => {
|
||||||
|
op.rec = rec;
|
||||||
|
for (let [key, val] of Object.entries(op.inputs)) {
|
||||||
|
let type = val.type;
|
||||||
|
let from = map[key];
|
||||||
|
let rval = rec[key];
|
||||||
|
// fill undef entries older defines
|
||||||
|
if (type && (rval === null || rval === undefined)) {
|
||||||
|
if (typeof (from) === 'string') {
|
||||||
|
rec[key] = env.current.process[from];
|
||||||
|
} else if (from !== undefined) {
|
||||||
|
rec[key] = from;
|
||||||
|
} else {
|
||||||
|
console.log('error', { key, val, type, from });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
api.util.rec2ui(rec, op.inputs);
|
||||||
|
op.hideshow();
|
||||||
|
},
|
||||||
|
using: (rec) => {
|
||||||
|
return op.rec === rec;
|
||||||
|
},
|
||||||
|
bind: (ev) => {
|
||||||
|
api.util.ui2rec(op.rec, op.inputs);
|
||||||
|
|
||||||
|
const settings = conf.get();
|
||||||
|
const { tool } = new Tool(settings, op.rec.tool); //get tool by id
|
||||||
|
const opType = op.rec.type
|
||||||
|
const drillOrRegister = opType == "drill" || opType == "register"
|
||||||
|
|
||||||
|
if (!drillOrRegister && tool.type == "drill") {
|
||||||
|
alerts.show(`Warning: Drills should not be used for ${opType} operations.`)
|
||||||
|
}
|
||||||
|
else if (drillOrRegister && tool.type != "drill") {
|
||||||
|
alerts.show(`Warning: Only drills should be used for drilling operations.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let [key, val] of Object.entries(op.rec)) {
|
||||||
|
let saveTo = map[key];
|
||||||
|
if (saveTo && typeof (key) === 'string' && !key.startsWith("~")) {
|
||||||
|
env.current.process[saveTo] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
api.conf.save();
|
||||||
|
op.hideshow();
|
||||||
|
},
|
||||||
|
new: () => {
|
||||||
|
let rec = { type };
|
||||||
|
for (let [key, src] of Object.entries(map)) {
|
||||||
|
rec[key] = typeof (src) === 'string'
|
||||||
|
? env.current.process[src.replace('~', '')]
|
||||||
|
: src;
|
||||||
|
}
|
||||||
|
return rec;
|
||||||
|
},
|
||||||
|
hideshow: () => {
|
||||||
|
for (let inp of Object.values(op.inputs)) {
|
||||||
|
let parent = inp.parentElement;
|
||||||
|
if (parent && parent.setVisible && parent.__opt.show) {
|
||||||
|
parent.setVisible(parent.__opt.show(op, api.conf.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addNote: () => {
|
||||||
|
if (!op.note && type !== 'flip') {
|
||||||
|
const divid = `div-${++seed}`;
|
||||||
|
const noteid = `note-${++seed}`;
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.setAttribute('id', divid);
|
||||||
|
div.classList.add('pop-tics')
|
||||||
|
op.div.appendChild(div);
|
||||||
|
div.innerHTML = h.build(
|
||||||
|
h.div([h.label({ id: noteid })])
|
||||||
|
);
|
||||||
|
op.note = { divid, noteid };
|
||||||
|
}
|
||||||
|
if (op.note) {
|
||||||
|
const { divid, noteid } = op.note;
|
||||||
|
const div = $(divid);
|
||||||
|
if (div) div.onclick = () => {
|
||||||
|
api.uc.prompt('Edit Note for Operation', env.poppedRec.note || '').then(note => {
|
||||||
|
if (note !== undefined && note !== null) {
|
||||||
|
env.poppedRec.note = op.x = note;
|
||||||
|
api.conf.save();
|
||||||
|
}
|
||||||
|
opRender();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const note = $(noteid);
|
||||||
|
if (note) note.innerText = env.poppedRec.note || '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
group: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function createRecordGetter
|
||||||
|
* @description Creates a getter function for the current record.
|
||||||
|
* The getter will bind the current record to the op before returning it.
|
||||||
|
* This is useful for passing a record to a pre-slice function
|
||||||
|
* @returns {function} A getter function for the current record.
|
||||||
|
*/
|
||||||
|
op.createRecordGetter = () => {
|
||||||
|
return () => {
|
||||||
|
op.bind();
|
||||||
|
return op.rec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UC.restore({
|
||||||
|
addTo: op.div,
|
||||||
|
bindTo: op.bind,
|
||||||
|
lastDiv: op.div,
|
||||||
|
lastGroup: op.group
|
||||||
|
});
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createPopOps() {
|
||||||
|
createPopOp('level', {
|
||||||
|
tool: 'camLevelTool',
|
||||||
|
spindle: 'camLevelSpindle',
|
||||||
|
step: 'camLevelOver',
|
||||||
|
rate: 'camLevelSpeed',
|
||||||
|
down: 'camLevelDown',
|
||||||
|
over: 'camLevelOver',
|
||||||
|
stock: 'camLevelStock'
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0) }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
down: UC.newInput(LANG.cc_loff_s, { title: LANG.cc_loff_l, convert: UC.toFloat, units: true }),
|
||||||
|
over: UC.newInput(LANG.cc_lxyo_s, { title: LANG.cc_lxyo_l, convert: UC.toFloat, units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
stock: UC.newBoolean(LANG.cc_lsto_s, undefined, { title: LANG.cc_lsto_l }),
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('rough', {
|
||||||
|
tool: 'camRoughTool',
|
||||||
|
spindle: 'camRoughSpindle',
|
||||||
|
down: 'camRoughDown',
|
||||||
|
step: 'camRoughOver',
|
||||||
|
rate: 'camRoughSpeed',
|
||||||
|
plunge: 'camRoughPlunge',
|
||||||
|
leave: 'camRoughStock',
|
||||||
|
leavez: 'camRoughStockZ',
|
||||||
|
all: 'camRoughAll',
|
||||||
|
voids: 'camRoughVoid',
|
||||||
|
flats: 'camRoughFlat',
|
||||||
|
inside: 'camRoughIn',
|
||||||
|
ov_topz: 0,
|
||||||
|
ov_botz: 0,
|
||||||
|
ov_conv: '~camConventional',
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0) }),
|
||||||
|
leave: UC.newInput(LANG.cr_lsto_s, { title: LANG.cr_lsto_l, convert: UC.toFloat, units: true }),
|
||||||
|
leavez: UC.newInput(LANG.cr_lstz_s, { title: LANG.cr_lstz_l, convert: UC.toFloat, bound: UC.bound(0, 10), units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
all: UC.newBoolean(LANG.cr_clst_s, undefined, { title: LANG.cr_clst_l, show: hasIndexing }),
|
||||||
|
voids: UC.newBoolean(LANG.cr_clrp_s, undefined, { title: LANG.cr_clrp_l }),
|
||||||
|
flats: UC.newBoolean(LANG.cr_clrf_s, undefined, { title: LANG.cr_clrf_l }),
|
||||||
|
inside: UC.newBoolean(LANG.cr_olin_s, undefined, { title: LANG.cr_olin_l }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
exp: UC.newExpand("overrides"),
|
||||||
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
|
exp_end: UC.endExpand(),
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('outline', {
|
||||||
|
tool: 'camOutlineTool',
|
||||||
|
spindle: 'camOutlineSpindle',
|
||||||
|
step: 'camOutlineOver',
|
||||||
|
steps: 'camOutlineOverCount',
|
||||||
|
down: 'camOutlineDown',
|
||||||
|
rate: 'camOutlineSpeed',
|
||||||
|
plunge: 'camOutlinePlunge',
|
||||||
|
dogbones: 'camOutlineDogbone',
|
||||||
|
omitvoid: 'camOutlineOmitVoid',
|
||||||
|
omitthru: 'camOutlineOmitThru',
|
||||||
|
outside: 'camOutlineOut',
|
||||||
|
inside: 'camOutlineIn',
|
||||||
|
wide: 'camOutlineWide',
|
||||||
|
top: 'camOutlineTop',
|
||||||
|
ov_topz: 0,
|
||||||
|
ov_botz: 0,
|
||||||
|
ov_conv: '~camConventional',
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0), show: () => env.popOp.outline.rec.wide }),
|
||||||
|
steps: UC.newInput(LANG.cc_sovc_s, { title: LANG.cc_sovc_l, convert: UC.toInt, bound: UC.bound(1, 5), show: () => env.popOp.outline.rec.wide }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
top: UC.newBoolean(LANG.co_clrt_s, undefined, { title: LANG.co_clrt_l }),
|
||||||
|
inside: UC.newBoolean(LANG.co_olin_s, undefined, { title: LANG.co_olin_l, show: (op) => { return !op.inputs.outside.checked } }),
|
||||||
|
outside: UC.newBoolean(LANG.co_olot_s, undefined, { title: LANG.co_olot_l, show: (op) => { return !op.inputs.inside.checked } }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
omitthru: UC.newBoolean(LANG.co_omit_s, undefined, { title: LANG.co_omit_l, xshow: (op) => { return op.inputs.outside.checked } }),
|
||||||
|
omitvoid: UC.newBoolean(LANG.co_omvd_s, undefined, { title: LANG.co_omvd_l, xshow: (op) => { return op.inputs.outside.checked } }),
|
||||||
|
wide: UC.newBoolean(LANG.co_wide_s, undefined, { title: LANG.co_wide_l, show: (op) => { return !op.inputs.inside.checked } }),
|
||||||
|
dogbones: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: (op) => { return !op.inputs.wide.checked } }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
exp: UC.newExpand("overrides"),
|
||||||
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
|
exp_end: UC.endExpand(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const contourFilter = gcodeEditor('Layer Filter', 'filter');
|
||||||
|
|
||||||
|
createPopOp('contour', {
|
||||||
|
tool: 'camContourTool',
|
||||||
|
spindle: 'camContourSpindle',
|
||||||
|
step: 'camContourOver',
|
||||||
|
rate: 'camContourSpeed',
|
||||||
|
angle: 'camContourAngle',
|
||||||
|
leave: 'camContourLeave',
|
||||||
|
tolerance: 'camTolerance',
|
||||||
|
flatness: 'camFlatness',
|
||||||
|
reduction: 'camContourReduce',
|
||||||
|
bridging: 'camContourBridge',
|
||||||
|
bottom: 'camContourBottom',
|
||||||
|
curves: 'camContourCurves',
|
||||||
|
inside: 'camContourIn',
|
||||||
|
filter: 'camContourFilter',
|
||||||
|
axis: 'X'
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
axis: UC.newSelect(LANG.cd_axis, {}, "xyaxis"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 10.0) }),
|
||||||
|
leave: UC.newInput(LANG.cf_leav_s, { title: LANG.cf_leav_l, convert: UC.toFloat, bound: UC.bound(0, 100) }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
angle: UC.newInput(LANG.cf_angl_s, { title: LANG.cf_angl_l, convert: UC.toFloat, bound: UC.bound(45, 90), show: (op) => op.inputs.curves.checked }),
|
||||||
|
flatness: UC.newInput(LANG.ou_flat_s, { title: LANG.ou_flat_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), units: false, round: 4 }),
|
||||||
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: UC.toFloat, bound: UC.bound(0, 10.0), units: true, round: 4 }),
|
||||||
|
reduction: UC.newInput(LANG.ou_redu_s, { title: LANG.ou_redu_l, convert: UC.toInt, bound: UC.bound(0, 10), units: false }),
|
||||||
|
// bridging: UC.newInput(LANG.ou_brdg_s, {title:LANG.ou_brdg_l, convert:UC.toFloat, bound:UC.bound(0,1000.0), units:true, round:4, show:(op) => op.inputs.curves.checked}),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
curves: UC.newBoolean(LANG.cf_curv_s, undefined, { title: LANG.cf_curv_l }),
|
||||||
|
inside: UC.newBoolean(LANG.cf_olin_s, undefined, { title: LANG.cf_olin_l }),
|
||||||
|
bottom: UC.newBoolean(LANG.cf_botm_s, undefined, { title: LANG.cf_botm_l, show: (op, conf) => conf ? conf.process.camZBottom : 0 }),
|
||||||
|
filter: UC.newRow([UC.newButton(LANG.filter, contourFilter)], { class: "ext-buttons f-row" })
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('lathe', {
|
||||||
|
tool: 'camLatheTool',
|
||||||
|
spindle: 'camLatheSpindle',
|
||||||
|
step: 'camLatheOver',
|
||||||
|
angle: 'camLatheAngle',
|
||||||
|
rate: 'camLatheSpeed',
|
||||||
|
tolerance: 'camTolerance',
|
||||||
|
filter: 'camContourFilter',
|
||||||
|
leave: 'camContourLeave',
|
||||||
|
linear: 'camLatheLinear'
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
// axis: UC.newSelect(LANG.cd_axis, {}, "xyaxis"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 100.0) }),
|
||||||
|
angle: UC.newInput(LANG.cc_sang_s, { title: LANG.cc_sang_l, convert: UC.toFloat, bound: UC.bound(0.01, 180.0) }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: UC.toFloat, bound: UC.bound(0, 10.0), units: true, round: 4 }),
|
||||||
|
leave: UC.newInput(LANG.cf_leav_s, { title: LANG.cf_leav_l, convert: UC.toFloat, bound: UC.bound(0, 100) }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
linear: UC.newBoolean(LANG.ci_line_s, undefined, { title: LANG.ci_line_l }),
|
||||||
|
// filter: UC.newRow([ UC.newButton(LANG.filter, contourFilter) ], {class:"ext-buttons f-row"})
|
||||||
|
};
|
||||||
|
|
||||||
|
function canDogBones() {
|
||||||
|
if (!env.poppedRec) return false;
|
||||||
|
return env.poppedRec.mode === 'follow';// && env.poppedRec.offset && env.poppedRec.offset !== 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function canDogBonesRev() {
|
||||||
|
return canDogBones() && env.poppedRec.dogbone;
|
||||||
|
}
|
||||||
|
|
||||||
|
function zDogSep() {
|
||||||
|
return canDogBones() || zBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
createPopOp('trace', {
|
||||||
|
mode: 'camTraceType',
|
||||||
|
offset: 'camTraceOffset',
|
||||||
|
spindle: 'camTraceSpindle',
|
||||||
|
tool: 'camTraceTool',
|
||||||
|
step: 'camTraceOver',
|
||||||
|
down: 'camTraceDown',
|
||||||
|
thru: 'camTraceThru',
|
||||||
|
rate: 'camTraceSpeed',
|
||||||
|
plunge: 'camTracePlunge',
|
||||||
|
offover: 'camTraceOffOver',
|
||||||
|
dogbone: 'camTraceDogbone',
|
||||||
|
revbone: 'camTraceDogbone',
|
||||||
|
merge: 'camTraceMerge',
|
||||||
|
ov_topz: 0,
|
||||||
|
ov_botz: 0,
|
||||||
|
ov_conv: '~camConventional',
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
mode: UC.newSelect(LANG.cu_type_s, { title: LANG.cu_type_l }, "trace"),
|
||||||
|
offset: UC.newSelect(LANG.cc_offs_s, { title: LANG.cc_offs_l, show: () => (env.poppedRec.mode === 'follow') }, "traceoff"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0), show: (op) => env.popOp.trace.rec.mode === "clear" }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
||||||
|
thru: UC.newInput(LANG.cc_thru_s, { title: LANG.cc_thru_l, convert: UC.toFloat, units: true }),
|
||||||
|
offover: UC.newInput(LANG.cc_offd_s, { title: LANG.cc_offd_l, convert: UC.toFloat, units: true, show: () => env.poppedRec.offset !== "none" || env.poppedRec.mode === "clear" }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep", modes: MODES.CAM, xshow: zDogSep }),
|
||||||
|
merge: UC.newBoolean(LANG.co_merg_s, undefined, { title: LANG.co_merg_l, show: () => !env.popOp.trace.rec.down }),
|
||||||
|
dogbone: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: canDogBones }),
|
||||||
|
revbone: UC.newBoolean(LANG.co_dogr_s, undefined, { title: LANG.co_dogr_l, show: canDogBonesRev }),
|
||||||
|
exp: UC.newExpand("overrides"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
|
exp_end: UC.endExpand(),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
menu: UC.newRow([UC.newButton("select", traceAdd)], { class: "ext-buttons f-row" }),
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('pocket', {
|
||||||
|
spindle: 'camPocketSpindle',
|
||||||
|
tool: 'camPocketTool',
|
||||||
|
step: 'camPocketOver',
|
||||||
|
down: 'camPocketDown',
|
||||||
|
rate: 'camPocketSpeed',
|
||||||
|
plunge: 'camPocketPlunge',
|
||||||
|
expand: 'camPocketExpand',
|
||||||
|
smooth: 'camPocketSmooth',
|
||||||
|
refine: 'camPocketRefine',
|
||||||
|
follow: 'camPocketFollow',
|
||||||
|
contour: 'camPocketContour',
|
||||||
|
engrave: 'camPocketEngrave',
|
||||||
|
outline: 'camPocketOutline',
|
||||||
|
ov_topz: 0,
|
||||||
|
ov_botz: 0,
|
||||||
|
ov_conv: '~camConventional',
|
||||||
|
tolerance: 'camTolerance',
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true }),
|
||||||
|
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0) }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.contour }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
expand: UC.newInput(LANG.cp_xpnd_s, { title: LANG.cp_xpnd_l, convert: UC.toFloat, units: true, xshow: () => !env.poppedRec.contour }),
|
||||||
|
refine: UC.newInput(LANG.cp_refi_s, { title: LANG.cp_refi_l, convert: UC.toInt, show: () => env.poppedRec.contour }),
|
||||||
|
smooth: UC.newInput(LANG.cp_smoo_s, { title: LANG.cp_smoo_l, convert: UC.toInt }),
|
||||||
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: UC.toFloat, bound: UC.bound(0, 10.0), units: true, round: 4, show: () => env.poppedRec.contour }),
|
||||||
|
follow: UC.newInput(LANG.cp_foll_s, { title: LANG.cp_foll_l, convert: UC.toFloat }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
contour: UC.newBoolean(LANG.cp_cont_s, undefined, { title: LANG.cp_cont_s }),
|
||||||
|
engrave: UC.newBoolean(LANG.cp_engr_s, undefined, { title: LANG.cp_engr_l, show: () => env.poppedRec.contour }),
|
||||||
|
outline: UC.newBoolean(LANG.cp_outl_s, undefined, { title: LANG.cp_outl_l }),
|
||||||
|
exp: UC.newExpand("overrides"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
||||||
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
|
exp_end: UC.endExpand(),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
menu: UC.newRow([UC.newButton("select", surfaceAdd)], { class: "ext-buttons f-row" }),
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('drill', {
|
||||||
|
tool: 'camDrillTool',
|
||||||
|
spindle: 'camDrillSpindle',
|
||||||
|
down: 'camDrillDown',
|
||||||
|
rate: 'camDrillDownSpeed',
|
||||||
|
dwell: 'camDrillDwell',
|
||||||
|
lift: 'camDrillLift',
|
||||||
|
mark: 'camDrillMark',
|
||||||
|
precision: 'camDrillPrecision',
|
||||||
|
thru: 'camDrillThru',
|
||||||
|
fromTop: 'camDrillFromStockTop',
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
||||||
|
dwell: UC.newInput(LANG.cd_dwll_s, { title: LANG.cd_dwll_l, convert: UC.toFloat }),
|
||||||
|
lift: UC.newInput(LANG.cd_lift_s, { title: LANG.cd_lift_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.mark }),
|
||||||
|
mark: UC.newBoolean(LANG.cd_mark_s, undefined, { title: LANG.cd_mark_l, show: () => !env.poppedRec.fromTop }),
|
||||||
|
fromTop: UC.newBoolean(LANG.cd_ftop_s, undefined, { title: LANG.cd_ftop_l, show: () => !env.poppedRec.mark }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
thru: UC.newInput(LANG.cd_dtru_s, { title: LANG.cd_dtru_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.mark }),
|
||||||
|
precision: UC.newInput(LANG.cd_prcn_s, { title: LANG.cd_prcn_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.mark }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep", }),
|
||||||
|
actions: UC.newRow([
|
||||||
|
UC.newButton(LANG.select, () => selectHoles(true), { title: LANG.cd_seli_l }),
|
||||||
|
UC.newButton(LANG.cd_sela_s, () => selectHoles(false), { title: LANG.cd_sela_l })
|
||||||
|
], { class: "ext-buttons f-col" })
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('register', {
|
||||||
|
tool: 'camDrillTool',
|
||||||
|
spindle: 'camDrillSpindle',
|
||||||
|
down: 'camDrillDown',
|
||||||
|
rate: 'camDrillDownSpeed',
|
||||||
|
dwell: 'camDrillDwell',
|
||||||
|
lift: 'camDrillLift',
|
||||||
|
feed: 'camRegisterSpeed',
|
||||||
|
thru: 'camRegisterThru'
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
axis: UC.newSelect(LANG.cd_axis, {}, "regaxis"),
|
||||||
|
points: UC.newSelect(LANG.cd_points, { show: () => env.poppedRec.axis !== '-' }, "regpoints"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
||||||
|
feed: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: UC.toInt, units: true, show: () => env.poppedRec.axis === '-' }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
||||||
|
dwell: UC.newInput(LANG.cd_dwll_s, { title: LANG.cd_dwll_l, convert: UC.toFloat, show: () => env.poppedRec.axis !== '-' }),
|
||||||
|
lift: UC.newInput(LANG.cd_lift_s, { title: LANG.cd_lift_l, convert: UC.toFloat, units: true, show: () => env.poppedRec.axis !== '-' }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
thru: UC.newInput(LANG.cd_thru_s, { title: LANG.cd_thru_l, convert: UC.toFloat, units: true }),
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('flip', {
|
||||||
|
axis: 'camFlipAxis',
|
||||||
|
invert: 'camFlipInvert'
|
||||||
|
}).inputs = {
|
||||||
|
axis: UC.newSelect(LANG.cd_axis, {}, "regaxis"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep", modes: MODES.CAM, show: zBottom }),
|
||||||
|
invert: UC.newBoolean(LANG.cf_nvrt_s, undefined, { title: LANG.cf_nvrt_l, show: zBottom }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
action: UC.newRow([UC.newButton(LANG.cf_menu, opFlip)], { class: "ext-buttons f-row" })
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('gcode', {
|
||||||
|
gcode: 'camCustomGcode',
|
||||||
|
}).inputs = {
|
||||||
|
action: UC.newRow([UC.newButton(LANG.edit, gcodeEditor())], { class: "ext-buttons f-row" })
|
||||||
|
};
|
||||||
|
|
||||||
|
function angleTowardZUp() {
|
||||||
|
api.event.emit('tool.mesh.face-up');
|
||||||
|
}
|
||||||
|
|
||||||
|
createPopOp('index', {
|
||||||
|
degrees: 'camIndexAxis',
|
||||||
|
absolute: 'camIndexAbs'
|
||||||
|
}).inputs = {
|
||||||
|
degrees: UC.newInput(LANG.ci_degr_s, { title: LANG.ci_degr_l, convert: UC.toFloat, bound: UC.bound(-360, 360.0) }),
|
||||||
|
absolute: UC.newBoolean(LANG.ci_abso_s, undefined, { title: LANG.ci_abso_l }),
|
||||||
|
select: UC.newRow([UC.newButton(LANG.ci_face_s, angleTowardZUp)], { class: "ext-buttons f-row" })
|
||||||
|
};
|
||||||
|
|
||||||
|
const editEnable = gcodeEditor('Laser Enable Script', 'enable');
|
||||||
|
const editOn = gcodeEditor('Laser On Script', 'on');
|
||||||
|
const editOff = gcodeEditor('Laser Off Script', 'off');
|
||||||
|
|
||||||
|
createPopOp('laser on', {
|
||||||
|
enable: 'camLaserEnable',
|
||||||
|
on: 'camLaserOn',
|
||||||
|
off: 'camLaserOff',
|
||||||
|
power: 'camLaserPower',
|
||||||
|
adapt: 'camLaserAdaptive',
|
||||||
|
adaptrp: 'camLaserAdaptMod',
|
||||||
|
flat: 'camLaserFlatten',
|
||||||
|
flatz: 'camLaserFlatZ',
|
||||||
|
minp: 'camLaserPowerMin',
|
||||||
|
maxp: 'camLaserPowerMax',
|
||||||
|
minz: 'camLaserZMin',
|
||||||
|
maxz: 'camLaserZMax',
|
||||||
|
}).inputs = {
|
||||||
|
enable: UC.newRow([UC.newButton(LANG.enable, editEnable)], { class: "ext-buttons f-row" }),
|
||||||
|
on: UC.newRow([UC.newButton(LANG.on, editOn)], { class: "ext-buttons f-row" }),
|
||||||
|
off: UC.newRow([UC.newButton(LANG.off, editOff)], { class: "ext-buttons f-row" }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
power: UC.newInput(LANG.cl_powr_s, { title: LANG.cl_powr_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), show: () => !env.poppedRec.adapt }),
|
||||||
|
maxp: UC.newInput(LANG.cl_maxp_s, { title: LANG.cl_maxp_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), show: () => env.poppedRec.adapt }),
|
||||||
|
minp: UC.newInput(LANG.cl_minp_s, { title: LANG.cl_minp_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), show: () => env.poppedRec.adapt }),
|
||||||
|
maxz: UC.newInput(LANG.cl_maxz_s, { title: LANG.cl_maxz_l, convert: UC.toFloat, show: () => env.poppedRec.adapt }),
|
||||||
|
minz: UC.newInput(LANG.cl_minz_s, { title: LANG.cl_minz_l, convert: UC.toFloat, show: () => env.poppedRec.adapt }),
|
||||||
|
flatz: UC.newInput(LANG.cl_flaz_s, { title: LANG.cl_flaz_l, convert: UC.toFloat, show: () => env.poppedRec.flat }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
adapt: UC.newBoolean(LANG.cl_adap_s, undefined, { title: LANG.cl_adap_l }),
|
||||||
|
adaptrp: UC.newBoolean(LANG.cl_adrp_s, undefined, { title: LANG.cl_adrp_l, show: () => env.poppedRec.adapt }),
|
||||||
|
flat: UC.newBoolean(LANG.cl_flat_s, undefined, { title: LANG.cl_flat_l }),
|
||||||
|
};
|
||||||
|
|
||||||
|
const editDisable = gcodeEditor('Laser Disable Script', 'disable');
|
||||||
|
|
||||||
|
createPopOp('laser off', {
|
||||||
|
disable: 'camLaserDisable',
|
||||||
|
}).inputs = {
|
||||||
|
disable: UC.newRow([UC.newButton(LANG.disable, editDisable)], { class: "ext-buttons f-row" }),
|
||||||
|
};
|
||||||
|
|
||||||
|
createPopOp('|', {}).inputs = {};
|
||||||
|
}
|
||||||
141
src2/kiri-mode/cam/cl-stock.js
Normal file
141
src2/kiri-mode/cam/cl-stock.js
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { api } from '../../kiri/api.js';
|
||||||
|
import { env } from './client.js';
|
||||||
|
import { space as SPACE } from '../../moto/space.js';
|
||||||
|
|
||||||
|
const { ui: UI } = api;
|
||||||
|
|
||||||
|
export function updateStock() {
|
||||||
|
if (env.isAnimate) {
|
||||||
|
if (env.isIndexed) {
|
||||||
|
SPACE.world.remove(env.camStock);
|
||||||
|
env.camStock = undefined;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!env.isCamMode) {
|
||||||
|
SPACE.world.remove(env.camZTop);
|
||||||
|
SPACE.world.remove(env.camZBottom);
|
||||||
|
SPACE.world.remove(env.camStock);
|
||||||
|
env.camStock = null;
|
||||||
|
env.camZTop = null;
|
||||||
|
env.camZBottom = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
api.platform.update_bounds();
|
||||||
|
|
||||||
|
const settings = api.conf.get();
|
||||||
|
const widgets = api.widgets.all();
|
||||||
|
|
||||||
|
const { stock, process } = settings;
|
||||||
|
const { x, y, z, center } = stock;
|
||||||
|
|
||||||
|
UI.func.animate.classList.add('disabled');
|
||||||
|
if (env.camStock) {
|
||||||
|
SPACE.world.remove(env.camStock);
|
||||||
|
env.camStock = null;
|
||||||
|
}
|
||||||
|
if (x && y && z) {
|
||||||
|
UI.func.animate.classList.remove('disabled');
|
||||||
|
{
|
||||||
|
let geo = new THREE.BoxGeometry(1, 1, 1);
|
||||||
|
let mat = new THREE.MeshBasicMaterial({
|
||||||
|
color: 0x777777,
|
||||||
|
opacity: 0.05,
|
||||||
|
transparent: true,
|
||||||
|
side: THREE.DoubleSide
|
||||||
|
});
|
||||||
|
env.camStock = new THREE.Mesh(geo, mat);
|
||||||
|
env.camStock.renderOrder = 2;
|
||||||
|
|
||||||
|
let lo = 0.5;
|
||||||
|
let lidat = [
|
||||||
|
lo, lo, lo, lo, lo, -lo,
|
||||||
|
lo, lo, lo, lo, -lo, lo,
|
||||||
|
lo, lo, lo, -lo, lo, lo,
|
||||||
|
-lo, -lo, -lo, -lo, -lo, lo,
|
||||||
|
-lo, -lo, -lo, -lo, lo, -lo,
|
||||||
|
-lo, -lo, -lo, lo, -lo, -lo,
|
||||||
|
lo, lo, -lo, -lo, lo, -lo,
|
||||||
|
lo, lo, -lo, lo, -lo, -lo,
|
||||||
|
lo, -lo, -lo, lo, -lo, lo,
|
||||||
|
lo, -lo, lo, -lo, -lo, lo,
|
||||||
|
-lo, -lo, lo, -lo, lo, lo,
|
||||||
|
-lo, lo, lo, -lo, lo, -lo
|
||||||
|
];
|
||||||
|
let ligeo = new THREE.BufferGeometry();
|
||||||
|
ligeo.setAttribute('position', new THREE.BufferAttribute(lidat.toFloat32(), 3));
|
||||||
|
let limat = new THREE.LineBasicMaterial({ color: 0xaaaaaa });
|
||||||
|
let lines = new THREE.LineSegments(ligeo, limat);
|
||||||
|
env.camStock.lines = lines;
|
||||||
|
env.camStock.add(lines);
|
||||||
|
SPACE.world.add(env.camStock);
|
||||||
|
}
|
||||||
|
// fight z fighting in threejs
|
||||||
|
const { scale, position, lines } = env.camStock;
|
||||||
|
scale.x = x + 0.005;
|
||||||
|
scale.y = y + 0.005;
|
||||||
|
scale.z = z + 0.005;
|
||||||
|
position.x = center.x;
|
||||||
|
position.y = center.y;
|
||||||
|
position.z = center.z;
|
||||||
|
lines.material.color = new THREE.Color(env.isDark() ? 0x555555 : 0xaaaaaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPACE.world.remove(env.camZTop);
|
||||||
|
if (process.camZTop && widgets.length) {
|
||||||
|
let max = { x, y, z };
|
||||||
|
for (let w of widgets) {
|
||||||
|
max.x = Math.max(max.x, w.track.box.w);
|
||||||
|
max.y = Math.max(max.y, w.track.box.h);
|
||||||
|
max.z = Math.max(max.z, w.track.box.d);
|
||||||
|
}
|
||||||
|
let geo = new THREE.PlaneGeometry(max.x, max.y);
|
||||||
|
let mat = new THREE.MeshBasicMaterial({
|
||||||
|
color: 0x777777,
|
||||||
|
opacity: 0.55,
|
||||||
|
transparent: true,
|
||||||
|
side: THREE.DoubleSide
|
||||||
|
});
|
||||||
|
const camZTop = env.camZTop = new THREE.Mesh(geo, mat);
|
||||||
|
camZTop._max = max;
|
||||||
|
camZTop.renderOrder = 1;
|
||||||
|
camZTop.position.x = center.x;
|
||||||
|
camZTop.position.y = center.y;
|
||||||
|
camZTop.position.z = process.camZTop;
|
||||||
|
SPACE.world.add(camZTop);
|
||||||
|
} else {
|
||||||
|
env.camZTop = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPACE.world.remove(env.camZBottom);
|
||||||
|
if (process.camZBottom && widgets.length) {
|
||||||
|
let max = { x, y, z };
|
||||||
|
for (let w of widgets) {
|
||||||
|
max.x = Math.max(max.x, w.track.box.w);
|
||||||
|
max.y = Math.max(max.y, w.track.box.h);
|
||||||
|
max.z = Math.max(max.z, w.track.box.d);
|
||||||
|
}
|
||||||
|
let geo = new THREE.PlaneGeometry(max.x, max.y);
|
||||||
|
let mat = new THREE.MeshBasicMaterial({
|
||||||
|
color: 0x777777,
|
||||||
|
opacity: 0.55,
|
||||||
|
transparent: true,
|
||||||
|
side: THREE.DoubleSide
|
||||||
|
});
|
||||||
|
const camZBottom = env.camZBottom = new THREE.Mesh(geo, mat);
|
||||||
|
camZBottom._max = max;
|
||||||
|
camZBottom.renderOrder = 1;
|
||||||
|
camZBottom.position.x = center.x;
|
||||||
|
camZBottom.position.y = center.y;
|
||||||
|
camZBottom.position.z = process.camZBottom;
|
||||||
|
SPACE.world.add(camZBottom);
|
||||||
|
} else {
|
||||||
|
env.camZBottom = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPACE.update();
|
||||||
|
}
|
||||||
65
src2/kiri-mode/cam/cl-surface.js
Normal file
65
src2/kiri-mode/cam/cl-surface.js
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { api } from '../../kiri/api.js';
|
||||||
|
import { env } from './client.js';
|
||||||
|
import { CAM } from './driver-fe.js';
|
||||||
|
|
||||||
|
const DEG2RAD = Math.PI / 180;
|
||||||
|
const RAD2DEG = 180 / Math.PI;
|
||||||
|
|
||||||
|
export let surfaceOn = false;
|
||||||
|
|
||||||
|
let alert, lastWidget;
|
||||||
|
|
||||||
|
export function surfaceAdd(ev) {
|
||||||
|
if (surfaceOn) {
|
||||||
|
return surfaceDone();
|
||||||
|
}
|
||||||
|
env.clearPops();
|
||||||
|
alert = api.show.alert("analyzing surfaces...", 1000);
|
||||||
|
let surfaces = env.poppedRec.surfaces;
|
||||||
|
let radians = env.poppedRec.follow * DEG2RAD;
|
||||||
|
CAM.surface_prep(env.currentIndex * RAD2DEG, () => {
|
||||||
|
api.hide.alert(alert);
|
||||||
|
alert = api.show.alert("[esc] cancels surface selection");
|
||||||
|
for (let [wid, arr] of Object.entries(surfaces)) {
|
||||||
|
let widget = api.widgets.forid(wid);
|
||||||
|
if (widget && arr.length)
|
||||||
|
for (let faceid of arr) {
|
||||||
|
CAM.surface_toggle(widget, faceid, radians, faceids => {
|
||||||
|
// surfaces[widget.id] = faceids;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
surfaceOn = env.hoveredOp;
|
||||||
|
surfaceOn.classList.add("editing");
|
||||||
|
api.feature.on_mouse_up = (obj, ev) => {
|
||||||
|
let { face } = obj;
|
||||||
|
let min = Math.min(face.a, face.b, face.c);
|
||||||
|
let faceid = min / 3;
|
||||||
|
let widget = lastWidget = obj.object.widget;
|
||||||
|
CAM.surface_toggle(widget, faceid, radians, faceids => {
|
||||||
|
surfaces[widget.id] = faceids;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function surfaceDone() {
|
||||||
|
if (!(surfaceOn && env.poppedRec && env.poppedRec.surfaces)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let surfaces = env.poppedRec.surfaces;
|
||||||
|
for (let wid of Object.keys(surfaces)) {
|
||||||
|
let widget = api.widgets.forid(wid);
|
||||||
|
if (widget) {
|
||||||
|
CAM.surface_clear(widget);
|
||||||
|
} else {
|
||||||
|
delete surfaces[wid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
api.hide.alert(alert);
|
||||||
|
api.feature.on_mouse_up = undefined;
|
||||||
|
surfaceOn.classList.remove("editing");
|
||||||
|
surfaceOn = false;
|
||||||
|
}
|
||||||
0
src2/kiri-mode/cam/cl-tab.js
Normal file
0
src2/kiri-mode/cam/cl-tab.js
Normal file
181
src2/kiri-mode/cam/cl-trace.js
Normal file
181
src2/kiri-mode/cam/cl-trace.js
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { api } from '../../kiri/api.js';
|
||||||
|
import { env } from './client.js';
|
||||||
|
import { CAM } from './driver-fe.js';
|
||||||
|
import { Layers } from '../../kiri/layers.js';
|
||||||
|
import { Stack } from '../../kiri/stack.js';
|
||||||
|
|
||||||
|
export let traceOn = false;
|
||||||
|
export let lastTrace;
|
||||||
|
|
||||||
|
export function setLastTrace(trace) {
|
||||||
|
lastTrace = trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function traceAdd(ev) {
|
||||||
|
if (traceOn) {
|
||||||
|
return traceDone();
|
||||||
|
}
|
||||||
|
env.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(env.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) 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(env.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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue