Python: Key Error while initializing GUI, Dictionary, self



  • "Dictionary" "self" and old SDK sample code might be my issue, but can somebody help me and point out, why I get a key error by just adding more gui elements to this old SDK ToolData plugin liquid-painter sample code.

    adding a Checkbox (Bool) worked, but adding other gui elements breaks the smaple code somehow.

    Key error on line 39 & 107 (marked in the Code so you don't need to search)
    Thanks in advance
    R20 Visualice

    import c4d
    import os
    from c4d import gui, plugins, bitmaps
    
    # be sure to use a unique ID obtained from www.plugincafe.com
    PLUGIN_ID = 1015073
    
    # for GeLoadString values must match with the header file
    IDS_PRIMITIVETOOL = 50000
    
    class SettingsDialog(gui.SubDialog):
        parameters = None
    
        def __init__(self, arg):
            self.parameters = arg
    
        def CreateLayout(self):
            self.GroupBegin(id=1000, flags=c4d.BFH_SCALEFIT, cols=2, rows=5)
            self.GroupBorderSpace(1, 1, 1, 1)
    
            # Bool
            self.element = self.AddStaticText(id=2003, flags=c4d.BFH_SCALEFIT, initw=1, name="Extend Vector: ", borderstyle=c4d.BORDER_NONE)
            self.element = self.AddCheckbox(id=2002, flags=c4d.BFH_SCALEFIT, initw=1, inith=0, name="")
            #valuebool = self.parameters['extend_vector']
            self.SetBool(2002, False)
    
            # Extension Value
            self.element = self.AddStaticText(id=3001, flags=c4d.BFH_SCALEFIT, initw=1, name="Extension Ratio: ", borderstyle=c4d.BORDER_NONE)
            valueextension = self.parameters['extension_ratio']
            self.AddEditSlider(id=3002, flags=c4d.BFH_SCALEFIT)
            self.SetFloat(id=3002, value=valueextension, min=0.1, max=100, step=0.1, min2=0.0001, max2=1000, quadscale=True)
    
            print self.parameters
    
            self.element = self.AddStaticText(id=1001, flags=c4d.BFH_SCALEFIT, initw=1, name="Sphere Size: ", borderstyle=c4d.BORDER_NONE)
            valuespheresize = self.parameters["sphere_size"]                         
    # first key error 
            self.AddEditNumberArrows(id=1002, flags=c4d.BFH_SCALEFIT)
            self.SetFloat(id=1002, value=valuespheresize, min=0, max=20)
    
            self.GroupEnd()
            return True
    
        def Command(self, id, msg):
            if id == 1002:
                self.parameters['sphere_size'] = self.GetFloat(1002)
                print "Sphere Size: ", self.GetFloat(1002)
            if id == 2002:
                self.parameters['extend_vector'] = self.GetBool(2002)
                print "Extend Vector:", self.GetBool(2002)
            if id == 3002:
                self.parameters['extension_ratio'] = self.GetFloat(3002)
                print "Extension Ratio: ", self.GetFloat(3002)
            return True
    
    
    class AVTTool(plugins.ToolData):
        # Inherit from ToolData to create your own tool
    
        def __init__(self):
            self.data = {'sphere_size': 15}
            self.data = {'extension_ratio': 1}
    
        def GetState(self, doc):
            if doc.GetMode() == c4d.Mpaint: return False
            return c4d.CMD_ENABLED
    
        def Debug(self, msg):
            # c4d.CallCommand(13957) # Konsole loeschen
            print "Konsole geloescht."
            return True
    
        def KeyboardInput(self, doc, data, bd, win, msg):
            key = msg.GetLong( c4d.BFM_INPUT_CHANNEL )
            cstr = msg.GetString( c4d.BFM_INPUT_ASC )
            if key == c4d.KEY_ESC:
                # do what you want
                print "ESC Key Pressed."
                # return True to signal that the key is processed
                return True
            return False
    
        def MouseInput(self, doc, data, bd, win, msg):
            mx = msg[c4d.BFM_INPUT_X]
            my = msg[c4d.BFM_INPUT_Y]
    
            device = 0
            if msg[c4d.BFM_INPUT_CHANNEL] == c4d.BFM_INPUT_MOUSELEFT:
                device = c4d.KEY_MLEFT
            elif msg[c4d.BFM_INPUT_CHANNEL] == c4d.BFM_INPUT_MOUSERIGHT:
                device = c4d.KEY_MRIGHT
            else:
                return True
    
            null = c4d.BaseObject( c4d.Ometaball )
            null[c4d.METABALLOBJECT_SUBEDITOR] = 10
            null.MakeTag( c4d.Tphong )
    
            doc.AddUndo( c4d.UNDO_NEW, null )
    
            doc.InsertObject( null )
            doc.SetActiveObject( null )
            c4d.DrawViews( c4d.DA_ONLY_ACTIVE_VIEW | c4d.DA_NO_THREAD | c4d.DA_NO_ANIMATION )
    
            rad = self.data['sphere_size']                                                 
    # second key error 
            dx = 0.0
            dy = 0.0
    
            win.MouseDragStart( button=device, mx=int( mx ), my=int( my ),
                                flags=c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE )
            result, dx, dy, channel = win.MouseDrag()
            while result == c4d.MOUSEDRAGRESULT_CONTINUE:
                mx += dx
                my += dy
    
                # continue if user doesnt move the mouse anymore
                if dx == 0.0 and dy == 0.0:
                    result, dx, dy, channel = win.MouseDrag()
                    continue
    
                cl = c4d.BaseObject( c4d.Osphere )
    
                cl.SetAbsPos( bd.SW( c4d.Vector( mx, my, 500.0 ) ) )
                cl[c4d.PRIM_SPHERE_RAD] = rad
                cl.InsertUnder( null )
    
                c4d.DrawViews( c4d.DA_ONLY_ACTIVE_VIEW | c4d.DA_NO_THREAD | c4d.DA_NO_ANIMATION )
                result, dx, dy, channel = win.MouseDrag()
    
            if win.MouseDragEnd() == c4d.MOUSEDRAGRESULT_ESCAPE:
                doc.DoUndo( True )
    
            c4d.EventAdd()
            return True
    
        def GetCursorInfo(self, doc, data, bd, x, y, bc):
            if bc.GetId() == c4d.BFM_CURSORINFO_REMOVE:
                return True
    
            bc.SetString( c4d.RESULT_BUBBLEHELP, plugins.GeLoadString( IDS_PRIMITIVETOOL ) )
            bc.SetLong( c4d.RESULT_CURSOR, c4d.MOUSE_POINT_HAND )
            return True
    
        def AllocSubDialog(self, bc):
            return SettingsDialog( self.data )  # always return new instance
    
    
    if __name__ == "__main__":
        bmp = bitmaps.BaseBitmap()
        dir, file = os.path.split(__file__)
        fn = os.path.join(dir, "res", "AligntoVector.tif")
        bmp.InitWith(fn)
        plugins.RegisterToolPlugin( id=PLUGIN_ID, str="Py-AlignToVector",
                                    info=0, icon=bmp,
                                    help="Select two Points to generate a Vector. Then Click additional points to move them onto the Vector.",
                                    dat=AVTTool() )
    


  • Hello,

    as always, please use the Q&A system and also tell us the version of Cinema 4D you are using.

    There is no issue with adding GUI elements. The issue is with these lines of code:

    self.data = {'sphere_size': 15}
    self.data = {'extension_ratio': 1}
    

    Please make sure you understand how to use a Dictionary in Python.

    best wishes,
    Sebastian



  • Thanks Sebastian,

    I did read your dictionary link but was wondering why then this code works in the sample sdk

    what i've tried so far to set or read the dic. in the init

            self.data["sphere_size"] = 15
            self.data["extension_ratio"] = 1
    
            self.data.get("sphere_size")
            self.data.get("extension_ratio")
    
            self.data = parameters["sphere_size"] = 15
            self.data = parameters["extension_ratio"] = 1
    
            self.data = parameters.get("sphere_size")
            self.data = parameters.get("extension_ratio")
            
            self.data = {'sphere_size': 15}       # original SDK Code !
            self.data = {'extension_ratio': 1}
    

    This is obviously a problem of myself understanding the concept of "self" but I really like to learn by solving c4d problems instead of generic Phyton lessons.

    kind regards mogh
    R20 Visualize



  • Hello,

    this isn't a Cinema 4D issue; it has also nothing to do with "self". It is just about understanding basic Python syntax.

    Just run this code

    someDict = { "a", 1}
    someDict = { "b", 2}
    print(someDict)
    

    to see that it only contains one key/value pair. This is because the second line does not add a key/pair value. The assignment operator overwrites the variable with a new Dictionary.

    I strongly recommend do to some generic Python lessons.

    best wishes,
    Sebastian



  • thanks solved:

    self.data = {'sphere_size': 15, 'extension_ratio': 1, 'extend_vector': False}
    

    kind regards