open_toontown_panda3d/panda/src/event/eventHandler.cxx

343 lines
11 KiB
C++

// Filename: eventHandler.cxx
// Created by: drose (08Feb99)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "eventHandler.h"
#include "eventQueue.h"
#include "config_event.h"
TypeHandle EventHandler::_type_handle;
EventHandler *EventHandler::_global_event_handler = 0;
////////////////////////////////////////////////////////////////////
// Function: EventHandler::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EventHandler::
EventHandler(EventQueue *ev_queue) : _queue(*ev_queue) {
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::process_events
// Access: Public
// Description: The main processing loop of the EventHandler. This
// function must be called periodically to service
// events. Walks through each pending event and calls
// its assigned hooks.
////////////////////////////////////////////////////////////////////
void EventHandler::
process_events() {
while (!_queue.is_queue_empty()) {
dispatch_event(_queue.dequeue_event());
}
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::dispatch_event
// Access: Public, Virtual
// Description: Calls the hooks assigned to the indicated single
// event.
////////////////////////////////////////////////////////////////////
void EventHandler::
dispatch_event(const Event *event) {
nassertv(event != (Event *)NULL);
// Is the event name defined in the hook table? It will be if
// anyone has ever assigned a hook to this particular event name.
Hooks::const_iterator hi;
hi = _hooks.find(event->get_name());
if (hi != _hooks.end()) {
// Yes, it is! Now walk through all the functions assigned to
// that event name.
Functions copy_functions = (*hi).second;
Functions::const_iterator fi;
for (fi = copy_functions.begin(); fi != copy_functions.end(); ++fi) {
if (event_cat.is_spam()) {
event_cat->spam()
<< "calling callback 0x" << (void*)(*fi)
<< " for event '" << event->get_name() << "'"
<< endl;
}
(*fi)(event);
}
}
// now for callback hooks
CallbackHooks::const_iterator chi;
chi = _cbhooks.find(event->get_name());
if (chi != _cbhooks.end()) {
// found one
CallbackFunctions copy_functions = (*chi).second;
CallbackFunctions::const_iterator cfi;
for (cfi = copy_functions.begin(); cfi != copy_functions.end(); ++cfi) {
((*cfi).first)(event, (*cfi).second);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::write
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void EventHandler::
write(ostream &out) const {
Hooks::const_iterator hi;
hi = _hooks.begin();
CallbackHooks::const_iterator chi;
chi = _cbhooks.begin();
while (hi != _hooks.end() && chi != _cbhooks.end()) {
if ((*hi).first < (*chi).first) {
write_hook(out, *hi);
++hi;
} else if ((*chi).first < (*hi).first) {
write_cbhook(out, *chi);
++chi;
} else {
write_hook(out, *hi);
write_cbhook(out, *chi);
++hi;
++chi;
}
}
while (hi != _hooks.end()) {
write_hook(out, *hi);
++hi;
}
while (chi != _cbhooks.end()) {
write_cbhook(out, *chi);
++chi;
}
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::add_hook
// Access: Public
// Description: 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.
////////////////////////////////////////////////////////////////////
bool EventHandler::
add_hook(const string &event_name, EventFunction *function) {
if (event_cat.is_debug()) {
event_cat.debug()
<< "adding hook for event '" << event_name
<< "' with function 0x" << (void*)function << endl;
}
assert(!event_name.empty());
assert(function);
return _hooks[event_name].insert(function).second;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::add_hook
// Access: Public
// Description: 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 records an untyped pointer
// to user callback data.
////////////////////////////////////////////////////////////////////
bool EventHandler::
add_hook(const string &event_name, EventCallbackFunction *function,
void *data) {
assert(!event_name.empty());
assert(function);
return _cbhooks[event_name].insert(CallbackFunction(function, data)).second;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::has_hook
// Access: Public
// Description: Returns true if there is any hook added on the
// indicated event name, false otherwise.
////////////////////////////////////////////////////////////////////
bool EventHandler::
has_hook(const string &event_name) const {
assert(!event_name.empty());
Hooks::const_iterator hi;
hi = _hooks.find(event_name);
if (hi != _hooks.end()) {
if (!(*hi).second.empty()) {
return true;
}
}
CallbackHooks::const_iterator chi;
chi = _cbhooks.find(event_name);
if (chi != _cbhooks.end()) {
if (!(*chi).second.empty()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::remove_hook
// Access: Public
// Description: Removes the indicated function from the named event
// hook. Returns true if the hook was removed, false if
// it wasn't there in the first place.
////////////////////////////////////////////////////////////////////
bool EventHandler::
remove_hook(const string &event_name, EventFunction *function) {
assert(!event_name.empty());
assert(function);
return _hooks[event_name].erase(function) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::remove_hook
// Access: Public
// Description: Removes the indicated function from the named event
// hook. Returns true if the hook was removed, false if
// it wasn't there in the first place. This version
// takes an untyped pointer to user callback data.
////////////////////////////////////////////////////////////////////
bool EventHandler::
remove_hook(const string &event_name, EventCallbackFunction *function,
void *data) {
assert(!event_name.empty());
assert(function);
return _cbhooks[event_name].erase(CallbackFunction(function, data)) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::remove_hooks
// Access: Public
// Description: Removes all functions from the named event hook.
// Returns true if any functions were removed, false if
// there were no functions added to the hook.
////////////////////////////////////////////////////////////////////
bool EventHandler::
remove_hooks(const string &event_name) {
assert(!event_name.empty());
bool any_removed = false;
Hooks::iterator hi = _hooks.find(event_name);
if (hi != _hooks.end()) {
if (!(*hi).second.empty()) {
any_removed = true;
}
_hooks.erase(hi);
}
CallbackHooks::iterator chi = _cbhooks.find(event_name);
if (chi != _cbhooks.end()) {
if (!(*chi).second.empty()) {
any_removed = true;
}
_cbhooks.erase(chi);
}
return any_removed;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::remove_hooks_with
// Access: Public
// Description: Removes all CallbackFunction hooks that have the
// indicated pointer as the associated data pointer.
////////////////////////////////////////////////////////////////////
bool EventHandler::
remove_hooks_with(void *data) {
bool any_removed = false;
CallbackHooks::iterator chi;
for (chi = _cbhooks.begin(); chi != _cbhooks.end(); ++chi) {
CallbackFunctions &funcs = (*chi).second;
CallbackFunctions::iterator cfi;
CallbackFunctions new_funcs;
for (cfi = funcs.begin(); cfi != funcs.end(); ++cfi) {
if ((*cfi).second == data) {
any_removed = true;
} else {
new_funcs.insert(*cfi);
}
}
funcs.swap(new_funcs);
}
return any_removed;
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::remove_all_hooks
// Access: Public
// Description: Removes all hooks assigned to all events.
////////////////////////////////////////////////////////////////////
void EventHandler::
remove_all_hooks() {
_hooks.clear();
_cbhooks.clear();
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::make_global_event_handler
// Access: Protected, Static
// Description:
////////////////////////////////////////////////////////////////////
void EventHandler::
make_global_event_handler() {
_global_event_handler = new EventHandler(EventQueue::get_global_event_queue());
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::write_hook
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void EventHandler::
write_hook(ostream &out, const EventHandler::Hooks::value_type &hook) const {
if (!hook.second.empty()) {
out << hook.first << " has " << hook.second.size() << " functions.\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: EventHandler::write_cbhook
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void EventHandler::
write_cbhook(ostream &out, const EventHandler::CallbackHooks::value_type &hook) const {
if (!hook.second.empty()) {
out << hook.first << " has " << hook.second.size() << " callback functions.\n";
}
}