What i am trying to achieve is to rig in Maya a ratchet. Right now I have a controller with limit rotation X values from 0-55. I created a driven key between my controller and the ratchet's rotation Z, so when the driver is 0 the driven is 0 and when the driver is 55 the driven is 60, there are also some in-between keys. What I want is, when the animator put the driver to 55 the driven must go to 60, until now all good, but when the animator puts the driver's value back to 0 I want the drive n's value to remain at 60. so when the driver goes again to 55 then the driver will go to 120 etc. This will be repeated until the ratchet goes 360. The only I have manage to do is to create a long attribute with values from 0-336, where everything happens at once. So there is no need for the animator to place the driver back to 0. But this is quite confusing. I know driven keys are mapped values so it is unavoidable , but how can I do this? I need script node with python where the animation node stops? and then starts again
So I am trying to write a function that will be in a scriptNode so will run each time the animator put values on the rotateX of the hammer. From 0—>55 is working, but i am stuck at the point where i have to lower the values from 55–>0.
import maya.cmds as mc
def hammer_C():
RX = mc.getAttr(‘hammer.rotateX’)
RZ = mc.getAttr(‘cylider.rotateZ’)
if RX > 0:
mc.setAttr(‘cylider.rotateZ’, -RX )
elif RX < 55:
mc.setAttr(‘cylider.rotateZ’, RZ )
else:
print ‘TEST’
So basically i would like to know if there is a way in Python to say: As the value_A goes from 0 to 55 do that and as the value_A goes from 55 to 0 do something else
I don't know maya, but I think I understand what you need, you are trying to model ratchet device and by 55
or 60
or 360
you mean current rotation angle in degrees.
I also expect that you need to lock your ratchet at every 60
degrees, meaning that as soon as it has reached angle multiple of 60
degrees it should be locked from going backward below that degree. And between two multiples of 60
it may go forward and backward.
Hence I suggest next code, it is not maya-specific but still it may give you idea what to do and can be adopted to your case. We can start from this code and imporve it if needed.
I understood that you don't know python much and for that I've also created very small piece of code with one-line formula (computation of next_driven_angle
) that you can also try online (plus accepted final version with maya):
import math
previous_driver_angle = 0.
previous_driven_angle = 0.
for next_driver_angle in [0, 10, 25, 35, 55, 35, 45]:
next_driven_angle = max(math.floor(previous_driven_angle / 60. + 10 ** -6) * 60., previous_driven_angle + (next_driver_angle - previous_driver_angle) * 60. / 55.)
print('driver', next_driver_angle, 'driven', next_driven_angle)
previous_driver_angle = next_driver_angle
previous_driven_angle = next_driven_angle
Output of this small code above is:
driver 0 driven 0.0
driver 10 driven 10.909090909090908
driver 25 driven 27.272727272727273
driver 35 driven 38.18181818181818
driver 55 driven 60.0
driver 35 driven 60.0
driver 45 driven 70.9090909090909
Output of next big code (listed down below afterwards) emulating random process of ratchet:
0: driver 0.0 driven 0.0 non-locked | 1: driver -33.8 driven 0.0 locked |
2: driver -17.0 driven 18.4 non-locked | 3: driver 3.5 driven 40.7 non-locked |
4: driver 34.8 driven 74.9 non-locked | 5: driver 53.9 driven 95.7 non-locked |
6: driver 90.2 driven 135.3 non-locked | 7: driver 79.0 driven 123.0 non-locked |
8: driver 103.7 driven 150.0 non-locked | 9: driver 67.3 driven 120.0 locked |
10: driver 34.9 driven 120.0 locked | 11: driver 22.5 driven 120.0 locked |
12: driver -13.5 driven 120.0 locked | 13: driver 5.4 driven 140.6 non-locked |
14: driver -11.9 driven 121.7 non-locked | 15: driver -48.5 driven 120.0 locked |
16: driver -67.5 driven 120.0 locked | 17: driver -78.0 driven 120.0 locked |
18: driver -56.0 driven 143.9 non-locked | 19: driver -27.2 driven 175.3 non-locked |
20: driver -60.2 driven 139.4 non-locked | 21: driver -60.2 driven 139.4 non-locked |
22: driver -25.5 driven 177.3 non-locked | 23: driver -38.5 driven 163.1 non-locked |
24: driver -30.8 driven 171.4 non-locked | 25: driver -40.4 driven 161.0 non-locked |
26: driver -8.3 driven 196.0 non-locked | 27: driver -5.0 driven 199.6 non-locked |
28: driver -25.4 driven 180.0 locked | 29: driver -21.0 driven 184.8 non-locked |
30: driver 7.3 driven 215.6 non-locked | 31: driver 39.9 driven 251.1 non-locked |
32: driver 1.3 driven 240.0 locked | 33: driver 24.8 driven 265.6 non-locked |
34: driver 48.7 driven 291.7 non-locked | 35: driver 71.7 driven 316.8 non-locked |
36: driver 79.3 driven 325.0 non-locked | 37: driver 54.7 driven 300.0 locked |
38: driver 73.8 driven 320.8 non-locked | 39: driver 43.5 driven 300.0 locked |
40: driver 6.6 driven 300.0 locked | 41: driver -29.4 driven 300.0 locked |
42: driver -7.7 driven 323.6 non-locked | 43: driver 20.5 driven 354.4 non-locked |
44: driver -12.0 driven 318.9 non-locked | 45: driver 23.8 driven 358.0 non-locked |
46: driver 61.8 driven 399.4 non-locked |
Next code can be also run online here.
def Main():
import math, random, sys
driven_lock_angle_step = 60.
driver_to_driven_ratio = 55. / driven_lock_angle_step
driver_angle = 0.
driven_angle = 0.
def SetDriverAngle(new_driver_angle):
nonlocal driver_angle, driven_angle
driver_angle_delta = new_driver_angle - driver_angle
driven_angle_delta = driver_angle_delta / driver_to_driven_ratio
nearest_driven_lock_angle = math.floor(driven_angle / driven_lock_angle_step + 10 ** -6) * driven_lock_angle_step
driven_was_locked = driven_angle + driven_angle_delta < nearest_driven_lock_angle
driven_angle = max(nearest_driven_lock_angle, driven_angle + driven_angle_delta)
driver_angle += driver_angle_delta
return driven_was_locked
# Emulate Process
forward_prob = 0.6 # Probability of forward move, backward move probability will be 1 - forward_prob
max_step = 40 # Maximum random jump to do
max_possible_steps = 1000
driven_stop_angle = 360.
outputs_per_line = 2 # Entries per line when printing text
was_locked = False
random.seed(0)
for i in range(max_possible_steps):
sys.stdout.write(
f'{str(i).rjust(3)}: driver {str(round(driver_angle, 1)).rjust(5)} ' +
f'driven {str(round(driven_angle, 1)).rjust(5)} ' +
f'{("locked" if was_locked else "non-locked").rjust(10)} | '
)
if (i + 1) % outputs_per_line == 0 or i + 1 >= max_possible_steps or driven_angle >= driven_stop_angle:
sys.stdout.write('\n')
if driven_angle >= driven_stop_angle:
break
driver_angle_delta = random.random() * max_step * (1. if random.random() < forward_prob else -1.)
was_locked = SetDriverAngle(driver_angle + driver_angle_delta)
Main()