Using AddCustomGui for primitive controls
-
Hello;
using AddCustomGui for complex controls like Quicktab or Linkbox seems easy enough, as you get a specific class derived from BaseCustomGui. However, in the description for GeDialog::AddCustomGui there are numerous "Symbol ID"s listed that do not have a specific class but result in a BaseCustomGui being returned: CUSTOMGUI_REAL, CUSTOMGUI_STATICTEXT, CUSTOMGUI_TIME, etc.Mostly they seem to correspond with certain primitives (which already have their own dedicated Add functions, e.g. CUSTOMGUI_REALSLIDER and AddEditSlider), but sometimes there is no separate Add function, as e.g. for CUSTOMGUI_PROGRESSBAR or CUSTOMGUI_MATRIX.
I have no idea how to work with these.
For complex controls, I just create the GUI:
self.customcontrol = self.AddCustomGui(ID_CUSTOM, c4d.CUSTOMGUI_QUICKTAB, name="A quick tab", flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30, customdata=bc)
and work from there with the returned class. No issues here.
If I try the same for a primitive control like CUSTOMGUI_REALSLIDER, no GUI appears in the dialog at all (the return value is BaseCustomGui, not None, so the call did not fail at least). I cannot find any documentation on parameters to be set through the passed BaseContainer, if that's the issue.
You may say "use AddEditSlider" but there is no AddTime or AddProgressBar so I would expect AddCustomGui to work.
I seem to overlook something important. What do these "Symbol ID"s document, and how do I use them?
-
Hi,
you have function to retrieve the custom datatype corresponding to the custom gui you are adding. But not all gadgets works the same.
for CUSTOMGUI_PROGRESSBAR , you must send a message. DateTime you can either use the returned gadget or use FindCustomGui to update its data. CUSTOMGUI_QUICKTAB you can define the tabs in the CreateLayout function etc etc.
as FindCustomData says:
The method returns a BaseCustomGui when there is no class available for the custom GUI. This allows to interact with any custom GUI, calling for instance BaseCustomGui.GetData()/SetData().
You can find this manual about the DateTime control/datatype.
Some gadgets could be restricted to Description and looks bad or not work in a GeDialog.
I wrote a plugin to test different cases and show how to use some gadgets.
import c4d import collections import os from datetime import datetime # Be sure to use a unique ID obtained from www.plugincafe.com PLUGIN_ID = 9025250 class MemoryViewerDialog(c4d.gui.GeDialog): def CreateLayout(self): """ This Method is called automatically when Cinema 4D Create the Layout (display) of the Dialog. """ self.GroupBegin(0, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 1) self.dateTimeControl = self.AddCustomGui(1000, c4d.DATETIME_GUI, name="date time", flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30) quickTabGadgetBC = c4d.BaseContainer() quickTabGadgetBC.SetBool(c4d.QUICKTAB_SHOWSINGLE, True) quickTabGadgetBC.SetBool(c4d.QUICKTAB_NOMULTISELECT, False) self.quickTabGadget = self.AddCustomGui(1001, c4d.CUSTOMGUI_QUICKTAB, name="quick tab", flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30, customdata = quickTabGadgetBC) self.quickTabGadget.AppendString(0, "First Tab", False) self.quickTabGadget.AppendString(0, "Second Tab Selected", True) self.AddButton(2000, c4d.BFH_SCALEFIT, 0, 0, "click me") self.progressBarGadget = self.AddCustomGui(1002, c4d.CUSTOMGUI_PROGRESSBAR, name="", flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30) self.GroupEnd() return True def Command(self, id, msg): print (id) if id == 2000: timeDataType = self.FindCustomGui(1000, c4d.DATETIME_GUI) print("this is timedata", timeDataType, self.dateTimeControl ) # Parse the time string dt = datetime.strptime('16.07.2011 03:37:12',"%d.%m.%Y %H:%M:%S") dtd = c4d.DateTimeData() # Fills the Data object with the DateTime object dtd.SetDateTime(dt) timeDataType.SetDateTime(dtd, True, True) progressMessage = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR) progressMessage.SetData(c4d.BFM_STATUSBAR_TXT , "this is displayed in the status bar") self.SendMessage(1002, progressMessage) return True class MemoryViewerCommandData(c4d.plugins.CommandData): dialog = None def Execute(self, doc): """ Called when the user Execute the command (CallCommand or a clicks on the Command from the plugin menu) :param doc: the current active document :type doc: c4d.documents.BaseDocument :return: True if the command success """ # Creates the dialog if its not already exists if self.dialog is None: self.dialog = MemoryViewerDialog() # Opens the dialog return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaulth=400, defaultw=400) def RestoreLayout(self, sec_ref): """ Used to restore an asynchronous dialog that has been placed in the users layout. :param sec_ref: The data that needs to be passed to the dlg (almost no use of it). :type sec_ref: PyCObject :return: True if the restore success """ # Creates the dialog if its not already exists if self.dialog is None: self.dialog = MemoryViewerDialog() # Restores the layout return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref) if __name__ == "__main__": # Retrieves the icon path directory, _ = os.path.split(__file__) fn = os.path.join(directory, "res", "mviewer.tif") # Creates a BaseBitmap # Registers the Command plugin c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID, str="Py-MemoryViewer 2", help="Show the current mem usage of Cinema 4D.", info=0, dat=MemoryViewerCommandData(), icon=None)
Cheers,
Manuel -
@manuel Thanks for the notes, there seems to be a lot that requires additional explanation beyond the API description. I may ask more specific questions later...
Regarding the DateTime, I got a weird error when I try to show the extended GUI: the clock and calendar fields get duplicated:
This happens upon calling
self.dateTimeControl.SetLayoutMode(c4d.LAYOUTMODE_MAXIMIZED)
or if you like the full script,
import c4d from c4d import gui from datetime import datetime ID_BUTTON_CLOSE = 1001 ID_DATETIME = 1002 class CustomDialog(c4d.gui.GeDialog): def __init__(self): self.customcontrol = None def CreateLayout(self): self.SetTitle("Custom Control Test") self.GroupBorderSpace(10, 10, 10, 10) if self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT, cols=1, title="", groupflags=0): bc = c4d.BaseContainer() bc[c4d.DATETIME_TIME_CONTROL] = True bc[c4d.DATETIME_DATE_CONTROL] = True self.dateTimeControl = self.AddCustomGui(ID_DATETIME, c4d.DATETIME_GUI, name="DateTime", flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=10, minh=10, customdata=bc) self.dateTimeControl.SetLayoutMode(c4d.LAYOUTMODE_MAXIMIZED) dt = datetime.strptime('16.07.2011 03:37:12',"%d.%m.%Y %H:%M:%S") dtd = c4d.DateTimeData() dtd.SetDateTime(dt) self.dateTimeControl.SetDateTime(dtd) self.GroupEnd() if self.GroupBegin(id=0, flags=c4d.BFH_CENTER, cols=2, title="", groupflags=0): self.GroupBorderSpace(0, 20, 0, 0) self.AddButton(ID_BUTTON_CLOSE, c4d.BFH_SCALEFIT, name="Close") self.GroupEnd() return True def Command(self, messageId, bc): if messageId == ID_BUTTON_CLOSE: self.Close() return True def main(): dlg = CustomDialog() dlg.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE) dt = dlg.dateTimeControl.GetDateTime().GetDateTime() print (dt.year, dt.month, dt.day) print (dt.hour, dt.minute, dt.second) if __name__=='__main__': main()
(and no, it doesn't work in a CommandData plugin either...)
I am still on R23.1 and have no current access to more recent versions, so this may actually be an error that has already been corrected, and it's no longer a valid question... -
Hello @Cairyn ,
without further questions or postings, we will consider this topic as solved by Friday 11th of august 2023 and flag it accordingly.
Thank you for your understanding,
Maxon SDK Group