Skip to content

Commit

Permalink
Implement MPlug::set<T> methods that accept POD
Browse files Browse the repository at this point in the history
  • Loading branch information
yantor3d committed May 9, 2021
1 parent 06152fd commit 9a6c7fd
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 22 deletions.
56 changes: 42 additions & 14 deletions src/MPlug.inl
Original file line number Diff line number Diff line change
Expand Up @@ -442,59 +442,87 @@ Note that the behavior of connectedTo() is identical to destinationsWithConversi
}, R"pbdoc(Switches the plug to reference the given attribute of the same node as the previously referenced attribute.)pbdoc")

.def("setBool", [](MPlug & self, bool value) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setBool(value);
}, R"pbdoc(Sets the plug's value as a boolean.)pbdoc")

.def("setChar", [](MPlug & self, char value) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setChar(value);
}, R"pbdoc(Sets the plug's value as a single-byte integer.)pbdoc")

.def("setDouble", [](MPlug & self, double value) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setDouble(value);
}, R"pbdoc(Sets the plug's value as a double-precision float.)pbdoc")

.def("setFloat", [](MPlug & self, float value) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setFloat(value);
}, R"pbdoc(Sets the plug's value as a single-precision float.)pbdoc")

.def("setInt", [](MPlug & self, int value) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setInt(value);
}, R"pbdoc(Sets the plug's value as a regular integer.)pbdoc")

.def("setMAngle", [](MPlug & self, MAngle angle) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setMAngle(angle);
}, R"pbdoc(Sets the plug's value as an MAngle.)pbdoc")

.def("setMDataHandle", [](MPlug & self, MDataHandle dataHandle) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setMDataHandle(dataHandle);
}, R"pbdoc(Sets the plug's value as a data handle.)pbdoc")

.def("setMDistance", [](MPlug & self, MDistance distance) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setMDistance(distance);
}, R"pbdoc(Sets the plug's value as an MDistance.)pbdoc")

.def("setMObject", [](MPlug & self, MObject object) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setMObject(object);
}, R"pbdoc(Sets the plug's value as an MObject.)pbdoc")

.def("setMPxData", [](MPlug & self, MPxData *data) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setMPxData(data);
}, R"pbdoc(Sets the plug's value using custom plug-in data.)pbdoc")

.def("setMTime", [](MPlug & self, MTime time) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setMTime(time);
}, R"pbdoc(Sets the plug's value as an MTime.)pbdoc")

.def("setNumElements", [](MPlug & self, unsigned int num_elements) {
throw std::logic_error{"Function not yet implemented."};
}, R"pbdoc(Pre-allocates space for count elements in an array of plugs.)pbdoc")

.def("setShort", [](MPlug & self, short value) {
throw std::logic_error{"Function not yet implemented."};
plug::assert_not_null(self);

self.setShort(value);
}, R"pbdoc(Sets the plug's value as a short integer.)pbdoc")

.def("setString", [](MPlug & self, MString value) {
throw std::logic_error{"Function not yet implemented."};
.def("setString", [](MPlug & self, std::string value) {
plug::assert_not_null(self);

MString string(value.c_str());

self.setString(string);
}, R"pbdoc(Sets the plug's value as a string.)pbdoc")

.def("source", [](MPlug & self) -> MPlug {
Expand Down
103 changes: 95 additions & 8 deletions tests/test_MPlug.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import cmdc


def p(base, *args):
"""Construct a plug string from the given attributes."""

Expand All @@ -26,7 +27,7 @@ def p(base, *args):

return '.'.join(parts)

@unittest.skip('')

class TestCommonMethods(unittest.TestCase):
"""Tests for common MPlug methods bindings."""

Expand Down Expand Up @@ -55,7 +56,7 @@ def test_info(self):
# You would think it would return the full plug path, but it doesn't...
assert plug.info() == p(self.node, 'branch', 0, 'leaf')

@unittest.skip('')

class TestArrayMethods(unittest.TestCase):
"""Tests for MPlug methods bindings for array/element plugs."""

Expand Down Expand Up @@ -191,7 +192,7 @@ def test_numElements(self):
nose.tools.assert_raises(TypeError, non_array_root.numElements)
nose.tools.assert_raises(ValueError, cmdc.Plug().numElements)

@unittest.skip('')

class TestCompoundPlugMethods(unittest.TestCase):
"""Tests for MPlug methods bindings for compound plugs."""

Expand Down Expand Up @@ -262,7 +263,7 @@ def test_numChildren(self):
nose.tools.assert_raises(TypeError, non_parent.numChildren)
nose.tools.assert_raises(ValueError, cmdc.Plug().numChildren)

@unittest.skip('')

class TestConnectionMethods(unittest.TestCase):
"""Tests for MPlug methods bindings for connections."""

Expand Down Expand Up @@ -381,7 +382,7 @@ def test_sourceWithConversion(self):
nose.tools.assert_raises(ValueError, cmdc.Plug().sourceWithConversion)


def test_asType():
def test_asType_methods():
"""Test for MPlug::as* bindings."""

for (method_name, value, add_attr_kwargs, set_attr_kwargs) in [
Expand All @@ -399,12 +400,12 @@ def test_asType():
('asString', 'hello', {'dt': 'string'}, {'type': 'string'}),
]:
# Somehow, this works
test_asType.__doc__ = """Test for MPlug::{} bindings.""".format(method_name)
test_asType_methods.__doc__ = """Test for MPlug::{} bindings.""".format(method_name)

yield check_asType, method_name, value, add_attr_kwargs, set_attr_kwargs
yield check_asType_method, method_name, value, add_attr_kwargs, set_attr_kwargs


def check_asType(method_name, value, add_attr_kwargs, set_attr_kwargs):
def check_asType_method(method_name, value, add_attr_kwargs, set_attr_kwargs):
"""Test for MPlug::as* bindings."""

# 'asChar' expects an int but returns a char in Python
Expand Down Expand Up @@ -454,4 +455,90 @@ def test_asMObject():
assert value is not None, 'Plug.asMObject returned a null'
assert not value.isNull(), 'Plug.asMObject returned a null MObject'
assert value.hasFn(cmdc.Fn.kMesh), \
'Plug.asMObject returned an object of type {} instead of kMesh'.format(value.apiTypeStr())


def test_setType_methods():
"""Test for MPlug::as* bindings."""

for (method_name, value, add_attr_kwargs) in [
('setBool', True, {'at': 'bool'}),
('setChar', ('A', 65), {'at': 'char'}),
('setDouble', 1.0, {'at': 'double'}),
('setFloat', 1.0, {'at': 'float'}),
('setInt', 5, {'at': 'long'}),
# setMAngle - not yet implemented
# setMDataHandle - not yet implemented
# setMDistance - not yet implemented
# setMObject - custom test (see below)
# setMPxData - not yet implemented
# setMTime - not yet implemented
('setShort', 3, {'at': 'enum', 'enumName': 'a:b:c:d'}),
('setString', 'hello', {'dt': 'string'}),
]:
# Somehow, this works
test_setType_methods.__doc__ = """Test for MPlug::{} bindings.""".format(method_name)

yield check_setType_method, method_name, value, add_attr_kwargs


def check_setType_method(method_name, value, add_attr_kwargs):
"""Test for MPlug::set* bindings."""

# 'asChar' expects an int but returns a char in Python
if isinstance(value, tuple):
in_value, out_value = value
else:
in_value = value
out_value = value

node = cmds.createNode('network')

attr = p(node, 'attr')

cmds.addAttr(node, ln='attr', **add_attr_kwargs)

plug = cmdc.SelectionList().add(attr).getPlug(0)

method = getattr(plug, method_name)
method(in_value)

expected = out_value
actual = cmds.getAttr(attr)

error_message = (
'Plug method {} set the wrong value - expected: {}, actual: {}'
.format(
method_name, expected, actual
)
)

if isinstance(expected, float):
assert abs(expected - actual) <= 1e-5, error_message
else:
assert expected == actual, error_message


def test_setMObject():
"""Test for MPlug::setMObject bindings."""

node = cmds.createNode('network')

cmds.addAttr(node, ln='attr', dt='mesh')

cube, = cmds.polyCube(constructionHistory=False)
mesh, = cmds.listRelatives(cube, children=True, type='mesh')

src_plug = cmdc.SelectionList().add(p(mesh, 'worldMesh')).getPlug(0)
dst_plug = cmdc.SelectionList().add(p(node, 'attr')).getPlug(0)

src_value = src_plug.asMObject()

dst_plug.setMObject(src_value)

dst_value = dst_plug.asMObject()

assert dst_value is not None, 'Plug.asMObject returned a null'
assert not dst_value.isNull(), 'Plug.asMObject returned a null MObject'
assert dst_value.hasFn(cmdc.Fn.kMesh), \
'Plug.asMObject returned an object of type {} instead of kMesh'.format(value.apiTypeStr())

0 comments on commit 9a6c7fd

Please sign in to comment.