options for line numbers and checksums, closes #35

master
Sameer Puri 2 years ago
parent 99cde4ae4b
commit 2d9fa036b2

49
Cargo.lock generated

@ -59,7 +59,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
] ]
[[package]] [[package]]
@ -407,7 +407,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
] ]
[[package]] [[package]]
@ -442,9 +442,9 @@ dependencies = [
[[package]] [[package]]
name = "g-code" name = "g-code"
version = "0.3.4" version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af84627294d66ff823b6947819ae8878db6b5d78d1bf9e86b1073026b6f3db83" checksum = "426e8db123028351d46f0befecb1fe15e326ab53cd9449c1296083981859519c"
dependencies = [ dependencies = [
"codespan", "codespan",
"codespan-reporting", "codespan-reporting",
@ -757,12 +757,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "lyon_geom" name = "lyon_geom"
@ -803,9 +800,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.1" version = "1.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
[[package]] [[package]]
name = "paste" name = "paste"
@ -863,7 +860,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
] ]
[[package]] [[package]]
@ -1145,7 +1142,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
] ]
[[package]] [[package]]
@ -1245,7 +1242,7 @@ dependencies = [
[[package]] [[package]]
name = "svg2gcode" name = "svg2gcode"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"cairo-rs", "cairo-rs",
"euclid", "euclid",
@ -1325,9 +1322,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.17" version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45b6ddbb36c5b969c182aec3c4a0bce7df3fbad4b77114706a49aacc80567388" checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1394,7 +1391,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
] ]
[[package]] [[package]]
@ -1414,9 +1411,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.28.1" version = "1.28.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"pin-project-lite", "pin-project-lite",
@ -1497,7 +1494,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
] ]
[[package]] [[package]]
@ -1594,7 +1591,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1628,7 +1625,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.17", "syn 2.0.18",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1823,9 +1820,9 @@ dependencies = [
[[package]] [[package]]
name = "yewdux" name = "yewdux"
version = "0.9.2" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "653ba356bc60d1804c28ec6cc8ddac2741c686bde2a65074d07faba735914464" checksum = "3c528544a814a0beb30059c8340eb78c88160141db788112b51a5a08098cef2d"
dependencies = [ dependencies = [
"anymap", "anymap",
"async-trait", "async-trait",
@ -1842,9 +1839,9 @@ dependencies = [
[[package]] [[package]]
name = "yewdux-macros" name = "yewdux-macros"
version = "0.9.2" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25bcd923aceaa85cb4affad8657cc36e3d6b6932740e711574182f7817492739" checksum = "cc318072e34a9083d651ecd126153e9f1c39ae705794ef953a30b561b5eaab6d"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro-error", "proc-macro-error",

@ -67,6 +67,17 @@ struct Opt {
/// Please check if your machine supports G2/G3 commands before enabling this. /// Please check if your machine supports G2/G3 commands before enabling this.
#[structopt(long)] #[structopt(long)]
circular_interpolation: Option<bool>, circular_interpolation: Option<bool>,
#[structopt(long)]
/// Include line numbers at the beginning of each line
///
/// Useful for debugging/streaming g-code
line_numbers: Option<bool>,
#[structopt(long)]
/// Include checksums at the end of each line
///
/// Useful for streaming g-code
checksums: Option<bool>,
} }
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
@ -128,6 +139,15 @@ fn main() -> io::Result<()> {
} }
} }
} }
if let Some(line_numbers) = opt.line_numbers {
settings.postprocess.line_numbers = line_numbers;
}
if let Some(checksums) = opt.checksums {
settings.postprocess.checksums = checksums;
}
settings settings
}; };
@ -253,8 +273,24 @@ fn main() -> io::Result<()> {
let program = svg2program(&document, &settings.conversion, options, machine); let program = svg2program(&document, &settings.conversion, options, machine);
if let Some(out_path) = opt.out { if let Some(out_path) = opt.out {
format_gcode_io(&program, FormatOptions::default(), File::create(out_path)?) format_gcode_io(
&program,
FormatOptions {
line_numbers: settings.postprocess.line_numbers,
checksums: settings.postprocess.checksums,
..Default::default()
},
File::create(out_path)?,
)
} else { } else {
format_gcode_io(&program, FormatOptions::default(), std::io::stdout()) format_gcode_io(
&program,
FormatOptions {
line_numbers: settings.postprocess.line_numbers,
checksums: settings.postprocess.checksums,
..Default::default()
},
std::io::stdout(),
)
} }
} }

@ -1,6 +1,6 @@
[package] [package]
name = "svg2gcode" name = "svg2gcode"
version = "0.1.1" version = "0.1.2"
authors = ["Sameer Puri <crates@purisa.me>"] authors = ["Sameer Puri <crates@purisa.me>"]
edition = "2021" edition = "2021"
description = "Convert paths in SVG files to GCode for a pen plotter, laser engraver, or other machine." description = "Convert paths in SVG files to GCode for a pen plotter, laser engraver, or other machine."
@ -8,7 +8,7 @@ repository = "https://github.com/sameer/svg2gcode"
license = "MIT" license = "MIT"
[dependencies] [dependencies]
g-code = { version = "0.3.4", features = ["serde"] } g-code = { version = "0.3.5", features = ["serde"] }
lyon_geom = "1.0.4" lyon_geom = "1.0.4"
euclid = "0.22" euclid = "0.22"
log = "0.4" log = "0.4"

@ -162,4 +162,57 @@ mod test {
"#; "#;
serde_json::from_str::<Settings>(json).unwrap(); serde_json::from_str::<Settings>(json).unwrap();
} }
#[test]
#[cfg(feature = "serde")]
fn deserialize_v2_config_succeeds() {
let json = r#"
{
"conversion": {
"tolerance": 0.002,
"feedrate": 300.0,
"dpi": 96.0
},
"machine": {
"supported_functionality": {
"circular_interpolation": true
},
"tool_on_sequence": null,
"tool_off_sequence": null,
"begin_sequence": null,
"end_sequence": null
},
"postprocess": { }
}
"#;
serde_json::from_str::<Settings>(json).unwrap();
}
#[test]
#[cfg(feature = "serde")]
fn deserialize_v3_config_succeeds() {
let json = r#"
{
"conversion": {
"tolerance": 0.002,
"feedrate": 300.0,
"dpi": 96.0
},
"machine": {
"supported_functionality": {
"circular_interpolation": true
},
"tool_on_sequence": null,
"tool_off_sequence": null,
"begin_sequence": null,
"end_sequence": null
},
"postprocess": {
"checksums": false,
"line_numbers": false
}
}
"#;
serde_json::from_str::<Settings>(json).unwrap();
}
} }

@ -3,4 +3,11 @@ use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Default, Clone, PartialEq)] #[derive(Debug, Default, Clone, PartialEq)]
pub struct PostprocessConfig {} pub struct PostprocessConfig {
/// Convenience field for [g_code::emit::FormatOptions] field
#[cfg_attr(feature = "serde", serde(default))]
pub checksums: bool,
/// Convenience field for [g_code::emit::FormatOptions] field
#[cfg_attr(feature = "serde", serde(default))]
pub line_numbers: bool,
}

@ -69,13 +69,13 @@ form_input! {
} }
OriginX { OriginX {
"Origin X", "Origin X",
"X-axis coordinate for the bottom left corner of the machine", "X-axis coordinate for the lower left corner of the machine",
origin => 0, origin => 0,
settings.conversion.origin => 0, settings.conversion.origin => 0,
} }
OriginY { OriginY {
"Origin Y", "Origin Y",
"Y-axis coordinate for the bottom left corner of the machine", "Y-axis coordinate for the lower left corner of the machine",
origin => 1, origin => 1,
settings.conversion.origin => 1, settings.conversion.origin => 1,
} }

@ -65,13 +65,21 @@ pub fn settings_form() -> Html {
// but historically hasn't been the case, on change is safer. // but historically hasn't been the case, on change is safer.
let on_circular_interpolation_change = let on_circular_interpolation_change =
form_dispatch.reduce_mut_callback_with(|form, event: Event| { form_dispatch.reduce_mut_callback_with(|form, event: Event| {
let checkbox = event.target_unchecked_into::<HtmlInputElement>(); form.circular_interpolation =
form.circular_interpolation = checkbox.checked(); event.target_unchecked_into::<HtmlInputElement>().checked();
}); });
let circular_interpolation_checked = form_state.circular_interpolation;
let on_checksums_change = form_dispatch.reduce_mut_callback_with(|form, event: Event| {
form.checksums = event.target_unchecked_into::<HtmlInputElement>().checked();
});
let on_line_numbers_change = form_dispatch.reduce_mut_callback_with(|form, event: Event| {
form.line_numbers = event.target_unchecked_into::<HtmlInputElement>().checked();
});
let save_onclick = { let save_onclick = {
let close_ref = close_ref.clone(); let close_ref = close_ref.clone();
let form_state = form_state.clone();
app_dispatch.reduce_mut_callback(move |app| { app_dispatch.reduce_mut_callback(move |app| {
if !disabled { if !disabled {
app.settings = form_state.as_ref().try_into().unwrap(); app.settings = form_state.as_ref().try_into().unwrap();
@ -104,25 +112,65 @@ pub fn settings_form() -> Html {
) )
} }
body={html!( body={html!(
<> <div class="columns">
<ToleranceInput/> <div class="column col-6 col-sm-12">
<FeedrateInput/> <ToleranceInput/>
<OriginXInput/> </div>
<OriginYInput/> <div class="column col-6 col-sm-12">
<FormGroup> <FeedrateInput/>
<Checkbox </div>
label="Enable circular interpolation (experimental)" <div class="column col-6 col-sm-12">
desc="Please check if your machine supports G2/G3 commands before enabling this" <OriginXInput/>
checked={circular_interpolation_checked} </div>
onchange={on_circular_interpolation_change} <div class="column col-6 col-sm-12">
/> <OriginYInput/>
</FormGroup> </div>
<DpiInput/> <div class="column col-12">
<ToolOnSequenceInput/> <FormGroup>
<ToolOffSequenceInput/> <Checkbox
<BeginSequenceInput/> label="Enable circular interpolation (experimental)"
<EndSequenceInput/> desc="Please check if your machine supports G2/G3 commands before enabling this"
</> checked={form_state.circular_interpolation}
onchange={on_circular_interpolation_change}
/>
</FormGroup>
</div>
<div class="column col-12">
<DpiInput/>
</div>
<div class="column col-12">
<ToolOnSequenceInput/>
</div>
<div class="column col-12">
<ToolOffSequenceInput/>
</div>
<div class="column col-12">
<BeginSequenceInput/>
</div>
<div class="column col-12">
<EndSequenceInput/>
</div>
<div class="column col-6 col-sm-12">
<FormGroup>
<Checkbox
label="Generate checksums"
desc="Useful when streaming g-code"
checked={form_state.checksums}
onchange={on_checksums_change}
/>
</FormGroup>
</div>
<div class="column col-6 col-sm-12">
<FormGroup>
<Checkbox
label="Generate line numbers"
desc="Useful when streaming g-code or debugging"
checked={form_state.line_numbers}
onchange={on_line_numbers_change}
/>
</FormGroup>
</div>
</div>
)} )}
footer={ footer={
html!( html!(
@ -221,9 +269,9 @@ pub fn import_export_modal() -> Html {
let close_ref = close_ref.clone(); let close_ref = close_ref.clone();
app_dispatch.reduce_mut_callback(move |app| { app_dispatch.reduce_mut_callback(move |app| {
if let Some(Ok(ref settings)) = *import_state { if let Some(Ok(ref settings)) = *import_state {
app.settings = settings.clone(); app.settings = settings.clone();
// App only hydrates the form on start now, so need to do it again here // App only hydrates the form on start now, so need to do it again here
form_dispatch.reduce_mut(|form| *form = (&app.settings).into()); form_dispatch.reduce_mut(|form| *form = (&app.settings).into());
import_state.set(None); import_state.set(None);
// TODO: another way to close the modal? // TODO: another way to close the modal?
if let Some(element) = close_ref.cast::<HtmlElement>() { if let Some(element) = close_ref.cast::<HtmlElement>() {

@ -21,19 +21,6 @@ use ui::*;
use util::*; use util::*;
use yewdux::prelude::{use_store, Dispatch}; use yewdux::prelude::{use_store, Dispatch};
// struct App {
// app_store: Rc<AppState>,
// form_state: Rc<FormState>,
// generating: bool,
// }
// enum AppMsg {
// AppState(Rc<AppState>),
// FormState(Rc<FormState>),
// Generate,
// Done,
// }
#[function_component] #[function_component]
fn App(_props: &()) -> Html { fn App(_props: &()) -> Html {
let generating = use_state_eq(|| false); let generating = use_state_eq(|| false);
@ -104,8 +91,17 @@ fn App(_props: &()) -> Html {
svg2program(&document, &app_store.settings.conversion, options, machine); svg2program(&document, &app_store.settings.conversion, options, machine);
let gcode = { let gcode = {
let mut acc = String::new(); let mut acc: String = String::new();
format_gcode_fmt(&program, FormatOptions::default(), &mut acc).unwrap(); format_gcode_fmt(
&program,
FormatOptions {
checksums: app_store.settings.postprocess.checksums,
line_numbers: app_store.settings.postprocess.line_numbers,
..Default::default()
},
&mut acc,
)
.unwrap();
acc acc
}; };

@ -19,6 +19,8 @@ pub struct FormState {
pub tool_off_sequence: Option<Result<String, String>>, pub tool_off_sequence: Option<Result<String, String>>,
pub begin_sequence: Option<Result<String, String>>, pub begin_sequence: Option<Result<String, String>>,
pub end_sequence: Option<Result<String, String>>, pub end_sequence: Option<Result<String, String>>,
pub checksums: bool,
pub line_numbers: bool,
} }
impl Default for FormState { impl Default for FormState {
@ -75,7 +77,10 @@ impl<'a> TryInto<Settings> for &'a FormState {
.transpose() .transpose()
.map_err(FormStateConversionError::GCode)?, .map_err(FormStateConversionError::GCode)?,
}, },
postprocess: PostprocessConfig {}, postprocess: PostprocessConfig {
checksums: self.checksums,
line_numbers: self.line_numbers,
},
}) })
} }
} }
@ -98,6 +103,8 @@ impl From<&Settings> for FormState {
tool_off_sequence: settings.machine.tool_off_sequence.clone().map(Ok), tool_off_sequence: settings.machine.tool_off_sequence.clone().map(Ok),
begin_sequence: settings.machine.begin_sequence.clone().map(Ok), begin_sequence: settings.machine.begin_sequence.clone().map(Ok),
end_sequence: settings.machine.end_sequence.clone().map(Ok), end_sequence: settings.machine.end_sequence.clone().map(Ok),
checksums: settings.postprocess.checksums,
line_numbers: settings.postprocess.line_numbers,
} }
} }
} }

Loading…
Cancel
Save