1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.Window.EventHandler; 25 26 private { 27 import derelict.sdl2.types; 28 import derelict.sdl2.functions; 29 30 import Dgame.Internal.Log; 31 } 32 33 public import Dgame.Window.Event; 34 35 /** 36 * These class handles incomming events and returns outcomming events. 37 * 38 * Author: rschuett 39 */ 40 final abstract class EventHandler { 41 enum State { 42 Query = SDL_QUERY, 43 Ignore = SDL_IGNORE, 44 Disable = SDL_DISABLE, 45 Enable = SDL_ENABLE 46 } 47 48 private: 49 static bool _process(Event* event, ref const SDL_Event sdl_event) in { 50 assert(event !is null, "Null Event"); 51 } body { 52 switch (sdl_event.type) { 53 case Event.Type.KeyDown: 54 case Event.Type.KeyUp: 55 event.type = sdl_event.type == Event.Type.KeyDown ? Event.Type.KeyDown : Event.Type.KeyUp; 56 57 event.timestamp = sdl_event.key.timestamp; 58 event.windowId = sdl_event.key.windowID; 59 60 event.keyboard.code = cast(Keyboard.Code) sdl_event.key.keysym.sym; 61 event.keyboard.scancode = cast(Keyboard.ScanCode) sdl_event.key.keysym.scancode; 62 63 event.keyboard.repeat = sdl_event.key.repeat != 0; 64 event.keyboard.state = cast(Keyboard.State) sdl_event.key.state; 65 66 event.keyboard.mod = Keyboard.getModifier(); 67 68 return true; 69 case Event.Type.Window: 70 event.type = Event.Type.Window; 71 72 event.windowId = sdl_event.window.windowID; 73 event.timestamp = sdl_event.window.timestamp; 74 75 event.window.eventId = cast(WindowEventId) sdl_event.window.event; 76 77 return true; 78 case Event.Type.Quit: 79 event.type = Event.Type.Quit; 80 81 return true; 82 case Event.Type.MouseButtonDown: 83 case Event.Type.MouseButtonUp: 84 if (sdl_event.type == Event.Type.MouseButtonUp) 85 event.type = Event.Type.MouseButtonUp; 86 else 87 event.type = Event.Type.MouseButtonDown; 88 89 event.timestamp = sdl_event.button.timestamp; 90 event.windowId = sdl_event.button.windowID; 91 92 event.mouseButton.button = cast(Mouse.Button) sdl_event.button.button; 93 94 event.mouseButton.x = cast(short) sdl_event.button.x; 95 event.mouseButton.y = cast(short) sdl_event.button.y; 96 97 return true; 98 case Event.Type.MouseMotion: 99 event.type = Event.Type.MouseMotion; 100 101 event.timestamp = sdl_event.motion.timestamp; 102 event.windowId = sdl_event.motion.windowID; 103 104 if (sdl_event.button.state == SDL_PRESSED) 105 event.mouseMotion.state = Mouse.State.Pressed; 106 else 107 event.mouseMotion.state = Mouse.State.Released; 108 109 event.mouseMotion.x = cast(short) sdl_event.motion.x; 110 event.mouseMotion.y = cast(short) sdl_event.motion.y; 111 112 event.mouseMotion.rel_x = cast(short) sdl_event.motion.xrel; 113 event.mouseMotion.rel_y = cast(short) sdl_event.motion.yrel; 114 115 return true; 116 case Event.Type.MouseWheel: 117 event.type = Event.Type.MouseWheel; 118 119 event.timestamp = sdl_event.wheel.timestamp; 120 event.windowId = sdl_event.wheel.windowID; 121 122 event.mouseWheel.x = cast(short) sdl_event.wheel.x; 123 event.mouseWheel.y = cast(short) sdl_event.wheel.y; 124 125 event.mouseWheel.delta_x = cast(short) sdl_event.wheel.x; 126 event.mouseWheel.delta_y = cast(short) sdl_event.wheel.y; 127 128 return true; 129 case Event.Type.TextEdit: 130 event.type = Event.Type.TextEdit; 131 132 event.timestamp = sdl_event.edit.timestamp; 133 event.windowId = sdl_event.edit.windowID; 134 135 event.textEdit.text = sdl_event.edit.text; 136 event.textEdit.start = cast(short) sdl_event.edit.start; 137 event.textEdit.length = cast(ushort) sdl_event.edit.length; 138 139 return true; 140 case Event.Type.TextInput: 141 event.type = Event.Type.TextInput; 142 143 event.timestamp = sdl_event.text.timestamp; 144 event.windowId = sdl_event.text.windowID; 145 146 event.textInput.text = sdl_event.text.text; 147 148 return true; 149 default: 150 return false; 151 } 152 } 153 154 public: 155 /** 156 * Update the parameter event and set the data of the current event in it. 157 * 158 * Returns: true, if there was a valid event and false if not. 159 */ 160 static bool poll(Event* event) in { 161 assert(event !is null, "Null Event"); 162 } body { 163 SDL_Event sdl_event; 164 SDL_PollEvent(&sdl_event); 165 166 return EventHandler._process(event, sdl_event); 167 } 168 169 /** 170 * Push an event of the given type inside the Event queue. 171 * 172 * Returns: if the push was successfull or not. 173 */ 174 static bool push(Event.Type type) { 175 SDL_Event sdl_event; 176 sdl_event.type = type; 177 178 return SDL_PushEvent(&sdl_event) == 1; 179 } 180 181 /** 182 * Clear the Event queue. 183 */ 184 static void clear(Event.Type type) { 185 SDL_FlushEvent(type); 186 } 187 188 /** 189 * Set a state for a Event.Type. 190 * 191 * Returns: the previous type. 192 * 193 * See: State enum 194 */ 195 static State setState(Event.Type type, State state) { 196 return cast(State) SDL_EventState(type, state); 197 } 198 199 /** 200 * Returns: if inside of the Event Queue is an Event of the given type. 201 */ 202 static bool hasEvent(Event.Type type) { 203 return SDL_HasEvent(type) == SDL_TRUE; 204 } 205 206 /** 207 * Returns: if the current Event queue has the Quit Event. 208 */ 209 static bool hasQuitEvent() { 210 return SDL_QuitRequested(); 211 } 212 213 /** 214 * Waits for the given Event. 215 * If the seconds parameter is greater then -1, it waits maximal timeout seconds. 216 */ 217 static bool wait(Event* event, int timeout = -1) { 218 int result = 0; 219 SDL_Event sdl_event; 220 221 if (timeout < 0) 222 result = SDL_WaitEvent(&sdl_event); 223 else 224 result = SDL_WaitEventTimeout(&sdl_event, timeout); 225 226 EventHandler._process(event, sdl_event); 227 228 return result > 0; 229 } 230 }