1 /**
2  * Copyright:       Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:         $(Gabriel Gheorghe)
4  * License:         $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:          $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/core/window.d)
6  * Documentation:
7  * Coverage:
8 **/
9 module liberty.core.window;
10 
11 import std..string : toStringz;
12 
13 import bindbc.glfw;
14 
15 import liberty.core.engine;
16 import liberty.input.event;
17 import liberty.logger;
18 
19 /**
20  * It represents an OS window.
21 **/
22 final class Window {
23   private {
24     int width;
25     int height;
26     GLFWwindow* handle;
27     int frameBufferWidth;
28     int frameBufferHeight;
29     bool fullscreen;
30     int lastXStartPos;
31     int lastYStartPos;
32     int lastXSize;
33     int lastYSize;
34     // getTitle, setTitle
35     string title;
36   }
37 
38   /**
39    * Create a new system window specifying the width, the height and its title.
40   **/
41   this(int width, int height, string title) {
42     // Set window size and title
43     this.width = width;
44     this.height = height;
45     this.title = title;
46 
47     Logger.info(InfoMessage.Creating, typeof(this).stringof);
48 
49     // Create window internally
50     handle = glfwCreateWindow(width, height, title.toStringz, null, null);
51 
52     resizeFrameBuffer();
53     glfwSetFramebufferSizeCallback(handle, &EventManager.frameBufferResizeCallback);
54 
55     // Create the current context
56     glfwMakeContextCurrent(handle);
57 
58     // Check if window is created
59     if (this.handle is null)
60       Logger.error("Failed to create window", typeof(this).stringof);
61 
62     Logger.info(InfoMessage.Created, typeof(this).stringof);
63   }
64 
65   ~this() {
66     Logger.info(InfoMessage.Destroying, typeof(this).stringof);
67 
68     // Destroy the window if not null
69     if (handle !is null) {
70       glfwTerminate();
71       handle = null;
72     } else {
73       Logger.warning(
74         "You are trying to destory a non-existent window",
75         typeof(this).stringof
76       );
77     }
78 
79     Logger.info(InfoMessage.Destroyed, typeof(this).stringof);
80   }
81 
82   /**
83    * Returns window width.
84   **/
85   int getWidth()   const {
86     return width;
87   }
88 
89   /**
90    * Returns window height.
91   **/
92   int getHeight()   const {
93     return height;
94   }
95 
96   /**
97    * Returns handle to this window.
98   **/
99   GLFWwindow* getHandle()   {
100     return handle;
101   }
102 
103   /**
104    * Resize the current frame buffer of the window.
105    * Returns reference to this so it can be used in a stream.
106   **/
107   typeof(this) resizeFrameBuffer() {
108     glfwGetFramebufferSize(handle, &width, &height);
109     return this;
110   }
111 
112   /**
113    * Enter or leave fullscreen mode.
114    * Returns reference to this so it can be used in a stream.
115   **/
116   typeof(this) setFullscreen(bool fullscreen) {
117     if (fullscreen) {
118       // Backup window position and window size
119       glfwGetWindowPos(handle, &lastXStartPos, &lastYStartPos);
120       glfwGetWindowSize(handle, &lastXSize, &lastYSize);
121 
122       // Get resolution of monitor
123       const(GLFWvidmode)* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
124 
125       // Switch to fullscreen
126       glfwSetWindowMonitor(handle, glfwGetPrimaryMonitor(), 0, 0, mode.width, mode.height, 0);
127     } else
128       // Restore last window size and position
129       glfwSetWindowMonitor(handle, null, lastXStartPos, lastYStartPos, lastXSize, lastYSize, 0);
130 
131     // Update vsync state
132     if (CoreEngine.isVSyncEnabled())
133       CoreEngine.enableVSync();
134     else
135       CoreEngine.disableVSync();
136 
137     this.fullscreen = fullscreen;
138     return this;
139   }
140 
141   /**
142    * Swap between window fullscreen and windowed mode.
143   **/
144   typeof(this) swapFullscreen() {
145     return setFullscreen(!fullscreen);
146   }
147 
148   /**
149    * Returns true if window is in fullscreen mode.
150   **/
151   bool isFullscreen()   const {
152     return fullscreen;
153   }
154 
155   /**
156    * Returns true if window should close.
157   **/
158   bool shouldClose() {
159     return cast(bool)glfwWindowShouldClose(handle);
160   }
161 
162   /**
163    * Set window title.
164    * Returns reference to this so it can be used in a stream.
165   **/
166   typeof(this) setTitle(string title)  {
167     this.title = title;
168     glfwSetWindowTitle(handle, title.toStringz);
169     return this;
170   }
171 
172   /**
173    * Returns window title.
174   **/
175   string getTitle()   const {
176     return title;
177   }
178 }