forked from 1b-agent/opencadstudio-upstream
style: apply cargo fmt across workspace
This commit is contained in:
1 parent
85710e5454
commit
9cf9ff2c5c
531 files changed
+57740
-33906
No files matched your search
@@ -97,9 +97,9 @@ impl CadCommand for CoincidentConstraintCommand {
|
||||
}
|
||||
Step::FirstObject => "COINCIDENT Select object:".to_string(),
|
||||
Step::Second(_) => "COINCIDENT Select second point or object:".to_string(),
|
||||
Step::PointsOnCurve { multiple: false, .. } => {
|
||||
"COINCIDENT Select point or [Multiple]:".to_string()
|
||||
}
|
||||
Step::PointsOnCurve {
|
||||
multiple: false, ..
|
||||
} => "COINCIDENT Select point or [Multiple]:".to_string(),
|
||||
Step::PointsOnCurve { multiple: true, .. } => {
|
||||
"COINCIDENT Select points to coincide with the first object (Enter = done):"
|
||||
.to_string()
|
||||
@@ -143,7 +143,9 @@ impl CadCommand for CoincidentConstraintCommand {
|
||||
CmdOption::new("Object", "O"),
|
||||
CmdOption::new("Autoconstrain", "A"),
|
||||
],
|
||||
Step::PointsOnCurve { multiple: false, .. } => vec![
|
||||
Step::PointsOnCurve {
|
||||
multiple: false, ..
|
||||
} => vec![
|
||||
CmdOption::new("Point", "P"),
|
||||
CmdOption::new("Multiple", "M"),
|
||||
],
|
||||
@@ -161,17 +163,16 @@ impl CadCommand for CoincidentConstraintCommand {
|
||||
}
|
||||
|
||||
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
||||
let keyword = text
|
||||
.trim()
|
||||
.trim_start_matches('_')
|
||||
.to_ascii_uppercase();
|
||||
let keyword = text.trim().trim_start_matches('_').to_ascii_uppercase();
|
||||
match (&mut self.step, keyword.as_str()) {
|
||||
(Step::First, "O" | "OBJECT") => {
|
||||
self.step = Step::FirstObject;
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
(Step::First, "A" | "AUTOCONSTRAIN") => {
|
||||
self.step = Step::AutoConstrain { handles: Vec::new() };
|
||||
self.step = Step::AutoConstrain {
|
||||
handles: Vec::new(),
|
||||
};
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
(Step::PointsOnCurve { multiple, .. }, "M" | "MULTIPLE") => {
|
||||
@@ -211,10 +212,7 @@ impl CadCommand for CoincidentConstraintCommand {
|
||||
.picked_entity
|
||||
.as_ref()
|
||||
.is_some_and(|entity| Self::picked_constraint_point(entity, point));
|
||||
let is_curve = self
|
||||
.picked_entity
|
||||
.as_ref()
|
||||
.is_some_and(Self::valid_curve);
|
||||
let is_curve = self.picked_entity.as_ref().is_some_and(Self::valid_curve);
|
||||
self.picked_entity = None;
|
||||
|
||||
match self.step.clone() {
|
||||
@@ -312,9 +310,10 @@ mod tests {
|
||||
command.on_text_input("Object"),
|
||||
Some(CmdResult::NeedPoint)
|
||||
));
|
||||
command.inject_picked_entity(EntityType::Line(
|
||||
codec::entities::Line::from_points(Vector3::ZERO, Vector3::UNIT_X),
|
||||
));
|
||||
command.inject_picked_entity(EntityType::Line(codec::entities::Line::from_points(
|
||||
Vector3::ZERO,
|
||||
Vector3::UNIT_X,
|
||||
)));
|
||||
let handle = Handle::new(7);
|
||||
assert!(matches!(
|
||||
command.on_entity_pick(handle, DVec3::ZERO),
|
||||
|
||||
@@ -46,7 +46,11 @@ impl ConcentricConstraintCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn picked_reference(entity: &EntityType, handle: Handle, point: DVec3) -> Option<ParametricRef> {
|
||||
fn picked_reference(
|
||||
entity: &EntityType,
|
||||
handle: Handle,
|
||||
point: DVec3,
|
||||
) -> Option<ParametricRef> {
|
||||
match entity {
|
||||
EntityType::Circle(_) | EntityType::Arc(_) | EntityType::Ellipse(_) => {
|
||||
Some(ParametricRef::center(handle))
|
||||
@@ -167,10 +171,7 @@ mod tests {
|
||||
let mut polyline = codec::entities::LwPolyline::new();
|
||||
polyline.vertices = vec![
|
||||
codec::entities::LwVertex::from_coords(0.0, 0.0),
|
||||
codec::entities::LwVertex::with_bulge(
|
||||
codec::types::Vector2::new(5.0, 0.0),
|
||||
1.0,
|
||||
),
|
||||
codec::entities::LwVertex::with_bulge(codec::types::Vector2::new(5.0, 0.0), 1.0),
|
||||
codec::entities::LwVertex::from_coords(10.0, 0.0),
|
||||
];
|
||||
|
||||
|
||||
@@ -81,7 +81,10 @@ mod tests {
|
||||
let handles = vec![Handle::new(2), Handle::new(5)];
|
||||
let mut command = ConstraintBarOptionCommand::new(handles.clone());
|
||||
|
||||
assert_eq!(relaunch(command.on_enter()), ("GCSHOW".to_string(), handles));
|
||||
assert_eq!(
|
||||
relaunch(command.on_enter()),
|
||||
("GCSHOW".to_string(), handles)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -270,7 +270,10 @@ impl DimConstraintCommand {
|
||||
let r1 = first - vertex;
|
||||
let r2 = second - vertex;
|
||||
let at = location - vertex;
|
||||
if r1.length_squared() < 1.0e-18 || r2.length_squared() < 1.0e-18 || at.length_squared() < 1.0e-18 {
|
||||
if r1.length_squared() < 1.0e-18
|
||||
|| r2.length_squared() < 1.0e-18
|
||||
|| at.length_squared() < 1.0e-18
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let a1 = r1.y.atan2(r1.x);
|
||||
@@ -402,9 +405,10 @@ impl DimConstraintCommand {
|
||||
point: DVec3,
|
||||
) -> Option<(ParametricRef, ParametricRef)> {
|
||||
match entity {
|
||||
EntityType::Line(_) | EntityType::Arc(_) => {
|
||||
Some((ParametricRef::point(handle, 0), ParametricRef::point(handle, 1)))
|
||||
}
|
||||
EntityType::Line(_) | EntityType::Arc(_) => Some((
|
||||
ParametricRef::point(handle, 0),
|
||||
ParametricRef::point(handle, 1),
|
||||
)),
|
||||
EntityType::LwPolyline(_) | EntityType::Polyline2D(_) => {
|
||||
let (source, _, _) =
|
||||
crate::scene::centerline::picked_source(entity, handle, point)?;
|
||||
@@ -415,7 +419,10 @@ impl DimConstraintCommand {
|
||||
} else {
|
||||
0
|
||||
};
|
||||
Some((ParametricRef::point(handle, index), ParametricRef::point(handle, end)))
|
||||
Some((
|
||||
ParametricRef::point(handle, index),
|
||||
ParametricRef::point(handle, end),
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
@@ -456,18 +463,28 @@ impl DimConstraintCommand {
|
||||
// A text's baseline or an ellipse's axis is a line whose one
|
||||
// constraint point is the insertion point / the center.
|
||||
EntityType::Text(_) | EntityType::MText(_) => {
|
||||
return Self::axis_target(entity, ParametricRef::text_baseline(handle), ParametricRef::point(handle, 0));
|
||||
return Self::axis_target(
|
||||
entity,
|
||||
ParametricRef::text_baseline(handle),
|
||||
ParametricRef::point(handle, 0),
|
||||
);
|
||||
}
|
||||
EntityType::Ellipse(_) => {
|
||||
let center = ParametricRef::point(handle, -3);
|
||||
let major = Self::axis_target(entity, ParametricRef::ellipse_major_axis(handle), center);
|
||||
let minor = Self::axis_target(entity, ParametricRef::ellipse_minor_axis(handle), center);
|
||||
let major =
|
||||
Self::axis_target(entity, ParametricRef::ellipse_major_axis(handle), center);
|
||||
let minor =
|
||||
Self::axis_target(entity, ParametricRef::ellipse_minor_axis(handle), center);
|
||||
let gap = |target: &LineTarget| {
|
||||
let offset = point - target.ends[0].1;
|
||||
(offset.x * target.dir.y - offset.y * target.dir.x).abs()
|
||||
};
|
||||
return match (major, minor) {
|
||||
(Some(major), Some(minor)) => Some(if gap(&minor) < gap(&major) { minor } else { major }),
|
||||
(Some(major), Some(minor)) => Some(if gap(&minor) < gap(&major) {
|
||||
minor
|
||||
} else {
|
||||
major
|
||||
}),
|
||||
(major, minor) => major.or(minor),
|
||||
};
|
||||
}
|
||||
@@ -485,7 +502,11 @@ impl DimConstraintCommand {
|
||||
|
||||
/// A directional axis (text baseline, ellipse axis) as a line target
|
||||
/// whose only constraint point is `anchor`.
|
||||
fn axis_target(entity: &EntityType, axis: ParametricRef, anchor: ParametricRef) -> Option<LineTarget> {
|
||||
fn axis_target(
|
||||
entity: &EntityType,
|
||||
axis: ParametricRef,
|
||||
anchor: ParametricRef,
|
||||
) -> Option<LineTarget> {
|
||||
let [start, end] =
|
||||
crate::scene::parametric_constraints::directional_axis_endpoints(entity, axis)?;
|
||||
let (start, end) = (
|
||||
@@ -640,9 +661,7 @@ impl CadCommand for DimConstraintCommand {
|
||||
format!("{name} Specify second angle constraint point:")
|
||||
}
|
||||
Step::RadialObject => format!("{name} Select arc or circle:"),
|
||||
Step::AngularLocation { .. }
|
||||
| Step::Location { .. }
|
||||
| Step::RadialLocation { .. } => {
|
||||
Step::AngularLocation { .. } | Step::Location { .. } | Step::RadialLocation { .. } => {
|
||||
format!("{name} Specify dimension line location:")
|
||||
}
|
||||
Step::RadialValue { measured, .. } => format!(
|
||||
@@ -727,7 +746,9 @@ impl CadCommand for DimConstraintCommand {
|
||||
Step::Value { .. } | Step::AngularValue { .. } | Step::RadialValue { .. } => {
|
||||
let text = text.trim();
|
||||
let (name, expression) = match text.split_once('=') {
|
||||
Some((name, expression)) => (name.trim().to_string(), expression.trim().to_string()),
|
||||
Some((name, expression)) => {
|
||||
(name.trim().to_string(), expression.trim().to_string())
|
||||
}
|
||||
None => (self.default_name.clone(), text.to_string()),
|
||||
};
|
||||
match self.step {
|
||||
@@ -792,26 +813,27 @@ impl CadCommand for DimConstraintCommand {
|
||||
whole_curve: false,
|
||||
})
|
||||
}
|
||||
Step::PointLineLine { point: first, point_pos } => {
|
||||
match self.pick_line(handle, point) {
|
||||
Ok(line) => {
|
||||
if line.line.entity == first.entity {
|
||||
return Self::report(Self::SAME_POINT);
|
||||
}
|
||||
let (second, second_point) = line.nearest_end(point_pos);
|
||||
self.step = Step::Location {
|
||||
first,
|
||||
second,
|
||||
first_point: point_pos,
|
||||
second_point,
|
||||
direction: Some(line),
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
Step::PointLineLine {
|
||||
point: first,
|
||||
point_pos,
|
||||
} => match self.pick_line(handle, point) {
|
||||
Ok(line) => {
|
||||
if line.line.entity == first.entity {
|
||||
return Self::report(Self::SAME_POINT);
|
||||
}
|
||||
Err("") => CmdResult::NeedPoint,
|
||||
Err(message) => Self::report(message),
|
||||
let (second, second_point) = line.nearest_end(point_pos);
|
||||
self.step = Step::Location {
|
||||
first,
|
||||
second,
|
||||
first_point: point_pos,
|
||||
second_point,
|
||||
direction: Some(line),
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
}
|
||||
Err("") => CmdResult::NeedPoint,
|
||||
Err(message) => Self::report(message),
|
||||
},
|
||||
Step::LineFirst => match self.pick_line(handle, point) {
|
||||
Ok(line) => {
|
||||
self.step = Step::LinePoint { line };
|
||||
@@ -989,7 +1011,12 @@ impl CadCommand for DimConstraintCommand {
|
||||
}
|
||||
|
||||
fn accept_parallel_line(&mut self, ends: [(ParametricRef, DVec3); 2]) -> CmdResult {
|
||||
let Step::TwoLinesParallel { first, second, pick } = self.step else {
|
||||
let Step::TwoLinesParallel {
|
||||
first,
|
||||
second,
|
||||
pick,
|
||||
} = self.step
|
||||
else {
|
||||
return CmdResult::NeedPoint;
|
||||
};
|
||||
let Some(dir) = (ends[1].1 - ends[0].1).try_normalize() else {
|
||||
@@ -1458,8 +1485,13 @@ mod tests {
|
||||
"DCLINEAR Enter value or name and value <d1=100>:"
|
||||
);
|
||||
let CmdResult::AddDimensionalConstraint {
|
||||
kind, name, expression, ..
|
||||
} = command.on_text_input("w=d1*2").expect("a value builds the constraint")
|
||||
kind,
|
||||
name,
|
||||
expression,
|
||||
..
|
||||
} = command
|
||||
.on_text_input("w=d1*2")
|
||||
.expect("a value builds the constraint")
|
||||
else {
|
||||
panic!("the value must build the constraint");
|
||||
};
|
||||
|
||||
@@ -202,7 +202,10 @@ mod tests {
|
||||
use codec::types::Vector3;
|
||||
|
||||
fn line() -> EntityType {
|
||||
EntityType::Line(Line::from_points(Vector3::ZERO, Vector3::new(10.0, 0.0, 0.0)))
|
||||
EntityType::Line(Line::from_points(
|
||||
Vector3::ZERO,
|
||||
Vector3::new(10.0, 0.0, 0.0),
|
||||
))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -231,7 +234,10 @@ mod tests {
|
||||
#[test]
|
||||
fn multiple_applies_each_pick_and_ends_on_enter() {
|
||||
let mut command = EqualConstraintCommand::new();
|
||||
assert!(matches!(command.on_text_input("M"), Some(CmdResult::NeedPoint)));
|
||||
assert!(matches!(
|
||||
command.on_text_input("M"),
|
||||
Some(CmdResult::NeedPoint)
|
||||
));
|
||||
command.inject_picked_entity(line());
|
||||
command.on_entity_pick(Handle::new(7), DVec3::ZERO);
|
||||
command.inject_picked_entity(line());
|
||||
|
||||
@@ -62,10 +62,7 @@ impl CadCommand for GeomConstraintCommand {
|
||||
}
|
||||
|
||||
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
||||
let keyword = text
|
||||
.trim()
|
||||
.trim_start_matches('_')
|
||||
.to_ascii_uppercase();
|
||||
let keyword = text.trim().trim_start_matches('_').to_ascii_uppercase();
|
||||
Self::dispatch(&keyword).map(|command| CmdResult::Dispatch(command.to_string()))
|
||||
}
|
||||
|
||||
|
||||
+142
-41
@@ -4,17 +4,17 @@
|
||||
|
||||
mod coincident;
|
||||
mod concentric;
|
||||
mod dim_constraint;
|
||||
mod parameters_cli;
|
||||
mod constraint_bar;
|
||||
mod equal_distance;
|
||||
mod dim_constraint;
|
||||
#[path = "equal.rs"]
|
||||
mod equal_command;
|
||||
mod equal_distance;
|
||||
#[path = "fixed.rs"]
|
||||
mod fixed_command;
|
||||
mod geom_constraint;
|
||||
#[path = "horizontal.rs"]
|
||||
mod horizontal_command;
|
||||
mod parameters_cli;
|
||||
#[path = "perpendicular.rs"]
|
||||
mod perpendicular_command;
|
||||
mod point_on_entity;
|
||||
@@ -27,17 +27,17 @@ mod tools;
|
||||
mod value;
|
||||
pub use coincident::{coincident_tool, CoincidentConstraintCommand};
|
||||
pub use concentric::ConcentricConstraintCommand;
|
||||
pub use constraint_bar::ConstraintBarOptionCommand;
|
||||
pub use dim_constraint::{
|
||||
ConstraintFormCommand, DimConstraintAxis, DimConstraintCommand, DimConstraintMenuCommand,
|
||||
DimensionValueCommand,
|
||||
};
|
||||
pub use parameters_cli::ParametersCliCommand;
|
||||
pub use constraint_bar::ConstraintBarOptionCommand;
|
||||
pub use equal_command::EqualConstraintCommand;
|
||||
pub use equal_distance::{equal_distance_tool, EqualDistanceConstraintCommand};
|
||||
pub use fixed_command::FixConstraintCommand;
|
||||
pub use geom_constraint::GeomConstraintCommand;
|
||||
pub use horizontal_command::HorizontalConstraintCommand;
|
||||
pub use parameters_cli::ParametersCliCommand;
|
||||
pub use perpendicular_command::{PerpendicularConstraintCommand, PerpendicularPick};
|
||||
pub use point_on_entity::{
|
||||
center_point_tool, midpoint_tool, point_on_curve_tool, PointOnEntityConstraintCommand,
|
||||
@@ -50,8 +50,7 @@ pub use tools::{
|
||||
perpendicular, symmetric, tangent, vertical,
|
||||
};
|
||||
pub use value::{
|
||||
angle_tool, dimensional_tools, distance_tool,
|
||||
DistanceConstraintCommand, DistanceMode,
|
||||
angle_tool, dimensional_tools, distance_tool, DistanceConstraintCommand, DistanceMode,
|
||||
};
|
||||
|
||||
use crate::modules::{CadModule, IconKind, ModuleEvent, RibbonGroup, RibbonItem, ToolDef};
|
||||
@@ -71,14 +70,18 @@ impl CadModule for ParametricModule {
|
||||
static GROUPS: std::sync::OnceLock<Vec<RibbonGroup>> = std::sync::OnceLock::new();
|
||||
GROUPS.get_or_init(|| {
|
||||
let command = |id: &'static str, label: &'static str, icon: &'static [u8]| ToolDef {
|
||||
id, label, icon: IconKind::Svg(icon), event: ModuleEvent::Command(id.to_string()),
|
||||
id,
|
||||
label,
|
||||
icon: IconKind::Svg(icon),
|
||||
event: ModuleEvent::Command(id.to_string()),
|
||||
};
|
||||
vec![
|
||||
RibbonGroup {
|
||||
title: "Geometric",
|
||||
tools: vec![
|
||||
RibbonItem::LargeTool(command(
|
||||
"AUTOCONSTRAIN", "Auto Constrain",
|
||||
"AUTOCONSTRAIN",
|
||||
"Auto Constrain",
|
||||
include_bytes!("../../../assets/icons/constrain/auto.svg"),
|
||||
)),
|
||||
RibbonItem::LargeTool(coincident_tool::tool()),
|
||||
@@ -87,7 +90,8 @@ impl CadModule for ParametricModule {
|
||||
RibbonItem::LargeTool(colinear::tool()),
|
||||
RibbonItem::LargeTool(perpendicular::tool()),
|
||||
RibbonItem::LargeTool(command(
|
||||
"GCSMOOTH", "Smooth",
|
||||
"GCSMOOTH",
|
||||
"Smooth",
|
||||
include_bytes!("../../../assets/icons/constrain/smooth.svg"),
|
||||
)),
|
||||
RibbonItem::LargeTool(concentric_tool::tool()),
|
||||
@@ -97,19 +101,45 @@ impl CadModule for ParametricModule {
|
||||
RibbonItem::LargeTool(vertical::tool()),
|
||||
RibbonItem::LargeTool(equal::tool()),
|
||||
RibbonItem::LabeledDropdown {
|
||||
id: "GCVISIBILITY", label: "Show/Hide",
|
||||
icon: IconKind::Svg(include_bytes!("../../../assets/icons/constrain/show.svg")),
|
||||
id: "GCVISIBILITY",
|
||||
label: "Show/Hide",
|
||||
icon: IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/show.svg"
|
||||
)),
|
||||
items: vec![
|
||||
("GCSHOW", "Show", IconKind::Svg(include_bytes!("../../../assets/icons/constrain/show.svg"))),
|
||||
("GCHIDE", "Hide", IconKind::Svg(include_bytes!("../../../assets/icons/constrain/hide_all.svg"))),
|
||||
("GCRESET", "Reset", IconKind::Svg(include_bytes!("../../../assets/icons/constrain/show.svg"))),
|
||||
], default: "GCSHOW",
|
||||
(
|
||||
"GCSHOW",
|
||||
"Show",
|
||||
IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/show.svg"
|
||||
)),
|
||||
),
|
||||
(
|
||||
"GCHIDE",
|
||||
"Hide",
|
||||
IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/hide_all.svg"
|
||||
)),
|
||||
),
|
||||
(
|
||||
"GCRESET",
|
||||
"Reset",
|
||||
IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/show.svg"
|
||||
)),
|
||||
),
|
||||
],
|
||||
default: "GCSHOW",
|
||||
},
|
||||
RibbonItem::LabeledTool(command(
|
||||
"GCSHOWALL", "Show All", include_bytes!("../../../assets/icons/constrain/show_all.svg"),
|
||||
"GCSHOWALL",
|
||||
"Show All",
|
||||
include_bytes!("../../../assets/icons/constrain/show_all.svg"),
|
||||
)),
|
||||
RibbonItem::LabeledTool(command(
|
||||
"GCHIDEALL", "Hide All", include_bytes!("../../../assets/icons/constrain/hide_all.svg"),
|
||||
"GCHIDEALL",
|
||||
"Hide All",
|
||||
include_bytes!("../../../assets/icons/constrain/hide_all.svg"),
|
||||
)),
|
||||
],
|
||||
},
|
||||
@@ -117,9 +147,17 @@ impl CadModule for ParametricModule {
|
||||
title: "Dimensional",
|
||||
tools: vec![
|
||||
RibbonItem::LargeDropdown {
|
||||
id: "DC_LINEAR_MENU", label: "Linear", icon: dimensional_tools::linear().icon,
|
||||
items: [dimensional_tools::linear(), dimensional_tools::horizontal(), dimensional_tools::vertical()]
|
||||
.iter().map(|tool| (tool.id, tool.label, tool.icon)).collect(),
|
||||
id: "DC_LINEAR_MENU",
|
||||
label: "Linear",
|
||||
icon: dimensional_tools::linear().icon,
|
||||
items: [
|
||||
dimensional_tools::linear(),
|
||||
dimensional_tools::horizontal(),
|
||||
dimensional_tools::vertical(),
|
||||
]
|
||||
.iter()
|
||||
.map(|tool| (tool.id, tool.label, tool.icon))
|
||||
.collect(),
|
||||
default: "DCLINEAR",
|
||||
},
|
||||
RibbonItem::LargeTool(dimensional_tools::aligned()),
|
||||
@@ -132,18 +170,38 @@ impl CadModule for ParametricModule {
|
||||
],
|
||||
},
|
||||
RibbonItem::LabeledDropdown {
|
||||
id: "DCVISIBILITY", label: "Show/Hide",
|
||||
icon: IconKind::Svg(include_bytes!("../../../assets/icons/constrain/show.svg")),
|
||||
id: "DCVISIBILITY",
|
||||
label: "Show/Hide",
|
||||
icon: IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/show.svg"
|
||||
)),
|
||||
items: vec![
|
||||
("DCSHOW", "Show", IconKind::Svg(include_bytes!("../../../assets/icons/constrain/show.svg"))),
|
||||
("DCHIDE", "Hide", IconKind::Svg(include_bytes!("../../../assets/icons/constrain/hide_all.svg"))),
|
||||
], default: "DCSHOW",
|
||||
(
|
||||
"DCSHOW",
|
||||
"Show",
|
||||
IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/show.svg"
|
||||
)),
|
||||
),
|
||||
(
|
||||
"DCHIDE",
|
||||
"Hide",
|
||||
IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/constrain/hide_all.svg"
|
||||
)),
|
||||
),
|
||||
],
|
||||
default: "DCSHOW",
|
||||
},
|
||||
RibbonItem::LabeledTool(command(
|
||||
"DCSHOWALL", "Show All", include_bytes!("../../../assets/icons/constrain/show_all.svg"),
|
||||
"DCSHOWALL",
|
||||
"Show All",
|
||||
include_bytes!("../../../assets/icons/constrain/show_all.svg"),
|
||||
)),
|
||||
RibbonItem::LabeledTool(command(
|
||||
"DCHIDEALL", "Hide All", include_bytes!("../../../assets/icons/constrain/hide_all.svg"),
|
||||
"DCHIDEALL",
|
||||
"Hide All",
|
||||
include_bytes!("../../../assets/icons/constrain/hide_all.svg"),
|
||||
)),
|
||||
],
|
||||
},
|
||||
@@ -151,10 +209,14 @@ impl CadModule for ParametricModule {
|
||||
title: "Manage",
|
||||
tools: vec![
|
||||
RibbonItem::LargeTool(command(
|
||||
"DELCONSTRAINT", "Delete Constraints", include_bytes!("../../../assets/icons/constrain/delete.svg"),
|
||||
"DELCONSTRAINT",
|
||||
"Delete Constraints",
|
||||
include_bytes!("../../../assets/icons/constrain/delete.svg"),
|
||||
)),
|
||||
RibbonItem::LargeTool(command(
|
||||
"PARAMETERS", "Parameters Manager", include_bytes!("../../../assets/icons/constrain/parameters.svg"),
|
||||
"PARAMETERS",
|
||||
"Parameters Manager",
|
||||
include_bytes!("../../../assets/icons/constrain/parameters.svg"),
|
||||
)),
|
||||
],
|
||||
},
|
||||
@@ -165,9 +227,23 @@ impl CadModule for ParametricModule {
|
||||
|
||||
inventory::submit!(crate::command::CommandRegistration {
|
||||
names: &[
|
||||
"AUTOCONSTRAIN", "CONSTRAINTSETTINGS", "GCSMOOTH", "GCSHOW", "GCHIDE", "GCRESET",
|
||||
"GCSHOWALL", "GCHIDEALL", "DCSHOW", "DCHIDE", "DCSHOWALL", "DCHIDEALL",
|
||||
"DCCONVERT", "DELCONSTRAINT", "DIMCONSTRAINT", "DCFORM", "-PARAMETERS",
|
||||
"AUTOCONSTRAIN",
|
||||
"CONSTRAINTSETTINGS",
|
||||
"GCSMOOTH",
|
||||
"GCSHOW",
|
||||
"GCHIDE",
|
||||
"GCRESET",
|
||||
"GCSHOWALL",
|
||||
"GCHIDEALL",
|
||||
"DCSHOW",
|
||||
"DCHIDE",
|
||||
"DCSHOWALL",
|
||||
"DCHIDEALL",
|
||||
"DCCONVERT",
|
||||
"DELCONSTRAINT",
|
||||
"DIMCONSTRAINT",
|
||||
"DCFORM",
|
||||
"-PARAMETERS",
|
||||
]
|
||||
});
|
||||
|
||||
@@ -177,8 +253,11 @@ mod tests {
|
||||
|
||||
fn item_id(item: &RibbonItem) -> &'static str {
|
||||
match item {
|
||||
RibbonItem::Tool(tool) | RibbonItem::LabeledTool(tool) | RibbonItem::LargeTool(tool) => tool.id,
|
||||
RibbonItem::Dropdown { id, .. } | RibbonItem::LabeledDropdown { id, .. }
|
||||
RibbonItem::Tool(tool)
|
||||
| RibbonItem::LabeledTool(tool)
|
||||
| RibbonItem::LargeTool(tool) => tool.id,
|
||||
RibbonItem::Dropdown { id, .. }
|
||||
| RibbonItem::LabeledDropdown { id, .. }
|
||||
| RibbonItem::LargeDropdown { id, .. } => id,
|
||||
RibbonItem::ToolGrid { .. } => "GRID",
|
||||
_ => panic!("unexpected composite ribbon item"),
|
||||
@@ -196,15 +275,34 @@ mod tests {
|
||||
assert_eq!(
|
||||
groups[0].tools.iter().map(item_id).collect::<Vec<_>>(),
|
||||
[
|
||||
"AUTOCONSTRAIN", "CCONSTRAINT", "PCONSTRAINT", "TCONSTRAINT",
|
||||
"LCONSTRAINT", "QCONSTRAINT", "GCSMOOTH", "GCCONCENTRIC",
|
||||
"GCHORIZONTAL", "SYCONSTRAINT", "FXCONSTRAINT", "VCONSTRAINT",
|
||||
"ECONSTRAINT", "GCVISIBILITY", "GCSHOWALL", "GCHIDEALL",
|
||||
"AUTOCONSTRAIN",
|
||||
"CCONSTRAINT",
|
||||
"PCONSTRAINT",
|
||||
"TCONSTRAINT",
|
||||
"LCONSTRAINT",
|
||||
"QCONSTRAINT",
|
||||
"GCSMOOTH",
|
||||
"GCCONCENTRIC",
|
||||
"GCHORIZONTAL",
|
||||
"SYCONSTRAINT",
|
||||
"FXCONSTRAINT",
|
||||
"VCONSTRAINT",
|
||||
"ECONSTRAINT",
|
||||
"GCVISIBILITY",
|
||||
"GCSHOWALL",
|
||||
"GCHIDEALL",
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
groups[1].tools.iter().map(item_id).collect::<Vec<_>>(),
|
||||
["DC_LINEAR_MENU", "DCALIGNED", "GRID", "DCVISIBILITY", "DCSHOWALL", "DCHIDEALL"]
|
||||
[
|
||||
"DC_LINEAR_MENU",
|
||||
"DCALIGNED",
|
||||
"GRID",
|
||||
"DCVISIBILITY",
|
||||
"DCSHOWALL",
|
||||
"DCHIDEALL"
|
||||
]
|
||||
);
|
||||
let RibbonItem::ToolGrid { columns } = &groups[1].tools[2] else {
|
||||
panic!("radius, diameter, angular and convert must be a small-button grid");
|
||||
@@ -216,7 +314,10 @@ mod tests {
|
||||
.collect::<Vec<_>>(),
|
||||
[["DCRADIUS", "DCANGULAR"], ["DCDIAMETER", "DCCONVERT"]]
|
||||
);
|
||||
assert_eq!(groups[2].tools.iter().map(item_id).collect::<Vec<_>>(), ["DELCONSTRAINT", "PARAMETERS"]);
|
||||
assert_eq!(
|
||||
groups[2].tools.iter().map(item_id).collect::<Vec<_>>(),
|
||||
["DELCONSTRAINT", "PARAMETERS"]
|
||||
);
|
||||
|
||||
let RibbonItem::LargeDropdown { items, default, .. } = &groups[1].tools[0] else {
|
||||
panic!("linear dimensional constraint must be a split dropdown");
|
||||
|
||||
@@ -112,22 +112,22 @@ impl CadCommand for ParametersCliCommand {
|
||||
};
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
Step::NewExpression { name } => {
|
||||
Some(CmdResult::Dispatch(format!("-PARAMETERS NEW {name} {text}")))
|
||||
}
|
||||
Step::NewExpression { name } => Some(CmdResult::Dispatch(format!(
|
||||
"-PARAMETERS NEW {name} {text}"
|
||||
))),
|
||||
Step::EditName => Some(CmdResult::Dispatch(format!("-PARAMETERS EDIT {text}"))),
|
||||
Step::EditExpression { name } => {
|
||||
Some(CmdResult::Dispatch(format!("-PARAMETERS SET {name} {text}")))
|
||||
}
|
||||
Step::EditExpression { name } => Some(CmdResult::Dispatch(format!(
|
||||
"-PARAMETERS SET {name} {text}"
|
||||
))),
|
||||
Step::RenameOld => {
|
||||
self.step = Step::RenameNew {
|
||||
old: text.to_string(),
|
||||
};
|
||||
Some(CmdResult::NeedPoint)
|
||||
}
|
||||
Step::RenameNew { old } => {
|
||||
Some(CmdResult::Dispatch(format!("-PARAMETERS RENAME {old} {text}")))
|
||||
}
|
||||
Step::RenameNew { old } => Some(CmdResult::Dispatch(format!(
|
||||
"-PARAMETERS RENAME {old} {text}"
|
||||
))),
|
||||
Step::DeleteName => Some(CmdResult::Dispatch(format!("-PARAMETERS DELETE {text}"))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,11 @@ impl SmoothConstraintCommand {
|
||||
.map(|(index, _)| index as i32)
|
||||
}
|
||||
|
||||
fn source_reference(entity: &EntityType, handle: Handle, point: DVec3) -> Option<ParametricRef> {
|
||||
fn source_reference(
|
||||
entity: &EntityType,
|
||||
handle: Handle,
|
||||
point: DVec3,
|
||||
) -> Option<ParametricRef> {
|
||||
let EntityType::Spline(spline) = entity else {
|
||||
return None;
|
||||
};
|
||||
@@ -109,32 +113,24 @@ impl SmoothConstraintCommand {
|
||||
) -> Option<Vec<ParametricRef>> {
|
||||
let source_points = crate::scene::dimension_assoc::source_points(first.0);
|
||||
let source_ends = [*source_points.first()?, *source_points.last()?];
|
||||
let source_point = source_ends
|
||||
.iter()
|
||||
.copied()
|
||||
.min_by(|left, right| {
|
||||
let target_points = crate::scene::dimension_assoc::source_points(second.0);
|
||||
let distance = |source: codec::types::Vector3| {
|
||||
target_points
|
||||
.iter()
|
||||
.map(|target| (source - *target).length_squared())
|
||||
.fold(f64::INFINITY, f64::min)
|
||||
};
|
||||
distance(*left).total_cmp(&distance(*right))
|
||||
})?;
|
||||
let source_point = source_ends.iter().copied().min_by(|left, right| {
|
||||
let target_points = crate::scene::dimension_assoc::source_points(second.0);
|
||||
let distance = |source: codec::types::Vector3| {
|
||||
target_points
|
||||
.iter()
|
||||
.map(|target| (source - *target).length_squared())
|
||||
.fold(f64::INFINITY, f64::min)
|
||||
};
|
||||
distance(*left).total_cmp(&distance(*right))
|
||||
})?;
|
||||
let source = Self::source_reference(first.0, first.1, Self::point(source_point))?;
|
||||
|
||||
let target_points = crate::scene::dimension_assoc::source_points(second.0);
|
||||
let target_point = target_points
|
||||
.iter()
|
||||
.copied()
|
||||
.min_by(|left, right| {
|
||||
(Self::point(*left) - Self::point(source_point))
|
||||
.length_squared()
|
||||
.total_cmp(
|
||||
&(Self::point(*right) - Self::point(source_point)).length_squared(),
|
||||
)
|
||||
})?;
|
||||
let target_point = target_points.iter().copied().min_by(|left, right| {
|
||||
(Self::point(*left) - Self::point(source_point))
|
||||
.length_squared()
|
||||
.total_cmp(&(Self::point(*right) - Self::point(source_point)).length_squared())
|
||||
})?;
|
||||
let target = Self::target_reference(second.0, second.1, Self::point(target_point))?;
|
||||
let mut refs = vec![source, target.endpoint];
|
||||
if target.curve.marker.is_some() {
|
||||
@@ -242,10 +238,7 @@ mod tests {
|
||||
let mut polyline = codec::entities::LwPolyline::new();
|
||||
polyline.vertices = vec![
|
||||
codec::entities::LwVertex::from_coords(0.0, 0.0),
|
||||
codec::entities::LwVertex::with_bulge(
|
||||
codec::types::Vector2::new(5.0, 0.0),
|
||||
1.0,
|
||||
),
|
||||
codec::entities::LwVertex::with_bulge(codec::types::Vector2::new(5.0, 0.0), 1.0),
|
||||
codec::entities::LwVertex::from_coords(10.0, 0.0),
|
||||
];
|
||||
|
||||
|
||||
@@ -193,15 +193,11 @@ impl CadCommand for SymmetricConstraintCommand {
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match self.step {
|
||||
Step::ObjectOrTwoPoints => {
|
||||
"Select first object or [2Points] <2Points>:".to_string()
|
||||
}
|
||||
Step::ObjectOrTwoPoints => "Select first object or [2Points] <2Points>:".to_string(),
|
||||
Step::SecondObject(_) => "Select second object:".to_string(),
|
||||
Step::FirstPoint => "Select first point:".to_string(),
|
||||
Step::SecondPoint(_) => "Select second point:".to_string(),
|
||||
Step::ObjectAxis(_, _) | Step::PointAxis(_, _) => {
|
||||
"Select symmetry line:".to_string()
|
||||
}
|
||||
Step::ObjectAxis(_, _) | Step::PointAxis(_, _) => "Select symmetry line:".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,8 @@ impl TangentConstraintCommand {
|
||||
}
|
||||
EntityType::Ellipse(_) => (ParametricRef::whole(handle), TangentOperand::Ellipse),
|
||||
EntityType::LwPolyline(_) | EntityType::Polyline2D(_) => {
|
||||
let (source, _, _) = crate::scene::centerline::picked_source(entity, handle, point)?;
|
||||
let (source, _, _) =
|
||||
crate::scene::centerline::picked_source(entity, handle, point)?;
|
||||
let index = usize::try_from(source.segment_index).ok()?;
|
||||
(ParametricRef::segment(handle, index), TangentOperand::Line)
|
||||
}
|
||||
@@ -66,10 +67,7 @@ impl TangentConstraintCommand {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn preselected_reference(
|
||||
entity: &EntityType,
|
||||
handle: Handle,
|
||||
) -> Option<ParametricRef> {
|
||||
pub fn preselected_reference(entity: &EntityType, handle: Handle) -> Option<ParametricRef> {
|
||||
match entity {
|
||||
EntityType::Line(_)
|
||||
| EntityType::Circle(_)
|
||||
@@ -141,9 +139,7 @@ impl CadCommand for TangentConstraintCommand {
|
||||
self.first = Some(pick);
|
||||
return CmdResult::NeedPoint;
|
||||
};
|
||||
if first.reference == pick.reference
|
||||
|| !Self::pair_supported(first.operand, pick.operand)
|
||||
{
|
||||
if first.reference == pick.reference || !Self::pair_supported(first.operand, pick.operand) {
|
||||
return Self::invalid_selection();
|
||||
}
|
||||
CmdResult::AddTangentConstraint {
|
||||
|
||||
Reference in new issue
Block a user