add CAM custom gcode operator
This commit is contained in:
parent
bc3e738a8d
commit
c67d641e43
10 changed files with 94 additions and 14 deletions
15
notes.md
15
notes.md
|
|
@ -74,34 +74,35 @@
|
||||||
* `B` need to force cut line at synthetic z bottom (midlines, etc)
|
* `B` need to force cut line at synthetic z bottom (midlines, etc)
|
||||||
* `B` contour does not honor clip to stock
|
* `B` contour does not honor clip to stock
|
||||||
|
|
||||||
|
* `F` add custom gcode operation for things like injecting pauses
|
||||||
|
* `F` add optional hover notes or titles to help visually differentiate dup ops
|
||||||
* `F` all ops should allow limit and milling direction / ease down overrides
|
* `F` all ops should allow limit and milling direction / ease down overrides
|
||||||
* `F` drill op should allow selecting holes >= current tool
|
* `F` drill op should allow selecting holes >= current tool
|
||||||
* `F` intelligently turn circle hole pocket clear into spiral down
|
* `F` intelligently turn circle hole pocket clear into spiral down
|
||||||
* `F` separate leveling op. add features like uni-directional cutting
|
* `F` separate leveling op. add features like uni-directional cutting
|
||||||
* `F` add custom gcode operation for things like injecting pauses
|
|
||||||
* `F` add option for op-major ordering (instead of part major)
|
* `F` add option for op-major ordering (instead of part major)
|
||||||
* `F` animate only selected range (as an option)
|
* `F` animate only selected range (as an option)
|
||||||
* `F` add `plunge max` to contouring that can override z feed limit
|
* `F` add `plunge max` to contouring that can override z feed limit
|
||||||
* `F` add ability to select regions for contouring op (like pocketing)
|
* `F` add ability to select regions for contouring op (like pocketing)
|
||||||
* `F` roughing flats should be constrained to flat region, not create a new layer
|
|
||||||
* `F` limit cut depth to flute length of selected tool (or warn)
|
|
||||||
* `F` change color of line selection in trace op when not a closed poly
|
|
||||||
* `F` add lead-in milling (requires adding clamp / no go areas)
|
* `F` add lead-in milling (requires adding clamp / no go areas)
|
||||||
* `F` add linear clearing strategy
|
* `F` add linear clearing strategy
|
||||||
* `F` add adaptive clearing strategy
|
* `F` add adaptive clearing strategy
|
||||||
* `F` add ease-down support to trace op
|
* `F` add ease-down support to trace op
|
||||||
* `F` user-defined origin (issue #28)
|
|
||||||
* `F` add climb/conventional into each operation
|
* `F` add climb/conventional into each operation
|
||||||
|
* `F` add lathe mode / A-axis / 4th axis / rotary milling ops
|
||||||
|
* `F` add support for tapered ball mills
|
||||||
|
* `F` roughing flats should be constrained to flat region, not create a new layer
|
||||||
|
* `F` change color of line selection in trace op when not a closed poly
|
||||||
|
* `F` limit cut depth to flute length of selected tool (or warn)
|
||||||
|
* `F` user-defined origin (issue #28)
|
||||||
* `F` validate muti-part layout and spacing exceeds largest outside tool diameter
|
* `F` validate muti-part layout and spacing exceeds largest outside tool diameter
|
||||||
* `F` parameterize dropping close points in prep.js. ensure long segments remain straight
|
* `F` parameterize dropping close points in prep.js. ensure long segments remain straight
|
||||||
* `F` flat and volumetric rendering of paths
|
* `F` flat and volumetric rendering of paths
|
||||||
* `F` z planar settings visualizations (edit using snappable dragging of planes)
|
* `F` z planar settings visualizations (edit using snappable dragging of planes)
|
||||||
* `F` trapezoidal tabs in Z
|
* `F` trapezoidal tabs in Z
|
||||||
* `F` add support for tapered ball mills
|
|
||||||
* `F` ease-in and ease-out especially on tab cut-out start/stop
|
* `F` ease-in and ease-out especially on tab cut-out start/stop
|
||||||
* `F` add option to spiral in vs out (optimal tool life) vs mixed (optimal path)
|
* `F` add option to spiral in vs out (optimal tool life) vs mixed (optimal path)
|
||||||
* `F` can animation clear the mesh in areas where the cuts go through the stock?
|
* `F` can animation clear the mesh in areas where the cuts go through the stock?
|
||||||
* `F` add lathe mode / A-axis / 4th axis / rotary milling ops
|
|
||||||
* `F` gcode output option as zip for multiple or flip ops or tool change
|
* `F` gcode output option as zip for multiple or flip ops or tool change
|
||||||
* `F` maintain several part orientations + op chains in a single profile
|
* `F` maintain several part orientations + op chains in a single profile
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
|
||||||
* add CAM pocket option to ignore interior features (outline only)
|
* add CAM pocket option to ignore interior features (outline only)
|
||||||
* add CAM Z bottom visualization, make it relative to stock instead of part
|
* add CAM Z bottom visualization, make it relative to stock instead of part
|
||||||
* add CAM z bottom inversion option to flip operator
|
* add CAM z bottom inversion option to flip operator
|
||||||
|
* add CAM custom gcode operator
|
||||||
* extend url loading of workspaces to all formats
|
* extend url loading of workspaces to all formats
|
||||||
* alert when healing is enabled and non-manifold geometries are detected
|
* alert when healing is enabled and non-manifold geometries are detected
|
||||||
* fix thin output start and end point tracking which broke retraction
|
* fix thin output start and end point tracking which broke retraction
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ CAM.init = function(kiri, api) {
|
||||||
let settings = API.conf.get();
|
let settings = API.conf.get();
|
||||||
let { process, device } = settings;
|
let { process, device } = settings;
|
||||||
switch (ev.target.innerText) {
|
switch (ev.target.innerText) {
|
||||||
|
case "gcode": return func.opAddGCode();
|
||||||
case "level": return func.opAddLevel();
|
case "level": return func.opAddLevel();
|
||||||
case "rough": return func.opAddRough();
|
case "rough": return func.opAddRough();
|
||||||
case "outline": return func.opAddOutline();
|
case "outline": return func.opAddOutline();
|
||||||
|
|
@ -195,6 +196,10 @@ CAM.init = function(kiri, api) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
func.opAddGCode = () => {
|
||||||
|
func.opAdd(popOp.gcode.new());
|
||||||
|
};
|
||||||
|
|
||||||
func.opAddLevel = () => {
|
func.opAddLevel = () => {
|
||||||
func.opAdd(popOp.level.new());
|
func.opAdd(popOp.level.new());
|
||||||
};
|
};
|
||||||
|
|
@ -421,6 +426,25 @@ CAM.init = function(kiri, api) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
func.opGCode = () => {
|
||||||
|
API.dialog.show('any');
|
||||||
|
const { c_gcode } = h.bind(
|
||||||
|
$('mod-any'), h.div({ id: "camop_dialog" }, [
|
||||||
|
h.label('custom gcode operation'),
|
||||||
|
h.textarea({ id: "c_gcode", rows: 15, cols: 50 }),
|
||||||
|
h.button({ _: 'done', onclick: () => {
|
||||||
|
API.dialog.hide();
|
||||||
|
API.conf.save();
|
||||||
|
} })
|
||||||
|
])
|
||||||
|
);
|
||||||
|
c_gcode.value = poppedRec.gcode || '';
|
||||||
|
c_gcode.onkeyup = (el) => {
|
||||||
|
poppedRec.gcode = c_gcode.value;
|
||||||
|
};
|
||||||
|
c_gcode.focus();
|
||||||
|
};
|
||||||
|
|
||||||
func.opFlip = () => {
|
func.opFlip = () => {
|
||||||
let widgets = API.widgets.all();
|
let widgets = API.widgets.all();
|
||||||
let { process } = current;
|
let { process } = current;
|
||||||
|
|
@ -932,6 +956,12 @@ CAM.init = function(kiri, api) {
|
||||||
return current.device.spindleMax > 0;
|
return current.device.spindleMax > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createPopOp('gcode', {
|
||||||
|
gcode: 'camCustomGcode',
|
||||||
|
}).inputs = {
|
||||||
|
action: UC.newRow([ UC.newButton(LANG.edit, func.opGCode) ], {class:"ext-buttons f-row"})
|
||||||
|
};
|
||||||
|
|
||||||
createPopOp('level', {
|
createPopOp('level', {
|
||||||
tool: 'camLevelTool',
|
tool: 'camLevelTool',
|
||||||
spindle: 'camLevelSpindle',
|
spindle: 'camLevelSpindle',
|
||||||
|
|
|
||||||
|
|
@ -275,9 +275,11 @@ CAM.export = function(print, online) {
|
||||||
|
|
||||||
// collect tool info to add to header
|
// collect tool info to add to header
|
||||||
let toolz = {}, ctool;
|
let toolz = {}, ctool;
|
||||||
|
|
||||||
// remap points as necessary for origins, offsets, inversions
|
// remap points as necessary for origins, offsets, inversions
|
||||||
print.output.forEach(function(layer) {
|
print.output.forEach(function(layer) {
|
||||||
|
if (!Array.isArray(layer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
layer.forEach(function(out) {
|
layer.forEach(function(out) {
|
||||||
if (out.tool && out.tool !== ctool) {
|
if (out.tool && out.tool !== ctool) {
|
||||||
ctool = toolByNumber(out.tool);
|
ctool = toolByNumber(out.tool);
|
||||||
|
|
@ -311,6 +313,10 @@ CAM.export = function(print, online) {
|
||||||
|
|
||||||
// emit all points in layer/point order
|
// emit all points in layer/point order
|
||||||
for (let layerout of print.output) {
|
for (let layerout of print.output) {
|
||||||
|
if (!Array.isArray(layerout)) {
|
||||||
|
append(layerout.toString().trim());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (mode !== layerout.mode || consts.tool !== layerout[0].tool) {
|
if (mode !== layerout.mode || consts.tool !== layerout[0].tool) {
|
||||||
if (mode && !stripComments) {
|
if (mode && !stripComments) {
|
||||||
append("; ending " + mode + " op after " + Math.round(time/60) + " seconds");
|
append("; ending " + mode + " op after " + Math.round(time/60) + " seconds");
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,18 @@ class CamOp {
|
||||||
prepare() { }
|
prepare() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OpGCode extends CamOp {
|
||||||
|
constructor(state, op) {
|
||||||
|
super(state, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare(ops, progress) {
|
||||||
|
if (this.op.gcode) {
|
||||||
|
ops.addGCode(this.op.gcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class OpLevel extends CamOp {
|
class OpLevel extends CamOp {
|
||||||
constructor(state, op) {
|
constructor(state, op) {
|
||||||
super(state, op);
|
super(state, op);
|
||||||
|
|
@ -1504,6 +1516,7 @@ CAM.OPS = CamOp.MAP = {
|
||||||
"trace": OpTrace,
|
"trace": OpTrace,
|
||||||
"drill": OpDrill,
|
"drill": OpDrill,
|
||||||
"register": OpRegister,
|
"register": OpRegister,
|
||||||
|
"gcode": OpGCode,
|
||||||
"flip": CamOp
|
"flip": CamOp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,8 @@ CAM.prepare = function(widgets, settings, update) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
print.render = render.path(print.output, (progress, layer) => {
|
const output = print.output.filter(level => Array.isArray(level));
|
||||||
|
print.render = render.path(output, (progress, layer) => {
|
||||||
update(0.75 + progress * 0.25, "render", layer);
|
update(0.75 + progress * 0.25, "render", layer);
|
||||||
}, {
|
}, {
|
||||||
thin: true,
|
thin: true,
|
||||||
|
|
@ -127,6 +128,15 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
layerOut.spindle = spindle;
|
layerOut.spindle = spindle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addGCode(text) {
|
||||||
|
newOutput.push(text);
|
||||||
|
if (layerOut.length) {
|
||||||
|
layerOut = [];
|
||||||
|
layerOut.mode = lastMode;
|
||||||
|
layerOut.spindle = spindle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// non-zero means contouring
|
// non-zero means contouring
|
||||||
function setTolerance(dist) {
|
function setTolerance(dist) {
|
||||||
tolerance = dist;
|
tolerance = dist;
|
||||||
|
|
@ -372,6 +382,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
setPrintPoint,
|
setPrintPoint,
|
||||||
printPoint,
|
printPoint,
|
||||||
newLayer,
|
newLayer,
|
||||||
|
addGCode,
|
||||||
camOut,
|
camOut,
|
||||||
polyEmit,
|
polyEmit,
|
||||||
poly2polyEmit,
|
poly2polyEmit,
|
||||||
|
|
@ -505,9 +516,13 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// last layer/move is to zmax
|
// last layer/move is to zmax
|
||||||
// injected into the last layer generated
|
// re-inject that point into the last layer generated
|
||||||
if (lastPoint && newOutput.length)
|
if (lastPoint && newOutput.length) {
|
||||||
print.addOutput(newOutput[newOutput.length-1], printPoint = lastPoint.clone().setZ(zmax_outer), 0, 0, tool.getNumber());
|
let lastLayer = newOutput.filter(layer => Array.isArray(layer)).peek();
|
||||||
|
if (Array.isArray(lastLayer)) {
|
||||||
|
print.addOutput(lastLayer, printPoint = lastPoint.clone().setZ(zmax_outer), 0, 0, tool.getNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// replace output single flattened layer with all points
|
// replace output single flattened layer with all points
|
||||||
print.output = newOutput;
|
print.output = newOutput;
|
||||||
|
|
|
||||||
|
|
@ -1705,8 +1705,8 @@ gapp.register("kiri.init", [], (root, exports) => {
|
||||||
extNozzle: uc.newInput(LANG.dv_nozl_s, {title:LANG.dv_nozl_l, convert:uc.toFloat, modes:FDM}),
|
extNozzle: uc.newInput(LANG.dv_nozl_s, {title:LANG.dv_nozl_l, convert:uc.toFloat, modes:FDM}),
|
||||||
extOffsetX: uc.newInput(LANG.dv_exox_s, {title:LANG.dv_exox_l, convert:uc.toFloat, modes:FDM}),
|
extOffsetX: uc.newInput(LANG.dv_exox_s, {title:LANG.dv_exox_l, convert:uc.toFloat, modes:FDM}),
|
||||||
extOffsetY: uc.newInput(LANG.dv_exoy_s, {title:LANG.dv_exoy_l, convert:uc.toFloat, modes:FDM}),
|
extOffsetY: uc.newInput(LANG.dv_exoy_s, {title:LANG.dv_exoy_l, convert:uc.toFloat, modes:FDM}),
|
||||||
extSelect: uc.newText(LANG.dv_exts_s, {title:LANG.dv_exts_l, modes:FDM, size:14, height:3, modes:FDM, area:gcode}),
|
extSelect: uc.newText(LANG.dv_exts_s, {title:LANG.dv_exts_l, modes:FDM, size:14, height:3, area:gcode}),
|
||||||
extDeselect: uc.newText(LANG.dv_dext_s, {title:LANG.dv_dext_l, modes:FDM, size:14, height:3, modes:FDM, area:gcode}),
|
extDeselect: uc.newText(LANG.dv_dext_s, {title:LANG.dv_dext_l, modes:FDM, size:14, height:3, area:gcode}),
|
||||||
extPad: uc.newBlank({class:"grow", modes:FDM}),
|
extPad: uc.newBlank({class:"grow", modes:FDM}),
|
||||||
extActions: uc.newRow([
|
extActions: uc.newRow([
|
||||||
ui.extPrev = uc.newButton(undefined, undefined, {icon:'<i class="fas fa-less-than"></i>'}),
|
ui.extPrev = uc.newButton(undefined, undefined, {icon:'<i class="fas fa-less-than"></i>'}),
|
||||||
|
|
|
||||||
|
|
@ -788,6 +788,18 @@ th, tr, td, label {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
}
|
}
|
||||||
|
#camop_dialog {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
#camop_dialog textarea {
|
||||||
|
border: 1px solid gray;
|
||||||
|
margin: 5px 1px 5px 1px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
#camop_dialog button, #camop_dialog label {
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
#camops {
|
#camops {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,7 @@
|
||||||
<div title="drill any holes matching selected tool diameter">drill</div>
|
<div title="drill any holes matching selected tool diameter">drill</div>
|
||||||
<hr width="100%">
|
<hr width="100%">
|
||||||
<div title="drill registration holes along the X or Y axis for double-sided work">register</div>
|
<div title="drill registration holes along the X or Y axis for double-sided work">register</div>
|
||||||
|
<div title="insert custom gcode">gcode</div>
|
||||||
<div title="flip part and load profile for other side for double-sided work">flip</div>
|
<div title="flip part and load profile for other side for double-sided work">flip</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ self.kiri.lang['en-us'] = {
|
||||||
delete: "delete",
|
delete: "delete",
|
||||||
detail: "detail",
|
detail: "detail",
|
||||||
done: "done",
|
done: "done",
|
||||||
|
edit: "edit",
|
||||||
enable: "enable",
|
enable: "enable",
|
||||||
export: "export",
|
export: "export",
|
||||||
files: "files",
|
files: "files",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue