Lumenarium/src_v2/platform/win32/lumenarium_first_win32.cpp

313 lines
8.9 KiB
C++

#include "../lumenarium_compiler_flags.h"
#include "../lumenarium_platform_common_includes.h"
#include <windows.h>
#include <gl/gl.h>
#include <stdio.h>
#include "../../lumenarium_types.h"
#include "../../lumenarium_memory.h"
#include "../lumenarium_platform.h"
#include "../../lumenarium_first.cpp"
global DWORD win32_last_error = 0;
void
win32_get_last_error()
{
win32_last_error = GetLastError();
}
global bool running = true;
#include "lumenarium_win32_opengl.h"
global Win32_OpenGL_Extensions gl;
#include "lumenarium_win32_memory.cpp"
#include "lumenarium_win32_window.cpp"
#include "lumenarium_win32_time.cpp"
#include "lumenarium_win32_file.cpp"
#include "lumenarium_win32_thread.cpp"
#include "lumenarium_win32_graphics.cpp"
internal Platform_Key_Flags
win32_get_key_flags_mod()
{
Platform_Key_Flags result = 0;
if (GetKeyState(VK_SHIFT) & 0x8000) add_flag(result, KeyFlag_Mod_Shift);
if (GetKeyState(VK_MENU) & 0x8000) add_flag(result, KeyFlag_Mod_Alt);
if (GetKeyState(VK_CONTROL) & 0x8000) add_flag(result, KeyFlag_Mod_Ctrl);
return result;
}
internal void
win32_mouse_capture(Win32_Window* win)
{
// NOTE(Peter): We capture events when the mouse goes down so that
// if the user drags outside the window, we still get the mouse up
// event and can process it. Otherwise, we can get into cases where
// an event was started, didn't end, but the user can click again and
// try to start the event again.
// We relase event capture on mouse up.
SetCapture(win->window_handle);
}
internal void
win32_mouse_release(Win32_Window* win)
{
ReleaseCapture();
}
internal Platform_Window_Event
win32_button_event(Platform_Key_Code key, bool is_down, bool was_down)
{
Platform_Window_Event evt = {};
evt.kind = WindowEvent_ButtonDown;
evt.key_code = key;
evt.key_flags = win32_get_key_flags_mod();
if (is_down) add_flag(evt.key_flags, KeyFlag_State_IsDown);
if (was_down) add_flag(evt.key_flags, KeyFlag_State_WasDown);
return evt;
}
internal void
win32_set_mouse_pos_evt(Platform_Window_Event* evt)
{
POINT mouse_p;
GetCursorPos(&mouse_p);
ScreenToClient(win32_main_window.window_handle, &mouse_p);
evt->mouse_x = mouse_p.x;
evt->mouse_y = mouse_p.y;
}
internal void
win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
{
switch (msg.message)
{
case WM_MOUSEWHEEL:
{
Platform_Window_Event evt = {};
evt.kind = WindowEvent_MouseScroll;
evt.scroll_amt = GET_WHEEL_DELTA_WPARAM(msg.wParam);
lumenarium_event(evt, state);
}break;
case WM_LBUTTONDOWN:
{
Platform_Window_Event evt = win32_button_event(
KeyCode_MouseLeftButton,
true, false
);
win32_set_mouse_pos_evt(&evt);
lumenarium_event(evt, state);
win32_mouse_capture(win);
}break;
case WM_MBUTTONDOWN:
{
Platform_Window_Event evt = win32_button_event(
KeyCode_MouseMiddleButton,
true, false
);
win32_set_mouse_pos_evt(&evt);
lumenarium_event(evt, state);
win32_mouse_capture(win);
}break;
case WM_RBUTTONDOWN:
{
Platform_Window_Event evt = win32_button_event(
KeyCode_MouseRightButton,
true, false
);
win32_set_mouse_pos_evt(&evt);
lumenarium_event(evt, state);
win32_mouse_capture(win);
}break;
case WM_LBUTTONUP:
{
Platform_Window_Event evt = win32_button_event(
KeyCode_MouseLeftButton,
false, true
);
win32_set_mouse_pos_evt(&evt);
lumenarium_event(evt, state);
win32_mouse_release(win);
}break;
case WM_MBUTTONUP:
{
Platform_Window_Event evt = win32_button_event(
KeyCode_MouseMiddleButton,
false, true
);
win32_set_mouse_pos_evt(&evt);
lumenarium_event(evt, state);
win32_mouse_release(win);
}break;
case WM_RBUTTONUP:
{
Platform_Window_Event evt = win32_button_event(
KeyCode_MouseRightButton,
false, true
);
win32_set_mouse_pos_evt(&evt);
lumenarium_event(evt, state);
win32_mouse_release(win);
}break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
Platform_Key_Code key = 0;
b32 was_down = (msg.lParam & (1 << 30)) != 0;
b32 is_down = (msg.lParam & (1 << 31)) == 0;
Platform_Window_Event evt = win32_button_event(key, is_down, was_down);
lumenarium_event(evt, state);
TranslateMessage(&msg);
DispatchMessage(&msg);
}break;
case WM_CHAR:
{
Platform_Window_Event evt = {};
evt.kind = WindowEvent_Char;
evt.char_value = (char)msg.wParam;
lumenarium_event(evt, state);
}break;
default:
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}break;
}
}
INT WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR lpCmdLine,
INT nCmdShow)
{
open_err_file();
// Window Setup
win32_window_create(
&win32_main_window,
hInstance,
"Lumenariumtest0",
1400,
800,
win32_window_event_handler
);
win32_window_update_dim(&win32_main_window);
win32_time_init();
win32_files_init();
win32_threads_init();
App_State* state = lumenarium_init();
if (!has_flag(state->flags, AppState_IsRunning)) return 0;
Platform_Ticks ticks_start = platform_get_ticks();
while (running && has_flag(state->flags, AppState_IsRunning))
{
win32_threads_reclaim();
lumenarium_frame_prepare(state);
// Potentially pass the window closed event to the runtime
if (win32_window_event_flags & WindowEventFlag_CloseRequested)
{
Platform_Window_Event evt = {
WindowEvent_WindowClosed,
};
lumenarium_event(evt, state);
}
// Get the position of the mouse every frame
{
POINT mouse_p;
GetCursorPos(&mouse_p);
ScreenToClient(win32_main_window.window_handle, &mouse_p);
Platform_Window_Event evt = {};
evt.kind = WindowEvent_MouseMoved;
evt.mouse_x = mouse_p.x;
evt.mouse_y = mouse_p.y;
lumenarium_event(evt, state);
}
// Pass Window Events to the runtime
MSG window_msg;
while (PeekMessageA(
&window_msg,
win32_main_window.window_handle,
0,
0,
PM_REMOVE)
){
win32_window_handle_event(window_msg, &win32_main_window, state);
}
// NOTE(PS): WM_CLOSE and WM_DESTROY can both be issued
// the same frame, meaning our drawing context is destroyed
// before calling lumenarium_frame so skipping here to avoid
// using invalid resources
if (!running || !has_flag(state->flags, AppState_IsRunning)) continue;
// Update window size
if (has_flag(state->flags, AppState_RunEditor))
{
state->editor->window_dim = (v2){
(r32)win32_main_window.info.width,
(r32)win32_main_window.info.height
};
}
lumenarium_frame(state);
SwapBuffers(win32_main_window.dc);
////////////////////////////////////////
// Maintain Frame Rate
Platform_Ticks ticks_end = platform_get_ticks();
r64 seconds_elapsed = get_seconds_elapsed(ticks_start, ticks_end);
while (seconds_elapsed < target_seconds_per_frame)
{
u32 sleep_time = (u32)(1000.0f * (target_seconds_per_frame - seconds_elapsed));
Sleep(sleep_time);
ticks_end = platform_get_ticks();
seconds_elapsed = get_seconds_elapsed(ticks_start, ticks_end);
}
ticks_start = ticks_end;
}
lumenarium_cleanup(state);
// threads cleanup
for (u32 i = 1; i < win32_threads_cap; i++)
{
if (win32_threads[i] == INVALID_HANDLE_VALUE) continue;
TerminateThread(win32_threads[i], 0);
}
// windows cleanup
UnregisterClass(win32_main_window.window_class.lpszClassName, hInstance);
close_err_file();
return 0;
}