核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
193 lines
6.1 KiB
C
193 lines
6.1 KiB
C
// ============================================================================
|
|
// window.c - Win32 窗口实现
|
|
// ============================================================================
|
|
|
|
#include "window.h"
|
|
#include "../Core/logger.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// 窗口类名
|
|
static const wchar_t* WINDOW_CLASS = L"MiMoEngineWindow";
|
|
|
|
// 全局回调
|
|
static WindowKeyCallback g_key_callback = NULL;
|
|
static WindowResizeCallback g_resize_callback = NULL;
|
|
static WindowMouseMoveCallback g_mouse_move_callback = NULL;
|
|
static WindowMouseButtonCallback g_mouse_button_callback = NULL;
|
|
|
|
// 窗口过程
|
|
static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|
Window* window = NULL;
|
|
|
|
if (msg == WM_NCCREATE) {
|
|
CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
|
|
window = (Window*)cs->lpCreateParams;
|
|
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)window);
|
|
} else {
|
|
window = (Window*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
|
}
|
|
|
|
if (window) {
|
|
switch (msg) {
|
|
case WM_SIZE:
|
|
window->width = LOWORD(lParam);
|
|
window->height = HIWORD(lParam);
|
|
window->minimized = (wParam == SIZE_MINIMIZED);
|
|
if (g_resize_callback && !window->minimized) {
|
|
g_resize_callback(window->width, window->height);
|
|
}
|
|
return 0;
|
|
|
|
case WM_PAINT:
|
|
ValidateRect(hwnd, NULL);
|
|
return 0;
|
|
|
|
case WM_ERASEBKGND:
|
|
return 1;
|
|
|
|
case WM_KEYDOWN:
|
|
if (g_key_callback) g_key_callback((int)wParam);
|
|
return 0;
|
|
|
|
case WM_KEYUP:
|
|
return 0;
|
|
|
|
case WM_MOUSEMOVE:
|
|
if (g_mouse_move_callback) g_mouse_move_callback(LOWORD(lParam), HIWORD(lParam));
|
|
return 0;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
if (g_mouse_button_callback) g_mouse_button_callback(0);
|
|
return 0;
|
|
case WM_RBUTTONDOWN:
|
|
if (g_mouse_button_callback) g_mouse_button_callback(1);
|
|
return 0;
|
|
case WM_MBUTTONDOWN:
|
|
if (g_mouse_button_callback) g_mouse_button_callback(2);
|
|
return 0;
|
|
|
|
case WM_LBUTTONUP:
|
|
if (g_mouse_button_callback) g_mouse_button_callback(0);
|
|
return 0;
|
|
case WM_RBUTTONUP:
|
|
if (g_mouse_button_callback) g_mouse_button_callback(1);
|
|
return 0;
|
|
case WM_MBUTTONUP:
|
|
if (g_mouse_button_callback) g_mouse_button_callback(2);
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
// 注册窗口类
|
|
static void register_window_class(void) {
|
|
WNDCLASSEXW wc = {0};
|
|
wc.cbSize = sizeof(WNDCLASSEXW);
|
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
wc.lpfnWndProc = window_proc;
|
|
wc.hInstance = GetModuleHandleW(NULL);
|
|
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = NULL;
|
|
wc.lpszClassName = WINDOW_CLASS;
|
|
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
|
|
|
if (!RegisterClassExW(&wc)) {
|
|
LOG_ERROR("Failed to register window class!");
|
|
}
|
|
}
|
|
|
|
Window* window_create(const char* title, int width, int height, int fullscreen) {
|
|
Window* window = (Window*)calloc(1, sizeof(Window));
|
|
if (!window) return NULL;
|
|
|
|
window->title = title;
|
|
window->width = width;
|
|
window->height = height;
|
|
window->fullscreen = fullscreen;
|
|
|
|
register_window_class();
|
|
|
|
DWORD style = WS_OVERLAPPEDWINDOW;
|
|
DWORD ex_style = WS_EX_APPWINDOW;
|
|
|
|
RECT rect = {0, 0, width, height};
|
|
AdjustWindowRectEx(&rect, style, FALSE, ex_style);
|
|
|
|
int adjusted_width = rect.right - rect.left;
|
|
int adjusted_height = rect.bottom - rect.top;
|
|
|
|
int screen_w = GetSystemMetrics(SM_CXSCREEN);
|
|
int screen_h = GetSystemMetrics(SM_CYSCREEN);
|
|
int pos_x = (screen_w - adjusted_width) / 2;
|
|
int pos_y = (screen_h - adjusted_height) / 2;
|
|
|
|
// 转换标题为宽字符
|
|
wchar_t w_title[256];
|
|
MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, 256);
|
|
|
|
window->hwnd = CreateWindowExW(
|
|
ex_style, WINDOW_CLASS, w_title, style,
|
|
pos_x, pos_y, adjusted_width, adjusted_height,
|
|
NULL, NULL, GetModuleHandleW(NULL), window
|
|
);
|
|
|
|
if (!window->hwnd) {
|
|
LOG_ERROR("Failed to create window! Error: %lu", GetLastError());
|
|
free(window);
|
|
return NULL;
|
|
}
|
|
|
|
ShowWindow(window->hwnd, SW_SHOW);
|
|
UpdateWindow(window->hwnd);
|
|
|
|
LOG_INFO("Window created: %dx%d", width, height);
|
|
return window;
|
|
}
|
|
|
|
void window_destroy(Window* window) {
|
|
if (window) {
|
|
if (window->hwnd) {
|
|
DestroyWindow(window->hwnd);
|
|
window->hwnd = NULL;
|
|
}
|
|
free(window);
|
|
}
|
|
}
|
|
|
|
void window_show(Window* window) {
|
|
if (window && window->hwnd) ShowWindow(window->hwnd, SW_SHOW);
|
|
}
|
|
|
|
void window_hide(Window* window) {
|
|
if (window && window->hwnd) ShowWindow(window->hwnd, SW_HIDE);
|
|
}
|
|
|
|
int window_process_messages(Window* window) {
|
|
MSG msg = {0};
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
if (msg.message == WM_QUIT) return 0;
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int window_get_width(Window* window) { return window ? window->width : 0; }
|
|
int window_get_height(Window* window) { return window ? window->height : 0; }
|
|
HWND window_get_handle(Window* window) { return window ? window->hwnd : NULL; }
|
|
int window_is_fullscreen(Window* window) { return window ? window->fullscreen : 0; }
|
|
int window_is_minimized(Window* window) { return window ? window->minimized : 0; }
|
|
|
|
void window_set_key_callback(Window* window, WindowKeyCallback callback) { g_key_callback = callback; }
|
|
void window_set_resize_callback(Window* window, WindowResizeCallback callback) { g_resize_callback = callback; }
|
|
void window_set_mouse_move_callback(Window* window, WindowMouseMoveCallback callback) { g_mouse_move_callback = callback; }
|
|
void window_set_mouse_button_callback(Window* window, WindowMouseButtonCallback callback) { g_mouse_button_callback = callback; }
|