#include "../lumenarium_compiler_flags.h" #include "../lumenarium_platform_common_includes.h" #include #include #include #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; }