editing the wiki

Really? Something must be wrong. The DirectButton class relies on PGButton for its implementation, and we have been using DirectButton without any trouble for almost a decade now.

Can you give an example of using a PGButton that crashes?


Sure, but give me a day or so. I need to get it out of my menu class and strip it back to a bear function again.
( I hope it contains an error )


Hmm. Just took away:

framework_ptr->define_key(but->get_click_event(MouseButton::one() ), “button press”, (EventHandler::EventCallbackFunction *)&GUI_Callback_LMB_Clicked, Buttons[ButtonName]);

and the callback function:

void GraphicsUserInterface::GUI_ListButtonCallback_LMB_Clicked(const Event *ev, GeneralButton_Info *data)
// empty for testing purpose

and it doesn’t crash. ( it has no purpose too now :wink: )

I’m I using this incorrectly ?
Buttons[ButtonName] is a pointer to a existing structure, the callback is able to read and write to it (might cause problems ) but it also crashes when I use NULL instead.

Am I using the callback system incorrectly ?

Is it possible that you’re using reference counts incorrectly? It’s an easy mistake to make in C++ code. Since PGButton inherits (indirectly) from ReferenceCount, it means you have to apply the standard Panda C++ reference-counting rules: always store it in a PT(PGButton) instead of a PGButton *, pass it by pointer instead of as a concrete object, and never try to delete it explicitly.


Fast response ! Quick dump:

		Texture *readyTex, *pressedTex, *rolloverTex;
		readyTex = TexturePool::load_texture("VPB_ProjectFiles/Gui/Buttons/button_inactive.png");
		pressedTex = TexturePool::load_texture("VPB_ProjectFiles/Gui/Buttons/button_pressed.png");
		rolloverTex = TexturePool::load_texture("VPB_ProjectFiles/Gui/Buttons/button_active.png");

	  	float Width=4;
		float Height=1;
		CardMaker cm("cardMaker");

		// create node paths
		NodePath readyPath(cm.generate());	 readyPath.set_texture( readyTex );
		NodePath pressPath(cm.generate());	 pressPath.set_texture( pressedTex );
		NodePath rollPath(cm.generate());	 rollPath.set_texture( rolloverTex );
		NodePath inactPath( cm.generate());	 inactPath.set_texture( readyTex );

		PT(PGButton) but;
		but = new PGButton(ButtonName);

		// Set the button frame size.
		LPoint3f min_point, max_point;
		readyPath.calc_tight_bounds(min_point, max_point);
		but->set_frame(min_point[0], max_point[0],min_point[2], max_point[2]); 

		NodePath butNP = win_ptr->get_aspect_2d().attach_new_node(but);

OK, seems all right as far as that goes.

I’m a little worried by this:

(EventHandler::EventCallbackFunction *)&GUI_Callback_LMB_Clicked

Typecasting a C function is risky, because you might cast away important aspects of the function prototype, causing a crash when the function is called. I would prefer that you defined GUI_Callback_LMB_Clicked() to receive a void * for the second parameter (so that it exactly matched the EventCallbackFunction type) and performed typecasting on the void * parameter within the function, instead of typecasting the function itself.

Also, your GUI_Callback_LMB_Clicked method is declared static, right? If it isn’t static, it will certainly cause a crash when it is called, because you are typecasting it into a static method type.


Oops, problem here:

Texture *readyTex, *pressedTex, *rolloverTex; 

These should all be PT(Texture) instead of Texture *, because of that reference-counting thing. This probably isn’t causing you any trouble in practice, though, because the TexturePool is keeping a pointer for you.


Thanks. I seem to remember it was crashing all the time using PT(Texture). Please let me make a clean code out if this so you can examine it. Would like to have this problem solved.
Now, It’s bed time… Thanks for the help !

Hi Drwr, I completely missed your first message yesterday evening !
You might be on to something.
I made GUI_Callback_LMB_Clicked() to receive a void * as second parameter.

in GraphicsUserInterface.h:

static void GraphicsUserInterface::GUI_Callback_LMB_Clicked(const Event *ev, void *data)

In the OnScreenMenu button creation I use: framework_ptr->define_key(but->get_click_event(MouseButton::one() ), “button press”, &GUI_Callback_LMB_Clicked, Buttons[ButtonName]);

When I run it -without debugging- It will crash sooner or later ( clicking the button 10 to 40 times in very short intervals)

However, when I run it using debugging, it does not crash.
How annoying :wink:

I’m using MS visual 2008 Express edition.

What am I missing ??

What do you mean by running with and without debugging? Do you mean compiling in a different mode? You always have to compile your application in the same mode that Panda was compiled in. Unless you download and comile Panda yourself, this means compiling your application in Release mode, and you also have to remove NDEBUG from the set of pre-defined symbols.


By running without debugging, I meant compiling in release mode.
By default, I compile using release mode, using #undef NDEBUG

Is this wrong ?

Yes. Due to a minor bug in Panda’s header files, you may not #define NDEBUG when you compile your own application. If you do, it will compile in incorrect offsets to Panda’s own structures, leading to memory corruption and a crash.

This bug will be fixed in 1.7, but in the meantime, you have to leave NDEBUG out of your own application project. :slight_smile:


Note the -un-def… ( #undef NDEBUG )
Shouldn’t that disable any previously defined commands ?

Well, I just checked my buildlog.html and indeed: NDEBUG is defined

Solved by:
rightclick on the project
C/C++: Preprocessor: Preprocessor Definitions: remove NDEBUG

(I guess this will be mentioned somewhere already but just wanted to add
it in case somebody is searching for it )

Thanks for the help !

To get on-topic again:
I have made an attempt to update the manual:


Please judge it.

It’s good, useful information; though I might suggest paring it down a bit to some more essentials. This text seems more suited to a tutorial than to a manual. Tutorials are useful and needed, but let’s keep them separate from the manual itself (or at least in their own chapters labeled “tutorial”).

Also, there are some specific points that you may not have known. You don’t need to use a CardMaker to generate geometry for any PGItem class; the class includes a set_frame_style() method that can generate its own geometry, including not-too-ugly beveled buttons.

Also, for creating custom texture buttons, I would recommend using egg-texture-cards to load up cards with textures already applied, rather than loading the textures individually and applying them to your own cards. The reason being that egg-texture-cards can automatically make the cards the appropriate size and aspect ratio to match your texture image; you don’t have to deal with that separately.


Thanks for the feedback.
I’ll look in to the egg-texture-cards system and change the article accordingly.
I’ll also add the set_frame_style() method, I knew it exists but since I found it ugly and called it the default way on top of the page :wink:
Also I will try to change the writing style to manual style. Not a very easy task.

Now how about that, I completely missed the power of the set_frame_style() method…
Manual rewritten… cut back to 10% of it’s original size :wink:
I have chosen not to use the egg-cards in this case in order not to over complicate things.

What I find very frustrating, is the way the textnode for the PGuiButton is build.
There is no normal way to reach it as far as I can see in pgButton.cxx,
so setting text properties like color does not seem to be possible.
I see a way around that, but that involves resetting all the pandanodes for the states, plus some more work.
Is there any known way to change the textnode properties ?

Not sure what you mean. You can call PGItem::get_text_node(), which returns a pointer to the globally-shared TextNode which is used to generate the text at the next call to PGButton::setup(). If you want to change the text color you will have to call setup() again.


I see. Okay, thanks.
It’s clear that the whole PGui class is never made for flexibility…
By now I have made a whole wrapper for myself, utilizing the PGui class so, that it suits my needs.
How am I supposed to make a manual for this class ? It will get way bigger then a simple tutorial. On top of that, the sliderbar and waitbar are quite outdated and very hard to setup to anyones needs in my opinion.
Also it lacks default things like listboxes, checkboxes, and so on.

Is there any interest in a flexible c++ class, utilizing the Pgui class ?
This thing works on my nerves :wink:

I hope I’m not stepping on anyones toes !

Sure, why not create a flexible C++ wrapper around the PGui classes? Sounds like it would be useful.