HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UN_Node.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UN_Node.h ( UN Library, C++)
7  *
8  * COMMENTS:
9  *
10  */
11 
12 #ifndef __UN_Node_h__
13 #define __UN_Node_h__
14 
15 #include "UN_API.h"
16 #include "UN_Iterator.h"
17 #include "UN_Handle.h"
18 #include "UN_Parm.h" // for ParmIterator implementation
19 #include "UN_Port.h" // for PortIterator implementation
20 
21 #include <UT/UT_StringHolder.h>
22 
23 
24 class UN_Graph;
25 class UT_Options;
26 
27 
28 // ============================================================================
29 /// A light-weight handle for a node data.
30 ///
31 /// The actual node data (UN_NodeData) is owned and managed by UN_GraphData.
32 /// UN_Node serves as a handle for clients to refer to that node data.
33 
34 // TODO: FIXME: consider constant handles too, UN_ConstNode, to enforce
35 // const-correctness:
36 // - they hold 'const UN_GraphData*' and can call only const functions
37 // - they have methods that access graph, but never modify it
38 // - UN_Node is a subclass of UN_ConstNode and adds methods
39 // that modify the graph.
40 // - it takes non-const 'UN_GraphData *' as now, and passes it as
41 // to base constructor, but is able to cast away constness
42 // to regain non-const data to operate on
43 // - This allows having const iterators, that can just reference index
44 // arrays, since there is no danger of such arrays getting reallocated,
45 // because adding new data objects inside the loop would not be allowed.
46 // Eg, currently UN_Node::childRange() makes a copy of index array.
47 // The child node ID could also be looked up on demand, when
48 // dereferencing iterator, instad of pre-fetching it into an ID array.
49 
50 class UN_API UN_Node : public UN_Handle
51 {
52 public:
53  /// Convenience constructor for the node handle.
54  UN_Node( UN_GraphData *graph_data,
55  UN_NodeIndex node_index,
56  UN_NodeID node_id );
57 
58  /// @{ Default constructors and assignment operators.
59  UN_Node();
60  ~UN_Node();
61  UN_Node( const UN_Node& );
62  UN_Node( UN_Node&& );
63  UN_Node & operator=( const UN_Node& );
64  UN_Node & operator=( UN_Node&& );
65  /// @}
66 
67 
68  /// @{ Returns true if this is a valid node; false otherwise.
69  bool isValid() const;
70  explicit operator bool() const
71  { return isValid(); }
72  /// @}
73 
74 
75  /// @{ Comparison operators
76  bool operator==( const UN_Node &other ) const
77  { return UN_Handle::operator==( other ); }
78  bool operator!=( const UN_Node &other ) const
79  { return UN_Handle::operator!=( other ); }
80  /// @}
81 
82  /// Returns the graph which owns this node.
83  UN_Graph graph() const;
84 
85  /// Returns the parent of this node.
86  UN_Node parent() const;
87 
88 
89  /// @{ The node name that differentiates it among its siblings.
90  const UT_StringHolder & name() const;
91  void setName( const UT_StringRef &name ) const;
92  /// @}
93 
94  /// @{ The node's type that determines its functional behavour.
95  const UT_StringHolder & typeName() const;
96  void setTypeName(
97  const UT_StringRef &type_name ) const;
98  /// @}
99 
100  /// @{ Sets and gets the node's category that groups it with other nodes
101  /// that are operationally compatible (and connectable).
102  const UT_StringHolder & categoryName() const;
103  void setCategoryName(
104  const UT_StringRef &category ) const;
105  /// @}
106 
107 
108  /// Deletes this node from the graph.
109  void destroy() const;
110 
111 
112  /// Adds and returns a new parameter to this node.
113  /// If another parameter of a given name already exists, returns an
114  /// invalid parameter, indicating a failure due to the name collision.
115  UN_Parm createParm( const UT_StringRef &parm_name,
116  const UT_StringRef &parm_type_name =
117  UN_UNDEFINED_PARM_TYPE_NAME.asRef()
118  ) const;
119 
120  /// Returns a parameter by the given name, or null if not found.
121  UN_Parm findParm( const UT_StringRef &parm_name ) const;
122 
123  /// Returns the names of the node parameters.
124  UT_Array< UT_StringHolder > parmNames() const;
125 
126  /// An iterator and a range for parameters that belong to this node.
127  using ParmIterator =
130 
131  /// Returns a range for iterating over node parameters.
132  ParmRange parmRange() const;
133 
134 
135  /// Adds and returns a new port to this node.
136  /// If another port of a given kind and name already exists, returns an
137  /// invalid port, indicating a failure due to the name collision.
138  UN_Port createPort( UN_PortKind port_kind,
139  const UT_StringRef &port_name,
140  const UT_StringRef &port_type_name =
141  UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const;
142 
143  /// Returns a input port by the given name, or null if not found.
144  UN_Port findPort( UN_PortKind port_kind,
145  const UT_StringRef &port_name ) const;
146 
147  /// Returns the names of the node ports of a given kind
148  UT_Array< UT_StringHolder > portNames( UN_PortKind port_kind ) const;
149 
150  /// And iterator and a range for ports that belong to this node.
151  using PortIterator =
154 
155  /// Returns a range for iterating over node input ports.
156  PortRange portRange( UN_PortKind port_kind ) const;
157 
158 
159  /// Adds and returns a new input port to this node.
160  /// If another input port of a given name already exists, returns an
161  /// invalid port, indicating a failure due to the name collision.
163  const UT_StringRef &port_type_name =
164  UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const
165  {
166  return createPort( UN_PortKind::INPUT,
167  port_name, port_type_name );
168  }
169 
170 
171  /// Returns a input port by the given name, or null if not found.
172  UN_Port findInputPort( const UT_StringRef &port_name ) const
173  { return findPort(UN_PortKind::INPUT, port_name); }
174 
175  /// Returns the names of the node input ports.
177  { return portNames(UN_PortKind::INPUT); }
178 
179  /// Returns a range for iterating over node input ports.
181  { return portRange( UN_PortKind::INPUT ); }
182 
183  /// Returns true if any of the node's input ports has a connected source.
184  /// Ie, if the node is not a leaf in the tree formed by input chains.
185  bool hasConnectedInputPortSource() const;
186 
187 
188  /// Adds and returns a new output port to this node.
189  /// If another outupt port of a given name already exists, returns an
190  /// invalid port, indicating a failure due to the name collision.
192  const UT_StringRef &port_type_name =
193  UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const
194  {
195  return createPort( UN_PortKind::OUTPUT,
196  port_name, port_type_name );
197  }
198 
199  /// Returns an output port by the given name, or null if not found.
200  UN_Port findOutputPort( const UT_StringRef &port_name ) const
201  { return findPort(UN_PortKind::OUTPUT, port_name); }
202 
203  /// Returns the names of the node output ports.
205  { return portNames(UN_PortKind::OUTPUT); }
206 
207  /// Returns a range for iterating over node output ports.
209  { return portRange( UN_PortKind::OUTPUT ); }
210 
211  /// Returns true if any of the nodes output ports has a connected
212  /// destination. Ie, if the node is not a terminal node.
213  /// Ie, if hte node is not a root in the tree formed by input chains.
214  bool hasConnectedOutputPortDestination() const;
215 
216 
217  /// Returns a node name that is not taken by any of this nodes' children.
218  UT_StringHolder findUniqueChildName( const UT_StringRef &name ) const;
219 
220  /// Creates and returns a new node that is a child of this node.
221  /// @param child_name - The name of the node that uniquely identifies it
222  /// among other children inside this network.
223  UN_Node createChild(
224  const UT_StringRef &child_name = UT_StringRef(),
225  const UT_StringRef &child_type = UT_StringRef(),
226  const UT_StringRef &child_category =
227  UT_StringRef()) const;
228 
229  /// Returns the child node by the given name.
230  /// Note, the return object may be invalid if no such child node was found.
231  UN_Node findChild( const UT_StringRef &child_name ) const;
232 
233  /// Removes and deletes the child node from this network.
234  void deleteChild( const UT_StringRef &child_name ) const;
235 
236  /// Returns true if the node has immediate child nodes.
237  bool hasChildren() const;
238 
239  /// Returns the names of the node children nodes.
240  UT_Array< UT_StringHolder > childNames() const;
241 
242  /// An iterator and a range for the children of this parent node.
243  using ChildIterator =
246 
247  /// Returns a range for iterating over node's immediate children.
248  ChildRange childRange() const;
249 
250  /// An iterator and a range for the descendants (children, grandchildren,
251  /// etc) of this ancestor node.
254 
255  /// Returns a range for iterating over nodes's descendants
256  /// (ie, children, and their grand children, etc).
257  DescendantRange descendantRange() const;
258 
259 
260  /// An iterator and a range for the connection wires between immediate
261  /// children inside this node.
262  /// (And also direct wires between inputs and outputs on this node).
263  using ChildWireIterator = UN_NodeWireIterator< /*child_only=*/ true >;
265 
266  /// Returns a range for iterating over the connection wires between
267  /// this node's immediate children.
268  /// (And also direct wires between inputs and outputs on this node).
269  ChildWireRange childWireRange() const;
270 
271 
272  /// An iterator and a range for the connection wires between
273  /// the descendants inside this node.
274  /// (And also direct wires between inputs and outputs on this node).
275  using DescendantWireIterator = UN_NodeWireIterator< /*child_only=*/ false >;
277 
278  /// Returns a range for iterating over the connection wires between
279  /// this node's descendants (ie, its children and grandchildren, etc).
280  /// (And also direct wires between inputs and outputs on this node).
281  DescendantWireRange descendantWireRange() const;
282 
283 
284  /// Returns the options object representing this node.
285  /// This can be then used for serialization to JSON, etc.
286  UT_Options asOptions() const;
287 
288  /// Configure the node based on the given options.
289  void setFromOptions( const UT_Options &node_opts ) const;
290 
291 
292  /// Returns the node data index this handle refers to.
294  { return UN_NodeIndex( dataIndex() ); }
295 
296  /// Returns the unique ID of the node data this handle refers to.
298  { return UN_NodeID( dataID() ); }
299 };
300 
301 
302 #endif
303 
UN_Port findInputPort(const UT_StringRef &port_name) const
Returns a input port by the given name, or null if not found.
Definition: UN_Node.h:172
UN_Port findOutputPort(const UT_StringRef &port_name) const
Returns an output port by the given name, or null if not found.
Definition: UN_Node.h:200
UN_PortKind
Differentiates input node ports from output node ports.
Definition: UN_Types.h:322
UN_DataID dataID() const
The unique ID of a data object during the lifespan of the owner graph.
Definition: UN_Handle.h:74
UT_Array< UT_StringHolder > inputPortNames() const
Returns the names of the node input ports.
Definition: UN_Node.h:176
UN_Port createOutputPort(const UT_StringRef &port_name, const UT_StringRef &port_type_name=UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const
Definition: UN_Node.h:191
bool operator!=(const UN_Node &other) const
Comparison operators.
Definition: UN_Node.h:78
#define UN_API
Definition: UN_API.h:11
bool operator==(const UN_Handle &other) const
Comparison operators.
Definition: UN_Handle.h:53
UN_NodeIndex nodeIndex() const
Returns the node data index this handle refers to.
Definition: UN_Node.h:293
UT_Array< UT_StringHolder > outputPortNames() const
Returns the names of the node output ports.
Definition: UN_Node.h:204
UN_DataIndex dataIndex() const
Definition: UN_Handle.h:70
PortRange inputPortRange() const
Returns a range for iterating over node input ports.
Definition: UN_Node.h:180
constexpr std::enable_if< I< type_count_base< T >::value, int >::type tuple_type_size(){return subtype_count< typename std::tuple_element< I, T >::type >::value+tuple_type_size< T, I+1 >);}template< typename T > struct type_count< T, typename std::enable_if< is_tuple_like< T >::value >::type >{static constexpr int value{tuple_type_size< T, 0 >)};};template< typename T > struct subtype_count{static constexpr int value{is_mutable_container< T >::value?expected_max_vector_size:type_count< T >::value};};template< typename T, typename Enable=void > struct type_count_min{static const int value{0};};template< typename T >struct type_count_min< T, typename std::enable_if<!is_mutable_container< T >::value &&!is_tuple_like< T >::value &&!is_wrapper< T >::value &&!is_complex< T >::value &&!std::is_void< T >::value >::type >{static constexpr int value{type_count< T >::value};};template< typename T > struct type_count_min< T, typename std::enable_if< is_complex< T >::value >::type >{static constexpr int value{1};};template< typename T >struct type_count_min< T, typename std::enable_if< is_wrapper< T >::value &&!is_complex< T >::value &&!is_tuple_like< T >::value >::type >{static constexpr int value{subtype_count_min< typename T::value_type >::value};};template< typename T, std::size_t I >constexpr typename std::enable_if< I==type_count_base< T >::value, int >::type tuple_type_size_min(){return 0;}template< typename T, std::size_t I > constexpr typename std::enable_if< I< type_count_base< T >::value, int >::type tuple_type_size_min(){return subtype_count_min< typename std::tuple_element< I, T >::type >::value+tuple_type_size_min< T, I+1 >);}template< typename T > struct type_count_min< T, typename std::enable_if< is_tuple_like< T >::value >::type >{static constexpr int value{tuple_type_size_min< T, 0 >)};};template< typename T > struct subtype_count_min{static constexpr int value{is_mutable_container< T >::value?((type_count< T >::value< expected_max_vector_size)?type_count< T >::value:0):type_count_min< T >::value};};template< typename T, typename Enable=void > struct expected_count{static const int value{0};};template< typename T >struct expected_count< T, typename std::enable_if<!is_mutable_container< T >::value &&!is_wrapper< T >::value &&!std::is_void< T >::value >::type >{static constexpr int value{1};};template< typename T > struct expected_count< T, typename std::enable_if< is_mutable_container< T >::value >::type >{static constexpr int value{expected_max_vector_size};};template< typename T >struct expected_count< T, typename std::enable_if<!is_mutable_container< T >::value &&is_wrapper< T >::value >::type >{static constexpr int value{expected_count< typename T::value_type >::value};};enum class object_category:int{char_value=1, integral_value=2, unsigned_integral=4, enumeration=6, boolean_value=8, floating_point=10, number_constructible=12, double_constructible=14, integer_constructible=16, string_assignable=23, string_constructible=24, other=45, wrapper_value=50, complex_number=60, tuple_value=70, container_value=80,};template< typename T, typename Enable=void > struct classify_object{static constexpr object_category value{object_category::other};};template< typename T >struct classify_object< T, typename std::enable_if< std::is_integral< T >::value &&!std::is_same< T, char >::value &&std::is_signed< T >::value &&!is_bool< T >::value &&!std::is_enum< T >::value >::type >{static constexpr object_category value{object_category::integral_value};};template< typename T >struct classify_object< T, typename std::enable_if< std::is_integral< T >::value &&std::is_unsigned< T >::value &&!std::is_same< T, char >::value &&!is_bool< T >::value >::type >{static constexpr object_category value{object_category::unsigned_integral};};template< typename T >struct classify_object< T, typename std::enable_if< std::is_same< T, char >::value &&!std::is_enum< T >::value >::type >{static constexpr object_category value{object_category::char_value};};template< typename T > struct classify_object< T, typename std::enable_if< is_bool< T >::value >::type >{static constexpr object_category value{object_category::boolean_value};};template< typename T > struct classify_object< T, typename std::enable_if< std::is_floating_point< T >::value >::type >{static constexpr object_category value{object_category::floating_point};};template< typename T >struct classify_object< T, typename std::enable_if<!std::is_floating_point< T >::value &&!std::is_integral< T >::value &&std::is_assignable< T &, std::string >::value >::type >{static constexpr object_category value{object_category::string_assignable};};template< typename T >struct classify_object< T, typename std::enable_if<!std::is_floating_point< T >::value &&!std::is_integral< T >::value &&!std::is_assignable< T &, std::string >::value &&(type_count< T >::value==1)&&std::is_constructible< T, std::string >::value >::type >{static constexpr object_category value{object_category::string_constructible};};template< typename T > struct classify_object< T, typename std::enable_if< std::is_enum< T >::value >::type >{static constexpr object_category value{object_category::enumeration};};template< typename T > struct classify_object< T, typename std::enable_if< is_complex< T >::value >::type >{static constexpr object_category value{object_category::complex_number};};template< typename T > struct uncommon_type{using type=typename std::conditional<!std::is_floating_point< T >::value &&!std::is_integral< T >::value &&!std::is_assignable< T &, std::string >::value &&!std::is_constructible< T, std::string >::value &&!is_complex< T >::value &&!is_mutable_container< T >::value &&!std::is_enum< T >::value, std::true_type, std::false_type >::type;static constexpr bool value=type::value;};template< typename T >struct classify_object< T, typename std::enable_if<(!is_mutable_container< T >::value &&is_wrapper< T >::value &&!is_tuple_like< T >::value &&uncommon_type< T >::value)>::type >{static constexpr object_category value{object_category::wrapper_value};};template< typename T >struct classify_object< T, typename std::enable_if< uncommon_type< T >::value &&type_count< T >::value==1 &&!is_wrapper< T >::value &&is_direct_constructible< T, double >::value &&is_direct_constructible< T, int >::value >::type >{static constexpr object_category value{object_category::number_constructible};};template< typename T >struct classify_object< T, typename std::enable_if< uncommon_type< T >::value &&type_count< T >::value==1 &&!is_wrapper< T >::value &&!is_direct_constructible< T, double >::value &&is_direct_constructible< T, int >::value >::type >{static constexpr object_category value{object_category::integer_constructible};};template< typename T >struct classify_object< T, typename std::enable_if< uncommon_type< T >::value &&type_count< T >::value==1 &&!is_wrapper< T >::value &&is_direct_constructible< T, double >::value &&!is_direct_constructible< T, int >::value >::type >{static constexpr object_category value{object_category::double_constructible};};template< typename T >struct classify_object< T, typename std::enable_if< is_tuple_like< T >::value &&((type_count< T >::value >=2 &&!is_wrapper< T >::value)||(uncommon_type< T >::value &&!is_direct_constructible< T, double >::value &&!is_direct_constructible< T, int >::value)||(uncommon_type< T >::value &&type_count< T >::value >=2))>::type >{static constexpr object_category value{object_category::tuple_value};};template< typename T > struct classify_object< T, typename std::enable_if< is_mutable_container< T >::value >::type >{static constexpr object_category value{object_category::container_value};};template< typename T, enable_if_t< classify_object< T >::value==object_category::char_value, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"CHAR";}template< typename T, enable_if_t< classify_object< T >::value==object_category::integral_value||classify_object< T >::value==object_category::integer_constructible, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"INT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::unsigned_integral, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"UINT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::floating_point||classify_object< T >::value==object_category::number_constructible||classify_object< T >::value==object_category::double_constructible, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"FLOAT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::enumeration, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"ENUM";}template< typename T, enable_if_t< classify_object< T >::value==object_category::boolean_value, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"BOOLEAN";}template< typename T, enable_if_t< classify_object< T >::value==object_category::complex_number, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"COMPLEX";}template< typename T, enable_if_t< classify_object< T >::value >=object_category::string_assignable &&classify_object< T >::value<=object_category::other, detail::enabler >=detail::dummy >constexpr const char *type_name(){return"TEXT";}template< typename T, enable_if_t< classify_object< T >::value==object_category::tuple_value &&type_count_base< T >::value >=2, detail::enabler >=detail::dummy >std::string type_name();template< typename T, enable_if_t< classify_object< T >::value==object_category::container_value||classify_object< T >::value==object_category::wrapper_value, detail::enabler >=detail::dummy >std::string type_name();template< typename T, enable_if_t< classify_object< T >::value==object_category::tuple_value &&type_count_base< T >::value==1, detail::enabler >=detail::dummy >inline std::string type_name(){return type_name< typename std::decay< typename std::tuple_element< 0, T >::type >::type >);}template< typename T, std::size_t I >inline typename std::enable_if< I==type_count_base< T >::value, std::string >::type tuple_name(){return std::string{};}template< typename T, std::size_t I >inline typename std::enable_if<(I< type_count_base< T >::value), std::string >::type tuple_name(){auto str=std::string{type_name< typename std::decay< typename std::tuple_element< I, T >::type >::type >)}+ ','+tuple_name< T, I+1 >);if(str.back()== ',') str.pop_back();return str;}template< typename T, enable_if_t< classify_object< T >::value==object_category::tuple_value &&type_count_base< T >::value >=2, detail::enabler > > std::string type_name()
Recursively generate the tuple type name.
Definition: CLI11.h:1729
bool operator!=(const UN_Handle &other) const
Comparison operators.
Definition: UN_Handle.h:60
UN_NodeID nodeID() const
Returns the unique ID of the node data this handle refers to.
Definition: UN_Node.h:297
UN_Handle & operator=(const UN_Handle &)=default
Default destructor, constructors and assignment operators.
GLuint const GLchar * name
Definition: glcorearb.h:786
A map of string to various well defined value types.
Definition: UT_Options.h:84
UN_Port createInputPort(const UT_StringRef &port_name, const UT_StringRef &port_type_name=UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const
Definition: UN_Node.h:162
bool operator==(const UN_Node &other) const
Comparison operators.
Definition: UN_Node.h:76
PortRange outputPortRange() const
Returns a range for iterating over node output ports.
Definition: UN_Node.h:208
An node ID.
Definition: UN_Types.h:273