forked from 1b-agent/opencadstudio-upstream
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>
178 lines
4.9 KiB
Rust
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",
|
|
]
|
|
});
|