diff --git a/src/ForwardDeclarations.inl b/src/ForwardDeclarations.inl index 08f719c..7817aba 100644 --- a/src/ForwardDeclarations.inl +++ b/src/ForwardDeclarations.inl @@ -1,12 +1,16 @@ py::class_ Angle(m, "Angle"); py::class_ DAGDrawOverrideInfo(m, "DAGDrawOverrideInfo"); +py::class_ DGModifier(m, "DGModifier"); +py::class_ DagModifier(m, "DagModifier"); py::class_ DagPath(m, "DagPath"); py::class_ DagPathArray(m, "DagPathArray"); py::class_ DataBlock(m, "DataBlock"); py::class_ DataHandle(m, "DataHandle"); py::class_ Distance(m, "Distance"); py::class_ Fn(m, "Fn"); -py::class_ FnDependencyNode(m, "FnDependencyNode"); +py::class_ FnBase(m, "FnBase"); +py::class_ FnDependencyNode(m, "FnDependencyNode"); +py::class_ FnDagNode(m, "FnDagNode"); py::class_ Matrix(m, "Matrix"); py::class_ Object(m, "Object"); py::class_ ObjectArray(m, "ObjectArray"); @@ -24,7 +28,5 @@ py::class_ Vector(m, "Vector"); py::enum_ fn_type(Fn, "Type"); py::class_ Uuid(m, "Uuid"); py::class_ NodeClass(m, "NodeClass"); -py::class_ DGModifier(m, "DGModifier"); -py::class_ FnDagNode(m, "FnDagNode"); py::class_ BoundingBox(m, "BoundingBox"); py::class_ Color(m, "Color"); \ No newline at end of file diff --git a/src/MDagModifier.inl b/src/MDagModifier.inl index 8c457f6..2dffb6d 100644 --- a/src/MDagModifier.inl +++ b/src/MDagModifier.inl @@ -25,9 +25,7 @@ "If it is not a transform type then the doIt() will raise a RuntimeError." -#include "MDGModifier.inl" - -py::class_(m, "DagModifier") +DagModifier .def(py::init<>()) .def("createNode", [](MDagModifier & self, std::string type, MObject parent = MObject::kNullObj) -> MObject { diff --git a/src/MFnBase.inl b/src/MFnBase.inl new file mode 100644 index 0000000..6b43687 --- /dev/null +++ b/src/MFnBase.inl @@ -0,0 +1,57 @@ +#define _doc_FnBase_type \ + "Returns the type of the function set." + +#define _doc_FnBase_hasObj \ + "Returns True if the function set is compatible with the specified Maya object." + +#define _doc_FnBase_object \ + "Returns a reference to the object to which the function set is currently attached, or MObject.kNullObj if none." + +#define _doc_FnBase_setObject \ + "Attaches the function set to the specified Maya object." + +#define _doc_FnBase_className \ + "Returns the name of this class." + +#define _doc_FnBase_typeString \ + "Returns the type string for a given type." + +#define _doc_FnBase_isValid \ + "Returns true if type is in the range of valid types." + + +FnBase + .def("type", &MFnBase::type, _doc_FnBase_type) + + .def("hasObj", [](MFnBase& self, MFn::Type mtype) -> bool + { return self.hasObj(mtype); }, + py::arg("mtype"), _doc_FnBase_hasObj) + + .def("hasObj", [](MFnBase& self, const MObject& object) -> bool + { return self.hasObj(object); }, + py::arg("object"), _doc_FnBase_hasObj) + + .def("object", [](MFnBase& self) -> MObject { + MStatus status; + MObject result = self.object(&status); + CHECK_STATUS(status); + return result; + }, _doc_FnBase_object) + + .def("setObject", [](MFnBase& self, const MObject & object) -> void { + if (!self.setObject(object)) throw std::runtime_error( + "Invalid parameter passed for node - " + "not a DAG Node, " + "Node does not exist or " + "no valid pointer to Node" + ); + }, py::arg("object"), _doc_FnBase_setObject) + + .def("className", &MFnBase::className, _doc_FnBase_className) + + // These methods are new in maya 2020+ + #if MAYA_APP_VERSION >= 2020 + .def_static( "typeString", &MFnBase::typeString, py::arg("mtype"), _doc_FnBase_typeString) + .def_static("isValid", &MFnBase::isValid, py::arg("mtype"), _doc_FnBase_isValid) + #endif +; \ No newline at end of file diff --git a/src/MFnDagNode.inl b/src/MFnDagNode.inl index 5fb1d73..b135313 100644 --- a/src/MFnDagNode.inl +++ b/src/MFnDagNode.inl @@ -97,9 +97,6 @@ #define _doc_FnDagNode_setObject \ "Attaches the function set to the specified node or DAG path." -#define _doc_FnDagNode_setObject \ - "Attaches the function set to the specified node or DAG path." - #define _doc_FnDagNode_transformationMatrix \ "Returns the object space transformation matrix for this DAG node." @@ -388,16 +385,6 @@ FnDagNode return self.removeChildAt(index); }, py::arg("index"), _doc_FnDagNode_removeChildAt) - .def("setObject", [](MFnDagNode& self, MObject& object) -> void { - if (!self.setObject(object)) throw std::runtime_error( - "Invalid parameter passed for node - " - "not a DAG Node, " - "Node does not exist or " - "no valid pointer to Node" - ); - }, py::arg("object"), - _doc_FnDagNode_setObject) - .def("setObject", [](MFnDagNode& self, MDagPath path) { if (!self.setObject(path)) throw std::runtime_error( "Invalid parameter passed for objectPath - " diff --git a/src/main.cpp b/src/main.cpp index 89c967b..a6929f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -73,10 +74,11 @@ PYBIND11_MODULE(cmdc, m) { #include "MDagPath.inl" #include "MDGModifier.inl" #include "MFn.inl" - #include "Types.inl" - #include "MObject.inl" + #include "MFnBase.inl" #include "MFnDependencyNode.inl" #include "MFnDagNode.inl" + #include "Types.inl" + #include "MObject.inl" #include "MBoundingBox.inl" #include "MPlug.inl" #include "MSelectionList.inl" diff --git a/tests/test_MDagModifier.py b/tests/test_MDagModifier.py index 9d2fa6e..cbd0082 100644 --- a/tests/test_MDagModifier.py +++ b/tests/test_MDagModifier.py @@ -8,6 +8,9 @@ from . import assert_equals, as_obj, as_plug, new_scene +def test_subclassDGModifier(): + assert issubclass(cmdc.DagModifier, cmdc.DGModifier) + def test_createNode(): return diff --git a/tests/test_MFnBase.py b/tests/test_MFnBase.py new file mode 100644 index 0000000..9f933bb --- /dev/null +++ b/tests/test_MFnBase.py @@ -0,0 +1,62 @@ +import cmdc +import maya.api.OpenMaya as om +import nose +from nose.tools import raises + + +def test_type(): + sel = cmdc.SelectionList().add("persp") + persp = sel.getDependNode(0) + fn = cmdc.FnDagNode(persp) + assert cmdc.FnBase.type(fn) == cmdc.Fn.kDagNode + +def test_hasObj(): + # we have to test this on a subclass of FnBase as it can't be instantiated + sel = cmdc.SelectionList().add("persp") + persp = sel.getDependNode(0) + fn = cmdc.FnDagNode(persp) + assert fn.hasObj(persp) + +def test_object(): + # we have to test this on a subclass of FnBase as it can't be instantiated + sel = cmdc.SelectionList().add("persp") + persp = sel.getDependNode(0) + fn = cmdc.FnDagNode(persp) + assert fn.object() == persp + +@raises(RuntimeError) +def test_object_invalid(): + fn = cmdc.FnDagNode() + fn.object() + +def test_setObject(): + # we have to test this on a subclass of FnBase as it can't be instantiated + sel = cmdc.SelectionList().add("persp").add("perspShape") + persp = sel.getDependNode(0) + persp_shape = sel.getDependNode(1) + + fn = cmdc.FnDagNode(persp) + assert fn.object() == persp + + fn.setObject(persp_shape) + assert fn.object() == persp_shape + +def test_className(): + assert cmdc.FnBase.className() == cmdc.FnBase.__name__ + +def test_typeString(): + if om.MGlobal.apiVersion() < 20200000: + raise nose.SkipTest( + "MFnBase::typeString is not defined prior to maya 2020." + ) + + assert cmdc.FnBase.typeString(cmdc.Fn.kDagNode) == "kDagNode" + +def test_isValid(): + if om.MGlobal.apiVersion() < 20200000: + raise nose.SkipTest( + "MFnBase::isValid is not defined prior to maya 2020." + ) + + assert cmdc.FnBase.isValid(cmdc.Fn.kDagNode) is True + assert cmdc.FnBase.isValid(cmdc.Fn.kLast) is False diff --git a/tests/test_MFnDagNode.py b/tests/test_MFnDagNode.py index a498841..dd0d0be 100644 --- a/tests/test_MFnDagNode.py +++ b/tests/test_MFnDagNode.py @@ -4,6 +4,8 @@ assert_equals, ) +def test_inherits_FnDependencyNode(): + assert issubclass(cmdc.FnDagNode, cmdc.FnDependencyNode) def test_create(): fn = cmdc.FnDagNode() diff --git a/tests/test_MFnDependencyNode.py b/tests/test_MFnDependencyNode.py new file mode 100644 index 0000000..22541f5 --- /dev/null +++ b/tests/test_MFnDependencyNode.py @@ -0,0 +1,4 @@ +import cmdc + +def test_inherits_FnBase(): + assert issubclass(cmdc.FnDependencyNode, cmdc.FnBase) \ No newline at end of file