Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Unable to insert a key frame for the color attribute of the plugin.

    Cinema 4D SDK
    python c++ r19 r20 r21
    2
    9
    1.4k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      sean
      last edited by sean

      Hello, I'm here for help.

      1. I want to insert some keyframes for a color property of the plug-in, and the sub-level light object will change accordingly.The problem now is that I can't insert a keyframe for this color property (the keyframe icon always appears yellow).
      2. In addition, I have another question: where can I listen for the click event of the key frame icon?

      These two problems have been bothering me for two or three days now, either pyhton or C++ code, Any ideas would be much appreciated!

      Thanks,
      Sean

      import c4d
      import os
      
      class res(object):
          AAAAAA_COLOR = 1000
      
      res = res()
      
      def load_bitmap(path):
          path = os.path.join(os.path.dirname(__file__), path)
          bmp = c4d.bitmaps.BaseBitmap()
          if bmp.InitWith(path)[0] != c4d.IMAGERESULT_OK:
              bmp = None
          return bmp
      
      
      class aaaaaaData(c4d.plugins.ObjectData):
      
          PLUGIN_ID = 123566
          PLUGIN_NAME = 'aaaaaa'
          PLUGIN_INFO = 0
          PLUGIN_DESC = 'Oaaaaaa'
          PLUGIN_ICON = load_bitmap('res/icons/aaaaaa.tiff')
          PLUGIN_DISKLEVEL = 0
      
          def __init__(self):
              self.value = c4d.Vector(1, 0, 0)
      
          @classmethod
          def Register(cls):
              return c4d.plugins.RegisterObjectPlugin(
                  cls.PLUGIN_ID, cls.PLUGIN_NAME, cls, cls.PLUGIN_DESC, cls.PLUGIN_INFO,
                  cls.PLUGIN_ICON, cls.PLUGIN_DISKLEVEL)
      
          def Init(self, node):
              #self.InitAttr(node, c4d.Vector(1,0,0), [res.AAAAAA_COLOR])
              node[res.AAAAAA_COLOR] = c4d.Vector(1, 0, 0)
      
              return True
      
          def CreateKey(self, obj, id, value):
              track = obj.FindCTrack(id)
              if not track:
                  track = c4d.CTrack(obj, id)
                  obj.InsertTrackSorted(track)
                  c4d.EventAdd()
      
              curve = track.GetCurve()
              key = curve.AddKey(obj.GetDocument().GetTime())
              if not key:
                  return False
      
              if type(value) == int or type(value) == float:
                  key["key"].SetValue(curve, value)
              else:
                  key["key"].SetGeData(curve, value)
      
              return True
      
          def setColor(self, node, data):
              plugin_color = c4d.DescLevel(res.AAAAAA_COLOR, c4d.DTYPE_COLOR, 0)
              plugin_color_r = c4d.DescLevel(c4d.COLOR_R, c4d.DTYPE_REAL, 0)
              plugin_color_g = c4d.DescLevel(c4d.COLOR_G, c4d.DTYPE_REAL, 0)
              plugin_color_b = c4d.DescLevel(c4d.COLOR_B, c4d.DTYPE_REAL, 0)
              self.CreateKey(node, c4d.DescID(plugin_color, plugin_color_r), data.x)
              self.CreateKey(node, c4d.DescID(plugin_color, plugin_color_g), data.y)
              self.CreateKey(node, c4d.DescID(plugin_color, plugin_color_b), data.z)
      
              light = node.GetDown()
              if light:
                  light[c4d.LIGHT_COLOR] = data
                  light_color = c4d.DescLevel(c4d.LIGHT_COLOR, c4d.DTYPE_COLOR, 0)
                  light_color_r = c4d.DescLevel(c4d.COLOR_R, c4d.DTYPE_REAL, 0)
                  light_color_g = c4d.DescLevel(c4d.COLOR_G, c4d.DTYPE_REAL, 0)
                  light_color_b = c4d.DescLevel(c4d.COLOR_B, c4d.DTYPE_REAL, 0)
                  self.CreateKey(light, c4d.DescID(
                      light_color, light_color_r), data.x)
                  self.CreateKey(light, c4d.DescID(
                      light_color, light_color_g), data.y)
                  self.CreateKey(light, c4d.DescID(
                      light_color, light_color_b), data.z)
      
          def SetDParameter(self, node, id, data, flags):
              paramID = id[0].id
              if paramID == res.AAAAAA_COLOR:
                  self.setColor(node, data)
                  self.value = data
                  return True, flags | c4d.DESCFLAGS_SET_PARAM_SET
      
          def GetDParameter(self, node, id, flags):
              paramID = id[0].id
              if paramID == res.AAAAAA_COLOR:
                  data = self.value
                  return True, data, flags | c4d.DESCFLAGS_GET_PARAM_GET
      
              return True
      
      
      if __name__ == '__main__':
          aaaaaaData.Register()
      

      未命名图片.png

      1 Reply Last reply Reply Quote 0
      • S
        sean
        last edited by sean

        Please, either pyhton or C++ code, Any ideas would be much appreciated!

        1 Reply Last reply Reply Quote 0
        • ManuelM
          Manuel
          last edited by

          Hello,

          about the keyframe you have to use TranslateDescID we have an example in our github repository

          The keyFrame will be create on the target parameter and not yours.

          For your second question, I have to double check.

          Cheers,
          Manuel

          MAXON SDK Specialist

          MAXON Registered Developer

          S 1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by Manuel

            Hello,

            For Vectors, in c++ you have to use the macro HandleDescGetVector and HandleDescSetVector

            They are simple switch to handle individual component (x, y, z)

            // Macro that handles GetParameter() calls for Vector. (For an example of usage see @em datatype.cpp SDK example.)
            #define HandleDescGetVector(tid, vector, t_data, flags) \
            	switch (tid[1].id) \
            	{ \
            		case 0:			t_data = GeData(vector);   flags |= DESCFLAGS_GET::PARAM_GET; break; \
            		case 1000:	t_data = GeData(vector.x); flags |= DESCFLAGS_GET::PARAM_GET; break; \
            		case 1001:	t_data = GeData(vector.y); flags |= DESCFLAGS_GET::PARAM_GET; break; \
            		case 1002:	t_data = GeData(vector.z); flags |= DESCFLAGS_GET::PARAM_GET; break; \
            	} \
            
            /// Macro that handles SetParameter() calls for Vector. (For an example of usage see @em datatype.cpp SDK example.)
            #define HandleDescSetVector(v, tid, vector, t_data, flags) \
            	switch (tid[1].id) \
            	{ \
            		case 0:			v = t_data.GetVector(); flags |= DESCFLAGS_SET::PARAM_SET; break; \
            		case 1000:	v = Vector(t_data.GetFloat(), vector.y, vector.z); flags |= DESCFLAGS_SET::PARAM_SET; break; \
            		case 1001:	v = Vector(vector.x, t_data.GetFloat(), vector.z); flags |= DESCFLAGS_SET::PARAM_SET; break; \
            		case 1002:	v = Vector(vector.x, vector.y, t_data.GetFloat()); flags |= DESCFLAGS_SET::PARAM_SET; break; \
            	} \
            
            

            It doesn't exist in python you have to come with your own solution, something like this :
            Note that i've added an extra case where the id depth is only one level. Seems that in python it doesn't sent a two level DescID with the second level ID set to 0.

             def HandleDescGetVector(self, tid, value, flags):
                    data = None
                    result = False
                    if tid.GetDepth() != 2:
                        data = value
                        flags |=  c4d.DESCFLAGS_GET_PARAM_GET
                        result = True
                        return result, data, flags
                    
                    if tid[1].id == 0:
                        data = value
                        flags |=  c4d.DESCFLAGS_GET_PARAM_GET
                        result = True
                    elif tid[1].id == 1000:
                        data = value.x
                        flags |=  c4d.DESCFLAGS_GET_PARAM_GET
                        result = True
                    elif tid[1].id == 1001:
                        data = value.y
                        flags |=  c4d.DESCFLAGS_GET_PARAM_GET
                        result = True
                    elif tid[1].id == 1002:
                        data = value.z
                        flags |=  c4d.DESCFLAGS_GET_PARAM_GET
                        result = True
                    return result, data, flags
            
              
                def SetDParameter(self, node, id, data, flags):
                    paramID = id[0].id
                    if paramID == res.AAAAAA_COLOR:
                        if id.GetDepth() == 1:
                            self.value = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
                        elif id[1].id == 1000:
                            self.value.x = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
                      
                        elif id[1].id == 1001:
                            self.value.y = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
                        
                        elif id[1].id == 1002:
                            self.value.z = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
                        
                        return True, flags
            
                    elif paramID == res.myReal:
                        self.myReal = data
                    elif paramID == res.myVector:
                        
                        if id.GetDepth() == 1:
                            self.myVector = data
                            flags |= c4d.DESCFLAGS_SET_PARAM_SET
                            
                        elif id[1].id == 1000:
                            self.myVector.x = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
                            
                        elif id[1].id == 1001:
                            self.myVector.y = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
                            
                        elif id[1].id == 1002:
                            self.myVector.z = data
                            flags |=  c4d.DESCFLAGS_SET_PARAM_SET
            
                        return True, flags
            
                    return True
            
                def GetDParameter(self, node, id, flags):
                    paramID = id[0].id
                    
            
                    if id[0].id == res.AAAAAA_COLOR:
                        return  self.HandleDescGetVector(id, self.value, flags)
                    elif paramID == res.myReal:
                        return True, self.myReal, flags | c4d.DESCFLAGS_GET_PARAM_GET
                    elif paramID == res.myVector:
                        return  self.HandleDescGetVector(id, self.myVector, flags)
                        
            
                    return True
            
            

            About detecting the click on the icon, there's no solution for that.
            just to be sure, you are talking about the circle in front of the parameter, not the "record active object" command ? (shortcut f9)

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 1
            • S
              sean @Manuel
              last edited by sean

              @m_magalhaes Hello, thank you for providing the method, I have already done it. The problem now is that the color properties of the plug-in do route to the color properties of the sub-lights, and the lights have keyframe markers on the timeline, but nothing on the plug-in's timeline.

                  def TranslateDescID(self, node, id):
              
                      paramID = id[0].id
              
                      if paramID == res.AAAAAA_COLOR:
                          light = node.GetDown()
                          if light:
                              desc = light.GetDescription(c4d.DESCFLAGS_DESC_0)
                              if not desc:
                                  return False
              
                              descid = c4d.DescID(c4d.DescLevel(c4d.LIGHT_COLOR))
                              completeid = desc.CheckDescID(descid, None)
              
                              return (True, completeid, light)
              
                      return False
              

              微信图片_20191205225400.png 微信图片_20191205225410.png

              1 Reply Last reply Reply Quote 0
              • ManuelM
                Manuel
                last edited by

                hello,

                this is also the case when you have for example a cube with a phong tag.
                If you select the cube, the phong tag tab is visible in the attribute manager and you can add keyframe but they only appear on the time line if you select the phong tag itself.

                Those keyframe appear if the selected object have tracks and keyframe witch is not the case of your NodeData. The track is created on the light itself.

                You have to create the keyframe on both but that will double the keyframes for nothing.

                Cheers,
                Manuel.

                MAXON SDK Specialist

                MAXON Registered Developer

                S 1 Reply Last reply Reply Quote 0
                • S
                  sean @Manuel
                  last edited by

                  @m_magalhaes Hello, your statement is consistent with my imagination, but when you click the little circle in front of the color attribute of the plug-in, how about creating keyframes for both?Can you provide simple code?Ingredient gratitude!

                  Cheers,
                  Sean

                  1 Reply Last reply Reply Quote 0
                  • ManuelM
                    Manuel
                    last edited by

                    You can simply pick the code you write to create the key for both parameters. That part was right.
                    The only issue you had was the way you have to get and set parameters for vector for x, y and z.

                    But in that case, (two tracks) you will have to make decisions, what happen if i create a keyframe in the light myself ? Will it be erased by your NodeData ?

                    Cheers,
                    Manuel

                    MAXON SDK Specialist

                    MAXON Registered Developer

                    S 1 Reply Last reply Reply Quote 0
                    • S
                      sean @Manuel
                      last edited by sean

                      @m_magalhaes
                      Hello, thank you very much for your inspiration. You've been very helpful.

                      There is no need to overwrite TranslateDescID(), only two macros HandleDescGetVector and HandleDescSetVector can realize my idea. Thanks again!

                      Cheers,
                      Sean

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post