mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Rename the "Table" type to "List" everywhere (#4133)
* Rename the "Table" type to "List" everywhere * Fix a few missed ones * Re-save demo artwork
This commit is contained in:
@@ -8,9 +8,9 @@ use glam::{Affine2, DAffine2, Vec2};
|
||||
use graph_craft::document::NodeId;
|
||||
use graphene_std::blending::BlendMode;
|
||||
use graphene_std::gradient::GradientStops;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::memo::IORecord;
|
||||
use graphene_std::raster_types::{CPU, GPU, Raster};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::vector::Vector;
|
||||
use graphene_std::vector::style::{Fill, FillChoice, GradientSpreadMethod, GradientType};
|
||||
use graphene_std::{Artboard, Color, Context, Graphic};
|
||||
@@ -155,7 +155,7 @@ struct LayoutData<'a> {
|
||||
desired_path: &'a mut Vec<PathStep>,
|
||||
network_interface: &'a NodeNetworkInterface,
|
||||
/// The `network_path` to use when resolving a `NodeId` against the network interface.
|
||||
/// Defaults to root (`&[]`); `Table<NodeId>` rendering temporarily sets it to the path's prefix so nested
|
||||
/// Defaults to root (`&[]`); `List<NodeId>` rendering temporarily sets it to the path's prefix so nested
|
||||
/// layers (e.g. inside a Ctrl+M-merged custom subgraph) resolve correctly.
|
||||
node_lookup_network_path: Vec<NodeId>,
|
||||
breadcrumbs: Vec<String>,
|
||||
@@ -175,27 +175,27 @@ macro_rules! generate_layout_downcast {
|
||||
}
|
||||
// TODO: We simply try all these types sequentially. Find a better strategy.
|
||||
fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'static>, data: &mut LayoutData) -> Option<Vec<LayoutGroup>> {
|
||||
// `Table<NodeId>` is interpreted as a path (e.g. the value produced by `path_of_subgraph`), shown as a
|
||||
// `Table` where each item's NodeId resolves against the prefix made up of the items above it.
|
||||
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<NodeId>>>() {
|
||||
// `List<NodeId>` is interpreted as a path (e.g. the value produced by `path_of_subgraph`), shown as a
|
||||
// `List` where each item's NodeId resolves against the prefix made up of the items above it.
|
||||
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<NodeId>>>() {
|
||||
return Some(table_node_id_path_layout_with_breadcrumb(&io.output, data));
|
||||
}
|
||||
generate_layout_downcast!(introspected_data, data, [
|
||||
Table<Artboard>,
|
||||
Table<Graphic>,
|
||||
Table<Vector>,
|
||||
Table<Raster<CPU>>,
|
||||
Table<Raster<GPU>>,
|
||||
Table<Color>,
|
||||
Table<GradientStops>,
|
||||
Table<String>,
|
||||
Table<f64>,
|
||||
Table<u8>,
|
||||
Table<bool>,
|
||||
Table<DAffine2>,
|
||||
Table<BlendMode>,
|
||||
Table<GradientType>,
|
||||
Table<GradientSpreadMethod>,
|
||||
List<Artboard>,
|
||||
List<Graphic>,
|
||||
List<Vector>,
|
||||
List<Raster<CPU>>,
|
||||
List<Raster<GPU>>,
|
||||
List<Color>,
|
||||
List<GradientStops>,
|
||||
List<String>,
|
||||
List<f64>,
|
||||
List<u8>,
|
||||
List<bool>,
|
||||
List<DAffine2>,
|
||||
List<BlendMode>,
|
||||
List<GradientType>,
|
||||
List<GradientSpreadMethod>,
|
||||
GradientStops,
|
||||
f64,
|
||||
u32,
|
||||
@@ -227,7 +227,7 @@ trait TableItemLayout {
|
||||
data.breadcrumbs.push(self.identifier());
|
||||
self.value_page(data)
|
||||
}
|
||||
/// Renders this value as a single inline widget inside an item of a Table.
|
||||
/// Renders this value as a single inline widget inside an item of a `List`.
|
||||
/// `target` is the [`PathStep`] to push when the widget is clicked to drill into the value.
|
||||
/// `data` provides shared context (notably `network_interface`) for types whose label or content
|
||||
/// depends on lookup beyond their own value (e.g. `NodeId` resolving a node's display name).
|
||||
@@ -245,9 +245,9 @@ trait TableItemLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TableItemLayout> TableItemLayout for Table<T> {
|
||||
impl<T: TableItemLayout> TableItemLayout for List<T> {
|
||||
fn type_name() -> &'static str {
|
||||
"Table"
|
||||
"List"
|
||||
}
|
||||
fn identifier(&self) -> String {
|
||||
format!("{}[] ({} item{})", T::type_name(), self.len(), if self.len() == 1 { "" } else { "s" })
|
||||
@@ -312,14 +312,14 @@ impl TableItemLayout for Artboard {
|
||||
"Artboard"
|
||||
}
|
||||
fn identifier(&self) -> String {
|
||||
self.as_graphic_table().identifier()
|
||||
self.as_graphic_list().identifier()
|
||||
}
|
||||
// Don't put a breadcrumb for Artboard
|
||||
fn layout_with_breadcrumb(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||
self.value_page(data)
|
||||
}
|
||||
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||
self.as_graphic_table().layout_with_breadcrumb(data)
|
||||
self.as_graphic_list().layout_with_breadcrumb(data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,12 +329,12 @@ impl TableItemLayout for Graphic {
|
||||
}
|
||||
fn identifier(&self) -> String {
|
||||
match self {
|
||||
Self::Graphic(table) => table.identifier(),
|
||||
Self::Vector(table) => table.identifier(),
|
||||
Self::RasterCPU(table) => table.identifier(),
|
||||
Self::RasterGPU(table) => table.identifier(),
|
||||
Self::Color(table) => table.identifier(),
|
||||
Self::Gradient(table) => table.identifier(),
|
||||
Self::Graphic(list) => list.identifier(),
|
||||
Self::Vector(list) => list.identifier(),
|
||||
Self::RasterCPU(list) => list.identifier(),
|
||||
Self::RasterGPU(list) => list.identifier(),
|
||||
Self::Color(list) => list.identifier(),
|
||||
Self::Gradient(list) => list.identifier(),
|
||||
}
|
||||
}
|
||||
// Don't put a breadcrumb for Graphic
|
||||
@@ -343,12 +343,12 @@ impl TableItemLayout for Graphic {
|
||||
}
|
||||
fn value_page(&self, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||
match self {
|
||||
Self::Graphic(table) => table.layout_with_breadcrumb(data),
|
||||
Self::Vector(table) => table.layout_with_breadcrumb(data),
|
||||
Self::RasterCPU(table) => table.layout_with_breadcrumb(data),
|
||||
Self::RasterGPU(table) => table.layout_with_breadcrumb(data),
|
||||
Self::Color(table) => table.layout_with_breadcrumb(data),
|
||||
Self::Gradient(table) => table.layout_with_breadcrumb(data),
|
||||
Self::Graphic(list) => list.layout_with_breadcrumb(data),
|
||||
Self::Vector(list) => list.layout_with_breadcrumb(data),
|
||||
Self::RasterCPU(list) => list.layout_with_breadcrumb(data),
|
||||
Self::RasterGPU(list) => list.layout_with_breadcrumb(data),
|
||||
Self::Color(list) => list.layout_with_breadcrumb(data),
|
||||
Self::Gradient(list) => list.layout_with_breadcrumb(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -834,7 +834,7 @@ impl TableItemLayout for NodeId {
|
||||
}
|
||||
// The value's label resolves the node's display name via the network interface so the button reads as the name shown
|
||||
// in the Node Graph / Layers panels. The lookup uses `data.node_lookup_network_path` (set by the enclosing
|
||||
// `Table<NodeId>` if rendering a path) so the resolution succeeds at any nesting depth. The button's icon
|
||||
// `List<NodeId>` if rendering a path) so the resolution succeeds at any nesting depth. The button's icon
|
||||
// signals layer-vs-node kind. Falls back to "Node {id}" with no icon if the lookup misses.
|
||||
fn value_widget(&self, target: PathStep, data: &LayoutData) -> WidgetInstance {
|
||||
let label = node_id_display_label(*self, data.network_interface, &data.node_lookup_network_path);
|
||||
@@ -935,20 +935,20 @@ impl TableItemLayout for NodeId {
|
||||
/// 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 {
|
||||
macro_rules! known_item_types {
|
||||
($apply:ident) => {
|
||||
$apply!(
|
||||
Table<Artboard>,
|
||||
Table<Graphic>,
|
||||
Table<Vector>,
|
||||
Table<Raster<CPU>>,
|
||||
Table<Raster<GPU>>,
|
||||
Table<Color>,
|
||||
Table<GradientStops>,
|
||||
Table<String>,
|
||||
Table<NodeId>,
|
||||
Table<f64>,
|
||||
Table<u8>,
|
||||
List<Artboard>,
|
||||
List<Graphic>,
|
||||
List<Vector>,
|
||||
List<Raster<CPU>>,
|
||||
List<Raster<GPU>>,
|
||||
List<Color>,
|
||||
List<GradientStops>,
|
||||
List<String>,
|
||||
List<NodeId>,
|
||||
List<f64>,
|
||||
List<u8>,
|
||||
GradientStops,
|
||||
Color,
|
||||
NodeId,
|
||||
@@ -983,7 +983,7 @@ fn display_value_override(any: &dyn Any) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Type-dispatched widget for displaying an attribute value in a `Table<T>` item.
|
||||
/// Type-dispatched widget for displaying an attribute value in a `List<T>` 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`].
|
||||
@@ -997,16 +997,16 @@ fn dispatch_value_widget(any: &dyn Any, target: PathStep, data: &LayoutData) ->
|
||||
)*
|
||||
};
|
||||
}
|
||||
known_table_row_types!(check);
|
||||
known_item_types!(check);
|
||||
None
|
||||
}
|
||||
|
||||
/// Renders a `Table<NodeId>` as a path: the standard table view, but each item's `NodeId` value is resolved
|
||||
/// Renders a `List<NodeId>` as a path: the standard table view, but each item's `NodeId` value is resolved
|
||||
/// against the network path made up of all preceding items. So for a path `[outer, middle, leaf]`, item 0
|
||||
/// resolves at root, item 1 resolves at `[outer]`, and item 2 resolves at `[outer, middle]` — letting deeply
|
||||
/// nested layers display each step's correct name. Drilling into an item drops into that node's value page
|
||||
/// using the same prefix as `network_path`.
|
||||
fn table_node_id_path_layout_with_breadcrumb(path: &Table<NodeId>, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||
fn table_node_id_path_layout_with_breadcrumb(path: &List<NodeId>, data: &mut LayoutData) -> Vec<LayoutGroup> {
|
||||
data.breadcrumbs.push(path.identifier());
|
||||
|
||||
if let Some(step) = data.desired_path.get(data.current_depth).cloned() {
|
||||
@@ -1044,9 +1044,9 @@ fn table_node_id_path_layout_with_breadcrumb(path: &Table<NodeId>, data: &mut La
|
||||
/// 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<Vec<LayoutGroup>> {
|
||||
// `Table<NodeId>` is interpreted as a path (e.g. the `editor:layer_path` attribute), so each item's NodeId value
|
||||
// resolves against the prefix made up of preceding items. Handled before the generic `Table<T>` blanket impl.
|
||||
if let Some(path) = any.downcast_ref::<Table<NodeId>>() {
|
||||
// `List<NodeId>` is interpreted as a path (e.g. the `editor:layer_path` attribute), so each item's NodeId value
|
||||
// resolves against the prefix made up of preceding items. Handled before the generic `List<T>` blanket impl.
|
||||
if let Some(path) = any.downcast_ref::<List<NodeId>>() {
|
||||
return Some(table_node_id_path_layout_with_breadcrumb(path, data));
|
||||
}
|
||||
macro_rules! check {
|
||||
@@ -1058,7 +1058,7 @@ fn drilldown_attribute_layout(any: &dyn Any, data: &mut LayoutData) -> Option<Ve
|
||||
)*
|
||||
};
|
||||
}
|
||||
known_table_row_types!(check);
|
||||
known_item_types!(check);
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
@@ -2427,7 +2427,7 @@ impl DocumentMessageHandler {
|
||||
});
|
||||
|
||||
if layer_to_move.parent(self.metadata()) != Some(parent) {
|
||||
// TODO: Fix this so it works when dragging a layer into a group parent which has a Transform node, which used to work before #2689 caused this regression by removing the empty `Table<Vector>` item.
|
||||
// TODO: Fix this so it works when dragging a layer into a group parent which has a Transform node, which used to work before #2689 caused this regression by removing the empty `List<Vector>` item.
|
||||
// TODO: See #2688 for this issue.
|
||||
let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(layer_to_move);
|
||||
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
|
||||
@@ -3345,7 +3345,7 @@ impl DocumentMessageHandler {
|
||||
/// Create a network interface with a single export
|
||||
fn default_document_network_interface() -> NodeNetworkInterface {
|
||||
let mut network_interface = NodeNetworkInterface::default();
|
||||
network_interface.add_export(TaggedValue::TypeDefault(descriptor!(graphene_std::table::Table<graphene_std::Artboard>)), -1, "", &[]);
|
||||
network_interface.add_export(TaggedValue::TypeDefault(descriptor!(graphene_std::list::List<graphene_std::Artboard>)), -1, "", &[]);
|
||||
network_interface
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ use crate::messages::tool::common_functionality::graph_modification_utils::get_c
|
||||
use glam::{DAffine2, DVec2, IVec2};
|
||||
use graph_craft::descriptor;
|
||||
use graph_craft::document::{NodeId, NodeInput};
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::renderer::Quad;
|
||||
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::{Font, TypesettingConfig};
|
||||
use graphene_std::vector::style::{Fill, Gradient, GradientSpreadMethod, GradientStop, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||
use graphene_std::{Artboard, Color};
|
||||
@@ -170,7 +170,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
|
||||
}
|
||||
|
||||
// Set the bottom input of the artboard back to artboard
|
||||
let bottom_input = NodeInput::type_default(descriptor!(Table<Artboard>), true);
|
||||
let bottom_input = NodeInput::type_default(descriptor!(List<Artboard>), true);
|
||||
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 0), bottom_input, &[]);
|
||||
} else {
|
||||
// We have some non layers (e.g. just a rectangle node). We disconnect the bottom input and connect it to the left input.
|
||||
@@ -178,7 +178,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
|
||||
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 1), primary_input, &[]);
|
||||
|
||||
// Set the bottom input of the artboard back to artboard
|
||||
let bottom_input = NodeInput::type_default(descriptor!(Table<Artboard>), true);
|
||||
let bottom_input = NodeInput::type_default(descriptor!(List<Artboard>), true);
|
||||
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 0), bottom_input, &[]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{NodeId, NodeInput};
|
||||
use graph_craft::{ProtoNodeIdentifier, concrete, descriptor};
|
||||
use graphene_std::brush::brush_stroke::BrushStroke;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::raster::BlendMode;
|
||||
use graphene_std::raster_types::Image;
|
||||
use graphene_std::subpath::Subpath;
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::{Font, TypesettingConfig};
|
||||
use graphene_std::vector::style::{Fill, GradientSpreadMethod, GradientType, Stroke};
|
||||
use graphene_std::vector::{GradientStops, PointId, Vector, VectorModification, VectorModificationType};
|
||||
@@ -132,8 +132,8 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
/// Creates an artboard as the primary export for the document network.
|
||||
pub fn create_artboard(&mut self, new_id: NodeId, location: DVec2, dimensions: DVec2, background: Color, clip: bool) -> LayerNodeIdentifier {
|
||||
let artboard_node_template = resolve_network_node_type("Artboard").expect("Node").node_template_input_override([
|
||||
Some(NodeInput::type_default(descriptor!(Table<Artboard>), true)),
|
||||
Some(NodeInput::type_default(descriptor!(Table<Graphic>), true)),
|
||||
Some(NodeInput::type_default(descriptor!(List<Artboard>), true)),
|
||||
Some(NodeInput::type_default(descriptor!(List<Graphic>), true)),
|
||||
Some(NodeInput::value(TaggedValue::DVec2(location), false)),
|
||||
Some(NodeInput::value(TaggedValue::DVec2(dimensions), false)),
|
||||
Some(NodeInput::value(TaggedValue::Color(Some(background)), false)),
|
||||
@@ -147,7 +147,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
let boolean = resolve_proto_node_type(graphene_std::path_bool_nodes::boolean_operation::IDENTIFIER)
|
||||
.expect("Boolean node does not exist")
|
||||
.node_template_input_override([
|
||||
Some(NodeInput::type_default(descriptor!(Table<Graphic>), true)),
|
||||
Some(NodeInput::type_default(descriptor!(List<Graphic>), true)),
|
||||
Some(NodeInput::value(TaggedValue::BooleanOperation(operation), false)),
|
||||
]);
|
||||
|
||||
@@ -159,7 +159,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
pub fn insert_blend_data(&mut self, layer: LayerNodeIdentifier, count: f64) -> NodeId {
|
||||
let blend = resolve_network_node_type("Blend")
|
||||
.expect("Blend node does not exist")
|
||||
.node_template_input_override([Some(NodeInput::type_default(descriptor!(Table<Graphic>), true)), Some(NodeInput::value(TaggedValue::F64(count), false))]);
|
||||
.node_template_input_override([Some(NodeInput::type_default(descriptor!(List<Graphic>), true)), Some(NodeInput::value(TaggedValue::F64(count), false))]);
|
||||
|
||||
let blend_id = NodeId::new();
|
||||
self.network_interface.insert_node(blend_id, blend, &[]);
|
||||
@@ -171,7 +171,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
pub fn insert_morph_data(&mut self, layer: LayerNodeIdentifier) -> NodeId {
|
||||
let morph = resolve_proto_node_type(graphene_std::vector::morph::IDENTIFIER)
|
||||
.expect("Morph node does not exist")
|
||||
.node_template_input_override([Some(NodeInput::type_default(descriptor!(Table<Graphic>), true)), Some(NodeInput::value(TaggedValue::F64(0.5), false))]);
|
||||
.node_template_input_override([Some(NodeInput::type_default(descriptor!(List<Graphic>), true)), Some(NodeInput::value(TaggedValue::F64(0.5), false))]);
|
||||
|
||||
let morph_id = NodeId::new();
|
||||
self.network_interface.insert_node(morph_id, morph, &[]);
|
||||
@@ -390,10 +390,10 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
};
|
||||
|
||||
// If inserting a 'Path' node, insert a 'Flatten Path' node if the type is `Graphic`.
|
||||
// TODO: Allow the 'Path' node to operate on `Table` data by utilizing the reference (index or ID?) for each item.
|
||||
// TODO: Allow the 'Path' node to operate on `List` data by utilizing the reference (index or ID?) for each item.
|
||||
if node_definition.identifier == "Path" {
|
||||
let layer_input_type = self.network_interface.input_type(&InputConnector::node(output_layer.to_node(), 1), &[]);
|
||||
if layer_input_type.compiled_nested_type() == Some(&concrete!(Table<Graphic>)) {
|
||||
if layer_input_type.compiled_nested_type() == Some(&concrete!(List<Graphic>)) {
|
||||
let Some(flatten_path_definition) = resolve_proto_node_type(graphene_std::vector_nodes::flatten_path::IDENTIFIER) else {
|
||||
log::error!("Flatten Path does not exist in ModifyInputsContext::existing_node_id");
|
||||
return None;
|
||||
@@ -489,7 +489,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Set the stops table on the 'Gradient Value' node, creating it if necessary.
|
||||
/// Set the GradientStops list on the 'Gradient Value' node, creating it if necessary.
|
||||
pub fn gradient_stops_set(&mut self, stops: GradientStops) {
|
||||
let Some(gradient_node_id) = self.existing_proto_node_id(graphene_std::math_nodes::gradient_value::IDENTIFIER, true) else {
|
||||
return;
|
||||
@@ -612,7 +612,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64(stroke.join_miter_limit), false), false);
|
||||
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::PaintOrderInput::INDEX);
|
||||
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::PaintOrder(stroke.paint_order), false), false);
|
||||
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::DashLengthsInput::<graphene_std::table::Table<f64>>::INDEX);
|
||||
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::DashLengthsInput::<graphene_std::list::List<f64>>::INDEX);
|
||||
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64Array(stroke.dash_lengths), false), true);
|
||||
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::DashOffsetInput::INDEX);
|
||||
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64(stroke.dash_offset), false), true);
|
||||
|
||||
@@ -17,9 +17,9 @@ use graph_craft::document::value::*;
|
||||
use graph_craft::document::*;
|
||||
use graph_craft::{concrete, descriptor};
|
||||
use graphene_std::extract_xy::XY;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::raster::{CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, NoiseType, RedGreenBlueAlpha};
|
||||
use graphene_std::raster_types::{CPU, Raster};
|
||||
use graphene_std::table::Table;
|
||||
#[allow(unused_imports)]
|
||||
use graphene_std::transform::Footprint;
|
||||
use graphene_std::vector::Vector;
|
||||
@@ -205,7 +205,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![NodeInput::type_default(descriptor!(Table<Graphic>), true), NodeInput::type_default(descriptor!(Table<Graphic>), true)],
|
||||
inputs: vec![NodeInput::type_default(descriptor!(List<Graphic>), true), NodeInput::type_default(descriptor!(List<Graphic>), true)],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
@@ -325,7 +325,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::import(graphene_std::Type::Fn(Box::new(concrete!(Context)), Box::new(concrete!(Table<Artboard>))), 0),
|
||||
NodeInput::import(graphene_std::Type::Fn(Box::new(concrete!(Context)), Box::new(concrete!(List<Artboard>))), 0),
|
||||
NodeInput::node(NodeId(3), 0),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::extend::IDENTIFIER),
|
||||
@@ -339,8 +339,8 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
NodeInput::type_default(descriptor!(Table<Artboard>), true),
|
||||
NodeInput::type_default(descriptor!(Table<Graphic>), true),
|
||||
NodeInput::type_default(descriptor!(List<Artboard>), true),
|
||||
NodeInput::type_default(descriptor!(List<Graphic>), true),
|
||||
NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false),
|
||||
NodeInput::value(TaggedValue::DVec2(DVec2::new(1920., 1080.)), false),
|
||||
NodeInput::value(TaggedValue::Color(Some(Color::WHITE)), false),
|
||||
@@ -573,11 +573,11 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
NodeInput::type_default(descriptor!(Table<Vector>), true),
|
||||
NodeInput::type_default(descriptor!(List<Vector>), true),
|
||||
NodeInput::value(TaggedValue::F64(10.), false),
|
||||
NodeInput::value(TaggedValue::Bool(Default::default()), false),
|
||||
NodeInput::value(TaggedValue::InterpolationDistribution(Default::default()), false),
|
||||
NodeInput::type_default(descriptor!(Table<Vector>), false),
|
||||
NodeInput::type_default(descriptor!(List<Vector>), false),
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
@@ -824,7 +824,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![NodeInput::type_default(descriptor!(Table<Vector>), true)],
|
||||
inputs: vec![NodeInput::type_default(descriptor!(List<Vector>), true)],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
@@ -1009,7 +1009,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
NodeInput::type_default(descriptor!(Table<Vector>), true),
|
||||
NodeInput::type_default(descriptor!(List<Vector>), true),
|
||||
NodeInput::value(
|
||||
TaggedValue::Footprint(Footprint {
|
||||
transform: DAffine2::from_scale_angle_translation(DVec2::new(1000., 1000.), 0., DVec2::new(0., 0.)),
|
||||
@@ -1079,7 +1079,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::import(concrete!(Table<Raster<CPU>>), 0),
|
||||
NodeInput::import(concrete!(List<Raster<CPU>>), 0),
|
||||
NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Red), false),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(raster_nodes::adjustments::extract_channel::IDENTIFIER),
|
||||
@@ -1088,7 +1088,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::import(concrete!(Table<Raster<CPU>>), 0),
|
||||
NodeInput::import(concrete!(List<Raster<CPU>>), 0),
|
||||
NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Green), false),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(raster_nodes::adjustments::extract_channel::IDENTIFIER),
|
||||
@@ -1097,7 +1097,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::import(concrete!(Table<Raster<CPU>>), 0),
|
||||
NodeInput::import(concrete!(List<Raster<CPU>>), 0),
|
||||
NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Blue), false),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(raster_nodes::adjustments::extract_channel::IDENTIFIER),
|
||||
@@ -1106,7 +1106,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::import(concrete!(Table<Raster<CPU>>), 0),
|
||||
NodeInput::import(concrete!(List<Raster<CPU>>), 0),
|
||||
NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Alpha), false),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(raster_nodes::adjustments::extract_channel::IDENTIFIER),
|
||||
@@ -1120,7 +1120,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![NodeInput::type_default(descriptor!(Table<Raster<CPU>>), true)],
|
||||
inputs: vec![NodeInput::type_default(descriptor!(List<Raster<CPU>>), true)],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
@@ -1257,7 +1257,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::import(concrete!(Table<Raster<CPU>>), 0), NodeInput::node(NodeId(0), 0)],
|
||||
inputs: vec![NodeInput::import(concrete!(List<Raster<CPU>>), 0), NodeInput::node(NodeId(0), 0)],
|
||||
call_argument: generic!(T),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(wgpu_executor::texture_conversion::upload_texture::IDENTIFIER),
|
||||
..Default::default()
|
||||
@@ -1275,7 +1275,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![NodeInput::type_default(descriptor!(Table<Raster<CPU>>), true)],
|
||||
inputs: vec![NodeInput::type_default(descriptor!(List<Raster<CPU>>), true)],
|
||||
..Default::default()
|
||||
},
|
||||
persistent_node_metadata: DocumentNodePersistentMetadata {
|
||||
@@ -1346,11 +1346,11 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
exports: vec![
|
||||
// Primary output: the whole match (String)
|
||||
NodeInput::node(NodeId(1), 0),
|
||||
// Secondary output: capture groups (Table<String>), each item carries `start`/`end`/`name` attributes from `regex_find`
|
||||
// Secondary output: capture groups (List<String>), each item carries `start`/`end`/`name` attributes from `regex_find`
|
||||
NodeInput::node(NodeId(2), 0),
|
||||
],
|
||||
nodes: [
|
||||
// Node 0: regex_find proto node — returns Table<String> of [whole_match, ...capture_groups]
|
||||
// Node 0: regex_find proto node — returns List<String> of [whole_match, ...capture_groups]
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::import(concrete!(String), 0),
|
||||
@@ -1368,7 +1368,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::extract_element::IDENTIFIER),
|
||||
..Default::default()
|
||||
},
|
||||
// Node 2: omit_element at index 0, returns the capture group items as a Table<String>, preserving each item's start/end/name attributes
|
||||
// Node 2: omit_element at index 0, returns the capture group items as a List<String>, preserving each item's start/end/name attributes
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::F64(0.), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(graphic::omit_element::IDENTIFIER),
|
||||
@@ -1453,7 +1453,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
||||
nodes: vec![
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::import(concrete!(Table<Vector>), 0)],
|
||||
inputs: vec![NodeInput::import(concrete!(List<Vector>), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(memo::monitor::IDENTIFIER),
|
||||
call_argument: generic!(T),
|
||||
skip_deduplication: true,
|
||||
@@ -1477,7 +1477,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
NodeInput::type_default(descriptor!(Table<Vector>), true),
|
||||
NodeInput::type_default(descriptor!(List<Vector>), true),
|
||||
NodeInput::value(TaggedValue::VectorModification(Default::default()), false),
|
||||
],
|
||||
..Default::default()
|
||||
|
||||
@@ -19,12 +19,12 @@ use graphene_std::NodeInputDecleration;
|
||||
use graphene_std::animation::RealTimeMode;
|
||||
use graphene_std::brush::brush_stroke::BrushStroke;
|
||||
use graphene_std::extract_xy::XY;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::raster::{
|
||||
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute,
|
||||
SelectiveColorChoice,
|
||||
};
|
||||
use graphene_std::raster_types::Image;
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::{Font, TextAlign};
|
||||
use graphene_std::text_nodes::StringCapitalization;
|
||||
use graphene_std::transform::{Footprint, ReferencePoint, ScaleType, Transform};
|
||||
@@ -212,13 +212,13 @@ pub(crate) fn property_from_type(
|
||||
Some(x) if x == TypeId::of::<String>() => text_widget(default_info).into(),
|
||||
Some(x) if x == TypeId::of::<DVec2>() => vec2_widget(default_info, "X", "Y", "", None, false),
|
||||
Some(x) if x == TypeId::of::<DAffine2>() => transform_widget(default_info, &mut extra_widgets),
|
||||
// ===========
|
||||
// TABLE TYPES
|
||||
// ===========
|
||||
Some(x) if x == TypeId::of::<Table<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
|
||||
Some(x) if x == TypeId::of::<Table<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
||||
Some(x) if x == TypeId::of::<Table<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
||||
Some(x) if x == TypeId::of::<Table<BrushStroke>>() => brush_strokes_widget(default_info).into(),
|
||||
// ==========
|
||||
// LIST TYPES
|
||||
// ==========
|
||||
Some(x) if x == TypeId::of::<List<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
|
||||
Some(x) if x == TypeId::of::<List<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
||||
Some(x) if x == TypeId::of::<List<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
||||
Some(x) if x == TypeId::of::<List<BrushStroke>>() => brush_strokes_widget(default_info).into(),
|
||||
// ============
|
||||
// STRUCT TYPES
|
||||
// ============
|
||||
@@ -2681,7 +2681,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
|
||||
_ => &StrokeJoin::Miter,
|
||||
};
|
||||
|
||||
let has_dash_lengths = match &document_node.inputs[DashLengthsInput::<Table<f64>>::INDEX].as_value() {
|
||||
let has_dash_lengths = match &document_node.inputs[DashLengthsInput::<List<f64>>::INDEX].as_value() {
|
||||
Some(TaggedValue::F64Array(values)) => values.is_empty(),
|
||||
_ => true,
|
||||
};
|
||||
@@ -2709,7 +2709,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
|
||||
.property_row();
|
||||
let disabled_number_input = NumberInput::default().unit(" px").disabled(has_dash_lengths);
|
||||
let dash_lengths = array_of_number_widget(
|
||||
ParameterWidgetsInfo::new(node_id, DashLengthsInput::<Table<f64>>::INDEX, true, context),
|
||||
ParameterWidgetsInfo::new(node_id, DashLengthsInput::<List<f64>>::INDEX, true, context),
|
||||
TextInput::default().centered(true),
|
||||
);
|
||||
let number_input = disabled_number_input;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use graph_craft::document::NodeId;
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graphene_std::Type;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::raster_types::{CPU, Raster};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::vector::Vector;
|
||||
use graphene_std::{Artboard, Graphic};
|
||||
|
||||
@@ -31,11 +31,11 @@ impl FrontendGraphDataType {
|
||||
TaggedValue::String(_) => Self::Typography,
|
||||
// Types whose `TaggedValue` variant has been removed are routed through `TypeDefault` and identified by the descriptor's type name.
|
||||
TaggedValue::TypeDefault(td) => match td.name.as_ref() {
|
||||
n if n == std::any::type_name::<Table<Graphic>>() => Self::Graphic,
|
||||
n if n == std::any::type_name::<Table<Artboard>>() => Self::Artboard,
|
||||
n if n == std::any::type_name::<Table<Raster<CPU>>>() => Self::Raster,
|
||||
n if n == std::any::type_name::<Table<Vector>>() => Self::Vector,
|
||||
n if n == std::any::type_name::<Table<String>>() => Self::Typography,
|
||||
n if n == std::any::type_name::<List<Graphic>>() => Self::Graphic,
|
||||
n if n == std::any::type_name::<List<Artboard>>() => Self::Artboard,
|
||||
n if n == std::any::type_name::<List<Raster<CPU>>>() => Self::Raster,
|
||||
n if n == std::any::type_name::<List<Vector>>() => Self::Vector,
|
||||
n if n == std::any::type_name::<List<String>>() => Self::Typography,
|
||||
_ => Self::General,
|
||||
},
|
||||
_ => Self::General,
|
||||
|
||||
@@ -11,9 +11,9 @@ use core::borrow::Borrow;
|
||||
use core::f64::consts::{FRAC_PI_2, PI, TAU};
|
||||
use glam::{DAffine2, DVec2};
|
||||
use graphene_std::ATTR_TRANSFORM;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::math::quad::Quad;
|
||||
use graphene_std::subpath::{self, Subpath};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::{Font, TextAlign, TypesettingConfig};
|
||||
use graphene_std::vector::click_target::ClickTargetType;
|
||||
use graphene_std::vector::misc::point_to_dvec2;
|
||||
@@ -1129,7 +1129,7 @@ impl OverlayContextInternal {
|
||||
let text_bounds = kurbo::Rect::new(0., 0., text_width, text_height);
|
||||
|
||||
// Convert text to vector paths for rendering
|
||||
let text_table = text_context.to_path(text, &font, &GLOBAL_FONT_CACHE, typesetting, false);
|
||||
let text_list = text_context.to_path(text, &font, &GLOBAL_FONT_CACHE, typesetting, false);
|
||||
|
||||
// Calculate position based on pivot
|
||||
let mut position = DVec2::ZERO;
|
||||
@@ -1161,20 +1161,20 @@ impl OverlayContextInternal {
|
||||
}
|
||||
|
||||
// Render the actual text paths
|
||||
self.render_text_paths(&text_table, font_color, vello_transform);
|
||||
self.render_text_paths(&text_list, font_color, vello_transform);
|
||||
}
|
||||
|
||||
// Render text paths to the vello scene using existing infrastructure
|
||||
fn render_text_paths(&mut self, text_table: &Table<Vector>, font_color: &str, base_transform: kurbo::Affine) {
|
||||
fn render_text_paths(&mut self, text_list: &List<Vector>, font_color: &str, base_transform: kurbo::Affine) {
|
||||
let color = Self::parse_color(font_color);
|
||||
|
||||
for index in 0..text_table.len() {
|
||||
for index in 0..text_list.len() {
|
||||
// Use the existing bezier_to_path infrastructure to convert Vector to BezPath
|
||||
let mut path = BezPath::new();
|
||||
let mut last_point = None;
|
||||
let transform: DAffine2 = text_table.attribute_cloned_or_default(ATTR_TRANSFORM, index);
|
||||
let transform: DAffine2 = text_list.attribute_cloned_or_default(ATTR_TRANSFORM, index);
|
||||
|
||||
let Some(element) = text_table.element(index) else { continue };
|
||||
let Some(element) = text_list.element(index) else { continue };
|
||||
for (_, bezier, start_id, end_id) in element.segment_iter() {
|
||||
let move_to = last_point != Some(start_id);
|
||||
last_point = Some(end_id);
|
||||
|
||||
@@ -4,8 +4,8 @@ use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{DocumentNodeImplementation, InlineRust, NodeInput};
|
||||
use graph_craft::proto::{GraphErrorType, GraphErrors};
|
||||
use graph_craft::{Type, concrete};
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::raster_types::{CPU, Raster};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::uuid::NodeId;
|
||||
use graphene_std::vector::Vector;
|
||||
use graphene_std::{Artboard, Graphic};
|
||||
@@ -65,11 +65,11 @@ impl TypeSource {
|
||||
TaggedValue::String(_) => FrontendGraphDataType::Typography,
|
||||
// Types whose `TaggedValue` variant has been removed are routed through `TypeDefault` and identified by the descriptor's type name.
|
||||
TaggedValue::TypeDefault(td) => match td.name.as_ref() {
|
||||
n if n == std::any::type_name::<Table<Graphic>>() => FrontendGraphDataType::Graphic,
|
||||
n if n == std::any::type_name::<Table<Artboard>>() => FrontendGraphDataType::Artboard,
|
||||
n if n == std::any::type_name::<Table<Raster<CPU>>>() => FrontendGraphDataType::Raster,
|
||||
n if n == std::any::type_name::<Table<Vector>>() => FrontendGraphDataType::Vector,
|
||||
n if n == std::any::type_name::<Table<String>>() => FrontendGraphDataType::Typography,
|
||||
n if n == std::any::type_name::<List<Graphic>>() => FrontendGraphDataType::Graphic,
|
||||
n if n == std::any::type_name::<List<Artboard>>() => FrontendGraphDataType::Artboard,
|
||||
n if n == std::any::type_name::<List<Raster<CPU>>>() => FrontendGraphDataType::Raster,
|
||||
n if n == std::any::type_name::<List<Vector>>() => FrontendGraphDataType::Vector,
|
||||
n if n == std::any::type_name::<List<String>>() => FrontendGraphDataType::Typography,
|
||||
_ => FrontendGraphDataType::General,
|
||||
},
|
||||
_ => FrontendGraphDataType::General,
|
||||
|
||||
@@ -28,6 +28,7 @@ const TEXT_REPLACEMENTS: &[(&str, &str)] = &[
|
||||
("graphene_core::transform::Footprint", "graphene_core::transform::Footprint"),
|
||||
("\"OptionalF64\":", "\"F64\":"),
|
||||
("\"path_bool_nodes::BooleanOperation\"", "\"vector_types::vector::misc::BooleanOperation\""),
|
||||
("\"core_types::table::Table<", "\"core_types::list::List<"),
|
||||
];
|
||||
|
||||
pub struct NodeReplacement<'a> {
|
||||
@@ -1803,20 +1804,20 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
.set_input(&InputConnector::node(*node_id, 1), NodeInput::value(TaggedValue::U32(0), false), network_path);
|
||||
}
|
||||
|
||||
// Migrate from the old source/target v1 "Morph" node to the new `Table<Vector>`-based v2 "Morph" node.
|
||||
// This doesn't produce exactly equivalent results in cases involving input `Table<Vector>` values with multiple items.
|
||||
// Migrate from the old source/target v1 "Morph" node to the new `List<Vector>`-based v2 "Morph" node.
|
||||
// This doesn't produce exactly equivalent results in cases involving input `List<Vector>` values with multiple items.
|
||||
// The old version would zip the source and target items, interpolating each pair together.
|
||||
// The migrated version will instead deeply flatten both merged `Table`s and morph sequentially between all source vectors and all target vector elements.
|
||||
// The migrated version will instead deeply flatten both merged `List`s and morph sequentially between all source vectors and all target vector elements.
|
||||
// This migration assumes most usages didn't involve multiple parallel vector elements, and instead morphed from a single source to a single target vector element.
|
||||
if reference == DefinitionIdentifier::ProtoNode(graphene_std::vector::morph::IDENTIFIER) && (inputs_count == 3 || inputs_count == 4) {
|
||||
// 3 inputs - old signature (#3405):
|
||||
// async fn morph(_: impl Ctx, source: Table<Vector>, #[expose] target: Table<Vector>, #[default(0.5)] time: Fraction) -> Table<Vector> { ... }
|
||||
// async fn morph(_: impl Ctx, source: List<Vector>, #[expose] target: List<Vector>, #[default(0.5)] time: Fraction) -> List<Vector> { ... }
|
||||
//
|
||||
// 4 inputs - even older signature (commit 80b8df8d4298b6669f124b929ce61bfabfc44e41):
|
||||
// async fn morph(_: impl Ctx, source: Table<Vector>, #[expose] target: Table<Vector>, #[default(0.5)] time: Fraction, start_index: u32) -> Table<Vector> { ... }
|
||||
// async fn morph(_: impl Ctx, source: List<Vector>, #[expose] target: List<Vector>, #[default(0.5)] time: Fraction, start_index: u32) -> List<Vector> { ... }
|
||||
//
|
||||
// v2 signature:
|
||||
// async fn morph<I: IntoGraphicTable>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Vector>)] content: I, progression: Progression) -> Table<Vector> { ... }
|
||||
// async fn morph<I: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<Vector>)] content: I, progression: Progression) -> List<Vector> { ... }
|
||||
|
||||
let mut node_template = resolve_document_node_type(&reference)?.default_node_template();
|
||||
let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut node_template)?;
|
||||
@@ -1873,7 +1874,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
return None;
|
||||
};
|
||||
|
||||
// Create Count Elements node: counts content `Table` items → N
|
||||
// Create Count Elements node: counts content `List` items → N
|
||||
let Some(count_elements_def) = resolve_document_node_type(&DefinitionIdentifier::ProtoNode(graphene_std::vector::count_elements::IDENTIFIER)) else {
|
||||
log::error!("Could not get count_elements node from definition when upgrading morph");
|
||||
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
||||
@@ -2102,7 +2103,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
||||
|
||||
document.network_interface.set_input(
|
||||
&InputConnector::node(*node_id, 0),
|
||||
NodeInput::type_default(descriptor!(graphene_std::table::Table<graphene_std::vector::Vector>), true),
|
||||
NodeInput::type_default(descriptor!(graphene_std::list::List<graphene_std::vector::Vector>), true),
|
||||
network_path,
|
||||
);
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ use graph_craft::document::{NodeId, NodeInput};
|
||||
use graph_craft::{ProtoNodeIdentifier, concrete};
|
||||
use graphene_std::Color;
|
||||
use graphene_std::NodeInputDecleration;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::raster::BlendMode;
|
||||
use graphene_std::raster_types::{CPU, GPU, Image, Raster};
|
||||
use graphene_std::subpath::Subpath;
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::{Font, TypesettingConfig};
|
||||
use graphene_std::vector::misc::ManipulatorPointId;
|
||||
use graphene_std::vector::style::{Fill, Gradient};
|
||||
@@ -291,15 +291,15 @@ pub fn get_gradient_stops(layer: LayerNodeIdentifier, network_interface: &NodeNe
|
||||
Some(stops.clone())
|
||||
}
|
||||
|
||||
/// Compute the transform from a gradient's local space to viewport space for the given layer. For a `Table<GradientStops>`
|
||||
/// Compute the transform from a gradient's local space to viewport space for the given layer. For a `List<GradientStops>`
|
||||
/// layer this is the layer's incoming footprint transform; for the legacy `Fill::Gradient` path it composes the layer's
|
||||
/// viewport transform with the [0,1]² → bounding-box mapping.
|
||||
pub fn gradient_space_transform(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> glam::DAffine2 {
|
||||
use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier;
|
||||
|
||||
let metadata = network_interface.document_metadata();
|
||||
let is_gradient_table = is_layer_fed_by_node_of_name(layer, network_interface, &DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_value::IDENTIFIER));
|
||||
if is_gradient_table {
|
||||
let is_gradient_list = is_layer_fed_by_node_of_name(layer, network_interface, &DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_value::IDENTIFIER));
|
||||
if is_gradient_list {
|
||||
return metadata
|
||||
.upstream_footprints
|
||||
.get(&layer.to_node())
|
||||
@@ -637,6 +637,6 @@ impl<'a> NodeGraphLayer<'a> {
|
||||
pub fn is_raster_layer(layer: LayerNodeIdentifier, network_interface: &mut NodeNetworkInterface) -> bool {
|
||||
let layer_input_type = network_interface.input_type(&InputConnector::node(layer.to_node(), 1), &[]);
|
||||
|
||||
layer_input_type.compiled_nested_type() == Some(&concrete!(Table<Raster<CPU>>)) || layer_input_type.compiled_nested_type() == Some(&concrete!(Table<Raster<GPU>>))
|
||||
layer_input_type.compiled_nested_type() == Some(&concrete!(List<Raster<CPU>>)) || layer_input_type.compiled_nested_type() == Some(&concrete!(List<Raster<GPU>>))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ use crate::messages::tool::utility_types::ToolType;
|
||||
use glam::{DAffine2, DVec2};
|
||||
use graph_craft::concrete;
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::renderer::Quad;
|
||||
use graphene_std::subpath::{Bezier, BezierHandles};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::FontCache;
|
||||
use graphene_std::vector::algorithms::bezpath_algorithms::pathseg_compute_lookup_table;
|
||||
use graphene_std::vector::misc::{HandleId, ManipulatorPointId, dvec2_to_point};
|
||||
@@ -568,11 +568,11 @@ pub fn make_path_editable_is_allowed(network_interface: &mut NodeNetworkInterfac
|
||||
}
|
||||
for _ in selected_layers {}
|
||||
|
||||
// Must be a layer of type Table<Vector>
|
||||
// Must be a layer of type List<Vector>
|
||||
let node_id = NodeGraphLayer::new(first_layer, network_interface).horizontal_layer_flow().nth(1)?;
|
||||
|
||||
let output_type = network_interface.output_type(&OutputConnector::node(node_id, 0), &[]);
|
||||
if output_type.compiled_nested_type() != Some(&concrete!(Table<Vector>)) {
|
||||
if output_type.compiled_nested_type() != Some(&concrete!(List<Vector>)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -612,9 +612,9 @@ impl Fsm for ArtboardToolFsmState {
|
||||
mod test_artboard {
|
||||
pub use crate::test_utils::test_prelude::*;
|
||||
use graphene_std::Artboard;
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::list::List;
|
||||
|
||||
async fn get_artboards(editor: &mut EditorTestUtils) -> Table<Artboard> {
|
||||
async fn get_artboards(editor: &mut EditorTestUtils) -> List<Artboard> {
|
||||
let instrumented = match editor.eval_graph().await {
|
||||
Ok(instrumented) => instrumented,
|
||||
Err(e) => panic!("Failed to evaluate graph: {e}"),
|
||||
|
||||
@@ -459,8 +459,8 @@ struct SelectedGradient {
|
||||
gradient: Gradient,
|
||||
dragging: GradientDragTarget,
|
||||
initial_gradient: Gradient,
|
||||
// TODO: Remove (and the matching branches in `render_gradient` / pointer-up) once `Table<GradientStops>` replaces legacy `Fill::Gradient`
|
||||
is_gradient_table: bool,
|
||||
// TODO: Remove (and the matching branches in `render_gradient` / pointer-up) once `List<GradientStops>` replaces legacy `Fill::Gradient`
|
||||
is_gradient_list: bool,
|
||||
}
|
||||
|
||||
fn calculate_insertion(start: DVec2, end: DVec2, stops: &GradientStops, mouse: DVec2) -> Option<f64> {
|
||||
@@ -504,14 +504,14 @@ fn calculate_insertion(start: DVec2, end: DVec2, stops: &GradientStops, mouse: D
|
||||
impl SelectedGradient {
|
||||
pub fn new(gradient: Gradient, layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> Self {
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
let is_gradient_table = get_gradient_stops(layer, &document.network_interface).is_some();
|
||||
let is_gradient_list = get_gradient_stops(layer, &document.network_interface).is_some();
|
||||
Self {
|
||||
layer: Some(layer),
|
||||
transform,
|
||||
gradient: gradient.clone(),
|
||||
dragging: GradientDragTarget::End,
|
||||
initial_gradient: gradient,
|
||||
is_gradient_table,
|
||||
is_gradient_list,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,8 +727,8 @@ impl SelectedGradient {
|
||||
/// Update the layer fill to the current gradient
|
||||
pub fn render_gradient(&mut self, responses: &mut VecDeque<Message>) {
|
||||
if let Some(layer) = self.layer {
|
||||
// TODO: Drop the `Fill::Gradient` branch when all gradients become `Table<GradientStops>`
|
||||
if self.is_gradient_table {
|
||||
// TODO: Drop the `Fill::Gradient` branch when all gradients become `List<GradientStops>`
|
||||
if self.is_gradient_list {
|
||||
dispatch_gradient_writes(layer, &self.gradient, responses);
|
||||
} else {
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
@@ -1144,9 +1144,9 @@ impl Fsm for GradientToolFsmState {
|
||||
};
|
||||
|
||||
// The gradient has only one point and so should become a fill
|
||||
// TODO: Drop the legacy `Fill::Solid` branch when all gradients become `Table<GradientStops>`
|
||||
// TODO: Drop the legacy `Fill::Solid` branch when all gradients become `List<GradientStops>`
|
||||
if selected_gradient.gradient.stops.len() == 1 {
|
||||
if selected_gradient.is_gradient_table {
|
||||
if selected_gradient.is_gradient_list {
|
||||
selected_gradient.render_gradient(responses);
|
||||
} else if let Some(layer) = selected_gradient.layer {
|
||||
responses.add(GraphOperationMessage::FillSet {
|
||||
@@ -1242,7 +1242,7 @@ impl Fsm for GradientToolFsmState {
|
||||
for layer in document.network_interface.selected_nodes().selected_visible_layers(&document.network_interface) {
|
||||
let Some(gradient) = get_gradient(layer, &document.network_interface) else { continue };
|
||||
let transform = gradient_space_transform(layer, document);
|
||||
let is_gradient_table = get_gradient_stops(layer, &document.network_interface).is_some();
|
||||
let is_gradient_list = get_gradient_stops(layer, &document.network_interface).is_some();
|
||||
|
||||
// Check for dragging a midpoint diamond
|
||||
if drag_hint.is_none() {
|
||||
@@ -1270,7 +1270,7 @@ impl Fsm for GradientToolFsmState {
|
||||
gradient: gradient.clone(),
|
||||
dragging: GradientDragTarget::Midpoint(i),
|
||||
initial_gradient: gradient.clone(),
|
||||
is_gradient_table,
|
||||
is_gradient_list,
|
||||
});
|
||||
|
||||
break;
|
||||
@@ -1311,7 +1311,7 @@ impl Fsm for GradientToolFsmState {
|
||||
gradient: gradient.clone(),
|
||||
dragging: drag_target,
|
||||
initial_gradient: gradient.clone(),
|
||||
is_gradient_table,
|
||||
is_gradient_list,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1328,7 +1328,7 @@ impl Fsm for GradientToolFsmState {
|
||||
gradient: gradient.clone(),
|
||||
dragging: dragging_target,
|
||||
initial_gradient: gradient.clone(),
|
||||
is_gradient_table,
|
||||
is_gradient_list,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1377,8 +1377,8 @@ impl Fsm for GradientToolFsmState {
|
||||
GradientToolFsmState::Drawing { drag_hint: hint }
|
||||
} else {
|
||||
let document_mouse = document.metadata().document_to_viewport.inverse().transform_point2(mouse);
|
||||
// Table-based gradients render no geometry, so a click on empty canvas yields no layer. Fall back to a
|
||||
// selected gradient-table layer so the user can drag a fresh gradient line anywhere.
|
||||
// List-based gradients render no geometry, so a click on empty canvas yields no layer.
|
||||
// Fall back to a selected gradient list layer so the user can drag a fresh gradient line anywhere.
|
||||
let selected_layer = document.click_based_on_position(document_mouse).or_else(|| {
|
||||
document
|
||||
.network_interface
|
||||
@@ -1747,8 +1747,8 @@ fn apply_gradient_update(
|
||||
}
|
||||
update(&mut gradient);
|
||||
|
||||
// Only check for the gradient table once we know we'll write back, since this is a graph traversal per layer
|
||||
// TODO: Drop the `Fill::Gradient` branch when all gradients become `Table<GradientStops>`
|
||||
// Only check for the gradient list once we know we'll write back, since this is a graph traversal per layer
|
||||
// TODO: Drop the `Fill::Gradient` branch when all gradients become `List<GradientStops>`
|
||||
if get_gradient_stops(layer, &context.document.network_interface).is_some() {
|
||||
dispatch_gradient_writes(layer, &gradient, responses);
|
||||
} else {
|
||||
@@ -1932,7 +1932,7 @@ mod test_gradient {
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_gradient_table_layer(editor: &mut EditorTestUtils) -> LayerNodeIdentifier {
|
||||
async fn create_gradient_list_layer(editor: &mut EditorTestUtils) -> LayerNodeIdentifier {
|
||||
editor.drag_tool(ToolType::Rectangle, 0., 0., 100., 100., ModifierKeys::empty()).await;
|
||||
let document = editor.active_document();
|
||||
let layer = document.metadata().all_layers().next().unwrap();
|
||||
@@ -2335,10 +2335,10 @@ mod test_gradient {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gradient_table_drag_endpoint() {
|
||||
async fn gradient_list_drag_endpoint() {
|
||||
let mut editor = EditorTestUtils::create();
|
||||
editor.new_document().await;
|
||||
let layer = create_gradient_table_layer(&mut editor).await;
|
||||
let layer = create_gradient_list_layer(&mut editor).await;
|
||||
|
||||
// Create original transform for the control geometry and apply it
|
||||
let initial_start = DVec2::new(10., 50.);
|
||||
@@ -2407,10 +2407,10 @@ mod test_gradient {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gradient_table_preserves_stops() {
|
||||
async fn gradient_list_preserves_stops() {
|
||||
let mut editor = EditorTestUtils::create();
|
||||
editor.new_document().await;
|
||||
let layer = create_gradient_table_layer(&mut editor).await;
|
||||
let layer = create_gradient_list_layer(&mut editor).await;
|
||||
|
||||
// Set up a 3-stop gradient with distinct colors
|
||||
let original_stops = GradientStops::new([
|
||||
|
||||
@@ -9,13 +9,13 @@ use graph_craft::proto::GraphErrors;
|
||||
use graph_craft::{ProtoNodeIdentifier, concrete};
|
||||
use graphene_std::application_io::{ApplicationIo, ExportFormat, ImageTexture, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
|
||||
use graphene_std::bounds::{BoundingBox, RenderBoundingBox};
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::memo::IORecord;
|
||||
use graphene_std::ops::Convert;
|
||||
#[cfg(all(target_family = "wasm", feature = "gpu", feature = "wasm"))]
|
||||
use graphene_std::platform_application_io::canvas_utils::{Canvas, CanvasSurface, CanvasSurfaceHandle};
|
||||
use graphene_std::raster_types::Raster;
|
||||
use graphene_std::renderer::{Render, RenderParams, RenderSvgSegmentList, SvgRender, SvgSegment};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::FontCache;
|
||||
use graphene_std::transform::RenderQuality;
|
||||
use graphene_std::vector::Vector;
|
||||
@@ -432,8 +432,8 @@ impl NodeRuntime {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Graphic table: thumbnail
|
||||
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Graphic>>>() {
|
||||
// Graphic list: thumbnail
|
||||
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<Graphic>>>() {
|
||||
if update_thumbnails {
|
||||
let bounds = io.output.thumbnail_bounding_box(DAffine2::IDENTITY, true);
|
||||
Self::render_thumbnail(&mut self.thumbnail_renders, parent_network_node_id, &io.output, bounds, responses)
|
||||
@@ -441,14 +441,14 @@ impl NodeRuntime {
|
||||
}
|
||||
// Artboard thumbnail bounds come from the clipping rectangles, not the content union, since the renderer
|
||||
// clips content to those rectangles so anything outside isn't visible
|
||||
else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Artboard>>>() {
|
||||
else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<Artboard>>>() {
|
||||
if update_thumbnails {
|
||||
let bounds = artboard_clip_bounds(&io.output);
|
||||
Self::render_thumbnail(&mut self.thumbnail_renders, parent_network_node_id, &io.output, bounds, responses)
|
||||
}
|
||||
}
|
||||
// Vector table: vector modifications
|
||||
else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, Table<Vector>>>() {
|
||||
// Vector list: vector modifications
|
||||
else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<Vector>>>() {
|
||||
// Insert the vector modify
|
||||
self.vector_modify.insert(parent_network_node_id, io.output.element(0).cloned().unwrap_or_default());
|
||||
}
|
||||
@@ -522,7 +522,7 @@ impl NodeRuntime {
|
||||
|
||||
/// Returns the union of the artboards' clipping rectangles, used as the thumbnail bounds for an artboard layer so the
|
||||
/// framing matches what's actually visible after clipping rather than the unclipped content extents.
|
||||
fn artboard_clip_bounds(artboards: &Table<Artboard>) -> RenderBoundingBox {
|
||||
fn artboard_clip_bounds(artboards: &List<Artboard>) -> RenderBoundingBox {
|
||||
let mut combined: Option<[DVec2; 2]> = None;
|
||||
for index in 0..artboards.len() {
|
||||
let location: DVec2 = artboards.attribute_cloned_or_default(graphene_std::ATTR_LOCATION, index);
|
||||
|
||||
Reference in New Issue
Block a user