| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- //========================================================================
- // EventManagerImpl.cpp : implementation side of the event system
- //
- // Part of the GameCode4 Application
- //
- // GameCode4 is the sample application that encapsulates much of the source code
- // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
- // "Rez" Graham, published by Charles River Media.
- // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
- //
- // If this source code has found it's way to you, and you think it has helped you
- // in any way, do the authors a favor and buy a new copy of the book - there are
- // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
- // by clicking here:
- // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
- //
- // There's a companion web site at http://www.mcshaffry.com/GameCode/
- //
- // The source code is managed and maintained through Google Code:
- // http://code.google.com/p/gamecode4/
- //
- // (c) Copyright 2012 Michael L. McShaffry and David Graham
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU Lesser GPL v3
- // as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
- //
- // You should have received a copy of the GNU Lesser GPL v3
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- //
- //========================================================================
- #include "../Unix/GameCodeStd.h"
- #include "EventManagerImpl.h"
- #include "../Utilities/String.h"
- #include <SDL3/SDL.h>
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::EventManager
- //---------------------------------------------------------------------------------------------------------------------
- EventManager::EventManager(const char* pName, bool setAsGlobal)
- : IEventManager(pName, setAsGlobal)
- {
- m_activeQueue = 0;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::~EventManager
- //---------------------------------------------------------------------------------------------------------------------
- EventManager::~EventManager()
- {
- //
- }
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::VAddListener
- //---------------------------------------------------------------------------------------------------------------------
- bool EventManager::VAddListener(const EventListenerDelegate& eventDelegate, const EventType& type)
- {
- GCC_LOG("Events", "Attempting to add delegate function for event type: " + ToStr(type, 16));
- EventListenerList& eventListenerList = m_eventListeners[type]; // this will find or create the entry;
- for (auto it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
- {
- if (eventDelegate == (*it))
- {
- GCC_WARNING("Attempting to double-register a delegate");
- return false;
- }
- }
- eventListenerList.push_back(eventDelegate);
- GCC_LOG("Events", "Successfully added delegate for event type: " + ToStr(type, 16));
- return true;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::VRemoveListener
- //---------------------------------------------------------------------------------------------------------------------
- bool EventManager::VRemoveListener(const EventListenerDelegate& eventDelegate, const EventType& type)
- {
- GCC_LOG("Events", "Attempting to remove delegate function from event type: " + ToStr(type, 16));
- bool success = false;
- auto findIt = m_eventListeners.find(type);
- if (findIt != m_eventListeners.end())
- {
- EventListenerList& listeners = findIt->second;
- for (auto it = listeners.begin(); it != listeners.end(); ++it)
- {
- if (eventDelegate == (*it))
- {
- listeners.erase(it);
- GCC_LOG("Events", "Successfully removed delegate function from event type: " + ToStr(type, 16));
- success = true;
- break; // we don't need to continue because it should be impossible for the same delegate function to be registered for the same event more than once
- }
- }
- }
- return success;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::VTrigger
- //---------------------------------------------------------------------------------------------------------------------
- bool EventManager::VTriggerEvent(const IEventDataPtr& pEvent) const
- {
- GCC_LOG("Events", "Attempting to trigger event " + std::string(pEvent->GetName()));
- bool processed = false;
- auto findIt = m_eventListeners.find(pEvent->VGetEventType());
- if (findIt != m_eventListeners.end())
- {
- const EventListenerList& eventListenerList = findIt->second;
- for (EventListenerList::const_iterator it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
- {
- EventListenerDelegate listener = (*it);
- GCC_LOG("Events", "Sending Event " + std::string(pEvent->GetName()) + " to delegate.");
- listener(pEvent); // call the delegate
- processed = true;
- }
- }
- return processed;
- }
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::VQueueEvent
- //---------------------------------------------------------------------------------------------------------------------
- bool EventManager::VQueueEvent(const IEventDataPtr& pEvent)
- {
- GCC_ASSERT(m_activeQueue >= 0);
- GCC_ASSERT(m_activeQueue < EVENTMANAGER_NUM_QUEUES);
- // make sure the event is valid
- if (!pEvent)
- {
- GCC_ERROR("Invalid event in VQueueEvent()");
- return false;
- }
- GCC_LOG("Events", "Attempting to queue event: " + std::string(pEvent->GetName()));
- auto findIt = m_eventListeners.find(pEvent->VGetEventType());
- if (findIt != m_eventListeners.end())
- {
- m_queues[m_activeQueue].push_back(pEvent);
- GCC_LOG("Events", "Successfully queued event: " + std::string(pEvent->GetName()));
- return true;
- }
- else
- {
- GCC_LOG("Events", "Skipping event since there are no delegates registered to receive it: " + std::string(pEvent->GetName()));
- return false;
- }
- }
- //---------------------------------------------------------------------------------------------------------------------
- // EventManager::VTick
- //---------------------------------------------------------------------------------------------------------------------
- bool EventManager::VUpdate(unsigned long maxMillis)
- {
- unsigned long currMs = SDL_GetTicks();
- unsigned long maxMs = ((maxMillis == IEventManager::kINFINITE) ? (IEventManager::kINFINITE) : (currMs + maxMillis));
- // This section added to handle events from other threads. Check out Chapter 20.
- // IEventDataPtr pRealtimeEvent;
- // while (m_realtimeEventQueue.try_pop(pRealtimeEvent))
- // {
- // VQueueEvent(pRealtimeEvent);
- // currMs = SDL_GetTicks();
- // if (maxMillis != IEventManager::kInfinite)
- // {
- // if (currMs >= maxMs)
- // {
- // GCC_ERROR("A realtime process is spamming the event manager");
- // }
- // }
- // }
- // swap active queues and clear the new queue after the swap
- int queueToProcess = m_activeQueue;
- m_activeQueue = (m_activeQueue + 1) % EVENTMANAGER_NUM_QUEUES;
- m_queues[m_activeQueue].clear();
- GCC_LOG("EventLoop", "Processing Event Queue " + ToStr(queueToProcess) + "; " + ToStr((unsigned long)m_queues[queueToProcess].size()) + " events to process");
- // process the queue
- while (!m_queues[queueToProcess].empty())
- {
- // pop the front of the queue
- IEventDataPtr pEvent = m_queues[queueToProcess].front();
- m_queues[queueToProcess].pop_front();
- GCC_LOG("EventLoop", "\t\tProcessing Event " + std::string(pEvent->GetName()));
- const EventType& eventType = pEvent->VGetEventType();
- // find all the delegate functions registered for this event
- auto findIt = m_eventListeners.find(eventType);
- if (findIt != m_eventListeners.end())
- {
- const EventListenerList& eventListeners = findIt->second;
- GCC_LOG("EventLoop", "\t\tFound " + ToStr((unsigned long)eventListeners.size()) + " delegates");
- // call each listener
- for (auto it = eventListeners.begin(); it != eventListeners.end(); ++it)
- {
- EventListenerDelegate listener = (*it);
- GCC_LOG("EventLoop", "\t\tSending event " + std::string(pEvent->GetName()) + " to delegate");
- listener(pEvent);
- }
- }
- // check to see if time ran out
- currMs = SDL_GetTicks();
- if (maxMillis != IEventManager::kINFINITE && currMs >= maxMs)
- {
- GCC_LOG("EventLoop", "Aborting event processing; time ran out");
- break;
- }
- }
- // If we couldn't process all of the events, push the remaining events to the new active queue.
- // Note: To preserve sequencing, go back-to-front inserting them at the head of the active queue
- bool queueFlushed = (m_queues[queueToProcess].empty());
- if (!queueFlushed)
- {
- while (!m_queues[queueToProcess].empty())
- {
- IEventDataPtr pEvent = m_queues[queueToProcess].back();
- m_queues[queueToProcess].pop_back();
- m_queues[m_activeQueue].push_front(pEvent);
- }
- }
- return queueFlushed;
- }
|