Move source_node_id to "editor:layer" and Vector<Upstream> to "editor:merged_layers", backed by a new 'Write Attribute' node (#4061)

* Fix click target propagation with the Rasterize node

* Add the 'Write Attribute' node

* Remove tag_layer in favor of the new Write Attribute node, prune redundant attribute writes

* Replace the Vector<Upstream> type argument with the "editor:merged_layers" attribute
This commit is contained in:
Keavon Chambers
2026-04-28 03:07:23 -07:00
parent 76938eb69a
commit afc2c9178e
27 changed files with 312 additions and 376 deletions

View File

@@ -46,7 +46,10 @@ async fn boolean_operation<I: graphic_types::IntoGraphicTable + 'n + Send + Clon
let result_vector = result_vector_table.element_mut(0).unwrap();
Vector::transform(result_vector, transform);
result_vector.style.set_stroke_transform(DAffine2::IDENTITY);
result_vector.upstream_data = Some(content.clone());
// Snapshot the input layers as the `editor:merged_layers` row attribute so the renderer can recurse into them
// for editor click-target preservation.
result_vector_table.set_attribute("editor:merged_layers", 0, content.clone());
// Clean up the boolean operation result by merging duplicated points
let merge_transform: DAffine2 = result_vector_table.attribute_cloned_or_default("transform", 0);
@@ -127,7 +130,6 @@ fn boolean_operation_on_vector_table(vector: &Table<Vector>, boolean_operation:
let copy_from = vector.element(index).unwrap();
let element = Vector {
style: copy_from.style.clone(),
upstream_data: copy_from.upstream_data.clone(),
..Default::default()
};
TableRow::from_parts(element, attributes)
@@ -177,7 +179,7 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
}
Graphic::RasterCPU(image) => {
let parent_transform: DAffine2 = graphic_table.attribute_cloned_or_default("transform", index);
let make_row = |transform, source_node_id, alpha_blending| {
let make_row = |transform, layer, alpha_blending| {
let mut subpath = Subpath::new_rectangle(DVec2::ZERO, DVec2::ONE);
subpath.apply_transform(transform);
@@ -186,24 +188,24 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
TableRow::new_from_element(element)
.with_attribute("alpha_blending", alpha_blending)
.with_attribute("source_node_id", source_node_id)
.with_attribute("editor:layer", layer)
};
// Apply the parent graphic's transform to each raster element, preserving each row's source_node_id
// Apply the parent graphic's transform to each raster element, preserving each row's layer
// and alpha_blending so the boolean op downstream can route clicks (and inherit blending state)
// back to the originating raster layer
(0..image.len())
.map(|i| {
let row_transform: DAffine2 = image.attribute_cloned_or_default("transform", i);
let source_node_id: Option<NodeId> = image.attribute_cloned_or_default("source_node_id", i);
let layer: Option<NodeId> = image.attribute_cloned_or_default("editor:layer", i);
let alpha_blending: AlphaBlending = image.attribute_cloned_or_default("alpha_blending", i);
make_row(parent_transform * row_transform, source_node_id, alpha_blending)
make_row(parent_transform * row_transform, layer, alpha_blending)
})
.collect::<Vec<_>>()
}
Graphic::RasterGPU(image) => {
let parent_transform: DAffine2 = graphic_table.attribute_cloned_or_default("transform", index);
let make_row = |transform, source_node_id, alpha_blending| {
let make_row = |transform, layer, alpha_blending| {
let mut subpath = Subpath::new_rectangle(DVec2::ZERO, DVec2::ONE);
subpath.apply_transform(transform);
@@ -212,18 +214,18 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
TableRow::new_from_element(element)
.with_attribute("alpha_blending", alpha_blending)
.with_attribute("source_node_id", source_node_id)
.with_attribute("editor:layer", layer)
};
// Apply the parent graphic's transform to each raster element, preserving each row's source_node_id
// Apply the parent graphic's transform to each raster element, preserving each row's layer
// and alpha_blending so the boolean op downstream can route clicks (and inherit blending state)
// back to the originating raster layer
(0..image.len())
.map(|i| {
let row_transform: DAffine2 = image.attribute_cloned_or_default("transform", i);
let source_node_id: Option<NodeId> = image.attribute_cloned_or_default("source_node_id", i);
let layer: Option<NodeId> = image.attribute_cloned_or_default("editor:layer", i);
let alpha_blending: AlphaBlending = image.attribute_cloned_or_default("alpha_blending", i);
make_row(parent_transform * row_transform, source_node_id, alpha_blending)
make_row(parent_transform * row_transform, layer, alpha_blending)
})
.collect::<Vec<_>>()
}