Autokey method
-
On 04/03/2013 at 06:18, xxxxxxxx wrote:
I created a method for autokeying object psr changes.
It seems to work well and behave exactly like in Cinema autokey.But maybe some of you much more experienced guys could have a look at the code and tell me if there´s something wrong, missing or could be done in a much better manner.
It currently works on a single object, I wonder if it would be preferable to call the method within a object list loop or to iterate an object list within the function itself?
def Autokey(self, obj_list, psr_track, xyz_vector, value, min_value) : self.psr_track = psr_track self.xyz_vector = xyz_vector self.obj_list = obj_list self.value = value self.min_value = min_value # Get the psr track type: desc_id = c4d.DescID(c4d.DescLevel(self.psr_track, c4d.DTYPE_VECTOR, 0, ), c4d.DescLevel(self.xyz_vector, c4d.DTYPE_REAL, 0)) doc = c4d.documents.GetActiveDocument() current_time = doc.GetTime() start_time = doc.GetMinTime() a_track = self.obj_list.FindCTrack(desc_id) # find the track for selection if not a_track: # no animation yet, sets a key at start time if current_time == start_time: # if at start time, set no new track/key return True new_track = c4d.CTrack(self.obj_list, desc_id) a_track = self.obj_list.InsertTrackSorted(new_track) a_track = self.obj_list.FindCTrack(desc_id) a_curve = a_track.GetCurve() keydict = a_curve.AddKey(start_time) key = keydict["key"] key.SetValue(a_curve, self.min_value) a_curve.SetKeyDefault(doc, keydict["nidx"]) if a_track: # there is animation a_curve = a_track.GetCurve() keyfind = a_curve.FindKey(current_time) if not keyfind: # if no key is already at current time, set a key keydict = a_curve.AddKey(current_time) key = keydict["key"] key.SetValue(a_curve, self.value) a_curve.SetKeyDefault(doc, keydict["nidx"]) c4d.EventAdd() return True else: # if there is a key already, just modify the value found_key = keyfind["key"] found_key.SetValue(a_curve, self.value) c4d.EventAdd() return True return True
The arguments could be and the method could be called with:
obj_list = c4d.documents.GetActiveDocument().GetActiveObject() psr_track = c4d.ID_BASEOBJECT_POSITION xyz_vector = c4d.VECTOR_X value = 100 # received form a Number Edit field min_value = 0 # initial value of a Number Edit field if c4d.IsCommandChecked(12425) == True: # check for Autokey State Autokey(obj, psr_track, xyz_vector, value, min_value)
-
On 04/03/2013 at 06:55, xxxxxxxx wrote:
It depends on what you want the method to do. It'd be a more modular approach letting the function
work on a single object only, but more generous in most cases to let the function itself do it. However,
if the algorithm does not include iterating over the other objects, I prefer to not to do it. Keep
a functions implementation as narrow as possible to its required behavior. Iterating over the other
objects can still be done outside and if necessary even put into another function.-Niklas
-
On 04/03/2013 at 10:47, xxxxxxxx wrote:
Thanks Niklas, I´ll keep it single object then.
For anybody who´s interested, I extended it to get vectors and set keys for all three vector curves, like native autokey does too:def Autokey(self, obj, psr_track, value, min_value) : # psr_track can be: # -c4d.ID_BASEOBJECT_POSITION # -c4d.ID_BASEOBJECT_SCALE # -c4d.ID_BASEOBJECT_ROTATION self.psr_track = psr_track # single Object input self.obj = obj # Values input must be a vector self.value = value self.min_value = min_value l_value = [self.value.x, self.value.y, self.value.z] # vector to x,y,z list for the "for" loop l_min_value = [self.min_value.x, self.min_value.y, self.min_value.z] # ^ # Get the psr track type: desc_id_x = c4d.DescID(c4d.DescLevel(self.psr_track, c4d.DTYPE_VECTOR, 0, ), c4d.DescLevel(c4d.VECTOR_X, c4d.DTYPE_REAL, 0)) desc_id_y = c4d.DescID(c4d.DescLevel(self.psr_track, c4d.DTYPE_VECTOR, 0, ), c4d.DescLevel(c4d.VECTOR_Y, c4d.DTYPE_REAL, 0)) desc_id_z = c4d.DescID(c4d.DescLevel(self.psr_track, c4d.DTYPE_VECTOR, 0, ), c4d.DescLevel(c4d.VECTOR_Z, c4d.DTYPE_REAL, 0)) l_desc_id = [desc_id_x, desc_id_y, desc_id_z] # desc_id x,y,z list for the "for" loop doc = c4d.documents.GetActiveDocument() current_time = doc.GetTime() start_time = doc.GetMinTime() # loop through x-y-z for i in range(0, 3) : a_track = self.obj.FindCTrack(l_desc_id[i]) # find the track for selection if not a_track: # no animation yet if current_time == start_time: # if at doc-start time, set no new track return True new_track = c4d.CTrack(self.obj, l_desc_id[i]) a_track = self.obj.InsertTrackSorted(new_track) a_track = self.obj.FindCTrack(l_desc_id[i]) a_curve = a_track.GetCurve() keydict = a_curve.AddKey(start_time) # sets a key at start time key = keydict["key"] key.SetValue(a_curve, l_min_value[i]) a_curve.SetKeyDefault(doc, keydict["nidx"]) if a_track: # there is already animation a_curve = a_track.GetCurve() keyfind = a_curve.FindKey(current_time) if not keyfind: # if no key is already at current time, set a key keydict = a_curve.AddKey(current_time) key = keydict["key"] key.SetValue(a_curve, l_value[i]) a_curve.SetKeyDefault(doc, keydict["nidx"]) else: # if there is a key already, just modify the value found_key = keyfind["key"] found_key.SetValue(a_curve, l_value[i]) c4d.EventAdd() return True