1 /* 2 Copyright (c) 2013 Andrey Penechko 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license the "Software" to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 module anchovy.graphics.windows.glfwwindow; 30 31 private 32 { 33 import std.conv : to; 34 import std.stdio; 35 import std.string; 36 import anchovy.core.interfaces.iwindow; 37 } 38 39 public 40 { 41 import derelict.glfw3.glfw3; 42 import derelict.opengl3.gl3; 43 import anchovy.utils.string; 44 } 45 46 class GlfwWindow : IWindow 47 { 48 public: 49 50 override void init(uvec2 size, in string caption) 51 { 52 if (!glfwInited) 53 { 54 initGlfw(); 55 } 56 57 scope(failure) glfwTerminate(); 58 59 _size = size; 60 61 //BUG: sometimes fails in Windows 8. Maybe because of old drivers. 62 _window = glfwCreateWindow(_size.x, _size.y, toStringz(caption), null, null); 63 64 if (_window is null) 65 { 66 throw new Error("Error creating GLFW3 window"); 67 } 68 69 glfwMakeContextCurrent(_window); 70 glfwSwapInterval(0); 71 72 glClearColor(1.0, 1.0, 1.0, 1.0); 73 glViewport(0, 0, _size.x, _size.y); 74 75 DerelictGL3.reload(); 76 77 glfwSetWindowUserPointer(_window, cast(void*)this); 78 glfwSetWindowPosCallback(_window, &windowposfun); 79 glfwSetFramebufferSizeCallback(_window, &windowsizefun); 80 glfwSetWindowCloseCallback(_window, &windowclosefun); 81 //glfwSetWindowRefreshCallback(_window, &windowrefreshfun); 82 glfwSetWindowFocusCallback(_window, &windowfocusfun); 83 glfwSetWindowIconifyCallback(_window, &windowiconifyfun); 84 glfwSetMouseButtonCallback(_window, &mousebuttonfun); 85 glfwSetCursorPosCallback(_window, &cursorposfun); 86 glfwSetScrollCallback(_window, &scrollfun); 87 glfwSetKeyCallback(_window, &keyfun); 88 glfwSetCharCallback(_window, &charfun); 89 90 91 //glfwSetCursorEnterCallback(window, GLFWcursorenterfun cbfun); 92 } 93 94 override void processEvents() 95 { 96 glfwPollEvents(); 97 } 98 99 override double elapsedTime() @property //in seconds 100 { 101 return glfwGetTime(); 102 } 103 104 override void reshape(uvec2 viewportSize) 105 { 106 glViewport(0, 0, cast(int)viewportSize.x, cast(int)viewportSize.y); 107 } 108 109 override void releaseWindow() 110 { 111 glfwDestroyWindow(_window); 112 glfwTerminate(); 113 } 114 115 override void mousePosition(ivec2 newPosition) @property 116 { 117 glfwSetCursorPos(_window, newPosition.x, newPosition.y); 118 } 119 120 override ivec2 mousePosition() @property 121 { 122 double x, y; 123 glfwGetCursorPos(_window, &x, &y); 124 return ivec2(cast(int)x, cast(int)y); 125 } 126 127 override void swapBuffers() 128 { 129 glfwSwapBuffers(_window); 130 } 131 132 override void grabMouse(){} 133 134 override void releaseMouse(){} 135 136 override void size(uvec2 newSize) @property 137 { 138 glfwSetWindowSize(_window, cast(int)newSize.x, cast(int)newSize.y); 139 } 140 141 override uvec2 size() @property 142 { 143 int width, height; 144 glfwGetWindowSize(_window, &width, &height); 145 return uvec2(cast(uint)width, cast(uint)height); 146 } 147 148 override string clipboardString() @property 149 { 150 const(char*) data = glfwGetClipboardString(_window); 151 if (data is null) return ""; 152 return ZToString(data); 153 } 154 155 override void clipboardString(string newClipboardString) @property 156 { 157 glfwSetClipboardString(_window, toStringz(newClipboardString)); 158 } 159 160 override bool isKeyPressed(uint key) 161 { 162 return glfwGetKey(_window, key) == GLFW_PRESS; 163 } 164 165 protected: 166 167 static void initGlfw() 168 { 169 DerelictGLFW3.load(); 170 DerelictGL3.load(); 171 172 glfwSetErrorCallback(&errorfun); 173 174 if (glfwInit() == 0) 175 { 176 throw new Error("Error initializing GLFW3"); //TODO: add proper error handling 177 } 178 179 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 180 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); 181 //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 182 183 glfwInited = true; 184 } 185 186 private: 187 188 189 GLFWwindow* _window; 190 uvec2 _size; 191 192 bool _mouseGrabbed = false; 193 194 static bool glfwInited = false; 195 } 196 197 static GlfwWindow getWinFromUP(GLFWwindow* w) nothrow 198 { 199 GlfwWindow win; 200 win = cast(GlfwWindow) glfwGetWindowUserPointer(w); 201 return win; 202 } 203 204 extern(C) 205 { 206 static void errorfun(int errorCode, const(char)* msg) nothrow 207 { 208 throw new Error("GLFW error ocured ["~to!string(errorCode)~"] : "~ZToString(msg)); 209 } 210 static void windowposfun(GLFWwindow* w, int nx, int ny) nothrow 211 { 212 try 213 { 214 getWinFromUP(w).windowMoved.emit(ivec2(nx, ny)); 215 } 216 catch(Exception e) 217 { 218 throw new Error(to!string(e)); 219 } 220 } 221 static void windowsizefun(GLFWwindow* w, int newWidth, int newHeight) nothrow 222 { 223 try 224 { 225 getWinFromUP(w).windowResized.emit(uvec2(cast(uint)newWidth, cast(uint)newHeight)); 226 } 227 catch(Exception e) 228 { 229 throw new Error(to!string(e)); 230 } 231 } 232 static void windowclosefun(GLFWwindow* w) nothrow 233 { 234 try 235 { 236 getWinFromUP(w).closePressed.emit();//------------------ 237 } 238 catch(Exception e) 239 { 240 throw new Error(to!string(e)); 241 } 242 } 243 static void windowrefreshfun(GLFWwindow* w) nothrow 244 { 245 246 } 247 static void windowfocusfun(GLFWwindow* w, int focus) nothrow 248 { 249 try 250 { 251 getWinFromUP(w).focusChanged.emit(cast(bool)focus); 252 } 253 catch(Exception e) 254 { 255 throw new Error(to!string(e)); 256 } 257 } 258 static void windowiconifyfun(GLFWwindow* w, int iconified) nothrow 259 { 260 try 261 { 262 getWinFromUP(w).windowIconified.emit(cast(bool)iconified); 263 } 264 catch(Exception e) 265 { 266 throw new Error(to!string(e)); 267 } 268 } 269 static void mousebuttonfun(GLFWwindow* w, int mouseButton, int action, int) nothrow 270 { 271 try 272 { 273 if(action == GLFW_RELEASE) 274 { 275 getWinFromUP(w).mouseReleased.emit(mouseButton); 276 } 277 else 278 { 279 getWinFromUP(w).mousePressed.emit(mouseButton); 280 } 281 } 282 catch(Exception e) 283 { 284 throw new Error(to!string(e)); 285 } 286 } 287 static void cursorposfun(GLFWwindow* w, double nx, double ny) nothrow 288 { 289 try 290 { 291 getWinFromUP(w).mouseMoved.emit(ivec2(cast(int)nx, cast(int)ny)); 292 } 293 catch(Exception e) 294 { 295 throw new Error(to!string(e)); 296 } 297 } 298 static void scrollfun(GLFWwindow* w, double x, double y) nothrow 299 { 300 try 301 { 302 getWinFromUP(w).wheelScrolled.emit(dvec2(x, y)); 303 } 304 catch(Exception e) 305 { 306 throw new Error(to!string(e)); 307 } 308 } 309 static void cursorenterfun(GLFWwindow* w, int) nothrow 310 { 311 312 } 313 static void keyfun(GLFWwindow* w, int key, int, int action, int) nothrow 314 { 315 try 316 { 317 if (action == GLFW_RELEASE) 318 { 319 getWinFromUP(w).keyReleased.emit(key); 320 } 321 else 322 { 323 getWinFromUP(w).keyPressed.emit(key); 324 } 325 } 326 catch(Exception e) 327 { 328 throw new Error(to!string(e)); 329 } 330 } 331 static void charfun(GLFWwindow* w, uint unicode) nothrow 332 { 333 try 334 { 335 getWinFromUP(w).charEntered.emit(cast(dchar)unicode); 336 } 337 catch(Exception e) 338 { 339 throw new Error(to!string(e)); 340 } 341 } 342 }