-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathWindowMan.h
More file actions
312 lines (234 loc) · 14.9 KB
/
WindowMan.h
File metadata and controls
312 lines (234 loc) · 14.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#pragma once
#include "Singleton.h"
#include "glm/fwd.hpp"
#include "glad/gl.h"
#include <memory>
#include <vector>
#define g_WindowMan WindowMan::Instance()
extern "C" {
struct SDL_Window;
struct SDL_Renderer;
struct SDL_Texture;
struct SDL_Rect;
struct SDL_GLContextState;
union SDL_Event;
}
namespace RTE {
class Shader;
class RenderTarget;
struct SDLWindowDeleter {
void operator()(SDL_Window* window) const;
};
struct SDLRendererDeleter {
void operator()(SDL_Renderer* renderer) const;
};
struct SDLTextureDeleter {
void operator()(SDL_Texture* texture) const;
};
struct SDLContextDeleter {
void operator()(SDL_GLContextState* context) const;
};
/// The singleton manager over the game window and display of frames.
class WindowMan : public Singleton<WindowMan> {
friend class SettingsMan;
public:
#pragma region Creation
/// Constructor method used to instantiate a WindowMan object in system memory. Initialize() should be called before using the object.
WindowMan();
/// Makes the WindowMan object ready for use.
void Initialize();
#pragma endregion
#pragma region Destruction
/// Destructor method used to clean up a WindowMan object before deletion from system memory.
~WindowMan();
/// Clean up GL pointers.
void Destroy();
#pragma endregion
#pragma region Getters and Setters
/// Gets a pointer to the primary game window. OWNERSHIP IS NOT TRANSFERRED!
/// @return Pointer to the primary game window.
SDL_Window* GetWindow() const { return m_PrimaryWindow.get(); }
/// Gets whether any of the game windows is currently in focus.
/// @return Whether any of the game windows is currently in focus.
bool AnyWindowHasFocus() const { return m_AnyWindowHasFocus; }
/// Gets the maximum horizontal resolution the game can be resized to.
/// @return The maximum horizontal resolution the game can be resized to.
int GetMaxResX() const { return m_MaxResX; }
/// Gets the maximum vertical resolution the game can be resized to.
/// @return The maximum vertical resolution the game can be resized to.
int GetMaxResY() const { return m_MaxResY; }
/// Gets the horizontal resolution the game is currently sized at.
/// @return The horizontal resolution the game is currently sized at, in pixels.
int GetResX() const { return m_ResX; }
/// Gets the vertical resolution the game is currently sized at.
/// @return The vertical resolution the game is currently sized at, in pixels.
int GetResY() const { return m_ResY; }
/// Gets the horizontal resolution the game window is currently sized at, in pixels.
/// @return The horizontal resolution the game window is currently sized at, in pixels.
int GetWindowResX();
/// Gets the vertical resolution the game window is currently sized at, in pixels.
/// @return The vertical resolution the game window is currently sized at, in pixels.
int GetWindowResY();
/// Gets how many times the game resolution is currently being multiplied and the backbuffer stretched across for better readability.
/// @return What multiple the game resolution is currently sized at.
float GetResMultiplier() const { return m_ResMultiplier; }
/// Gets whether VSync is enabled.
/// @return Whether VSync is enabled.
bool GetVSyncEnabled() const { return m_EnableVSync; }
/// Sets whether VSync is enabled.
/// @param enable Whether to enable VSync.
void SetVSyncEnabled(bool enable);
/// Gets whether the game window is currently in fullscreen.
/// @return Whether the game window is currently in fullscreen.
bool IsFullscreen() { return m_Fullscreen; }
/// Gets whether the multi-display arrangement should be used or whether only the display the main window is currently positioned at should be used for fullscreen.
/// @return Whether the multi-display arrangement is used.
bool GetUseMultiDisplays() const { return m_UseMultiDisplays; }
/// Sets whether the multi-display arrangement should be used or whether only the display the main window is currently positioned at should be used for fullscreen.
/// @param use Whether the multi-display arrangement should be used
void SetUseMultiDisplays(bool use) { m_UseMultiDisplays = use; }
/// Checks whether the current resolution settings fully cover all the available displays.
/// @return Whether the current resolution settings fully cover all the available displays.
bool FullyCoversAllDisplays() const { return m_NumDisplays > 1 && (m_ResX * m_ResMultiplier == m_MaxResX) && (m_ResY * m_ResMultiplier == m_MaxResY); }
/// Gets the absolute left-most position in the OS display arrangement. Used for correcting mouse position in multi-display fullscreen when the left-most display is not primary.
/// @return The absolute left-most position in the OS display arrangement.
int GetDisplayArrangementAbsOffsetX() const { return std::abs(m_DisplayArrangementLeftMostOffset); }
/// Gets the absolute top-most position in the OS display arrangement. Used for correcting mouse position in multi-display fullscreen when the left-most display is not primary.
/// @return The absolute top-most position in the OS display arrangement.
int GetDisplayArrangementAbsOffsetY() const { return std::abs(m_DisplayArrangementTopMostOffset); }
/// Get the screen buffer texture.
/// @return The screen buffer texture.
std::shared_ptr<RenderTarget> GetScreenBuffer() const { return m_ScreenBuffer; }
void RefocusWindow() const;
#pragma endregion
#pragma region Resolution Change Handling
/// Attempts to figure our what the hell the OS display arrangement is and what are the resolution capabilities for single or multi-display fullscreen.
/// @param updatePrimaryDisplayInfo Whether to update the stored info of the display the primary window is currently positioned at.
void MapDisplays(bool updatePrimaryDisplayInfo = true);
/// Gets the horizontal resolution of the display the primary game window is currently positioned at.
/// @return The horizontal resolution of the display the primary game window is currently positioned at.
int GetPrimaryWindowDisplayWidth() const { return m_PrimaryWindowDisplayWidth; }
/// Gets the vertical resolution of the display the primary game window is currently positioned at.
/// @return The vertical resolution of the display the primary game window is currently positioned at.
int GetPrimaryWindowDisplayHeight() const { return m_PrimaryWindowDisplayHeight; }
/// Gets whether the game resolution was changed.
/// @return Whether the game resolution was changed.
bool ResolutionChanged() const { return m_ResolutionChanged; }
/// Switches the game resolution to the specified dimensions.
/// @param newResX New width to resize to.
/// @param newResY New height to resize to.
/// @param upscaled Whether the new resolution should be upscaled.
/// @param displaysAlreadyMapped Whether to skip mapping displays because they were already mapped elsewhere.
void ChangeResolution(int newResX, int newResY, float newResMultiplier = 1.0f, bool fullscreen = false, bool displaysAlreadyMapped = false);
/// Toggles between windowed and fullscreen mode (single display).
void ToggleFullscreen();
/// Completes the resolution change by resetting the flag.
void CompleteResolutionChange() { m_ResolutionChanged = false; }
#pragma endregion
#pragma region Concrete Methods
/// SDL_EventFilter to handle window exposed events for live resize.
static bool HandleWindowExposedEvent(void* userdata, SDL_Event* event);
/// Adds an SDL_Event to the Event queue for processing on Update.
/// @param windowEvent The SDL window event to queue.
void QueueWindowEvent(const SDL_Event& windowEvent);
/// Updates the state of this WindowMan.
void Update();
/// Clears the window framebuffer (FBO0).
void ClearBackbuffer(bool clearFrameMan = true);
/// Set this Frame to draw the game. To be set before UploadFrame. Resets on ClearBackbuffer.
void DrawPostProcessBuffer() { m_DrawPostProcessBuffer = true; }
/// Copies the BackBuffer32 content to GPU and shows it on screen.
void UploadFrame();
void Present();
#pragma endregion
private:
std::vector<SDL_Event> m_EventQueue; //!< List of incoming window events.
bool m_FocusEventsDispatchedByMovingBetweenWindows; //!< Whether queued events were dispatched due to raising windows when moving between windows in multi-display fullscreen in the previous update.
bool m_FocusEventsDispatchedByDisplaySwitchIn; //!< Whether queued events were dispatched due to raising windows when taking focus of any game window in the previous update.
std::shared_ptr<SDL_Window> m_PrimaryWindow; //!< The main window.
GLuint m_BackBuffer32Texture; //!< Streaming texture for the software rendered stuff.
std::shared_ptr<RenderTarget> m_ScreenBuffer{};
std::unique_ptr<SDL_Rect> m_PrimaryWindowViewport; //!< Viewport for the main window.
std::vector<std::shared_ptr<SDL_Window>> m_MultiDisplayWindows; //!< Additional windows for multi-display fullscreen.
std::vector<glm::mat4> m_MultiDisplayProjections; //!< Projection Matrices for MultiDisplay.
std::vector<glm::mat4> m_MultiDisplayTextureOffsets; //!< Texture offsets for multi-display fullscreen.
std::unique_ptr<SDL_GLContextState, SDLContextDeleter> m_GLContext; //!< OpenGL context.
GLuint m_ScreenVAO; //!< Vertex Array Object for the screen quad.
GLuint m_ScreenVBO; //!< Vertex Buffer Object for the screen quad.
std::unique_ptr<Shader> m_ScreenBlitShader; //!< Blit shader to combine the menu layer and post process layers and show them on screen.
bool m_AnyWindowHasFocus; //!< Whether any game window has focus.
bool m_ResolutionChanged; //!< Whether the resolution was changed through the settings.
int m_NumDisplays; //!< Number of physical displays.
int m_MaxResX; //!< Maximum width the game window can be (desktop width).
int m_MaxResY; //!< Maximum height the game window can be (desktop height).
std::vector<std::pair<int, SDL_Rect>> m_ValidDisplayIndicesAndBoundsForMultiDisplayFullscreen; //!< Display indices and bounds that can be used for multi-display fullscreen.
bool m_CanMultiDisplayFullscreen; //!< Whether the display arrangement allows switching to multi-display fullscreen.
int m_DisplayArrangmentLeftMostDisplayIndex; //!< The index of the left-most screen in the OS display arrangement.
int m_DisplayArrangementLeftMostOffset; //!< The left-most position in the OS display arrangement.
int m_DisplayArrangementTopMostOffset; //!< The top-most position in the OS display arrangement.
int m_PrimaryWindowDisplayIndex; //!< The index of the display the main window is currently positioned at.
int m_PrimaryWindowDisplayWidth; //!< The width of the display the main window is currently positioned at.
int m_PrimaryWindowDisplayHeight; //!< The height of the display the main window is currently positioned at.
int m_ResX; //!< Game window width.
int m_ResY; //!< Game window height.
float m_ResMultiplier; //!< The number of times the game window and image should be multiplied and stretched across for better visibility.
float m_MaxResMultiplier; //!< The maximum resolution multiplier before the game starts breaking.
bool m_Fullscreen; //!< Whether the game window is currently in fullscreen.
bool m_EnableVSync; //!< Whether vertical synchronization is enabled.
bool m_UseMultiDisplays; //!< Whether the multi-display arrangement should be ignored and only the display the main window is currently positioned at should be used for fullscreen.
bool m_DrawPostProcessBuffer; //!< Whether to draw the PostProcessBuffer while not in Activity. Resets on Frame Clear.
#pragma region Initialize Breakdown
/// Creates the main game window.
void CreatePrimaryWindow();
/// Initializes all opengl objects (textures, vbo, vao, and fbo).
void InitializeOpenGL();
/// Creates the main game window renderer's drawing surface.
void CreateBackBufferTexture();
#pragma endregion
#pragma region Resolution Handling
void SetViewportLetterboxed();
/// Updates the stored info of the display the primary window is currently positioned at.
void UpdatePrimaryDisplayInfo();
/// Gets the maximum available window bounds for a decorated window on the specified display.
/// May not provide accurate results if the window is in fullscreen or has just been created.
/// @param display The display to get the bounds for.
/// @return The maximum available window bounds for a decorated window on the specified display.
SDL_Rect GetUsableBoundsWithDecorations(int display);
/// Calculates whether the given resolution and multiplier would create a maximized window.
/// @param resX Game window width to check.
/// @param resY Game window height to check.
/// @param resMultiplier Game window resolution multiplier to check.
/// @return Whether the given resolution and multiplier create a maximized window.
bool IsResolutionMaximized(int resX, int resY, float resMultiplier);
/// Checks whether the passed in resolution settings make sense. If not, overrides them to prevent crashes or unexpected behavior.
/// @param resX Game window width to check.
/// @param resY Game window height to check.
/// @param resMultiplier Game window resolution multiplier to check.
void ValidateResolution(int& resX, int& resY, float& resMultiplier) const;
/// Attempts to revert to the previous resolution settings if the new ones failed for whatever reason. Will recursively attempt to revert to defaults if previous settings fail as well.
/// @param revertToDefaults Whether to attempt to revert to defaults. Will be set by this.
void AttemptToRevertToPreviousResolution(bool revertToDefaults = false);
#pragma endregion
#pragma region Multi-Display Handling
/// Clears all the multi-display data, resetting the game to a single-window-single-display state.
void ClearMultiDisplayData();
/// Resize the window to enable fullscreen on multiple displays, using the arrangement info gathered during display mapping.
/// @param resMultiplier Requested resolution multiplier.
/// @return Whether all displays were created successfully.
bool ChangeResolutionToMultiDisplayFullscreen(float resMultiplier);
#pragma endregion
#pragma region Display Switch Handling
/// Handles focus gain when switching back to the game window.
/// @param windowThatShouldTakeInputFocus The window that should take focus of input after all the windows are raised. This is only relevant in multi-display fullscreen.
void DisplaySwitchIn(SDL_Window* windowThatShouldTakeInputFocus) const;
/// Handles focus loss when switching away from the game window.
/// Will temporarily disable positioning of the mouse so that when focus is switched back to the game window, the game window won't fly away because the user clicked the title bar of the window.
void DisplaySwitchOut() const;
#pragma endregion
/// Clears all the member variables of this WindowMan, effectively resetting the members of this abstraction level only.
void Clear();
// Disallow the use of some implicit methods.
WindowMan(const WindowMan& reference) = delete;
WindowMan& operator=(const WindowMan& rhs) = delete;
};
} // namespace RTE