Skip to content

Commit bdf1bb7

Browse files
committed
initial sdl3
1 parent 68b03c1 commit bdf1bb7

File tree

5 files changed

+426
-1
lines changed

5 files changed

+426
-1
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(GAMEWINDOW_SOURCES include/game_window.h include/game_window_manager.h src/g
88
set(GAMEWINDOW_SOURCES_LINUX_GAMEPAD src/joystick_manager_linux_gamepad.cpp src/joystick_manager_linux_gamepad.h src/window_with_linux_gamepad.cpp src/window_with_linux_gamepad.h)
99
set(GAMEWINDOW_SOURCES_EGLUT src/window_eglut.h src/window_eglut.cpp src/window_manager_eglut.cpp src/window_manager_eglut.h)
1010
set(GAMEWINDOW_SOURCES_GLFW src/window_glfw.h src/window_glfw.cpp src/window_manager_glfw.cpp src/window_manager_glfw.h src/joystick_manager_glfw.cpp src/joystick_manager_glfw.h)
11+
set(GAMEWINDOW_SOURCES_SDL3 src/window_sdl3.h src/window_sdl3.cpp src/window_manager_sdl3.cpp src/window_manager_sdl3.h)
1112

1213
add_library(gamewindow ${GAMEWINDOW_SOURCES})
1314
target_include_directories(gamewindow PUBLIC include/)
@@ -23,4 +24,7 @@ elseif (GAMEWINDOW_SYSTEM STREQUAL "GLFW")
2324
target_link_libraries(gamewindow PUBLIC eglut linux-gamepad)
2425
target_compile_definitions(gamewindow PRIVATE FALLBACK_EGLUT)
2526
endif()
26-
endif()
27+
elseif (GAMEWINDOW_SYSTEM STREQUAL "SDL3")
28+
target_sources(gamewindow PRIVATE ${GAMEWINDOW_SOURCES_SDL3})
29+
target_link_libraries(gamewindow PRIVATE SDL3::SDL3)
30+
endif()

src/window_manager_sdl3.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include "window_manager_sdl3.h"
2+
#include "window_sdl3.h"
3+
#include <stdexcept>
4+
5+
#include <SDL3/SDL.h>
6+
7+
SDL3WindowManager::SDL3WindowManager() {
8+
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD);
9+
}
10+
11+
GameWindowManager::ProcAddrFunc SDL3WindowManager::getProcAddrFunc() {
12+
return (GameWindowManager::ProcAddrFunc) SDL_GL_GetProcAddress;
13+
}
14+
15+
std::shared_ptr<GameWindow> SDL3WindowManager::createWindow(const std::string& title, int width, int height,
16+
GraphicsApi api) {
17+
return std::shared_ptr<GameWindow>(new SDL3GameWindow(title, width, height, api));
18+
}
19+
20+
void SDL3WindowManager::addGamepadMappingFile(const std::string &path) {
21+
SDL_AddGamepadMappingsFromFile(path.data());
22+
}
23+
24+
void SDL3WindowManager::addGamePadMapping(const std::string &content) {
25+
SDL_AddGamepadMapping(content.data());
26+
}
27+
28+
// Define this window manager as the used one
29+
std::shared_ptr<GameWindowManager> GameWindowManager::createManager() {
30+
return std::shared_ptr<GameWindowManager>(new SDL3WindowManager());
31+
}

src/window_manager_sdl3.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "game_window_manager.h"
4+
5+
class SDL3WindowManager : public GameWindowManager {
6+
7+
public:
8+
SDL3WindowManager();
9+
10+
ProcAddrFunc getProcAddrFunc() override;
11+
12+
std::shared_ptr<GameWindow> createWindow(const std::string& title, int width, int height, GraphicsApi api) override;
13+
14+
void addGamepadMappingFile(const std::string& path) override;
15+
16+
void addGamePadMapping(const std::string &content) override;
17+
};

src/window_sdl3.cpp

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
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

Comments
 (0)