From 1100bf0a3db81f0c0388916ccf0ab479bcb02397 Mon Sep 17 00:00:00 2001 From: Stefan Habel <19556655+StefanHabel@users.noreply.github.com> Date: Sun, 6 Oct 2024 16:52:51 -0700 Subject: [PATCH] Docstrings for PyMaterialXCore classes. Mostly copied from corresponding C++ header files, but using backticks to automatically link to relevant sections in the Python API documentation, e.g. `Document` to link to `PyMaterialXCore.Document.html`. Using `mod.attr("").doc() = ...` syntax so that this patch only adds new lines, rather than modifying existing lines. Using `:see:` fields to link to the corresponding C++ API docs page. Demo of generated HTML page available here: https://stefanhabel.github.io/generated/PyMaterialXCore.html Split from #1567. Update #342. Signed-off-by: Stefan Habel <19556655+StefanHabel@users.noreply.github.com> --- .../PyMaterialXCore/PyDefinition.cpp | 43 +++++++++++ .../PyMaterialXCore/PyDocument.cpp | 6 ++ .../PyMaterialX/PyMaterialXCore/PyElement.cpp | 73 +++++++++++++++++++ .../PyMaterialXCore/PyException.cpp | 5 ++ source/PyMaterialX/PyMaterialXCore/PyGeom.cpp | 33 +++++++++ .../PyMaterialXCore/PyInterface.cpp | 29 ++++++++ source/PyMaterialX/PyMaterialXCore/PyLook.cpp | 21 ++++++ source/PyMaterialX/PyMaterialXCore/PyNode.cpp | 24 ++++++ .../PyMaterialXCore/PyProperty.cpp | 16 ++++ .../PyMaterialXCore/PyTraversal.cpp | 30 ++++++++ .../PyMaterialX/PyMaterialXCore/PyTypes.cpp | 43 +++++++++++ .../PyMaterialXCore/PyUnitConverter.cpp | 15 ++++ .../PyMaterialX/PyMaterialXCore/PyValue.cpp | 20 +++++ .../PyMaterialX/PyMaterialXCore/PyVariant.cpp | 12 +++ 14 files changed, 370 insertions(+) diff --git a/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp b/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp index 7990387f96..720d8bf656 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp @@ -35,6 +35,13 @@ void bindPyDefinition(py::module& mod) .def_readonly_static("CHANNEL_NODE_GROUP", &mx::NodeDef::CHANNEL_NODE_GROUP) .def_readonly_static("ORGANIZATION_NODE_GROUP", &mx::NodeDef::ORGANIZATION_NODE_GROUP) .def_readonly_static("TRANSLATION_NODE_GROUP", &mx::NodeDef::TRANSLATION_NODE_GROUP); + mod.attr("NodeDef").doc() = R"docstring( + A node definition element within a `Document`. + + A `NodeDef` provides the declaration of a node interface, which may then + be instantiated as a `Node`. + + :see: https://materialx.org/docs/api/class_node_def.html)docstring"; py::class_(mod, "Implementation") .def("setFile", &mx::Implementation::setFile) @@ -51,6 +58,14 @@ void bindPyDefinition(py::module& mod) .def_readonly_static("CATEGORY", &mx::Implementation::CATEGORY) .def_readonly_static("FILE_ATTRIBUTE", &mx::Implementation::FILE_ATTRIBUTE) .def_readonly_static("FUNCTION_ATTRIBUTE", &mx::Implementation::FUNCTION_ATTRIBUTE); + mod.attr("Implementation").doc() = R"docstring( + 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. + + :see: https://materialx.org/docs/api/class_implementation.html)docstring"; py::class_(mod, "TypeDef") .def("setSemantic", &mx::TypeDef::setSemantic) @@ -67,12 +82,24 @@ void bindPyDefinition(py::module& mod) .def_readonly_static("CATEGORY", &mx::TypeDef::CATEGORY) .def_readonly_static("SEMANTIC_ATTRIBUTE", &mx::TypeDef::SEMANTIC_ATTRIBUTE) .def_readonly_static("CONTEXT_ATTRIBUTE", &mx::TypeDef::CONTEXT_ATTRIBUTE); + mod.attr("TypeDef").doc() = R"docstring( + A type definition element within a `Document`. + + :see: https://materialx.org/docs/api/class_type_def.html)docstring"; py::class_(mod, "Member") .def_readonly_static("CATEGORY", &mx::TypeDef::CATEGORY); + mod.attr("Member").doc() = R"docstring( + A member element within a `TypeDef`. + + :see: https://materialx.org/docs/api/class_member.html)docstring"; py::class_(mod, "Unit") .def_readonly_static("CATEGORY", &mx::Unit::CATEGORY); + mod.attr("Unit").doc() = R"docstring( + A unit declaration element within a `UnitDef`. + + :see: https://materialx.org/docs/api/class_unit.html)docstring"; py::class_(mod, "UnitDef") .def("setUnitType", &mx::UnitDef::setUnitType) @@ -83,10 +110,18 @@ void bindPyDefinition(py::module& mod) .def("getUnits", &mx::UnitDef::getUnits) .def_readonly_static("CATEGORY", &mx::UnitDef::CATEGORY) .def_readonly_static("UNITTYPE_ATTRIBUTE", &mx::UnitDef::UNITTYPE_ATTRIBUTE); + mod.attr("UnitDef").doc() = R"docstring( + A unit definition element within a `Document`. + + :see: https://materialx.org/docs/api/class_unit_def.html)docstring"; py::class_(mod, "UnitTypeDef") .def("getUnitDefs", &mx::UnitTypeDef::getUnitDefs) .def_readonly_static("CATEGORY", &mx::UnitTypeDef::CATEGORY); + mod.attr("UnitTypeDef").doc() = R"docstring( + A unit type definition element within a `Document`. + + :see: https://materialx.org/docs/api/class_unit_type_def.html)docstring"; py::class_(mod, "AttributeDef") .def("setAttrName", &mx::AttributeDef::setAttrName) @@ -98,8 +133,16 @@ void bindPyDefinition(py::module& mod) .def("setExportable", &mx::AttributeDef::setExportable) .def("getExportable", &mx::AttributeDef::getExportable) .def_readonly_static("CATEGORY", &mx::AttributeDef::CATEGORY); + mod.attr("AttributeDef").doc() = R"docstring( + An attribute definition element within a `Document`. + + :see: https://materialx.org/docs/api/class_attribute_def.html)docstring"; py::class_(mod, "TargetDef") .def("getMatchingTargets", &mx::TargetDef::getMatchingTargets) .def_readonly_static("CATEGORY", &mx::TargetDef::CATEGORY); + mod.attr("TargetDef").doc() = R"docstring( + The definition of an implementation target as a `TypedElement`. + + :see: https://materialx.org/docs/api/class_target_def.html)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp index 3f4403c673..9bc61878d3 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp @@ -117,4 +117,10 @@ void bindPyDocument(py::module& mod) .def("setColorManagementConfig", &mx::Document::setColorManagementConfig) .def("hasColorManagementConfig", &mx::Document::hasColorManagementConfig) .def("getColorManagementConfig", &mx::Document::getColorManagementConfig); + mod.attr("Document").doc() = R"docstring( + A MaterialX document, which represents the top-level element in the MaterialX ownership hierarchy. + + Use the factory function `createDocument()` to create a `Document` instance. + + :see: https://materialx.org/docs/api/class_document.html)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp index 9f35770e8b..c13ce9bae3 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyElement.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyElement.cpp @@ -128,6 +128,18 @@ void bindPyElement(py::module& mod) BIND_ELEMENT_FUNC_INSTANCE(Token) BIND_ELEMENT_FUNC_INSTANCE(TypeDef) BIND_ELEMENT_FUNC_INSTANCE(Visibility); + mod.attr("Element").doc() = R"docstring( + The base class for MaterialX elements. + + An `Element` is a named object within a `Document`, which may possess any + number of child elements and attributes. + + Inherited by: `TypedElement`, `GeomElement`, `Backdrop`, `Collection`, + `CommentElement`, `GenericElement`, `Look`, `LookGroup`, `NewlineElement`, + `PropertySet`, `TypeDef`, `Unit`, `UnitDef`, `UnitTypeDef`, `VariantSet`, + and `VariantAssign`. + + :see: https://materialx.org/docs/api/class_element.html)docstring"; py::class_(mod, "TypedElement") .def("setType", &mx::TypedElement::setType) @@ -137,6 +149,13 @@ void bindPyElement(py::module& mod) .def("isMultiOutputType", &mx::TypedElement::isMultiOutputType) .def("getTypeDef", &mx::TypedElement::getTypeDef) .def_readonly_static("TYPE_ATTRIBUTE", &mx::TypedElement::TYPE_ATTRIBUTE); + mod.attr("TypedElement").doc() = R"docstring( + The base class for typed elements. + + Inherited by: `InterfaceElement`, `ValueElement`, `AttributeDef`, + `GeomPropDef`, `Member`, and `TargetDef`. + + :see: https://materialx.org/docs/api/class_typed_element.html)docstring"; py::class_(mod, "ValueElement") .def("setValueString", &mx::ValueElement::setValueString) @@ -192,18 +211,49 @@ void bindPyElement(py::module& mod) BIND_VALUE_ELEMENT_FUNC_INSTANCE(booleanarray, mx::BoolVec) BIND_VALUE_ELEMENT_FUNC_INSTANCE(floatarray, mx::FloatVec) BIND_VALUE_ELEMENT_FUNC_INSTANCE(stringarray, mx::StringVec); + mod.attr("ValueElement").doc() = R"docstring( + The base class for elements that support typed values. + + Inherited by: `PortElement`, `GeomProp`, `Property`, `PropertyAssign`, and + `Token`. + + :see: https://materialx.org/docs/api/class_value_element.html)docstring"; py::class_(mod, "Token") .def_readonly_static("CATEGORY", &mx::Token::CATEGORY); + mod.attr("Token").doc() = R"docstring( + A token element representing a string value. + + Token elements are used to define input and output values for string + substitutions in image filenames. + + :see: https://materialx.org/docs/api/class_token.html)docstring"; py::class_(mod, "CommentElement") .def_readonly_static("CATEGORY", &mx::CommentElement::CATEGORY); + mod.attr("CommentElement").doc() = R"docstring( + An element representing a block of descriptive text within a `Document`, + which will be stored as a comment when the document is written out. + + The comment text may be accessed with the methods `Element.getDocString()` + and `Element.setDocString()`. + + :see: https://materialx.org/docs/api/class_comment_element.html)docstring"; py::class_(mod, "NewlineElement") .def_readonly_static("CATEGORY", &mx::NewlineElement::CATEGORY); + mod.attr("NewlineElement").doc() = R"docstring( + An element representing a newline within a `Document`. + + :see: https://materialx.org/docs/api/class_newline_element.html)docstring"; py::class_(mod, "GenericElement") .def_readonly_static("CATEGORY", &mx::GenericElement::CATEGORY); + mod.attr("GenericElement").doc() = R"docstring( + A generic element subclass, for instantiating elements with unrecognized + categories. + + :see: https://materialx.org/docs/api/class_generic_element.html)docstring"; py::class_(mod, "StringResolver") .def("setFilePrefix", &mx::StringResolver::setFilePrefix) @@ -217,10 +267,33 @@ void bindPyElement(py::module& mod) .def("setGeomNameSubstitution", &mx::StringResolver::setGeomNameSubstitution) .def("getGeomNameSubstitutions", &mx::StringResolver::getGeomNameSubstitutions) .def("resolve", &mx::StringResolver::resolve); + mod.attr("StringResolver").doc() = R"docstring( + A helper object for applying string modifiers to data values in the context + of a specific element and geometry. + + A `StringResolver` may be constructed through the `Element.createStringResolver()` + method, which initializes it in the context of a specific `Element`, geometry, + and material. + + Calling the `StringResolver.resolve()` method applies all modifiers to a + particular string value. + + Methods such as `StringResolver.setFilePrefix()` may be used to edit the + stored string modifiers before calling `StringResolver.resolve()`. + + :see: https://materialx.org/docs/api/class_string_resolver.html)docstring"; py::class_(mod, "ElementPredicate"); + mod.attr("ElementPredicate").doc() = R"docstring( + A function that takes an `Element` and returns a `bool`, + to check whether some criteria has passed.)docstring"; py::register_exception(mod, "ExceptionOrphanedElement"); + mod.attr("ExceptionOrphanedElement").doc() = R"docstring( + A type of exception that is raised when an `Element` is used after its + owning `Document` has gone out of scope. + + :see: https://materialx.org/docs/api/class_exception_orphaned_element.html)docstring"; mod.def("targetStringsMatch", &mx::targetStringsMatch); mod.def("prettyPrint", &mx::prettyPrint); diff --git a/source/PyMaterialX/PyMaterialXCore/PyException.cpp b/source/PyMaterialX/PyMaterialXCore/PyException.cpp index 6f953ffc06..bb869f7a70 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyException.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyException.cpp @@ -13,6 +13,11 @@ namespace mx = MaterialX; void bindPyException(py::module& mod) { static py::exception pyException(mod, "Exception"); + mod.attr("Exception").doc() = R"docstring( + The base class for exceptions that are propagated from the MaterialX + library to the client application. + + :see: https://materialx.org/docs/api/class_exception.html)docstring"; py::register_exception_translator( [](std::exception_ptr errPtr) diff --git a/source/PyMaterialX/PyMaterialXCore/PyGeom.cpp b/source/PyMaterialX/PyMaterialXCore/PyGeom.cpp index 712851fac2..b3541d90ed 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyGeom.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyGeom.cpp @@ -24,6 +24,14 @@ void bindPyGeom(py::module& mod) .def("getCollectionString", &mx::GeomElement::getCollectionString) .def("setCollection", &mx::GeomElement::setCollection) .def("getCollection", &mx::GeomElement::getCollection); + mod.attr("GeomElement").doc() = R"docstring( + The base class for geometric elements, which support bindings to geometries + and geometric collections. + + Inherited by: `GeomInfo`, `MaterialAssign`, `PropertySetAssign`, and + `Visibility`. + + :see: https://materialx.org/docs/api/class_geom_element.html)docstring"; py::class_(mod, "GeomInfo") .def("addGeomProp", &mx::GeomInfo::addGeomProp) @@ -52,9 +60,18 @@ void bindPyGeom(py::module& mod) BIND_GEOMINFO_FUNC_INSTANCE(floatarray, mx::FloatVec) BIND_GEOMINFO_FUNC_INSTANCE(stringarray, mx::StringVec) .def_readonly_static("CATEGORY", &mx::GeomInfo::CATEGORY); + mod.attr("GeomInfo").doc() = R"docstring( + A geometry info element within a `Document`. + + :see: https://materialx.org/docs/api/class_geom_info.html)docstring"; py::class_(mod, "GeomProp") .def_readonly_static("CATEGORY", &mx::GeomProp::CATEGORY); + mod.attr("GeomProp").doc() = R"docstring( + A geometric property element within a `GeomInfo`. + + :see: https://materialx.org/docs/api/class_geom_prop.html + )docstring"; py::class_(mod, "GeomPropDef") .def("setGeomProp", &mx::GeomPropDef::setGeomProp) @@ -70,6 +87,18 @@ void bindPyGeom(py::module& mod) .def("hasGeomProp", &mx::GeomPropDef::hasGeomProp) .def("getGeomProp", &mx::GeomPropDef::getGeomProp) .def_readonly_static("CATEGORY", &mx::GeomPropDef::CATEGORY); + mod.attr("GeomPropDef").doc() = R"docstring( + An element representing a declaration of geometric property data. + + A `GeomPropDef` element contains a reference to a geometric node and a set + of modifiers for that node. For example, a world-space normal can be + declared as a reference to the `"normal"` geometric node with a space + setting of `"world"`, or a specific set of texture coordinates can be + declared as a reference to the `"texcoord"` geometric node with an index + setting of `"1"`. + + :see: https://materialx.org/docs/api/class_geom_prop_def.html + )docstring"; py::class_(mod, "Collection") .def("setIncludeGeom", &mx::Collection::setIncludeGeom) @@ -87,6 +116,10 @@ void bindPyGeom(py::module& mod) .def("hasIncludeCycle", &mx::Collection::hasIncludeCycle) .def("matchesGeomString", &mx::Collection::matchesGeomString) .def_readonly_static("CATEGORY", &mx::Collection::CATEGORY); + mod.attr("Collection").doc() = R"docstring( + A collection element within a `Document`. + + :see: https://materialx.org/docs/api/class_collection.html)docstring"; mod.def("geomStringsMatch", &mx::geomStringsMatch); diff --git a/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp b/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp index 42e978d282..1f05447277 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp @@ -30,6 +30,14 @@ void bindPyInterface(py::module& mod) .def("getConnectedNode", &mx::PortElement::getConnectedNode) .def("setConnectedOutput", &mx::PortElement::setConnectedOutput) .def("getConnectedOutput", &mx::PortElement::getConnectedOutput); + mod.attr("PortElement").doc() = R"docstring( + The base class for port elements. + + Port elements support spatially-varying upstream connections to nodes. + + Inherited by: `Input` and `Output`. + + :see: https://materialx.org/docs/api/class_port_element.html)docstring"; py::class_(mod, "Input") .def("setDefaultGeomPropString", &mx::Input::setDefaultGeomPropString) @@ -40,11 +48,22 @@ void bindPyInterface(py::module& mod) .def("setConnectedInterfaceName", &mx::Input::setConnectedInterfaceName) .def("getInterfaceInput", &mx::Input::getInterfaceInput) .def_readonly_static("CATEGORY", &mx::Input::CATEGORY); + mod.attr("Input").doc() = R"docstring( + An input element within a `Node` or `NodeDef`. + + An `Input` holds either a uniform value or a connection to a spatially-varying + `Output`, either of which may be modified within the scope of a `Material`. + + :see: https://materialx.org/docs/api/class_input.html)docstring"; py::class_(mod, "Output") .def("hasUpstreamCycle", &mx::Output::hasUpstreamCycle) .def_readonly_static("CATEGORY", &mx::Output::CATEGORY) .def_readonly_static("DEFAULT_INPUT_ATTRIBUTE", &mx::Output::DEFAULT_INPUT_ATTRIBUTE); + mod.attr("Output").doc() = R"docstring( + A spatially-varying output element within a `NodeGraph` or `NodeDef`. + + :see: https://materialx.org/docs/api/class_output.html)docstring"; py::class_(mod, "InterfaceElement") .def("setNodeDefString", &mx::InterfaceElement::setNodeDefString) @@ -111,4 +130,14 @@ void bindPyInterface(py::module& mod) BIND_INTERFACE_TYPE_INSTANCE(floatarray, mx::FloatVec) BIND_INTERFACE_TYPE_INSTANCE(stringarray, mx::StringVec) .def_readonly_static("NODE_DEF_ATTRIBUTE", &mx::InterfaceElement::NODE_DEF_ATTRIBUTE); + mod.attr("InterfaceElement").doc() = R"docstring( + The base class for interface elements. + + An `InterfaceElement` supports a set of `Input` and `Output` elements, with + an API for setting their values. + + Inherited by: `GraphElement`, `Implementation`, `Node`, `NodeDef`, and + `Variant`. + + :see: https://materialx.org/docs/api/class_interface_element.html)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp index 5d1e1e8af3..fdc7d39690 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyLook.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyLook.cpp @@ -47,6 +47,10 @@ void bindPyLook(py::module& mod) .def("getActiveVisibilities", &mx::Look::getActiveVisibilities) .def("removeVisibility", &mx::Look::removeVisibility) .def_readonly_static("CATEGORY", &mx::Look::CATEGORY); + mod.attr("Look").doc() = R"docstring( + A look element within a `Document`. + + :see: https://materialx.org/docs/api/class_look.html)docstring"; py::class_(mod, "LookGroup") .def("getLooks", &mx::LookGroup::getLooks) @@ -56,6 +60,10 @@ void bindPyLook(py::module& mod) .def_readonly_static("CATEGORY", &mx::LookGroup::CATEGORY) .def_readonly_static("LOOKS_ATTRIBUTE", &mx::LookGroup::LOOKS_ATTRIBUTE) .def_readonly_static("ACTIVE_ATTRIBUTE", &mx::LookGroup::ACTIVE_ATTRIBUTE); + mod.attr("LookGroup").doc() = R"docstring( + A look group element within a `Document`. + + :see: https://materialx.org/docs/api/class_look_group.html)docstring"; py::class_(mod, "MaterialAssign") .def("setMaterial", &mx::MaterialAssign::setMaterial) @@ -66,6 +74,10 @@ void bindPyLook(py::module& mod) .def("getExclusive", &mx::MaterialAssign::getExclusive) .def("getReferencedMaterial", &mx::MaterialAssign::getReferencedMaterial) .def_readonly_static("CATEGORY", &mx::MaterialAssign::CATEGORY); + mod.attr("MaterialAssign").doc() = R"docstring( + A material assignment element within a `Look`. + + :see: https://materialx.org/docs/api/class_material_assign.html)docstring"; py::class_(mod, "Visibility") .def("setViewerGeom", &mx::Visibility::setViewerGeom) @@ -80,6 +92,15 @@ void bindPyLook(py::module& mod) .def("setVisible", &mx::Visibility::setVisible) .def("getVisible", &mx::Visibility::getVisible) .def_readonly_static("CATEGORY", &mx::Visibility::CATEGORY); + mod.attr("Visibility").doc() = R"docstring( + A visibility element within a `Look`. + + Describes the visibility relationship between two geometries or geometric + collections. + + :todo: Add a `Look.geomIsVisible()` method that computes the visibility + between two geometries in the context of a specific `Look`. + :see: https://materialx.org/docs/api/class_visibility.html)docstring"; mod.def("getGeometryBindings", &mx::getGeometryBindings, py::arg("materialNode") , py::arg("geom") = mx::UNIVERSAL_GEOM_NAME); diff --git a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp index 55448dee80..6583b5b1a9 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp @@ -13,6 +13,9 @@ namespace mx = MaterialX; void bindPyNode(py::module& mod) { py::class_(mod, "NodePredicate"); + mod.attr("NodePredicate").doc() = R"docstring( + A function that takes a `Node` and returns a `bool`, + to check whether some criteria has passed.)docstring"; py::class_(mod, "Node") .def("setConnectedNode", &mx::Node::setConnectedNode) @@ -27,6 +30,13 @@ void bindPyNode(py::module& mod) .def("addInputFromNodeDef", &mx::Node::addInputFromNodeDef) .def("addInputsFromNodeDef", &mx::Node::addInputsFromNodeDef) .def_readonly_static("CATEGORY", &mx::Node::CATEGORY); + mod.attr("Node").doc() = R"docstring( + A node element within a `NodeGraph` or `Document`. + + Represents an instance of a `NodeDef` within a graph, and its `Input` + elements apply specific values and connections to that instance. + + :see: https://materialx.org/docs/api/class_node.html)docstring"; py::class_(mod, "GraphElement") .def("addNode", &mx::GraphElement::addNode, @@ -50,6 +60,12 @@ void bindPyNode(py::module& mod) .def("topologicalSort", &mx::GraphElement::topologicalSort) .def("addGeomNode", &mx::GraphElement::addGeomNode) .def("asStringDot", &mx::GraphElement::asStringDot); + mod.attr("GraphElement").doc() = R"docstring( + The base class for graph elements. + + Inherited by: `NodeGraph` and `Document`. + + :see: https://materialx.org/docs/api/class_graph_element.html)docstring"; py::class_(mod, "NodeGraph") .def("getMaterialOutputs", &mx::NodeGraph::getMaterialOutputs) @@ -61,6 +77,10 @@ void bindPyNode(py::module& mod) .def("modifyInterfaceName", &mx::NodeGraph::modifyInterfaceName) .def("getDownstreamPorts", &mx::NodeGraph::getDownstreamPorts) .def_readonly_static("CATEGORY", &mx::NodeGraph::CATEGORY); + mod.attr("NodeGraph").doc() = R"docstring( + A node graph element within a `Document`. + + :see: https://materialx.org/docs/api/class_node_graph.html)docstring"; py::class_(mod, "Backdrop") .def("setContainsString", &mx::Backdrop::setContainsString) @@ -78,4 +98,8 @@ void bindPyNode(py::module& mod) .def_readonly_static("CONTAINS_ATTRIBUTE", &mx::Backdrop::CONTAINS_ATTRIBUTE) .def_readonly_static("WIDTH_ATTRIBUTE", &mx::Backdrop::WIDTH_ATTRIBUTE) .def_readonly_static("HEIGHT_ATTRIBUTE", &mx::Backdrop::HEIGHT_ATTRIBUTE); + mod.attr("Backdrop").doc() = R"docstring( + A layout element used to contain, group, and document nodes within a graph. + + :see: https://materialx.org/docs/api/class_backdrop.html)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyProperty.cpp b/source/PyMaterialX/PyMaterialXCore/PyProperty.cpp index a9b213a19b..792c2f6f42 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyProperty.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyProperty.cpp @@ -17,6 +17,10 @@ void bindPyProperty(py::module& mod) { py::class_(mod, "Property") .def_readonly_static("CATEGORY", &mx::Property::CATEGORY); + mod.attr("Property").doc() = R"docstring( + A property element within a `PropertySet`. + + :see: https://materialx.org/docs/api/class_property.html)docstring"; py::class_(mod, "PropertyAssign") .def("setProperty", &mx::PropertyAssign::setProperty) @@ -31,6 +35,10 @@ void bindPyProperty(py::module& mod) .def("setCollection", &mx::PropertyAssign::setCollection) .def("getCollection", &mx::PropertyAssign::getCollection) .def_readonly_static("CATEGORY", &mx::PropertyAssign::CATEGORY); + mod.attr("PropertyAssign").doc() = R"docstring( + A property assignment element within a `Look`. + + :see: https://materialx.org/docs/api/class_property_assign.html)docstring"; py::class_(mod, "PropertySet") .def("addProperty", &mx::PropertySet::addProperty) @@ -53,6 +61,10 @@ void bindPyProperty(py::module& mod) BIND_PROPERTYSET_TYPE_INSTANCE(floatarray, mx::FloatVec) BIND_PROPERTYSET_TYPE_INSTANCE(stringarray, mx::StringVec) .def_readonly_static("CATEGORY", &mx::Property::CATEGORY); + mod.attr("PropertySet").doc() = R"docstring( + A property set element within a `Document`. + + :see: https://materialx.org/docs/api/class_property_set.html)docstring"; py::class_(mod, "PropertySetAssign") .def("setPropertySetString", &mx::PropertySetAssign::setPropertySetString) @@ -61,4 +73,8 @@ void bindPyProperty(py::module& mod) .def("setPropertySet", &mx::PropertySetAssign::setPropertySet) .def("getPropertySet", &mx::PropertySetAssign::getPropertySet) .def_readonly_static("CATEGORY", &mx::PropertySetAssign::CATEGORY); + mod.attr("PropertySetAssign").doc() = R"docstring( + A property set assignment element within a `Look`. + + :see: https://materialx.org/docs/api/class_property_set_assign.html)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyTraversal.cpp b/source/PyMaterialX/PyMaterialXCore/PyTraversal.cpp index f83200b680..86caf3905c 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyTraversal.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyTraversal.cpp @@ -19,6 +19,16 @@ void bindPyTraversal(py::module& mod) .def("getConnectingElement", &mx::Edge::getConnectingElement) .def("getUpstreamElement", &mx::Edge::getUpstreamElement) .def("getName", &mx::Edge::getName); + mod.attr("Edge").doc() = R"docstring( + An edge between two connected `Element` objects, returned during graph traversal. + + A valid `Edge` consists of a downstream element, an upstream element, and + optionally a connecting element that binds them. As an example, the edge + between two `Node` elements will contain a connecting element for the `Input` + of the downstream `Node`. + + :see: `Element.traverseGraph()` + :see: https://materialx.org/docs/api/class_edge.html)docstring"; py::class_(mod, "TreeIterator") .def("getElement", &mx::TreeIterator::getElement) @@ -35,6 +45,11 @@ void bindPyTraversal(py::module& mod) throw py::stop_iteration(); return *it; }); + mod.attr("TreeIterator").doc() = R"docstring( + An iterator representing the state of a tree traversal. + + :see: `Element.traverseTree()` + :see: https://materialx.org/docs/api/class_tree_iterator.html)docstring"; py::class_(mod, "GraphIterator") .def("getDownstreamElement", &mx::GraphIterator::getDownstreamElement) @@ -55,6 +70,11 @@ void bindPyTraversal(py::module& mod) throw py::stop_iteration(); return *it; }); + mod.attr("GraphIterator").doc() = R"docstring( + An iterator representing the state of an upstream graph traversal. + + :see: `Element.traverseGraph()` + :see: https://materialx.org/docs/api/class_graph_iterator.html)docstring"; py::class_(mod, "InheritanceIterator") .def("__iter__", [](mx::InheritanceIterator& it) -> mx::InheritanceIterator& @@ -67,6 +87,16 @@ void bindPyTraversal(py::module& mod) throw py::stop_iteration(); return *it; }); + mod.attr("InheritanceIterator").doc() = R"docstring( + An iterator representing the current state of an inheritance traversal. + + :see: `Element.traverseInheritance()` + :see: https://materialx.org/docs/api/class_inheritance_iterator.html)docstring"; py::register_exception(mod, "ExceptionFoundCycle"); + mod.attr("ExceptionFoundCycle").doc() = R"docstring( + A type of exception that is raised when a traversal call encounters a cycle. + + :see: `Element.traverseGraph()` + :see: `Element.traverseInheritance()`)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyTypes.cpp b/source/PyMaterialX/PyMaterialXCore/PyTypes.cpp index ce11951259..50245e790a 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyTypes.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyTypes.cpp @@ -73,24 +73,45 @@ using IndexPair = std::pair; void bindPyTypes(py::module& mod) { py::class_(mod, "VectorBase"); + mod.attr("VectorBase").doc() = R"docstring( + The base class for vectors of scalar values. + + :see: https://materialx.org/docs/api/class_vector_base.html)docstring"; + py::class_(mod, "MatrixBase"); + mod.attr("MatrixBase").doc() = R"docstring( + The base class for square matrices of scalar values. + + :see: https://materialx.org/docs/api/class_matrix_base.html)docstring"; py::class_(mod, "Vector2") BIND_VECTOR_SUBCLASS(mx::Vector2, 2) .def(py::init()) .def("cross", &mx::Vector2::cross) .def("asTuple", [](const mx::Vector2& v) { return std::make_tuple(v[0], v[1]); }); + mod.attr("Vector2").doc() = R"docstring( + A vector of two floating-point values. + + :see: https://materialx.org/docs/api/class_vector2.html)docstring"; py::class_(mod, "Vector3") BIND_VECTOR_SUBCLASS(mx::Vector3, 3) .def(py::init()) .def("cross", &mx::Vector3::cross) .def("asTuple", [](const mx::Vector3& v) { return std::make_tuple(v[0], v[1], v[2]); }); + mod.attr("Vector3").doc() = R"docstring( + A vector of three floating-point values. + + :see: https://materialx.org/docs/api/class_vector3.html)docstring"; py::class_(mod, "Vector4") BIND_VECTOR_SUBCLASS(mx::Vector4, 4) .def(py::init()) .def("asTuple", [](const mx::Vector4& v) { return std::make_tuple(v[0], v[1], v[2], v[3]); }); + mod.attr("Vector4").doc() = R"docstring( + A vector of four floating-point values. + + :see: https://materialx.org/docs/api/class_vector4.html)docstring"; py::class_(mod, "Color3") BIND_VECTOR_SUBCLASS(mx::Color3, 3) @@ -98,11 +119,19 @@ void bindPyTypes(py::module& mod) .def("linearToSrgb", &mx::Color3::linearToSrgb) .def("srgbToLinear", &mx::Color3::srgbToLinear) .def("asTuple", [](const mx::Color3& v) { return std::make_tuple(v[0], v[1], v[2]); }); + mod.attr("Color3").doc() = R"docstring( + A three-component RGB color value. + + :see: https://materialx.org/docs/api/class_color3.html)docstring"; py::class_(mod, "Color4") BIND_VECTOR_SUBCLASS(mx::Color4, 4) .def(py::init()) .def("asTuple", [](const mx::Color4& v) { return std::make_tuple(v[0], v[1], v[2], v[3]); }); + mod.attr("Color4").doc() = R"docstring( + A four-component RGBA color value. + + :see: https://materialx.org/docs/api/class_color4.html)docstring"; py::class_(mod, "Matrix33") BIND_MATRIX_SUBCLASS(mx::Matrix33, 3) @@ -115,6 +144,13 @@ void bindPyTypes(py::module& mod) .def("transformNormal", &mx::Matrix33::transformNormal) .def_static("createRotation", &mx::Matrix33::createRotation) .def_readonly_static("IDENTITY", &mx::Matrix33::IDENTITY); + mod.attr("Matrix33").doc() = R"docstring( + A 3x3 matrix of floating-point values. + + Vector transformation methods follow the row-vector convention, + with matrix-vector multiplication computed as `v' = vM`. + + :see: https://materialx.org/docs/api/class_matrix33.html)docstring"; py::class_(mod, "Matrix44") BIND_MATRIX_SUBCLASS(mx::Matrix44, 4) @@ -130,6 +166,13 @@ void bindPyTypes(py::module& mod) .def_static("createRotationY", &mx::Matrix44::createRotationY) .def_static("createRotationZ", &mx::Matrix44::createRotationZ) .def_readonly_static("IDENTITY", &mx::Matrix44::IDENTITY); + mod.attr("Matrix44").doc() = R"docstring( + A 4x4 matrix of floating-point values. + + Vector transformation methods follow the row-vector convention, + with matrix-vector multiplication computed as `v' = vM`. + + :see: https://materialx.org/docs/api/class_matrix44.html)docstring"; mod.attr("DEFAULT_TYPE_STRING") = mx::DEFAULT_TYPE_STRING; mod.attr("FILENAME_TYPE_STRING") = mx::FILENAME_TYPE_STRING; diff --git a/source/PyMaterialX/PyMaterialXCore/PyUnitConverter.cpp b/source/PyMaterialX/PyMaterialXCore/PyUnitConverter.cpp index bf3bcbf0f9..8a0d9a7db3 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyUnitConverter.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyUnitConverter.cpp @@ -73,6 +73,12 @@ void bindPyUnitConverters(py::module& mod) .def("convert", (mx::Vector4 (mx::UnitConverter::*)(const mx::Vector4&, const std::string&, const std::string&)const) &mx::UnitConverter::convert) .def("getUnitAsInteger", &mx::UnitConverter::getUnitAsInteger) .def("getUnitFromInteger", &mx::UnitConverter::getUnitFromInteger); + mod.attr("UnitConverter").doc() = R"docstring( + An abstract base class for unit converters. + + Each unit converter instance is responsible for a single unit type. + + :see: https://materialx.org/docs/api/class_unit_converter.html)docstring"; py::class_(mod, "LinearUnitConverter") .def_static("create", &mx::LinearUnitConverter::create) @@ -83,6 +89,11 @@ void bindPyUnitConverters(py::module& mod) .def("convert", (mx::Vector4 (mx::LinearUnitConverter::*)(const mx::Vector4&, const std::string&, const std::string&)const) &mx::LinearUnitConverter::convert) .def("getUnitAsInteger", &mx::LinearUnitConverter::getUnitAsInteger) .def("getUnitFromInteger", &mx::LinearUnitConverter::getUnitFromInteger); + mod.attr("LinearUnitConverter").doc() = R"docstring( + A `UnitConverter` class for linear units that require only a scalar + multiplication. + + :see: https://materialx.org/docs/api/class_linear_unit_converter.html)docstring"; py::class_(mod, "UnitConverterRegistry") .def_static("create", &mx::UnitConverterRegistry::create) @@ -90,4 +101,8 @@ void bindPyUnitConverters(py::module& mod) .def("removeUnitConverter", &mx::UnitConverterRegistry::removeUnitConverter) .def("getUnitConverter", &mx::UnitConverterRegistry::getUnitConverter) .def("clearUnitConverters", &mx::UnitConverterRegistry::clearUnitConverters); + mod.attr("UnitConverterRegistry").doc() = R"docstring( + Class implementing a registry for `UnitConverter` objects. + + :see: https://materialx.org/docs/api/class_unit_converter_registry.html)docstring"; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyValue.cpp b/source/PyMaterialX/PyMaterialXCore/PyValue.cpp index 501f9d5f04..194638fa78 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyValue.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyValue.cpp @@ -23,6 +23,10 @@ void bindPyValue(py::module& mod) .def("getValueString", &mx::Value::getValueString) .def("getTypeString", &mx::Value::getTypeString) .def_static("createValueFromStrings", &mx::Value::createValueFromStrings); + mod.attr("Value").doc() = R"docstring( + A generic, discriminated value, whose type may be queried dynamically. + + :see: https://materialx.org/docs/api/class_value.html)docstring"; BIND_TYPE_INSTANCE(integer, int) BIND_TYPE_INSTANCE(boolean, bool) @@ -39,4 +43,20 @@ void bindPyValue(py::module& mod) BIND_TYPE_INSTANCE(booleanarray, mx::BoolVec) BIND_TYPE_INSTANCE(floatarray, mx::FloatVec) BIND_TYPE_INSTANCE(stringarray, mx::StringVec) + + mod.attr("TypedValue_boolean").doc() = "A `Value` object that stores a value of type `bool`."; + mod.attr("TypedValue_booleanarray").doc() = "A `Value` object that stores a `list` of `bool` values."; + mod.attr("TypedValue_color3").doc() = "A `Value` object that stores a value of type `Color3`."; + mod.attr("TypedValue_color4").doc() = "A `Value` object that stores a value of type `Color4`."; + mod.attr("TypedValue_float").doc() = "A `Value` object that stores a value of type `float`."; + mod.attr("TypedValue_floatarray").doc() = "A `Value` object that stores a `list` of `float` values."; + mod.attr("TypedValue_integer").doc() = "A `Value` object that stores a value of type `int`."; + mod.attr("TypedValue_integerarray").doc() = "A `Value` object that stores a `list` of `int` values."; + mod.attr("TypedValue_matrix33").doc() = "A `Value` object that stores a value of type `Matrix33`."; + mod.attr("TypedValue_matrix44").doc() = "A `Value` object that stores a value of type `Matrix44`."; + mod.attr("TypedValue_string").doc() = "A `Value` object that stores a value of type `str`."; + mod.attr("TypedValue_stringarray").doc() = "A `Value` object that stores a `list` of `str` values."; + mod.attr("TypedValue_vector2").doc() = "A `Value` object that stores a value of type `Vector2`."; + mod.attr("TypedValue_vector3").doc() = "A `Value` object that stores a value of type `Vector3`."; + mod.attr("TypedValue_vector4").doc() = "A `Value` object that stores a value of type `Vector4`."; } diff --git a/source/PyMaterialX/PyMaterialXCore/PyVariant.cpp b/source/PyMaterialX/PyMaterialXCore/PyVariant.cpp index 13c7fa572c..02fb69b4b9 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyVariant.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyVariant.cpp @@ -14,6 +14,10 @@ void bindPyVariant(py::module& mod) { py::class_(mod, "Variant") .def_readonly_static("CATEGORY", &mx::Variant::CATEGORY); + mod.attr("Variant").doc() = R"docstring( + A variant element within a `VariantSet`. + + :see: https://materialx.org/docs/api/class_variant.html)docstring"; py::class_(mod, "VariantSet") .def("addVariant", &mx::VariantSet::addVariant, @@ -22,6 +26,10 @@ void bindPyVariant(py::module& mod) .def("getVariants", &mx::VariantSet::getVariants) .def("removeVariant", &mx::VariantSet::removeVariant) .def_readonly_static("CATEGORY", &mx::VariantSet::CATEGORY); + mod.attr("VariantSet").doc() = R"docstring( + A variant set element within a `Document`. + + :see: https://materialx.org/docs/api/class_variant_set.html)docstring"; py::class_(mod, "VariantAssign") .def("setVariantSetString", &mx::VariantAssign::setVariantSetString) @@ -31,4 +39,8 @@ void bindPyVariant(py::module& mod) .def("hasVariantString", &mx::VariantAssign::hasVariantString) .def("getVariantString", &mx::VariantAssign::getVariantString) .def_readonly_static("CATEGORY", &mx::VariantAssign::CATEGORY); + mod.attr("VariantAssign").doc() = R"docstring( + A variant assignment element within a `Look`. + + :see: https://materialx.org/docs/api/class_variant_assign.html)docstring"; }