Need help editing DirectButton code

I’m trying to make a toggle button so when you click it goes into the relief state and stays there until you click it back. I’ve looked through DirectButton.py and DirectGuiBase.py and couldn’t locate the code that controls the default clicking behaviour. Where can I find this? Any more help on making a toggleButton would be greatly appreciated.

It actually is handled by the underlying PGui system, which is implemented in C++. PGButton is what you are looking for (links below). You could make a PGToggleButton class that inherits from PGButton and overrides the mouse watcher callback methods to toggle the state on click rather than on mouse enter/exit.



Thank you for your reply. I’ve got no experience with C++ whatsoever, so if it is not too much to ask for, can you please assist me further? I’m guessing all you need to do is copy paste the pgButton class and modify a little?

Also, I’m unable to locate any pg file. Panda3d is installed in python site-packages so the layout of the folders is very different than panda on github.

I believe that the contents of “side-packages” will hold the Python side of Panda3D, not the C++ source-code, which is compiled.

To get the C++ source-code, you should be able to download it from GitHub.

That said, there may be a simpler way to achieve what you want–albeit noting that I suggest this without testing it, and so haven’t confirmed that it does work!

Instead of sub-classing or modifying DirectButton or PGButton, you might be able to sub-class DirectFrame, use the “bind” method to have it to respond to mouse-clicks, and in the callback specified to “bind” toggle the DirectFrame’s “relief” value.

I tried implementing your suggestion and it works! I inherited from DirectFrame and copy pasted most of DirectButton’s code and added a bind function to control the toggle. Here is the code if anyone is trying to do the same.

class DirectToggle(DirectFrame):
    def __init__(self, parent=None, **kw):
        optiondefs = (
            ('numStates', 2, None),
            ('state', DGG.NORMAL, None),
            ('relief', DGG.RAISED, None),
            ('invertedFrames', (1,), None),
            ('pressEffect', 1, DGG.INITOPT),
        )
        self.defineoptions(kw, optiondefs)

        DirectFrame.__init__(self, parent)

        pressEffectNP = None
        if self['pressEffect']:
            pressEffectNP = self.stateNodePath[1].attachNewNode('pressEffect', 1)
            self.stateNodePath[1] = pressEffectNP

        self.initialiseoptions(DirectToggle)

        if pressEffectNP:
            bounds = self.getBounds()
            centerX = (bounds[0] + bounds[1]) / 2
            centerY = (bounds[2] + bounds[3]) / 2

            mat = Mat4.translateMat(-centerX, 0, -centerY) * \
                  Mat4.scaleMat(0.98) * \
                  Mat4.translateMat(centerX, 0, centerY)
            pressEffectNP.setMat(mat)

        toggle = 'up'
        def toggle(*kw):
            nonlocal toggle
            if toggle == 'up':
                self['relief'] = 2
                toggle = 'down'
            else:
                self['relief'] = 3
                toggle = 'up'
            print(toggle)

        self.bind(DGG.B1PRESS, toggle)