SOLVED Command() does not honor Dynamic Lists/Variable

Hi,

For some reason, the dynamic list exists on the CreateLayout() but entirely nonexistent on the Command().

The resulting code below output this
Button ID List under CreateLayout()[101012, 101013, 101014, 101015, 101016, 101017, 101018, 101019, 101020]
Button ID List under Command() []

I would expect the both output the same list since they are in the same variable, but they don't.
Is there a way around this?

You can check the working code here:

import c4d
from c4d import bitmaps, documents, gui, plugins, threading, utils

PLUGIN_ID   = 987654321

class MyDialog(gui.GeDialog):

    def __init__(self):
        self.button_id_list = []


    def InitValues(self):
        self.button_id_list = []
        
        return True

    def CreateLayout(self):

        self.SetTitle('Button Problem')
        
        self.GroupBegin(id=202020, flags=c4d.BFH_FIT, cols=1, title="General")

        total_buttons = 10

        for x in range(1, total_buttons):            
            button_id = x + 101011
            self.button_id_list.append(button_id)
            self.AddButton(button_id, c4d.BFH_CENTER, initw=100, inith=10, name="Button ID " + str(button_id))
 
        self.GroupEnd()

        print "Button ID List under CreateLayout()", self.button_id_list

        return True

    def Command(self, id, msg):


        print "Button ID List under Command()", self.button_id_list
       
        return True

class MyMenuPlugin(plugins.CommandData):

    dialog = None
    def Execute(self, doc):
    # create the dialog
       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)

    def RestoreLayout(self, sec_ref):
    # manage the dialog
       if self.dialog is None:
          self.dialog = MyDialog()
       return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)

if __name__ == "__main__":

    okyn = plugins.RegisterCommandPlugin(PLUGIN_ID, "ButtonID",0, None, "ButtonID", MyMenuPlugin())
    if (okyn):
        print "ButtonID"

``

On InitValues(), you're resetting the list. Since InitValues() is usually called once one construction(if done right) and CreateLayout() everytime, the Dialog is opened your list is reset.

Just to add some extra information about what's @mp5gosu,

InitValues is called only the first time the dialog is opened, not all time after CreateLayout.
So this way if you have some value in your GeDialog, you close it, reopen it (if it's the same instance) values within the Dialog are still similar and not reset.

Cheers,
Maxime.

edited my answer accordingly. Messed up the order. 😉

@mp5gosu and @m_adam

Thanks for the rest, but I'm not sure what exactly is the solution.

I tried with this one but it still gives me zero list. I kinda need the live self.button_id_list to also live under the Command.

    def Command(self, id, msg):

        self.InitValues()
        print "Button ID List under Command()", self.button_id_list
       
        return True

You should have a reset somewhere else in your code using the code you provided with the change on InitValues work as expected.

import c4d

class TestDialog(c4d.gui.GeDialog):
    def __init__(self):
        self.button_id_list = []


    def InitValues(self):        
        return True

    def CreateLayout(self):

        self.SetTitle('Button Problem')
        
        self.GroupBegin(id=202020, flags=c4d.BFH_FIT, cols=1, title="General")

        total_buttons = 10

        for x in range(1, total_buttons):            
            button_id = x + 101011
            self.button_id_list.append(button_id)
            print button_id
            self.AddButton(button_id, c4d.BFH_SCALEFIT, initw=0, inith=10, name="Button ID " + str(button_id))
 
        self.GroupEnd()

        print "Button ID List under CreateLayout()", self.button_id_list

        return True

    def Command(self, id, msg):
        print id

        print "Button ID List under Command()", self.button_id_list
       
        return True

if __name__ == '__main__':
    global dlg
    dlg = TestDialog()
    dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC)

Cheers,
Maxime.

@m_adam

Thanks for the code. It seems to work as expected.
You mentioned reset and I assumed it is just a matter of moving the InitValues() command but it turns out InitValues is not being used.

So basically, don't put any variable in InitValues if it is to be used in Command()?

Is this assessment correct?

Let's re-take everything together.

  1. Cinema 4D Call __init__() because you initialize the GeDialog class.
    • 1.1: Here you create an empty list called button_id_list stored in the class instance.
  2. You call dialog.Open()
    • 2.1: Cinema 4D call CreateLayout.
      • 2.1.1: You add some data to button_id_list.
    • 2.2: Cinema 4D call InitValues if it's the first time this instance of the dialog is opened.
      • 2.2.1: You reset the value of button_id_list to an empty list.
  3. A user presses a button.
    • Cinema 4D call Command with the gadget ID the user clicked.
      • Due to step 2.2.1, you button_id_list is empty so no way to retrieve the data.

And what I'm saying by You should have a reset somewhere else in your code is if the initial code you provided on this topic, didn't work even after removing the self.button_id_list = [] of your InitValues, then that means you have another self.button_id_list = [] in your code somewhere else.

Cheers,
Maxime.

When you presented the order of execution of __init__(), CreateLayout and InitValues. That makes total sense especially the 2.2.1 when it resets to an empty list.

Thanks for the clarification!