TextNode, set_text() mystery and PGButton

I’m in need of skilled C++ forum guys support again.
Now I’m putting my hands over the PGBbutton component to use it in my project but I’m experiencing strange occurrences just form the beginning using this simple python code:

import direct.directbase.DirectStart
from pandac.PandaModules import *
class mybutton(PGButton):
  def __init__(self, name="Button", parent=aspect2d, label=""):
    PGButton.__init__(self, name)
    if not label: label=name
if __name__ == '__main__':
  b=mybutton(name="Yello!", parent=None)
  tpMgr = TextPropertiesManager.getGlobalPtr()
  tpMgr.setGraphic("gr1", tpGg1)

The PGbutton part goes fine until I pretend to wrap it into a TextNode, after that the button text label disappear. To investigate the problem I found a good idea to watch into the core TextNode.cxx to understand the ::set_text() mechanics but…there is no method, just an override of TextEncdoder component and no method there too, therefore I’m lost.
So could somebody address me where the heck is it?

digging further into things some other doubts arose:

does anybody knows why there are these NON CONSTANT variable definitions OUTSIDE the PGItem component in panda/src/pgui/pgitem.cxx?

39  TypeHandle PGItem::_type_handle;
40  PT(TextNode)  PGItem::_text_node;
41  PGItem *PGItem::_focus_item = (PGItem *)NULL;
42  PGItem::BackgroundFocus PGItem::_background_focus;

I tellya because @ line 40 there is a ‘suspect’ _text_node that is used indeed for labelling pgui widgets, PGButton as well. And also there is a private definition into PGItem (line 237 in pgitem.h) with the same name so I guess that this double exposure could bring about troubles somehow.

That sounds like those are static members and thus should be initialized outside the PGItem component stuff.

The entry you found in the header file is the declaration of this variable, what you saw in the .cxx file is the actual initialization of it. This is not “double exposure” at all or so, this is just how it’s done usually in C++, the header file just says that the stuff exists, the source files contain the actual implementation of those things. (I hope I worded this right)

You made yourself clear man thank you. You confirm my worries tough: I said “double exposure” inappropriately but I sense that those variables put there could cause trouble for sure (actually is just an old C coder instinct but I guess so).

Actually, when I paste in your code, I get an exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "astelix.py", line 12, in ?
    b=mybutton(name="Yello!", parent=None)
  File "astelix.py", line 9, in __init__
AttributeError: 'NoneType' object has no attribute 'attachNewNode'

which makes sense, since you are passing in parent=None, but not handling that case in your mybutton class.

As to the disappearance of your label, that appears to be a bug in PGButton, and has nothing to do with the TextNode. If you simply parent b.NP to aspect2d, it doesn’t have a visible label either. (Though it works if you parent it to render2d instead.) What’s happening is that the default sort order is different under aspect2d or render2d, and the PGButton has created its nodes in the wrong order for drawing them under aspect2d. The label gets drawn behind the bevel. There’s a simple fix for this; I’ll put it in.

For the record, though, the TextNode::set_text() method does indeed call up to TextEncoder::set_text(), which exists and sets the _text member of the object. It doesn’t immediately generate the associated geometry, though, because you might follow this up with calls to set_font() or set_width() or some series of properties changes, each of which would require regenerating the geometry, and that could get expensive. Instead, the geometry is only regenerated once, the next time the TextNode is rendered. You can see this happen if you follow through the logic in TextNode::cull_callback(), which is called every frame the TextNode is rendered. The actual logic to regenerate the geometry is handled in TextNode::generate().

No worries. pro-rsoft is right; there is no double exposure or anything incorrect here. This is the way you declare static data members in C++. It’s a weird language, I’ll give you that.


sorry David, I mistakenly posted my last try without backing off to the good one.
I ain’t tested at all with render2D mainly cos’ around in the forum you said that PG stuff needs aspect2D for the PGTop reason.

Glad you found so fast how to fix it David, so I may forget it.

About C++ language weirdness it’s just my fault - if I pretend to put my hands into it then I need to learn how to ‘talk’ it; luckily there are you guys! :wink:

today I saw you fixed it perfectly - great job David!