Implementing mouse in Cxx


how do i implement mouse control in panda3D C++? I understand that i can get the position of the mouse pointer with:

mouseX = window->get_graphics_window()->get_pointer(0).get_x();
mouseY = window->get_graphics_window()->get_pointer(0).get_y();

but i want to use the more extensive features of the mouse functions in mouseWatcher.h. So how should i go about implementing it?

window->get_mouse() is a MouseWatcher NodePath. You can do:

MouseWatcher *mwatcher = DCAST(MouseWatcher, window->get_mouse().node());


thanks for your reply! i’ll try this out. :slight_smile:

edit: I implemented it as you said but mwatcher->has_mouse() always returns false. Do i have to specify a region for detection?

It should return true when the mouse is over the window, and false when it is not. It works for me in pview. Are you sure the mouse is over the window?


!!! bringing up old topic, I know, but it is needed. !!!

Hey David, this is for you, in C++ the mwatcher node, retrieved using the method you’ve given is not tracking mouse movement.

has_mouse appears to be reporting correctly. get_mouse_x() and get_mouse_y() do not.

Is there another step being missed here? Some initialization or something?

it also causes an unhandled exception, looks like panda is trying to work with an object that is null on the close_framework() call.

This only happens when trying to access the mouse, and seems only to happen when the mouse goes outside the window while the program is running. It doesn’t matter if the mouse returns or not before program close.

I also attemped:


Which is returning values this time, but the exception still occurs.

Panda 1.7.0

This works fine for me in 1.70:

mouseWatcher = (MouseWatcher*)window->get_mouse().node();

// bla bla bla - other setup etc

// inside of main loop
if (mouseWatcher->has_mouse())
 LPoint2f mpos = mouseWatcher->get_mouse();
// do something with mpos.get_x() and mpos.get_y()

I don’t get any crashes in the close_framework call. You might want to also put pointer != null checks before the has_mouse() call.

The NULL is coming from framework_close() which means Panda is referencing a NULL object.

If I was, it would crash on my code.

Nah, the problem is somewhere underneath.

get_mouse_x() and get_mouse_y() both use the _mouse variable which is what get_mouse() returns anyway, so its all the same thing.

Can you move the mouse outside the program, then return to the window then close it and see if you get the exception?

Noticed this in the source:

//     Function: WindowFramework::get_mouse
//       Access: Public
//  Description: Returns the node in the data graph corresponding to
//               the mouse associated with this window.
NodePath WindowFramework::
get_mouse() {
  if (_mouse.is_empty()) {
    NodePath mouse = _panda_framework->get_mouse(_window);

    // Create a MouseWatcher to filter the mouse input.  We do this
    // mainly so we can constrain the mouse input to our particular
    // display region, if we have one.  This means the node we return
    // from get_mouse() is actually a MouseWatcher, but since it
    // presents the same interface as a Mouse, no one should mind.

    // Another advantage to using a MouseWatcher is that the PGTop of
    // aspect2d likes it better.
    PT(MouseWatcher) mw = new MouseWatcher("watcher");
    _mouse = mouse.attach_new_node(mw);
  return _mouse;

but where is it deleted? Still looking…

I noticed the panda framework has a get_mouse and a remove_mouse, shouldn’t the window framework always work off of this mouse?

This all should work properly. It sounds like something deeper is wrong in your environment.

Are you sure that you have removed the NDEBUG symbol from your project? This is a common mistake that can cause mysterious problems like this.


Absolutely sure.

AsyncTask::DoneStatus ctank::tankUpdateTask(GenericAsyncTask* task, void* data)
	// NOTE: Left and right components move opposite of each other, so in order
	// to have them go the same direction, one is the inverse of the other.
	// This is because of the way the wheels and tracks were modelled, one side
	// is dupes of the other, in order to save time. Modelling each wheel
	// and track from scratch would make me go insane.

	ctank* tank = (ctank*)data;	
	NodePath track;
	NodePathCollection npc;

	// Turret rotation by mouse
	WindowFramework* window = getWindow();
	PandaNode *mouse_node = window->get_mouse().node();
	PT(MouseWatcher) mwatcher = DCAST(MouseWatcher, mouse_node);

		LPoint2f mouse = mwatcher->get_mouse();

		static int omx = mouse.get_x();
		static int omy = mouse.get_y();
		int mx = mouse.get_x();
		int my = mouse.get_y();

		int diffx = mx - omx;

		if(diffx != 0)
			NodePath turret = tank->getActor().find("*/Turret");
			turret.set_h(turret.get_h() - diffx);		
		omx = mx;
		omy = my;

Looks like window is bad when it crashes. But the task shouldn’t be getting called on close_framework() should it?

Hmm, looks like close_framework() doesn’t explicitly stop the task manager or remove any tasks, so it’s still possible for a task to be invoked after close_framework() has been called, depending on your task loop.



Tried stopping the task, didn’t work.
Tried removing the task… didn’t work.

Still causing an exception.

Do you stop the task before you call close_framework()? It’s probably important to do it in that order. It’s not a threaded task, is it?


Yes, it is in proper order. :wink:

threaded, no.

Gonna start a smaller project, see if I can repeat this problem in a different setting.

IIRC, from tracking something else down, that the tasks are queued up and do get played back even after the framework is stopped. So the workaround is to set a “teardown” flag that bypasses the task functions.

Also, is your ctank::tankUpdateTask declared as static? What is your getWindow() function doing?

(Plus it’s C++, you should be checking your pointers for null, always.)

sry it took so long.
The window function just returns the window framework for the open window…

PT(WindowFramework) getWindow(void) { return _main_window; }

The task was a static method, but I’ve since removed it from the class making it a stand-alone function.

In the Panda source I see that tasks have been PT()'d so I PT()'d all my tasks as well. However, this is not reflected in the online manual.

Other than that, I don’t know what’s going on here. This access violation b.s. has gotta be something else. It’s not making any sense, and the fact that any auto watch and local watch values are all turd-pie & tail-up when the violation occurs makes me wonder…

I’m gonna remove some memory see if that new stuff is bad.

I created a side project, can still get it to crash, this time it points me to the PointerTo class Reassign method, and the copy value seems valid

// panda.cpp
// author: mss

//#include "global.h" // -- you wont need this.

PandaFramework framework;
PT(WindowFramework) window = NULL;

EventHandler *eventHandler = EventHandler::get_global_event_handler();
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr();
PT(ClockObject) globalClock = ClockObject::get_global_clock();

NodePath pandaCamera;

//   A generic task

AsyncTask::DoneStatus mouseTask(GenericAsyncTask* task, void* data)
	PT(MouseWatcher) mWatcher = DCAST(MouseWatcher, window->get_mouse().node());	

		printf("%f, %f\n", mWatcher->get_mouse_x(), mWatcher->get_mouse_y());

	return AsyncTask::DS_cont;

//   Panda Tasks

AsyncTask::DoneStatus IntervalManagerTask(GenericAsyncTask* task, void* data)

	return AsyncTask::DS_cont;

//   Global Panda Objects Accessors

PT(ClockObject) getClock(void)
	return globalClock;

PT(AsyncTaskManager) getTaskMgr(void)
	return taskMgr;

PT(WindowFramework) getWindow(void)
	return window;

PandaFramework* getPanda(void)
	return &framework;

EventHandler* getEventHandler(void)
	return eventHandler;

//   Other..

// TODO: Add other (misc) stuff here.

//   Custom Setup & Shutdown Functions

void Setup(void)
	PT(GenericAsyncTask) intervalTask = 
		new GenericAsyncTask("Updates the Interval Manager", &IntervalManagerTask, NULL);
	// Add Interval Manager Task

	PT(GenericAsyncTask) genericTask = 
		new GenericAsyncTask("Mouse Check", &mouseTask, NULL);

	// Add a generic Task (tests mouse)

void Shutdown(void)

//	 Start Function

void start(char** vargs, int cargs)
	// Open the Framework
	framework.open_framework(cargs, vargs);	

	// Open the Window
	framework.set_window_title("Hello World!");
	window = framework.open_window();
	// Verify window has opened successfully
	if(window != NULL)
		// Must call this to enable keyboard input.
		// Set the camera.
		pandaCamera = window->get_camera_group();	

		// Any extra custom setup.

		// Main loop

		// Any extra custom shutdown stuff.

		// Close the framework

Where does it crash in your sample code that you posted? I put it into a test app just for my curiosity, and it didn’t fail at all.

inside the PointerTo<> class, at reassign… the thing is I don’t know where its coming from because the stack trace is all panda dll’s and all variable watches are bogus/dirty info, and I can’t build panda in debug cuz I don’t have the windows framework and it seems microsoft is not giiving it out for windows xp. :\ uhg. such a dirty dirty job. I hate programming, I’m just addicted to it.

So, build Panda in release. You’ll still be able to debug it.


Can’t without microsoft framework, and like I said, have yet to find a downloadable distribution for xp/msvc 2008

I haven’t had any trouble downloading MSVS 2008 Express for Window XP and using it to build Panda.

On this page: there’s a tab labeled “Visual Studio 2008 Express”.

Of course, if you’re building all of Panda yourself, you can use any version of MSVS; it doesn’t necessarily have to be 2008. (But it still helps to use 2008, because of the precompiled thirdparty libraries. If you use a different compiler version, you might have to rebuild all of these libraries, which is an enormous pain.)