Harden parametric sketch constraints

This commit is contained in:
Hakan Seven committed 2026-09-11 09:45:57 +03:00
1 parent 41c07e9858
commit 9b58ca8a93
101 files changed
+3128 -13767

No files matched your search

+13 -43
View File
@@ -661,7 +661,6 @@ pub(super) enum HistorySnapshot {
// which one it actually holds.
Delta(Box<DeltaSnapshot>),
ObjectVisibility(ObjectVisibilitySnapshot),
SketchConstraints(SketchConstraintsSnapshot),
}
impl HistorySnapshot {
@@ -669,7 +668,6 @@ impl HistorySnapshot {
match self {
HistorySnapshot::Delta(d) => &d.label,
HistorySnapshot::ObjectVisibility(v) => &v.label,
HistorySnapshot::SketchConstraints(s) => &s.label,
}
}
@@ -699,7 +697,12 @@ impl HistorySnapshot {
.iter()
.map(|entry| entry.before.constraints.len().saturating_add(entry.after.constraints.len()))
.sum::<usize>()
.saturating_mul(96), // matches HistorySnapshot::SketchConstraints's own rough per-constraint estimate
.saturating_mul(96),
)
.saturating_add(
d.named_parameters
.as_ref()
.map_or(0, |(before, after)| before.len().saturating_add(after.len()).saturating_mul(128)),
)
.saturating_add(d.label.len()),
HistorySnapshot::ObjectVisibility(v) => v
@@ -723,40 +726,10 @@ impl HistorySnapshot {
.saturating_add(v.selected_after.len())
.saturating_mul(16)
.saturating_add(v.label.len()),
HistorySnapshot::SketchConstraints(s) => s
.before
.as_ref()
.map_or(0, |set| set.constraints.len())
.saturating_add(s.after.as_ref().map_or(0, |set| set.constraints.len()))
.saturating_mul(96) // rough per-constraint size (a handful of refs + an id/kind/f64)
.saturating_add(s.label.len()),
}
}
}
/// Undo/redo image for one persistent-constraint edit (design doc §5.1/§9):
/// a `SketchConstraintSet` add/remove, captured as a whole-set before/after
/// pair rather than a per-constraint diff — sketches are small, so cloning
/// the whole set is cheap, and it sidesteps needing a separate "undo one
/// constraint add" vs. "undo one constraint remove" representation. Kept as
/// its own `HistorySnapshot` variant (not folded into `DeltaSnapshot`) since
/// `SketchConstraintSet` lives on `Scene`, not in the entity/object store
/// `DeltaSnapshot` already covers — see the design doc's §5.1 discussion of
/// why this needs its own path. A geometry-changing constraint add (the
/// common case) pushes this *alongside* its own `DeltaSnapshot` entry rather
/// than merged into one atomic step — two adjacent undo presses instead of
/// one, a deliberate scope-down from the design doc's recommended "live
/// XRecord" approach (§5.1(b)), which needs stage 4 (save/load) wired up
/// first; this variant needs nothing beyond what already exists.
#[derive(Clone)]
pub(super) struct SketchConstraintsSnapshot {
pub(super) scope: crate::scene::sketch_constraints::SketchScope,
/// `None` when the scope had no constraint set at all yet.
pub(super) before: Option<crate::scene::sketch_constraints::SketchConstraintSet>,
pub(super) after: Option<crate::scene::sketch_constraints::SketchConstraintSet>,
pub(super) label: String,
}
/// Symmetric undo/redo image for session-only object visibility. It contains
/// no document entity data and therefore can never make isolation serializable.
#[derive(Clone)]
@@ -793,6 +766,11 @@ pub(super) struct DeltaSnapshot {
/// `document.objects`, so it needs its own channel here rather than
/// riding along with `entities`/`structure`. Almost always empty.
pub(super) sketch_constraints: Vec<SketchConstraintsEntryDelta>,
/// Drawing-wide parameter table changed by this transaction.
pub(super) named_parameters: Option<(
crate::scene::named_parameters::ParameterTable,
crate::scene::named_parameters::ParameterTable,
)>,
pub(super) label: String,
}
@@ -853,16 +831,8 @@ pub(super) struct ObjectEntryDelta {
pub(super) after: Option<acadrust::objects::ObjectType>,
}
/// One sketch-constraint scope's before/after image within an entity
/// `DeltaSnapshot` — e.g. ERASE removing an entity's constraints along with
/// it (`Scene::refresh_sketch_constraints`'s deletion policy). Distinct from
/// [`SketchConstraintsSnapshot`]: that type is its own separate
/// `HistorySnapshot` entry for a dedicated constraint add/remove command
/// (still a deliberate two-step undo, design doc's own scope-down); this one
/// rides inside the *same* delta as the entity change that caused it, so one
/// undo restores both together. `before`/`after` are always `Some` scope
/// state (never absent) — a scope's `Vec` entry, once created, is never
/// removed, so there is no "scope didn't exist" case to represent here.
/// One sketch-constraint scope's before/after image within an entity delta.
/// This keeps constraint cleanup atomic with edits such as entity erasure.
#[derive(Clone)]
pub(super) struct SketchConstraintsEntryDelta {
pub(super) scope: crate::scene::sketch_constraints::SketchScope,