Skip to content

Commit

Permalink
Fix input/output count in Element::clearContent (AcademySoftwareFound…
Browse files Browse the repository at this point in the history
…ation#1520)

When clearContent() is called on an InterfaceElement its _inputCount and _outputCount were not updated even though all inputs and outputs were removed. This led to problems including potential crash in Document::validate().
  • Loading branch information
rasmusbonnedal authored Sep 7, 2023
1 parent f822dc9 commit 49b0835
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 1 deletion.
2 changes: 1 addition & 1 deletion source/MaterialXCore/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ class MX_CORE_API Element : public std::enable_shared_from_this<Element>
void copyContentFrom(const ConstElementPtr& source);

/// Clear all attributes and descendants from this element.
void clearContent();
virtual void clearContent();

/// Using the input name as a starting point, modify it to create a valid,
/// unique name for a child element.
Expand Down
7 changes: 7 additions & 0 deletions source/MaterialXCore/Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,13 @@ ConstInterfaceElementPtr InterfaceElement::getDeclaration(const string&) const
return InterfaceElementPtr();
}

void InterfaceElement::clearContent()
{
_inputCount = 0;
_outputCount = 0;
TypedElement::clearContent();
}

bool InterfaceElement::hasExactInputMatch(ConstInterfaceElementPtr declaration, string* message) const
{
for (InputPtr input : getActiveInputs())
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXCore/Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,9 @@ class MX_CORE_API InterfaceElement : public TypedElement
/// no declaration was found.
virtual ConstInterfaceElementPtr getDeclaration(const string& target = EMPTY_STRING) const;

/// Clear all attributes and descendants from this element.
void clearContent() override;

/// Return true if this instance has an exact input match with the given
/// declaration, where each input of this the instance corresponds to a
/// declaration input of the same name and type.
Expand Down
18 changes: 18 additions & 0 deletions source/MaterialXTest/MaterialXCore/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,24 @@ TEST_CASE("Node", "[node]")
REQUIRE(doc->getOutputs().empty());
}

TEST_CASE("Node inputCount repro", "[node]")
{
// Create a document.
mx::DocumentPtr doc = mx::createDocument();
mx::NodePtr constant = doc->addNode("constant");
constant->setInputValue<float>("value", 0.5f);

// Check that input count is correct after clearContent
constant->clearContent();
CHECK(constant->getInputCount() == 0);

// Check that validate succeeds after clear and rebuild
constant->setType("float");
mx::OutputPtr output = doc->addOutput(mx::EMPTY_STRING, "float");
output->setConnectedNode(constant);
CHECK(doc->validate());
}

TEST_CASE("Flatten", "[nodegraph]")
{
// Read an example containing graph-based custom nodes.
Expand Down
1 change: 1 addition & 0 deletions source/PyMaterialX/PyMaterialXCore/PyInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ void bindPyInterface(py::module& mod)
.def("getDefaultVersion", &mx::InterfaceElement::getDefaultVersion)
.def("getDeclaration", &mx::InterfaceElement::getDeclaration,
py::arg("target") = mx::EMPTY_STRING)
.def("clearContent", &mx::InterfaceElement::clearContent)
.def("hasExactInputMatch", &mx::InterfaceElement::hasExactInputMatch,
py::arg("declaration"), py::arg("message") = nullptr)
BIND_INTERFACE_TYPE_INSTANCE(integer, int)
Expand Down

0 comments on commit 49b0835

Please sign in to comment.