From bfa48439c8319448c3d63aa5f6d64b298c274d98 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 15 Aug 2026 08:48:29 +0000 Subject: [PATCH] Resolve coercion nodes and dynamic values in the layout pass --- node-graph/graph-craft/src/document/value.rs | 13 +++++++++++-- .../interpreted-executor/src/node_registry.rs | 6 +++--- node-graph/libraries/core-types/src/record.rs | 13 +++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index 484336a1f5..0a23d0eeca 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -263,11 +263,20 @@ macro_rules! tagged_value { } } - /// `None` for values whose element type is only known dynamically ([`Self::TypeDefault`]). + /// `None` for a [`Self::TypeDefault`] whose named type is outside `for_each_type_default!`. pub fn element_write(&self) -> Option { Some(match self { Self::None => core_types::record::element_write::<()>(), - Self::TypeDefault(_) => return None, + Self::TypeDefault(td) => { + let name = td.name.as_ref(); + macro_rules! check { + ($type_default:ty) => { + if name == std::any::type_name::<$type_default>() { return Some(core_types::record::element_write::<$type_default>()); } + }; + } + for_each_type_default!(check); + return None; + } Self::F64Array(_) => core_types::record::element_write::>(), Self::Color(_) => core_types::record::element_write::>(), Self::Gradient(_) => core_types::record::element_write::>(), diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 6fdbdda6af..3928b0d6ef 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -179,7 +179,7 @@ mod node_registry_macros { ( ProtoNodeIdentifier::new(concat!["graphene_core::ops::IntoNode<", stringify!($to), ">"]), RegistryEntry { - layout_meta: None, + layout_meta: Some(core_types::record::LayoutMeta::retype(core_types::record::element_write::<$to>())), io: NodeIOTypes::new( concrete!(Context), core_types::registry::record_type::<$to>(), @@ -247,7 +247,7 @@ mod node_registry_macros { ( ProtoNodeIdentifier::new(concat!["graphene_core::ops::ConvertNode<", stringify!($to), ">"]), RegistryEntry { - layout_meta: None, + layout_meta: Some(core_types::record::LayoutMeta::retype(core_types::record::element_write::<$to>())), io: NodeIOTypes::new( concrete!(Context), core_types::registry::record_type::<$to>(), @@ -293,7 +293,7 @@ mod node_registry_macros { ( ProtoNodeIdentifier::new(concat!["graphene_core::ops::ConvertNode<", stringify!($to), ">"]), RegistryEntry { - layout_meta: None, + layout_meta: Some(core_types::record::LayoutMeta::retype(core_types::record::element_write::<$to>())), io: NodeIOTypes::new( concrete!(Context), core_types::registry::record_type::<$to>(), diff --git a/node-graph/libraries/core-types/src/record.rs b/node-graph/libraries/core-types/src/record.rs index 9607b02c56..896e2404b3 100644 --- a/node-graph/libraries/core-types/src/record.rs +++ b/node-graph/libraries/core-types/src/record.rs @@ -287,6 +287,19 @@ pub enum ElementSpec { } impl LayoutMeta { + /// The meta of an elementwise carrier flip that retypes input 0's element, + /// preserving its depth and attributes: what an `Into`/`Convert` coercion derives. + pub fn retype(element: ElementWrite) -> Self { + Self { + sources: vec![0], + reads: Vec::new(), + element: ElementSpec::Concrete(element), + writes: Vec::new(), + removes: Vec::new(), + level_delta: 0, + } + } + /// Folds the node's output layout from its inputs', reproducing what the /// node's constructor derives at wiring. `inputs` is indexed by proto-input /// position; [`sources`](LayoutMeta::sources) selects the base layouts, which