PGButton not responding to a mouse click on pixel2d

Hi, I am currently creating a menu structure. Since I have problems with alignment on aspect2d (I couldn’t get the width of a PGButton to place a new button right next to it), I am about to try pixel2d. Now I have a PGButton which can be clicked (and throws events) in aspect2d, but not in pixel2d. It even does not change the look when the mouse is over the button. I am using C++ and Panda 1.10.10.
The source code is attached. Thanks (596 Bytes)

Perhaps your problem is related to this one.

I guess they forgot about the frame size according to the coordinate system for pixel2d node.

I may be mistaken, but I seem to recall that DirectGUI (and I presume then by extension PGUI) widgets only function when attached to aspect2d.

That said, you don’t need to parent an object to pixel2d in order to use the latter for positioning: you should be able to place your objects relative to pixel2d, like so:

button_node_path.set_pos(pixel2d, new_pos)
1 Like

Interesting! I will check that. Thanks

1 Like

I tried button_node_path.set_pos(pixel2d, new_pos) and it worked as you said, but I loose the advantages of pixel2d (for example: Not having to reposition the buttons due to a windows resize). But if the DirectGUI/PGUI elements are only for aspect2d then I have to look further.
Strange I can see the button in pixel2d, I just cannot click on it.

I’m using DirectGUI elements with pixel2d without any issues at all. @Thaumaturge , even your TabbedFrame widget is working with pixel2d :wink:

I have no experience with PGui elements but they should work with the correct configuration. Perhaps the scale is not properly applied and PGUI maps incorrectly the mouse position onto the button frame as suggested by @serega-kkz ?

Ah, I stand (gladly) corrected, then!

It is possible.

I suppose that the question, then, is this: how does your code, @eldee, differ from jbandhauer’s…?

I’m sorry I didn’t make it explicit, my GUI code is in Python and I’m using DirectGUI, not PGUI :slight_smile: That said, after a cursory glance at DirectGUI code, I don’t see any mouse or pixel2d specific code, so I would say PGButton should work when parented to pixel2d.

Ah, right, of course–it was silly of me to not realise that! (Especially as TabbedFrame has not C++ version. ^^; )

Fair enough, then!

Here is the source code of this constructor.

void PGButton::
setup(const std::string &label, PN_stdfloat bevel) {
  LightReMutexHolder holder(_lock);

  TextNode *text_node = get_text_node();
  PT(PandaNode) geom = text_node->generate();

  LVecBase4 frame = text_node->get_card_actual();
  set_frame(frame[0] - 0.4, frame[1] + 0.4, frame[2] - 0.15f, frame[3] + 0.15f);

  PT(PandaNode) ready = new PandaNode("ready");
  PT(PandaNode) depressed = new PandaNode("depressed");
  PT(PandaNode) rollover = new PandaNode("rollover");
  PT(PandaNode) inactive = new PandaNode("inactive");

  PGFrameStyle style;
  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
  style.set_width(bevel, bevel);

  set_frame_style(S_ready, style);

  style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
  set_frame_style(S_rollover, style);

  inactive->set_attrib(ColorAttrib::make_flat(LColor(0.8f, 0.8f, 0.8f, 1.0f)));
  style.set_color(0.6f, 0.6f, 0.6f, 1.0f);
  set_frame_style(S_inactive, style);

  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
  set_frame_style(S_depressed, style);
  depressed->set_transform(TransformState::make_pos(LVector3(0.05f, 0.0f, -0.05f)));

  get_state_def(S_ready).attach_new_node(ready, 1);
  get_state_def(S_depressed).attach_new_node(depressed, 1);
  get_state_def(S_rollover).attach_new_node(rollover, 1);
  get_state_def(S_inactive).attach_new_node(inactive, 1);


Frame is calculated with float-type numbers, which is not applicable to pixels.

However, you can try another constructor by passing it a TextNode for the desired state.

void PGButton::
setup(const NodePath &ready, const NodePath &depressed,
      const NodePath &rollover, const NodePath &inactive) {
  LightReMutexHolder holder(_lock);

  instance_to_state_def(S_ready, ready);
  instance_to_state_def(S_depressed, depressed);
  instance_to_state_def(S_rollover, rollover);
  instance_to_state_def(S_inactive, inactive);

  // Set the button frame size.
  LPoint3 min_point, max_point;
  ready.calc_tight_bounds(min_point, max_point);
  set_frame(min_point[0], max_point[0],
            min_point[2], max_point[2]);

On which note, have you tried explicitly setting the frame-size to something appropriate to pixel2d via “set_frame”?

It seems that the problem is deeper than it seems.

#include "pandaFramework.h"
#include "pandaSystem.h"
#include <iostream>
using namespace std;

//global variables
PandaFramework* framework;
WindowFramework* window;

int main(int argc, char* argv[]) {

    // Open a new window framework
    PandaFramework framework;
    framework.open_framework(argc, argv);

    // Set the window title and open the window
    framework.set_window_title("My Panda3D Window");
    WindowFramework* window = framework.open_window();

    PT(TextNode) text_node = new TextNode("instructions");
    LVecBase4 frame = text_node->get_card_actual();
    cout << frame << endl;

    PT(PandaNode) geom_text = text_node->generate();
    NodePath button_text = NodePath(geom_text);
    button_text.set_pos(400, 0, -300);

    // Do the main loop, equal to run() in python
    return (0);


Known pipe types:
(all display modules loaded.)
0 2.0375 -0.1975 0.79

I just did that. I used the line: my_button->set_frame(0, 25,-17, 20);
It affects the background of the Button (it is much larger now), but when the mouse is over it, it does not change its look or is clickable.

Hum. Very odd!

In that case, I don’t know! I’ll defer to other forum-members for now, then, I fear!

1 Like

Is it appropriate to open an issue for that?

The thread has been open for a little while, so I see no harm in doing so.

@rdb supplied a workaround which (of course) works:

As a workaround, use this to set up the MouseWatcher to watch pixel2d as well:

DCAST(PGTop, window->get_pixel_2d().node())->set_mouse_watcher(DCAST(MouseWatcher, window->get_mouse().node()));

These includes are needed:

#include "dcast.h"
#include "pgTop.h"
#include "mouseWatcher.h"

The final solution will be in 1.11

1 Like