A Mirror window for sketch entities, holding both picks until OK (#734)
Sketch Mirror now opens a tool window with Entities and Mirror line inputs, so both picks stay visible and editable until OK, replacing the old click-then-right-click flow.
This commit is contained in:
1 parent
d437c21368
commit
d4fd760b0d
8 files changed
+205
-19
No files matched your search
@@ -4,9 +4,10 @@
|
||||
//! reached no tool and no dialog at all, so a press ran `sketch.scale` with no parameters and
|
||||
//! the engine answered "`factor` must be a positive number". Offset joins it here (upstream
|
||||
//! issue #162 item 1: "Offset does not create a constraint, the size of the offset seems
|
||||
//! random"). `sketch.fillet`, the three `sketch.chamfer.*` commands, the sketch patterns,
|
||||
//! `sketch.mirror` and `sketch.move` are the same gap and join this module later, each its own
|
||||
//! change.
|
||||
//! random"). Mirror joins them here, which ran as a bare click flow: entities until a
|
||||
//! right-click, then one more click for the line, with nothing on screen saying what was
|
||||
//! picked. `sketch.fillet`, the three `sketch.chamfer.*` commands, the sketch patterns and
|
||||
//! `sketch.move` are the same gap and join this module later, each its own change.
|
||||
|
||||
use serde_json::{Map, Value, json};
|
||||
use solidcraft_engine::Sel;
|
||||
@@ -14,7 +15,7 @@ use solidcraft_engine::doc::expr::Kind as ValueKind;
|
||||
|
||||
use crate::SolveApp;
|
||||
use crate::dialogs::{Kind, check, field, row_label};
|
||||
use crate::selection::{CURVES, POINTS, SelInput};
|
||||
use crate::selection::{AXES, CURVES, POINTS, SelInput};
|
||||
|
||||
/// A sketch modify tool window's values.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -27,6 +28,10 @@ pub enum Mod {
|
||||
/// chain follows. A positive distance is left of the chain, as the command defines it;
|
||||
/// `flip` reverses whatever sign the field holds.
|
||||
Offset { distance: String, chain: bool, flip: bool },
|
||||
/// `sketch.mirror`: the entities and the line they reflect in. The command has no number of
|
||||
/// its own, so the window's whole job is to show what is picked and let a pick be changed
|
||||
/// before anything is committed.
|
||||
Mirror,
|
||||
}
|
||||
|
||||
impl Mod {
|
||||
@@ -34,15 +39,17 @@ impl Mod {
|
||||
match self {
|
||||
Mod::Scale { .. } => "SKETCH SCALE",
|
||||
Mod::Offset { .. } => "OFFSET",
|
||||
Mod::Mirror => "MIRROR",
|
||||
}
|
||||
}
|
||||
|
||||
/// The value on the canvas.
|
||||
pub fn primary(&mut self) -> Option<(&'static str, ValueKind, &mut String)> {
|
||||
Some(match self {
|
||||
Mod::Scale { factor } => ("Factor", ValueKind::Unitless, factor),
|
||||
Mod::Offset { distance, .. } => ("Distance", ValueKind::Length, distance),
|
||||
})
|
||||
match self {
|
||||
Mod::Scale { factor } => Some(("Factor", ValueKind::Unitless, factor)),
|
||||
Mod::Offset { distance, .. } => Some(("Distance", ValueKind::Length, distance)),
|
||||
Mod::Mirror => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +57,8 @@ fn inputs(k: &Mod) -> Vec<SelInput> {
|
||||
match k {
|
||||
Mod::Scale { .. } => vec![SelInput::new("Entities", CURVES | POINTS, true), SelInput::new("Base point", POINTS, false)],
|
||||
Mod::Offset { .. } => vec![SelInput::new("Curves", CURVES, true)],
|
||||
// AXES is the mask that takes a straight sketch curve (`selection::SelInput::accepts`).
|
||||
Mod::Mirror => vec![SelInput::new("Entities", CURVES | POINTS, true), SelInput::new("Mirror line", AXES, false)],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +67,7 @@ pub fn start(_app: &SolveApp, id: &str) -> Option<(Kind, Vec<SelInput>)> {
|
||||
let k = match id {
|
||||
"sketch.scale" => Mod::Scale { factor: "2".into() },
|
||||
"sketch.offset" => Mod::Offset { distance: "2 mm".into(), chain: true, flip: false },
|
||||
"sketch.mirror" => Mod::Mirror,
|
||||
_ => return None,
|
||||
};
|
||||
let i = inputs(&k);
|
||||
@@ -84,6 +94,8 @@ pub fn rows(ui: &mut egui::Ui, k: &mut Mod) -> bool {
|
||||
check(ui, chain);
|
||||
ui.end_row();
|
||||
}
|
||||
// Mirror has no value of its own: its inputs are the whole window.
|
||||
Mod::Mirror => {}
|
||||
}
|
||||
enter
|
||||
}
|
||||
@@ -167,6 +179,23 @@ pub fn commands(app: &SolveApp, k: &Mod, inputs: &[SelInput], extra: &Map<String
|
||||
let d = signed_length(app, distance, *flip)?;
|
||||
("sketch.offset", json!({"curves": curves, "distance": d, "chain": chain}))
|
||||
}
|
||||
Mod::Mirror => {
|
||||
let entities = entity_ids(inputs, 0);
|
||||
if entities.is_empty() {
|
||||
return Err("Select the sketch curves or points to mirror first".into());
|
||||
}
|
||||
// The AXES mask also takes an origin axis, which is not a curve of this sketch and
|
||||
// cannot be a mirror line.
|
||||
let line = match items(inputs, 1).first() {
|
||||
Some(Sel::SketchCurve { id }) => id.clone(),
|
||||
Some(_) => return Err("The mirror line must be a straight curve of this sketch, not an origin axis".into()),
|
||||
None => return Err("Select the mirror line".into()),
|
||||
};
|
||||
if entities.contains(&line) {
|
||||
return Err("The mirror line cannot also be mirrored".into());
|
||||
}
|
||||
("sketch.mirror", json!({"entities": entities, "line": line}))
|
||||
}
|
||||
};
|
||||
if let Value::Object(m) = &mut params {
|
||||
for (key, value) in extra {
|
||||
|
||||
Reference in new issue
Block a user