187 lines
6.7 KiB
JavaScript
187 lines
6.7 KiB
JavaScript
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
|
|
|
import { api } from '../../app/api.js';
|
|
import { env, clearPops } from './init-ui.js';
|
|
import { CAM } from './driver-fe.js';
|
|
|
|
export let holeSelOn = false;
|
|
export let lastSelHoles;
|
|
|
|
let holeGeo = new THREE.CylinderGeometry(1,1,1,20);
|
|
let holeMaterial = new THREE.MeshPhongMaterial( );
|
|
let alert;
|
|
|
|
/**
|
|
* 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();
|
|
}
|
|
clearPops();
|
|
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} drills - {depth,selected}[] object of the hole
|
|
* @returns {Mesh} the created mesh
|
|
*/
|
|
function createHoleMesh(widget,drills){
|
|
if(widget.holeMesh) widget.holeMesh.dispose()
|
|
widget.holeMesh = new THREE.InstancedMesh(holeGeo, holeMaterial,drills.length);
|
|
let baseMx = new THREE.Matrix4()
|
|
|
|
for(let [i,drill] of drills.entries()){
|
|
let { depth, selected, diam } = drill
|
|
let color = selected ? 0xFF0000 : 0x39e366
|
|
let mx = new THREE.Matrix4();
|
|
mx.copy( baseMx );
|
|
mx.multiply( new THREE.Matrix4().makeTranslation(drill.x, drill.y, drill.z-depth/2));
|
|
mx.multiply( new THREE.Matrix4().makeRotationX(Math.PI / 2))
|
|
mx.multiply( new THREE.Matrix4().makeScale(diam /2, depth,diam /2));
|
|
widget.holeMesh.setMatrixAt(i, mx);
|
|
widget.holeMesh.setColorAt(i, new THREE.Color(color));
|
|
drill.widgetID = widget.id
|
|
}
|
|
widget.mesh.add(widget.holeMesh);
|
|
widget.adds.push(widget.holeMesh); // for click detection
|
|
return widget.holeMesh
|
|
}
|
|
let meshesCached = widgets.every(widget => env.poppedRec.drills[widget.id] != undefined)
|
|
if (individual && meshesCached) {
|
|
// if any widget already has cached holes
|
|
api.hide.alert(alert);
|
|
api.widgets.for(widget => {
|
|
if (widget.adds) {
|
|
let drills = env.poppedRec.drills[widget.id];
|
|
createHoleMesh(widget, drills);
|
|
}
|
|
})
|
|
} 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)
|
|
createHoleMesh(widget, holes);
|
|
//add hole data to record
|
|
env.poppedRec.drills = env.poppedRec.drills ?? {};
|
|
env.poppedRec.drills[widget.id] = 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.setOpacity(0.8);
|
|
}
|
|
|
|
export function selectHolesHover(data) {
|
|
//not used right now. may be useful in the future
|
|
}
|
|
|
|
export function selectHolesHoverUp(int, ev) {
|
|
if (!int) return; //if not a hole mesh return
|
|
let { instanceId, object } = int;
|
|
selectHoleToggle(instanceId, object);
|
|
}
|
|
|
|
/**
|
|
* Toggle the selection of a hole mesh and update its color
|
|
* @param {Object3D} mesh - the hole mesh to toggle
|
|
*/
|
|
export function selectHoleToggle(id,mesh) {
|
|
|
|
if (id === undefined) return
|
|
let widget = mesh.parent.widget;
|
|
if(env.poppedRec.drills[widget.id][id].selected !== undefined){
|
|
env.poppedRec.drills[widget.id][id].selected = !env.poppedRec.drills[widget.id][id].selected
|
|
widget.holeMesh.setColorAt(id, new THREE.Color(env.poppedRec.drills[widget.id][id].selected ? 0xFF0000 : 0x39e366));
|
|
widget.holeMesh.instanceColor.needsUpdate = true
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.adds) {
|
|
widget.adds.length = 0 //clear adds array
|
|
if (env.poppedRec?.drills) delete env.poppedRec.drills[widget.id]
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.setOpacity(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);
|
|
}
|
|
});
|
|
}
|