forked from 1b-agent/opencadstudio-upstream
value toggle, and redesigned constraint-ribbon icons Properties panel: - New "Parameters" section (shown with no selection) listing every named parameter with inline name/formula editing, add, and delete, backed by new PropValue::ParamRow/ParamAddRow and command_driver handlers (resolve_named_parameter_edit, on_prop_param_commit/_delete/_add_new). A fresh parameter's formula now defaults to "1", not "0" — a 0-length seed value is a genuine solver singularity for a Distance constraint driven by that parameter, with no defined direction to grow back out of. - New "Constraints" section (shown for a single selected entity) listing every constraint touching it as a clickable PropValue::EntityLink that selects the linked entities in the viewport, danger-tinted when the constraint conflicts. Constraint pills: - New Options > General toggle, "Show values and parameter names on constraint markers" (on by default, persisted). Off, every pill shows just its bare glyph instead of glyph+driven-value/parameter-name — the glyph alone is enough to see a constraint is present, without the value text covering nearby geometry on a dense sketch. Constraint-ribbon icons: - Replaced all 18 unicode/letter glyph icons (including the plain "F", "L", "M", "S" letters) with proper SVGs under assets/icons/constrain/, matching the Modify section's two-color style (#B4B6B9 white / #6DB7ED blue, consistent stroke width). Tangent reuses the Draw section's white-arc-plus-blue-dots motif. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
77 lines
2.4 KiB
Rust
77 lines
2.4 KiB
Rust
//! CCONSTRAINT — the manual Coincident UI (design doc §6.1's open item):
|
|
//! unlike the rest of this module's plain select-and-click constraints,
|
|
//! Coincident addresses a *point* on an entity (an endpoint, a circle/arc
|
|
//! center), not the whole entity, so it needs two point picks instead of a
|
|
//! selection.
|
|
//!
|
|
//! A `CadCommand` has no document access (see `value.rs`'s module doc
|
|
//! comment for the same constraint on `DCONSTRAINT`/`ACONSTRAINT`), so this
|
|
//! command only accumulates the two raw points `on_point` receives and hands
|
|
//! them back as `CmdResult::AddCoincidentConstraint` — the host resolves
|
|
//! each point to a real `SketchRef` (`sketch_constraints::nearest_sketch_point`)
|
|
//! and adds the constraint, the same split `ReassociateCenterMark` already
|
|
//! uses for a similar reason.
|
|
|
|
use glam::DVec3;
|
|
|
|
use crate::command::{CadCommand, CmdResult};
|
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
|
|
|
pub mod coincident_tool {
|
|
use super::*;
|
|
pub fn tool() -> ToolDef {
|
|
ToolDef {
|
|
id: "CCONSTRAINT",
|
|
label: "Coincident",
|
|
icon: IconKind::Svg(include_bytes!("../../../../assets/icons/constrain/coincident.svg")),
|
|
event: ModuleEvent::Command("CCONSTRAINT".to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct CoincidentConstraintCommand {
|
|
first: Option<DVec3>,
|
|
}
|
|
|
|
impl CoincidentConstraintCommand {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
}
|
|
|
|
impl CadCommand for CoincidentConstraintCommand {
|
|
fn name(&self) -> &'static str {
|
|
"CCONSTRAINT"
|
|
}
|
|
|
|
fn prompt(&self) -> String {
|
|
if self.first.is_none() {
|
|
"COINCIDENT Specify first point:".to_string()
|
|
} else {
|
|
"COINCIDENT Specify second point:".to_string()
|
|
}
|
|
}
|
|
|
|
fn on_point(&mut self, pt: DVec3) -> CmdResult {
|
|
match self.first {
|
|
None => {
|
|
self.first = Some(pt);
|
|
CmdResult::NeedPoint
|
|
}
|
|
Some(first) => CmdResult::AddCoincidentConstraint { point_a: first, point_b: pt, label: "Coincident constraint" },
|
|
}
|
|
}
|
|
|
|
fn on_enter(&mut self) -> CmdResult {
|
|
CmdResult::Cancel
|
|
}
|
|
|
|
fn on_escape(&mut self) -> CmdResult {
|
|
CmdResult::Cancel
|
|
}
|
|
}
|
|
|
|
// ── Autocomplete registry ─────────────────────────────────
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["CCONSTRAINT"] });
|