DirectButton parenting issue

Hello!

I have some misunderstanding or something like that, but, when i create directButton and parent it on aspect2d it shows up like it should, but when i try to parent it on my_window.a2dRightCenter(or any), button will be created without visible geometry and any text, but still clickable and in parent’s coordinates. What am i doing wrong? :smiley:

First created button is where green frame painted and console shows, that it’s working.

It seems to be random culling since the center button is off the edge of the display; you might want to try setting your own bounding volume for the geometry.

button.node().set_bounds(OmniBoundingVolume())
button.node().set_final(True)

Nope, doesn’t work. I don’t think it’s about positioning, because in the past i created buttons just like that, and they was visible but half-drowned in border no mater what scale they was, so i just need to offset them myself.
Interesting fact: custom geometry doesn’t apply either.

1 Like

Maybe you accidentally called the hide() method somewhere?

1 Like

Nope, all related to this buttons are in screenshot.

Just try show() to check just in case. After all, the hide method does not have to be on the button, it can easily be on the node above.

1 Like

And nope, .show() doesn’t help either.
Well, if you hide a button, it’s collision hides aswell, so you can’t click on it. But worth to try, since i don’t know what to do next.

Just in case, this is how i created a window:

monitor = get_monitors() #from screeninfo
main = monitor[0] if monitor[0].is_primary else None
main_window = ShowBase(windowType="none")
main_window.start_tk()
frame = base.tkRoot

#somwere in beetwen i splited my root-frame for 3 frames with tk.PanedWindow but i don't think this can cause troubles

win_id = frame2.winfo_id()
props = WindowProperties()
props.setParentWindow(win_id)
props.setSize(1200, main.height - 50)
props.setOrigin(0,0)
base.makeDefaultPipe()
base.openDefaultWindow(props=props)
1 Like

I suspect the problem is that the main_window.a2dRightCenter node is not a child of the aspect 2d node?

aspect2d.getChildren()
Hm, 1 button is not parented, and manual reparenting doesn’t do anything.

render2d/aspect2d/a2dBackground
render2d/aspect2d/a2dTopCenter
render2d/aspect2d/a2dTopCenterNS
render2d/aspect2d/a2dBottomCenter
render2d/aspect2d/a2dBottomCenterNS
render2d/aspect2d/a2dLeftCenter
render2d/aspect2d/a2dLeftCenterNS
render2d/aspect2d/a2dRightCenter
render2d/aspect2d/a2dRightCenterNS
render2d/aspect2d/a2dTopLeft
render2d/aspect2d/a2dTopLeftNS
render2d/aspect2d/a2dTopRight
render2d/aspect2d/a2dTopRightNS
render2d/aspect2d/a2dBottomLeft
render2d/aspect2d/a2dBottomLeftNS
render2d/aspect2d/a2dBottomRight
render2d/aspect2d/a2dBottomRightNS
render2d/aspect2d/DirectFrame-pg0
render2d/aspect2d/DirectButton-pg2
1 Like

Ok, my_window.a2dRightCenter.attachNewNode(self.reset_pos.node()) made it. But the question still there, wtf is going on :smiley:

1 Like

The bottom line is that the camera that renders the GUI is reparent to the render2d node, so it can only render children of the render2d node.

import direct.directbase.DirectStart
from direct.gui.OnscreenText import OnscreenText
from direct.gui.DirectGui import DirectButton
from panda3d.core import TextNode

textObject = OnscreenText(text = "This is my Demo", 
                          pos = (0.95,-0.95), 
                          scale = 0.07, 
                          fg = (1, 0.5, 0.5, 1), 
                          align = TextNode.ACenter,
                          mayChange = 1)

button = DirectButton(text = ("OK", "click!", "rolling over", "disabled"),
                       scale = .05)

render2d.ls()
base.run()
PandaNode render2d S:(CullFaceAttrib DepthTestAttrib DepthWriteAttrib MaterialAttrib)
  PGTop aspect2d T:(scale 0.75 1 1) S:(CullBinAttrib)
    PandaNode a2dBackground
    PandaNode a2dTopCenter T:(pos 0 0 1)
    PandaNode a2dTopCenterNS T:(pos 0 0 1)
    PandaNode a2dBottomCenter T:(pos 0 0 -1)
    PandaNode a2dBottomCenterNS T:(pos 0 0 -1)
    PandaNode a2dLeftCenter T:(pos -1.33333 0 0)
    PandaNode a2dLeftCenterNS T:(pos -1.33333 0 0)
    PandaNode a2dRightCenter T:(pos 1.33333 0 0)
    PandaNode a2dRightCenterNS T:(pos 1.33333 0 0)
    PandaNode a2dTopLeft T:(pos -1.33333 0 1)
    PandaNode a2dTopLeftNS T:(pos -1.33333 0 1)
    PandaNode a2dTopRight T:(pos 1.33333 0 1)
    PandaNode a2dTopRightNS T:(pos 1.33333 0 1)
    PandaNode a2dBottomLeft T:(pos -1.33333 0 -1)
    PandaNode a2dBottomLeftNS T:(pos -1.33333 0 -1)
    PandaNode a2dBottomRight T:(pos 1.33333 0 -1)
    PandaNode a2dBottomRightNS T:(pos 1.33333 0 -1)
    TextNode  (1 geoms)
      with font
      alignment is A_center
      text color is 1 0.5 0.5 1
      transform is: T:m(pos 0.95 0 -0.95 scale 0.07 1 0.07)
      in coordinate system default
      text is This is my Demo
    PGButton DirectButton-pg0 T:(scale 0.05)
  PGTop pixel2d T:(pos -1 0 1 scale 0.0025 1 0.00333333) S:(CullBinAttrib)
  PandaNode camera2d
    Camera cam2d ( OrthographicLens )
      OrthographicLens film size = 2 2

PandaNode camera2d
Camera cam2d ( OrthographicLens )
OrthographicLens film size = 2 2

1 Like

And aspect2d is a render2d, just with precalculated screen spaces and aspect ratio. That’s why i can’t understand, why my_window(or base).a2dRightCenter link doesn’t work in my case.

1 Like

The principle here is simple: you create a display area and connect the camera to it, then create a node and attach the connected camera to it, the objects that are located lower in the hierarchy and will be rendered by the camera.

This principle also uses lighting, a geometry node will be illuminated by a light source if it is attached to the same hierarchy as the light source node.

1 Like

Okay, new day = clean head!

Further experimentations revealed:
If aspect2d already has parented directFrame, aspect2d childs will partially “ignores” any further parenting attempts.(or, to be precise, class constructor can’t build another frame and creates buttons without visible parts, how i think)

uncomented and commented background frame


So if you want to make a visible button and have a background:
wrong: self.background = DirectFrame(frameSize=(-2048, 2048, -2048, 2048), frameColor=(.25, .25, .25, 1))

right:
self.background = DirectFrame(parent=my_window(or base).a2dBackground, frameSize=(-2048, 2048, -2048, 2048), frameColor=(.25, .25, .25, 1))

self.button = DirectButton(parent=my_window(or base).a2dRightCenter, text=("center",), scale=.07, pos=(-.25, 0, 0))

Maybe, the fact, that background node even exists should be added in DirectGUI documentation, for preventing this kind of misunderstandings? Or, at least, list of all a2d nodes?

Looking at your element sizes, I understood your problem, and I think you can guess for yourself what’s going on. And yes, the presence of the a2dBackground node does not limit you in any way. You can always create your own, and do whatever you want with it.

from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import DirectButton, DirectFrame
from panda3d.core import NodePath

base = ShowBase()

background2d = NodePath("a2dMyBackground")
background2d.setPos(0, 0, 0.8)
background2d.reparent_to(aspect2d)

my_button_background = DirectButton(text = "MyBackground", scale = 0.1)
my_button_background.reparent_to(background2d)

one = DirectFrame(frameSize = (-0.4, 0.4, -0.4, 0.4), frameColor = (1, 0, 0, 1))
one.setPos(0.2, 0, 0)

button_one = DirectButton(text = "Yes", scale = 0.1)
button_one.reparent_to(one)

two = DirectFrame(frameSize = (-0.4, 0.4, -0.4, 0.4), frameColor = (0, 1, 0, 1))
two.setPos(0.6, 0, 0)

button_two = DirectButton(text = "No", scale = 0.1)
button_two.reparent_to(two)

render2d.ls()
base.run()

1 Like

Elements scale was nothing wrong here, since buttons was created as intended but without visible parts, and now, while i’m not parenting any DirectFrames to aspect2d but i’s childs - everything working as intended.

The buttons were not created without visible parts, they were just overlapped. The order matters, if you use a ready-made hierarchy of nodes, then focus on the order in which they were added.

Note that the green frame is superimposed on the red one on top, covering its elements located on the red one.

Based on a quick test, serega would seem to be correct:

The issue isn’t that the button isn’t being rendered, it’s that it’s being covered by a huge DirectFrame that happens to have a grey colour, and which thus looks like the default clear-colour.

Parenting the DirectFrame to the “a2dBackground” node just forces it to be “behind” the button, thus not covering it.

This can be seen by taking the code from the example labelled “wrong”, and replacing the alpha-value of its frame-colour with a value between zero and one: this should result in the DirectFrame becoming semi-transparent, and as a result, in the button becoming partially visible behind it.

See the following test-program:

from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import DirectFrame, DirectButton, DGG

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        #frameAlpha = 1   # Makes the button "disappear"
        frameAlpha = 0.5  # Makes the button partially visible

        self.background = DirectFrame(frameSize=(-2048, 2048, -2048, 2048), frameColor=(.25, .25, .25, frameAlpha))
        
        self.button = DirectButton(self.a2dRightCenter, text=("center",), scale=.07, pos=(-.25, 0, 0)) 

app = Game()
app.run()

Note the “frameAlpha” variable: the commented-out value gives your original result, while the uncommented value should give a partially-visible button due to a semi-transparent DirectFrame.

See screenshots below:

With “frameAlpha = 1”

With "frameAlpha = 0.5

(You can also see the sheer covering extent of the DirectFrame by making it a more-prominent colour, like green.)

[edit]
That said, I am a little surprised that the DirectFrame renders “in front of” the DirectButton, given that the button is made after the frame: I would expect them to render in order of parenting. Perhaps one class or the other has an explicit bin or sort-order applied that forces this render-order?