1
+ #include " window_sdl3.h"
2
+ #include " game_window_manager.h"
3
+
4
+ #include < codecvt>
5
+ #include < iomanip>
6
+ #include < thread>
7
+
8
+ #include < math.h>
9
+ #include < SDL3/SDL.h>
10
+
11
+ SDL3GameWindow::SDL3GameWindow (const std::string& title, int width, int height, GraphicsApi api) :
12
+ GameWindow(title, width, height, api), width(width), height(height), windowedWidth(width), windowedHeight(height) {
13
+ if (api == GraphicsApi::OPENGL_ES2) {
14
+ SDL_GL_SetAttribute (SDL_GL_CONTEXT_FLAGS, 0 );
15
+ SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
16
+ SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
17
+ SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0 );
18
+ }
19
+ SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1 );
20
+ SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24 );
21
+ SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 8 );
22
+ window = SDL_CreateWindow (title.data (), width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
23
+ if (window == nullptr ) {
24
+ // Throw an exception, otherwise it would crash due to a nullptr without any information
25
+ const char * error = SDL_GetError ();
26
+ throw std::runtime_error (error == nullptr ? " SDL3 failed to create a window without any error message" : error);
27
+ }
28
+ context = SDL_GL_CreateContext (window);
29
+ if (context == nullptr ) {
30
+ SDL_DestroyWindow (window);
31
+ const char * error = SDL_GetError ();
32
+ throw std::runtime_error (error == nullptr ? " SDL3 failed to create a window context without any error message" : error);
33
+ }
34
+ SDL_GL_MakeCurrent (window, context);
35
+
36
+ setRelativeScale ();
37
+ }
38
+
39
+ void SDL3GameWindow::makeCurrent (bool c) {
40
+ SDL_GL_MakeCurrent (window, c ? context : nullptr );
41
+ }
42
+
43
+ SDL3GameWindow::~SDL3GameWindow () {
44
+ SDL_DestroyWindow (window);
45
+ }
46
+
47
+ void SDL3GameWindow::setIcon (std::string const & iconPath) {
48
+ // TODO:
49
+ }
50
+
51
+ void SDL3GameWindow::setRelativeScale () {
52
+ int fx, fy;
53
+ SDL_GetWindowSizeInPixels (window, &fx, &fy);
54
+
55
+ int wx, wy;
56
+ SDL_GetWindowSize (window, &wx, &wy);
57
+
58
+ relativeScale = (int ) floor (((fx / wx) + (fy / wy)) / 2 );
59
+ // Update window size to match content size mismatch
60
+ width = fx;
61
+ height = fy;
62
+ resized = true ;
63
+ }
64
+
65
+ int SDL3GameWindow::getRelativeScale () const {
66
+ return relativeScale;
67
+ }
68
+
69
+ void SDL3GameWindow::getWindowSize (int & width, int & height) const {
70
+ width = this ->width ;
71
+ height = this ->height ;
72
+ }
73
+
74
+ void SDL3GameWindow::show () {
75
+ SDL_ShowWindow (window);
76
+ }
77
+
78
+ void SDL3GameWindow::close () {
79
+ }
80
+
81
+ static GamepadButtonId getKeyGamePad (int btn) {
82
+ switch (btn)
83
+ {
84
+ case SDL_GAMEPAD_BUTTON_SOUTH:
85
+ return GamepadButtonId::A;
86
+ case SDL_GAMEPAD_BUTTON_EAST:
87
+ return GamepadButtonId::B;
88
+ case SDL_GAMEPAD_BUTTON_WEST:
89
+ return GamepadButtonId::X;
90
+ case SDL_GAMEPAD_BUTTON_NORTH:
91
+ return GamepadButtonId::Y;
92
+ case SDL_GAMEPAD_BUTTON_BACK:
93
+ return GamepadButtonId::BACK;
94
+ case SDL_GAMEPAD_BUTTON_GUIDE:
95
+ return GamepadButtonId::GUIDE;
96
+ case SDL_GAMEPAD_BUTTON_START:
97
+ return GamepadButtonId::START;
98
+ case SDL_GAMEPAD_BUTTON_LEFT_STICK:
99
+ return GamepadButtonId::LEFT_STICK;
100
+ case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
101
+ return GamepadButtonId::RIGHT_STICK;
102
+ case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
103
+ return GamepadButtonId::LB;
104
+ case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
105
+ return GamepadButtonId::RB;
106
+ case SDL_GAMEPAD_BUTTON_DPAD_UP:
107
+ return GamepadButtonId::DPAD_UP;
108
+ case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
109
+ return GamepadButtonId::DPAD_DOWN;
110
+ case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
111
+ return GamepadButtonId::DPAD_LEFT;
112
+ case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
113
+ return GamepadButtonId::DPAD_RIGHT;
114
+ default :
115
+ return GamepadButtonId::UNKNOWN;
116
+ }
117
+ }
118
+
119
+ static GamepadAxisId getAxisGamepad (int btn) {
120
+ switch (btn)
121
+ {
122
+ case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
123
+ return GamepadAxisId::LEFT_TRIGGER;
124
+ case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
125
+ return GamepadAxisId::RIGHT_TRIGGER;
126
+ case SDL_GAMEPAD_AXIS_LEFTX:
127
+ return GamepadAxisId::LEFT_X;
128
+ case SDL_GAMEPAD_AXIS_LEFTY:
129
+ return GamepadAxisId::LEFT_Y;
130
+ case SDL_GAMEPAD_AXIS_RIGHTX:
131
+ return GamepadAxisId::RIGHT_X;
132
+ case SDL_GAMEPAD_AXIS_RIGHTY:
133
+ return GamepadAxisId::RIGHT_Y;
134
+ default :
135
+ return GamepadAxisId::UNKNOWN;
136
+ }
137
+ }
138
+
139
+ void SDL3GameWindow::pollEvents () {
140
+ SDL_Event ev;
141
+ while (SDL_PollEvent (&ev)) {
142
+ switch (ev.type )
143
+ {
144
+ case SDL_EVENT_MOUSE_MOTION:
145
+ if (!SDL_GetRelativeMouseMode ()) {
146
+ onMousePosition (ev.motion .x , ev.motion .y );
147
+ } else {
148
+ onMouseRelativePosition (ev.motion .xrel , ev.motion .yrel );
149
+ }
150
+ break ;
151
+ case SDL_EVENT_MOUSE_WHEEL:
152
+ onMouseScroll (ev.wheel .mouseX , ev.wheel .mouseY , ev.wheel .x , ev.wheel .y );
153
+ break ;
154
+ case SDL_EVENT_MOUSE_BUTTON_DOWN:
155
+ case SDL_EVENT_MOUSE_BUTTON_UP:
156
+ onMouseButton (ev.button .x , ev.button .y , ev.button .button , ev.type == SDL_EVENT_MOUSE_BUTTON_DOWN ? MouseButtonAction::PRESS : MouseButtonAction::RELEASE);
157
+ break ;
158
+ case SDL_EVENT_FINGER_DOWN:
159
+ onTouchStart (ev.tfinger .fingerId , ev.tfinger .x , ev.tfinger .y );
160
+ break ;
161
+ case SDL_EVENT_FINGER_UP:
162
+ onTouchEnd (ev.tfinger .fingerId , ev.tfinger .x , ev.tfinger .y );
163
+ break ;
164
+ case SDL_EVENT_FINGER_MOTION:
165
+ onTouchUpdate (ev.tfinger .fingerId , ev.tfinger .x , ev.tfinger .y );
166
+ break ;
167
+ case SDL_EVENT_KEY_DOWN:
168
+ case SDL_EVENT_KEY_UP:
169
+ onKeyboard (getKeyMinecraft (ev.key .keysym .sym ), ev.type == SDL_EVENT_KEY_DOWN ? ev.key .repeat ? KeyAction::REPEAT : KeyAction::PRESS : KeyAction::RELEASE );
170
+ break ;
171
+ case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
172
+ case SDL_EVENT_GAMEPAD_BUTTON_UP:
173
+ onGamepadButton (ev.gbutton .which , getKeyGamePad (ev.gbutton .button ), ev.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
174
+ break ;
175
+ case SDL_EVENT_GAMEPAD_AXIS_MOTION:
176
+ onGamepadAxis (ev.gbutton .which , getAxisGamepad (ev.gbutton .button ), ev.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
177
+ break ;
178
+ case SDL_EVENT_GAMEPAD_ADDED:
179
+ case SDL_EVENT_GAMEPAD_REMOVED:
180
+ onGamepadState (ev.gdevice .which , ev.type == SDL_EVENT_GAMEPAD_ADDED);
181
+ break ;
182
+ case SDL_EVENT_WINDOW_RESIZED:
183
+ width = ev.window .data1 ;
184
+ height = ev.window .data2 ;
185
+ onWindowSizeChanged (ev.window .data1 , ev.window .data2 );
186
+ break ;
187
+ case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
188
+ onClose ();
189
+ default :
190
+ break ;
191
+ }
192
+ }
193
+ }
194
+
195
+ void SDL3GameWindow::setCursorDisabled (bool disabled) {
196
+ SDL_SetRelativeMouseMode (disabled);
197
+ }
198
+
199
+ void SDL3GameWindow::setFullscreen (bool fullscreen) {
200
+ SDL_SetWindowFullscreen (window, fullscreen);
201
+ }
202
+
203
+ void SDL3GameWindow::setClipboardText (std::string const &text) {
204
+ SDL_SetClipboardText (text.data ());
205
+ }
206
+
207
+ void SDL3GameWindow::swapBuffers () {
208
+ SDL_GL_SwapWindow (window);
209
+ }
210
+
211
+ void SDL3GameWindow::setSwapInterval (int interval) {
212
+ SDL_GL_SetSwapInterval (interval);
213
+ }
214
+
215
+ KeyCode SDL3GameWindow::getKeyMinecraft (int keyCode) {
216
+ if (keyCode >= SDLK_F1 && keyCode <= SDLK_F12)
217
+ return (KeyCode) (keyCode - SDLK_F1 + (int ) KeyCode::FN1);
218
+ if (keyCode >= SDLK_KP_0 && keyCode <= SDLK_KP_9)
219
+ return (KeyCode) (keyCode - SDLK_KP_0 + (int ) KeyCode::NUMPAD_0);
220
+ if (keyCode >= SDLK_a && keyCode <= SDLK_z)
221
+ return (KeyCode) (keyCode - SDLK_a + (int ) KeyCode::A);
222
+ switch (keyCode) {
223
+ case SDLK_BACKSPACE:
224
+ return KeyCode::BACKSPACE;
225
+ case SDLK_TAB:
226
+ return KeyCode::TAB;
227
+ case SDLK_RETURN:
228
+ return KeyCode::ENTER;
229
+ case SDLK_LSHIFT:
230
+ return KeyCode::LEFT_SHIFT;
231
+ case SDLK_RSHIFT:
232
+ return KeyCode::RIGHT_SHIFT;
233
+ case SDLK_LCTRL:
234
+ return KeyCode::LEFT_CTRL;
235
+ case SDLK_RCTRL:
236
+ return KeyCode::RIGHT_CTRL;
237
+ case SDLK_PAUSE:
238
+ return KeyCode::PAUSE;
239
+ case SDLK_CAPSLOCK:
240
+ return KeyCode::CAPS_LOCK;
241
+ case SDLK_ESCAPE:
242
+ return KeyCode::ESCAPE;
243
+ case SDLK_PAGEUP:
244
+ return KeyCode::PAGE_UP;
245
+ case SDLK_PAGEDOWN:
246
+ return KeyCode::PAGE_DOWN;
247
+ case SDLK_END:
248
+ return KeyCode::END;
249
+ case SDLK_HOME:
250
+ return KeyCode::HOME;
251
+ case SDLK_LEFT:
252
+ return KeyCode::LEFT;
253
+ case SDLK_UP:
254
+ return KeyCode::UP;
255
+ case SDLK_RIGHT:
256
+ return KeyCode::RIGHT;
257
+ case SDLK_DOWN:
258
+ return KeyCode::DOWN;
259
+ case SDLK_INSERT:
260
+ return KeyCode::INSERT;
261
+ case SDLK_DELETE:
262
+ return KeyCode::DELETE;
263
+ case SDLK_NUMLOCKCLEAR:
264
+ return KeyCode::NUM_LOCK;
265
+ case SDLK_SCROLLLOCK:
266
+ return KeyCode::SCROLL_LOCK;
267
+ case SDLK_SEMICOLON:
268
+ return KeyCode::SEMICOLON;
269
+ case SDLK_EQUALS:
270
+ return KeyCode::EQUAL;
271
+ case SDLK_COMMA:
272
+ return KeyCode::COMMA;
273
+ case SDLK_MINUS:
274
+ return KeyCode::MINUS;
275
+ case SDLK_PERIOD:
276
+ return KeyCode::PERIOD;
277
+ case SDLK_SLASH:
278
+ return KeyCode::SLASH;
279
+ case SDLK_BACKQUOTE:
280
+ return KeyCode::GRAVE;
281
+ case SDLK_LEFTBRACKET:
282
+ return KeyCode::LEFT_BRACKET;
283
+ case SDLK_BACKSLASH:
284
+ return KeyCode::BACKSLASH;
285
+ case SDLK_RIGHTBRACKET:
286
+ return KeyCode::RIGHT_BRACKET;
287
+ case SDLK_QUOTE:
288
+ return KeyCode::APOSTROPHE;
289
+ case SDLK_LGUI:
290
+ return KeyCode::LEFT_SUPER;
291
+ case SDLK_RGUI:
292
+ return KeyCode::RIGHT_SUPER;
293
+ case SDLK_LALT:
294
+ return KeyCode::LEFT_ALT;
295
+ case SDLK_RALT:
296
+ return KeyCode::RIGHT_ALT;
297
+ case SDLK_KP_ENTER:
298
+ return KeyCode::ENTER;
299
+ case SDLK_KP_MINUS:
300
+ return KeyCode::NUMPAD_SUBTRACT;
301
+ case SDLK_KP_MULTIPLY:
302
+ return KeyCode::NUMPAD_MULTIPLY;
303
+ case SDLK_KP_PLUS:
304
+ return KeyCode::NUMPAD_ADD;
305
+ case SDLK_KP_DIVIDE:
306
+ return KeyCode::NUMPAD_DIVIDE;
307
+ case SDLK_KP_DECIMAL:
308
+ return KeyCode::NUMPAD_DECIMAL;
309
+ }
310
+ if (keyCode < 256 )
311
+ return (KeyCode) keyCode;
312
+ return KeyCode::UNKNOWN;
313
+ }
0 commit comments