// // Copyright Contributors to the MaterialX Project // SPDX-License-Identifier: Apache-2.0 // #ifndef MATERIALX_DEFINITION_H #define MATERIALX_DEFINITION_H /// @file /// Definition element subclasses #include #include MATERIALX_NAMESPACE_BEGIN extern MX_CORE_API const string COLOR_SEMANTIC; extern MX_CORE_API const string SHADER_SEMANTIC; class NodeDef; class Implementation; class TypeDef; class TargetDef; class Member; class Unit; class UnitDef; class UnitTypeDef; class AttributeDef; /// A shared pointer to a NodeDef using NodeDefPtr = shared_ptr; /// A shared pointer to a const NodeDef using ConstNodeDefPtr = shared_ptr; /// A shared pointer to an Implementation using ImplementationPtr = shared_ptr; /// A shared pointer to a const Implementation using ConstImplementationPtr = shared_ptr; /// A shared pointer to a TypeDef using TypeDefPtr = shared_ptr; /// A shared pointer to a const TypeDef using ConstTypeDefPtr = shared_ptr; /// A shared pointer to a TargetDef using TargetDefPtr = shared_ptr; /// A shared pointer to a const TargetDef using ConstTargetDefPtr = shared_ptr; /// A shared pointer to a Member using MemberPtr = shared_ptr; /// A shared pointer to a const Member using ConstMemberPtr = shared_ptr; /// A shared pointer to a Unit using UnitPtr = shared_ptr; /// A shared pointer to a const Unit using ConstUnitPtr = shared_ptr; /// A shared pointer to a UnitDef using UnitDefPtr = shared_ptr; /// A shared pointer to a const UnitDef using ConstUnitDefPtr = shared_ptr; /// A shared pointer to a UnitTypeDef using UnitTypeDefPtr = shared_ptr; /// A shared pointer to a const UnitTypeDef using ConstUnitTypeDefPtr = shared_ptr; /// A shared pointer to an AttributeDef using AttributeDefPtr = shared_ptr; /// A shared pointer to a const AttributeDef using AttributeDefDefPtr = shared_ptr; /// @class NodeDef /// A node definition element within a Document. /// /// A NodeDef provides the declaration of a node interface, which may then /// be instantiated as a Node. class MX_CORE_API NodeDef : public InterfaceElement { public: NodeDef(ElementPtr parent, const string& name) : InterfaceElement(parent, CATEGORY, name) { } virtual ~NodeDef() { } /// @name Node String /// @{ /// Set the node string of the NodeDef. void setNodeString(const string& node) { setAttribute(NODE_ATTRIBUTE, node); } /// Return true if the given NodeDef has a node string. bool hasNodeString() const { return hasAttribute(NODE_ATTRIBUTE); } /// Return the node string of the NodeDef. const string& getNodeString() const { return getAttribute(NODE_ATTRIBUTE); } /// Return the element's output type. const string& getType() const override; /// @} /// @name Node Group /// @{ /// Set the node group of the NodeDef. void setNodeGroup(const string& category) { setAttribute(NODE_GROUP_ATTRIBUTE, category); } /// Return true if the given NodeDef has a node group. bool hasNodeGroup() const { return hasAttribute(NODE_GROUP_ATTRIBUTE); } /// Return the node group of the NodeDef. const string& getNodeGroup() const { return getAttribute(NODE_GROUP_ATTRIBUTE); } /// @} /// @name Implementation References /// @{ /// Return the first implementation for this nodedef, optionally filtered /// by the given target name. Resolving any indirection chain in the /// implementations. /// @param target An optional target name, which will be used to filter /// the implementations that are considered. /// @param resolveNodeGraph Allow resolution of Implementation elements /// to their linked NodeGraph elements. Defaults to true. /// @return An implementation for this nodedef, 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, bool resolveNodeGraph = true) const; /// @} /// @name Hints /// @{ /// Return list of input hint pairs of the form { input_name, hint_string } StringMap getInputHints() 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; /// @} /// @name Utility /// @{ /// Return true if the given version string is compatible with this /// NodeDef. This may be used to test, for example, whether a NodeDef /// and Node may be used together. bool isVersionCompatible(const string& version) const; /// Return the first declaration of this interface, optionally filtered /// by the given target name. ConstInterfaceElementPtr getDeclaration(const string& target = EMPTY_STRING) const override; /// @} public: static const string CATEGORY; static const string NODE_ATTRIBUTE; static const string NODE_GROUP_ATTRIBUTE; static const string TEXTURE_NODE_GROUP; static const string PROCEDURAL_NODE_GROUP; static const string GEOMETRIC_NODE_GROUP; static const string ADJUSTMENT_NODE_GROUP; static const string CONDITIONAL_NODE_GROUP; static const string CHANNEL_NODE_GROUP; static const string ORGANIZATION_NODE_GROUP; static const string TRANSLATION_NODE_GROUP; }; /// @class Implementation /// An implementation element within a Document. /// /// An Implementation is used to associate external source code with a specific /// NodeDef, providing a definition for the node that may either be universal or /// restricted to a specific target. class MX_CORE_API Implementation : public InterfaceElement { public: Implementation(ElementPtr parent, const string& name) : InterfaceElement(parent, CATEGORY, name) { } virtual ~Implementation() { } /// @name File String /// @{ /// Set the file string for the Implementation. void setFile(const string& file) { setAttribute(FILE_ATTRIBUTE, file); } /// Return true if the given Implementation has a file string. bool hasFile() const { return hasAttribute(FILE_ATTRIBUTE); } /// Return the file string for the Implementation. const string& getFile() const { return getAttribute(FILE_ATTRIBUTE); } /// @} /// @name Function String /// @{ /// Set the function string for the Implementation. void setFunction(const string& function) { setAttribute(FUNCTION_ATTRIBUTE, function); } /// Return true if the given Implementation has a function string. bool hasFunction() const { return hasAttribute(FUNCTION_ATTRIBUTE); } /// Return the function string for the Implementation. const string& getFunction() const { return getAttribute(FUNCTION_ATTRIBUTE); } /// @} /// @name Nodegraph String /// @{ /// Set the nodegraph string for the Implementation. void setNodeGraph(const string& nodegraph) { setAttribute(NODE_GRAPH_ATTRIBUTE, nodegraph); } /// Return true if the given Implementation has a nodegraph string. bool hasNodeGraph() const { return hasAttribute(NODE_GRAPH_ATTRIBUTE); } /// Return the nodegraph string for the Implementation. const string& getNodeGraph() const { return getAttribute(PortElement::NODE_GRAPH_ATTRIBUTE); } /// @} /// @name NodeDef References /// @{ /// Set the NodeDef element referenced by the Implementation. void setNodeDef(ConstNodeDefPtr nodeDef); /// Return the NodeDef element referenced by the Implementation. NodeDefPtr getNodeDef() 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; /// @} /// @name Utility /// @{ /// Return the first declaration of this interface, optionally filtered /// by the given target name. ConstInterfaceElementPtr getDeclaration(const string& target = EMPTY_STRING) const override; /// @} public: static const string CATEGORY; static const string FILE_ATTRIBUTE; static const string FUNCTION_ATTRIBUTE; static const string NODE_GRAPH_ATTRIBUTE; }; /// @class TypeDef /// A type definition element within a Document. class MX_CORE_API TypeDef : public Element { public: TypeDef(ElementPtr parent, const string& name) : Element(parent, CATEGORY, name) { } virtual ~TypeDef() { } /// @name Semantic /// @{ /// Set the semantic string of the TypeDef. void setSemantic(const string& semantic) { setAttribute(SEMANTIC_ATTRIBUTE, semantic); } /// Return true if the given TypeDef has a semantic string. bool hasSemantic() const { return hasAttribute(SEMANTIC_ATTRIBUTE); } /// Return the semantic string of the TypeDef. const string& getSemantic() const { return getAttribute(SEMANTIC_ATTRIBUTE); } /// @} /// @name Context /// @{ /// Set the context string of the TypeDef. void setContext(const string& context) { setAttribute(CONTEXT_ATTRIBUTE, context); } /// Return true if the given TypeDef has a context string. bool hasContext() const { return hasAttribute(CONTEXT_ATTRIBUTE); } /// Return the context string of the TypeDef. const string& getContext() const { return getAttribute(CONTEXT_ATTRIBUTE); } /// @} /// @name Member Elements /// @{ /// Add a Member to the TypeDef. /// @param name The name of the new Member. /// If no name is specified, then a unique name will automatically be /// generated. /// @return A shared pointer to the new Member. MemberPtr addMember(const string& name = EMPTY_STRING) { return addChild(name); } /// Return the Member, if any, with the given name. MemberPtr getMember(const string& name) const { return getChildOfType(name); } /// Return a vector of all Member elements in the TypeDef. vector getMembers() const { return getChildrenOfType(); } /// Remove the Member, if any, with the given name. void removeMember(const string& name) { removeChildOfType(name); } /// @} public: static const string CATEGORY; static const string SEMANTIC_ATTRIBUTE; static const string CONTEXT_ATTRIBUTE; }; /// @class TargetDef /// A definition of an implementation target. class MX_CORE_API TargetDef : public TypedElement { public: TargetDef(ElementPtr parent, const string& name) : TypedElement(parent, CATEGORY, name) { } virtual ~TargetDef() { } /// Return a vector of target names that is matching this targetdef /// either by itself of by its inheritance. /// The vector is ordered by priority starting with this targetdef /// itself and then upwards in the inheritance hierarchy. StringVec getMatchingTargets() const; public: static const string CATEGORY; }; /// @class Member /// A member element within a TypeDef. class MX_CORE_API Member : public ValueElement { public: Member(ElementPtr parent, const string& name) : ValueElement(parent, CATEGORY, name) { } virtual ~Member() { } public: static const string CATEGORY; }; /// @class Unit /// A unit declaration within a UnitDef. class MX_CORE_API Unit : public Element { public: Unit(ElementPtr parent, const string& name) : Element(parent, CATEGORY, name) { } virtual ~Unit() { } public: static const string CATEGORY; }; /// @class UnitDef /// A unit definition element within a Document. class MX_CORE_API UnitDef : public Element { public: UnitDef(ElementPtr parent, const string& name) : Element(parent, CATEGORY, name) { } virtual ~UnitDef() { } /// @name Unit Type methods /// @{ /// Set the element's unittype string. void setUnitType(const string& type) { setAttribute(UNITTYPE_ATTRIBUTE, type); } /// Return true if the given element has a unittype string. bool hasUnitType() const { return hasAttribute(UNITTYPE_ATTRIBUTE); } /// Return the element's type string. const string& getUnitType() const { return getAttribute(UNITTYPE_ATTRIBUTE); } /// @} /// @name Unit methods /// @{ /// Add a Unit to the UnitDef. /// @param name The name of the new Unit. An exception is thrown /// if the name provided is an empty string. /// @return A shared pointer to the new Unit. UnitPtr addUnit(const string& name) { if (name.empty()) { throw Exception("A unit definition name cannot be empty"); } return addChild(name); } /// Return the Unit, if any, with the given name. UnitPtr getUnit(const string& name) const { return getChildOfType(name); } /// Return a vector of all Unit elements in the UnitDef. vector getUnits() const { return getChildrenOfType(); } /// Remove the Unit, if any, with the given name. void removeUnit(const string& name) { removeChildOfType(name); } /// @} public: static const string CATEGORY; static const string UNITTYPE_ATTRIBUTE; }; /// @class UnitTypeDef /// A unit type definition element within a Document. class MX_CORE_API UnitTypeDef : public Element { public: UnitTypeDef(ElementPtr parent, const string& name) : Element(parent, CATEGORY, name) { } virtual ~UnitTypeDef() { } /// Find all UnitDefs for the UnitTypeDef vector getUnitDefs() const; public: static const string CATEGORY; }; /// @class AttributeDef /// An attribute definition element within a Document. class MX_CORE_API AttributeDef : public TypedElement { public: AttributeDef(ElementPtr parent, const string& name) : TypedElement(parent, CATEGORY, name) { } virtual ~AttributeDef() { } /// @name Attribute name /// @{ /// Set the element's attrname string. void setAttrName(const string& name) { setAttribute(ATTRNAME_ATTRIBUTE, name); } /// Return true if this element has an attrname string. bool hasAttrName() const { return hasAttribute(ATTRNAME_ATTRIBUTE); } /// Return the element's attrname string. const string& getAttrName() const { return getAttribute(ATTRNAME_ATTRIBUTE); } /// @} /// @name Value String /// @{ /// Set the value string of an element. void setValueString(const string& value) { setAttribute(VALUE_ATTRIBUTE, value); } /// Return true if the given element has a value string. bool hasValueString() const { return hasAttribute(VALUE_ATTRIBUTE); } /// Get the value string of a element. const string& getValueString() const { return getAttribute(VALUE_ATTRIBUTE); } /// @} /// @name Typed Value /// @{ /// Set the typed value of an element. template void setValue(const T& value, const string& type = EMPTY_STRING) { setType(!type.empty() ? type : getTypeString()); setValueString(toValueString(value)); } /// Set the typed value of an element from a C-style string. void setValue(const char* value, const string& type = EMPTY_STRING) { setValue(value ? string(value) : EMPTY_STRING, type); } /// Return true if the element possesses a typed value. bool hasValue() const { return hasAttribute(VALUE_ATTRIBUTE); } /// Return the typed value of an element as a generic value object, which /// may be queried to access its data. /// /// @return A shared pointer to the typed value of this element, or an /// empty shared pointer if no value is present. ValuePtr getValue() const; /// @} /// @name Elements /// @{ /// Set the element's elements string. void setElements(const string& elements) { setAttribute(ELEMENTS_ATTRIBUTE, elements); } /// Return true if the element has an elements string. bool hasElements() const { return hasAttribute(ELEMENTS_ATTRIBUTE); } /// Return the element's elements string. const string& getElements() const { return getAttribute(ELEMENTS_ATTRIBUTE); } /// @} /// @name Exportable /// @{ /// Set the exportable boolean for the element. void setExportable(bool value) { setTypedAttribute(EXPORTABLE_ATTRIBUTE, value); } /// Return the exportable boolean for the element. /// Defaults to false if exportable is not set. bool getExportable() const { return getTypedAttribute(EXPORTABLE_ATTRIBUTE); } /// @} public: static const string CATEGORY; static const string ATTRNAME_ATTRIBUTE; static const string VALUE_ATTRIBUTE; static const string ELEMENTS_ATTRIBUTE; static const string EXPORTABLE_ATTRIBUTE; }; MATERIALX_NAMESPACE_END #endif