2026-04-03 09:29:11 +03:00
|
|
|
|
// DIMALIGNED command — aligned dimension (measures true distance between two points).
|
|
|
|
|
|
|
|
|
|
|
|
use acadrust::entities::{Dimension, DimensionAligned};
|
|
|
|
|
|
use acadrust::types::Vector3;
|
|
|
|
|
|
use acadrust::EntityType;
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
use glam::DVec3;
|
2026-04-03 09:29:11 +03:00
|
|
|
|
|
|
|
|
|
|
use crate::command::{CadCommand, CmdResult};
|
feat: redesign Annotate ribbon tab with proper groups and SVG icons
Added 15 SVG icons for all annotation tools (dimensions, leaders,
table, wipeout, revision cloud, tolerance, ddedit).
Annotate ribbon now has 6 groups matching standard CAD layout:
- Text: MText (large dropdown) + Text + Edit Text
- Dimensions: Linear (large dropdown with 6 types) + Continue + Baseline + Tolerance
- Leaders: Multileader (large dropdown) + Leader
- Tables: Table (large)
- Markup: Wipeout + Rev Cloud
- Annotation Scaling: Scale List, Add Scale, Scale Edit, Sync Scales
Added pub tool() + ICON to all annotate tools that were missing them
(aligned_dim, diameter_dim, dim_continue, dim_baseline, table_cmd,
tolerance_cmd, ddedit), and to home/draw/wipeout and revcloud.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 03:03:08 +03:00
|
|
|
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
2026-06-16 11:33:46 +03:00
|
|
|
|
use crate::scene::model::wire_model::WireModel;
|
2026-04-03 09:29:11 +03:00
|
|
|
|
|
feat: redesign Annotate ribbon tab with proper groups and SVG icons
Added 15 SVG icons for all annotation tools (dimensions, leaders,
table, wipeout, revision cloud, tolerance, ddedit).
Annotate ribbon now has 6 groups matching standard CAD layout:
- Text: MText (large dropdown) + Text + Edit Text
- Dimensions: Linear (large dropdown with 6 types) + Continue + Baseline + Tolerance
- Leaders: Multileader (large dropdown) + Leader
- Tables: Table (large)
- Markup: Wipeout + Rev Cloud
- Annotation Scaling: Scale List, Add Scale, Scale Edit, Sync Scales
Added pub tool() + ICON to all annotate tools that were missing them
(aligned_dim, diameter_dim, dim_continue, dim_baseline, table_cmd,
tolerance_cmd, ddedit), and to home/draw/wipeout and revcloud.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 03:03:08 +03:00
|
|
|
|
pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/dim_aligned.svg"));
|
|
|
|
|
|
|
|
|
|
|
|
pub fn tool() -> ToolDef {
|
|
|
|
|
|
ToolDef {
|
|
|
|
|
|
id: "DIMALIGNED",
|
|
|
|
|
|
label: "Aligned",
|
|
|
|
|
|
icon: ICON,
|
|
|
|
|
|
event: ModuleEvent::Command("DIMALIGNED".to_string()),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-03 09:29:11 +03:00
|
|
|
|
enum Step {
|
|
|
|
|
|
First,
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
Second(DVec3),
|
|
|
|
|
|
DimLine { p1: DVec3, p2: DVec3 },
|
2026-04-03 09:29:11 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct AlignedDimensionCommand {
|
|
|
|
|
|
step: Step,
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
/// Optional text that replaces the measured value (None = measurement).
|
|
|
|
|
|
text_override: Option<String>,
|
|
|
|
|
|
/// True while the next typed line is captured as the text override.
|
|
|
|
|
|
awaiting_text: bool,
|
|
|
|
|
|
/// Explicit text rotation in radians (None = follow the UCS/style).
|
|
|
|
|
|
text_angle: Option<f64>,
|
|
|
|
|
|
/// True while the next typed value is captured as the text angle.
|
|
|
|
|
|
awaiting_angle: bool,
|
2026-04-03 09:29:11 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl AlignedDimensionCommand {
|
|
|
|
|
|
pub fn new() -> Self {
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
Self {
|
|
|
|
|
|
step: Step::First,
|
|
|
|
|
|
text_override: None,
|
|
|
|
|
|
awaiting_text: false,
|
|
|
|
|
|
text_angle: None,
|
|
|
|
|
|
awaiting_angle: false,
|
|
|
|
|
|
}
|
2026-04-03 09:29:11 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl CadCommand for AlignedDimensionCommand {
|
2026-05-12 10:36:15 +03:00
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
|
|
"DIMALIGNED"
|
|
|
|
|
|
}
|
2026-04-03 09:29:11 +03:00
|
|
|
|
|
|
|
|
|
|
fn prompt(&self) -> String {
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
if self.awaiting_text {
|
|
|
|
|
|
return "DIMALIGNED Enter dimension text (blank = measured value):".into();
|
|
|
|
|
|
}
|
|
|
|
|
|
if self.awaiting_angle {
|
|
|
|
|
|
return "DIMALIGNED Specify text angle (degrees):".into();
|
|
|
|
|
|
}
|
2026-04-03 09:29:11 +03:00
|
|
|
|
match self.step {
|
2026-05-12 10:36:15 +03:00
|
|
|
|
Step::First => "DIMALIGNED Specify first extension line origin:".into(),
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
Step::Second(_) => {
|
|
|
|
|
|
"DIMALIGNED Specify second extension line origin [Text/Angle]:".into()
|
|
|
|
|
|
}
|
|
|
|
|
|
Step::DimLine { .. } => {
|
|
|
|
|
|
"DIMALIGNED Specify dimension line location [Text/Angle]:".into()
|
|
|
|
|
|
}
|
2026-04-03 09:29:11 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
2026-04-03 09:29:11 +03:00
|
|
|
|
match self.step {
|
|
|
|
|
|
Step::First => {
|
|
|
|
|
|
self.step = Step::Second(pt);
|
|
|
|
|
|
CmdResult::NeedPoint
|
|
|
|
|
|
}
|
|
|
|
|
|
Step::Second(p1) => {
|
|
|
|
|
|
self.step = Step::DimLine { p1, p2: pt };
|
|
|
|
|
|
CmdResult::NeedPoint
|
|
|
|
|
|
}
|
|
|
|
|
|
Step::DimLine { p1, p2 } => {
|
|
|
|
|
|
let mut dim = DimensionAligned::new(v3(p1), v3(p2));
|
2026-06-25 17:55:39 +03:00
|
|
|
|
// The dimension line runs through the cursor: store it as the
|
|
|
|
|
|
// definition point and let the renderer project it onto the
|
|
|
|
|
|
// line perpendicular (same as the preview and DIMLINEAR).
|
|
|
|
|
|
//
|
|
|
|
|
|
// The old path called `set_offset` with the straight-line
|
|
|
|
|
|
// p2→cursor *distance*, which `set_offset` then re-applies along
|
|
|
|
|
|
// the line perpendicular — placing the line at the wrong
|
|
|
|
|
|
// perpendicular distance and always on the +perp side, so it
|
|
|
|
|
|
// never matched the preview the user was dragging. (#150)
|
|
|
|
|
|
dim.definition_point = v3(pt);
|
2026-04-03 09:29:11 +03:00
|
|
|
|
dim.base.definition_point = v3(pt);
|
2026-06-25 17:55:39 +03:00
|
|
|
|
let (d1, d2) = dim_line_endpoints(p1, p2, pt);
|
|
|
|
|
|
dim.base.text_middle_point = v3((d1 + d2) * 0.5);
|
2026-04-03 09:29:11 +03:00
|
|
|
|
dim.base.insertion_point = dim.base.text_middle_point;
|
|
|
|
|
|
dim.base.actual_measurement = dim.measurement();
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
dim.base.user_text = self.text_override.clone();
|
|
|
|
|
|
// An explicit text angle overrides the default rotation.
|
|
|
|
|
|
if let Some(a) = self.text_angle {
|
|
|
|
|
|
dim.base.text_rotation = a;
|
|
|
|
|
|
}
|
2026-04-03 09:29:11 +03:00
|
|
|
|
CmdResult::CommitAndExit(EntityType::Dimension(Dimension::Aligned(dim)))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 10:36:15 +03:00
|
|
|
|
fn on_enter(&mut self) -> CmdResult {
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
// A bare Enter while entering override text/angle accepts the default.
|
|
|
|
|
|
if self.awaiting_text {
|
|
|
|
|
|
self.awaiting_text = false;
|
|
|
|
|
|
return CmdResult::NeedPoint;
|
|
|
|
|
|
}
|
|
|
|
|
|
if self.awaiting_angle {
|
|
|
|
|
|
self.awaiting_angle = false;
|
|
|
|
|
|
return CmdResult::NeedPoint;
|
|
|
|
|
|
}
|
2026-05-12 10:36:15 +03:00
|
|
|
|
CmdResult::Cancel
|
|
|
|
|
|
}
|
2026-04-03 09:29:11 +03:00
|
|
|
|
|
feat(commands): integrate standard CAD commands and fix behavior gaps
Broad pass over the command set: integrate missing commands, wire
previously-unreachable ribbon/menu buttons, and correct name/behaviour
mismatches. Every UI command token now resolves (real handler where the
infrastructure exists, an honest "not yet implemented" status otherwise).
New commands:
- Draw: 3DPOLY, 2D solid (SO/SOLID2D), HELIX, TRACE, SKETCH, DIMCENTER
(DCE/CENTERMARK)
- Modify/inquiry: REVERSE, MEASUREGEOM (MEA), DBLIST
- Data/manage: BASE, OVERKILL (exact-duplicate removal), AUDIT (read-only
integrity report), SETVAR (system-variable get/set), SCRIPT (.scr runner),
FINDNONPURGEABLE
Behaviour fixes:
- LINE and SPLINE gain Close/Undo; AREA computes area/perimeter in f64
(correct at large coordinates)
- ATTEDIT/ATE unified so the alias and the ribbon button open the
interactive editor; -ATTEDIT is the command-line form
- Linear/aligned/radius/diameter dimensions gain a text override (Text) and
text angle (Angle) option
- INSERT gains Scale/Rotate options; COPY gains an Array option
- LINETYPE SET sets the current entity linetype; SETBYLAYER resets overrides
- UNDO accepts a step count
Integrations: standard dimension/block aliases (DLI/DRA/DAN, BMAKE,
EXPORTPDF, DDIM), drafting-aid and screen toggles (GRID/SNAP/POLAR/OSNAP/
DSETTINGS/CLEANSCREEN/QUICKPROPERTIES), viewport tiling
(CASCADE/HORIZONTAL/VERTICAL/VPJOIN), and customization entry points
(CUI/ALIASEDIT).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 19:27:35 +03:00
|
|
|
|
fn wants_text_input(&self) -> bool {
|
|
|
|
|
|
true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn point_step_accepts_keywords(&self) -> bool {
|
|
|
|
|
|
// While entering the override text or angle it is a value, not a point
|
|
|
|
|
|
// step.
|
|
|
|
|
|
!self.awaiting_text && !self.awaiting_angle
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn wants_text_with_spaces(&self) -> bool {
|
|
|
|
|
|
// The override text may contain spaces.
|
|
|
|
|
|
self.awaiting_text
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn on_text_input(&mut self, text: &str) -> Option<CmdResult> {
|
|
|
|
|
|
if self.awaiting_text {
|
|
|
|
|
|
let t = text.trim();
|
|
|
|
|
|
// Blank (or the "<>" placeholder) keeps the measured value.
|
|
|
|
|
|
self.text_override = if t.is_empty() || t == "<>" {
|
|
|
|
|
|
None
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Some(t.to_string())
|
|
|
|
|
|
};
|
|
|
|
|
|
self.awaiting_text = false;
|
|
|
|
|
|
return Some(CmdResult::NeedPoint);
|
|
|
|
|
|
}
|
|
|
|
|
|
if self.awaiting_angle {
|
|
|
|
|
|
let t = text.trim();
|
|
|
|
|
|
// Blank clears any explicit angle (follow the default again).
|
|
|
|
|
|
self.text_angle = if t.is_empty() {
|
|
|
|
|
|
None
|
|
|
|
|
|
} else {
|
|
|
|
|
|
t.parse::<f64>().ok().map(f64::to_radians)
|
|
|
|
|
|
};
|
|
|
|
|
|
self.awaiting_angle = false;
|
|
|
|
|
|
return Some(CmdResult::NeedPoint);
|
|
|
|
|
|
}
|
|
|
|
|
|
match text.trim().to_uppercase().as_str() {
|
|
|
|
|
|
"T" | "TEXT" | "M" | "MTEXT" => {
|
|
|
|
|
|
self.awaiting_text = true;
|
|
|
|
|
|
Some(CmdResult::NeedPoint)
|
|
|
|
|
|
}
|
|
|
|
|
|
"A" | "ANGLE" => {
|
|
|
|
|
|
self.awaiting_angle = true;
|
|
|
|
|
|
Some(CmdResult::NeedPoint)
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => None,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
|
2026-04-03 09:29:11 +03:00
|
|
|
|
let (p1, p2) = match self.step {
|
|
|
|
|
|
Step::First => return None,
|
|
|
|
|
|
Step::Second(p1) => (p1, pt),
|
|
|
|
|
|
Step::DimLine { p1, p2 } => {
|
|
|
|
|
|
return Some(preview_aligned(p1, p2, pt));
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
// Preview WireModel points are screen/GPU-side: downcast to f32.
|
|
|
|
|
|
let p1 = p1.as_vec3();
|
|
|
|
|
|
let p2 = p2.as_vec3();
|
2026-04-03 09:29:11 +03:00
|
|
|
|
Some(WireModel {
|
2026-07-20 16:36:06 +03:00
|
|
|
|
taper_widths: Vec::new(),
|
2026-07-20 14:50:27 +03:00
|
|
|
|
world_width: 0.0,
|
2026-07-18 15:15:24 +03:00
|
|
|
|
fill_is_3d: false,
|
fix(pick): hit-test lineweight width and thickness walls
Selection tested a flat 8 px radius around each wire's centreline and
nothing else, so two things the user can see were not pickable.
A wire renders as a band `line_weight_px` wide, so pick now widens to that
rendered half-width via `pick_tolerance_px`, mirroring the wire shader's
`select(0.5, half_width, lwdisplay_enable)`. Behaviour is unchanged for
every standard weight (the widest, 2.11 mm, renders 7.97 px half-width —
just under the 8 px threshold); this keeps the two sides from drifting
apart if the display boost in `lineweight_to_px` ever changes.
Entities extruded by a DXF thickness draw their wall as four edges with
nothing in between, so the interior was a hole the cursor fell through.
WireModel gains `pick_tris`: triangles hit-testing treats as solid and the
renderer never uploads. Kept apart from `fill_tris` because that channel
reaches the GPU, and a wall that rendered shaded would change how every
thickness drawing looks. Ranked below `fill_tris` — those are drawn, these
are not, so where they overlap the drawn face is what the user means.
Walls are dropped when a wire is projected into a floating viewport:
`points` are reprojected and clipped into paper coords there, so cloned
model-space triangles would hit-test at a model-scale offset. Extruded
entities stay selectable by their edges, which do get projected.
The wall loop runs on every hover that misses everything else, so it
rejects on the wire's AABB first — an extruded circle is ~128 triangles
and a drawing full of thickness would otherwise project every wall on
each mouse move.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:58:55 +03:00
|
|
|
|
pick_tris: Vec::new(),
|
|
|
|
|
|
pick_tris_low: Vec::new(),
|
2026-07-17 01:49:18 +03:00
|
|
|
|
dash_from_start: false,
|
2026-07-17 02:59:11 +03:00
|
|
|
|
dash_align_end: None,
|
refactor(text): per-entity SDF text — all text kinds, selection/hover highlight
Rearchitect SDF text from a document-wide collector to per-entity
production during tessellation, so each entity owns its glyph quads and
composite/nested text is covered for free (no re-explosion, no per-frame
document walk).
- WireModel gains `text_verts`: glyph quads ride on the wire, so they are
cached by the tess memo, cloned on hit, and transformed by the block
expand loop exactly like `points`.
- Text arm (tessellate.rs) builds the quads when SDF is on and suppresses
the strokes; render gathers text_verts from the viewport wire set
(`gather_text_verts`, cached on wire content id) — the old collector is
removed. Covers model, dimension, table, block-internal and paper-sheet
text uniformly.
- MLEADER text (lays out via layout_mtext, not the Text arm) gets its own
SDF branch driven by the per-run GlyphRun.
- Pick box comes from the rendered glyph quads (true text extent), not
entity_aabb which mis-places the box for MTEXT; composite paths no longer
clobber the empty text wire's tight AABB (dim pick box hugs the text).
- Selection / hover highlight via a text-highlight overlay (upload_text_
highlight, keyed on selection_generation) mirroring the selected-wire
xray overlay; base glyphs stay neutral so a deselect leaves no stale tint.
- Debug: env OCS_TEXT_BOX draws each run's glyph-bounds rectangle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:01:36 +03:00
|
|
|
|
text_verts: Vec::new(),
|
2026-04-03 09:29:11 +03:00
|
|
|
|
name: "dimaligned_preview".into(),
|
|
|
|
|
|
points: vec![[p1.x, p1.y, p1.z], [p2.x, p2.y, p2.z]],
|
2026-06-23 17:08:54 +03:00
|
|
|
|
points_low: Vec::new(),
|
2026-04-03 09:29:11 +03:00
|
|
|
|
color: WireModel::CYAN,
|
|
|
|
|
|
selected: false,
|
|
|
|
|
|
pattern_length: 0.0,
|
|
|
|
|
|
pattern: [0.0; 8],
|
|
|
|
|
|
line_weight_px: 1.0,
|
|
|
|
|
|
snap_pts: vec![],
|
|
|
|
|
|
tangent_geoms: vec![],
|
2026-04-06 23:19:08 +03:00
|
|
|
|
aci: 0,
|
2026-04-03 09:29:11 +03:00
|
|
|
|
key_vertices: vec![],
|
2026-04-26 12:21:51 +03:00
|
|
|
|
aabb: WireModel::UNBOUNDED_AABB,
|
2026-05-06 06:55:28 +03:00
|
|
|
|
plinegen: true,
|
2026-05-06 23:24:26 +03:00
|
|
|
|
fill_tris: vec![],
|
2026-06-23 18:03:40 +03:00
|
|
|
|
fill_tris_low: Vec::new(),
|
2026-04-03 09:29:11 +03:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
fn v3(p: DVec3) -> Vector3 {
|
|
|
|
|
|
Vector3::new(p.x, p.y, p.z)
|
2026-04-03 09:29:11 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-25 17:55:39 +03:00
|
|
|
|
/// Dimension-line endpoints: the baseline `p1`–`p2` shifted to pass through
|
|
|
|
|
|
/// the cursor's perpendicular projection. Uses the XY-plane perpendicular so
|
|
|
|
|
|
/// it matches the committed entity's renderer (and DIMLINEAR). The old
|
|
|
|
|
|
/// preview used an XZ-plane perpendicular, drawing the offset in the wrong
|
|
|
|
|
|
/// spatial direction. (#150)
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
fn dim_line_endpoints(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> (DVec3, DVec3) {
|
2026-06-25 17:55:39 +03:00
|
|
|
|
let axis = (p2 - p1).normalize_or_zero();
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
let perp = DVec3::new(-axis.y, axis.x, 0.0);
|
2026-06-25 17:55:39 +03:00
|
|
|
|
let offset = (dim_pt - p1).dot(perp);
|
|
|
|
|
|
(p1 + perp * offset, p2 + perp * offset)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
fn preview_aligned(p1: DVec3, p2: DVec3, dim_pt: DVec3) -> WireModel {
|
2026-06-25 17:55:39 +03:00
|
|
|
|
// Show ext lines + dim line.
|
|
|
|
|
|
let (d1, d2) = dim_line_endpoints(p1, p2, dim_pt);
|
fix(precision): keep typed coordinates exact in f64 (#311)
Typed values were quantized to the f32 grid before reaching the
entity (e.g. a length of 2000.8 committed as 2000.8020), worsening
with magnitude. The interaction point layer was all glam::Vec3 (f32).
Two-layer fix:
1. Coordinate backbone -> f64. last_point, last_cursor_world,
dyn_anchor, dyn_ref become DVec3; UcsXform transforms, parse_coord,
the ucs helper fns, dyn_resolve_point, the OTRACK typed-distance
paths, command-line coordinate entry and the coordinate readout all
compute in f64. Screen/GPU/alignment stays f32 (snap engine, render
geometry, projection, UCS-icon/viewcube drawing) with casts only at
those boundaries.
2. Per-command committed storage -> DVec3. on_point already received a
DVec3, but many command impls narrowed it back to f32 (let pt =
pt.as_vec3(); Vec<Vec3> fields) and re-widened at build, quantizing
the committed coordinate. Migrated PLINE, SPLINE, MLINE, LENGTHEN,
INSERT, 3D primitives, every dimension/leader/mleader, ray, revcloud,
wipeout, attdef, table, tolerance, array center, mview, plot_window,
plus the QDIM_PLACE handler and qdim_collect_points. Preview,
hit-test and rubber-band paths keep f32 at the boundary.
Hatch manual boundaries are left for a follow-up: HatchModel.boundary
is structurally Arc<Vec<[f32;2]>> and needs a model-level widen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:26:40 +03:00
|
|
|
|
// Preview WireModel points are screen/GPU-side: downcast to f32.
|
|
|
|
|
|
let p1 = p1.as_vec3();
|
|
|
|
|
|
let p2 = p2.as_vec3();
|
|
|
|
|
|
let d1 = d1.as_vec3();
|
|
|
|
|
|
let d2 = d2.as_vec3();
|
2026-04-03 09:29:11 +03:00
|
|
|
|
WireModel {
|
2026-07-20 16:36:06 +03:00
|
|
|
|
taper_widths: Vec::new(),
|
2026-07-20 14:50:27 +03:00
|
|
|
|
world_width: 0.0,
|
2026-07-18 15:15:24 +03:00
|
|
|
|
fill_is_3d: false,
|
fix(pick): hit-test lineweight width and thickness walls
Selection tested a flat 8 px radius around each wire's centreline and
nothing else, so two things the user can see were not pickable.
A wire renders as a band `line_weight_px` wide, so pick now widens to that
rendered half-width via `pick_tolerance_px`, mirroring the wire shader's
`select(0.5, half_width, lwdisplay_enable)`. Behaviour is unchanged for
every standard weight (the widest, 2.11 mm, renders 7.97 px half-width —
just under the 8 px threshold); this keeps the two sides from drifting
apart if the display boost in `lineweight_to_px` ever changes.
Entities extruded by a DXF thickness draw their wall as four edges with
nothing in between, so the interior was a hole the cursor fell through.
WireModel gains `pick_tris`: triangles hit-testing treats as solid and the
renderer never uploads. Kept apart from `fill_tris` because that channel
reaches the GPU, and a wall that rendered shaded would change how every
thickness drawing looks. Ranked below `fill_tris` — those are drawn, these
are not, so where they overlap the drawn face is what the user means.
Walls are dropped when a wire is projected into a floating viewport:
`points` are reprojected and clipped into paper coords there, so cloned
model-space triangles would hit-test at a model-scale offset. Extruded
entities stay selectable by their edges, which do get projected.
The wall loop runs on every hover that misses everything else, so it
rejects on the wire's AABB first — an extruded circle is ~128 triangles
and a drawing full of thickness would otherwise project every wall on
each mouse move.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:58:55 +03:00
|
|
|
|
pick_tris: Vec::new(),
|
|
|
|
|
|
pick_tris_low: Vec::new(),
|
2026-07-17 01:49:18 +03:00
|
|
|
|
dash_from_start: false,
|
2026-07-17 02:59:11 +03:00
|
|
|
|
dash_align_end: None,
|
refactor(text): per-entity SDF text — all text kinds, selection/hover highlight
Rearchitect SDF text from a document-wide collector to per-entity
production during tessellation, so each entity owns its glyph quads and
composite/nested text is covered for free (no re-explosion, no per-frame
document walk).
- WireModel gains `text_verts`: glyph quads ride on the wire, so they are
cached by the tess memo, cloned on hit, and transformed by the block
expand loop exactly like `points`.
- Text arm (tessellate.rs) builds the quads when SDF is on and suppresses
the strokes; render gathers text_verts from the viewport wire set
(`gather_text_verts`, cached on wire content id) — the old collector is
removed. Covers model, dimension, table, block-internal and paper-sheet
text uniformly.
- MLEADER text (lays out via layout_mtext, not the Text arm) gets its own
SDF branch driven by the per-run GlyphRun.
- Pick box comes from the rendered glyph quads (true text extent), not
entity_aabb which mis-places the box for MTEXT; composite paths no longer
clobber the empty text wire's tight AABB (dim pick box hugs the text).
- Selection / hover highlight via a text-highlight overlay (upload_text_
highlight, keyed on selection_generation) mirroring the selected-wire
xray overlay; base glyphs stay neutral so a deselect leaves no stale tint.
- Debug: env OCS_TEXT_BOX draws each run's glyph-bounds rectangle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:01:36 +03:00
|
|
|
|
text_verts: Vec::new(),
|
2026-04-03 09:29:11 +03:00
|
|
|
|
name: "dimaligned_preview".into(),
|
|
|
|
|
|
points: vec![
|
2026-05-12 10:36:15 +03:00
|
|
|
|
[p1.x, p1.y, p1.z],
|
|
|
|
|
|
[d1.x, d1.y, d1.z],
|
2026-04-03 09:29:11 +03:00
|
|
|
|
[f32::NAN, 0.0, 0.0],
|
2026-05-12 10:36:15 +03:00
|
|
|
|
[p2.x, p2.y, p2.z],
|
|
|
|
|
|
[d2.x, d2.y, d2.z],
|
2026-04-03 09:29:11 +03:00
|
|
|
|
[f32::NAN, 0.0, 0.0],
|
2026-05-12 10:36:15 +03:00
|
|
|
|
[d1.x, d1.y, d1.z],
|
|
|
|
|
|
[d2.x, d2.y, d2.z],
|
2026-04-03 09:29:11 +03:00
|
|
|
|
],
|
2026-06-23 17:08:54 +03:00
|
|
|
|
points_low: Vec::new(),
|
2026-04-03 09:29:11 +03:00
|
|
|
|
color: WireModel::CYAN,
|
|
|
|
|
|
selected: false,
|
|
|
|
|
|
pattern_length: 0.0,
|
|
|
|
|
|
pattern: [0.0; 8],
|
|
|
|
|
|
line_weight_px: 1.0,
|
|
|
|
|
|
snap_pts: vec![],
|
|
|
|
|
|
tangent_geoms: vec![],
|
2026-04-06 23:19:08 +03:00
|
|
|
|
aci: 0,
|
2026-05-12 10:36:15 +03:00
|
|
|
|
key_vertices: vec![],
|
|
|
|
|
|
aabb: WireModel::UNBOUNDED_AABB,
|
|
|
|
|
|
plinegen: true,
|
|
|
|
|
|
fill_tris: vec![],
|
2026-06-23 18:03:40 +03:00
|
|
|
|
fill_tris_low: Vec::new(),
|
2026-04-03 09:29:11 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-26 22:45:54 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── Autocomplete registry ─────────────────────────────────
|
feat(alias): centralize command aliases in user-editable ocad.pgp (#286/#288)
Command aliases (L→LINE, CC→COPYCLIP) were scattered across dispatch match
arms and CommandRegistration name arrays. Move them all into a single
user-editable file:
- assets/ocad.pgp: shipped default alias table (ALIAS,*COMMAND format),
embedded and copied to config/ocad.pgp on first launch; only that user
copy is read after. AA→AREA default closes #286.
- resolve_alias() rewrites the leading command token at the top of
dispatch_command_inner, so aliases resolve for every path (families,
plugins, Repeat menu). Args after the first space are untouched.
- Autocomplete hides alias keys and, when the whole input is an alias,
surfaces its target command as the top (highlighted) suggestion so the
highlight matches what Enter runs (AA→AREA, L→LINE).
- ALIASEDIT opens a new editor modal (add/edit/delete rows) with an Apply
button; Apply persists to ocad.pgp, closing discards unapplied edits.
- Strip alias tokens from all 8 dispatch match-arm files and 71 module
CommandRegistration arrays, keeping canonical/synonym/distinct-command
names. ocad.pgp is now the sole source: deleting or remapping an alias
there takes effect. CUI stays on the keyboard-shortcut panel.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 12:39:22 +03:00
|
|
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["DIMALIGNED"] }); // AlignedDimensionCommand
|