1 // -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi:tw=80:et:ts=2:sts=2
3 //
4 // -----------------------------------------------------------------------
5 //
6 // This file is part of RLVM, a RealLive virtual machine clone.
7 //
8 // -----------------------------------------------------------------------
9 //
10 // Copyright (C) 2006, 2007 Elliot Glaysher
11 //
12 // This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 //
26 // -----------------------------------------------------------------------
27 
28 #include "systems/base/event_system.h"
29 
30 #include "libreallive/gameexe.h"
31 #include "machine/long_operation.h"
32 #include "machine/rlmachine.h"
33 #include "systems/base/event_listener.h"
34 #include "systems/base/frame_counter.h"
35 #include "utilities/exception.h"
36 
37 // -----------------------------------------------------------------------
38 // EventSystemGlobals
39 // -----------------------------------------------------------------------
EventSystemGlobals()40 EventSystemGlobals::EventSystemGlobals()
41     : generic1_(false), generic2_(false) {
42 }
43 
EventSystemGlobals(Gameexe & gexe)44 EventSystemGlobals::EventSystemGlobals(Gameexe& gexe)
45     : generic1_(gexe("INIT_ORIGINALSETING1_MOD").ToInt(0)),
46       generic2_(gexe("INIT_ORIGINALSETING2_MOD").ToInt(0)) {}
47 
48 // -----------------------------------------------------------------------
49 // EventSystem
50 // -----------------------------------------------------------------------
EventSystem(Gameexe & gexe)51 EventSystem::EventSystem(Gameexe& gexe) : globals_(gexe) {}
52 
~EventSystem()53 EventSystem::~EventSystem() {}
54 
GetTimer(int layer,int counter)55 RLTimer& EventSystem::GetTimer(int layer, int counter) {
56   if (layer >= 2)
57     throw rlvm::Exception("Invalid layer in EventSystem::GetTimer.");
58   if (counter >= 255)
59     throw rlvm::Exception("Invalid counter in EventSystem::GetTimer.");
60   return timers_[layer][counter];
61 }
62 
SetFrameCounter(int layer,int frame_counter,FrameCounter * counter)63 void EventSystem::SetFrameCounter(int layer,
64                                   int frame_counter,
65                                   FrameCounter* counter) {
66   CheckLayerAndCounter(layer, frame_counter);
67   frame_counters_[layer][frame_counter].reset(counter);
68 }
69 
GetFrameCounter(int layer,int frame_counter)70 FrameCounter& EventSystem::GetFrameCounter(int layer, int frame_counter) {
71   CheckLayerAndCounter(layer, frame_counter);
72 
73   std::unique_ptr<FrameCounter>& counter =
74       frame_counters_[layer][frame_counter];
75   if (counter.get() == NULL)
76     throw rlvm::Exception("Trying to get an uninitialized frame counter!");
77 
78   return *counter;
79 }
80 
FrameCounterExists(int layer,int frame_counter)81 bool EventSystem::FrameCounterExists(int layer, int frame_counter) {
82   CheckLayerAndCounter(layer, frame_counter);
83   std::unique_ptr<FrameCounter>& counter =
84       frame_counters_[layer][frame_counter];
85   return counter.get() != NULL;
86 }
87 
AddMouseListener(EventListener * listener)88 void EventSystem::AddMouseListener(EventListener* listener) {
89   event_listeners_.insert(listener);
90 }
91 
RemoveMouseListener(EventListener * listener)92 void EventSystem::RemoveMouseListener(EventListener* listener) {
93   event_listeners_.erase(listener);
94 }
95 
DispatchEvent(RLMachine & machine,const std::function<bool (EventListener &)> & event)96 void EventSystem::DispatchEvent(
97     RLMachine& machine,
98     const std::function<bool(EventListener&)>& event) {
99   // In addition to the handled variable, we need to add break statements to
100   // the loops since |event| can be any arbitrary code and may modify listeners
101   // or handlers. (i.e., System::showSyscomMenu)
102   bool handled = false;
103 
104   // Give the mostly passive listeners first shot at handling this event
105   EventListeners::iterator listenerIt = listeners_begin();
106   for (; !handled && listenerIt != listeners_end(); ++listenerIt) {
107     if (event(**listenerIt)) {
108       handled = true;
109       break;
110     }
111   }
112 
113   // Try to pass the event on to the top of the call stack.
114   std::shared_ptr<LongOperation> current_op = machine.CurrentLongOperation();
115   if (current_op)
116     event(*current_op);
117 }
118 
BroadcastEvent(RLMachine & machine,const std::function<void (EventListener &)> & event)119 void EventSystem::BroadcastEvent(
120     RLMachine& machine,
121     const std::function<void(EventListener&)>& event) {
122   for (EventListener* listener : event_listeners_)
123     event(*listener);
124 
125   std::shared_ptr<LongOperation> current_op = machine.CurrentLongOperation();
126   if (current_op)
127     event(*current_op);
128 }
129 
CheckLayerAndCounter(int layer,int frame_counter)130 void EventSystem::CheckLayerAndCounter(int layer, int frame_counter) {
131   if (layer < 0 || layer > 1)
132     throw rlvm::Exception("Illegal frame counter layer!");
133 
134   if (frame_counter < 0 || frame_counter > 255)
135     throw rlvm::Exception("Frame Counter index out of range!");
136 }
137