Skip to content
Merged
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 @@ -12,7 +12,7 @@ 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};
use graphene_std::vector::style::{Fill, FillChoice, GradientSpreadMethod, GradientType};
use graphene_std::{Artboard, Color, Context, Graphic};
use std::any::Any;
use std::sync::Arc;
Expand Down Expand Up @@ -191,6 +191,11 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
Table<String>,
Table<f64>,
Table<u8>,
Table<bool>,
Table<DAffine2>,
Table<BlendMode>,
Table<GradientType>,
Table<GradientSpreadMethod>,
GradientStops,
f64,
u32,
Expand All @@ -200,6 +205,9 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
Option<f64>,
DVec2,
DAffine2,
BlendMode,
GradientType,
GradientSpreadMethod,
])
}

Expand Down Expand Up @@ -757,6 +765,51 @@ impl TableRowLayout for Affine2 {
}
}

impl TableRowLayout for BlendMode {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
fn type_name() -> &'static str {
"BlendMode"
}
fn identifier(&self) -> String {
self.to_string()
}
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
TextLabel::new(self.to_string()).narrow(true).widget_instance()
}
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
}
}

impl TableRowLayout for GradientType {
fn type_name() -> &'static str {
"GradientType"
}
fn identifier(&self) -> String {
self.to_string()
}
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
TextLabel::new(self.to_string()).narrow(true).widget_instance()
}
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
}
}

impl TableRowLayout for GradientSpreadMethod {
fn type_name() -> &'static str {
"GradientSpreadMethod"
}
fn identifier(&self) -> String {
self.to_string()
}
fn value_widget(&self, _target: PathStep, _data: &LayoutData) -> WidgetInstance {
TextLabel::new(self.to_string()).narrow(true).widget_instance()
}
fn value_page(&self, _data: &mut LayoutData) -> Vec<LayoutGroup> {
vec![LayoutGroup::row(vec![self.value_widget(PathStep::Element(0), _data)])]
}
}

/// Resolves the value/breadcrumb label for a `NodeId` against `network_interface` at the given `network_path`,
/// falling back to "Node {id}" if the node isn't present (e.g. an ID that no longer maps to a real node).
fn node_id_display_label(node_id: NodeId, network_interface: &NodeNetworkInterface, network_path: &[NodeId]) -> String {
Expand Down Expand Up @@ -921,6 +974,9 @@ macro_rules! known_table_row_types {

/// Uses `Display` instead of `Debug` for attribute types that have a nicer human-readable format.
fn display_value_override(any: &dyn Any) -> Option<String> {
if let Some(value) = any.downcast_ref::<DVec2>() {
return Some(format_dvec2(*value));
}
if let Some(value) = any.downcast_ref::<BlendMode>() {
return Some(value.to_string());
}
Expand Down
75 changes: 71 additions & 4 deletions node-graph/interpreted-executor/src/node_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,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::Table;
use graphene_std::table::{AttributeColumnDyn, AttributeValueDyn, Table, TableDyn};
use graphene_std::transform::Footprint;
use graphene_std::uuid::NodeId;
use graphene_std::vector::Vector;
Expand All @@ -42,6 +42,54 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
convert_node!(from: Table<Raster<CPU>>, to: Table<Graphic>),
#[cfg(feature = "gpu")]
convert_node!(from: Table<Raster<GPU>>, to: Table<Graphic>),
// Type-erased attribute column conversions for the `Attach Attribute` node, so it monomorphizes only over the destination table type.
convert_node!(from: Table<Artboard>, to: AttributeColumnDyn),
convert_node!(from: Table<Graphic>, to: AttributeColumnDyn),
convert_node!(from: Table<Vector>, to: AttributeColumnDyn),
convert_node!(from: Table<Raster<CPU>>, to: AttributeColumnDyn),
convert_node!(from: Table<Color>, to: AttributeColumnDyn),
convert_node!(from: Table<GradientStops>, to: AttributeColumnDyn),
convert_node!(from: Table<f64>, to: AttributeColumnDyn),
convert_node!(from: Table<bool>, to: AttributeColumnDyn),
convert_node!(from: Table<String>, to: AttributeColumnDyn),
convert_node!(from: Table<DAffine2>, to: AttributeColumnDyn),
convert_node!(from: Table<BlendMode>, to: AttributeColumnDyn),
convert_node!(from: Table<graphene_std::vector::style::GradientType>, to: AttributeColumnDyn),
convert_node!(from: Table<graphene_std::vector::style::GradientSpreadMethod>, to: AttributeColumnDyn),
convert_node!(from: Table<Artboard>, to: TableDyn),
convert_node!(from: Table<Graphic>, to: TableDyn),
convert_node!(from: Table<Vector>, to: TableDyn),
convert_node!(from: Table<Raster<CPU>>, to: TableDyn),
#[cfg(feature = "gpu")]
convert_node!(from: Table<Raster<GPU>>, to: TableDyn),
convert_node!(from: Table<Color>, to: TableDyn),
convert_node!(from: Table<GradientStops>, to: TableDyn),
convert_node!(from: Table<f64>, to: TableDyn),
convert_node!(from: Table<bool>, to: TableDyn),
convert_node!(from: Table<String>, to: TableDyn),
convert_node!(from: Table<u8>, to: TableDyn),
convert_node!(from: Table<NodeId>, to: TableDyn),
convert_node!(from: Table<DAffine2>, to: TableDyn),
convert_node!(from: Table<BlendMode>, to: TableDyn),
convert_node!(from: Table<graphene_std::vector::style::GradientType>, to: TableDyn),
convert_node!(from: Table<graphene_std::vector::style::GradientSpreadMethod>, to: TableDyn),
// Type-erased attribute value conversions for the `Write Attribute` node, so it monomorphizes only over the destination table type.
convert_node!(from: f64, to: AttributeValueDyn),
convert_node!(from: u32, to: AttributeValueDyn),
convert_node!(from: u64, to: AttributeValueDyn),
convert_node!(from: bool, to: AttributeValueDyn),
convert_node!(from: String, to: AttributeValueDyn),
convert_node!(from: DVec2, to: AttributeValueDyn),
convert_node!(from: DAffine2, to: AttributeValueDyn),
convert_node!(from: Color, to: AttributeValueDyn),
convert_node!(from: BlendMode, to: AttributeValueDyn),
convert_node!(from: graphene_std::vector::style::GradientType, to: AttributeValueDyn),
convert_node!(from: graphene_std::vector::style::GradientSpreadMethod, to: AttributeValueDyn),
convert_node!(from: Table<String>, to: AttributeValueDyn),
convert_node!(from: Table<NodeId>, to: AttributeValueDyn),
convert_node!(from: Table<Color>, to: AttributeValueDyn),
convert_node!(from: Table<GradientStops>, to: AttributeValueDyn),
convert_node!(from: Table<Graphic>, to: AttributeValueDyn),
// into_node!(from: Table<Raster<CPU>>, to: Table<Raster<SRGBA8>>),
#[cfg(feature = "gpu")]
into_node!(from: &PlatformEditorApi, to: &WgpuExecutor),
Expand Down Expand Up @@ -99,6 +147,14 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<NodeId>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<f64>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<u8>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<bool>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<DAffine2>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<BlendMode>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<graphene_std::vector::style::GradientType>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<graphene_std::vector::style::GradientSpreadMethod>]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => AttributeColumnDyn]),
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]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::text::Font]),
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Table<BrushStroke>]),
Expand Down Expand Up @@ -138,11 +194,14 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
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 => 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 => 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")]
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => CanvasHandle, Context => graphene_std::ContextFeatures]),
// =============
// MEMOIZE NODES
// =============
// ==========
// MEMO NODES
// ==========
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => ()]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => bool]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<Artboard>]),
Expand All @@ -156,6 +215,14 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<NodeId>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<f64>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<u8>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<bool>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<DAffine2>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<BlendMode>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<graphene_std::vector::style::GradientType>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => Table<graphene_std::vector::style::GradientSpreadMethod>]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => AttributeColumnDyn]),
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")]
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => CanvasHandle]),
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => f64]),
Expand Down
31 changes: 30 additions & 1 deletion node-graph/libraries/core-types/src/ops.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::Node;
use crate::table::{Table, TableRow};
use crate::table::{AttributeColumnDyn, AttributeValueDyn, Column, Table, TableDyn, TableRow};
use crate::transform::Footprint;
use glam::DVec2;
use graphene_hash::CacheHash;
use std::future::Future;
use std::marker::PhantomData;

Expand Down Expand Up @@ -71,6 +72,34 @@ impl<U, T: TableConvert<U> + Send> Convert<Table<U>, ()> for Table<T> {
}
}

/// Wraps each row's element into a type-erased column. Lets nodes that accept a source attribute
/// from any `Table<U>` 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<T: Clone + Send + Sync + Default + std::fmt::Debug + PartialEq + CacheHash + 'static> Convert<AttributeColumnDyn, ()> for Table<T> {
async fn convert(self, _: Footprint, _: ()) -> AttributeColumnDyn {
let values: Vec<T> = self.into_iter().map(|row| row.into_element()).collect();
AttributeColumnDyn(Box::new(Column(values)))
}
}

/// Wraps a value into a type-erased attribute value. Lets nodes that take a per-item value source
/// (such as `write_attribute`'s value-producing input) be generic over the destination table type
/// alone, with the compiler-inserted convert handling each concrete value type at the wire level.
impl<T: Clone + Send + Sync + Default + std::fmt::Debug + PartialEq + CacheHash + 'static> Convert<AttributeValueDyn, ()> for T {
async fn convert(self, _: Footprint, _: ()) -> AttributeValueDyn {
AttributeValueDyn(Box::new(self))
}
}

/// Erases a `Table<T>`'s element type, exposing only its attributes and row count. Lets nodes that
/// only need attribute access (such as the `read_attribute_*` family) take a single `TableDyn` input
/// instead of monomorphizing over every possible carrier table type.
impl<T: Send> Convert<TableDyn, ()> for Table<T> {
async fn convert(self, _: Footprint, _: ()) -> TableDyn {
self.into()
}
}

impl Convert<DVec2, ()> for DVec2 {
async fn convert(self, _: Footprint, _: ()) -> DVec2 {
self
Expand Down
Loading
Loading