forked from 1b-agent/opencadstudio-upstream
Whole command/snap/grip/cursor chain now builds on f64 DVec3 end to end,
so picked points, snaps and grip drags stay precise at UTM-scale
coordinates instead of quantizing to ~0.5 m through f32.
- All ~80 command files migrated: draw (line/circle/arc/ellipse/shapes
in full f64; others via point methods), modify, annotate, insert, view,
inquiry, layers, groups, clipboard, layout.
- Entity apply_grip impls updated for GripApply::{Absolute,Translate}(DVec3).
- Construction sites (EntityTransform/CmdResult/DynAnchor) emit DVec3;
wire-preview boundaries cast to f32 only at the GPU edge.
- Modify/annotate commands keep internal Vec3 geometry where precision is
non-critical, casting at the DVec3 boundary; key draw commands store f64.
Builds clean (no warnings). Visual verification of crosshair/snap/grip at
extreme UTM zoom pending.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
104 lines
3.2 KiB
Rust
104 lines
3.2 KiB
Rust
// DIMBREAK command — insert a break in a dimension/extension line where
|
|
// another object crosses it.
|
|
//
|
|
// Simplified workflow:
|
|
// 1. Select the dimension to break
|
|
// 2. Select the object that crosses it (or Enter for AUTO mode on all crossings)
|
|
//
|
|
// Because breaking a dimension line requires deep geometric intersection logic
|
|
// that depends on the renderer, this implementation records the target handles
|
|
// and emits a ReplaceEntity sentinel that commands.rs intercepts to apply the break.
|
|
|
|
use acadrust::Handle;
|
|
use glam::DVec3;
|
|
|
|
use crate::command::{CadCommand, CmdResult};
|
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
|
|
|
pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_break.svg"));
|
|
|
|
pub fn tool() -> ToolDef {
|
|
ToolDef {
|
|
id: "DIMBREAK",
|
|
label: "Dim Break",
|
|
icon: ICON,
|
|
event: ModuleEvent::Command("DIMBREAK".to_string()),
|
|
}
|
|
}
|
|
|
|
enum Step {
|
|
PickDim,
|
|
PickCrossing { dim_handle: Handle },
|
|
}
|
|
|
|
pub struct DimBreakCommand {
|
|
step: Step,
|
|
}
|
|
|
|
impl DimBreakCommand {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
step: Step::PickDim,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CadCommand for DimBreakCommand {
|
|
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()
|
|
}
|
|
}
|
|
}
|
|
|
|
fn needs_entity_pick(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
|
|
if handle.is_null() {
|
|
return CmdResult::NeedPoint;
|
|
}
|
|
match &self.step {
|
|
Step::PickDim => {
|
|
self.step = Step::PickCrossing { dim_handle: handle };
|
|
CmdResult::NeedPoint
|
|
}
|
|
Step::PickCrossing { dim_handle } => {
|
|
let dim_h = *dim_handle;
|
|
// Emit sentinel: the actual break logic is in commands.rs
|
|
use acadrust::entities::XLine;
|
|
let mut xl = XLine::default();
|
|
xl.common.layer = format!("__DIMBREAK__{},{}", dim_h.value(), handle.value());
|
|
CmdResult::ReplaceEntity(dim_h, vec![acadrust::EntityType::XLine(xl)])
|
|
}
|
|
}
|
|
}
|
|
|
|
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
|
|
CmdResult::NeedPoint
|
|
}
|
|
|
|
fn on_enter(&mut self) -> CmdResult {
|
|
// Auto mode: apply to all crossings
|
|
if let Step::PickCrossing { dim_handle } = &self.step {
|
|
let dim_h = *dim_handle;
|
|
use acadrust::entities::XLine;
|
|
let mut xl = XLine::default();
|
|
xl.common.layer = format!("__DIMBREAK_AUTO__{}", dim_h.value());
|
|
return CmdResult::ReplaceEntity(dim_h, vec![acadrust::EntityType::XLine(xl)]);
|
|
}
|
|
CmdResult::Cancel
|
|
}
|
|
}
|
|
|
|
|
|
// ── Autocomplete registry ─────────────────────────────────
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["DBR", "DIMBREAK"] }); // DimBreakCommand
|