2025-04-20 17:40:57 +09:00

189 lines
4.7 KiB
C

#define GF_EXPOSE_DRAW_PLATFORM
#define GF_EXPOSE_DRAW
#define GF_EXPOSE_INPUT
#include <gf_pre.h>
/* External library */
#include <gf_directx.h>
/* Interface */
#include <gf_draw_platform.h>
/* Engine */
#include <gf_draw_driver.h>
#include <gf_log.h>
#include <gf_draw.h>
#include <gf_input.h>
/* Standard */
#include <string.h>
#include <stdlib.h>
void gf_draw_platform_begin(void) {}
void gf_draw_platform_end(void) {}
LRESULT CALLBACK gf_draw_platform_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
PAINTSTRUCT ps;
RECT rect;
gf_draw_t* draw = (gf_draw_t*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch(msg) {
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
if(draw->platform != NULL) {
GetClientRect(hWnd, &rect);
draw->x = rect.left;
draw->y = rect.top;
draw->width = rect.right - rect.left;
draw->height = rect.bottom - rect.top;
gf_draw_reshape(draw);
}
break;
case WM_MOUSEMOVE:
if(draw->input != NULL) {
draw->input->mouse_x = LOWORD(lp);
draw->input->mouse_y = HIWORD(lp);
}
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
if(draw->input != NULL) {
if(msg == WM_LBUTTONDOWN) {
SetCapture(hWnd);
draw->input->mouse_flag |= GF_INPUT_MOUSE_LEFT_MASK;
} else {
draw->input->mouse_flag ^= GF_INPUT_MOUSE_LEFT_MASK;
ReleaseCapture();
}
}
break;
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
if(draw->input != NULL) {
if(msg == WM_MBUTTONDOWN) {
SetCapture(hWnd);
draw->input->mouse_flag |= GF_INPUT_MOUSE_MIDDLE_MASK;
} else {
draw->input->mouse_flag ^= GF_INPUT_MOUSE_MIDDLE_MASK;
ReleaseCapture();
}
}
break;
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
if(draw->input != NULL) {
if(msg == WM_RBUTTONDOWN) {
SetCapture(hWnd);
draw->input->mouse_flag |= GF_INPUT_MOUSE_RIGHT_MASK;
} else {
draw->input->mouse_flag ^= GF_INPUT_MOUSE_RIGHT_MASK;
ReleaseCapture();
}
}
break;
case WM_CLOSE:
draw->close = 1;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wp, lp);
}
return 0;
}
int gf_draw_platform_has_extension(gf_draw_t* draw, const char* query) { return 0; }
int gf_draw_platform_step(gf_draw_t* draw) {
MSG msg;
int ret = 0;
while(PeekMessage(&msg, draw->platform->window, 0, 0, PM_NOREMOVE)) {
if(GetMessage(&msg, draw->platform->window, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
ret = 1;
break;
}
}
if(ret == 0) {
gf_draw_driver_before(draw);
gf_draw_frame(draw);
gf_draw_driver_after(draw);
SwapBuffers(draw->platform->dc);
}
return ret;
}
gf_draw_platform_t* gf_draw_platform_create(gf_engine_t* engine, gf_draw_t* draw) {
WNDCLASSEX wc;
RECT rect;
DWORD style;
gf_draw_platform_t* platform = malloc(sizeof(*platform));
memset(platform, 0, sizeof(*platform));
platform->engine = engine;
platform->instance = (HINSTANCE)GetModuleHandle(NULL);
if(platform->instance == NULL) {
gf_log_function(engine, "Failed to get instance", "");
gf_draw_platform_destroy(platform);
return NULL;
}
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = gf_draw_platform_proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = platform->instance;
wc.hIcon = LoadIcon(platform->instance, "GAME");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "goldfish";
wc.hIconSm = LoadIcon(platform->instance, "GAME");
if(!RegisterClassEx(&wc)) {
gf_log_function(engine, "Failed to register class", "");
gf_draw_platform_destroy(platform);
return NULL;
}
platform->window = CreateWindow("goldfish", draw->title, (WS_OVERLAPPEDWINDOW), draw->x, draw->y, draw->width, draw->height, NULL, 0, platform->instance, NULL);
if(platform->window == NULL) {
gf_log_function(engine, "Failed to create window", "");
gf_draw_platform_destroy(platform);
return NULL;
}
SetWindowLongPtr(platform->window, GWLP_USERDATA, (LONG_PTR)draw);
platform->dc = GetDC(platform->window);
SetRect(&rect, 0, 0, draw->width, draw->height);
style = (DWORD)GetWindowLongPtr(platform->window, GWL_STYLE);
AdjustWindowRect(&rect, style, FALSE);
SetWindowPos(platform->window, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE);
ShowWindow(platform->window, SW_NORMAL);
UpdateWindow(platform->window);
return platform;
}
void gf_draw_platform_destroy(gf_draw_platform_t* platform) {
if(platform->dc != NULL) {
ReleaseDC(platform->window, platform->dc);
}
if(platform->window != NULL) {
DestroyWindow(platform->window);
}
gf_log_function(platform->engine, "Destroyed platform-dependent part of drawing driver", "");
free(platform);
}