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 <noreply@anthropic.com>
This commit is contained in:
commit
d675244fb8
89 files changed
+5700
-1101
No files matched your search
+121
-3
@@ -1839,10 +1839,32 @@ impl OpenCADStudio {
|
||||
Message::CommandHistoryCopy => {
|
||||
let text = self.command_line.history_plain_text();
|
||||
if text.is_empty() {
|
||||
Task::none()
|
||||
} else {
|
||||
iced::clipboard::write(text).discard()
|
||||
return Task::none();
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
let promise = crate::sys::copy_history_text(
|
||||
&text,
|
||||
crate::t!("Clipboard access is unavailable. Press Ctrl+C or Command+C to copy the selected history.").as_ref(),
|
||||
crate::t!("Close").as_ref(),
|
||||
);
|
||||
Task::perform(async move {
|
||||
wasm_bindgen_futures::JsFuture::from(promise).await
|
||||
.ok().and_then(|value| value.as_bool()).unwrap_or(false)
|
||||
}, Message::CommandHistoryCopied)
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
iced::clipboard::write(text).discard()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
Message::CommandHistoryCopied(copied) => {
|
||||
if copied {
|
||||
self.command_line.push_info(crate::t!("Copied").as_ref());
|
||||
} else {
|
||||
self.command_line.push_error(crate::t!("Clipboard access is unavailable. Press Ctrl+C or Command+C to copy the selected history.").as_ref());
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::CommandHistoryClear => {
|
||||
@@ -5108,6 +5130,20 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropSectionToggle(title) => {
|
||||
let sections = &mut self.collapsed_property_sections;
|
||||
if !sections.remove(&title) {
|
||||
sections.insert(title);
|
||||
}
|
||||
// Keep already-built panels in other open documents in sync,
|
||||
// rather than waiting for each one to rebuild on selection.
|
||||
let sections = self.collapsed_property_sections.clone();
|
||||
for tab in &mut self.tabs {
|
||||
tab.properties.collapsed_sections = sections.clone();
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PropEditChoiceToggle => {
|
||||
let panel = &mut self.tabs[self.active_tab].properties;
|
||||
panel.edit_choice_open = !panel.edit_choice_open;
|
||||
@@ -5216,6 +5252,21 @@ impl OpenCADStudio {
|
||||
Message::PropColorFieldChanged { field, color } => {
|
||||
let i = self.active_tab;
|
||||
let handles = self.property_target_handles(i);
|
||||
if field == "indicator_fill_color" {
|
||||
self.apply_property_op(i, "CHPROP", &handles, |app, handle| {
|
||||
if let Some(acadrust::EntityType::Extended(extended)) =
|
||||
app.tabs[i].scene.document.get_entity_mut(handle)
|
||||
{
|
||||
if let acadrust::entities::ExtendedEntityData::SectionObject(data) =
|
||||
&mut extended.data
|
||||
{
|
||||
data.indicator_color = color;
|
||||
}
|
||||
}
|
||||
});
|
||||
self.tabs[i].properties.open_color_field = None;
|
||||
return Task::none();
|
||||
}
|
||||
// Dim-line colour override (Leader / Dimension): write it as an
|
||||
// ACAD_DSTYLE code-176 override (an ACI index) so it round-trips
|
||||
// through DWG and DXF. RGB picks collapse to the nearest ACI, in
|
||||
@@ -5921,6 +5972,18 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::DoubleClickBlockRefeditChanged(enabled) => {
|
||||
self.double_click_block_refedit = enabled;
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::DoubleClickBlockAtteditChanged(enabled) => {
|
||||
self.double_click_block_attedit = enabled;
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::CursorTypeChanged(value) => {
|
||||
self.cursor_type = value;
|
||||
self.persist_settings_if_changed();
|
||||
@@ -6148,6 +6211,48 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::GripObjectLimitChanged(limit) => {
|
||||
self.grip_object_limit = limit.clamp(0, 32767);
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::SelectionEffectToggled(enabled) => {
|
||||
self.model_space.selection_effect = enabled;
|
||||
self.sync_model_space_theme(false);
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// SELECTIONPREVIEW is a bitmask and the two checkboxes own one bit
|
||||
// each: 1 = rollover while idle, 2 = rollover during a command.
|
||||
Message::SelectionPreviewIdleToggled(enabled) => {
|
||||
self.model_space.selection_preview =
|
||||
set_preview_bit(self.model_space.selection_preview, 1, enabled);
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::SelectionPreviewCommandToggled(enabled) => {
|
||||
self.model_space.selection_preview =
|
||||
set_preview_bit(self.model_space.selection_preview, 2, enabled);
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// "Use Shift to add" is the inverse of PICKADD.
|
||||
Message::ShiftToAddToggled(shift_to_add) => {
|
||||
self.pick_add = !shift_to_add;
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::PickDragRectToggled(rectangle) => {
|
||||
self.pick_drag_rect = rectangle;
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::RestoreSelectionVisualDefaults => {
|
||||
self.model_space.selection_area = true;
|
||||
self.model_space.selection_opacity = 12;
|
||||
@@ -6160,6 +6265,10 @@ impl OpenCADStudio {
|
||||
self.model_space.grip_color = 0;
|
||||
self.model_space.grip_hot = 0;
|
||||
self.model_space.grip_hover = 0;
|
||||
// The button restores the *visual* defaults, which is why the
|
||||
// grip limit is here and PICKADD / PICKDRAG are not — those are
|
||||
// how selection behaves, not how it looks.
|
||||
self.grip_object_limit = crate::app::settings::DEFAULT_GRIP_OBJECT_LIMIT;
|
||||
self.sync_model_space_theme(false);
|
||||
self.persist_settings_if_changed();
|
||||
Task::none()
|
||||
@@ -8677,3 +8786,12 @@ mod free_text_entry_tests {
|
||||
assert_eq!(app.text_entry_mode(), TextEntryMode::Command);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set or clear one bit of `SELECTIONPREVIEW`.
|
||||
fn set_preview_bit(current: u8, bit: u8, enabled: bool) -> u8 {
|
||||
if enabled {
|
||||
current | bit
|
||||
} else {
|
||||
current & !bit
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user