keymapping

This commit is contained in:
2026-07-03 22:07:03 +03:00
parent c809aa98f5
commit 7a98eb4dfb
12 changed files with 248 additions and 119 deletions

View File

@@ -54,7 +54,9 @@ endif
executable( executable(
'scuffedcraft', 'scuffedcraft',
'src/pltf/win32/gl_funcs.c', 'src/pltf/win32/gl_funcs.c',
'src/pltf/win32/internal.c',
'src/pltf/win32/pltf.c', 'src/pltf/win32/pltf.c',
'src/pltf/win32/win_proc.c',
'src/DynArray.c', 'src/DynArray.c',
'src/DynString.c', 'src/DynString.c',
'src/log.c', 'src/log.c',

View File

@@ -2,16 +2,16 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
void log_error(char* file, size_t line, char* str) { void log_with_tag(FILE* out_file, char* file_name, size_t line, const char* tag, char* str) {
fprintf(stderr, "[ERROR] %s:%zu: %s\n", file, line, str); fprintf(out_file, "[%s] %s:%zu: %s\n", tag, file_name, line, str);
} }
void log_errorf(char* file, size_t line, char* fmt, ...) { void logf_with_tag(FILE* out_file, char* file_name, size_t line, const char* tag, char* fmt, ...) {
fprintf(stderr, "[ERROR] %s:%zu: ", file, line); fprintf(out_file, "[%s] %s:%zu: ", tag, file_name, line);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
vfprintf(stderr, fmt, args); vfprintf(out_file, fmt, args);
va_end(args); va_end(args);
fprintf(stderr, "\n"); fprintf(out_file, "\n");
} }

View File

@@ -3,14 +3,18 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#define LOG_ERROR(str) log_error(__FILE__, __LINE__, (str)) #define LOG_ERROR(str) log_with_tag(stderr, __FILE__, __LINE__, "ERROR", (str))
#define LOG_ERRORF(fmt, ...) log_errorf(__FILE__, __LINE__, (fmt), __VA_ARGS__) #define LOG_ERRORF(fmt, ...) logf_with_tag(stderr, __FILE__, __LINE__, "ERROR", (fmt), __VA_ARGS__)
#define LOG_FATAL(str) LOG_ERROR(str); exit(-1); #define LOG_FATAL(str) LOG_ERROR(str); exit(-1)
#define LOG_FATALF(fmt, ...) LOG_ERRORF(fmt, __VA_ARGS__); exit(-1); #define LOG_FATALF(fmt, ...) LOG_ERRORF(fmt, __VA_ARGS__); exit(-1)
void log_error(char* file, size_t line, char* str); #define LOG_FATAL_TODO(str) log_with_tag(stderr, __FILE__, __LINE__, "FATAL TODO", (str)); exit(-1)
void log_errorf(char* file, size_t line, char* fmt, ...); #define LOG_FATAL_TODOF(fmt, ...) logf_with_tag(stderr, __FILE__, __LINE__, "FATAL TODO", (fmt), __VA_ARGS__); exit(-1)
void log_with_tag(FILE* out_file, char* file_name, size_t line, const char* tag, char* str);
void logf_with_tag(FILE* out_file, char* file_name, size_t line, const char* tag, char* fmt, ...);
#endif // LOG_H_ #endif // LOG_H_

View File

@@ -7,6 +7,12 @@
#include "pltf/gl_funcs.h" #include "pltf/gl_funcs.h"
#include "shader.h" #include "shader.h"
void counter_cb(void* user_data) {
int* counter = (int*) user_data;
printf("Counter: %d\n", *counter);
(*counter)++;
}
int main() { int main() {
pltf_init(); pltf_init();
pltf_window_create(); pltf_window_create();
@@ -15,6 +21,10 @@ int main() {
pltf_gl_ctx_info_print(); pltf_gl_ctx_info_print();
pltf_key_callback_set(PLTF_KEY_ESC, pltf_window_close, NULL);
int counter = 0;
pltf_key_callback_set(PLTF_KEY_Q, counter_cb, &counter);
// clang-format off // clang-format off
const float triangle_verts[] = { const float triangle_verts[] = {
// pos // pos
@@ -60,10 +70,6 @@ int main() {
glClearColor(0.0f, 0.0f, 0.8f, 1.0f); glClearColor(0.0f, 0.0f, 0.8f, 1.0f);
while (true) { while (true) {
if (pltf_window_event_handle() == PLTF_WE_QUIT) {
goto cleanup;
}
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader); glUseProgram(shader);
@@ -71,9 +77,13 @@ int main() {
glDrawArrays(GL_TRIANGLES, 0, triangle_vert_count); glDrawArrays(GL_TRIANGLES, 0, triangle_vert_count);
pltf_swap_buffers(); pltf_swap_buffers();
const int pltf_we = pltf_window_event_handle();
if (pltf_we == PLTF_WE_DESTROY) {
break;
}
} }
cleanup:
pltf_gl_ctx_destroy(); pltf_gl_ctx_destroy();
pltf_window_destroy(); pltf_window_destroy();
pltf_deinit(); pltf_deinit();

View File

@@ -5,17 +5,38 @@
typedef enum { typedef enum {
PLTF_WE_NULL, PLTF_WE_NULL,
PLTF_WE_QUIT PLTF_WE_DESTROY,
} PltfWindowEvent; } PltfWindowEvent;
#define PLTF_KEYS(PLTF_KEYS_X) \
PLTF_KEYS_X(esc, ESC) \
PLTF_KEYS_X(q, Q)
#define PLTF_KEYS_X(lower, upper) PLTF_KEY_##upper,
typedef enum {
PLTF_KEY_NONE, // None doesn't need a cb etc. so it's declared outside of the macro and handled specially where needed
PLTF_KEYS(PLTF_KEYS_X)
} PltfKey;
#undef PLTF_KEYS_X
typedef void (*PltfKeyCallback)(void* user_data);
void pltf_init(); void pltf_init();
void pltf_deinit(); void pltf_deinit();
void pltf_window_create(); void pltf_window_create();
void pltf_window_close();
void pltf_window_destroy(); void pltf_window_destroy();
void pltf_gl_ctx_create(); void pltf_gl_ctx_create();
void pltf_gl_ctx_destroy(); void pltf_gl_ctx_destroy();
void pltf_gl_ctx_info_print(); void pltf_gl_ctx_info_print();
void pltf_swap_buffers(); void pltf_swap_buffers();
PltfWindowEvent pltf_window_event_handle(); PltfWindowEvent pltf_window_event_handle();
void pltf_key_callback_set(
const PltfKey key,
const PltfKeyCallback cb,
const void* user_data
);
#endif // PLTF_H_ #endif // PLTF_H_

View File

@@ -1,6 +1,6 @@
#include "../gl_funcs.h" #include "../gl_funcs.h"
#include "log.h" #include "log.h"
#include "pltf_win32.h" #include "internal.h"
#define X(type, name) \ #define X(type, name) \
type name = NULL type name = NULL

52
src/pltf/win32/internal.c Normal file
View File

@@ -0,0 +1,52 @@
#include <windows.h>
#include "internal.h"
#include "pltf/pltf.h"
HMODULE opengl_module = NULL;
#define PLTF_KEYS_X(lower, upper) \
.key_##lower##_cb = NULL, \
.key_##lower##_cb_user_data = NULL,
PltfWin32State pltf_state = {
.wc_name = L"Scuffedcraft Window Class",
.exe_module = NULL,
.hwnd = NULL,
.hdc = NULL,
.wgl_extensions = { 0 },
.window_state = (WinState) {
.gl_ctx = NULL },
PLTF_KEYS(PLTF_KEYS_X)
};
#undef PLTF_KEYS_X
bool pltf_has_wgl_extension(const DynString* name) {
for (size_t i = 0; i < pltf_state.wgl_extensions.len; i++) {
if (DynString_equal(name, DynArray_DynString_at(&pltf_state.wgl_extensions, i))) {
return true;
}
}
return false;
}
bool pltf_has_wgl_extension_c_str(const char* name) {
DynString name_dstr = DynString_alloc(name, strlen(name));
const bool res = pltf_has_wgl_extension(&name_dstr);
DynString_free(&name_dstr);
return res;
}
unsigned int vk_to_pltf_key(WPARAM key) {
switch (key) {
case VK_ESCAPE:
return PLTF_KEY_ESC;
case 'Q':
return PLTF_KEY_Q;
default:
return PLTF_KEY_NONE;
}
}

37
src/pltf/win32/internal.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef PLTF_WIN32_INTERNAL_H_
#define PLTF_WIN32_INTERNAL_H_
#include <windef.h>
#include "../pltf.h"
#include "DynArray.h"
typedef struct {
HGLRC gl_ctx;
} WinState;
#define PLTF_KEYS_X(lower, upper) \
PltfKeyCallback key_##lower##_cb; \
void* key_##lower##_cb_user_data;
typedef struct {
const wchar_t* wc_name;
HMODULE exe_module;
HWND hwnd;
HDC hdc;
DynArray_DynString wgl_extensions;
WinState window_state;
PLTF_KEYS(PLTF_KEYS_X);
} PltfWin32State;
#undef PLTF_KEYS_X
extern PltfWin32State pltf_state;
extern HMODULE opengl_module;
bool pltf_has_wgl_extension(const DynString* name);
bool pltf_has_wgl_extension_c_str(const char* name);
unsigned int vk_to_pltf_key(WPARAM key);
#endif // PLTF_WIN32_INTERNAL_H_

View File

@@ -9,33 +9,9 @@
#include "../pltf.h" #include "../pltf.h"
#include "DynArray.h" #include "DynArray.h"
#include "DynString.h" #include "DynString.h"
#include "internal.h"
#include "log.h" #include "log.h"
#include "win_proc.h"
typedef struct {
HGLRC gl_ctx;
} WinState;
HMODULE opengl_module = NULL;
static struct {
const wchar_t* wc_name;
HMODULE exe_module;
HWND hwnd;
HDC hdc;
DynArray_DynString wgl_extensions;
WinState window_state;
} pltf_state = {
.wc_name = L"Sample Window Class",
.exe_module = NULL,
.hwnd = NULL,
.hdc = NULL,
.wgl_extensions = { 0 },
.window_state = (WinState) {
.gl_ctx = NULL
}
};
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void pltf_init() { void pltf_init() {
pltf_state.exe_module = GetModuleHandle(NULL); pltf_state.exe_module = GetModuleHandle(NULL);
@@ -62,23 +38,6 @@ void pltf_deinit() {
UnregisterClass(pltf_state.wc_name, pltf_state.exe_module); UnregisterClass(pltf_state.wc_name, pltf_state.exe_module);
} }
static bool pltf_has_wgl_extension(const DynString* name) {
for (size_t i = 0; i < pltf_state.wgl_extensions.len; i++) {
if (DynString_equal(name, DynArray_DynString_at(&pltf_state.wgl_extensions, i))) {
return true;
}
}
return false;
}
static bool pltf_has_wgl_extension_c_str(const char* name) {
DynString name_dstr = DynString_alloc(name, strlen(name));
const bool res = pltf_has_wgl_extension(&name_dstr);
DynString_free(&name_dstr);
return res;
}
void pltf_window_create() { void pltf_window_create() {
// Create the window // Create the window
pltf_state.hwnd = CreateWindowEx( pltf_state.hwnd = CreateWindowEx(
@@ -108,6 +67,10 @@ void pltf_window_create() {
ShowWindow(pltf_state.hwnd, SW_SHOWDEFAULT); ShowWindow(pltf_state.hwnd, SW_SHOWDEFAULT);
} }
void pltf_window_close() {
PostMessage(pltf_state.hwnd, WM_CLOSE, 0, 0);
}
void pltf_window_destroy() { void pltf_window_destroy() {
if (pltf_state.hwnd != NULL) { if (pltf_state.hwnd != NULL) {
DestroyWindow(pltf_state.hwnd); DestroyWindow(pltf_state.hwnd);
@@ -288,63 +251,37 @@ void pltf_swap_buffers() {
PltfWindowEvent pltf_window_event_handle() { PltfWindowEvent pltf_window_event_handle() {
MSG msg = { 0 }; MSG msg = { 0 };
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (PeekMessage(&msg, pltf_state.hwnd, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
if (msg.message == WM_QUIT) { switch (msg.message) {
return PLTF_WE_QUIT; case WM_DESTROY:
return PLTF_WE_DESTROY;
} }
} }
return PLTF_WE_NULL; return PLTF_WE_NULL;
} }
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { #define PLTF_KEYS_X(lower, upper) \
WinState* pState = NULL; case PLTF_KEY_##upper: { \
if (uMsg == WM_CREATE) { pltf_state.key_##lower##_cb = cb; \
CREATESTRUCT* pCreate = (CREATESTRUCT*) lParam; pltf_state.key_##lower##_cb_user_data = (void*) user_data; \
pState = (WinState*) pCreate->lpCreateParams; break; \
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pState);
} else {
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
pState = (WinState*) ptr;
} }
switch (uMsg) { void pltf_key_callback_set(
// case WM_LBUTTONDOWN: { const PltfKey key,
// printf("State: msg: %s, num: %d\n", pState->msg, pState->num); const PltfKeyCallback cb,
// const void* user_data
// printf("lParam: %llx\n", lParam); ) {
// int mouse_x = GET_X_LPARAM(lParam);
// printf("mouse_x: %x\n", mouse_x);
// int mouse_y = GET_Y_LPARAM(lParam);
// printf("mouse_y: %x\n", mouse_y);
// printf("x: %d y: %d\n", mouse_x, mouse_y);
//
// return 0;
// }
case WM_CREATE: { switch (key) {
return 0; case PLTF_KEY_NONE:
} break;
case WM_KEYDOWN: PLTF_KEYS(PLTF_KEYS_X);
if (wParam == VK_ESCAPE) {
PostMessage(hwnd, WM_DESTROY, 0, 0);
} }
return 0;
case WM_DESTROY:
wglDeleteContext(pState->gl_ctx);
PostQuitMessage(0);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, L"Really quit?", L"My Application", MB_OKCANCEL) == IDOK) {
DestroyWindow(hwnd);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
} }
#undef PLTF_KEYS_X

View File

@@ -1,8 +0,0 @@
#ifndef PLTF_WIN32_H_
#define PLTF_WIN32_H_
#include <windef.h>
extern HMODULE opengl_module;
#endif // PLTF_WIN32_H_

66
src/pltf/win32/win_proc.c Normal file
View File

@@ -0,0 +1,66 @@
#include <windows.h>
#include "internal.h"
#include "pltf/pltf.h"
#define PLTF_KEYS_X(lower, upper) \
case PLTF_KEY_##upper: \
if (pltf_state.key_##lower##_cb != NULL) { \
pltf_state.key_##lower##_cb(pltf_state.key_##lower##_cb_user_data); \
} \
break;
static void key_down_handle(WPARAM key) {
const PltfKey pltf_key = vk_to_pltf_key(key);
switch (pltf_key) {
case PLTF_KEY_NONE:
break;
PLTF_KEYS(PLTF_KEYS_X);
}
}
#undef PLTF_KEYS_X
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
WinState* pState = NULL;
if (uMsg == WM_CREATE) {
CREATESTRUCT* pCreate = (CREATESTRUCT*) lParam;
pState = (WinState*) pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pState);
} else {
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
pState = (WinState*) ptr;
}
switch (uMsg) {
// case WM_LBUTTONDOWN: {
// printf("State: msg: %s, num: %d\n", pState->msg, pState->num);
//
// printf("lParam: %llx\n", lParam);
// int mouse_x = GET_X_LPARAM(lParam);
// printf("mouse_x: %x\n", mouse_x);
// int mouse_y = GET_Y_LPARAM(lParam);
// printf("mouse_y: %x\n", mouse_y);
// printf("x: %d y: %d\n", mouse_x, mouse_y);
//
// return 0;
// }
// case WM_CREATE: {
// return 0;
// }
case WM_KEYDOWN:
key_down_handle(wParam);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, L"Really quit?", L"My Application", MB_OKCANCEL) == IDOK) {
PostMessage(hwnd, WM_DESTROY, 0, 0);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

View File

@@ -0,0 +1,8 @@
#ifndef WIN_PROC_H_
#define WIN_PROC_H_
#include <windef.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif // WIN_PROC_H_