Files
SDL3CPlusPlus/MaterialX/source/MaterialXCore/Definition.cpp
2026-01-06 13:25:49 +00:00

226 lines
6.2 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXCore/Definition.h>
#include <MaterialXCore/Document.h>
MATERIALX_NAMESPACE_BEGIN
const string COLOR_SEMANTIC = "color";
const string SHADER_SEMANTIC = "shader";
const string NodeDef::TEXTURE_NODE_GROUP = "texture";
const string NodeDef::PROCEDURAL_NODE_GROUP = "procedural";
const string NodeDef::GEOMETRIC_NODE_GROUP = "geometric";
const string NodeDef::ADJUSTMENT_NODE_GROUP = "adjustment";
const string NodeDef::CONDITIONAL_NODE_GROUP = "conditional";
const string NodeDef::CHANNEL_NODE_GROUP = "channel";
const string NodeDef::ORGANIZATION_NODE_GROUP = "organization";
const string NodeDef::TRANSLATION_NODE_GROUP = "translation";
const string NodeDef::NODE_ATTRIBUTE = "node";
const string NodeDef::NODE_GROUP_ATTRIBUTE = "nodegroup";
const string TypeDef::SEMANTIC_ATTRIBUTE = "semantic";
const string TypeDef::CONTEXT_ATTRIBUTE = "context";
const string Implementation::FILE_ATTRIBUTE = "file";
const string Implementation::FUNCTION_ATTRIBUTE = "function";
const string Implementation::NODE_GRAPH_ATTRIBUTE = "nodegraph";
const string UnitDef::UNITTYPE_ATTRIBUTE = "unittype";
const string AttributeDef::ATTRNAME_ATTRIBUTE = "attrname";
const string AttributeDef::VALUE_ATTRIBUTE = "value";
const string AttributeDef::ELEMENTS_ATTRIBUTE = "elements";
const string AttributeDef::EXPORTABLE_ATTRIBUTE = "exportable";
//
// NodeDef methods
//
const string& NodeDef::getType() const
{
const vector<OutputPtr>& activeOutputs = getActiveOutputs();
size_t numActiveOutputs = activeOutputs.size();
if (numActiveOutputs > 1)
{
return MULTI_OUTPUT_TYPE_STRING;
}
else if (numActiveOutputs == 1)
{
return activeOutputs[0]->getType();
}
else
{
return DEFAULT_TYPE_STRING;
}
}
InterfaceElementPtr NodeDef::getImplementation(const string& target, bool resolveNodeGraph) const
{
vector<InterfaceElementPtr> interfaces = getDocument()->getMatchingImplementations(getQualifiedName(getName()));
vector<InterfaceElementPtr> secondary = getDocument()->getMatchingImplementations(getName());
interfaces.insert(interfaces.end(), secondary.begin(), secondary.end());
// If requested, resolve Implementation elements to their linked NodeGraph elements.
if (resolveNodeGraph)
{
for (size_t i = 0; i < interfaces.size(); ++i)
{
ImplementationPtr impl = interfaces[i]->asA<Implementation>();
if (impl && impl->hasNodeGraph())
{
NodeGraphPtr nodeGraph = getDocument()->getNodeGraph(impl->getNodeGraph());
if (nodeGraph)
{
interfaces[i] = nodeGraph;
}
}
}
}
// Return the first implementation when no target is specified.
if (target.empty())
{
return !interfaces.empty() ? interfaces[0] : InterfaceElementPtr();
}
// Get all candidate targets matching the given target,
// taking inheritance into account.
const TargetDefPtr targetDef = getDocument()->getTargetDef(target);
const StringVec candidateTargets = targetDef ? targetDef->getMatchingTargets() : StringVec();
// First, search for a target-specific match.
for (const string& candidateTarget : candidateTargets)
{
for (InterfaceElementPtr interface : interfaces)
{
const std::string& interfaceTarget = interface->getTarget();
if (!interfaceTarget.empty() && targetStringsMatch(interfaceTarget, candidateTarget))
{
return interface;
}
}
}
// Then search for a generic match.
for (InterfaceElementPtr interface : interfaces)
{
// Look for interfaces without targets
const std::string& interfaceTarget = interface->getTarget();
if (interfaceTarget.empty())
{
return interface;
}
}
return InterfaceElementPtr();
}
StringMap NodeDef::getInputHints() const
{
StringMap hints;
for (InputPtr input : getActiveInputs())
{
if (input->hasHint())
{
hints[input->getName()] = input->getHint();
}
}
return hints;
}
bool NodeDef::validate(string* message) const
{
bool res = true;
validateRequire(!hasType(), res, message, "Nodedef should not have a type but an explicit output");
return InterfaceElement::validate(message) && res;
}
bool NodeDef::isVersionCompatible(const string& version) const
{
if (getVersionString() == version)
{
return true;
}
if (getDefaultVersion() && version.empty())
{
return true;
}
return false;
}
ConstInterfaceElementPtr NodeDef::getDeclaration(const string&) const
{
return getSelf()->asA<InterfaceElement>();
}
//
// Implementation methods
//
void Implementation::setNodeDef(ConstNodeDefPtr nodeDef)
{
if (nodeDef)
{
setNodeDefString(nodeDef->getName());
}
else
{
removeAttribute(NODE_DEF_ATTRIBUTE);
}
}
NodeDefPtr Implementation::getNodeDef() const
{
return resolveNameReference<NodeDef>(getNodeDefString());
}
bool Implementation::validate(string* message) const
{
bool res = true;
validateRequire(!hasVersionString(), res, message, "Implementation elements do not support version strings");
return InterfaceElement::validate(message) && res;
}
ConstInterfaceElementPtr Implementation::getDeclaration(const string&) const
{
return getNodeDef();
}
StringVec TargetDef::getMatchingTargets() const
{
StringVec result = { getName() };
ElementPtr base = getInheritsFrom();
while (base)
{
result.push_back(base->getName());
base = base->getInheritsFrom();
}
return result;
}
vector<UnitDefPtr> UnitTypeDef::getUnitDefs() const
{
vector<UnitDefPtr> unitDefs;
for (UnitDefPtr unitDef : getDocument()->getChildrenOfType<UnitDef>())
{
if (unitDef->getUnitType() == _name)
{
unitDefs.push_back(unitDef);
}
}
return unitDefs;
}
ValuePtr AttributeDef::getValue() const
{
if (!hasValue())
return ValuePtr();
return Value::createValueFromStrings(getValueString(), getType(), getDocument()->getTypeDef(getType()));
}
MATERIALX_NAMESPACE_END