Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Thank you very much @ferdinand, that's exactly what I was looking for. Cheers
Hi there, is it possible to test "Lock Overrides" and return if it is on or off using Python? The same question for the "Enable all overrides" button.
Cheers
@m_magalhaes said in Copying Take Overrides from an object to another via Python not working properly:
adding the backupvalue
You are master! thanks my friend, it's working!
Hi there, I'm working on a script to transfer (or copy) the overrides from a source object to a target one and it seems to be working if there is no overrides in sub-Takes. Basically what the script does is a scan through all Takes starting from the first after the Main (takeData.GetMainTake().GetDown()) and retrieves each override ID and value and it adds to the target object via FindOrAddOverrideParam(). But for any odd reason the result is not consistent if there are sub-Takes involved as it changes depending on which one is active before running the script, and in all cases, I would expect a perfect copy but that's not what's happening. I must be missing something here My gut feeling says that the problem is related to the backup so I just tried forcing it via FindOverrideCounterPart() but without success.
takeData.GetMainTake().GetDown()
FindOrAddOverrideParam()
FindOverrideCounterPart()
I'm sending a dummy file attached with a set of Takes just to show the problem I'm trying to describe here:
copy_overrides_to_another_object.c4d
This is the script that works with the file above:
import c4d def GetNextTake(op): if op == None: return None if op.GetDown(): return op.GetDown() while not op.GetNext() and op.GetUp(): op = op.GetUp() return op.GetNext() def getDescIdName(op, descID): description = op.GetDescription(c4d.DESCFLAGS_DESC_0) for bc, paramid, groupid in description: if paramid == descID: return bc[c4d.DESC_NAME] def TransferTakeOverrides(srcObj, trgObj, takeData, currentTake): while currentTake: srcOverride = currentTake.FindOverride(takeData, srcObj) if srcOverride is not None: for descID in srcOverride.GetAllOverrideDescID(): # Get the backup node for the source override backup, result = takeData.FindOverrideCounterPart(srcOverride, descID) # backup: The counterpart node // result: the Take if backup is None: raise RuntimeError("Failed to find the default override.") # Get the backup value of the given Description ID backupValue = backup.GetParameter(descID, c4d.DESCFLAGS_GET_0) print(currentTake.GetName(), " DescID:", getDescIdName(srcObj,descID)) print(" --->",srcOverride.GetSceneNode().GetName()) print(" overr. value:", srcOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0)) print(" backup value:", backupValue,"from", result.GetName()) # Get the override value srcOverValue = srcOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0) # add override to the target object trgOverride = currentTake.FindOrAddOverrideParam(takeData, trgObj, descID, srcOverValue) # Get the backup node for the target override trg_backup, trg_result = takeData.FindOverrideCounterPart(trgOverride, descID) trg_backupValue = trg_backup.GetParameter(descID, c4d.DESCFLAGS_GET_0) # force adding source backup value to the target backup take (just trying to fix the problem!) trgBackup = trg_result.FindOrAddOverrideParam(takeData, trgObj, descID, backupValue) trgBackup.UpdateSceneNode(takeData, descID) trgOverride.UpdateSceneNode(takeData, descID) print(" --->",trgOverride.GetSceneNode().GetName()) print(" overr. value:", trgOverride.GetParameter(descID, c4d.DESCFLAGS_GET_0)) print(" backup value:", trg_backupValue,"from", trg_result.GetName()) print(" ----------------") currentTake = GetNextTake(currentTake) print("======================================") def main(): op = c4d.BaseObject(c4d.Ocube) op[c4d.ID_BASELIST_NAME] = "trg_Cube" doc.InsertObject(op) objs = doc.GetObjects() objs.reverse() if len(objs) != 2: return takeData = doc.GetTakeData() currentTake = takeData.GetMainTake().GetDown() TransferTakeOverrides(srcObj=objs[0], trgObj=objs[1], takeData=takeData, currentTake=currentTake) c4d.EventAdd() if __name__=='__main__': main()
@ferdinand Thank you for your awesome explanation! I will keep this post as a reference for my studies as your approach seems a bit complicated for my understanding at the moment. I'm learning a lot with your contribution in this forum, and in this case here it's not gonna be different. Cheers
@cairyn thanks for your time and helpful answer. I was trying to retrieve the value of a variable from another class by calling it directly. This is why you could see OptionsDialog() within class processing. This is the source of my problems, because as far as I know, this is how a class variable should be called from another class. Probably I'm wrong or things are different when there's a dialog involved
Anyways, this is the working code, with your solution addressed:
import c4d pluginVersion = "v1.0.0" pluginName = "Get Value From Dialog" PLUGIN_ID = 1111222 class OptionsDialog (c4d.gui.GeDialog): GROUP_OPTIONS = 1011 CHKBX1 = 1007 CHKBX2 = 1008 CHKBX3 = 1009 BTN_OK = 1010 def __init__(self): self._hasBeenInitalized = False self._hasLayoutDone = False def Message(self, msg, result): if msg.GetId() == c4d.BFM_ACTION: msg[c4d.BFM_ACTION_VALUE] return c4d.gui.GeDialog.Message(self, msg, result) def CreateLayout(self): self.SetTitle(pluginName + ' ' + pluginVersion) self.AddCheckbox(self.CHKBX1, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 1') self.AddCheckbox(self.CHKBX2, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 2') self.AddCheckbox(self.CHKBX3, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 3') if self.GroupBegin(self.GROUP_OPTIONS, c4d.BFH_CENTER, 1, 1): self.AddButton(self.BTN_OK, c4d.BFH_SCALEFIT, initw=500, inith=15,name='Go!') self.GroupEnd() self._hasLayoutDone = True self._hasBeenInitalized = False return True def Command(self, id, msg): if id==self.BTN_OK or id==c4d.IDC_OK: self.print_msg1 = self.GetBool(self.CHKBX1) self.print_msg2 = self.GetBool(self.CHKBX2) self.print_msg3 = self.GetBool(self.CHKBX3) self.Run() return True def InitValues(self): if self._hasBeenInitalized is True: return True self.SetBool(self.CHKBX1, True) self._hasBeenInitalized = True return True def Run(self): message = processing().set_nice_message(self.print_msg1, self.print_msg2, self.print_msg3) print(message) c4d.EventAdd() return True class processing: def set_nice_message(self, msg1, msg2, msg3): if msg1: result = 'Hello world 1' if msg2: result = 'Hello world 2' if msg3: result = 'Hello world 3' return result class DialogCommandData(c4d.plugins.CommandData): dlg = None def Execute(self, doc): if self.dlg is None: self.dlg = OptionsDialog() return self.dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, xpos=-2, ypos=-2, defaultw=720, defaulth=50) def RestoreLayout(self, secret): if self.dlg is None: self.dlg = OptionsDialog() return self.dlg.Restore(pluginid=PLUGIN_ID, secret=secret) if __name__ == '__main__': myPlugin = DialogCommandData() c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID, str=pluginName, info=0, icon=None, help=pluginName, dat=myPlugin)
This is probably a silly question, but I'm stuck and need some help so I can move forward in my plugin without using global dialog. The original dialog has much more checkboxes and edit texts to guide the whole processing, but I've been able to get a very simplified sample of my code with a similar structure.
I have a class
class processing
that needs to retrieve data from the dialog in order to process the script, but I really don't know how to get it since the code below is returning this error:
AttributeError: 'OptionsDialog' object has no attribute 'print_msg1'
I have to keep the structure like it is at the moment.
This the sample, any help would be awesome:
import c4d pluginVersion = "v1.0.0" pluginName = "Get Value From Dialog" PLUGIN_ID = 1111222 class OptionsDialog (c4d.gui.GeDialog): GROUP_OPTIONS = 1011 CHKBX1 = 1007 CHKBX2 = 1008 CHKBX3 = 1009 BTN_OK = 1010 def __init__(self): self._hasBeenInitalized = False self._hasLayoutDone = False def Message(self, msg, result): if msg.GetId() == c4d.BFM_ACTION: msg[c4d.BFM_ACTION_VALUE] return c4d.gui.GeDialog.Message(self, msg, result) def CreateLayout(self): self.SetTitle(pluginName + ' ' + pluginVersion) self.AddCheckbox(self.CHKBX1, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 1') self.AddCheckbox(self.CHKBX2, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 2') self.AddCheckbox(self.CHKBX3, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 3') if self.GroupBegin(self.GROUP_OPTIONS, c4d.BFH_CENTER, 1, 1): self.AddButton(self.BTN_OK, c4d.BFH_SCALEFIT, initw=500, inith=15,name='Go!') self.GroupEnd() self._hasLayoutDone = True self._hasBeenInitalized = False return True def Command(self, id, msg): if id==self.BTN_OK or id==c4d.IDC_OK: self.print_msg1 = self.GetBool(self.CHKBX1) self.print_msg2 = self.GetBool(self.CHKBX2) self.print_msg3 = self.GetBool(self.CHKBX3) self.Run() return True def InitValues(self): if self._hasBeenInitalized is True: return True self.SetBool(self.CHKBX1, True) self._hasBeenInitalized = True return True def Run(self): message = processing().set_nice_message() print(message) c4d.EventAdd() return True class processing: dlg = OptionsDialog() def set_nice_message(self): """ how can I get values from OptionsDialog() ??? """ if self.dlg.print_msg1: result = 'Hello world 1' if self.dlg.print_msg2: result = 'Hello world 2' if self.dlg.print_msg3: result = 'Hello world 3' return result class DialogCommandData(c4d.plugins.CommandData): dlg = None def Execute(self, doc): if self.dlg is None: self.dlg = OptionsDialog() return self.dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, xpos=-2, ypos=-2, defaultw=720, defaulth=50) def RestoreLayout(self, secret): if self.dlg is None: self.dlg = OptionsDialog() return self.dlg.Restore(pluginid=PLUGIN_ID, secret=secret) if __name__ == '__main__': myPlugin = DialogCommandData() c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID, str=pluginName, info=0, icon=None, help=pluginName, dat=myPlugin)
Great! Cheers!
Hey Ferdinand, thank you very much for your time. I really appreciate that!
A custom GUI is so much easier, that I think my whole script is gonna be much shorter and with a pretty nice new functionality.
I have a gui.GeDialog with a few Edit Text boxes and I wanted to drop textures from my Windows Explorer on there and get the full path of each texture, just like in the texture field on a material.
I found a couple of useful posts approaching the same question, but the solution seems to be directed to more experienced Python users, as they have only parts of code, not a full working example.
I'd appreciate if someone could share an example on how to do that in this dialog here:
import c4d class MyDialog(c4d.gui.GeDialog): def CreateLayout(self): self.AddEditText(1000, c4d.BFH_SCALEFIT, initw=0, inith=0) self.AddEditText(1001, c4d.BFH_SCALEFIT, initw=0, inith=0) self.AddEditText(1002, c4d.BFH_SCALEFIT, initw=0, inith=0) self.AddEditText(1003, c4d.BFH_SCALEFIT, initw=0, inith=0) return True def main(): dialog = MyDialog() dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500) if __name__ == '__main__': main()
@pim I'm trying to figure out how you did this. Could you please share a sample code of this example? I'm trying to get the full path of an image by dragging it into a edit text field...
Hi Manuel
I've used the "Upload Image" button, don't know why the image is not visible for you.
I'm using Windows 10.
I hope you are able to see this one:
@m_magalhaes said in Gui Dialog in Python not respecting the dimensions:
you never specified it was working as expected in R19/R20.
My fault in not being clear enough, I should have been more specific.
The problem was implicit, where on the image attached we see "Dialog 700x200px" (defaultw=700, defaulth=200), but with different numbers in red. By deduction we can read something as not correct. But again, my fault in not being clear enough, sorry about that.
defaultw=700, defaulth=200
So, just to confirm, the issue is about the dimension in pixels not matching what was expected from the code.
I was expecting a dialog with 700x200 pixels, and was getting 686x193 in R19/20 and 333x146 in R21.
After your workaround, R21 is working better, but still not matching the 700x200 pixels.
Thank you again for your time! Cheers
I think I did it correctly and now I have R21 rendering the dialog exactly like R19 and R20 is doing. But I'm struggling to understand why the dialog is being created with slightly smaller dimension than the specified.
Why is this happening?
Hey Manuel, how are you?
I'm sorry for the mess! Could you please provide an example on how this PluginID should be used so we have the function working as expected?
I am still learning and I appreciate any help.
Thanks for your time! Cheers
Hi there
I'm setting up the dimensions of a dialog in Python, but the result is not correct as you can see on the image below.
Is this way the right way to do this or there is a better one?
import c4d from c4d import gui class OptionsDialog(gui.GeDialog): def CreateLayout(self): self.SetTitle('Dummy Dialog 700x200px') self.AddMultiLineEditText(1000, c4d.BFH_SCALEFIT, inith=50, initw=500, style=c4d.DR_MULTILINE_READONLY) self.SetString(1000, "Hello World!") if self.GroupBegin(1001, c4d.BFH_CENTER, 2, 1): self.AddDlgGroup(c4d.DLG_CANCEL|c4d.DLG_OK) self.GroupEnd() self.ok = False return True def Command(self, id, msg): if id==c4d.DLG_CANCEL: self.Close() return False elif id==c4d.DLG_OK: self.ok = True self.Close() return True def main(): dlg = OptionsDialog() dlg.Open(c4d.DLG_TYPE_MODAL, xpos=-2, ypos=-2, defaultw=700, defaulth=200) if __name__=='__main__': main()