1 /* 2 Copyright © 2020, Luna Nielsen 3 Distributed under the 2-Clause BSD License, see LICENSE file. 4 5 Authors: Luna Nielsen 6 */ 7 module engine.core.window; 8 import bindbc.glfw; 9 import bindbc.opengl; 10 import engine.render : kmViewport; 11 12 /** 13 Static instance of the game window 14 */ 15 static Window GameWindow; 16 17 /** 18 A Window 19 */ 20 class Window { 21 private: 22 GLFWwindow* window; 23 string title_; 24 int width_; 25 int height_; 26 27 int fbWidth; 28 int fbHeight; 29 30 public: 31 32 /** 33 Destructor 34 */ 35 ~this() { 36 glfwDestroyWindow(window); 37 } 38 39 /** 40 Constructor 41 */ 42 this(string title = "My Game", int width = 640, int height = 480) { 43 this.title_ = title; 44 this.width_ = width; 45 this.height_ = height; 46 this.fbWidth = width; 47 this.fbHeight = height; 48 49 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 50 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 51 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // To make macOS happy 52 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); 53 window = glfwCreateWindow(640, 480, this.title_.ptr, null, null); 54 55 } 56 57 /** 58 Hides the window 59 */ 60 void hide() { 61 glfwHideWindow(window); 62 } 63 64 /** 65 Show window 66 */ 67 void show() { 68 glfwShowWindow(window); 69 } 70 71 /** 72 Gets the title of the window 73 */ 74 @property string title() { 75 return this.title_; 76 } 77 78 /** 79 Sets the title of the window 80 */ 81 @property void title(string value) { 82 this.title_ = value; 83 glfwSetWindowTitle(window, this.title_.ptr); 84 } 85 86 /** 87 Gets the width of the window's framebuffer 88 */ 89 @property int width() { 90 return this.fbWidth; 91 } 92 93 /** 94 Gets the height of the window's framebuffer 95 */ 96 @property int height() { 97 return this.fbHeight; 98 } 99 100 /** 101 Resizes the window 102 */ 103 void resize(int width, int height) { 104 this.width_ = width; 105 this.height_ = height; 106 glfwSetWindowSize(window, width, height); 107 } 108 109 /** 110 Gets whether the window is fullscreen 111 */ 112 bool fullscreen() { 113 return glfwGetWindowMonitor(window) !is null; 114 } 115 116 /** 117 Sets the window's fullscreen state 118 */ 119 void fullscreen(bool value) { 120 if (this.fullscreen == value) return; 121 122 // TODO: change state 123 // HACK: currently we're just setting the window as borderless 124 if (value) { 125 const(GLFWvidmode)* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); 126 this.resize(mode.width, mode.height); 127 glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE); 128 } else { 129 glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_TRUE); 130 } 131 } 132 133 /** 134 poll for new window events 135 */ 136 void update() { 137 glfwPollEvents(); 138 glfwGetFramebufferSize(window, &fbWidth, &fbHeight); 139 } 140 141 /** 142 Set the close request flag 143 */ 144 void close() { 145 glfwSetWindowShouldClose(window, 1); 146 } 147 148 /** 149 Gets whether the window has requested to close (aka the game is requested to exit) 150 */ 151 bool isExitRequested() { 152 return cast(bool)glfwWindowShouldClose(window); 153 } 154 155 /** 156 Makes the OpenGL context of the window current 157 */ 158 void makeCurrent() { 159 glfwMakeContextCurrent(window); 160 } 161 162 /** 163 Swaps the OpenGL buffers for the window 164 */ 165 void swapBuffers() { 166 glfwSwapBuffers(window); 167 } 168 169 /** 170 Sets the swap interval, by default vsync 171 */ 172 void setSwapInterval(SwapInterval interval = SwapInterval.VSync) { 173 glfwSwapInterval(cast(int)interval); 174 } 175 176 /** 177 Resets the OpenGL viewport to fit the window 178 */ 179 void resetViewport() { 180 kmViewport(0, 0, width, height); 181 } 182 183 /** 184 Gets the glfw window pointer 185 */ 186 GLFWwindow* winPtr() { 187 return window; 188 } 189 } 190 191 /** 192 A swap interval 193 */ 194 enum SwapInterval : int { 195 Unlimited = 0, 196 VSync = 1 197 }