1 module evael.system.window; 2 3 import std.traits : EnumMembers; 4 import std.experimental.logger; 5 6 public import bindbc.glfw; 7 8 import evael.core.game_config : GraphicsSettings; 9 import evael.system.cursor; 10 11 import evael.lib.memory : NoGCClass; 12 import evael.lib..string : Cstring; 13 14 /** 15 * Window. 16 * 17 * High-level interface to GLFWWindow. 18 */ 19 class Window : NoGCClass 20 { 21 /// GLFW window handle 22 private GLFWwindow* m_glfwWindow; 23 24 /// GLFW cursors 25 private GLFWcursor*[Cursor] m_cursors; 26 27 /// Current cursor 28 private Cursor m_currentCursor; 29 30 mixin(GLFWCallback!("onWindowClose", "GLFWwindowclosefun")); 31 mixin(GLFWCallback!("onWindowSize", "GLFWwindowsizefun")); 32 mixin(GLFWCallback!("onCursorPos", "GLFWcursorposfun")); 33 mixin(GLFWCallback!("onMouseButton", "GLFWmousebuttonfun")); 34 mixin(GLFWCallback!("onScroll", "GLFWscrollfun")); 35 mixin(GLFWCallback!("onKey", "GLFWkeyfun")); 36 mixin(GLFWCallback!("onChar", "GLFWcharfun")); 37 38 /** 39 * Window constructor. 40 * Params: 41 * title : window title 42 * settings : window settings 43 */ 44 @nogc 45 public this(in string title, in ref GraphicsSettings graphicsSettings) 46 { 47 glfwWindowHint(GLFW_RESIZABLE, graphicsSettings.resizable); 48 49 this.m_glfwWindow = glfwCreateWindow(graphicsSettings.width, graphicsSettings.height, 50 Cstring(title), graphicsSettings.fullscreen ? glfwGetPrimaryMonitor() : null, null); 51 52 /*foreach(cursor; [EnumMembers!(Cursor)]) 53 { 54 this.m_cursors[cursor] = glfwCreateStandardCursor(cursor); 55 } 56 57 this.setCursor(Cursor.Arrow);*/ 58 } 59 60 /** 61 * Window destructor. 62 */ 63 @nogc 64 public ~this() 65 { 66 foreach (cursor; this.m_cursors.byValue()) 67 { 68 glfwDestroyCursor(cursor); 69 } 70 71 glfwDestroyWindow(this.m_glfwWindow); 72 } 73 74 /** 75 * Polls window events. 76 */ 77 @nogc 78 public void pollEvents() nothrow 79 { 80 glfwSwapBuffers(this.m_glfwWindow); 81 glfwPollEvents(); 82 } 83 84 /** 85 * Sets window cursor. 86 * Params: 87 * cursor: cursor to set 88 */ 89 @nogc 90 public void setCursor(in Cursor cursor) nothrow 91 { 92 if (this.m_currentCursor == cursor) 93 { 94 return; 95 } 96 97 auto cursorPtr = cursor in this.m_cursors; 98 99 if (cursorPtr !is null) 100 { 101 this.m_currentCursor = cursor; 102 glfwSetCursor(this.m_glfwWindow, *cursorPtr); 103 } 104 } 105 106 /** 107 * Hides cursor. 108 */ 109 @nogc 110 public void hideCursor() nothrow 111 { 112 glfwSetInputMode(this.m_glfwWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); 113 } 114 115 @nogc 116 @property nothrow 117 { 118 GLFWwindow* glfwWindow() 119 { 120 return this.m_glfwWindow; 121 } 122 } 123 } 124 125 template GLFWCallback(string name, string glfwCallback) 126 { 127 string GLFWCallbackImpl() 128 { 129 enum callbackName = name ~ "Callback"; 130 return "@nogc @property public void " ~ name ~ "(" ~ glfwCallback ~ " cb) { glfwSet" ~ callbackName[2..$] ~ "(this.m_glfwWindow, cb); }"; 131 } 132 133 enum GLFWCallback = GLFWCallbackImpl; 134 }