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
    

Log in to reply