Skip to content

Commit 8726577

Browse files
authored
Reinstate prior API behavior for NodeDef::getImplementation (#2722)
Reinstate prior API behavior for NodeDef.getImplementation() and introduce new accessor. Based on feedback from Bernard here #2701. Add new method to access the implementation elements directly.
1 parent b812789 commit 8726577

File tree

6 files changed

+92
-34
lines changed

6 files changed

+92
-34
lines changed

source/MaterialXCore/Definition.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,12 @@ const string& NodeDef::getType() const
5757
}
5858
}
5959

60-
InterfaceElementPtr NodeDef::getImplementation(const string& target) const
60+
namespace
61+
{
62+
InterfaceElementPtr selectImplementation(const vector<InterfaceElementPtr>& interfaces, const TargetDefPtr targetDef)
6163
{
62-
vector<InterfaceElementPtr> interfaces = getDocument()->getMatchingImplementations(getQualifiedName(getName()));
63-
vector<InterfaceElementPtr> secondary = getDocument()->getMatchingImplementations(getName());
64-
interfaces.insert(interfaces.end(), secondary.begin(), secondary.end());
65-
66-
if (target.empty())
67-
{
68-
return !interfaces.empty() ? interfaces[0] : InterfaceElementPtr();
69-
}
70-
7164
// Get all candidate targets matching the given target,
7265
// taking inheritance into account.
73-
const TargetDefPtr targetDef = getDocument()->getTargetDef(target);
7466
const StringVec candidateTargets = targetDef ? targetDef->getMatchingTargets() : StringVec();
7567

7668
// First, search for a target-specific match.
@@ -99,6 +91,35 @@ InterfaceElementPtr NodeDef::getImplementation(const string& target) const
9991

10092
return InterfaceElementPtr();
10193
}
94+
};
95+
96+
InterfaceElementPtr NodeDef::getImplementation(const string& target) const
97+
{
98+
vector<InterfaceElementPtr> interfaces = getDocument()->getMatchingImplementations(getQualifiedName(getName()));
99+
vector<InterfaceElementPtr> secondary = getDocument()->getMatchingImplementations(getName());
100+
interfaces.insert(interfaces.end(), secondary.begin(), secondary.end());
101+
102+
if (target.empty())
103+
{
104+
return !interfaces.empty() ? interfaces[0] : InterfaceElementPtr();
105+
}
106+
107+
return selectImplementation(interfaces, getDocument()->getTargetDef(target));
108+
}
109+
110+
InterfaceElementPtr NodeDef::getUnmappedImplementation(const string& target) const
111+
{
112+
vector<InterfaceElementPtr> interfaces = getDocument()->getMatchingUnmappedImplementations(getQualifiedName(getName()));
113+
vector<InterfaceElementPtr> secondary = getDocument()->getMatchingUnmappedImplementations(getName());
114+
interfaces.insert(interfaces.end(), secondary.begin(), secondary.end());
115+
116+
if (target.empty())
117+
{
118+
return !interfaces.empty() ? interfaces[0] : InterfaceElementPtr();
119+
}
120+
121+
return selectImplementation(interfaces, getDocument()->getTargetDef(target));
122+
}
102123

103124
StringMap NodeDef::getInputHints() const
104125
{

source/MaterialXCore/Definition.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,24 @@ class MX_CORE_API NodeDef : public InterfaceElement
138138
/// @{
139139

140140
/// Return the first implementation for this nodedef, optionally filtered
141-
/// by the given target name.
141+
/// by the given target name. Resolving any indirection chain in the
142+
/// implementations.
142143
/// @param target An optional target name, which will be used to filter
143144
/// the implementations that are considered.
144145
/// @return An implementation for this nodedef, or an empty shared pointer
145146
/// if none was found. Note that a node implementation may be either
146147
/// an Implementation element or a NodeGraph element.
147148
InterfaceElementPtr getImplementation(const string& target = EMPTY_STRING) const;
148149

150+
/// Return the first implementation for this nodedef, optionally filtered
151+
/// by the given target name.
152+
/// @param target An optional target name, which will be used to filter
153+
/// the implementations that are considered.
154+
/// @return An implementation for this nodedef, or an empty shared pointer
155+
/// if none was found. Note that a node implementation may be either
156+
/// an Implementation element or a NodeGraph element.
157+
InterfaceElementPtr getUnmappedImplementation(const string& target = EMPTY_STRING) const;
158+
149159
/// @}
150160
/// @name Hints
151161
/// @{

source/MaterialXCore/Document.cpp

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class Document::Cache
4444
// Clear the existing cache.
4545
portElementMap.clear();
4646
nodeDefMap.clear();
47-
implementationMap.clear();
47+
implementationDirectMap.clear();
48+
implementationIndirectMap.clear();
4849

4950
// Traverse the document to build a new cache.
5051
for (ElementPtr elem : doc.lock()->traverseTree())
@@ -88,12 +89,26 @@ class Document::Cache
8889
{
8990
if (interface->isA<NodeGraph>())
9091
{
91-
implementationMap[interface->getQualifiedName(nodeDefString)].push_back(interface);
92+
implementationDirectMap[interface->getQualifiedName(nodeDefString)].push_back(interface);
93+
implementationIndirectMap[interface->getQualifiedName(nodeDefString)].push_back(interface);
9294
}
9395
ImplementationPtr impl = interface->asA<Implementation>();
9496
if (impl)
9597
{
96-
implementationMap[interface->getQualifiedName(nodeDefString)].push_back(interface);
98+
implementationDirectMap[interface->getQualifiedName(nodeDefString)].push_back(interface);
99+
100+
// Check for implementation which specifies a nodegraph as the implementation
101+
const string& nodeGraphString = impl->getNodeGraph();
102+
if (!nodeGraphString.empty())
103+
{
104+
NodeGraphPtr nodeGraph = impl->getDocument()->getNodeGraph(nodeGraphString);
105+
if (nodeGraph)
106+
implementationIndirectMap[interface->getQualifiedName(nodeDefString)].push_back(nodeGraph);
107+
}
108+
else
109+
{
110+
implementationIndirectMap[interface->getQualifiedName(nodeDefString)].push_back(interface);
111+
}
97112
}
98113
}
99114
}
@@ -109,7 +124,8 @@ class Document::Cache
109124
bool valid;
110125
std::unordered_map<string, std::vector<PortElementPtr>> portElementMap;
111126
std::unordered_map<string, std::vector<NodeDefPtr>> nodeDefMap;
112-
std::unordered_map<string, std::vector<InterfaceElementPtr>> implementationMap;
127+
std::unordered_map<string, std::vector<InterfaceElementPtr>> implementationDirectMap;
128+
std::unordered_map<string, std::vector<InterfaceElementPtr>> implementationIndirectMap;
113129
};
114130

115131
//
@@ -374,9 +390,28 @@ vector<InterfaceElementPtr> Document::getMatchingImplementations(const string& n
374390
_cache->refresh();
375391

376392
// Return all implementations matching the given nodedef string.
377-
if (_cache->implementationMap.count(nodeDef))
393+
if (_cache->implementationIndirectMap.count(nodeDef))
378394
{
379-
matchingImplementations.insert(matchingImplementations.end(), _cache->implementationMap.at(nodeDef).begin(), _cache->implementationMap.at(nodeDef).end());
395+
matchingImplementations.insert(matchingImplementations.end(), _cache->implementationIndirectMap.at(nodeDef).begin(), _cache->implementationIndirectMap.at(nodeDef).end());
396+
}
397+
398+
return matchingImplementations;
399+
}
400+
401+
vector<InterfaceElementPtr> Document::getMatchingUnmappedImplementations(const string& nodeDef) const
402+
{
403+
// Recurse to data library if present.
404+
vector<InterfaceElementPtr> matchingImplementations = hasDataLibrary() ?
405+
getDataLibrary()->getMatchingUnmappedImplementations(nodeDef) :
406+
vector<InterfaceElementPtr>();
407+
408+
// Refresh the cache.
409+
_cache->refresh();
410+
411+
// Return all implementations matching the given nodedef string.
412+
if (_cache->implementationDirectMap.count(nodeDef))
413+
{
414+
matchingImplementations.insert(matchingImplementations.end(), _cache->implementationDirectMap.at(nodeDef).begin(), _cache->implementationDirectMap.at(nodeDef).end());
380415
}
381416

382417
return matchingImplementations;

source/MaterialXCore/Document.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,15 @@ class MX_CORE_API Document : public GraphElement
548548

549549
/// Return a vector of all node implementations that match the given
550550
/// NodeDef string. Note that a node implementation may be either an
551-
/// Implementation element or NodeGraph element.
551+
/// Implementation element or NodeGraph element. Resolving any inheritance
552+
/// chain present in the implementations.
552553
vector<InterfaceElementPtr> getMatchingImplementations(const string& nodeDef) const;
553554

555+
/// Return a vector of all node implementations that match the given
556+
/// NodeDef string. Note that a node implementation may be either an
557+
/// Implementation element or NodeGraph element.
558+
vector<InterfaceElementPtr> getMatchingUnmappedImplementations(const string& nodeDef) const;
559+
554560
/// @}
555561
/// @name UnitDef Elements
556562
/// @{

source/MaterialXGenOsl/LibsToOso.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ int main(int argc, char* const argv[])
398398
{
399399
// Determine whether or not there's a valid implementation of the current `NodeDef` for the type associated
400400
// to our OSL shader generator, i.e. OSL, and if not, skip it.
401-
mx::InterfaceElementPtr nodeImpl = nodeDef->getImplementation(oslShaderGen->getTarget());
401+
mx::InterfaceElementPtr nodeImpl = nodeDef->getUnmappedImplementation(oslShaderGen->getTarget());
402402

403403
if (!nodeImpl)
404404
{

source/MaterialXGenShader/ShaderGenerator.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -323,20 +323,6 @@ ShaderNodeImplPtr ShaderGenerator::getImplementation(const NodeDef& nodedef, Gen
323323
{
324324
impl = getColorManagementSystem()->createImplementation(name);
325325
}
326-
else if (implementationElement->hasNodeGraph())
327-
{
328-
const string& nodegraphElementName = implementationElement->getNodeGraph();
329-
NodeGraphPtr nodegraph = implElement->getDocument()->getNodeGraph(nodegraphElementName);
330-
if (nodegraph)
331-
{
332-
impl = createShaderNodeImplForNodeGraph(*nodegraph);
333-
implElement = nodegraph;
334-
}
335-
else
336-
{
337-
return nullptr;
338-
}
339-
}
340326
else
341327
{
342328
// Try creating a new in the factory.

0 commit comments

Comments
 (0)