add annotations necessary to allow object cancellation during print

This commit is contained in:
Stewart Allen 2025-02-13 17:44:55 -05:00
commit 4d6b72d81d
7 changed files with 103 additions and 23 deletions

View file

@ -14,14 +14,20 @@ const { getRangeParameters } = FDM;
const debug = false; const debug = false;
FDM.export = function(print, online, ondone, ondebug) { FDM.export = function(print, online, ondone, ondebug) {
const { settings, belty, tools, firstTool } = print; const { widgets, settings, belty, tools, firstTool } = print;
const { bounds, controller, device, process, filter, mode } = settings; const { bounds, controller, device, process, filter, mode } = settings;
const { extruders, fwRetract } = device; const { extruders, fwRetract } = device;
const { bedWidth, bedDepth, bedRound, bedBelt, maxHeight } = device; const { bedWidth, bedDepth, bedRound, bedBelt, maxHeight } = device;
const { gcodeFan, gcodeLayer, gcodeTrack, gcodePause, gcodeFeature } = device; const { gcodeFan, gcodeLayer, gcodeTrack, gcodePause, gcodeFeature } = device;
let model_labels = [];
for (let widget of widgets) {
model_labels.push(widget.track.grid_id);
}
let layers = print.output, let layers = print.output,
extras = device.extras || {}, extras = device.extras || {},
isBambu = extras.bbl,
{ extrudeAbs } = device, { extrudeAbs } = device,
{ exportThumb } = controller, { exportThumb } = controller,
extused = Object.keys(print.extruders).map(v => parseInt(v)), extused = Object.keys(print.extruders).map(v => parseInt(v)),
@ -108,7 +114,8 @@ FDM.export = function(print, online, ondone, ondebug) {
layers: layers.length, layers: layers.length,
progress: 0, progress: 0,
nozzle: tool, nozzle: tool,
tool: tool tool: tool,
model_labels: model_labels.sort().join(',')
}, },
pidx, path, out, speedMMM, emitMM, emitPerMM, lastp, laste, dist, pidx, path, out, speedMMM, emitMM, emitPerMM, lastp, laste, dist,
lines = 0, lines = 0,
@ -588,11 +595,36 @@ FDM.export = function(print, online, ondone, ondebug) {
moveTo({z:zpos}, seekMMM); moveTo({z:zpos}, seekMMM);
} }
function encodeOffset(index) {
let bytes = new Uint8Array(8);
let byteIndex = Math.floor(index / 8);
let bitPosition = index % 8;
bytes[byteIndex] |= (1 << bitPosition);
return btoa(String.fromCharCode(...bytes));
}
let cwidget;
// iterate through layer outputs // iterate through layer outputs
for (pidx=0; pidx<path.length; pidx++) { for (pidx=0; pidx<path.length; pidx++) {
out = path[pidx]; out = path[pidx];
speedMMM = (out.speed || process.outputFeedrate) * 60; // range speedMMM = (out.speed || process.outputFeedrate) * 60; // range
// hint to controller that we're working on a specific object
// so that gcode between start/stop comments can be cancelled
if (out.widget !== cwidget) {
if (cwidget) {
append(`; end object id: ${cwidget.track.grid_id}`);
isBambu && append('M625');
}
if (out.widget) {
let off = model_labels.indexOf(out.widget.track.grid_id);
let b64 = encodeOffset(off);
append(`; start object id: ${out.widget.track.grid_id}`);
isBambu && append(`M624 ${b64}`);
}
cwidget = out.widget;
}
// emit comment on output type chage // emit comment on output type chage
if (last && out.type !== last.type) { if (last && out.type !== last.type) {
lastType = subst.feature = out.type; lastType = subst.feature = out.type;
@ -791,6 +823,11 @@ FDM.export = function(print, online, ondone, ondebug) {
laste = out.emit; laste = out.emit;
} }
layer++; layer++;
if (cwidget) {
append(`; end object id: ${cwidget.track.grid_id}`);
isBambu && append('M625');
cwidget = undefined;
}
// end open loop when detected // end open loop when detected
while (endloop-- > 0) { while (endloop-- > 0) {
@ -949,6 +986,7 @@ FDM.export = function(print, online, ondone, ondebug) {
print.lines = lines; print.lines = lines;
print.bytes = bytes + lines - 1; print.bytes = bytes + lines - 1;
print.time = time; print.time = time;
print.labels = model_labels;
if (debug) { if (debug) {
console.log('segments', segments); console.log('segments', segments);

View file

@ -549,6 +549,7 @@ FDM.prepare = async function(widgets, settings, update) {
let beltStart = slice.belt && slice.belt.touch;// && (widgets.length === 1); let beltStart = slice.belt && slice.belt.touch;// && (widgets.length === 1);
// output seek to start point between mesh slices if previous data // output seek to start point between mesh slices if previous data
print.setType('layer'); print.setType('layer');
print.setWidget(lastWidget);
printPoint = slicePrintPath( printPoint = slicePrintPath(
print, print,
slice, slice,
@ -579,6 +580,7 @@ FDM.prepare = async function(widgets, settings, update) {
} }
} }
); );
print.setWidget(null);
lastOut = slice; lastOut = slice;
lastExt = lastOut.extruder; lastExt = lastOut.extruder;

View file

@ -63,6 +63,19 @@ FDM.sliceAll = function(settings, onupdate) {
.sort((a,b) => { .sort((a,b) => {
return a.slices[0].z - b.slices[0].z return a.slices[0].z - b.slices[0].z
}); });
// assign grid_id which can be embedded in gcode and
// used by the controller to cancel objects during print
let { bounds } = settings;
for (let widget of widgets) {
let { pos, box } = widget.track;
// calculate top/left coordinate for widget
// relative to bounding box for all widgets
let tl = {
x: Math.round((pos.x - box.w/2 - bounds.min.x) / 10) + 1,
y: Math.round((pos.y - box.h/2 - bounds.min.y) / 10) + 1
};
widget.track.grid_id = tl.x * 100 + tl.y;
}
// count extruders used // count extruders used
let ext = []; let ext = [];
for (let w of widgets) { for (let w of widgets) {

View file

@ -494,15 +494,29 @@ kiri.worker = {
send.data({debug}); send.data({debug});
}); });
const { const {
bounds, time, lines, bytes, distance, bounds,
settings, segments, purges time,
lines,
bytes,
distance,
settings,
segments,
purges,
labels
} = current.print; } = current.print;
send.done({ send.done({
done: true, done: true,
output: output ? output : { output: output ? output : {
bounds, time, lines, bytes, distance, bounds,
settings, segments, purges time,
lines,
bytes,
distance,
settings,
segments,
purges,
labels
} }
}); });
}, },

View file

@ -529,7 +529,11 @@ function exportGCodeDialog(gcode, sections, info, names) {
api.bambu.prep_export(gen3mf, gcode, info, settings); api.bambu.prep_export(gen3mf, gcode, info, settings);
} }
function gen3mf(then, ptype = 'unknown') { // let wids = api.widgets.all();
// let bnds = settings.bounds;
// console.log({ wids, bnds });
function gen3mf(then, ptype = 'unknown', ams = [0]) {
let now = new Date(); let now = new Date();
let ymd = [ let ymd = [
now.getFullYear(), now.getFullYear(),
@ -582,28 +586,28 @@ function exportGCodeDialog(gcode, sections, info, names) {
' <Relationship Target="/Metadata/plate_1.gcode" Id="rel-1" Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/gcode"/>', ' <Relationship Target="/Metadata/plate_1.gcode" Id="rel-1" Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/gcode"/>',
'</Relationships>' '</Relationships>'
].join('\n') ].join('\n')
},{ // },{
// name: `Metadata/plate_1.json`, // name: `Metadata/plate_1.json`,
// data: JSON.toString({ // data: JSON.stringify({
// "bbox_all": [ 115.199992, 115.199992, 140.799992, 140.799992 ], // "bbox_all": [ 100, 100, 200, 200 ],
// "bbox_objects": [ // "bbox_objects": (info.labels || []).map(label => {
// { // return {
// "area": 655.3599853515625, // area: 600,
// "bbox": [ 115.199992, 115.199992, 140.799992, 140.799992 ], // bbox: [ 100, 100, 200, 200 ],
// "id": 42, // id: label,
// "layer_height": 0.25, // layer_height: 0.2,
// "name": "Cube" // name: "Object"
// } // }
// ], // }),
// "bed_type": "textured_plate", // "bed_type": "textured_plate",
// "filament_colors": ["#FFFFFF"], // "filament_colors": ["#FFFFFF"],
// "filament_ids": [0], // "filament_ids": ams,
// "first_extruder": 0, // "first_extruder": ams[0],
// "is_seq_print": false, // "is_seq_print": false,
// "nozzle_diameter": 0.6, // "nozzle_diameter": 0.6,
// "version": 2 // "version": 2
// }) // })
// },{ },{
name: `Metadata/model_settings.config`, name: `Metadata/model_settings.config`,
data: [ data: [
'<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-8"?>',
@ -639,12 +643,13 @@ function exportGCodeDialog(gcode, sections, info, names) {
' <metadata key="outside" value="false"/>', ' <metadata key="outside" value="false"/>',
' <metadata key="support_used" value="false"/>', ' <metadata key="support_used" value="false"/>',
' <metadata key="label_object_enabled" value="false"/>', ' <metadata key="label_object_enabled" value="false"/>',
// ' <object identify_id="560" name="Cube" skipped="false" />', (info.labels || []).map(label =>
` <object identify_id="${label}" name="Object" skipped="false" />`),
// ' <filament id="1" tray_info_idx="GFL96" type="PLA" color="#FFFFFF" used_m="0.17" used_g="0.50" />', // ' <filament id="1" tray_info_idx="GFL96" type="PLA" color="#FFFFFF" used_m="0.17" used_g="0.50" />',
// ' <warning msg="bed_temperature_too_high_than_filament" level="1" error_code ="1000C001" />', // ' <warning msg="bed_temperature_too_high_than_filament" level="1" error_code ="1000C001" />',
' </plate>', ' </plate>',
'</config>' '</config>'
].join('\n') ].filter(v => v).flat().join('\n')
},{ },{
name: `Metadata/project_settings.config`, name: `Metadata/project_settings.config`,
data: JSON.stringify({},undefined,4) data: JSON.stringify({},undefined,4)

View file

@ -35,6 +35,12 @@ class Print {
this.nextType = type; this.nextType = type;
} }
// allows for gcode object id annotations enabling
// discrete object cancellation during print (bambu)
setWidget(widget) {
this.widget = widget;
}
addOutput(array, point, emit, speed, tool, type) { addOutput(array, point, emit, speed, tool, type) {
let { lastPoint, lastEmit, lastOut } = this; let { lastPoint, lastEmit, lastOut } = this;
// drop duplicates (usually intruced by FDM bisections) // drop duplicates (usually intruced by FDM bisections)
@ -52,6 +58,7 @@ class Print {
if (tool !== undefined) { if (tool !== undefined) {
this.tools[tool] = true; this.tools[tool] = true;
} }
lastOut.widget = this.widget;
array.push(lastOut); array.push(lastOut);
this.nextType = undefined; this.nextType = undefined;
return lastOut; return lastOut;

View file

@ -212,6 +212,7 @@ details[open] summary::after {
transform: rotate(90deg); transform: rotate(90deg);
} }
/* for bambu mgr dialog */
.video { .video {
border: 1px solid #888; border: 1px solid #888;
border-radius: 3px; border-radius: 3px;