00001 #include "glfw_input_impl.hpp"
00002 #include <utils_string.hpp>
00003 #include <GL/glfw.h>
00004
00005 #warning "Note : GLFW input handler is not fully functional, since \
00006 GLFW doesn't provide keyboard layout independent key codes."
00007
00008 namespace input
00009 {
00010 const int glfw_handler::lKeyToGLFW[106][2] =
00011 {
00012
00013 {key::K_SPACE, GLFW_KEY_SPACE},
00014 {key::K_Q, 'Q'},
00015 {key::K_W, 'W'},
00016 {key::K_E, 'E'},
00017 {key::K_R, 'R'},
00018 {key::K_T, 'T'},
00019 {key::K_Y, 'Y'},
00020 {key::K_U, 'U'},
00021 {key::K_I, 'I'},
00022 {key::K_O, 'O'},
00023 {key::K_P, 'P'},
00024 {key::K_A, 'A'},
00025 {key::K_S, 'S'},
00026 {key::K_D, 'D'},
00027 {key::K_F, 'F'},
00028 {key::K_G, 'G'},
00029 {key::K_H, 'H'},
00030 {key::K_J, 'J'},
00031 {key::K_K, 'K'},
00032 {key::K_L, 'L'},
00033 {key::K_Z, 'Z'},
00034 {key::K_X, 'X'},
00035 {key::K_C, 'C'},
00036 {key::K_V, 'V'},
00037 {key::K_B, 'B'},
00038 {key::K_N, 'N'},
00039 {key::K_M, 'M'},
00040 {key::K_0, '0'},
00041 {key::K_1, '1'},
00042 {key::K_2, '2'},
00043 {key::K_3, '3'},
00044 {key::K_4, '4'},
00045 {key::K_5, '5'},
00046 {key::K_6, '6'},
00047 {key::K_7, '7'},
00048 {key::K_8, '8'},
00049 {key::K_9, '9'},
00050 {key::K_MINUS, '-'},
00051 {key::K_EQUALS, '='},
00052 {key::K_LBRACKET, '['},
00053 {key::K_RBRACKET, ']'},
00054 {key::K_SEMICOLON, ';'},
00055 {key::K_APOSTROPHE, '\''},
00056 {key::K_GRAVE, '`'},
00057 {key::K_BACKSLASH, '\\'},
00058 {key::K_COMMA, ','},
00059 {key::K_PERIOD, '.'},
00060 {key::K_SLASH, '/'},
00061 {key::K_ESCAPE, GLFW_KEY_ESC},
00062 {key::K_F1, GLFW_KEY_F1},
00063 {key::K_F2, GLFW_KEY_F2},
00064 {key::K_F3, GLFW_KEY_F3},
00065 {key::K_F4, GLFW_KEY_F4},
00066 {key::K_F5, GLFW_KEY_F5},
00067 {key::K_F6, GLFW_KEY_F6},
00068 {key::K_F7, GLFW_KEY_F7},
00069 {key::K_F8, GLFW_KEY_F8},
00070 {key::K_F9, GLFW_KEY_F9},
00071 {key::K_F10, GLFW_KEY_F10},
00072 {key::K_F11, GLFW_KEY_F11},
00073 {key::K_F12, GLFW_KEY_F12},
00074 {key::K_F13, GLFW_KEY_F13},
00075 {key::K_F14, GLFW_KEY_F14},
00076 {key::K_F15, GLFW_KEY_F15},
00077 {key::K_UP, GLFW_KEY_UP},
00078 {key::K_DOWN, GLFW_KEY_DOWN},
00079 {key::K_LEFT, GLFW_KEY_LEFT},
00080 {key::K_RIGHT, GLFW_KEY_RIGHT},
00081 {key::K_LSHIFT, GLFW_KEY_LSHIFT},
00082 {key::K_RSHIFT, GLFW_KEY_RSHIFT},
00083 {key::K_LCONTROL, GLFW_KEY_LCTRL},
00084 {key::K_RCONTROL, GLFW_KEY_RCTRL},
00085 {key::K_LMENU, GLFW_KEY_LALT},
00086 {key::K_RMENU, GLFW_KEY_RALT},
00087 {key::K_TAB, GLFW_KEY_TAB},
00088 {key::K_RETURN, GLFW_KEY_ENTER},
00089 {key::K_BACK, GLFW_KEY_BACKSPACE},
00090 {key::K_INSERT, GLFW_KEY_INSERT},
00091 {key::K_DELETE, GLFW_KEY_DEL},
00092 {key::K_PGUP, GLFW_KEY_PAGEUP},
00093 {key::K_PGDOWN, GLFW_KEY_PAGEDOWN},
00094 {key::K_HOME, GLFW_KEY_HOME},
00095 {key::K_END, GLFW_KEY_END},
00096 {key::K_NUMPAD0, GLFW_KEY_KP_0},
00097 {key::K_NUMPAD1, GLFW_KEY_KP_1},
00098 {key::K_NUMPAD2, GLFW_KEY_KP_2},
00099 {key::K_NUMPAD3, GLFW_KEY_KP_3},
00100 {key::K_NUMPAD4, GLFW_KEY_KP_4},
00101 {key::K_NUMPAD5, GLFW_KEY_KP_5},
00102 {key::K_NUMPAD6, GLFW_KEY_KP_6},
00103 {key::K_NUMPAD7, GLFW_KEY_KP_7},
00104 {key::K_NUMPAD8, GLFW_KEY_KP_8},
00105 {key::K_NUMPAD9, GLFW_KEY_KP_9},
00106 {key::K_DIVIDE, GLFW_KEY_KP_DIVIDE},
00107 {key::K_MULTIPLY, GLFW_KEY_KP_MULTIPLY},
00108 {key::K_SUBTRACT, GLFW_KEY_KP_SUBTRACT},
00109 {key::K_ADD, GLFW_KEY_KP_ADD},
00110 {key::K_DECIMAL, GLFW_KEY_KP_DECIMAL},
00111 {key::K_NUMPADENTER, GLFW_KEY_KP_ENTER},
00112 {key::K_NUMLOCK, GLFW_KEY_KP_NUM_LOCK},
00113 {key::K_CAPITAL, GLFW_KEY_CAPS_LOCK},
00114 {key::K_SCROLL, GLFW_KEY_SCROLL_LOCK},
00115 {key::K_PAUSE, GLFW_KEY_PAUSE},
00116 {key::K_LWIN, GLFW_KEY_LSUPER},
00117 {key::K_RWIN, GLFW_KEY_RSUPER},
00118 {key::K_APPS, GLFW_KEY_MENU}
00119 };
00120
00121 glfw_handler::glfw_handler(bool bMouseGrab) :
00122 bMouseGrab_(bMouseGrab), bFirst_(true)
00123 {
00124 mMouse.bHasDelta = true;
00125 }
00126
00127 int glfw_handler::to_glfw_(key::code mKey) const
00128 {
00129 for (size_t i = 0; i < 106; ++i)
00130 {
00131 if (lKeyToGLFW[i][0] == mKey)
00132 return lKeyToGLFW[i][1];
00133 }
00134
00135 return GLFW_KEY_UNKNOWN;
00136 }
00137
00138 void glfw_handler::toggle_mouse_grab()
00139 {
00140 bMouseGrab_ = !bMouseGrab_;
00141 #warning "Note : GLFW 2.x does not support mouse grab switching. \
00142 The mouse is always grabbed if using fullscreen mode, and \
00143 never grabbed if using windowed mode."
00144 }
00145
00146 #ifdef WIN32
00147 #include <windows.h>
00148
00149 #ifndef VK_OEM_COMMA
00150 #define VK_OEM_PLUS 0xBB
00151 #define VK_OEM_COMMA 0xBC
00152 #define VK_OEM_MINUS 0xBD
00153 #define VK_OEM_PERIOD 0xBE
00154 #endif
00155
00156 int to_vkey_(int key)
00157 {
00158 switch (key)
00159 {
00160 default: return 0;
00161 case 'A': return 'A';
00162 case 'B': return 'B';
00163 case 'C': return 'C';
00164 case 'D': return 'D';
00165 case 'E': return 'E';
00166 case 'F': return 'F';
00167 case 'G': return 'G';
00168 case 'H': return 'H';
00169 case 'I': return 'I';
00170 case 'J': return 'J';
00171 case 'K': return 'K';
00172 case 'L': return 'L';
00173 case 'M': return 'M';
00174 case 'N': return 'N';
00175 case 'O': return 'O';
00176 case 'P': return 'P';
00177 case 'Q': return 'Q';
00178 case 'R': return 'R';
00179 case 'S': return 'S';
00180 case 'T': return 'T';
00181 case 'U': return 'U';
00182 case 'V': return 'V';
00183 case 'W': return 'W';
00184 case 'X': return 'X';
00185 case 'Y': return 'Y';
00186 case 'Z': return 'Z';
00187 case '0': return '0';
00188 case '1': return '1';
00189 case '2': return '2';
00190 case '3': return '3';
00191 case '4': return '4';
00192 case '5': return '5';
00193 case '6': return '6';
00194 case '7': return '7';
00195 case '8': return '8';
00196 case '9': return '9';
00197 case GLFW_KEY_ESC: return VK_ESCAPE;
00198 case GLFW_KEY_LCTRL: return VK_LCONTROL;
00199 case GLFW_KEY_LSHIFT: return VK_LSHIFT;
00200 case GLFW_KEY_LALT: return VK_LMENU;
00201 case GLFW_KEY_LSUPER: return VK_LWIN;
00202 case GLFW_KEY_RCTRL: return VK_RCONTROL;
00203 case GLFW_KEY_RSHIFT: return VK_RSHIFT;
00204 case GLFW_KEY_RALT: return VK_RMENU;
00205 case GLFW_KEY_RSUPER: return VK_RWIN;
00206 case GLFW_KEY_MENU: return VK_APPS;
00207 case '[': return VK_OEM_4;
00208 case ']': return VK_OEM_6;
00209 case ';': return VK_OEM_1;
00210 case ',': return VK_OEM_COMMA;
00211 case '.': return VK_OEM_PERIOD;
00212 case '\'': return VK_OEM_7;
00213 case '/': return VK_OEM_2;
00214 case '\\': return VK_OEM_5;
00215 case '~': return VK_OEM_3;
00216 case '=': return VK_OEM_PLUS;
00217 case '-': return VK_OEM_MINUS;
00218 case GLFW_KEY_SPACE: return VK_SPACE;
00219 case GLFW_KEY_ENTER: return VK_RETURN;
00220 case GLFW_KEY_BACKSPACE: return VK_BACK;
00221 case GLFW_KEY_TAB: return VK_TAB;
00222 case GLFW_KEY_PAGEUP: return VK_PRIOR;
00223 case GLFW_KEY_PAGEDOWN: return VK_NEXT;
00224 case GLFW_KEY_END: return VK_END;
00225 case GLFW_KEY_HOME: return VK_HOME;
00226 case GLFW_KEY_INSERT: return VK_INSERT;
00227 case GLFW_KEY_DEL: return VK_DELETE;
00228 case GLFW_KEY_KP_ADD: return VK_ADD;
00229 case GLFW_KEY_KP_SUBTRACT: return VK_SUBTRACT;
00230 case GLFW_KEY_KP_MULTIPLY: return VK_MULTIPLY;
00231 case GLFW_KEY_KP_DIVIDE: return VK_DIVIDE;
00232 case GLFW_KEY_LEFT: return VK_LEFT;
00233 case GLFW_KEY_RIGHT: return VK_RIGHT;
00234 case GLFW_KEY_UP: return VK_UP;
00235 case GLFW_KEY_DOWN: return VK_DOWN;
00236 case GLFW_KEY_KP_0: return VK_NUMPAD0;
00237 case GLFW_KEY_KP_1: return VK_NUMPAD1;
00238 case GLFW_KEY_KP_2: return VK_NUMPAD2;
00239 case GLFW_KEY_KP_3: return VK_NUMPAD3;
00240 case GLFW_KEY_KP_4: return VK_NUMPAD4;
00241 case GLFW_KEY_KP_5: return VK_NUMPAD5;
00242 case GLFW_KEY_KP_6: return VK_NUMPAD6;
00243 case GLFW_KEY_KP_7: return VK_NUMPAD7;
00244 case GLFW_KEY_KP_8: return VK_NUMPAD8;
00245 case GLFW_KEY_KP_9: return VK_NUMPAD9;
00246 case GLFW_KEY_F1: return VK_F1;
00247 case GLFW_KEY_F2: return VK_F2;
00248 case GLFW_KEY_F3: return VK_F3;
00249 case GLFW_KEY_F4: return VK_F4;
00250 case GLFW_KEY_F5: return VK_F5;
00251 case GLFW_KEY_F6: return VK_F6;
00252 case GLFW_KEY_F7: return VK_F7;
00253 case GLFW_KEY_F8: return VK_F8;
00254 case GLFW_KEY_F9: return VK_F9;
00255 case GLFW_KEY_F10: return VK_F10;
00256 case GLFW_KEY_F11: return VK_F11;
00257 case GLFW_KEY_F12: return VK_F12;
00258 case GLFW_KEY_F13: return VK_F13;
00259 case GLFW_KEY_F14: return VK_F14;
00260 case GLFW_KEY_F15: return VK_F16;
00261 case GLFW_KEY_PAUSE: return VK_PAUSE;
00262 }
00263 }
00264
00265 #else
00266 #include <X11/Xlib.h>
00267 #include <X11/keysym.h>
00268
00269 KeySym to_xkey_(int key)
00270 {
00271 switch (key)
00272 {
00273 case 'A': return XK_A;
00274 case 'B': return XK_B;
00275 case 'C': return XK_C;
00276 case 'D': return XK_D;
00277 case 'E': return XK_E;
00278 case 'F': return XK_F;
00279 case 'G': return XK_G;
00280 case 'H': return XK_H;
00281 case 'I': return XK_I;
00282 case 'J': return XK_J;
00283 case 'K': return XK_K;
00284 case 'L': return XK_L;
00285 case 'M': return XK_M;
00286 case 'N': return XK_N;
00287 case 'O': return XK_O;
00288 case 'P': return XK_P;
00289 case 'Q': return XK_Q;
00290 case 'R': return XK_R;
00291 case 'S': return XK_S;
00292 case 'T': return XK_T;
00293 case 'U': return XK_U;
00294 case 'V': return XK_V;
00295 case 'W': return XK_W;
00296 case 'X': return XK_X;
00297 case 'Y': return XK_Y;
00298 case 'Z': return XK_Z;
00299 case '0': return XK_0;
00300 case '1': return XK_1;
00301 case '2': return XK_2;
00302 case '3': return XK_3;
00303 case '4': return XK_4;
00304 case '5': return XK_5;
00305 case '6': return XK_6;
00306 case '7': return XK_7;
00307 case '8': return XK_8;
00308 case '9': return XK_9;
00309 case GLFW_KEY_ESC: return XK_Escape;
00310 case GLFW_KEY_LCTRL: return XK_Control_L;
00311 case GLFW_KEY_LSHIFT: return XK_Shift_L;
00312 case GLFW_KEY_LALT: return XK_Alt_L;
00313 case GLFW_KEY_LSUPER: return XK_Super_L;
00314 case GLFW_KEY_RCTRL: return XK_Control_R;
00315 case GLFW_KEY_RSHIFT: return XK_Shift_R;
00316 case GLFW_KEY_RALT: return XK_Alt_R;
00317 case GLFW_KEY_RSUPER: return XK_Super_R;
00318 case GLFW_KEY_MENU: return XK_Menu;
00319 case '[': return XK_bracketleft;
00320 case ']': return XK_bracketright;
00321 case ';': return XK_semicolon;
00322 case ',': return XK_comma;
00323 case '.': return XK_period;
00324 case '\'': return XK_dead_acute;
00325 case '/': return XK_slash;
00326 case '\\': return XK_backslash;
00327 case '~': return XK_dead_grave;
00328 case '=': return XK_equal;
00329 case '-': return XK_minus;
00330 case GLFW_KEY_SPACE: return XK_space;
00331 case GLFW_KEY_ENTER: return XK_Return;
00332 case GLFW_KEY_BACKSPACE: return XK_BackSpace;
00333 case GLFW_KEY_TAB: return XK_Tab;
00334 case GLFW_KEY_PAGEUP: return XK_Prior;
00335 case GLFW_KEY_PAGEDOWN: return XK_Next;
00336 case GLFW_KEY_END: return XK_End;
00337 case GLFW_KEY_HOME: return XK_Home;
00338 case GLFW_KEY_INSERT: return XK_Insert;
00339 case GLFW_KEY_DEL: return XK_Delete;
00340 case GLFW_KEY_KP_ADD: return XK_KP_Add;
00341 case GLFW_KEY_KP_SUBTRACT: return XK_KP_Subtract;
00342 case GLFW_KEY_KP_MULTIPLY: return XK_KP_Multiply;
00343 case GLFW_KEY_KP_DIVIDE: return XK_KP_Divide;
00344 case GLFW_KEY_LEFT: return XK_Left;
00345 case GLFW_KEY_RIGHT: return XK_Right;
00346 case GLFW_KEY_UP: return XK_Up;
00347 case GLFW_KEY_DOWN: return XK_Down;
00348 case GLFW_KEY_KP_0: return XK_KP_0;
00349 case GLFW_KEY_KP_1: return XK_KP_1;
00350 case GLFW_KEY_KP_2: return XK_KP_2;
00351 case GLFW_KEY_KP_3: return XK_KP_3;
00352 case GLFW_KEY_KP_4: return XK_KP_4;
00353 case GLFW_KEY_KP_5: return XK_KP_5;
00354 case GLFW_KEY_KP_6: return XK_KP_6;
00355 case GLFW_KEY_KP_7: return XK_KP_7;
00356 case GLFW_KEY_KP_8: return XK_KP_8;
00357 case GLFW_KEY_KP_9: return XK_KP_9;
00358 case GLFW_KEY_F1: return XK_F1;
00359 case GLFW_KEY_F2: return XK_F2;
00360 case GLFW_KEY_F3: return XK_F3;
00361 case GLFW_KEY_F4: return XK_F4;
00362 case GLFW_KEY_F5: return XK_F5;
00363 case GLFW_KEY_F6: return XK_F6;
00364 case GLFW_KEY_F7: return XK_F7;
00365 case GLFW_KEY_F8: return XK_F8;
00366 case GLFW_KEY_F9: return XK_F9;
00367 case GLFW_KEY_F10: return XK_F10;
00368 case GLFW_KEY_F11: return XK_F11;
00369 case GLFW_KEY_F12: return XK_F12;
00370 case GLFW_KEY_F13: return XK_F13;
00371 case GLFW_KEY_F14: return XK_F14;
00372 case GLFW_KEY_F15: return XK_F15;
00373 case GLFW_KEY_PAUSE: return XK_Pause;
00374 default: return 0;
00375 }
00376 }
00377
00378 #endif
00379
00380 std::string glfw_handler::get_key_name(key::code mKey) const
00381 {
00382 #ifdef WIN32
00383 int vkey = to_vkey_(to_glfw_(mKey));
00384 unsigned int code = MapVirtualKey(vkey, 0 );
00385
00386 char name[50];
00387 if (GetKeyNameText(code << 16, name, sizeof(name)) != 0)
00388 return name;
00389 else
00390 return "Unknown";
00391
00392 #else
00393
00394 KeySym keysym = to_xkey_(to_glfw_(mKey));
00395 if (keysym == 0)
00396 return "Unknown";
00397
00398
00399 char* name = XKeysymToString(keysym);
00400 if (name != 0)
00401 {
00402 std::string s(name);
00403
00404 if (s.substr(0, 3) == "KP_")
00405 {
00406 s.erase(0, 3);
00407 s.append(" (Num.)");
00408 }
00409
00410 s[0] = toupper(s[0]);
00411 bool bPrevUnderscore = false;
00412 for (auto& c : s)
00413 {
00414 if (c == '_')
00415 {
00416 c = ' ';
00417 bPrevUnderscore = true;
00418 }
00419 else if (bPrevUnderscore)
00420 {
00421 c = toupper(c);
00422 bPrevUnderscore = false;
00423 }
00424 }
00425
00426 return s;
00427 }
00428 else
00429 return "Unknown";
00430 #endif
00431 }
00432
00433 void glfw_handler::update()
00434 {
00435 for (int i = 0; i < 106; ++i)
00436 mKeyboard.lKeyState[lKeyToGLFW[i][0]] = glfwGetKey(lKeyToGLFW[i][1]);
00437
00438 int width, height;
00439 glfwGetWindowSize(&width, &height);
00440
00441 if (bFirst_)
00442 {
00443 int mx, my;
00444 glfwGetMousePos(&mx, &my);
00445 mMouse.fAbsX = mx;
00446 mMouse.fAbsY = my;
00447 mMouse.fRelX = mx/float(width);
00448 mMouse.fRelY = my/float(height);
00449
00450 mMouse.fDX = mMouse.fDY = mMouse.fRelDX = mMouse.fRelDY = 0.0f;
00451 bFirst_ = false;
00452
00453 fOldMouseX_ = mMouse.fAbsX;
00454 fOldMouseY_ = mMouse.fAbsY;
00455 }
00456 else
00457 {
00458 int mx, my;
00459 glfwGetMousePos(&mx, &my);
00460 mMouse.fDX = mx - fOldMouseX_;
00461 mMouse.fDY = my - fOldMouseY_;
00462 mMouse.fRelDX = mMouse.fDX/width;
00463 mMouse.fRelDY = mMouse.fDY/height;
00464
00465 mMouse.fAbsX += mMouse.fDX;
00466 mMouse.fAbsY += mMouse.fDY;
00467 mMouse.fRelX = mMouse.fAbsX/width;
00468 mMouse.fRelY = mMouse.fAbsY/height;
00469
00470 fOldMouseX_ = mMouse.fAbsX;
00471 fOldMouseY_ = mMouse.fAbsY;
00472 }
00473
00474 int wheel = glfwGetMouseWheel();
00475 mMouse.fRelWheel = wheel - fOldWheel_;
00476 fOldWheel_ = wheel;
00477
00478 static const int lMouseToGLFW[3] = {GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_MIDDLE};
00479 for (int i = 0; i < INPUT_MOUSE_BUTTON_NUMBER; ++i)
00480 mMouse.lButtonState[i] = glfwGetMouseButton(lMouseToGLFW[i]) == GLFW_PRESS;
00481 }
00482 }