Files
OneCAD-Draft/src/modules/parametric/tools.rs
T
ramox81andClaude Fable 5.1 f998b59193 Match Fix geometric constraint behavior
1) FXCONSTRAINT (and the new GCFIX name) prompts "Select point or [Object]
   <Object>:" — a pick fixes that constraint point; Enter or O asks for one
   line, polyline segment, circle, arc, ellipse or spline; misses and
   unsupported objects report the reference messages and re-prompt.
2) Point, block, text, MText, attribute and table insertion points are
   addressable constraint points.
3) Re-applying Fixed to the same point or object reports that the constraint
   already exists instead of adding a duplicate.
4) A persistent Fixed holds its pre-edit geometry through MOVE, ROTATE,
   SCALE, STRETCH, grip and Properties edits: fixed points stay, free points
   of a partly fixed entity follow the edit, and size retention skips fixed
   entities.
5) Object mode on a polyline fixes the picked segment (natively persisted)
   instead of the whole polyline; arc segments pin endpoints, center and
   radius.
6) Ribbon label "Fix" with a padlock icon.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 15:38:33 +03:00

178 lines
4.9 KiB
Rust

//! Ribbon button definitions for the Constraints group.
use crate::modules::{IconKind, ModuleEvent, ToolDef};
pub mod horizontal {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "GCHORIZONTAL",
label: "Horizontal",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/horizontal.svg"
)),
event: ModuleEvent::Command("GCHORIZONTAL".to_string()),
}
}
}
pub mod vertical {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "VCONSTRAINT",
label: "Vertical",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/vertical.svg"
)),
event: ModuleEvent::Command("VCONSTRAINT".to_string()),
}
}
}
pub mod parallel {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "PCONSTRAINT",
label: "Parallel",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/parallel.svg"
)),
event: ModuleEvent::Command("PCONSTRAINT".to_string()),
}
}
}
pub mod perpendicular {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "QCONSTRAINT",
label: "Perpendicular",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/perpendicular.svg"
)),
event: ModuleEvent::Command("GCPERPENDICULAR".to_string()),
}
}
}
pub mod equal {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "ECONSTRAINT",
label: "Equal",
icon: IconKind::Svg(include_bytes!("../../../assets/icons/constrain/equal.svg")),
event: ModuleEvent::Command("ECONSTRAINT".to_string()),
}
}
}
pub mod tangent {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "TCONSTRAINT",
label: "Tangent",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/tangent.svg"
)),
event: ModuleEvent::Command("TCONSTRAINT".to_string()),
}
}
}
pub mod concentric {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "GCCONCENTRIC",
label: "Concentric",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/concentric.svg"
)),
event: ModuleEvent::Command("GCCONCENTRIC".to_string()),
}
}
}
/// A line perpendicular to a circle/arc's tangent at their point of
/// contact — for the Line/Circle-only entity model this is equivalent to
/// "the line passes through the circle's center" (a circle's radius is
/// always normal to its own tangent), so it's built from the same
/// `PointOnLine` primitive `PointOnCurve` already uses for a point-on-line
/// case (`parametric_solve.rs`). Distinct from `Perpendicular`, which only
/// covers line-to-line.
pub mod normal {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "NRCONSTRAINT",
label: "Normal",
icon: IconKind::Svg(include_bytes!("../../../assets/icons/constrain/normal.svg")),
event: ModuleEvent::Command("NRCONSTRAINT".to_string()),
}
}
}
pub mod colinear {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "LCONSTRAINT",
label: "Colinear",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/colinear.svg"
)),
event: ModuleEvent::Command("LCONSTRAINT".to_string()),
}
}
}
pub mod fixed {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "FXCONSTRAINT",
label: "Fix",
icon: IconKind::Svg(include_bytes!("../../../assets/icons/constrain/fixed.svg")),
event: ModuleEvent::Command("FXCONSTRAINT".to_string()),
}
}
}
pub mod symmetric {
use super::*;
pub fn tool() -> ToolDef {
ToolDef {
id: "SYCONSTRAINT",
label: "Symmetric",
icon: IconKind::Svg(include_bytes!(
"../../../assets/icons/constrain/symmetric.svg"
)),
event: ModuleEvent::Command("SYCONSTRAINT".to_string()),
}
}
}
// ── Autocomplete registry ─────────────────────────────────
inventory::submit!(crate::command::CommandRegistration {
names: &[
"GCHORIZONTAL",
"VCONSTRAINT",
"PCONSTRAINT",
"QCONSTRAINT",
"GCPERPENDICULAR",
"ECONSTRAINT",
"TCONSTRAINT",
"GCCONCENTRIC",
"NRCONSTRAINT",
"LCONSTRAINT",
"FXCONSTRAINT",
"GCFIX",
"SYCONSTRAINT",
]
});