From 50abe8194507c411634f39ec2b1f874e58d1a069 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Fri, 8 May 2026 20:59:42 -0700 Subject: [PATCH 1/4] Rename TableRow -> Item --- .../data_panel/data_panel_message_handler.rs | 54 ++++++------- node-graph/graph-craft/src/document/value.rs | 16 ++-- node-graph/libraries/core-types/src/ops.rs | 4 +- node-graph/libraries/core-types/src/table.rs | 76 +++++++++---------- .../libraries/rendering/src/renderer.rs | 6 +- .../per_pixel_adjust_runtime.rs | 4 +- .../wgpu-executor/src/texture_conversion.rs | 8 +- node-graph/nodes/blending/src/lib.rs | 6 +- node-graph/nodes/brush/src/brush.rs | 12 +-- node-graph/nodes/brush/src/brush_cache.rs | 22 +++--- node-graph/nodes/graphic/src/artboard.rs | 4 +- node-graph/nodes/graphic/src/graphic.rs | 28 +++---- .../nodes/gstd/src/platform_application_io.rs | 8 +- node-graph/nodes/path-bool/src/lib.rs | 14 ++-- .../nodes/raster/src/image_color_palette.rs | 4 +- node-graph/nodes/raster/src/std_nodes.rs | 12 +-- node-graph/nodes/text/src/json.rs | 4 +- node-graph/nodes/text/src/lib.rs | 9 ++- node-graph/nodes/text/src/path_builder.rs | 6 +- node-graph/nodes/text/src/regex.rs | 8 +- .../vector/src/vector_modification_nodes.rs | 4 +- node-graph/nodes/vector/src/vector_nodes.rs | 28 +++---- 22 files changed, 170 insertions(+), 167 deletions(-) diff --git a/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs b/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs index 41c6048e57..925ea09a2f 100644 --- a/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs @@ -220,7 +220,7 @@ fn label(x: impl Into) -> Vec { vec![LayoutGroup::row(error)] } -trait TableRowLayout { +trait TableItemLayout { fn type_name() -> &'static str; fn identifier(&self) -> String; fn layout_with_breadcrumb(&self, data: &mut LayoutData) -> Vec { @@ -245,7 +245,7 @@ trait TableRowLayout { } } -impl TableRowLayout for Table { +impl TableItemLayout for Table { fn type_name() -> &'static str { "Table" } @@ -307,7 +307,7 @@ impl TableRowLayout for Table { } } -impl TableRowLayout for Artboard { +impl TableItemLayout for Artboard { fn type_name() -> &'static str { "Artboard" } @@ -323,7 +323,7 @@ impl TableRowLayout for Artboard { } } -impl TableRowLayout for Graphic { +impl TableItemLayout for Graphic { fn type_name() -> &'static str { "Graphic" } @@ -353,7 +353,7 @@ impl TableRowLayout for Graphic { } } -impl TableRowLayout for Vector { +impl TableItemLayout for Vector { fn type_name() -> &'static str { "Vector" } @@ -512,7 +512,7 @@ impl TableRowLayout for Vector { } } -impl TableRowLayout for Raster { +impl TableItemLayout for Raster { fn type_name() -> &'static str { "Raster" } @@ -543,7 +543,7 @@ impl TableRowLayout for Raster { } } -impl TableRowLayout for Raster { +impl TableItemLayout for Raster { fn type_name() -> &'static str { "Raster" } @@ -556,7 +556,7 @@ impl TableRowLayout for Raster { } } -impl TableRowLayout for Color { +impl TableItemLayout for Color { fn type_name() -> &'static str { "Color" } @@ -576,7 +576,7 @@ impl TableRowLayout for Color { } } -impl TableRowLayout for GradientStops { +impl TableItemLayout for GradientStops { fn type_name() -> &'static str { "Gradient" } @@ -596,7 +596,7 @@ impl TableRowLayout for GradientStops { } } -impl TableRowLayout for f64 { +impl TableItemLayout for f64 { fn type_name() -> &'static str { "Number (f64)" } @@ -611,7 +611,7 @@ impl TableRowLayout for f64 { } } -impl TableRowLayout for u8 { +impl TableItemLayout for u8 { fn type_name() -> &'static str { "Byte" } @@ -624,7 +624,7 @@ impl TableRowLayout for u8 { } } -impl TableRowLayout for u32 { +impl TableItemLayout for u32 { fn type_name() -> &'static str { "Number (u32)" } @@ -639,7 +639,7 @@ impl TableRowLayout for u32 { } } -impl TableRowLayout for u64 { +impl TableItemLayout for u64 { fn type_name() -> &'static str { "Number (u64)" } @@ -655,7 +655,7 @@ impl TableRowLayout for u64 { } } -impl TableRowLayout for bool { +impl TableItemLayout for bool { fn type_name() -> &'static str { "Bool" } @@ -670,7 +670,7 @@ impl TableRowLayout for bool { } } -impl TableRowLayout for String { +impl TableItemLayout for String { fn type_name() -> &'static str { "String" } @@ -689,7 +689,7 @@ impl TableRowLayout for String { } } -impl TableRowLayout for Option { +impl TableItemLayout for Option { fn type_name() -> &'static str { "Option" } @@ -704,7 +704,7 @@ impl TableRowLayout for Option { } } -impl TableRowLayout for DVec2 { +impl TableItemLayout for DVec2 { fn type_name() -> &'static str { "Vec2" } @@ -719,7 +719,7 @@ impl TableRowLayout for DVec2 { } } -impl TableRowLayout for Vec2 { +impl TableItemLayout for Vec2 { fn type_name() -> &'static str { "Vec2" } @@ -734,7 +734,7 @@ impl TableRowLayout for Vec2 { } } -impl TableRowLayout for DAffine2 { +impl TableItemLayout for DAffine2 { fn type_name() -> &'static str { "Transform" } @@ -749,7 +749,7 @@ impl TableRowLayout for DAffine2 { } } -impl TableRowLayout for Affine2 { +impl TableItemLayout for Affine2 { fn type_name() -> &'static str { "Transform" } @@ -765,7 +765,7 @@ impl TableRowLayout for Affine2 { } } -impl TableRowLayout for BlendMode { +impl TableItemLayout for BlendMode { fn type_name() -> &'static str { "BlendMode" } @@ -780,7 +780,7 @@ impl TableRowLayout for BlendMode { } } -impl TableRowLayout for GradientType { +impl TableItemLayout for GradientType { fn type_name() -> &'static str { "GradientType" } @@ -795,7 +795,7 @@ impl TableRowLayout for GradientType { } } -impl TableRowLayout for GradientSpreadMethod { +impl TableItemLayout for GradientSpreadMethod { fn type_name() -> &'static str { "GradientSpreadMethod" } @@ -820,7 +820,7 @@ fn node_id_display_label(node_id: NodeId, network_interface: &NodeNetworkInterfa } } -impl TableRowLayout for NodeId { +impl TableItemLayout for NodeId { fn type_name() -> &'static str { "NodeId" } @@ -932,7 +932,7 @@ impl TableRowLayout for NodeId { } } -/// Invokes another macro with the full list of `TableRowLayout`-implementing types whose values may appear +/// Invokes another macro with the full list of `TableItemLayout`-implementing types whose values may appear /// as attribute values. Both the value-rendering and drilldown-navigation dispatchers iterate this list, /// so adding a new attribute-displayable type is a single edit here. macro_rules! known_table_row_types { @@ -984,7 +984,7 @@ fn display_value_override(any: &dyn Any) -> Option { } /// Type-dispatched widget for displaying an attribute value in a `Table` item. -/// Delegates to [`TableRowLayout::value_widget`] so the same widget code is shared between +/// Delegates to [`TableItemLayout::value_widget`] so the same widget code is shared between /// element-column rendering and attribute-column rendering. Returns `None` for unrecognized types so the /// caller can fall back to a debug-formatted [`TextLabel`]. fn dispatch_value_widget(any: &dyn Any, target: PathStep, data: &LayoutData) -> Option { @@ -1041,7 +1041,7 @@ fn table_node_id_path_layout_with_breadcrumb(path: &Table, data: &mut La } /// Type-dispatched recursion into an attribute value for the Data panel breadcrumb navigation. -/// Mirrors [`dispatch_value_widget`] but routes to [`TableRowLayout::layout_with_breadcrumb`]. +/// Mirrors [`dispatch_value_widget`] but routes to [`TableItemLayout::layout_with_breadcrumb`]. /// Returns `None` for unrecognized types. fn drilldown_attribute_layout(any: &dyn Any, data: &mut LayoutData) -> Option> { // `Table` is interpreted as a path (e.g. the `editor:layer_path` attribute), so each item's NodeId value diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index aa984986ef..6ebdd8f99d 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -142,16 +142,16 @@ macro_rules! tagged_value { Self::from_type_or_none(&Type::Concrete(td)).to_dynany() } Self::F64Array(values) => { - let table: Table = values.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = values.into_iter().map(core_types::table::Item::new_from_element).collect(); Box::new(table) } Self::Color(color) => { - let table: Table = color.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = color.into_iter().map(core_types::table::Item::new_from_element).collect(); Box::new(table) } Self::Gradient(stops) => Box::new(Table::::new_from_element(stops)), Self::BrushStrokes(strokes) => { - let table: Table = strokes.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = strokes.into_iter().map(core_types::table::Item::new_from_element).collect(); Box::new(table) } // ======================= @@ -163,7 +163,7 @@ macro_rules! tagged_value { // ======================= Self::RenderOutput(x) => Box::new(x), Self::NodeIdPath(path) => { - let table: Table = path.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = path.into_iter().map(core_types::table::Item::new_from_element).collect(); Box::new(table) } Self::DocumentNode(node) => Box::new(node), @@ -191,16 +191,16 @@ macro_rules! tagged_value { Self::from_type_or_none(&Type::Concrete(td)).to_any() } Self::F64Array(values) => { - let table: Table = values.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = values.into_iter().map(core_types::table::Item::new_from_element).collect(); Arc::new(table) } Self::Color(color) => { - let table: Table = color.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = color.into_iter().map(core_types::table::Item::new_from_element).collect(); Arc::new(table) } Self::Gradient(stops) => Arc::new(Table::::new_from_element(stops)), Self::BrushStrokes(strokes) => { - let table: Table = strokes.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = strokes.into_iter().map(core_types::table::Item::new_from_element).collect(); Arc::new(table) } // ======================= @@ -212,7 +212,7 @@ macro_rules! tagged_value { // ======================= Self::RenderOutput(x) => Arc::new(x), Self::NodeIdPath(path) => { - let table: Table = path.into_iter().map(core_types::table::TableRow::new_from_element).collect(); + let table: Table = path.into_iter().map(core_types::table::Item::new_from_element).collect(); Arc::new(table) } Self::DocumentNode(node) => Arc::new(node), diff --git a/node-graph/libraries/core-types/src/ops.rs b/node-graph/libraries/core-types/src/ops.rs index 9c9205c02a..f0832726f5 100644 --- a/node-graph/libraries/core-types/src/ops.rs +++ b/node-graph/libraries/core-types/src/ops.rs @@ -1,5 +1,5 @@ use crate::Node; -use crate::table::{AttributeColumnDyn, AttributeValueDyn, Column, Table, TableDyn, TableRow}; +use crate::table::{AttributeColumnDyn, AttributeValueDyn, Column, Table, TableDyn, Item}; use crate::transform::Footprint; use glam::DVec2; use graphene_hash::CacheHash; @@ -65,7 +65,7 @@ impl + Send> Convert, ()> for Table { .into_iter() .map(|row| { let (element, attributes) = row.into_parts(); - TableRow::from_parts(element.convert_row(), attributes) + Item::from_parts(element.convert_row(), attributes) }) .collect(); table diff --git a/node-graph/libraries/core-types/src/table.rs b/node-graph/libraries/core-types/src/table.rs index 260550230c..b3dd28c7b6 100644 --- a/node-graph/libraries/core-types/src/table.rs +++ b/node-graph/libraries/core-types/src/table.rs @@ -82,7 +82,7 @@ pub const ATTR_GRADIENT_TYPE: &str = "gradient_type"; // ===================== /// Enables type-erased scalar storage that supports Clone, Send, Sync, and downcasting. -/// Used for individual attribute values in a TableRow. +/// Used for individual attribute values in an [`Item`]. pub trait AttributeValue: std::any::Any + Send + Sync { /// Clones this value into a new boxed trait object. fn clone_box(&self) -> Box; @@ -528,7 +528,7 @@ unsafe impl StaticType for TableDyn { /// Scalar attribute storage. /// /// A small ordered map of type-erased scalar attribute values, keyed by string name. -/// Used for individual attribute values in a TableRow. +/// Used for individual attribute values in an [`Item`]. /// Linear search preserves insertion order and is likely faster than a HashMap for small attribute counts. #[derive(Clone, Default)] pub struct AttributeValues(Vec<(String, Box)>); @@ -631,7 +631,7 @@ impl AttributeValues { /// /// A collection of type-erased parallel attribute columns, keyed by string name. /// Used for columnar attribute storage in a Table. -/// Not public. All access goes through Table and TableRow. +/// Not public. All access goes through [`Table`] and [`Item`]. /// Invariant: every column in `columns` has exactly `len` elements. #[derive(Clone, Default)] struct AttributeColumns { @@ -845,7 +845,7 @@ impl AttributeColumns { /// /// Elements are stored contiguously in a `Vec`, while attributes live in an internal /// [`AttributeColumns`] store that keeps one column per attribute key. Rows are accessed -/// by index through element/attribute accessor methods, or consumed as owned [`TableRow`]s via iteration. +/// by index through element/attribute accessor methods, or consumed as owned [`Item`]s via iteration. #[derive(Clone, Debug)] pub struct Table { element: Vec, @@ -874,8 +874,8 @@ impl Table { } } - /// Creates a table containing a single row from the given [`TableRow`], preserving its attributes. - pub fn new_from_row(row: TableRow) -> Self { + /// Creates a table containing a single item from the given [`Item`], preserving its attributes. + pub fn new_from_row(row: Item) -> Self { let mut attributes = AttributeColumns::new(); attributes.push_row(row.attributes); Self { @@ -885,7 +885,7 @@ impl Table { } /// Appends a row to the end of this table. - pub fn push(&mut self, row: TableRow) { + pub fn push(&mut self, row: Item) { self.element.push(row.element); self.attributes.push_row(row.attributes); } @@ -1046,18 +1046,18 @@ impl Table { // Row-level cloning // ================== - /// Clones both the element and all attributes at the given row index into a new owned [`TableRow`], or `None` if out of bounds. - pub fn clone_row(&self, index: usize) -> Option> + /// Clones both the element and all attributes at the given item index into a new owned [`Item`], or [`None`] if out of bounds. + pub fn clone_row(&self, index: usize) -> Option> where T: Clone, { - Some(TableRow { + Some(Item { element: self.element.get(index)?.clone(), attributes: self.attributes.clone_row(index), }) } - /// Clones all attribute values at the given row index into a new [`AttributeValues`], without cloning the element. + /// Clones all attribute values at the given item index into a new [`AttributeValues`], without cloning the element. pub fn clone_row_attributes(&self, index: usize) -> AttributeValues { self.attributes.clone_row(index) } @@ -1110,13 +1110,13 @@ impl BoundingBox for Table { } impl IntoIterator for Table { - type Item = TableRow; - type IntoIter = TableRowIter; + type Item = Item; + type IntoIter = ItemIter; - /// Consumes a [`Table`] and returns an iterator of [`TableRow`]s, each containing the owned data of the respective row from the original table. + /// Consumes a [`Table`] and returns an iterator of [`Item`]s, each containing the owned data of the respective row from the original table. fn into_iter(self) -> Self::IntoIter { let row_attributes = self.attributes.into_row_vec(); - TableRowIter { + ItemIter { element: self.element.into_iter(), attributes: row_attributes.into_iter(), } @@ -1179,9 +1179,9 @@ unsafe impl StaticType for Table { type Static = Table; } -impl FromIterator> for Table { - /// Collects an iterator of [`TableRow`]s into a [`Table`], pre-allocating based on the iterator's size hint. - fn from_iter>>(iter: I) -> Self { +impl FromIterator> for Table { + /// Collects an iterator of [`Item`]s into a [`Table`], pre-allocating based on the iterator's size hint. + fn from_iter>>(iter: I) -> Self { let iter = iter.into_iter(); let (lower_bound, _) = iter.size_hint(); let mut table = Self::with_capacity(lower_bound); @@ -1194,34 +1194,34 @@ impl FromIterator> for Table { } } -// =========== -// TableRow -// =========== +// ======= +// Item +// ======= -/// An owned row containing an element of type `T` and a set of type-erased scalar attributes. +/// An owned item containing an element of type `T` and a set of type-erased scalar attributes. /// -/// Used to build rows before pushing them into a [`Table`], or when consuming rows out of a -/// table via [`IntoIterator`]. Attribute values use scalar [`AttributeValues`] storage rather +/// Used to build individual items before pushing them into a [`Table`], or when consuming rows out +/// of a table via [`IntoIterator`]. Attribute values use scalar [`AttributeValues`] storage rather /// than the columnar layout inside a [`Table`]. #[derive(Clone, Debug)] -pub struct TableRow { +pub struct Item { element: T, attributes: AttributeValues, } -impl Default for TableRow { +impl Default for Item { fn default() -> Self { Self::new_from_element(T::default()) } } -impl PartialEq for TableRow { +impl PartialEq for Item { fn eq(&self, other: &Self) -> bool { self.element == other.element } } -impl TableRow { +impl Item { /// Constructs a row from a pre-built element and attributes pair. pub fn from_parts(element: T, attributes: AttributeValues) -> Self { Self { element, attributes } @@ -1309,33 +1309,33 @@ impl TableRow { } } -// =============== -// TableRowIter -// =============== +// =========== +// ItemIter +// =========== -/// Owning iterator over the rows of a consumed [`Table`], yielding [`TableRow`]s. +/// Owning iterator over the rows of a consumed [`Table`], yielding [`Item`]s. /// /// Created by [`Table::into_iter`]. The table's columnar attributes are converted into /// per-row scalar [`AttributeValues`] during construction so each yielded row is self-contained. -pub struct TableRowIter { +pub struct ItemIter { element: std::vec::IntoIter, attributes: std::vec::IntoIter, } -impl Iterator for TableRowIter { - type Item = TableRow; +impl Iterator for ItemIter { + type Item = Item; fn next(&mut self) -> Option { - Some(TableRow { + Some(Item { element: self.element.next()?, attributes: self.attributes.next()?, }) } } -impl DoubleEndedIterator for TableRowIter { +impl DoubleEndedIterator for ItemIter { fn next_back(&mut self) -> Option { - Some(TableRow { + Some(Item { element: self.element.next_back()?, attributes: self.attributes.next_back()?, }) diff --git a/node-graph/libraries/rendering/src/renderer.rs b/node-graph/libraries/rendering/src/renderer.rs index bec5a5e6aa..f028fab529 100644 --- a/node-graph/libraries/rendering/src/renderer.rs +++ b/node-graph/libraries/rendering/src/renderer.rs @@ -7,7 +7,7 @@ use core_types::bounds::RenderBoundingBox; use core_types::color::Color; use core_types::math::quad::Quad; use core_types::render_complexity::RenderComplexity; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::transform::Footprint; use core_types::uuid::{NodeId, generate_uuid}; use core_types::{ @@ -987,7 +987,7 @@ impl Render for Table { // The mask must draw at full alpha so the SVG ``/`` fully zeroes the path interior. // The wrapping SVG group (above) handles the user-set opacity. - let vector_item = Table::new_from_row(TableRow::new_from_element(cloned_vector).with_attribute(ATTR_TRANSFORM, multiplied_transform)); + let vector_item = Table::new_from_row(Item::new_from_element(cloned_vector).with_attribute(ATTR_TRANSFORM, multiplied_transform)); (id, mask_type, vector_item) }); @@ -1312,7 +1312,7 @@ impl Render for Table { // The mask must draw at full alpha so `SrcOut` fully zeroes the path interior. // The outer opacity/blend layer (above) handles the user-set opacity. - let vector_table = Table::new_from_row(TableRow::new_from_element(cloned_element).with_attribute(ATTR_TRANSFORM, item_transform)); + let vector_table = Table::new_from_row(Item::new_from_element(cloned_element).with_attribute(ATTR_TRANSFORM, item_transform)); let bounds = element.bounding_box_with_transform(multiplied_transform).unwrap_or(layer_bounds); // This branch is gated on `can_draw_aligned_stroke`, which already requires every subpath is closed diff --git a/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs b/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs index 9485e8b69c..74db382580 100644 --- a/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs +++ b/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs @@ -1,7 +1,7 @@ use crate::WgpuContext; use crate::shader_runtime::{FULLSCREEN_VERTEX_SHADER_NAME, ShaderRuntime}; use core_types::shaders::buffer_struct::BufferStruct; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use futures::lock::Mutex; use raster_types::{GPU, Raster}; use std::borrow::Cow; @@ -234,7 +234,7 @@ impl PerPixelAdjustGraphicsPipeline { rp.draw(0..3, 0..1); let attributes = textures.clone_row_attributes(index); - TableRow::from_parts(Raster::new(GPU { texture: tex_out }), attributes) + Item::from_parts(Raster::new(GPU { texture: tex_out }), attributes) }) .collect::>(); context.queue.submit([cmd.finish()]); diff --git a/node-graph/libraries/wgpu-executor/src/texture_conversion.rs b/node-graph/libraries/wgpu-executor/src/texture_conversion.rs index 7acce3632f..0eba467fac 100644 --- a/node-graph/libraries/wgpu-executor/src/texture_conversion.rs +++ b/node-graph/libraries/wgpu-executor/src/texture_conversion.rs @@ -3,7 +3,7 @@ use core_types::Color; use core_types::Ctx; use core_types::color::SRGBA8; use core_types::ops::Convert; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::transform::Footprint; use raster_types::Image; use raster_types::{CPU, GPU, Raster}; @@ -155,7 +155,7 @@ impl<'i> Convert>, &'i WgpuExecutor> for Table> { let (image, attributes) = row.into_parts(); let texture = upload_to_texture(device, queue, &image); - TableRow::from_parts(Raster::new_gpu(texture), attributes) + Item::from_parts(Raster::new_gpu(texture), attributes) }) .collect(); @@ -199,7 +199,7 @@ impl<'i> Convert>, &'i WgpuExecutor> for Table> { for row in self { let (element, attributes) = row.into_parts(); converters.push(RasterGpuToRasterCpuConverter::new(device, &mut encoder, element)); - rows_meta.push(TableRow::from_parts((), attributes)); + rows_meta.push(Item::from_parts((), attributes)); } queue.submit([encoder.finish()]); @@ -219,7 +219,7 @@ impl<'i> Convert>, &'i WgpuExecutor> for Table> { .zip(rows_meta) .map(|(element, row)| { let (_, attributes) = row.into_parts(); - TableRow::from_parts(element, attributes) + Item::from_parts(element, attributes) }) .collect() } diff --git a/node-graph/nodes/blending/src/lib.rs b/node-graph/nodes/blending/src/lib.rs index a719c4a8a5..3f1480e70a 100644 --- a/node-graph/nodes/blending/src/lib.rs +++ b/node-graph/nodes/blending/src/lib.rs @@ -176,7 +176,7 @@ fn blend_mode( /// The choice of equation that controls how brightness and color blends between overlapping pixels. blend_mode: BlendMode, ) -> T { - // TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or TableRow) rather than applying to each item in its own table, which produces the undesired result + // TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or Item) rather than applying to each item in its own table, which produces the undesired result content.set_blend_mode(blend_mode); content } @@ -214,7 +214,7 @@ fn opacity( #[default(100.)] fill: Percentage, ) -> T { - // TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or TableRow) rather than applying to each item in its own table, which produces the undesired result + // TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or Item) rather than applying to each item in its own table, which produces the undesired result if has_opacity { content.multiply_alpha(opacity / 100.); } @@ -240,7 +240,7 @@ fn clipping_mask( /// Whether the content inherits the alpha of the content beneath it. clip: bool, ) -> T { - // TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or TableRow) rather than applying to each item in its own table, which produces the undesired result + // TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or Item) rather than applying to each item in its own table, which produces the undesired result content.set_clip(clip); content } diff --git a/node-graph/nodes/brush/src/brush.rs b/node-graph/nodes/brush/src/brush.rs index 1ed67007b5..3ed889d988 100644 --- a/node-graph/nodes/brush/src/brush.rs +++ b/node-graph/nodes/brush/src/brush.rs @@ -6,7 +6,7 @@ use core_types::color::{Alpha, Color, Pixel, Sample}; use core_types::generic::FnNode; use core_types::math::bbox::{AxisAlignedBbox, Bbox}; use core_types::registry::FutureWrapperNode; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::transform::Transform; use core_types::uuid::NodeId; use core_types::value::ClonedNode; @@ -143,7 +143,7 @@ pub async fn create_brush_texture(brush_style: &BrushStyle) -> Raster { image.into_element() } -pub fn blend_with_mode(background: TableRow>, foreground: TableRow>, blend_mode: BlendMode, opacity: f64) -> TableRow> { +pub fn blend_with_mode(background: Item>, foreground: Item>, blend_mode: BlendMode, opacity: f64) -> Item> { let opacity = opacity as f32 / 100.; match std::hint::black_box(blend_mode) { // Normal group @@ -199,7 +199,7 @@ async fn brush( cache: BrushCache, ) -> Table> { if background.is_empty() { - background.push(TableRow::default()); + background.push(Item::default()); } // TODO: Find a way to handle more than one item let table_row = background.clone_row(0).expect("Expected the one item we just pushed"); @@ -286,7 +286,7 @@ async fn brush( let has_erase_or_restore_strokes = trace.iter_element_values().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(ATTR_TRANSFORM, background_bounds); + let mut erase_restore_mask = Item::new_from_element(Raster::new_cpu(opaque_image)).with_attribute(ATTR_TRANSFORM, background_bounds); for stroke in trace.into_iter().map(|row| row.into_element()) { let mut brush_texture = cache.get_cached_brush(&stroke.style); @@ -336,7 +336,7 @@ async fn brush( background } -pub fn blend_image_closure(foreground: TableRow>, mut background: TableRow>, map_fn: impl Fn(Color, Color) -> Color) -> TableRow> { +pub fn blend_image_closure(foreground: Item>, mut background: Item>, map_fn: impl Fn(Color, Color) -> Color) -> Item> { let foreground_size = DVec2::new(foreground.element().width as f64, foreground.element().height as f64); let background_size = DVec2::new(background.element().width as f64, background.element().height as f64); @@ -369,7 +369,7 @@ pub fn blend_image_closure(foreground: TableRow>, mut background: Ta background } -pub fn blend_stamp_closure(foreground: BrushStampGenerator, mut background: TableRow>, map_fn: impl Fn(Color, Color) -> Color) -> TableRow> { +pub fn blend_stamp_closure(foreground: BrushStampGenerator, mut background: Item>, map_fn: impl Fn(Color, Color) -> Color) -> Item> { let background_size = DVec2::new(background.element().width as f64, background.element().height as f64); // Transforms a point from the background image to the foreground image diff --git a/node-graph/nodes/brush/src/brush_cache.rs b/node-graph/nodes/brush/src/brush_cache.rs index 929f0f6c05..9ec3b4a59c 100644 --- a/node-graph/nodes/brush/src/brush_cache.rs +++ b/node-graph/nodes/brush/src/brush_cache.rs @@ -2,7 +2,7 @@ use crate::brush_stroke::BrushStroke; use crate::brush_stroke::BrushStyle; use core_types::ATTR_TRANSFORM; use core_types::graphene_hash::CacheHashWrapper; -use core_types::table::TableRow; +use core_types::table::Item; use raster_types::CPU; use raster_types::Raster; use std::collections::HashMap; @@ -14,16 +14,16 @@ struct BrushCacheImpl { prev_input: Vec, // The strokes that have been fully processed and blended into the background. - background: TableRow>, - blended_image: TableRow>, - last_stroke_texture: TableRow>, + background: Item>, + blended_image: Item>, + last_stroke_texture: Item>, // A cache for brush textures. brush_texture_cache: HashMap, Raster>, } impl BrushCacheImpl { - fn compute_brush_plan(&mut self, mut background: TableRow>, input: &[BrushStroke]) -> BrushPlan { + fn compute_brush_plan(&mut self, mut background: Item>, input: &[BrushStroke]) -> BrushPlan { // Do background invalidation. if background != self.background { self.background = background.clone(); @@ -51,7 +51,7 @@ impl BrushCacheImpl { // Check if the first non-blended stroke is an extension of the last one. // Transform is set to ZERO (not the default IDENTITY) as a sentinel to mark this item as uninitialized. - let mut first_stroke_texture = TableRow::new_from_element(Raster::::default()).with_attribute(ATTR_TRANSFORM, glam::DAffine2::ZERO); + let mut first_stroke_texture = Item::new_from_element(Raster::::default()).with_attribute(ATTR_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 { @@ -75,7 +75,7 @@ impl BrushCacheImpl { } } - pub fn cache_results(&mut self, input: Vec, blended_image: TableRow>, last_stroke_texture: TableRow>) { + pub fn cache_results(&mut self, input: Vec, blended_image: Item>, last_stroke_texture: Item>) { self.prev_input = input; self.blended_image = blended_image; self.last_stroke_texture = last_stroke_texture; @@ -85,8 +85,8 @@ impl BrushCacheImpl { #[derive(Clone, Debug, Default)] pub struct BrushPlan { pub strokes: Vec, - pub background: TableRow>, - pub first_stroke_texture: TableRow>, + pub background: Item>, + pub first_stroke_texture: Item>, pub first_stroke_point_skip: usize, } @@ -94,12 +94,12 @@ pub struct BrushPlan { pub struct BrushCache(Arc>); impl BrushCache { - pub fn compute_brush_plan(&self, background: TableRow>, input: &[BrushStroke]) -> BrushPlan { + pub fn compute_brush_plan(&self, background: Item>, input: &[BrushStroke]) -> BrushPlan { let mut inner = self.0.lock().unwrap(); inner.compute_brush_plan(background, input) } - pub fn cache_results(&self, input: Vec, blended_image: TableRow>, last_stroke_texture: TableRow>) { + pub fn cache_results(&self, input: Vec, blended_image: Item>, last_stroke_texture: Item>) { let mut inner = self.0.lock().unwrap(); inner.cache_results(input, blended_image, last_stroke_texture) } diff --git a/node-graph/nodes/graphic/src/artboard.rs b/node-graph/nodes/graphic/src/artboard.rs index a684807453..2a01d0b538 100644 --- a/node-graph/nodes/graphic/src/artboard.rs +++ b/node-graph/nodes/graphic/src/artboard.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, TableRow}; +use core_types::table::{Item, Table}; use core_types::transform::TransformMut; use core_types::{ATTR_BACKGROUND, ATTR_CLIP, ATTR_DIMENSIONS, ATTR_LOCATION, CloneVarArgs, Color, Context, Ctx, ExtractAll, OwnedContextImpl}; use glam::{DAffine2, DVec2}; @@ -50,7 +50,7 @@ pub async fn create_artboard( // Name is not stored here, it's resolved live from the parent layer's display name Table::new_from_row( - TableRow::new_from_element(Artboard::new(content)) + Item::new_from_element(Artboard::new(content)) .with_attribute(ATTR_LOCATION, normalized_location) .with_attribute(ATTR_DIMENSIONS, normalized_dimensions) .with_attribute(ATTR_BACKGROUND, background) diff --git a/node-graph/nodes/graphic/src/graphic.rs b/node-graph/nodes/graphic/src/graphic.rs index e3701a6309..5bfc7fb6e2 100644 --- a/node-graph/nodes/graphic/src/graphic.rs +++ b/node-graph/nodes/graphic/src/graphic.rs @@ -1,6 +1,6 @@ use core_types::bounds::{BoundingBox, RenderBoundingBox}; use core_types::registry::types::{Angle, SignedInteger}; -use core_types::table::{AttributeColumnDyn, AttributeValueDyn, Table, TableDyn, TableRow}; +use core_types::table::{AttributeColumnDyn, AttributeValueDyn, Table, TableDyn, Item}; use core_types::uuid::NodeId; use core_types::{ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_TRANSFORM, AnyHash, BlendMode, CacheHash, CloneVarArgs, Color, Context, Ctx, ExtractAll, OwnedContextImpl}; use glam::{DAffine2, DVec2}; @@ -304,7 +304,7 @@ fn read_attribute_vector( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(value.clone())); + result.push(Item::new_from_element(value.clone())); } result } @@ -325,7 +325,7 @@ fn read_attribute_number( .or_else(|| content.attribute::(&name, index).map(|v| *v as f64)) .or_else(|| content.attribute::(&name, index).map(|v| *v as f64)); let Some(value) = value else { continue }; - result.push(TableRow::new_from_element(value)); + result.push(Item::new_from_element(value)); } result } @@ -341,7 +341,7 @@ fn read_attribute_bool( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(*value)); + result.push(Item::new_from_element(*value)); } result } @@ -357,7 +357,7 @@ fn read_attribute_string( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(value.clone())); + result.push(Item::new_from_element(value.clone())); } result } @@ -373,7 +373,7 @@ fn read_attribute_transform( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(*value)); + result.push(Item::new_from_element(*value)); } result } @@ -389,7 +389,7 @@ fn read_attribute_color( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(*value)); + result.push(Item::new_from_element(*value)); } result } @@ -405,7 +405,7 @@ fn read_attribute_blend_mode( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(*value)); + result.push(Item::new_from_element(*value)); } result } @@ -421,7 +421,7 @@ fn read_attribute_gradient_type( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(*value)); + result.push(Item::new_from_element(*value)); } result } @@ -437,7 +437,7 @@ fn read_attribute_spread_method( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(*value)); + result.push(Item::new_from_element(*value)); } result } @@ -453,7 +453,7 @@ fn read_attribute_gradient_stops( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(value.clone())); + result.push(Item::new_from_element(value.clone())); } result } @@ -469,7 +469,7 @@ fn read_attribute_artboard( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::(&name, index) else { continue }; - result.push(TableRow::new_from_element(value.clone())); + result.push(Item::new_from_element(value.clone())); } result } @@ -485,7 +485,7 @@ fn read_attribute_raster( let mut result = Table::with_capacity(content.len()); for index in 0..content.len() { let Some(value) = content.attribute::>(&name, index) else { continue }; - result.push(TableRow::new_from_element(value.clone())); + result.push(Item::new_from_element(value.clone())); } result } @@ -598,7 +598,7 @@ pub async fn flatten_graphic(_: impl Ctx, content: Table, fully_flatten // Push any leaf elements we encounter: either `Graphic::Graphic(...)` values beyond the recursion depth, or non-`Graphic::Graphic` variants (e.g. `Graphic::Vector`, `Graphic::Raster*`, `Graphic::Color`, `Graphic::Gradient`) _ => { let attributes = current_graphic_table.clone_row_attributes(index); - output_graphic_table.push(TableRow::from_parts(current_element, attributes)); + output_graphic_table.push(Item::from_parts(current_element, attributes)); } } } diff --git a/node-graph/nodes/gstd/src/platform_application_io.rs b/node-graph/nodes/gstd/src/platform_application_io.rs index 9002f553a3..6b6fb6d2d7 100644 --- a/node-graph/nodes/gstd/src/platform_application_io.rs +++ b/node-graph/nodes/gstd/src/platform_application_io.rs @@ -4,7 +4,7 @@ use base64::Engine; use canvas_utils::{Canvas, CanvasHandle}; #[cfg(target_family = "wasm")] use core_types::math::bbox::Bbox; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; #[cfg(target_family = "wasm")] use core_types::transform::Footprint; #[cfg(target_family = "wasm")] @@ -116,14 +116,14 @@ async fn post_request( /// Converts a text string to raw binary data. Useful for transmission over HTTP or writing to files. #[node_macro::node(category("Web Request"), name("String to Bytes"))] fn string_to_bytes(_: impl Ctx, string: String) -> Table { - string.into_bytes().into_iter().map(TableRow::new_from_element).collect() + string.into_bytes().into_iter().map(Item::new_from_element).collect() } /// Converts extracted raw RGBA pixel data from an input image. Each pixel becomes 4 sequential bytes. Useful for transmission over HTTP or writing to files. #[node_macro::node(category("Web Request"), name("Image to Bytes"))] fn image_to_bytes(_: impl Ctx, image: Table>) -> Table { let Some(image) = image.element(0) else { return Table::new() }; - image.data.iter().flat_map(|color| color.to_rgba8_srgb()).map(TableRow::new_from_element).collect() + image.data.iter().flat_map(|color| color.to_rgba8_srgb()).map(Item::new_from_element).collect() } /// Loads binary from URLs and local asset paths. Returns a transparent placeholder if the resource fails to load, allowing rendering to continue. @@ -236,7 +236,7 @@ where let image = Image::from_image_data(&rasterized.data().0, resolution.x as u32, resolution.y as u32); Table::new_from_row( - TableRow::new_from_element(Raster::new_cpu(image)) + Item::new_from_element(Raster::new_cpu(image)) .with_attribute(ATTR_TRANSFORM, footprint.transform) .with_attribute(ATTR_EDITOR_MERGED_LAYERS, upstream_graphic_table), ) diff --git a/node-graph/nodes/path-bool/src/lib.rs b/node-graph/nodes/path-bool/src/lib.rs index da94d9f633..dd1d5a11c0 100644 --- a/node-graph/nodes/path-bool/src/lib.rs +++ b/node-graph/nodes/path-bool/src/lib.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::uuid::NodeId; use core_types::{ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, BlendMode, Color, Ctx}; use glam::{DAffine2, DVec2}; @@ -132,9 +132,9 @@ fn boolean_operation_on_vector_table(vector: &Table, boolean_operation: style: copy_from.style.clone(), ..Default::default() }; - TableRow::from_parts(element, attributes) + Item::from_parts(element, attributes) } else { - TableRow::::default() + Item::::default() }; for index in 0..vector.len() { @@ -188,7 +188,7 @@ fn flatten_vector(graphic_table: &Table) -> Table { let mut element = Vector::from_subpath(subpath); element.style.set_fill(Fill::Solid(Color::BLACK)); - TableRow::new_from_element(element) + Item::new_from_element(element) .with_attribute(ATTR_BLEND_MODE, blend_mode) .with_attribute(ATTR_OPACITY, opacity) .with_attribute(ATTR_OPACITY_FILL, fill) @@ -220,7 +220,7 @@ fn flatten_vector(graphic_table: &Table) -> Table { let mut element = Vector::from_subpath(subpath); element.style.set_fill(Fill::Solid(Color::BLACK)); - TableRow::new_from_element(element) + Item::new_from_element(element) .with_attribute(ATTR_BLEND_MODE, blend_mode) .with_attribute(ATTR_OPACITY, opacity) .with_attribute(ATTR_OPACITY_FILL, fill) @@ -264,7 +264,7 @@ fn flatten_vector(graphic_table: &Table) -> Table { element.style.set_fill(Fill::Solid(color)); element.style.set_stroke_transform(DAffine2::IDENTITY); - TableRow::from_parts(element, attributes) + Item::from_parts(element, attributes) }) .collect::>(), Graphic::Gradient(gradient) => gradient @@ -275,7 +275,7 @@ fn flatten_vector(graphic_table: &Table) -> Table { element.style.set_fill(Fill::Gradient(graphic_types::vector_types::gradient::Gradient { stops, ..Default::default() })); element.style.set_stroke_transform(DAffine2::IDENTITY); - TableRow::from_parts(element, attributes) + Item::from_parts(element, attributes) }) .collect::>(), } diff --git a/node-graph/nodes/raster/src/image_color_palette.rs b/node-graph/nodes/raster/src/image_color_palette.rs index 8ba1c7aa13..c8c90e8354 100644 --- a/node-graph/nodes/raster/src/image_color_palette.rs +++ b/node-graph/nodes/raster/src/image_color_palette.rs @@ -1,6 +1,6 @@ use core_types::color::Color; use core_types::context::Ctx; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use raster_types::{CPU, Raster}; #[node_macro::node(category("Color"))] @@ -56,7 +56,7 @@ async fn image_color_palette( b /= list.len() as f32; a /= list.len() as f32; - Color::from_rgbaf32(r, g, b, a).map(TableRow::new_from_element).into_iter() + Color::from_rgbaf32(r, g, b, a).map(Item::new_from_element).into_iter() }) .collect() } diff --git a/node-graph/nodes/raster/src/std_nodes.rs b/node-graph/nodes/raster/src/std_nodes.rs index 8590adf9ae..567684e2cf 100644 --- a/node-graph/nodes/raster/src/std_nodes.rs +++ b/node-graph/nodes/raster/src/std_nodes.rs @@ -4,7 +4,7 @@ use core_types::color::Color; use core_types::color::{Alpha, AlphaMut, Channel, LinearChannel, Luminance, RGBMut}; use core_types::context::{Ctx, ExtractFootprint}; use core_types::math::bbox::Bbox; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::transform::Transform; use dyn_any::DynAny; use fastnoise_lite; @@ -88,7 +88,7 @@ pub fn sample_image(ctx: impl ExtractFootprint + Clone + Send, image_frame: Tabl let new_transform = image_frame_transform * DAffine2::from_translation(offset) * DAffine2::from_scale(size); attributes.insert(ATTR_TRANSFORM, new_transform); - Some(TableRow::from_parts(Raster::new_cpu(image), attributes)) + Some(Item::from_parts(Raster::new_cpu(image), attributes)) }) .collect() } @@ -169,7 +169,7 @@ pub fn combine_channels( } } - Some(TableRow::from_parts(Raster::new_cpu(image), attributes)) + Some(Item::from_parts(Raster::new_cpu(image), attributes)) }) .collect() } @@ -392,7 +392,7 @@ pub fn noise_pattern( } } - return Table::new_from_row(TableRow::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)); + return Table::new_from_row(Item::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)); } }; noise.set_noise_type(Some(noise_type)); @@ -450,7 +450,7 @@ pub fn noise_pattern( } } - Table::new_from_row(TableRow::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)) + Table::new_from_row(Item::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)) } #[node_macro::node(category("Raster: Pattern"))] @@ -489,7 +489,7 @@ pub fn mandelbrot(ctx: impl ExtractFootprint + Send) -> Table> { } Table::new_from_row( - TableRow::new_from_element(Raster::new_cpu(Image { + Item::new_from_element(Raster::new_cpu(Image { width, height, data, diff --git a/node-graph/nodes/text/src/json.rs b/node-graph/nodes/text/src/json.rs index 19de888043..a8ea779ad7 100644 --- a/node-graph/nodes/text/src/json.rs +++ b/node-graph/nodes/text/src/json.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::{ATTR_TYPE, Ctx}; use serde_json::Value; @@ -250,7 +250,7 @@ fn query_json_all( results .into_iter() - .map(|(text, ty)| TableRow::new_from_element(text).with_attribute(ATTR_TYPE, ty.to_string())) + .map(|(text, ty)| Item::new_from_element(text).with_attribute(ATTR_TYPE, ty.to_string())) .collect() } diff --git a/node-graph/nodes/text/src/lib.rs b/node-graph/nodes/text/src/lib.rs index c590619f6b..3fd2bd76c3 100644 --- a/node-graph/nodes/text/src/lib.rs +++ b/node-graph/nodes/text/src/lib.rs @@ -8,7 +8,7 @@ mod to_path; use convert_case::{Boundary, Converter, pattern}; use core_types::graphene_hash::CacheHash; use core_types::registry::types::{SignedInteger, TextArea}; -use core_types::table::{Table, TableRow}; +use core_types::table::{Item, Table}; use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractVarArgs, OwnedContextImpl}; use dyn_any::DynAny; use glam::{DAffine2, DVec2}; @@ -30,10 +30,13 @@ pub use vector_types; pub enum TextAlign { #[default] #[icon("TextAlignLeft")] + #[cfg_attr(feature = "serde", serde(alias = "Left"))] AlignLeft, #[icon("TextAlignCenter")] + #[cfg_attr(feature = "serde", serde(alias = "Center"))] AlignCenter, #[icon("TextAlignRight")] + #[cfg_attr(feature = "serde", serde(alias = "Right"))] AlignRight, #[icon("TextJustifyLeft")] JustifyLeft, @@ -737,7 +740,7 @@ fn string_split( ) -> Table { let delimiter = if delimiter_escaping { unescape_string(delimiter) } else { delimiter }; - string.split(&delimiter).map(str::to_string).map(TableRow::new_from_element).collect() + string.split(&delimiter).map(str::to_string).map(Item::new_from_element).collect() } /// Joins a list of strings together with a separator between each pair. This is the inverse of the **String Split** node. @@ -778,7 +781,7 @@ async fn map_string( let owned_ctx = owned_ctx.with_vararg(Box::new(string)).with_index(i); let mapped_string = mapped.eval(owned_ctx.into_context()).await; - result.push(TableRow::new_from_element(mapped_string)); + result.push(Item::new_from_element(mapped_string)); } result diff --git a/node-graph/nodes/text/src/path_builder.rs b/node-graph/nodes/text/src/path_builder.rs index f1a6865610..385b9eafe6 100644 --- a/node-graph/nodes/text/src/path_builder.rs +++ b/node-graph/nodes/text/src/path_builder.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::{ATTR_EDITOR_CLICK_TARGET, ATTR_EDITOR_TEXT_FRAME, ATTR_TRANSFORM}; use glam::{DAffine2, DVec2}; use parley::GlyphRun; @@ -84,7 +84,7 @@ impl PathBuilder { // back to the layer-local frame origin, regardless of which glyph survived let frame_in_item_local = DAffine2::from_scale_angle_translation(self.text_frame_size, 0., -glyph_offset); - let item = TableRow::new_from_element(Vector::from_subpaths(core::mem::take(&mut self.glyph_subpaths), false)) + let item = Item::new_from_element(Vector::from_subpaths(core::mem::take(&mut self.glyph_subpaths), false)) .with_attribute(ATTR_TRANSFORM, DAffine2::from_translation(glyph_offset)) .with_attribute(ATTR_EDITOR_TEXT_FRAME, frame_in_item_local); self.vector_table.push(item); @@ -169,7 +169,7 @@ impl PathBuilder { // TODO: Remove this hack and move the attribute up to the parent return value when is done. if self.vector_table.is_empty() { let frame_in_item_local = DAffine2::from_scale_angle_translation(self.text_frame_size, 0., -self.first_glyph_offset); - let item = TableRow::new_from_element(Vector::default()) + let item = Item::new_from_element(Vector::default()) .with_attribute(ATTR_TRANSFORM, DAffine2::from_translation(self.first_glyph_offset)) .with_attribute(ATTR_EDITOR_TEXT_FRAME, frame_in_item_local); self.vector_table.push(item); diff --git a/node-graph/nodes/text/src/regex.rs b/node-graph/nodes/text/src/regex.rs index b43611d90d..9c74771aeb 100644 --- a/node-graph/nodes/text/src/regex.rs +++ b/node-graph/nodes/text/src/regex.rs @@ -1,5 +1,5 @@ use core_types::registry::types::SignedInteger; -use core_types::table::{Table, TableRow}; +use core_types::table::{Table, Item}; use core_types::{ATTR_END, ATTR_NAME, ATTR_START, Ctx}; /// Checks whether the string contains a match for the given regular expression pattern. Optionally restricts the match to only the start and/or end of the string. @@ -143,7 +143,7 @@ fn regex_find( let start = captured.map_or(0_u64, |m| m.start() as u64); let end = captured.map_or(0_u64, |m| m.end() as u64); let name = capture_names.get(i).cloned().flatten().unwrap_or_default(); - TableRow::new_from_element(text) + Item::new_from_element(text) .with_attribute(ATTR_START, start) .with_attribute(ATTR_END, end) .with_attribute(ATTR_NAME, name) @@ -187,7 +187,7 @@ fn regex_find_all( .find_iter(&string) .filter_map(|m| m.ok()) .map(|m| { - TableRow::new_from_element(m.as_str().to_string()) + Item::new_from_element(m.as_str().to_string()) .with_attribute(ATTR_START, m.start() as u64) .with_attribute(ATTR_END, m.end() as u64) }) @@ -226,5 +226,5 @@ fn regex_split( return Table::new_from_element(string); }; - regex.split(&string).filter_map(|s| s.ok()).map(|s| s.to_string()).map(TableRow::new_from_element).collect() + regex.split(&string).filter_map(|s| s.ok()).map(|s| s.to_string()).map(Item::new_from_element).collect() } diff --git a/node-graph/nodes/vector/src/vector_modification_nodes.rs b/node-graph/nodes/vector/src/vector_modification_nodes.rs index 2fcfae22d5..951aa4fd46 100644 --- a/node-graph/nodes/vector/src/vector_modification_nodes.rs +++ b/node-graph/nodes/vector/src/vector_modification_nodes.rs @@ -8,10 +8,10 @@ use vector_types::vector::VectorModification; /// Applies a differential modification to a vector path, associating changes made by the Pen and Path tools to indices of edited points and segments. #[node_macro::node(category(""))] async fn path_modify(_ctx: impl Ctx, mut vector: Table, modification: Box, node_path: Table) -> Table { - use core_types::table::TableRow; + use core_types::table::Item; if vector.is_empty() { - vector.push(TableRow::default()); + vector.push(Item::default()); } modification.apply(vector.element_mut(0).expect("push should give one item")); diff --git a/node-graph/nodes/vector/src/vector_nodes.rs b/node-graph/nodes/vector/src/vector_nodes.rs index 3aa7db2c2b..99e959f78e 100644 --- a/node-graph/nodes/vector/src/vector_nodes.rs +++ b/node-graph/nodes/vector/src/vector_nodes.rs @@ -4,7 +4,7 @@ use core::hash::{Hash, Hasher}; use core_types::blending::BlendMode; use core_types::bounds::{BoundingBox, RenderBoundingBox}; use core_types::registry::types::{Angle, Length, Multiplier, Percentage, PixelLength, Progression, SeedValue}; -use core_types::table::{Table, TableDyn, TableRow}; +use core_types::table::{Table, TableDyn, Item}; use core_types::transform::{Footprint, Transform}; use core_types::uuid::NodeId; use core_types::{ @@ -442,7 +442,7 @@ async fn round_corners( result.append_bezpath(rounded_subpath); } - TableRow::from_parts(result, attributes) + Item::from_parts(result, attributes) }) .collect() } @@ -799,7 +799,7 @@ where } // Prepare the items to be sorted - let mut items: Vec<(f64, f64, DVec2, TableRow)> = elements + let mut items: Vec<(f64, f64, DVec2, Item)> = elements .into_iter() .map(|row| { // Single-item `Table` to query its bounding box @@ -1035,7 +1035,7 @@ async fn auto_tangents( } } - TableRow::from_parts(result, attributes) + Item::from_parts(result, attributes) }) .collect() } @@ -1083,7 +1083,7 @@ async fn vec2_to_point(_: impl Ctx, vec2: DVec2) -> Table { let mut point_domain = PointDomain::new(); point_domain.push(PointId::generate(), vec2); - Table::new_from_row(TableRow::new_from_element(Vector { point_domain, ..Default::default() })) + Table::new_from_row(Item::new_from_element(Vector { point_domain, ..Default::default() })) } /// Creates a polyline from a series of vector points, replacing any existing segments and regions that may already exist. @@ -1222,10 +1222,10 @@ async fn solidify_stroke(_: impl Ctx, # let has_fill = !vector.style.fill().is_none(); let fill_row = has_fill.then(|| { vector.style.clear_stroke(); - TableRow::from_parts(vector, attributes.clone()) + Item::from_parts(vector, attributes.clone()) }); - let stroke_row = TableRow::from_parts(solidified_stroke, attributes); + let stroke_row = Item::from_parts(solidified_stroke, attributes); // Ordering based on the paint order. The first item in the `Table` is rendered below the second. match paint_order { @@ -1271,9 +1271,9 @@ async fn separate_subpaths(_: impl Ctx, content: Table) -> Table vector.append_bezpath(bezpath); vector.style = style.clone(); - TableRow::from_parts(vector, attributes.clone()) + Item::from_parts(vector, attributes.clone()) }) - .collect::>>() + .collect::>>() }) .collect() } @@ -2413,7 +2413,7 @@ async fn morph( attributes.insert(ATTR_TRANSFORM, lerped_transform); attributes.insert(ATTR_EDITOR_MERGED_LAYERS, graphic_table_content); - return Table::new_from_row(TableRow::from_parts(endpoint_element.clone(), attributes)); + return Table::new_from_row(Item::from_parts(endpoint_element.clone(), attributes)); } let mut vector = Vector { @@ -2570,7 +2570,7 @@ async fn morph( let layer_path: Table = content.attribute_cloned_or_default(ATTR_EDITOR_LAYER_PATH, primary_index); Table::new_from_row( - TableRow::new_from_element(vector) + Item::new_from_element(vector) .with_attribute(ATTR_TRANSFORM, lerped_transform) .with_attribute(ATTR_BLEND_MODE, lerped_blend_mode) .with_attribute(ATTR_OPACITY, lerped_opacity) @@ -2859,7 +2859,7 @@ fn bevel(_: impl Ctx, source: Table, #[default(10.)] distance: Length) - let transform: DAffine2 = row.attribute_cloned_or_default(ATTR_TRANSFORM); let (element, attributes) = row.into_parts(); - TableRow::from_parts(bevel_algorithm(element, transform, distance), attributes) + Item::from_parts(bevel_algorithm(element, transform, distance), attributes) }) .collect() } @@ -3046,10 +3046,10 @@ mod test { Table::new_from_element(Vector::from_bezpath(bezpath)) } - fn create_vector_row(bezpath: BezPath, transform: DAffine2) -> TableRow { + fn create_vector_row(bezpath: BezPath, transform: DAffine2) -> Item { let mut row = Vector::default(); row.append_bezpath(bezpath); - TableRow::new_from_element(row).with_attribute(ATTR_TRANSFORM, transform) + Item::new_from_element(row).with_attribute(ATTR_TRANSFORM, transform) } #[tokio::test] From d843ce2891b5b77b2a939d91849b8b182fa50e72 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Fri, 8 May 2026 22:15:02 -0700 Subject: [PATCH 2/4] Rename row -> item and column -> attribute throughout --- .../data_panel/data_panel_message_handler.rs | 4 +- .../interpreted-executor/src/node_registry.rs | 34 +- node-graph/libraries/core-types/src/ops.rs | 8 +- node-graph/libraries/core-types/src/table.rs | 662 +++++++++--------- .../nodes/gcore/src/context_modification.rs | 4 +- node-graph/nodes/graphic/src/graphic.rs | 10 +- 6 files changed, 363 insertions(+), 359 deletions(-) diff --git a/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs b/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs index 925ea09a2f..e89fa51d35 100644 --- a/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs @@ -985,8 +985,8 @@ fn display_value_override(any: &dyn Any) -> Option { /// Type-dispatched widget for displaying an attribute value in a `Table` item. /// Delegates to [`TableItemLayout::value_widget`] so the same widget code is shared between -/// element-column rendering and attribute-column rendering. Returns `None` for unrecognized types so the -/// caller can fall back to a debug-formatted [`TextLabel`]. +/// element-column rendering and attribute-column rendering. Returns `None` for unrecognized +/// types so the caller can fall back to a debug-formatted [`TextLabel`]. fn dispatch_value_widget(any: &dyn Any, target: PathStep, data: &LayoutData) -> Option { macro_rules! check { ( $($ty:ty),* $(,)? ) => { diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 97e8474b4a..8e1d149ec5 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -16,7 +16,7 @@ use graphene_std::raster::color::Color; use graphene_std::raster::*; use graphene_std::raster::{CPU, Raster}; use graphene_std::render_node::RenderIntermediate; -use graphene_std::table::{AttributeColumnDyn, AttributeValueDyn, Table, TableDyn}; +use graphene_std::table::{AttributeDyn, AttributeValueDyn, Table, TableDyn}; use graphene_std::transform::Footprint; use graphene_std::uuid::NodeId; use graphene_std::vector::Vector; @@ -42,19 +42,19 @@ fn node_registry() -> HashMap>, to: Table), // Type-erased attribute column conversions for the `Attach Attribute` node, so it monomorphizes only over the destination table type. - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table>, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), - convert_node!(from: Table, to: AttributeColumnDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table>, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), + convert_node!(from: Table, to: AttributeDyn), convert_node!(from: Table, to: TableDyn), convert_node!(from: Table, to: TableDyn), convert_node!(from: Table, to: TableDyn), @@ -151,7 +151,7 @@ fn node_registry() -> HashMap, input: Context, fn_params: [Context => Table]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table]), - async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => AttributeColumnDyn]), + async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => AttributeDyn]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => AttributeValueDyn]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => TableDyn]), async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Graphic]), @@ -190,7 +190,7 @@ fn node_registry() -> HashMap, input: Context, fn_params: [Context => &PlatformEditorApi, Context => graphene_std::ContextFeatures]), async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => RenderIntermediate, Context => graphene_std::ContextFeatures]), async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => RenderOutput, Context => graphene_std::ContextFeatures]), - async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => AttributeColumnDyn, Context => graphene_std::ContextFeatures]), + async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => AttributeDyn, Context => graphene_std::ContextFeatures]), async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => AttributeValueDyn, Context => graphene_std::ContextFeatures]), async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => TableDyn, Context => graphene_std::ContextFeatures]), #[cfg(target_family = "wasm")] @@ -216,7 +216,7 @@ fn node_registry() -> HashMap, input: Context, fn_params: [Context => Table]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table]), - async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => AttributeColumnDyn]), + async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => AttributeDyn]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => AttributeValueDyn]), async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => TableDyn]), #[cfg(target_family = "wasm")] diff --git a/node-graph/libraries/core-types/src/ops.rs b/node-graph/libraries/core-types/src/ops.rs index f0832726f5..17da54f8c1 100644 --- a/node-graph/libraries/core-types/src/ops.rs +++ b/node-graph/libraries/core-types/src/ops.rs @@ -1,5 +1,5 @@ use crate::Node; -use crate::table::{AttributeColumnDyn, AttributeValueDyn, Column, Table, TableDyn, Item}; +use crate::table::{Attribute, AttributeDyn, AttributeValueDyn, Item, Table, TableDyn}; use crate::transform::Footprint; use glam::DVec2; use graphene_hash::CacheHash; @@ -75,10 +75,10 @@ impl + Send> Convert, ()> for Table { /// Wraps each row's element into a type-erased column. Lets nodes that accept a source attribute /// from any `Table` express their signature as `AttributeColumnDyn` and avoid monomorphizing /// over `U`; the compiler inserts this convert to bridge concrete-typed graph wires to the dyn input. -impl Convert for Table { - async fn convert(self, _: Footprint, _: ()) -> AttributeColumnDyn { +impl Convert for Table { + async fn convert(self, _: Footprint, _: ()) -> AttributeDyn { let values: Vec = self.into_iter().map(|row| row.into_element()).collect(); - AttributeColumnDyn(Box::new(Column(values))) + AttributeDyn(Box::new(Attribute(values))) } } diff --git a/node-graph/libraries/core-types/src/table.rs b/node-graph/libraries/core-types/src/table.rs index b3dd28c7b6..92522a0016 100644 --- a/node-graph/libraries/core-types/src/table.rs +++ b/node-graph/libraries/core-types/src/table.rs @@ -6,28 +6,28 @@ use glam::DAffine2; use graphene_hash::CacheHash; use std::fmt::Debug; -// ===================================================================== +// ================================================= // Standard attribute keys used across the data flow -// ===================================================================== +// ================================================= -/// Row's `DAffine2` transformation, composed multiplicatively through nested groups. +/// Item's `DAffine2` transformation, composed multiplicatively through nested groups. pub const ATTR_TRANSFORM: &str = "transform"; -/// Row's `BlendMode`, controlling how it composites with content beneath it. +/// Item's `BlendMode`, controlling how it composites with content beneath it. pub const ATTR_BLEND_MODE: &str = "blend_mode"; -/// Row's opacity multiplier (`f64`, implicit default `1.`). -/// Composed multiplicatively through nested groups. Affects content clipped to the row. +/// Item's opacity multiplier (`f64`, implicit default `1.`). +/// Composed multiplicatively through nested groups. Affects content clipped to the item. pub const ATTR_OPACITY: &str = "opacity"; -/// Row's fill opacity multiplier (`f64`, implicit default `1.`). -/// Like opacity but does not affect content clipped to the row. +/// Item's fill opacity multiplier (`f64`, implicit default `1.`). +/// Like opacity but does not affect content clipped to the item. pub const ATTR_OPACITY_FILL: &str = "opacity_fill"; -/// `bool` for whether a row inherits the alpha of the content beneath it (clipping mask). +/// `bool` for whether an item inherits the alpha of the content beneath it (clipping mask). pub const ATTR_CLIPPING_MASK: &str = "clipping_mask"; -/// `Table` path from the root network to the layer node owning this row. +/// `Table` path from the root network to the layer node owning this item. /// Used by editor tools to route clicks/selection back to the originating layer. pub const ATTR_EDITOR_LAYER_PATH: &str = "editor:layer_path"; @@ -36,13 +36,13 @@ pub const ATTR_EDITOR_LAYER_PATH: &str = "editor:layer_path"; /// the original child layers after their content has been collapsed. pub const ATTR_EDITOR_MERGED_LAYERS: &str = "editor:merged_layers"; -/// Optional `Vector` that overrides the row's own geometry for click-target generation. +/// Optional `Vector` that overrides the item's own geometry for click-target generation. /// Used by the 'Text' node for per-glyph bounding-box rectangles so glyphs are selectable /// by clicking anywhere within their bounds, not just the filled letterform. pub const ATTR_EDITOR_CLICK_TARGET: &str = "editor:click_target"; /// `DAffine2` mapping the unit square `[(0, 0), (1, 1)]` (top-left convention) onto the 'Text' -/// node's text frame in this row's local space. Each row carries the frame relative to its own +/// node's text frame in this item's local space. Each item carries the frame relative to its own /// glyph origin so it survives `Index Elements` filtering. The Text tool reads this to position /// its drag cage. Stored as an affine to allow non-axis-aligned frames in the future. pub const ATTR_EDITOR_TEXT_FRAME: &str = "editor:text_frame"; @@ -77,15 +77,15 @@ pub const ATTR_SPREAD_METHOD: &str = "spread_method"; /// Gradient's `GradientType` (`Linear` or `Radial`). pub const ATTR_GRADIENT_TYPE: &str = "gradient_type"; -// ===================== -// TRAIT: AttributeValue -// ===================== +// ======================== +// TRAIT: AnyAttributeValue +// ======================== /// Enables type-erased scalar storage that supports Clone, Send, Sync, and downcasting. /// Used for individual attribute values in an [`Item`]. -pub trait AttributeValue: std::any::Any + Send + Sync { +pub trait AnyAttributeValue: std::any::Any + Send + Sync { /// Clones this value into a new boxed trait object. - fn clone_box(&self) -> Box; + fn clone_box(&self) -> Box; /// Returns a shared reference to the underlying concrete type for downcasting. fn as_any(&self) -> &dyn std::any::Any; @@ -99,14 +99,13 @@ pub trait AttributeValue: std::any::Any + Send + Sync { /// Returns a debug-formatted string representation of this value. fn display_string(&self) -> String; - /// Wraps this scalar value into a new column for columnar storage, - /// with `preceding_defaults` default values before this value. - fn into_column(self: Box, preceding_defaults: usize) -> Box; + /// Wraps this scalar value into a new attribute with `preceding_defaults` default values before this value. + fn into_attribute(self: Box, preceding_defaults: usize) -> Box; } -impl AttributeValue for T { +impl AnyAttributeValue for T { /// Clones this value into a new boxed trait object. - fn clone_box(&self) -> Box { + fn clone_box(&self) -> Box { Box::new(self.clone()) } @@ -130,28 +129,28 @@ impl, preceding_defaults: usize) -> Box { + /// Wraps this scalar value into a new attribute, padded with `preceding_defaults` default values before it. + fn into_attribute(self: Box, preceding_defaults: usize) -> Box { let mut data = vec![T::default(); preceding_defaults]; data.push(*self); - Box::new(Column(data)) + Box::new(Attribute(data)) } } -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { (**self).clone_box() } } -// ====================== -// TRAIT: AttributeColumn -// ====================== +// =================== +// TRAIT: AnyAttribute +// =================== -/// Enables type-erased columnar storage for parallel attribute lists in a Table. -pub trait AttributeColumn: std::any::Any + Send + Sync { - /// Clones this column into a new boxed trait object. - fn clone_box(&self) -> Box; +/// Enables type-erased storage for parallel attribute lists in a [`Table`]. +pub trait AnyAttribute: std::any::Any + Send + Sync { + /// Clones this attribute into a new boxed trait object. + fn clone_box(&self) -> Box; /// Returns a shared reference to the underlying concrete type for downcasting. fn as_any(&self) -> &dyn std::any::Any; @@ -159,29 +158,29 @@ pub trait AttributeColumn: std::any::Any + Send + Sync { /// Returns a mutable reference to the underlying concrete type for downcasting. fn as_any_mut(&mut self) -> &mut dyn std::any::Any; - /// Pushes a scalar attribute value onto the end of this column. - fn push(&mut self, value: Box); + /// Pushes a scalar attribute value onto the end of this attribute. + fn push(&mut self, value: Box); - /// Pushes a default value onto the end of this column. + /// Pushes a default value onto the end of this attribute. fn push_default(&mut self); - /// Sets the value at the given index, padding with defaults if the column is shorter than `index`. + /// Sets the value at the given index, padding with defaults if the attribute is shorter than `index`. /// Falls back to a default if the value's type doesn't match. - fn set_at(&mut self, index: usize, value: Box); + fn set_at(&mut self, index: usize, value: Box); - /// Creates a new column of the same type filled with `count` number of default values. - fn new_with_defaults(&self, count: usize) -> Box; + /// Creates a new attribute of the same type filled with `count` number of default values. + fn new_with_defaults(&self, count: usize) -> Box; - /// Returns the number of elements in this column. + /// Returns the number of elements in this attribute. fn len(&self) -> usize; - /// Returns whether this column has any elements. + /// Returns whether this attribute has any elements. fn is_empty(&self) -> bool { self.len() == 0 } - /// Appends all values from another column of the same type. - fn extend(&mut self, other: Box); + /// Appends all values from another attribute of the same type. + fn extend(&mut self, other: Box); /// Returns a shared reference to the value at the requested index. fn get_any(&self, index: usize) -> Option<&dyn std::any::Any>; @@ -189,18 +188,18 @@ pub trait AttributeColumn: std::any::Any + Send + Sync { /// Returns a debug-formatted display string for the value at the requested index. fn display_at(&self, index: usize) -> Option; - /// Clones a single value from this column into a boxed scalar attribute value. - fn clone_value(&self, index: usize) -> Option>; + /// Clones a single value from this attribute into a boxed scalar attribute value. + fn clone_value(&self, index: usize) -> Option>; - /// Drains all values out of this column into a Vec of scalar attribute values. - fn drain(self: Box) -> Vec>; + /// Drains all values out of this attribute into a Vec of scalar attribute values. + fn drain(self: Box) -> Vec>; - /// Hashes every value in this column into the given hasher (object-safe wrapper around `CacheHash`). + /// Hashes every value in this attribute into the given hasher (object-safe wrapper around `CacheHash`). fn cache_hash_dyn(&self, state: &mut dyn core::hash::Hasher); - /// Compares this column to another for value-by-value equality (object-safe wrapper around `PartialEq`). + /// Compares this attribute to another for value-by-value equality (object-safe wrapper around `PartialEq`). /// Returns `false` if the underlying types differ. - fn eq_dyn(&self, other: &dyn AttributeColumn) -> bool; + fn eq_dyn(&self, other: &dyn AnyAttribute) -> bool; } /// Adapts a `&mut dyn Hasher` so generic `CacheHash::cache_hash` calls (which require `H: Sized + Hasher`) can @@ -215,23 +214,23 @@ impl core::hash::Hasher for DynHasher<'_> { } } -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { (**self).clone_box() } } -// ========= -// Column -// ========= +// ============ +// Attribute +// ============ -/// Wraps a Vec for column-major attribute storage in a Table. -pub struct Column(pub Vec); +/// Wraps a Vec for attribute storage in a [`Table`]. +pub struct Attribute(pub Vec); -impl AttributeColumn for Column { - /// Clones this column into a new boxed trait object. - fn clone_box(&self) -> Box { - Box::new(Column(self.0.clone())) +impl AnyAttribute for Attribute { + /// Clones this attribute into a new boxed trait object. + fn clone_box(&self) -> Box { + Box::new(Attribute(self.0.clone())) } /// Returns a shared reference to the underlying concrete type for downcasting. @@ -244,9 +243,9 @@ impl self } - /// Pushes a scalar attribute value onto the end of this column, downcasting it to `T`. - /// Falls back to a default value if the type doesn't match, to maintain the column-length invariant. - fn push(&mut self, value: Box) { + /// Pushes an attribute value onto the end of this attribute's list, downcasting it to `T`. + /// Falls back to a default value if the type doesn't match, to maintain the attribute-length invariant. + fn push(&mut self, value: Box) { if let Ok(value) = value.into_any().downcast::() { self.0.push(*value); } else { @@ -254,14 +253,14 @@ impl } } - /// Pushes a default `T` value onto the end of this column. + /// Pushes a default `T` value onto the end of this attribute list. fn push_default(&mut self) { self.0.push(T::default()); } - /// Sets the value at the given index, padding with defaults if the column is shorter than `index`. + /// Sets the value at the given index, padding with defaults if the attribute is shorter than `index`. /// Falls back to a default if the value's type doesn't match. - fn set_at(&mut self, index: usize, value: Box) { + fn set_at(&mut self, index: usize, value: Box) { while self.0.len() < index { self.0.push(T::default()); } @@ -273,19 +272,19 @@ impl } } - /// Creates a new column filled with `count` default `T` values. - fn new_with_defaults(&self, count: usize) -> Box { - Box::new(Column(vec![T::default(); count])) + /// Creates a new attribute filled with `count` default `T` values. + fn new_with_defaults(&self, count: usize) -> Box { + Box::new(Attribute(vec![T::default(); count])) } - /// Returns the number of elements in this column. + /// Returns the number of elements in this attribute. fn len(&self) -> usize { self.0.len() } - /// Appends all values from another column, downcasting it to the same `Column` type. - /// Falls back to padding with defaults if the type doesn't match, to maintain the column-length invariant. - fn extend(&mut self, other: Box) { + /// Appends all values from another attribute, downcasting it to the same `Attribute` type. + /// Falls back to padding with defaults if the type doesn't match, to maintain the attribute-length invariant. + fn extend(&mut self, other: Box) { let other_len = other.len(); if let Ok(other) = (other as Box).downcast::() { self.0.extend(other.0); @@ -305,48 +304,48 @@ impl } /// Clones the value at the given index into a boxed scalar attribute value. - fn clone_value(&self, index: usize) -> Option> { - self.0.get(index).map(|v| Box::new(v.clone()) as Box) + fn clone_value(&self, index: usize) -> Option> { + self.0.get(index).map(|v| Box::new(v.clone()) as Box) } - /// Consumes this column and returns all values as a Vec of boxed scalar attribute values. - fn drain(self: Box) -> Vec> { - self.0.into_iter().map(|v| Box::new(v) as Box).collect() + /// Consumes this attribute and returns all values as a Vec of boxed scalar attribute values. + fn drain(self: Box) -> Vec> { + self.0.into_iter().map(|v| Box::new(v) as Box).collect() } - /// Hashes every value in this column into the given hasher (object-safe wrapper around `CacheHash`). + /// Hashes every value in this attribute into the given hasher (object-safe wrapper around `CacheHash`). fn cache_hash_dyn(&self, state: &mut dyn core::hash::Hasher) { self.0.cache_hash(&mut DynHasher(state)); } - /// Compares this column to another for value-by-value equality (object-safe wrapper around `PartialEq`). - fn eq_dyn(&self, other: &dyn AttributeColumn) -> bool { + /// Compares this attribute to another for value-by-value equality (object-safe wrapper around `PartialEq`). + fn eq_dyn(&self, other: &dyn AnyAttribute) -> bool { other.as_any().downcast_ref::().is_some_and(|other| self.0 == other.0) } } -// =================== -// AttributeColumnDyn -// =================== +// ============ +// AttributeDyn +// ============ -/// Type-erased column of attribute values, used as a node graph parameter type. -/// Lets a node accept any `Table` source via the auto-inserted `Convert` +/// Type-erased list of attribute values, used as a node graph parameter type. +/// Lets a node accept any `Table` source via the auto-inserted `Convert` /// without monomorphizing over `U` (so the cartesian product of `(content T, source U)` collapses to just `T`). -pub struct AttributeColumnDyn(pub Box); +pub struct AttributeDyn(pub Box); -impl AttributeColumnDyn { - /// Number of values in this column. +impl AttributeDyn { + /// Number of values in this attribute. pub fn len(&self) -> usize { self.0.len() } - /// Whether this column has zero values. + /// Whether this attribute has zero values. pub fn is_empty(&self) -> bool { self.0.len() == 0 } - /// Builds a new column matching `target_len` items, taking values from this column (wrapping if shorter, truncating if longer). - pub fn cloned_to_length(&self, target_len: usize) -> Box { + /// Builds a new attribute matching `target_len` items, taking values from this attribute (wrapping if shorter, truncating if longer). + pub fn cloned_to_length(&self, target_len: usize) -> Box { let mut result = self.0.new_with_defaults(0); let source_len = self.0.len(); if source_len == 0 { @@ -363,37 +362,37 @@ impl AttributeColumnDyn { } } -impl Clone for AttributeColumnDyn { +impl Clone for AttributeDyn { fn clone(&self) -> Self { Self(self.0.clone_box()) } } -impl Default for AttributeColumnDyn { +impl Default for AttributeDyn { fn default() -> Self { - Self(Box::new(Column::(Vec::new()))) + Self(Box::new(Attribute::(Vec::new()))) } } -impl Debug for AttributeColumnDyn { +impl Debug for AttributeDyn { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "AttributeColumnDyn(len: {})", self.0.len()) + write!(f, "AttributeDyn(len: {})", self.0.len()) } } -impl PartialEq for AttributeColumnDyn { +impl PartialEq for AttributeDyn { fn eq(&self, other: &Self) -> bool { self.0.eq_dyn(&*other.0) } } -impl CacheHash for AttributeColumnDyn { +impl CacheHash for AttributeDyn { fn cache_hash(&self, state: &mut H) { self.0.cache_hash_dyn(state); } } -unsafe impl StaticType for AttributeColumnDyn { +unsafe impl StaticType for AttributeDyn { type Static = Self; } @@ -404,7 +403,7 @@ unsafe impl StaticType for AttributeColumnDyn { /// Type-erased single attribute value, used as a node graph parameter type. /// Lets a node accept a value of any concrete type via the auto-inserted `Convert` /// without monomorphizing over the value type. -pub struct AttributeValueDyn(pub Box); +pub struct AttributeValueDyn(pub Box); impl Clone for AttributeValueDyn { fn clone(&self) -> Self { @@ -444,12 +443,12 @@ unsafe impl StaticType for AttributeValueDyn { // TableDyn // ======== -/// Type-erased view of a `Table` exposing only its attribute columns and row count, used as a node graph parameter type. +/// Type-erased view of a `Table` exposing only its attributes and item count, used as a node graph parameter type. /// Lets a node accept any `Table` source via the auto-inserted `Convert` without monomorphizing over `U`, /// for cases where the element type is irrelevant (such as nodes that read out a named attribute regardless of the carrier table). #[derive(Default)] pub struct TableDyn { - columns: Vec<(String, Box)>, + attributes: Vec<(String, Box)>, len: usize, } @@ -466,14 +465,16 @@ impl TableDyn { /// Returns a reference to the attribute value at the given key and item index, downcast to `U`, if present and matching. pub fn attribute(&self, key: &str, index: usize) -> Option<&U> { - self.columns.iter().find_map(|(k, column)| if k == key { column.get_any(index)?.downcast_ref::() } else { None }) + self.attributes + .iter() + .find_map(|(k, attribute)| if k == key { attribute.get_any(index)?.downcast_ref::() } else { None }) } } impl From> for TableDyn { fn from(table: Table) -> Self { Self { - columns: table.attributes.columns, + attributes: table.attributes.attributes, len: table.attributes.len, } } @@ -482,7 +483,7 @@ impl From> for TableDyn { impl Clone for TableDyn { fn clone(&self) -> Self { Self { - columns: self.columns.iter().map(|(key, column)| (key.clone(), column.clone_box())).collect(), + attributes: self.attributes.iter().map(|(key, attribute)| (key.clone(), attribute.clone_box())).collect(), len: self.len, } } @@ -490,7 +491,7 @@ impl Clone for TableDyn { impl Debug for TableDyn { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let keys: Vec<&str> = self.columns.iter().map(|(k, _)| k.as_str()).collect(); + let keys: Vec<&str> = self.attributes.iter().map(|(k, _)| k.as_str()).collect(); f.debug_struct("TableDyn").field("keys", &keys).field("len", &self.len).finish() } } @@ -498,21 +499,21 @@ impl Debug for TableDyn { impl PartialEq for TableDyn { fn eq(&self, other: &Self) -> bool { self.len == other.len - && self.columns.len() == other.columns.len() + && self.attributes.len() == other.attributes.len() && self - .columns + .attributes .iter() - .zip(&other.columns) - .all(|((key_a, column_a), (key_b, column_b))| key_a == key_b && column_a.eq_dyn(&**column_b)) + .zip(&other.attributes) + .all(|((key_a, attribute_a), (key_b, attribute_b))| key_a == key_b && attribute_a.eq_dyn(&**attribute_b)) } } impl CacheHash for TableDyn { fn cache_hash(&self, state: &mut H) { self.len.cache_hash(state); - for (key, column) in &self.columns { + for (key, attribute) in &self.attributes { key.cache_hash(state); - column.cache_hash_dyn(state); + attribute.cache_hash_dyn(state); } } } @@ -521,26 +522,26 @@ unsafe impl StaticType for TableDyn { type Static = Self; } -// =============== -// AttributeValues -// =============== +// =================== +// ItemAttributeValues +// =================== -/// Scalar attribute storage. +/// Scalar attribute storage for a single item. /// /// A small ordered map of type-erased scalar attribute values, keyed by string name. /// Used for individual attribute values in an [`Item`]. /// Linear search preserves insertion order and is likely faster than a HashMap for small attribute counts. #[derive(Clone, Default)] -pub struct AttributeValues(Vec<(String, Box)>); +pub struct ItemAttributeValues(Vec<(String, Box)>); -impl Debug for AttributeValues { +impl Debug for ItemAttributeValues { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let keys: Vec<&str> = self.0.iter().map(|(k, _)| k.as_str()).collect(); f.debug_struct("Attributes").field("keys", &keys).finish() } } -impl AttributeValues { +impl ItemAttributeValues { /// Creates an empty set of attributes. pub fn new() -> Self { Self::default() @@ -623,198 +624,203 @@ impl AttributeValues { } } -// ================ -// AttributeColumns -// ================ +// ========== +// Attributes +// ========== -/// Columnar attribute storage. +/// The storage data structure for attributes. /// -/// A collection of type-erased parallel attribute columns, keyed by string name. -/// Used for columnar attribute storage in a Table. -/// Not public. All access goes through [`Table`] and [`Item`]. -/// Invariant: every column in `columns` has exactly `len` elements. +/// A collection of type-erased parallel attributes, keyed by string name. +/// All access goes through [`Table`] and [`Item`] since internals are private. +/// Invariant: every attribute in `attributes` has exactly `len` elements. #[derive(Clone, Default)] -struct AttributeColumns { - columns: Vec<(String, Box)>, +struct Attributes { + attributes: Vec<(String, Box)>, len: usize, } -impl Debug for AttributeColumns { +impl Debug for Attributes { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let keys: Vec<&str> = self.columns.iter().map(|(k, _)| k.as_str()).collect(); - f.debug_struct("AttributeColumns").field("keys", &keys).field("len", &self.len).finish() + let keys: Vec<&str> = self.attributes.iter().map(|(k, _)| k.as_str()).collect(); + f.debug_struct("Attributes").field("keys", &keys).field("len", &self.len).finish() } } -impl AttributeColumns { - /// Creates an empty column store with no columns and zero length. +impl Attributes { + /// Creates an empty attribute store with no attributes and zero length. fn new() -> Self { Self::default() } - /// Creates an empty column store with no columns but a pre-set row count. + /// Creates an empty attribute store with no attributes but a pre-set item count. fn with_len(len: usize) -> Self { - Self { columns: Vec::new(), len } + Self { attributes: Vec::new(), len } } - /// Pushes a row's scalar attributes into this column store. - /// Existing columns that the row lacks receive a default value. - /// New attribute keys create a new column padded with defaults for all prior rows. - fn push_row(&mut self, row: AttributeValues) { - let mut row_entries = row.0; + /// Pushes an item's scalar attributes into this attribute store. + /// Existing attributes that the item lacks receive a default value. + /// New attribute keys create a new attribute padded with defaults for all prior items. + fn push_item(&mut self, item: ItemAttributeValues) { + let mut item_entries = item.0; - // Push values into existing columns, or a default if the row lacks that attribute - for (column_key, column) in &mut self.columns { - if let Some(position) = row_entries.iter().position(|(k, _)| k == column_key) { - let (_, value) = row_entries.swap_remove(position); - column.push(value); + // Push values into existing attributes, or a default if the item lacks that attribute + for (attribute_key, attribute) in &mut self.attributes { + if let Some(position) = item_entries.iter().position(|(k, _)| k == attribute_key) { + let (_, value) = item_entries.swap_remove(position); + attribute.push(value); } else { - column.push_default(); + attribute.push_default(); } } - // Create new columns for any remaining row entries, padded with defaults for prior rows - for (key, value) in row_entries { - self.columns.push((key, value.into_column(self.len))); + // Create new attributes for any remaining item values, padded with defaults for prior items + for (key, value) in item_entries { + self.attributes.push((key, value.into_attribute(self.len))); } self.len += 1; } - /// Appends all column data from another column store into this one. - /// Columns present in only one side are padded with defaults for the other side's rows. - fn extend(&mut self, other: AttributeColumns) { + /// Appends all attribute data from another attribute store into this one. + /// Attributes present in only one side are padded with defaults for the other side's items. + fn extend(&mut self, other: Attributes) { let other_len = other.len; - let mut other_entries = other.columns; + let mut other_entries = other.attributes; - // Extend matching columns, or pad self's columns with defaults for the other's row count - for (key, self_column) in &mut self.columns { + // Extend matching attributes, or pad self's attributes with defaults for the other's item count + for (key, self_attribute) in &mut self.attributes { if let Some(position) = other_entries.iter().position(|(k, _)| k == key) { - let (_, other_column) = other_entries.swap_remove(position); - self_column.extend(other_column); + let (_, other_attribute) = other_entries.swap_remove(position); + self_attribute.extend(other_attribute); } else { for _ in 0..other_len { - self_column.push_default(); + self_attribute.push_default(); } } } - // Remaining other columns are new, pad with defaults for self's existing rows - for (key, other_column) in other_entries { - let mut combined = other_column.new_with_defaults(self.len); - combined.extend(other_column); - self.columns.push((key, combined)); + // Remaining other attributes are new, so we pad with defaults for self's existing items + for (key, other_attribute) in other_entries { + let mut combined = other_attribute.new_with_defaults(self.len); + combined.extend(other_attribute); + self.attributes.push((key, combined)); } self.len += other_len; } - /// Gets a reference to the value at the given index from the column for the given key. + /// Gets a reference to the value at the given index from the attribute for the given key. fn get_value(&self, key: &str, index: usize) -> Option<&T> { - self.columns.iter().find_map(|(k, column)| if k == key { column.get_any(index)?.downcast_ref::() } else { None }) + self.attributes + .iter() + .find_map(|(k, attribute)| if k == key { attribute.get_any(index)?.downcast_ref::() } else { None }) } - /// Removes the entire column for the given key, if present. - fn remove_column(&mut self, key: &str) { - if let Some(position) = self.columns.iter().position(|(k, _)| k == key) { - self.columns.remove(position); + /// Removes the entire attribute for the given key, if present. + fn remove_attribute(&mut self, key: &str) { + if let Some(position) = self.attributes.iter().position(|(k, _)| k == key) { + self.attributes.remove(position); } } - /// Finds or creates a column for the given key and type, returning its position. - /// If a column with the key exists but has the wrong type, it is removed and replaced with a new column of the correct type, padded with defaults. - /// A newly created column is filled with `T::default()` for all existing rows. - fn find_or_create_column(&mut self, key: &str) -> usize { - match self.columns.iter().position(|(k, _)| k == key) { + /// Finds or creates an attribute for the given key and type, returning its position. + /// If an attribute with the key exists but has the wrong type, it is removed and replaced with a new attribute of the correct type, padded with defaults. + /// A newly created attribute is filled with `T::default()` for all existing items. + fn find_or_create_attribute(&mut self, key: &str) -> usize { + match self.attributes.iter().position(|(k, _)| k == key) { Some(position) => { - if (*self.columns[position].1).as_any().downcast_ref::>().is_some() { + if (*self.attributes[position].1).as_any().downcast_ref::>().is_some() { position } else { - self.columns.remove(position); - self.columns.push((key.to_string(), Box::new(Column::(vec![T::default(); self.len])))); - self.columns.len() - 1 + self.attributes.remove(position); + self.attributes.push((key.to_string(), Box::new(Attribute::(vec![T::default(); self.len])))); + self.attributes.len() - 1 } } None => { - self.columns.push((key.to_string(), Box::new(Column::(vec![T::default(); self.len])))); - self.columns.len() - 1 + self.attributes.push((key.to_string(), Box::new(Attribute::(vec![T::default(); self.len])))); + self.attributes.len() - 1 } } } - /// Gets a mutable reference to the value at the given index, creating the column if it doesn't exist or has the wrong type. + /// Gets a mutable reference to the value at the given index, creating the attribute if it doesn't exist or has the wrong type. fn get_or_insert_default_value(&mut self, key: &str, index: usize) -> &mut T { - let column_position = self.find_or_create_column::(key); - let column = (*self.columns[column_position].1).as_any_mut().downcast_mut::>().unwrap(); - &mut column.0[index] + let attribute_position = self.find_or_create_attribute::(key); + let attribute = (*self.attributes[attribute_position].1).as_any_mut().downcast_mut::>().unwrap(); + &mut attribute.0[index] } - /// Sets the value at the given index in the column for the given key. - /// Creates the column with defaults if it doesn't exist. + /// Sets the value at the given index in the attribute for the given key. + /// Creates the attribute with defaults if it doesn't exist. fn set_value(&mut self, key: impl Into, index: usize, value: T) { let key = key.into(); - let column_position = self.find_or_create_column::(&key); - let column = (*self.columns[column_position].1).as_any_mut().downcast_mut::>().unwrap(); - column.0[index] = value; + let attribute_position = self.find_or_create_attribute::(&key); + let attribute = (*self.attributes[attribute_position].1).as_any_mut().downcast_mut::>().unwrap(); + attribute.0[index] = value; } - /// Returns a debug-formatted string for the value at the given index in the column for the given key. + /// Returns a debug-formatted string for the value at the given index in the attribute for the given key. fn display_value(&self, key: &str, index: usize, overrides: fn(&dyn std::any::Any) -> Option) -> Option { - self.columns.iter().find_map(|(k, column)| { + self.attributes.iter().find_map(|(k, attribute)| { if k == key { - if let Some(value) = column.get_any(index) + if let Some(value) = attribute.get_any(index) && let Some(text) = overrides(value) { return Some(text); } - column.display_at(index) + attribute.display_at(index) } else { None } }) } - /// Returns a type-erased reference to the value at the given index in the column for the given key. + /// Returns a type-erased reference to the value at the given index in the attribute for the given key. fn get_any_value(&self, key: &str, index: usize) -> Option<&dyn std::any::Any> { - self.columns.iter().find_map(|(k, column)| if k == key { column.get_any(index) } else { None }) + self.attributes.iter().find_map(|(k, attribute)| if k == key { attribute.get_any(index) } else { None }) } - /// Returns an iterator over the keys of all stored attribute columns, in insertion order. + /// Returns an iterator over the keys of all stored attributes (in insertion order). fn keys(&self) -> impl Iterator { - self.columns.iter().map(|(key, _)| key.as_str()) + self.attributes.iter().map(|(key, _)| key.as_str()) } - /// Returns a typed slice of the column for the given key, if it exists and can be downcast to `Column`. - fn get_column_slice(&self, key: &str) -> Option<&[T]> { - self.columns - .iter() - .find_map(|(k, column)| if k == key { column.as_any().downcast_ref::>().map(|c| c.0.as_slice()) } else { None }) + /// Returns a typed slice of the attribute for the given key, if it exists and can be downcast to `Attribute`. + fn get_attribute_slice(&self, key: &str) -> Option<&[T]> { + self.attributes.iter().find_map(|(k, attribute)| { + if k == key { + attribute.as_any().downcast_ref::>().map(|c| c.0.as_slice()) + } else { + None + } + }) } - /// Returns a mutable typed slice of the column for the given key, if it exists and can be downcast to `Column`. - fn get_column_slice_mut(&mut self, key: &str) -> Option<&mut [T]> { - self.columns.iter_mut().find_map(|(k, column)| { + /// Returns a mutable typed slice of the attribute for the given key, if it exists and can be downcast to `Attribute`. + fn get_attribute_slice_mut(&mut self, key: &str) -> Option<&mut [T]> { + self.attributes.iter_mut().find_map(|(k, attribute)| { if k == key { - column.as_any_mut().downcast_mut::>().map(|c| c.0.as_mut_slice()) + attribute.as_any_mut().downcast_mut::>().map(|c| c.0.as_mut_slice()) } else { None } }) } - /// Returns a mutable typed slice of the column for the given key, creating a new column filled with defaults if it doesn't exist. - fn get_or_create_column_slice_mut(&mut self, key: &str) -> &mut [T] { - let position = self.find_or_create_column::(key); - let column = (*self.columns[position].1).as_any_mut().downcast_mut::>().unwrap(); - &mut column.0 + /// Returns a mutable typed slice of the attribute for the given key, creating a new attribute filled with defaults if it doesn't exist. + fn get_or_create_attribute_slice_mut(&mut self, key: &str) -> &mut [T] { + let position = self.find_or_create_attribute::(key); + let attribute = (*self.attributes[position].1).as_any_mut().downcast_mut::>().unwrap(); + &mut attribute.0 } - /// Clones all attribute values at the given row index into a new scalar Attributes. - fn clone_row(&self, index: usize) -> AttributeValues { - let mut attributes = AttributeValues::new(); + /// Clones all attribute values at the given item index into a new scalar Attributes. + fn clone_row(&self, index: usize) -> ItemAttributeValues { + let mut attributes = ItemAttributeValues::new(); - for (key, column) in &self.columns { - if let Some(value) = column.clone_value(index) { + for (key, attribute) in &self.attributes { + if let Some(value) = attribute.clone_value(index) { attributes.0.push((key.clone(), value)); } } @@ -822,17 +828,17 @@ impl AttributeColumns { attributes } - /// Drains all column data into a Vec of per-row scalar Attributes. - fn into_row_vec(self) -> Vec { - let mut rows: Vec = (0..self.len).map(|_| AttributeValues::new()).collect(); + /// Drains all attribute data into a Vec of per-item scalar Attributes. + fn into_row_vec(self) -> Vec { + let mut items: Vec = (0..self.len).map(|_| ItemAttributeValues::new()).collect(); - for (key, column) in self.columns { - for (i, value) in column.drain().into_iter().enumerate() { - rows[i].0.push((key.clone(), value)); + for (key, attribute) in self.attributes { + for (i, value) in attribute.drain().into_iter().enumerate() { + items[i].0.push((key.clone(), value)); } } - rows + items } } @@ -840,68 +846,68 @@ impl AttributeColumns { // Table // ======== -/// A struct-of-arrays collection where each row holds an element of type `T` alongside -/// a set of type-erased, dynamically-typed attributes stored in parallel columns. +/// A struct-of-arrays collection where each item holds an element of type `T` alongside +/// a set of type-erased, dynamically-typed attributes stored in parallel attributes. /// /// Elements are stored contiguously in a `Vec`, while attributes live in an internal -/// [`AttributeColumns`] store that keeps one column per attribute key. Rows are accessed -/// by index through element/attribute accessor methods, or consumed as owned [`Item`]s via iteration. +/// [`Attributes`] store that keeps one attribute per attribute key. Items are accessed by +/// index through element/attribute accessor methods, or consumed as owned [`Item`]s via iteration. #[derive(Clone, Debug)] pub struct Table { element: Vec, - attributes: AttributeColumns, + attributes: Attributes, } impl Table { - /// Creates an empty table with no rows. + /// Creates an empty table with no items. pub fn new() -> Self { Self::default() } - /// Creates an empty table with pre-allocated capacity for the given number of rows. + /// Creates an empty table with pre-allocated capacity for the given number of items. pub fn with_capacity(capacity: usize) -> Self { Self { element: Vec::with_capacity(capacity), - attributes: AttributeColumns::new(), + attributes: Attributes::new(), } } - /// Creates a table containing a single row with the given element and no attributes. + /// Creates a table containing a single item with the given element and no attributes. pub fn new_from_element(element: T) -> Self { Self { element: vec![element], - attributes: AttributeColumns::with_len(1), + attributes: Attributes::with_len(1), } } /// Creates a table containing a single item from the given [`Item`], preserving its attributes. - pub fn new_from_row(row: Item) -> Self { - let mut attributes = AttributeColumns::new(); - attributes.push_row(row.attributes); + pub fn new_from_row(item: Item) -> Self { + let mut attributes = Attributes::new(); + attributes.push_item(item.attributes); Self { - element: vec![row.element], + element: vec![item.element], attributes, } } - /// Appends a row to the end of this table. - pub fn push(&mut self, row: Item) { - self.element.push(row.element); - self.attributes.push_row(row.attributes); + /// Appends an item to the end of this table. + pub fn push(&mut self, item: Item) { + self.element.push(item.element); + self.attributes.push_item(item.attributes); } - /// Appends all rows from another table into this one. + /// Appends all items from another table into this one. pub fn extend(&mut self, table: Table) { self.element.extend(table.element); self.attributes.extend(table.attributes); } - /// Returns the number of rows in this table. + /// Returns the number of items in this table. pub fn len(&self) -> usize { self.element.len() } - /// Returns `true` if this table contains no rows. + /// Returns `true` if this table contains no items. pub fn is_empty(&self) -> bool { self.element.is_empty() } @@ -911,9 +917,9 @@ impl Table { self.attributes.keys() } - // =========================== - // Column-oriented iteration - // =========================== + // ============================ + // Attribute-oriented iteration + // ============================ /// Returns an iterator over shared references to all element values. pub fn iter_element_values(&self) -> std::slice::Iter<'_, T> { @@ -925,31 +931,31 @@ impl Table { self.element.iter_mut() } - /// Returns an iterator over shared references to the values of a typed attribute column, or `None` if the column doesn't exist or has the wrong type. + /// Returns an iterator over shared references to the values of a typed attribute, or `None` if the attribute doesn't exist or has the wrong type. pub fn iter_attribute_values(&self, key: &str) -> Option> { - self.attributes.get_column_slice::(key).map(|s| s.iter()) + self.attributes.get_attribute_slice::(key).map(|s| s.iter()) } - /// Returns an iterator over mutable references to the values of a typed attribute column, or `None` if the column doesn't exist or has the wrong type. + /// Returns an iterator over mutable references to the values of a typed attribute attribute, or `None` if the attribute doesn't exist or has the wrong type. pub fn iter_attribute_values_mut(&mut self, key: &str) -> Option> { - self.attributes.get_column_slice_mut::(key).map(|s| s.iter_mut()) + self.attributes.get_attribute_slice_mut::(key).map(|s| s.iter_mut()) } - /// Returns an iterator that yields cloned attribute values for the given key, falling back to `U::default()` for each row if the column is missing or has the wrong type. + /// Returns an iterator that yields cloned attribute values for the given key, falling back to `U::default()` for each item if the attribute is missing or has the wrong type. pub fn iter_attribute_values_or_default(&self, key: &str) -> impl Iterator + '_ { - let slice = self.attributes.get_column_slice::(key); + let slice = self.attributes.get_attribute_slice::(key); let len = self.element.len(); (0..len).map(move |i| slice.map_or_else(U::default, |s| s[i].clone())) } - /// Returns a mutable iterator over a typed attribute column, creating the column with default values if it doesn't exist or has the wrong type. + /// Returns a mutable iterator over a typed attribute, creating the attribute with default values if it doesn't exist or has the wrong type. pub fn iter_attribute_values_mut_or_default(&mut self, key: &str) -> std::slice::IterMut<'_, U> { - self.attributes.get_or_create_column_slice_mut::(key).iter_mut() + self.attributes.get_or_create_attribute_slice_mut::(key).iter_mut() } - // ======================= + // ====================== // Indexed element access - // ======================= + // ====================== /// Returns a shared reference to the element at the given index, or `None` if out of bounds. pub fn element(&self, index: usize) -> Option<&T> { @@ -961,89 +967,89 @@ impl Table { self.element.get_mut(index) } - // ========================= + // ======================== // Indexed attribute access - // ========================= + // ======================== - /// Returns a shared reference to the attribute value at the given row index and key, if it exists and can be downcast to the requested type. + /// Returns a shared reference to the attribute value at the given item index and key, if it exists and can be downcast to the requested type. pub fn attribute(&self, key: &str, index: usize) -> Option<&U> { self.attributes.get_value(key, index) } - /// Returns a clone of the attribute value at the given row index and key, or `U::default()` if absent or of a different type. + /// Returns a clone of the attribute value at the given item index and key, or `U::default()` if absent or of a different type. pub fn attribute_cloned_or_default(&self, key: &str, index: usize) -> U { self.attributes.get_value::(key, index).cloned().unwrap_or_default() } - /// Returns a clone of the attribute value at the given row index and key, or the provided default if absent or of a different type. + /// Returns a clone of the attribute value at the given item index and key, or the provided default if absent or of a different type. pub fn attribute_cloned_or(&self, key: &str, index: usize, default: U) -> U { self.attributes.get_value::(key, index).cloned().unwrap_or(default) } - /// Sets the attribute value at the given row index and key, creating the column with defaults if it doesn't exist. + /// Sets the attribute value at the given item index and key, creating the attribute with defaults if it doesn't exist. pub fn set_attribute(&mut self, key: impl Into, index: usize, value: U) { self.attributes.set_value(key, index, value); } - /// Replaces (or adds) an attribute column from a type-erased source. The source is wrapped or truncated to match this table's item count. - pub fn set_column_dyn(&mut self, key: impl Into, source: AttributeColumnDyn) { + /// Replaces (or adds) an attribute from a type-erased source. The source is wrapped or truncated to match this table's item count. + pub fn set_attribute_dyn(&mut self, key: impl Into, source: AttributeDyn) { let key = key.into(); - self.attributes.columns.retain(|(k, _)| k != &key); - let new_column = source.cloned_to_length(self.element.len()); - self.attributes.columns.push((key, new_column)); + self.attributes.attributes.retain(|(k, _)| k != &key); + let new_attribute = source.cloned_to_length(self.element.len()); + self.attributes.attributes.push((key, new_attribute)); } - /// Sets a single type-erased attribute value at the given index, creating the column from the value's underlying type if it doesn't exist (padded with defaults to match the table's length). Falls back to default if the value's type doesn't match an existing column. - pub fn set_attribute_dyn(&mut self, key: impl Into, index: usize, value: AttributeValueDyn) { + /// Sets a single type-erased attribute value at the given index, creating the attribute from the value's underlying type if it doesn't exist (padded with defaults to match the table's length). + /// Falls back to default if the value's type doesn't match an existing attribute. + pub fn set_attribute_value_dyn(&mut self, key: impl Into, index: usize, value: AttributeValueDyn) { let key = key.into(); - if let Some(position) = self.attributes.columns.iter().position(|(k, _)| k == &key) { - self.attributes.columns[position].1.set_at(index, value.0); + if let Some(position) = self.attributes.attributes.iter().position(|(k, _)| k == &key) { + self.attributes.attributes[position].1.set_at(index, value.0); } else { - let mut new_column = value.0.into_column(index); - while new_column.len() < self.element.len() { - new_column.push_default(); + let mut new_attribute = value.0.into_attribute(index); + while new_attribute.len() < self.element.len() { + new_attribute.push_default(); } - self.attributes.columns.push((key, new_column)); + self.attributes.attributes.push((key, new_attribute)); } } - /// Removes the entire attribute column for the given key, if present. + /// Removes the entire attribute for the given key, if present. pub fn remove_attribute(&mut self, key: &str) { - self.attributes.remove_column(key); + self.attributes.remove_attribute(key); } - /// Runs the given closure on a mutable reference to the attribute value at the given row index, - /// creating the column with defaults if it doesn't exist, and returns the closure's result. + /// Runs the given closure on a mutable reference to the attribute value at the given item index, + /// creating the attribute with defaults if it doesn't exist, and returns the closure's result. pub fn with_attribute_mut_or_default R>(&mut self, key: &str, index: usize, f: F) -> R { f(self.attributes.get_or_insert_default_value::(key, index)) } - /// Returns a debug-formatted display string for the attribute at the given row index and key. + /// Returns a debug-formatted display string for the attribute at the given item index and key. pub fn attribute_display_value(&self, key: &str, index: usize, overrides: fn(&dyn std::any::Any) -> Option) -> Option { self.attributes.display_value(key, index, overrides) } - /// Returns a type-erased reference to the attribute value at the given row index and key, or `None` if absent. + /// Returns a type-erased reference to the attribute value at the given item index and key, or `None` if absent. pub fn attribute_any(&self, key: &str, index: usize) -> Option<&dyn std::any::Any> { self.attributes.get_any_value(key, index) } - // ===================== + // ==================== // Split borrow helpers - // ===================== + // ==================== - /// Returns disjoint mutable references to the element slice and a typed attribute column slice, - /// creating the column with defaults if it doesn't exist. This enables simultaneous mutable - /// access to elements and a single attribute column without borrowing conflicts. + /// Returns disjoint mutable references to the element slice and a typed attribute slice, creating the attribute with defaults if it doesn't exist. + /// This enables simultaneous mutable access to elements and a single attribute without borrowing conflicts. pub fn element_and_attribute_slices_mut(&mut self, key: &str) -> (&mut [T], &mut [U]) { let Self { element, attributes } = self; - let column_position = attributes.find_or_create_column::(key); - let column = (*attributes.columns[column_position].1).as_any_mut().downcast_mut::>().unwrap(); - (element.as_mut_slice(), &mut column.0) + let attribute_position = attributes.find_or_create_attribute::(key); + let attribute = (*attributes.attributes[attribute_position].1).as_any_mut().downcast_mut::>().unwrap(); + (element.as_mut_slice(), &mut attribute.0) } // ================== - // Row-level cloning + // Item-level cloning // ================== /// Clones both the element and all attributes at the given item index into a new owned [`Item`], or [`None`] if out of bounds. @@ -1057,8 +1063,8 @@ impl Table { }) } - /// Clones all attribute values at the given item index into a new [`AttributeValues`], without cloning the element. - pub fn clone_row_attributes(&self, index: usize) -> AttributeValues { + /// Clones all attribute values at the given item index into a new [`ItemAttributeValues`], without cloning the element. + pub fn clone_row_attributes(&self, index: usize) -> ItemAttributeValues { self.attributes.clone_row(index) } } @@ -1113,7 +1119,7 @@ impl IntoIterator for Table { type Item = Item; type IntoIter = ItemIter; - /// Consumes a [`Table`] and returns an iterator of [`Item`]s, each containing the owned data of the respective row from the original table. + /// Consumes a [`Table`] and returns an iterator of [`Item`]s, each containing the owned data of the respective item from the original table. fn into_iter(self) -> Self::IntoIter { let row_attributes = self.attributes.into_row_vec(); ItemIter { @@ -1127,7 +1133,7 @@ impl Default for Table { fn default() -> Self { Self { element: Vec::new(), - attributes: AttributeColumns::new(), + attributes: Attributes::new(), } } } @@ -1136,11 +1142,11 @@ impl CacheHash for Table { fn cache_hash(&self, state: &mut H) { self.element.cache_hash(state); - // Hash every attribute column (key + values) rather than just the well-known ones, so changes to user-defined keys + // Hash every attribute attribute (key + values) rather than just the well-known ones, so changes to user-defined keys // (e.g., gradient_type, spread_method) invalidate downstream graph caches as expected - for (key, column) in &self.attributes.columns { + for (key, attribute) in &self.attributes.attributes { std::hash::Hash::hash(key.as_str(), state); - column.cache_hash_dyn(state); + attribute.cache_hash_dyn(state); } } } @@ -1149,13 +1155,13 @@ impl PartialEq for Table { fn eq(&self, other: &Self) -> bool { // Attributes participate in equality so the `a == b` ⇒ `hash(a) == hash(b)` contract holds with `cache_hash` self.element == other.element - && self.attributes.columns.len() == other.attributes.columns.len() + && self.attributes.attributes.len() == other.attributes.attributes.len() && self .attributes - .columns + .attributes .iter() - .zip(&other.attributes.columns) - .all(|((self_key, self_column), (other_key, other_column))| self_key == other_key && self_column.eq_dyn(other_column.as_ref())) + .zip(&other.attributes.attributes) + .all(|((self_key, self_attribute), (other_key, other_attribute))| self_key == other_key && self_attribute.eq_dyn(other_attribute.as_ref())) } } @@ -1186,8 +1192,8 @@ impl FromIterator> for Table { let (lower_bound, _) = iter.size_hint(); let mut table = Self::with_capacity(lower_bound); - for row in iter { - table.push(row); + for item in iter { + table.push(item); } table @@ -1200,13 +1206,11 @@ impl FromIterator> for Table { /// An owned item containing an element of type `T` and a set of type-erased scalar attributes. /// -/// Used to build individual items before pushing them into a [`Table`], or when consuming rows out -/// of a table via [`IntoIterator`]. Attribute values use scalar [`AttributeValues`] storage rather -/// than the columnar layout inside a [`Table`]. +/// Used to build individual items before pushing them into a [`Table`], or when consuming items out of a table via [`IntoIterator`]. #[derive(Clone, Debug)] pub struct Item { element: T, - attributes: AttributeValues, + attributes: ItemAttributeValues, } impl Default for Item { @@ -1222,43 +1226,43 @@ impl PartialEq for Item { } impl Item { - /// Constructs a row from a pre-built element and attributes pair. - pub fn from_parts(element: T, attributes: AttributeValues) -> Self { + /// Constructs an item from a pre-built element and attributes pair. + pub fn from_parts(element: T, attributes: ItemAttributeValues) -> Self { Self { element, attributes } } - /// Constructs a row with the given element and an empty set of attributes. + /// Constructs an item with the given element and an empty set of attributes. pub fn new_from_element(element: T) -> Self { - Self::from_parts(element, AttributeValues::new()) + Self::from_parts(element, ItemAttributeValues::new()) } - /// Returns a shared reference to this row's element. + /// Returns a shared reference to this item's element. pub fn element(&self) -> &T { &self.element } - /// Returns a mutable reference to this row's element. + /// Returns a mutable reference to this item's element. pub fn element_mut(&mut self) -> &mut T { &mut self.element } - /// Consumes this row and returns the owned element, discarding attributes. + /// Consumes this item and returns the owned element, discarding attributes. pub fn into_element(self) -> T { self.element } - /// Consumes this row and returns its element and attributes as separate owned values. - pub fn into_parts(self) -> (T, AttributeValues) { + /// Consumes this item and returns its element and attributes as separate owned values. + pub fn into_parts(self) -> (T, ItemAttributeValues) { (self.element, self.attributes) } - /// Returns a shared reference to all attributes of this row. - pub fn attributes(&self) -> &AttributeValues { + /// Returns a shared reference to all attributes of this item. + pub fn attributes(&self) -> &ItemAttributeValues { &self.attributes } - /// Returns a mutable reference to all attributes of this row. - pub fn attributes_mut(&mut self) -> &mut AttributeValues { + /// Returns a mutable reference to all attributes of this item. + pub fn attributes_mut(&mut self) -> &mut ItemAttributeValues { &mut self.attributes } @@ -1297,7 +1301,7 @@ impl Item { self.attributes.insert(key, value); } - /// Sets the attribute value for the given key and returns the row, enabling builder-style chaining. + /// Sets the attribute value for the given key and returns the item, enabling builder-style chaining. pub fn with_attribute(mut self, key: impl Into, value: U) -> Self { self.set_attribute(key, value); self @@ -1313,13 +1317,13 @@ impl Item { // ItemIter // =========== -/// Owning iterator over the rows of a consumed [`Table`], yielding [`Item`]s. +/// Owning iterator over the items of a consumed [`Table`], yielding [`Item`]s. /// -/// Created by [`Table::into_iter`]. The table's columnar attributes are converted into -/// per-row scalar [`AttributeValues`] during construction so each yielded row is self-contained. +/// Created by [`Table::into_iter`]. The table's attributes are converted into per-item +/// scalar [`ItemAttributeValues`] during construction so each yielded item is self-contained. pub struct ItemIter { element: std::vec::IntoIter, - attributes: std::vec::IntoIter, + attributes: std::vec::IntoIter, } impl Iterator for ItemIter { diff --git a/node-graph/nodes/gcore/src/context_modification.rs b/node-graph/nodes/gcore/src/context_modification.rs index aba8c8d9cd..6eb280b7ae 100644 --- a/node-graph/nodes/gcore/src/context_modification.rs +++ b/node-graph/nodes/gcore/src/context_modification.rs @@ -1,6 +1,6 @@ use core::f64; use core_types::context::{CloneVarArgs, Context, ContextFeatures, Ctx, ExtractAll}; -use core_types::table::{AttributeColumnDyn, AttributeValueDyn, Table, TableDyn}; +use core_types::table::{AttributeDyn, AttributeValueDyn, Table, TableDyn}; use core_types::transform::Footprint; use core_types::uuid::NodeId; use core_types::{Color, OwnedContextImpl}; @@ -37,7 +37,7 @@ async fn context_modification( Context -> Table, Context -> Table, Context -> Table, - Context -> AttributeColumnDyn, + Context -> AttributeDyn, Context -> AttributeValueDyn, Context -> TableDyn, )] diff --git a/node-graph/nodes/graphic/src/graphic.rs b/node-graph/nodes/graphic/src/graphic.rs index 5bfc7fb6e2..b15431e8a8 100644 --- a/node-graph/nodes/graphic/src/graphic.rs +++ b/node-graph/nodes/graphic/src/graphic.rs @@ -1,6 +1,6 @@ use core_types::bounds::{BoundingBox, RenderBoundingBox}; use core_types::registry::types::{Angle, SignedInteger}; -use core_types::table::{AttributeColumnDyn, AttributeValueDyn, Table, TableDyn, Item}; +use core_types::table::{AttributeDyn, AttributeValueDyn, Item, Table, TableDyn}; use core_types::uuid::NodeId; use core_types::{ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_TRANSFORM, AnyHash, BlendMode, CacheHash, CloneVarArgs, Color, Context, Ctx, ExtractAll, OwnedContextImpl}; use glam::{DAffine2, DVec2}; @@ -253,13 +253,13 @@ async fn write_attribute( let row = content.clone_row(index).expect("index is within bounds"); let owned_ctx = OwnedContextImpl::from(ctx.clone()).with_vararg(Box::new(Table::new_from_row(row))).with_index(index); let v = value.eval(owned_ctx.into_context()).await; - content.set_attribute_dyn(&name, index, v); + content.set_attribute_value_dyn(&name, index, v); } content } /// Sets a named attribute on the primary table, with each value taken from the corresponding item's element in the source table (paired by index, wrapping if the source has fewer items). -/// The source is type-erased into an `AttributeColumnDyn` by an auto-inserted convert node, so this node only monomorphizes over `T` instead of the cartesian product `(T, U)`. +/// The source is type-erased into an `AttributeDyn` by an auto-inserted convert node, so this node only monomorphizes over `T` instead of the cartesian product `(T, U)`. #[node_macro::node(category("Attributes: Write"))] fn attach_attribute( _: impl Ctx, @@ -282,14 +282,14 @@ fn attach_attribute( mut content: Table, /// The source values to attach. Any `Table` wired here is type-erased via an auto-inserted convert. #[expose] - source: AttributeColumnDyn, + source: AttributeDyn, /// The name to assign to the new destination attribute. name: String, ) -> Table { if source.is_empty() { return content; } - content.set_column_dyn(name, source); + content.set_attribute_dyn(name, source); content } From 607debc2cd80e2a80527dbf5674cb4243fc04e09 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Fri, 8 May 2026 22:53:49 -0700 Subject: [PATCH 3/4] Fix a few missed ones --- node-graph/libraries/core-types/src/table.rs | 18 +++++++------- .../libraries/graphic-types/src/graphic.rs | 4 ++-- .../libraries/rendering/src/renderer.rs | 4 ++-- .../per_pixel_adjust_runtime.rs | 4 ++-- node-graph/nodes/brush/src/brush.rs | 12 +++++----- node-graph/nodes/graphic/src/artboard.rs | 2 +- node-graph/nodes/graphic/src/graphic.rs | 8 +++---- .../nodes/gstd/src/platform_application_io.rs | 4 ++-- node-graph/nodes/path-bool/src/lib.rs | 4 ++-- node-graph/nodes/raster/src/std_nodes.rs | 6 ++--- node-graph/nodes/repeat/src/repeat_nodes.rs | 4 ++-- node-graph/nodes/vector/src/vector_nodes.rs | 24 +++++++++---------- 12 files changed, 47 insertions(+), 47 deletions(-) diff --git a/node-graph/libraries/core-types/src/table.rs b/node-graph/libraries/core-types/src/table.rs index 92522a0016..dfc603bb6f 100644 --- a/node-graph/libraries/core-types/src/table.rs +++ b/node-graph/libraries/core-types/src/table.rs @@ -816,7 +816,7 @@ impl Attributes { } /// Clones all attribute values at the given item index into a new scalar Attributes. - fn clone_row(&self, index: usize) -> ItemAttributeValues { + fn clone_item(&self, index: usize) -> ItemAttributeValues { let mut attributes = ItemAttributeValues::new(); for (key, attribute) in &self.attributes { @@ -829,7 +829,7 @@ impl Attributes { } /// Drains all attribute data into a Vec of per-item scalar Attributes. - fn into_row_vec(self) -> Vec { + fn into_item_vec(self) -> Vec { let mut items: Vec = (0..self.len).map(|_| ItemAttributeValues::new()).collect(); for (key, attribute) in self.attributes { @@ -881,7 +881,7 @@ impl Table { } /// Creates a table containing a single item from the given [`Item`], preserving its attributes. - pub fn new_from_row(item: Item) -> Self { + pub fn new_from_item(item: Item) -> Self { let mut attributes = Attributes::new(); attributes.push_item(item.attributes); Self { @@ -1053,19 +1053,19 @@ impl Table { // ================== /// Clones both the element and all attributes at the given item index into a new owned [`Item`], or [`None`] if out of bounds. - pub fn clone_row(&self, index: usize) -> Option> + pub fn clone_item(&self, index: usize) -> Option> where T: Clone, { Some(Item { element: self.element.get(index)?.clone(), - attributes: self.attributes.clone_row(index), + attributes: self.attributes.clone_item(index), }) } /// Clones all attribute values at the given item index into a new [`ItemAttributeValues`], without cloning the element. - pub fn clone_row_attributes(&self, index: usize) -> ItemAttributeValues { - self.attributes.clone_row(index) + pub fn clone_item_attributes(&self, index: usize) -> ItemAttributeValues { + self.attributes.clone_item(index) } } @@ -1121,10 +1121,10 @@ impl IntoIterator for Table { /// Consumes a [`Table`] and returns an iterator of [`Item`]s, each containing the owned data of the respective item from the original table. fn into_iter(self) -> Self::IntoIter { - let row_attributes = self.attributes.into_row_vec(); + let attributes = self.attributes.into_item_vec(); ItemIter { element: self.element.into_iter(), - attributes: row_attributes.into_iter(), + attributes: attributes.into_iter(), } } } diff --git a/node-graph/libraries/graphic-types/src/graphic.rs b/node-graph/libraries/graphic-types/src/graphic.rs index 4039a649ec..dc3dcb411e 100644 --- a/node-graph/libraries/graphic-types/src/graphic.rs +++ b/node-graph/libraries/graphic-types/src/graphic.rs @@ -436,7 +436,7 @@ impl AtIndex for Table { type Output = Table; fn at_index(&self, index: usize) -> Option { - self.clone_row(index).map(|row| { + self.clone_item(index).map(|row| { let mut result_table = Self::default(); result_table.push(row); result_table @@ -469,7 +469,7 @@ impl OmitIndex for Table { let mut result = Self::default(); for i in 0..self.len() { if i != index - && let Some(row) = self.clone_row(i) + && let Some(row) = self.clone_item(i) { result.push(row); } diff --git a/node-graph/libraries/rendering/src/renderer.rs b/node-graph/libraries/rendering/src/renderer.rs index f028fab529..259fc39573 100644 --- a/node-graph/libraries/rendering/src/renderer.rs +++ b/node-graph/libraries/rendering/src/renderer.rs @@ -987,7 +987,7 @@ impl Render for Table { // The mask must draw at full alpha so the SVG ``/`` fully zeroes the path interior. // The wrapping SVG group (above) handles the user-set opacity. - let vector_item = Table::new_from_row(Item::new_from_element(cloned_vector).with_attribute(ATTR_TRANSFORM, multiplied_transform)); + let vector_item = Table::new_from_item(Item::new_from_element(cloned_vector).with_attribute(ATTR_TRANSFORM, multiplied_transform)); (id, mask_type, vector_item) }); @@ -1312,7 +1312,7 @@ impl Render for Table { // The mask must draw at full alpha so `SrcOut` fully zeroes the path interior. // The outer opacity/blend layer (above) handles the user-set opacity. - let vector_table = Table::new_from_row(Item::new_from_element(cloned_element).with_attribute(ATTR_TRANSFORM, item_transform)); + let vector_table = Table::new_from_item(Item::new_from_element(cloned_element).with_attribute(ATTR_TRANSFORM, item_transform)); let bounds = element.bounding_box_with_transform(multiplied_transform).unwrap_or(layer_bounds); // This branch is gated on `can_draw_aligned_stroke`, which already requires every subpath is closed diff --git a/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs b/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs index 74db382580..3570e28486 100644 --- a/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs +++ b/node-graph/libraries/wgpu-executor/src/shader_runtime/per_pixel_adjust_runtime.rs @@ -1,7 +1,7 @@ use crate::WgpuContext; use crate::shader_runtime::{FULLSCREEN_VERTEX_SHADER_NAME, ShaderRuntime}; use core_types::shaders::buffer_struct::BufferStruct; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use futures::lock::Mutex; use raster_types::{GPU, Raster}; use std::borrow::Cow; @@ -233,7 +233,7 @@ impl PerPixelAdjustGraphicsPipeline { rp.set_bind_group(0, Some(&bind_group), &[]); rp.draw(0..3, 0..1); - let attributes = textures.clone_row_attributes(index); + let attributes = textures.clone_item_attributes(index); Item::from_parts(Raster::new(GPU { texture: tex_out }), attributes) }) .collect::>(); diff --git a/node-graph/nodes/brush/src/brush.rs b/node-graph/nodes/brush/src/brush.rs index 3ed889d988..a6c09bb6d2 100644 --- a/node-graph/nodes/brush/src/brush.rs +++ b/node-graph/nodes/brush/src/brush.rs @@ -6,7 +6,7 @@ use core_types::color::{Alpha, Color, Pixel, Sample}; use core_types::generic::FnNode; use core_types::math::bbox::{AxisAlignedBbox, Bbox}; use core_types::registry::FutureWrapperNode; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::transform::Transform; use core_types::uuid::NodeId; use core_types::value::ClonedNode; @@ -202,9 +202,9 @@ async fn brush( background.push(Item::default()); } // TODO: Find a way to handle more than one item - let table_row = background.clone_row(0).expect("Expected the one item we just pushed"); + let table_row = background.clone_item(0).expect("Expected the one item we just pushed"); - let bounds = Table::new_from_row(table_row.clone()).bounding_box(DAffine2::IDENTITY, false); + let bounds = Table::new_from_item(table_row.clone()).bounding_box(DAffine2::IDENTITY, false); let [start, end] = if let RenderBoundingBox::Rectangle(rect) = bounds { rect } else { [DVec2::ZERO, DVec2::ZERO] }; let background_bbox = AxisAlignedBbox { start, end }; let stroke_bbox = trace.iter_element_values().map(|s| s.bounding_box()).reduce(|a, b| a.union(&b)).unwrap_or(AxisAlignedBbox::ZERO); @@ -224,7 +224,7 @@ async fn brush( let mut brush_plan = cache.compute_brush_plan(table_row, &draw_strokes); // TODO: Find a way to handle more than one item - let Some(mut actual_image) = extend_image_to_bounds((), Table::new_from_row(brush_plan.background), background_bounds).into_iter().next() else { + let Some(mut actual_image) = extend_image_to_bounds((), Table::new_from_item(brush_plan.background), background_bounds).into_iter().next() else { return Table::new(); }; @@ -263,7 +263,7 @@ async fn brush( ); let blit_target = if idx == 0 { let target = core::mem::take(&mut brush_plan.first_stroke_texture); - extend_image_to_bounds((), Table::new_from_row(target), stroke_to_layer) + extend_image_to_bounds((), Table::new_from_item(target), stroke_to_layer) } else { empty_image((), stroke_to_layer, Table::new_from_element(Color::TRANSPARENT)) // EmptyImageNode::new(CopiedNode::new(stroke_to_layer), CopiedNode::new(Color::TRANSPARENT)).eval(()) @@ -311,7 +311,7 @@ async fn brush( FutureWrapperNode::new(ClonedNode::new(positions)), FutureWrapperNode::new(ClonedNode::new(blend_params)), ); - erase_restore_mask = blit_node.eval(Table::new_from_row(erase_restore_mask)).await.into_iter().next().unwrap_or_default(); + erase_restore_mask = blit_node.eval(Table::new_from_item(erase_restore_mask)).await.into_iter().next().unwrap_or_default(); } let blend_params = FnNode::new(|(a, b)| blend_colors(a, b, BlendMode::MultiplyAlpha, 1.)); diff --git a/node-graph/nodes/graphic/src/artboard.rs b/node-graph/nodes/graphic/src/artboard.rs index 2a01d0b538..ffd64b8c80 100644 --- a/node-graph/nodes/graphic/src/artboard.rs +++ b/node-graph/nodes/graphic/src/artboard.rs @@ -49,7 +49,7 @@ pub async fn create_artboard( let background = background.element(0).copied().unwrap_or(Color::WHITE); // Name is not stored here, it's resolved live from the parent layer's display name - Table::new_from_row( + Table::new_from_item( Item::new_from_element(Artboard::new(content)) .with_attribute(ATTR_LOCATION, normalized_location) .with_attribute(ATTR_DIMENSIONS, normalized_dimensions) diff --git a/node-graph/nodes/graphic/src/graphic.rs b/node-graph/nodes/graphic/src/graphic.rs index b15431e8a8..c559f5a282 100644 --- a/node-graph/nodes/graphic/src/graphic.rs +++ b/node-graph/nodes/graphic/src/graphic.rs @@ -131,7 +131,7 @@ async fn map( for (i, row) in content.into_iter().enumerate() { let owned_ctx = OwnedContextImpl::from(ctx.clone()); - let owned_ctx = owned_ctx.with_vararg(Box::new(Table::new_from_row(row))).with_index(i); + let owned_ctx = owned_ctx.with_vararg(Box::new(Table::new_from_item(row))).with_index(i); let table = mapped.eval(owned_ctx.into_context()).await; rows.extend(table); @@ -250,8 +250,8 @@ async fn write_attribute( value: impl Node<'n, Context<'static>, Output = AttributeValueDyn>, ) -> Table { for index in 0..content.len() { - let row = content.clone_row(index).expect("index is within bounds"); - let owned_ctx = OwnedContextImpl::from(ctx.clone()).with_vararg(Box::new(Table::new_from_row(row))).with_index(index); + let row = content.clone_item(index).expect("index is within bounds"); + let owned_ctx = OwnedContextImpl::from(ctx.clone()).with_vararg(Box::new(Table::new_from_item(row))).with_index(index); let v = value.eval(owned_ctx.into_context()).await; content.set_attribute_value_dyn(&name, index, v); } @@ -597,7 +597,7 @@ pub async fn flatten_graphic(_: impl Ctx, content: Table, fully_flatten } // Push any leaf elements we encounter: either `Graphic::Graphic(...)` values beyond the recursion depth, or non-`Graphic::Graphic` variants (e.g. `Graphic::Vector`, `Graphic::Raster*`, `Graphic::Color`, `Graphic::Gradient`) _ => { - let attributes = current_graphic_table.clone_row_attributes(index); + let attributes = current_graphic_table.clone_item_attributes(index); output_graphic_table.push(Item::from_parts(current_element, attributes)); } } diff --git a/node-graph/nodes/gstd/src/platform_application_io.rs b/node-graph/nodes/gstd/src/platform_application_io.rs index 6b6fb6d2d7..eaed6e3056 100644 --- a/node-graph/nodes/gstd/src/platform_application_io.rs +++ b/node-graph/nodes/gstd/src/platform_application_io.rs @@ -4,7 +4,7 @@ use base64::Engine; use canvas_utils::{Canvas, CanvasHandle}; #[cfg(target_family = "wasm")] use core_types::math::bbox::Bbox; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; #[cfg(target_family = "wasm")] use core_types::transform::Footprint; #[cfg(target_family = "wasm")] @@ -235,7 +235,7 @@ where let rasterized = context.get_image_data(0., 0., resolution.x as f64, resolution.y as f64).unwrap(); let image = Image::from_image_data(&rasterized.data().0, resolution.x as u32, resolution.y as u32); - Table::new_from_row( + Table::new_from_item( Item::new_from_element(Raster::new_cpu(image)) .with_attribute(ATTR_TRANSFORM, footprint.transform) .with_attribute(ATTR_EDITOR_MERGED_LAYERS, upstream_graphic_table), diff --git a/node-graph/nodes/path-bool/src/lib.rs b/node-graph/nodes/path-bool/src/lib.rs index dd1d5a11c0..2f06df0955 100644 --- a/node-graph/nodes/path-bool/src/lib.rs +++ b/node-graph/nodes/path-bool/src/lib.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::uuid::NodeId; use core_types::{ATTR_BLEND_MODE, ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_EDITOR_MERGED_LAYERS, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, BlendMode, Color, Ctx}; use glam::{DAffine2, DVec2}; @@ -124,7 +124,7 @@ fn boolean_operation_on_vector_table(vector: &Table, boolean_operation: if !vector.is_empty() { Some(vector.len() - 1) } else { None } }; let mut row = if let Some(index) = copy_from_index { - let mut attributes = vector.clone_row_attributes(index); + let mut attributes = vector.clone_item_attributes(index); // The boolean op bakes input transforms into the output geometry, so the result item carries no transform of its own attributes.insert(ATTR_TRANSFORM, DAffine2::IDENTITY); let copy_from = vector.element(index).unwrap(); diff --git a/node-graph/nodes/raster/src/std_nodes.rs b/node-graph/nodes/raster/src/std_nodes.rs index 567684e2cf..0b063ea362 100644 --- a/node-graph/nodes/raster/src/std_nodes.rs +++ b/node-graph/nodes/raster/src/std_nodes.rs @@ -392,7 +392,7 @@ pub fn noise_pattern( } } - return Table::new_from_row(Item::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)); + return Table::new_from_item(Item::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)); } }; noise.set_noise_type(Some(noise_type)); @@ -450,7 +450,7 @@ pub fn noise_pattern( } } - Table::new_from_row(Item::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)) + Table::new_from_item(Item::new_from_element(Raster::new_cpu(image)).with_attribute(ATTR_TRANSFORM, transform)) } #[node_macro::node(category("Raster: Pattern"))] @@ -488,7 +488,7 @@ pub fn mandelbrot(ctx: impl ExtractFootprint + Send) -> Table> { } } - Table::new_from_row( + Table::new_from_item( Item::new_from_element(Raster::new_cpu(Image { width, height, diff --git a/node-graph/nodes/repeat/src/repeat_nodes.rs b/node-graph/nodes/repeat/src/repeat_nodes.rs index e4d94bbf8c..aadeb6715b 100644 --- a/node-graph/nodes/repeat/src/repeat_nodes.rs +++ b/node-graph/nodes/repeat/src/repeat_nodes.rs @@ -78,7 +78,7 @@ pub async fn repeat_array + Default + Send + Clone + 'static>( let generated_content = content.eval(new_ctx.into_context()).await; for row_index in 0..generated_content.len() { - let Some(mut row) = generated_content.clone_row(row_index) else { continue }; + let Some(mut row) = generated_content.clone_item(row_index) else { continue }; let local_transform: DAffine2 = row.attribute_cloned_or_default(ATTR_TRANSFORM); let local_translation = DAffine2::from_translation(local_transform.translation); @@ -124,7 +124,7 @@ async fn repeat_radial + Default + Send + Clone + 'static>( let generated_content = content.eval(new_ctx.into_context()).await; for row_index in 0..generated_content.len() { - let Some(mut row) = generated_content.clone_row(row_index) else { continue }; + let Some(mut row) = generated_content.clone_item(row_index) else { continue }; let local_transform: DAffine2 = row.attribute_cloned_or_default(ATTR_TRANSFORM); let local_translation = DAffine2::from_translation(local_transform.translation); diff --git a/node-graph/nodes/vector/src/vector_nodes.rs b/node-graph/nodes/vector/src/vector_nodes.rs index 99e959f78e..67ffa9ee6d 100644 --- a/node-graph/nodes/vector/src/vector_nodes.rs +++ b/node-graph/nodes/vector/src/vector_nodes.rs @@ -4,7 +4,7 @@ use core::hash::{Hash, Hasher}; use core_types::blending::BlendMode; use core_types::bounds::{BoundingBox, RenderBoundingBox}; use core_types::registry::types::{Angle, Length, Multiplier, Percentage, PixelLength, Progression, SeedValue}; -use core_types::table::{Table, TableDyn, Item}; +use core_types::table::{Item, Table, TableDyn}; use core_types::transform::{Footprint, Transform}; use core_types::uuid::NodeId; use core_types::{ @@ -321,7 +321,7 @@ async fn copy_to_points( let transform = DAffine2::from_scale_angle_translation(DVec2::splat(scale), rotation, translation); for row_index in 0..content.len() { - let Some(mut row) = content.clone_row(row_index) else { continue }; + let Some(mut row) = content.clone_item(row_index) else { continue }; let row_transform: DAffine2 = row.attribute_cloned_or_default(ATTR_TRANSFORM); row.set_attribute(ATTR_TRANSFORM, transform * row_transform); @@ -356,7 +356,7 @@ async fn round_corners( .map(|index| { let source_transform: DAffine2 = source.attribute_cloned_or_default(ATTR_TRANSFORM, index); let source_transform_inverse = source_transform.inverse(); - let attributes = source.clone_row_attributes(index); + let attributes = source.clone_item_attributes(index); let source = source.element(index).unwrap(); // Flip the roundness to help with user intuition @@ -803,7 +803,7 @@ where .into_iter() .map(|row| { // Single-item `Table` to query its bounding box - let single = Table::new_from_row(row.clone()); + let single = Table::new_from_item(row.clone()); let (w, h, top_left) = match single.bounding_box(DAffine2::IDENTITY, false) { RenderBoundingBox::Rectangle([min, max]) => { let size = max - min; @@ -902,7 +902,7 @@ async fn auto_tangents( (0..source.len()) .map(|index| { let transform: DAffine2 = source.attribute_cloned_or_default(ATTR_TRANSFORM, index); - let attributes = source.clone_row_attributes(index); + let attributes = source.clone_item_attributes(index); let source = source.element(index).unwrap(); let mut result = Vector { @@ -1083,7 +1083,7 @@ async fn vec2_to_point(_: impl Ctx, vec2: DVec2) -> Table { let mut point_domain = PointDomain::new(); point_domain.push(PointId::generate(), vec2); - Table::new_from_row(Item::new_from_element(Vector { point_domain, ..Default::default() })) + Table::new_from_item(Item::new_from_element(Vector { point_domain, ..Default::default() })) } /// Creates a polyline from a series of vector points, replacing any existing segments and regions that may already exist. @@ -2409,11 +2409,11 @@ async fn morph( let endpoint_index = if time == 0. { source_index } else { target_index }; let endpoint_element = content.element(endpoint_index).unwrap(); - let mut attributes = content.clone_row_attributes(endpoint_index); + let mut attributes = content.clone_item_attributes(endpoint_index); attributes.insert(ATTR_TRANSFORM, lerped_transform); attributes.insert(ATTR_EDITOR_MERGED_LAYERS, graphic_table_content); - return Table::new_from_row(Item::from_parts(endpoint_element.clone(), attributes)); + return Table::new_from_item(Item::from_parts(endpoint_element.clone(), attributes)); } let mut vector = Vector { @@ -2569,7 +2569,7 @@ async fn morph( let primary_index = if time < 0.5 { source_index } else { target_index }; let layer_path: Table = content.attribute_cloned_or_default(ATTR_EDITOR_LAYER_PATH, primary_index); - Table::new_from_row( + Table::new_from_item( Item::new_from_element(vector) .with_attribute(ATTR_TRANSFORM, lerped_transform) .with_attribute(ATTR_BLEND_MODE, lerped_blend_mode) @@ -3046,7 +3046,7 @@ mod test { Table::new_from_element(Vector::from_bezpath(bezpath)) } - fn create_vector_row(bezpath: BezPath, transform: DAffine2) -> Item { + fn create_vector_item(bezpath: BezPath, transform: DAffine2) -> Item { let mut row = Vector::default(); row.append_bezpath(bezpath); Item::new_from_element(row).with_attribute(ATTR_TRANSFORM, transform) @@ -3155,7 +3155,7 @@ mod test { async fn path_length() { let bezpath = Rect::new(100., 100., 201., 201.).to_path(DEFAULT_ACCURACY); let transform = DAffine2::from_scale(DVec2::new(2., 2.)); - let row = create_vector_row(bezpath, transform); + let row = create_vector_item(bezpath, transform); let table = (0..5).map(|_| row.clone()).collect::>(); let length = super::path_length(Footprint::default(), table).await; @@ -3173,7 +3173,7 @@ mod test { #[tokio::test] async fn morph() { let mut rectangles = vector_node_from_bezpath(Rect::new(0., 0., 100., 100.).to_path(DEFAULT_ACCURACY)); - let mut second_rectangle = rectangles.clone_row(0).unwrap(); + let mut second_rectangle = rectangles.clone_item(0).unwrap(); *second_rectangle.attribute_mut_or_insert_default::(ATTR_TRANSFORM) *= DAffine2::from_translation((-100., -100.).into()); rectangles.push(second_rectangle); From 663bb82b6fb859e5faebf61a89ce595324611af6 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Fri, 8 May 2026 22:58:16 -0700 Subject: [PATCH 4/4] Format --- node-graph/libraries/rendering/src/renderer.rs | 2 +- .../libraries/wgpu-executor/src/texture_conversion.rs | 2 +- node-graph/nodes/raster/src/image_color_palette.rs | 2 +- node-graph/nodes/raster/src/std_nodes.rs | 2 +- node-graph/nodes/text/src/json.rs | 7 ++----- node-graph/nodes/text/src/path_builder.rs | 2 +- node-graph/nodes/text/src/regex.rs | 2 +- 7 files changed, 8 insertions(+), 11 deletions(-) diff --git a/node-graph/libraries/rendering/src/renderer.rs b/node-graph/libraries/rendering/src/renderer.rs index 259fc39573..35c7ee3ba0 100644 --- a/node-graph/libraries/rendering/src/renderer.rs +++ b/node-graph/libraries/rendering/src/renderer.rs @@ -7,7 +7,7 @@ use core_types::bounds::RenderBoundingBox; use core_types::color::Color; use core_types::math::quad::Quad; use core_types::render_complexity::RenderComplexity; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::transform::Footprint; use core_types::uuid::{NodeId, generate_uuid}; use core_types::{ diff --git a/node-graph/libraries/wgpu-executor/src/texture_conversion.rs b/node-graph/libraries/wgpu-executor/src/texture_conversion.rs index 0eba467fac..058f46859c 100644 --- a/node-graph/libraries/wgpu-executor/src/texture_conversion.rs +++ b/node-graph/libraries/wgpu-executor/src/texture_conversion.rs @@ -3,7 +3,7 @@ use core_types::Color; use core_types::Ctx; use core_types::color::SRGBA8; use core_types::ops::Convert; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::transform::Footprint; use raster_types::Image; use raster_types::{CPU, GPU, Raster}; diff --git a/node-graph/nodes/raster/src/image_color_palette.rs b/node-graph/nodes/raster/src/image_color_palette.rs index c8c90e8354..f4f91e9147 100644 --- a/node-graph/nodes/raster/src/image_color_palette.rs +++ b/node-graph/nodes/raster/src/image_color_palette.rs @@ -1,6 +1,6 @@ use core_types::color::Color; use core_types::context::Ctx; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use raster_types::{CPU, Raster}; #[node_macro::node(category("Color"))] diff --git a/node-graph/nodes/raster/src/std_nodes.rs b/node-graph/nodes/raster/src/std_nodes.rs index 0b063ea362..5b79e34df2 100644 --- a/node-graph/nodes/raster/src/std_nodes.rs +++ b/node-graph/nodes/raster/src/std_nodes.rs @@ -4,7 +4,7 @@ use core_types::color::Color; use core_types::color::{Alpha, AlphaMut, Channel, LinearChannel, Luminance, RGBMut}; use core_types::context::{Ctx, ExtractFootprint}; use core_types::math::bbox::Bbox; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::transform::Transform; use dyn_any::DynAny; use fastnoise_lite; diff --git a/node-graph/nodes/text/src/json.rs b/node-graph/nodes/text/src/json.rs index a8ea779ad7..6eb4f0af92 100644 --- a/node-graph/nodes/text/src/json.rs +++ b/node-graph/nodes/text/src/json.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::{ATTR_TYPE, Ctx}; use serde_json::Value; @@ -248,10 +248,7 @@ fn query_json_all( let mut results = Vec::new(); resolve_all(&value, &segments, !unquote_strings, &mut results); - results - .into_iter() - .map(|(text, ty)| Item::new_from_element(text).with_attribute(ATTR_TYPE, ty.to_string())) - .collect() + results.into_iter().map(|(text, ty)| Item::new_from_element(text).with_attribute(ATTR_TYPE, ty.to_string())).collect() } /// A parsed segment of a JSON access path. diff --git a/node-graph/nodes/text/src/path_builder.rs b/node-graph/nodes/text/src/path_builder.rs index 385b9eafe6..15a5a02232 100644 --- a/node-graph/nodes/text/src/path_builder.rs +++ b/node-graph/nodes/text/src/path_builder.rs @@ -1,4 +1,4 @@ -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::{ATTR_EDITOR_CLICK_TARGET, ATTR_EDITOR_TEXT_FRAME, ATTR_TRANSFORM}; use glam::{DAffine2, DVec2}; use parley::GlyphRun; diff --git a/node-graph/nodes/text/src/regex.rs b/node-graph/nodes/text/src/regex.rs index 9c74771aeb..ddc3d186cb 100644 --- a/node-graph/nodes/text/src/regex.rs +++ b/node-graph/nodes/text/src/regex.rs @@ -1,5 +1,5 @@ use core_types::registry::types::SignedInteger; -use core_types::table::{Table, Item}; +use core_types::table::{Item, Table}; use core_types::{ATTR_END, ATTR_NAME, ATTR_START, Ctx}; /// Checks whether the string contains a match for the given regular expression pattern. Optionally restricts the match to only the start and/or end of the string.