Instance tables refactor part 6: unwrap VectorData and ImageFrame from single-row to multi-row tables (#2684)

* Start refactoring the boolean operations code

* Switch to iterators in the boolean operations code

* Make boolean operations work on rows of a table, not Vecs of single-row tables

* Remove more .transform()

* Simplify brush code

* Attempt to remove .transform() by using Instance<Image<Color>> in brush code, but a regression is introduced

* Improve blend_image_closure

* Simplify

* Remove leading underscore from type arguments

* Remove .transform() from ImageFrameTable<P> and fix Mask node behavior on stencils not fully overlapping its target image

* Remove more .one_instance_ref()

* Fully remove .one_instance_ref() and improve the 'Combine Channels' node robustness

* Fully remove .once_instance_mut()

* Fix tests

* Remove .one_empty_image()

* Make Instances<T>::default() return an empty table for images, but still not yet vector

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
This commit is contained in:
Keavon Chambers
2025-06-04 20:40:15 -07:00
committed by GitHub
parent 76ecdc8f1b
commit cb4289169d
29 changed files with 882 additions and 811 deletions

View File

@@ -129,7 +129,9 @@ mod test {
.instance
.as_vector_data()
.unwrap()
.one_instance_ref()
.instance_ref_iter()
.next()
.unwrap()
.instance
.bounding_box_with_transform(*instanced.transform)
.unwrap();

View File

@@ -253,9 +253,9 @@ fn isometric_grid_test() {
// Works properly
let grid = grid((), (), GridType::Isometric, 10., (30., 30.).into(), 5, 5);
assert_eq!(grid.one_instance_ref().instance.point_domain.ids().len(), 5 * 5);
assert_eq!(grid.one_instance_ref().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9);
for (_, bezier, _, _) in grid.one_instance_ref().instance.segment_bezier_iter() {
assert_eq!(grid.instance_ref_iter().next().unwrap().instance.point_domain.ids().len(), 5 * 5);
assert_eq!(grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9);
for (_, bezier, _, _) in grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter() {
assert_eq!(bezier.handles, bezier_rs::BezierHandles::Linear);
assert!(
((bezier.start - bezier.end).length() - 10.).abs() < 1e-5,
@@ -268,9 +268,9 @@ fn isometric_grid_test() {
#[test]
fn skew_isometric_grid_test() {
let grid = grid((), (), GridType::Isometric, 10., (40., 30.).into(), 5, 5);
assert_eq!(grid.one_instance_ref().instance.point_domain.ids().len(), 5 * 5);
assert_eq!(grid.one_instance_ref().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9);
for (_, bezier, _, _) in grid.one_instance_ref().instance.segment_bezier_iter() {
assert_eq!(grid.instance_ref_iter().next().unwrap().instance.point_domain.ids().len(), 5 * 5);
assert_eq!(grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9);
for (_, bezier, _, _) in grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter() {
assert_eq!(bezier.handles, bezier_rs::BezierHandles::Linear);
let vector = bezier.start - bezier.end;
let angle = (vector.angle_to(DVec2::X).to_degrees() + 180.) % 180.;

View File

@@ -60,8 +60,8 @@ pub fn migrate_vector_data<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
region_domain: old.region_domain,
upstream_graphic_group: old.upstream_graphic_group,
});
*vector_data_table.one_instance_mut().transform = old.transform;
*vector_data_table.one_instance_mut().alpha_blending = old.alpha_blending;
*vector_data_table.instance_mut_iter().next().unwrap().transform = old.transform;
*vector_data_table.instance_mut_iter().next().unwrap().alpha_blending = old.alpha_blending;
vector_data_table
}
EitherFormat::VectorDataTable(vector_data_table) => vector_data_table,

View File

@@ -1193,11 +1193,16 @@ async fn flatten_vector_elements(_: impl Ctx, graphic_group_input: GraphicGroupT
}
}
let mut output_table = VectorDataTable::default();
let Some(mut output) = output_table.instance_mut_iter().next() else { return output_table };
// Create a table with one instance of an empty VectorData, then get a mutable reference to it which we append flattened subpaths to
let mut output_table = VectorDataTable::new(VectorData::default());
let Some(mut output) = output_table.instance_mut_iter().next() else {
return output_table;
};
// Flatten the graphic group input into the output VectorData instance
flatten_group(&graphic_group_input, &mut output);
// Return the single-row VectorDataTable containing the flattened VectorData subpaths
output_table
}
@@ -1217,6 +1222,8 @@ async fn sample_points(_: impl Ctx, vector_data: VectorDataTable, spacing: f64,
style: std::mem::take(&mut vector_data_instance.instance.style),
upstream_graphic_group: std::mem::take(&mut vector_data_instance.instance.upstream_graphic_group),
};
// Transfer the stroke transform from the input vector data to the result.
result.style.set_stroke_transform(vector_data_instance.transform);
// Using `stroke_bezpath_iter` so that the `subpath_segment_lengths` is aligned to the segments of each bezpath.
// So we can index into `subpath_segment_lengths` to get the length of the segments.
@@ -1249,10 +1256,6 @@ async fn sample_points(_: impl Ctx, vector_data: VectorDataTable, spacing: f64,
result.append_bezpath(sample_bezpath);
}
// Transfer the style from the input vector data to the result.
result.style = vector_data_instance.instance.style;
result.style.set_stroke_transform(vector_data_instance.transform);
vector_data_instance.instance = result;
result_table.push(vector_data_instance);
}
@@ -1459,11 +1462,6 @@ async fn spline(_: impl Ctx, vector_data: VectorDataTable) -> VectorDataTable {
result_table.push(vector_data_instance);
}
// TODO: remove after pt6 of instance table refactor
if result_table.is_empty() {
return VectorDataTable::new(VectorData::empty());
}
result_table
}
@@ -1732,14 +1730,14 @@ fn bevel(_: impl Ctx, source: VectorDataTable, #[default(10.)] distance: Length)
#[node_macro::node(category("Vector"), path(graphene_core::vector))]
fn close_path(_: impl Ctx, source: VectorDataTable) -> VectorDataTable {
let mut new_table = VectorDataTable::empty();
let mut result_table = VectorDataTable::empty();
for mut source_instance in source.instance_iter() {
source_instance.instance.close_subpaths();
new_table.push(source_instance);
result_table.push(source_instance);
}
new_table
result_table
}
#[node_macro::node(category("Vector"), path(graphene_core::vector))]