@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
22
33use graph_craft:: document:: value:: TaggedValue ;
44use graph_craft:: document:: { DocumentNodeImplementation , InlineRust , NodeInput } ;
5- use graph_craft:: { Type , concrete} ;
5+ use graph_craft:: { ProtoNodeIdentifier , Type , concrete} ;
66use graphene_std:: uuid:: NodeId ;
77use interpreted_executor:: dynamic_executor:: { NodeTypes , ResolvedDocumentNodeTypesDelta } ;
88use interpreted_executor:: node_registry:: NODE_REGISTRY ;
@@ -43,6 +43,32 @@ pub enum TypeSource {
4343}
4444
4545impl TypeSource {
46+ /// The reduced set of frontend types for displaying color.
47+ pub fn displayed_type ( & self ) -> FrontendGraphDataType {
48+ match self . compiled_nested_type ( ) {
49+ Some ( nested_type) => match TaggedValue :: from_type_or_none ( nested_type) {
50+ TaggedValue :: U32 ( _)
51+ | TaggedValue :: U64 ( _)
52+ | TaggedValue :: F32 ( _)
53+ | TaggedValue :: F64 ( _)
54+ | TaggedValue :: DVec2 ( _)
55+ | TaggedValue :: F64Array4 ( _)
56+ | TaggedValue :: VecF64 ( _)
57+ | TaggedValue :: VecDVec2 ( _)
58+ | TaggedValue :: DAffine2 ( _) => FrontendGraphDataType :: Number ,
59+ TaggedValue :: Artboard ( _) => FrontendGraphDataType :: Artboard ,
60+ TaggedValue :: Graphic ( _) => FrontendGraphDataType :: Graphic ,
61+ TaggedValue :: Raster ( _) => FrontendGraphDataType :: Raster ,
62+ TaggedValue :: Vector ( _) => FrontendGraphDataType :: Vector ,
63+ TaggedValue :: Color ( _) => FrontendGraphDataType :: Color ,
64+ TaggedValue :: Gradient ( _) | TaggedValue :: GradientStops ( _) | TaggedValue :: GradientTable ( _) => FrontendGraphDataType :: Gradient ,
65+ TaggedValue :: String ( _) => FrontendGraphDataType :: Typography ,
66+ _ => FrontendGraphDataType :: General ,
67+ } ,
68+ None => FrontendGraphDataType :: General ,
69+ }
70+ }
71+
4672 pub fn compiled_nested_type ( & self ) -> Option < & Type > {
4773 match self {
4874 TypeSource :: Compiled ( compiled_type) => Some ( compiled_type. nested_type ( ) ) ,
@@ -71,14 +97,6 @@ impl TypeSource {
7197 TypeSource :: Error ( _) => "Error" . to_string ( ) ,
7298 }
7399 }
74-
75- /// The reduced set of frontend types for displaying color.
76- pub fn displayed_type ( & self ) -> FrontendGraphDataType {
77- match self . compiled_nested_type ( ) {
78- Some ( nested_type) => FrontendGraphDataType :: from_type ( nested_type) ,
79- None => FrontendGraphDataType :: General ,
80- }
81- }
82100}
83101
84102impl NodeNetworkInterface {
@@ -126,7 +144,7 @@ impl NodeNetworkInterface {
126144 TypeSource :: TaggedValue ( value) => value,
127145 TypeSource :: DocumentNodeDefinition ( definition) => definition,
128146 TypeSource :: Unknown => {
129- let mut valid_types = self . valid_input_types ( input_connector, network_path) ;
147+ let mut valid_types = self . potential_valid_input_types ( input_connector, network_path) ;
130148
131149 match valid_types. pop ( ) {
132150 Some ( valid_type) => valid_type,
@@ -147,7 +165,8 @@ impl NodeNetworkInterface {
147165 TaggedValue :: from_type_or_none ( & guaranteed_type)
148166 }
149167
150- pub fn valid_input_types ( & mut self , input_connector : & InputConnector , network_path : & [ NodeId ] ) -> Vec < Type > {
168+ /// A list of all valid input types for this specific node.
169+ pub fn potential_valid_input_types ( & mut self , input_connector : & InputConnector , network_path : & [ NodeId ] ) -> Vec < Type > {
151170 let InputConnector :: Node { node_id, input_index } = input_connector else {
152171 // An export can have any type connected to it
153172 return vec ! [ graph_craft:: generic!( T ) ] ;
@@ -171,7 +190,7 @@ impl NodeNetworkInterface {
171190 let intersection: HashSet < Type > = inputs_from_import
172191 . clone ( )
173192 . iter ( )
174- . map ( |input_connector| self . valid_input_types ( input_connector, & nested_path) . into_iter ( ) . collect :: < HashSet < _ > > ( ) )
193+ . map ( |input_connector| self . potential_valid_input_types ( input_connector, & nested_path) . into_iter ( ) . collect :: < HashSet < _ > > ( ) )
175194 . fold ( None , |acc : Option < HashSet < Type > > , set| match acc {
176195 Some ( acc_set) => Some ( acc_set. intersection ( & set) . cloned ( ) . collect ( ) ) ,
177196 None => Some ( set) ,
@@ -191,10 +210,9 @@ impl NodeNetworkInterface {
191210 . filter_map ( |( node_io, _) | {
192211 let valid_implementation = ( 0 ..number_of_inputs) . filter ( |iterator_index| iterator_index != input_index) . all ( |iterator_index| {
193212 let input_type = self . input_type ( & InputConnector :: node ( * node_id, iterator_index) , network_path) ;
194- // Value inputs are stored as concrete, so they are compared to the nested type. Node inputs are stored as fn, so they are compared to the entire type.
195- // For example a node input of (Footprint) -> Vector would not be compatible with () -> Vector
196- node_io. inputs . get ( iterator_index) . map ( |ty| ty. nested_type ( ) . clone ( ) ) . as_ref ( ) == input_type. compiled_nested_type ( )
197- || node_io. inputs . get ( iterator_index) == input_type. compiled_nested_type ( )
213+ // TODO: Fix type checking for different call arguments
214+ // For example a node input of (Footprint) -> Vector would not be compatible with a node that is called with () and returns Vector
215+ node_io. inputs . get ( iterator_index) . map ( |ty| ty. nested_type ( ) ) == input_type. compiled_nested_type ( )
198216 } ) ;
199217 if valid_implementation { node_io. inputs . get ( * input_index) . cloned ( ) } else { None }
200218 } )
@@ -207,6 +225,66 @@ impl NodeNetworkInterface {
207225 }
208226 }
209227
228+ /// Performs a downstream traversal to ensure input type will work in the full context of the graph.
229+ pub fn complete_valid_input_types ( & mut self , input_connector : & InputConnector , network_path : & [ NodeId ] ) -> Result < Vec < Type > , String > {
230+ match input_connector {
231+ InputConnector :: Node { node_id, input_index } => {
232+ let Some ( implementation) = self . implementation ( node_id, network_path) else {
233+ return Err ( format ! ( "Could not get node implementation for {:?} {} in valid_input_types" , network_path, * node_id) ) ;
234+ } ;
235+ match implementation {
236+ DocumentNodeImplementation :: Network ( _) => self . valid_output_types ( & OutputConnector :: Import ( input_connector. input_index ( ) ) , & [ network_path, & [ * node_id] ] . concat ( ) ) ,
237+ DocumentNodeImplementation :: ProtoNode ( proto_node_identifier) => {
238+ let Some ( implementations) = NODE_REGISTRY . get ( proto_node_identifier) else {
239+ return Err ( format ! ( "Protonode {proto_node_identifier:?} not found in registry" ) ) ;
240+ } ;
241+ let valid_output_types = match self . valid_output_types ( & OutputConnector :: node ( * node_id, 0 ) , network_path) {
242+ Ok ( valid_types) => valid_types,
243+ Err ( e) => return Err ( e) ,
244+ } ;
245+
246+ let valid_types = implementations
247+ . iter ( )
248+ . filter_map ( |( node_io, _) | {
249+ if !valid_output_types. iter ( ) . any ( |output_type| output_type. nested_type ( ) == node_io. return_value . nested_type ( ) ) {
250+ return None ;
251+ }
252+
253+ let valid_inputs = ( 0 ..node_io. inputs . len ( ) ) . filter ( |iterator_index| iterator_index != input_index) . all ( |iterator_index| {
254+ let input_type = self . input_type ( & InputConnector :: node ( * node_id, iterator_index) , network_path) ;
255+ match input_type. compiled_nested_type ( ) {
256+ Some ( input_type) => node_io. inputs . get ( iterator_index) . is_some_and ( |node_io_input_type| node_io_input_type. nested_type ( ) == input_type) ,
257+ None => true ,
258+ }
259+ } ) ;
260+ if valid_inputs { node_io. inputs . get ( * input_index) . cloned ( ) } else { None }
261+ } )
262+ . collect :: < Vec < _ > > ( ) ;
263+ Ok ( valid_types)
264+ }
265+ DocumentNodeImplementation :: Extract => {
266+ log:: error!( "Input types for extract node not supported" ) ;
267+ Ok ( Vec :: new ( ) )
268+ }
269+ }
270+ }
271+ InputConnector :: Export ( export_index) => {
272+ match network_path. split_last ( ) {
273+ Some ( ( encapsulating_node, encapsulating_path) ) => self . valid_output_types ( & OutputConnector :: node ( * encapsulating_node, * export_index) , encapsulating_path) ,
274+ None => {
275+ // Valid types for the export are all types that can be fed into the render node
276+ // TODO: Use ::IDENTIFIER
277+ let render_node = "graphene_std::wasm_application_io::RenderNode" ;
278+ let Some ( implementations) = NODE_REGISTRY . get ( & ProtoNodeIdentifier :: new ( render_node) ) else {
279+ return Err ( format ! ( "Protonode {render_node:?} not found in registry" ) ) ;
280+ } ;
281+ Ok ( implementations. iter ( ) . map ( |( types, _) | types. inputs [ 1 ] . clone ( ) ) . collect ( ) )
282+ }
283+ }
284+ }
285+ }
286+ }
287+
210288 pub fn output_type ( & mut self , output_connector : & OutputConnector , network_path : & [ NodeId ] ) -> TypeSource {
211289 match output_connector {
212290 OutputConnector :: Node { node_id, output_index } => {
@@ -243,7 +321,7 @@ impl NodeNetworkInterface {
243321 let intersection = inputs_from_import
244322 . clone ( )
245323 . iter ( )
246- . map ( |input_connector| self . valid_input_types ( input_connector, & network_path) . into_iter ( ) . collect :: < HashSet < _ > > ( ) )
324+ . map ( |input_connector| self . potential_valid_input_types ( input_connector, & network_path) . into_iter ( ) . collect :: < HashSet < _ > > ( ) )
247325 . fold ( None , |acc : Option < HashSet < Type > > , set| match acc {
248326 Some ( acc_set) => Some ( acc_set. intersection ( & set) . cloned ( ) . collect ( ) ) ,
249327 None => Some ( set) ,
@@ -281,7 +359,7 @@ impl NodeNetworkInterface {
281359 log:: error!( "Protonode {proto_node_identifier:?} not found in registry" ) ;
282360 return None ;
283361 } ;
284- implementations. keys ( ) . next ( ) . and_then ( |node_io| node_io. inputs . get ( input_connector. input_index ( ) ) ) . cloned ( )
362+ implementations. keys ( ) . min ( ) . and_then ( |node_io| node_io. inputs . get ( input_connector. input_index ( ) ) ) . cloned ( )
285363 }
286364 DocumentNodeImplementation :: Extract => None ,
287365 }
0 commit comments