chore: bump codec d28fd71, kernel a03e4f0, graph 79bdc4b

Codec: PRs #71-#74 merged (MPOLYGON layout, multiline ATTDEF/ATTRIB DXF,
DXF MATERIAL/ACSH matrix, restorable SAT/SAB + history roots) and issues
#55 #64-#69 fixed. EntityType now boxes Surface, Extended, Table,
MultiLeader and Helix (2344 B -> 848 B per entity): construction sites
wrap in Box, the entity traits forward through Box, and the python
plugin generator converts with into(). Kernel: PR #70 (cuboid ring
winding).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-02 00:08:55 +03:00
1 parent 8c1471078d
commit 443b935a3f
31 files changed
+147 -84

No files matched your search

Generated
+4 -4
View File
@@ -4205,7 +4205,7 @@ dependencies = [
[[package]] [[package]]
name = "opencadcodec" name = "opencadcodec"
version = "0.5.5" version = "0.5.5"
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=5ef9376#5ef9376e02996097ff649cd9268c343327413787" source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=d28fd71#d28fd710268e7301798703d3ca9c5698a1af91ed"
dependencies = [ dependencies = [
"ahash 0.8.12", "ahash 0.8.12",
"anyhow", "anyhow",
@@ -4228,7 +4228,7 @@ dependencies = [
[[package]] [[package]]
name = "opencadgraph" name = "opencadgraph"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=5384cbe#5384cbe499e97aac800f348659317b502a72da52" source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=79bdc4b#79bdc4b0586b227edad722d220227caa7f06b32f"
dependencies = [ dependencies = [
"opencadkernel", "opencadkernel",
"serde_json", "serde_json",
@@ -4237,7 +4237,7 @@ dependencies = [
[[package]] [[package]]
name = "opencadkernel" name = "opencadkernel"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=8b4980b#8b4980bad0b40f49fc6b85310c0b1b699dc8b05c" source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=a03e4f0#a03e4f094331949c8b27fb659e6891b84eeaa813"
dependencies = [ dependencies = [
"cavalier_contours", "cavalier_contours",
"opencadcodec", "opencadcodec",
@@ -4248,7 +4248,7 @@ dependencies = [
[[package]] [[package]]
name = "opencadkernel-constraints" name = "opencadkernel-constraints"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=8b4980b#8b4980bad0b40f49fc6b85310c0b1b699dc8b05c" source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=a03e4f0#a03e4f094331949c8b27fb659e6891b84eeaa813"
dependencies = [ dependencies = [
"nalgebra", "nalgebra",
] ]
+4 -4
View File
@@ -34,10 +34,10 @@ rfd = "0.17"
clap = { version = "4", features = ["derive", "string"] } clap = { version = "4", features = ["derive", "string"] }
env_logger = "0.11" env_logger = "0.11"
log = "0.4" log = "0.4"
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "5ef9376", features = ["serde"] } codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d28fd71", features = ["serde"] }
kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "8b4980b", features = ["acis", "offset"] } kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "a03e4f0", features = ["acis", "offset"] }
kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "8b4980b" } kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "a03e4f0" }
graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "5384cbe" } graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "79bdc4b" }
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" } dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
flate2 = "1" flate2 = "1"
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] } image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
+2 -2
View File
@@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true }
# Pulled in only by the `host` feature, which adds the `opencadcodec`-typed # Pulled in only by the `host` feature, which adds the `opencadcodec`-typed
# `HostApi` runtime surface. The default crate stays dependency-free so engine # `HostApi` runtime surface. The default crate stays dependency-free so engine
# crates and external tooling can depend on the manifest/ribbon contract cheaply. # crates and external tooling can depend on the manifest/ribbon contract cheaply.
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "5ef9376", optional = true, features = ["serde"] } codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d28fd71", optional = true, features = ["serde"] }
# Runtime IPC and serialization (host feature only). # Runtime IPC and serialization (host feature only).
interprocess = { version = "2", optional = true } interprocess = { version = "2", optional = true }
@@ -39,7 +39,7 @@ serde_json = "1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
cargo-lock = "11" cargo-lock = "11"
# opencadcodec is scanned at build time to generate the embedded type registry. # opencadcodec is scanned at build time to generate the embedded type registry.
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "5ef9376", features = ["serde"] } codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d28fd71", features = ["serde"] }
[dev-dependencies] [dev-dependencies]
serde_json = "1" serde_json = "1"
+1 -1
View File
@@ -1958,7 +1958,7 @@ pub fn validate_entity_mutation(
if old.is_mpolygon != new.is_mpolygon if old.is_mpolygon != new.is_mpolygon
|| old.mpolygon_hatch_color != new.mpolygon_hatch_color || old.mpolygon_hatch_color != new.mpolygon_hatch_color
|| old.mpolygon_x_direction != new.mpolygon_x_direction || old.mpolygon_x_direction != new.mpolygon_x_direction
|| old.mpolygon_boundary_handle_count != new.mpolygon_boundary_handle_count || old.mpolygon_invalid_loops != new.mpolygon_invalid_loops
{ {
return Err("Hatch MPOLYGON fields are unmapped and read-only".into()); return Err("Hatch MPOLYGON fields are unmapped and read-only".into());
} }
+1 -1
View File
@@ -8,7 +8,7 @@ publish = false
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "5ef9376", features = ["serde"] } codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "d28fd71", features = ["serde"] }
bincode = "1.3" bincode = "1.3"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
+1 -1
View File
@@ -1265,7 +1265,7 @@ dependencies = [
[[package]] [[package]]
name = "opencadcodec" name = "opencadcodec"
version = "0.5.5" version = "0.5.5"
source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=5ef9376#5ef9376e02996097ff649cd9268c343327413787" source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=d28fd71#d28fd710268e7301798703d3ca9c5698a1af91ed"
dependencies = [ dependencies = [
"ahash 0.8.12", "ahash 0.8.12",
"anyhow", "anyhow",
+4 -4
View File
@@ -925,7 +925,7 @@ fn gen_dict_to_entity(manifest: &Manifest, registry: &TypeRegistry) -> String {
} }
if manifest.manual_kinds.contains(kind) { if manifest.manual_kinds.contains(kind) {
arms.push_str(&format!( arms.push_str(&format!(
" \"{kind}\" => codec::EntityType::{kind}({}_from_dict(dict, vm)?),\n", " \"{kind}\" => codec::EntityType::{kind}({}_from_dict(dict, vm)?.into()),\n",
snake_case(kind) snake_case(kind)
)); ));
continue; continue;
@@ -962,7 +962,7 @@ fn gen_dict_to_entity(manifest: &Manifest, registry: &TypeRegistry) -> String {
for f in &fields { for f in &fields {
body.push_str(&format!(" {}\n", f.setter)); body.push_str(&format!(" {}\n", f.setter));
} }
body.push_str(&format!(" codec::EntityType::{kind}({var})\n")); body.push_str(&format!(" codec::EntityType::{kind}({var}.into())\n"));
arms.push_str(&format!(" \"{kind}\" => {{\n{body} }}\n")); arms.push_str(&format!(" \"{kind}\" => {{\n{body} }}\n"));
} }
format!( format!(
@@ -990,7 +990,7 @@ fn gen_apply_dict_to_entity(manifest: &Manifest, registry: &TypeRegistry) -> Str
for kind in &manifest.type_filter { for kind in &manifest.type_filter {
if manifest.manual_kinds.contains(kind) { if manifest.manual_kinds.contains(kind) {
arms.push_str(&format!( arms.push_str(&format!(
" codec::EntityType::{kind}(existing_value) => codec::EntityType::{kind}({}_apply(existing_value, dict, vm)?),\n", " codec::EntityType::{kind}(existing_value) => codec::EntityType::{kind}({}_apply(existing_value, dict, vm)?.into()),\n",
snake_case(kind) snake_case(kind)
)); ));
continue; continue;
@@ -1032,7 +1032,7 @@ fn gen_apply_dict_to_entity(manifest: &Manifest, registry: &TypeRegistry) -> Str
for f in &fields { for f in &fields {
body.push_str(&format!(" {}\n", f.setter)); body.push_str(&format!(" {}\n", f.setter));
} }
body.push_str(&format!(" codec::EntityType::{kind}({var})\n")); body.push_str(&format!(" codec::EntityType::{kind}({var}.into())\n"));
arms.push_str(&format!( arms.push_str(&format!(
" codec::EntityType::{kind}(existing_value) => {{\n{body} }}\n" " codec::EntityType::{kind}(existing_value) => {{\n{body} }}\n"
)); ));
+1 -1
View File
@@ -3699,7 +3699,7 @@ mod ocs {
} }
host_ctx::with_host(|host| { host_ctx::with_host(|host| {
host_ctx::ensure_undo_started(host); host_ctx::ensure_undo_started(host);
host.add_entity(EntityType::Table(builder.build())).value() host.add_entity(EntityType::Table(Box::new(builder.build()))).value()
}) })
.ok_or_else(|| vm.new_runtime_error("ocs: not running inside a PY_ command".to_owned())) .ok_or_else(|| vm.new_runtime_error("ocs: not running inside a PY_ command".to_owned()))
} }
+4 -4
View File
@@ -965,16 +965,16 @@ mod thicken_tests {
) )
.unwrap(); .unwrap();
let source = app.add_surface_model( let source = app.add_surface_model(
codec::EntityType::Surface(Surface::new(SurfaceKind::Plane)), codec::EntityType::Surface(Box::new(Surface::new(SurfaceKind::Plane))),
body, body,
); );
assert!(!source.is_null()); assert!(!source.is_null());
let i = app.active_tab; let i = app.active_tab;
let invalid = app.tabs[i] let invalid = app.tabs[i]
.scene .scene
.add_entity(codec::EntityType::Surface(Surface::new( .add_entity(codec::EntityType::Surface(Box::new(Surface::new(
SurfaceKind::Generic, SurfaceKind::Generic,
))); ))));
let original = let original =
serde_json::to_value(app.tabs[i].scene.document.get_entity(source).unwrap()).unwrap(); serde_json::to_value(app.tabs[i].scene.document.get_entity(source).unwrap()).unwrap();
let before = app.tabs[i].history.undo_stack.len(); let before = app.tabs[i].history.undo_stack.len();
@@ -1060,7 +1060,7 @@ mod thicken_tests {
kernel::brep::extrude_surface(Plane::XY, &[Curve::Nurbs(profile)], [0.0, 0.0, 2.0]) kernel::brep::extrude_surface(Plane::XY, &[Curve::Nurbs(profile)], [0.0, 0.0, 2.0])
.unwrap(); .unwrap();
let source = app.add_surface_model( let source = app.add_surface_model(
codec::EntityType::Surface(Surface::new(SurfaceKind::Generic)), codec::EntityType::Surface(Box::new(Surface::new(SurfaceKind::Generic))),
body, body,
); );
let i = app.active_tab; let i = app.active_tab;
+1 -1
View File
@@ -322,7 +322,7 @@ impl OpenCADStudio {
"_PCCROPCIRC" => "C", "_PCCROPCIRC" => "C",
_ => "", _ => "",
}; };
let command = crate::modules::insert::pc_crop::PointCloudCropCommand::for_cloud(handle, cloud, option); let command = crate::modules::insert::pc_crop::PointCloudCropCommand::for_cloud(handle, *cloud, option);
self.command_line.push_info(&command.prompt()); self.command_line.push_info(&command.prompt());
self.tabs[i].active_cmd = Some(Box::new(command)); self.tabs[i].active_cmd = Some(Box::new(command));
} }
+2 -2
View File
@@ -163,10 +163,10 @@ impl OpenCADStudio {
elevation_as_gradient: false, elevation_as_gradient: false,
croppings: Vec::new(), croppings: Vec::new(),
}; };
let entity = codec::EntityType::Extended(codec::entities::ExtendedEntity { let entity = codec::EntityType::Extended(Box::new(codec::entities::ExtendedEntity {
common: codec::entities::EntityCommon::new(), common: codec::entities::EntityCommon::new(),
data: codec::entities::ExtendedEntityData::PointCloudEx(data), data: codec::entities::ExtendedEntityData::PointCloudEx(data),
}); }));
if let Some(cloud) = self.commit_entity_handle(entity) { if let Some(cloud) = self.commit_entity_handle(entity) {
// The reactor, owned by the cloud, tells the definition who uses it. // The reactor, owned by the cloud, tells the definition who uses it.
let document = &mut self.tabs[i].scene.document; let document = &mut self.tabs[i].scene.document;
+9 -9
View File
@@ -685,15 +685,15 @@ impl OpenCADStudio {
/// Add is delta-safe when its layer and XData application IDs already exist /// Add is delta-safe when its layer and XData application IDs already exist
/// and it creates no block records. /// and it creates no block records.
pub(super) fn delta_add_safe(&self, i: usize, entity: &EntityType) -> bool { pub(super) fn delta_add_safe(&self, i: usize, entity: &EntityType) -> bool {
if matches!( if matches!(entity, EntityType::Block(_) | EntityType::BlockEnd(_))
entity, || matches!(
EntityType::Block(_) entity,
| EntityType::BlockEnd(_) EntityType::Extended(extended) if matches!(
| EntityType::Extended(codec::entities::ExtendedEntity { extended.data,
data: codec::entities::ExtendedEntityData::SectionObject(_), codec::entities::ExtendedEntityData::SectionObject(_)
.. )
}) )
) { {
return false; return false;
} }
let layer = entity.common().layer.clone(); let layer = entity.common().layer.clone();
+2 -2
View File
@@ -1354,7 +1354,7 @@ impl super::OpenCADStudio {
let mut entity = Surface::new(SurfaceKind::Generic); let mut entity = Surface::new(SurfaceKind::Generic);
entity.common = group.common; entity.common = group.common;
self.add_surface_model_preserving_style( self.add_surface_model_preserving_style(
EntityType::Surface(entity), EntityType::Surface(Box::new(entity)),
group.body, group.body,
) )
} }
@@ -2316,7 +2316,7 @@ impl super::OpenCADStudio {
} }
let n = surfaces.len(); let n = surfaces.len();
for surf in surfaces { for surf in surfaces {
self.tabs[i].scene.add_entity(EntityType::Surface(surf)); self.tabs[i].scene.add_entity(EntityType::Surface(Box::new(surf)));
} }
self.tabs[i].dirty = true; self.tabs[i].dirty = true;
self.refresh_properties(); self.refresh_properties();
+5 -5
View File
@@ -198,14 +198,14 @@ impl<'a> HostSession<'a> {
} }
if let EntityType::Helix(new) = entity { if let EntityType::Helix(new) = entity {
let old = match old { let old = match old {
Some(EntityType::Helix(old)) => Some(old), Some(EntityType::Helix(old)) => Some(&**old),
_ => None, _ => None,
}; };
crate::entities::helix::normalize_scripted_helix(old, new)?; crate::entities::helix::normalize_scripted_helix(old, new)?;
} }
if let EntityType::Table(new) = entity { if let EntityType::Table(new) = entity {
let old = match old { let old = match old {
Some(EntityType::Table(old)) => Some(old), Some(EntityType::Table(old)) => Some(&**old),
_ => None, _ => None,
}; };
crate::entities::table::normalize_scripted_table(old, new); crate::entities::table::normalize_scripted_table(old, new);
@@ -758,7 +758,7 @@ impl<'a> HostSession<'a> {
surface.wires = model::edge_wires(&body); surface.wires = model::edge_wires(&body);
surface.acis_data = codec::entities::AcisData::from_sat(&sat.to_sat_string()); surface.acis_data = codec::entities::AcisData::from_sat(&sat.to_sat_string());
surface.common.layer = layer; surface.common.layer = layer;
self.commit_profile_result(EntityType::Surface(surface), source, delete_source, "Create surface") self.commit_profile_result(EntityType::Surface(Box::new(surface)), source, delete_source, "Create surface")
} }
SolidOperation::Extrude { source, direction, layer, delete_source } => { SolidOperation::Extrude { source, direction, layer, delete_source } => {
if direction.iter().any(|v| !v.is_finite()) { if direction.iter().any(|v| !v.is_finite()) {
@@ -788,7 +788,7 @@ impl<'a> HostSession<'a> {
surface.wires = model::edge_wires(&body); surface.wires = model::edge_wires(&body);
surface.acis_data = codec::entities::AcisData::from_sat(&sat.to_sat_string()); surface.acis_data = codec::entities::AcisData::from_sat(&sat.to_sat_string());
surface.common.layer = layer; surface.common.layer = layer;
EntityType::Surface(surface) EntityType::Surface(Box::new(surface))
}; };
self.commit_profile_result(result, source, delete_source, "Extrude profile") self.commit_profile_result(result, source, delete_source, "Extrude profile")
} }
@@ -7201,7 +7201,7 @@ mod tests {
let unliftable = host.add_entity(EntityType::Solid3D(codec::entities::Solid3D::new())); let unliftable = host.add_entity(EntityType::Solid3D(codec::entities::Solid3D::new()));
let mut plane = codec::entities::Surface::new(codec::entities::SurfaceKind::Plane); let mut plane = codec::entities::Surface::new(codec::entities::SurfaceKind::Plane);
plane.acis_data = codec::entities::AcisData::new(); plane.acis_data = codec::entities::AcisData::new();
let surface = host.add_entity(EntityType::Surface(plane)); let surface = host.add_entity(EntityType::Surface(Box::new(plane)));
let far = { dispatch(&mut host, "PY_EVAL ocs.active_document.solids.box(center=(500, 500, 500), size=(1, 1, 1)).handle"); let far = { dispatch(&mut host, "PY_EVAL ocs.active_document.solids.box(center=(500, 500, 500), size=(1, 1, 1)).handle");
*solids_in(host.document()).last().unwrap() }; *solids_in(host.document()).last().unwrap() };
let counts = (host.document().entities().count(), host.app.tabs[0].history.undo_stack.len()); let counts = (host.document().entities().count(), host.app.tabs[0].history.undo_stack.len());
+1 -1
View File
@@ -140,7 +140,7 @@ impl super::OpenCADStudio {
surface.surface_data = solid_history::extrusion_surface_data(record) surface.surface_data = solid_history::extrusion_surface_data(record)
.ok_or("PRESSPULL: the surface parameters could not be retained.")?; .ok_or("PRESSPULL: the surface parameters could not be retained.")?;
} }
EntityType::Surface(surface) EntityType::Surface(Box::new(surface))
}; };
(body, history, entity) (body, history, entity)
} }
+1 -1
View File
@@ -10922,7 +10922,7 @@ mod free_text_entry_tests {
let handle = app.tabs[0] let handle = app.tabs[0]
.scene .scene
.document .document
.add_entity(EntityType::Table(table.clone())) .add_entity(EntityType::Table(Box::new(table.clone())))
.unwrap(); .unwrap();
app.set_active_command(0, Box::new(TableCellEditCommand::new(handle, &table, 0, 0))); app.set_active_command(0, Box::new(TableCellEditCommand::new(handle, &table, 0, 0)));
(app, handle) (app, handle)
+1 -1
View File
@@ -2108,7 +2108,7 @@ impl MultiLeaderTess for MultiLeader {
fill_tris_low: Vec::new(), fill_tris_low: Vec::new(),
}); });
let host = codec::EntityType::MultiLeader(ml.clone()); let host = codec::EntityType::MultiLeader(Box::new(ml.clone()));
for block_use in crate::scene::render_graph::entity_render_block_uses(document, &host, 1.0) for block_use in crate::scene::render_graph::entity_render_block_uses(document, &host, 1.0)
.into_iter() .into_iter()
.filter(|block_use| { .filter(|block_use| {
+57
View File
@@ -81,6 +81,63 @@ pub trait Transformable {
fn apply_transform(&mut self, t: &EntityTransform); fn apply_transform(&mut self, t: &EntityTransform);
} }
// The codec boxes its rare wide entity kinds (Surface, Table, MultiLeader,
// Helix, Extended) so every other entity is stored narrow; the boxed ones
// answer through their contents.
impl<T: RenderConvertible + ?Sized> RenderConvertible for Box<T> {
fn to_render(&self, document: &CadDocument) -> Option<RenderEntity> {
(**self).to_render(document)
}
}
impl<T: Grippable + ?Sized> Grippable for Box<T> {
fn grips(&self) -> Vec<GripDef> {
(**self).grips()
}
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
(**self).apply_grip(grip_id, apply)
}
fn grip_menu(&self, grip_id: usize) -> Vec<GripMenuItem> {
(**self).grip_menu(grip_id)
}
fn apply_grip_menu(&mut self, grip_id: usize, action: GripMenuAction) {
(**self).apply_grip_menu(grip_id, action)
}
fn apply_grip_menu_value(&mut self, grip_id: usize, action: GripMenuAction, value: f64) {
(**self).apply_grip_menu_value(grip_id, action, value)
}
fn grip_menu_value_prompt(
&self,
grip_id: usize,
action: GripMenuAction,
) -> Option<&'static str> {
(**self).grip_menu_value_prompt(grip_id, action)
}
fn grip_menu_point_value(
&self,
grip_id: usize,
action: GripMenuAction,
point: glam::DVec3,
) -> Option<f64> {
(**self).grip_menu_point_value(grip_id, action, point)
}
}
impl<T: PropertyEditable + ?Sized> PropertyEditable for Box<T> {
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
(**self).geometry_properties(text_style_names)
}
fn apply_geom_prop(&mut self, field: &str, value: &str) {
(**self).apply_geom_prop(field, value)
}
}
impl<T: Transformable + ?Sized> Transformable for Box<T> {
fn apply_transform(&mut self, t: &EntityTransform) {
(**self).apply_transform(t)
}
}
/// Inquiry-time mass / area / perimeter properties for entities whose /// Inquiry-time mass / area / perimeter properties for entities whose
/// 2D footprint has a meaningful area or perimeter (Circle, Arc, Line, /// 2D footprint has a meaningful area or perimeter (Circle, Arc, Line,
/// LwPolyline, Ellipse). Entities outside this set get `None` via the /// LwPolyline, Ellipse). Entities outside this set get `None` via the
+1 -1
View File
@@ -160,7 +160,7 @@ impl CadCommand for DataLinkPlaceCommand {
self.table.insertion_point = codec::types::Vector3::new(point.x, point.y, point.z); self.table.insertion_point = codec::types::Vector3::new(point.x, point.y, point.z);
CmdResult::CommitAndExit( CmdResult::CommitAndExit(
self.plane self.plane
.place_entity(EntityType::Table(self.table.clone())), .place_entity(EntityType::Table(Box::new(self.table.clone()))),
) )
} }
+1 -1
View File
@@ -269,7 +269,7 @@ impl MLeaderCommand {
ml.text_style_handle = style_handle; ml.text_style_handle = style_handle;
ml.context.text_style_handle = style_handle; ml.context.text_style_handle = style_handle;
} }
let entity = self.plane.place_entity(EntityType::MultiLeader(ml)); let entity = self.plane.place_entity(EntityType::MultiLeader(Box::new(ml)));
if self.content_type == LeaderContentType::MText && self.text.is_empty() { if self.content_type == LeaderContentType::MText && self.text.is_empty() {
CmdResult::CommitAndEditText(entity) CmdResult::CommitAndEditText(entity)
} else { } else {
+2 -2
View File
@@ -271,7 +271,7 @@ impl TableCommand {
row.style = Some(styles[row_index.min(2)].clone()); row.style = Some(styles[row_index.min(2)].clone());
} }
} }
self.plane.place_entity(EntityType::Table(table)) self.plane.place_entity(EntityType::Table(Box::new(table)))
} }
fn preview_grid( fn preview_grid(
@@ -795,7 +795,7 @@ impl CadCommand for TableCellEditCommand {
cell.set_text(&formatted); cell.set_text(&formatted);
self.table.block_record_handle = None; self.table.block_record_handle = None;
Some(CmdResult::ReplaceMany( Some(CmdResult::ReplaceMany(
vec![(self.handle, vec![EntityType::Table(self.table.clone())])], vec![(self.handle, vec![EntityType::Table(Box::new(self.table.clone()))])],
Vec::new(), Vec::new(),
)) ))
} }
+1 -1
View File
@@ -139,7 +139,7 @@ impl HelixCommand {
helix.turn_height = if curve.turns == 0.0 { 0.0 } else { height / curve.turns }; helix.turn_height = if curve.turns == 0.0 { 0.0 } else { height / curve.turns };
helix.handedness = self.counter_clockwise; helix.handedness = self.counter_clockwise;
helix.constraint = self.constraint; helix.constraint = self.constraint;
Some(EntityType::Helix(helix)) Some(EntityType::Helix(Box::new(helix)))
} }
fn commit(&mut self, height: f64, axis: DVec3) -> CmdResult { fn commit(&mut self, height: f64, axis: DVec3) -> CmdResult {
+2 -1
View File
@@ -75,7 +75,8 @@ impl ReverseCommand {
} }
EntityType::Spline(sp) => Some(EntityType::Spline(reverse_spline(sp))), EntityType::Spline(sp) => Some(EntityType::Spline(reverse_spline(sp))),
EntityType::Helix(helix) => { EntityType::Helix(helix) => {
crate::entities::helix::reversed(helix).map(EntityType::Helix) crate::entities::helix::reversed(helix)
.map(|helix| EntityType::Helix(Box::new(helix)))
} }
_ => None, _ => None,
} }
+5 -2
View File
@@ -117,7 +117,10 @@ impl PointCloudCropCommand {
if let ExtendedEntityData::PointCloudEx(data) = &mut cloud.data { if let ExtendedEntityData::PointCloudEx(data) = &mut cloud.data {
change(data); change(data);
} }
CmdResult::UpdateEntityAndFinish { handle: self.handle, entity: EntityType::Extended(cloud) } CmdResult::UpdateEntityAndFinish {
handle: self.handle,
entity: EntityType::Extended(Box::new(cloud)),
}
} }
fn axes(data: &PointCloudExData) -> glam::DMat3 { fn axes(data: &PointCloudExData) -> glam::DMat3 {
@@ -296,7 +299,7 @@ impl CadCommand for PointCloudCropCommand {
match self.picked.take() { match self.picked.take() {
Some(EntityType::Extended(cloud)) if matches!(cloud.data, ExtendedEntityData::PointCloudEx(_)) => { Some(EntityType::Extended(cloud)) if matches!(cloud.data, ExtendedEntityData::PointCloudEx(_)) => {
self.handle = handle; self.handle = handle;
self.cloud = Some(cloud); self.cloud = Some(*cloud);
if self.uncrop { if self.uncrop {
return self.finish(|data| data.croppings.clear()); return self.finish(|data| data.croppings.clear());
} }
+3 -3
View File
@@ -2793,7 +2793,7 @@ pub fn empty_extruded_surface(direction: DVec3, taper_angle: f64) -> EntityType
options.is_solid = false; options.is_solid = false;
*sweep_vector = Vector3::new(direction.x, direction.y, direction.z); *sweep_vector = Vector3::new(direction.x, direction.y, direction.z);
} }
EntityType::Surface(surface) EntityType::Surface(Box::new(surface))
} }
pub fn empty_revolved_surface( pub fn empty_revolved_surface(
@@ -2832,7 +2832,7 @@ pub fn empty_revolved_surface(
*stored_start = start_angle; *stored_start = start_angle;
*solid = false; *solid = false;
} }
EntityType::Surface(surface) EntityType::Surface(Box::new(surface))
} }
// ── Autocomplete registry ───────────────────────────────── // ── Autocomplete registry ─────────────────────────────────
@@ -2909,7 +2909,7 @@ mod thicken_command_tests {
let handle = Handle::new(42); let handle = Handle::new(42);
let mut command = ThickenCommand::new(vec![ let mut command = ThickenCommand::new(vec![
(Handle::new(1), EntityType::Line(codec::entities::Line::default())), (Handle::new(1), EntityType::Line(codec::entities::Line::default())),
(handle, EntityType::Surface(codec::entities::Surface::new(codec::entities::SurfaceKind::Plane))), (handle, EntityType::Surface(Box::new(codec::entities::Surface::new(codec::entities::SurfaceKind::Plane)))),
]); ]);
assert!(!command.is_selection_gathering()); assert!(!command.is_selection_gathering());
assert_eq!(command.handles, vec![handle]); assert_eq!(command.handles, vec![handle]);
+1 -1
View File
@@ -172,7 +172,7 @@ impl SectionPlaneCommand {
self.kind == SectionKind::Slice, self.kind == SectionKind::Slice,
depth, depth,
); );
EntityType::Extended(entity) EntityType::Extended(Box::new(entity))
} }
fn line_at(&self, point: DVec3, viewing: DVec3, vertical_hint: DVec3) -> (Vec<DVec3>, DVec3) { fn line_at(&self, point: DVec3, viewing: DVec3, vertical_hint: DVec3) -> (Vec<DVec3>, DVec3) {
+18 -20
View File
@@ -3052,10 +3052,10 @@ impl Scene {
let is_insert = matches!(entity, EntityType::Insert(_)); let is_insert = matches!(entity, EntityType::Insert(_));
let is_section = matches!( let is_section = matches!(
entity, entity,
EntityType::Extended(codec::entities::ExtendedEntity { EntityType::Extended(extended) if matches!(
data: codec::entities::ExtendedEntityData::SectionObject(_), extended.data,
.. codec::entities::ExtendedEntityData::SectionObject(_)
}) )
); );
if self.meshes.contains_key(&handle) if self.meshes.contains_key(&handle)
|| self.block_meshes.contains_key(&handle) || self.block_meshes.contains_key(&handle)
@@ -7691,16 +7691,14 @@ impl Scene {
CACHE_CATEGORY_MESH, CACHE_CATEGORY_MESH,
|h| { |h| {
self.meshes.contains_key(&h) self.meshes.contains_key(&h)
|| matches!( || match self.document.get_entity(h) {
self.document.get_entity(h), Some(EntityType::Insert(_)) => true,
Some(EntityType::Insert(_)) Some(EntityType::Extended(extended)) => matches!(
| Some(EntityType::Extended( extended.data,
codec::entities::ExtendedEntity { codec::entities::ExtendedEntityData::SectionObject(_)
data: codec::entities::ExtendedEntityData::SectionObject(_), ),
.. _ => false,
} }
))
)
}, },
) => ) =>
{ {
@@ -12153,15 +12151,15 @@ mod section_tests {
#[test] #[test]
fn adding_and_erasing_a_section_keeps_its_object_graph_consistent() { fn adding_and_erasing_a_section_keeps_its_object_graph_consistent() {
let mut scene = Scene::new(); let mut scene = Scene::new();
let handle = scene.add_entity(EntityType::Extended(ExtendedEntity { let handle = scene.add_entity(EntityType::Extended(Box::new(ExtendedEntity {
common: EntityCommon::new(), common: EntityCommon::new(),
data: ExtendedEntityData::SectionObject(section(1, 0.0)), data: ExtendedEntityData::SectionObject(section(1, 0.0)),
})); })));
let settings_handle = match scene.document.get_entity(handle).unwrap() { let settings_handle = match scene.document.get_entity(handle).unwrap() {
EntityType::Extended(ExtendedEntity { EntityType::Extended(extended) => match &extended.data {
data: ExtendedEntityData::SectionObject(data), ExtendedEntityData::SectionObject(data) => data.settings_handle,
.. _ => unreachable!(),
}) => data.settings_handle, },
_ => unreachable!(), _ => unreachable!(),
}; };
assert!(matches!( assert!(matches!(
+1 -1
View File
@@ -91,5 +91,5 @@ pub fn surface_entity(record: &SolidHistoryLoft) -> EntityType {
ruled_surface: settings.normals == 0, virtual_guide: false, ruled_surface: settings.normals == 0, virtual_guide: false,
cross_sections: Vec::new(), guide_curves: Vec::new(), path_curve: None, cross_sections: Vec::new(), guide_curves: Vec::new(), path_curve: None,
}; };
EntityType::Surface(surface) EntityType::Surface(Box::new(surface))
} }
+1 -1
View File
@@ -109,5 +109,5 @@ pub fn swept_surface_entity(record: &SolidHistorySweep) -> EntityType {
..SurfaceSweepOptions::default() ..SurfaceSweepOptions::default()
}, },
}; };
EntityType::Surface(surface) EntityType::Surface(Box::new(surface))
} }
+8 -4
View File
@@ -1002,10 +1002,14 @@ impl Scene {
continue; continue;
} }
let settings_handle = self.document.get_entity(h).and_then(|entity| match entity { let settings_handle = self.document.get_entity(h).and_then(|entity| match entity {
EntityType::Extended(codec::entities::ExtendedEntity { EntityType::Extended(extended) => match &extended.data {
data: codec::entities::ExtendedEntityData::SectionObject(data), codec::entities::ExtendedEntityData::SectionObject(data)
.. if !data.settings_handle.is_null() =>
}) if !data.settings_handle.is_null() => Some(data.settings_handle), {
Some(data.settings_handle)
}
_ => None,
},
_ => None, _ => None,
}); });
let section_managers: Vec<Handle> = managers_by_section let section_managers: Vec<Handle> = managers_by_section
+2 -2
View File
@@ -14,7 +14,7 @@ fn add_slice(scene: &mut Scene) -> Handle {
thickness.values = vec![XDataValue::Real(0.75)]; thickness.values = vec![XDataValue::Real(0.75)];
common.extended_data.add_record(thickness); common.extended_data.add_record(thickness);
scene.add_entity(EntityType::Extended(ExtendedEntity { scene.add_entity(EntityType::Extended(Box::new(ExtendedEntity {
common, common,
data: ExtendedEntityData::SectionObject(SectionObjectData { data: ExtendedEntityData::SectionObject(SectionObjectData {
state: 1, state: 1,
@@ -29,7 +29,7 @@ fn add_slice(scene: &mut Scene) -> Handle {
back_line_vertices: Vec::new(), back_line_vertices: Vec::new(),
settings_handle: Handle::NULL, settings_handle: Handle::NULL,
}), }),
})) })))
} }
fn assert_section_graph(document: &codec::CadDocument, extension: &str) { fn assert_section_graph(document: &codec::CadDocument, extension: &str) {