From 7d44f6ec9efcde2cbba34c370d013ffd5ee9f4e8 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Wed, 26 Aug 2026 21:50:35 +0000 Subject: [PATCH] Collect a group element as its typed lowering --- .../libraries/rendering/src/renderer.rs | 92 +++++++++---------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/node-graph/libraries/rendering/src/renderer.rs b/node-graph/libraries/rendering/src/renderer.rs index 175c9a6435..a6d5fffd31 100644 --- a/node-graph/libraries/rendering/src/renderer.rs +++ b/node-graph/libraries/rendering/src/renderer.rs @@ -701,8 +701,9 @@ fn element_can_reduce_to_clip_path<'a>(element: &'a Graphic, reach: PaintReach<' fn collect_element_metadata<'a>(element: &'a Graphic, reach: PaintReach<'a>, metadata: &mut RenderMetadata, footprint: Footprint, element_id: Option) { if let Some(element_id) = element_id { match element { - Graphic::Group(_) => { + Graphic::Group(group) => { metadata.upstream_footprints.insert(element_id, footprint); + collect_group_row_metadata(group, metadata, element_id); } Graphic::Graphic(_) => { metadata.upstream_footprints.insert(element_id, footprint); @@ -775,6 +776,35 @@ fn collect_element_metadata<'a>(element: &'a Graphic, reach: PaintReach<'a>, met } } +/// The id-level metadata the legacy lowering exposed for a group element: a +/// bare typed run serves its lane-0 transform (and source id for vectors) as +/// the layer's local transform, matching the typed list the conversion made. +fn collect_group_row_metadata(group: &Group, metadata: &mut RenderMetadata, element_id: NodeId) { + fn lane_zero_transform(item: &core_types::record::GroupItem) -> Option { + RunView::::new(item).map(|run| run.attr::(0)) + } + + let GroupContent::Run(item) = &group.content else { return }; + if group.row.is_some() || item.is_empty() || item.typed_lanes::().is_some() { + return; + } + if let Some(run) = RunView::::new(item) { + let layer_path: &[NodeId] = run.attr::(0); + metadata.first_element_source_id.insert(element_id, layer_path.last().copied()); + metadata.local_transforms.insert(element_id, run.attr::(0)); + return; + } + let transform = None + .or_else(|| lane_zero_transform::>(item)) + .or_else(|| lane_zero_transform::>(item)) + .or_else(|| lane_zero_transform::(item)) + .or_else(|| lane_zero_transform::(item)) + .or_else(|| lane_zero_transform::(item)); + if let Some(transform) = transform { + metadata.local_transforms.insert(element_id, transform); + } +} + fn add_element_upstream_click_targets<'a>(element: &'a Graphic, reach: PaintReach<'a>, click_targets: &mut Vec) { match element { Graphic::Graphic(list) => add_graphic_upstream_click_targets_with(list, reach.nested(), click_targets), @@ -853,29 +883,10 @@ fn render_group_vello<'a>(group: &'a Group, reach: PaintReach<'a>, scene: &mut S } } -/// Reproduces the legacy wrapper's metadata effects for a typed run: the -/// lanes collect with their own recovered ids, and the caller's element id -/// aggregates the run's upstream click targets and outlines. +/// Collects a group as its legacy lowering did: a typed run behaves as the +/// typed variant the conversion produced, so a caller's element id passes +/// through to the typed body unchanged. fn collect_group_metadata<'a>(group: &'a Group, reach: PaintReach<'a>, metadata: &mut RenderMetadata, footprint: Footprint, element_id: Option) { - fn typed_run( - source: &S, - metadata: &mut RenderMetadata, - footprint: Footprint, - element_id: Option, - collect: impl Fn(&S, &mut RenderMetadata, Footprint, Option), - click: impl Fn(&S, &mut Vec), - outline: impl Fn(&S, &mut Vec), - ) { - collect(source, metadata, footprint, None); - let Some(element_id) = element_id else { return }; - let mut click_targets = Vec::new(); - click(source, &mut click_targets); - metadata.click_targets.insert(element_id, click_targets.into_iter().map(Into::into).collect()); - let mut outlines = Vec::new(); - outline(source, &mut outlines); - metadata.outlines.insert(element_id, outlines.into_iter().map(Into::into).collect()); - } - let GroupContent::Run(item) = &group.content else { return group_to_legacy_list(group).collect_metadata(metadata, footprint, element_id); }; @@ -883,31 +894,16 @@ fn collect_group_metadata<'a>(group: &'a Group, reach: PaintReach<'a>, metadata: collect_graphic_metadata_with(&run, reach.into_group_graphics(), metadata, footprint, element_id) } else if let Some(run) = RunView::::new(item) { match reach.applies() { - true => typed_run( - &PaintOverlay::new(&run, reach.paint), - metadata, - footprint, - element_id, - collect_vector_metadata, - add_vector_upstream_click_targets, - add_vector_upstream_outline_targets, - ), - false => typed_run(&run, metadata, footprint, element_id, collect_vector_metadata, add_vector_upstream_click_targets, add_vector_upstream_outline_targets), + true => collect_vector_metadata(&PaintOverlay::new(&run, reach.paint), metadata, footprint, element_id), + false => collect_vector_metadata(&run, metadata, footprint, element_id), } } else if let Some(run) = RunView::>::new(item) { - typed_run(&run, metadata, footprint, element_id, collect_raster_metadata, |_, out| add_raster_upstream_click_targets(out), |_, out| { - add_raster_upstream_click_targets(out) - }) + collect_raster_metadata(&run, metadata, footprint, element_id) } else if let Some(run) = RunView::>::new(item) { - typed_run(&run, metadata, footprint, element_id, collect_raster_metadata, |_, out| add_raster_upstream_click_targets(out), |_, out| { - add_raster_upstream_click_targets(out) - }) - } else if let Some(run) = RunView::::new(item) { - typed_run(&run, metadata, footprint, element_id, |_, _, _, _| (), |_, _| (), |_, _| ()) - } else if let Some(run) = RunView::::new(item) { - typed_run(&run, metadata, footprint, element_id, |_, _, _, _| (), |_, _| (), |_, _| ()) + collect_raster_metadata(&run, metadata, footprint, element_id) + } else if item.typed_lanes::().is_some() || item.typed_lanes::().is_some() { } else if let Some(run) = RunView::::new(item) { - typed_run(&run, metadata, footprint, element_id, collect_text_metadata, add_text_upstream_click_targets, add_text_upstream_click_targets) + collect_text_metadata(&run, metadata, footprint, element_id) } else { group_to_legacy_list(group).collect_metadata(metadata, footprint, element_id) } @@ -3105,7 +3101,7 @@ mod group_walk_tests { } #[test] - fn a_group_collects_the_wrapper_metadata() { + fn a_group_collects_like_its_legacy_lowering() { let paint = color_paint(); let vectors = [unit_square_at(DVec2::ZERO)]; let layout = Layout::default().with_writes(0, element_write_hashed::(), &[FieldWrite::of::(0)]); @@ -3122,15 +3118,15 @@ mod group_walk_tests { Graphic::Group(group.clone()).collect_metadata(&mut native, footprint, Some(caller)); let mut legacy = RenderMetadata::default(); - legacy.upstream_footprints.insert(caller, footprint); - graphic_types::graphic::group_to_legacy_list(&group).collect_metadata(&mut legacy, footprint, Some(caller)); + group_to_legacy_graphic(&group).collect_metadata(&mut legacy, footprint, Some(caller)); assert!(native.click_targets.get(&caller).is_some_and(|targets| !targets.is_empty())); + assert!(native.local_transforms.contains_key(&caller)); assert_eq!(native, legacy); } #[test] - fn a_group_serves_the_wrapper_click_targets() { + fn a_group_serves_its_legacy_lowerings_click_targets() { let paint = color_paint(); let vectors = [unit_square_at(DVec2::ZERO), unit_square_at(DVec2::new(2., 2.))]; let layout = Layout::default().with_writes(0, element_write_hashed::(), &[FieldWrite::of::(0)]);