diff --git a/panda/src/event/eventHandler.cxx b/panda/src/event/eventHandler.cxx index e3e389e1bf..5ad4bbe0e6 100644 --- a/panda/src/event/eventHandler.cxx +++ b/panda/src/event/eventHandler.cxx @@ -104,6 +104,20 @@ dispatch_event(const Event *event) { } } + // now for lambda hooks + LambdaHooks::const_iterator lhi; + lhi = _lambdahooks.find(event->get_name()); + + if (lhi != _lambdahooks.end()) { + // found one + const LambdaFunctions &functions = (*lhi).second; + + size_t num_functions = functions.size(); + for (size_t i = 0; i < num_functions; ++i) { + functions[i](event); + } + } + // Finally, check for futures that need to be triggered. Futures::iterator fi; fi = _futures.find(event->get_name()); @@ -189,6 +203,19 @@ add_hook(const string &event_name, EventCallbackFunction *function, return _cbhooks[event_name].insert(CallbackFunction(function, data)).second; } +/** + * Adds the indicated function to the list of those that will be called when + * the named event is thrown. Returns true if the function was successfully + * added, false if it was already defined on the indicated event name. This + * version stores an arbitrary C++ lambda. + */ +void EventHandler:: +add_hook(const string &event_name, EventLambda function) { + assert(!event_name.empty()); + assert(function); + _lambdahooks[event_name].push_back(function); +} + /** * Returns true if there is any hook added on the indicated event name, false * otherwise. @@ -212,6 +239,14 @@ has_hook(const string &event_name) const { } } + LambdaHooks::const_iterator lhi; + lhi = _lambdahooks.find(event_name); + if (lhi != _lambdahooks.end()) { + if (!(*lhi).second.empty()) { + return true; + } + } + return false; } @@ -306,6 +341,14 @@ remove_hooks(const string &event_name) { _cbhooks.erase(chi); } + LambdaHooks::iterator lhi = _lambdahooks.find(event_name); + if (lhi != _lambdahooks.end()) { + if (!(*lhi).second.empty()) { + any_removed = true; + } + _lambdahooks.erase(lhi); + } + return any_removed; } @@ -344,6 +387,7 @@ void EventHandler:: remove_all_hooks() { _hooks.clear(); _cbhooks.clear(); + _lambdahooks.clear(); } /** diff --git a/panda/src/event/eventHandler.h b/panda/src/event/eventHandler.h index 8e616f1581..4aa3d0924e 100644 --- a/panda/src/event/eventHandler.h +++ b/panda/src/event/eventHandler.h @@ -23,6 +23,10 @@ #include "pset.h" #include "pmap.h" +#ifndef CPPPARSER +#include +#endif + class EventQueue; /** @@ -40,6 +44,12 @@ public: typedef void EventFunction(const Event *); typedef void EventCallbackFunction(const Event *, void *); +#ifdef CPPPARSER + typedef EventFunction EventLambda; +#else + typedef std::function EventLambda; +#endif + PUBLISHED: explicit EventHandler(EventQueue *ev_queue); ~EventHandler() {} @@ -58,6 +68,7 @@ public: bool add_hook(const std::string &event_name, EventFunction *function); bool add_hook(const std::string &event_name, EventCallbackFunction *function, void *data); + void add_hook(const std::string &event_name, EventLambda function); bool has_hook(const std::string &event_name) const; bool has_hook(const std::string &event_name, EventFunction *function) const; bool has_hook(const std::string &event_name, EventCallbackFunction *function, @@ -78,10 +89,13 @@ protected: typedef std::pair CallbackFunction; typedef pset CallbackFunctions; typedef pmap CallbackHooks; + typedef pvector LambdaFunctions; + typedef pmap LambdaHooks; typedef pmap Futures; Hooks _hooks; CallbackHooks _cbhooks; + LambdaHooks _lambdahooks; Futures _futures; EventQueue &_queue; diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index c046deef8a..6c0fb681fc 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -310,6 +310,39 @@ define_key(const string &event_name, const string &description, } } +/** + * Sets up a handler for the indicated key. When the key is pressed in a + * window, the given callback will be called. The description is a one-line + * description of the function of the key, for display to the user. + */ +void PandaFramework:: +define_key(const string &event_name, const string &description, + EventHandler::EventLambda function) { + if (_event_handler.has_hook(event_name)) { + // If there is already a hook for the indicated keyname, we're most likely + // replacing a previous definition of a key. Search for the old + // definition and remove it. + KeyDefinitions::iterator di; + di = _key_definitions.begin(); + while (di != _key_definitions.end() && (*di)._event_name != event_name) { + ++di; + } + if (di != _key_definitions.end()) { + _key_definitions.erase(di); + } + } + + // Now add a new hook for the keyname, and also add the new description. + _event_handler.add_hook(event_name, function); + + if (!description.empty()) { + KeyDefinition keydef; + keydef._event_name = event_name; + keydef._description = description; + _key_definitions.push_back(keydef); + } +} + /** * Fills in the indicated window properties structure according to the normal * window properties for this application. diff --git a/panda/src/framework/pandaFramework.h b/panda/src/framework/pandaFramework.h index 3c901d8e27..18747dcfa1 100644 --- a/panda/src/framework/pandaFramework.h +++ b/panda/src/framework/pandaFramework.h @@ -56,6 +56,9 @@ public: const std::string &description, EventHandler::EventCallbackFunction *function, void *data); + void define_key(const std::string &event_name, + const std::string &description, + EventHandler::EventLambda function); INLINE void set_window_title(const std::string &title); virtual void get_default_window_props(WindowProperties &props);