Frames: state-following ribbon list, DWF/DGN frames, image frame encoding and profile, frame-only picking

- The Frames list shows the drawing's frame state (hide / display and plot /
  display but not plot / frames vary), follows commands, undo and document
  switches, and lists the mixed state as a disabled item.
- DWFFRAME and DGNFRAME are frame variables of their own, kept in the header,
  and FRAME sets them with the others.
- Out-of-range frame values say "Requires an integer between 0 and 2." and
  ask again; a set value reports "Regenerating model.".
- IMAGEFRAME is stored in the image variables as bits (2 is written as 3) and
  a drawing without them uses the profile value, which setting IMAGEFRAME
  updates and the settings file keeps.
- Raster images, PDF underlays and wipeouts are picked on their frame only;
  underlay snap geometry is never picked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-09-28 10:53:53 +03:00
1 parent 801882314f
commit 7f8f8457c7
72 files changed
+451 -65

No files matched your search

+7
View File
@@ -4041,6 +4041,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -4077,6 +4078,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -4113,6 +4115,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -4150,6 +4153,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -4195,6 +4199,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -4244,6 +4249,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -4295,6 +4301,7 @@ fn tessellate_dimension_inner(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
+2
View File
@@ -679,6 +679,7 @@ impl LeaderTess for Leader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -860,6 +861,7 @@ impl LeaderTess for Leader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
+5
View File
@@ -2075,6 +2075,7 @@ impl MultiLeaderTess for MultiLeader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -2389,6 +2390,7 @@ impl MultiLeaderTess for MultiLeader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -2464,6 +2466,7 @@ impl MultiLeaderTess for MultiLeader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -2554,6 +2557,7 @@ impl MultiLeaderTess for MultiLeader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
@@ -2599,6 +2603,7 @@ impl MultiLeaderTess for MultiLeader {
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
+6 -32
View File
@@ -178,9 +178,9 @@ impl RenderConvertible for RasterImage {
path.is_empty() || crate::scene::model::image_model::resolve_image(path).is_some();
if resolvable {
return Some(RenderEntity {
// Interior pick surface: the image selects on a click anywhere
// inside its frame, not just on the border.
pick_tris: crate::entities::common::quad_pick_tris(&corners),
// Picked on its frame only (shown or hidden), like the other
// framed objects: a click inside the picture selects nothing.
pick_tris: vec![],
object: RenderObject::Lines(pts),
snap_pts: vec![],
tangent_geoms: vec![],
@@ -269,7 +269,7 @@ impl RenderConvertible for RasterImage {
}
Some(RenderEntity {
pick_tris: crate::entities::common::quad_pick_tris(&corners),
pick_tris: vec![],
object: RenderObject::Text(groups),
snap_pts: vec![],
tangent_geoms: vec![],
@@ -512,30 +512,6 @@ fn wipeout_axis_length(axis: &codec::types::Vector3, size: f64) -> f64 {
(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z).sqrt() * size.abs()
}
fn wipeout_pick_rings(wipeout: &Wipeout) -> Vec<Vec<[f64; 3]>> {
let boundary = wipeout_boundary(wipeout);
if wipeout_is_polygonal(wipeout)
&& matches!(
wipeout.clip_mode,
codec::entities::WipeoutClipMode::Inside
)
{
vec![
image_corners(
&wipeout.insertion_point,
&wipeout.u_vector,
&wipeout.v_vector,
wipeout.size.x,
wipeout.size.y,
)
.to_vec(),
boundary,
]
} else {
vec![boundary]
}
}
fn wipeout_world_to_clip(wipeout: &Wipeout, world: [f64; 3]) -> Option<codec::types::Vector2> {
let [x, y] = wipeout_plane(wipeout).project(world)?;
Some(codec::types::Vector2::new(
@@ -553,10 +529,8 @@ impl RenderConvertible for Wipeout {
}
Some(RenderEntity {
pick_tris: kernel::space::polygon::triangulate_rings(
&wipeout_pick_rings(self),
kernel::geom2d::Tolerance::default(),
),
// Picked on its frame only; the masked area selects nothing.
pick_tris: vec![],
object: RenderObject::Lines(pts),
snap_pts: boundary
.iter()
+1
View File
@@ -2036,6 +2036,7 @@ pub fn tessellate_table(
world_width: 0.0,
depth_override: None,
display_visible: true,
snap_only: false,
plot_visible: true,
fill_is_3d: false,
fill_is_2d_solid: false,
+4 -5
View File
@@ -288,21 +288,20 @@ impl RenderConvertible for Underlay {
});
}
// Pick surface over the shown area so a click inside selects it.
let pick_ring: Vec<[f64; 3]> = if !clip.is_empty() && !self.clip_inverted {
// Picked on its frame only; the page itself selects nothing.
let key_ring: Vec<[f64; 3]> = if !clip.is_empty() && !self.clip_inverted {
clip.clone()
} else {
quad.map(|q| q.to_vec()).unwrap_or_default()
};
let pick_tris = crate::entities::mesh::triangulate_planar(&pick_ring);
let mut snap_pts = vec![insertion_snap];
snap_pts.extend(crate::scene::model::pdf_vector::underlay_snap_points(self, document));
Some(RenderEntity {
pick_tris,
pick_tris: vec![],
object: RenderObject::Lines(pts),
snap_pts,
tangent_geoms: vec![],
key_vertices: pick_ring,
key_vertices: key_ring,
fill_tris: vec![],
})
}