Jump to content
  • Advertisement
Sign in to follow this  
Green_Baron

Is my user event handling ok ? (glfw/c++)

Recommended Posts

Posted (edited)

So this is how i do it:

On creation, my window object (GlfwWindow * is passed in) creates an EventHandler, which holds a data structure for objects to register themselves and offers virtual methods for the c-style callback functions (code for the cursor callback, not every callback is implemented yet). In EventHandler.h/.cpp:

typedef enum eventType : unsigned int  {
		MOUSE_MOVE = 0b1,
		MOUSE_BUTTON = 0b10,
		MOUSE_SCROLL = 0b100,
		KEY = 0b1000,
		CHAR = 0b10000,
		FRAMEBUFFER_RESIZE = 0b100000
	} eventType;

std::vector<EventHandler::RegisteredObject> EventHandler::s_registeredObjects {};

EventHandler::EventHandler( GlfwWindow *win ) : m_window { win } {
	glfwSetCursorPosCallback( m_window->getWindow(), cursorPosCallback );
  ...
  ...

The callback redirects to the virtual method:

// static
void EventHandler::cursorPosCallback( GLFWwindow *w, double x, double y ) {
	EventHandler *e = reinterpret_cast<EventHandler *>( glfwGetWindowUserPointer( w ) );
	e->onMouseMove( (float)x, (float)y );
}

The virtual method iterates over registered objects and calls their respective overriden methods, that can return a bool if they don't want anybody else to handle the event:

// virtual
bool EventHandler::onMouseMove( float x, float y ) {
	bool handled = false;
	for( RegisteredObject &obj : s_registeredObjects ) {
		if( obj.types & MOUSE_MOVE ) {
			//handled = reinterpret_cast<EventHandler *>(obj.object)->onMouseMove( x, y );
			handled = obj.object->onMouseMove( x, y );
			if( handled )
				break;
		}
	}
	return handled;
}

A class that wants to receive user events must inherit from EventHandler and register the events it wants to receive via a method from the eventhandler, via a simple bit field (in the first code snippet):

void EventHandler::registerObject( RegisteredObject &obj ) {
	bool found = false;
	for( RegisteredObject &r : s_registeredObjects ) {
		if( r.object == obj.object ) {
			Logbook::getInstance().logMsg( Logbook::WINDOW, Logbook::WARNING,
				 "Ignoring try to register an already registered object with the event handler." );
			found = true;
		}
	}
	if( !found )
		s_registeredObjects.push_back( obj );
}

And overrides the inherited virtual method:

// virtual
bool Camera::onMouseMove( float x, float y ) {
	bool handled{ false };
	... do mouse move stuff ...
	return handled;
}	// onMouseMove()

It works, for Camera, UI interface and my drawing apps.

What do you think ? It is probably a standard, though i have seen more complicated solutions. Have i missed something ? Could it be done better with the window user pointer, whose function i haven't really understood ?

Edited by Green_Baron

Share this post


Link to post
Share on other sites
Advertisement

You are reinventing the wheels. And your solution is not easy to use by requiring inheritance.

There are quite some C++ event dispatcher libraries out of there. I develop my eventpp library which can be used for general purpose.

Share this post


Link to post
Share on other sites

Well, i am aware, i checked a lot of those, and finally thought that i wanted to "cook my own soup", but am still at the beginning with all this. I needed a solution for the problem that the callbacks are c-functions, but i want to access them from different objects in c++.

But I didn't think about thread safety (yet, it is on the table), so that's a thing to keep in mind for the near future.

Question ... what's wrong with inheritance ? I find it pretty straight forward and use it for other things as well, like my renderable objects that inherit their life cycle (setup, pre-frame, render, post-frame, cleanup) as well as camera/window/ui-access via inheritance.

Edit: It is no meant as a generalized solution, others can do this much better than i will ever be able to. Just for my own brew 🙂

Edited by Green_Baron

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!