Skip to content

Commit

Permalink
Implement MDagModifier::createNode bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
yantor3d committed Jun 6, 2021
1 parent 504c432 commit 64f18b0
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 8 deletions.
60 changes: 52 additions & 8 deletions src/MDagModifier.inl
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
py::class_<MDagModifier>(m, "DagModifier")
py::class_<MDagModifier>(m, "DagModifier", "DGModifier")
.def(py::init<>())

.def("createNode", [](MDagModifier & self, MString type, MObject parent = MObject::kNullObj) -> MObject {
throw std::logic_error{"Function not yet implemented."};
},
R"pbdoc(Adds an operation to the modifier to create a DAG node of the specified type.
.def("createNode", [](MDagModifier & self, std::string type, MObject parent = MObject::kNullObj) -> MObject {
if (!parent.isNull())
{
validate::has_fn(
parent, MFn::kDagNode,
"Cannot createNode - 'parent' must be a 'kDagNode' object , not a '^1s' object."
);
}

MString type_name(type.c_str());
MStatus status;
MObject result = self.createNode(type_name, parent, &status);

if (status == MS::kInvalidParameter)
{
MString error_msg("Cannot create dependency node '^1s' - use DGModifier instead.");
error_msg.format(error_msg, type_name);
throw pybind11::type_error(error_msg.asChar());
} else if (result.isNull()) {
MString error_msg("Cannot create unknown node type '^1s'.");
error_msg.format(error_msg, type_name);
throw pybind11::type_error(error_msg.asChar());
}

CHECK_STATUS(status)

return result;
}, R"pbdoc(Adds an operation to the modifier to create a DAG node of the specified type.
If a parent DAG node is provided the new node will be parented under it.
If no parent is provided and the new DAG node is a transform type then it will be parented under the world.
In both of these cases, the method returns the new DAG node.
Expand All @@ -17,8 +41,27 @@ and it is the transform node which will be returned by the method, not the child
None of the newly created nodes will be added to the DAG until the modifier's doIt() method is called.)pbdoc")

.def("createNode", [](MDagModifier & self, MTypeId typeId, MObject parent = MObject::kNullObj) -> MObject {
throw std::logic_error{"Function not yet implemented."};
}, R"pbdoc(Adds an operation to the modifier to create a DAG node of the specified type.
MString type_id_str = MString() + typeId.id();

MStatus status;
MObject result = self.createNode(typeId, parent, &status);

if (status == MS::kInvalidParameter)
{
MString error_msg("Cannot create dependency node with type ID '^1s'' - use DGModifier instead.");
error_msg.format(error_msg, type_id_str);
throw pybind11::type_error(error_msg.asChar());
} else if (result.isNull()) {
MString error_msg("Cannot create unknown node with type ID '^1s'.");
error_msg.format(error_msg, type_id_str);
throw pybind11::type_error(error_msg.asChar());
}

CHECK_STATUS(status)

return result;
},
R"pbdoc(Adds an operation to the modifier to create a DAG node of the specified type.
If a parent DAG node is provided the new node will be parented under it.
If no parent is provided and the new DAG node is a transform type then it will be parented under the world.
Expand All @@ -33,7 +76,8 @@ None of the newly created nodes will be added to the DAG until the modifier's do

.def("reparentNode", [](MDagModifier & self, MObject node, MObject newParent = MObject::kNullObj) {
throw std::logic_error{"Function not yet implemented."};
}, R"pbdoc(Adds an operation to the modifier to reparent a DAG node under a specified parent.
},
R"pbdoc(Adds an operation to the modifier to reparent a DAG node under a specified parent.
If no parent is provided then the DAG node will be reparented under the world, so long as it is a transform type.
If it is not a transform type then the doIt() will raise a RuntimeError.)pbdoc");
62 changes: 62 additions & 0 deletions tests/test_MDagModifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import cmdc
import nose

from nose.plugins.skip import SkipTest

from maya import cmds
from maya.api import OpenMaya

from . import assert_equals, as_obj, as_plug, new_scene

def test_createNode():
raise SkipTest("Cannot test DAGModifier.createNode - not sure how to subclass from DGModifier.")


node = as_obj(cmds.createNode('transform'))
type_id = cmdc.FnDependencyNode(node).typeId()

for name, value in (
['typeName', 'transform'],
['typeId', cmdc.TypeId(type_id)]
):
test_createNode.__doc__ = """Test MDagModifier::createNode if called with a valid {}.""".format(name)

yield _createNode_pass, value

for name, value in (
['typeName', 'foobar'],
['typeName', 'network'],
['typeId', cmdc.TypeId(0xdeadbeef)]
):
test_createNode.__doc__ = """Test MDagGModifier::createNode raises error if called with an invalid {}.""".format(name)

yield _createNode_fail, value


@nose.with_setup(teardown=new_scene)
def _createNode_fail(arg):
old_nodes = cmds.ls(long=True)

nose.tools.assert_raises(
TypeError, _createNode_pass, arg
)

new_nodes = cmds.ls(long=True)

assert len(old_nodes) == len(new_nodes), "DagModifier.createNode modified the scene graph."


@nose.with_setup(teardown=new_scene)
def _createNode_pass(arg):
old_nodes = cmds.ls(long=True)

mod = cmdc.DagModifier()
node = mod.createNode(arg, cmdc.Object())
mod.doIt()

new_nodes = cmds.ls(long=True)

add_nodes = set(new_nodes) - set(old_nodes)

assert not node.isNull(), "Created node is not valid."
assert len(add_nodes) == 1, "`ls` did not return new node."

0 comments on commit 64f18b0

Please sign in to comment.