1 // Written in the D programming language.
2 /++
3  + Authors: KanzakiKino
4  + Copyright: KanzakiKino 2018
5  + License: LGPL-3.0
6 ++/
7 module g4d.glfw.window;
8 import g4d.gl.lib,
9        g4d.glfw.cursor,
10        g4d.glfw.handler,
11        g4d.glfw.lib;
12 import gl3n.linalg;
13 import std.conv,
14        std.string;
15 
16 /// Hints of Window.
17 enum WindowHint
18 {
19     None      = 0x0000,
20     Resizable = 0b0001,
21     Maximized = 0b0010,
22     Floating  = 0b0100,
23     Visible   = 0b1000,
24 }
25 
26 /// A class of GLFWwindow.
27 /// Initializing GLFW will be executed automatically if it's necessary.
28 class Window
29 {
30     private static __gshared bool _loadedLibraries = false;
31     private static loadLibraries ()
32     {
33         if ( !_loadedLibraries ) {
34             initGLFW();
35             initGL();
36             Cursor.createStandardCursors();
37         }
38         _loadedLibraries = true;
39     }
40 
41     /// Handles events of all window.
42     static void pollEvents ()
43     {
44         enforce!glfwPollEvents();
45     }
46 
47     protected GLFWwindow* _window;
48 
49     /// Event handlers.
50     EventHandler handler;
51 
52     ///
53     this ( vec2i sz, string text, int hint = WindowHint.None )
54     {
55         loadLibraries();
56 
57         enforce!glfwWindowHint( GLFW_RESIZABLE, hint & WindowHint.Resizable );
58         enforce!glfwWindowHint(   GLFW_VISIBLE, hint & WindowHint.Visible   );
59         enforce!glfwWindowHint(  GLFW_FLOATING, hint & WindowHint.Floating  );
60         enforce!glfwWindowHint( GLFW_MAXIMIZED, hint & WindowHint.Maximized );
61 
62         enforce!glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
63         enforce!glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
64         enforce!glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
65 
66         _window = enforce!glfwCreateWindow(
67                 sz.x, sz.y, text.toStringz, null, null );
68         handler = EventHandler( _window );
69 
70         enforce!glfwMakeContextCurrent( _window );
71         DerelictGL3.reload();
72     }
73 
74     ///
75     ~this ()
76     {
77         dispose();
78     }
79     /// Checks if the window is disposed.
80     const @property disposed ()
81     {
82         return !_window;
83     }
84     /// Deletes the window.
85     void dispose ()
86     {
87         if ( !disposed ) {
88             enforce!glfwDestroyWindow( _window );
89         }
90         _window = null;
91     }
92 
93     /// Checks if the window shouldn't close.
94     const @property bool alive ()
95     {
96         return !enforce!glfwWindowShouldClose(
97                 cast(GLFWwindow*)_window );
98     }
99 
100     /// Prepares the window to draw.
101     /// This method doesn't clear the buffers.
102     /// The saved exception at handler will be throwed from here.
103     void resetFrame ()
104     {
105         if ( handler.throwedException ) {
106             throw handler.throwedException;
107         }
108         enforce!glfwMakeContextCurrent( _window );
109         DerelictGL3.reload();
110 
111         auto size = size;
112         enforce!glViewport( 0,0, size.x, size.y );
113     }
114     /// Swaps the back and front buffers.
115     void applyFrame ()
116     {
117         enforce!glfwSwapBuffers( _window );
118     }
119 
120     /// Sets title of the window. (writeonly)
121     @property void title ( string text )
122     {
123         enforce!glfwSetWindowTitle( _window, text.toStringz );
124     }
125 
126     /// Gets position of the window.
127     const @property vec2i pos ()
128     {
129         int x, y;
130         enforce!glfwGetWindowPos(
131                 cast(GLFWwindow*)_window, &x, &y );
132         return vec2i(x,y);
133     }
134     /// Sets position of the window.
135     @property void pos ( vec2i p )
136     {
137         enforce!glfwSetWindowPos( _window, p.x, p.y );
138     }
139 
140     /// Gets size of the window.
141     const @property vec2i size ()
142     {
143         int w, h;
144         enforce!glfwGetWindowSize(
145                 cast(GLFWwindow*)_window, &w, &h );
146         return vec2i(w,h);
147     }
148     /// Sets size of the window.
149     @property void size ( vec2i sz )
150     {
151         enforce!glfwSetWindowSize( _window, sz.x, sz.y );
152     }
153     /// Sets aspect ratio of the window.
154     @property void aspectRatio ( vec2i ratio )
155     {
156         enforce!glfwSetWindowAspectRatio(
157                 _window, ratio.x, ratio.y );
158     }
159     /// Sets size limitations.
160     void setClampSize ( vec2i min, vec2i max )
161     {
162         enforce!glfwSetWindowSizeLimits(
163                 _window, min.x, min.y, max.x, max.y );
164     }
165 
166     /// Sets cursor shape for the window. (writeonly)
167     @property void cursor ( in Cursor c )
168     {
169         enforce!glfwSetCursor(
170                 _window, cast(GLFWcursor*)c.ptr );
171     }
172 
173     /// Shows the hidden window.
174     void show ()
175     {
176         enforce!glfwShowWindow( _window );
177     }
178     /// Hides the shown window.
179     void hide ()
180     {
181         enforce!glfwHideWindow( _window );
182     }
183     /// Focuses to the unfocused window.
184     void focus ()
185     {
186         enforce!glfwFocusWindow( _window );
187     }
188     /// Closes the opened window.
189     void close ()
190     {
191         enforce!glfwSetWindowShouldClose( _window, true );
192     }
193 
194     /// Minimizes the window.
195     void minimize ()
196     {
197         enforce!glfwIconifyWindow( _window );
198     }
199     /// Maximizes the window.
200     void maximize ()
201     {
202         enforce!glfwMaximizeWindow( _window );
203     }
204     /// Restores the window.
205     void restore ()
206     {
207         enforce!glfwRestoreWindow( _window );
208     }
209 }