commit 87387d9
uint
·
2026-08-03 12:36:29 +0000 UTC
parent 8e4434f
platform agnostic key handling
8 files changed,
+224,
-76
M
TODO
+4,
-2
1@@ -1,11 +1,13 @@
2 uint:
3+[ ] Maus wayland
4+[ ] Separate SDL from main.c
5+
6 [X] Wireframe
7 [-] Face Hiding
8 [-] Chunk meshing
9 [ ] Greedily
10-[ ] Separate SDL from main.c
11 [ ] Render multiplayer
12 [ ] Fonts
13-[ ] Maus wayland
14 [ ] MGEvents abstraction
15+[ ] Check it works on Windows
16
+97,
-0
1@@ -0,0 +1,97 @@
2+#ifndef KEYS_H
3+#define KEYS_H
4+
5+#define MG_KEYS_DOWN_MAX 64
6+
7+#ifdef MG_PLATFORM_SDL
8+#include <SDL2/SDL_keycode.h>
9+typedef SDL_Keycode MGKey;
10+enum {
11+ MGK_UNKNOWN = SDLK_UNKNOWN,
12+
13+ MGK_A = SDLK_a, MGK_B = SDLK_b, MGK_C = SDLK_c,
14+ MGK_D = SDLK_d, MGK_E = SDLK_e, MGK_F = SDLK_f,
15+ MGK_G = SDLK_g, MGK_H = SDLK_h, MGK_I = SDLK_i,
16+ MGK_J = SDLK_j, MGK_K = SDLK_k, MGK_L = SDLK_l,
17+ MGK_M = SDLK_m, MGK_N = SDLK_n, MGK_O = SDLK_o,
18+ MGK_P = SDLK_p, MGK_Q = SDLK_q, MGK_R = SDLK_r,
19+ MGK_S = SDLK_s, MGK_T = SDLK_t, MGK_U = SDLK_u,
20+ MGK_V = SDLK_v, MGK_W = SDLK_w, MGK_X = SDLK_x,
21+ MGK_Y = SDLK_y, MGK_Z = SDLK_z,
22+
23+ MGK_0 = SDLK_0, MGK_1 = SDLK_1, MGK_2 = SDLK_2,
24+ MGK_3 = SDLK_3, MGK_4 = SDLK_4, MGK_5 = SDLK_5,
25+ MGK_6 = SDLK_6, MGK_7 = SDLK_7, MGK_8 = SDLK_8,
26+ MGK_9 = SDLK_9,
27+
28+ MGK_RETURN = SDLK_RETURN,
29+ MGK_ESCAPE = SDLK_ESCAPE,
30+ MGK_BACKSPACE = SDLK_BACKSPACE,
31+ MGK_TAB = SDLK_TAB,
32+ MGK_SPACE = SDLK_SPACE,
33+
34+ MGK_MINUS = SDLK_MINUS,
35+ MGK_EQUALS = SDLK_EQUALS,
36+ MGK_LEFTBRACKET = SDLK_LEFTBRACKET,
37+ MGK_RIGHTBRACKET = SDLK_RIGHTBRACKET,
38+ MGK_BACKSLASH = SDLK_BACKSLASH,
39+ MGK_SEMICOLON = SDLK_SEMICOLON,
40+ MGK_APOSTROPHE = SDLK_QUOTE,
41+ MGK_GRAVE = SDLK_BACKQUOTE,
42+ MGK_COMMA = SDLK_COMMA,
43+ MGK_PERIOD = SDLK_PERIOD,
44+ MGK_SLASH = SDLK_SLASH,
45+
46+ MGK_CAPSLOCK = SDLK_CAPSLOCK,
47+
48+ MGK_F1 = SDLK_F1, MGK_F2 = SDLK_F2, MGK_F3 = SDLK_F3,
49+ MGK_F4 = SDLK_F4, MGK_F5 = SDLK_F5, MGK_F6 = SDLK_F6,
50+ MGK_F7 = SDLK_F7, MGK_F8 = SDLK_F8, MGK_F9 = SDLK_F9,
51+ MGK_F10 = SDLK_F10, MGK_F11 = SDLK_F11, MGK_F12 = SDLK_F12,
52+
53+ MGK_PRINTSCREEN = SDLK_PRINTSCREEN,
54+ MGK_SCROLLLOCK = SDLK_SCROLLLOCK,
55+ MGK_PAUSE = SDLK_PAUSE,
56+ MGK_INSERT = SDLK_INSERT,
57+ MGK_HOME = SDLK_HOME,
58+ MGK_PAGEUP = SDLK_PAGEUP,
59+ MGK_DELETE = SDLK_DELETE,
60+ MGK_END = SDLK_END,
61+ MGK_PAGEDOWN = SDLK_PAGEDOWN,
62+ MGK_RIGHT = SDLK_RIGHT,
63+ MGK_LEFT = SDLK_LEFT,
64+ MGK_DOWN = SDLK_DOWN,
65+ MGK_UP = SDLK_UP,
66+
67+ MGK_NUMLOCKCLEAR = SDLK_NUMLOCKCLEAR,
68+ MGK_KP_DIVIDE = SDLK_KP_DIVIDE,
69+ MGK_KP_MULTIPLY = SDLK_KP_MULTIPLY,
70+ MGK_KP_MINUS = SDLK_KP_MINUS,
71+ MGK_KP_PLUS = SDLK_KP_PLUS,
72+ MGK_KP_ENTER = SDLK_KP_ENTER,
73+ MGK_KP_0 = SDLK_KP_0,
74+ MGK_KP_1 = SDLK_KP_1,
75+ MGK_KP_2 = SDLK_KP_2,
76+ MGK_KP_3 = SDLK_KP_3,
77+ MGK_KP_4 = SDLK_KP_4,
78+ MGK_KP_5 = SDLK_KP_5,
79+ MGK_KP_6 = SDLK_KP_6,
80+ MGK_KP_7 = SDLK_KP_7,
81+ MGK_KP_8 = SDLK_KP_8,
82+ MGK_KP_9 = SDLK_KP_9,
83+ MGK_KP_PERIOD = SDLK_KP_PERIOD,
84+
85+ MGK_LCTRL = SDLK_LCTRL,
86+ MGK_LSHIFT = SDLK_LSHIFT,
87+ MGK_LALT = SDLK_LALT,
88+ MGK_LGUI = SDLK_LGUI,
89+ MGK_RCTRL = SDLK_RCTRL,
90+ MGK_RSHIFT = SDLK_RSHIFT,
91+ MGK_RALT = SDLK_RALT,
92+ MGK_RGUI = SDLK_RGUI
93+};
94+
95+#else /* libmaus */
96+#endif
97+
98+#endif /* KEYS_H */
+10,
-13
1@@ -1,20 +1,14 @@
2 #ifndef PLATFORM_H
3 #define PLATFORM_H
4
5-#include <SDL2/SDL.h>
6-
7 #include "types.h"
8+#include "platform/keys.h"
9
10-typedef SDL_Window MGWindow;
11-
12-typedef struct {
13-#ifdef MG_RENDERER_SMALL3DLIB
14- SDL_Renderer* renderer;
15+#ifdef MG_PLATFORM_SDL
16+ #include "platform/platform_sdl.h"
17+#elif MG_PLATFORM_MAUS
18+ /* TODO */
19 #endif
20-#ifdef MG_RENDERER_SOKOL
21- SDL_GLContext gl;
22-#endif
23-} MGVidBE;
24
25 typedef struct {
26 MGWindow* win;
27@@ -24,15 +18,18 @@ typedef struct {
28 i32 y;
29 i32 width;
30 i32 height;
31+ MGKey keys[MG_KEYS_DOWN_MAX];
32 } MGContext;
33
34-/* get drawable screen size. usually different due to hi-dpi options
35- > probably can stub out on software renderer */
36+/* get drawable screen size. usually different due to hi-dpi options */
37 void platform_get_drawable_size(MGContext* ctx, i32* width, i32* height);
38
39 /* initialise resources */
40 void platform_init(MGContext* ctx);
41
42+/* check if a logical key is pressed */
43+i32 platform_key_down(MGContext* ctx, MGKey key);
44+
45 /* poll for next events */
46 i32 platform_poll(MGContext* ctx);
47
+17,
-0
1@@ -0,0 +1,17 @@
2+#ifndef PLATFORM_SDL_H
3+#define PLATFORM_SDL_H
4+
5+#include <SDL2/SDL.h>
6+
7+typedef SDL_Window MGWindow;
8+
9+typedef struct {
10+#ifdef MG_RENDERER_SMALL3DLIB
11+ SDL_Renderer* renderer;
12+#endif
13+#ifdef MG_RENDERER_SOKOL
14+ SDL_GLContext gl;
15+#endif
16+} MGVidBE;
17+
18+#endif /* PLATFORM_SDL_H */
+17,
-4
1@@ -18,6 +18,7 @@ bearssl_dep = cc.find_library('bearssl')
2
3
4 renderer_backend = get_option('renderer')
5+window_backend = get_option('windowing')
6
7 sources = [
8 'source/main.c',
9@@ -32,7 +33,6 @@ sources = [
10 'source/mcproto/client.c',
11 'source/mcproto/crypto.c',
12 'source/mcproto/packet.c',
13- 'source/platform/platform.c',
14 'vendor/stb_image_c89.c',
15 ]
16
17@@ -60,9 +60,21 @@ mgmath_dep = declare_dependency(
18 )
19
20 renderer_c_args = []
21+platform_c_args = []
22 renderer_sources = [
23 'source/renderer/renderer.c',
24 ]
25+
26+if window_backend == 'sdl'
27+ sources += [ 'source/platform/platform_sdl.c' ]
28+ platform_c_args += [ '-DMG_PLATFORM_SDL' ]
29+ platform_dep = declare_dependency(dependencies: sdl_dep)
30+elif window_backend == 'maus'
31+ sources += [ 'source/platform/platform_maus.c' ]
32+ platform_c_args += [ '-DMG_PLATFORM_MAUS' ]
33+ platform_dep = declare_dependency(dependencies: sdl_dep)
34+endif
35+
36 if renderer_backend == 'sokol'
37 opengl_dep = dependency('opengl', required: false)
38 if not opengl_dep.found() # fallback (at least for alpine)
39@@ -98,7 +110,7 @@ renderer_lib = static_library(
40 renderer_sources,
41 include_directories: include_dirs,
42 dependencies: renderer_backend_dep,
43- c_args: renderer_c_args,
44+ c_args: platform_c_args + renderer_c_args,
45 override_options: [ 'c_std=c99' ],
46 )
47
48@@ -106,10 +118,11 @@ renderer_dep = declare_dependency(
49 include_directories: include_dirs,
50 link_with: renderer_lib,
51 dependencies: renderer_backend_dep,
52+ compile_args: platform_c_args,
53 )
54
55 deps = [
56- sdl_dep,
57+ platform_dep,
58 zlib_dep,
59 tls_dep,
60 bearssl_dep,
61@@ -130,7 +143,7 @@ executable(
62 sources,
63 include_directories: include_dirs,
64 dependencies: deps,
65- c_args: renderer_c_args,
66+ c_args: platform_c_args + renderer_c_args,
67 link_args: extra_libs,
68 override_options: [ 'c_std=c99' ],
69 )
+8,
-0
1@@ -5,3 +5,11 @@ option(
2 value: 'sokol',
3 description: '3D renderer backend',
4 )
5+
6+option(
7+ 'windowing',
8+ type: 'combo',
9+ choices: [ 'sdl', 'maus' ],
10+ value: 'sdl',
11+ description: 'Windowing backend',
12+)
+14,
-53
1@@ -10,20 +10,19 @@
2 #include "renderer/test_scene.h"
3
4 static MGContext ctx = {
5- NULL, { NULL }, "Magnolia", 0, 0, 1024, 768,
6+ NULL, { NULL }, "Magnolia", 0, 0, 1024, 768, { MGK_UNKNOWN },
7 };
8
9 static void input(void)
10 {
11 static u32 last;
12
13- const u8* keys = SDL_GetKeyboardState(NULL);
14- MGVec3 move = MG_V3(0.0f, 0.0f, 0.0f);
15- u32 now = SDL_GetTicks();
16- float sensitivity = mg_config.input_sensitivity;
17- float dt;
18- i32 mx;
19- i32 my;
20+ MGVec3 move = MG_V3(0.0f, 0.0f, 0.0f);
21+ u32 now = SDL_GetTicks();
22+ float sensitivity = mg_config.input_sensitivity;
23+ float dt;
24+ i32 mx;
25+ i32 my;
26
27 if (!last) {
28 last = now;
29@@ -33,21 +32,21 @@ static void input(void)
30 dt = (float)(now - last) / 1000.0f;
31 last = now;
32
33- if (keys[SDL_SCANCODE_W])
34+ if (platform_key_down(&ctx, MGK_W))
35 move.z += 1.0f;
36- if (keys[SDL_SCANCODE_A])
37+ if (platform_key_down(&ctx, MGK_A))
38 move.x -= 1.0f;
39- if (keys[SDL_SCANCODE_S])
40+ if (platform_key_down(&ctx, MGK_S))
41 move.z -= 1.0f;
42- if (keys[SDL_SCANCODE_D])
43+ if (platform_key_down(&ctx, MGK_D))
44 move.x += 1.0f;
45- if (keys[SDL_SCANCODE_SPACE])
46+ if (platform_key_down(&ctx, MGK_SPACE))
47 move.y += 1.0f;
48- if (keys[SDL_SCANCODE_LCTRL])
49+ if (platform_key_down(&ctx, MGK_LCTRL))
50 move.y -= 1.0f;
51
52 /* debug keys */
53- if (keys[SDL_SCANCODE_L]) {
54+ if (platform_key_down(&ctx, MGK_L)) {
55 mg_config.debug_wireframe = !mg_config.debug_wireframe;
56 renderer_debug_wireframe(mg_config.debug_wireframe);
57 }
58@@ -58,44 +57,6 @@ static void input(void)
59 camera_rotate(&cam, mx * sensitivity, -my * sensitivity);
60 }
61
62-static int protocol_poc(const char* address, const char* username)
63-{
64- MCAccount account;
65- MCClient* client;
66- char error[1024];
67-
68- account.username = username;
69- account.profile_uuid = getenv("MANGOLIA_PROFILE_UUID");
70- account.access_token = getenv("MANGOLIA_ACCESS_TOKEN");
71- if (!mc_client_login(&client, address, &account, error, sizeof(error))) {
72- fprintf(stderr, "%s\n", error);
73- return MG_ERR_EXIT_FAILURE;
74- }
75- /* offline mode protocol test:
76- packet keep alive is play/clientbound 0x00 in protocol 47
77- https://prismarinejs.github.io/minecraft-data/protocol/pc/1.8/#play.toClient.types.packet_keep_alive */
78- puts("entered play state: printing packet ids and echoing keepalives");
79- for (;;) {
80- MCPacket packet;
81- if (!mc_client_read(client, &packet, error, sizeof(error))) {
82- fprintf(stderr, "%s\n", error);
83- mc_client_destroy(client);
84- return MG_ERR_EXIT_FAILURE;
85- }
86- printf("play packet 0x%02x size %lu\n", packet.id, (unsigned long)packet.size);
87- if (packet.id == 0x00) {
88- if (!mc_client_write(client, 0x00, packet.data, packet.size)) {
89- fprintf(stderr, "failed to echo keepalive\n");
90- mc_packet_free(&packet);
91- mc_client_destroy(client);
92- return MG_ERR_EXIT_FAILURE;
93- }
94- puts("echoed keepalive");
95- }
96- mc_packet_free(&packet);
97- }
98-}
99-
100 int main(int argc, char** argv)
101 {
102 MCClient* client = NULL;
R source/platform/platform.c =>
source/platform/platform_sdl.c
+57,
-4
1@@ -3,6 +3,35 @@
2 #include "util.h"
3 #include "platform/platform.h"
4
5+/* set the state of a logical key */
6+static void platform_key_set(MGContext* ctx, MGKey key, i32 down);
7+
8+static void platform_key_set(MGContext* ctx, MGKey key, i32 down)
9+{
10+ int i;
11+
12+ if (key == MGK_UNKNOWN)
13+ return;
14+
15+ for (i = 0; i < MG_KEYS_DOWN_MAX; i++) {
16+ if (ctx->keys[i] == key) {
17+ if (!down)
18+ ctx->keys[i] = MGK_UNKNOWN;
19+ return;
20+ }
21+ }
22+
23+ if (!down)
24+ return;
25+
26+ for (i = 0; i < MG_KEYS_DOWN_MAX; i++) {
27+ if (ctx->keys[i] == MGK_UNKNOWN) {
28+ ctx->keys[i] = key;
29+ return;
30+ }
31+ }
32+}
33+
34 void platform_get_drawable_size(MGContext* ctx, i32* width, i32* height)
35 {
36 #ifdef MG_RENDERER_SMALL3DLIB
37@@ -14,12 +43,16 @@ void platform_get_drawable_size(MGContext* ctx, i32* width, i32* height)
38
39 void platform_init(MGContext* ctx)
40 {
41- (void)ctx;
42+ int i;
43+
44+ for (i = 0; i < MG_KEYS_DOWN_MAX; i++)
45+ ctx->keys[i] = MGK_UNKNOWN;
46+
47 if (SDL_Init(SDL_INIT_VIDEO) != 0)
48 mg_die(MG_ERR_SDL_INIT, "SDL_Init failed: %s", SDL_GetError());
49
50 #ifdef MG_RENDERER_SOKOL
51- /* TODO: OpenGL specifis */
52+ /* TODO: OpenGL specifics */
53 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
54 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
55 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
56@@ -28,17 +61,22 @@ void platform_init(MGContext* ctx)
57 #endif
58 }
59
60-/* TODO: platform independant design MGEvent, MGPoll */
61 i32 platform_poll(MGContext* ctx)
62 {
63 SDL_Event ev;
64+
65 while (SDL_PollEvent(&ev)) {
66 switch (ev.type) {
67 case SDL_QUIT:
68 return 0;
69
70+ case SDL_KEYDOWN:
71+ case SDL_KEYUP:
72+ platform_key_set(ctx, ev.key.keysym.sym, ev.type == SDL_KEYDOWN);
73+ break;
74+
75 case SDL_WINDOWEVENT:
76- if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { /* resize */
77+ if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
78 ctx->width = ev.window.data1;
79 ctx->height = ev.window.data2;
80 }
81@@ -48,6 +86,21 @@ i32 platform_poll(MGContext* ctx)
82 return 1;
83 }
84
85+i32 platform_key_down(MGContext* ctx, MGKey key)
86+{
87+ int i;
88+
89+ if (!ctx || key == MGK_UNKNOWN)
90+ return 0;
91+
92+ for (i = 0; i < MG_KEYS_DOWN_MAX; i++) {
93+ if (ctx->keys[i] == key)
94+ return 1;
95+ }
96+
97+ return 0;
98+}
99+
100 void platform_present(MGContext* ctx)
101 {
102 #ifdef MG_RENDERER_SMALL3DLIB