forked from 1b-agent/opencadstudio-upstream
cargo fmt
This commit is contained in:
1 parent
468cbde5e1
commit
ca07268c7c
204 files changed
+13997
-5525
No files matched your search
@@ -37,13 +37,15 @@ impl AlignedDimensionCommand {
|
||||
}
|
||||
|
||||
impl CadCommand for AlignedDimensionCommand {
|
||||
fn name(&self) -> &'static str { "DIMALIGNED" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMALIGNED"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match self.step {
|
||||
Step::First => "DIMALIGNED Specify first extension line origin:".into(),
|
||||
Step::Second(_) => "DIMALIGNED Specify second extension line origin:".into(),
|
||||
Step::DimLine { .. } => "DIMALIGNED Specify dimension line location:".into(),
|
||||
Step::First => "DIMALIGNED Specify first extension line origin:".into(),
|
||||
Step::Second(_) => "DIMALIGNED Specify second extension line origin:".into(),
|
||||
Step::DimLine { .. } => "DIMALIGNED Specify dimension line location:".into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,13 +67,11 @@ impl CadCommand for AlignedDimensionCommand {
|
||||
let offset = (dx * dx + dy * dy).sqrt();
|
||||
dim.set_offset(offset);
|
||||
dim.base.definition_point = v3(pt);
|
||||
dim.base.text_middle_point = v3(
|
||||
Vec3::new(
|
||||
(p1.x + p2.x) * 0.5,
|
||||
(p1.y + p2.y) * 0.5,
|
||||
(p1.z + p2.z) * 0.5,
|
||||
)
|
||||
);
|
||||
dim.base.text_middle_point = v3(Vec3::new(
|
||||
(p1.x + p2.x) * 0.5,
|
||||
(p1.y + p2.y) * 0.5,
|
||||
(p1.z + p2.z) * 0.5,
|
||||
));
|
||||
dim.base.insertion_point = dim.base.text_middle_point;
|
||||
dim.base.actual_measurement = dim.measurement();
|
||||
CmdResult::CommitAndExit(EntityType::Dimension(Dimension::Aligned(dim)))
|
||||
@@ -79,7 +79,9 @@ impl CadCommand for AlignedDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
let (p1, p2) = match self.step {
|
||||
@@ -123,11 +125,14 @@ fn preview_aligned(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> WireModel {
|
||||
WireModel {
|
||||
name: "dimaligned_preview".into(),
|
||||
points: vec![
|
||||
[p1.x, p1.y, p1.z], [d1.x, d1.y, d1.z],
|
||||
[p1.x, p1.y, p1.z],
|
||||
[d1.x, d1.y, d1.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[p2.x, p2.y, p2.z], [d2.x, d2.y, d2.z],
|
||||
[p2.x, p2.y, p2.z],
|
||||
[d2.x, d2.y, d2.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[d1.x, d1.y, d1.z], [d2.x, d2.y, d2.z],
|
||||
[d1.x, d1.y, d1.z],
|
||||
[d2.x, d2.y, d2.z],
|
||||
],
|
||||
color: WireModel::CYAN,
|
||||
selected: false,
|
||||
@@ -137,10 +142,10 @@ fn preview_aligned(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,15 @@ pub fn tool() -> ToolDef {
|
||||
enum Step {
|
||||
Vertex,
|
||||
FirstRay(Vec3),
|
||||
SecondRay { vertex: Vec3, first: Vec3 },
|
||||
ArcPoint { vertex: Vec3, first: Vec3, second: Vec3 },
|
||||
SecondRay {
|
||||
vertex: Vec3,
|
||||
first: Vec3,
|
||||
},
|
||||
ArcPoint {
|
||||
vertex: Vec3,
|
||||
first: Vec3,
|
||||
second: Vec3,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct AngularDimensionCommand {
|
||||
@@ -95,9 +102,13 @@ impl CadCommand for AngularDimensionCommand {
|
||||
match self.step {
|
||||
Step::Vertex => None,
|
||||
Step::FirstRay(vertex) => Some(preview_wire(vec![vertex, pt])),
|
||||
Step::SecondRay { vertex, first } => {
|
||||
Some(preview_wire(vec![vertex, first, Vec3::new(f32::NAN, f32::NAN, f32::NAN), vertex, pt]))
|
||||
}
|
||||
Step::SecondRay { vertex, first } => Some(preview_wire(vec![
|
||||
vertex,
|
||||
first,
|
||||
Vec3::new(f32::NAN, f32::NAN, f32::NAN),
|
||||
vertex,
|
||||
pt,
|
||||
])),
|
||||
Step::ArcPoint {
|
||||
vertex,
|
||||
first,
|
||||
@@ -123,11 +134,11 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,17 +32,23 @@ pub struct DdeditCommand {
|
||||
|
||||
impl DdeditCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: DdeditStep::PickEntity }
|
||||
Self {
|
||||
step: DdeditStep::PickEntity,
|
||||
}
|
||||
}
|
||||
|
||||
/// Start with a pre-picked entity (for double-click use).
|
||||
pub fn with_handle(handle: Handle, current: String) -> Self {
|
||||
Self { step: DdeditStep::EnterText { handle, current } }
|
||||
Self {
|
||||
step: DdeditStep::EnterText { handle, current },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for DdeditCommand {
|
||||
fn name(&self) -> &'static str { "DDEDIT" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DDEDIT"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
@@ -58,10 +64,15 @@ impl CadCommand for DdeditCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
// The current value will be filled in by the caller (commands.rs dispatch)
|
||||
// via on_text_input once the entity is known. Store handle here.
|
||||
self.step = DdeditStep::EnterText { handle, current: String::new() };
|
||||
self.step = DdeditStep::EnterText {
|
||||
handle,
|
||||
current: String::new(),
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
@@ -75,23 +86,32 @@ impl CadCommand for DdeditCommand {
|
||||
_ => return None,
|
||||
};
|
||||
// Empty input → keep existing text
|
||||
let new_text = if text.trim().is_empty() { current } else { text.to_string() };
|
||||
let new_text = if text.trim().is_empty() {
|
||||
current
|
||||
} else {
|
||||
text.to_string()
|
||||
};
|
||||
Some(CmdResult::DdeditEntity { handle, new_text })
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult { CmdResult::NeedPoint }
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_escape(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
fn on_escape(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the text content from a Text or MText entity.
|
||||
pub fn entity_text(entity: &EntityType) -> Option<String> {
|
||||
match entity {
|
||||
EntityType::Text(t) => Some(t.value.clone()),
|
||||
EntityType::Text(t) => Some(t.value.clone()),
|
||||
EntityType::MText(t) => Some(t.value.clone()),
|
||||
EntityType::AttributeDefinition(a) => Some(a.default_value.clone()),
|
||||
EntityType::AttributeEntity(a) => Some(a.get_value().to_string()),
|
||||
EntityType::AttributeEntity(a) => Some(a.get_value().to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,18 +32,22 @@ pub struct DiameterDimensionCommand {
|
||||
|
||||
impl DiameterDimensionCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::CenterPoint }
|
||||
Self {
|
||||
step: Step::CenterPoint,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for DiameterDimensionCommand {
|
||||
fn name(&self) -> &'static str { "DIMDIAMETER" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMDIAMETER"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match self.step {
|
||||
Step::CenterPoint => "DIMDIAMETER Specify center point:".into(),
|
||||
Step::ArcPoint(_) => "DIMDIAMETER Specify point on circle:".into(),
|
||||
Step::TextPoint {..} => "DIMDIAMETER Specify dimension line location:".into(),
|
||||
Step::CenterPoint => "DIMDIAMETER Specify center point:".into(),
|
||||
Step::ArcPoint(_) => "DIMDIAMETER Specify point on circle:".into(),
|
||||
Step::TextPoint { .. } => "DIMDIAMETER Specify dimension line location:".into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +63,9 @@ impl CadCommand for DiameterDimensionCommand {
|
||||
}
|
||||
Step::TextPoint { center, arc_pt } => {
|
||||
let mut dim = DimensionDiameter::new(v3(center), v3(arc_pt));
|
||||
dim.base.definition_point = v3(arc_pt);
|
||||
dim.base.definition_point = v3(arc_pt);
|
||||
dim.base.text_middle_point = v3(pt);
|
||||
dim.base.insertion_point = v3(pt);
|
||||
dim.base.insertion_point = v3(pt);
|
||||
dim.leader_length = arc_pt.distance(pt) as f64;
|
||||
dim.base.actual_measurement = dim.measurement();
|
||||
CmdResult::CommitAndExit(EntityType::Dimension(Dimension::Diameter(dim)))
|
||||
@@ -69,7 +73,9 @@ impl CadCommand for DiameterDimensionCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
match self.step {
|
||||
@@ -99,10 +105,10 @@ fn preview_line(a: Vec3, b: Vec3) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,11 @@ impl DimBaselineCommand {
|
||||
/// `definition_point` — dim-line position of the base dim (defines perpendicular side).
|
||||
/// `rotation` — 0.0 = horizontal, PI/2 = vertical.
|
||||
pub fn from_base(p1: Vec3, _p2: Vec3, definition_point: Vec3, rotation: f64) -> Self {
|
||||
let axis = if rotation.abs() < 0.1 { Vec3::X } else { Vec3::Y };
|
||||
let axis = if rotation.abs() < 0.1 {
|
||||
Vec3::X
|
||||
} else {
|
||||
Vec3::Y
|
||||
};
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
let base_offset = (definition_point - p1).dot(perp);
|
||||
// Next baseline dim goes one DIMDLI further from the baseline.
|
||||
@@ -77,7 +81,9 @@ impl DimBaselineCommand {
|
||||
}
|
||||
|
||||
impl CadCommand for DimBaselineCommand {
|
||||
fn name(&self) -> &'static str { "DIMBASELINE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMBASELINE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
if !self.ready {
|
||||
@@ -126,9 +132,11 @@ impl CadCommand for DimBaselineCommand {
|
||||
Some(WireModel {
|
||||
name: "dimbase_preview".into(),
|
||||
points: vec![
|
||||
[p1.x, p1.y, p1.z], [dim_line_pt.x, dim_line_pt.y, dim_line_pt.z],
|
||||
[p1.x, p1.y, p1.z],
|
||||
[dim_line_pt.x, dim_line_pt.y, dim_line_pt.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[pt.x, pt.y, pt.z], [dim_line_pt2.x, dim_line_pt2.y, dim_line_pt2.z],
|
||||
[pt.x, pt.y, pt.z],
|
||||
[dim_line_pt2.x, dim_line_pt2.y, dim_line_pt2.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[dim_line_pt.x, dim_line_pt.y, dim_line_pt.z],
|
||||
[dim_line_pt2.x, dim_line_pt2.y, dim_line_pt2.z],
|
||||
|
||||
@@ -59,7 +59,11 @@ impl DimContinueCommand {
|
||||
/// `rotation` — 0.0 = horizontal dim, PI/2 = vertical dim.
|
||||
pub fn from_base(p1: Vec3, p2: Vec3, definition_point: Vec3, rotation: f64) -> Self {
|
||||
// Axis unit vector along the measurement direction.
|
||||
let axis = if rotation.abs() < 0.1 { Vec3::X } else { Vec3::Y };
|
||||
let axis = if rotation.abs() < 0.1 {
|
||||
Vec3::X
|
||||
} else {
|
||||
Vec3::Y
|
||||
};
|
||||
// Perpendicular unit vector toward the dim line.
|
||||
let perp = Vec3::new(-axis.y, axis.x, 0.0);
|
||||
let dim_offset = (definition_point - p1).dot(perp);
|
||||
@@ -74,7 +78,9 @@ impl DimContinueCommand {
|
||||
}
|
||||
|
||||
impl CadCommand for DimContinueCommand {
|
||||
fn name(&self) -> &'static str { "DIMCONTINUE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMCONTINUE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
if !self.ready {
|
||||
@@ -123,9 +129,11 @@ impl CadCommand for DimContinueCommand {
|
||||
Some(WireModel {
|
||||
name: "dimcont_preview".into(),
|
||||
points: vec![
|
||||
[p1.x, p1.y, p1.z], [dim_line_pt.x, dim_line_pt.y, dim_line_pt.z],
|
||||
[p1.x, p1.y, p1.z],
|
||||
[dim_line_pt.x, dim_line_pt.y, dim_line_pt.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[pt.x, pt.y, pt.z], [dim_line_pt2.x, dim_line_pt2.y, dim_line_pt2.z],
|
||||
[pt.x, pt.y, pt.z],
|
||||
[dim_line_pt2.x, dim_line_pt2.y, dim_line_pt2.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[dim_line_pt.x, dim_line_pt.y, dim_line_pt.z],
|
||||
[dim_line_pt2.x, dim_line_pt2.y, dim_line_pt2.z],
|
||||
|
||||
@@ -37,24 +37,34 @@ pub struct DimBreakCommand {
|
||||
|
||||
impl DimBreakCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::PickDim }
|
||||
Self {
|
||||
step: Step::PickDim,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for DimBreakCommand {
|
||||
fn name(&self) -> &'static str { "DIMBREAK" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMBREAK"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::PickDim => "DIMBREAK Select dimension to break:".into(),
|
||||
Step::PickCrossing { .. } => "DIMBREAK Select object to break at, or Enter for Auto:".into(),
|
||||
Step::PickCrossing { .. } => {
|
||||
"DIMBREAK Select object to break at, or Enter for Auto:".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn needs_entity_pick(&self) -> bool { true }
|
||||
fn needs_entity_pick(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
match &self.step {
|
||||
Step::PickDim => {
|
||||
self.step = Step::PickCrossing { dim_handle: handle };
|
||||
@@ -71,7 +81,9 @@ impl CadCommand for DimBreakCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult { CmdResult::NeedPoint }
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
// Auto mode: apply to all crossings
|
||||
|
||||
@@ -32,17 +32,23 @@ pub struct DimEditCommand {
|
||||
|
||||
impl DimEditCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::PickDim }
|
||||
Self {
|
||||
step: Step::PickDim,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for DimEditCommand {
|
||||
fn name(&self) -> &'static str { "DIMEDIT" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMEDIT"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::PickDim => "DIMEDIT Select dimension:".into(),
|
||||
Step::EnterText { .. } => "DIMEDIT Enter text override (blank = reset to measured):".into(),
|
||||
Step::EnterText { .. } => {
|
||||
"DIMEDIT Enter text override (blank = reset to measured):".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +57,9 @@ impl CadCommand for DimEditCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
self.step = Step::EnterText { handle };
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
@@ -70,6 +78,10 @@ impl CadCommand for DimEditCommand {
|
||||
Some(CmdResult::DdeditEntity { handle, new_text })
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult { CmdResult::NeedPoint }
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
}
|
||||
@@ -33,12 +33,16 @@ pub struct DimJogLineCommand {
|
||||
|
||||
impl DimJogLineCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::PickDim }
|
||||
Self {
|
||||
step: Step::PickDim,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for DimJogLineCommand {
|
||||
fn name(&self) -> &'static str { "DIMJOGLINE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMJOGLINE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
@@ -52,7 +56,9 @@ impl CadCommand for DimJogLineCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
self.step = Step::PickJogPos { handle };
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
@@ -69,7 +75,9 @@ impl CadCommand for DimJogLineCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
if !matches!(self.step, Step::PickJogPos { .. }) {
|
||||
|
||||
@@ -34,18 +34,24 @@ pub struct DimSpaceCommand {
|
||||
|
||||
impl DimSpaceCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::PickBase }
|
||||
Self {
|
||||
step: Step::PickBase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for DimSpaceCommand {
|
||||
fn name(&self) -> &'static str { "DIMSPACE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMSPACE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::PickBase => "DIMSPACE Select base dimension:".into(),
|
||||
Step::PickOthers { others, .. } =>
|
||||
format!("DIMSPACE Select dimension to space ({} selected, Enter when done):", others.len()),
|
||||
Step::PickOthers { others, .. } => format!(
|
||||
"DIMSPACE Select dimension to space ({} selected, Enter when done):",
|
||||
others.len()
|
||||
),
|
||||
Step::EnterSpacing { .. } => "DIMSPACE Enter value (0 = auto):".into(),
|
||||
}
|
||||
}
|
||||
@@ -55,10 +61,15 @@ impl CadCommand for DimSpaceCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
match &mut self.step {
|
||||
Step::PickBase => {
|
||||
self.step = Step::PickOthers { base: handle, others: vec![] };
|
||||
self.step = Step::PickOthers {
|
||||
base: handle,
|
||||
others: vec![],
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
Step::PickOthers { others, .. } => {
|
||||
@@ -84,13 +95,23 @@ impl CadCommand for DimSpaceCommand {
|
||||
use acadrust::entities::XLine;
|
||||
let mut xl = XLine::default();
|
||||
let handles_str: Vec<String> = o.iter().map(|h| h.value().to_string()).collect();
|
||||
xl.common.layer = format!("__DIMSPACE__{},{},{}", b.value(), handles_str.join(";"), spacing);
|
||||
return Some(CmdResult::ReplaceEntity(b, vec![acadrust::EntityType::XLine(xl)]));
|
||||
xl.common.layer = format!(
|
||||
"__DIMSPACE__{},{},{}",
|
||||
b.value(),
|
||||
handles_str.join(";"),
|
||||
spacing
|
||||
);
|
||||
return Some(CmdResult::ReplaceEntity(
|
||||
b,
|
||||
vec![acadrust::EntityType::XLine(xl)],
|
||||
));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult { CmdResult::NeedPoint }
|
||||
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
match &self.step {
|
||||
|
||||
@@ -24,7 +24,10 @@ pub fn tool() -> ToolDef {
|
||||
|
||||
enum Step {
|
||||
PickDim,
|
||||
PickTextPos { handle: Handle, entity: Option<EntityType> },
|
||||
PickTextPos {
|
||||
handle: Handle,
|
||||
entity: Option<EntityType>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct DimTeditCommand {
|
||||
@@ -33,13 +36,16 @@ pub struct DimTeditCommand {
|
||||
|
||||
impl DimTeditCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::PickDim }
|
||||
Self {
|
||||
step: Step::PickDim,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl CadCommand for DimTeditCommand {
|
||||
fn name(&self) -> &'static str { "DIMTEDIT" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMTEDIT"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
@@ -53,8 +59,13 @@ impl CadCommand for DimTeditCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
self.step = Step::PickTextPos { handle, entity: None };
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
self.step = Step::PickTextPos {
|
||||
handle,
|
||||
entity: None,
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
@@ -63,7 +74,8 @@ impl CadCommand for DimTeditCommand {
|
||||
let h = *handle;
|
||||
if let Some(mut ent) = entity.take() {
|
||||
if let EntityType::Dimension(ref mut d) = ent {
|
||||
let new_pt = acadrust::types::Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64);
|
||||
let new_pt =
|
||||
acadrust::types::Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64);
|
||||
d.base_mut().text_middle_point = new_pt;
|
||||
d.base_mut().insertion_point = new_pt;
|
||||
}
|
||||
@@ -76,7 +88,9 @@ impl CadCommand for DimTeditCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
if !matches!(self.step, Step::PickTextPos { .. }) {
|
||||
|
||||
@@ -39,25 +39,36 @@ pub struct LeaderCommand {
|
||||
|
||||
impl LeaderCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::CollectPoints { verts: Vec::new() } }
|
||||
Self {
|
||||
step: Step::CollectPoints { verts: Vec::new() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for LeaderCommand {
|
||||
fn name(&self) -> &'static str { "LEADER" }
|
||||
fn name(&self) -> &'static str {
|
||||
"LEADER"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::CollectPoints { verts } if verts.is_empty() =>
|
||||
"LEADER Specify arrowhead point:".into(),
|
||||
Step::CollectPoints { verts } =>
|
||||
format!("LEADER Specify next point [{} pts — Enter to finish]:", verts.len()),
|
||||
Step::AskCreationType { .. } =>
|
||||
"LEADER Annotation type [None/Text/Block/Tolerance] <Text>:".into(),
|
||||
Step::AskText { verts } =>
|
||||
format!("LEADER Annotation text [{} pts — blank = skip]:", verts.len()),
|
||||
Step::AskBlock { verts } =>
|
||||
format!("LEADER Block name [{} pts — blank = skip]:", verts.len()),
|
||||
Step::CollectPoints { verts } if verts.is_empty() => {
|
||||
"LEADER Specify arrowhead point:".into()
|
||||
}
|
||||
Step::CollectPoints { verts } => format!(
|
||||
"LEADER Specify next point [{} pts — Enter to finish]:",
|
||||
verts.len()
|
||||
),
|
||||
Step::AskCreationType { .. } => {
|
||||
"LEADER Annotation type [None/Text/Block/Tolerance] <Text>:".into()
|
||||
}
|
||||
Step::AskText { verts } => format!(
|
||||
"LEADER Annotation text [{} pts — blank = skip]:",
|
||||
verts.len()
|
||||
),
|
||||
Step::AskBlock { verts } => {
|
||||
format!("LEADER Block name [{} pts — blank = skip]:", verts.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +85,9 @@ impl CadCommand for LeaderCommand {
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
if let Step::CollectPoints { verts } = &self.step {
|
||||
if verts.len() < 2 { return CmdResult::Cancel; }
|
||||
if verts.len() < 2 {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
let verts = verts.clone();
|
||||
self.step = Step::AskCreationType { verts };
|
||||
CmdResult::NeedPoint
|
||||
@@ -91,7 +104,9 @@ impl CadCommand for LeaderCommand {
|
||||
match parse_ct(text) {
|
||||
LeaderCreationType::NoAnnotation | LeaderCreationType::WithTolerance => {
|
||||
let ct = parse_ct(text);
|
||||
Some(CmdResult::CommitAndExit(EntityType::Leader(build_leader(&verts, ct))))
|
||||
Some(CmdResult::CommitAndExit(EntityType::Leader(build_leader(
|
||||
&verts, ct,
|
||||
))))
|
||||
}
|
||||
LeaderCreationType::WithBlock => {
|
||||
self.step = Step::AskBlock { verts };
|
||||
@@ -109,7 +124,11 @@ impl CadCommand for LeaderCommand {
|
||||
if text.is_empty() {
|
||||
return Some(CmdResult::CommitAndExit(EntityType::Leader(leader)));
|
||||
}
|
||||
let mtext = build_mtext(text, landing_pt(&verts, leader.text_height), leader.text_height);
|
||||
let mtext = build_mtext(
|
||||
text,
|
||||
landing_pt(&verts, leader.text_height),
|
||||
leader.text_height,
|
||||
);
|
||||
Some(CmdResult::ReplaceMany(
|
||||
vec![],
|
||||
vec![EntityType::Leader(leader), EntityType::MText(mtext)],
|
||||
@@ -131,11 +150,15 @@ impl CadCommand for LeaderCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_escape(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_escape(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
if let Step::CollectPoints { verts } = &self.step {
|
||||
if verts.is_empty() { return None; }
|
||||
if verts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut pts = verts.clone();
|
||||
pts.push(pt);
|
||||
Some(preview_wire(&pts))
|
||||
@@ -149,14 +172,16 @@ impl CadCommand for LeaderCommand {
|
||||
|
||||
fn parse_ct(s: &str) -> LeaderCreationType {
|
||||
match s.to_ascii_uppercase().as_str() {
|
||||
"N" | "NONE" => LeaderCreationType::NoAnnotation,
|
||||
"B" | "BLOCK" => LeaderCreationType::WithBlock,
|
||||
"TL"| "TOLERANCE" => LeaderCreationType::WithTolerance,
|
||||
_ => LeaderCreationType::WithText,
|
||||
"N" | "NONE" => LeaderCreationType::NoAnnotation,
|
||||
"B" | "BLOCK" => LeaderCreationType::WithBlock,
|
||||
"TL" | "TOLERANCE" => LeaderCreationType::WithTolerance,
|
||||
_ => LeaderCreationType::WithText,
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 { Vector3::new(p.x as f64, p.y as f64, p.z as f64) }
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
}
|
||||
|
||||
fn build_leader(verts: &[Vec3], ct: LeaderCreationType) -> Leader {
|
||||
let mut l = Leader::from_vertices(verts.iter().map(|p| v3(*p)).collect());
|
||||
@@ -200,11 +225,11 @@ fn preview_wire(pts: &[Vec3]) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +240,15 @@ pub fn arrowhead_wings(tip: Vec3, next: Vec3, size: f32) -> [Vec3; 2] {
|
||||
let angle = std::f32::consts::PI / 6.0;
|
||||
let (s, c) = angle.sin_cos();
|
||||
[
|
||||
Vec3::new(tip.x + (dx*c - dy*s)*size, tip.y + (dx*s + dy*c)*size, tip.z),
|
||||
Vec3::new(tip.x + (dx*c + dy*s)*size, tip.y + (-dx*s + dy*c)*size, tip.z),
|
||||
Vec3::new(
|
||||
tip.x + (dx * c - dy * s) * size,
|
||||
tip.y + (dx * s + dy * c) * size,
|
||||
tip.z,
|
||||
),
|
||||
Vec3::new(
|
||||
tip.x + (dx * c + dy * s) * size,
|
||||
tip.y + (-dx * s + dy * c) * size,
|
||||
tip.z,
|
||||
),
|
||||
]
|
||||
}
|
||||
@@ -111,11 +111,11 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,21 +36,30 @@ pub struct MLeaderCommand {
|
||||
|
||||
impl MLeaderCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::CollectPoints { verts: Vec::new() } }
|
||||
Self {
|
||||
step: Step::CollectPoints { verts: Vec::new() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for MLeaderCommand {
|
||||
fn name(&self) -> &'static str { "MLEADER" }
|
||||
fn name(&self) -> &'static str {
|
||||
"MLEADER"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::CollectPoints { verts } if verts.is_empty() =>
|
||||
"MLEADER Specify arrowhead point:".into(),
|
||||
Step::CollectPoints { verts } =>
|
||||
format!("MLEADER Specify next point [{} pts — Enter to finish]:", verts.len()),
|
||||
Step::AskText { verts } =>
|
||||
format!("MLEADER Enter annotation text [{} pts — blank = no text]:", verts.len()),
|
||||
Step::CollectPoints { verts } if verts.is_empty() => {
|
||||
"MLEADER Specify arrowhead point:".into()
|
||||
}
|
||||
Step::CollectPoints { verts } => format!(
|
||||
"MLEADER Specify next point [{} pts — Enter to finish]:",
|
||||
verts.len()
|
||||
),
|
||||
Step::AskText { verts } => format!(
|
||||
"MLEADER Enter annotation text [{} pts — blank = no text]:",
|
||||
verts.len()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +76,9 @@ impl CadCommand for MLeaderCommand {
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
if let Step::CollectPoints { verts } = &self.step {
|
||||
if verts.len() < 2 { return CmdResult::Cancel; }
|
||||
if verts.len() < 2 {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
let verts = verts.clone();
|
||||
self.step = Step::AskText { verts };
|
||||
CmdResult::NeedPoint
|
||||
@@ -86,11 +97,15 @@ impl CadCommand for MLeaderCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_escape(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_escape(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
if let Step::CollectPoints { verts } = &self.step {
|
||||
if verts.is_empty() { return None; }
|
||||
if verts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut pts = verts.clone();
|
||||
pts.push(pt);
|
||||
Some(preview_wire(&pts))
|
||||
@@ -102,7 +117,9 @@ impl CadCommand for MLeaderCommand {
|
||||
|
||||
// ── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 { Vector3::new(p.x as f64, p.y as f64, p.z as f64) }
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
Vector3::new(p.x as f64, p.y as f64, p.z as f64)
|
||||
}
|
||||
|
||||
fn build_mleader(text: &str, verts: &[Vec3]) -> MultiLeader {
|
||||
// Last vertex = content/text location; remaining = leader line points
|
||||
@@ -115,13 +132,15 @@ fn build_mleader(text: &str, verts: &[Vec3]) -> MultiLeader {
|
||||
let mut ml = MultiLeader::with_text(text, content_v3, leader_v3);
|
||||
|
||||
// Match Leader entity defaults
|
||||
ml.text_height = 2.5;
|
||||
ml.context.text_height = 2.5;
|
||||
ml.arrowhead_size = 2.5;
|
||||
ml.dogleg_length = 2.5;
|
||||
ml.text_height = 2.5;
|
||||
ml.context.text_height = 2.5;
|
||||
ml.arrowhead_size = 2.5;
|
||||
ml.dogleg_length = 2.5;
|
||||
|
||||
// Direction: from last leader pt toward content
|
||||
if let (Some(last_leader), Some(root)) = (leader_pts.last(), ml.context.leader_roots.first_mut()) {
|
||||
if let (Some(last_leader), Some(root)) =
|
||||
(leader_pts.last(), ml.context.leader_roots.first_mut())
|
||||
{
|
||||
let dx = (content_pt.x - last_leader.x) as f64;
|
||||
let dy = (content_pt.y - last_leader.y) as f64;
|
||||
let len = (dx * dx + dy * dy).sqrt().max(1e-9);
|
||||
@@ -153,11 +172,11 @@ fn preview_wire(pts: &[Vec3]) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +187,15 @@ fn arrowhead_wings(tip: Vec3, next: Vec3, size: f32) -> [Vec3; 2] {
|
||||
let angle = std::f32::consts::PI / 6.0;
|
||||
let (s, c) = angle.sin_cos();
|
||||
[
|
||||
Vec3::new(tip.x + (dx*c - dy*s)*size, tip.y + (dx*s + dy*c)*size, tip.z),
|
||||
Vec3::new(tip.x + (dx*c + dy*s)*size, tip.y + (-dx*s + dy*c)*size, tip.z),
|
||||
Vec3::new(
|
||||
tip.x + (dx * c - dy * s) * size,
|
||||
tip.y + (dx * s + dy * c) * size,
|
||||
tip.z,
|
||||
),
|
||||
Vec3::new(
|
||||
tip.x + (dx * c + dy * s) * size,
|
||||
tip.y + (-dx * s + dy * c) * size,
|
||||
tip.z,
|
||||
),
|
||||
]
|
||||
}
|
||||
@@ -16,7 +16,8 @@ use crate::scene::wire_model::WireModel;
|
||||
|
||||
// ── MLEADERADD ────────────────────────────────────────────────────────────────
|
||||
|
||||
pub const ICON_ADD: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/mleader_add.svg"));
|
||||
pub const ICON_ADD: IconKind =
|
||||
IconKind::Svg(include_bytes!("../../../assets/icons/mleader_add.svg"));
|
||||
|
||||
pub fn tool_add() -> ToolDef {
|
||||
ToolDef {
|
||||
@@ -29,8 +30,15 @@ pub fn tool_add() -> ToolDef {
|
||||
|
||||
enum AddStep {
|
||||
PickMLeader,
|
||||
PickArrowhead { handle: Handle, entity: Option<EntityType> },
|
||||
CollectPoints { handle: Handle, entity: EntityType, pts: Vec<Vec3> },
|
||||
PickArrowhead {
|
||||
handle: Handle,
|
||||
entity: Option<EntityType>,
|
||||
},
|
||||
CollectPoints {
|
||||
handle: Handle,
|
||||
entity: EntityType,
|
||||
pts: Vec<Vec3>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct MLeaderAddCommand {
|
||||
@@ -38,20 +46,26 @@ pub struct MLeaderAddCommand {
|
||||
}
|
||||
|
||||
impl MLeaderAddCommand {
|
||||
pub fn new() -> Self { Self { step: AddStep::PickMLeader } }
|
||||
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
step: AddStep::PickMLeader,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for MLeaderAddCommand {
|
||||
fn name(&self) -> &'static str { "MLEADERADD" }
|
||||
fn name(&self) -> &'static str {
|
||||
"MLEADERADD"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
AddStep::PickMLeader => "MLEADERADD Select a multileader:".into(),
|
||||
AddStep::PickArrowhead { .. } => "MLEADERADD Specify arrowhead location:".into(),
|
||||
AddStep::CollectPoints { pts, .. } =>
|
||||
format!("MLEADERADD Specify next leader point ({} pts, Enter to finish):", pts.len()),
|
||||
AddStep::CollectPoints { pts, .. } => format!(
|
||||
"MLEADERADD Specify next leader point ({} pts, Enter to finish):",
|
||||
pts.len()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +74,13 @@ impl CadCommand for MLeaderAddCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
self.step = AddStep::PickArrowhead { handle, entity: None };
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
self.step = AddStep::PickArrowhead {
|
||||
handle,
|
||||
entity: None,
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
@@ -70,7 +89,11 @@ impl CadCommand for MLeaderAddCommand {
|
||||
AddStep::PickArrowhead { handle, entity } => {
|
||||
if let Some(ent) = entity.take() {
|
||||
let h = *handle;
|
||||
self.step = AddStep::CollectPoints { handle: h, entity: ent, pts: vec![pt] };
|
||||
self.step = AddStep::CollectPoints {
|
||||
handle: h,
|
||||
entity: ent,
|
||||
pts: vec![pt],
|
||||
};
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
CmdResult::NeedPoint
|
||||
@@ -84,12 +107,20 @@ impl CadCommand for MLeaderAddCommand {
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
if let AddStep::CollectPoints { handle, entity, pts } = &mut self.step {
|
||||
if pts.len() < 1 { return CmdResult::Cancel; }
|
||||
if let AddStep::CollectPoints {
|
||||
handle,
|
||||
entity,
|
||||
pts,
|
||||
} = &mut self.step
|
||||
{
|
||||
if pts.len() < 1 {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
let h = *handle;
|
||||
if let EntityType::MultiLeader(ref mut ml) = entity {
|
||||
// Add a new leader root with the collected points
|
||||
let points: Vec<Vector3> = pts.iter()
|
||||
let points: Vec<Vector3> = pts
|
||||
.iter()
|
||||
.map(|p| Vector3::new(p.x as f64, p.y as f64, p.z as f64))
|
||||
.collect();
|
||||
let root = ml.context.add_leader_root();
|
||||
@@ -120,7 +151,8 @@ impl CadCommand for MLeaderAddCommand {
|
||||
|
||||
// ── MLEADERREMOVE ─────────────────────────────────────────────────────────────
|
||||
|
||||
pub const ICON_REMOVE: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/mleader_remove.svg"));
|
||||
pub const ICON_REMOVE: IconKind =
|
||||
IconKind::Svg(include_bytes!("../../../assets/icons/mleader_remove.svg"));
|
||||
|
||||
pub fn tool_remove() -> ToolDef {
|
||||
ToolDef {
|
||||
@@ -133,7 +165,10 @@ pub fn tool_remove() -> ToolDef {
|
||||
|
||||
enum RemoveStep {
|
||||
PickMLeader,
|
||||
PickLeaderToRemove { handle: Handle, entity: Option<EntityType> },
|
||||
PickLeaderToRemove {
|
||||
handle: Handle,
|
||||
entity: Option<EntityType>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct MLeaderRemoveCommand {
|
||||
@@ -141,18 +176,24 @@ pub struct MLeaderRemoveCommand {
|
||||
}
|
||||
|
||||
impl MLeaderRemoveCommand {
|
||||
pub fn new() -> Self { Self { step: RemoveStep::PickMLeader } }
|
||||
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
step: RemoveStep::PickMLeader,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for MLeaderRemoveCommand {
|
||||
fn name(&self) -> &'static str { "MLEADERREMOVE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"MLEADERREMOVE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
RemoveStep::PickMLeader => "MLEADERREMOVE Select a multileader:".into(),
|
||||
RemoveStep::PickLeaderToRemove { .. } => "MLEADERREMOVE Click near the leader line to remove:".into(),
|
||||
RemoveStep::PickLeaderToRemove { .. } => {
|
||||
"MLEADERREMOVE Click near the leader line to remove:".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,8 +202,13 @@ impl CadCommand for MLeaderRemoveCommand {
|
||||
}
|
||||
|
||||
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
|
||||
if handle.is_null() { return CmdResult::NeedPoint; }
|
||||
self.step = RemoveStep::PickLeaderToRemove { handle, entity: None };
|
||||
if handle.is_null() {
|
||||
return CmdResult::NeedPoint;
|
||||
}
|
||||
self.step = RemoveStep::PickLeaderToRemove {
|
||||
handle,
|
||||
entity: None,
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
@@ -173,15 +219,17 @@ impl CadCommand for MLeaderRemoveCommand {
|
||||
if let EntityType::MultiLeader(ref mut ml) = ent {
|
||||
// Remove the leader root whose first point is closest to `pt`
|
||||
let pick = Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64);
|
||||
let best = ml.context.leader_roots.iter().enumerate()
|
||||
let best = ml
|
||||
.context
|
||||
.leader_roots
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, root)| {
|
||||
root.lines.first()
|
||||
.and_then(|l| l.points.first())
|
||||
.map(|p| {
|
||||
let dx = p.x - pick.x;
|
||||
let dz = p.z - pick.z;
|
||||
(i, dx * dx + dz * dz)
|
||||
})
|
||||
root.lines.first().and_then(|l| l.points.first()).map(|p| {
|
||||
let dx = p.x - pick.x;
|
||||
let dz = p.z - pick.z;
|
||||
(i, dx * dx + dz * dz)
|
||||
})
|
||||
})
|
||||
.min_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
|
||||
if let Some((idx, _)) = best {
|
||||
@@ -196,8 +244,12 @@ impl CadCommand for MLeaderRemoveCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> { None }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> {
|
||||
None
|
||||
}
|
||||
|
||||
fn inject_picked_entity(&mut self, entity: EntityType) {
|
||||
if let RemoveStep::PickLeaderToRemove { entity: slot, .. } = &mut self.step {
|
||||
@@ -208,7 +260,8 @@ impl CadCommand for MLeaderRemoveCommand {
|
||||
|
||||
// ── MLEADERALIGN ─────────────────────────────────────────────────────────────
|
||||
|
||||
pub const ICON_ALIGN: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/mleader_align.svg"));
|
||||
pub const ICON_ALIGN: IconKind =
|
||||
IconKind::Svg(include_bytes!("../../../assets/icons/mleader_align.svg"));
|
||||
|
||||
pub fn tool_align() -> ToolDef {
|
||||
ToolDef {
|
||||
@@ -230,17 +283,29 @@ pub struct MLeaderAlignCommand {
|
||||
}
|
||||
|
||||
impl MLeaderAlignCommand {
|
||||
pub fn new() -> Self { Self { step: AlignStep::Gathering } }
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
step: AlignStep::Gathering,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for MLeaderAlignCommand {
|
||||
fn name(&self) -> &'static str { "MLEADERALIGN" }
|
||||
fn name(&self) -> &'static str {
|
||||
"MLEADERALIGN"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
AlignStep::Gathering => "MLEADERALIGN Select multileaders to align (Enter when done):".into(),
|
||||
AlignStep::PickDirection { .. } => "MLEADERALIGN Specify direction — pick start point:".into(),
|
||||
AlignStep::PickEndDir { .. } => "MLEADERALIGN Specify end point of alignment direction:".into(),
|
||||
AlignStep::Gathering => {
|
||||
"MLEADERALIGN Select multileaders to align (Enter when done):".into()
|
||||
}
|
||||
AlignStep::PickDirection { .. } => {
|
||||
"MLEADERALIGN Specify direction — pick start point:".into()
|
||||
}
|
||||
AlignStep::PickEndDir { .. } => {
|
||||
"MLEADERALIGN Specify end point of alignment direction:".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +314,9 @@ impl CadCommand for MLeaderAlignCommand {
|
||||
}
|
||||
|
||||
fn on_selection_complete(&mut self, handles: Vec<Handle>) -> CmdResult {
|
||||
if handles.is_empty() { return CmdResult::Cancel; }
|
||||
if handles.is_empty() {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
self.step = AlignStep::PickDirection { handles };
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
@@ -258,7 +325,10 @@ impl CadCommand for MLeaderAlignCommand {
|
||||
match &mut self.step {
|
||||
AlignStep::PickDirection { handles } => {
|
||||
let h = handles.clone();
|
||||
self.step = AlignStep::PickEndDir { handles: h, from: pt };
|
||||
self.step = AlignStep::PickEndDir {
|
||||
handles: h,
|
||||
from: pt,
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
AlignStep::PickEndDir { handles, from } => {
|
||||
@@ -268,8 +338,14 @@ impl CadCommand for MLeaderAlignCommand {
|
||||
use acadrust::entities::XLine;
|
||||
let mut xl = XLine::default();
|
||||
let hstr: Vec<String> = h.iter().map(|hh| hh.value().to_string()).collect();
|
||||
xl.common.layer = format!("__MLEADERALIGN__{};{:.4},{:.4};{:.4},{:.4}",
|
||||
hstr.join(","), f.x, f.z, pt.x, pt.z);
|
||||
xl.common.layer = format!(
|
||||
"__MLEADERALIGN__{};{:.4},{:.4};{:.4},{:.4}",
|
||||
hstr.join(","),
|
||||
f.x,
|
||||
f.z,
|
||||
pt.x,
|
||||
pt.z
|
||||
);
|
||||
// Use first handle as the "replaced" entity (sentinel)
|
||||
if let Some(&first) = h.first() {
|
||||
return CmdResult::ReplaceEntity(first, vec![EntityType::XLine(xl)]);
|
||||
@@ -280,13 +356,18 @@ impl CadCommand for MLeaderAlignCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> { None }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// ── MLEADERCOLLECT ────────────────────────────────────────────────────────────
|
||||
|
||||
pub const ICON_COLLECT: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/mleader_collect.svg"));
|
||||
pub const ICON_COLLECT: IconKind =
|
||||
IconKind::Svg(include_bytes!("../../../assets/icons/mleader_collect.svg"));
|
||||
|
||||
pub fn tool_collect() -> ToolDef {
|
||||
ToolDef {
|
||||
@@ -307,16 +388,26 @@ pub struct MLeaderCollectCommand {
|
||||
}
|
||||
|
||||
impl MLeaderCollectCommand {
|
||||
pub fn new() -> Self { Self { step: CollectStep::Gathering } }
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
step: CollectStep::Gathering,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for MLeaderCollectCommand {
|
||||
fn name(&self) -> &'static str { "MLEADERCOLLECT" }
|
||||
fn name(&self) -> &'static str {
|
||||
"MLEADERCOLLECT"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
CollectStep::Gathering => "MLEADERCOLLECT Select multileaders to collect (Enter when done):".into(),
|
||||
CollectStep::PickLocation { .. } => "MLEADERCOLLECT Specify collected multileader location:".into(),
|
||||
CollectStep::Gathering => {
|
||||
"MLEADERCOLLECT Select multileaders to collect (Enter when done):".into()
|
||||
}
|
||||
CollectStep::PickLocation { .. } => {
|
||||
"MLEADERCOLLECT Specify collected multileader location:".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +416,9 @@ impl CadCommand for MLeaderCollectCommand {
|
||||
}
|
||||
|
||||
fn on_selection_complete(&mut self, handles: Vec<Handle>) -> CmdResult {
|
||||
if handles.is_empty() { return CmdResult::Cancel; }
|
||||
if handles.is_empty() {
|
||||
return CmdResult::Cancel;
|
||||
}
|
||||
self.step = CollectStep::PickLocation { handles };
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
@@ -338,7 +431,12 @@ impl CadCommand for MLeaderCollectCommand {
|
||||
use acadrust::entities::XLine;
|
||||
let mut xl = XLine::default();
|
||||
let hstr: Vec<String> = h.iter().map(|hh| hh.value().to_string()).collect();
|
||||
xl.common.layer = format!("__MLEADERCOLLECT__{};{:.4},{:.4}", hstr.join(","), pt.x, pt.z);
|
||||
xl.common.layer = format!(
|
||||
"__MLEADERCOLLECT__{};{:.4},{:.4}",
|
||||
hstr.join(","),
|
||||
pt.x,
|
||||
pt.z
|
||||
);
|
||||
if let Some(&first) = h.first() {
|
||||
return CmdResult::ReplaceEntity(first, vec![EntityType::XLine(xl)]);
|
||||
}
|
||||
@@ -346,8 +444,12 @@ impl CadCommand for MLeaderCollectCommand {
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> { None }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// ── Shared helpers ────────────────────────────────────────────────────────────
|
||||
@@ -366,9 +468,9 @@ fn preview_wire(pts: &[Vec3]) -> WireModel {
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+55
-40
@@ -1,9 +1,9 @@
|
||||
// Annotate module — dimension, text, leader, table, and markup tools.
|
||||
|
||||
pub mod aligned_dim;
|
||||
pub mod angular_dim;
|
||||
pub mod data_extract;
|
||||
pub mod data_link;
|
||||
pub mod angular_dim;
|
||||
pub mod ddedit;
|
||||
pub mod diameter_dim;
|
||||
pub mod dim_baseline;
|
||||
@@ -38,7 +38,7 @@ impl CadModule for AnnotateModule {
|
||||
}
|
||||
|
||||
fn ribbon_groups(&self) -> Vec<RibbonGroup> {
|
||||
use crate::modules::home::draw::{wipeout, revcloud};
|
||||
use crate::modules::home::draw::{revcloud, wipeout};
|
||||
|
||||
vec![
|
||||
// ── Text ─────────────────────────────────────────────────────
|
||||
@@ -51,7 +51,7 @@ impl CadModule for AnnotateModule {
|
||||
icon: mtext::ICON,
|
||||
items: vec![
|
||||
(mtext::tool().id, mtext::tool().label, mtext::tool().icon),
|
||||
(text::tool().id, text::tool().label, text::tool().icon),
|
||||
(text::tool().id, text::tool().label, text::tool().icon),
|
||||
(ddedit::tool().id, ddedit::tool().label, ddedit::tool().icon),
|
||||
],
|
||||
default: "MTEXT",
|
||||
@@ -60,16 +60,14 @@ impl CadModule for AnnotateModule {
|
||||
style_key: StyleKey::TextStyle,
|
||||
combo_id: "TEXT_STYLE_COMBO",
|
||||
manager_cmd: Some("STYLE"),
|
||||
rows: vec![
|
||||
vec![
|
||||
crate::modules::ToolDef {
|
||||
id: "FIND",
|
||||
label: "Find",
|
||||
icon: crate::modules::IconKind::Svg(include_bytes!("../../../assets/icons/find.svg")),
|
||||
event: crate::modules::ModuleEvent::Command("FIND".to_string()),
|
||||
},
|
||||
],
|
||||
],
|
||||
rows: vec![vec![crate::modules::ToolDef {
|
||||
id: "FIND",
|
||||
label: "Find",
|
||||
icon: crate::modules::IconKind::Svg(include_bytes!(
|
||||
"../../../assets/icons/find.svg"
|
||||
)),
|
||||
event: crate::modules::ModuleEvent::Command("FIND".to_string()),
|
||||
}]],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -82,12 +80,36 @@ impl CadModule for AnnotateModule {
|
||||
label: "Dimension",
|
||||
icon: linear_dim::ICON,
|
||||
items: vec![
|
||||
(linear_dim::tool().id, linear_dim::tool().label, linear_dim::tool().icon),
|
||||
(aligned_dim::tool().id, aligned_dim::tool().label, aligned_dim::tool().icon),
|
||||
(angular_dim::tool().id, angular_dim::tool().label, angular_dim::tool().icon),
|
||||
(radius_dim::tool().id, radius_dim::tool().label, radius_dim::tool().icon),
|
||||
(diameter_dim::tool().id, diameter_dim::tool().label, diameter_dim::tool().icon),
|
||||
(ordinate_dim::tool().id, ordinate_dim::tool().label, ordinate_dim::tool().icon),
|
||||
(
|
||||
linear_dim::tool().id,
|
||||
linear_dim::tool().label,
|
||||
linear_dim::tool().icon,
|
||||
),
|
||||
(
|
||||
aligned_dim::tool().id,
|
||||
aligned_dim::tool().label,
|
||||
aligned_dim::tool().icon,
|
||||
),
|
||||
(
|
||||
angular_dim::tool().id,
|
||||
angular_dim::tool().label,
|
||||
angular_dim::tool().icon,
|
||||
),
|
||||
(
|
||||
radius_dim::tool().id,
|
||||
radius_dim::tool().label,
|
||||
radius_dim::tool().icon,
|
||||
),
|
||||
(
|
||||
diameter_dim::tool().id,
|
||||
diameter_dim::tool().label,
|
||||
diameter_dim::tool().icon,
|
||||
),
|
||||
(
|
||||
ordinate_dim::tool().id,
|
||||
ordinate_dim::tool().label,
|
||||
ordinate_dim::tool().icon,
|
||||
),
|
||||
(qdim::tool().id, qdim::tool().label, qdim::tool().icon),
|
||||
],
|
||||
default: "DIMLINEAR",
|
||||
@@ -97,11 +119,7 @@ impl CadModule for AnnotateModule {
|
||||
combo_id: "DIM_STYLE_COMBO",
|
||||
manager_cmd: Some("DIMSTYLE"),
|
||||
rows: vec![
|
||||
vec![
|
||||
qdim::tool(),
|
||||
dim_continue::tool(),
|
||||
dim_baseline::tool(),
|
||||
],
|
||||
vec![qdim::tool(), dim_continue::tool(), dim_baseline::tool()],
|
||||
vec![
|
||||
tolerance_cmd::tool(),
|
||||
dimedit::tool(),
|
||||
@@ -123,8 +141,16 @@ impl CadModule for AnnotateModule {
|
||||
label: "Multileader",
|
||||
icon: mleader_cmd::ICON,
|
||||
items: vec![
|
||||
(mleader_cmd::tool().id, mleader_cmd::tool().label, mleader_cmd::tool().icon),
|
||||
(leader_cmd::tool().id, leader_cmd::tool().label, leader_cmd::tool().icon),
|
||||
(
|
||||
mleader_cmd::tool().id,
|
||||
mleader_cmd::tool().label,
|
||||
mleader_cmd::tool().icon,
|
||||
),
|
||||
(
|
||||
leader_cmd::tool().id,
|
||||
leader_cmd::tool().label,
|
||||
leader_cmd::tool().icon,
|
||||
),
|
||||
],
|
||||
default: "MLEADER",
|
||||
},
|
||||
@@ -133,14 +159,8 @@ impl CadModule for AnnotateModule {
|
||||
combo_id: "MLEADER_STYLE_COMBO",
|
||||
manager_cmd: Some("MLEADERSTYLE"),
|
||||
rows: vec![
|
||||
vec![
|
||||
mleader_edit::tool_add(),
|
||||
mleader_edit::tool_remove(),
|
||||
],
|
||||
vec![
|
||||
mleader_edit::tool_align(),
|
||||
mleader_edit::tool_collect(),
|
||||
],
|
||||
vec![mleader_edit::tool_add(), mleader_edit::tool_remove()],
|
||||
vec![mleader_edit::tool_align(), mleader_edit::tool_collect()],
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -154,12 +174,7 @@ impl CadModule for AnnotateModule {
|
||||
style_key: StyleKey::TableStyle,
|
||||
combo_id: "TABLE_STYLE_COMBO",
|
||||
manager_cmd: Some("TABLESTYLE"),
|
||||
rows: vec![
|
||||
vec![
|
||||
data_extract::tool(),
|
||||
data_link::tool(),
|
||||
],
|
||||
],
|
||||
rows: vec![vec![data_extract::tool(), data_link::tool()]],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -37,12 +37,16 @@ pub struct OrdinateDimCommand {
|
||||
|
||||
impl OrdinateDimCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::FeaturePoint }
|
||||
Self {
|
||||
step: Step::FeaturePoint,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for OrdinateDimCommand {
|
||||
fn name(&self) -> &'static str { "DIMORDINATE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"DIMORDINATE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match self.step {
|
||||
@@ -71,8 +75,12 @@ impl CadCommand for OrdinateDimCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_preview_wires(&mut self, _pt: Vec3) -> Vec<WireModel> { vec![] }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
fn on_preview_wires(&mut self, _pt: Vec3) -> Vec<WireModel> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
fn v3(p: Vec3) -> Vector3 {
|
||||
|
||||
@@ -37,14 +37,16 @@ pub struct QdimCommand {
|
||||
|
||||
impl QdimCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::Gathering }
|
||||
Self {
|
||||
step: Step::Gathering,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl CadCommand for QdimCommand {
|
||||
fn name(&self) -> &'static str { "QDIM" }
|
||||
fn name(&self) -> &'static str {
|
||||
"QDIM"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
@@ -76,7 +78,9 @@ impl CadCommand for QdimCommand {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_enter(&mut self) -> CmdResult { CmdResult::Cancel }
|
||||
fn on_enter(&mut self) -> CmdResult {
|
||||
CmdResult::Cancel
|
||||
}
|
||||
|
||||
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
||||
if !matches!(self.step, Step::PlaceLine { .. }) {
|
||||
@@ -85,10 +89,7 @@ impl CadCommand for QdimCommand {
|
||||
let d = 0.5_f32;
|
||||
Some(WireModel {
|
||||
name: "qdim_preview".into(),
|
||||
points: vec![
|
||||
[pt.x - d * 3.0, pt.y, pt.z],
|
||||
[pt.x + d * 3.0, pt.y, pt.z],
|
||||
],
|
||||
points: vec![[pt.x - d * 3.0, pt.y, pt.z], [pt.x + d * 3.0, pt.y, pt.z]],
|
||||
color: WireModel::CYAN,
|
||||
selected: false,
|
||||
pattern_length: 0.0,
|
||||
@@ -114,7 +115,11 @@ pub fn make_linear_dim(p1: Vec3, p2: Vec3, dim_pt: Vec3) -> EntityType {
|
||||
// Determine axis: horizontal if Δx > Δz, else vertical
|
||||
let dx = (p2.x - p1.x).abs();
|
||||
let dz = (p2.z - p1.z).abs();
|
||||
dim.rotation = if dz > dx { std::f64::consts::FRAC_PI_2 } else { 0.0 };
|
||||
dim.rotation = if dz > dx {
|
||||
std::f64::consts::FRAC_PI_2
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
dim.definition_point = v(dim_pt);
|
||||
dim.base.definition_point = v(dim_pt);
|
||||
let text_pos = (p1 + p2) * 0.5;
|
||||
|
||||
@@ -110,10 +110,10 @@ fn preview_wire(points: Vec<Vec3>) -> WireModel {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
}
|
||||
}
|
||||
@@ -44,18 +44,26 @@ pub struct TableCommand {
|
||||
|
||||
impl TableCommand {
|
||||
pub fn new() -> Self {
|
||||
Self { step: Step::Columns }
|
||||
Self {
|
||||
step: Step::Columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CadCommand for TableCommand {
|
||||
fn name(&self) -> &'static str { "TABLE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"TABLE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::Columns => format!("TABLE Enter number of columns [{DEFAULT_COLS}]:"),
|
||||
Step::Rows { cols } => format!("TABLE Enter number of rows (incl. header) [{DEFAULT_ROWS}] ({cols} cols):"),
|
||||
Step::Insertion { cols, rows } => format!("TABLE Specify insertion point [{cols}×{rows}]:"),
|
||||
Step::Rows { cols } => format!(
|
||||
"TABLE Enter number of rows (incl. header) [{DEFAULT_ROWS}] ({cols} cols):"
|
||||
),
|
||||
Step::Insertion { cols, rows } => {
|
||||
format!("TABLE Specify insertion point [{cols}×{rows}]:")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +106,10 @@ impl CadCommand for TableCommand {
|
||||
}
|
||||
Step::Rows { cols } => {
|
||||
let cols = *cols;
|
||||
self.step = Step::Insertion { cols, rows: DEFAULT_ROWS };
|
||||
self.step = Step::Insertion {
|
||||
cols,
|
||||
rows: DEFAULT_ROWS,
|
||||
};
|
||||
CmdResult::NeedPoint
|
||||
}
|
||||
Step::Insertion { .. } => CmdResult::Cancel,
|
||||
@@ -130,10 +141,14 @@ impl CadCommand for TableCommand {
|
||||
Some(WireModel {
|
||||
name: "table_preview".into(),
|
||||
points: vec![
|
||||
[x, y, z], [x + w, y, z],
|
||||
[x + w, y, z], [x + w, y, z - h],
|
||||
[x + w, y, z - h], [x, y, z - h],
|
||||
[x, y, z - h], [x, y, z],
|
||||
[x, y, z],
|
||||
[x + w, y, z],
|
||||
[x + w, y, z],
|
||||
[x + w, y, z - h],
|
||||
[x + w, y, z - h],
|
||||
[x, y, z - h],
|
||||
[x, y, z - h],
|
||||
[x, y, z],
|
||||
],
|
||||
color: WireModel::CYAN,
|
||||
selected: false,
|
||||
@@ -143,11 +158,11 @@ impl CadCommand for TableCommand {
|
||||
snap_pts: vec![],
|
||||
tangent_geoms: vec![],
|
||||
aci: 0,
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
key_vertices: vec![],
|
||||
aabb: WireModel::UNBOUNDED_AABB,
|
||||
plinegen: true,
|
||||
vp_scissor: None,
|
||||
fill_tris: vec![],
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -40,7 +40,9 @@ impl ToleranceCommand {
|
||||
}
|
||||
|
||||
impl CadCommand for ToleranceCommand {
|
||||
fn name(&self) -> &'static str { "TOLERANCE" }
|
||||
fn name(&self) -> &'static str {
|
||||
"TOLERANCE"
|
||||
}
|
||||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
@@ -84,9 +86,11 @@ impl CadCommand for ToleranceCommand {
|
||||
Some(WireModel {
|
||||
name: "tolerance_preview".into(),
|
||||
points: vec![
|
||||
[pt.x - d, pt.y, pt.z], [pt.x + d, pt.y, pt.z],
|
||||
[pt.x - d, pt.y, pt.z],
|
||||
[pt.x + d, pt.y, pt.z],
|
||||
[f32::NAN, 0.0, 0.0],
|
||||
[pt.x, pt.y, pt.z - d], [pt.x, pt.y, pt.z + d],
|
||||
[pt.x, pt.y, pt.z - d],
|
||||
[pt.x, pt.y, pt.z + d],
|
||||
],
|
||||
color: WireModel::CYAN,
|
||||
selected: false,
|
||||
|
||||
Reference in new issue
Block a user