feat(f64): command layer compiles on DVec3

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 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-24 03:51:50 +03:00
1 parent 3da71698b1
commit 4f7a98a2ad
84 files changed
+358 -336

No files matched your search

+4 -4
View File
@@ -16,7 +16,7 @@ pub const MENU_ITEMS: &[(&str, &str, IconKind)] = &[
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -43,7 +43,7 @@ impl CadCommand for PasteCommand {
"PASTECLIP Pick insertion point:".into()
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
CmdResult::PasteClipboard { base_pt: pt }
}
@@ -51,11 +51,11 @@ impl CadCommand for PasteCommand {
CmdResult::Cancel
}
fn on_hover_entity(&mut self, _handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, _handle: Handle, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> { let pt = pt.as_vec3();
let delta = pt - self.centroid;
self.wires.iter().map(|w| w.translated(delta)).collect()
}
+3 -3
View File
@@ -9,7 +9,7 @@
use acadrust::entities::AttributeDefinition;
use acadrust::types::Vector3;
use acadrust::EntityType;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -106,7 +106,7 @@ impl CadCommand for AttdefCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if let Step::Insertion {
tag,
prompt,
@@ -153,7 +153,7 @@ impl CadCommand for AttdefCommand {
}
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if !matches!(self.step, Step::Insertion { .. }) {
return None;
}
+2 -2
View File
@@ -12,7 +12,7 @@
use acadrust::entities::{LwPolyline, LwVertex};
use acadrust::EntityType;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -91,7 +91,7 @@ impl CadCommand for DonutCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
match &self.state {
DonutState::PlaceCenter => {
let entity = make_donut(pt.x as f64, pt.y as f64, self.inner_r, self.outer_r);
+6 -6
View File
@@ -13,7 +13,7 @@ use crate::command::{CadCommand, CmdResult};
use crate::modules::IconKind;
use crate::scene::model::hatch_model::{HatchModel, HatchPattern, PatFamily};
use crate::scene::model::wire_model::WireModel;
use glam::Vec3;
use glam::{DVec3, Vec3};
// ── Icons ──────────────────────────────────────────────────────────────────
@@ -154,7 +154,7 @@ impl CadCommand for HatchCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match &self.mode {
Mode::PickInside => {
let xy = [pt.x, pt.y];
@@ -204,7 +204,7 @@ impl CadCommand for HatchCommand {
None
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if let Mode::Manual = &self.mode {
if self.manual_pts.is_empty() {
return None;
@@ -292,7 +292,7 @@ impl CadCommand for GradientCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match &self.mode {
Mode::PickInside => {
let xy = [pt.x, pt.y];
@@ -342,7 +342,7 @@ impl CadCommand for GradientCommand {
None
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if let Mode::Manual = &self.mode {
if self.manual_pts.is_empty() {
return None;
@@ -395,7 +395,7 @@ impl CadCommand for BoundaryCommand {
format!("BOUNDARY Pick internal point:{miss}")
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
let xy = [pt.x, pt.y];
for outline in &self.outlines {
if point_in_polygon(xy, outline) {
+3 -3
View File
@@ -9,7 +9,7 @@
// Press Enter to apply changes.
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -67,7 +67,7 @@ impl CadCommand for HatcheditCommand {
matches!(self.step, HatcheditStep::PickHatch)
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -136,7 +136,7 @@ impl CadCommand for HatcheditCommand {
Some(CmdResult::NeedPoint)
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
+10 -7
View File
@@ -12,7 +12,7 @@ use acadrust::{EntityType, Line};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::model::wire_model::WireModel;
use glam::Vec3;
use glam::DVec3;
// ── Ribbon definition ─────────────────────────────────────────────────────
@@ -29,7 +29,7 @@ pub fn tool() -> ToolDef {
pub struct LineCommand {
/// The last committed point (start of the next segment).
last: Option<Vec3>,
last: Option<DVec3>,
}
impl LineCommand {
@@ -51,11 +51,11 @@ impl CadCommand for LineCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
if let Some(last) = self.last {
let line = Line::from_points(
Vector3::new(last.x as f64, last.y as f64, last.z as f64),
Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64),
Vector3::new(last.x, last.y, last.z),
Vector3::new(pt.x, pt.y, pt.z),
);
self.last = Some(pt);
CmdResult::CommitEntity(EntityType::Line(line))
@@ -73,11 +73,14 @@ impl CadCommand for LineCommand {
CmdResult::Cancel
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
let last = self.last?;
Some(WireModel {
name: "rubber_band".to_string(),
points: vec![[last.x, last.y, last.z], [pt.x, pt.y, pt.z]],
points: vec![
[last.x as f32, last.y as f32, last.z as f32],
[pt.x as f32, pt.y as f32, pt.z as f32],
],
points_low: Vec::new(),
color: WireModel::CYAN,
selected: false,
+3 -3
View File
@@ -8,7 +8,7 @@
use acadrust::entities::MLine;
use acadrust::types::Vector3;
use acadrust::EntityType;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -111,7 +111,7 @@ impl CadCommand for MlineCommand {
None
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
self.points.push(pt);
CmdResult::NeedPoint
}
@@ -124,7 +124,7 @@ impl CadCommand for MlineCommand {
CmdResult::CommitAndExit(entity)
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if self.points.is_empty() {
return None;
}
+3 -3
View File
@@ -9,7 +9,7 @@ use acadrust::{EntityType, Point as CadPoint};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::model::wire_model::WireModel;
use glam::Vec3;
use glam::DVec3;
#[allow(dead_code)]
pub fn tool() -> ToolDef {
@@ -37,7 +37,7 @@ impl CadCommand for PointCommand {
"POINT Specify point [Enter=done]:".into()
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
let p = CadPoint {
location: Vector3::new(pt.x as f64, pt.y as f64, pt.z as f64),
..Default::default()
@@ -51,7 +51,7 @@ impl CadCommand for PointCommand {
fn on_escape(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, _pt: DVec3) -> Option<WireModel> {
None
}
}
+3 -3
View File
@@ -12,7 +12,7 @@
use acadrust::entities::LwVertex;
use acadrust::types::Vector2;
use acadrust::{EntityType, Handle, LwPolyline};
use glam::{Vec2, Vec3};
use glam::{DVec3, Vec2, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -224,7 +224,7 @@ impl CadCommand for PlineCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if !self.vertices.is_empty() {
let last = *self.vertices.last().unwrap();
let last_idx = self.vertices.len() - 1;
@@ -302,7 +302,7 @@ impl CadCommand for PlineCommand {
}
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
// The committed vertices already render as a real document entity, so
// the preview is just the pending segment from the last vertex to the
// cursor. (#119)
+3 -3
View File
@@ -9,7 +9,7 @@
use acadrust::entities::RasterImage;
use acadrust::types::Vector3;
use acadrust::EntityType;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -75,7 +75,7 @@ impl CadCommand for ImageCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if let Some(origin) = self.origin {
let entity = self.make_entity(origin, pt);
CmdResult::CommitAndExit(entity)
@@ -97,7 +97,7 @@ impl CadCommand for ImageCommand {
}
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
let origin = self.origin?;
let world_width = (pt.x - origin.x).abs().max(0.001);
let world_height = world_width / self.aspect() as f32;
+5 -5
View File
@@ -10,7 +10,7 @@ use acadrust::EntityType;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
use glam::Vec3;
use glam::{DVec3, Vec3};
const DISPLAY_EXTENT: f32 = 1_000_000.0;
@@ -39,7 +39,7 @@ impl CadCommand for RayCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if let Some(base) = self.base {
let dir = pt - base;
let len = dir.length();
@@ -69,7 +69,7 @@ impl CadCommand for RayCommand {
CmdResult::Cancel
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
let base = self.base?;
let dir = (pt - base).normalize_or_zero();
let far = base + dir * DISPLAY_EXTENT;
@@ -120,7 +120,7 @@ impl CadCommand for XLineCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if let Some(base) = self.base {
let dir = pt - base;
let len = dir.length();
@@ -148,7 +148,7 @@ impl CadCommand for XLineCommand {
CmdResult::Cancel
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
let base = self.base?;
let dir = (pt - base).normalize_or_zero();
let far_pos = base + dir * DISPLAY_EXTENT;
+3 -3
View File
@@ -7,7 +7,7 @@
use acadrust::entities::LwPolyline;
use acadrust::types::Vector2;
use acadrust::{entities::LwVertex, EntityType};
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -59,7 +59,7 @@ impl CadCommand for RevCloudCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
self.points.push(pt);
CmdResult::NeedPoint
}
@@ -72,7 +72,7 @@ impl CadCommand for RevCloudCommand {
CmdResult::CommitAndExit(entity)
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if self.points.is_empty() {
return None;
}
+3 -3
View File
@@ -9,7 +9,7 @@ use acadrust::{EntityType, Spline};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::model::wire_model::WireModel;
use glam::Vec3;
use glam::{DVec3, Vec3};
#[allow(dead_code)]
pub fn tool() -> ToolDef {
@@ -84,7 +84,7 @@ impl CadCommand for SplineCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
self.pts.push(pt);
CmdResult::NeedPoint
}
@@ -103,7 +103,7 @@ impl CadCommand for SplineCommand {
}
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if self.pts.is_empty() {
return None;
}
+3 -3
View File
@@ -7,7 +7,7 @@
use acadrust::entities::Wipeout;
use acadrust::types::Vector3;
use acadrust::EntityType;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -79,7 +79,7 @@ impl CadCommand for WipeoutCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match &self.mode {
WipeoutMode::Rectangular => {
if let Some(p1) = self.first {
@@ -107,7 +107,7 @@ impl CadCommand for WipeoutCommand {
}
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
match &self.mode {
WipeoutMode::Rectangular => {
let p1 = self.first?;
+3 -3
View File
@@ -14,7 +14,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -64,11 +64,11 @@ impl CadCommand for GroupCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_hover_entity(&mut self, _handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, _handle: Handle, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
}
+3 -3
View File
@@ -14,7 +14,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -47,7 +47,7 @@ impl CadCommand for UngroupCommand {
CmdResult::DeleteGroups { handles }
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
@@ -55,7 +55,7 @@ impl CadCommand for UngroupCommand {
CmdResult::Cancel
}
fn on_hover_entity(&mut self, _handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, _handle: Handle, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
// AREA command — compute area and perimeter of a polygon picked point by point.
// Press Enter to close and calculate.
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -32,7 +32,7 @@ impl CadCommand for AreaCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
self.points.push(pt);
CmdResult::NeedPoint
}
@@ -56,7 +56,7 @@ impl CadCommand for AreaCommand {
CmdResult::Measurement(msg)
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
if self.points.is_empty() {
return None;
}
+3 -3
View File
@@ -1,6 +1,6 @@
// DIST command — measure distance and angle between two picked points.
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -28,7 +28,7 @@ impl CadCommand for DistCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if let Some(p1) = self.first {
let delta = pt - p1;
let dist = delta.length();
@@ -56,7 +56,7 @@ impl CadCommand for DistCommand {
CmdResult::Cancel
}
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
let p1 = self.first?;
Some(WireModel {
name: "dist_preview".into(),
+5 -5
View File
@@ -6,7 +6,7 @@ use std::f64::consts::PI;
use acadrust::entities::Point as PointEnt;
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -43,7 +43,7 @@ impl CadCommand for DivideCommand {
self.target.is_none()
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -71,7 +71,7 @@ impl CadCommand for DivideCommand {
Some(CmdResult::DivideEntity { handle, n })
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
@@ -112,7 +112,7 @@ impl CadCommand for MeasureCommand {
self.target.is_none()
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -148,7 +148,7 @@ impl CadCommand for MeasureCommand {
})
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
+2 -2
View File
@@ -1,6 +1,6 @@
// ID command — report coordinates of a picked point.
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -21,7 +21,7 @@ impl CadCommand for IdCommand {
"ID Specify point:".into()
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
// Drawing plane is world XY (z = elevation).
let x = pt.x;
let y = pt.y;
+3 -3
View File
@@ -16,7 +16,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -66,7 +66,7 @@ impl CadCommand for LayMatchCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
@@ -75,7 +75,7 @@ impl CadCommand for LayMatchCommand {
fn on_escape(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_hover_entity(&mut self, _handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, _handle: Handle, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
}
+6 -6
View File
@@ -10,7 +10,7 @@
// With 2 pairs: translate + rotate (+ optional uniform scale to fit)
use acadrust::Handle;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult, EntityTransform};
@@ -74,7 +74,7 @@ impl CadCommand for AlignCommand {
CmdResult::NeedPoint
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match self.state {
AlignState::Gathering => CmdResult::NeedPoint,
AlignState::Src1 => {
@@ -117,7 +117,7 @@ impl CadCommand for AlignCommand {
let delta = d - s;
CmdResult::TransformSelected(
self.handles.clone(),
EntityTransform::Translate(delta),
EntityTransform::Translate(delta.as_dvec3()),
)
}
_ => CmdResult::Cancel,
@@ -163,7 +163,7 @@ impl AlignCommand {
let delta = d1 - s1;
return CmdResult::TransformSelected(
self.handles.clone(),
EntityTransform::Translate(delta),
EntityTransform::Translate(delta.as_dvec3()),
);
}
@@ -182,8 +182,8 @@ impl AlignCommand {
// Compose via AlignTransform CmdResult
CmdResult::AlignSelected {
handles: self.handles.clone(),
src1: s1,
dst1: d1,
src1: s1.as_dvec3(),
dst1: d1.as_dvec3(),
angle_rad: angle,
scale: scale_factor,
}
+4 -4
View File
@@ -7,7 +7,7 @@
// After all attributes are processed, commit via ReplaceMany.
use acadrust::EntityType;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -59,7 +59,7 @@ impl CadCommand for AtteditCommand {
matches!(self.step, Step::SelectInsert)
}
fn on_entity_pick(&mut self, handle: acadrust::Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: acadrust::Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -114,13 +114,13 @@ impl CadCommand for AtteditCommand {
None
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_preview_wires(&mut self, _pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
+9 -9
View File
@@ -15,7 +15,7 @@ use acadrust::entities::{
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::{DVec3, Vec3};
use truck_modeling::base::{BoundedCurve, Cut};
use crate::command::{CadCommand, CmdResult};
@@ -382,7 +382,7 @@ impl CadCommand for BreakInteractiveCommand {
self.target.is_none()
}
fn on_entity_pick(&mut self, handle: Handle, pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -391,7 +391,7 @@ impl CadCommand for BreakInteractiveCommand {
CmdResult::NeedPoint
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
let handle = match self.target {
Some(h) => h,
None => return CmdResult::Cancel,
@@ -403,14 +403,14 @@ impl CadCommand for BreakInteractiveCommand {
return CmdResult::NeedPoint;
}
};
CmdResult::BreakEntity { handle, p1, p2: pt }
CmdResult::BreakEntity { handle, p1: p1.as_dvec3(), p2: pt.as_dvec3() }
}
fn on_enter(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_mouse_move(&mut self, _pt: Vec3) -> Option<WireModel> {
fn on_mouse_move(&mut self, _pt: DVec3) -> Option<WireModel> {
None
}
}
@@ -444,7 +444,7 @@ impl CadCommand for BreakAtPointCommand {
self.target.is_none()
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -452,12 +452,12 @@ impl CadCommand for BreakAtPointCommand {
CmdResult::NeedPoint
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match self.target {
Some(handle) => CmdResult::BreakEntity {
handle,
p1: pt,
p2: pt,
p1: pt.as_dvec3(),
p2: pt.as_dvec3(),
},
None => CmdResult::Cancel,
}
+9 -6
View File
@@ -6,7 +6,7 @@
// Step 2+: each click makes another copy at (click - base); Enter to finish.
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, EntityTransform};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -27,7 +27,7 @@ pub fn tool() -> ToolDef {
enum Step {
Base,
Placing(Vec3),
Placing(DVec3),
}
pub struct CopyCommand {
@@ -66,7 +66,7 @@ impl CadCommand for CopyCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
match &self.step {
Step::Base => {
self.step = Step::Placing(pt);
@@ -87,7 +87,7 @@ impl CadCommand for CopyCommand {
CmdResult::Cancel
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
let Step::Placing(base) = &self.step else {
return vec![];
};
@@ -95,11 +95,14 @@ impl CadCommand for CopyCommand {
let mut out: Vec<WireModel> = self
.wire_models
.iter()
.map(|w| w.translated(delta))
.map(|w| w.translated(delta.as_vec3()))
.collect();
out.push(WireModel::solid(
"rubber_band".into(),
vec![[base.x, base.y, base.z], [pt.x, pt.y, pt.z]],
vec![
[base.x as f32, base.y as f32, base.z as f32],
[pt.x as f32, pt.y as f32, pt.z as f32],
],
WireModel::CYAN,
false,
));
+2 -2
View File
@@ -26,7 +26,7 @@ use acadrust::{CadDocument, EntityType, Handle};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use glam::Vec3;
use glam::DVec3;
// ── Ribbon definition ──────────────────────────────────────────────────────
@@ -447,7 +447,7 @@ impl CadCommand for ExplodeCommand {
"EXPLODE Select objects to explode:".into()
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::Cancel
}
fn on_enter(&mut self) -> CmdResult {
+7 -7
View File
@@ -12,7 +12,7 @@
use acadrust::entities::{Arc as ArcEnt, Line as LineEnt, LwPolyline};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::DVec3;
const TAU: f64 = std::f64::consts::TAU;
@@ -1328,7 +1328,7 @@ impl CadCommand for FilletCommand {
!matches!(self.step, FilletStep::WaitingForRadius)
}
fn on_entity_pick(&mut self, handle: Handle, pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -1406,7 +1406,7 @@ impl CadCommand for FilletCommand {
}
}
fn on_hover_entity(&mut self, handle: Handle, pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, handle: Handle, pt: DVec3) -> Vec<WireModel> {
if handle.is_null() {
return vec![];
}
@@ -1484,7 +1484,7 @@ impl CadCommand for FilletCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
@@ -1743,7 +1743,7 @@ impl CadCommand for ChamferCommand {
)
}
fn on_entity_pick(&mut self, handle: Handle, pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -1825,7 +1825,7 @@ impl CadCommand for ChamferCommand {
}
}
fn on_hover_entity(&mut self, handle: Handle, pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, handle: Handle, pt: DVec3) -> Vec<WireModel> {
if handle.is_null() {
return vec![];
}
@@ -1915,7 +1915,7 @@ impl CadCommand for ChamferCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
+2 -2
View File
@@ -11,7 +11,7 @@
use acadrust::types::{Vector2, Vector3};
use acadrust::{EntityType, Handle};
use glam::{DVec3, Vec3};
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -52,7 +52,7 @@ impl CadCommand for JoinCommand {
CmdResult::NeedPoint
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
+4 -3
View File
@@ -13,7 +13,7 @@ use acadrust::entities::{
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::{DVec3, Vec3};
use truck_modeling::base::{BoundedCurve, Cut};
use crate::command::{CadCommand, CmdResult};
@@ -53,7 +53,7 @@ impl CadCommand for LengthenCommand {
matches!(self.state, LenState::PickEntity)
}
fn on_entity_pick(&mut self, handle: Handle, pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -81,6 +81,7 @@ impl CadCommand for LengthenCommand {
LenState::PickOption { handle, pick_pt } => (*handle, *pick_pt),
_ => return None,
};
let pick_pt = pick_pt.as_dvec3();
let text = text.trim().to_uppercase();
if let Some(rest) = text.strip_prefix("DE ").or_else(|| text.strip_prefix("DE")) {
@@ -125,7 +126,7 @@ impl CadCommand for LengthenCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
+11 -8
View File
@@ -9,7 +9,7 @@
// Yes → flip the original in place (no copy kept)
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, EntityTransform};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -26,9 +26,9 @@ pub fn tool() -> ToolDef {
enum Step {
P1,
P2(Vec3),
P2(DVec3),
/// Both mirror-line points fixed; waiting on the erase-source answer.
AskErase { p1: Vec3, p2: Vec3 },
AskErase { p1: DVec3, p2: DVec3 },
}
pub struct MirrorCommand {
@@ -66,7 +66,7 @@ impl CadCommand for MirrorCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
match &self.step {
Step::P1 => {
self.step = Step::P2(pt);
@@ -113,7 +113,7 @@ impl CadCommand for MirrorCommand {
Some(self.finish(p1, p2, erase))
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
// While picking the second point the ghost tracks the cursor; once it
// is fixed (erase prompt) the ghost freezes at the chosen axis.
let (p1, p2) = match &self.step {
@@ -125,12 +125,15 @@ impl CadCommand for MirrorCommand {
let mut out: Vec<WireModel> = self
.wire_models
.iter()
.map(|w| w.mirrored(p1, p2))
.map(|w| w.mirrored(p1.as_vec3(), p2.as_vec3()))
.collect();
// Mirror-axis line (rubber-band).
out.push(WireModel::solid(
"rubber_band".into(),
vec![[p1.x, p1.y, p1.z], [p2.x, p2.y, p2.z]],
vec![
[p1.x as f32, p1.y as f32, p1.z as f32],
[p2.x as f32, p2.y as f32, p2.z as f32],
],
WireModel::CYAN,
false,
));
@@ -141,7 +144,7 @@ impl CadCommand for MirrorCommand {
impl MirrorCommand {
/// Commit the mirror. `erase` true flips the originals in place; false
/// keeps them and adds a mirrored copy. Either way the command ends.
fn finish(&self, p1: Vec3, p2: Vec3, erase: bool) -> CmdResult {
fn finish(&self, p1: DVec3, p2: DVec3, erase: bool) -> CmdResult {
let xform = EntityTransform::Mirror { p1, p2 };
if erase {
CmdResult::TransformSelected(self.handles.clone(), xform)
+11 -11
View File
@@ -18,7 +18,7 @@ use acadrust::entities::{
Spline as SplineEnt,
};
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::modules::draw::defaults;
@@ -632,7 +632,7 @@ impl CadCommand for OffsetCommand {
matches!(self.step, Step::SelectObject)
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() || !matches!(self.step, Step::SelectObject) {
return CmdResult::NeedPoint;
}
@@ -672,10 +672,10 @@ impl CadCommand for OffsetCommand {
}
}
fn dyn_live_value(&self, cursor: Vec3) -> Option<f64> {
fn dyn_live_value(&self, cursor: DVec3) -> Option<f64> {
match &self.step {
Step::PickSide { entity, locked, .. } => {
Some(locked.unwrap_or_else(|| perp_distance(entity, cursor)))
Some(locked.unwrap_or_else(|| perp_distance(entity, cursor.as_vec3())))
}
_ => None,
}
@@ -697,7 +697,7 @@ impl CadCommand for OffsetCommand {
None
}
fn on_hover_entity(&mut self, handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, handle: Handle, _pt: DVec3) -> Vec<WireModel> {
if handle.is_null() {
return vec![];
}
@@ -719,33 +719,33 @@ impl CadCommand for OffsetCommand {
vec![]
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
let (locked, entity) = match &self.step {
Step::PickSide { locked, entity, .. } => (*locked, entity.clone()),
_ => return CmdResult::NeedPoint,
};
let mag = locked.unwrap_or_else(|| perp_distance(&entity, pt));
let mag = locked.unwrap_or_else(|| perp_distance(&entity, pt.as_vec3()));
if mag < 1e-9 {
return CmdResult::NeedPoint;
}
match compute_offset(&entity, mag, pt) {
match compute_offset(&entity, mag, pt.as_vec3()) {
Some(new_entity) => CmdResult::CommitAndExit(new_entity),
None => CmdResult::NeedPoint,
}
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
let (locked, entity) = match &self.step {
Step::PickSide { locked, entity, .. } => (*locked, entity.clone()),
_ => return vec![],
};
let mag = locked.unwrap_or_else(|| perp_distance(&entity, pt));
let mag = locked.unwrap_or_else(|| perp_distance(&entity, pt.as_vec3()));
if mag < 1e-9 {
return vec![];
}
if let Some(result) = compute_offset(&entity, mag, pt) {
if let Some(result) = compute_offset(&entity, mag, pt.as_vec3()) {
let pts = entity_wire_pts(&result);
if !pts.is_empty() {
return vec![WireModel::solid(
+3 -3
View File
@@ -10,7 +10,7 @@
// X / EXIT — exit
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
@@ -41,7 +41,7 @@ impl CadCommand for PeditCommand {
self.target.is_none()
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -90,7 +90,7 @@ impl CadCommand for PeditCommand {
None
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
+4 -4
View File
@@ -14,7 +14,7 @@
// require per-entity matrix transforms not yet in EntityTransform.
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -80,7 +80,7 @@ impl CadCommand for RefEditPickCommand {
true
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -89,7 +89,7 @@ impl CadCommand for RefEditPickCommand {
CmdResult::Relaunch(format!("REFEDIT_BEGIN:{}", handle.value()), vec![handle])
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
@@ -134,7 +134,7 @@ impl CadCommand for RefCloseCommand {
// Default: SAVE
CmdResult::Relaunch("REFCLOSE_SAVE".into(), vec![])
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
}
+17 -14
View File
@@ -7,7 +7,7 @@
// Step 3: pick destination point → rotates by (dest_angle - ref_angle)
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, DynField, EntityTransform};
use crate::modules::draw::defaults;
@@ -29,8 +29,8 @@ pub fn tool() -> ToolDef {
enum Step {
Center,
RefPoint { center: Vec3 },
Angle { center: Vec3, ref_angle: f32 },
RefPoint { center: DVec3 },
Angle { center: DVec3, ref_angle: f64 },
}
pub struct RotateCommand {
@@ -73,7 +73,7 @@ impl CadCommand for RotateCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
match &self.step {
Step::Center => {
self.step = Step::RefPoint { center: pt };
@@ -90,13 +90,13 @@ impl CadCommand for RotateCommand {
let ref_angle = *ref_angle;
let dest_angle = (pt.y - center.y).atan2(pt.x - center.x);
let delta = dest_angle - ref_angle;
defaults::set_rotate_angle(delta.to_degrees());
self.default_angle = delta.to_degrees();
defaults::set_rotate_angle(delta.to_degrees() as f32);
self.default_angle = delta.to_degrees() as f32;
CmdResult::TransformSelected(
self.handles.clone(),
EntityTransform::Rotate {
center,
angle_rad: delta,
angle_rad: delta as f32,
},
)
}
@@ -137,14 +137,17 @@ impl CadCommand for RotateCommand {
None
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
let (center, ref_angle) = match &self.step {
Step::Angle { center, ref_angle } => (*center, *ref_angle),
Step::RefPoint { center } => {
// Show a reference line from center to cursor only.
return vec![WireModel::solid(
"rubber_band".into(),
vec![[center.x, center.y, center.z], [pt.x, pt.y, pt.z]],
vec![
[center.x as f32, center.y as f32, center.z as f32],
[pt.x as f32, pt.y as f32, pt.z as f32],
],
WireModel::CYAN,
false,
)];
@@ -157,12 +160,12 @@ impl CadCommand for RotateCommand {
// committing with Enter rotates the way the cursor is dragging — the
// dynamic-input box shows the unsigned magnitude, but the committed
// value must keep its direction (clockwise = negative).
self.default_angle = angle_rad.to_degrees();
self.default_angle = angle_rad.to_degrees() as f32;
// Object ghosts rotated to the new angle. The rotation sweep arc is
// drawn by the dynamic-input overlay (polar guide), not here.
self.wire_models
.iter()
.map(|w| w.rotated(center, angle_rad))
.map(|w| w.rotated(center.as_vec3(), angle_rad as f32))
.collect()
}
@@ -179,7 +182,7 @@ impl CadCommand for RotateCommand {
// direction. The polar guide arc is anchored at the centre and starts
// at the reference (via ref_point), with the value box centred on it.
if let Step::Angle { center, ref_angle } = self.step {
let ref_dir = Vec3::new(center.x + ref_angle.cos(), center.y + ref_angle.sin(), center.z);
let ref_dir = DVec3::new(center.x + ref_angle.cos(), center.y + ref_angle.sin(), center.z);
Some(DynSpec {
anchor: DynAnchor::Point(center),
fields: vec![DynFieldSpec::new(DynRole::Angle)],
@@ -195,12 +198,12 @@ impl CadCommand for RotateCommand {
matches!(self.step, Step::Angle { .. })
}
fn dyn_live_value(&self, cursor: Vec3) -> Option<f64> {
fn dyn_live_value(&self, cursor: DVec3) -> Option<f64> {
// The rotation amount = cursor direction from the centre minus the
// reference angle, so the box reads the actual rotation.
if let Step::Angle { center, ref_angle } = &self.step {
let dest = (cursor.y - center.y).atan2(cursor.x - center.x);
Some(crate::command::dyn_display_angle_deg(dest - ref_angle) as f64)
Some(crate::command::dyn_display_angle_deg((dest - ref_angle) as f32) as f64)
} else {
None
}
+22 -16
View File
@@ -13,7 +13,7 @@
// Step 2b: specify new length (pick a point or type a length)
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, EntityTransform};
use crate::modules::draw::defaults;
@@ -33,11 +33,11 @@ pub fn tool() -> ToolDef {
enum Step {
Base,
/// Default flow: factor is the cursor distance from `base`.
Factor { base: Vec3 },
Factor { base: DVec3 },
/// Reference flow: defining the reference length from `base`.
RefLen { base: Vec3 },
RefLen { base: DVec3 },
/// Reference flow: factor is `cursor_dist / ref_dist` from `base`.
RefNew { base: Vec3, ref_dist: f32 },
RefNew { base: DVec3, ref_dist: f32 },
}
pub struct ScaleCommand {
@@ -58,7 +58,7 @@ impl ScaleCommand {
}
/// Commit a uniform scale about `base` and end the command.
fn commit(&self, base: Vec3, factor: f32) -> CmdResult {
fn commit(&self, base: DVec3, factor: f32) -> CmdResult {
defaults::set_scale_factor(factor);
CmdResult::TransformSelected(
self.handles.clone(),
@@ -95,7 +95,7 @@ impl CadCommand for ScaleCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
match &self.step {
Step::Base => {
self.step = Step::Factor { base: pt };
@@ -103,18 +103,18 @@ impl CadCommand for ScaleCommand {
}
Step::Factor { base } => {
let base = *base;
let factor = base.distance(pt).max(1e-6);
let factor = base.distance(pt).max(1e-6) as f32;
self.commit(base, factor)
}
Step::RefLen { base } => {
let base = *base;
let ref_dist = base.distance(pt).max(1e-6);
let ref_dist = base.distance(pt).max(1e-6) as f32;
self.step = Step::RefNew { base, ref_dist };
CmdResult::NeedPoint
}
Step::RefNew { base, ref_dist } => {
let base = *base;
let new_dist = base.distance(pt).max(1e-6);
let new_dist = base.distance(pt).max(1e-6) as f32;
self.commit(base, new_dist / *ref_dist)
}
}
@@ -164,19 +164,22 @@ impl CadCommand for ScaleCommand {
}
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
let (base, factor) = match &self.step {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
let (base, factor): (DVec3, f32) = match &self.step {
// Default flow: scale live by cursor distance from the base.
Step::Factor { base } => (*base, base.distance(pt).max(1e-6)),
Step::Factor { base } => (*base, base.distance(pt).max(1e-6) as f32),
// Reference flow, new-length step: factor = cursor_dist / ref_dist.
Step::RefNew { base, ref_dist } => {
(*base, base.distance(pt).max(1e-6) / ref_dist)
(*base, base.distance(pt).max(1e-6) as f32 / ref_dist)
}
// Reference-length step: rubber-band only, no factor defined yet.
Step::RefLen { base } => {
return vec![WireModel::solid(
"rubber_band".into(),
vec![[base.x, base.y, base.z], [pt.x, pt.y, pt.z]],
vec![
[base.x as f32, base.y as f32, base.z as f32],
[pt.x as f32, pt.y as f32, pt.z as f32],
],
WireModel::CYAN,
false,
)];
@@ -186,11 +189,14 @@ impl CadCommand for ScaleCommand {
let mut out: Vec<WireModel> = self
.wire_models
.iter()
.map(|w| w.scaled(base, factor))
.map(|w| w.scaled(base.as_vec3(), factor))
.collect();
out.push(WireModel::solid(
"rubber_band".into(),
vec![[base.x, base.y, base.z], [pt.x, pt.y, pt.z]],
vec![
[base.x as f32, base.y as f32, base.z as f32],
[pt.x as f32, pt.y as f32, pt.z as f32],
],
WireModel::CYAN,
false,
));
+4 -4
View File
@@ -10,7 +10,7 @@
// Control-point dragging is already supported via the grip editing system.
use acadrust::EntityType;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -61,7 +61,7 @@ impl CadCommand for SplineditCommand {
matches!(self.step, Step::SelectSpline)
}
fn on_entity_pick(&mut self, handle: acadrust::Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: acadrust::Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -96,13 +96,13 @@ impl CadCommand for SplineditCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_preview_wires(&mut self, _pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
}
+6 -6
View File
@@ -16,7 +16,7 @@
// All others : move the whole entity if any point is inside.
use acadrust::Handle;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -86,7 +86,7 @@ impl CadCommand for StretchCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match &self.step {
Step::WindowCorner1 => {
self.step = Step::WindowCorner2(pt);
@@ -115,9 +115,9 @@ impl CadCommand for StretchCommand {
let delta = pt - *base;
CmdResult::StretchEntities {
handles: self.handles.clone(),
win_min: *win_min,
win_max: *win_max,
delta,
win_min: win_min.as_dvec3(),
win_max: win_max.as_dvec3(),
delta: delta.as_dvec3(),
}
}
}
@@ -130,7 +130,7 @@ impl CadCommand for StretchCommand {
CmdResult::Cancel
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> { let pt = pt.as_vec3();
match &self.step {
Step::WindowCorner2(c1) => {
// Show crossing-window rectangle preview (dashed green)
+3 -3
View File
@@ -6,7 +6,7 @@
// Step 2: If first point picked, pick second point to define angle vector.
use acadrust::Handle;
use glam::Vec3;
use glam::{DVec3, Vec3};
use crate::command::{CadCommand, CmdResult, DynField};
use crate::scene::model::wire_model::WireModel;
@@ -122,7 +122,7 @@ impl CadCommand for TorientCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult { let pt = pt.as_vec3();
match self.step {
Step::AngleOrFirstPoint => {
self.step = Step::SecondPoint { first_point: pt };
@@ -157,7 +157,7 @@ impl CadCommand for TorientCommand {
}
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> { let pt = pt.as_vec3();
if let Step::SecondPoint { first_point } = self.step {
vec![WireModel::solid(
"rubber_band".into(),
+9 -6
View File
@@ -6,7 +6,7 @@
// Step 2: pick destination → translates all selected entities by (dest - base)
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult, EntityTransform};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
@@ -27,7 +27,7 @@ pub fn tool() -> ToolDef {
enum Step {
Base,
Target(Vec3),
Target(DVec3),
}
pub struct MoveCommand {
@@ -64,7 +64,7 @@ impl CadCommand for MoveCommand {
}
}
fn on_point(&mut self, pt: Vec3) -> CmdResult {
fn on_point(&mut self, pt: DVec3) -> CmdResult {
match &self.step {
Step::Base => {
self.step = Step::Target(pt);
@@ -87,7 +87,7 @@ impl CadCommand for MoveCommand {
CmdResult::Cancel
}
fn on_preview_wires(&mut self, pt: Vec3) -> Vec<WireModel> {
fn on_preview_wires(&mut self, pt: DVec3) -> Vec<WireModel> {
let Step::Target(base) = &self.step else {
return vec![];
};
@@ -96,11 +96,14 @@ impl CadCommand for MoveCommand {
let mut out: Vec<WireModel> = self
.wire_models
.iter()
.map(|w| w.translated(delta))
.map(|w| w.translated(delta.as_vec3()))
.collect();
out.push(WireModel::solid(
"rubber_band".into(),
vec![[base.x, base.y, base.z], [pt.x, pt.y, pt.z]],
vec![
[base.x as f32, base.y as f32, base.z as f32],
[pt.x as f32, pt.y as f32, pt.z as f32],
],
WireModel::CYAN,
false,
));
+7 -7
View File
@@ -16,7 +16,7 @@ use acadrust::entities::{
};
use acadrust::types::Vector3;
use acadrust::{EntityType, Handle};
use glam::Vec3;
use glam::DVec3;
use truck_modeling::base::{BoundedCurve, Cut, ParametricCurve};
use crate::command::{CadCommand, CmdResult};
@@ -1990,7 +1990,7 @@ impl CadCommand for TrimCommand {
true
}
fn on_entity_pick(&mut self, handle: Handle, pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -2169,7 +2169,7 @@ impl CadCommand for TrimCommand {
self.geos = build_geos(&self.all_entities);
}
fn on_hover_entity(&mut self, handle: Handle, pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, handle: Handle, pt: DVec3) -> Vec<WireModel> {
if handle.is_null() {
return vec![];
}
@@ -2407,7 +2407,7 @@ impl CadCommand for TrimCommand {
}
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
@@ -2458,7 +2458,7 @@ impl CadCommand for ExtendCommand {
true
}
fn on_entity_pick(&mut self, handle: Handle, pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint;
}
@@ -2555,7 +2555,7 @@ impl CadCommand for ExtendCommand {
}
}
fn on_hover_entity(&mut self, handle: Handle, pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, handle: Handle, pt: DVec3) -> Vec<WireModel> {
if handle.is_null() {
return vec![];
}
@@ -2643,7 +2643,7 @@ impl CadCommand for ExtendCommand {
vec![]
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
+4 -4
View File
@@ -14,7 +14,7 @@ pub fn tool() -> ToolDef {
// ── CadCommand implementation ─────────────────────────────────────────────
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -53,7 +53,7 @@ impl CadCommand for MatchPropCommand {
!self.phase1_done()
}
fn on_entity_pick(&mut self, handle: Handle, _pt: Vec3) -> CmdResult {
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
if handle.is_null() {
return CmdResult::NeedPoint; // nothing hit, keep waiting
}
@@ -81,11 +81,11 @@ impl CadCommand for MatchPropCommand {
CmdResult::Cancel
}
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_hover_entity(&mut self, _handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, _handle: Handle, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
}
+3 -3
View File
@@ -6,7 +6,7 @@
// immediately — no Enter required.
use acadrust::Handle;
use glam::Vec3;
use glam::DVec3;
use crate::command::{CadCommand, CmdResult};
use crate::scene::model::wire_model::WireModel;
@@ -47,7 +47,7 @@ impl CadCommand for SelectObjectsCommand {
// These are never called while is_selection_gathering is true, but the
// trait requires implementations.
fn on_point(&mut self, _pt: Vec3) -> CmdResult {
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
CmdResult::NeedPoint
}
fn on_enter(&mut self) -> CmdResult {
@@ -56,7 +56,7 @@ impl CadCommand for SelectObjectsCommand {
fn on_escape(&mut self) -> CmdResult {
CmdResult::Cancel
}
fn on_hover_entity(&mut self, _handle: Handle, _pt: Vec3) -> Vec<WireModel> {
fn on_hover_entity(&mut self, _handle: Handle, _pt: DVec3) -> Vec<WireModel> {
vec![]
}
}