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:28:31 -07:00
parent 76938eb69a
commit afc2c9178e
27 changed files with 312 additions and 376 deletions
+3 -6
View File
@@ -276,10 +276,7 @@ async fn brush(
let has_erase_or_restore_strokes = strokes.iter().any(|s| matches!(s.style.blend_mode, BlendMode::Erase | BlendMode::Restore));
if has_erase_or_restore_strokes {
let opaque_image = Image::new(bbox.size().x as u32, bbox.size().y as u32, Color::WHITE);
let mut erase_restore_mask = TableRow::new_from_element(Raster::new_cpu(opaque_image))
.with_attribute("transform", background_bounds)
.with_attribute("alpha_blending", AlphaBlending::default())
.with_attribute("source_node_id", None::<NodeId>);
let mut erase_restore_mask = TableRow::new_from_element(Raster::new_cpu(opaque_image)).with_attribute("transform", background_bounds);
for stroke in strokes {
let mut brush_texture = cache.get_cached_brush(&stroke.style);
@@ -313,12 +310,12 @@ async fn brush(
let transform: DAffine2 = actual_image.attribute_cloned_or_default("transform");
let alpha_blending: AlphaBlending = actual_image.attribute_cloned_or_default("alpha_blending");
let source_node_id: Option<NodeId> = actual_image.attribute_cloned_or_default("source_node_id");
let layer: Option<NodeId> = actual_image.attribute_cloned_or_default("editor:layer");
*image.element_mut(0).unwrap() = actual_image.into_element();
image.set_attribute("transform", 0, transform);
image.set_attribute("alpha_blending", 0, alpha_blending);
image.set_attribute("source_node_id", 0, source_node_id);
image.set_attribute("editor:layer", 0, layer);
image
}
+2 -4
View File
@@ -64,10 +64,8 @@ impl BrushCacheImpl {
background = std::mem::take(&mut self.blended_image);
// Check if the first non-blended stroke is an extension of the last one.
let mut first_stroke_texture = TableRow::new_from_element(Raster::<CPU>::default())
.with_attribute("transform", glam::DAffine2::ZERO)
.with_attribute("alpha_blending", core_types::AlphaBlending::default())
.with_attribute("source_node_id", None::<core_types::uuid::NodeId>);
// Transform is set to ZERO (not the default IDENTITY) as a sentinel to mark this row as uninitialized.
let mut first_stroke_texture = TableRow::new_from_element(Raster::<CPU>::default()).with_attribute("transform", glam::DAffine2::ZERO);
let mut first_stroke_point_skip = 0;
let strokes = input[num_blended_strokes..].to_vec();
if !strokes.is_empty() && self.prev_input.len() > num_blended_strokes {