diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
index 8f9d9b9e..7014846a 100644
--- a/.github/workflows/build-docs.yml
+++ b/.github/workflows/build-docs.yml
@@ -2,6 +2,8 @@ name: 'docs-publish'
on:
push:
branches: [ master ]
+ paths:
+ - 'docs/**'
workflow_dispatch:
diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index e9092fd2..5ec1acde 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -3,6 +3,8 @@ name: Test Electron App Production Build
on:
# Runs on pushes targeting the default branch
push:
+ paths:
+ - '!docs/**'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
diff --git a/.github/workflows/prettier-check.yml b/.github/workflows/prettier-check.yml
index 90dfe288..0625c749 100644
--- a/.github/workflows/prettier-check.yml
+++ b/.github/workflows/prettier-check.yml
@@ -2,7 +2,7 @@ name: 'Docs Fomatting Check'
on:
push:
paths:
- - './docs/**'
+ - 'docs/**'
workflow_dispatch:
jobs:
diff --git a/.github/workflows/prod-test.yml b/.github/workflows/prod-test.yml
index aba0391f..3a07ffb4 100644
--- a/.github/workflows/prod-test.yml
+++ b/.github/workflows/prod-test.yml
@@ -3,6 +3,8 @@ name: Test NPM Production Build
on:
# Runs on pushes targeting the default branch
push:
+ paths:
+ - '!docs/**'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
diff --git a/conf/docusaurus.config.js b/conf/docusaurus.config.js
index 316a7ece..8ff533cf 100644
--- a/conf/docusaurus.config.js
+++ b/conf/docusaurus.config.js
@@ -7,7 +7,28 @@ module.exports = {
favicon: 'img/gs-logo.png',
staticDirectories: ['./docs/static/'],
// ...
- plugins: [require.resolve('docusaurus-lunr-search')],
+ plugins: [
+ require.resolve('docusaurus-lunr-search'),
+ ['@docusaurus/plugin-client-redirects',
+ {
+ redirects: [
+ // /docs/oldDoc -> /docs/newDoc
+ {
+ to: '/kiri-moto',
+ from: '/projects/kiri-moto',
+ },
+ // Redirect from multiple old paths to the new path
+ {
+ to: '/gridbot',
+ from: '/projects/gridbot',
+ },
+ {
+ to: '/mesh-tool',
+ from: '/projects/mesh-tool',
+ },
+ ],
+ }],
+ ],
presets: [
[
'@docusaurus/preset-classic',
diff --git a/conf/prettier.config.js b/conf/prettier.config.js
index 5a5bf0eb..0ec558d1 100644
--- a/conf/prettier.config.js
+++ b/conf/prettier.config.js
@@ -8,12 +8,12 @@ const config = {
useTabs: false,
bracketSpacing: true,
objectWrap: "preserve",
- tabWidth: 4,
- semi: false,
- singleQuote: true,
+ tabWidth: 2,
+ semi: true,
+ singleQuote: false,
bracketSameLine: true,
arrowParens: "always",
- endOfLine: "crlf"
+ endOfLine: "lf"
}
module.exports = config
\ No newline at end of file
diff --git a/docs/kiri-moto/CAM/interface.mdx b/docs/kiri-moto/CAM/interface.mdx
new file mode 100644
index 00000000..c83cb992
--- /dev/null
+++ b/docs/kiri-moto/CAM/interface.mdx
@@ -0,0 +1,29 @@
+---
+description: Overview of CAM mode
+---
+
+import { ImageCarousel } from "@site/docs/src/components/carousel.js";
+
+# Interface
+
+The CAM interface is, in most respects, the same as the [general interface](/kiri-moto/interface). It is highly recommended to familiarize yourself with the general interface before using the CAM interface.
+
+With that in mind, here are the key differences:
+
+## Operation List
+
+The Operation List defines the order in which operations are
+performed on the model. Selecting the **plus** button will open a
+popup menu for choosing an operation to add. The operations are
+draggable, enabling easy re-ordering.
+
+- An operation can be disabled by **Ctrl+clicking** it. Disabled operations will be skipped in the slice/preview/export process.
+- The thin blue bar in the Operation List is also draggable. Moving the bar automatically disables all operations below it. This allows you to slice, preview, and export up to a specific point in the timeline.
+
+
+
+## Origin Selection
+
+Origin Selection (introduced in v4.3) enables automatically setting an origin to points of interest on the model, including corners and arc centers.
+
+
diff --git a/docs/kiri-moto/CAM/machines.md b/docs/kiri-moto/CAM/machines.md
index 3b49ea05..21676e2d 100644
--- a/docs/kiri-moto/CAM/machines.md
+++ b/docs/kiri-moto/CAM/machines.md
@@ -39,7 +39,6 @@ Customize how your G-code is formatted for your controller or post-processor:
- **Enable Laser** — Enables [Laser](./ops#laser-operations) operations (typically uses `M3/M5`; adjusts movement strategy)
- **File Extension** — Optional override for exported file type (e.g., `.nc`, `.ngc`, `.cnc`, `.cam`, `.gcode`, `.txt`)
-
---
## G-code Macros
diff --git a/docs/kiri-moto/interface.md b/docs/kiri-moto/interface.md
deleted file mode 100644
index f02b8de3..00000000
--- a/docs/kiri-moto/interface.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-description: A tour of Kiri:Moto's web-based interface
----
-
-# Interface
-
-Kiri:Moto's interface is designed for maximum access to the workspace and to present only the options that are necessary and relevant to the current action.
-
-The left menus control workspace, work mode, and objects while.
-
-The right menus control the behavior and settings for slicing, path routing, and path to code exports.
-
-[OBJ](https://www.cs.cmu.edu/~mbz/personal/graphics/obj.html), [STL](), and [3MF](https://docs.fileformat.com/3d/3mf/) files import natively. [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [JPG](https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format), and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics) are auto-extruded into a 3D parts.
-
-
-
-In CNC mode, there is an additional storyboard menu at the bottom where you can plan and re-order milling operations.
-
-
-
-The Setup menu offers access to Device selection and customization.
-
-
-
-Application preferences are mode-dependent. For example, CNC preferences show animation controls.
-
-
-
-
diff --git a/docs/kiri-moto/interface.mdx b/docs/kiri-moto/interface.mdx
new file mode 100644
index 00000000..f372e032
--- /dev/null
+++ b/docs/kiri-moto/interface.mdx
@@ -0,0 +1,54 @@
+---
+description: A tour of Kiri:Moto's web-based interface
+---
+
+import { ImageCarousel } from "@site/docs/src/components/carousel.js";
+
+# Interface
+
+Kiri:Moto's interface is designed for maximum access to the workspace, showing only the options necessary and relevant to the current action.
+
+[OBJ](https://www.cs.cmu.edu/~mbz/personal/graphics/obj.html), [STL](), and [3MF](https://docs.fileformat.com/3d/3mf/) files import natively. [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [JPG](https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format), and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics) files are auto-extruded into 3D parts.
+
+For the CAM interface, click [here](/kiri-moto/CAM).
+
+
+
+## Top Menu
+
+- **Left:** Buttons to move through the `Arrange → Slice → Preview → Export` workflow. These steps are also available as [keyboard shortcuts](/kiri-moto/controls). Selecting an option here will automatically run prior steps as needed.
+- **Center:** Clicking the [logo](/kiri-moto) opens a dialog with version selection, helpful links, and your current Kiri:Moto version. If you are unsure which version to use, check the [release notes](https://github.com/GridSpace/grid-apps/releases/) on GitHub.
+- **Right:** Options for importing/exporting the workspace, manipulating the view, changing modes, and setting preferences. Kiri:Moto currently supports CAM, FDM, SLA, and LASER modes. Some other modes are extensions of the LASER workflow, but do not have first-class support. The [preferences menu](#preferences) will be covered later in this section.
+ - Changing the mode updates the left menu and enables/disables mode-specific options such as the `CAM Operation` menu and the `CAM Animate` step.
+ - Learn about K:M file types [here](/kiri-moto/faq#what-are-the-kmz-and-km-file-formats-short-for).
+
+## Left Menu
+
+The left menu contains options for the current mode. These vary widely:
+
+- CAM has ample documentation on [Process Options](/kiri-moto/CAM/processOpts).
+- Other modes are less documented but many options are self-explanatory if you're familiar with the manufacturing process.
+- Hovering over an option provides tooltips. When in doubt, a quick search usually explains the option in detail.
+
+## Right Menu
+
+The right menu contains controls for objects in the workspace.
+
+- Hovering over the arrow next to an object reveals options for deleting, renaming, disabling, or replacing it.
+- Disabled objects remain visible but are ignored during slicing and exporting.
+
+## Machines Dialog
+
+
+
+The device dialog is accessed through the settings dropdown. It allows you to configure a device or select a predefined one.
+
+- The dropdown only shows devices available for the current mode.
+- Stock device settings are greyed out. To modify them, click `Customize`.
+- Learn more about how K:M handles CAM devices [here](/kiri-moto/CAM/machines).
+
+## Preferences
+
+Application preferences are also accessed through the settings dropdown. These are mode-dependent but share many common options. For example, CNC preferences include animation controls.
+
+
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 429f8036..89c74d27 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -35,6 +35,7 @@ const sidebars = {
id: "kiri-moto/CAM/index",
},
items: [
+ "kiri-moto/CAM/interface",
"kiri-moto/CAM/processOpts",
"kiri-moto/CAM/machines",
"kiri-moto/CAM/tools",
diff --git a/docs/src/components/carousel.js b/docs/src/components/carousel.js
index 49634d04..0174fc2d 100644
--- a/docs/src/components/carousel.js
+++ b/docs/src/components/carousel.js
@@ -4,59 +4,69 @@ import "react-responsive-carousel/lib/styles/carousel.min.css";
const imageDescripts = {
outline: [
- ["/1.png", "outline of a complex part"],
- ["/2.png", "outline of a non-flat part with inside holes"],
- ["/3.png", "outside-only outline"],
- ["/4.png", "inside-only outline"],
+ ["/1.png", "Outline of a complex part"],
+ ["/2.png", "Outline of a non-flat part with inside holes"],
+ ["/3.png", "Outside-only outline"],
+ ["/4.png", "Inside-only outline"],
],
level: [
- ["/1.png", "level of a large part"],
- ["/2.png", `level of a square part's stock`],
- ["/3.png", `level of a part with a non-uniform top surface`],
+ ["/1.png", "Level of a large part"],
+ ["/2.png", `Level of a square part's stock`],
+ ["/3.png", `Level of a part with a non-uniform top surface`],
],
rough: [
- ["/1.png", "rough cut of two parts"],
- ["/2.png", "side-view of a rough cut"],
- ["/3.png", "rough cut of a part with a complex top surface"],
- ["/4.gif", "animate of complex rough cut"],
+ ["/1.png", "Rough cut of two parts"],
+ ["/2.png", "Side-view of a rough cut"],
+ ["/3.png", "Rough cut of a part with a complex top surface"],
+ ["/4.gif", "Animate of complex rough cut"],
],
contour: [
- ["/1.png", "close-up of a precise contour"],
- ["/2.png", "contour of multiple parts at once"],
- ["/3.png", "low precision contour"],
+ ["/1.png", "Close-up of a precise contour"],
+ ["/2.png", "Contour of multiple parts at once"],
+ ["/3.png", "Low precision contour"],
],
register: [
["/1.png", "2-drill register"],
["/2.png", "3-drill register"],
- ["/3.png", "jigsaw register"],
+ ["/3.png", "Jigsaw register"],
],
drill: [
- ["/1.png", "drills for a robot baseplate"],
- ["/2.png", "drills for a pegboard"],
- ["/3.png", "selecting only matching-size holes"],
+ ["/1.png", "Drills for a robot baseplate"],
+ ["/2.png", "Drills for a pegboard"],
+ ["/3.png", "Selecting only matching-size holes"],
],
trace: [
- ["/1.png", "toolpath tracing a design into a part"],
- ["/2.png", "selecting loops to trace"],
- ["/3.png", "tracing edges for deburring"],
- ["/4.png", "trace to clear a pocket"],
- ["/5.png", "arbitrary offset outline"],
+ ["/1.png", "Toolpath tracing a design into a part"],
+ ["/2.png", "Selecting loops to trace"],
+ ["/3.png", "Tracing edges for deburring"],
+ ["/4.png", "Trace to clear a pocket"],
+ ["/5.png", "Arbitrary offset outline"],
],
pocket: [
- ["/1.png", "selecting areas to pocket"],
- ["/2.png", "toolpath for pocket"],
- ["/3.gif", "pocket animation"],
- ["/4.png", "toolpath for v-bit carve"],
- ["/5.png", "many-pocketed part"],
+ ["/1.png", "Selecting areas to pocket"],
+ ["/2.png", "Toolpath for pocket"],
+ ["/3.gif", "Pocket animation"],
+ ["/4.png", "Toolpath for v-bit carve"],
+ ["/5.png", "Many-pocketed part"],
],
- gcode: [["/1.png", "the gcode editor popup"]],
+ gcode: [["/1.png", "The gcode editor popup"]],
laserOn: [],
laserOff: [],
index: [],
lathe: [],
tabs: [
- ["/1.png", "tabs added to part"],
- ["/2.png", "sliced part with tabs"],
+ ["/1.png", "Tabs added to part"],
+ ["/2.png", "Sliced part with tabs"],
+ ],
+ camInterface: [
+ ["/1.png", "Empty Ops list"],
+ ["/2.png", "Sample Ops list"],
+ ["/3.png", "Ops list with history bar"],
+ ],
+ prefs: [
+ ["/prefs-CAM.png", "Preferences in CAM mode"],
+ ["/prefs-FDM.png", "Preferences in FDM mode"],
+ ["/prefs-LASER.png", "Preferences in laser mode"],
],
};
@@ -66,15 +76,17 @@ const imageDescripts = {
* @param {keyof typeof imageDescripts} images - The key to an array of images and descriptions.
* @returns {ReactElement} - A carousel of the given images.
*/
-export function ImageCarousel({ base, images }) {
+export function ImageCarousel({ base, images, sml }) {
return (
-
- {imageDescripts[images].map(([image, caption], index) => (
-
-

-
{caption}
-
- ))}
-
+
+
+ {imageDescripts[images].map(([image, caption], index) => (
+
+

+
{caption}
+
+ ))}
+
+
);
}
diff --git a/docs/src/custom.css b/docs/src/custom.css
index e51d1d87..23ac403b 100644
--- a/docs/src/custom.css
+++ b/docs/src/custom.css
@@ -5,3 +5,14 @@
.navbar .navbar__items {
height: 4.5rem;
}
+
+.carouselWrapper {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+}
+
+.carouselWrapper .carousel-root {
+ width: fit-content;
+ max-width: 20rem;
+}
diff --git a/docs/static/img/CAM/interface/1.png b/docs/static/img/CAM/interface/1.png
new file mode 100644
index 00000000..2a75a236
Binary files /dev/null and b/docs/static/img/CAM/interface/1.png differ
diff --git a/docs/static/img/CAM/interface/2.png b/docs/static/img/CAM/interface/2.png
new file mode 100644
index 00000000..16b3e591
Binary files /dev/null and b/docs/static/img/CAM/interface/2.png differ
diff --git a/docs/static/img/CAM/interface/3.png b/docs/static/img/CAM/interface/3.png
new file mode 100644
index 00000000..4b29a334
Binary files /dev/null and b/docs/static/img/CAM/interface/3.png differ
diff --git a/docs/static/img/CAM/interface/originSelect.png b/docs/static/img/CAM/interface/originSelect.png
new file mode 100644
index 00000000..808e9570
Binary files /dev/null and b/docs/static/img/CAM/interface/originSelect.png differ
diff --git a/docs/static/img/device-dialog.png b/docs/static/img/device-dialog.png
deleted file mode 100644
index d282d2c0..00000000
Binary files a/docs/static/img/device-dialog.png and /dev/null differ
diff --git a/docs/static/img/interface/CAMDevice.png b/docs/static/img/interface/CAMDevice.png
new file mode 100644
index 00000000..4226882c
Binary files /dev/null and b/docs/static/img/interface/CAMDevice.png differ
diff --git a/docs/static/img/interface/main.png b/docs/static/img/interface/main.png
new file mode 100644
index 00000000..a9bedf9d
Binary files /dev/null and b/docs/static/img/interface/main.png differ
diff --git a/docs/static/img/interface/prefs-CAM.png b/docs/static/img/interface/prefs-CAM.png
new file mode 100644
index 00000000..d68372f5
Binary files /dev/null and b/docs/static/img/interface/prefs-CAM.png differ
diff --git a/docs/static/img/interface/prefs-FDM.png b/docs/static/img/interface/prefs-FDM.png
new file mode 100644
index 00000000..bb947612
Binary files /dev/null and b/docs/static/img/interface/prefs-FDM.png differ
diff --git a/docs/static/img/interface/prefs-LASER.png b/docs/static/img/interface/prefs-LASER.png
new file mode 100644
index 00000000..363cfbfe
Binary files /dev/null and b/docs/static/img/interface/prefs-LASER.png differ
diff --git a/docs/static/img/preferences-cam.png b/docs/static/img/preferences-cam.png
deleted file mode 100644
index d0236bf3..00000000
Binary files a/docs/static/img/preferences-cam.png and /dev/null differ
diff --git a/docs/static/img/preferences-fdm.png b/docs/static/img/preferences-fdm.png
deleted file mode 100644
index fb521b82..00000000
Binary files a/docs/static/img/preferences-fdm.png and /dev/null differ
diff --git a/package.json b/package.json
index 1e56a302..08eba04b 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"node": ">=22.0.0"
},
"dependencies": {
+ "@docusaurus/plugin-client-redirects": "^3.9.0",
"@fortawesome/fontawesome-free": "^6.1.1",
"@gridspace/app-server": "^0.0.20",
"@gridspace/basic-ftp": "github:gridspace/basic-ftp#v5.0.5-gridspace",
@@ -68,8 +69,8 @@
"ws": "^8.18.2"
},
"devDependencies": {
- "@docusaurus/core": "^3.7.0",
- "@docusaurus/preset-classic": "^3.7.0",
+ "@docusaurus/core": "^3.9.0",
+ "@docusaurus/preset-classic": "^3.9.0",
"@electron/notarize": "^3.0.0",
"copy-webpack-plugin": "^12.0.2",
"cross-env": "^10.1.0",
diff --git a/src/kiri/mode/cam/cl-hole.js b/src/kiri/mode/cam/cl-hole.js
index 8ebf6e56..77d703ab 100644
--- a/src/kiri/mode/cam/cl-hole.js
+++ b/src/kiri/mode/cam/cl-hole.js
@@ -7,6 +7,9 @@ import { lastTrace, setLastTrace } from './cl-trace.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.
@@ -21,7 +24,7 @@ export async function selectHoles(individual) {
return selectHolesDone();
}
clearPops();
- let alert = api.show.alert("analyzing parts...");
+ alert = api.show.alert("analyzing parts...");
holeSelOn = env.hoveredOp;
holeSelOn.classList.add("editing");
api.feature.hover = true;
@@ -33,48 +36,38 @@ export async function selectHoles(individual) {
/**
* 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
+ * @param {Object} drills - {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
+ 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
- // 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);
- });
- }
+ let drills = env.poppedRec.drills[widget.id];
+ createHoleMesh(widget, drills);
}
})
} else {
@@ -86,7 +79,7 @@ export async function selectHoles(individual) {
(progress, msg) => {
alert2[0] = msg;
api.show.progress(progress, msg);
- api.alerts.update();
+ // api.alerts.update();
},
async centers => {
api.show.progress(0);
@@ -108,17 +101,10 @@ export async function selectHoles(individual) {
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);
- });
+ createHoleMesh(widget, holes);
//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);
+ env.poppedRec.drills[widget.id] = holes;
})
}
);
@@ -140,24 +126,27 @@ export async function selectHoles(individual) {
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 { object } = int;
- selectHoleToggle(object);
+ 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(mesh) {
- let { hole } = mesh
- if (!hole) return
- hole.selected = !hole.selected;
- mesh.material.color.setHex(hole.selected ? 0xFF0000 : 0x39e366);
+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
+ }
}
/**
@@ -166,12 +155,9 @@ export function selectHoleToggle(mesh) {
* @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
+ delete env.poppedRec.drills[widget.id]
}
}
@@ -199,10 +185,3 @@ export function selectHolesDone() {
}
});
}
-
-export function unselectHoles(widget) {
- if (!widget.holes) return
- widget.holes.forEach(hole => {
- hole.selected = false
- })
-}