forked from AcademySoftwareFoundation/MaterialX
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNode.h
479 lines (387 loc) · 14.7 KB
/
Node.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
//
// TM & (c) 2017 Lucasfilm Entertainment Company Ltd. and Lucasfilm Ltd.
// All rights reserved. See LICENSE.txt for license.
//
#ifndef MATERIALX_NODE_H
#define MATERIALX_NODE_H
/// @file
/// Node element subclasses
#include <MaterialXCore/Library.h>
#include <MaterialXCore/Definition.h>
namespace MaterialX
{
class Node;
class GraphElement;
class NodeGraph;
class Backdrop;
/// A shared pointer to a Node
using NodePtr = shared_ptr<Node>;
/// A shared pointer to a const Node
using ConstNodePtr = shared_ptr<const Node>;
/// A shared pointer to a GraphElement
using GraphElementPtr = shared_ptr<GraphElement>;
/// A shared pointer to a const GraphElement
using ConstGraphElementPtr = shared_ptr<const GraphElement>;
/// A shared pointer to a NodeGraph
using NodeGraphPtr = shared_ptr<NodeGraph>;
/// A shared pointer to a const NodeGraph
using ConstNodeGraphPtr = shared_ptr<const NodeGraph>;
/// A shared pointer to a Backdrop
using BackdropPtr = shared_ptr<Backdrop>;
/// A shared pointer to a const Backdrop
using ConstBackdropPtr = shared_ptr<const Backdrop>;
// Predicate to test a node against some criteria whether
// that criteria has passed
using NodePredicate = std::function<bool(NodePtr node)>;
/// @class Node
/// A node element within a NodeGraph or Document.
///
/// A Node represents an instance of a NodeDef within a graph, and its Input
/// elements apply specific values and connections to that instance.
class Node : public InterfaceElement
{
public:
Node(ElementPtr parent, const string& name) :
InterfaceElement(parent, CATEGORY, name)
{
}
virtual ~Node() { }
/// @name Connections
/// @{
/// Set the node to which the given input is connected, creating a
/// child input if needed. If the node argument is null, then any
/// existing node connection on the input will be cleared.
void setConnectedNode(const string& inputName, NodePtr node);
/// Return the Node connected to the given input. If the given input is
/// not present, then an empty NodePtr is returned.
NodePtr getConnectedNode(const string& inputName) const;
/// Set the name of the Node connected to the given input, creating a child
/// element for the input if needed.
void setConnectedNodeName(const string& inputName, const string& nodeName);
/// Return the name of the Node connected to the given input. If the given
/// input is not present, then an empty string is returned.
string getConnectedNodeName(const string& inputName) const;
/// Set the output to which the given input is connected, creating a
/// child input if needed. If the node argument is null, then any
/// existing output connection on the input will be cleared.
void setConnectedOutput(const string& inputName, OutputPtr output);
/// Return the output connected to the given input. If the given input is
/// not present, then an empty OutputPtr is returned.
OutputPtr getConnectedOutput(const string& inputName) const;
/// @}
/// @name NodeDef References
/// @{
/// Return the first NodeDef that declares this node, optionally filtered
/// by the given target name.
/// @param target An optional target name, which will be used to filter
/// the nodedefs that are considered.
/// @return A NodeDef for this node, or an empty shared pointer if none
/// was found.
NodeDefPtr getNodeDef(const string& target = EMPTY_STRING) const;
/// @}
/// @name Implementation References
/// @{
/// Return the first implementation for this node, optionally filtered by
/// the given target and language names.
/// @param target An optional target name, which will be used to filter
/// the implementations that are considered.
/// @return An implementation for this node, or an empty shared pointer if
/// none was found. Note that a node implementation may be either an
/// Implementation element or a NodeGraph element.
InterfaceElementPtr getImplementation(const string& target = EMPTY_STRING) const
{
NodeDefPtr nodeDef = getNodeDef(target);
return nodeDef ? nodeDef->getImplementation(target) : InterfaceElementPtr();
}
/// @}
/// @name Traversal
/// @{
/// Return the Edge with the given index that lies directly upstream from
/// this element in the dataflow graph.
Edge getUpstreamEdge(size_t index = 0) const override;
/// Return the number of queriable upstream edges for this element.
size_t getUpstreamEdgeCount() const override
{
return getInputCount();
}
/// Given a connecting element (Input or Output) return the NodeDef output
/// corresponding to the output the element is connected to. This is only valid if
/// the NodeDef has explicit outputs defined, e.g. multiple outputs or an explicitly
/// named output. If this is not the case, nullptr is returned, which implies the
/// node is a standard node with a single implicit output.
OutputPtr getNodeDefOutput(ElementPtr connectingElement);
/// Return a vector of all downstream ports that connect to this node, ordered by
/// the names of the port elements.
vector<PortElementPtr> getDownstreamPorts() const;
/// @}
/// @name Utility
/// @{
/// Return the first declaration of this interface, optionally filtered
/// by the given target name.
ConstNodeDefPtr getDeclaration(const string& target = EMPTY_STRING) const override
{
return getNodeDef(target);
}
/// Add an input based on the corresponding input for the associated node definition.
/// If the input already exists on the node it will just be returned.
ValueElementPtr addInputFromNodeDef(const string& name);
/// @}
/// @name Validation
/// @{
/// Validate that the given element tree, including all descendants, is
/// consistent with the MaterialX specification.
bool validate(string* message = nullptr) const override;
/// @}
public:
static const string CATEGORY;
};
/// @class GraphElement
/// The base class for graph elements such as NodeGraph and Document.
class GraphElement : public InterfaceElement
{
protected:
GraphElement(ElementPtr parent, const string& category, const string& name) :
InterfaceElement(parent, category, name)
{
}
public:
virtual ~GraphElement() { }
/// @name Node Elements
/// @{
/// Add a Node to the graph.
/// @param category The category of the new Node.
/// @param name The name of the new Node.
/// If no name is specified, then a unique name will automatically be
/// generated.
/// @param type An optional type string.
/// @return A shared pointer to the new Node.
NodePtr addNode(const string& category,
const string& name = EMPTY_STRING,
const string& type = DEFAULT_TYPE_STRING)
{
NodePtr node = addChild<Node>(name);
node->setCategory(category);
node->setType(type);
return node;
}
/// Add a Node that is an instance of the given NodeDef.
NodePtr addNodeInstance(ConstNodeDefPtr nodeDef, const string& name = EMPTY_STRING)
{
NodePtr node = addNode(nodeDef->getNodeString(), name, nodeDef->getType());
node->setNodeDefString(nodeDef->getName());
return node;
}
/// Return the Node, if any, with the given name.
NodePtr getNode(const string& name) const
{
return getChildOfType<Node>(name);
}
/// Return a vector of all Nodes in the graph, optionally filtered by the
/// given category string.
vector<NodePtr> getNodes(const string& category = EMPTY_STRING) const
{
return getChildrenOfType<Node>(category);
}
/// Return a vector of nodes in the graph which have a given type
vector<NodePtr> getNodesOfType(const string& nodeType) const
{
vector<NodePtr> nodes;
for (auto node : getNodes())
{
if (node->getType() == nodeType)
{
nodes.push_back(node);
}
}
return nodes;
}
/// Remove the Node, if any, with the given name.
void removeNode(const string& name)
{
removeChildOfType<Node>(name);
}
/// @}
/// @name Material Nodes
/// @{
/// Add a material node to the graph, optionally connecting it to the given
/// shader node.
NodePtr addMaterialNode(const string& name = EMPTY_STRING, ConstNodePtr shaderNode = nullptr);
/// Return a vector of all material nodes.
vector<NodePtr> getMaterialNodes() const
{
return getNodesOfType(MATERIAL_TYPE_STRING);
}
/// @}
/// @name Backdrop Elements
/// @{
/// Add a Backdrop to the graph.
BackdropPtr addBackdrop(const string& name = EMPTY_STRING)
{
return addChild<Backdrop>(name);
}
/// Return the Backdrop, if any, with the given name.
BackdropPtr getBackdrop(const string& name) const
{
return getChildOfType<Backdrop>(name);
}
/// Return a vector of all Backdrop elements in the graph.
vector<BackdropPtr> getBackdrops() const
{
return getChildrenOfType<Backdrop>();
}
/// Remove the Backdrop, if any, with the given name.
void removeBackdrop(const string& name)
{
removeChildOfType<Backdrop>(name);
}
/// @}
/// @name Utility
/// @{
/// Flatten any references to graph-based node definitions within this
/// node graph, replacing each reference with the equivalent node network.
void flattenSubgraphs(const string& target = EMPTY_STRING, NodePredicate filter=nullptr);
/// Return a vector of all children (nodes and outputs) sorted in
/// topological order.
/// @throws ExceptionFoundCycle if a cycle is encountered.
vector<ElementPtr> topologicalSort() const;
/// Convert this graph to a string in the DOT language syntax. This can be
/// used to visualise the graph using GraphViz (http://www.graphviz.org).
///
/// If declarations for the contained nodes are provided as nodedefs in
/// the owning document, then they will be used to provide additional
/// formatting details.
string asStringDot() const;
/// @}
};
/// @class NodeGraph
/// A node graph element within a Document.
class NodeGraph : public GraphElement
{
public:
NodeGraph(ElementPtr parent, const string& name) :
GraphElement(parent, CATEGORY, name)
{
}
virtual ~NodeGraph() { }
/// @name NodeDef References
/// @{
/// Set the NodeDef element referenced by this NodeGraph.
void setNodeDef(ConstNodeDefPtr nodeDef);
/// Return the NodeDef element referenced by this NodeGraph.
NodeDefPtr getNodeDef() const;
/// Return the first implementation for this node graph
/// @return An implementation for this node, or an empty shared pointer if
/// none was found.
InterfaceElementPtr getImplementation() const;
/// @}
/// @name Utility
/// @{
/// Return the first declaration of this interface, optionally filtered
/// by the given target name.
ConstNodeDefPtr getDeclaration(const string& target = EMPTY_STRING) const override;
/// Add an interface name to an existing NodeDef associated with this NodeGraph.
/// @param inputPath Path to an input descendant of this graph.
/// @param interfaceName The new interface name.
void addInterfaceName(const string& inputPath, const string& interfaceName);
/// Remove an interface name from an existing NodeDef associated with this NodeGraph.
/// @param inputPath Path to an input descendant of this graph.
void removeInterfaceName(const string& inputPath);
/// Modify the interface name on an existing NodeDef associated with this NodeGraph.
/// @param inputPath Path to an input descendant of this graph.
/// @param interfaceName The new interface name.
void modifyInterfaceName(const string& inputPath, const string& interfaceName);
/// @}
/// @name Validation
/// @{
/// Validate that the given element tree, including all descendants, is
/// consistent with the MaterialX specification.
bool validate(string* message = nullptr) const override;
/// @}
public:
static const string CATEGORY;
};
/// @class Backdrop
/// A layout element used to contain, group and document nodes within a graph.
class Backdrop : public Element
{
public:
Backdrop(ElementPtr parent, const string& name) :
Element(parent, CATEGORY, name)
{
}
virtual ~Backdrop() { }
/// @name Contains String
/// @{
/// Set the contains string for this backdrop.
void setContainsString(const string& contains)
{
setAttribute(CONTAINS_ATTRIBUTE, contains);
}
/// Return true if this backdrop has a contains string.
bool hasContainsString() const
{
return hasAttribute(CONTAINS_ATTRIBUTE);
}
/// Return the contains string for this backdrop.
string getContainsString() const
{
return getAttribute(CONTAINS_ATTRIBUTE);
}
/// @}
/// @name Width
/// @{
/// Set the width attribute of the backdrop.
void setWidth(float width)
{
setTypedAttribute<float>(WIDTH_ATTRIBUTE, width);
}
/// Return true if this backdrop has a width attribute.
bool hasWidth() const
{
return hasAttribute(WIDTH_ATTRIBUTE);
}
/// Return the width attribute of the backdrop.
float getWidth() const
{
return getTypedAttribute<float>(WIDTH_ATTRIBUTE);
}
/// @}
/// @name Height
/// @{
/// Set the height attribute of the backdrop.
void setHeight(float height)
{
setTypedAttribute<float>(HEIGHT_ATTRIBUTE, height);
}
/// Return true if this backdrop has a height attribute.
bool hasHeight() const
{
return hasAttribute(HEIGHT_ATTRIBUTE);
}
/// Return the height attribute of the backdrop.
float getHeight() const
{
return getTypedAttribute<float>(HEIGHT_ATTRIBUTE);
}
/// @}
/// @name Utility
/// @{
/// Set the vector of elements that this backdrop contains.
void setContainsElements(const vector<ConstTypedElementPtr>& nodes);
/// Return the vector of elements that this backdrop contains.
vector<TypedElementPtr> getContainsElements() const;
/// @}
/// @name Validation
/// @{
/// Validate that the given element tree, including all descendants, is
/// consistent with the MaterialX specification.
bool validate(string* message = nullptr) const override;
/// @}
public:
static const string CATEGORY;
static const string CONTAINS_ATTRIBUTE;
static const string WIDTH_ATTRIBUTE;
static const string HEIGHT_ATTRIBUTE;
};
} // namespace MaterialX
#endif