Dynamic Update on Plug-ins
-
NOTE: Not talking about updating to new version but updating the execution of the plug-in.
I have a test plug-in that prints out "There are no objects in the scene" or "There are # objects in the scene".
It works as expected upon initial open of the plug-in but not through-out.You can see an illustration of the problem here:
https://www.dropbox.com/s/6j0aqtvgg6o2vg6/c4d131_automatic_update-plug-in.mp4?dl=0Thank you for looking at my problem
P.S. I need the
LayoutFLushGroup
andLayoutChanged
in the code since I'm planning to list all objects and all their parameters.You can see the illustration code here:
import c4d import os from c4d import gui, plugins, bitmaps, utils, documents PLUGIN_ID = 1011321 class MyDialog(gui.GeDialog): def get_all_objects(self, op): output = [] while op: output.append(op) self.get_all_objects(op.GetDown()) op = op.GetNext() return output def CreateLayout(self): doc = c4d.documents.GetActiveDocument() self.object_count = len(self.get_all_objects(doc.GetFirstObject())) self.GroupBegin(id=1000, flags=c4d.BFH_FIT, cols=0, rows=4, title="Rigging") if self.object_count == 0: self.LayoutFlushGroup(1001) self.AddStaticText(0, c4d.BFH_CENTER, name="There are no objects in the scene") self.LayoutChanged(1001) if self.object_count > 0 : self.LayoutFlushGroup(1001) self.AddStaticText(0, c4d.BFH_CENTER, name="There are %s objects in the scene" %self.object_count) self.LayoutChanged(1001) self.GroupEnd() return True def Command(self, id, msg): return True class MyMenuPlugin(plugins.CommandData): dialog = None def Execute(self, doc): if self.dialog is None: self.dialog = MyDialog() return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) if __name__ == "__main__": plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Utilities",0, None, "Python Menu", MyMenuPlugin())
-
I haven't looked at your dropbox video, but from your explanation I seem to understand you will have to listen and react to message EVMSG_CHANGE. There is no other way to react to objects being added, or removed from the Object Manager.
Obviously, the EVMSG_CHANGE will be called for every little change that occur in a scene, so you will probably need to filter out "false positives", if you don't want/need to update too frequently. -
@C4DS
Thanks for the response. I incorporated theEVMSG_CHANGE
. It does not error out but it also does not work as expected (Behavior is still the same as before). Is there a way around this?You can check the revised code here:
import c4d import os from c4d import gui, plugins, bitmaps, utils, documents PLUGIN_ID = 1011321 class MyDialog(gui.GeDialog): def get_all_objects(self, op): output = [] while op: output.append(op) self.get_all_objects(op.GetDown()) op = op.GetNext() return output def Update(self): # NEW CODE if self.object_count == 0: self.LayoutFlushGroup(1001) self.AddStaticText(0, c4d.BFH_CENTER, name="There are no objects in the scene") self.LayoutChanged(1001) if self.object_count > 0 : self.LayoutFlushGroup(1001) self.AddStaticText(0, c4d.BFH_CENTER, name="There are %s objects in the scene" %self.object_count) self.LayoutChanged(1001) def CreateLayout(self): doc = c4d.documents.GetActiveDocument() self.object_count = len(self.get_all_objects(doc.GetFirstObject())) self.GroupBegin(id=1001, flags=c4d.BFH_FIT, cols=0, rows=4, title="Rigging") self.GroupEnd() self.Update() # NEW CODE return True def Command(self, id, msg): return True def CoreMessage(self, id, msg): if id == c4d.EVMSG_CHANGE: # NEW CODE self.Update() return True class MyMenuPlugin(plugins.CommandData): dialog = None def Execute(self, doc): if self.dialog is None: self.dialog = MyDialog() return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) if __name__ == "__main__": plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Utilities",0, None, "Python Menu", MyMenuPlugin())
-
hello @bentraje,
In your code
get_all_objects
was not called and not updatingobject_count
I've changed your code a bit. I've used a
non-recursive hierarchy iteration found in our blog
[URL-REMOVED] so you don't hit the stack limit in case of a big hierarchy.InitValues
is called after CreateLayout so that's why I've used__init__
in the first place to init my values.In my code i'm using
self.objectsList
to store the object list. It's just for this example, GeDialog is not the best place to store data.import c4d import os from c4d import gui, plugins, bitmaps, utils, documents PLUGIN_ID = 1011321 class MyDialog(gui.GeDialog): def __init__(self): # Be sure that we have the object list before building the UI # as InitValues is called after CreateLayout() self.objectsList = [] self.GetAllObjects() self.object_count = len(self.objectsList) def InitValues(self): # Use to Init and in Case of an Update needed. self.objectsList = [] self.GetAllObjects() self.object_count = len(self.objectsList) self.Update() return True def GetNextObject(self, op ): # use a non-recursive method to iterate the hierarchy # [URL-REMOVED] # allow to not hit the recursive stack limit. if not op: return None if op.GetDown(): return op.GetDown() while not op.GetNext() and op.GetUp(): op = op.GetUp() return op.GetNext() def GetAllObjects(self): doc = c4d.documents.GetActiveDocument() op = doc.GetFirstObject() self.objectsList = [] while op: self.objectsList.append(op) op = self.GetNextObject(op) def Update(self): # NEW CODE if self.object_count == 0: self.LayoutFlushGroup(1001) self.AddStaticText(0, c4d.BFH_CENTER, name="There are no objects in the scene") self.LayoutChanged(1001) if self.object_count > 0 : self.LayoutFlushGroup(1001) self.AddStaticText(0, c4d.BFH_CENTER, name="There are %s objects in the scene" %self.object_count) self.LayoutChanged(1001) def CreateLayout(self): print "nombre d'objet ", self.object_count self.GroupBegin(id=1001, flags=c4d.BFH_FIT, cols=0, rows=4, title="Rigging") self.GroupEnd() self.Update() # NEW CODE return True def Command(self, id, msg): return True def CoreMessage(self, id, msg): if id == c4d.EVMSG_CHANGE: # NEW CODE self.InitValues() return True class MyMenuPlugin(plugins.CommandData): dialog = None def Execute(self, doc): if self.dialog is None: self.dialog = MyDialog() return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) if __name__ == "__main__": plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Utilities",0, None, "Python Menu", MyMenuPlugin())
Cheers
Manuel
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.
-
Hi @m_magalhaes
Thanks for the response and clarification specially with the
def __init___
anddef InitValues
that was news to me.The plug-in works as expected. Have a great day ahead!