forked from 1b-agent/opencadstudio-upstream
perf(glyphs): memoize constraint-glyph placements behind constraints_epoch
Placements (entity lookups, intersections, String labels, projections) recomputed per view() and per mouse-move hit-test, with overlay re-clones and 2-3x offset recomputes. New constraints_epoch bumped on every set mutation/visibility/undo/DWG-load (plus new set_constraint_enabled API); single-slot Arc<[GlyphEntry]> memo on an 11-field key (hover/selection excluded); overlay de-cloned/de-duped to the single geometry source; hit paths reuse the cache. Tests: - cached_glyph_placements_hit_returns_same_arc: same-key Arc identity - cached_glyph_placements_invalidated_by_metadata_edit: edit + selection change yield new Arc - glyph_hit_test_entries_matches_precomputed_boxes: shared hit-test helper Bench (cargo bench glyph, 60 constraints): 8.18us -> 0.05-0.15us (~55x). A/B reference deleted.
This commit is contained in:
1 parent
2d49204c50
commit
4432f633e7
12 files changed
+767
-239
No files matched your search
@@ -1409,6 +1409,7 @@ impl OpenCADStudio {
|
||||
dimension.into_iter().collect(),
|
||||
parameter.into_iter().collect(),
|
||||
);
|
||||
self.tabs[i].scene.bump_constraints_epoch();
|
||||
if self.tabs[i].scene.selected_constraint == Some(id) {
|
||||
self.tabs[i].scene.selected_constraint = None;
|
||||
}
|
||||
@@ -1720,6 +1721,9 @@ impl OpenCADStudio {
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.record_undo_parametric_constraints_before(scope, before);
|
||||
// A parameter rename rewrites the `Named` driving references
|
||||
// pointing at it — the glyph labels change with them.
|
||||
let mut renamed = false;
|
||||
for constraint in
|
||||
&mut self.tabs[i].scene.parametric_constraints[set_index].constraints
|
||||
{
|
||||
@@ -1728,9 +1732,13 @@ impl OpenCADStudio {
|
||||
{
|
||||
if name == ¤t.name {
|
||||
*name = typed.clone();
|
||||
renamed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if renamed {
|
||||
self.tabs[i].scene.bump_constraints_epoch();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.resolve_named_parameter_edit(i, &resolve_name);
|
||||
@@ -1866,6 +1874,10 @@ impl OpenCADStudio {
|
||||
if let Some(constraint) = set.constraints.iter_mut().find(|c| c.id == id) {
|
||||
constraint.enabled = !reference;
|
||||
}
|
||||
// Toggling `enabled` changes the glyph placement set (and the
|
||||
// dynamic pills), so the memoised placements must miss next
|
||||
// frame — same guarantee `set_constraint_enabled` gives.
|
||||
self.tabs[i].scene.bump_constraints_epoch();
|
||||
self.tabs[i].scene.refresh_dynamic_dimension_texts();
|
||||
self.tabs[i].scene.sync_native_parametric_graph();
|
||||
self.tabs[i].dirty = true;
|
||||
|
||||
@@ -1159,6 +1159,7 @@ impl OpenCADStudio {
|
||||
set.remove(*id);
|
||||
}
|
||||
self.purge_dimensional_extras(i, dimensions, parameters);
|
||||
self.tabs[i].scene.bump_constraints_epoch();
|
||||
let changes: Vec<_> = handles
|
||||
.iter()
|
||||
.copied()
|
||||
|
||||
@@ -978,6 +978,9 @@ impl OpenCADStudio {
|
||||
}
|
||||
let changes = self.tabs[i].scene.apply_entity_delta(&d.entities, undo);
|
||||
let scene = &mut self.tabs[i].scene;
|
||||
if !d.parametric_constraints.is_empty() {
|
||||
scene.bump_constraints_epoch();
|
||||
}
|
||||
for entry in &d.parametric_constraints {
|
||||
let value = if undo { &entry.before } else { &entry.after };
|
||||
*scene.parametric_constraint_set_mut(entry.scope) = value.clone();
|
||||
|
||||
+18
-30
@@ -863,39 +863,26 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
.map(|constraint| constraint.kind.glyph_symbol().to_string())
|
||||
})
|
||||
};
|
||||
let constraint_glyphs: Vec<(
|
||||
iced::Point,
|
||||
[f32; 2],
|
||||
String,
|
||||
bool,
|
||||
bool,
|
||||
Vec<iced::Point>,
|
||||
)> = if is_paper {
|
||||
Vec::new()
|
||||
let constraint_glyphs: std::sync::Arc<
|
||||
[crate::scene::parametric_constraints::GlyphEntry],
|
||||
> = if is_paper {
|
||||
std::sync::Arc::from([])
|
||||
} else {
|
||||
let scope = tab.current_parametric_scope();
|
||||
tab.scene
|
||||
.constraint_glyph_placements_screen(
|
||||
scope,
|
||||
sel_ref.vp_size,
|
||||
self.show_constraint_values,
|
||||
self.constraint_bar_display,
|
||||
self.constraint_bar_mode,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|(id, point, direction, label, is_conflicting, hover_points)| {
|
||||
let selected = tab.scene.selected_constraint == Some(id);
|
||||
(
|
||||
point,
|
||||
direction,
|
||||
label,
|
||||
is_conflicting,
|
||||
selected,
|
||||
hover_points,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
tab.scene.cached_glyph_placements(
|
||||
scope,
|
||||
sel_ref.vp_size,
|
||||
self.show_constraint_values,
|
||||
self.constraint_bar_display,
|
||||
self.constraint_bar_mode,
|
||||
)
|
||||
};
|
||||
// Selection stays OUTSIDE the cache (applied post-hoc): a selection
|
||||
// change must not invalidate the placement memo.
|
||||
let constraint_glyph_selected: std::sync::Arc<[bool]> = constraint_glyphs
|
||||
.iter()
|
||||
.map(|entry| tab.scene.selected_constraint == Some(entry.id))
|
||||
.collect();
|
||||
crate::ui::overlay::selection_overlay(
|
||||
std::sync::Arc::clone(&tab.scene.selection),
|
||||
snap_info,
|
||||
@@ -939,6 +926,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
grip_hover: self.model_space.grip_hover,
|
||||
},
|
||||
constraint_glyphs,
|
||||
constraint_glyph_selected,
|
||||
self.constraint_glyph_tooltip
|
||||
.map(|kind| crate::t!(kind.label()).into_owned()),
|
||||
constraint_cursor_badge,
|
||||
|
||||
Reference in new issue
Block a user