def test_reparent(): _new() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) joint3 = cmds.joint() # tip cmds.move(10, 5, 0) joint4 = cmds.joint() cmds.move(5, 10, 0) # o <-- reparent to b # \ # o---o---o # a b solver = api.createSolver() markers = api.assignMarkers([joint1, joint2, joint3, joint4], solver) api.reparentMarker(markers[3], markers[1]) # Check it child = cmdx.encode(markers[3]) parent = cmdx.encode(markers[1]) assert child["parentMarker"].input() is parent, "%s != %s" % ( child["parentMarker"].input(), parent)
def test_unparent(): _new() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) joint3 = cmds.joint() # tip cmds.move(10, 5, 0) joint4 = cmds.joint() cmds.move(5, 10, 0) # o <-- unparent # \ # o---o---o # a b solver = api.createSolver() markers = api.assignMarkers([joint1, joint2, joint3, joint4], solver) api.unparentMarker(markers[3]) # Check it child = cmdx.encode(markers[3]) old_parent = cmdx.encode(markers[2]) assert child["parentMarker"].input() is None, "%s == %s" % ( child["parentMarker"].input(), old_parent)
def test_retarget(): _new() solver = api.createSolver() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) cmds.joint() # tip cmds.move(10, 5, 0) markers = api.assignMarkers([joint1, joint2], solver) # Retarget to this box box, _ = cmds.polyCube() api.retargetMarker(markers[1], box) # The box should now get recorded, not the joint cmdx.min_time(1) cmdx.max_time(50) api.recordPhysics(solver) joint2 = cmdx.encode(joint2) box = cmdx.encode(box) assert not joint2["tx"].input(), "%s was connected" % joint2["tx"].path() assert box["tx"].input(), "%s was not connected" % box["tx"].path()
def test_record_constrained_controls(): # Existing constraints should be preserved _new() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) joint3 = cmds.joint() # tip cmds.move(10, 5, 0) ctrl = cmds.createNode("transform", name="control") con = cmds.parentConstraint(ctrl, joint1)[0] # o---o---o # 1 2 3 solver = api.createSolver() api.assignMarkers([joint1, joint2, joint3], solver) cmdx.min_time(1) cmdx.max_time(5) # Won't need many frames api.recordPhysics(solver) # The joint was kinematic, and is still connected joint1 = cmdx.encode(joint1) con = cmdx.encode(con) assert_equals(joint1["tx"].input(type="parentConstraint"), con)
def test_record_ik(): # Recording IK involves retargeting and untargeting _new() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) joint3 = cmds.joint() # tip cmds.move(10, 5, 0) handle, eff = cmds.ikHandle(joint1, joint2) pole = cmds.spaceLocator()[0] cmds.poleVectorConstraint(pole, handle)[0] # o---o---o # 1 2 3 solver = api.createSolver() markers = api.assignMarkers([joint1, joint2, joint3], solver) api.untarget_marker(markers[0]) api.retarget_marker(markers[1], pole) api.retarget_marker(markers[2], handle) cmdx.min_time(1) cmdx.max_time(5) # Won't need many frames api.recordPhysics(solver) joint1 = cmdx.encode(joint1) joint2 = cmdx.encode(joint2) handle = cmdx.encode(handle) assert not joint1["tx"].connected, "%s was connected" % joint1["tx"].path() assert not joint2["tx"].connected, "%s was connected" % joint2["tx"].path() assert handle["tx"].connected, "%s was not connected" % handle["tx"].path()
def test_record_options(): _new() solver = api.createSolver() cube1, _ = cmds.polyCube() cmds.move(0, 100) cmds.setAttr(solver + ".startTime", api.StartTimeCustom) cmds.setAttr(solver + ".startTimeCustom", 10) api.assignMarker(cube1, solver) start = cmdx.time(10) end = cmdx.time(15) api.record_physics(solver, opts={ "startTime": start, "endTime": end, "toLayer": False, }) # Should still be at a Y-value of 100 here cube1 = cmdx.encode(cube1) assert cube1["ty"].read(time=start) > 99, ("%s was not 100" % cube1["ty"].read(time=start)) assert cube1["ty"].read(time=end) < 99, ( "Should have fallen more than %s" % cube1["ty"].read(time=end)) # Not baking to a layer curve_type = "animCurveTL" assert cube1["ty"].input().isA(curve_type), ( "%s.%s should have been an '%s'" % (cube1["ty"].input(), cube1["ty"].input().type_name, curve_type))
def test_link_solver(): _new() cube1, _ = cmds.polyCube(height=1) cmds.move(0, 5, 0) cube2, _ = cmds.polyCube(height=1) cmds.move(0, 10, 0) solver1 = api.createSolver() solver2 = api.createSolver() api.createGround(solver1) api.createGround(solver2) api.assignMarker(cube1, solver1) api.assignMarker(cube2, solver2) api.linkSolver(solver1, solver2) api.recordPhysics(solver2, opts={"startTime": 1, "endTime": 20}) # box2 is now stacked on top of box1 cube2 = cmdx.encode(cube2) # The center of the cube on top of the other cube # both of which are 1 unit high. # ____ # / /| # /___/ | <--- 1.5 units # | | / # |___|/| # | | / # |___|/ # assert_almost_equals(cmds.getAttr("pCube2.ty", time=20), 1.5, 1)
def test_animated_controls(): # Existing animation should be kept and ignored, # new animation ending up on a layer _new() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) joint3 = cmds.joint() # tip cmds.move(10, 5, 0) joint = cmdx.encode(joint2) joint["rz"] = {1: 0.0, 10: 1.0, 20: 0.0} # Some animation solver = api.createSolver() api.assignMarkers([joint1, joint2, joint3], solver) cmdx.min_time(1) cmdx.max_time(15) api.recordPhysics(solver) # It must have changed by now value = joint["rz"].read(time=cmdx.time(10)) assert_not_equals("%.1f" % value, "1.0") # Deleting the animation layer restores the original animation cmds.delete(cmds.ls(type="container")) value = joint["rz"].read(time=cmdx.time(10)) assert_equals("%.1f" % value, "1.0")
def test_record_nokinematic(): _new() solver = api.createSolver() cube1, _ = cmds.polyCube() marker = api.assignMarker(cube1, solver) cmds.setAttr(marker + ".inputType", api.InputKinematic) api.recordPhysics(solver, opts={"includeKinematic": False}) cube1 = cmdx.encode(cube1) assert not cube1["tx"].connected, ( "%s was kinematic, it should not have been recorded" % cube1["tx"].path())
def test_assign_group(): _new() solver = api.createSolver() joint1 = cmds.joint() cmds.move(0, 5, 0) joint2 = cmds.joint() cmds.move(5, 5, 0) cmds.joint() # tip cmds.move(10, 5, 0) markers = api.assignMarkers([joint1, joint2], solver) # Check the results marker = cmdx.encode(markers[0]) group = marker["startState"].output(type="rdGroup") group["driveStiffness"] = 0.001 cmdx.min_time(1) cmdx.max_time(50) api.recordPhysics(solver) joint2 = cmdx.encode(joint2) assert_almost_equals(joint2["rz", cmdx.Degrees].read(time=cmdx.time(50)), -32, 0)
def test_marker_options(): _new() solver = api.createSolver() cube1, _ = cmds.polyCube() marker1 = api.assignMarker(cube1, solver, opts={ "density": api.DensityWood, }) marker1 = cmdx.encode(marker1) assert marker1["densityType"] == api.DensityWood, ( "Density '%d' should have been '%d'" % (marker1["densityType"], api.DensityWood))
def test_record(): _new() solver = api.createSolver() cube1, _ = cmds.polyCube() api.assignMarker(cube1, solver) api.record_physics(solver) cube1 = cmdx.encode(cube1) assert cube1["tx"].connected, ("%s should have been recorded" % cube1["tx"].path()) # Baking to layer per default, which means the curve type is curve_type = "animBlendNodeAdditiveDL" assert cube1["tx"].input().isA(curve_type), ( "%s.%s should have been an '%s'" % (cube1["tx"].input(), cube1["tx"].input().type_name, curve_type))