00001 // 00002 // $Id: event_map.cpp 2 2008-03-01 20:58:50Z kulibali $ 00003 // 00004 // Copyright (c) 2008, The Periapsis Project. All rights reserved. 00005 // 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are 00008 // met: 00009 // 00010 // * Redistributions of source code must retain the above copyright notice, 00011 // this list of conditions and the following disclaimer. 00012 // 00013 // * Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // * Neither the name of the The Periapsis Project nor the names of its 00018 // contributors may be used to endorse or promote products derived from 00019 // this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00022 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00023 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00024 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00025 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00027 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00033 00034 #include "scenegraph/event_map.hpp" 00035 #include "scenegraph/event.hpp" 00036 #include "scenegraph/simulation.hpp" 00037 00038 #include "data/exception.hpp" 00039 #include "data/string.hpp" 00040 #include "data/config.hpp" 00041 #include "framework/application.hpp" 00042 00043 #include "platform/lowlevel.hpp" 00044 00045 // 00046 00047 #define SG_EVENT(name) sg_event_codes[L#name] = scenegraph::sg_event::name 00048 00049 #define SDL_EVENT(name) sdl_event_codes[L#name] = SDLK_##name 00050 00051 // 00052 00053 namespace gsgl 00054 { 00055 00056 using namespace data; 00057 00058 scenegraph::event_map *scenegraph::event_map::instance = 0; 00059 00060 00061 namespace scenegraph 00062 { 00063 00064 static data::dictionary<int, string> sg_event_codes; 00065 static data::dictionary<int, string> sdl_event_codes; 00066 00067 00068 static void init_dictionaries() 00069 { 00070 // scenegraph event codes 00071 SG_EVENT(SIM_QUIT); 00072 00073 SG_EVENT(VIEW_ROT_X_POS); 00074 SG_EVENT(VIEW_ROT_X_NEG); 00075 SG_EVENT(VIEW_ROT_Y_POS); 00076 SG_EVENT(VIEW_ROT_Y_NEG); 00077 SG_EVENT(VIEW_ROT_Z_POS); 00078 SG_EVENT(VIEW_ROT_Z_NEG); 00079 SG_EVENT(VIEW_TOGGLE_ROT_MODE); 00080 SG_EVENT(VIEW_ZOOM_IN); 00081 SG_EVENT(VIEW_ZOOM_OUT); 00082 SG_EVENT(VIEW_RESET); 00083 00084 SG_EVENT(TIME_INC_SCALE); 00085 SG_EVENT(TIME_DEC_SCALE); 00086 SG_EVENT(TIME_RESET_SCALE); 00087 SG_EVENT(TIME_PAUSE); 00088 00089 SG_EVENT(RENDER_TOGGLE_LABELS); 00090 SG_EVENT(RENDER_TOGGLE_COORD_SYSTEMS); 00091 00092 // SDL event codes 00093 00094 SDL_EVENT(BACKSPACE); 00095 SDL_EVENT(TAB); 00096 SDL_EVENT(CLEAR); 00097 SDL_EVENT(RETURN); 00098 SDL_EVENT(PAUSE); 00099 SDL_EVENT(ESCAPE); 00100 SDL_EVENT(SPACE); 00101 SDL_EVENT(EXCLAIM); 00102 SDL_EVENT(QUOTEDBL); 00103 SDL_EVENT(HASH); 00104 SDL_EVENT(DOLLAR); 00105 SDL_EVENT(AMPERSAND); 00106 SDL_EVENT(QUOTE); 00107 SDL_EVENT(LEFTPAREN); 00108 SDL_EVENT(RIGHTPAREN); 00109 SDL_EVENT(ASTERISK); 00110 SDL_EVENT(PLUS); 00111 SDL_EVENT(COMMA); 00112 SDL_EVENT(MINUS); 00113 SDL_EVENT(PERIOD); 00114 SDL_EVENT(SLASH); 00115 SDL_EVENT(0); 00116 SDL_EVENT(1); 00117 SDL_EVENT(2); 00118 SDL_EVENT(3); 00119 SDL_EVENT(4); 00120 SDL_EVENT(5); 00121 SDL_EVENT(6); 00122 SDL_EVENT(7); 00123 SDL_EVENT(8); 00124 SDL_EVENT(9); 00125 SDL_EVENT(COLON); 00126 SDL_EVENT(SEMICOLON); 00127 SDL_EVENT(LESS); 00128 SDL_EVENT(EQUALS); 00129 SDL_EVENT(GREATER); 00130 SDL_EVENT(QUESTION); 00131 SDL_EVENT(AT); 00132 SDL_EVENT(LEFTBRACKET); 00133 SDL_EVENT(BACKSLASH); 00134 SDL_EVENT(RIGHTBRACKET); 00135 SDL_EVENT(CARET); 00136 SDL_EVENT(UNDERSCORE); 00137 SDL_EVENT(BACKQUOTE); 00138 SDL_EVENT(a); 00139 SDL_EVENT(b); 00140 SDL_EVENT(c); 00141 SDL_EVENT(d); 00142 SDL_EVENT(e); 00143 SDL_EVENT(f); 00144 SDL_EVENT(g); 00145 SDL_EVENT(h); 00146 SDL_EVENT(i); 00147 SDL_EVENT(j); 00148 SDL_EVENT(k); 00149 SDL_EVENT(l); 00150 SDL_EVENT(m); 00151 SDL_EVENT(n); 00152 SDL_EVENT(o); 00153 SDL_EVENT(p); 00154 SDL_EVENT(q); 00155 SDL_EVENT(r); 00156 SDL_EVENT(s); 00157 SDL_EVENT(t); 00158 SDL_EVENT(u); 00159 SDL_EVENT(v); 00160 SDL_EVENT(w); 00161 SDL_EVENT(x); 00162 SDL_EVENT(y); 00163 SDL_EVENT(z); 00164 SDL_EVENT(DELETE); 00165 SDL_EVENT(KP0); 00166 SDL_EVENT(KP1); 00167 SDL_EVENT(KP2); 00168 SDL_EVENT(KP3); 00169 SDL_EVENT(KP4); 00170 SDL_EVENT(KP5); 00171 SDL_EVENT(KP6); 00172 SDL_EVENT(KP7); 00173 SDL_EVENT(KP8); 00174 SDL_EVENT(KP9); 00175 SDL_EVENT(KP_PERIOD); 00176 SDL_EVENT(KP_DIVIDE); 00177 SDL_EVENT(KP_MULTIPLY); 00178 SDL_EVENT(KP_MINUS); 00179 SDL_EVENT(KP_PLUS); 00180 SDL_EVENT(KP_ENTER); 00181 SDL_EVENT(KP_EQUALS); 00182 SDL_EVENT(UP); 00183 SDL_EVENT(DOWN); 00184 SDL_EVENT(RIGHT); 00185 SDL_EVENT(LEFT); 00186 SDL_EVENT(INSERT); 00187 SDL_EVENT(HOME); 00188 SDL_EVENT(END); 00189 SDL_EVENT(PAGEUP); 00190 SDL_EVENT(PAGEDOWN); 00191 SDL_EVENT(F1); 00192 SDL_EVENT(F2); 00193 SDL_EVENT(F3); 00194 SDL_EVENT(F4); 00195 SDL_EVENT(F5); 00196 SDL_EVENT(F6); 00197 SDL_EVENT(F7); 00198 SDL_EVENT(F8); 00199 SDL_EVENT(F9); 00200 SDL_EVENT(F10); 00201 SDL_EVENT(F11); 00202 SDL_EVENT(F12); 00203 SDL_EVENT(F13); 00204 SDL_EVENT(F14); 00205 SDL_EVENT(F15); 00206 SDL_EVENT(NUMLOCK); 00207 SDL_EVENT(CAPSLOCK); 00208 SDL_EVENT(SCROLLOCK); 00209 SDL_EVENT(RSHIFT); 00210 SDL_EVENT(LSHIFT); 00211 SDL_EVENT(RCTRL); 00212 SDL_EVENT(LCTRL); 00213 SDL_EVENT(RALT); 00214 SDL_EVENT(LALT); 00215 SDL_EVENT(RMETA); 00216 SDL_EVENT(LMETA); 00217 SDL_EVENT(LSUPER); 00218 SDL_EVENT(RSUPER); 00219 SDL_EVENT(MODE); 00220 SDL_EVENT(COMPOSE); 00221 SDL_EVENT(HELP); 00222 SDL_EVENT(PRINT); 00223 SDL_EVENT(SYSREQ); 00224 SDL_EVENT(BREAK); 00225 SDL_EVENT(MENU); 00226 SDL_EVENT(POWER); 00227 SDL_EVENT(EURO); 00228 SDL_EVENT(UNDO); 00229 } // init_dictionaries() 00230 00231 // 00232 00233 event_map::event_map(const string & fname) 00234 : scenegraph_object(), data::singleton<event_map>() 00235 { 00236 init_dictionaries(); 00237 load_events(fname); 00238 } // event_map::event_map() 00239 00240 event_map::~event_map() 00241 { 00242 } // event_map::~event_map() 00243 00244 // 00245 00246 bool event_map::handle_event(const SDL_Event & e, simulation *sim) 00247 { 00248 scenegraph::sg_event sge; 00249 00250 switch (e.type) 00251 { 00252 case SDL_KEYDOWN: 00253 { 00254 SDLKey sdlsym = e.key.keysym.sym; 00255 SDLMod sdlmod = e.key.keysym.mod; 00256 00257 int mod = 0; 00258 if (sdlmod & KMOD_CTRL) 00259 mod |= CTRL_MODIFIER; 00260 if (sdlmod & KMOD_ALT) 00261 mod |= ALT_MODIFIER; 00262 if (sdlmod & KMOD_SHIFT) 00263 mod |= SHIFT_MODIFIER; 00264 00265 sge.get_code() = static_cast<scenegraph::sg_event::event_code>(key_events[sdlsym][mod]); 00266 break; 00267 } 00268 default: 00269 break; 00270 } 00271 00272 if (sge.get_code()) 00273 { 00274 return sim->handle_event(sge); 00275 } 00276 00277 return false; 00278 } // event_map::handle_event() 00279 00280 00281 00282 void event_map::load_events(const string & fname) 00283 { 00284 config_record conf(fname); 00285 00286 if (conf.get_name() != L"event_map") 00287 throw runtime_exception(L"Invalid event map configuration format."); 00288 00289 for (list<config_record>::iterator child = conf.get_children().iter(); child.is_valid(); ++child) 00290 { 00291 if (child->get_name() == L"keyboard") 00292 { 00293 load_keyboard_events(*child); 00294 } 00295 else 00296 { 00297 throw runtime_exception(L"Unknown event map section type '%ls'.", child->get_name().w_string()); 00298 } 00299 } 00300 } // event_map::load_events() 00301 00302 00303 void event_map::load_keyboard_events(config_record & keyboard_conf) 00304 { 00305 for (list<config_record>::iterator child = keyboard_conf.get_children().iter(); child.is_valid(); ++child) 00306 { 00307 if (child->get_name() == L"event") 00308 { 00309 string name = child->get_attribute(L"name"); 00310 string key = child->get_attribute(L"key"); 00311 00312 if (!name.is_empty() && !key.is_empty()) 00313 { 00314 scenegraph::sg_event::event_code code = static_cast<scenegraph::sg_event::event_code>(sg_event_codes[name]); 00315 00316 if (!code) 00317 throw runtime_exception(L"Unknown event code '%ls'", name.w_string()); 00318 00319 int modifiers = 0; 00320 00321 string sdlsim = key; 00322 sdlsim.trim(); 00323 while (sdlsim.size()) 00324 { 00325 if (sdlsim.left_substring(5) == L"CTRL_") 00326 { 00327 modifiers |= CTRL_MODIFIER; 00328 sdlsim = sdlsim.substring(5); 00329 continue; 00330 } 00331 00332 if (sdlsim.left_substring(4) == L"ALT_") 00333 { 00334 modifiers |= ALT_MODIFIER; 00335 sdlsim = sdlsim.substring(4); 00336 continue; 00337 } 00338 00339 if (sdlsim.left_substring(6) == L"SHIFT_") 00340 { 00341 modifiers |= SHIFT_MODIFIER; 00342 sdlsim = sdlsim.substring(6); 00343 continue; 00344 } 00345 00346 if (sdl_event_codes.contains_index(sdlsim)) 00347 { 00348 int keysim = sdl_event_codes[sdlsim]; 00349 key_events[keysim][modifiers] = code; 00350 break; 00351 } 00352 else 00353 { 00354 throw runtime_exception(L"Unknown keyboard code '%ls'", key.w_string()); 00355 } 00356 } 00357 00358 } 00359 else 00360 { 00361 throw runtime_exception(L"Invalid keyboard event specified."); 00362 } 00363 } 00364 } 00365 } // event_map::load_keyboard_events() 00366 00367 00368 } // namespace scenegraph 00369 00370 } // namespace gsgl