forked from 1b-agent/opencadstudio-upstream
Merge pull request #1747 from schoeller/reference_only_entities
Reference-only entities (plugin API v9): a scene-scoped, in-memory designation for plugin-owned display geometry, plus HostNotification dispatch to native plugins so they can re-mark on DocumentOpened. Resolves the new DeltaSnapshot site in block_editor.rs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
68330ce39e
40 files changed
+1977
-85
No files matched your search
+84
-5
@@ -1,8 +1,8 @@
|
||||
use super::{
|
||||
document::{
|
||||
DeltaSnapshot, HistorySnapshot, ObjectEntryDelta, ObjectVisibilitySnapshot,
|
||||
ParametricConstraintsEntryDelta, PendingHistorySnapshot, StructureSnapshot,
|
||||
TableEntryDelta,
|
||||
ParametricConstraintsEntryDelta, PendingHistorySnapshot, ReferenceDesignationDelta,
|
||||
StructureSnapshot, TableEntryDelta,
|
||||
},
|
||||
OpenCADStudio,
|
||||
};
|
||||
@@ -226,6 +226,7 @@ impl OpenCADStudio {
|
||||
active_layer: None,
|
||||
structure: (!objects.is_empty()).then_some(StructureSnapshot::Objects(objects)),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations: Vec::new(),
|
||||
named_parameters: None,
|
||||
label: label.into(),
|
||||
};
|
||||
@@ -328,8 +329,26 @@ impl OpenCADStudio {
|
||||
let selected_after: Vec<Handle> = self.tabs[i].scene.selected.iter().copied().collect();
|
||||
let dirty_after = self.tabs[i].dirty;
|
||||
let active_layer_after = self.tabs[i].active_layer.clone();
|
||||
// The designation set is scene state mutated through the plugin API:
|
||||
// a scope that (un)marked entities carries the first-touch before
|
||||
// values here; the after value is whatever the set holds now, and
|
||||
// only untouched-value entries drop out (an idempotent re-mark never
|
||||
// got recorded in the first place).
|
||||
let reference_designations: Vec<_> = pending
|
||||
.reference_designations_before
|
||||
.into_iter()
|
||||
.filter_map(|(handle, before)| {
|
||||
let after = self.tabs[i].scene.reference_only.is_marked(handle);
|
||||
(before != after).then_some(ReferenceDesignationDelta {
|
||||
handle,
|
||||
before,
|
||||
after,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
if !pending.keep_empty
|
||||
&& entities.is_empty()
|
||||
&& reference_designations.is_empty()
|
||||
&& !structure_changed
|
||||
&& pending.selected_before == selected_after
|
||||
&& pending.dirty_before == dirty_after
|
||||
@@ -350,6 +369,7 @@ impl OpenCADStudio {
|
||||
structure: structure_changed
|
||||
.then_some(StructureSnapshot::Full(pending.structure_before)),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations,
|
||||
named_parameters: None,
|
||||
label: pending.label,
|
||||
};
|
||||
@@ -390,10 +410,33 @@ impl OpenCADStudio {
|
||||
dirty_before,
|
||||
structure_before,
|
||||
recorder,
|
||||
reference_designations_before: Vec::new(),
|
||||
keep_empty: false,
|
||||
});
|
||||
}
|
||||
|
||||
/// Record the pre-mutation value of a reference-only designation (API v9)
|
||||
/// into the open plugin pending scope — first touch wins. No-op when no
|
||||
/// scope is open: like the XRecord methods, a designation change must open
|
||||
/// its own scope before mutating, so by the time this runs a scope either
|
||||
/// covers it or the caller owns one.
|
||||
pub(super) fn record_reference_designation_before_pending(
|
||||
&mut self,
|
||||
i: usize,
|
||||
handle: Handle,
|
||||
before: bool,
|
||||
) {
|
||||
if let Some(pending) = self.tabs[i].history.pending.as_mut() {
|
||||
if !pending
|
||||
.reference_designations_before
|
||||
.iter()
|
||||
.any(|(recorded, _)| *recorded == handle)
|
||||
{
|
||||
pending.reference_designations_before.push((handle, before));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Self::push_undo_snapshot`] for a command that is an undo step even
|
||||
/// when it changes nothing (UNDO and U then name it and undo nothing).
|
||||
pub(super) fn push_undo_mark(&mut self, i: usize, label: impl Into<String>) {
|
||||
@@ -481,6 +524,7 @@ impl OpenCADStudio {
|
||||
active_layer: None,
|
||||
structure: Some(StructureSnapshot::Layers(entries)),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations: Vec::new(),
|
||||
named_parameters: None,
|
||||
label: pending.label,
|
||||
};
|
||||
@@ -538,6 +582,7 @@ impl OpenCADStudio {
|
||||
active_layer: None,
|
||||
structure: Some(StructureSnapshot::TextStyles(entries)),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations: Vec::new(),
|
||||
named_parameters: None,
|
||||
label: pending.label,
|
||||
};
|
||||
@@ -595,6 +640,7 @@ impl OpenCADStudio {
|
||||
active_layer: None,
|
||||
structure: Some(StructureSnapshot::DimStyles(entries)),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations: Vec::new(),
|
||||
named_parameters: None,
|
||||
label: pending.label,
|
||||
};
|
||||
@@ -660,6 +706,7 @@ impl OpenCADStudio {
|
||||
active_layer: None,
|
||||
structure: Some(StructureSnapshot::Objects(entries)),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations: Vec::new(),
|
||||
named_parameters: None,
|
||||
label: pending.label,
|
||||
};
|
||||
@@ -695,6 +742,7 @@ impl OpenCADStudio {
|
||||
object_handles,
|
||||
}),
|
||||
parametric_constraints: Vec::new(),
|
||||
reference_designations: Vec::new(),
|
||||
named_parameters: None,
|
||||
label: "STYLE".to_string(),
|
||||
};
|
||||
@@ -777,8 +825,13 @@ impl OpenCADStudio {
|
||||
pending.label
|
||||
);
|
||||
}
|
||||
let (entity_before, object_before, parametric_constraints_before, named_parameters_before) =
|
||||
rec.into_recorded_images();
|
||||
let (
|
||||
entity_before,
|
||||
object_before,
|
||||
parametric_constraints_before,
|
||||
named_parameters_before,
|
||||
reference_designations_before,
|
||||
) = rec.into_recorded_images();
|
||||
let entities: Vec<(Handle, Option<Arc<EntityType>>, Option<Arc<EntityType>>)> =
|
||||
entity_before
|
||||
.into_iter()
|
||||
@@ -824,6 +877,20 @@ impl OpenCADStudio {
|
||||
let after = self.tabs[i].scene.named_parameters().clone();
|
||||
(before != after).then_some((before, after))
|
||||
});
|
||||
// Designations recorded by `remove_entities`'s delta path (the
|
||||
// first-touch before values) close symmetric with the set's current
|
||||
// state as the after image.
|
||||
let reference_designations: Vec<ReferenceDesignationDelta> = reference_designations_before
|
||||
.into_iter()
|
||||
.filter_map(|(handle, before)| {
|
||||
let after = self.tabs[i].scene.reference_only.is_marked(handle);
|
||||
(before != after).then_some(ReferenceDesignationDelta {
|
||||
handle,
|
||||
before,
|
||||
after,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let selected_after = self.tabs[i].scene.selected.iter().copied().collect();
|
||||
let dirty_after = self.tabs[i].dirty;
|
||||
let mut structure = pending.structure_before.map(StructureSnapshot::Full);
|
||||
@@ -875,6 +942,7 @@ impl OpenCADStudio {
|
||||
active_layer: None,
|
||||
structure,
|
||||
parametric_constraints,
|
||||
reference_designations,
|
||||
named_parameters,
|
||||
label: pending.label,
|
||||
};
|
||||
@@ -1029,8 +1097,19 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
}
|
||||
let changes = self.tabs[i].scene.apply_entity_delta(&d.entities, undo);
|
||||
let mut changes = self.tabs[i].scene.apply_entity_delta(&d.entities, undo);
|
||||
let scene = &mut self.tabs[i].scene;
|
||||
// Designations: restore the chosen side's value on the scene-owned set
|
||||
// (the entity images above already applied, so a restored entity is
|
||||
// present before its designation is). Each actual flip joins the
|
||||
// returned per-handle change list so the deferred cache reseed and
|
||||
// geometry bump re-stamp that entity's wires.
|
||||
for entry in &d.reference_designations {
|
||||
let value = if undo { entry.before } else { entry.after };
|
||||
if scene.set_reference_only_membership(entry.handle, value) {
|
||||
changes.push((entry.handle, crate::scene::ChangeKind::Modified));
|
||||
}
|
||||
}
|
||||
if !d.parametric_constraints.is_empty() {
|
||||
scene.bump_constraints_epoch();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user