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 class UN_NodeData;
27 
28 
29 // ============================================================================
30 /// A light-weight handle for a node data.
31 ///
32 /// The actual node data is owned and managed by UN_GraphData.
33 /// UN_Node serves as a handle for clients to refer to that node data.
34 
35 // TODO: FIXME: consider constant handles too, UN_ConstNode, to enforce
36 // const-correctness:
37 // - they hold 'const UN_GraphData*' and can call only const functions
38 // - they have methods that access graph, but never modify it
39 // - UN_Node is a subclass of UN_ConstNode and adds methods
40 // that modify the graph.
41 // - it takes non-const 'UN_GraphData *' as now, and passes it as
42 // to base constructor, but is able to cast away constness
43 // to regain non-const data to operate on
44 // - This allows having const iterators, that can just reference index
45 // arrays, since there is no danger of such arrays getting reallocated,
46 // because adding new data objects inside the loop would not be allowed.
47 // Eg, currently UN_Node::childRange() makes a copy of index array.
48 // The child node ID could also be looked up on demand, when
49 // dereferencing iterator, instad of pre-fetching it into an ID array.
50 
51 class UN_API UN_Node : public UN_Handle
52 {
53 public:
54  /// Convenience constructor for the node handle.
55  UN_Node( UN_GraphData *graph_data, UN_NodeID node_id );
56 
57  /// @{ Default constructors and assignment operators.
58  UN_Node();
59  ~UN_Node();
60  UN_Node( const UN_Node& );
61  UN_Node( UN_Node&& );
62  UN_Node & operator=( const UN_Node& );
63  UN_Node & operator=( UN_Node&& );
64  /// @}
65 
66 
67  /// @{ Returns true if this is a valid node; false otherwise.
68  bool isValid() const;
69  explicit operator bool() const
70  { return isValid(); }
71  /// @}
72 
73 
74  /// @{ Comparison operators
75  bool operator==( const UN_Node &other ) const
76  { return UN_Handle::operator==( other ); }
77  bool operator!=( const UN_Node &other ) const
78  { return UN_Handle::operator!=( other ); }
79  /// @}
80 
81  /// Returns the graph which owns this node.
82  UN_Graph graph() const;
83 
84  /// Returns the parent of this node.
85  UN_Node parent() const;
86 
87 
88  /// @{ The node name that differentiates it among its siblings.
89  const UT_StringHolder & name() const;
90  void setName( const UT_StringRef &name ) const;
91  /// @}
92 
93  /// @{ The node's type that determines its functional behavour.
94  const UT_StringHolder & typeName() const;
95  void setTypeName(
96  const UT_StringRef &type_name ) const;
97  /// @}
98 
99  /// @{ Sets and gets the node's category that groups it with other nodes
100  /// that are operationally compatible (and connectable).
101  const UT_StringHolder & categoryName() const;
102  void setCategoryName(
103  const UT_StringRef &category ) const;
104  /// @}
105 
106 
107  /// Deletes this node from the graph.
108  void destroy() const;
109 
110 
111  /// Adds and returns a new parameter to this node.
112  /// If another parameter of a given name already exists, returns an
113  /// invalid parameter, indicating a failure due to the name collision.
114  UN_Parm createParm( const UT_StringRef &parm_name,
115  const UT_StringRef &parm_type_name =
116  UN_UNDEFINED_PARM_TYPE_NAME.asRef()
117  ) const;
118 
119  /// Returns a parameter by the given name, or null if not found.
120  UN_Parm findParm( const UT_StringRef &parm_name ) const;
121 
122  /// Returns the names of the node parameters.
123  UT_Array< UT_StringHolder > parmNames() const;
124 
125  /// An iterator and a range for parameters that belong to this node.
128 
129  /// Returns a range for iterating over node parameters.
130  ParmRange parmRange() const;
131 
132 
133  /// Adds and returns a new port to this node.
134  /// If another port of a given kind and name already exists, returns an
135  /// invalid port, indicating a failure due to the name collision.
136  UN_Port createPort( UN_PortKind port_kind,
137  const UT_StringRef &port_name,
138  const UT_StringRef &port_type_name =
139  UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const;
140 
141  /// Returns a input port by the given name, or null if not found.
142  UN_Port findPort( UN_PortKind port_kind,
143  const UT_StringRef &port_name ) const;
144 
145  /// Returns the names of the node ports of a given kind
146  UT_Array< UT_StringHolder > portNames( UN_PortKind port_kind ) const;
147 
148  /// And iterator and a range for ports that belong to this node.
151 
152  /// Returns a range for iterating over node input ports.
153  PortRange portRange( UN_PortKind port_kind ) const;
154 
155 
156  /// Adds and returns a new input port to this node.
157  /// If another input port of a given name already exists, returns an
158  /// invalid port, indicating a failure due to the name collision.
160  const UT_StringRef &port_type_name =
161  UN_UNDEFINED_PORT_TYPE_NAME.asRef()) const
162  {
163  return createPort( UN_PortKind::Input,
164  port_name, port_type_name );
165  }
166 
167 
168  /// Returns a input port by the given name, or null if not found.
169  UN_Port findInputPort( const UT_StringRef &port_name ) const
170  { return findPort(UN_PortKind::Input, port_name); }
171 
172  /// Returns the names of the node input ports.
174  { return portNames(UN_PortKind::Input); }
175 
176  /// Returns a range for iterating over node input ports.
178  { return portRange( UN_PortKind::Input ); }
179 
180  /// Returns true if any of the node's input ports has a connected source
181  /// wire feeding data from a source port.
182  /// In other words, if the node is not a leaf in the tree formed by
183  /// input chains in the subnet, ie, the node is not an original data
184  /// source in the subnet.
185  bool hasAnyInputPortSrcWires() 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 node's output ports has a connected
212  /// destination wire feeding data to a destination port.
213  /// In other woreds, if the node is not a terminal node, ie, if the node
214  /// is not a root in a tree formed by the input chains in the subnet.
215  bool hasAnyOutputPortDstWires() const;
216 
217 
218  /// Returns a node name that is not taken by any of this nodes' children.
219  UT_StringHolder findUniqueChildName( const UT_StringRef &name ) const;
220 
221  /// Creates and returns a new node that is a child of this node.
222  /// @param child_name - The name of the node that uniquely identifies it
223  /// among other children inside this network.
224  UN_Node createChild(
225  const UT_StringRef &child_name = UT_StringRef(),
226  const UT_StringRef &child_type = UT_StringRef(),
227  const UT_StringRef &child_category =
228  UT_StringRef()) const;
229 
230  /// Returns the child node by the given name.
231  /// Note, the return object may be invalid if no such child node was found.
232  UN_Node findChild( const UT_StringRef &child_name ) const;
233 
234  /// Removes and deletes the child node from this network.
235  void deleteChild( const UT_StringRef &child_name ) const;
236 
237  /// Returns true if the node can have child nodes inside.
238  bool isSubnet() const;
239 
240  /// Returns the names of the node children nodes.
241  UT_Array< UT_StringHolder > childNames() const;
242 
243  /// An iterator and a range for the children of this parent node.
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  /// Returns the unique ID of the node data this handle refers to.
292  UN_NodeID nodeID() const
293  { return UN_NodeID( dataID() ); }
294 
295 protected:
296  /// The node data container for all the nodes in the graph.
297  UN_NodeData * nodeData() const;
298 };
299 
300 
301 #endif
302 
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:169
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 between input and output ports.
Definition: UN_Types.h:308
UN_DataID dataID() const
Definition: UN_Handle.h:66
UT_Array< UT_StringHolder > inputPortNames() const
Returns the names of the node input ports.
Definition: UN_Node.h:173
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:77
#define UN_API
Definition: UN_API.h:11
bool operator==(const UN_Handle &other) const
Comparison operators.
Definition: UN_Handle.h:50
UT_Array< UT_StringHolder > outputPortNames() const
Returns the names of the node output ports.
Definition: UN_Node.h:204
PortRange inputPortRange() const
Returns a range for iterating over node input ports.
Definition: UN_Node.h:177
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:56
UN_NodeID nodeID() const
Returns the unique ID of the node data this handle refers to.
Definition: UN_Node.h:292
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:159
bool operator==(const UN_Node &other) const
Comparison operators.
Definition: UN_Node.h:75
PortRange outputPortRange() const
Returns a range for iterating over node output ports.
Definition: UN_Node.h:208