commit 87387d9

uint  ·  2026-08-03 12:36:29 +0000 UTC
parent 8e4434f
platform agnostic key handling
8 files changed,  +224, -76
M TODO
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