parent
8018ab1523
commit
ecb29767d4
3 changed files with 75 additions and 8 deletions
|
|
@ -366,6 +366,24 @@ impl OpenCADStudio {
|
||||||
self.commit_undo_delta(i, pd);
|
self.commit_undo_delta(i, pd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CmdResult::CommitEntities(entities) => {
|
||||||
|
let label = self.history_label_from_active_cmd(i, "ENTITY");
|
||||||
|
let delta_safe = entities
|
||||||
|
.iter()
|
||||||
|
.all(|entity| self.delta_add_safe(i, entity));
|
||||||
|
let pending = self.begin_undo(i, label, entities.len(), delta_safe);
|
||||||
|
for entity in entities {
|
||||||
|
self.commit_entity(entity);
|
||||||
|
}
|
||||||
|
self.tabs[i].dirty = true;
|
||||||
|
let prompt = self.tabs[i].active_cmd.as_ref().map(|c| c.prompt());
|
||||||
|
if let Some(p) = prompt {
|
||||||
|
self.command_line.push_info(&p);
|
||||||
|
}
|
||||||
|
if let Some(pd) = pending {
|
||||||
|
self.commit_undo_delta(i, pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
CmdResult::TransformSelected(handles, transform) => {
|
CmdResult::TransformSelected(handles, transform) => {
|
||||||
let label = self.history_label_from_active_cmd(i, "MOVE");
|
let label = self.history_label_from_active_cmd(i, "MOVE");
|
||||||
// A move/rotate/scale/mirror mutates only the selected entities
|
// A move/rotate/scale/mirror mutates only the selected entities
|
||||||
|
|
|
||||||
|
|
@ -806,6 +806,8 @@ pub enum CmdResult {
|
||||||
Preview(WireModel),
|
Preview(WireModel),
|
||||||
/// Commit an acadrust entity to the document; keep the command active.
|
/// Commit an acadrust entity to the document; keep the command active.
|
||||||
CommitEntity(EntityType),
|
CommitEntity(EntityType),
|
||||||
|
/// Commit several acadrust entities in one undo step; keep the command active.
|
||||||
|
CommitEntities(Vec<EntityType>),
|
||||||
/// Commit an acadrust entity to the document and end the command.
|
/// Commit an acadrust entity to the document and end the command.
|
||||||
CommitAndExit(EntityType),
|
CommitAndExit(EntityType),
|
||||||
/// Commit a Model-tab 3D solid: the acadrust entity (for selection /
|
/// Commit a Model-tab 3D solid: the acadrust entity (for selection /
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
// Steps:
|
// Steps:
|
||||||
// 1. Text input: "Specify offset distance <last>:" → enter float or Enter for default
|
// 1. Text input: "Specify offset distance <last>:" → enter float or Enter for default
|
||||||
// 2. Pick object to offset (Line, Arc, Circle, LwPolyline)
|
// 2. Pick object to offset (Line, Arc, Circle, LwPolyline)
|
||||||
// 3. Pick a point on the side to offset toward
|
// 3. Pick a point on the side to offset toward, or choose Multiple
|
||||||
|
// to keep offsetting the newly created result at the same distance
|
||||||
|
|
||||||
use std::f64::consts::TAU;
|
use std::f64::consts::TAU;
|
||||||
|
|
||||||
|
|
@ -687,6 +688,9 @@ enum Step {
|
||||||
/// True when the targets came from the pre-selection: the commit ends
|
/// True when the targets came from the pre-selection: the commit ends
|
||||||
/// the command instead of looping back for another pick.
|
/// the command instead of looping back for another pick.
|
||||||
from_selection: bool,
|
from_selection: bool,
|
||||||
|
/// Keep the side-pick step active and use each new result as the source
|
||||||
|
/// for the next offset.
|
||||||
|
multiple: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -747,6 +751,7 @@ impl OffsetCommand {
|
||||||
targets: std::mem::take(&mut self.preselected),
|
targets: std::mem::take(&mut self.preselected),
|
||||||
locked,
|
locked,
|
||||||
from_selection: true,
|
from_selection: true,
|
||||||
|
multiple: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
CmdResult::NeedPoint
|
CmdResult::NeedPoint
|
||||||
|
|
@ -767,15 +772,28 @@ impl CadCommand for OffsetCommand {
|
||||||
Step::SelectObject { .. } => {
|
Step::SelectObject { .. } => {
|
||||||
"OFFSET Select object to offset (Enter to finish):".into()
|
"OFFSET Select object to offset (Enter to finish):".into()
|
||||||
}
|
}
|
||||||
Step::PickSide { targets, locked, .. } => {
|
Step::PickSide {
|
||||||
|
targets,
|
||||||
|
locked,
|
||||||
|
multiple,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
let n = if targets.len() > 1 {
|
let n = if targets.len() > 1 {
|
||||||
format!(" ({} objects)", targets.len())
|
format!(" ({} objects)", targets.len())
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
match locked {
|
match (locked, multiple) {
|
||||||
Some(d) => format!("OFFSET{n} Click side [distance {d:.4}]:"),
|
(Some(d), false) => {
|
||||||
None => format!("OFFSET{n} Click through point:"),
|
format!("OFFSET{n} Click side or [Multiple] [distance {d:.4}]:")
|
||||||
|
}
|
||||||
|
(Some(d), true) => {
|
||||||
|
format!("OFFSET{n} Multiple Click next side [distance {d:.4}]:")
|
||||||
|
}
|
||||||
|
(None, false) => {
|
||||||
|
format!("OFFSET{n} Click through point or [Multiple]:")
|
||||||
|
}
|
||||||
|
(None, true) => format!("OFFSET{n} Multiple Click next through point:"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -790,6 +808,9 @@ impl CadCommand for OffsetCommand {
|
||||||
defaults::get_offset_dist()
|
defaults::get_offset_dist()
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
|
Step::PickSide {
|
||||||
|
multiple: false, ..
|
||||||
|
} => vec![crate::command::CmdOption::new("Multiple", "M")],
|
||||||
_ => Vec::new(),
|
_ => Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -819,6 +840,7 @@ impl CadCommand for OffsetCommand {
|
||||||
targets: vec![e],
|
targets: vec![e],
|
||||||
locked,
|
locked,
|
||||||
from_selection: false,
|
from_selection: false,
|
||||||
|
multiple: false,
|
||||||
};
|
};
|
||||||
CmdResult::NeedPoint
|
CmdResult::NeedPoint
|
||||||
}
|
}
|
||||||
|
|
@ -866,7 +888,15 @@ impl CadCommand for OffsetCommand {
|
||||||
}
|
}
|
||||||
Some(CmdResult::NeedPoint)
|
Some(CmdResult::NeedPoint)
|
||||||
}
|
}
|
||||||
Step::PickSide { locked, .. } => {
|
Step::PickSide {
|
||||||
|
locked,
|
||||||
|
multiple,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if t.eq_ignore_ascii_case("m") || t.eq_ignore_ascii_case("multiple") {
|
||||||
|
*multiple = true;
|
||||||
|
return Some(CmdResult::NeedPoint);
|
||||||
|
}
|
||||||
if !t.is_empty() {
|
if !t.is_empty() {
|
||||||
if let Ok(d) = t.parse::<f64>() {
|
if let Ok(d) = t.parse::<f64>() {
|
||||||
let d = d.abs().max(1e-9);
|
let d = d.abs().max(1e-9);
|
||||||
|
|
@ -902,12 +932,13 @@ impl CadCommand for OffsetCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||||
let (locked, targets, from_selection) = match &self.step {
|
let (locked, targets, from_selection, multiple) = match &self.step {
|
||||||
Step::PickSide {
|
Step::PickSide {
|
||||||
locked,
|
locked,
|
||||||
targets,
|
targets,
|
||||||
from_selection,
|
from_selection,
|
||||||
} => (*locked, targets.clone(), *from_selection),
|
multiple,
|
||||||
|
} => (*locked, targets.clone(), *from_selection, *multiple),
|
||||||
_ => return CmdResult::NeedPoint,
|
_ => return CmdResult::NeedPoint,
|
||||||
};
|
};
|
||||||
// Each target offsets by its own through-distance (or the locked
|
// Each target offsets by its own through-distance (or the locked
|
||||||
|
|
@ -925,6 +956,22 @@ impl CadCommand for OffsetCommand {
|
||||||
if news.is_empty() {
|
if news.is_empty() {
|
||||||
return CmdResult::NeedPoint;
|
return CmdResult::NeedPoint;
|
||||||
}
|
}
|
||||||
|
if multiple {
|
||||||
|
// Multiple mode chains from the result just created, matching
|
||||||
|
// OFFSET's repeated fixed-distance behavior (parallel/concentric
|
||||||
|
// series instead of duplicate copies at the first offset).
|
||||||
|
self.step = Step::PickSide {
|
||||||
|
targets: news.clone(),
|
||||||
|
locked,
|
||||||
|
from_selection,
|
||||||
|
multiple: true,
|
||||||
|
};
|
||||||
|
return if news.len() == 1 {
|
||||||
|
CmdResult::CommitEntity(news.pop().unwrap())
|
||||||
|
} else {
|
||||||
|
CmdResult::CommitEntities(news)
|
||||||
|
};
|
||||||
|
}
|
||||||
if from_selection {
|
if from_selection {
|
||||||
// Pre-selection commit ends the command in one undo step.
|
// Pre-selection commit ends the command in one undo step.
|
||||||
return CmdResult::ReplaceMany(vec![], news);
|
return CmdResult::ReplaceMany(vec![], news);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue