1 /* _______ __ __ __ ______ __ __ _______ __ __ 2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 8 * 9 * Copyright (c) 2004 - 2008 Olof Naess�n and Per Larsson 10 * 11 * 12 * Per Larsson a.k.a finalman 13 * Olof Naess�n a.k.a jansem/yakslem 14 * 15 * Visit: http://guichan.sourceforge.net 16 * 17 * License: (BSD) 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in 25 * the documentation and/or other materials provided with the 26 * distribution. 27 * 3. Neither the name of Guichan nor the names of its contributors may 28 * be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 37 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 39 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 /* 45 * For comments regarding functions please see the header file. 46 */ 47 48 #include "guichan/allegro/allegroinput.hpp" 49 50 #include <allegro.h> 51 52 #include "guichan/exception.hpp" 53 54 namespace gcn 55 { AllegroInput()56 AllegroInput::AllegroInput() 57 { 58 mMouseButton1 = mMouseButton2 = mMouseButton3 = false; 59 mLastMouseZ = 0; 60 mLastMouseX = 0; 61 mLastMouseY = 0; 62 } 63 isKeyQueueEmpty()64 bool AllegroInput::isKeyQueueEmpty() 65 { 66 return mKeyQueue.empty(); 67 } 68 dequeueKeyInput()69 KeyInput AllegroInput::dequeueKeyInput() 70 { 71 if (isKeyQueueEmpty()) 72 { 73 throw GCN_EXCEPTION("Key queue is empty."); 74 } 75 76 KeyInput ki = mKeyQueue.front(); 77 mKeyQueue.pop(); 78 79 return ki; 80 } 81 isMouseQueueEmpty()82 bool AllegroInput::isMouseQueueEmpty() 83 { 84 return mMouseQueue.empty(); 85 } 86 dequeueMouseInput()87 MouseInput AllegroInput::dequeueMouseInput() 88 { 89 if (isMouseQueueEmpty()) 90 { 91 throw GCN_EXCEPTION("Mouse queue is empty."); 92 } 93 94 MouseInput mi = mMouseQueue.front(); 95 mMouseQueue.pop(); 96 97 return mi; 98 } 99 _pollInput()100 void AllegroInput::_pollInput() 101 { 102 pollMouseInput(); 103 pollKeyInput(); 104 } 105 pollMouseInput()106 void AllegroInput::pollMouseInput() 107 { 108 if (mouse_needs_poll()) 109 { 110 poll_mouse(); 111 } 112 int mouseX = mouse_x; 113 int mouseY = mouse_y; 114 int mouseZ = mouse_z; 115 int mouseB1 = mouse_b & 1; 116 int mouseB2 = mouse_b & 2; 117 int mouseB3 = mouse_b & 4; 118 119 // Check mouse movement 120 if (mouseX != mLastMouseX || mouseY != mLastMouseY) 121 { 122 mMouseQueue.push(MouseInput(MouseInput::EMPTY, 123 MouseInput::MOVED, 124 mouseX, 125 mouseY, 126 0)); 127 mLastMouseX = mouseX; 128 mLastMouseY = mouseY; 129 } 130 131 // Check mouse Wheel 132 while (mLastMouseZ < mouseZ) 133 { 134 mMouseQueue.push(MouseInput(MouseInput::EMPTY, 135 MouseInput::WHEEL_MOVED_UP, 136 mouseX, 137 mouseY, 138 0)); 139 mLastMouseZ++; 140 } 141 142 while (mLastMouseZ > mouseZ) 143 { 144 mMouseQueue.push(MouseInput(MouseInput::EMPTY, 145 MouseInput::WHEEL_MOVED_DOWN, 146 mouseX, 147 mouseY, 148 0)); 149 mLastMouseZ--; 150 } 151 152 // Check mouse buttons 153 if (!mMouseButton1 && mouseB1) 154 { 155 mMouseQueue.push(MouseInput(MouseInput::LEFT, 156 MouseInput::PRESSED, 157 mouseX, 158 mouseY, 159 0)); 160 } 161 162 if (mMouseButton1 && !mouseB1) 163 { 164 mMouseQueue.push(MouseInput(MouseInput::LEFT, 165 MouseInput::RELEASED, 166 mouseX, 167 mouseY, 168 0)); 169 } 170 171 172 if (!mMouseButton2 && mouseB2) 173 { 174 mMouseQueue.push(MouseInput(MouseInput::RIGHT, 175 MouseInput::PRESSED, 176 mouseX, 177 mouseY, 178 0)); 179 } 180 181 if (mMouseButton2 && !mouseB2) 182 { 183 mMouseQueue.push(MouseInput(MouseInput::RIGHT, 184 MouseInput::RELEASED, 185 mouseX, 186 mouseY, 187 0)); 188 } 189 190 191 if (!mMouseButton3 && mouseB3) 192 { 193 mMouseQueue.push(MouseInput(MouseInput::MIDDLE, 194 MouseInput::PRESSED, 195 mouseX, 196 mouseY, 197 0)); 198 } 199 200 if (mMouseButton3 && !mouseB3) 201 { 202 mMouseQueue.push(MouseInput(MouseInput::MIDDLE, 203 MouseInput::RELEASED, 204 mouseX, 205 mouseY, 206 0)); 207 } 208 209 mMouseButton1 = mouseB1; 210 mMouseButton2 = mouseB2; 211 mMouseButton3 = mouseB3; 212 } 213 pollKeyInput()214 void AllegroInput::pollKeyInput() 215 { 216 int unicode, scancode; 217 218 if (keyboard_needs_poll()) 219 { 220 poll_keyboard(); 221 } 222 223 while (keypressed()) 224 { 225 unicode = ureadkey(&scancode); 226 Key keyObj = convertToKey(scancode, unicode); 227 228 KeyInput keyInput(keyObj, KeyInput::PRESSED); 229 230 keyInput.setNumericPad(isNumericPad(scancode)); 231 keyInput.setShiftPressed(key_shifts & KB_SHIFT_FLAG); 232 keyInput.setAltPressed(key_shifts & KB_ALT_FLAG); 233 keyInput.setControlPressed(key_shifts & KB_CTRL_FLAG); 234 #ifdef KB_COMMAND_FLAG 235 keyInput.setMetaPressed(key_shifts & (KB_COMMAND_FLAG | 236 KB_LWIN_FLAG | 237 KB_RWIN_FLAG)); 238 #else 239 keyInput.setMetaPressed(key_shifts & (KB_LWIN_FLAG | 240 KB_RWIN_FLAG)); 241 #endif 242 243 244 mKeyQueue.push(keyInput); 245 246 mPressedKeys[scancode] = keyInput; 247 } 248 249 if (key[KEY_ALT] && mPressedKeys.find(KEY_ALT) == mPressedKeys.end()) 250 { 251 KeyInput keyInput(convertToKey(KEY_ALT, 0), KeyInput::PRESSED); 252 mKeyQueue.push(keyInput); 253 mPressedKeys[KEY_ALT] = keyInput; 254 } 255 256 if (key[KEY_ALTGR] && mPressedKeys.find(KEY_ALTGR) == mPressedKeys.end()) 257 { 258 KeyInput keyInput(convertToKey(KEY_ALTGR, 0), KeyInput::PRESSED); 259 mKeyQueue.push(keyInput); 260 mPressedKeys[KEY_ALTGR] = keyInput; 261 } 262 263 if (key[KEY_LSHIFT] && mPressedKeys.find(KEY_LSHIFT) == mPressedKeys.end()) 264 { 265 KeyInput keyInput(convertToKey(KEY_LSHIFT, 0), KeyInput::PRESSED); 266 mKeyQueue.push(keyInput); 267 mPressedKeys[KEY_LSHIFT] = keyInput; 268 } 269 270 if (key[KEY_RSHIFT] && mPressedKeys.find(KEY_RSHIFT) == mPressedKeys.end()) 271 { 272 KeyInput keyInput(convertToKey(KEY_RSHIFT, 0), KeyInput::PRESSED); 273 mKeyQueue.push(keyInput); 274 mPressedKeys[KEY_RSHIFT] = keyInput; 275 } 276 277 if (key[KEY_LCONTROL] && mPressedKeys.find(KEY_LCONTROL) == mPressedKeys.end()) 278 { 279 KeyInput keyInput(convertToKey(KEY_LCONTROL, 0), KeyInput::PRESSED); 280 mKeyQueue.push(keyInput); 281 mPressedKeys[KEY_LCONTROL] = keyInput; 282 } 283 284 if (key[KEY_RCONTROL] && mPressedKeys.find(KEY_RCONTROL) == mPressedKeys.end()) 285 { 286 KeyInput keyInput(convertToKey(KEY_RCONTROL, 0), KeyInput::PRESSED); 287 mKeyQueue.push(keyInput); 288 mPressedKeys[KEY_RCONTROL] = keyInput; 289 } 290 291 // Check for released keys 292 std::map<int, KeyInput>::iterator iter, tempIter; 293 for (iter = mPressedKeys.begin(); iter != mPressedKeys.end(); ) 294 { 295 if (!key[iter->first]) 296 { 297 KeyInput keyInput(iter->second.getKey(), KeyInput::RELEASED); 298 keyInput.setNumericPad(iter->second.isNumericPad()); 299 keyInput.setShiftPressed(iter->second.isShiftPressed()); 300 keyInput.setAltPressed(iter->second.isAltPressed()); 301 keyInput.setControlPressed(iter->second.isControlPressed()); 302 303 mKeyQueue.push(keyInput); 304 305 tempIter = iter; 306 iter++; 307 mPressedKeys.erase(tempIter); 308 } 309 else 310 { 311 iter++; 312 } 313 } 314 } 315 convertToKey(int scancode,int unicode)316 Key AllegroInput::convertToKey(int scancode, int unicode) 317 { 318 int keysym; 319 bool pad = false; 320 321 switch(scancode) 322 { 323 case KEY_ESC: 324 keysym = Key::ESCAPE; 325 break; 326 327 case KEY_ALT: 328 keysym = Key::LEFT_ALT; 329 break; 330 331 case KEY_ALTGR: 332 keysym = Key::RIGHT_ALT; 333 break; 334 335 case KEY_LSHIFT: 336 keysym = Key::LEFT_SHIFT; 337 break; 338 339 case KEY_RSHIFT: 340 keysym = Key::RIGHT_SHIFT; 341 break; 342 343 case KEY_LCONTROL: 344 keysym = Key::LEFT_CONTROL; 345 break; 346 347 case KEY_RCONTROL: 348 keysym = Key::RIGHT_CONTROL; 349 break; 350 351 case KEY_LWIN: 352 keysym = Key::LEFT_META; 353 break; 354 355 case KEY_RWIN: 356 keysym = Key::RIGHT_META; 357 break; 358 359 case KEY_INSERT: 360 keysym = Key::INSERT; 361 break; 362 363 case KEY_HOME: 364 keysym = Key::HOME; 365 break; 366 367 case KEY_PGUP: 368 keysym = Key::PAGE_UP; 369 break; 370 371 case KEY_PGDN: 372 keysym = Key::PAGE_DOWN; 373 break; 374 375 case KEY_DEL: 376 keysym = Key::DELETE; 377 break; 378 379 case KEY_DEL_PAD: 380 keysym = Key::DELETE; 381 pad = true; 382 break; 383 384 case KEY_END: 385 keysym = Key::END; 386 break; 387 388 case KEY_CAPSLOCK: 389 keysym = Key::CAPS_LOCK; 390 break; 391 392 case KEY_BACKSPACE: 393 keysym = Key::BACKSPACE; 394 break; 395 396 case KEY_F1: 397 keysym = Key::F1; 398 break; 399 400 case KEY_F2: 401 keysym = Key::F2; 402 break; 403 404 case KEY_F3: 405 keysym = Key::F3; 406 break; 407 408 case KEY_F4: 409 keysym = Key::F4; 410 break; 411 412 case KEY_F5: 413 keysym = Key::F5; 414 break; 415 416 case KEY_F6: 417 keysym = Key::F6; 418 break; 419 420 case KEY_F7: 421 keysym = Key::F7; 422 break; 423 424 case KEY_F8: 425 keysym = Key::F8; 426 break; 427 428 case KEY_F9: 429 keysym = Key::F9; 430 break; 431 432 case KEY_F10: 433 keysym = Key::F10; 434 break; 435 436 case KEY_F11: 437 keysym = Key::F11; 438 break; 439 440 case KEY_F12: 441 keysym = Key::F12; 442 break; 443 444 case KEY_PRTSCR: 445 keysym = Key::PRINT_SCREEN; 446 break; 447 448 case KEY_PAUSE: 449 keysym = Key::PAUSE; 450 break; 451 452 case KEY_SCRLOCK: 453 keysym = Key::SCROLL_LOCK; 454 break; 455 456 case KEY_NUMLOCK: 457 keysym = Key::NUM_LOCK; 458 break; 459 460 case KEY_LEFT: 461 keysym = Key::LEFT; 462 break; 463 464 case KEY_RIGHT: 465 keysym = Key::RIGHT; 466 break; 467 468 case KEY_UP: 469 keysym = Key::UP; 470 break; 471 472 case KEY_DOWN: 473 keysym = Key::DOWN; 474 break; 475 476 case KEY_ENTER_PAD: 477 pad = true; 478 case KEY_ENTER: 479 keysym = Key::ENTER; 480 break; 481 default: 482 keysym = unicode; 483 } 484 485 Key k = Key(keysym); 486 487 return k; 488 489 //Now, THAT was fun to code! =D =D =D 490 } 491 isNumericPad(int scancode)492 bool AllegroInput::isNumericPad(int scancode) 493 { 494 switch (scancode) 495 { 496 case KEY_0_PAD: 497 case KEY_1_PAD: 498 case KEY_2_PAD: 499 case KEY_3_PAD: 500 case KEY_4_PAD: 501 case KEY_5_PAD: 502 case KEY_6_PAD: 503 case KEY_7_PAD: 504 case KEY_8_PAD: 505 case KEY_9_PAD: 506 case KEY_SLASH_PAD: 507 case KEY_MINUS_PAD: 508 case KEY_PLUS_PAD: 509 return true; 510 default: 511 return false; 512 } 513 } 514 } 515