forked from 1b-agent/opencadstudio-upstream
Map Viewport in the Python host model
Curated view fields are writable; the owner must be a paper-space block and frozen layers must exist. staged_python_viewport_lifecycle_over_real_ipc passes every gate except a paper-space canvas oracle, so the kind is recorded as integration-tested. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2e4d77dc09
commit
9075e53511
10 files changed
+219
-14
No files matched your search
@@ -794,6 +794,7 @@ fn generate_entity_coverage(out_dir: &Path, registry: &TypeRegistry) {
|
||||
| ("RasterImage", _)
|
||||
| ("Wipeout", _)
|
||||
| ("Underlay", _)
|
||||
| ("Viewport", _)
|
||||
| (
|
||||
"MLine",
|
||||
"flags"
|
||||
|
||||
@@ -432,6 +432,26 @@
|
||||
"fade",
|
||||
"clip_boundary_vertices",
|
||||
"clip_inverted"
|
||||
],
|
||||
"Viewport": [
|
||||
"layer",
|
||||
"center",
|
||||
"width",
|
||||
"height",
|
||||
"status",
|
||||
"view_center",
|
||||
"view_direction",
|
||||
"view_target",
|
||||
"lens_length",
|
||||
"front_clip_z",
|
||||
"back_clip_z",
|
||||
"view_height",
|
||||
"twist_angle",
|
||||
"custom_scale",
|
||||
"frozen_layers",
|
||||
"render_mode",
|
||||
"circle_sides",
|
||||
"ucs_icon_visible"
|
||||
]
|
||||
},
|
||||
"readable": {
|
||||
@@ -503,6 +523,36 @@
|
||||
"class_version",
|
||||
"definition_handle",
|
||||
"definition_reactor_handle"
|
||||
],
|
||||
"Viewport": [
|
||||
"id",
|
||||
"snap_base",
|
||||
"snap_spacing",
|
||||
"grid_spacing",
|
||||
"snap_angle",
|
||||
"clip_boundary_handle",
|
||||
"style_sheet",
|
||||
"ucs_at_origin",
|
||||
"ucs_per_viewport",
|
||||
"ucs_origin",
|
||||
"ucs_x_axis",
|
||||
"ucs_y_axis",
|
||||
"ucs_handle",
|
||||
"base_ucs_handle",
|
||||
"ucs_ortho_type",
|
||||
"elevation",
|
||||
"shade_plot_mode",
|
||||
"grid_flags",
|
||||
"grid_major",
|
||||
"background_handle",
|
||||
"shade_plot_handle",
|
||||
"visual_style_handle",
|
||||
"sun_handle",
|
||||
"default_lighting",
|
||||
"default_lighting_type",
|
||||
"brightness",
|
||||
"contrast",
|
||||
"ambient_color"
|
||||
]
|
||||
},
|
||||
"aliases": {
|
||||
|
||||
@@ -919,6 +919,36 @@ fn validate_underlay(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Viewport view state. Owner and layer-handle references are checked with the
|
||||
/// other references; this validates the numbers.
|
||||
#[cfg(feature = "host")]
|
||||
fn validate_viewport(
|
||||
old: Option<&crate::host::acadrust::entities::Viewport>,
|
||||
new: &crate::host::acadrust::entities::Viewport,
|
||||
) -> Result<(), String> {
|
||||
if old == Some(new) {
|
||||
return Ok(());
|
||||
}
|
||||
finite_vector("Viewport.center", &new.center)?;
|
||||
finite_vector("Viewport.view_center", &new.view_center)?;
|
||||
finite_vector("Viewport.view_target", &new.view_target)?;
|
||||
solid_normal("Viewport.view_direction", &new.view_direction)?;
|
||||
for (name, value) in [("width", new.width), ("height", new.height), ("view_height", new.view_height), ("lens_length", new.lens_length), ("custom_scale", new.custom_scale)] {
|
||||
if !value.is_finite() || value <= 0.0 {
|
||||
return Err(format!("Viewport.{name} must be finite and greater than zero"));
|
||||
}
|
||||
}
|
||||
for (name, value) in [("front_clip_z", new.front_clip_z), ("back_clip_z", new.back_clip_z), ("twist_angle", new.twist_angle)] {
|
||||
if !value.is_finite() {
|
||||
return Err(format!("Viewport.{name} must be finite"));
|
||||
}
|
||||
}
|
||||
if new.circle_sides < 3 {
|
||||
return Err("Viewport.circle_sides must be at least 3".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate newly created geometry for the kinds whose mapped fields have
|
||||
/// host checks. Called by the Python add path before an entity enters the document.
|
||||
#[cfg(feature = "host")]
|
||||
@@ -1022,6 +1052,7 @@ pub fn validate_new_canvas_entity(entity: &crate::host::EntityType) -> Result<()
|
||||
EntityType::RasterImage(value) => validate_raster_image(None, value)?,
|
||||
EntityType::Wipeout(value) => validate_wipeout(None, value)?,
|
||||
EntityType::Underlay(value) => validate_underlay(None, value)?,
|
||||
EntityType::Viewport(value) => validate_viewport(None, value)?,
|
||||
EntityType::AttributeDefinition(value) => {
|
||||
finite_vector(
|
||||
"AttributeDefinition.insertion_point",
|
||||
@@ -1386,6 +1417,7 @@ pub fn validate_entity_mutation(
|
||||
(EntityType::RasterImage(old), EntityType::RasterImage(new)) => validate_raster_image(Some(old), new)?,
|
||||
(EntityType::Wipeout(old), EntityType::Wipeout(new)) => validate_wipeout(Some(old), new)?,
|
||||
(EntityType::Underlay(old), EntityType::Underlay(new)) => validate_underlay(Some(old), new)?,
|
||||
(EntityType::Viewport(old), EntityType::Viewport(new)) => validate_viewport(Some(old), new)?,
|
||||
(EntityType::MLine(old), EntityType::MLine(new)) => validate_mline(Some(old), new)?,
|
||||
(EntityType::Leader(old), EntityType::Leader(new)) => validate_leader(Some(old), new)?,
|
||||
(EntityType::AttributeDefinition(old), EntityType::AttributeDefinition(new)) => {
|
||||
@@ -1649,6 +1681,22 @@ pub fn validate_canvas_entity_references(
|
||||
return Err(format!("Shape text style {:?} has no SHX file", style.name));
|
||||
}
|
||||
}
|
||||
if let EntityType::Viewport(value) = entity {
|
||||
let owner = value.common.owner_handle;
|
||||
let in_paper_space = !owner.is_null()
|
||||
&& document
|
||||
.block_records
|
||||
.iter()
|
||||
.any(|record| record.handle == owner && record.is_paper_space());
|
||||
if !in_paper_space {
|
||||
return Err("Viewport must be owned by a paper-space layout block".into());
|
||||
}
|
||||
for handle in &value.frozen_layers {
|
||||
if !document.layers.iter().any(|layer| layer.handle == *handle) {
|
||||
return Err(format!("Viewport frozen layer {handle:?} does not exist"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let EntityType::Underlay(value) = entity {
|
||||
match document.objects.get(&value.definition_handle) {
|
||||
Some(crate::host::acadrust::objects::ObjectType::UnderlayDefinition(definition)) => {
|
||||
@@ -2095,6 +2143,7 @@ mod tests {
|
||||
| "RasterImage"
|
||||
| "Wipeout"
|
||||
| "Underlay"
|
||||
| "Viewport"
|
||||
)
|
||||
{
|
||||
assert!(
|
||||
@@ -2393,6 +2442,23 @@ mod tests {
|
||||
"Underlay.fade".to_owned(),
|
||||
"Underlay.clip_boundary_vertices".to_owned(),
|
||||
"Underlay.clip_inverted".to_owned(),
|
||||
"Viewport.center".to_owned(),
|
||||
"Viewport.width".to_owned(),
|
||||
"Viewport.height".to_owned(),
|
||||
"Viewport.status".to_owned(),
|
||||
"Viewport.view_center".to_owned(),
|
||||
"Viewport.view_direction".to_owned(),
|
||||
"Viewport.view_target".to_owned(),
|
||||
"Viewport.lens_length".to_owned(),
|
||||
"Viewport.front_clip_z".to_owned(),
|
||||
"Viewport.back_clip_z".to_owned(),
|
||||
"Viewport.view_height".to_owned(),
|
||||
"Viewport.twist_angle".to_owned(),
|
||||
"Viewport.custom_scale".to_owned(),
|
||||
"Viewport.frozen_layers".to_owned(),
|
||||
"Viewport.render_mode".to_owned(),
|
||||
"Viewport.circle_sides".to_owned(),
|
||||
"Viewport.ucs_icon_visible".to_owned(),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user