forked from 1b-agent/opencadstudio-upstream
Merge branch 'main' into feature/parametric-constraint-system
Brings in 54 commits from origin/main: a selection-performance overhaul, surface thickening, GPU-native wide/tapered stroke rendering, continued ocs_doc_api evolution, and assorted fixes/polish (block double-click editing, DWG hatch/database repair, clipboard, collapsible Properties sections). Six real conflicts, all where this branch had independently re-applied a fix upstream later revised or already carried natively: - src/app/automation.rs, src/app/command_driver.rs: combined both sides — kept this branch's sketch-constraint/named-parameter loading on "new"/"open", adopted main's Scene::clear()/material_base_dir and its newer rebuild_derived_caches() over the older bump_geometry(). Scene::clear() (src/scene/entity.rs) now also resets sketch_constraints/named_parameters, so every caller gets this for free instead of each call site repeating it. - src/io/mod.rs, src/scene/render_graph.rs: adopted main's design outright (commit973af87d, authored by Hakan directly) — a large MINSERT is no longer purged as "corrupt" at load, only its rendering is bounded, preserving the source data. This branch's own earlier design (reject at load) predates that revision. - src/scene/pipeline/mesh_gpu.rs: adopted main's valid_rgba_size() guard (a real robustness improvement over this branch's version). - src/snap.rs: replaced wholesale with main's version — this branch's copy was an explicit verbatim snapshot from an earlier upstream PR (commit4c264b8c) with zero constraint-system-specific content, and main has since evolved it considerably further. Also removed two now-dead duplicates the merge surfaced without a conflict marker (both branches had independently fixed the same things): the OPTIONS/OP command dispatch/autocomplete entries, and automation.rs's open_finalizes_and_purges_like_the_ui_open_path test (kept main's version, which covers strictly more: solid_models/ material_base_dir reset on "new"). Full workspace suite passes (812 lib tests + this branch's own 24 constraint/persistence integration tests) except the one pre-existing, unrelated font-test failure already present on main. Zero clippy findings in the hand-written merge resolution itself; the ~1,171 warnings clippy reports are pre-existing in the 54 absorbed commits, not introduced here. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
commit
d675244fb8
89 files changed
+5700
-1101
No files matched your search
+115
-1
@@ -143,6 +143,106 @@ impl Scene {
|
||||
let _ = self.document.app_ids.add(app_id);
|
||||
}
|
||||
|
||||
fn prepare_section_objects(&mut self, entity: &mut EntityType) -> bool {
|
||||
use acadrust::entities::ExtendedEntityData;
|
||||
use acadrust::objects::{
|
||||
ClassObject, ClassObjectData, SectionManager, SectionSettings,
|
||||
SectionTypeSettings,
|
||||
};
|
||||
|
||||
let EntityType::Extended(extended) = entity else {
|
||||
return false;
|
||||
};
|
||||
let ExtendedEntityData::SectionObject(data) = &mut extended.data else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if extended.common.handle.is_null() {
|
||||
extended.common.handle = self.document.allocate_handle();
|
||||
}
|
||||
let entity_handle = extended.common.handle;
|
||||
|
||||
let valid_settings = matches!(
|
||||
self.document.objects.get(&data.settings_handle),
|
||||
Some(ObjectType::ClassObject(object))
|
||||
if matches!(&object.data, ClassObjectData::SectionSettings(_))
|
||||
);
|
||||
if !valid_settings {
|
||||
let settings_handle = self.document.allocate_handle();
|
||||
let mut settings = ClassObject::new(ClassObjectData::SectionSettings(
|
||||
SectionSettings {
|
||||
current_type: 4,
|
||||
types: vec![SectionTypeSettings {
|
||||
section_type: 4,
|
||||
generation: 17,
|
||||
..SectionTypeSettings::default()
|
||||
}],
|
||||
},
|
||||
));
|
||||
settings.handle = settings_handle;
|
||||
settings.owner = entity_handle;
|
||||
self.document
|
||||
.objects
|
||||
.insert(settings_handle, ObjectType::ClassObject(settings));
|
||||
data.settings_handle = settings_handle;
|
||||
} else if let Some(ObjectType::ClassObject(settings)) =
|
||||
self.document.objects.get_mut(&data.settings_handle)
|
||||
{
|
||||
settings.owner = entity_handle;
|
||||
}
|
||||
|
||||
let root = crate::scene::annotative::root_named_dict_handle(&mut self.document);
|
||||
let manager_handle = self
|
||||
.document
|
||||
.objects
|
||||
.get(&root)
|
||||
.and_then(|object| match object {
|
||||
ObjectType::Dictionary(dictionary) => dictionary
|
||||
.entries
|
||||
.iter()
|
||||
.find(|(name, _)| name.eq_ignore_ascii_case("ACAD_SECTION_MANAGER"))
|
||||
.map(|(_, handle)| *handle),
|
||||
_ => None,
|
||||
})
|
||||
.filter(|handle| {
|
||||
matches!(
|
||||
self.document.objects.get(handle),
|
||||
Some(ObjectType::ClassObject(object))
|
||||
if matches!(&object.data, ClassObjectData::SectionManager(_))
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let handle = self.document.allocate_handle();
|
||||
let mut manager =
|
||||
ClassObject::new(ClassObjectData::SectionManager(SectionManager::default()));
|
||||
manager.handle = handle;
|
||||
manager.owner = root;
|
||||
self.document
|
||||
.objects
|
||||
.insert(handle, ObjectType::ClassObject(manager));
|
||||
if let Some(ObjectType::Dictionary(dictionary)) =
|
||||
self.document.objects.get_mut(&root)
|
||||
{
|
||||
dictionary.entries.retain(|(name, _)| {
|
||||
!name.eq_ignore_ascii_case("ACAD_SECTION_MANAGER")
|
||||
});
|
||||
dictionary.add_entry("ACAD_SECTION_MANAGER", handle);
|
||||
}
|
||||
handle
|
||||
});
|
||||
if let Some(ObjectType::ClassObject(manager)) =
|
||||
self.document.objects.get_mut(&manager_handle)
|
||||
{
|
||||
manager.owner = root;
|
||||
if let ClassObjectData::SectionManager(manager) = &mut manager.data {
|
||||
if !manager.sections.contains(&entity_handle) {
|
||||
manager.sections.push(entity_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn add_entity(&mut self, entity: EntityType) -> Handle {
|
||||
self.add_entity_internal(entity, true)
|
||||
}
|
||||
@@ -195,6 +295,7 @@ impl Scene {
|
||||
// bookkeeping and remains in place while an entity delta is undone.
|
||||
let mutates_block_structure =
|
||||
matches!(&entity, EntityType::Block(_) | EntityType::BlockEnd(_));
|
||||
let creates_section_structure = self.prepare_section_objects(&mut entity);
|
||||
let hatch_seed = if let EntityType::Hatch(dxf) = &entity {
|
||||
let color = self.render_style(&entity).0;
|
||||
Self::hatch_model_from_dxf(dxf, color)
|
||||
@@ -298,6 +399,9 @@ impl Scene {
|
||||
};
|
||||
|
||||
if !handle.is_null() {
|
||||
if let Some(keep) = self.refedit_keep.as_mut() {
|
||||
keep.insert(handle);
|
||||
}
|
||||
self.invalidate_dependency_index();
|
||||
if let Some(model) = hatch_seed {
|
||||
self.hatches.insert(handle, model);
|
||||
@@ -334,7 +438,11 @@ impl Scene {
|
||||
// state (a new layer, application ID, or block).
|
||||
if self.is_recording_undo() {
|
||||
self.record_undo_before(handle, None);
|
||||
if creates_layer || creates_app_id || mutates_block_structure {
|
||||
if creates_layer
|
||||
|| creates_app_id
|
||||
|| mutates_block_structure
|
||||
|| creates_section_structure
|
||||
{
|
||||
self.poison_undo_recording();
|
||||
}
|
||||
}
|
||||
@@ -2583,6 +2691,12 @@ impl Scene {
|
||||
self.solid_models = HashMap::default();
|
||||
*self.camera.borrow_mut() = Camera::default();
|
||||
self.camera_generation += 1;
|
||||
// A brand-new/replaced document has none of these yet — without
|
||||
// resetting them, a "new"/"open" (e.g. via automation, which reuses
|
||||
// this same reset) would leak the previous document's constraints
|
||||
// and named parameters into the fresh one.
|
||||
self.sketch_constraints.clear();
|
||||
self.named_parameters = crate::scene::named_parameters::ParameterTable::new();
|
||||
self.bump_geometry();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user