def test_getattrcomplex(): """Complex getAttr""" node = cmdx.createNode("transform") assert_equals(node["worldMatrix"], (( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, ),)) # Note the returned tuple in the above assert_equals(node["worldMatrix"][0], ( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, )) node["tx"] = 5.0 assert_equals(node["worldMatrix"][0], ( 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 5.0, 0.0, 0.0, 1.0, )) locator = cmdx.createNode("locator", parent=node) assert_equals(locator["worldPosition"], ( 5.0, 0.0, 0.0 ))
def test_descendents(): """Returning all descendents works""" gp = cmdx.createNode("transform") p = cmdx.createNode("transform", parent=gp) c = cmdx.createNode("transform", parent=p) descendents = list(gp.descendents()) assert_equals(descendents, [p, c])
def test_descendents_typeid(): """Returning only descendents of typeName works""" gp = cmdx.createNode("transform") p = cmdx.createNode("transform", parent=gp) c = cmdx.createNode("transform", parent=p) m = cmdx.createNode("mesh", parent=c) descendents = list(gp.descendents(type=cmdx.tMesh)) assert_equals(descendents, [m])
def test_createNode(): """cmdx.createNode works""" node = cmdx.createNode("transform") parent = cmdx.createNode("transform", name="MyNode") assert_equals(parent.name(), "MyNode") child = cmdx.createNode("transform", name="MyNode", parent=parent) assert_equals(child, parent.child()) node = cmdx.createNode("transform", name="MyNode") node = cmdx.createNode("transform", name="MyNode", parent=node)
def test_nodereuse_equalexist(): """Node re-use on new, same-name nodes""" nodeA = cmdx.createNode("transform", name="myNode") nodeB = cmdx.createNode("transform", parent=nodeA) assert_is(cmdx.encode("|myNode"), nodeA) assert_is(nodeB.parent(), nodeA) cmds.file(new=True, force=True) assert_raises(cmdx.ExistError, cmdx.encode, "|myNode") nodeC = cmdx.createNode("transform", name="myNode") assert_is(cmdx.encode("|myNode"), nodeC)
def test_timings(): """CMDX_TIMINGS outputs timing information""" import cmdx cmdx.createNode("transform", name="myNode") # Trigger re-use timings cmdx.encode("myNode") assert cmdx.LastTiming is None with environment("CMDX_TIMINGS") as cmdx: cmdx.encode("myNode") assert cmdx.LastTiming is not None, cmdx.LastTiming
def test_rouge_mode(): """CMDX_ROGUE_MODE is faster""" node = cmdx.createNode("transform") Compare("norogue", "createNode", node.name) with environment("CMDX_ROGUE_MODE"): node = cmdx.createNode("transform") Compare("rogue", "createNode", node.name) rogue_vs_norogue = (timings["createNode"]["norogue"]["percall"] / timings["createNode"]["rogue"]["percall"]) assert_greater(rogue_vs_norogue, 0.9)
def test_getattrtime(): """getAttr(time=)""" transform = cmdx.createNode("transform") for time, value in ((1, 1.0), (10, 10.0)): cmds.setKeyframe(str(transform), time=[time], attribute="translateY", value=value) cmds.keyTangent(str(transform), edit=True, time=(1, 10), attribute="translateY", outTangentType="linear") # These floating point values can differ ever so slightly assert_almost_equals(transform["ty"].read(time=1), 1.0, places=5) assert_almost_equals(transform["ty"].read(time=5), 5.0, places=5) assert_almost_equals(transform["ty"].read(time=10), 10.0, places=5) # From the current context (Maya 2018 and above) if hasattr(om.MDGContext, "makeCurrent"): with cmdx.DGContext(1.0): assert_almost_equals(transform["ty"].read(), 1.0, places=5) with cmdx.DGContext(5.0): assert_almost_equals(transform["ty"].read(), 5.0, places=5) with cmdx.DGContext(10.0): assert_almost_equals(transform["ty"].read(), 10.0, places=5)
def test_createNode_performance(): """createNode cmdx vs cmds > 2x""" versions = ( ("mel", lambda: mel.eval("createNode \"transform\"")), ("cmds", lambda: cmds.createNode("transform")), ("cmdx", lambda: cmdx.createNode(cmdx.tTransform)), # ("PyMEL", lambda: pm.createNode("transform")), ("API 1.0", lambda: om1.MFnDagNode().create("transform")), ("API 2.0", lambda: om2.MFnDagNode().create("transform")), ) for contender, test in versions: Compare(contender, "createNode", test, setup=New) cmdx_vs_cmds = (timings["createNode"]["cmds"]["percall"] / timings["createNode"]["cmdx"]["percall"]) cmdx_vs_api = (timings["createNode"]["API 2.0"]["percall"] / timings["createNode"]["cmdx"]["percall"]) if cmdx.__maya_version__ == 2017: assert_greater(cmdx_vs_cmds, 0.4545) # at most 2.2x slower than cmds assert_greater(cmdx_vs_api, 0.1818) # at most 5.5x slower than API 2.0 else: assert_greater(cmdx_vs_cmds, 0.5) # at most 2x slower than cmds assert_greater(cmdx_vs_api, 0.20) # at most 5x slower than API 2.0
def test_nodeoperators(): """Node operators works""" node = cmdx.createNode(cmdx.tTransform, name="myNode") assert_equals(node, "|myNode") assert_not_equals(node, "|NotEquals") assert_equals(str(node), repr(node))
def test_assign_tm(): """Assign MTransformationMatrix works""" node = cmdx.createNode("transform") tm = node["worldMatrix"][0].asTm() node["translate"] = tm.translation() node["rotate"] = tm.rotation()
def test_assign_toangle(): """Assign to Angle3 works""" node = cmdx.createNode("transform") node["Limits"] = cmdx.Angle3() node["Limits"] = (0, 0, 0) node["Limits"] = 0 # Crash!
def test_nodereuse_noexist(): """Node re-use works on non-existent nodes""" nodeA = cmdx.createNode("transform", name="myNode") nodeB = cmdx.createNode("transform", parent=nodeA) assert_is(cmdx.encode("|myNode"), nodeA) assert_is(nodeB.parent(), nodeA) cmds.file(new=True, force=True) # Even if it's available for re-use, it will still throw # a cmdx.ExistError on account of trying to fetch an MObject # from a non-existing node. assert_raises(cmdx.ExistError, cmdx.encode, "|myNode") # Any operation on a deleted node raises RuntimeError assert_raises(RuntimeError, lambda: nodeA.name())
def test_getattrtypes(): """Explicit getAttr""" node = cmdx.createNode("transform") assert_equals(node["translate"].read(), (0.0, 0.0, 0.0)) assert_equals(node["rotate"].read(), (0.0, 0.0, 0.0)) assert_equals(node["scale"].read(), (1.0, 1.0, 1.0)) assert_equals(node["tx"].read(), 0.0) assert_equals(node["ry"].read(), 0.0) assert_equals(node["sz"].read(), 1.0)
def test_getcached(): """Returning a cached plug works""" node = cmdx.createNode("transform") assert_equals(node["translate"], (0.0, 0.0, 0.0)) assert_equals(node["rotate"], (0.0, 0.0, 0.0)) node["tx"] = 5 assert_equals(node["tx"], 5) node["tx"] = 10 assert_equals(node["tx", cmdx.Cached], 5) assert_equals(node["tx"], 10)
def test_nodereuse(): """Node re-use works ok""" import cmdx nodeA = cmdx.createNode("transform", name="myNode") nodeB = cmdx.createNode("transform", parent=nodeA) assert_is(cmdx.encode("|myNode"), nodeA) assert_is(nodeB.parent(), nodeA) with tempdir() as tmp: fname = os.path.join(tmp, "myScene.ma") cmds.file(rename=fname) cmds.file(save=True, type="mayaAscii") cmds.file(fname, open=True, force=True) # On scene open, the current scene is closed, triggering # the nodeDestroyed callback which invalidates the node # for cmdx. Upon encoding this node anew, cmdx will # allocate a new instance for it. assert_is_not(cmdx.encode("|myNode"), nodeA)
def test_channelBox(): """Plug.channelBox = True works""" node = cmdx.createNode("transform") assert_equals(node["translateX"].channelBox, False) node["translateX"].channelBox = True assert_equals(node["translateX"].channelBox, True) assert_equals(node["translate"].channelBox, False) node["translate"].channelBox = True assert_equals(node["translate"].channelBox, True)
def test_keyable(): """Plug.keyable = True works""" node = cmdx.createNode("transform") assert_equals(node["translateX"].keyable, True) node["translateX"].keyable = False assert_equals(node["translateX"].keyable, False) assert_equals(node["rotate"].keyable, True) node["rotate"].keyable = False assert_equals(node["rotate"].keyable, False)
def test_setattr(): """Setting attributes works well""" transform = cmdx.createNode("transform") # Setting single with single transform["translateX"] = 1.0 # Multi with multi transform["translate"] = (1.0, 2.0, 3.0) transform["translate"] = (1, 2, 3) # Automatic cast to float # Multi with single transform["translate"] = 1.0 assert_equals(transform["translate"].read(), (1.0, 1.0, 1.0)) # Plug with plug transform["translate"] = transform["translate"]
def test_getattrtime(): """getAttr(time=)""" transform = cmdx.createNode("transform") for time, value in ((0, 0.0), (24, 10.0)): cmds.setKeyframe(str(transform), time=[time], attribute="translateY", value=value) cmds.keyTangent(str(transform), edit=True, time=(0, 24), attribute="translateY", inTangentType="linear", outTangentType="linear") # These floating point values can differ ever so slightly assert_almost_equals(transform["ty"].read(time=0.0), 0.0, places=5) assert_almost_equals(transform["ty"].read(time=0.5), 5.0, places=5) assert_almost_equals(transform["ty"].read(time=1.0), 10.0, places=5) # From the current context (Maya 2018 and above) if hasattr(om.MDGContext, "makeCurrent"): with cmdx.DGContext(0.0): assert_almost_equals(transform["ty"].read(), 0.0, places=5) with cmdx.DGContext(0.5): assert_almost_equals(transform["ty"].read(), 5.0, places=5) with cmdx.DGContext(1.0): assert_almost_equals(transform["ty"].read(), 10.0, places=5) # Custom units with cmdx.DGContext(0, cmdx.TimeUiUnit()): assert_almost_equals(transform["ty"].read(), 0.0, places=5) with cmdx.DGContext(12, cmdx.TimeUiUnit()): assert_almost_equals(transform["ty"].read(), 5.0, places=5) with cmdx.DGContext(24, cmdx.TimeUiUnit()): assert_almost_equals(transform["ty"].read(), 10.0, places=5) # Alternate syntax with cmdx.DGContext(cmdx.TimeUiUnit()(0)): assert_almost_equals(transform["ty"].read(), 0.0, places=5) with cmdx.DGContext(cmdx.TimeUiUnit()(12)): assert_almost_equals(transform["ty"].read(), 5.0, places=5) with cmdx.DGContext(cmdx.TimeUiUnit()(24)): assert_almost_equals(transform["ty"].read(), 10.0, places=5)
def test_getattrtime(): """getAttr(time=)""" transform = cmdx.createNode("transform") for time, value in ((1, 1.0), (10, 10.0)): cmds.setKeyframe(str(transform), time=[time], attribute="translateY", value=value) cmds.keyTangent(str(transform), edit=True, time=(1, 10), attribute="translateY", outTangentType="linear") # These floating point values can differ ever so slightly assert_almost_equals(transform["ty"].read(time=1), 1.0, places=5) assert_almost_equals(transform["ty"].read(time=5), 5.0, places=5) assert_almost_equals(transform["ty"].read(time=10), 10.0, places=5)
# Basic scenegraph manipulation import cmdx node1 = cmdx.createNode("transform") node2 = cmdx.createNode(cmdx.Transform) node1["tx"] = 2.5 print(node1) print(node1["tx"]) # 2.5 node1["tx"] >> node2["tx"] print(node2["tx"]) # 2.5
def test_getattrimplicit(): """Implicit getAttr""" node = cmdx.createNode("transform") assert_equals(node["sz"], 1.0)
def test_plugreuse(): """Plug re-use works ok""" import cmdx node = cmdx.createNode("transform") id(node["translate"]) == id(node["translate"])
def om2SetAttr(value): """Fastest way of getting an attribute with API 2.0""" plug = api2mfn.findPlug("translateX", False) return plug.setDouble(value) New() Test("cmdx", "import", lambda: reload(cmdx), number=100) Test("cmds", "import", lambda: reload(cmds), number=100) Test("PyMEL", "import", reload_pymel, number=1) New() node = cmdx.createNode("transform", name="Node") path = node.path() pynode = pm.PyNode(path) api1node = om1.MFnDagNode().create("transform") api2node = om2.MFnDagNode().create("transform") api1mfn = om1.MFnDagNode(api1node) api2mfn = om2.MFnDagNode(api2node) node = cmdx.createNode("transform", name="Node") path = node.path() pynode = pm.PyNode(path) api1node = om1.MFnDagNode().create("transform") api2node = om2.MFnDagNode().create("transform") api1mfn = om1.MFnDagNode(api1node) api2mfn = om2.MFnDagNode(api2node)