From 295dcd12ece3a307095ebbbcf7c4d0753f7d05e7 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 30 Sep 2025 07:37:39 -0400 Subject: [PATCH 01/11] sort fdm, cam, control property names for easier navigation --- src/kiri/core/conf.js | 574 +++++++++++++++++++++--------------------- 1 file changed, 287 insertions(+), 287 deletions(-) diff --git a/src/kiri/core/conf.js b/src/kiri/core/conf.js index 71908b54..7ea214ac 100644 --- a/src/kiri/core/conf.js +++ b/src/kiri/core/conf.js @@ -182,33 +182,33 @@ function normalize(settings) { // auto field renaming on import const renamed = { - roughingTool: "camRoughTool", - roughingSpindle: "camRoughSpindle", - roughingDown: "camRoughDown", - roughingOver: "camRoughOver", - roughingSpeed: "camRoughSpeed", - roughingPlunge: "camRoughPlunge", - roughingStock: "camRoughStock", - roughingPocket: "camRoughVoid", - roughingOn: "camRoughOn", - finishingTool: "camOutlineTool", - finishingSpindle: "camOutlineSpindle", + camWideCutout: "camOutlineWide", + drillDown: "camDrillDown", + drillDownSpeed: "camDrillDownSpeed", + drillDwell: "camDrillDwell", + drillingOn: "camDrillingOn", + drillLift: "camDrillLift", + drillSpindle: "camDrillSpindle", + drillTool: "camDrillTool", finishingDown: "camOutlineDown", - finishingOver: "camContourOver", - finishingSpeed: "camOutlineSpeed", - finishingPlunge: "camOutlinePlunge", finishingOn: "camOutlineOn", + finishingOver: "camContourOver", + finishingPlunge: "camOutlinePlunge", + finishingSpeed: "camOutlineSpeed", + finishingSpindle: "camOutlineSpindle", + finishingTool: "camOutlineTool", finishingXOn: "camContourXOn", finishingYOn: "camContourYOn", - drillTool: "camDrillTool", - drillSpindle: "camDrillSpindle", - drillDownSpeed: "camDrillDownSpeed", - drillDown: "camDrillDown", - drillDwell: "camDrillDwell", - drillLift: "camDrillLift", - drillingOn: "camDrillingOn", - camWideCutout: "camOutlineWide", - outputClockwise: "camConventional" + outputClockwise: "camConventional", + roughingDown: "camRoughDown", + roughingOn: "camRoughOn", + roughingOver: "camRoughOver", + roughingPlunge: "camRoughPlunge", + roughingPocket: "camRoughVoid", + roughingSpeed: "camRoughSpeed", + roughingSpindle: "camRoughSpindle", + roughingStock: "camRoughStock", + roughingTool: "camRoughTool", }; export const conf = { @@ -258,97 +258,97 @@ export const conf = { }, // process defaults FDM:Process p:{ + antiBacklash: 0, + arcTolerance: 0, + firstLayerBedTemp: 0, + firstLayerBeltBump: 0, + firstLayerBeltLead: 3, + firstLayerBrim: 0, + firstLayerBrimGap: 0, + firstLayerBrimIn: 0, + firstLayerBrimTrig: 0, + firstLayerFanSpeed: 0, + firstLayerFillRate: 35, + firstLayerFlatten: 0, + firstLayerLineMult: 1.0, + firstLayerNozzleTemp: 0, + firstLayerPrintMult: 1.0, + firstLayerRate: 30, + firstLayerYOffset: 0, + firstSliceHeight: 0.25, + outputAlternating: false, + outputAvoidGaps: true, + outputBedTemp: 60, + outputBeltFirst: false, + outputBrimCount: 2, + outputBrimOffset: 2, + outputCoastDist: 0, + outputDraftShield: false, + outputFanLayer: 1, + outputFanSpeed: 255, + outputFeedrate: 50, + outputFillMult: 1.25, + outputFinishrate: 50, + outputInvertX: false, + outputInvertY: false, + outputLayerRetract: false, + outputLoops: 0, + outputMinLayerTime: 10, + outputMinSpeed: 10.0, + outputPurgeTower: 0, + outputRaft: false, + outputRaftSpacing: 0.2, + outputRetractDist: 1.5, + outputRetractDwell: 20, + outputRetractSpeed: 40, + outputRetractWipe: 0, + outputScarfLength: 5, + outputSeekrate: 80, + outputShellMult: 1.25, + outputShortPoly: 0.0, + outputSparseMult: 1.25, + outputTemp: 200, processName: "default", + ranges: [], + sliceAdaptive: false, sliceAngle: 45, + sliceBottomLayers: 3, + sliceCompInner: 0, + sliceCompOuter: 0, + sliceDetectThin: "basic", + sliceFillAngle: 45, + sliceFillGrow: 0, + sliceFillOverlap: 0.35, + sliceFillRate: 0, + sliceFillRepeat: 1, + sliceFillSparse: 0.25, + sliceFillType: "hex", + sliceFillWidth: 1, sliceHeight: 0.25, - sliceShells: 3, - sliceShellOrder: "in-out", sliceLayerStart: "last", sliceLayerStartX: 0, sliceLayerStartY: 0, sliceLineWidth: 0, - sliceCompInner: 0, - sliceCompOuter: 0, - sliceFillGrow: 0, - sliceFillAngle: 45, - sliceFillWidth: 1, - sliceFillOverlap: 0.35, - sliceFillSparse: 0.25, - sliceFillRepeat: 1, - sliceFillRate: 0, - sliceSolidRate: 0, - sliceFillType: "hex", - sliceSupportDensity: 0.1, - sliceSupportOffset: 1.0, - sliceSupportGap: 1, - sliceSupportSize: 5, - sliceSupportArea: 0.1, - sliceSupportSpan: 5, - sliceSupportGrow: 0, - sliceSupportExtra: 0, - sliceSupportAngle: 50, - sliceSupportNozzle: 0, - sliceSupportEnable: false, - sliceSupportOutline: true, - sliceZInterleave: false, - sliceSolidMinArea: 1, - sliceBottomLayers: 3, - sliceTopLayers: 3, - firstSliceHeight: 0.25, - firstLayerRate: 30, - firstLayerFillRate: 35, - firstLayerPrintMult: 1.0, - firstLayerLineMult: 1.0, - firstLayerYOffset: 0, - firstLayerNozzleTemp: 0, - firstLayerBedTemp: 0, - firstLayerBrim: 0, - firstLayerBrimIn: 0, - firstLayerBrimTrig: 0, - firstLayerBrimGap: 0, - firstLayerBeltLead: 3, - firstLayerBeltBump: 0, - firstLayerFanSpeed: 0, - firstLayerFlatten: 0, - outputRaft: false, - outputRaftSpacing: 0.2, - outputDraftShield: false, - outputTemp: 200, - outputBedTemp: 60, - outputFeedrate: 50, - outputFinishrate: 50, - outputSeekrate: 80, - outputShellMult: 1.25, - outputFillMult: 1.25, - outputSparseMult: 1.25, - outputFanLayer: 1, - outputFanSpeed: 255, - outputRetractDist: 1.5, - outputRetractSpeed: 40, - outputRetractWipe: 0, - outputRetractDwell: 20, - outputBrimCount: 2, - outputBrimOffset: 2, - outputScarfLength: 0, - outputShortPoly: 100.0, - outputMinSpeed: 10.0, - outputMinLayerTime: 0, - outputCoastDist: 0, - outputPurgeTower: 0, - outputBeltFirst: false, - outputAvoidGaps: true, - outputAlternating: false, - outputLayerRetract: false, - outputLoops: 0, - outputInvertX: false, - outputInvertY: false, - sliceDetectThin: "off", sliceMinHeight: 0, - sliceAdaptive: false, + sliceShellOrder: "in-out", + sliceShells: 3, + sliceSolidMinArea: 1, + sliceSolidRate: 0, + sliceSupportAngle: 50, + sliceSupportArea: 0.1, + sliceSupportDensity: 0.1, + sliceSupportEnable: false, + sliceSupportExtra: 0, + sliceSupportGap: 1, + sliceSupportGrow: 0, + sliceSupportNozzle: 0, + sliceSupportOffset: 1.0, + sliceSupportOutline: true, + sliceSupportSize: 5, + sliceSupportSpan: 5, + sliceTopLayers: 3, + sliceZInterleave: false, zHopDistance: 0.2, - arcTolerance: 0, - antiBacklash: 0, - ranges: [] } }, sla:{ @@ -422,186 +422,186 @@ export const conf = { }, // process defaults CAM:Process p:{ - processName: "default", - camLevelTool: 1000, - camLevelSpindle: 1000, - camLevelOver: 0.75, - camLevelStepZ: 0, - camLevelSpeed: 1000, - camLevelDown: 0, - camLevelInset: 0.5, - camLevelStock: true, - camRoughTool: 1000, - camRoughSpindle: 1000, - camRoughDown: 2, - camRoughOver: 0.4, - camRoughSpeed: 1000, - camRoughPlunge: 250, - camRoughStock: 0, - camRoughStockZ: 0, - camRoughAll: true, - camRoughVoid: false, - camRoughFlat: true, - camRoughTop: true, - camRoughIn: true, - camRoughOn: true, - camRoughOmitThru: false, - camRoughOmitVoid: false, - camOutlineTool: 1000, - camOutlineSpindle: 1000, - camOutlineTop: true, - camOutlineDown: 3, - camOutlineOver: 0.4, - camOutlineOverCount: 1, - camOutlineSpeed: 800, - camOutlinePlunge: 250, - camOutlineWide: false, - camOutlineDogbone: false, - camOutlineOmitThru: false, - camOutlineOmitVoid: false, - camOutlineOut: true, - camOutlineIn: false, - camOutlineOn: true, - camContourTool: 1000, - camContourSpindle: 1000, - camContourOver: 0.5, - camContourSpeed: 1000, + camArcEnabled: false, + camArcResolution: 5, + camArcTolerance: 0.15, camContourAngle: 85, - camContourLeave: 0, - camContourReduce: 2, camContourBottom: false, + camContourBridge: 0, camContourCurves: false, camContourIn: false, + camContourLeave: 0, + camContourOver: 0.5, + camContourReduce: 2, + camContourSpeed: 1000, + camContourSpindle: 1000, + camContourTool: 1000, camContourXOn: true, camContourYOn: true, - camLatheTool: 1000, - camLatheSpindle: 1000, - camLatheOver: 0.1, - camLatheAngle: 1, - camLatheSpeed: 500, - camLatheLinear: true, - camTolerance: 0, - camTraceTool: 1000, - camTraceSpindle: 1000, - camTraceType: "follow", - camTraceOver: 0.5, - camTraceDown: 0, - camTraceThru: 0, - camTraceSpeed: 250, - camTracePlunge: 200, - camTraceOffOver: 0, - camTraceDogbone: false, - camTraceMerge: false, - camTraceLines: false, - camTraceZTop: 0, - camTraceZBottom: 0, - camPocketSpindle: 1000, - camPocketTool: 1000, - camPocketOver: 0.25, - camPocketDown: 1, - camPocketSpeed: 250, - camPocketPlunge: 200, - camPocketExpand: 0, - camPocketSmooth: 0, - camPocketRefine: 20, - camPocketFollow: 5, - camPocketContour: false, - camPocketEngrave: false, - camPocketOutline: false, - camPocketZTop: 0, - camPocketZBottom: 0, - camDrillTool: 1006, - camDrillSpindle: 1000, - camDrillDownSpeed: 250, + camConventional: false, // outputClockwise + camDepthFirst: false, camDrillDown: 5, + camDrillDownSpeed: 250, camDrillDwell: 250, + camDrillFromStockTop: false, + camDrillingOn: false, camDrillLift: 2, camDrillMark: false, - camDrillFromStockTop: false, - camDrillThru: 5, camDrillPrecision: 1, - camDrillingOn: false, - camRegisterSpeed: 1000, - camRegisterThru: 5, - camRegisterOffset: 10, - camHelicalTool: 1000, - camHelicalSpindle: 1000, - camHelicalDownSpeed: 250, - camHelicalSpeed: 1000, - camHelicalDown: 5, - camHelicalBottomFinish: true, - camHelicalThru: 0, - camHelicalOffset: "auto", - camHelicalForceStartAngle: false, - camHelicalStartAngle: 0, - camHelicalOffsetOverride: 0, - camHelicalEntry: false, - camHelicalEntryOffset:0, - camHelicalReverse: false, - camHelicalClockwise: true, - camFlipAxis: "X", - camFlipOther: "", - camLaserEnable: ["M321"], - camLaserDisable: ["M322"], - camLaserOn: ["M3"], - camLaserOff: ["M5"], - camLaserSpeed: 100, - camLaserPower: 1, - camLaserAdaptive: false, - camLaserAdaptMod: false, - camLaserFlatten: false, - camLaserFlatZ: 0, - camLaserPowerMin: 0, - camLaserPowerMax: 1, - camLaserZMin: 0, - camLaserZMax: 0, - camTabsWidth: 5, - camTabsHeight: 5, - camTabsDepth: 5, - camTabsMidline: false, - camDepthFirst: false, - camInnerFirst: false, - camEaseDown: false, + camDrillSpindle: 1000, + camDrillThru: 5, + camDrillTool: 1006, camEaseAngle: 10, - camOriginTop: true, - camZAnchor: "middle", - camZOffset: 0, - camZTop: 0, - camZBottom: 0, - camZClearance: 1, - camZThru: 0, + camEaseDown: false, + camExpertFast: false, camFastFeed: 6000, camFastFeedZ: 300, - camTolerance: 0, + camFirstZMax: false, camFlatness: 0.001, - camContourBridge: 0, - camStockX: 5, - camStockY: 5, - camStockZ: 5, - camStockOffset: true, - camStockClipTo: false, - camStockIndexed: false, - camStockIndexGrid: true, - camIndexAxis: 0, + camFlipAxis: "X", + camFlipOther: "", + camForceZMax: false, + camFullEngage: 0.8, + camHelicalBottomFinish: true, + camHelicalClockwise: true, + camHelicalDown: 5, + camHelicalDownSpeed: 250, + camHelicalEntry: false, + camHelicalEntryOffset:0, + camHelicalForceStartAngle: false, + camHelicalOffset: "auto", + camHelicalOffsetOverride: 0, + camHelicalReverse: false, + camHelicalSpeed: 1000, + camHelicalSpindle: 1000, + camHelicalStartAngle: 0, + camHelicalThru: 0, + camHelicalTool: 1000, camIndexAbs: true, - camConventional: false, // outputClockwise + camIndexAxis: 0, + camInnerFirst: false, + camLaserAdaptive: false, + camLaserAdaptMod: false, + camLaserDisable: ["M322"], + camLaserEnable: ["M321"], + camLaserFlatten: false, + camLaserFlatZ: 0, + camLaserOff: ["M5"], + camLaserOn: ["M3"], + camLaserPower: 1, + camLaserPowerMax: 1, + camLaserPowerMin: 0, + camLaserSpeed: 100, + camLaserZMax: 0, + camLaserZMin: 0, + camLatheAngle: 1, + camLatheLinear: true, + camLatheOver: 0.1, + camLatheSpeed: 500, + camLatheSpindle: 1000, + camLatheTool: 1000, + camLevelDown: 0, + camLevelInset: 0.5, + camLevelOver: 0.75, + camLevelSpeed: 1000, + camLevelSpindle: 1000, + camLevelStepZ: 0, + camLevelStock: true, + camLevelTool: 1000, camOriginCenter: false, camOriginOffX: 0, camOriginOffY: 0, camOriginOffZ: 0, + camOriginTop: true, + camOutlineDogbone: false, + camOutlineDown: 3, + camOutlineIn: false, + camOutlineOmitThru: false, + camOutlineOmitVoid: false, + camOutlineOn: true, + camOutlineOut: true, + camOutlineOver: 0.4, + camOutlineOverCount: 1, + camOutlinePlunge: 250, + camOutlineSpeed: 800, + camOutlineSpindle: 1000, + camOutlineTool: 1000, + camOutlineTop: true, + camOutlineWide: false, + camPocketContour: false, + camPocketDown: 1, + camPocketEngrave: false, + camPocketExpand: 0, + camPocketFollow: 5, + camPocketOutline: false, + camPocketOver: 0.25, + camPocketPlunge: 200, + camPocketRefine: 20, + camPocketSmooth: 0, + camPocketSpeed: 250, + camPocketSpindle: 1000, + camPocketTool: 1000, + camPocketZBottom: 0, + camPocketZTop: 0, + camRegisterOffset: 10, + camRegisterSpeed: 1000, + camRegisterThru: 5, + camRoughAll: true, + camRoughDown: 2, + camRoughFlat: true, + camRoughIn: true, + camRoughOmitThru: false, + camRoughOmitVoid: false, + camRoughOn: true, + camRoughOver: 0.4, + camRoughPlunge: 250, + camRoughSpeed: 1000, + camRoughSpindle: 1000, + camRoughStock: 0, + camRoughStockZ: 0, + camRoughTool: 1000, + camRoughTop: true, + camRoughVoid: false, + camStockClipTo: false, + camStockIndexed: false, + camStockIndexGrid: true, + camStockOffset: true, + camStockX: 5, + camStockY: 5, + camStockZ: 5, + camTabsDepth: 5, + camTabsHeight: 5, + camTabsMidline: false, + camTabsWidth: 5, + camTolerance: 0, + camTolerance: 0, + camToolInit: true, + camTraceDogbone: false, + camTraceDown: 0, + camTraceLines: false, + camTraceMerge: false, + camTraceOffOver: 0, + camTraceOver: 0.5, + camTracePlunge: 200, + camTraceSpeed: 250, + camTraceSpindle: 1000, + camTraceThru: 0, + camTraceTool: 1000, + camTraceType: "follow", + camTraceZBottom: 0, + camTraceZTop: 0, + camTrueShadow: false, + camZAnchor: "middle", + camZBottom: 0, + camZClearance: 1, + camZOffset: 0, + camZThru: 0, + camZTop: 0, + op2: [], // flip ops + ops: [], // current ops outputInvertX: false, outputInvertY: false, - camExpertFast: false, - camTrueShadow: false, - camArcEnabled: false, - camArcTolerance: 0.15, - camArcResolution: 5, - camForceZMax: false, - camFirstZMax: false, - camToolInit: true, - camFullEngage: 0.8, - ops: [], // current ops - op2: [] // flip ops + processName: "default", } }, laser: { @@ -917,37 +917,37 @@ export const conf = { devproc: {}, // application ui and control preferences (Q menu) controller:{ - view: null, - dark: false, - shiny: false, - drawer: false, - scrolls: true, - zoomSpeed: 1.0, - lineType: "path", - autoSave: true, + animesh: "800", antiAlias: true, + assembly: false, + autoLayout: true, + autoSave: true, + dark: false, + detail: "50", + devel: false, + drawer: false, + edgeangle: 20, + exportGhost: false, + exportLocal: false, + exportOcto: false, + exportPreview: false, + exportThumb: false, + freeLayout: true, + healMesh: false, + lineType: "path", + ortho: false, reverseZoom: true, + scrolls: true, + shiny: true, showOrigin: false, showRulers: true, showSpeeds: true, - freeLayout: true, - autoLayout: true, - spaceRandoX: false, spaceLayout: 1, - edgeangle: 20, - units: "mm", - exportOcto: false, - exportGhost: false, - exportLocal: false, - exportThumb: false, - exportPreview: false, - detail: "50", - animesh: "800", - healMesh: false, + spaceRandoX: false, threaded: true, - assembly: false, - ortho: false, - devel: false + units: "mm", + view: null, + zoomSpeed: 1.0, }, // default hidden ui groups hidden: { From 07bbe547e32acc1aed2f6d7ab45ab5e4c671e4a0 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 30 Sep 2025 16:30:53 -0400 Subject: [PATCH 02/11] fix legacy png lib to work with esm build --- notes.md | 1 + src/ext/pngjs.esm.js | 2 +- src/ext/pngjs.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/notes.md b/notes.md index 7cf2186c..56c74577 100644 --- a/notes.md +++ b/notes.md @@ -15,6 +15,7 @@ * `P` move all persisted / workspace settings/data to IndexedDB (LS limitations) * `P` faster ray intersect https://github.com/gkjohnson/three-mesh-bvh/ * `P` try material clipping planes for slice range selection +* `P` switch png lib to https://github.com/photopea/UPNG.js * `F` edit in Mesh:Tool * `F` custom device vars for profiles / ranges / gcode diff --git a/src/ext/pngjs.esm.js b/src/ext/pngjs.esm.js index 1da89a23..fd8cbbb7 100644 --- a/src/ext/pngjs.esm.js +++ b/src/ext/pngjs.esm.js @@ -4,4 +4,4 @@ import './pngjs.js'; // Re-export the PNG object -export const PNG = self.png ? self.png.PNG : null; \ No newline at end of file +export const PNG = globalThis.png ? globalThis.png.PNG : null; \ No newline at end of file diff --git a/src/ext/pngjs.js b/src/ext/pngjs.js index 561ca443..da7ca622 100644 --- a/src/ext/pngjs.js +++ b/src/ext/pngjs.js @@ -1,4 +1,4 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.png = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i Date: Tue, 30 Sep 2025 16:44:16 -0400 Subject: [PATCH 03/11] add npm i to mods at setup --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d8d10734..c344e3d8 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,8 @@ "webpack-cli": "^5.1.4" }, "scripts": { - "setup": "npm i && npm run clean && npm run dev -- --dryrun && npm run webpack-ext", + "setup": "npm run setup-mods && npm i && npm run clean && npm run dev -- --dryrun && npm run webpack-ext", + "setup-mods": "cd mods && npm i", "build": "npm run prebuild && electron-builder", "build-nopublish": "npm run prebuild && electron-builder --publish never", "build-debug": "npm run prebuild && DEBUG=electron-builder electron-builder", From 53a65777f8a6abef881728abddb6e10c8a8c05e9 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Thu, 2 Oct 2025 10:15:14 -0400 Subject: [PATCH 04/11] update min layer time to respect min output speed --- src/kiri/core/conf.js | 2 +- src/kiri/core/print.js | 1 + src/kiri/mode/fdm/prepare.js | 26 ++++++++++++++------------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/kiri/core/conf.js b/src/kiri/core/conf.js index 7ea214ac..69303af1 100644 --- a/src/kiri/core/conf.js +++ b/src/kiri/core/conf.js @@ -294,7 +294,7 @@ export const conf = { outputLayerRetract: false, outputLoops: 0, outputMinLayerTime: 10, - outputMinSpeed: 10.0, + outputMinSpeed: 5.0, outputPurgeTower: 0, outputRaft: false, outputRaftSpacing: 0.2, diff --git a/src/kiri/core/print.js b/src/kiri/core/print.js index 86736811..5f3ee901 100644 --- a/src/kiri/core/print.js +++ b/src/kiri/core/print.js @@ -129,6 +129,7 @@ class Print { close = !options.open, scarf = !poly.open ? (options.scarf ?? 0) : false, tool = options.tool, + zmax = options.zmax, last = startPoint, first = true; diff --git a/src/kiri/mode/fdm/prepare.js b/src/kiri/mode/fdm/prepare.js index 8d560b43..c1453b77 100644 --- a/src/kiri/mode/fdm/prepare.js +++ b/src/kiri/mode/fdm/prepare.js @@ -46,8 +46,6 @@ export async function fdm_prepare(widgets, settings, update) { output = [], layerout = []; - let lastLayerStart = null; - // compute bounds if missing if (!bounds) { bounds = new THREE.Box3(); @@ -553,12 +551,9 @@ export async function fdm_prepare(widgets, settings, update) { offset, layerout, { - routeAround: process.outputAvoidGaps, - seedPoint: printPoint.sub(offset), - params, // range parameters first: slice.index === 0, - support: slice.widget.support, onBelt: beltStart, + params, // range parameters pretract: (wipeDist) => { if (!(lastLayer && lastLayer.length)) { return; @@ -573,7 +568,11 @@ export async function fdm_prepare(widgets, settings, update) { print.addOutput(lastLayer, endpoint, null, null, lastOut.tool); } } - } + }, + routeAround: process.outputAvoidGaps, + seedPoint: printPoint.sub(offset), + support: slice.widget.support, + zmax, } ); layerout.print_time = printPoint.layer_time; @@ -823,8 +822,10 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) { fillSpeed = opt.speed || opt.fillSpeed || (firstLayer ? firstFillSpeed || firstShellSpeed : process.outputFeedrate), infillSpeed = process.sliceFillRate || opt.infillSpeed || fillSpeed || printSpeed, moveSpeed = process.outputSeekrate, + minSpeed = process.outputMinSpeed, origin = startPoint.add(offset), zhop = process.zHopDistance || 0, + zmax = opt.zmax, antiBacklash = process.antiBacklash, wipeDist = process.outputRetractWipe || 0, isBelt = device.bedBelt, @@ -1100,9 +1101,6 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) { coast: firstLayer ? 0 : coastDist, extrude: numOrDefault(opt.extrude, shellMult), nozzleSize, - rate: finishShell ? finishSpeed : printSpeed, - scarf, - tool: extruder, onfirst: (firstPoint, preout) => { let from = seedPoint || startPoint; if (from.distTo2D(firstPoint) > retractDist) { @@ -1111,7 +1109,11 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) { } } seedPoint = null; - } + }, + rate: finishShell ? finishSpeed : printSpeed, + scarf, + tool: extruder, + zmax }); lastPoly = slice.lastPoly = poly; } @@ -1600,7 +1602,7 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) { if (minLayerTime && tt < minLayerTime) { let fact = tt / minLayerTime; for (let p of preout) { - if (p.emit) p.speed *= fact; + if (p.emit) p.speed = Math.max(p.speed * fact, minSpeed); } } From a697950a369ebcc9da7c0bee99157eafb90fe3d2 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 5 Oct 2025 10:22:14 -0400 Subject: [PATCH 05/11] lower fan speed for bridge layers --- src/kiri/mode/fdm/export.js | 5 +++-- src/kiri/mode/fdm/prepare.js | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/kiri/mode/fdm/export.js b/src/kiri/mode/fdm/export.js index b6768e4b..6b359f56 100644 --- a/src/kiri/mode/fdm/export.js +++ b/src/kiri/mode/fdm/export.js @@ -613,6 +613,7 @@ export function fdm_export(print, online, ondone, ondebug) { for (pidx=0; pidx Date: Sat, 11 Oct 2025 22:17:42 -0400 Subject: [PATCH 06/11] work in boot/install url using updated service worker --- app.js | 2 ++ bin/bundle.config.json | 11 ++++++ bin/bundler.mjs | 80 ++++++++++++++++++++++++++++++++++++++++++ src/main/service.js | 9 +++-- 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 bin/bundle.config.json create mode 100644 bin/bundler.mjs diff --git a/app.js b/app.js index 4c27cc73..f5e629f4 100644 --- a/app.js +++ b/app.js @@ -122,6 +122,7 @@ function init(mod) { mod.add(serveWasm); mod.add(serveCode); mod.add(fullpath({ + "/boot" : redir((pre??"") + "/boot/", 301), "/kiri" : redir((pre??"") + "/kiri/", 301), "/mesh" : redir((pre??"") + "/mesh/", 301), "/meta" : redir((pre??"") + "/meta/", 301), @@ -147,6 +148,7 @@ function init(mod) { mod.static("/mesh/", "web/mesh"); mod.static("/moto/", "web/moto"); mod.static("/kiri/", "web/kiri"); + mod.static("/boot/", "web/boot"); // module loader function load_modules(root, force) { diff --git a/bin/bundle.config.json b/bin/bundle.config.json new file mode 100644 index 00000000..655fa67e --- /dev/null +++ b/bin/bundle.config.json @@ -0,0 +1,11 @@ +{ + "outputs": { + "bundle": "./web/kiri/bundle.bin" + }, + "inputs": [ + { "root": "./web", "prefix": "" }, + { "root": "./src", "prefix": "lib" }, + { "root": "./src/wasm", "prefix": "wasm" }, + { "root": "./src/wasm", "prefix": "lib/kiri/wasm" } + ] +} diff --git a/bin/bundler.mjs b/bin/bundler.mjs new file mode 100644 index 00000000..199f4d45 --- /dev/null +++ b/bin/bundler.mjs @@ -0,0 +1,80 @@ +import fs from 'fs'; +import path from 'path'; +import { Buffer } from 'buffer'; + +const cfg = JSON.parse(fs.readFileSync(process.argv[2] || './bundle.config.json', 'utf8')); + +// --- recursive directory walker (follows symlinks safely) --- +function* walk(dir, seen = new Set()) { + const real = fs.realpathSync(dir); + if (seen.has(real)) { + return; + } + seen.add(real); + + for (const name of fs.readdirSync(dir)) { + const p = path.join(dir, name); + let st; + try { st = fs.statSync(p); } catch { continue; } + if (st.isDirectory()) yield* walk(p, seen); + else yield p; + } +} + +// --- collect all files according to config --- +let entries = []; +for (const input of cfg.inputs) { + const root = input.root; + const prefix = input.prefix || ''; + for (const file of walk(root)) { + const rel = path.relative(root, file).replace(/\\/g, '/'); + const virt = prefix ? `${prefix}/${rel}` : rel; + entries.push({ file, virt }); + } +} + +// --- build header and data --- +const dataParts = []; +const entryMeta = []; +let offset = 0; + +for (const { file, virt } of entries) { + const data = fs.readFileSync(file); + entryMeta.push({ virt, offset, length: data.length }); + dataParts.push(data); + offset += data.length; +} + +// temporary header without offsets to measure total size +let tempHeaderParts = []; +for (const { virt, offset, length } of entryMeta) { + const name = Buffer.from(virt, 'utf8'); + const nlen = Buffer.alloc(2); nlen.writeUInt16LE(name.length); + const offb = Buffer.alloc(4); offb.writeUInt32LE(0); // placeholder + const lenb = Buffer.alloc(4); lenb.writeUInt32LE(length); + tempHeaderParts.push(nlen, name, offb, lenb); +} +const count = Buffer.alloc(4); count.writeUInt32LE(entries.length); +const tempHeader = Buffer.concat([count, ...tempHeaderParts]); +const headerSize = tempHeader.length; // true data offset base + +// now rebuild header with correct absolute offsets +let headerParts = []; +for (const { virt, offset, length } of entryMeta) { + const name = Buffer.from(virt, 'utf8'); + const nlen = Buffer.alloc(2); nlen.writeUInt16LE(name.length); + const offb = Buffer.alloc(4); offb.writeUInt32LE(headerSize + offset); + const lenb = Buffer.alloc(4); lenb.writeUInt32LE(length); + headerParts.push(nlen, name, offb, lenb); + console.log(virt); +} + +const header = Buffer.concat([count, ...headerParts]); +const full = Buffer.concat([header, ...dataParts]); + +// --- write final bundle --- +const outPath = cfg.outputs.bundle || './bundle.bin'; +fs.mkdirSync(path.dirname(outPath), { recursive: true }); +fs.writeFileSync(outPath, full); // ⚡ write raw binary + +console.log(`✅ Bundled ${entries.length} files → ${outPath} (${full.length} bytes)`); diff --git a/src/main/service.js b/src/main/service.js index 6d8af693..80db6047 100644 --- a/src/main/service.js +++ b/src/main/service.js @@ -11,8 +11,9 @@ async function start_service_worker() { debug('service worker registration'); try { - // const reg = await navigator.serviceWorker.register("/src/moto/service.js?013", { scope: "/" }); - const reg = await navigator.serviceWorker.register("/code/service.js?"+version, { scope: "/" }); + const reg = await navigator + .serviceWorker + .register(`/code/service.js?${version}`, { scope: "/" }); if (reg.installing) { debug('service worker installing'); } else if (reg.waiting) { @@ -31,4 +32,6 @@ async function start_service_worker() { } } -if (service_worker && self.enable_service) start_service_worker(); +if (service_worker && self.enable_service) { + start_service_worker(); +} From 09a30911e89d71fdbef4c3a460c47975eecebbd0 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 12 Oct 2025 00:20:13 -0400 Subject: [PATCH 07/11] add option to compress/uglify boot image. fix indexeddb reload race --- bin/bundler.mjs | 36 +++++++++++++++++++++++++++++++----- src/data/index.js | 21 +++++++++++++++------ 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/bin/bundler.mjs b/bin/bundler.mjs index 199f4d45..21cec2bd 100644 --- a/bin/bundler.mjs +++ b/bin/bundler.mjs @@ -1,8 +1,10 @@ import fs from 'fs'; import path from 'path'; +import uglify from 'uglify-js'; import { Buffer } from 'buffer'; const cfg = JSON.parse(fs.readFileSync(process.argv[2] || './bundle.config.json', 'utf8')); +const compress = process.env.UGLIFY ? true : false // --- recursive directory walker (follows symlinks safely) --- function* walk(dir, seen = new Set()) { @@ -37,12 +39,36 @@ for (const input of cfg.inputs) { const dataParts = []; const entryMeta = []; let offset = 0; +let cache = new Map(); for (const { file, virt } of entries) { - const data = fs.readFileSync(file); - entryMeta.push({ virt, offset, length: data.length }); - dataParts.push(data); - offset += data.length; + let record = cache.get(file); + if (record) { + // console.log({ dup: file }); + entryMeta.push({ ...record, virt }); + } else { + let data = fs.readFileSync(file); + if (compress && file.endsWith("js")) { + console.log('compress', file); + data = uglify.minify(data.toString(), { + compress: { + merge_vars: false, + unused: false + } + }); + // console.log({ to: typeof(data), data }); + if (!data.code) { + console.log({ skip: file }); + continue; + } + data = Buffer.from(data.code); + } + record = { virt, offset, length: data.length }; + cache.set(file, record); + entryMeta.push(record); + dataParts.push(data); + offset += data.length; + } } // temporary header without offsets to measure total size @@ -66,7 +92,7 @@ for (const { virt, offset, length } of entryMeta) { const offb = Buffer.alloc(4); offb.writeUInt32LE(headerSize + offset); const lenb = Buffer.alloc(4); lenb.writeUInt32LE(length); headerParts.push(nlen, name, offb, lenb); - console.log(virt); + // console.log(virt); } const header = Buffer.concat([count, ...headerParts]); diff --git a/src/data/index.js b/src/data/index.js index e28217be..f92b7089 100644 --- a/src/data/index.js +++ b/src/data/index.js @@ -168,7 +168,7 @@ SP.init = function(options = {}) { request = IDB.open(name, this.version); request.onupgradeneeded = function(event) { - let db = storage.db = request.result; + let db = request.result; let current = [...db.objectStoreNames]; let stores = storage.stores; // add missing stores @@ -184,16 +184,16 @@ SP.init = function(options = {}) { // remove obsolete stores for (let curr of current) { if (stores.indexOf(curr) < 0) { - storage.db.deleteObjectStore(curr); + db.deleteObjectStore(curr); console.log({index_dropped: curr}); } } - event.target.transaction.oncomplete = function(event) { - storage.runQueue(); - }; + // allow transactions + storage.db = db; }; request.onsuccess = function(event) { + console.log('IDB open succeeded'); storage.current = storage.stores[0]; storage.db = request.result; storage.runQueue(); @@ -217,6 +217,7 @@ SP.runQueue = function() { let i = 0, q = this.queue, e; while (i < q.length) { e = q[i++]; + // console.log('runQ', i, ...e); switch (e.shift()) { case 'iterate': this.iterate(...e); break; case 'keys': this.keys(...e); break; @@ -252,7 +253,11 @@ SP.put = function(key, value, callback, store = this.current) { req.onerror = function(event) { callback(false) }; } } catch (e) { - console.log(e); + if (e.name === 'InvalidStateError') { + console.log({ putRetry: key }); + return this.queue.push(['put', key, value, callback, store]); + } + console.log(e.name, e); if (callback) callback(false); } }; @@ -275,6 +280,10 @@ SP.get = function(key, callback, store = this.current) { req.onerror = function(event) { callback(null) }; } } catch (e) { + if (e.name === 'InvalidStateError') { + console.log({ getRetry: key }); + return this.queue.push(['get', key, callback, store]); + } console.log(e); if (callback) callback(null); } From 6afa649f20ddde5d323a6526392f6613660863c9 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 12 Oct 2025 01:25:39 -0400 Subject: [PATCH 08/11] remove grid:local and grid:host targets --- src/kiri/core/api.js | 3 +- src/kiri/core/conf.js | 2 - src/kiri/core/export.js | 231 ---------------------------------------- src/kiri/core/init.js | 5 - src/kiri/core/main.js | 44 +------- web/kiri/index.html | 27 ----- 6 files changed, 2 insertions(+), 310 deletions(-) diff --git a/src/kiri/core/api.js b/src/kiri/core/api.js index 42ec035c..eb41dccb 100644 --- a/src/kiri/core/api.js +++ b/src/kiri/core/api.js @@ -9,7 +9,7 @@ import { client as work } from './client.js'; import { consts, COLOR as color, LISTS as lists } from './consts.js'; import { device, devices } from './devices.js'; import { catalog, dialog, event, group, help, hide, image } from './main.js'; -import { modal, mode, probe, process, show, space, util, view } from './main.js'; +import { modal, mode, process, show, space, util, view } from './main.js'; import { local as dataLocal } from '../../data/local.js'; import { noop, ajax, o2js, js2o } from './utils.js'; import { functions } from './function.js'; @@ -162,7 +162,6 @@ export const api = { o2js, onkey, platform, - probe, process, sdb: dataLocal, selection, diff --git a/src/kiri/core/conf.js b/src/kiri/core/conf.js index 69303af1..affad216 100644 --- a/src/kiri/core/conf.js +++ b/src/kiri/core/conf.js @@ -927,8 +927,6 @@ export const conf = { devel: false, drawer: false, edgeangle: 20, - exportGhost: false, - exportLocal: false, exportOcto: false, exportPreview: false, exportThumb: false, diff --git a/src/kiri/core/export.js b/src/kiri/core/export.js index b7440ab1..dbabe999 100644 --- a/src/kiri/core/export.js +++ b/src/kiri/core/export.js @@ -218,207 +218,6 @@ function exportGCodeDialog(gcode, sections, info, names) { ajax.send(form); } - function gridhost_tracker(host,key) { - ajax(host+"/api/check?key="+key, function(data) { - data = js2o(data); - console.log(data); - if (!(data.done || data.error)) { - setTimeout(function() { gridhost_tracker(host,key) }, 1000); - } - }); - } - - function gridlocal_probe(ev, devs) { - if (ev && ev.code !== 'Enter') return; - - if (!devs && api.probe.local(gridlocal_probe)) return; - - grid_local = devs; - - let gdev = localGet('grid-local'); - let gloc = $('grid-local'); - let html = []; - for (let uuid in devs) { - gdev = gdev || uuid; - let dev = devs[uuid]; - let sel = uuid === gdev ? ' selected' : ''; - html.push(``); - } - - if (html.length) { - gloc.innerHTML = html.join('\n'); - gloc.onchange = (ev) => { - localSet('grid-local', gloc.options[gloc.selectedIndex].value); - }; - $('send-to-gridhead').style.display = 'flex'; - $('send-to-gridspool').style.display = 'flex'; - } else { - $('send-to-gridhead').style.display = ''; - $('send-to-gridspool').style.display = ''; - } - } - - function sendto_gridlocal() { - let uuid = $('grid-local').value; - let dev = grid_local[uuid]; - if (dev) { - let file = $('print-filename').value; - fetch( - `${api.probe.live}/api/grid_send?uuid=${uuid}&file=${encodeURIComponent(file + "." + fileext)}`, - {method: "POST", body: gcode} - ) - .then(t => t.text()) - .then(t => { - api.stats.add(`ua_${api.mode.get_lower()}_print_local_ok`); - console.log({grid_spool_said: t}); - }) - .catch(e => { - api.stats.add(`ua_${api.mode.get_lower()}_print_local_err`); - console.log({grid_local_spool_error: e}); - }) - .finally(() => { - api.modal.hide(); - }); - } - } - - function admin_gridlocal() { - let dev = grid_local[$('grid-local').value]; - if (dev && dev.stat && dev.stat.device) { - let dsd = dev.stat.device; - window.open(`http://${dsd.addr[0]}:${dsd.port || 4080}`, "_grid_admin"); - } - } - - function gridhost_probe(ev, set_host) { - if (ev && ev.code !== 'Enter') return; - if (!(grid_host && grid_apik)) return; - - if (set_host) grid_host.value = set_host; - - let xhtr = new XMLHttpRequest(), - host = grid_host.value, - apik = grid_apik.value, - target = grid_target.value; - - if (!apik) $('gpapik').style.display = 'none'; - - if (!host && api.probe.grid(gridhost_probe)) return; - - if (!host) return; - - xhtr.onreadystatechange = function() { - if (xhtr.readyState === 4) { - if (xhtr.status >= 200 && xhtr.status < 300) { - localSet('grid-host', host); - localSet('grid-apik', apik); - let res = JSON.parse(xhtr.responseText); - let sel = false; - let match = false; - let first = null; - let html = []; - grid_targets = {}; - for (let key in res) { - first = first || key; - if (!localGet('grid-target')) { - localSet('grid-target', key); - sel = true; - } else { - sel = localGet('grid-target') === key; - } - match = match || sel; - grid_targets[html.length] = key; - html.push( - "" - ); - } - if (!match) { - localSet('grid-target', first); - } - grid_target.innerHTML = html.join('\n'); - } else if (xhtr.status === 401) { - $('gpapik').style.display = ''; - } else { - local.removeItem('grid-host'); - local.removeItem('grid-apik'); - console.log("invalid grid:host url"); - } - } - }; - - xhtr.open("GET", host + "/api/active?key=" + apik); - xhtr.send(); - } - - function sendto_gridhost() { - if (!(grid_host && grid_apik)) return; - - let xhtr = new XMLHttpRequest(), - host = grid_host.value, - apik = grid_apik.value, - target = localGet('grid-target') || ''; - - if (target === '') { - api.show.alert('invalid or missing target'); - return; - } - if (host.indexOf("http") !== 0) { - api.show.alert("host missing protocol (http:// or https://)"); - return; - } - if (host.indexOf("://") < 0) { - api.show.alert("host:port malformed"); - return; - } - if (api.const.SECURE && !api.util.isSecure(host)) { - api.show.alert("host must begin with 'https' on a secure site"); - return; - } - - localSet('grid-host', host.trim()); - localSet('grid-apik', apik.trim()); - - xhtr.onreadystatechange = function() { - if (xhtr.readyState === 4) { - let status = xhtr.status; - api.stats.add(`ua_${api.mode.get_lower()}_print_grid_${status}`); - if (status >= 200 && status < 300) { - let json = js2o(xhtr.responseText); - gridhost_tracker(host,json.key); - api.ajax(host+"/api/wait?key="+json.key, function(data) { - data = js2o(data); - console.log(data); - api.show.alert("print to "+target+": "+data.status, 600); - }); - } else { - api.show.alert("grid:host error\nstatus: "+status+"\nmessage: "+xhtr.responseText, 10000); - } - api.show.progress(0); - } - }; - xhtr.upload.addEventListener('progress', function(evt) { - api.show.progress(evt.loaded/evt.total, "sending"); - }); - filename = $('print-filename').value; - xhtr.open("POST", - host + "/api/print?" + - "filename=" + filename + - "&target=" + target + - "&key=" + apik + - "&time=" + Math.round(info.time) + - "&length=" + Math.round(info.distance) + - "&image=" + filename - ); - xhtr.setRequestHeader("Content-Type", "text/plain"); - let snapshot = api.view.snapshot; - xhtr.send(snapshot ? [gcode,snapshot].join("\0") : gcode); - api.modal.hide(); - } - function download() { filename = $('print-filename').value; api.util.download(gcode, filename + "." + fileext); @@ -463,8 +262,6 @@ function exportGCodeDialog(gcode, sections, info, names) { let set = api.conf.get(); let fdm = MODE === MODES.FDM; let octo = set.controller.exportOcto && MODE !== MODES.CAM; - let ghost = set.controller.exportGhost; - let local = set.controller.exportLocal; let preview = set.controller.exportPreview; $('code-preview-head').style.display = preview ? '' : 'none'; $('code-preview').style.display = preview ? '' : 'none'; @@ -484,8 +281,6 @@ function exportGCodeDialog(gcode, sections, info, names) { // persist fields when changed bindField('octo-host', 'octo-host'); bindField('octo-apik', 'octo-apik'); - bindField('grid-host', 'grid-host'); - bindField('grid-apik', 'grid-apik'); // in cam mode, show zip file option let downloadZip = $('print-zip'); @@ -699,37 +494,11 @@ function exportGCodeDialog(gcode, sections, info, names) { $('ophost').style.display = 'none'; $('opapik').style.display = 'none'; $('oph1nt').style.display = 'none'; - $('send-to-gridhost').style.display = 'none'; } octo_host.value = localGet('octo-host') || ''; octo_apik.value = localGet('octo-apik') || ''; } catch (e) { console.log(e) } - // grid:host setup - $('send-to-hosthead').style.display = ghost ? '' : 'none'; - $('send-to-gridhost').style.display = ghost ? '' : 'none'; - if (ghost) try { - $('print-gridhost').onclick = sendto_gridhost; - $('grid-host').onkeyup = gridhost_probe; - $('grid-apik').onkeyup = gridhost_probe; - grid_host = $('grid-host'); - grid_apik = $('grid-apik'); - grid_target = $('grid-target'); - grid_target.onchange = function(ev) { - localSet('grid-target', grid_targets[grid_target.selectedIndex]); - }; - grid_host.value = localGet('grid-host') || ''; - grid_apik.value = localGet('grid-apik') || ''; - gridhost_probe(); - } catch (e) { console.log(e) } - - // grid:local setup - if (local) try { - gridlocal_probe(); - $('print-gridlocal').onclick = sendto_gridlocal; - $('admin-gridlocal').onclick = admin_gridlocal; - } catch (e) { console.log(e) } - // preview of the generated GCODE (first 64k max) if (preview && gcode) $('code-preview-textarea').value = gcode.substring(0,65535); } diff --git a/src/kiri/core/init.js b/src/kiri/core/init.js index 02dd0a55..95492134 100644 --- a/src/kiri/core/init.js +++ b/src/kiri/core/init.js @@ -155,8 +155,6 @@ function booleanSave() { control.reverseZoom = ui.reverseZoom.checked; control.dark = ui.dark.checked; control.exportOcto = ui.exportOcto.checked; - control.exportGhost = ui.exportGhost.checked; - control.exportLocal = ui.exportLocal.checked; control.exportThumb = ui.exportThumb.checked; control.exportPreview = ui.exportPreview.checked; control.healMesh = ui.healMesh.checked; @@ -904,7 +902,6 @@ function init_one() { xany: $('mod-x-any'), xsla: $('mod-x-sla'), xlaser: $('mod-x-laser'), - local: $('mod-local'), don8: $('mod-don8'), any: $('mod-any'), }, @@ -1058,8 +1055,6 @@ function init_one() { spaceRandoX: newBoolean(LANG.op_spcx_s, booleanSave, {title:LANG.op_spcx_l, show:isBelt}), spaceLayout: newInput(LANG.op_spcr_s, {title:LANG.op_spcr_l, convert:toFloat, size:3, units}), _____: newGroup(LANG.xp_menu, $('prefs-xpo'), {inline: true}), - exportLocal: newBoolean(`Grid:Local`, booleanSave, {title:LANG.op_exgl_l}), - exportGhost: newBoolean(`Grid:Host`, booleanSave, {title:LANG.op_exgh_l}), exportOcto: newBoolean(`OctoPrint`, booleanSave, {title:LANG.op_exop_l}), exportThumb: newBoolean(`Thumbnail`, booleanSave, {modes:FDM}), exportPreview: newBoolean(`Code Preview`, booleanSave), diff --git a/src/kiri/core/main.js b/src/kiri/core/main.js index 51a00689..ed2f9363 100644 --- a/src/kiri/core/main.js +++ b/src/kiri/core/main.js @@ -114,12 +114,6 @@ export const mode = { } }; -export const probe = { - live: "https://live.grid.space", - grid: noop, - local: noop -}; - export const process = { code: currentProcessCode, get: currentProcessName @@ -784,43 +778,7 @@ function showHelpFile(local,then) { } function showLocal() { - showModal('local'); - api.probe.local((err,data) => { - let devc = 0; - let bind = []; - let html = ['']; - html.push(``); - html.push(``); - let recs = []; - for (let k in data) { - recs.push(data[k].stat); - } - recs.sort((a,b) => { - return a.device.name < b.device.name ? -1 : 1; - }); - for (let r of recs) { - bind.push({uuid: r.device.uuid, host: r.device.addr[0], port: r.device.port}); - html.push(``); - html.push(``); - html.push(``); - html.push(``); - html.push(``); - html.push(``); - devc++; - } - html.push(``); - html.push(`
devicetypestatus
${r.device.name}${r.device.mode}${r.state}
`); - if (devc) { - $('mod-local').innerHTML = html.join(''); - } else { - $('mod-local').innerHTML = `
no local devices`; - } - bind.forEach(rec => { - $(rec.uuid).onclick = () => { - window.open(`http://${rec.host}:${rec.port||4080}/`); - }; - }); - }); + // deprecated } function setViewMode(mode) { diff --git a/web/kiri/index.html b/web/kiri/index.html index a72a261a..2fcce519 100644 --- a/web/kiri/index.html +++ b/web/kiri/index.html @@ -612,8 +612,6 @@ - -
@@ -667,31 +665,6 @@
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- - -
-
- - -
-
-
From 46c135ba239747f322fd0b2005641917050aed18 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 12 Oct 2025 16:01:38 -0400 Subject: [PATCH 09/11] fix tab reference for mirror op add box area constraint for contour ops --- src/data/index.js | 1 - src/kiri/mode/cam/client.js | 2 +- src/kiri/mode/cam/op-contour.js | 75 +++++++++++++++++++++++++++------ src/kiri/mode/cam/op-lathe.js | 28 ++++++------ src/kiri/mode/cam/prepare.js | 4 +- src/kiri/mode/cam/topo3.js | 17 +++----- src/main/kiri.js | 1 + web/kiri/index.css | 2 + 8 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/data/index.js b/src/data/index.js index f92b7089..ee631f26 100644 --- a/src/data/index.js +++ b/src/data/index.js @@ -193,7 +193,6 @@ SP.init = function(options = {}) { }; request.onsuccess = function(event) { - console.log('IDB open succeeded'); storage.current = storage.stores[0]; storage.db = request.result; storage.runQueue(); diff --git a/src/kiri/mode/cam/client.js b/src/kiri/mode/cam/client.js index bd509dbf..aa847a64 100644 --- a/src/kiri/mode/cam/client.js +++ b/src/kiri/mode/cam/client.js @@ -10,7 +10,7 @@ import { Layers } from '../../core/layers.js'; import { Stack } from '../../core/stack.js'; import { updateStock } from './cl-stock.js'; import { createPopOps } from './cl-ops.js'; -import { tabAdd, tabDone, tabClear, restoreTabs, rotateTabs, updateTabs, clearTabs } from './cl-tab.js'; +import { tabAdd, tabDone, tabClear, restoreTabs, rotateTabs, updateTabs, clearTabs, mirrorTabs } 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'; diff --git a/src/kiri/mode/cam/op-contour.js b/src/kiri/mode/cam/op-contour.js index ae7e089a..1d14b313 100644 --- a/src/kiri/mode/cam/op-contour.js +++ b/src/kiri/mode/cam/op-contour.js @@ -4,26 +4,70 @@ import { CamOp } from './op.js'; import { Tool } from './tool.js'; import { generate as Topo } from './topo3.js'; import { newPoint } from '../../../geo/point.js'; +import { newPolygon } from '../../../geo/polygon.js'; import { tip2tipEmit } from '../../../geo/paths.js'; -function createFilter(op) { +function createFilter(op, origin, axis) { + console.log({ origin, axis }); + let ok = () => true; let filter = slices => slices; let filterString = op.filter?.map(l => l.trim()).join('\n'); if (filterString) { try { const obj = eval(`( ${filterString} )`); - let idx = 0; - if (obj && obj.slices) { - const nadd = []; - filter = function (slices) { - for (let slice of slices) { - if (obj.slices(slice, idx++)) { - nadd.push(slice); + let box = obj?.box; + let slice_fn = obj?.slices; + let index = 0; + const accept = []; + filter = function (slices) { + for (let slice of slices) { + if (slice_fn && slice_fn(slice, index++)) { + accept.push(slice); + } else if (box) { + // slice.z = x when axis = y + // slice.z = y when axis = x + let { x, y, z } = box; + x = x ?? [ -Infinity, Infinity ]; + y = y ?? [ -Infinity, Infinity ]; + z = z ?? [ -Infinity, Infinity ]; + let ok = false; + if (axis === 'x') { + let sy = slice.z + origin.y; + if (sy >= y[0] && sy <= y[1]) { + ok = true; + for (let p of slice.camLines) { + p.points = p.points.filter(p => + p.x - origin.x >= x[0] && p.x - origin.x <= x[1] && + p.z - origin.z >= z[0] && p.z - origin.z <= z[1] + ); + } + } + } else { + let sx = slice.z - origin.x; + if (sx >= x[0] && sx <= x[1]) { + ok = true; + for (let p of slice.camLines) { + p.points = p.points.filter(p => + p.y + origin.y >= y[0] && p.y + origin.y <= y[1] && + p.z - origin.z >= z[0] && p.z - origin.z <= z[1] + ); + } + } + } + if (ok) { + slice.camLines = slice.camLines.map(p => { + if (p.points.length > 1) { + return newPolygon(p.points).setOpen(true); + } else { + return undefined; + } + }).filter(p => p); + accept.push(slice); } } - return nadd; - }; - } + } + return accept; + }; } catch (e) { console.log('filter parse error', e, op.filter); } @@ -38,8 +82,8 @@ class OpContour extends CamOp { async slice(progress) { let { op, state } = this; - let { addSlices, settings, updateToolDiams } = state; - let filter = createFilter(op); + let { color, addSlices, settings, updateToolDiams } = state; + let filter = createFilter(op, settings.origin, op.axis.toLowerCase()); let toolDiam = this.toolDiam = new Tool(settings, op.tool).fluteDiameter(); updateToolDiams(toolDiam); // we need topo for safe travel moves when roughing and outlining @@ -54,6 +98,11 @@ class OpContour extends CamOp { slices = filter(slices); this.sliceOut = slices; addSlices(slices); + for (let slice of slices) { + slice.output() + .setLayer(`contour ${op.axis}`, { face: color, line: color }) + .addPolys(slice.camLines); + } }, contour: op, state: state diff --git a/src/kiri/mode/cam/op-lathe.js b/src/kiri/mode/cam/op-lathe.js index 915ae7e1..d1cde28b 100644 --- a/src/kiri/mode/cam/op-lathe.js +++ b/src/kiri/mode/cam/op-lathe.js @@ -6,22 +6,23 @@ import { generate as topo4_generate } from './topo4.js'; import { newPoint } from '../../../geo/point.js'; function createFilter(op) { + let ok = () => true; let filter = slices => slices; - if (op.filter) { + let filterString = op.filter?.map(l => l.trim()).join('\n'); + if (filterString) { try { - const obj = eval(`( ${op.filter.join('\n')} )`); - let idx = 0; - if (obj && obj.slices) { - const nadd = []; - filter = function (slices) { - for (let slice of slices) { - if (obj.slices(slice, idx++)) { - nadd.push(slice); - } + const obj = eval(`( ${filterString} )`); + const accept = []; + let index = 0; + let sl_fn = obj?.slices ?? ok; + filter = function (slices) { + for (let slice of slices) { + if (sl_fn(slice, index++)) { + accept.push(slice); } - return nadd; - }; - } + } + return accept; + }; } catch (e) { console.log('filter parse error', e, op.filter); } @@ -38,7 +39,6 @@ class OpLathe extends CamOp { let { op, state } = this; let { addSlices } = state; let filter = createFilter(op); - this.topo = await topo4_generate({ op, state, diff --git a/src/kiri/mode/cam/prepare.js b/src/kiri/mode/cam/prepare.js index fac80971..cbeefb87 100644 --- a/src/kiri/mode/cam/prepare.js +++ b/src/kiri/mode/cam/prepare.js @@ -973,8 +973,8 @@ export function prepEach(widget, settings, print, firstPoint, update) { let arcPoints = arcToPath(from, to, arcPreviewRes, { clockwise, center }) - .map(applyWidgetMovement); - + .map(applyWidgetMovement); + // console.log({arcPoints}) camOut(from, 1); diff --git a/src/kiri/mode/cam/topo3.js b/src/kiri/mode/cam/topo3.js index 84a54fce..678cf831 100644 --- a/src/kiri/mode/cam/topo3.js +++ b/src/kiri/mode/cam/topo3.js @@ -16,7 +16,7 @@ export class Topo { async generate(opt = {}) { let { state, contour, onupdate, ondone } = opt; - let { widget, settings, tshadow, center, tabs, color } = opt.state; + let { widget, settings, tshadow, tabs } = opt.state; let { controller, process } = settings, animesh = parseInt(controller.animesh || 100) * 2500, @@ -177,8 +177,7 @@ export class Topo { clipTabZ: clipTab ? clipTab.map(t => t.z) : undefined, tabHeight, newslices, - leave, - color + leave }, (i, l, p) => { onupdate(l / 2 + i / 2, l, p); }); @@ -304,7 +303,7 @@ export class Topo { const { minX, maxX, minY, maxY, boundsX, boundsY, stepsX, stepsY } = params; const { gridDelta, resolution, density, partOff, toolStep, contourX, contourY } = params; - const { clipTo, clipTab, clipTabZ, tabHeight, newslices, color, leave } = params; + const { clipTo, clipTab, clipTabZ, tabHeight, newslices, leave } = params; let stepsTaken = 0, stepsTotal = 0; @@ -370,11 +369,8 @@ export class Topo { gridy }, segments => { if (segments.length > 0) { - let slice = newSlice(gridx); + let slice = newSlice(x); slice.camLines = segments; - slice.output() - .setLayer("contour y", { face: color, line: color }) - .addPolys(segments); slicesY.push(slice); } onupdate(++stepsTaken, stepsTotal, "contour y"); @@ -399,11 +395,8 @@ export class Topo { gridy }, segments => { if (segments.length > 0) { - let slice = newSlice(gridy); + let slice = newSlice(y); slice.camLines = segments; - slice.output() - .setLayer("contour x", { face: color, line: color }) - .addPolys(segments); slicesX.push(slice); } onupdate(++stepsTaken, stepsTotal, "contour x"); diff --git a/src/main/kiri.js b/src/main/kiri.js index e21a7734..14ec062c 100644 --- a/src/main/kiri.js +++ b/src/main/kiri.js @@ -20,6 +20,7 @@ function safeExec(fn) { function checkReady() { if (document.readyState === 'complete') { + console.log(`kiri | boot ctrl | ` + (navigator.serviceWorker.controller ? true : false)); kiri.api = run(); self.$ = kiri.api.web.$; for (let fn of load) { diff --git a/web/kiri/index.css b/web/kiri/index.css index 5b39165b..aa19ea56 100644 --- a/web/kiri/index.css +++ b/web/kiri/index.css @@ -1376,6 +1376,8 @@ details[open] summary::after { #camops { display: flex; padding: 5px 0 0 0; + max-height: 70vh; + /* overflow-y: auto; */ } .cam-pop-op { top: 50%; From d7acc93872b268c23e53f1a0e45e592b3e9ba7bc Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 12 Oct 2025 19:23:28 -0400 Subject: [PATCH 10/11] fix overflowing ops lists and popup positioning --- src/kiri/mode/cam/client.js | 33 ++++++++++++++++++--------------- web/kiri/index.css | 10 +++++++--- web/kiri/index.html | 2 +- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/kiri/mode/cam/client.js b/src/kiri/mode/cam/client.js index aa847a64..8f6af172 100644 --- a/src/kiri/mode/cam/client.js +++ b/src/kiri/mode/cam/client.js @@ -320,6 +320,7 @@ export function opRender() { el.classList.add("disabled"); } bounds.push(el); + let parent = $('camops'); let timer = null; let inside = true; let popped = false; @@ -329,14 +330,14 @@ export function opRender() { } el.rec = rec; el.unpop = () => { - let pos = [...el.childNodes].indexOf(poprec.div); + let pos = [...parent.childNodes].indexOf(poprec.div); if (pos >= 0) { - el.removeChild(poprec.div); + parent.removeChild(poprec.div); } popped = false; }; function onEnter(ev) { - if ((surfaceOn || traceOn) && env.poppedRec != rec) { + if ((clock || surfaceOn || traceOn) && env.poppedRec != rec) { return; } if (popped && env.poppedRec != rec) { @@ -351,22 +352,24 @@ export function opRender() { popped = true; poprec.use(rec); env.hoveredOp = el; - if (!clock) { - // offset Y position of pop div by % of Y screen location of button - el.appendChild(poprec.div); - poprec.addNote(); - const { innerHeight } = window; - const brect = ev.target.getBoundingClientRect(); - const prect = poprec.div.getBoundingClientRect(); - const pcty = (brect.top / innerHeight) * 0.9; - const offpx = -pcty * prect.height; - poprec.div.style.transform = `translateY(${offpx}px)`; - } + // offset Y position of pop div by % of Y screen location of button + parent.appendChild(poprec.div); + poprec.addNote(); + const { innerHeight } = window; + const brect = ev.target.getBoundingClientRect(); + const prect = parent.getBoundingClientRect(); + const Prect = poprec.div.getBoundingClientRect(); + const tdiff = prect.top - brect.top; + const botoff = innerHeight - (brect.top + Prect.height); + const offpx = -tdiff + (botoff < 0 ? botoff : -Prect.height/3); + poprec.div.style.transform = `translateY(${offpx}px)`; + poprec.div.onmouseenter = () => { inside = true }; + poprec.div.onmouseleave = onLeave; // option click event appears latent // and overides the sticky settings setTimeout(() => { UC.setSticky(false); - }, 0); + }, 10); } function onLeave(ev) { inside = false; diff --git a/web/kiri/index.css b/web/kiri/index.css index aa19ea56..ad3b7705 100644 --- a/web/kiri/index.css +++ b/web/kiri/index.css @@ -1375,12 +1375,16 @@ details[open] summary::after { } #camops { display: flex; - padding: 5px 0 0 0; + padding: 0 0 0 0; +} +#oplist { max-height: 70vh; - /* overflow-y: auto; */ + min-height: 0; + overflow-y: auto; + padding-top: 1px; } .cam-pop-op { - top: 50%; + top: 0; right: calc(100% + 4px); text-align: left; position: absolute; diff --git a/web/kiri/index.html b/web/kiri/index.html index 2fcce519..598e6ad5 100644 --- a/web/kiri/index.html +++ b/web/kiri/index.html @@ -420,7 +420,7 @@
-
+
From 91fa194ab834407efccff577a53a6ae7756f817c Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 12 Oct 2025 19:25:06 -0400 Subject: [PATCH 11/11] bump rev 4.3.3 --- package.json | 2 +- src/moto/license.js | 2 +- web/kiri/manifest.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c344e3d8..1f9a9bca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grid-apps", - "version": "4.3.2", + "version": "4.3.3", "description": "grid.space 3d slicing & modeling tools", "author": "Stewart Allen ", "license": "MIT", diff --git a/src/moto/license.js b/src/moto/license.js index 62c0e58c..f3975212 100644 --- a/src/moto/license.js +++ b/src/moto/license.js @@ -3,7 +3,7 @@ const terms = { COPYRIGHT: "Copyright (C) Stewart Allen - All Rights Reserved", LICENSE: "See the license.md file included with the source distribution", - VERSION: "4.3.2" + VERSION: "4.3.3" }; export const beta = 0; diff --git a/web/kiri/manifest.json b/web/kiri/manifest.json index 80b2d2f8..0f24310a 100644 --- a/web/kiri/manifest.json +++ b/web/kiri/manifest.json @@ -1,5 +1,5 @@ { - "name": "Kiri:Moto 4.3.2", + "name": "Kiri:Moto 4.3.3", "short_name": "Kiri:Moto", "description": "Slicer for 3D printers, CNC mills, laser cutters and more", "start_url": "/kiri/",