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
@@ -734,7 +734,7 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
// ── EXTRUDE ────────────────────────────────────────────────────
|
||||
"EXTRUDE" | "THICKEN" => {
|
||||
"EXTRUDE" => {
|
||||
use crate::modules::insert::solid3d_cmds::ExtrudeCommand;
|
||||
// A preselection becomes the complete source set; otherwise
|
||||
// the interactive command gathers any number of profiles.
|
||||
@@ -769,6 +769,19 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
"THICKEN" => {
|
||||
use crate::modules::insert::solid3d_cmds::ThickenCommand;
|
||||
let selected = self.tabs[i]
|
||||
.scene
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(handle, entity)| (handle, entity.clone()))
|
||||
.collect();
|
||||
let command = ThickenCommand::new(selected);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
}
|
||||
|
||||
"PRESSPULL" => {
|
||||
use crate::modules::insert::solid3d_cmds::PresspullCommand;
|
||||
let color = self.tabs[i].scene.layer_color(&self.tabs[i].active_layer);
|
||||
|
||||
@@ -1400,6 +1400,64 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
"SECTIONPLANE" => {
|
||||
use crate::modules::model::sectionplane_cmd::SectionPlaneCommand;
|
||||
let (bounds, next_name) = {
|
||||
let scene = &mut self.tabs[i].scene;
|
||||
let solid_handles = scene
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|entity| {
|
||||
matches!(
|
||||
entity,
|
||||
acadrust::EntityType::Solid3D(_)
|
||||
| acadrust::EntityType::Surface(_)
|
||||
| acadrust::EntityType::Region(_)
|
||||
| acadrust::EntityType::Body(_)
|
||||
)
|
||||
.then_some(entity.common().handle)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
scene.restore_solid_models(&solid_handles);
|
||||
let bounds = solid_handles
|
||||
.iter()
|
||||
.filter_map(|handle| scene.solid_models.get(handle))
|
||||
.filter_map(crate::scene::model::solid_model::extent)
|
||||
.fold(None::<(glam::DVec3, glam::DVec3)>, |bounds, (low, high)| {
|
||||
let low = glam::DVec3::from_array(low);
|
||||
let high = glam::DVec3::from_array(high);
|
||||
Some(match bounds {
|
||||
None => (low, high),
|
||||
Some((min, max)) => (min.min(low), max.max(high)),
|
||||
})
|
||||
});
|
||||
let next_name = scene
|
||||
.document
|
||||
.entities()
|
||||
.filter_map(|entity| {
|
||||
let acadrust::EntityType::Extended(extended) = entity else {
|
||||
return None;
|
||||
};
|
||||
let acadrust::entities::ExtendedEntityData::SectionObject(data) =
|
||||
&extended.data
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
data.name
|
||||
.strip_prefix("Section Plane (")
|
||||
.and_then(|name| name.strip_suffix(')'))
|
||||
.and_then(|name| name.parse::<usize>().ok())
|
||||
})
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
+ 1;
|
||||
(bounds, next_name)
|
||||
};
|
||||
let command = SectionPlaneCommand::new(bounds, next_name);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
}
|
||||
|
||||
// 3DALIGN <18 numbers> — align the selected solid by 3 source→3 dest points.
|
||||
cmd if cmd == "3DALIGN"
|
||||
|| cmd == "ALIGN3D"
|
||||
|
||||
@@ -465,6 +465,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"3DALIGN",
|
||||
"ALIGN3D",
|
||||
"SECTION",
|
||||
"SECTIONPLANE",
|
||||
"PYRAMID",
|
||||
"PYR",
|
||||
"SPLINEFIT",
|
||||
@@ -551,6 +552,7 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"GRIPCOLOR",
|
||||
"GRIPHOT",
|
||||
"GRIPHOVER",
|
||||
"GRIPOBJLIMIT",
|
||||
// Reset selected entities' overrides to follow their layer.
|
||||
"SETBYLAYER",
|
||||
// Remove duplicate objects; set drawing base point; audit integrity;
|
||||
|
||||
@@ -918,6 +918,7 @@ impl OpenCADStudio {
|
||||
| "GRIPCOLOR"
|
||||
| "GRIPHOT"
|
||||
| "GRIPHOVER"
|
||||
| "GRIPOBJLIMIT"
|
||||
) =>
|
||||
{
|
||||
return self.dispatch_styleprops(&format!("SETVAR {cmd}"), i);
|
||||
@@ -940,7 +941,7 @@ impl OpenCADStudio {
|
||||
let value = it.next().map(|s| s.trim().to_string());
|
||||
if name.is_empty() || name == "?" {
|
||||
self.command_line.push_info(
|
||||
crate::t!("SETVAR: LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR CURSORSIZE PICKBOX CURSORTYPE SNAPANG TEXTFILL CLIPROMPTLINES COMMANDLINEFADETIME ATTREQ ATTDIA DIMASSOC DIMCONTINUEMODE ANGBASE ANGDIR SKETCHINC SKPOLY SKTOLERANCE DONUTID DONUTOD CENTEREXE CENTERLAYER CENTERLTYPE CENTERLTSCALE CENTERLTYPEFILE CENTERCROSSSIZE CENTERCROSSGAP CENTERMARKEXE COLORTHEME SELECTIONAREA SELECTIONAREAOPACITY SELECTIONEFFECT SELECTIONEFFECTCOLOR WINDOWSAREACOLOR CROSSINGAREACOLOR SELECTIONPREVIEW GRIPSIZE GRIPCOLOR GRIPHOT GRIPHOVER | CLAYER CELTYPE TEXTSTYLE (read-only)").as_ref(),
|
||||
crate::t!("SETVAR: LTSCALE CELTSCALE PDMODE PDSIZE TEXTSIZE ORTHOMODE FILLMODE MIRRTEXT FRAME IMAGEFRAME PDFFRAME WIPEOUTFRAME XCLIPFRAME POINTCLOUDCLIPFRAME ZOOMWHEEL ZOOMFACTOR CURSORSIZE PICKBOX CURSORTYPE SNAPANG TEXTFILL CLIPROMPTLINES COMMANDLINEFADETIME ATTREQ ATTDIA DIMASSOC DIMCONTINUEMODE ANGBASE ANGDIR SKETCHINC SKPOLY SKTOLERANCE DONUTID DONUTOD CENTEREXE CENTERLAYER CENTERLTYPE CENTERLTSCALE CENTERLTYPEFILE CENTERCROSSSIZE CENTERCROSSGAP CENTERMARKEXE COLORTHEME SELECTIONAREA SELECTIONAREAOPACITY SELECTIONEFFECT SELECTIONEFFECTCOLOR WINDOWSAREACOLOR CROSSINGAREACOLOR SELECTIONPREVIEW GRIPSIZE GRIPCOLOR GRIPHOT GRIPHOVER GRIPOBJLIMIT | CLAYER CELTYPE TEXTSTYLE (read-only)").as_ref(),
|
||||
);
|
||||
} else {
|
||||
if matches!(name.as_str(), "SHOWHIST" | "SOLIDHIST") {
|
||||
@@ -1444,6 +1445,22 @@ impl OpenCADStudio {
|
||||
},
|
||||
None => Ok((format!("GRIPSIZE = {}", self.model_space.grip_size), false)),
|
||||
},
|
||||
"GRIPOBJLIMIT" => match &value {
|
||||
Some(v) => match v.parse::<i32>() {
|
||||
Ok(limit @ 0..=32767) => {
|
||||
self.grip_object_limit = limit;
|
||||
Ok((format!("GRIPOBJLIMIT = {limit}"), true))
|
||||
}
|
||||
_ => Err(
|
||||
"SETVAR: integer from 0 to 32767 required (0 = no limit)."
|
||||
.into(),
|
||||
),
|
||||
},
|
||||
None => Ok((
|
||||
format!("GRIPOBJLIMIT = {}", self.grip_object_limit),
|
||||
false,
|
||||
)),
|
||||
},
|
||||
"GRIPCOLOR" => match &value {
|
||||
Some(v) => match v.parse::<u8>() {
|
||||
Ok(color) => {
|
||||
@@ -2126,6 +2143,7 @@ impl OpenCADStudio {
|
||||
| "GRIPCOLOR"
|
||||
| "GRIPHOT"
|
||||
| "GRIPHOVER"
|
||||
| "GRIPOBJLIMIT"
|
||||
) {
|
||||
self.persist_settings_if_changed();
|
||||
} else {
|
||||
@@ -2982,6 +3000,13 @@ mod tests {
|
||||
// SELECTIONPREVIEW
|
||||
let _ = app.run_command_line("SETVAR SELECTIONPREVIEW 2");
|
||||
assert_eq!(app.model_space.selection_preview, 2);
|
||||
|
||||
let _ = app.run_command_line("SETVAR GRIPOBJLIMIT 0");
|
||||
assert_eq!(app.grip_object_limit, 0);
|
||||
let _ = app.run_command_line("GRIPOBJLIMIT 32767");
|
||||
assert_eq!(app.grip_object_limit, 32767);
|
||||
let _ = app.run_command_line("GRIPOBJLIMIT 32768");
|
||||
assert_eq!(app.grip_object_limit, 32767);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1566,6 +1566,16 @@ mod tests {
|
||||
app
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn options_and_its_alias_dispatch_from_the_start_page() {
|
||||
let mut app = fresh_app();
|
||||
let i = app.active_tab;
|
||||
assert!(app.dispatch_view("OPTIONS", i).is_some());
|
||||
assert!(app.dispatch_view("OP", i).is_some());
|
||||
assert!(crate::app::commands::start_allowed("OPTIONS"));
|
||||
assert!(crate::app::commands::start_allowed("OP"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hatchtoback_no_hatches_warns_and_noop() {
|
||||
let mut app = fresh_app();
|
||||
|
||||
Reference in new issue
Block a user