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 #ifndef SRC_SYSTEMS_BASE_EVENT_SYSTEM_H_ 29 #define SRC_SYSTEMS_BASE_EVENT_SYSTEM_H_ 30 31 #include <functional> 32 #include <memory> 33 #include <queue> 34 #include <set> 35 36 #include "systems/base/rltimer.h" 37 #include "systems/base/rect.h" 38 39 class RLMachine; 40 41 class Gameexe; 42 class FrameCounter; 43 class EventListener; 44 45 // ----------------------------------------------------------------------- 46 47 struct EventSystemGlobals { 48 EventSystemGlobals(); 49 explicit EventSystemGlobals(Gameexe& gexe); 50 51 // The two generic values that the reallive game has control over 52 // with the Generic1 and Generic2 functions. 53 int generic1_; 54 int generic2_; 55 56 // boost::serialization support 57 template <class Archive> serializeEventSystemGlobals58 void serialize(Archive& ar, const unsigned int version) { 59 ar& generic1_ & generic2_; 60 } 61 }; 62 63 // ----------------------------------------------------------------------- 64 65 // Generalization of an event system. Reallive's event model is a bit 66 // weird; interpreted code will check the state of certain keyboard 67 // modifiers, with functions such as CtrlPressed() or ShiftPressed(). 68 // 69 // So what's the solution? Have two different event systems side by 70 // side. One is exposed to Reallive and mimics what RealLive bytecode 71 // expects. The other is based on event handlers and is sane. 72 class EventSystem { 73 public: 74 explicit EventSystem(Gameexe& gexe); 75 virtual ~EventSystem(); 76 globals()77 EventSystemGlobals& globals() { return globals_; } 78 79 RLTimer& GetTimer(int layer, int counter); 80 81 // Frame Counters 82 // 83 // "Frame counters are designed to make it simple to ensure events happen at a 84 // constant speed regardless of the host system's specifications. Once a frame 85 // counter has been initialized, it will count from one arbitrary number to 86 // another, over a given length of time. The counter can be queried at any 87 // point to get its current value." 88 // 89 // Valid values for layer are 0 and 1. Valid values for frame_counter are 0 90 // through 255. 91 void SetFrameCounter(int layer, int frame_counter, FrameCounter* counter); 92 FrameCounter& GetFrameCounter(int layer, int frame_counter); 93 bool FrameCounterExists(int layer, int frame_counter); 94 95 // Keyboard and Mouse Input (Event Listener style) 96 // 97 // rlvm event handling works by registering objects that received input 98 // notifications from the EventSystem. These objects are EventListeners, 99 // which passively listen for input and have a first chance grab at any click 100 // or keypress. 101 // 102 // If no EventListener claims the event, then we try to reinterpret the top 103 // of the RLMachine callstack as an EventListener. Otherwise, the events 104 // are handled RealLive style (see below). 105 void AddMouseListener(EventListener* listener); 106 void RemoveMouseListener(EventListener* listener); 107 108 // Generic values 109 // 110 // These values should have, from the beginning, been placed somewhere 111 // else. They will remain here till the end of time for save game file 112 // compatibility, though. 113 // 114 // "RealLive provides two generic settings to permit games using the standard 115 // system command menu to include custom options in it. The meaning of each 116 // generic flag is left up to the programmer. Valid values are 0 to 4." set_generic1(const int in)117 void set_generic1(const int in) { globals_.generic1_ = in; } generic1()118 int generic1() const { return globals_.generic1_; } set_generic2(const int in)119 void set_generic2(const int in) { globals_.generic2_ = in; } generic2()120 int generic2() const { return globals_.generic2_; } 121 122 // Run once per cycle through the game loop to process events. 123 virtual void ExecuteEventSystem(RLMachine& machine) = 0; 124 125 // Returns the number of milliseconds since the program 126 // started. Used for timing things. 127 virtual unsigned int GetTicks() const = 0; 128 129 // Idles the program for a certain amount of time in milliseconds. 130 virtual void Wait(unsigned int milliseconds) const = 0; 131 132 // Keyboard and Mouse Input (Reallive style) 133 // 134 // RealLive applications poll for input, with all the problems that sort of 135 // event handling has. We therefore provide an interface for polling. 136 // 137 // Don't use it. This interface is provided for RealLive 138 // bytecode. EventListeners should be used within rlvm code, instead. 139 140 // Returns whether shift is currently pressed. 141 virtual bool ShiftPressed() const = 0; 142 143 // Returns whether ctrl has been pressed since the last invocation of 144 // ctrlPresesd(). 145 virtual bool CtrlPressed() const = 0; 146 147 // Returns the current cursor hotspot. 148 virtual Point GetCursorPos() = 0; 149 150 // Gets the location of the mouse cursor and the button states. 151 // 152 // The following values are used to indicate a button's status: 153 // - 0 if unpressed 154 // - 1 if being pressed 155 // - 2 if pressed and released. 156 virtual void GetCursorPos(Point& position, int& button1, int& button2) = 0; 157 158 // Resets the state of the mouse buttons. 159 virtual void FlushMouseClicks() = 0; 160 161 // Returns the time in ticks of the last mouse movement. 162 virtual unsigned int TimeOfLastMouseMove() = 0; 163 164 // Testing 165 // 166 // Allows test systems like lua_rlvm to inject mouse movement and clicks. 167 virtual void InjectMouseMovement(RLMachine& machine, const Point& loc) = 0; 168 virtual void InjectMouseDown(RLMachine& machine) = 0; 169 virtual void InjectMouseUp(RLMachine& machine) = 0; 170 171 protected: 172 typedef std::set<EventListener*> EventListeners; 173 listeners_begin()174 EventListeners::iterator listeners_begin() { 175 return event_listeners_.begin(); 176 } listeners_end()177 EventListeners::iterator listeners_end() { return event_listeners_.end(); } 178 179 // Calls a EventListener member function on all event listeners, and then 180 // event handlers, stopping when an object says they handled it. 181 void DispatchEvent(RLMachine& machine, 182 const std::function<bool(EventListener&)>& event); 183 void BroadcastEvent(RLMachine& machine, 184 const std::function<void(EventListener&)>& event); 185 186 private: 187 // Helper function that verifies input 188 void CheckLayerAndCounter(int layer, int counter); 189 190 std::unique_ptr<FrameCounter> frame_counters_[255][2]; 191 RLTimer timers_[255][2]; 192 193 EventListeners event_listeners_; 194 195 EventSystemGlobals globals_; 196 }; 197 198 #endif // SRC_SYSTEMS_BASE_EVENT_SYSTEM_H_ 199