forked from 1b-agent/opencadstudio-upstream
fix(render): highlight untinted analytical curves and guard uniform bind group
- Fall back to WireModel::SELECTED when selected_tint is None (classic mode) so selected circles, arcs, and ellipses are not omitted from the highlight pass. - Explicitly rebind uniform_bind_group before drawing analytical curves in selection_xray pass. - Skip invisible wires (display_visible == false) during selection and hover wire extraction.
This commit is contained in:
1 parent
9868158e27
commit
08891816be
2 files changed
+171
-16
No files matched your search
@@ -457,6 +457,37 @@ fn test_selected_circle_arc_ellipse_highlight_overlay() {
|
|||||||
assert_eq!(pipeline.gpu_selected_circles[0].instance_count, 1);
|
assert_eq!(pipeline.gpu_selected_circles[0].instance_count, 1);
|
||||||
assert!(pipeline.gpu_selected_wires.is_empty());
|
assert!(pipeline.gpu_selected_wires.is_empty());
|
||||||
|
|
||||||
|
// Verify classic highlight mode (SELECTIONEFFECT 0 / selected_tint: None)
|
||||||
|
pipeline.upload_selected_wires(
|
||||||
|
&device,
|
||||||
|
&queue,
|
||||||
|
&wires,
|
||||||
|
&selected_handles,
|
||||||
|
&hover_handles,
|
||||||
|
&[],
|
||||||
|
&depth,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
assert_eq!(pipeline.gpu_selected_circles.len(), 1);
|
||||||
|
assert_eq!(pipeline.gpu_selected_circles[0].instance_count, 1);
|
||||||
|
|
||||||
|
// Verify hover highlight
|
||||||
|
let mut circle_hover = rustc_hash::FxHashSet::default();
|
||||||
|
circle_hover.insert(handle);
|
||||||
|
let empty_selected = rustc_hash::FxHashSet::default();
|
||||||
|
pipeline.upload_selected_wires(
|
||||||
|
&device,
|
||||||
|
&queue,
|
||||||
|
&wires,
|
||||||
|
&empty_selected,
|
||||||
|
&circle_hover,
|
||||||
|
&[],
|
||||||
|
&depth,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
assert_eq!(pipeline.gpu_selected_circles.len(), 1);
|
||||||
|
assert_eq!(pipeline.gpu_selected_circles[0].instance_count, 1);
|
||||||
|
|
||||||
pipeline.ensure_depth_texture(&device, iced::Size::new(512, 512));
|
pipeline.ensure_depth_texture(&device, iced::Size::new(512, 512));
|
||||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
label: Some("test_target"),
|
label: Some("test_target"),
|
||||||
@@ -490,6 +521,121 @@ fn test_selected_circle_arc_ellipse_highlight_overlay() {
|
|||||||
device.poll(wgpu::PollType::wait_indefinitely()).unwrap();
|
device.poll(wgpu::PollType::wait_indefinitely()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore = "requires a GPU adapter"]
|
||||||
|
fn test_selected_ellipse_overlay() {
|
||||||
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle());
|
||||||
|
let adapter = block_on(instance.request_adapter(&wgpu::RequestAdapterOptions::default()))
|
||||||
|
.expect("GPU adapter");
|
||||||
|
let (device, queue) = block_on(adapter.request_device(&wgpu::DeviceDescriptor {
|
||||||
|
required_limits: adapter.limits(),
|
||||||
|
..Default::default()
|
||||||
|
}))
|
||||||
|
.expect("GPU device");
|
||||||
|
let mut pipeline = Pipeline::new(&device, &queue, wgpu::TextureFormat::Bgra8UnormSrgb);
|
||||||
|
let depth = rustc_hash::FxHashMap::default();
|
||||||
|
|
||||||
|
let mut ellipse_wire = WireModel::default();
|
||||||
|
ellipse_wire.name = "ellipse_wire".into();
|
||||||
|
ellipse_wire.tangent_geoms.push(crate::scene::model::wire_model::TangentGeom::PlanarEllipse {
|
||||||
|
center: [0.0, 0.0, 0.0],
|
||||||
|
major_axis: [10.0, 0.0, 0.0],
|
||||||
|
normal: [0.0, 0.0, 1.0],
|
||||||
|
minor_axis_ratio: 0.5,
|
||||||
|
start_param: 0.0,
|
||||||
|
end_param: std::f64::consts::TAU,
|
||||||
|
});
|
||||||
|
|
||||||
|
let handle = acadrust::Handle::new(200);
|
||||||
|
let mut selected_handles = rustc_hash::FxHashSet::default();
|
||||||
|
selected_handles.insert(handle);
|
||||||
|
let hover_handles = rustc_hash::FxHashSet::default();
|
||||||
|
|
||||||
|
let mut index = rustc_hash::FxHashMap::default();
|
||||||
|
index.insert(handle.value(), vec![0]);
|
||||||
|
pipeline.wire_handle_index = std::sync::Arc::new(index);
|
||||||
|
|
||||||
|
let wires = vec![ellipse_wire];
|
||||||
|
// Standard tint
|
||||||
|
pipeline.upload_selected_wires(
|
||||||
|
&device,
|
||||||
|
&queue,
|
||||||
|
&wires,
|
||||||
|
&selected_handles,
|
||||||
|
&hover_handles,
|
||||||
|
&[],
|
||||||
|
&depth,
|
||||||
|
Some([0.0, 1.0, 1.0, 1.0]),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(pipeline.gpu_selected_ellipses.len(), 1);
|
||||||
|
assert_eq!(pipeline.gpu_selected_ellipses[0].instance_count, 1);
|
||||||
|
assert!(pipeline.gpu_selected_wires.is_empty());
|
||||||
|
|
||||||
|
// Classic highlight mode (SELECTIONEFFECT 0 / selected_tint: None)
|
||||||
|
pipeline.upload_selected_wires(
|
||||||
|
&device,
|
||||||
|
&queue,
|
||||||
|
&wires,
|
||||||
|
&selected_handles,
|
||||||
|
&hover_handles,
|
||||||
|
&[],
|
||||||
|
&depth,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
assert_eq!(pipeline.gpu_selected_ellipses.len(), 1);
|
||||||
|
assert_eq!(pipeline.gpu_selected_ellipses[0].instance_count, 1);
|
||||||
|
|
||||||
|
// Hover highlight
|
||||||
|
let mut ellipse_hover = rustc_hash::FxHashSet::default();
|
||||||
|
ellipse_hover.insert(handle);
|
||||||
|
let empty_selected = rustc_hash::FxHashSet::default();
|
||||||
|
pipeline.upload_selected_wires(
|
||||||
|
&device,
|
||||||
|
&queue,
|
||||||
|
&wires,
|
||||||
|
&empty_selected,
|
||||||
|
&ellipse_hover,
|
||||||
|
&[],
|
||||||
|
&depth,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
assert_eq!(pipeline.gpu_selected_ellipses.len(), 1);
|
||||||
|
assert_eq!(pipeline.gpu_selected_ellipses[0].instance_count, 1);
|
||||||
|
|
||||||
|
pipeline.ensure_depth_texture(&device, iced::Size::new(512, 512));
|
||||||
|
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: Some("test_target_ellipse"),
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: 512,
|
||||||
|
height: 512,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
|
view_formats: &[],
|
||||||
|
});
|
||||||
|
let target = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||||
|
label: Some("test_encoder_ellipse"),
|
||||||
|
});
|
||||||
|
pipeline.render(
|
||||||
|
&mut encoder,
|
||||||
|
&target,
|
||||||
|
iced::Size::new(512, 512),
|
||||||
|
iced::Rectangle { x: 0, y: 0, width: 512, height: 512 },
|
||||||
|
[0.0, 0.0, 0.0, 1.0],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
queue.submit(Some(encoder.finish()));
|
||||||
|
device.poll(wgpu::PollType::wait_indefinitely()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore = "requires a GPU adapter"]
|
#[ignore = "requires a GPU adapter"]
|
||||||
fn test_pline_arc_switch_preview_and_render() {
|
fn test_pline_arc_switch_preview_and_render() {
|
||||||
|
|||||||
+25
-16
@@ -2641,6 +2641,9 @@ impl Pipeline {
|
|||||||
slots.sort_unstable();
|
slots.sort_unstable();
|
||||||
for &i in &slots {
|
for &i in &slots {
|
||||||
if let Some(w) = wires.get(i as usize) {
|
if let Some(w) = wires.get(i as usize) {
|
||||||
|
if !w.display_visible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
selected_wires.push(w);
|
selected_wires.push(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2652,12 +2655,18 @@ impl Pipeline {
|
|||||||
slots.sort_unstable();
|
slots.sort_unstable();
|
||||||
for &i in &slots {
|
for &i in &slots {
|
||||||
if let Some(w) = wires.get(i as usize) {
|
if let Some(w) = wires.get(i as usize) {
|
||||||
|
if !w.display_visible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
hover_wires.push(w);
|
hover_wires.push(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for wire in annotation_context_wires {
|
for wire in annotation_context_wires {
|
||||||
|
if !wire.display_visible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if wire.selected {
|
if wire.selected {
|
||||||
selected_wires.push(wire);
|
selected_wires.push(wire);
|
||||||
} else {
|
} else {
|
||||||
@@ -2665,14 +2674,13 @@ impl Pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut selected_circles: Vec<CircleInstance> = Vec::new();
|
let mut selected_circles: Vec<CircleInstance> = Vec::new();
|
||||||
if let Some(tint) = selected_tint {
|
let circle_sel_tint = selected_tint.unwrap_or(WireModel::SELECTED);
|
||||||
for &wire in &selected_wires {
|
for &wire in &selected_wires {
|
||||||
let depth = wire_gpu::wire_draw_depth(wire, depth_map);
|
let depth = wire_gpu::wire_draw_depth(wire, depth_map);
|
||||||
if let Some(insts) = circle_gpu::extract_circle_instances(wire, depth) {
|
if let Some(insts) = circle_gpu::extract_circle_instances(wire, depth) {
|
||||||
for mut inst in insts {
|
for mut inst in insts {
|
||||||
inst.color = tint;
|
inst.color = circle_sel_tint;
|
||||||
selected_circles.push(inst);
|
selected_circles.push(inst);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2697,14 +2705,13 @@ impl Pipeline {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut selected_ellipses: Vec<EllipseInstance> = Vec::new();
|
let mut selected_ellipses: Vec<EllipseInstance> = Vec::new();
|
||||||
if let Some(tint) = selected_tint {
|
let ellipse_sel_tint = selected_tint.unwrap_or(WireModel::SELECTED);
|
||||||
for &wire in &selected_wires {
|
for &wire in &selected_wires {
|
||||||
let depth = wire_gpu::wire_draw_depth(wire, depth_map);
|
let depth = wire_gpu::wire_draw_depth(wire, depth_map);
|
||||||
if let Some(insts) = ellipse_gpu::extract_ellipse_instances(wire, depth) {
|
if let Some(insts) = ellipse_gpu::extract_ellipse_instances(wire, depth) {
|
||||||
for mut inst in insts {
|
for mut inst in insts {
|
||||||
inst.color = tint;
|
inst.color = ellipse_sel_tint;
|
||||||
selected_ellipses.push(inst);
|
selected_ellipses.push(inst);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4854,6 +4861,7 @@ impl Pipeline {
|
|||||||
} else {
|
} else {
|
||||||
&self.circle_xray_pipeline
|
&self.circle_xray_pipeline
|
||||||
});
|
});
|
||||||
|
pass.set_bind_group(0, &self.uniform_bind_group, &[]);
|
||||||
for cg in &self.gpu_selected_circles {
|
for cg in &self.gpu_selected_circles {
|
||||||
if cg.instance_count > 0 {
|
if cg.instance_count > 0 {
|
||||||
pass.set_vertex_buffer(0, cg.instance_buffer.slice(..));
|
pass.set_vertex_buffer(0, cg.instance_buffer.slice(..));
|
||||||
@@ -4867,6 +4875,7 @@ impl Pipeline {
|
|||||||
} else {
|
} else {
|
||||||
&self.ellipse_xray_pipeline
|
&self.ellipse_xray_pipeline
|
||||||
});
|
});
|
||||||
|
pass.set_bind_group(0, &self.uniform_bind_group, &[]);
|
||||||
for eg in &self.gpu_selected_ellipses {
|
for eg in &self.gpu_selected_ellipses {
|
||||||
if eg.instance_count > 0 {
|
if eg.instance_count > 0 {
|
||||||
pass.set_vertex_buffer(0, eg.instance_buffer.slice(..));
|
pass.set_vertex_buffer(0, eg.instance_buffer.slice(..));
|
||||||
|
|||||||
Reference in new issue
Block a user