Corner based DirectGui placement?

I dont know if this exist already, i made a little bit of code to place gui components directly to corner of parent.
Code sample is at bottom of post.

What i thought is if i can somehow override setPos() for GUI elements?
I think it would be good to have this in official panda, but its not my call.

So by default one would place gui elements based on topleft corner of parent. Both their topleft corners would be same by default.

so guiel.setPosGUI(0.5,0.5) would place topleft corner exactly in center of parent.

Z coord isnt needed, right?

There would be two optional args: corner and relativeCorner

case1
mybutton.setPosGUI(relativeWidget,0,0, corner=“BottomRight”, relativeCorner = “BottomLeft”)

relativeWidget is NodePath, this would work same as normal setPos if there are no these extra 2 args

This would make mybutton’s bottom left corner in same place as relativeWidgets botom right corner.

different case (case 2)
mybutton.setPosGUI(relativeWidget,0.3,0, corner=“BottomRight”, relativeCorner = “TopLeft”)

0.3 stands for 0.3 of mybutton’s parent width.

here is pretty pic :smiley:

If you guys think this is bad idea, i dont mind, i just wonder if i can somehow add some more methods to DirectFrame(i want all gui elements to have this methods) or any of its parents…

If thats not possible, i will just make function wrappers and pass objects to them.

I dont intend to make this in c/c++, i will write python code, it should be easy to copy all that to c++.

Or if someone else is interested in doing this i will be more than glad to help :slight_smile:

Code below does not offer any of that functionality, it just shows how to align widgets to corners?

from direct.gui.OnscreenText import OnscreenText
from direct.gui.DirectGui import *
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import *


class MainMenu(DirectObject):
    def __init__(self):
        self.accept("a", self.posDownLeft)
        self.accept("s", self.posDownRight)
        self.accept("d", self.posTopLeft)
        self.accept("f", self.posTopRight)
        self.text = OnscreenText(text = 'my text string', pos = (-0.9, -0.9), scale = 0.147)
        self.Frame = DirectFrame(frameColor=(0,0,0,1) , frameSize=(0,1.41,0,1.123 ) )
        self.Frame.reparentTo(base.a2dBottomLeft)
        self.Frame.setPos(self.Frame, 0.5,0,0.5)
        #Add button
        self.b = DirectButton(text = ("Sexy monster", "click!", "rolling over", "disabled"), scale=.2)
        self.b.reparentTo(self.Frame)

        
    def posDownLeft(self):
        bounds = self.b.getBounds()
        scale = self.b['scale']
        posX = bounds[0]*scale*-1
        posy = bounds[2]*scale*-1
        self.b.setPos(posX,0,posy)
        
    def posTopRight(self):
        bounds = self.b.getBounds()
        scale = self.b['scale']
        parent = self.b.getParent()
        ph = parent.node().getFrame()
        print ph
        posX = ph[1] - bounds[1]*scale
        posy = ph[3] - bounds[3]*scale
        self.b.setPos(posX,0,posy)
        
    def posDownRight(self):
        bounds = self.b.getBounds()
        scale = self.b['scale']
        parent = self.b.getParent()
        ph = parent.node().getFrame()
        print ph
        posX = ph[1] - bounds[1]*scale
        posy = bounds[2]*scale*-1
        self.b.setPos(posX,0,posy)
        
    def posTopLeft(self):
        bounds = self.b.getBounds()
        scale = self.b['scale']
        parent = self.b.getParent()
        ph = parent.node().getFrame()
        print ph
        posX = bounds[0]*scale*-1
        posy = ph[3] - bounds[3]*scale
        self.b.setPos(posX,0,posy)

This is already possible. You can reparent elements to base.a2dTopLeft, BottomRight, etc, etc.

Ah you got me all wrong…
I know for that, but can you get 3 buttons on topright corner of frame which is parented to basea2d.bottomLeft

Hmm, this could be a bit more work than i thought at first…

I dont understand how setPos() is supposed to work with directgui objects, i have tried several and each tends to have its own way of positiong itself.

For example DirectButton uses horizontal center (width/2) and vertical quarter (height/4).

DirectEntry uses something like point which is exactly in left line of boundingbox and in center of first line of text…

I read somewhere that all widgets are supposed to use center of bounding box, is that true?

Here is code for placing button in frame in way i described earlier

def setPosGUI(element,posX,posY,mode = "TL",relative = None,relCorner = "TL"):
    scale = element['scale']
    if scale == None:
        scale = 1
    bounds = element.getBounds()
    parent = element.getParent()
    parentBounds = parent.node().getFrame()
    width = (bounds[1]-bounds[0]) *scale
    height =(bounds[3]-bounds[2]) *scale
    pwidth = parentBounds[1]-parentBounds[0]
    pheight = parentBounds[3]-parentBounds[2]
    if relative == None:
        if mode == "TL":
            realPosX = (width / 2) + posX * pwidth
            realPosY = (pheight - height*0.75) + (posY * pheight *-1)
            element.setPos(realPosX,0,realPosY)

setPosGUI(button, 0, 0) #makes button and frame topleft corners to be in same place on screen

setPosGUI(button, 1, 1) # makes opposite corners to be in same place