Merge branch 'rel-4.5'

This commit is contained in:
Stewart Allen 2025-12-22 22:14:37 -05:00
commit 21add65252
12 changed files with 274 additions and 239 deletions

View file

@ -150,7 +150,7 @@ module.exports = async (server) => {
}
async function ftp_open(args = {}) {
const client = new Client();
const client = new Client(300000); // 5 minute timeout for large files
const port = parseInt(args.port || 990);
const host = args.host || "localhost";
const user = args.user || "bblp";

View file

@ -55,14 +55,14 @@
"hexer": "^1.5.0",
"i": "^0.3.7",
"jszip": "^3.7.1",
"manifold-3d": "^3.2.1",
"manifold-3d": "^3.3.2",
"moment": "^2.29.4",
"mqtt": "^5.10.3",
"npm": "^11.4.2",
"prettier": "^3.5.3",
"react-responsive-carousel": "^3.2.23",
"serve-static": "^2.2.0",
"three": "^0.178.0",
"three": "^0.182.0",
"three-mesh-bvh": "^0.7.6",
"uglify-js": "3.14.5",
"validator": ">=13.15.23",

View file

@ -126,6 +126,18 @@ class Point {
return this;
}
/**
* Swap X and Y coordinates in place
* @returns {Point} This point (for chaining)
*/
swapXY() {
let p = this,
t = p.x;
p.x = p.y;
p.y = t;
return this;
}
/**
* Swap X and Z coordinates in place
* @returns {Point} This point (for chaining)

View file

@ -76,6 +76,9 @@ function device_from_code(code,mode) {
// presence of internal field indicates already converted
if (code.internal >= 0) return code;
// presence of nested code field indicates newer encoding
if (code.code) return code.code;
// if (self.navigator) console.log({mode, convert: code});
let cmd = code.cmd || {},
set = code.settings || {},

View file

@ -117,6 +117,7 @@ function setDeviceCode(code, devicename) {
api.event.emit('device.select', devicename);
try {
if (typeof(code) === 'string') code = js2o(code) || {};
if (code.code) code = code.code;
let mode = api.mode.get(),
lmode = mode.toLowerCase(),

View file

@ -1772,6 +1772,7 @@ function init_two() {
};
$('context-contents').onclick = () => { api.SPACE.view.fit() };
$('view-fit').onclick = () => { api.SPACE.view.fit() };
$('wassup').onmouseover = () => { $('suppopp').classList.remove('hide') };
// ui.modal.onclick = api.modal.hide;
ui.modalBox.onclick = (ev) => { ev.stopPropagation() };

View file

@ -0,0 +1,186 @@
{
"mode": "FDM",
"internal": 0,
"bedHeight": 2.5,
"bedWidth": 220,
"bedDepth": 220,
"bedRound": false,
"bedBelt": false,
"deviceZMax": 0,
"gcodeTime": 1,
"maxHeight": 220,
"originCenter": true,
"gcodeFan": [
"M106 S{fan_speed}"
],
"gcodeFeature": [],
"gcodeTrack": [],
"gcodeLayer": [
";LAYER_CHANGE {layer} of {layers}",
";; IF { layer === 0 }",
"SET_VELOCITY_LIMIT ACCEL=500",
";; ELSE",
"SET_VELOCITY_LIMIT ACCEL=10000",
";; END"
],
"gcodePre": [
"; HEADER_BLOCK_START",
"; total layer number: {layers}",
"; max_z_height: {z_max}",
"; HEADER_BLOCK_END",
"; EXECUTABLE_BLOCK_START",
"M73 P0 R5",
"M106 S0",
"M106 P2 S0",
"M190 S55",
"M104 S220",
"G90",
"M83",
"G1 Z5 F6000",
"G1 E-0.2 F800",
"G1 X110 Y-110 F6000",
"G1 E2 F800",
"G1 Y-110 X55 Z0.25 F4800",
"G1 X-55 E8 F2400",
"M73 P1 R5",
"G1 Y-109.6 F2400",
"M73 P1 R5",
"G1 X55 E5 F2400",
"M73 P2 R5",
"G1 Y-110 X55 Z0.45 F4800",
"M73 P2 R5",
"G1 X-55 E8 F2400",
"M73 P3 R5",
"G1 Y-109.6 F2400",
"M73 P3 R5",
"G1 X55 E5 F2400",
"G92 E0",
"G90",
"G21",
"M83 ; use relative distances for extrusion",
"SET_PRESSURE_ADVANCE ADVANCE=0.025; Override pressure advance value",
"M106 S0",
"M106 P2 S0"
],
"gcodePost": [
"M107",
"M104 S0",
"M140 S0",
"M106 S0",
"M106 P2 S0",
"G1 E-3 F3600",
"G0 X50 Y50 F30000",
"; EXECUTABLE_BLOCK_END"
],
"gcodeProc": "",
"gcodeChange": [],
"gcodeFExt": "gcode",
"extruders": [
{
"extFilament": 1.75,
"extNozzle": 0.4,
"extOffsetX": 0,
"extOffsetY": 0
}
],
"new": false,
"deviceName": "Flashforge Adventurer 5M",
"imageURL": "",
"fwRetract": false,
"filamentSource": "direct",
"profiles": [
{
"processName": "Standard PLA",
"sliceHeight": 0.25,
"sliceShells": 3,
"sliceShellOrder": "out-in",
"sliceLayerStart": "last",
"sliceFillAngle": 45,
"sliceFillOverlap": 0.4,
"sliceFillSparse": 0.1,
"sliceFillType": "linear",
"sliceAdaptive": false,
"sliceMinHeight": 0,
"sliceSupportDensity": 0.2,
"sliceSupportOffset": 0.4,
"sliceSupportGap": 1,
"sliceSupportSize": 5,
"sliceSupportArea": 0.25,
"sliceSupportExtra": 0,
"sliceSupportAngle": 60,
"sliceSupportNozzle": 0,
"sliceSolidMinArea": 0,
"sliceBottomLayers": 2,
"sliceTopLayers": 2,
"firstLayerRate": 20,
"firstLayerYOffset": 0,
"firstLayerBrim": 0,
"firstLayerBeltLead": 0,
"firstLayerFanSpeed": 0,
"outputTemp": 220,
"outputBedTemp": 65,
"outputFanSpeed": 255,
"outputFeedrate": 120,
"outputFinishrate": 70,
"outputSeekrate": 200,
"outputShellMult": 1.21,
"outputFillMult": 1.18,
"outputSparseMult": 1.25,
"outputRetractDist": 1.3,
"outputRetractSpeed": 30,
"outputRetractWipe": 0,
"outputRetractDwell": 5,
"outputShortPoly": 0,
"outputMinSpeed": 1,
"outputCoastDist": 0,
"outputLayerRetract": false,
"zHopDistance": 0,
"antiBacklash": 0.1,
"sliceFillWidth": 1,
"sliceSupportEnable": false,
"firstSliceHeight": 0.3,
"firstLayerFillRate": 40,
"firstLayerNozzleTemp": 220,
"firstLayerBedTemp": 65,
"firstLayerBrimTrig": 0,
"firstLayerBrimGap": 0,
"outputRaft": false,
"outputRaftSpacing": 0.2,
"outputBrimCount": 2,
"outputBrimOffset": 2,
"outputPurgeTower": 0,
"outputInvertX": false,
"outputInvertY": false,
"arcTolerance": 0.2,
"ranges": [],
"sliceLineWidth": 0,
"sliceFillRepeat": 2,
"firstLayerBrimIn": 0,
"firstLayerBeltBump": 0,
"outputBeltFirst": false,
"outputLoops": 0,
"sliceFillGrow": 0,
"sliceSupportSpan": 5,
"sliceSupportOutline": false,
"firstLayerFlatten": 0,
"outputDraftShield": false,
"outputAvoidGaps": true,
"sliceDetectThin": "basic",
"outputAlternating": false,
"sliceLayerStartX": 0,
"sliceLayerStartY": 0,
"sliceSupportGrow": 0,
"outputFanLayer": 1,
"sliceAngle": 45,
"sliceZInterleave": false,
"outputScarfLength": 9,
"outputMinLayerTime": 9,
"sliceCompInner": 0,
"sliceCompOuter": 0,
"outputMaxFlowrate": 15,
"firstLayerBeltFact": 1,
"sliceSolidify": false
}
],
"extras": {}
}

View file

@ -1,219 +0,0 @@
{
"version": "4.2.3",
"device": "Flashforge 5M Pro",
"process": {
"processName": "Flashforge 5m Pro .2 Height",
"sliceHeight": 0.2,
"sliceShells": 3,
"sliceShellOrder": "in-out",
"sliceLayerStart": "last",
"sliceFillAngle": 45,
"sliceFillOverlap": 0.6,
"sliceFillSparse": 0.08,
"sliceFillRate": 300,
"sliceFillType": "hex",
"sliceSupportDensity": 0.2,
"sliceSupportOffset": 1,
"sliceSupportGap": 1,
"sliceSupportSize": 5,
"sliceSupportArea": 10,
"sliceSupportExtra": 3,
"sliceSupportAngle": 50,
"sliceSupportNozzle": "0",
"sliceSupportEnable": false,
"sliceSolidMinArea": 1.2,
"sliceBottomLayers": 2,
"sliceTopLayers": 2,
"firstSliceHeight": 0.2,
"firstLayerRate": 30,
"firstLayerFillRate": 40,
"firstLayerPrintMult": 1,
"firstLayerLineMult": 1,
"firstLayerYOffset": 0,
"firstLayerNozzleTemp": 205,
"firstLayerBedTemp": 56,
"firstLayerBrim": 0,
"firstLayerBrimTrig": 0,
"firstLayerBeltLead": 3,
"outputRaft": false,
"outputRaftSpacing": 0.2,
"outputTemp": 205,
"outputBedTemp": 56,
"outputFeedrate": 500,
"outputFinishrate": 250,
"outputSeekrate": 500,
"outputShellMult": 1.25,
"outputFillMult": 1.25,
"outputSparseMult": 1.3,
"outputRetractDist": 4,
"outputRetractSpeed": 40,
"outputRetractDwell": 20,
"outputBrimCount": 2,
"outputBrimOffset": 4,
"outputShortPoly": 100,
"outputMinSpeed": 10,
"outputCoastDist": 0,
"outputLayerRetract": false,
"outputInvertX": false,
"outputInvertY": false,
"sliceMinHeight": 0,
"sliceAdaptive": false,
"zHopDistance": 0.2,
"antiBacklash": 1,
"sliceFillWidth": 1,
"firstLayerFanSpeed": 0,
"outputFanSpeed": 255,
"outputRetractWipe": 4,
"outputPurgeTower": 0,
"arcTolerance": 0.15,
"ranges": [],
"sliceLineWidth": 0,
"sliceFillRepeat": 1,
"sliceSupportSpan": 5,
"sliceSupportOutline": false,
"firstLayerBrimIn": 0,
"firstLayerBrimGap": 0,
"firstLayerBeltBump": 0,
"firstLayerFlatten": 0,
"outputDraftShield": false,
"outputBeltFirst": false,
"outputAvoidGaps": true,
"outputLoops": 0,
"sliceFillGrow": 0,
"sliceSolidRate": 200,
"outputAlternating": false,
"sliceDetectThin": "off",
"sliceLayerStartX": 0,
"sliceLayerStartY": 0,
"sliceSupportGrow": 3,
"sliceAngle": 45,
"outputFanLayer": 1,
"sliceZInterleave": false
},
"code": {
"mode": "FDM",
"internal": 0,
"bedHeight": 2.5,
"bedWidth": 225,
"bedDepth": 225,
"bedRound": false,
"bedBelt": false,
"deviceZMax": 0,
"gcodeTime": 1,
"maxHeight": 225,
"originCenter": true,
"gcodeFan": [
"M106 S{fan_speed}"
],
"gcodeFeature": [],
"gcodeTrack": [],
"gcodeLayer": [
";AFTER_LAYER_CHANGE",
";[layer_z]"
],
"gcodePre": [
"; EXECUTABLE_BLOCK_START",
"M73 P0 R80",
"M106 S0",
"M106 P2 S0",
";TYPE:Custom",
"M190 S55",
"M104 S210",
"G90",
"M83",
"G1 Z5 F6000",
"G1 E-0.2 F800",
"G1 X110 Y-110 F6000",
"G1 E2 F800",
"G1 Y-110 X55 Z0.25 F4800",
"G1 X-55 E8 F2400",
"G1 Y-109.6 F2400",
"G1 X55 E5 F2400",
"G1 Y-110 X55 Z0.45 F4800",
"G1 X-55 E8 F2400",
"G1 Y-109.6 F2400",
"G1 X55 E5 F2400",
"G92 E0",
"G90",
"G21",
"M83 ; use relative distances for extrusion",
"; filament start gcode",
";right_extruder_material: PLA",
"SET_PRESSURE_ADVANCE ADVANCE=0; Override pressure advance value",
"M106 S0",
"M106 P2 S0",
";LAYER_CHANGE",
";Z:0.2",
";HEIGHT:0.2",
";BEFORE_LAYER_CHANGE",
";0.2",
"G1 E-.8 F2100",
";AFTER_LAYER_CHANGE",
";0.2",
";_SET_FAN_SPEED_CHANGING_LAYER",
"SET_VELOCITY_LIMIT ACCEL=500",
"G1 X-25.945 Y-17.607 F30000",
"G1 Z.4",
"G1 Z.2",
"G1 E.8 F2100"
],
"gcodePost": [
"M106 S0",
"M106 P2 S0",
";TYPE:Custom",
"; filament end gcode",
"G1 E-3 F3600",
"G0 X50 Y50 F30000",
"M104 S0 ; turn off temperature",
"M73 P100 R0"
],
"gcodeProc": "",
"gcodeFExt": "gcode",
"extruders": [
{
"extFilament": 1.75,
"extNozzle": 0.4,
"extSelect": [
"T0"
],
"extDeselect": [],
"extOffsetX": 0,
"extOffsetY": 0
},
{
"extFilament": 1.75,
"extNozzle": 0.4,
"extSelect": [
"T1"
],
"extDeselect": [],
"extOffsetX": 30,
"extOffsetY": 0
}
],
"new": false,
"deviceName": "Flashforge 5M Pro",
"imageURL": "",
"fwRetract": true,
"filamentSource": "direct",
"profiles": [],
"extras": {
"palette": {
"printer": "6806c3eabbdb",
"ping": null,
"feed": null,
"push": null,
"offset": null,
"heat": null,
"cool": null,
"press": null
}
},
"gcodeChange": [
"T{tool}"
]
},
"time": 1756051792656,
"mode": "FDM",
"name": "Flashforge 5m Pro .2 Height"
}

View file

@ -33,7 +33,7 @@ export class Topo {
minY = bounds.min.y,
maxY = bounds.max.y,
zBottom = contour.bottom ? workarea.bottom_z : 0,
zMin = workarea.bottom_z + 0.0001, //Math.max(bounds.min.z, zBottom) + 0.0001,
zMin = workarea.bottom_z + 0.0001,
boundsX = maxX - minX,
boundsY = maxY - minY,
inside = contour.inside,
@ -182,10 +182,7 @@ export class Topo {
for (let i=0; i<numScanlines; i++) {
let lineStart = i * pointsPerLine;
let lineData = pathData.slice(lineStart, lineStart + pointsPerLine);
let points = contourY
? Array.from(lineData).map((v,j) => calcPoint(i * ymult + yoff, j * xmult + xoff, v, i * xStep, j * yStep))
: Array.from(lineData).map((v,j) => calcPoint(j * xmult + xoff, i * ymult + yoff, v, j * xStep, i * yStep))
;
let points = Array.from(lineData).map((v,j) => calcPoint(j * xmult + xoff, i * ymult + yoff, v, j * xStep, i * yStep));
let slice = newSlice(i);
let poly = newPolygon().setOpen();
let lines = [ ];
@ -228,6 +225,12 @@ export class Topo {
if (poly.length > 1) {
lines.push(poly);
}
if (contourY) {
for (let poly of lines)
for (let p of poly.points) {
p.swapXY();
}
}
// raise output points when inside tab boundaries
if (!inside && tabsOn && clipTab.length)
for (let poly of lines) {
@ -471,7 +474,8 @@ export class Topo {
...params,
box,
lines: rec.lines,
gridx: rec.index
gridx: rec.index,
slice
});
return slice;
@ -654,7 +658,6 @@ export class Probe {
let iy = Math.round(ry * (py - minY));
return data[ix * stepsY + iy] || zMin;
};
}
}
@ -845,7 +848,7 @@ export class Trace {
checkr.y = y;
// when tabs are on and this point is inside the
// tab polygon, ensure z is at least tabHeight
if (clipTab && tv < tabHeight && inClip(clipTab, tv, checkr)) {
if (clipTab && clipTab.length && tv < tabHeight && inClip(clipTab, tv, checkr)) {
tv = this.tabZ;
}
// if the value is on the floor and inside the clip
@ -883,7 +886,7 @@ export class Trace {
checkr.y = y;
// when tabs are on and this point is inside the
// tab polygon, ensure z is at least tabHeight
if (clipTab && tv < tabHeight && inClip(clipTab, tv, checkr)) {
if (clipTab && clipTab.length && tv < tabHeight && inClip(clipTab, tv, checkr)) {
tv = this.tabZ;
}
// if the value is on the floor and inside the clip

View file

@ -254,6 +254,7 @@ const funcs = self.minion = {
trace_y(data, seq) {
const { trace } = cache.trace;
trace.crossY_sync(data.params, slice => {
// console.log('w',slice);
slice = codec.encode(slice);
reply({ seq, slice });
});

View file

@ -801,6 +801,39 @@ details[open] summary::after {
.mt10 {
margin-top: 5px;
}
#wassup {
background-color: rgba(0,255,100,0.3);
border-top: 5px solid rgba(0,255,100,0.5);
border-bottom: 5px solid rgba(0,255,100,0.5);
}
#wassup:hover {
border-top: 5px solid rgba(0,255,100,0.5);
border-bottom: 5px solid rgba(0,255,100,0.5);
}
.dark #wassup {
background-color: rgba(0,255,0,0.2);
}
.blurb {
max-width: 200px;
align-items: flex-end;
justify-content: center;
text-align: right;
padding: 10px 0 10px 0;
color: var(--blue-2);
gap: 10px;
}
.blurb p {
margin: 0;
}
.dark .blurb p:first-child, .dark .blurb p:last-child {
color: #fff;
}
.blurb p:first-child, .blurb p:last-child {
color: #000;
}
.mlr-10 {
margin: 0 10px 0 10px;
}
#curtain {
top: 0;

View file

@ -512,14 +512,28 @@
<label>Kiri:Moto Help</label>
</div>
<hr width="100%">
<div class="f-col">
<a target="_rsc" href="https://docs.grid.space/projects/kiri-moto"><i class="fas fa-question-circle"></i>Documentation & APIs</a>
<a target="_rsc" href="https://forum.grid.space"><i class="fab fa-discourse"></i> Discourse Forums</a>
<a target="_rsc" href="https://discord.gg/suyCCgr"><i class="fab fa-discord"></i> Discord Server</a>
<a target="_rsc" href="https://github.com/gridspace/grid-apps/issues"><i class="fas fa-bug"></i> Bug Reports</a>
<a target="_rsc" href="https://github.com/gridspace/grid-apps/releases"><i class="fab fa-github"></i> Releases & Binaries</a>
<a target="_rsc" onclick="kiri.api.modal.show('don8')"><i class="fa-solid fa-sack-dollar"></i> Support Development</a>
<a href="https://youtu.be/08795Sj22QE" target="youtube"><i class="fab fa-youtube"></i>Video Guide (from v2.5)</a>
<div class="f-row">
<div class="f-col">
<a target="_rsc" href="https://docs.grid.space/projects/kiri-moto"><i class="fas fa-question-circle"></i>Documentation & APIs</a>
<a target="_rsc" href="https://forum.grid.space"><i class="fab fa-discourse"></i> Discourse Forums</a>
<a target="_rsc" href="https://discord.gg/suyCCgr"><i class="fab fa-discord"></i> Discord Server</a>
<a target="_rsc" href="https://github.com/gridspace/grid-apps/issues"><i class="fas fa-bug"></i> Bug Reports</a>
<a href="https://youtu.be/08795Sj22QE" target="youtube"><i class="fab fa-youtube"></i>Video Guide (v2.5)</a>
<a target="_rsc" href="https://github.com/gridspace/grid-apps/releases"><i class="fab fa-github"></i> Releases & Binaries</a>
<a target="_rsc" id="wassup" onclick="kiri.api.modal.show('don8')"><i class="fa-solid fa-hand-holding-dollar"></i> Support Development</a>
</div>
<div id="suppopp" class="content hide">
<hr class="mlr-10">
<div class="f-col blurb">
<p>14 Years Under<br>Active Development</p>
<span class="grow"></span>
<p>A project for makers, hobbyist, professionals, students, and educators</p>
<span class="grow"></span>
<p>Help keep it free. Ask about Institutional support</p>
<span class="grow"></span>
<p>Support funds continued development, bug fixes, documentation, and discussion forums</p>
</div>
</div>
</div>
<hr width="100%">
<div class="f-row j-center">