forked from 1b-agent/opencadstudio-upstream
Decide Insert and Polyline: Insert creatable by block name, Polyline update-only
Insert can be created by naming an existing ordinary block; the host refuses unknown blocks, model/paper space and containment cycles, and keeps legacy inserts of missing blocks editable. The legacy Polyline is update-only with a hint toward Polyline2D and Polyline3D because both writers convert it on save. The generator gains update_only_message. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
cae188dd08
commit
eb22de636b
8 files changed
+734
-201
No files matched your search
@@ -55,6 +55,9 @@ pub struct EntityOverride {
|
||||
/// create one without host-side reference setup.
|
||||
#[serde(default)]
|
||||
pub update_only: bool,
|
||||
/// Message returned when a script tries to create an update-only kind.
|
||||
#[serde(default)]
|
||||
pub update_only_message: Option<String>,
|
||||
#[serde(default)]
|
||||
pub fields: std::collections::BTreeMap<String, FieldOverride>,
|
||||
}
|
||||
@@ -874,7 +877,13 @@ pub(crate) fn entity_to_dict(vm: &VirtualMachine, entity: &acadrust::EntityType)
|
||||
fn gen_dict_to_entity(manifest: &Manifest, registry: &TypeRegistry) -> String {
|
||||
let mut arms = String::new();
|
||||
for kind in &manifest.type_filter {
|
||||
if manifest.overrides.get(kind).is_some_and(|override_def| override_def.update_only) {
|
||||
if let Some(override_def) = manifest.overrides.get(kind).filter(|o| o.update_only) {
|
||||
let message = override_def.update_only_message.clone().unwrap_or_else(|| {
|
||||
format!("{kind} cannot be created through the generic API; only existing {kind} entities can be edited")
|
||||
});
|
||||
arms.push_str(&format!(
|
||||
" \"{kind}\" => {{ return Err(vm.new_value_error({message:?}.to_owned())); }}\n"
|
||||
));
|
||||
continue;
|
||||
}
|
||||
if manifest.manual_kinds.contains(kind) {
|
||||
|
||||
@@ -38,54 +38,90 @@
|
||||
"ViewBorder",
|
||||
"Light"
|
||||
],
|
||||
"manual_kinds": ["Dimension"],
|
||||
"base_fields": ["handle", "layer", "owner_handle"],
|
||||
"manual_kinds": [
|
||||
"Dimension"
|
||||
],
|
||||
"base_fields": [
|
||||
"handle",
|
||||
"layer",
|
||||
"owner_handle"
|
||||
],
|
||||
"overrides": {
|
||||
"Point": {
|
||||
"fields": {
|
||||
"location": { "required": true }
|
||||
"location": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Line": {
|
||||
"fields": {
|
||||
"start": { "required": true },
|
||||
"end": { "required": true }
|
||||
"start": {
|
||||
"required": true
|
||||
},
|
||||
"end": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Circle": {
|
||||
"fields": {
|
||||
"center": { "required": true },
|
||||
"radius": { "required": true }
|
||||
"center": {
|
||||
"required": true
|
||||
},
|
||||
"radius": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Arc": {
|
||||
"fields": {
|
||||
"center": { "required": true },
|
||||
"radius": { "required": true },
|
||||
"start_angle": { "required": true },
|
||||
"end_angle": { "required": true }
|
||||
"center": {
|
||||
"required": true
|
||||
},
|
||||
"radius": {
|
||||
"required": true
|
||||
},
|
||||
"start_angle": {
|
||||
"required": true
|
||||
},
|
||||
"end_angle": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Ellipse": {
|
||||
"fields": {
|
||||
"center": { "required": true },
|
||||
"major_axis": { "required": true },
|
||||
"minor_axis_ratio": { "required": true }
|
||||
"center": {
|
||||
"required": true
|
||||
},
|
||||
"major_axis": {
|
||||
"required": true
|
||||
},
|
||||
"minor_axis_ratio": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Polyline": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"flags": {
|
||||
"python_name": "closed",
|
||||
"rust_getter": "VAR.flags.is_closed()",
|
||||
"rust_setter": "VAR.flags.set_closed(get_opt_bool(dict, \"closed\", vm)?);"
|
||||
}
|
||||
}
|
||||
},
|
||||
"update_only": true,
|
||||
"update_only_message": "Polyline is the legacy 3-D-vertex polyline and both file formats save it as Polyline3D; create a Polyline2D or Polyline3D instead (existing Polyline entities can still be edited)"
|
||||
},
|
||||
"Polyline2D": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"flags": {
|
||||
"python_name": "closed",
|
||||
"rust_getter": "VAR.flags.is_closed()",
|
||||
@@ -95,121 +131,200 @@
|
||||
},
|
||||
"Polyline3D": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"smooth_type": {
|
||||
"exclude": true,
|
||||
"_comment": "acadrust defines two distinct SmoothSurfaceType enums with the same name (polyline.rs, used by Polyline2D's smooth_surface — and a separate one private to polyline3d.rs, used here); the type registry's tracer keys purely by name and collapses them, so the generically generated conversion resolves to the wrong one. Needs a hand-written override with the fully qualified acadrust::entities::polyline3d::SmoothSurfaceType path to support, not just a rename."
|
||||
"_comment": "acadrust defines two distinct SmoothSurfaceType enums with the same name (polyline.rs, used by Polyline2D's smooth_surface \u2014 and a separate one private to polyline3d.rs, used here); the type registry's tracer keys purely by name and collapses them, so the generically generated conversion resolves to the wrong one. Needs a hand-written override with the fully qualified acadrust::entities::polyline3d::SmoothSurfaceType path to support, not just a rename."
|
||||
}
|
||||
}
|
||||
},
|
||||
"LwPolyline": {
|
||||
"fields": {
|
||||
"vertices": { "required": true }
|
||||
"vertices": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Spline": {
|
||||
"fields": {
|
||||
"control_points": { "required": true }
|
||||
"control_points": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Text": {
|
||||
"fields": {
|
||||
"value": { "python_name": "text", "required": true },
|
||||
"insertion_point": { "python_name": "insertion", "required": true }
|
||||
"value": {
|
||||
"python_name": "text",
|
||||
"required": true
|
||||
},
|
||||
"insertion_point": {
|
||||
"python_name": "insertion",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"MText": {
|
||||
"fields": {
|
||||
"value": { "python_name": "text", "required": true },
|
||||
"insertion_point": { "python_name": "insertion", "required": true },
|
||||
"value": {
|
||||
"python_name": "text",
|
||||
"required": true
|
||||
},
|
||||
"insertion_point": {
|
||||
"python_name": "insertion",
|
||||
"required": true
|
||||
},
|
||||
"background_color": {
|
||||
"exclude": true,
|
||||
"_comment": "Color is a tagged enum (Index(u8)/Rgb{r,g,b} carry data, not just unit variants) — this generator only handles C-like unit enums generically; EntityCommon's own color/line_weight/transparency fields are out of scope for the same reason (see base_fields)."
|
||||
"_comment": "Color is a tagged enum (Index(u8)/Rgb{r,g,b} carry data, not just unit variants) \u2014 this generator only handles C-like unit enums generically; EntityCommon's own color/line_weight/transparency fields are out of scope for the same reason (see base_fields)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"Ray": {
|
||||
"fields": {
|
||||
"base_point": { "required": true },
|
||||
"direction": { "required": true }
|
||||
"base_point": {
|
||||
"required": true
|
||||
},
|
||||
"direction": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"XLine": {
|
||||
"fields": {
|
||||
"base_point": { "required": true },
|
||||
"direction": { "required": true }
|
||||
"base_point": {
|
||||
"required": true
|
||||
},
|
||||
"direction": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Solid": {
|
||||
"rust_constructor": "acadrust::entities::Solid::new(acadrust::types::Vector3::ZERO, acadrust::types::Vector3::ZERO, acadrust::types::Vector3::ZERO, acadrust::types::Vector3::ZERO)",
|
||||
"fields": {
|
||||
"first_corner": { "required": true },
|
||||
"second_corner": { "required": true },
|
||||
"third_corner": { "required": true },
|
||||
"fourth_corner": { "required": true }
|
||||
"first_corner": {
|
||||
"required": true
|
||||
},
|
||||
"second_corner": {
|
||||
"required": true
|
||||
},
|
||||
"third_corner": {
|
||||
"required": true
|
||||
},
|
||||
"fourth_corner": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Face3D": {
|
||||
"rust_constructor": "acadrust::entities::Face3D::new(acadrust::types::Vector3::ZERO, acadrust::types::Vector3::ZERO, acadrust::types::Vector3::ZERO, acadrust::types::Vector3::ZERO)",
|
||||
"fields": {
|
||||
"first_corner": { "required": true },
|
||||
"second_corner": { "required": true },
|
||||
"third_corner": { "required": true },
|
||||
"fourth_corner": { "required": true }
|
||||
"first_corner": {
|
||||
"required": true
|
||||
},
|
||||
"second_corner": {
|
||||
"required": true
|
||||
},
|
||||
"third_corner": {
|
||||
"required": true
|
||||
},
|
||||
"fourth_corner": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Insert": {
|
||||
"update_only": true,
|
||||
"fields": {
|
||||
"block_name": { "read_only": true },
|
||||
"block_name": {
|
||||
"required": true
|
||||
},
|
||||
"x_scale": {
|
||||
"rust_getter": "VAR.x_scale()",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"x_scale\", vm)? { let scale = v.try_into_value::<f64>(vm)?; if !scale.is_finite() || scale.abs() < 1e-12 { return Err(vm.new_value_error(\"Insert.x_scale must be finite and nonzero\".to_owned())); } VAR.set_x_scale(scale); }"
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"x_scale\", vm)? { let scale = py_number_to_f64(v, vm)?; if !scale.is_finite() || scale.abs() < 1e-12 { return Err(vm.new_value_error(\"Insert.x_scale must be finite and nonzero\".to_owned())); } VAR.set_x_scale(scale); }"
|
||||
},
|
||||
"y_scale": {
|
||||
"rust_getter": "VAR.y_scale()",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"y_scale\", vm)? { let scale = v.try_into_value::<f64>(vm)?; if !scale.is_finite() || scale.abs() < 1e-12 { return Err(vm.new_value_error(\"Insert.y_scale must be finite and nonzero\".to_owned())); } VAR.set_y_scale(scale); }"
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"y_scale\", vm)? { let scale = py_number_to_f64(v, vm)?; if !scale.is_finite() || scale.abs() < 1e-12 { return Err(vm.new_value_error(\"Insert.y_scale must be finite and nonzero\".to_owned())); } VAR.set_y_scale(scale); }"
|
||||
},
|
||||
"z_scale": {
|
||||
"rust_getter": "VAR.z_scale()",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"z_scale\", vm)? { let scale = v.try_into_value::<f64>(vm)?; if !scale.is_finite() || scale.abs() < 1e-12 { return Err(vm.new_value_error(\"Insert.z_scale must be finite and nonzero\".to_owned())); } VAR.set_z_scale(scale); }"
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"z_scale\", vm)? { let scale = py_number_to_f64(v, vm)?; if !scale.is_finite() || scale.abs() < 1e-12 { return Err(vm.new_value_error(\"Insert.z_scale must be finite and nonzero\".to_owned())); } VAR.set_z_scale(scale); }"
|
||||
},
|
||||
"dwg_minsert": { "exclude": true },
|
||||
"attributes": { "exclude": true },
|
||||
"view_rep_handle": { "exclude": true },
|
||||
"seqend_handle": { "exclude": true }
|
||||
}
|
||||
"dwg_minsert": {
|
||||
"exclude": true
|
||||
},
|
||||
"attributes": {
|
||||
"exclude": true
|
||||
},
|
||||
"view_rep_handle": {
|
||||
"exclude": true
|
||||
},
|
||||
"seqend_handle": {
|
||||
"exclude": true
|
||||
},
|
||||
"insert_point": {
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"rust_constructor": "acadrust::entities::Insert::new(String::new(), acadrust::types::Vector3::ZERO)"
|
||||
},
|
||||
"Tolerance": {
|
||||
"fields": {
|
||||
"insertion_point": { "required": true },
|
||||
"text": { "required": true },
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"text": {
|
||||
"required": true
|
||||
},
|
||||
"dimension_style_name": {
|
||||
"rust_getter": "VAR.dimension_style_name.clone()",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"dimension_style_name\", vm)? { VAR.dimension_style_name = v.try_into_value::<String>(vm)?; VAR.dimension_style_handle = None; }"
|
||||
},
|
||||
"dimension_style_handle": { "read_only": true },
|
||||
"dwg_unknown_short": { "exclude": true }
|
||||
"dimension_style_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"dwg_unknown_short": {
|
||||
"exclude": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Shape": {
|
||||
"fields": {
|
||||
"insertion_point": { "required": true },
|
||||
"size": { "required": true },
|
||||
"shape_name": { "required": true },
|
||||
"shape_number": { "required": true },
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"size": {
|
||||
"required": true
|
||||
},
|
||||
"shape_name": {
|
||||
"required": true
|
||||
},
|
||||
"shape_number": {
|
||||
"required": true
|
||||
},
|
||||
"style_name": {
|
||||
"rust_getter": "VAR.style_name.clone()",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"style_name\", vm)? { VAR.style_name = v.try_into_value::<String>(vm)?; VAR.style_handle = None; }"
|
||||
},
|
||||
"style_handle": { "read_only": true }
|
||||
"style_handle": {
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"AttributeDefinition": {
|
||||
"fields": {
|
||||
"tag": { "required": true },
|
||||
"insertion_point": { "required": true },
|
||||
"height": { "required": true },
|
||||
"tag": {
|
||||
"required": true
|
||||
},
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"height": {
|
||||
"required": true
|
||||
},
|
||||
"embedded_mtext": {
|
||||
"exclude": true,
|
||||
"_comment": "Embedded R2018+ MTEXT carries linked layout state. It remains snapshot-readable but is preserved untouched by Python edits until linked-payload mutation has dedicated validation."
|
||||
@@ -218,11 +333,21 @@
|
||||
},
|
||||
"AttributeEntity": {
|
||||
"fields": {
|
||||
"tag": { "required": true },
|
||||
"value": { "required": true },
|
||||
"insertion_point": { "required": true },
|
||||
"height": { "required": true },
|
||||
"attdef_handle": { "read_only": true },
|
||||
"tag": {
|
||||
"required": true
|
||||
},
|
||||
"value": {
|
||||
"required": true
|
||||
},
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"height": {
|
||||
"required": true
|
||||
},
|
||||
"attdef_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"embedded_mtext": {
|
||||
"exclude": true,
|
||||
"_comment": "The embedded R2018+ MTEXT payload remains snapshot-readable and is preserved by partial edits."
|
||||
@@ -231,7 +356,9 @@
|
||||
},
|
||||
"Hatch": {
|
||||
"fields": {
|
||||
"paths": { "required": true },
|
||||
"paths": {
|
||||
"required": true
|
||||
},
|
||||
"is_mpolygon": {
|
||||
"exclude": true,
|
||||
"_comment": "MPOLYGON is a distinct class-backed record and is preserved without exposing Hatch creation semantics."
|
||||
@@ -240,21 +367,35 @@
|
||||
"exclude": true,
|
||||
"_comment": "Gradient payload mutation requires a separate validated model; partial Hatch edits preserve it."
|
||||
},
|
||||
"mpolygon_hatch_color": { "exclude": true },
|
||||
"mpolygon_x_direction": { "exclude": true },
|
||||
"mpolygon_boundary_handle_count": { "exclude": true }
|
||||
"mpolygon_hatch_color": {
|
||||
"exclude": true
|
||||
},
|
||||
"mpolygon_x_direction": {
|
||||
"exclude": true
|
||||
},
|
||||
"mpolygon_boundary_handle_count": {
|
||||
"exclude": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"MLine": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"flags": {
|
||||
"rust_getter": "(VAR.flags.bits() as i64)",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"flags\", vm)? { let bits = v.try_into_value::<i64>(vm)?; VAR.flags = i16::try_from(bits).ok().and_then(acadrust::entities::MLineFlags::from_bits).ok_or_else(|| vm.new_value_error(\"MLine.flags has unknown bits\".to_owned()))?; }"
|
||||
},
|
||||
"start_point": { "read_only": true },
|
||||
"style_handle": { "read_only": true },
|
||||
"style_element_count": { "read_only": true },
|
||||
"start_point": {
|
||||
"read_only": true
|
||||
},
|
||||
"style_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"style_element_count": {
|
||||
"read_only": true
|
||||
},
|
||||
"style_name": {
|
||||
"rust_getter": "VAR.style_name.clone()",
|
||||
"rust_setter": "if let Some(v) = dict.get_item_opt(\"style_name\", vm)? { VAR.style_name = v.try_into_value::<String>(vm)?; VAR.style_handle = None; }"
|
||||
@@ -263,28 +404,67 @@
|
||||
},
|
||||
"Leader": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"origin": { "read_only": true },
|
||||
"dimension_gap": { "read_only": true },
|
||||
"arrowhead_type": { "read_only": true },
|
||||
"arrow_size": { "read_only": true },
|
||||
"byblock_color": { "read_only": true },
|
||||
"dwg_unknown_bit1": { "exclude": true },
|
||||
"dwg_unknown_bit2": { "exclude": true },
|
||||
"dwg_unknown_bit3": { "exclude": true },
|
||||
"dwg_unknown_bit4": { "exclude": true },
|
||||
"dwg_unknown_bit5": { "exclude": true },
|
||||
"dwg_unknown_short1": { "exclude": true }
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"origin": {
|
||||
"read_only": true
|
||||
},
|
||||
"dimension_gap": {
|
||||
"read_only": true
|
||||
},
|
||||
"arrowhead_type": {
|
||||
"read_only": true
|
||||
},
|
||||
"arrow_size": {
|
||||
"read_only": true
|
||||
},
|
||||
"byblock_color": {
|
||||
"read_only": true
|
||||
},
|
||||
"dwg_unknown_bit1": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_bit2": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_bit3": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_bit4": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_bit5": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_short1": {
|
||||
"exclude": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"MultiLeader": {
|
||||
"fields": {
|
||||
"arrowhead_overrides": { "exclude": true, "_comment": "Per-arrow override records carry linked block handles; preserved untouched until dedicated validation exists." },
|
||||
"block_attributes": { "exclude": true, "_comment": "Block attribute records carry attribute-definition handles; preserved untouched." },
|
||||
"dwg_version": { "read_only": true },
|
||||
"text_height": { "read_only": true, "_comment": "Neither writer stores the entity-level text height; scripts set the persisted context.text_height." },
|
||||
"property_override_flags": { "read_only": true },
|
||||
"text_align_in_ipe": { "read_only": true },
|
||||
"arrowhead_overrides": {
|
||||
"exclude": true,
|
||||
"_comment": "Per-arrow override records carry linked block handles; preserved untouched until dedicated validation exists."
|
||||
},
|
||||
"block_attributes": {
|
||||
"exclude": true,
|
||||
"_comment": "Block attribute records carry attribute-definition handles; preserved untouched."
|
||||
},
|
||||
"dwg_version": {
|
||||
"read_only": true
|
||||
},
|
||||
"text_height": {
|
||||
"read_only": true,
|
||||
"_comment": "Neither writer stores the entity-level text height; scripts set the persisted context.text_height."
|
||||
},
|
||||
"property_override_flags": {
|
||||
"read_only": true
|
||||
},
|
||||
"text_align_in_ipe": {
|
||||
"read_only": true
|
||||
},
|
||||
"context": {
|
||||
"keep_types": true,
|
||||
"rust_getter": "multi_leader_annot_context_to_dict(vm, &VAR.context)?",
|
||||
@@ -294,132 +474,311 @@
|
||||
},
|
||||
"Table": {
|
||||
"fields": {
|
||||
"insertion_point": { "required": true },
|
||||
"block_name": { "read_only": true },
|
||||
"block_record_handle": { "read_only": true },
|
||||
"data_version": { "read_only": true },
|
||||
"value_flags": { "read_only": true },
|
||||
"override_flag": { "read_only": true },
|
||||
"override_border_color": { "read_only": true },
|
||||
"override_border_line_weight": { "read_only": true },
|
||||
"override_border_visibility": { "read_only": true },
|
||||
"legacy_style_override": { "read_only": true },
|
||||
"name": { "read_only": true },
|
||||
"description": { "read_only": true },
|
||||
"field_handles": { "read_only": true },
|
||||
"base_style": { "read_only": true },
|
||||
"break_data": { "read_only": true },
|
||||
"break_ranges": { "read_only": true },
|
||||
"dwg_unknown_byte": { "exclude": true },
|
||||
"dwg_unknown_handle": { "exclude": true },
|
||||
"dwg_unknown_long1": { "exclude": true },
|
||||
"dwg_r2010_unknown_bit": { "exclude": true },
|
||||
"dwg_unknown_long2": { "exclude": true },
|
||||
"dwg_unknown_short": { "exclude": true },
|
||||
"legacy_border_colors": { "exclude": true, "_comment": "Generic LegacyBorderOverrides<T> is not expressible by the generator; legacy R13-R2000 border overrides are preserved untouched." },
|
||||
"legacy_border_line_weights": { "exclude": true },
|
||||
"legacy_border_visibility": { "exclude": true }
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"block_name": {
|
||||
"read_only": true
|
||||
},
|
||||
"block_record_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"data_version": {
|
||||
"read_only": true
|
||||
},
|
||||
"value_flags": {
|
||||
"read_only": true
|
||||
},
|
||||
"override_flag": {
|
||||
"read_only": true
|
||||
},
|
||||
"override_border_color": {
|
||||
"read_only": true
|
||||
},
|
||||
"override_border_line_weight": {
|
||||
"read_only": true
|
||||
},
|
||||
"override_border_visibility": {
|
||||
"read_only": true
|
||||
},
|
||||
"legacy_style_override": {
|
||||
"read_only": true
|
||||
},
|
||||
"name": {
|
||||
"read_only": true
|
||||
},
|
||||
"description": {
|
||||
"read_only": true
|
||||
},
|
||||
"field_handles": {
|
||||
"read_only": true
|
||||
},
|
||||
"base_style": {
|
||||
"read_only": true
|
||||
},
|
||||
"break_data": {
|
||||
"read_only": true
|
||||
},
|
||||
"break_ranges": {
|
||||
"read_only": true
|
||||
},
|
||||
"dwg_unknown_byte": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_handle": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_long1": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_r2010_unknown_bit": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_long2": {
|
||||
"exclude": true
|
||||
},
|
||||
"dwg_unknown_short": {
|
||||
"exclude": true
|
||||
},
|
||||
"legacy_border_colors": {
|
||||
"exclude": true,
|
||||
"_comment": "Generic LegacyBorderOverrides<T> is not expressible by the generator; legacy R13-R2000 border overrides are preserved untouched."
|
||||
},
|
||||
"legacy_border_line_weights": {
|
||||
"exclude": true
|
||||
},
|
||||
"legacy_border_visibility": {
|
||||
"exclude": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolygonMesh": {
|
||||
"rust_constructor": "acadrust::entities::PolygonMeshEntity::default()",
|
||||
"fields": { "vertices": { "required": true } }
|
||||
"fields": {
|
||||
"vertices": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"PolyfaceMesh": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"faces": { "required": true },
|
||||
"seqend_handle": { "read_only": true }
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"faces": {
|
||||
"required": true
|
||||
},
|
||||
"seqend_handle": {
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mesh": {
|
||||
"fields": {
|
||||
"vertices": { "required": true },
|
||||
"faces": { "required": true },
|
||||
"version": { "read_only": true }
|
||||
"vertices": {
|
||||
"required": true
|
||||
},
|
||||
"faces": {
|
||||
"required": true
|
||||
},
|
||||
"version": {
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Helix": {
|
||||
"fields": {
|
||||
"start_point": { "required": true },
|
||||
"spline": { "read_only": true, "_comment": "Derived by the host from the generating parameters." },
|
||||
"major_version": { "read_only": true },
|
||||
"maintenance_version": { "read_only": true }
|
||||
"start_point": {
|
||||
"required": true
|
||||
},
|
||||
"spline": {
|
||||
"read_only": true,
|
||||
"_comment": "Derived by the host from the generating parameters."
|
||||
},
|
||||
"major_version": {
|
||||
"read_only": true
|
||||
},
|
||||
"maintenance_version": {
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"RasterImage": {
|
||||
"fields": {
|
||||
"insertion_point": { "required": true },
|
||||
"file_path": { "required": true },
|
||||
"class_version": { "read_only": true },
|
||||
"size": { "read_only": true, "_comment": "Pixel size of the image; the host takes it from the file." },
|
||||
"definition_handle": { "read_only": true },
|
||||
"definition_reactor_handle": { "read_only": true }
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"file_path": {
|
||||
"required": true
|
||||
},
|
||||
"class_version": {
|
||||
"read_only": true
|
||||
},
|
||||
"size": {
|
||||
"read_only": true,
|
||||
"_comment": "Pixel size of the image; the host takes it from the file."
|
||||
},
|
||||
"definition_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"definition_reactor_handle": {
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wipeout": {
|
||||
"fields": {
|
||||
"insertion_point": { "required": true },
|
||||
"class_version": { "read_only": true },
|
||||
"definition_handle": { "read_only": true },
|
||||
"definition_reactor_handle": { "read_only": true }
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
},
|
||||
"class_version": {
|
||||
"read_only": true
|
||||
},
|
||||
"definition_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"definition_reactor_handle": {
|
||||
"read_only": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Underlay": {
|
||||
"fields": {
|
||||
"definition_handle": { "required": true },
|
||||
"insertion_point": { "required": true }
|
||||
"definition_handle": {
|
||||
"required": true
|
||||
},
|
||||
"insertion_point": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Viewport": {
|
||||
"fields": {
|
||||
"id": { "read_only": true },
|
||||
"snap_base": { "read_only": true },
|
||||
"snap_spacing": { "read_only": true },
|
||||
"grid_spacing": { "read_only": true },
|
||||
"snap_angle": { "read_only": true },
|
||||
"clip_boundary_handle": { "read_only": true },
|
||||
"style_sheet": { "read_only": true },
|
||||
"ucs_at_origin": { "read_only": true },
|
||||
"ucs_per_viewport": { "read_only": true },
|
||||
"ucs_origin": { "read_only": true },
|
||||
"ucs_x_axis": { "read_only": true },
|
||||
"ucs_y_axis": { "read_only": true },
|
||||
"ucs_handle": { "read_only": true },
|
||||
"base_ucs_handle": { "read_only": true },
|
||||
"ucs_ortho_type": { "read_only": true },
|
||||
"elevation": { "read_only": true },
|
||||
"shade_plot_mode": { "read_only": true },
|
||||
"grid_flags": { "read_only": true },
|
||||
"grid_major": { "read_only": true },
|
||||
"background_handle": { "read_only": true },
|
||||
"shade_plot_handle": { "read_only": true },
|
||||
"visual_style_handle": { "read_only": true },
|
||||
"sun_handle": { "read_only": true },
|
||||
"default_lighting": { "read_only": true },
|
||||
"default_lighting_type": { "read_only": true },
|
||||
"brightness": { "read_only": true },
|
||||
"contrast": { "read_only": true },
|
||||
"ambient_color": { "read_only": true },
|
||||
"center": { "required": true },
|
||||
"width": { "required": true },
|
||||
"height": { "required": true }
|
||||
"id": {
|
||||
"read_only": true
|
||||
},
|
||||
"snap_base": {
|
||||
"read_only": true
|
||||
},
|
||||
"snap_spacing": {
|
||||
"read_only": true
|
||||
},
|
||||
"grid_spacing": {
|
||||
"read_only": true
|
||||
},
|
||||
"snap_angle": {
|
||||
"read_only": true
|
||||
},
|
||||
"clip_boundary_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"style_sheet": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_at_origin": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_per_viewport": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_origin": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_x_axis": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_y_axis": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"base_ucs_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"ucs_ortho_type": {
|
||||
"read_only": true
|
||||
},
|
||||
"elevation": {
|
||||
"read_only": true
|
||||
},
|
||||
"shade_plot_mode": {
|
||||
"read_only": true
|
||||
},
|
||||
"grid_flags": {
|
||||
"read_only": true
|
||||
},
|
||||
"grid_major": {
|
||||
"read_only": true
|
||||
},
|
||||
"background_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"shade_plot_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"visual_style_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"sun_handle": {
|
||||
"read_only": true
|
||||
},
|
||||
"default_lighting": {
|
||||
"read_only": true
|
||||
},
|
||||
"default_lighting_type": {
|
||||
"read_only": true
|
||||
},
|
||||
"brightness": {
|
||||
"read_only": true
|
||||
},
|
||||
"contrast": {
|
||||
"read_only": true
|
||||
},
|
||||
"ambient_color": {
|
||||
"read_only": true
|
||||
},
|
||||
"center": {
|
||||
"required": true
|
||||
},
|
||||
"width": {
|
||||
"required": true
|
||||
},
|
||||
"height": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ViewBorder": {
|
||||
"fields": {
|
||||
"version": { "read_only": true },
|
||||
"min": { "required": true },
|
||||
"max": { "required": true },
|
||||
"active_viewport": { "required": true },
|
||||
"scale_handle": { "required": true }
|
||||
"version": {
|
||||
"read_only": true
|
||||
},
|
||||
"min": {
|
||||
"required": true
|
||||
},
|
||||
"max": {
|
||||
"required": true
|
||||
},
|
||||
"active_viewport": {
|
||||
"required": true
|
||||
},
|
||||
"scale_handle": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Light": {
|
||||
"fields": {
|
||||
"class_version": { "read_only": true },
|
||||
"position": { "required": true },
|
||||
"name": { "required": true }
|
||||
"class_version": {
|
||||
"read_only": true
|
||||
},
|
||||
"position": {
|
||||
"required": true
|
||||
},
|
||||
"name": {
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3851,7 +3851,7 @@ mod ocs {
|
||||
|
||||
#[cfg(feature = "experimental-host-model")]
|
||||
#[test]
|
||||
fn insert_is_update_only_and_preserves_block_identity() {
|
||||
fn insert_is_created_by_block_name_and_preserves_block_identity() {
|
||||
with_vm(|vm| {
|
||||
let mut insert =
|
||||
acadrust::entities::Insert::new("DOOR", Vector3::new(1.0, 2.0, 0.0));
|
||||
@@ -3877,7 +3877,14 @@ mod ocs {
|
||||
.unwrap(),
|
||||
2.0
|
||||
);
|
||||
assert!(dict_to_entity(&rendered, vm).is_err());
|
||||
// A round-tripped dict names an existing block, so it creates one.
|
||||
let recreated = dict_to_entity(&rendered, vm).unwrap();
|
||||
assert!(matches!(&recreated, EntityType::Insert(value)
|
||||
if value.block_name == "DOOR" && value.x_scale() == 2.0));
|
||||
// Creation must name the block.
|
||||
let unnamed = vm.ctx.new_dict();
|
||||
unnamed.set_item("kind", vm.new_pyobj("Insert"), vm).unwrap();
|
||||
assert!(dict_to_entity(&unnamed, vm).is_err());
|
||||
|
||||
let patch = vm.ctx.new_dict();
|
||||
set_vector3(vm, &patch, "insert_point", 4.0, 5.0, 0.0);
|
||||
@@ -3896,7 +3903,10 @@ mod ocs {
|
||||
patch
|
||||
.set_item("block_name", vm.new_pyobj("OTHER"), vm)
|
||||
.unwrap();
|
||||
assert!(apply_dict_to_entity(&original, &patch, vm).is_err());
|
||||
// The adapter only converts; the host mutation check refuses a
|
||||
// different block, so an edit cannot swap block identity.
|
||||
let renamed = apply_dict_to_entity(&original, &patch, vm).unwrap();
|
||||
assert!(ocs_plugin_api::entity_coverage::validate_entity_mutation(&original, &renamed).is_err());
|
||||
patch.del_item("block_name", vm).unwrap();
|
||||
patch.set_item("z_scale", vm.new_pyobj(0.0), vm).unwrap();
|
||||
assert!(apply_dict_to_entity(&original, &patch, vm).is_err());
|
||||
@@ -4387,7 +4397,7 @@ mod ocs {
|
||||
);
|
||||
|
||||
let dict = vm.ctx.new_dict();
|
||||
dict.set_item("kind", vm.new_pyobj("Polyline"), vm).unwrap();
|
||||
dict.set_item("kind", vm.new_pyobj("Polyline2D"), vm).unwrap();
|
||||
let err = dict_to_entity(&dict, vm).expect_err("missing vertices must error");
|
||||
let message = err.args().as_slice()[0]
|
||||
.clone()
|
||||
@@ -4401,7 +4411,7 @@ mod ocs {
|
||||
// An explicitly empty vertex list is exactly as invalid as an
|
||||
// absent one — both parse to the same empty Vec.
|
||||
let dict = vm.ctx.new_dict();
|
||||
dict.set_item("kind", vm.new_pyobj("Polyline"), vm).unwrap();
|
||||
dict.set_item("kind", vm.new_pyobj("Polyline2D"), vm).unwrap();
|
||||
dict.set_item("vertices", vm.ctx.new_list(vec![]).into(), vm)
|
||||
.unwrap();
|
||||
assert!(dict_to_entity(&dict, vm).is_err());
|
||||
@@ -4409,10 +4419,24 @@ mod ocs {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn polyline_flags_override_exposes_closed_as_a_plain_bool() {
|
||||
fn legacy_polyline_creation_is_refused_with_a_hint() {
|
||||
with_vm(|vm| {
|
||||
let dict = vm.ctx.new_dict();
|
||||
dict.set_item("kind", vm.new_pyobj("Polyline"), vm).unwrap();
|
||||
let err = dict_to_entity(&dict, vm).expect_err("legacy Polyline is update-only");
|
||||
let message = err.args().as_slice()[0]
|
||||
.clone()
|
||||
.try_into_value::<String>(vm)
|
||||
.unwrap();
|
||||
assert!(message.contains("Polyline2D or Polyline3D"), "{message}");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn polyline_flags_override_exposes_closed_as_a_plain_bool() {
|
||||
with_vm(|vm| {
|
||||
let dict = vm.ctx.new_dict();
|
||||
dict.set_item("kind", vm.new_pyobj("Polyline2D"), vm).unwrap();
|
||||
dict.set_item("closed", vm.new_pyobj(true), vm).unwrap();
|
||||
let vertex = vm.ctx.new_dict();
|
||||
let location = vm.ctx.new_dict();
|
||||
@@ -4424,8 +4448,8 @@ mod ocs {
|
||||
.unwrap();
|
||||
|
||||
let entity = dict_to_entity(&dict, vm).expect("dict_to_entity");
|
||||
let acadrust::EntityType::Polyline(polyline) = &entity else {
|
||||
panic!("expected Polyline, got {entity:?}");
|
||||
let acadrust::EntityType::Polyline2D(polyline) = &entity else {
|
||||
panic!("expected Polyline2D, got {entity:?}");
|
||||
};
|
||||
assert!(polyline.flags.is_closed());
|
||||
assert_eq!(polyline.vertices.len(), 1);
|
||||
|
||||
Reference in new issue
Block a user