From e4d04ef1323adcde510b40c99af9b4265c5230d1 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Fri, 16 Oct 2026 09:17:01 +0300 Subject: [PATCH] Cargo: codec e023bc3 (acadrust sync), kernel abca4e8, graph c63556f The codec now holds wide EntityType variants boxed (MText, Helix, Dimension, Hatch, Viewport, MultiLeader, Surface, Table, Ole2Frame, Light, Extended). Constructors box their entity; nested patterns reach a dimension through entities::dimension::as_dimension(_mut). Also follows BlockAction::action_ids, LineTypeComplexData::source_flags and the decimal tab stop with an explicit character. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 44 +++++++++--- Cargo.toml | 8 +-- benches/command_benchmarks.rs | 2 +- crates/ocs_plugin_api/Cargo.toml | 4 +- crates/ocs_plugin_api/src/entity_coverage.rs | 14 ++-- crates/ocs_save/Cargo.toml | 2 +- crates/ocs_web_worker/Cargo.toml | 2 +- docs/plugin-template-v2/Cargo.toml | 2 +- plugins/opencad-python/Cargo.lock | 12 +++- .../examples/create_layout_fixture.rs | 2 +- plugins/opencad-python/src/ocs_module.rs | 2 +- src/app/automation.rs | 14 ++-- src/app/command_driver/clipboard.rs | 2 +- src/app/command_driver/dim_edit.rs | 22 +++--- src/app/command_driver/entity_commit.rs | 16 ++--- src/app/command_driver/text_edit.rs | 2 +- src/app/command_driver/transform.rs | 2 +- src/app/command_driver/viewport.rs | 5 +- src/app/commands/pdf_shx_text.rs | 2 +- src/app/commands/sheet_set.rs | 2 +- src/app/commands/ucsfollow.rs | 4 +- src/app/commands/view.rs | 7 +- src/app/dim_viewport.rs | 4 +- src/app/mtext_editor.rs | 10 +-- src/app/navigation.rs | 2 +- src/app/plugin_host.rs | 8 +-- src/app/properties.rs | 70 ++++++++++--------- src/app/update/block_ops_tests.rs | 4 +- src/app/update/command.rs | 19 +++-- src/app/update/graphic_attributes.rs | 2 +- src/app/viewport_dimension_tests.rs | 10 +-- src/entities/dimension.rs | 29 ++++++-- src/entities/object_data.rs | 6 +- src/entities/text_support.rs | 4 +- src/entities/traits.rs | 10 +++ src/entity_creation.rs | 4 +- src/io/linetypes.rs | 2 + src/io/mod.rs | 13 ++-- src/io/ole_embed.rs | 2 +- src/io/xref.rs | 2 +- src/modules/annotate/aligned_dim.rs | 2 +- src/modules/annotate/angular_dim.rs | 6 +- src/modules/annotate/arc_length_dim.rs | 2 +- src/modules/annotate/diameter_dim.rs | 4 +- src/modules/annotate/dim_baseline.rs | 6 +- src/modules/annotate/dim_continue.rs | 6 +- src/modules/annotate/dimjogline.rs | 10 ++- src/modules/annotate/dimspace.rs | 13 ++-- src/modules/annotate/field_cmd.rs | 2 +- src/modules/annotate/jogged_radius_dim.rs | 4 +- src/modules/annotate/leader_cmd.rs | 2 +- src/modules/annotate/linear_dim.rs | 2 +- src/modules/annotate/mleader_cmd.rs | 2 +- src/modules/annotate/ordinate_dim.rs | 2 +- src/modules/annotate/qdim.rs | 10 +-- src/modules/annotate/radius_dim.rs | 4 +- src/modules/annotate/txt2mtxt.rs | 7 +- src/modules/draw/clipboard/pastespec.rs | 2 +- src/modules/draw/draw/hatchedit.rs | 4 +- src/modules/draw/draw/raster_image.rs | 2 +- src/modules/draw/modify/explode.rs | 26 +++---- src/modules/insert/dgn_import.rs | 2 +- src/modules/insert/pdf_import.rs | 4 +- src/modules/layout/mvsetup.rs | 2 +- src/scene/annotative.rs | 2 +- src/scene/block_service.rs | 4 +- src/scene/camera_ops.rs | 4 +- src/scene/dimension_assoc.rs | 48 +++++++------ src/scene/entity.rs | 2 +- src/scene/layout.rs | 6 +- src/scene/mod.rs | 10 +-- src/scene/mspace.rs | 4 +- src/scene/parametric_constraints.rs | 26 ++++--- src/scene/project.rs | 4 +- src/ui/node_graph.rs | 2 +- tests/active_space_roundtrip.rs | 4 +- tests/annotative_context_synthesis.rs | 6 +- tests/block_hatch_export.rs | 8 +-- tests/dim_copy_check.rs | 2 +- tests/dim_leader_render_check.rs | 2 +- tests/dim_line_color_roundtrip.rs | 2 +- tests/explode_regression.rs | 2 +- tests/pdf_export_images_check.rs | 2 +- tests/pdf_export_text_check.rs | 2 +- tests/text_font_rendering.rs | 2 +- tests/viewport_wide_polyline_plot_width.rs | 2 +- tests/zoom_extents_coverage.rs | 4 +- 87 files changed, 380 insertions(+), 269 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf8d59d12..dbea93f19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2397,7 +2397,7 @@ dependencies = [ "hayro-syntax", "kurbo 0.13.1", "moxcms", - "phf", + "phf 0.13.1", "rustc-hash 2.1.3", "siphasher", "skrifa 0.42.1", @@ -4348,6 +4348,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "oem_cp" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7959d3349f484aec36462f98226983578bf7d33f9b034c32967489c7000e1f" +dependencies = [ + "phf 0.11.3", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -4373,7 +4382,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=102f04c#102f04c8ecda1cd409f7ecc4b6eab2dc895c9095" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=e023bc3#e023bc37235dddecf9b3e79c522d8936d15e21e6" dependencies = [ "anyhow", "bitflags 2.13.1", @@ -4385,6 +4394,7 @@ dependencies = [ "itoa", "memmap2", "nom 7.1.3", + "oem_cp", "once_cell", "rayon", "ryu", @@ -4396,7 +4406,7 @@ dependencies = [ [[package]] name = "opencadgraph" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=88cdae0#88cdae06858f6811f5058a5686bc1edb5ff39910" +source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=c63556f#c63556f9f7a3cf658fd003a2e47fe67283b6afa7" dependencies = [ "opencadkernel", "serde_json", @@ -4405,7 +4415,7 @@ dependencies = [ [[package]] name = "opencadkernel" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=5811296#5811296a6c98ea9b12defa977f08d74cfc739014" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=abca4e8#abca4e81b089114a776ad6fe72a40c51a35646cb" dependencies = [ "cavalier_contours", "opencadcodec", @@ -4416,7 +4426,7 @@ dependencies = [ [[package]] name = "opencadkernel-constraints" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=5811296#5811296a6c98ea9b12defa977f08d74cfc739014" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=abca4e8#abca4e81b089114a776ad6fe72a40c51a35646cb" dependencies = [ "nalgebra", ] @@ -4595,6 +4605,15 @@ dependencies = [ "indexmap", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + [[package]] name = "phf" version = "0.13.1" @@ -4602,7 +4621,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.13.1", ] [[package]] @@ -4612,7 +4631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ "fastrand", - "phf_shared", + "phf_shared 0.13.1", ] [[package]] @@ -4622,12 +4641,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ "phf_generator", - "phf_shared", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn 2.0.119", ] +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.13.1" diff --git a/Cargo.toml b/Cargo.toml index a3cbad80c..76f14f916 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,10 +37,10 @@ rfd = "0.17" clap = { version = "4", features = ["derive", "string"] } env_logger = "0.11" log = "0.4" -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } -kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "5811296", features = ["acis", "offset"] } -kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "5811296" } -graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "88cdae0" } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "e023bc3", features = ["serde"] } +kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "abca4e8", features = ["acis", "offset"] } +kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "abca4e8" } +graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "c63556f" } dwg-thumbnailer = { path = "crates/dwg-thumbnailer" } # Shared SAVE serialization dispatch + web-worker wire format: one # implementation for the inline (fallback/native) path and the worker path. diff --git a/benches/command_benchmarks.rs b/benches/command_benchmarks.rs index c65439c4a..8e90a5c00 100644 --- a/benches/command_benchmarks.rs +++ b/benches/command_benchmarks.rs @@ -101,7 +101,7 @@ fn push_fixture_entities(doc: &mut CadDocument, quick: bool) -> Vec { d.definition_point = Vector3::new(x + 5.0, y + 3.0, 0.0); d.base.text_middle_point = Vector3::new(x + 5.0, y + 4.0, 0.0); handles.push( - doc.add_entity(EntityType::Dimension(Dimension::Linear(d))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(), ); } diff --git a/crates/ocs_plugin_api/Cargo.toml b/crates/ocs_plugin_api/Cargo.toml index 6a528cac8..f5f538245 100644 --- a/crates/ocs_plugin_api/Cargo.toml +++ b/crates/ocs_plugin_api/Cargo.toml @@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true } # Pulled in only by the `host` feature, which adds the `opencadcodec`-typed # `HostApi` runtime surface. The default crate stays dependency-free so engine # crates and external tooling can depend on the manifest/ribbon contract cheaply. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", optional = true, features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "e023bc3", optional = true, features = ["serde"] } # Runtime IPC and serialization (host feature only). interprocess = { version = "2", optional = true } @@ -39,7 +39,7 @@ serde_json = "1" serde = { version = "1", features = ["derive"] } cargo-lock = "11" # opencadcodec is scanned at build time to generate the embedded type registry. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "e023bc3", features = ["serde"] } [dev-dependencies] serde_json = "1" diff --git a/crates/ocs_plugin_api/src/entity_coverage.rs b/crates/ocs_plugin_api/src/entity_coverage.rs index aa2901297..c723c1266 100644 --- a/crates/ocs_plugin_api/src/entity_coverage.rs +++ b/crates/ocs_plugin_api/src/entity_coverage.rs @@ -3583,7 +3583,7 @@ mod tests { #[test] fn unsupported_canvas_kind_has_typed_snapshot_fields() { use crate::host::codec; - let hatch = codec::EntityType::Hatch(codec::entities::Hatch::default()); + let hatch = codec::EntityType::Hatch(Box::new(codec::entities::Hatch::default())); let snapshot = entity_snapshot(&hatch).unwrap(); let fields = snapshot .get("Hatch") @@ -3713,7 +3713,7 @@ mod tests { #[test] fn canvas_layer_patch_preserves_unmapped_hatch_fields() { use crate::host::codec; - let hatch = codec::EntityType::Hatch(codec::entities::Hatch::default()); + let hatch = codec::EntityType::Hatch(Box::new(codec::entities::Hatch::default())); let patched = patch_canvas_layer(&hatch, "HATCHES").unwrap(); assert_eq!(patched.common().layer, "HATCHES"); assert_eq!(hatch.common().layer, "0"); @@ -3809,13 +3809,13 @@ mod tests { })); } hatch.paths.push(path); - let entity = codec::EntityType::Hatch(hatch.clone()); + let entity = codec::EntityType::Hatch(Box::new(hatch.clone())); validate_new_canvas_entity(&entity).unwrap(); let mut invalid = hatch.clone(); invalid.paths.clear(); assert!( - validate_new_canvas_entity(&codec::EntityType::Hatch(invalid)) + validate_new_canvas_entity(&codec::EntityType::Hatch(Box::new(invalid))) .unwrap_err() .contains("at least one boundary path") ); @@ -3824,7 +3824,7 @@ mod tests { invalid.is_solid = false; invalid.pattern_scale = 0.0; assert!( - validate_new_canvas_entity(&codec::EntityType::Hatch(invalid)) + validate_new_canvas_entity(&codec::EntityType::Hatch(Box::new(invalid))) .unwrap_err() .contains("greater than zero") ); @@ -3841,13 +3841,13 @@ mod tests { associative.paths[0].boundary_handles.push(boundary); validate_canvas_entity_references( &document, - &codec::EntityType::Hatch(associative.clone()), + &codec::EntityType::Hatch(Box::new(associative.clone())), ) .unwrap(); associative.paths[0].boundary_handles[0] = codec::Handle::new(u64::MAX); assert!(validate_canvas_entity_references( &document, - &codec::EntityType::Hatch(associative), + &codec::EntityType::Hatch(Box::new(associative)), ) .unwrap_err() .contains("does not exist")); diff --git a/crates/ocs_save/Cargo.toml b/crates/ocs_save/Cargo.toml index 687cbe234..150de8021 100644 --- a/crates/ocs_save/Cargo.toml +++ b/crates/ocs_save/Cargo.toml @@ -10,6 +10,6 @@ publish = false # exactly one implementation. No UI/app dependencies — only the codec + serde. [dependencies] -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "e023bc3", features = ["serde"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } diff --git a/crates/ocs_web_worker/Cargo.toml b/crates/ocs_web_worker/Cargo.toml index 656935b3c..42aabfcd1 100644 --- a/crates/ocs_web_worker/Cargo.toml +++ b/crates/ocs_web_worker/Cargo.toml @@ -8,7 +8,7 @@ publish = false crate-type = ["cdylib"] [dependencies] -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "e023bc3", features = ["serde"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } console_error_panic_hook = "0.1" diff --git a/docs/plugin-template-v2/Cargo.toml b/docs/plugin-template-v2/Cargo.toml index 484fad237..d0a847190 100644 --- a/docs/plugin-template-v2/Cargo.toml +++ b/docs/plugin-template-v2/Cargo.toml @@ -16,4 +16,4 @@ ocs_plugin_api = { path = "../../crates/ocs_plugin_api", features = ["host"] } # entry): the plugin's entities and the host's re-exports are the same types # only when both resolve the same revision. The registration `rustc` / # `acadrust_source` gates enforce this at load time too. -acadrust = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c" } +acadrust = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "e023bc3" } diff --git a/plugins/opencad-python/Cargo.lock b/plugins/opencad-python/Cargo.lock index b4227ff83..d5afa7615 100644 --- a/plugins/opencad-python/Cargo.lock +++ b/plugins/opencad-python/Cargo.lock @@ -1245,6 +1245,15 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "oem_cp" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7959d3349f484aec36462f98226983578bf7d33f9b034c32967489c7000e1f" +dependencies = [ + "phf 0.11.3", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1264,7 +1273,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=102f04c#102f04c8ecda1cd409f7ecc4b6eab2dc895c9095" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=e023bc3#e023bc37235dddecf9b3e79c522d8936d15e21e6" dependencies = [ "anyhow", "bitflags", @@ -1276,6 +1285,7 @@ dependencies = [ "itoa", "memmap2", "nom", + "oem_cp", "once_cell", "rayon", "ryu", diff --git a/plugins/opencad-python/examples/create_layout_fixture.rs b/plugins/opencad-python/examples/create_layout_fixture.rs index b76e2158b..5cff8d471 100644 --- a/plugins/opencad-python/examples/create_layout_fixture.rs +++ b/plugins/opencad-python/examples/create_layout_fixture.rs @@ -41,7 +41,7 @@ fn main() -> Result<(), Box> { viewport.twist_angle = std::f64::consts::FRAC_PI_2; viewport.view_target = Vector3::new(5.0, 10.0, 0.0); } - document.add_entity_to_layout(EntityType::Viewport(viewport), "Sheet")?; + document.add_entity_to_layout(EntityType::Viewport(Box::new(viewport)), "Sheet")?; let mut file = std::fs::OpenOptions::new() .write(true) diff --git a/plugins/opencad-python/src/ocs_module.rs b/plugins/opencad-python/src/ocs_module.rs index 929268656..04f70baef 100644 --- a/plugins/opencad-python/src/ocs_module.rs +++ b/plugins/opencad-python/src/ocs_module.rs @@ -406,7 +406,7 @@ mod ocs { text.rotation = rotation; host_ctx::with_host(|host| { host_ctx::ensure_undo_started(host); - host.add_entity(EntityType::MText(text)).value() + host.add_entity(EntityType::MText(Box::new(text))).value() }) .ok_or_else(|| vm.new_runtime_error("ocs: not running inside a PY_ command".to_owned())) } diff --git a/src/app/automation.rs b/src/app/automation.rs index 20ed24436..74b95ce18 100644 --- a/src/app/automation.rs +++ b/src/app/automation.rs @@ -2129,7 +2129,7 @@ mod tests { dimension.definition_point = Vector3::new(0.0, 5.0, 0.0); dimension.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); document - .add_entity(EntityType::Dimension(Dimension::Linear(dimension))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))) .unwrap(); crate::modules::draw::modify::explode::bake_dimension_blocks(&mut document); @@ -2152,7 +2152,7 @@ mod tests { dimension.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); app.tabs[app.active_tab] .scene - .add_entity(EntityType::Dimension(Dimension::Linear(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))); let path = std::env::temp_dir().join(format!( "ocs_verified_dimension_{}_{}.dwg", std::process::id(), @@ -2190,7 +2190,7 @@ mod tests { let i = app.active_tab; app.tabs[i] .scene - .add_entity(EntityType::Dimension(Dimension::Linear(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))); let path = std::env::temp_dir().join(format!( "ocs_verified_dimension_follow_up_{}_{}.dwg", std::process::id(), @@ -2240,7 +2240,7 @@ mod tests { app.tabs[i] .scene .document - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); let path = std::env::temp_dir().join(format!( "ocs_verified_dim_{}_{}.dwg", @@ -2330,7 +2330,7 @@ mod tests { viewport.width = 100.0; viewport.height = 50.0; viewport.turn_on(); - scene.add_entity(codec::EntityType::Viewport(viewport)); + scene.add_entity(codec::EntityType::Viewport(Box::new(viewport))); for entity in scene.document.entities_mut() { if let codec::EntityType::Viewport(viewport) = entity { viewport.status.grid_on = true; @@ -2774,7 +2774,7 @@ mod tests { codec::MText::with_value("\\A1;10.5000", codec::types::Vector3::new(10.0, 20.0, 0.0)); app.tabs[i] .scene - .add_entity(codec::EntityType::MText(mtext)); + .add_entity(codec::EntityType::MText(Box::new(mtext))); let q = app.automation_op( r#"{"op":"query","type":"MTEXT","detail":"full","fields":["value","text","height","bounds"]}"#, @@ -3642,7 +3642,7 @@ mod tests { let mut dst_mtext = MText::new(); dst_mtext.value = "DSTM".into(); dst_mtext.height = 2.0; - let dst_mtext_h = app.tabs[i].scene.add_entity(EntityType::MText(dst_mtext)); + let dst_mtext_h = app.tabs[i].scene.add_entity(EntityType::MText(Box::new(dst_mtext))); // Drive the interactive command exactly as the viewport does: // phase 1 source pick, phase 2 destination selection. diff --git a/src/app/command_driver/clipboard.rs b/src/app/command_driver/clipboard.rs index 64827cad8..8e9d687ab 100644 --- a/src/app/command_driver/clipboard.rs +++ b/src/app/command_driver/clipboard.rs @@ -1405,7 +1405,7 @@ mod paste_entities_kernel_tests { fn remaps_leader_annotation_link_to_pasted_handles() { let mut seed = codec::CadDocument::new(); let note = seed - .add_entity(codec::EntityType::MText(codec::entities::MText::new())) + .add_entity(codec::EntityType::MText(Box::new(codec::entities::MText::new()))) .unwrap(); let mut leader = codec::entities::Leader::default(); leader.annotation_handle = note; diff --git a/src/app/command_driver/dim_edit.rs b/src/app/command_driver/dim_edit.rs index 906b4c636..e845bfe9a 100644 --- a/src/app/command_driver/dim_edit.rs +++ b/src/app/command_driver/dim_edit.rs @@ -36,10 +36,12 @@ impl OpenCADStudio { ) { let i = self.active_tab; let valid = matches!( - self.tabs[i].scene.document.get_entity(dimension), - Some(codec::EntityType::Dimension( - codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - )) + self.tabs[i] + .scene + .document + .get_entity(dimension) + .and_then(crate::entities::dimension::as_dimension), + Some(codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_)) ); if !valid { self.command_line.push_error( @@ -415,8 +417,12 @@ fn apply_dimspace( requested_spacing: Option, ) -> bool { use codec::entities::Dimension; - let (axis, normal, definition, auto_spacing) = match scene.document.get_entity(base_h) { - Some(codec::EntityType::Dimension(dimension @ Dimension::Linear(d))) => { + let base = scene + .document + .get_entity(base_h) + .and_then(crate::entities::dimension::as_dimension); + let (axis, normal, definition, auto_spacing) = match base { + Some(dimension @ Dimension::Linear(d)) => { let spacing = dimension_auto_spacing( &scene.document, dimension, @@ -433,7 +439,7 @@ fn apply_dimspace( spacing, ) } - Some(codec::EntityType::Dimension(dimension @ Dimension::Aligned(d))) => { + Some(dimension @ Dimension::Aligned(d)) => { let spacing = dimension_auto_spacing( &scene.document, dimension, @@ -471,7 +477,7 @@ fn apply_dimspace( kernel::space::move_to_dimension_spacing([p.x, p.y, p.z], frame, target); *p = codec::types::Vector3::new(point[0], point[1], point[2]); }; - match dim { + match &mut **dim { Dimension::Linear(d) => { slide(&mut d.definition_point); d.base.definition_point = d.definition_point; diff --git a/src/app/command_driver/entity_commit.rs b/src/app/command_driver/entity_commit.rs index 559961a35..b4ca6eac0 100644 --- a/src/app/command_driver/entity_commit.rs +++ b/src/app/command_driver/entity_commit.rs @@ -39,10 +39,8 @@ impl OpenCADStudio { let delta_safe = self.delta_add_safe(i, &entity); let pending = self.begin_undo(i, label, 1, delta_safe); let is_associative_dimension = matches!( - entity, - codec::EntityType::Dimension( - codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - ) + crate::entities::dimension::as_dimension(&entity), + Some(codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_)) ); let association_enabled = self.tabs[i].scene.document.header.dimension_associativity == 2; let committed = if preserve_commit_layer { @@ -257,10 +255,8 @@ impl OpenCADStudio { }; let pending = self.begin_undo(i, label, 1, delta_safe); let is_associative_dimension = matches!( - entity, - codec::EntityType::Dimension( - codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - ) + crate::entities::dimension::as_dimension(&entity), + Some(codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_)) ); let association_enabled = self.tabs[i].scene.document.header.dimension_associativity == 2; let committed = if preserve_commit_layer { @@ -324,8 +320,8 @@ impl OpenCADStudio { let label = self.history_label_from_active_cmd(i, "DIMENSION"); let association_mode = self.tabs[i].scene.document.header.dimension_associativity; let single_source_dimension = matches!( - &entity, - codec::EntityType::Dimension(codec::entities::Dimension::Ordinate(_)) + crate::entities::dimension::as_dimension(&entity), + Some(codec::entities::Dimension::Ordinate(_)) ); // A dimension placed on the sheet but measuring model geometry // through a viewport carries the compensation as a negative diff --git a/src/app/command_driver/text_edit.rs b/src/app/command_driver/text_edit.rs index 86cb2b713..3cf316d42 100644 --- a/src/app/command_driver/text_edit.rs +++ b/src/app/command_driver/text_edit.rs @@ -160,7 +160,7 @@ impl OpenCADStudio { Operation::Rotate(degrees) => { dimension.base_mut().text_rotation = degrees.to_radians(); } - Operation::Oblique(degrees) => match dimension { + Operation::Oblique(degrees) => match &mut **dimension { codec::entities::Dimension::Linear(value) => { value.ext_line_rotation = degrees.to_radians(); } diff --git a/src/app/command_driver/transform.rs b/src/app/command_driver/transform.rs index 421cdc274..dc4f070e3 100644 --- a/src/app/command_driver/transform.rs +++ b/src/app/command_driver/transform.rs @@ -463,7 +463,7 @@ impl OpenCADStudio { false } }; - match dim { + match &mut **dim { Dimension::Linear(d) => { stretched |= mv(&mut d.first_point); stretched |= mv(&mut d.second_point); diff --git a/src/app/command_driver/viewport.rs b/src/app/command_driver/viewport.rs index 05c5bfb5c..3208a1ca6 100644 --- a/src/app/command_driver/viewport.rs +++ b/src/app/command_driver/viewport.rs @@ -21,7 +21,7 @@ impl OpenCADStudio { }); let label = self.history_label_from_active_cmd(i, "MVIEW"); let pending = self.begin_undo(i, label, 1, true); - let handle = self.commit_entity_handle(codec::EntityType::Viewport(viewport)); + let handle = self.commit_entity_handle(codec::EntityType::Viewport(Box::new(viewport))); if let (Some(handle), Some(saved)) = (handle, saved_view) { if let Some(codec::EntityType::Viewport(viewport)) = self.tabs[i].scene.document.get_entity_mut(handle) @@ -244,7 +244,8 @@ impl OpenCADStudio { viewport.id = 2; viewport.clip_boundary_handle = clip_handle; viewport.status.non_rectangular_clipping = !clip_handle.is_null(); - let viewport_handle = self.commit_entity_handle(codec::EntityType::Viewport(viewport)); + let viewport_handle = + self.commit_entity_handle(codec::EntityType::Viewport(Box::new(viewport))); if let Some(viewport_handle) = viewport_handle { if !created_boundary { let before = self.tabs[i] diff --git a/src/app/commands/pdf_shx_text.rs b/src/app/commands/pdf_shx_text.rs index 3f500d98e..182448672 100644 --- a/src/app/commands/pdf_shx_text.rs +++ b/src/app/commands/pdf_shx_text.rs @@ -294,7 +294,7 @@ impl OpenCADStudio { } else { line.layer }; - scene.add_entity(codec::EntityType::MText(mtext)); + scene.add_entity(codec::EntityType::MText(Box::new(mtext))); erase.extend(line.handles); } erase.sort(); diff --git a/src/app/commands/sheet_set.rs b/src/app/commands/sheet_set.rs index 3da99868d..c62a06dce 100644 --- a/src/app/commands/sheet_set.rs +++ b/src/app/commands/sheet_set.rs @@ -2389,7 +2389,7 @@ impl OpenCADStudio { Vector3::new(mv.center.x - mv.target.x, mv.center.y - mv.target.y, 0.0); vp.view_height = mv.height; vp.custom_scale = scale; - scene.add_entity(codec::EntityType::Viewport(vp)); + scene.add_entity(codec::EntityType::Viewport(Box::new(vp))); // A paper-space named view of the same name frames it. let mut named = codec::tables::View::new(title.as_str()); named.handle = scene.document.allocate_handle(); diff --git a/src/app/commands/ucsfollow.rs b/src/app/commands/ucsfollow.rs index 77213208c..f76c4075c 100644 --- a/src/app/commands/ucsfollow.rs +++ b/src/app/commands/ucsfollow.rs @@ -126,10 +126,10 @@ mod tests { let i = app.active_tab; let first = app.tabs[i] .scene - .add_entity(codec::EntityType::Viewport(codec::entities::Viewport::new())); + .add_entity(codec::EntityType::Viewport(Box::new(codec::entities::Viewport::new()))); let second = app.tabs[i] .scene - .add_entity(codec::EntityType::Viewport(codec::entities::Viewport::new())); + .add_entity(codec::EntityType::Viewport(Box::new(codec::entities::Viewport::new()))); app.tabs[i].scene.active_viewport = Some(first); let _ = app.run_command_line("UCSFOLLOW 1"); assert!(app.tabs[i].scene.ucs_follow()); diff --git a/src/app/commands/view.rs b/src/app/commands/view.rs index 87e312163..5e7a7dfa7 100644 --- a/src/app/commands/view.rs +++ b/src/app/commands/view.rs @@ -1000,7 +1000,10 @@ impl OpenCADStudio { match self.tabs[i] .scene .document - .add_entity_to_layout(codec::EntityType::Viewport(vp), &layout_name) + .add_entity_to_layout( + codec::EntityType::Viewport(Box::new(vp)), + &layout_name, + ) { Ok(handle) => { self.tabs[i].scene.auto_fit_viewport(handle); @@ -2207,7 +2210,7 @@ mod tests { locked_hatch.common.layer = "LOCKED_LAYER".into(); let h_locked_hatch = app.tabs[i] .scene - .add_entity_clone(EntityType::Hatch(locked_hatch)); + .add_entity_clone(EntityType::Hatch(Box::new(locked_hatch))); let h_line = app.tabs[i] .scene diff --git a/src/app/dim_viewport.rs b/src/app/dim_viewport.rs index db3fc9322..49ffaded8 100644 --- a/src/app/dim_viewport.rs +++ b/src/app/dim_viewport.rs @@ -352,7 +352,7 @@ impl OpenCADStudio { fn is_angular_dimension(entity: &EntityType) -> bool { matches!( - entity, - EntityType::Dimension(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) + crate::entities::dimension::as_dimension(entity), + Some(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) ) } diff --git a/src/app/mtext_editor.rs b/src/app/mtext_editor.rs index 2f67342d1..24aa40da0 100644 --- a/src/app/mtext_editor.rs +++ b/src/app/mtext_editor.rs @@ -841,7 +841,7 @@ impl super::OpenCADStudio { // catastrophic cancellation. Insertion is a pure translation, so zeroing // it keeps the layout's shape, wrapping and alignment identical. mt.insertion_point = Vector3::new(0.0, 0.0, 0.0); - let entity = EntityType::MText(mt.clone()); + let entity = EntityType::MText(Box::new(mt.clone())); let anno = 1.0; let bg = self.tabs[i].scene.bg_color; let wires: Vec = tessellate::tessellate( @@ -1753,7 +1753,8 @@ impl super::OpenCADStudio { )); mt.insertion_point = codec::types::Vector3::new(position.x, position.y, position.z); self.push_undo_snapshot(i, "MTEXT"); - let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt))); + let handle = + self.commit_entity_handle(plane.place_entity(EntityType::MText(Box::new(mt)))); if annotative { let scale = self.tabs[i].scene.creation_annotation_scale_handle(); if let (Some(handle), Some(scale)) = (handle, scale) { @@ -1869,7 +1870,8 @@ impl super::OpenCADStudio { )); mt.insertion_point = codec::types::Vector3::new(position.x, position.y, position.z); self.push_undo_snapshot(i, "MTEXT"); - let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt))); + let handle = + self.commit_entity_handle(plane.place_entity(EntityType::MText(Box::new(mt)))); self.tabs[i].dirty = true; if annotative { let scale = self.tabs[i].scene.creation_annotation_scale_handle(); @@ -1885,7 +1887,7 @@ impl super::OpenCADStudio { if let (Some(h), Some(ed)) = (handle, self.mtext_editor.as_mut()) { ed.editing = Some(h); if let Some(EntityType::MText(mtext)) = self.tabs[i].scene.document.get_entity(h) { - ed.original = Some(mtext.clone()); + ed.original = Some((**mtext).clone()); } } } diff --git a/src/app/navigation.rs b/src/app/navigation.rs index 5a7267692..54c8c4e92 100644 --- a/src/app/navigation.rs +++ b/src/app/navigation.rs @@ -497,7 +497,7 @@ mod tests { vp.width = 200.; vp.height = 100.; vp.view_height = 50.; - let handle = scene.add_entity(codec::EntityType::Viewport(vp)); + let handle = scene.add_entity(codec::EntityType::Viewport(Box::new(vp))); scene.active_viewport = Some(handle); let mut camera = scene.navigation_camera(); camera.target = DVec3::new(120., 30., 8.); diff --git a/src/app/plugin_host.rs b/src/app/plugin_host.rs index 3088a9e07..e023cdb31 100644 --- a/src/app/plugin_host.rs +++ b/src/app/plugin_host.rs @@ -943,7 +943,7 @@ impl<'a> HostSession<'a> { frame.common.layer = layer; } self.push_undo("Embed picture"); - let handle = self.add_entity(EntityType::Ole2Frame(frame)); + let handle = self.add_entity(EntityType::Ole2Frame(Box::new(frame))); if handle.is_null() { return Err("the picture frame could not be added".into()); } @@ -6708,7 +6708,7 @@ mod tests { let EntityType::Dimension(dimension) = &mut after else { unreachable!() }; - if let codec::entities::Dimension::Linear(value) = dimension { + if let codec::entities::Dimension::Linear(value) = &mut **dimension { value.second_point.x = 30.0; } ocs_plugin_api::entity_coverage::validate_entity_mutation(&before, &after).unwrap(); @@ -7414,7 +7414,7 @@ mod tests { .unwrap(); let mut viewport = codec::entities::Viewport::new(); viewport.common.owner_handle = owner; - let viewport_handle = host.add_entity(EntityType::Viewport(viewport)); + let viewport_handle = host.add_entity(EntityType::Viewport(Box::new(viewport))); let scale_handle = host.document_mut().allocate_handle(); let mut scale = codec::objects::Scale::new("1:1", 1.0, 1.0); scale.handle = scale_handle; @@ -10861,7 +10861,7 @@ mod tests { bare.height = 30.0; let bare = host .document_mut() - .add_entity(EntityType::Viewport(bare)) + .add_entity(EntityType::Viewport(Box::new(bare))) .unwrap(); assert_eq!( host.document().get_entity(bare).map(|e| match e { diff --git a/src/app/properties.rs b/src/app/properties.rs index e376a84e9..1b88ad023 100644 --- a/src/app/properties.rs +++ b/src/app/properties.rs @@ -1489,12 +1489,14 @@ impl OpenCADStudio { if let Some((anno_field, insert_after)) = anno { let is_anno = crate::scene::annotative::is_annotative(doc, entity) || match entity { - codec::EntityType::Dimension(codec::entities::Dimension::Arc( - dimension, - )) => crate::scene::annotative::dim_style_is_annotative( - doc, - &dimension.base.style_name, - ), + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Arc(_)) => + { + crate::scene::annotative::dim_style_is_annotative( + doc, + &dimension.base().style_name, + ) + } codec::EntityType::Tolerance(_) => { crate::scene::annotative::annotation_style_is_annotative(doc, entity) } @@ -1530,7 +1532,9 @@ impl OpenCADStudio { "annotative", yes_no_choice(t.is_annotative || is_anno), ), - codec::EntityType::Dimension(codec::entities::Dimension::Arc(_)) => { + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Arc(_)) => + { set_row( &mut sections, "annotative", @@ -1683,10 +1687,14 @@ impl OpenCADStudio { format!("{} ({})", t!("Surface"), t!("Extrusion")) } // The reference names an angular dimension by its kind. - codec::EntityType::Dimension(codec::entities::Dimension::Angular2Ln(_)) => { + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Angular2Ln(_)) => + { t!("Angular Dimension").into_owned() } - codec::EntityType::Dimension(codec::entities::Dimension::Angular3Pt(_)) => { + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Angular3Pt(_)) => + { t!("3 Point Angular Dimension").into_owned() } codec::EntityType::Underlay(underlay) => match underlay.underlay_type { @@ -1719,22 +1727,14 @@ impl OpenCADStudio { title } else { use codec::entities::Dimension; - match entity { - codec::EntityType::Dimension(Dimension::Aligned(_)) => { - t!("Aligned Dimensional Constraint") - } - codec::EntityType::Dimension(Dimension::Angular2Ln(_)) => { - t!("Angular Dimension (Dynamic)") - } - codec::EntityType::Dimension(Dimension::Angular3Pt(_)) => { + match crate::entities::dimension::as_dimension(entity) { + Some(Dimension::Aligned(_)) => t!("Aligned Dimensional Constraint"), + Some(Dimension::Angular2Ln(_)) => t!("Angular Dimension (Dynamic)"), + Some(Dimension::Angular3Pt(_)) => { t!("3 Point Angular Dimension (Dynamic)") } - codec::EntityType::Dimension(Dimension::Radius(_)) => { - t!("Radius Dimensional Constraint") - } - codec::EntityType::Dimension(Dimension::Diameter(_)) => { - t!("Diameter Dimensional Constraint") - } + Some(Dimension::Radius(_)) => t!("Radius Dimensional Constraint"), + Some(Dimension::Diameter(_)) => t!("Diameter Dimensional Constraint"), _ => t!("Linear Dimensional Constraint"), } .into_owned() @@ -2743,7 +2743,7 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} // scale are available. if let codec::EntityType::Dimension(dim) = contextual.as_ref() { if matches!( - dim, + &**dim, codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) ) && !dim.base().text_user_positioned @@ -2780,13 +2780,17 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} } } } - let dynamic_angle = match contextual.as_ref() { - codec::EntityType::Dimension( - dim @ (codec::entities::Dimension::Angular2Ln(_) - | codec::entities::Dimension::Angular3Pt(_)), - ) if self.tabs[i].scene.is_dynamic_dimension(handle) => Some(dim), - _ => None, - }; + let contextual_dimension = + crate::entities::dimension::as_dimension(contextual.as_ref()); + let dynamic_angle = contextual_dimension + .filter(|dim| { + matches!( + dim, + codec::entities::Dimension::Angular2Ln(_) + | codec::entities::Dimension::Angular3Pt(_) + ) + }) + .filter(|_| self.tabs[i].scene.is_dynamic_dimension(handle)); if let Some(dim) = dynamic_angle { // A dynamic angle shows a triangle at each end of its arc // pointing away from it, and squares at the arc point and @@ -3060,8 +3064,8 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} ) -> Option { let i = self.active_tab; let tracks_dimension_chain = matches!( - &entity, - codec::EntityType::Dimension( + crate::entities::dimension::as_dimension(&entity), + Some( codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) | codec::entities::Dimension::Angular2Ln(_) diff --git a/src/app/update/block_ops_tests.rs b/src/app/update/block_ops_tests.rs index 8afcf5910..5d3c49121 100644 --- a/src/app/update/block_ops_tests.rs +++ b/src/app/update/block_ops_tests.rs @@ -224,7 +224,7 @@ fn fixture_dimension_reference(app: &mut OpenCADStudio) -> String { dimension.base.style_name = "BO_ARROWSTYLE".to_string(); app.tabs[i] .scene - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))); name.to_string() } @@ -244,7 +244,7 @@ fn fixture_dimension_name_reference(app: &mut OpenCADStudio) -> String { dimension.base.style_name = "BO_ARROWNAMESTYLE".to_string(); app.tabs[i] .scene - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))); name.to_string() } diff --git a/src/app/update/command.rs b/src/app/update/command.rs index 2d2a8ca8e..83e6fbc47 100644 --- a/src/app/update/command.rs +++ b/src/app/update/command.rs @@ -2913,9 +2913,12 @@ impl OpenCADStudio { &value, ); if applied && field == "dim_text_inside" { - if let Some(codec::EntityType::Dimension( - codec::entities::Dimension::LargeRadial(dimension), - )) = app.tabs[i].scene.document.get_entity_mut(handle) + let radial = app.tabs[i] + .scene + .document + .get_entity_mut(handle) + .and_then(crate::entities::dimension::as_dimension_mut); + if let Some(codec::entities::Dimension::LargeRadial(dimension)) = radial { dimension.base.text_user_positioned = false; } @@ -4182,9 +4185,13 @@ impl OpenCADStudio { &val, ); if applied && field == "dim_text_inside" { - if let Some(codec::EntityType::Dimension( - codec::entities::Dimension::LargeRadial(dimension), - )) = self.tabs[i].scene.document.get_entity_mut(handle) + if let Some(codec::entities::Dimension::LargeRadial( + dimension, + )) = self.tabs[i] + .scene + .document + .get_entity_mut(handle) + .and_then(crate::entities::dimension::as_dimension_mut) { dimension.base.text_user_positioned = false; } diff --git a/src/app/update/graphic_attributes.rs b/src/app/update/graphic_attributes.rs index 3157cd1bc..d34314779 100644 --- a/src/app/update/graphic_attributes.rs +++ b/src/app/update/graphic_attributes.rs @@ -1084,7 +1084,7 @@ mod tests { .document .entities() .filter_map(|entity| match entity { - EntityType::Hatch(hatch) => Some(hatch), + EntityType::Hatch(hatch) => Some(&**hatch), _ => None, }) .collect() diff --git a/src/app/viewport_dimension_tests.rs b/src/app/viewport_dimension_tests.rs index 0866e4f8d..94f0bd326 100644 --- a/src/app/viewport_dimension_tests.rs +++ b/src/app/viewport_dimension_tests.rs @@ -28,7 +28,7 @@ fn fixture() -> (OpenCADStudio, Handle, ViewportFrame) { viewport.custom_scale = 0.1; viewport.view_direction = Vector3::UNIT_Z; viewport.turn_on(); - let viewport = scene.add_entity(EntityType::Viewport(viewport)); + let viewport = scene.add_entity(EntityType::Viewport(Box::new(viewport))); let frame = scene.viewport_frame(viewport).unwrap(); scene.document.header.dimension_associativity = 2; let i = app.active_tab; @@ -323,7 +323,7 @@ fn viewport_dimension_linear_aligned_and_radial_object_picks() { assert_eq!( preview_text( &app, - &EntityType::Dimension(dimension(&app.tabs[i].scene.document).clone()) + &EntityType::Dimension(Box::new(dimension(&app.tabs[i].scene.document).clone())) ), value, "{name}" @@ -361,7 +361,7 @@ fn viewport_dimension_angular_preserves_angle_without_length_factor() { let _ = app.feed_command(StepInput::Point(place)); let doc = &app.tabs[app.active_tab].scene.document; assert_eq!( - preview_text(&app, &EntityType::Dimension(dimension(doc).clone())), + preview_text(&app, &EntityType::Dimension(Box::new(dimension(doc).clone()))), value ); assert!((dimension(doc).measurement() - 90.0).abs() < 1e-5); @@ -1461,9 +1461,9 @@ fn viewport_dimension_invalid_paths_leave_no_partial_association() { Vector3::new(55.0, 60.0, 0.0), ))); for (source, path) in [(model, vec![Handle::new(u64::MAX)]), (leaf, vec![root])] { - let dim = scene.add_entity(EntityType::Dimension(Dimension::Aligned( + let dim = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Aligned( DimensionAligned::new(Vector3::new(50.0, 50.0, 0.0), Vector3::new(55.0, 50.0, 0.0)), - ))); + )))); let invalid = AcceptedSnap { paper_point: DVec3::new(50.0, 50.0, 0.0), model_point: DVec3::ZERO, diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index 9b3eb9129..7c2bc8d6d 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -3248,7 +3248,7 @@ pub(crate) fn materialize_large_radial_text_position( let Some(EntityType::Dimension(dimension)) = document.get_entity(handle) else { return; }; - if !matches!(dimension, Dimension::LargeRadial(_)) || dimension.base().text_user_positioned { + if !matches!(&**dimension, Dimension::LargeRadial(_)) || dimension.base().text_user_positioned { return; } let source = document.dim_styles.iter().find(|style| { @@ -3262,8 +3262,8 @@ pub(crate) fn materialize_large_radial_text_position( .map(|style| resolved_dimension_style(style, dimension, document)) .map(|style| styled_dimension_text_position(dimension, &style, 1.0)) .unwrap_or_else(|| dimension_text_pos_f64(dimension, None, 2.5, 1.0)); - if let Some(EntityType::Dimension(Dimension::LargeRadial(radial))) = - document.get_entity_mut(handle) + if let Some(Dimension::LargeRadial(radial)) = + document.get_entity_mut(handle).and_then(as_dimension_mut) { radial.base.text_middle_point = position; } @@ -6491,7 +6491,7 @@ fn dimension_text_entity( } mtext.normal = base.normal; mtext.common = base.common.clone(); - return Some(EntityType::MText(mtext)); + return Some(EntityType::MText(Box::new(mtext))); } let value = if style.is_some_and(|style| style.dimtxtdirection) { @@ -7150,7 +7150,7 @@ fn dimension_tolerance_entity( mtext.style = primary_style; mtext.attachment_point = codec::entities::AttachmentPoint::MiddleCenter; mtext.common = primary_common; - return Some(EntityType::MText(mtext)); + return Some(EntityType::MText(Box::new(mtext))); } let mut t = Text::with_value(tol, pos) @@ -9559,3 +9559,22 @@ mod layout_parity_tests { ); } } + +/// The dimension an entity is, if it is one. The variant holds it boxed, so +/// a pattern cannot reach into it; match on this instead. +pub(crate) fn as_dimension(entity: &codec::EntityType) -> Option<&codec::entities::Dimension> { + match entity { + codec::EntityType::Dimension(dimension) => Some(dimension), + _ => None, + } +} + +/// [`as_dimension`], mutably. +pub(crate) fn as_dimension_mut( + entity: &mut codec::EntityType, +) -> Option<&mut codec::entities::Dimension> { + match entity { + codec::EntityType::Dimension(dimension) => Some(dimension), + _ => None, + } +} diff --git a/src/entities/object_data.rs b/src/entities/object_data.rs index d55d2cf86..71f9116bd 100644 --- a/src/entities/object_data.rs +++ b/src/entities/object_data.rs @@ -620,7 +620,7 @@ fn dynamic_data_text(data: &DynamicBlockData) -> String { "{}; dependencies {}; parameters {}; distance multiplier {:.6}; angle {:.6}", value.action.element.name, value.action.dependencies.len(), - value.action.parameter_ids.len(), + value.action.action_ids.len(), value.offsets.distance_multiplier, value.offsets.angle_offset ), @@ -628,14 +628,14 @@ fn dynamic_data_text(data: &DynamicBlockData) -> String { "{}; dependencies {}; parameters {}; connections {}", value.action.element.name, value.action.dependencies.len(), - value.action.parameter_ids.len(), + value.action.action_ids.len(), value.connections.len() ), DynamicBlockData::RotateAction(value) | DynamicBlockData::ScaleAction(value) => format!( "{}; dependencies {}; parameters {}; base {:.6},{:.6},{:.6}; dependent {}", value.action.action.element.name, value.action.action.dependencies.len(), - value.action.action.parameter_ids.len(), + value.action.action.action_ids.len(), value.action.base_point.x, value.action.base_point.y, value.action.base_point.z, diff --git a/src/entities/text_support.rs b/src/entities/text_support.rs index 16e827685..6d8b9d361 100644 --- a/src/entities/text_support.rs +++ b/src/entities/text_support.rs @@ -676,7 +676,9 @@ pub fn adapt_mtext_paragraphs( ATab::Left(_) => TabKind::Left, ATab::Center(_) => TabKind::Center, ATab::Right(_) => TabKind::Right, - ATab::Decimal(..) => TabKind::Decimal, + ATab::Decimal(..) | ATab::DecimalWithCharacter { .. } => { + TabKind::Decimal + } }; TabStop { position: ts.position() as f32 * entity_height, diff --git a/src/entities/traits.rs b/src/entities/traits.rs index 4fc27b30a..9a95575b7 100644 --- a/src/entities/traits.rs +++ b/src/entities/traits.rs @@ -158,6 +158,16 @@ pub trait TextContent { fn replace_text(&mut self, search: &str, rep: &str); } +/// Entity variants holding their entity boxed (MTEXT) dispatch through here. +impl TextContent for Box { + fn text_content(&self) -> Option { + (**self).text_content() + } + fn replace_text(&mut self, search: &str, rep: &str) { + (**self).replace_text(search, rep) + } +} + /// Human-readable variant name used by Quick Select / Select Similar /// filtering. Stable across releases — the strings here are the canonical /// type identifiers throughout the UI. diff --git a/src/entity_creation.rs b/src/entity_creation.rs index f07bfa678..96e5c29c4 100644 --- a/src/entity_creation.rs +++ b/src/entity_creation.rs @@ -638,7 +638,7 @@ pub(crate) fn build_entity( if let Some(style) = text_style_field(spec, document)? { mtext.style = style; } - EntityType::MText(mtext) + EntityType::MText(Box::new(mtext)) } "INSERT" => { let block = spec["block"].as_str().unwrap_or(""); @@ -724,7 +724,7 @@ pub(crate) fn build_entity( let mut path = BoundaryPath::external(); path.add_edge(BoundaryEdge::Polyline(PolylineEdge::new(vertices, true))); hatch.paths.push(path); - EntityType::Hatch(hatch) + EntityType::Hatch(Box::new(hatch)) } other => { return Err(failure( diff --git a/src/io/linetypes.rs b/src/io/linetypes.rs index f029496e5..7afc4b8ba 100644 --- a/src/io/linetypes.rs +++ b/src/io/linetypes.rs @@ -472,6 +472,7 @@ fn complex_elements( scale: decimal(*scale), rotation: decimal(*rot_deg).to_radians(), absolute_rotation: false, + source_flags: 0, offset: [decimal(*x), decimal(*y)], } } @@ -492,6 +493,7 @@ fn complex_elements( scale: decimal(*scale), rotation: decimal(*rot_deg).to_radians(), absolute_rotation: false, + source_flags: 0, offset: [decimal(*x), decimal(*y)], }, }; diff --git a/src/io/mod.rs b/src/io/mod.rs index 11392d93f..a0e639614 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -2969,7 +2969,7 @@ mod dimension_arrow_save_tests { dimension.definition_point = Vector3::new(0.0, 20.0, 0.0); dimension.base.definition_point = dimension.definition_point; dimension.base.text_middle_point = Vector3::new(50.0, 20.0, 0.0); - doc.add_entity(EntityType::Dimension(Dimension::Linear(dimension))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))) .unwrap(); doc } @@ -3545,11 +3545,12 @@ mod prepare_save_tests { dim.base.definition_point = Vector3::ZERO; dim.base.common.handle = doc.allocate_handle(); let handle = dim.base.common.handle; - doc.add_entity(EntityType::Dimension(Dimension::Linear(dim))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))) .unwrap(); let prepared = prepare_document_for_save(doc.clone(), doc.version); - let EntityType::Dimension(Dimension::Linear(linear)) = prepared.get_entity(handle).unwrap() + let Some(Dimension::Linear(linear)) = + crate::entities::dimension::as_dimension(prepared.get_entity(handle).unwrap()) else { panic!("dimension missing from prepared clone"); }; @@ -3565,7 +3566,9 @@ mod prepare_save_tests { assert_eq!(linear.base.definition_point, linear.definition_point); // The live document is untouched: no block name, stale group-10. - let EntityType::Dimension(Dimension::Linear(live)) = doc.get_entity(handle).unwrap() else { + let Some(Dimension::Linear(live)) = + crate::entities::dimension::as_dimension(doc.get_entity(handle).unwrap()) + else { panic!("dimension missing from live document"); }; assert!(live.base.block_name.is_empty()); @@ -3582,7 +3585,7 @@ mod prepare_save_tests { let mut dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); dim.base.common.handle = doc.allocate_handle(); - doc.add_entity(EntityType::Dimension(Dimension::Linear(dim))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))) .unwrap(); for ext in ["dwg", "dxf"] { let inline = save_to_bytes(&doc, ext, codec::DxfVersion::AC1032).expect("inline"); diff --git a/src/io/ole_embed.rs b/src/io/ole_embed.rs index c82e93cdc..29a87cec3 100644 --- a/src/io/ole_embed.rs +++ b/src/io/ole_embed.rs @@ -168,7 +168,7 @@ pub fn add_embedded_image( ) -> Result { let (upper_left, lower_right) = corners_from_placement(origin, width, image.aspect()); let ole = build_embedded_ole(image, upper_left, lower_right); - doc.add_entity(codec::EntityType::Ole2Frame(ole)) + doc.add_entity(codec::EntityType::Ole2Frame(Box::new(ole))) .map_err(|e| e.to_string()) } diff --git a/src/io/xref.rs b/src/io/xref.rs index 541362102..13c34f34f 100644 --- a/src/io/xref.rs +++ b/src/io/xref.rs @@ -3336,7 +3336,7 @@ mod tests { // Hatch (pattern names have no table — preserved verbatim). let mut hatch = codec::entities::Hatch::new(); hatch.pattern.name = "ANSI31".to_string(); - doc.add_entity(codec::EntityType::Hatch(hatch)).unwrap(); + doc.add_entity(codec::EntityType::Hatch(Box::new(hatch))).unwrap(); // Dim-style reference via a tolerance entity. doc.dim_styles .add(codec::tables::DimStyle::new("ARCH")) diff --git a/src/modules/annotate/aligned_dim.rs b/src/modules/annotate/aligned_dim.rs index ea0e326d6..5d62c941e 100644 --- a/src/modules/annotate/aligned_dim.rs +++ b/src/modules/annotate/aligned_dim.rs @@ -95,7 +95,7 @@ pub(crate) fn aligned_dimension_entity( crate::entities::dimension::reset_automatic_text_position(&mut dim.base); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override); - EntityType::Dimension(Dimension::Aligned(dim)) + EntityType::Dimension(Box::new(Dimension::Aligned(dim))) } impl CadCommand for AlignedDimensionCommand { diff --git a/src/modules/annotate/angular_dim.rs b/src/modules/annotate/angular_dim.rs index e101214fd..309d379e0 100644 --- a/src/modules/annotate/angular_dim.rs +++ b/src/modules/annotate/angular_dim.rs @@ -232,7 +232,7 @@ impl AngularDimensionCommand { } fn commit(&self, dimension: Dimension) -> CmdResult { - let entity = self.plane.place_entity(EntityType::Dimension(dimension)); + let entity = self.plane.place_entity(EntityType::Dimension(Box::new(dimension))); CmdResult::CommitDimension { entity, association: DimensionAssociationInput::Explicit(self.source_refs.clone()), @@ -1242,7 +1242,7 @@ pub(crate) fn angular_two_line_entity( dim.base.insertion_point = dim.dimension_arc; dim.base.actual_measurement = dim.measurement_degrees(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Angular2Ln(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Angular2Ln(dim)))) } /// A three-point angular dimension (vertex, two points, arc point), for a @@ -1261,7 +1261,7 @@ pub(crate) fn angular_three_point_entity( dim.base.insertion_point = dim.definition_point; dim.base.actual_measurement = dim.measurement_degrees(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Angular3Pt(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Angular3Pt(dim)))) } fn v3(point: DVec3) -> Vector3 { diff --git a/src/modules/annotate/arc_length_dim.rs b/src/modules/annotate/arc_length_dim.rs index 7dcfc758e..bd2476b9a 100644 --- a/src/modules/annotate/arc_length_dim.rs +++ b/src/modules/annotate/arc_length_dim.rs @@ -258,7 +258,7 @@ impl ArcLengthDimensionCommand { |handle| DimensionAssociationInput::Explicit(selection.association_sources(handle)), ); CmdResult::CommitDimension { - entity: plane.place_entity(EntityType::Dimension(Dimension::Arc(dimension))), + entity: plane.place_entity(EntityType::Dimension(Box::new(Dimension::Arc(dimension)))), association, preserve_base_style: false, continue_command: false, diff --git a/src/modules/annotate/diameter_dim.rs b/src/modules/annotate/diameter_dim.rs index 800370674..1dad74115 100644 --- a/src/modules/annotate/diameter_dim.rs +++ b/src/modules/annotate/diameter_dim.rs @@ -83,7 +83,7 @@ impl DiameterDimensionCommand { if let Some(angle) = self.text_angle { dim.base.text_rotation = angle; } - plane.place_entity(EntityType::Dimension(Dimension::Diameter(dim))) + plane.place_entity(EntityType::Dimension(Box::new(Dimension::Diameter(dim)))) } } @@ -103,7 +103,7 @@ pub(crate) fn diameter_constraint_entity( dim.leader_length = chord.distance(location).max(radius * 0.5); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Diameter(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Diameter(dim)))) } impl CadCommand for DiameterDimensionCommand { diff --git a/src/modules/annotate/dim_baseline.rs b/src/modules/annotate/dim_baseline.rs index 23612384c..4d2e862e8 100644 --- a/src/modules/annotate/dim_baseline.rs +++ b/src/modules/annotate/dim_baseline.rs @@ -151,7 +151,7 @@ impl DimBaselineCommand { let increment = self.effective_increment(&style.style_name); let plane = plane_from_normal(dimension.base().definition_point, style.normal); let pick = pick.and_then(|point| plane.project(point.to_array()).map(Vec2::from)); - let kind = match dimension { + let kind = match &**dimension { Dimension::Linear(source) => { let first = project(&plane, source.first_point); let second = project(&plane, source.second_point); @@ -441,7 +441,7 @@ impl CadCommand for DimBaselineCommand { self.committed += 1; self.advance(1.0); CmdResult::CommitDimension { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), association: DimensionAssociationInput::Infer(None), preserve_base_style: self.preserve_base_style, continue_command: true, @@ -489,7 +489,7 @@ impl CadCommand for DimBaselineCommand { fn dimension_preview(&self, cursor: DVec3) -> Option> { self.build_dimension(cursor).map(|dimension| { vec![DimensionPreview { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), preserve_base_style: self.preserve_base_style, }] }) diff --git a/src/modules/annotate/dim_continue.rs b/src/modules/annotate/dim_continue.rs index 8922e019b..1496f956d 100644 --- a/src/modules/annotate/dim_continue.rs +++ b/src/modules/annotate/dim_continue.rs @@ -117,7 +117,7 @@ impl DimContinueCommand { let style = SourceStyle::from_base(dimension.base()); let plane = plane_from_normal(dimension.base().definition_point, style.normal); let pick = pick_world.and_then(|point| plane.project(point.to_array()).map(Vec2::from)); - let kind = match dimension { + let kind = match &**dimension { Dimension::Linear(source) => { let rotation = source.rotation; let perpendicular = Vec2::new(-rotation.sin(), rotation.cos()); @@ -383,7 +383,7 @@ impl CadCommand for DimContinueCommand { } self.advance(point); CmdResult::CommitDimension { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), association: DimensionAssociationInput::Infer(None), preserve_base_style: self.preserve_base_style, continue_command: true, @@ -433,7 +433,7 @@ impl CadCommand for DimContinueCommand { fn dimension_preview(&self, cursor: DVec3) -> Option> { self.build_dimension(cursor).map(|dimension| { vec![DimensionPreview { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), preserve_base_style: self.preserve_base_style, }] }) diff --git a/src/modules/annotate/dimjogline.rs b/src/modules/annotate/dimjogline.rs index a80260e16..b63527637 100644 --- a/src/modules/annotate/dimjogline.rs +++ b/src/modules/annotate/dimjogline.rs @@ -145,13 +145,17 @@ impl CadCommand for DimJogLineCommand { } fn on_entity_pick(&mut self, handle: Handle, _point: DVec3) -> CmdResult { - let Some(EntityType::Dimension(dimension @ (Dimension::Linear(_) | Dimension::Aligned(_)))) = - self.picked_entity.take() - else { + let Some(EntityType::Dimension(dimension)) = self.picked_entity.take() else { return CmdResult::ReportError( t!("DIMJOGLINE: select a linear or aligned dimension.").into_owned(), ); }; + let dimension = *dimension; + if !matches!(dimension, Dimension::Linear(_) | Dimension::Aligned(_)) { + return CmdResult::ReportError( + t!("DIMJOGLINE: select a linear or aligned dimension.").into_owned(), + ); + } if handle.is_null() { return CmdResult::NeedPoint; } diff --git a/src/modules/annotate/dimspace.rs b/src/modules/annotate/dimspace.rs index ef0ef9e64..8c5959ff8 100644 --- a/src/modules/annotate/dimspace.rs +++ b/src/modules/annotate/dimspace.rs @@ -104,8 +104,8 @@ impl CadCommand for DimSpaceCommand { for selected in entities { if selected.handle != *base && matches!( - selected.entity, - EntityType::Dimension( + crate::entities::dimension::as_dimension(&selected.entity), + Some( codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) ) @@ -124,11 +124,14 @@ impl CadCommand for DimSpaceCommand { match &mut self.step { Step::PickBase => { if !matches!( - self.picked_entity.take(), - Some(EntityType::Dimension( + self.picked_entity + .take() + .as_ref() + .and_then(crate::entities::dimension::as_dimension), + Some( codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - )) + ) ) { return CmdResult::ReportError( t!("DIMSPACE: select a linear or aligned dimension.").into_owned(), diff --git a/src/modules/annotate/field_cmd.rs b/src/modules/annotate/field_cmd.rs index 7ab6a2920..6d24ae657 100644 --- a/src/modules/annotate/field_cmd.rs +++ b/src/modules/annotate/field_cmd.rs @@ -158,7 +158,7 @@ impl CadCommand for FieldPlaceCommand { mtext.attachment_point = self.attachment; // No defined width: the field text never wraps. mtext.rectangle_width = 0.0; - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(mtext))) + CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(Box::new(mtext)))) } fn on_enter(&mut self) -> CmdResult { diff --git a/src/modules/annotate/jogged_radius_dim.rs b/src/modules/annotate/jogged_radius_dim.rs index f566d5bf8..fe43b88bb 100644 --- a/src/modules/annotate/jogged_radius_dim.rs +++ b/src/modules/annotate/jogged_radius_dim.rs @@ -138,7 +138,9 @@ impl JoggedRadiusDimensionCommand { ); CmdResult::CommitDimension { - entity: plane.place_entity(EntityType::Dimension(Dimension::LargeRadial(dimension))), + entity: plane.place_entity(EntityType::Dimension(Box::new(Dimension::LargeRadial( + dimension, + )))), association, preserve_base_style: false, continue_command: false, diff --git a/src/modules/annotate/leader_cmd.rs b/src/modules/annotate/leader_cmd.rs index 654c7c281..6f03e83f1 100644 --- a/src/modules/annotate/leader_cmd.rs +++ b/src/modules/annotate/leader_cmd.rs @@ -151,7 +151,7 @@ impl LeaderCommand { CmdResult::CommitManyAndEditText { entities: vec![ self.plane.place_entity(EntityType::Leader(leader)), - self.plane.place_entity(EntityType::MText(mtext)), + self.plane.place_entity(EntityType::MText(Box::new(mtext))), ], edit_index: 1, open_editor, diff --git a/src/modules/annotate/linear_dim.rs b/src/modules/annotate/linear_dim.rs index c997067cd..ee365950e 100644 --- a/src/modules/annotate/linear_dim.rs +++ b/src/modules/annotate/linear_dim.rs @@ -141,7 +141,7 @@ pub(crate) fn linear_dimension_entity( crate::entities::dimension::reset_automatic_text_position(&mut dim.base); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override); - EntityType::Dimension(Dimension::Linear(dim)) + EntityType::Dimension(Box::new(Dimension::Linear(dim))) } impl CadCommand for LinearDimensionCommand { diff --git a/src/modules/annotate/mleader_cmd.rs b/src/modules/annotate/mleader_cmd.rs index 81eef14ea..c1cc4cab8 100644 --- a/src/modules/annotate/mleader_cmd.rs +++ b/src/modules/annotate/mleader_cmd.rs @@ -648,7 +648,7 @@ impl CadCommand for MLeaderCommand { text.insertion_point.z, )); self.text = text.value.clone(); - self.selected_mtext = Some(text); + self.selected_mtext = Some(*text); self.content_type = LeaderContentType::MText; self.order = CreationOrder::ContentFirst; self.step = Step::PickPoints; diff --git a/src/modules/annotate/ordinate_dim.rs b/src/modules/annotate/ordinate_dim.rs index 0aa9ddb48..b8dff08b5 100644 --- a/src/modules/annotate/ordinate_dim.rs +++ b/src/modules/annotate/ordinate_dim.rs @@ -80,7 +80,7 @@ impl OrdinateDimCommand { } dim.refresh_measurement(); self.plane - .place_entity(EntityType::Dimension(Dimension::Ordinate(dim))) + .place_entity(EntityType::Dimension(Box::new(Dimension::Ordinate(dim)))) } } diff --git a/src/modules/annotate/qdim.rs b/src/modules/annotate/qdim.rs index 3f1f2357a..e60029e5c 100644 --- a/src/modules/annotate/qdim.rs +++ b/src/modules/annotate/qdim.rs @@ -341,7 +341,7 @@ impl QdimCommand { ]); ( self.plane - .place_entity(EntityType::Dimension(Dimension::Linear(dimension))), + .place_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))), association, ) } @@ -366,7 +366,7 @@ impl QdimCommand { dimension.refresh_measurement(); ( self.plane - .place_entity(EntityType::Dimension(Dimension::Ordinate(dimension))), + .place_entity(EntityType::Dimension(Box::new(Dimension::Ordinate(dimension)))), DimensionAssociationInput::Explicit(vec![point.sources.first().copied()]), ) } @@ -405,7 +405,7 @@ impl QdimCommand { dimension.base.text_user_positioned = true; dimension.leader_length = chord.distance(text); dimension.base.actual_measurement = dimension.measurement(); - EntityType::Dimension(Dimension::Radius(dimension)) + EntityType::Dimension(Box::new(Dimension::Radius(dimension))) } else { let opposite = center - direction * radius; let mut dimension = DimensionDiameter::new(v3(chord), v3(opposite)); @@ -415,7 +415,7 @@ impl QdimCommand { dimension.base.text_user_positioned = true; dimension.leader_length = chord.distance(text); dimension.base.actual_measurement = dimension.measurement(); - EntityType::Dimension(Dimension::Diameter(dimension)) + EntityType::Dimension(Box::new(Dimension::Diameter(dimension))) }; (self.plane.place_entity(entity), association) }) @@ -680,7 +680,7 @@ fn preview_entity(index: usize, entity: &EntityType) -> Vec { return Vec::new(); }; let mut lines: Vec> = Vec::new(); - match dimension { + match &**dimension { Dimension::Linear(value) => { let first = d3(value.first_point); let second = d3(value.second_point); diff --git a/src/modules/annotate/radius_dim.rs b/src/modules/annotate/radius_dim.rs index 435ae9277..7a8d79f93 100644 --- a/src/modules/annotate/radius_dim.rs +++ b/src/modules/annotate/radius_dim.rs @@ -93,7 +93,7 @@ pub(crate) fn radial_dimension_entity( if let Some(angle) = text_angle { dim.base.text_rotation = angle; } - plane.place_entity(EntityType::Dimension(Dimension::Radius(dim))) + plane.place_entity(EntityType::Dimension(Box::new(Dimension::Radius(dim)))) } /// A radius dimension for a dimensional constraint: the leader leaves the @@ -111,7 +111,7 @@ pub(crate) fn radius_constraint_entity( dim.leader_length = chord.distance(location).max(radius * 0.5); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Radius(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Radius(dim)))) } /// The unit direction a radial constraint's dimension points in, from the diff --git a/src/modules/annotate/txt2mtxt.rs b/src/modules/annotate/txt2mtxt.rs index c0970a8aa..bd55200be 100644 --- a/src/modules/annotate/txt2mtxt.rs +++ b/src/modules/annotate/txt2mtxt.rs @@ -222,7 +222,7 @@ fn separate(p: &Piece, doc: &CadDocument) -> Vec { let at = p.point(p.rect[0] + x * (p.rect[1] - p.rect[0]), p.rect[3]); let mut m = mtext_from(p.entity, p.content.clone(), at, p.height, p.rotation); m.attachment_point = attachment; - vec![EntityType::MText(m)] + vec![EntityType::MText(Box::new(m))] } EntityType::MText(m) => { // The drawn words, grouped into lines by their baseline. @@ -261,7 +261,8 @@ fn separate(p: &Piece, doc: &CadDocument) -> Vec { .collect::>() .join(" "); let at = p.point(line[0].0 - origin_along, p.rect[3] - k as f64 * step); - EntityType::MText(mtext_from(p.entity, value, at, line[0].1.height, m.rotation)) + let height = line[0].1.height; + EntityType::MText(Box::new(mtext_from(p.entity, value, at, height, m.rotation))) }) .collect() } @@ -352,7 +353,7 @@ pub fn plan( } Some(Txt2MtxtPlan { erase: pieces.iter().map(|p| p.handle).collect(), - add: vec![EntityType::MText(m)], + add: vec![EntityType::MText(Box::new(m))], }) } diff --git a/src/modules/draw/clipboard/pastespec.rs b/src/modules/draw/clipboard/pastespec.rs index cbbefc93f..cc770ed7b 100644 --- a/src/modules/draw/clipboard/pastespec.rs +++ b/src/modules/draw/clipboard/pastespec.rs @@ -113,7 +113,7 @@ impl CadCommand for PasteSpecCommand { mtext.style = self.style.clone(); mtext.attachment_point = AttachmentPoint::TopLeft; mtext.rectangle_width = 0.0; - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(mtext))) + CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(Box::new(mtext)))) } fn on_enter(&mut self) -> CmdResult { diff --git a/src/modules/draw/draw/hatchedit.rs b/src/modules/draw/draw/hatchedit.rs index e05a26400..8acb6989d 100644 --- a/src/modules/draw/draw/hatchedit.rs +++ b/src/modules/draw/draw/hatchedit.rs @@ -925,7 +925,7 @@ mod tests { })); } hatch.paths.push(path); - let entity = EntityType::Hatch(hatch); + let entity = EntityType::Hatch(Box::new(hatch)); HatcheditCommand::with_handle(Handle::new(7), "ANSI31".into(), 1.0, 0.0, false) .with_appearance(Some(&entity), Color::Index(6), Transparency::T_40) .with_origin([9.0, 8.0]) @@ -1096,7 +1096,7 @@ mod tests { counter_clockwise: true, })); hatch.paths.push(path); - let entity = EntityType::Hatch(hatch); + let entity = EntityType::Hatch(Box::new(hatch)); let mut command = HatcheditCommand::with_handle(Handle::new(7), "ANSI31".into(), 1.0, 0.0, false) .with_appearance(Some(&entity), Color::ByLayer, Transparency::ByLayer); diff --git a/src/modules/draw/draw/raster_image.rs b/src/modules/draw/draw/raster_image.rs index 27b10c863..da1015837 100644 --- a/src/modules/draw/draw/raster_image.rs +++ b/src/modules/draw/draw/raster_image.rs @@ -104,7 +104,7 @@ impl ImageCommand { let (upper_left, lower_right) = corners_from_placement(ins, world_width, self.aspect()); let ole = build_embedded_ole(image, upper_left, lower_right); - self.plane.place_entity(EntityType::Ole2Frame(ole)) + self.plane.place_entity(EntityType::Ole2Frame(Box::new(ole))) } } } diff --git a/src/modules/draw/modify/explode.rs b/src/modules/draw/modify/explode.rs index 441909933..9e3c7c158 100644 --- a/src/modules/draw/modify/explode.rs +++ b/src/modules/draw/modify/explode.rs @@ -1439,7 +1439,7 @@ fn sync_dimension_base_points_and_collect_pending(doc: &mut CadDocument) -> Vec< let EntityType::Dimension(dimension) = entity else { return None; }; - let definition_point = match dimension { + let definition_point = match &**dimension { Dimension::Linear(value) => Some(value.definition_point), Dimension::Aligned(value) => Some(value.definition_point), Dimension::Radius(value) => Some(value.definition_point), @@ -1493,7 +1493,7 @@ pub fn bake_dimension_blocks(doc: &mut CadDocument) { let dimensions: Vec<(Handle, Dimension)> = pending .into_iter() .filter_map(|handle| match doc.get_entity(handle) { - Some(EntityType::Dimension(d)) => Some((handle, d.clone())), + Some(EntityType::Dimension(d)) => Some((handle, (**d).clone())), _ => None, }) .collect(); @@ -1654,7 +1654,7 @@ mod tests { d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); // block_name is left empty — exactly what OCS-created dimensions carry. let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); @@ -1693,7 +1693,7 @@ mod tests { // Exactly what OCS-created dimensions carry: insertion == text anchor. d.base.insertion_point = d.base.text_middle_point; let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); @@ -1720,7 +1720,7 @@ mod tests { d.definition_point = Vector3::new(0.0, 5.0, 0.0); d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); @@ -1798,7 +1798,7 @@ mod tests { d.rotation = 0.0; d.definition_point = Vector3::new(0.0, 8.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1827,7 +1827,7 @@ mod tests { let mut d = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); d.definition_point = Vector3::new(0.0, 5.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1875,7 +1875,7 @@ mod tests { .collect(); assert!(!expected.is_empty(), "the dimension explodes into no lines"); - let mut turned = EntityType::Dimension(flat); + let mut turned = EntityType::Dimension(Box::new(flat)); crate::scene::view::dispatch::apply_transform( &mut turned, &EntityTransform::Rotate { @@ -1911,7 +1911,7 @@ mod tests { ); d.definition_point = Vector3::new(5.0, 5.0, 0.0); // arc location let handle = doc - .add_entity(EntityType::Dimension(Dimension::Angular3Pt(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Angular3Pt(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1940,7 +1940,7 @@ mod tests { let mut d = DimensionDiameter::new(edge, far); d.base.text_middle_point = Vector3::new(3.0, 9.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Diameter(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Diameter(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1971,7 +1971,7 @@ mod tests { d.rotation = std::f64::consts::FRAC_PI_2; // 90°, vertical dimension line d.definition_point = Vector3::new(8.0, 0.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -2064,7 +2064,7 @@ mod tests { DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); d.definition_point = Vector3::new(0.0, 5.0, 0.0); d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); - doc.add_entity(EntityType::Dimension(Dimension::Linear(d))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); let path = @@ -2171,7 +2171,7 @@ mod tests { d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); d.base.common.xdictionary_handle = Some(dict_handle); let dim_handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); diff --git a/src/modules/insert/dgn_import.rs b/src/modules/insert/dgn_import.rs index 41b22f575..4b15efb03 100644 --- a/src/modules/insert/dgn_import.rs +++ b/src/modules/insert/dgn_import.rs @@ -262,7 +262,7 @@ fn mtext(lines: &[DgnGeom], style: String, node: bool) -> Option { m.rotation = *rotation; m.rectangle_width = 0.0; m.style = style; - Some(EntityType::MText(m)) + Some(EntityType::MText(Box::new(m))) } /// The object(s) one element converts to. diff --git a/src/modules/insert/pdf_import.rs b/src/modules/insert/pdf_import.rs index b8eb3c2bd..2c82251a5 100644 --- a/src/modules/insert/pdf_import.rs +++ b/src/modules/insert/pdf_import.rs @@ -1482,7 +1482,7 @@ pub fn convert( let layer = naming.layer(pdf_layer, Kind::Text); mtext.common.color = color_on(&layer, color_of(text.color)); mtext.common.layer = layer; - result.entities.push(EntityType::MText(mtext)); + result.entities.push(EntityType::MText(Box::new(mtext))); } } @@ -1712,7 +1712,7 @@ fn fill_entities( return Vec::new(); } hatch.elevation = z; - vec![EntityType::Hatch(hatch)] + vec![EntityType::Hatch(Box::new(hatch))] } inventory::submit!(crate::command::CommandRegistration { diff --git a/src/modules/layout/mvsetup.rs b/src/modules/layout/mvsetup.rs index 40b858ff1..50de2d2fb 100644 --- a/src/modules/layout/mvsetup.rs +++ b/src/modules/layout/mvsetup.rs @@ -144,7 +144,7 @@ impl MvsetupCommand { if self.arrangement == Arrangement::Engineering { viewport.view_direction = directions[(row * 2 + column) as usize].clone(); } - viewports.push(EntityType::Viewport(viewport)); + viewports.push(EntityType::Viewport(Box::new(viewport))); } } CmdResult::CommitEntitiesAndExit(viewports) diff --git a/src/scene/annotative.rs b/src/scene/annotative.rs index 9d1decb69..c7b287b29 100644 --- a/src/scene/annotative.rs +++ b/src/scene/annotative.rs @@ -322,7 +322,7 @@ pub fn supports_annotation_context(entity: &EntityType) -> bool { | EntityType::Tolerance(_) | EntityType::Hatch(_) => true, EntityType::Dimension(dimension) => { - !matches!(dimension, codec::entities::Dimension::Arc(_)) + !matches!(&**dimension, codec::entities::Dimension::Arc(_)) } _ => false, } diff --git a/src/scene/block_service.rs b/src/scene/block_service.rs index 5b20152d2..541321358 100644 --- a/src/scene/block_service.rs +++ b/src/scene/block_service.rs @@ -788,7 +788,7 @@ mod tests { dimension.base.block_name = "SVC_TARGET".to_string(); scene .document - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))) .unwrap(); // A table's picture block and a block-valued cell, by handle. @@ -894,7 +894,7 @@ mod tests { dimension.base.block_name = "SVC_RENAMED".to_string(); scene .document - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))) .unwrap(); let mut style = DimStyle::new("SVC_STYLE"); style.dimblk = target; diff --git a/src/scene/camera_ops.rs b/src/scene/camera_ops.rs index 62d728ded..179e4261b 100644 --- a/src/scene/camera_ops.rs +++ b/src/scene/camera_ops.rs @@ -479,7 +479,7 @@ impl Scene { self.previous_view = Some(ViewSnapshot::Floating { layout, handle, - viewport: Box::new(viewport.clone()), + viewport: viewport.clone(), }); return; } @@ -538,7 +538,7 @@ impl Scene { }); return false; } - let current = Box::new(current.clone()); + let current = current.clone(); if let Some(EntityType::Viewport(destination)) = self.document.get_entity_mut(handle) { diff --git a/src/scene/dimension_assoc.rs b/src/scene/dimension_assoc.rs index bbb40ae90..f6394d49e 100644 --- a/src/scene/dimension_assoc.rs +++ b/src/scene/dimension_assoc.rs @@ -869,7 +869,7 @@ pub(crate) fn constraint_from_associative_dimension( Some(ParametricRef::whole(*reference.xrefs.first()?)) }; let measurement = DrivingValue::Literal(dimension.measurement()); - match dimension { + match &**dimension { Dimension::Aligned(_) => Some(( ConstraintKind::Distance, vec![point(0)?, point(1)?], @@ -921,7 +921,7 @@ pub(crate) fn radial_extension_points( let EntityType::Dimension(dimension_entity) = document.get_entity(dimension)? else { return None; }; - let target_point = match dimension_entity { + let target_point = match &**dimension_entity { Dimension::Radius(radius) => radius.definition_point, Dimension::Diameter(diameter) => diameter.angle_vertex, Dimension::LargeRadial(radial) => radial.chord_point, @@ -1009,7 +1009,7 @@ impl Scene { else { return; }; - let radial_data = match dimension_entity { + let radial_data = match &**dimension_entity { Dimension::Radius(radius) => Some(( radius.angle_vertex, radius.measurement(), @@ -1223,7 +1223,7 @@ impl Scene { }; // Radial references identify a circle/arc and angle, rather than a vertex. let radial_dimension = matches!( - dimension_entity, + &**dimension_entity, Dimension::Radius(_) | Dimension::Diameter(_) | Dimension::LargeRadial(_) ); if radial_dimension { @@ -1383,7 +1383,7 @@ impl Scene { let Some(EntityType::Dimension(entity)) = self.document.get_entity(dimension) else { return Vec::new(); }; - match entity { + match &**entity { // A radial dimension's single reference describes the point where // the leader meets the circle. Dimension::Radius(radius) => vec![radius.definition_point], @@ -1458,17 +1458,15 @@ impl Scene { let measurement_supported = !association.trans_space || self.document.get_entity(dimension).is_some_and(|entity| { matches!( - entity, - EntityType::Dimension(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) + crate::entities::dimension::as_dimension(entity), + Some(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) ) || persisted_measurement_scale(&self.document, entity).is_some() }); let measurement_supported = measurement_supported && self.document.get_entity(dimension).is_some_and(|entity| { if !matches!( - entity, - EntityType::Dimension( - Dimension::Radius(_) | Dimension::Diameter(_) | Dimension::LargeRadial(_) - ) + crate::entities::dimension::as_dimension(entity), + Some(Dimension::Radius(_) | Dimension::Diameter(_) | Dimension::LargeRadial(_)) ) { return true; } @@ -1652,7 +1650,7 @@ impl Scene { let Some(EntityType::Dimension(entity)) = self.document.get_entity(dimension) else { return Vec::new(); }; - let radial_data = match entity { + let radial_data = match &**entity { Dimension::Radius(radius) => Some(( radius.angle_vertex, radius.measurement(), @@ -1850,8 +1848,8 @@ impl Scene { continue; }; let angular = matches!( - &before, - EntityType::Dimension(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) + crate::entities::dimension::as_dimension(&before), + Some(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) ); let measurement_scale = if let Some(frame) = map.frame.filter(|_| !angular) { let Some(mut scale) = persisted_measurement_scale(&self.document, &before) else { @@ -1874,7 +1872,7 @@ impl Scene { else { continue; }; - match dimension { + match &mut **dimension { Dimension::Linear(linear) => { // The sheet annotation the user placed — the dimension // line's standoff and, when they dragged it, the text — is @@ -2104,7 +2102,7 @@ impl Scene { arc.base.actual_measurement = arc.measurement(); } } - let measurement = match &*dimension { + let measurement = match &**dimension { Dimension::Linear(linear) => linear_measurement(linear), _ => dimension.measurement(), }; @@ -2155,8 +2153,12 @@ impl Scene { refreshed } pub(crate) fn sync_diameter_association_angle(&mut self, dimension: Handle) { - let chord = match self.document.get_entity(dimension) { - Some(EntityType::Dimension(Dimension::Diameter(diameter))) => diameter.angle_vertex, + let chord = match self + .document + .get_entity(dimension) + .and_then(crate::entities::dimension::as_dimension) + { + Some(Dimension::Diameter(diameter)) => diameter.angle_vertex, _ => return, }; @@ -2247,9 +2249,9 @@ mod tests { Vector3::ZERO, 5.0, ))); - let dimension = scene.add_entity(EntityType::Dimension(Dimension::Diameter( + let dimension = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Diameter( DimensionDiameter::new(Vector3::new(5.0, 0.0, 0.0), Vector3::new(-5.0, 0.0, 0.0)), - ))); + )))); scene.attach_dimension_association(dimension, vec![Some(circle)]); let association = scene .document @@ -2270,8 +2272,10 @@ mod tests { .expect("diameter association"); scene.begin_undo_recording(); - let Some(EntityType::Dimension(Dimension::Diameter(diameter))) = - scene.document.get_entity_mut(dimension) + let Some(Dimension::Diameter(diameter)) = scene + .document + .get_entity_mut(dimension) + .and_then(crate::entities::dimension::as_dimension_mut) else { panic!("diameter dimension"); }; diff --git a/src/scene/entity.rs b/src/scene/entity.rs index 2b6c14419..ac89c65c6 100644 --- a/src/scene/entity.rs +++ b/src/scene/entity.rs @@ -3206,7 +3206,7 @@ impl Scene { if let Some(origin) = model.pattern_origin { dxf.record_pattern_origin(Vector2::new(origin[0], origin[1])); } - let mut entity = EntityType::Hatch(dxf); + let mut entity = EntityType::Hatch(Box::new(dxf)); if let Some(layer) = layer { entity.as_entity_mut().set_layer(layer.to_string()); diff --git a/src/scene/layout.rs b/src/scene/layout.rs index a727d8fe7..d10d5d461 100644 --- a/src/scene/layout.rs +++ b/src/scene/layout.rs @@ -64,10 +64,10 @@ impl Scene { if let Some(EntityType::Viewport(sheet)) = self.document.get_entity(from.viewport).cloned() { if let Some(EntityType::Viewport(target)) = self.document.get_entity_mut(to.viewport) { - *target = codec::entities::Viewport { + *target = Box::new(codec::entities::Viewport { common: target.common.clone(), - ..sheet - }; + ..*sheet + }); } } self.unopened_layouts.remove(name); diff --git a/src/scene/mod.rs b/src/scene/mod.rs index d90117db5..a81d2f444 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -4956,7 +4956,7 @@ impl Scene { fit_sheet_viewport(&mut vp, min_lim, max_lim); if let Ok(handle) = self .document - .add_entity_to_layout(EntityType::Viewport(vp), layout_name) + .add_entity_to_layout(EntityType::Viewport(Box::new(vp)), layout_name) { if let Some(ObjectType::Layout(l)) = self.document.objects.get_mut(&layout_handle) { l.viewports.retain(|candidate| *candidate != handle); @@ -5027,7 +5027,7 @@ impl Scene { viewport.status = codec::entities::ViewportStatusFlags::default_on(); if let Ok(handle) = self .document - .add_entity_to_layout(EntityType::Viewport(viewport), layout_name) + .add_entity_to_layout(EntityType::Viewport(Box::new(viewport)), layout_name) { // The reference zooms the new viewport to the model's extents // with a margin of under one percent. @@ -13802,7 +13802,7 @@ mod journal_tests { let mut annotative = MText::new(); annotative.value = "annotative".to_string(); annotative.is_annotative = true; - let annotative = s.add_entity(EntityType::MText(annotative)); + let annotative = s.add_entity(EntityType::MText(Box::new(annotative))); let before_points = s.geometry_epoch; s.invalidate_point_dependencies(); @@ -14117,7 +14117,7 @@ mod journal_tests { scene.document.layers.add_or_replace(Layer::new("Shadows")); let mut hatch = Hatch::new(); hatch.common.layer = "Shadows".to_string(); - let handle = scene.add_entity(EntityType::Hatch(hatch)); + let handle = scene.add_entity(EntityType::Hatch(Box::new(hatch))); let model = scene.model_space_block_handle(); assert_eq!( scene @@ -15447,7 +15447,7 @@ mod layout_cache_tests { vp.height = 100.0; let handle = scene .document - .add_entity_to_layout(codec::EntityType::Viewport(vp), "P1") + .add_entity_to_layout(codec::EntityType::Viewport(Box::new(vp)), "P1") .unwrap(); assert!(scene.set_viewport_scale_named_for(handle, "1:50").is_some()); assert!(scene.active_viewport.is_none()); diff --git a/src/scene/mspace.rs b/src/scene/mspace.rs index 688376cca..d1c01595d 100644 --- a/src/scene/mspace.rs +++ b/src/scene/mspace.rs @@ -285,7 +285,7 @@ mod viewport_zoom_tests { viewport.width = 100.0; viewport.height = 100.0; viewport.view_height = 200.0; - let handle = scene.add_entity(EntityType::Viewport(viewport)); + let handle = scene.add_entity(EntityType::Viewport(Box::new(viewport))); scene.active_viewport = Some(handle); let view_height = |scene: &Scene| match scene.document.get_entity(handle) { @@ -337,7 +337,7 @@ mod clip_tests { viewport.height = 20.0; viewport.clip_boundary_handle = clip; viewport.status.non_rectangular_clipping = true; - let viewport = scene.add_entity(EntityType::Viewport(viewport)); + let viewport = scene.add_entity(EntityType::Viewport(Box::new(viewport))); for (x, y, inside) in [ (2.0, 2.0, true), (8.0, 2.0, true), diff --git a/src/scene/parametric_constraints.rs b/src/scene/parametric_constraints.rs index 4accc1dfe..5ac4bc6f4 100644 --- a/src/scene/parametric_constraints.rs +++ b/src/scene/parametric_constraints.rs @@ -696,7 +696,7 @@ fn dynamic_dimension_follow_points( target.attachment_point = base.attachment_point; target.line_spacing_style = base.line_spacing_style; target.line_spacing_factor = base.line_spacing_factor; - *dimension = rebuilt; + *dimension = *rebuilt; true } @@ -794,7 +794,7 @@ fn dynamic_dimension_follow_radial( let Some(codec::EntityType::Dimension(mut rebuilt)) = rebuilt else { return false; }; - let unchanged = match (&*dimension, &rebuilt) { + let unchanged = match (&*dimension, &*rebuilt) { (Dimension::Radius(old), Dimension::Radius(new)) => { same(old.angle_vertex, new.angle_vertex) && same(old.definition_point, new.definition_point) @@ -808,7 +808,7 @@ fn dynamic_dimension_follow_radial( if unchanged { return false; } - match &mut rebuilt { + match &mut *rebuilt { Dimension::Radius(new) => new.leader_length = leader, Dimension::Diameter(new) => new.leader_length = leader, _ => {} @@ -821,7 +821,7 @@ fn dynamic_dimension_follow_radial( target.attachment_point = base.attachment_point; target.line_spacing_style = base.line_spacing_style; target.line_spacing_factor = base.line_spacing_factor; - *dimension = rebuilt; + *dimension = *rebuilt; true } @@ -881,7 +881,7 @@ fn dynamic_dimension_follow_angle( target.attachment_point = base.attachment_point; target.line_spacing_style = base.line_spacing_style; target.line_spacing_factor = base.line_spacing_factor; - *dimension = rebuilt; + *dimension = *rebuilt; true } @@ -2264,10 +2264,14 @@ impl super::Scene { }); let measured = points.filter(|_| !angular).map(|(first, second)| { let delta = second - first; - let axis = match self.document.get_entity(*dimension) { - Some(codec::EntityType::Dimension(codec::entities::Dimension::Linear( - linear, - ))) => Some((linear.rotation.cos(), linear.rotation.sin())), + let axis = match self + .document + .get_entity(*dimension) + .and_then(crate::entities::dimension::as_dimension) + { + Some(codec::entities::Dimension::Linear(linear)) => { + Some((linear.rotation.cos(), linear.rotation.sin())) + } _ => None, }; match (constraint.kind, axis) { @@ -2605,7 +2609,7 @@ impl super::Scene { // line, which breaks around the text, so the text is centred on // it rather than lifted above it. let radial = matches!( - dimension, + &**dimension, codec::entities::Dimension::Radius(_) | codec::entities::Dimension::Diameter(_) ); let centred = !radial || ov::int(xdata, ov::DIMTAD) == Some(0); @@ -2615,7 +2619,7 @@ impl super::Scene { // The reference draws dynamic distance text horizontally; an // angle's text keeps its style's alignment. let angular = matches!( - dimension, + &**dimension, codec::entities::Dimension::Angular2Ln(_) | codec::entities::Dimension::Angular3Pt(_) ); diff --git a/src/scene/project.rs b/src/scene/project.rs index a2433eadf..711d371a6 100644 --- a/src/scene/project.rs +++ b/src/scene/project.rs @@ -16,7 +16,7 @@ impl Scene { let viewports: Vec<&Viewport> = viewport_handles .iter() .filter_map(|handle| match self.document.get_entity(*handle) { - Some(EntityType::Viewport(vp)) => Some(vp), + Some(EntityType::Viewport(vp)) => Some(&**vp), _ => None, }) .filter(|vp| { @@ -446,7 +446,7 @@ impl Scene { Some(EntityType::Viewport(viewport)) if viewport.common.owner_handle == paper_block && viewport.is_on() => { - Some(viewport) + Some(&**viewport) } _ => None, }) diff --git a/src/ui/node_graph.rs b/src/ui/node_graph.rs index c7ff9ded5..cdcbbc439 100644 --- a/src/ui/node_graph.rs +++ b/src/ui/node_graph.rs @@ -152,7 +152,7 @@ impl ObjectKind { EntityType::Text(e::Text::with_value("Text", origin).with_height(2.5)) } ObjectKind::MText => { - EntityType::MText(e::MText::with_value("MText", origin).with_height(2.5)) + EntityType::MText(Box::new(e::MText::with_value("MText", origin).with_height(2.5))) } } } diff --git a/tests/active_space_roundtrip.rs b/tests/active_space_roundtrip.rs index 85739c387..15530c41a 100644 --- a/tests/active_space_roundtrip.rs +++ b/tests/active_space_roundtrip.rs @@ -90,13 +90,13 @@ fn entered_viewport_survives_a_save_and_reload() { sheet.id = 1; sheet.width = 420.0; sheet.height = 297.0; - let sheet = scene.add_entity(EntityType::Viewport(sheet)); + let sheet = scene.add_entity(EntityType::Viewport(Box::new(sheet))); let mut model = Viewport::new(); model.id = 2; model.width = 100.0; model.height = 80.0; model.view_height = 80.0; - let model = scene.add_entity(EntityType::Viewport(model)); + let model = scene.add_entity(EntityType::Viewport(Box::new(model))); assert_ne!(sheet, model); for entered in [Some(model), None] { diff --git a/tests/annotative_context_synthesis.rs b/tests/annotative_context_synthesis.rs index 1f52ce560..4de593b2e 100644 --- a/tests/annotative_context_synthesis.rs +++ b/tests/annotative_context_synthesis.rs @@ -20,7 +20,7 @@ fn empty_annotation_scales_is_not_annotative() { let mut doc = CadDocument::with_version(DxfVersion::AC1032); let mut m = MText::new(); m.is_annotative = false; // no native flag, no annotative style - let ent = doc.add_entity(EntityType::MText(m)).unwrap(); + let ent = doc.add_entity(EntityType::MText(Box::new(m))).unwrap(); // Build xdict -> "AcDbContextDataManager" -> "ACDB_ANNOTATIONSCALES" (empty). let mk = |doc: &mut CadDocument, owner: Handle| -> Handle { @@ -92,7 +92,7 @@ fn ocs_synthesized_mtext_context_survives_dwg_roundtrip() { m.insertion_point = Vector3::new(100.0, 200.0, 0.0); m.rectangle_width = 50.0; m.is_annotative = true; - let ent = doc.add_entity(EntityType::MText(m)).expect("add mtext"); + let ent = doc.add_entity(EntityType::MText(Box::new(m))).expect("add mtext"); let sh = doc.allocate_handle(); let mut scale = Scale::new("1:50", 1.0, 50.0); @@ -174,7 +174,7 @@ fn object_scale_membership_add_remove_roundtrips() { let mut doc = CadDocument::with_version(DxfVersion::AC1032); let mut m = MText::new(); m.insertion_point = Vector3::new(1.0, 2.0, 0.0); - let ent = doc.add_entity(EntityType::MText(m)).unwrap(); + let ent = doc.add_entity(EntityType::MText(Box::new(m))).unwrap(); let mk_scale = |doc: &mut CadDocument, name: &str, d: f64| { let h = doc.allocate_handle(); diff --git a/tests/block_hatch_export.rs b/tests/block_hatch_export.rs index b65381871..574d2c98f 100644 --- a/tests/block_hatch_export.rs +++ b/tests/block_hatch_export.rs @@ -75,7 +75,7 @@ fn block_internal_hatch_reaches_export() { // A blue hatch, wrapped into a block and inserted in model space — the // minimal shape of "coloured fill nested in a block". - let h = scene.add_entity(EntityType::Hatch(square_hatch(5))); + let h = scene.add_entity(EntityType::Hatch(Box::new(square_hatch(5)))); let identity = codec::types::Transform::identity(); scene .create_block_from_entities(&[h], "LOGO", &identity, &identity) @@ -100,7 +100,7 @@ fn block_internal_hatch_reaches_export() { fn pattern_hatch_uses_stored_line_spacing() { let mut scene = Scene::new(); // Spacing 0.5; a big pattern_scale (10) that the catalog path would apply. - scene.add_entity(EntityType::Hatch(ansi31_stored(0.5, 10.0))); + scene.add_entity(EntityType::Hatch(Box::new(ansi31_stored(0.5, 10.0)))); scene.populate_hatches_from_document(); let hatches = scene.paper_plot_hatches(); @@ -143,7 +143,7 @@ fn far_from_origin_pattern_hatch_still_fills() { // the perpendicular index is |k| ≈ 4000·sin45°/0.3 ≈ 9400, well past the // 4096 clamp on both ends; the old absolute-index clamp inverts the range // (k_lo > k_hi) there and emits nothing. - scene.add_entity(EntityType::Hatch(ansi31_stored_at(0.3, 1.0, 4000.0, 0.0))); + scene.add_entity(EntityType::Hatch(Box::new(ansi31_stored_at(0.3, 1.0, 4000.0, 0.0)))); scene.populate_hatches_from_document(); let hatches = scene.paper_plot_hatches(); @@ -188,7 +188,7 @@ fn textbox_boundary_path_is_not_filled() { let mut tb = rect_path(0.0, 0.0, 200.0, 50.0); tb.flags = BoundaryPathFlags::from_bits(8 | 1); // TEXTBOX + EXTERNAL hatch.paths.push(tb); - scene.add_entity(EntityType::Hatch(hatch)); + scene.add_entity(EntityType::Hatch(Box::new(hatch))); scene.populate_hatches_from_document(); let hatches = scene.paper_plot_hatches(); diff --git a/tests/dim_copy_check.rs b/tests/dim_copy_check.rs index 0eb46f9cb..03388833c 100644 --- a/tests/dim_copy_check.rs +++ b/tests/dim_copy_check.rs @@ -28,7 +28,7 @@ fn copy_dimension_duplicates_its_block() { // A linear dimension whose drawn geometry is that baked block. let mut dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); dim.base.block_name = "*D0".to_string(); - let dim_h = scene.add_entity(EntityType::Dimension(Dimension::Linear(dim))); + let dim_h = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))); // Copy the dimension by (0, 50). let copies = scene.copy_entities( diff --git a/tests/dim_leader_render_check.rs b/tests/dim_leader_render_check.rs index 2484b52ef..7c48bf7d4 100644 --- a/tests/dim_leader_render_check.rs +++ b/tests/dim_leader_render_check.rs @@ -38,7 +38,7 @@ fn dim_leader_extends_only_when_requested() { base.insertion_point = base.text_middle_point; base.text_user_positioned = true; base.style_name = "Standard".into(); - let handle = scene.add_entity(EntityType::Dimension(dim)); + let handle = scene.add_entity(EntityType::Dimension(Box::new(dim))); for (code, value) in [ (ov::DIMTMOVE, XDataValue::Integer16(movement)), (ov::DIMTXT, XDataValue::Real(3.5)), diff --git a/tests/dim_line_color_roundtrip.rs b/tests/dim_line_color_roundtrip.rs index 1f800be11..e67d9a687 100644 --- a/tests/dim_line_color_roundtrip.rs +++ b/tests/dim_line_color_roundtrip.rs @@ -70,7 +70,7 @@ fn dimension_scene(aci: i16) -> Scene { let mut dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); dim.base.block_name = "*D0".to_string(); - let h = scene.add_entity(EntityType::Dimension(Dimension::Linear(dim))); + let h = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))); dov::set( &mut scene.document, h, diff --git a/tests/explode_regression.rs b/tests/explode_regression.rs index 1b277e15d..9ec6bbc95 100644 --- a/tests/explode_regression.rs +++ b/tests/explode_regression.rs @@ -130,7 +130,7 @@ fn explode_dimension_linear_golden_segments() { let mut d = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); d.definition_point = Vector3::new(5.0, 3.0, 0.0); d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); - let pieces = explode_entity(&EntityType::Dimension(Dimension::Linear(d)), &doc); + let pieces = explode_entity(&EntityType::Dimension(Box::new(Dimension::Linear(d))), &doc); // A baked linear dimension explodes to exactly 2 extension lines + 1 // dimension line. The arrowheads bake as SOLIDs (see the unit test // `linear_dim_bakes_filled_arrowheads`), which is why the Lines count is diff --git a/tests/pdf_export_images_check.rs b/tests/pdf_export_images_check.rs index 6859e6a1c..5e552458c 100644 --- a/tests/pdf_export_images_check.rs +++ b/tests/pdf_export_images_check.rs @@ -331,7 +331,7 @@ fn viewport_projection_clips_images_and_respects_frozen_and_nonplot_layers() { viewport.view_center = Vector3::new(20.0, 10.0, 0.0); viewport.id = 2; viewport.status.is_on = true; - let handle = scene.add_entity(EntityType::Viewport(viewport)); + let handle = scene.add_entity(EntityType::Viewport(Box::new(viewport))); let (_, _, _, images) = scene.viewport_plot_fills(); assert_eq!(images.len(), 1); let raster = Raster::from_pdf(&export(&[page(images)]), 0); diff --git a/tests/pdf_export_text_check.rs b/tests/pdf_export_text_check.rs index 8ad8037b3..947f6092e 100644 --- a/tests/pdf_export_text_check.rs +++ b/tests/pdf_export_text_check.rs @@ -26,7 +26,7 @@ fn text_and_dim_reach_pdf_export() { // A linear dimension — its measurement value is synthesized as SDF text too, // and dimension text is what #385 was actually filed about. let dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(40.0, 0.0, 0.0)); - let dim_h = scene.add_entity(EntityType::Dimension(Dimension::Linear(dim))); + let dim_h = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))); let wires = scene.entity_wires(); diff --git a/tests/text_font_rendering.rs b/tests/text_font_rendering.rs index 805988e6a..66ba96bf0 100644 --- a/tests/text_font_rendering.rs +++ b/tests/text_font_rendering.rs @@ -43,7 +43,7 @@ fn expand_block_mtext( mtext.style = "SHOP".to_string(); mtext.height = 20.0; mtext.rectangle_width = 0.0; - let mut sub = EntityType::MText(mtext); + let mut sub = EntityType::MText(Box::new(mtext)); sub.common_mut().owner_handle = br_h; doc.add_entity(sub).unwrap(); diff --git a/tests/viewport_wide_polyline_plot_width.rs b/tests/viewport_wide_polyline_plot_width.rs index 8ccf6851c..d898b5b43 100644 --- a/tests/viewport_wide_polyline_plot_width.rs +++ b/tests/viewport_wide_polyline_plot_width.rs @@ -43,7 +43,7 @@ fn viewport_projection_scales_wide_polyline_band_width() { viewport.view_center = Vector3::new(50.0, 0.0, 0.0); viewport.id = 2; viewport.status.is_on = true; - scene.add_entity(EntityType::Viewport(viewport)); + scene.add_entity(EntityType::Viewport(Box::new(viewport))); let (_paper, model) = scene.plot_wire_groups(None); let band = model diff --git a/tests/zoom_extents_coverage.rs b/tests/zoom_extents_coverage.rs index 455349760..c8fbb518d 100644 --- a/tests/zoom_extents_coverage.rs +++ b/tests/zoom_extents_coverage.rs @@ -75,7 +75,7 @@ fn fit_all_reaches_an_entity_parked_far_from_the_rest() { #[test] fn fit_all_frames_a_hatch_only_drawing() { let mut scene = Scene::new(); - scene.add_entity(EntityType::Hatch(square_hatch(100.0, 200.0, 40.0))); + scene.add_entity(EntityType::Hatch(Box::new(square_hatch(100.0, 200.0, 40.0)))); scene.fit_all(); @@ -103,7 +103,7 @@ fn fit_all_keeps_a_hatch_outside_the_wires_in_view() { } // The fill is the outermost thing in the drawing; the wires alone would // frame a 12 x 10 strip and leave it off screen. - scene.add_entity(EntityType::Hatch(square_hatch(500.0, 500.0, 50.0))); + scene.add_entity(EntityType::Hatch(Box::new(square_hatch(500.0, 500.0, 50.0)))); scene.fit_all();