Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

WindowGLFW.cpp 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*!
  2. * \file src/system/WindowGLFW.cpp
  3. * \brief GLFW Windowing Implementation
  4. *
  5. * \author xythobuz
  6. */
  7. #include <codecvt>
  8. #include <sstream>
  9. #define GLFW_INCLUDE_NONE
  10. #include <GLFW/glfw3.h>
  11. #include "global.h"
  12. #include "Log.h"
  13. #include "RunTime.h"
  14. #include "UI.h"
  15. #include "system/Window.h"
  16. #include "system/WindowGLFW.h"
  17. #include <glbinding/gl/gl33.h>
  18. glm::i32vec2 WindowGLFW::size(DEFAULT_WIDTH, DEFAULT_HEIGHT);
  19. bool WindowGLFW::fullscreen = false;
  20. bool WindowGLFW::mousegrab = false;
  21. bool WindowGLFW::textinput = false;
  22. GLFWwindow* WindowGLFW::window = nullptr;
  23. int WindowGLFW::lastMouseX = 0;
  24. int WindowGLFW::lastMouseY = 0;
  25. bool WindowGLFW::modShift = false;
  26. bool WindowGLFW::modControl = false;
  27. bool WindowGLFW::modAlt = false;
  28. bool WindowGLFW::modSuper = false;
  29. int WindowGLFW::initialize() {
  30. glfwSetErrorCallback(WindowGLFW::errorCallback);
  31. if (!glfwInit()) {
  32. return -1;
  33. }
  34. glfwWindowHint(GLFW_SAMPLES, 4);
  35. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  36. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  37. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  38. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, int(gl::GL_TRUE));
  39. window = glfwCreateWindow(size.x, size.y, VERSION,
  40. fullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
  41. if (!window) {
  42. glfwTerminate();
  43. return -2;
  44. }
  45. glfwMakeContextCurrent(window);
  46. glfwSetWindowSizeCallback(window, WindowGLFW::sizeCallback);
  47. glfwSetCursorPosCallback(window, WindowGLFW::cursorCallback);
  48. glfwSetKeyCallback(window, WindowGLFW::keyCallback);
  49. glfwSetCharCallback(window, WindowGLFW::charCallback);
  50. glfwSetMouseButtonCallback(window, WindowGLFW::buttonCallback);
  51. glfwSetScrollCallback(window, WindowGLFW::scrollCallback);
  52. int w = size.x, h = size.y;
  53. glfwGetWindowSize(window, &w, &h);
  54. size.x = w;
  55. size.y = h;
  56. return 0;
  57. }
  58. void WindowGLFW::eventHandling() {
  59. glfwPollEvents();
  60. if (glfwWindowShouldClose(window)) {
  61. RunTime::setRunning(false);
  62. }
  63. UI::eventsFinished();
  64. }
  65. void WindowGLFW::swapBuffers() {
  66. glfwSwapBuffers(window);
  67. }
  68. void WindowGLFW::shutdown() {
  69. if (window) {
  70. glfwDestroyWindow(window);
  71. glfwTerminate();
  72. window = nullptr;
  73. }
  74. }
  75. void WindowGLFW::setSize(glm::i32vec2 s) {
  76. orAssert((s.x > 0) && (s.y > 0));
  77. if (window) {
  78. if ((size.x != s.x) || (size.y != s.y)) {
  79. glfwSetWindowSize(window, s.x, s.y);
  80. }
  81. }
  82. size = s;
  83. }
  84. void WindowGLFW::setFullscreen(bool f) {
  85. fullscreen = f;
  86. //! \fixme GLFW does not support toggling fullscreen?!
  87. }
  88. void WindowGLFW::setMousegrab(bool g) {
  89. mousegrab = g;
  90. if (window) {
  91. if (mousegrab)
  92. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  93. else
  94. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  95. }
  96. }
  97. void WindowGLFW::setTextInput(bool t) {
  98. textinput = t;
  99. }
  100. void WindowGLFW::setClipboard(const char* s) {
  101. if (window)
  102. glfwSetClipboardString(window, s);
  103. }
  104. const char* WindowGLFW::getClipboard() {
  105. if (window)
  106. return glfwGetClipboardString(window);
  107. return nullptr;
  108. }
  109. std::string WindowGLFW::getVersion(bool linked) {
  110. if (linked) {
  111. return std::string("GLFW v") + glfwGetVersionString();
  112. } else {
  113. std::ostringstream str;
  114. str << "GLFW v" << GLFW_VERSION_MAJOR << "." << GLFW_VERSION_MINOR << "." << GLFW_VERSION_REVISION;
  115. return str.str();
  116. }
  117. }
  118. void WindowGLFW::inputPositionCallback(int x, int y) { }
  119. void WindowGLFW::errorCallback(int error, const char* desc) {
  120. Log::get(LOG_ERROR) << "GLFW Error (" << error << "): " << desc << Log::endl;
  121. }
  122. void WindowGLFW::sizeCallback(GLFWwindow* w, int width, int height) {
  123. size = glm::i32vec2(width, height);
  124. Window::setSize(size);
  125. }
  126. void WindowGLFW::cursorCallback(GLFWwindow* w, double xpos, double ypos) {
  127. int xrel = xpos - lastMouseX;
  128. int yrel = ypos - lastMouseY;
  129. UI::handleMouseMotion(xrel, yrel, xpos, ypos);
  130. lastMouseX = xpos;
  131. lastMouseY = ypos;
  132. }
  133. void WindowGLFW::keyCallback(GLFWwindow* w, int key, int scancode, int action, int mods) {
  134. if (((mods & GLFW_MOD_SHIFT) != 0) != modShift) {
  135. modShift = (mods & GLFW_MOD_SHIFT) != 0;
  136. UI::handleKeyboard(leftshiftKey, modShift);
  137. }
  138. if (((mods & GLFW_MOD_CONTROL) != 0) != modControl) {
  139. modControl = (mods & GLFW_MOD_CONTROL) != 0;
  140. UI::handleKeyboard(leftctrlKey, modControl);
  141. }
  142. if (((mods & GLFW_MOD_ALT) != 0) != modAlt) {
  143. modAlt = (mods & GLFW_MOD_ALT) != 0;
  144. UI::handleKeyboard(leftaltKey, modAlt);
  145. }
  146. if (((mods & GLFW_MOD_SUPER) != 0) != modSuper) {
  147. modSuper = (mods & GLFW_MOD_SUPER) != 0;
  148. UI::handleKeyboard(leftguiKey, modSuper);
  149. }
  150. KeyboardButton b = convertAsciiButton(key);
  151. UI::handleKeyboard(b, (action != GLFW_RELEASE));
  152. }
  153. void WindowGLFW::charCallback(GLFWwindow* w, unsigned int codepoint) {
  154. static std::codecvt_utf8<char32_t> conv;
  155. static mbstate_t state;
  156. static const int bufferSize = 42;
  157. static char buffer[bufferSize + 1];
  158. if (textinput) {
  159. char32_t inBuff[2] = { codepoint, '\0' };
  160. const char32_t* in = nullptr;
  161. char* ex = nullptr;
  162. auto res = conv.out(state, inBuff, inBuff + 1, in, buffer, buffer + bufferSize, ex);
  163. if (res != 0) {
  164. Log::get(LOG_DEBUG) << "UTF-32 to UTF-8 conversion error (" << res << ")" << Log::endl;
  165. return;
  166. }
  167. *ex = '\0';
  168. UI::handleText(buffer, false);
  169. }
  170. }
  171. void WindowGLFW::buttonCallback(GLFWwindow* w, int button, int action, int mods) {
  172. if (((mods & GLFW_MOD_SHIFT) != 0) != modShift) {
  173. modShift = (mods & GLFW_MOD_SHIFT) != 0;
  174. UI::handleKeyboard(leftshiftKey, modShift);
  175. }
  176. if (((mods & GLFW_MOD_CONTROL) != 0) != modControl) {
  177. modControl = (mods & GLFW_MOD_CONTROL) != 0;
  178. UI::handleKeyboard(leftctrlKey, modControl);
  179. }
  180. if (((mods & GLFW_MOD_ALT) != 0) != modAlt) {
  181. modAlt = (mods & GLFW_MOD_ALT) != 0;
  182. UI::handleKeyboard(leftaltKey, modAlt);
  183. }
  184. if (((mods & GLFW_MOD_SUPER) != 0) != modSuper) {
  185. modSuper = (mods & GLFW_MOD_SUPER) != 0;
  186. UI::handleKeyboard(leftguiKey, modSuper);
  187. }
  188. KeyboardButton b;
  189. switch (button) {
  190. case GLFW_MOUSE_BUTTON_LEFT:
  191. b = leftmouseKey;
  192. break;
  193. case GLFW_MOUSE_BUTTON_RIGHT:
  194. b = rightmouseKey;
  195. break;
  196. case GLFW_MOUSE_BUTTON_MIDDLE:
  197. b = middlemouseKey;
  198. break;
  199. default:
  200. b = unknownKey;
  201. break;
  202. }
  203. UI::handleMouseClick(lastMouseX, lastMouseY, b, (action == GLFW_RELEASE));
  204. }
  205. void WindowGLFW::scrollCallback(GLFWwindow* w, double xoffset, double yoffset) {
  206. UI::handleMouseScroll(xoffset, yoffset);
  207. }
  208. KeyboardButton WindowGLFW::convertAsciiButton(int key) {
  209. // Alphanumerics can be returned as is
  210. if ((key >= '0') && (key <= '9')) {
  211. return static_cast<KeyboardButton>(key);
  212. } else if ((key >= 'A') && (key <= 'Z')) {
  213. key = key - 'A' + 'a';
  214. return static_cast<KeyboardButton>(key);
  215. }
  216. //! \fixme GLFW requires keyboard layout, currently US is hard coded!
  217. switch (key) {
  218. case ' ':
  219. return spaceKey;
  220. case '!':
  221. return oneKey;
  222. case '@':
  223. return twoKey;
  224. case '#':
  225. return threeKey;
  226. case '$':
  227. return fourKey;
  228. case '%':
  229. return fiveKey;
  230. case '^':
  231. return sixKey;
  232. case '&':
  233. return sevenKey;
  234. case '*':
  235. return eightKey;
  236. case '(':
  237. return nineKey;
  238. case ')':
  239. return zeroKey;
  240. case '"':
  241. case '\'':
  242. return quoteKey;
  243. case '+':
  244. case '=':
  245. return equalsKey;
  246. case ',':
  247. case '<':
  248. return commaKey;
  249. case '-':
  250. case '_':
  251. return minusKey;
  252. case '.':
  253. case '>':
  254. return dotKey;
  255. case '/':
  256. case '?':
  257. return slashKey;
  258. case ':':
  259. case ';':
  260. return semicolonKey;
  261. case '[':
  262. case '{':
  263. return leftbracketKey;
  264. case ']':
  265. case '}':
  266. return rightbracketKey;
  267. case '\\':
  268. case '|':
  269. return backslashKey;
  270. case '`':
  271. case '~':
  272. return backquoteKey;
  273. case GLFW_KEY_TAB:
  274. return tabKey;
  275. case GLFW_KEY_BACKSPACE:
  276. return backspaceKey;
  277. case GLFW_KEY_ENTER:
  278. return enterKey;
  279. case GLFW_KEY_ESCAPE:
  280. return escapeKey;
  281. case GLFW_KEY_F1:
  282. return f1Key;
  283. case GLFW_KEY_F2:
  284. return f2Key;
  285. case GLFW_KEY_F3:
  286. return f3Key;
  287. case GLFW_KEY_F4:
  288. return f4Key;
  289. case GLFW_KEY_F5:
  290. return f5Key;
  291. case GLFW_KEY_F6:
  292. return f6Key;
  293. case GLFW_KEY_F7:
  294. return f7Key;
  295. case GLFW_KEY_F8:
  296. return f8Key;
  297. case GLFW_KEY_F9:
  298. return f9Key;
  299. case GLFW_KEY_F10:
  300. return f10Key;
  301. case GLFW_KEY_F11:
  302. return f11Key;
  303. case GLFW_KEY_F12:
  304. return f12Key;
  305. case GLFW_KEY_LEFT:
  306. return leftKey;
  307. case GLFW_KEY_UP:
  308. return upKey;
  309. case GLFW_KEY_RIGHT:
  310. return rightKey;
  311. case GLFW_KEY_DOWN:
  312. return downKey;
  313. case GLFW_KEY_PAGE_UP:
  314. return pageupKey;
  315. case GLFW_KEY_PAGE_DOWN:
  316. return pagedownKey;
  317. case GLFW_KEY_HOME:
  318. return homeKey;
  319. case GLFW_KEY_END:
  320. return endKey;
  321. case GLFW_KEY_INSERT:
  322. return insertKey;
  323. default:
  324. return unknownKey;
  325. }
  326. }