diff --git a/src/scene/pipeline/gpu_tests.rs b/src/scene/pipeline/gpu_tests.rs index 7b7ab968f..6ff34c4d0 100644 --- a/src/scene/pipeline/gpu_tests.rs +++ b/src/scene/pipeline/gpu_tests.rs @@ -457,6 +457,37 @@ fn test_selected_circle_arc_ellipse_highlight_overlay() { assert_eq!(pipeline.gpu_selected_circles[0].instance_count, 1); 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)); let texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("test_target"), @@ -490,6 +521,121 @@ fn test_selected_circle_arc_ellipse_highlight_overlay() { 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] #[ignore = "requires a GPU adapter"] fn test_pline_arc_switch_preview_and_render() { diff --git a/src/scene/pipeline/mod.rs b/src/scene/pipeline/mod.rs index 74313aa61..880464b12 100644 --- a/src/scene/pipeline/mod.rs +++ b/src/scene/pipeline/mod.rs @@ -2641,6 +2641,9 @@ impl Pipeline { slots.sort_unstable(); for &i in &slots { if let Some(w) = wires.get(i as usize) { + if !w.display_visible { + continue; + } selected_wires.push(w); } } @@ -2652,12 +2655,18 @@ impl Pipeline { slots.sort_unstable(); for &i in &slots { if let Some(w) = wires.get(i as usize) { + if !w.display_visible { + continue; + } hover_wires.push(w); } } } } for wire in annotation_context_wires { + if !wire.display_visible { + continue; + } if wire.selected { selected_wires.push(wire); } else { @@ -2665,14 +2674,13 @@ impl Pipeline { } } let mut selected_circles: Vec = Vec::new(); - if let Some(tint) = selected_tint { - for &wire in &selected_wires { - let depth = wire_gpu::wire_draw_depth(wire, depth_map); - if let Some(insts) = circle_gpu::extract_circle_instances(wire, depth) { - for mut inst in insts { - inst.color = tint; - selected_circles.push(inst); - } + let circle_sel_tint = selected_tint.unwrap_or(WireModel::SELECTED); + for &wire in &selected_wires { + let depth = wire_gpu::wire_draw_depth(wire, depth_map); + if let Some(insts) = circle_gpu::extract_circle_instances(wire, depth) { + for mut inst in insts { + inst.color = circle_sel_tint; + selected_circles.push(inst); } } } @@ -2697,14 +2705,13 @@ impl Pipeline { }; let mut selected_ellipses: Vec = Vec::new(); - if let Some(tint) = selected_tint { - for &wire in &selected_wires { - let depth = wire_gpu::wire_draw_depth(wire, depth_map); - if let Some(insts) = ellipse_gpu::extract_ellipse_instances(wire, depth) { - for mut inst in insts { - inst.color = tint; - selected_ellipses.push(inst); - } + let ellipse_sel_tint = selected_tint.unwrap_or(WireModel::SELECTED); + for &wire in &selected_wires { + let depth = wire_gpu::wire_draw_depth(wire, depth_map); + if let Some(insts) = ellipse_gpu::extract_ellipse_instances(wire, depth) { + for mut inst in insts { + inst.color = ellipse_sel_tint; + selected_ellipses.push(inst); } } } @@ -4854,6 +4861,7 @@ impl Pipeline { } else { &self.circle_xray_pipeline }); + pass.set_bind_group(0, &self.uniform_bind_group, &[]); for cg in &self.gpu_selected_circles { if cg.instance_count > 0 { pass.set_vertex_buffer(0, cg.instance_buffer.slice(..)); @@ -4867,6 +4875,7 @@ impl Pipeline { } else { &self.ellipse_xray_pipeline }); + pass.set_bind_group(0, &self.uniform_bind_group, &[]); for eg in &self.gpu_selected_ellipses { if eg.instance_count > 0 { pass.set_vertex_buffer(0, eg.instance_buffer.slice(..));