Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl<'a> ModifyInputsContext<'a> {
Some(NodeInput::value(TaggedValue::Graphic(Default::default()), true)),
Some(NodeInput::value(TaggedValue::DVec2(artboard.location.into()), false)),
Some(NodeInput::value(TaggedValue::DVec2(artboard.dimensions.into()), false)),
Some(NodeInput::value(TaggedValue::Color(Table::new_from_element(artboard.background)), false)),
Some(NodeInput::value(TaggedValue::Color(artboard.background), false)),
Some(NodeInput::value(TaggedValue::Bool(artboard.clip), false)),
]);
self.network_interface.insert_node(new_id, artboard_node_template, &[]);
Expand Down Expand Up @@ -293,10 +293,7 @@ impl<'a> ModifyInputsContext<'a> {
pub fn insert_color_value(&mut self, color: Color, layer: LayerNodeIdentifier) {
let color_value = resolve_proto_node_type(graphene_std::math_nodes::color_value::IDENTIFIER)
.expect("Color Value node does not exist")
.node_template_input_override([
Some(NodeInput::value(TaggedValue::None, false)),
Some(NodeInput::value(TaggedValue::Color(Table::new_from_element(color)), false)),
]);
.node_template_input_override([Some(NodeInput::value(TaggedValue::None, false)), Some(NodeInput::value(TaggedValue::OptionalColor(Some(color)), false))]);

let color_value_id = NodeId::new();
self.network_interface.insert_node(color_value_id, color_value, &[]);
Expand Down Expand Up @@ -420,11 +417,11 @@ impl<'a> ModifyInputsContext<'a> {
match &fill {
Fill::None => {
let input_connector = InputConnector::node(fill_node_id, backup_color_index);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::Color(Table::new()), false), true);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::OptionalColor(None), false), true);
}
Fill::Solid(color) => {
let input_connector = InputConnector::node(fill_node_id, backup_color_index);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::Color(Table::new_from_element(*color)), false), true);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::OptionalColor(Some(*color)), false), true);
}
Fill::Gradient(gradient) => {
let input_connector = InputConnector::node(fill_node_id, backup_gradient_index);
Expand Down Expand Up @@ -473,10 +470,8 @@ impl<'a> ModifyInputsContext<'a> {
return;
};

let stroke_color = if let Some(color) = stroke.color { Table::new_from_element(color) } else { Table::new() };

let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::ColorInput::INDEX);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::Color(stroke_color), false), true);
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::ColorInput::<Option<Color>>::INDEX);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::OptionalColor(stroke.color), false), true);
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::WeightInput::INDEX);
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::F64(stroke.weight), false), true);
let input_connector = InputConnector::node(stroke_node_id, graphene_std::vector::stroke::AlignInput::INDEX);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
NodeInput::value(TaggedValue::Graphic(Default::default()), true),
NodeInput::value(TaggedValue::DVec2(DVec2::ZERO), false),
NodeInput::value(TaggedValue::DVec2(DVec2::new(1920., 1080.)), false),
NodeInput::value(TaggedValue::Color(Table::new_from_element(Color::WHITE)), false),
NodeInput::value(TaggedValue::Color(Color::WHITE), false),
NodeInput::value(TaggedValue::Bool(true), false),
],
..Default::default()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use graphene_std::raster::{
SelectiveColorChoice,
};
use graphene_std::raster_types::Image;
use graphene_std::table::{Table, TableRow};
use graphene_std::text::{Font, TextAlign};
use graphene_std::transform::{Footprint, ReferencePoint, ScaleType, Transform};
use graphene_std::vector::misc::BooleanOperation;
Expand Down Expand Up @@ -220,11 +219,12 @@ pub(crate) fn property_from_type(
// ==========================
Some(x) if x == TypeId::of::<Vec<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
Some(x) if x == TypeId::of::<Vec<DVec2>>() => array_of_vec2_widget(default_info, TextInput::default()).into(),
// ===========
// TABLE TYPES
// ===========
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)),
// =========================
// COLOR AND GRADIENT TYPES
// =========================
Some(x) if x == TypeId::of::<Color>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Comment on lines +225 to +227
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The removal of Table<Color> and Table<GradientStops> from the TypeId matching in property_from_type causes a UI regression. Many nodes in the graph still return these tabular types (e.g., color_value, rgba_to_color, sample_gradient). For these nodes, the Properties panel will now fail to display a color picker widget and instead show a fallback message indicating that no widget exists for the type.

These cases should be restored to maintain UI compatibility with nodes that still produce tabular return types. Note that color_widget will still work correctly because TaggedValue::from_type (used for initializing widgets) already maps these tabular types to the new OptionalColor and GradientStops variants.

Suggested change
Some(x) if x == TypeId::of::<Color>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<Color>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<Option<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
Some(x) if x == TypeId::of::<graphene_std::table::Table<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(default_info, ColorInput::default().allow_none(false)),
Some(x) if x == TypeId::of::<graphene_std::table::Table<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),

// ============
// STRUCT TYPES
// ============
Expand Down Expand Up @@ -1180,28 +1180,28 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:

// Add the color input
match &**tagged_value {
TaggedValue::Color(color_table) => widgets.push(
TaggedValue::Color(color) => widgets.push(
color_button
.value(FillChoice::Solid(*color))
.on_update(update_value(|input: &ColorInput| TaggedValue::Color(input.value.as_solid().unwrap_or(Color::BLACK)), node_id, index))
.on_commit(commit_value)
.widget_instance(),
),
TaggedValue::OptionalColor(optional_color) => widgets.push(
color_button
.value(match color_table.iter().next() {
Some(color) => FillChoice::Solid(*color.element),
.value(match optional_color {
Some(color) => FillChoice::Solid(*color),
None => FillChoice::None,
})
.on_update(update_value(
|input: &ColorInput| TaggedValue::Color(input.value.as_solid().iter().map(|&color| TableRow::new_from_element(color)).collect()),
node_id,
index,
))
.on_update(update_value(|input: &ColorInput| TaggedValue::OptionalColor(input.value.as_solid()), node_id, index))
.on_commit(commit_value)
.widget_instance(),
),
TaggedValue::GradientTable(gradient_table) => widgets.push(
TaggedValue::GradientStops(gradient_stops) => widgets.push(
color_button
.value(match gradient_table.iter().next() {
Some(row) => FillChoice::Gradient(row.element.clone()),
None => FillChoice::Gradient(GradientStops::default()),
})
.value(FillChoice::Gradient(gradient_stops.clone()))
.on_update(update_value(
|input: &ColorInput| TaggedValue::GradientTable(input.value.as_gradient().iter().map(|&gradient| TableRow::new_from_element(gradient.clone())).collect()),
|input: &ColorInput| TaggedValue::GradientStops(input.value.as_gradient().cloned().unwrap_or_default()),
node_id,
index,
))
Expand Down Expand Up @@ -1884,7 +1884,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
}
};

let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), Some(TaggedValue::Color(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
let (fill, backup_color, backup_gradient) = if let (Some(TaggedValue::Fill(fill)), Some(TaggedValue::OptionalColor(backup_color)), Some(TaggedValue::Gradient(backup_gradient))) = (
&document_node.inputs[FillInput::<Color>::INDEX].as_value(),
&document_node.inputs[BackupColorInput::INDEX].as_value(),
&document_node.inputs[BackupGradientInput::INDEX].as_value(),
Expand All @@ -1894,7 +1894,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
return vec![LayoutGroup::row(widgets_first_row)];
};
let fill2 = fill.clone();
let backup_color_fill: Fill = backup_color.clone().into();
let backup_color_fill: Fill = (*backup_color).into();
let backup_gradient_fill: Fill = backup_gradient.clone().into();

widgets_first_row.push(Separator::new(SeparatorStyle::Unrelated).widget_instance());
Expand All @@ -1907,13 +1907,13 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
Fill::None => NodeGraphMessage::SetInputValue {
node_id,
input_index: BackupColorInput::INDEX,
value: TaggedValue::Color(Table::new()),
value: TaggedValue::OptionalColor(None),
}
.into(),
Fill::Solid(color) => NodeGraphMessage::SetInputValue {
node_id,
input_index: BackupColorInput::INDEX,
value: TaggedValue::Color(Table::new_from_element(*color)),
value: TaggedValue::OptionalColor(Some(*color)),
}
.into(),
Fill::Gradient(gradient) => NodeGraphMessage::SetInputValue {
Expand Down Expand Up @@ -2124,7 +2124,7 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -
let miter_limit_disabled = join_value != &StrokeJoin::Miter;

let color = color_widget(
ParameterWidgetsInfo::new(node_id, ColorInput::INDEX, true, context),
ParameterWidgetsInfo::new(node_id, ColorInput::<Option<Color>>::INDEX, true, context),
crate::messages::layout::utility_types::widgets::button_widgets::ColorInput::default(),
);
let weight = number_widget(ParameterWidgetsInfo::new(node_id, WeightInput::INDEX, true, context), NumberInput::default().unit(" px").min(0.));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ impl FrontendGraphDataType {
TaggedValue::Graphic(_) => Self::Graphic,
TaggedValue::Raster(_) => Self::Raster,
TaggedValue::Vector(_) => Self::Vector,
TaggedValue::Color(_) => Self::Color,
TaggedValue::Gradient(_) | TaggedValue::GradientTable(_) => Self::Gradient,
TaggedValue::Color(_) | TaggedValue::OptionalColor(_) => Self::Color,
TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) => Self::Gradient,
TaggedValue::String(_) | TaggedValue::VecString(_) => Self::Typography,
_ => Self::General,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ impl TypeSource {
TaggedValue::Graphic(_) => FrontendGraphDataType::Graphic,
TaggedValue::Raster(_) => FrontendGraphDataType::Raster,
TaggedValue::Vector(_) => FrontendGraphDataType::Vector,
TaggedValue::Color(_) => FrontendGraphDataType::Color,
TaggedValue::Gradient(_) | TaggedValue::GradientTable(_) => FrontendGraphDataType::Gradient,
TaggedValue::Color(_) | TaggedValue::OptionalColor(_) => FrontendGraphDataType::Color,
TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) => FrontendGraphDataType::Gradient,
TaggedValue::String(_) => FrontendGraphDataType::Typography,
_ => FrontendGraphDataType::General,
},
Expand Down
25 changes: 25 additions & 0 deletions editor/src/messages/portfolio/document_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1986,6 +1986,31 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
.set_input(&InputConnector::node(*node_id, 1), NodeInput::value(TaggedValue::ImageData(image), false), network_path);
}

// Migrate Color Value, Fill backup_color, and Stroke color inputs from Color(Table<Color>) to OptionalColor(Option<Color>)
let color_to_optional_cases: &[(_, usize)] = &[
(graphene_std::math_nodes::color_value::IDENTIFIER, 1),
(graphene_std::vector_nodes::fill::IDENTIFIER, 2),
(graphene_std::vector::stroke::IDENTIFIER, 1),
];
for &(ref identifier, input_index) in color_to_optional_cases {
if reference == DefinitionIdentifier::ProtoNode(identifier.clone())
&& let Some(NodeInput::Value { tagged_value, .. }) = node.inputs.get(input_index)
&& let TaggedValue::Color(color) = &**tagged_value
{
let color = *color;

document.network_interface.set_input(
&InputConnector::node(*node_id, input_index),
NodeInput::value(TaggedValue::OptionalColor(Some(color)), false),
network_path,
Comment on lines +1997 to +2005
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The color migration forcibly sets exposed to false, which can silently unexpose previously exposed inputs. Preserve the original exposure flag during conversion.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At editor/src/messages/portfolio/document_migration.rs, line 1997:

<comment>The color migration forcibly sets `exposed` to `false`, which can silently unexpose previously exposed inputs. Preserve the original exposure flag during conversion.</comment>

<file context>
@@ -1986,6 +1986,31 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
+	];
+	for &(ref identifier, input_index) in color_to_optional_cases {
+		if reference == DefinitionIdentifier::ProtoNode(identifier.clone())
+			&& let Some(NodeInput::Value { tagged_value, .. }) = node.inputs.get(input_index)
+			&& let TaggedValue::Color(color) = &**tagged_value
+		{
</file context>
Suggested change
&& let Some(NodeInput::Value { tagged_value, .. }) = node.inputs.get(input_index)
&& let TaggedValue::Color(color) = &**tagged_value
{
let color = *color;
document.network_interface.set_input(
&InputConnector::node(*node_id, input_index),
NodeInput::value(TaggedValue::OptionalColor(Some(color)), false),
network_path,
&& let Some(NodeInput::Value { tagged_value, exposed }) = node.inputs.get(input_index)
&& let TaggedValue::Color(color) = &**tagged_value
{
let color = *color;
document.network_interface.set_input(
&InputConnector::node(*node_id, input_index),
NodeInput::value(TaggedValue::OptionalColor(Some(color)), *exposed),
network_path,
);

);
}
}

// Migrate Artboard and Empty Image color inputs from Color(Table<Color>) to Color(Color), which is handled by serde migration already (no-op here)

// Migrate GradientTable(Table<GradientStops>) to GradientStops(GradientStops), which is handled by serde migration via alias (no-op here)

// ==================================
// PUT ALL MIGRATIONS ABOVE THIS LINE
// ==================================
Expand Down
25 changes: 13 additions & 12 deletions node-graph/graph-craft/src/document/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ macro_rules! tagged_value {
// Tries using the default for the tagged value type. If it not implemented, then uses the default used in document_node_types. If it is not used there, then TaggedValue::None is returned.
Some(match concrete_type.id? {
x if x == TypeId::of::<()>() => TaggedValue::None,
// Table-wrapped types need a single-row default with the element's default, not an empty table
x if x == TypeId::of::<Table<Color>>() => TaggedValue::Color(Table::new_from_element(Color::default())),
x if x == TypeId::of::<Table<GradientStops>>() => TaggedValue::GradientTable(Table::new_from_element(GradientStops::default())),
x if x == TypeId::of::<Table<Color>>() => TaggedValue::OptionalColor(Some(Color::default())),
x if x == TypeId::of::<Option<Color>>() => TaggedValue::OptionalColor(None),
x if x == TypeId::of::<Table<GradientStops>>() => TaggedValue::GradientStops(GradientStops::default()),
$( x if x == TypeId::of::<$ty>() => TaggedValue::$identifier(Default::default()), )*
_ => return None,
})
Expand Down Expand Up @@ -202,14 +202,16 @@ tagged_value! {
#[serde(alias = "ArtboardGroup")]
Artboard(Table<Artboard>),
#[serde(deserialize_with = "core_types::misc::migrate_color")] // TODO: Eventually remove this migration document upgrade code
#[serde(alias = "ColorTable", alias = "OptionalColor", alias = "ColorNotInTable")]
Color(Table<Color>),
#[serde(deserialize_with = "graphic_types::vector_types::gradient::migrate_gradient_stops")] // TODO: Eventually remove this migration document upgrade code
#[serde(alias = "GradientPositions", alias = "GradientStops")]
GradientTable(Table<GradientStops>),
// ============
// STRUCT TYPES
// ============
#[serde(alias = "ColorTable", alias = "ColorNotInTable")]
Color(Color),
#[serde(deserialize_with = "core_types::misc::migrate_optional_color")] // TODO: Eventually remove this migration document upgrade code
OptionalColor(Option<Color>),
#[serde(deserialize_with = "graphic_types::vector_types::gradient::migrate_gradient_stops")] // TODO: Eventually remove this migration document upgrade code
#[serde(alias = "GradientPositions", alias = "GradientTable")]
GradientStops(GradientStops),
Comment on lines +209 to +214
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Removing the Table<Color> and Table<GradientStops> variants from TaggedValue while they are still used as return types in the graph (e.g., in color_value, rgba_to_color, and sample_gradient) will cause try_from_any and try_from_std_any_ref to fail for these types. This will break monitoring and memoization for any node returning these tabular forms.

Since the tagged_value! macro (defined at line 33) generates these conversion methods by iterating over the variants, you should either:

  1. Add manual conversion logic to the macro definition to map these Table types to the new non-tabular variants.
  2. Keep the tabular variants as internal/deprecated forms to support runtime conversion of existing graph outputs.

FVec2(Vec2),
FAffine2(Affine2),
#[serde(alias = "IVec2", alias = "UVec2")]
Expand Down Expand Up @@ -397,10 +399,9 @@ impl TaggedValue {
() if ty == TypeId::of::<u32>() => FromStr::from_str(string).map(TaggedValue::U32).ok()?,
() if ty == TypeId::of::<DVec2>() => to_dvec2(string).map(TaggedValue::DVec2)?,
() if ty == TypeId::of::<bool>() => FromStr::from_str(string).map(TaggedValue::Bool).ok()?,
// `Color` (not in a table) is still currently needed by `BlackAndWhiteNode` and `ColorOverlayNode` GPU `shader_node(PerPixelAdjust)` variants
() if ty == TypeId::of::<Color>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
() if ty == TypeId::of::<Table<Color>>() => to_color(string).map(|color| TaggedValue::Color(Table::new_from_element(color)))?,
() if ty == TypeId::of::<Table<GradientStops>>() => to_gradient(string).map(|color| TaggedValue::GradientTable(Table::new_from_element(color)))?,
() if ty == TypeId::of::<Color>() => to_color(string).map(TaggedValue::Color)?,
() if ty == TypeId::of::<Option<Color>>() => TaggedValue::OptionalColor(to_color(string)),
() if ty == TypeId::of::<GradientStops>() => to_gradient(string).map(TaggedValue::GradientStops)?,
() if ty == TypeId::of::<Fill>() => to_color(string).map(|color| TaggedValue::Fill(Fill::solid(color)))?,
() if ty == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
_ => return None,
Expand Down
7 changes: 7 additions & 0 deletions node-graph/interpreted-executor/src/node_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
#[cfg(feature = "gpu")]
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Raster<GPU>>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<Color>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Color]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Option<Color>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => GradientStops]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<GradientStops>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Image<Color>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => String]),
Expand Down Expand Up @@ -137,6 +140,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
// Context nullification
#[cfg(feature = "gpu")]
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => &PlatformEditorApi, Context => graphene_std::ContextFeatures]),
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => Color, 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]),
#[cfg(target_family = "wasm")]
Expand All @@ -152,6 +156,9 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Raster<CPU>>]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<Color>]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Image<Color>]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Color]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Option<Color>]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => GradientStops]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Table<GradientStops>]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<DVec2>]),
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<NodeId>]),
Expand Down
Loading
Loading