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