forked from 1b-agent/opencadstudio-upstream
Add persistent sketch-constraint system (ocs_gcs port) and named-parameters handoff docs
Ports FreeCAD's planegcs 2D geometric constraint solver to Rust as a new crates/ocs_gcs workspace member, and wires it into the document/scene model as a persistent SketchConstraintSet: Coincident, Horizontal/Vertical, Parallel/Perpendicular, Equal, Tangent, Distance, Angle and Radius constraints that re-solve live (including mid-drag, not just on release), render glyphs and a DOF badge, flag conflicts with a one-click resolver pill, and round-trip through save/load via an XRecord blob. Also includes docs/command_reference.md (a statically generated reference of every registered command and its prompt sequence) and docs/named_parameters_design.md + docs/backlog.md, which hand off the next queued feature (a named-parameter/expression table) and consolidate every deliberate scope-down and open gap found along the way, so a fresh session has a complete starting point. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a39c7b8f71
commit
63a74b19a9
63 files changed
+12193
-49
No files matched your search
@@ -125,6 +125,16 @@ impl StatusBar {
|
||||
// Which pills the user has chosen to show on the bar.
|
||||
config: &'a StatusBarConfig,
|
||||
menu_data: StatusMenuData<'a>,
|
||||
// Remaining degrees of freedom for the current sketch scope's
|
||||
// persistent constraints (design doc §6.3) — `None` when the scope
|
||||
// has no `SketchConstraintSet` yet (nothing constrained), so the
|
||||
// badge stays invisible until it's actually relevant.
|
||||
sketch_dof: Option<usize>,
|
||||
// Number of redundant/conflicting constraints `solve_scope` flagged
|
||||
// in the current sketch scope (design doc §6.4, stage 11) — 0 hides
|
||||
// the pill entirely, so an ordinarily/fully-constrained drawing sees
|
||||
// no new clutter.
|
||||
sketch_conflicts: usize,
|
||||
) -> Element<'a, Message> {
|
||||
let StatusMenuData {
|
||||
layout_names,
|
||||
@@ -243,6 +253,44 @@ impl StatusBar {
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
// Not a `StatusPill` (so not user-hideable yet): invisible until the
|
||||
// current scope actually has a SketchConstraintSet, so a drawing
|
||||
// that never uses parametric constraints sees no new clutter.
|
||||
if let Some(dof) = sketch_dof {
|
||||
let pill = if dof == 0 {
|
||||
success_pill(crate::tf!("DOF: {dof}").into_owned())
|
||||
} else {
|
||||
status_pill(crate::tf!("DOF: {dof}").into_owned())
|
||||
};
|
||||
pills.push(
|
||||
tip(
|
||||
pill,
|
||||
if dof == 0 {
|
||||
t!("Fully constrained — no remaining degrees of freedom")
|
||||
} else {
|
||||
t!("Remaining degrees of freedom in the current sketch's persistent constraints")
|
||||
},
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
// Design doc §6.4 (stage 11): a bounded v1 of the guided conflict
|
||||
// resolver — click removes one flagged constraint at a time. See
|
||||
// `OpenCADStudio::resolve_one_sketch_conflict`'s doc comment for the
|
||||
// full scope-down rationale versus the design doc's named-candidate,
|
||||
// cyclable-preview panel.
|
||||
if sketch_conflicts > 0 {
|
||||
pills.push(
|
||||
tip(
|
||||
action_pill(
|
||||
crate::tf!("⚠ {sketch_conflicts} conflicting").into_owned(),
|
||||
Message::ResolveOneSketchConflict,
|
||||
),
|
||||
t!("One or more constraints in this sketch conflict or are redundant\nClick to remove one and re-solve"),
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
if vis(StatusPill::Ortho) {
|
||||
pills.push(
|
||||
tip(
|
||||
@@ -1034,6 +1082,25 @@ fn status_pill(label: impl Into<String>) -> Element<'static, Message> {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Like [`status_pill`], but with the theme's `success` accent — design doc
|
||||
/// §6.3's "simple color-coded constraint state" cue: used for the DOF badge
|
||||
/// when a sketch scope has reached zero remaining degrees of freedom, so
|
||||
/// "fully constrained" is visible at a glance without opening anything.
|
||||
fn success_pill(label: impl Into<String>) -> Element<'static, Message> {
|
||||
container(text(label.into()).size(12))
|
||||
.style(|theme: &Theme| {
|
||||
let palette = theme.palette();
|
||||
container::Style {
|
||||
background: Some(Background::Color(palette.success.weak.color)),
|
||||
text_color: Some(palette.success.weak.text),
|
||||
border: Border { color: palette.success.base.color, width: 1.0, radius: 4.0.into() },
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.padding([4, 8])
|
||||
.into()
|
||||
}
|
||||
|
||||
// ── Scale popup button ────────────────────────────────────────────────────
|
||||
|
||||
/// Shared visual root for labelled status-bar menus (units, scale, …).
|
||||
|
||||
Reference in new issue
Block a user