Merge pull request #889 from gianlucafiore/feat/offset-reference-distance
Improve OFFSET distance input
This commit is contained in:
commit
3a817cb379
1 changed files with 74 additions and 14 deletions
|
|
@ -415,19 +415,19 @@ fn entity_wire_pts(e: &EntityType) -> Vec<[f32; 3]> {
|
||||||
// ── Command implementation ─────────────────────────────────────────────────
|
// ── Command implementation ─────────────────────────────────────────────────
|
||||||
|
|
||||||
enum Step {
|
enum Step {
|
||||||
/// Classic first step (#418): type the offset distance, press Enter /
|
/// Type the offset distance, accept the previous value with Enter,
|
||||||
/// Space to accept the last one, or choose Through mode.
|
/// choose Through, or pick the first point of a reference distance.
|
||||||
Distance,
|
Distance,
|
||||||
/// Pick the object to offset. `locked == None` is "through" mode: the
|
|
||||||
/// magnitude follows the cursor (perpendicular distance to the object).
|
/// First reference point has been picked; the second point defines
|
||||||
|
/// the offset distance.
|
||||||
|
ReferenceSecond { first: DVec3 },
|
||||||
|
|
||||||
SelectObject { locked: Option<f64> },
|
SelectObject { locked: Option<f64> },
|
||||||
|
|
||||||
PickSide {
|
PickSide {
|
||||||
/// The object(s) being offset — one from a pick, or the whole
|
|
||||||
/// pre-selection when OFFSET starts with objects selected (#422).
|
|
||||||
targets: Vec<EntityType>,
|
targets: Vec<EntityType>,
|
||||||
locked: Option<f64>,
|
locked: Option<f64>,
|
||||||
/// Keep the side-pick step active and use each new result as the source
|
|
||||||
/// for the next offset.
|
|
||||||
multiple: bool,
|
multiple: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -499,6 +499,18 @@ impl OffsetCommand {
|
||||||
}
|
}
|
||||||
CmdResult::NeedPoint
|
CmdResult::NeedPoint
|
||||||
}
|
}
|
||||||
|
fn accept_distance(&mut self, distance: f64) -> CmdResult {
|
||||||
|
let distance = distance.abs().max(1e-9);
|
||||||
|
|
||||||
|
defaults::set_offset_dist(distance);
|
||||||
|
self.advance_from_distance(Some(distance));
|
||||||
|
|
||||||
|
let d = format!("{:.4}", distance);
|
||||||
|
|
||||||
|
CmdResult::ReportMeasurement(
|
||||||
|
t!("OFFSET distance = %{d}", d = d).into_owned()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CadCommand for OffsetCommand {
|
impl CadCommand for OffsetCommand {
|
||||||
|
|
@ -510,7 +522,15 @@ impl CadCommand for OffsetCommand {
|
||||||
match &self.step {
|
match &self.step {
|
||||||
Step::Distance => {
|
Step::Distance => {
|
||||||
let d = format!("{:.4}", defaults::get_offset_dist());
|
let d = format!("{:.4}", defaults::get_offset_dist());
|
||||||
t!("OFFSET Specify offset distance or [Through] <%{d}>:", d = d).into_owned()
|
t!(
|
||||||
|
"OFFSET Specify offset distance or first reference point [Through] <%{d}>:",
|
||||||
|
d = d
|
||||||
|
)
|
||||||
|
.into_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
Step::ReferenceSecond { .. } => {
|
||||||
|
t!("OFFSET Specify second reference point:").into_owned()
|
||||||
}
|
}
|
||||||
Step::SelectObject { .. } => {
|
Step::SelectObject { .. } => {
|
||||||
t!("OFFSET Select object to offset (Enter to finish):").into_owned()
|
t!("OFFSET Select object to offset (Enter to finish):").into_owned()
|
||||||
|
|
@ -623,7 +643,9 @@ impl CadCommand for OffsetCommand {
|
||||||
fn dyn_field(&self) -> crate::command::DynField {
|
fn dyn_field(&self) -> crate::command::DynField {
|
||||||
match self.step {
|
match self.step {
|
||||||
Step::Distance | Step::PickSide { .. } => crate::command::DynField::Scalar,
|
Step::Distance | Step::PickSide { .. } => crate::command::DynField::Scalar,
|
||||||
_ => crate::command::DynField::Point,
|
|
||||||
|
Step::ReferenceSecond { .. }
|
||||||
|
| Step::SelectObject { .. } => crate::command::DynField::Point,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -648,9 +670,7 @@ impl CadCommand for OffsetCommand {
|
||||||
return Some(self.advance_from_distance(None));
|
return Some(self.advance_from_distance(None));
|
||||||
}
|
}
|
||||||
if let Some(d) = crate::entities::common::parse_typed_length(&t) {
|
if let Some(d) = crate::entities::common::parse_typed_length(&t) {
|
||||||
let d = d.abs().max(1e-9);
|
return Some(self.accept_distance(d));
|
||||||
defaults::set_offset_dist(d);
|
|
||||||
return Some(self.advance_from_distance(Some(d)));
|
|
||||||
}
|
}
|
||||||
Some(CmdResult::NeedPoint)
|
Some(CmdResult::NeedPoint)
|
||||||
}
|
}
|
||||||
|
|
@ -698,12 +718,32 @@ impl CadCommand for OffsetCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
||||||
|
match &self.step {
|
||||||
|
Step::Distance => {
|
||||||
|
self.step = Step::ReferenceSecond { first: pt };
|
||||||
|
return CmdResult::NeedPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
Step::ReferenceSecond { first } => {
|
||||||
|
let distance = first.distance(pt);
|
||||||
|
|
||||||
|
if distance <= 1e-9 {
|
||||||
|
return CmdResult::NeedPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.accept_distance(distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let (locked, targets, multiple) = match &self.step {
|
let (locked, targets, multiple) = match &self.step {
|
||||||
Step::PickSide {
|
Step::PickSide {
|
||||||
locked,
|
locked,
|
||||||
targets,
|
targets,
|
||||||
multiple,
|
multiple,
|
||||||
} => (*locked, targets.clone(), *multiple),
|
} => (*locked, targets.clone(), *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
|
||||||
|
|
@ -745,6 +785,26 @@ impl CadCommand for OffsetCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
|
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
|
||||||
|
if let Step::ReferenceSecond { first } = &self.step {
|
||||||
|
return vec![WireModel::solid(
|
||||||
|
"offset_reference_distance".into(),
|
||||||
|
vec![
|
||||||
|
[
|
||||||
|
first.x as f32,
|
||||||
|
first.y as f32,
|
||||||
|
first.z as f32,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
pt.x as f32,
|
||||||
|
pt.y as f32,
|
||||||
|
pt.z as f32,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
WireModel::CYAN,
|
||||||
|
false,
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
|
||||||
let (locked, targets) = match &self.step {
|
let (locked, targets) = match &self.step {
|
||||||
Step::PickSide { locked, targets, .. } => (*locked, targets.clone()),
|
Step::PickSide { locked, targets, .. } => (*locked, targets.clone()),
|
||||||
_ => return vec![],
|
_ => return vec![],
|
||||||
|
|
@ -779,7 +839,7 @@ impl CadCommand for OffsetCommand {
|
||||||
// the "repeat the same value with just Space" flow (#418).
|
// the "repeat the same value with just Space" flow (#418).
|
||||||
Step::Distance => {
|
Step::Distance => {
|
||||||
let d = defaults::get_offset_dist();
|
let d = defaults::get_offset_dist();
|
||||||
self.advance_from_distance(Some(d.abs().max(1e-9)))
|
self.accept_distance(d)
|
||||||
}
|
}
|
||||||
_ => CmdResult::Cancel,
|
_ => CmdResult::Cancel,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue