Unable to insert a key frame for the color attribute of the plugin.
-
Hello, I'm here for help.
- 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).
- 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,
Seanimport 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()
-
Please, either pyhton or C++ code, Any ideas would be much appreciated!
-
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 -
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 -
@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
-
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. -
@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 -
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 -
@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