Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************/
- /******************************************************************************/
- //"opengl_metaballs_2025-06-26\src\win32\std.cpp":
- #include <public_stuff.hpp>
- #ifndef STDLIB_USED
- void* memSet(void* dst, int val, size_t len){
- if(!len) return dst;
- u8* dst8 = (u8*)dst;
- u8 val8 = (u8 )val;
- size_t remainder = len%sizeof(u32);
- len -= remainder;
- while((remainder--) > 0)
- *(dst8++) = val8;
- u32* dst32 = (u32*)dst8;
- u32 val32 = val8;
- val32 |= val32<< 8;
- val32 |= val32<<16;
- len /= sizeof(u32);
- while((len--) > 0)
- *(dst32++) = val32;
- return dst;
- }
- void* memCpy(void* dst, const void* src, size_t len){
- if(!len) return dst;
- u8* dst8 = (u8*)dst;
- u8* src8 = (u8*)src;
- while(len--) *(dst8++) = *(src8++);
- return dst;
- }
- // (len_max does not include null-terminator!)
- // (If !len_max, call is analogous to str(not n)len)
- size_t strnLen(const char* str, size_t len_max){
- size_t len = 0;
- if(!len_max){
- for(; str[len]; ++len);
- } else {
- for(; str[len] && len<len_max; ++len);
- }
- return len;
- }
- char* strnCpy(char* str_dst, const char* str_src, size_t len_max){
- char* _str_dst = str_dst; // Copy original state of str_dst
- if(!len_max){
- while((*str_dst++ = *str_src++));
- } else {
- size_t i = 0;
- while(i++ != len_max && (*str_dst++ = *str_src++));
- }
- *str_dst = 0; // Null-terminator
- return _str_dst;
- }
- char* strCat(char* dst, const char* src){
- char* dst_start = dst;
- while(*dst) ++dst;
- while((*dst++ = *src++));
- return dst_start;
- }
- // (len_max does not include null-terminator!)
- // (If !len_max, call is analogous to str(not n)cmp)
- s32 strnCmp(const char* str_a, const char* str_b, size_t len_max){
- if(!len_max){
- while(*str_a && (*str_a == *str_b))
- ++str_a, ++str_b;
- } else {
- --len_max;
- while(*str_a && (*str_a == *str_b) && len_max)
- ++str_a, ++str_b, --len_max;
- }
- return (*(const u8*)str_a) - (*(const u8*)str_b);
- }
- #define sinf_bhaskara_fmod(_x, _y) ( (_x) - ( (s64)((_x)/(_y)) * (_y) ) )
- // Custom sinf implementation; a little under 2% error iirc
- // (You could switch floats with doubles here, though the approximation's
- // lack of precision prevents that switch from being all that useful.)
- f32 sinF(f32 x){
- // Keep x within the domain of >=0 -> <pi,
- // while preserving relevant info
- bool negative = x<0.0f;
- if(x < 0.0f) x = -x; //x = fabsf(x);
- x = sinf_bhaskara_fmod(x, M_2PIf); //x %= 2pi
- // 'If original value of x%(2pi) is between _ -> _, returned value will be _':
- //>-2pi -> <=-pi, >=0
- //> -pi -> <= 0, <=0
- //>= 0 -> < pi, >=0
- //>= pi -> < 2pi, <=0
- negative ^= x>=M_PIf;
- if(x >= M_PIf) x -= M_PIf; //x %= pi
- // Uses Bhaskara I's sine approximation formula
- f32 result = 16.0f*x * (M_PIf-x);
- result /= 5.0f*M_PIf*M_PIf - result*0.25f;
- return (negative) ? -result : result;
- }
- #endif /* STDLIB_USED */
- /******************************************************************************/
- /******************************************************************************/
- //"opengl_metaballs_2025-06-26\src\win32\video.cpp":
- // If nonzero, WM_PAINT will fill the client area with the selected color
- #define FILL_WINDOW_TOGGLE 0
- // (This color is ignoredif FILL_WINDOW_TOGGLE != 1)
- #define FILL_WINDOW_COLOR RGB(0, 0, 0)
- #include "_WindowProc.hpp"
- #ifndef INT_MAX
- #define INT_MAX 2147483647
- #endif /* INT_MAX */
- static const char win_class_name[] = "Fullscreen Window Class";
- static WNDCLASS win_class = {0};
- HWND win;
- HDC win_dc;
- bool win_closed = false;
- Point2d win_size;
- bool win_has_focus;
- LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); // Forward declaration
- int WindowInit(HINSTANCE hThisInst){
- win_size.x = GetSystemMetrics(SM_CXSCREEN);
- win_size.y = GetSystemMetrics(SM_CYSCREEN);
- win_class.style = CS_DBLCLKS; // Allow double clicks
- win_class.lpfnWndProc = WindowProc;
- win_class.hInstance = hThisInst;
- win_class.hCursor = LoadCursorA(nullptr, IDC_ARROW);
- win_class.lpszClassName = win_class_name;
- RegisterClassA(&win_class);
- // (Window is intentionally hidden until initialization is done!)
- win = CreateWindowExA(WS_EX_APPWINDOW, // Extended Window Style
- win_class_name, WIN_NAME, // Class Name + Win. Name
- WS_POPUP /*| WS_VISIBLE*/, // Window style
- 0, 0, win_size.x, win_size.y, // X, Y, Width, Height
- nullptr, nullptr, hThisInst, nullptr);
- if(win == nullptr) return -2;
- win_dc = GetDC(win);
- if(win_dc == nullptr) return -3;
- return 0;
- }
- void WindowQuit(){} // Currently unnecessary
- // A thin wrapper
- void present_window(){
- SwapBuffers(win_dc);
- }
- void close_window(){
- if(win_closed) return;
- ShowWindow(win, SW_HIDE);
- ReleaseDC(win, win_dc);
- DestroyWindow(win);
- // These might not be necessary, due to the way uninitialization is set up
- //UnregisterClassA
- //DeleteCriticalSection
- win_closed = true;
- }
- bool is_win_closed(){
- return win_closed;
- }
- Point2d get_win_size(){
- return win_size;
- }
- bool is_win_focused(){
- return win_has_focus;
- }
- extern CRITICAL_SECTION events_lock;
- extern Event events_queue[65536];
- extern u16 events_next;
- extern u16 events_end;
- extern Event_Key_Mod key_mods;
- extern bool key_states[256];
- extern Point2d mouse_position;
- extern bool mouse_was_moved_before;
- extern bool cursor_trapped;
- extern bool cursor_hidden;
- static union {
- RECT v;
- struct { POINT topLeft, bottomRight; };
- } clipRect;
- #include <hidusage.h>
- static RAWINPUTDEVICE rid = {
- .usUsagePage = HID_USAGE_PAGE_GENERIC, // Generic desktop controls
- .usUsage = HID_USAGE_GENERIC_MOUSE, // Mouse
- //.dwFlags = RIDEV_NOLEGACY,
- .hwndTarget = nullptr,
- };
- MOUSE_ButtonStates mbutton_states; // Persistent mouse state
- static void update_cursor_clip(){
- LPRECT clipRect_p = nullptr;
- if(cursor_trapped){
- clipRect_p = &clipRect.v;
- GetClientRect(win, clipRect_p);
- ClientToScreen(win, &clipRect.topLeft);
- ClientToScreen(win, &clipRect.bottomRight);
- }
- ClipCursor(clipRect_p);
- }
- void trap_cursor(bool enable, bool condition){
- if(!condition) return;
- if(enable != cursor_hidden){
- cursor_hidden = enable;
- ShowCursor(!enable); // Enabling makes it hidden, hence the '!'
- }
- if(enable != cursor_trapped){
- cursor_trapped = enable;
- update_cursor_clip();
- if(enable) SetCapture(win);
- else ReleaseCapture();
- if(enable && rid.hwndTarget == nullptr){
- rid.dwFlags = RIDEV_NOLEGACY;
- rid.hwndTarget = win;
- if(!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE))){
- _printf("ERROR: failed to register mouse as a raw input device! "
- "(error code = 0x%08X)\n", (u32)GetLastError());
- rid.hwndTarget = nullptr;
- }
- }
- else if(!enable && rid.hwndTarget != nullptr){
- HWND hwndOld = rid.hwndTarget;
- rid.dwFlags = RIDEV_REMOVE;
- rid.hwndTarget = nullptr;
- if(!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE))){
- _printf("ERROR: failed to unregister mouse as a raw input device! "
- "(error code = 0x%08X)\n", (u32)GetLastError());
- rid.hwndTarget = hwndOld;
- }
- }
- Event evt;
- memSet(&evt, 0, sizeof(Event));
- evt.type = (enable) ? EVENT_CURSOR_TRAPPED : EVENT_CURSOR_RELEASED;
- AddToEventQueue(evt);
- }
- }
- static void add_event(Event& evt){
- // I pray AddToEventQueue never fails ever
- if(!AddToEventQueue(evt)){ _printf("ERROR: EVENT QUEUE IS FULL!!!\n"); }
- }
- // flag_which must be one of the "DOWN" flags (Ex.: RI_MOUSE_BUTTON_1_DOWN)
- // (Also, timestamp is assumed to have already been set inside evt!)
- static void send_raw_mbutton_press(Event& evt, u16 flags,
- u16 flag_which, u8 button_which)
- {
- if(flags&flag_which){ // Mouse down
- evt.type=EVENT_MOUSE_DOWN;
- evt.mouse.pressed = true;
- u8 button_old = evt.mouse.button;
- evt.mouse.button = button_which;
- add_event(evt);
- evt.mouse.button = button_old|button_which;
- mbutton_states.value |= button_which;
- }
- if(flags&(flag_which<<1)){ // Mouse up
- evt.type=EVENT_MOUSE_UP;
- evt.mouse.pressed = false;
- u8 button_old = evt.mouse.button;
- evt.mouse.button = button_which;
- add_event(evt);
- evt.mouse.button = button_old&(~button_which);
- mbutton_states.value &= ~button_which;
- }
- }
- LRESULT CALLBACK WindowProc(HWND winHandle, UINT message,
- WPARAM wParam, LPARAM lParam)
- {
- LRESULT returnResult = 0;
- Event evt; // Will be populated by any call to HANDLE_EVENT_<?>()...
- memSet(&evt, 0, sizeof(Event)); //(this is done BEFORE setting anything)
- evt.type = EVENT_COMMON; //...otherwise it will stay common
- bool switchBool = false; // Multipurpose
- bool switchBool2 = true; // ^^(switchBool2 intentionally initialized to true)
- u32 switchFlags = 0; // ^^
- bool addEvent = true;
- switch(message){
- case WM_DESTROY:
- PostQuitMessage(0);
- case WM_QUIT:
- {
- if(win_closed) break;
- evt.type = EVENT_QUIT;
- win_closed = true;
- trap_cursor(false, true);
- } break;
- case WM_GETMINMAXINFO: // For enforcing a minimum window size (redundant)
- {
- u32 winStyleCurrent = GetWindowLongA(winHandle, GWL_STYLE );
- u32 winStyleExCurrent = GetWindowLongA(winHandle, GWL_EXSTYLE);
- Point2d winSizeAdjusted = CalculateWindowSize(win_size.x, win_size.y,
- winStyleCurrent,
- winStyleExCurrent);
- // Set the MINMAXINFO struct provided by lParam
- MINMAXINFO* mmi = (MINMAXINFO*)lParam;
- mmi->ptMinTrackSize.x = winSizeAdjusted.x;
- mmi->ptMinTrackSize.y = winSizeAdjusted.y;
- } break;
- case WM_SIZE: // Also redraw canvas if window is being resized
- win_size.x = LOWORD(lParam);
- win_size.y = HIWORD(lParam);
- update_cursor_clip();
- case WM_PAINT:
- {
- // Dummy paint handling just in case Windows needs it
- // (optionally filling the window with black)
- PAINTSTRUCT p_s;
- #if FILL_WINDOW_TOGGLE == 1
- HDC hdc =
- #endif
- BeginPaint(winHandle, &p_s);
- #if FILL_WINDOW_TOGGLE == 1
- HBRUSH hBlackBrush = CreateSolidBrush(FILL_WINDOW_COLOR);
- FillRect(hdc, &p_s.rcPaint, hBlackBrush);
- DeleteObject(hBlackBrush);
- #endif
- EndPaint(winHandle, &p_s);
- } break;
- case WM_SETFOCUS:
- {
- win_has_focus = true;
- } break;
- case WM_KILLFOCUS:
- {
- // If a key is released outside the client area, its key up message
- // is never sent, so here the key states are reset when unfocusing...
- // ...but first, send a key up event for every currently pressed key
- // Call QPC only once, since the events technically happen simultaneously
- QueryPerformanceCounter((LARGE_INTEGER*)&evt.key.timestamp);
- KEY_Params params = 0;
- params.currUnpressed = 1;
- for(u32 chr=0; chr<256; ++chr){
- // Send a KEY_UP only if the state was previously true
- if(key_states[chr] == true){
- params.scanCode = MapVirtualKeyA(chr, MAPVK_VK_TO_VSC);
- HANDLE_KEY_CHARUPDOWN(evt, false, chr, params, 0);
- add_event(evt);
- }
- }
- memSet(key_states, 0, sizeof(bool)*256); //NOW the states can be reset
- // Reset all key modifiers (except for toggles) too
- key_mods.all &= 0xff00; // Non-toggles are stored in low byte
- mbutton_states.value = 0; // Reset mouse states as well
- trap_cursor(false, true);
- win_has_focus = false;
- } break;
- //EVENT_KEY_CHAR, EVENT_KEY_UP, EVENT_KEY_DOWN
- case WM_CHAR:
- case WM_SYSKEYUP:
- case WM_SYSKEYDOWN:
- case WM_KEYUP:
- case WM_KEYDOWN:
- case WM_SYSCHAR:
- {
- // Marshal relevant stuff to pass to event handler
- bool charEvent = message==WM_CHAR;
- u8 virtualKeyCode = (u8) wParam;
- KEY_Params params = (u32)lParam;
- // Set repeat flag
- params.repeatCount = (!params.currUnpressed) == true &&
- key_states[virtualKeyCode] == true;
- if(!charEvent){
- // (Uncomment the last part of the line below if issues occur
- // related to missed key press events or something!)
- bool keydown = message==WM_KEYDOWN;//|| message==WM_SYSKEYDOWN;
- bool pressed = !params.currUnpressed;
- key_states[virtualKeyCode] = pressed;
- // Update any relevant key modifiers
- switch(virtualKeyCode){
- case VKEY_SHIFT : { key_mods.lshift = key_mods.rshift = pressed; } break;
- case VKEY_CONTROL : { key_mods.lctrl = key_mods.rctrl = pressed; } break;
- case VKEY_ALT : { key_mods.lalt = key_mods.ralt = pressed; } break;
- case VKEY_LWIN : { key_mods.lgui = pressed; } break;
- case VKEY_RWIN : { key_mods.rgui = pressed; } break;
- case VKEY_NUMLOCK : if(keydown){ key_mods.numlock^=1; } break;
- case VKEY_CAPSLOCK : if(keydown){ key_mods.capslock^=1; } break;
- case VKEY_SCROLLOCK: if(keydown){ key_mods.scrollock^=1; } break;
- default:;
- }
- if( virtualKeyCode==VKEY_CTRL ) mbutton_states.ctrl = pressed;
- else if(virtualKeyCode==VKEY_SHIFT) mbutton_states.shift = pressed;
- bool repeat = params.repeatCount!=0;
- trap_cursor(!cursor_trapped,
- virtualKeyCode==VKEY_ENTER && keydown && !repeat);
- }
- HANDLE_KEY_CHARUPDOWN(evt, charEvent, virtualKeyCode,
- params, key_mods.all);
- } break;
- //EVENT_MOUSE_MOVED
- case WM_MOUSEMOVE:
- {
- // Get button states
- MOUSE_ButtonStates buttonStates;
- buttonStates.left = (wParam&MK_LBUTTON ) != 0;
- buttonStates.middle = (wParam&MK_MBUTTON ) != 0;
- buttonStates.right = (wParam&MK_RBUTTON ) != 0;
- buttonStates.x1 = (wParam&MK_XBUTTON1) != 0;
- buttonStates.x2 = (wParam&MK_XBUTTON2) != 0;
- buttonStates.ctrl = (wParam&MK_CONTROL ) != 0;
- buttonStates.shift = (wParam&MK_SHIFT ) != 0;
- // Get new mouse position
- Point2d mousePositionNew;
- mousePositionNew.x = GET_X_LPARAM(lParam);
- mousePositionNew.y = win_size.y-1 - GET_Y_LPARAM(lParam);
- // If this is the first instance of WINEVENT_MOUSE_MOVE,
- // there is no previous mouse position, so the delta should be 0 then
- if(!mouse_was_moved_before){
- mouse_position = mousePositionNew;
- mouse_was_moved_before = true;
- }
- HANDLE_MOUSE_MOVED(evt, buttonStates.value,
- mouse_position, mousePositionNew);
- mouse_position = mousePositionNew; // Set current position to new one
- } break;
- case WM_MOUSELEAVE:
- {
- // Indicates that the mouse will have yet to be moved inside client area
- mouse_was_moved_before = false;
- } break;
- //EVENT_MOUSE_HWHEEL, EVENT_MOUSE_VWHEEL
- case WM_MOUSEHWHEEL:
- case WM_MOUSEWHEEL:
- {
- bool verticalScroll = message==WM_MOUSEWHEEL;
- s16 scrollAmount = (s16)HIWORD(wParam);
- mbutton_states.left = (wParam&MK_LBUTTON ) != 0;
- mbutton_states.middle = (wParam&MK_MBUTTON ) != 0;
- mbutton_states.right = (wParam&MK_RBUTTON ) != 0;
- mbutton_states.x1 = (wParam&MK_XBUTTON1) != 0;
- mbutton_states.x2 = (wParam&MK_XBUTTON2) != 0;
- Point2d scrollMousePosition;
- scrollMousePosition.x = GET_X_LPARAM(lParam);
- scrollMousePosition.y = GET_Y_LPARAM(lParam);
- // The coordinates are, by default, relative to the screen
- // and not the window (for some reason)
- ScreenToClient(winHandle, (POINT*)&scrollMousePosition);
- HANDLE_MOUSE_HVWHEEL(evt, verticalScroll, scrollAmount,
- mbutton_states.value, scrollMousePosition);
- } break;
- //EVENT_MOUSE_UP, EVENT_MOUSE_DOWN
- //switchBool = evt.mouse.dblClick
- //switchBool2 = evt.mouse.pressed
- //switchFlags = evt.mouse.button
- case WM_LBUTTONDBLCLK: switchBool = true; goto _notLButtonUp;
- case WM_LBUTTONUP : switchBool2 = false; _notLButtonUp:
- case WM_LBUTTONDOWN : switchFlags |= MBUTTON_LEFT; goto _handleMouseClick;
- case WM_MBUTTONDBLCLK: switchBool = true; goto _notMButtonUp;
- case WM_MBUTTONUP : switchBool2 = false; _notMButtonUp:
- case WM_MBUTTONDOWN : switchFlags |=MBUTTON_MIDDLE; goto _handleMouseClick;
- case WM_RBUTTONDBLCLK: switchBool = true; goto _notRButtonUp;
- case WM_RBUTTONUP : switchBool2 = false; _notRButtonUp:
- case WM_RBUTTONDOWN : switchFlags |= MBUTTON_RIGHT; goto _handleMouseClick;
- case WM_XBUTTONDBLCLK: switchBool = true; goto _notXButtonUp;
- case WM_XBUTTONUP : switchBool2 = false; _notXButtonUp:
- case WM_XBUTTONDOWN : if(wParam & MK_XBUTTON1) switchFlags |= MBUTTON_X1;
- else switchFlags |= MBUTTON_X2;
- {
- _handleMouseClick:
- Point2d clickPosition;
- clickPosition.x = GET_X_LPARAM(lParam);
- clickPosition.y = GET_Y_LPARAM(lParam);
- bool pressed = switchBool2;
- bool doubleClick = switchBool;
- if(switchFlags&MBUTTON_LEFT ) mbutton_states.left = pressed;
- else if(switchFlags&MBUTTON_MIDDLE) mbutton_states.middle = pressed;
- else if(switchFlags&MBUTTON_RIGHT ) mbutton_states.right = pressed;
- else if(switchFlags&MBUTTON_X1 ) mbutton_states.x1 = pressed;
- else if(switchFlags&MBUTTON_X2 ) mbutton_states.x2 = pressed;
- HANDLE_MOUSE_UPDOWN(evt, clickPosition,
- mbutton_states.value, pressed, doubleClick);
- } break;
- case WM_INPUT:
- {
- // First call to query for the data's size
- UINT dataSize = 0;
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, nullptr,
- &dataSize, sizeof(RAWINPUTHEADER));
- RAWINPUT* data = (RAWINPUT*)alloca(dataSize);
- // Second call to get the actual data
- if(GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data,
- &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
- {
- const RAWMOUSE& mouse = data->data.mouse;
- if(data->header.dwType != RIM_TYPEMOUSE ||
- mouse.usFlags != MOUSE_MOVE_RELATIVE)
- {
- addEvent = false; break;
- }
- // Handle the actual event stuff
- {
- s32 _deltaWheel = mouse.usButtonData;
- if(_deltaWheel >= 32768) _deltaWheel -= 65536; // Unsigned-to-signed
- const u16 flags = mouse.usButtonFlags;
- const f32 deltaWheel = (f32)_deltaWheel/WHEEL_DELTA;
- const f32 deltaX = mouse.lLastX;
- const f32 deltaY = -mouse.lLastY; // GDI's bitmaps are *bottom-up*
- HANDLE_MOUSE_RAWINPUT(evt, flags, deltaWheel, deltaX, deltaY);
- }
- } else {
- _printf("ERROR: failed to get raw mouse input data! "
- "(error code = 0x%08X)\n", (u32)GetLastError());
- }
- // Any relevant raw input events will already have been sent by this point
- addEvent = false;
- } break;
- default: returnResult = DefWindowProcA(winHandle, message, wParam, lParam);
- }
- if(evt.type != EVENT_COMMON && evt.common.timestamp == 0 && addEvent)
- {
- // Idk how expensive QPC is, so I'll only call it if the event is valid
- QueryPerformanceCounter((LARGE_INTEGER*)&evt.common.timestamp);
- add_event(evt);
- }
- return returnResult;
- }
- /******************************************************************************/
- /******************************************************************************/
- //"opengl_metaballs_2025-06-26\include\public_stuff.hpp":
- #ifndef _PUBLIC_STUFF_HPP
- #define _PUBLIC_STUFF_HPP
- // Comment out any misc. functions you don't plan on using
- //#define PRINT_EVENT_USED
- #define FRAND_USED // (Includes all types of frand)
- //#define SOUND_STUFF_USED // 'Use the built-in sound effect mixer?'
- // Comment this line out if you don't plan on using stdlib's implementations of:
- // memset
- // memcpy
- // strnlen
- // strncpy
- // strcat
- // strncmp
- #define STDLIB_USED
- #if defined(FRAND_USED) && !defined(STDLIB_USED)
- #define STDLIB_USED
- #endif
- #ifdef STDLIB_USED
- #include <string.h>
- #include <math.h>
- // The framework uses its own implementations for the following stdlib
- // functions so that it doesn't require the C runtime libraries.
- // However, if the user plans on using the standard library for their
- // own purposes, having custom implementations would be redundant
- #define memSet memset
- #define memCpy memcpy
- #define strnLen strnlen
- #define strnCpy strncpy
- #define strCat strcat
- #define strnCmp strncmp
- // (sinF is only used for the example audio usage,
- // and that's commented out at first anyway!)
- #define sinF sinf
- #endif /* STDLIB_USED */
- // (I don't currently have a custom implementation of this yet,
- // but I also don't want to refactor every call if I do end up making one)
- #define strnCat strncat
- // If you don't end up using anything else from stdio,
- // using this makes sure printf is only included in the debug build!
- // This is useful for minimizing size, since the command line is
- // only shown in the debug build anyway.
- #ifdef _DEBUG
- #include <stdio.h>
- #define _printf(...) printf(__VA_ARGS__)
- #else
- #define _printf(...)
- #endif /* _DEBUG */
- // Float-specified versions of math.h's pi constants,
- // with a slightly different naming convention
- #ifndef M_PI4f
- #define M_PI4f 0.7853981633974483096156608f
- #endif /* M_PI2 */
- #ifndef M_PI2f
- #define M_PI2f 1.5707963267948966192313216f
- #endif /* M_PI2 */
- #ifndef M_PIf
- #define M_PIf 3.1415926535897932384626433f
- #endif /* M_PIf */
- #ifndef M_2PIf
- #define M_2PIf 6.2831853071795864769252866f
- #endif /* M_2PIf */
- #ifndef MIN
- #define MIN(a,b) ( ((a)<(b)) ? (a) : (b) )
- #endif /* MIN(a,b) */
- #ifndef MAX
- #define MAX(a,b) ( ((a)>(b)) ? (a) : (b) )
- #endif /* MAX(a,b) */
- #ifndef MIN3
- #define MIN3(_a, _b, _c) MIN(MIN(_a, _b), _c)
- #endif /* MIN3 */
- #ifndef MAX3
- #define MAX3(_a, _b, _c) MAX(MAX(_a, _b), _c)
- #endif /* MAX3 */
- #ifndef CLAMP
- #define CLAMP(n, mn, mx) MIN(MAX(n,mn),mx)
- #endif /* CLAMP(n, mn, mx) */
- // Precise version of linear interpolation
- #ifndef LERP
- #define LERP(_v0, _v1, _t) ( (1.0-(_t)) * (_v0) + (_t) * (_v1) )
- #endif /* LERP */
- // Imprecise (but theoretically faster?) version
- #ifndef LERP2
- #define LERP2(_v0, _v1, _t) ( (_v0) + (_t) * ((_v1)-(_v0)) )
- #endif /* LERP2 */
- #ifndef IN_BOUNDS
- #define IN_BOUNDS(_x, _y, _w, _h) ( (_x) >= 0 && (_x) < (_w) && \
- (_y) >= 0 && (_y) < (_h) )
- #endif /* IN_BOUNDS */
- // For printing the results of a boolean value.
- // To use this, use the "%s" format specifier,
- // with this as the parameter
- #ifndef BOOL_STR
- #define BOOL_STR(_is_true) ( (_is_true) ? "true" : "false" )
- #endif /* BOOL_STR */
- #ifdef __cplusplus
- #include <cstddef>
- #include <cstdint>
- #include <climits>
- #else
- #include <stdint.h>
- #endif /* __cplusplus */
- typedef uint8_t u8;
- typedef uint16_t u16;
- typedef uint32_t u32;
- typedef uint64_t u64;
- typedef int8_t s8;
- typedef int16_t s16;
- typedef int32_t s32;
- typedef int64_t s64;
- typedef float f32;
- typedef double f64;
- // There's no real point in messing with this stuff
- // unless you know how they're useful.
- // Relevant documentation if you want to know how to use these:
- // PACKED : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
- // NOINLINE : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
- // DEPRECATED : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute
- // FALLTHROUGH : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Statement-Attributes.html#index-fallthrough-statement-attribute
- // ALWAYS_INLINE: https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute
- #if defined(__GNUC__)
- #define ATTR_PACKED __attribute__((packed))
- #define ATTR_NOINLINE __attribute__((noinline))
- #define ATTR_DEPRECATED __attribute__((deprecated))
- #define ATTR_FALLTHROUGH __attribute__((fallthrough))
- #define ATTR_ALWAYS_INLINE __attribute__((always_inline))
- #endif
- /************************************ MISC ************************************/
- struct Fpoint2d { f32 x, y; };
- struct Fpoint3d { f32 x, y, z; };
- struct Point2d { s32 x, y; };
- struct Point3d { s32 x, y, z; };
- struct Rect2d { s32 x, y, w, h; };
- // These are custom implementations for necessary functions.
- // They're only included if the std library isn't used,
- // since the framework has to use them for some things.
- #ifndef STDLIB_USED
- void* memSet(void* dst, int val, size_t len);
- //(len_max does not include null-terminator!)
- //(if !len_max, call is analogous to str(not n)len)
- size_t strnLen(const char* str, size_t len_max);
- char* strnCpy(char* str_dst, const char* str_src, size_t len_max);
- char* strCat(char* dst, const char* src);
- //(len_max does not include null-terminator!)
- //(if !len_max, call is analogous to str(not n)cmp)
- s32 strnCmp(const char* str_a, const char* str_b, size_t len_max);
- f32 sinF(f32 x);
- #define cosF(_x) sinF((_x)+M_PI2f)
- #define tanF(_x) ( sinF(_x)/cosF(_x) )
- #endif
- enum MessageBoxEnum {
- // Return values
- MSGBOX_RTN_NULL = 0x00000000, //showMessageBox failed
- MSGBOX_RTN_OK = 0x00000001, //'ok' button was clicked
- MSGBOX_RTN_CANCEL = 0x00000002, //'cancel' button was clicked
- MSGBOX_RTN_ABORT = 0x00000003, //'abort' button was clicked
- MSGBOX_RTN_RETRY = 0x00000004, //'retry' button was clicked
- MSGBOX_RTN_IGNORE = 0x00000005, //'ignore' button was clicked
- MSGBOX_RTN_YES = 0x00000006, //'yes' button was clicked
- MSGBOX_RTN_NO = 0x00000007, //'no' button was clicked
- MSGBOX_RTN_TRYAGAIN = 0x0000000A, //'try again' button was clicked
- MSGBOX_RTN_CONTINUE = 0x0000000B, //'continue' button was clicked
- // Button types
- MSGBOX_BTN_OK = 0x00000000,
- MSGBOX_BTN_OKCANCEL = 0x00000001,
- MSGBOX_BTN_ABORTRETRYIGNORE = 0x00000002,
- MSGBOX_BTN_YESNOCANCEL = 0x00000003,
- MSGBOX_BTN_YESNO = 0x00000004,
- MSGBOX_BTN_RETRYCANCEL = 0x00000005,
- MSGBOX_BTN_CANCELTRYCONTINUE = 0x00000006,
- // Icon types
- MSGBOX_ICN_ERROR = 0x000000010,
- MSGBOX_ICN_QUESTION = 0x000000020, //apparently deprecated, but still supported
- MSGBOX_ICN_WARNING = 0x000000030,
- MSGBOX_ICN_INFO = 0x000000040,
- };
- u32 showMessageBox(const char* text = nullptr, const char* title = nullptr,
- u32 type = MSGBOX_BTN_OK|MSGBOX_ICN_INFO,
- u32 defaultButton = 0);
- u64 timeGetPerfCounter();
- u64 timeGetPerfFreq();
- f64 timeGetSeconds();
- void timeSleep(u32 milliseconds);
- #ifdef PRINT_EVENT_USED
- #ifdef _DEBUG
- union Event; // Forward declaration
- void print_event(Event& evt);
- #else
- #define print_event(_evt) {}
- #endif /* _DEBUG */
- #endif /* PRINT_EVENT_USED */
- // Warning: this doesn't check if buffer is not nullptr,
- // nor does it check if which_bit is inside buffer!
- bool is_bit_set(const void* buffer, u32 which_bit);
- #ifdef FRAND_USED
- f64 frand(); // 0.0f -> 1.0f
- f64 frand2(); //-1.0f -> 1.0f
- f32 frandf(); // 0.0f -> 1.0f
- f32 frandf2(); //-1.0f -> 1.0f
- #endif /* FRAND_USED */
- /* taken from stb_sprintf.h (what these 2 functions use under-the-hood):
- 64-BIT INTS:
- ============
- This library also supports 64-bit integers and you can use MSVC style or
- GCC style indicators (%I64d or %lld). It supports the C99 specifiers
- for size_t and ptr_diff_t (%jd %zd) as well.
- EXTRAS:
- =======
- Like some GCCs, for integers and floats, you can use a ' (single quote)
- specifier and commas will be inserted on the thousands: "%'d" on 12345
- would print 12,345.
- For integers and floats, you can use a "$" specifier and the number
- will be converted to float and then divided to get kilo, mega, giga or
- tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is
- "2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn
- 2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three
- $:s: "%$$$d" -> "2.42 M". To remove the space between the number and the
- suffix, add "_" specifier: "%_$d" -> "2.53M".
- In addition to octal and hexadecimal conversions, you can print
- integers in binary: "%b" for 256 would print 100.
- PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC):
- ===================================================================
- "%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC)
- "%24d" across all 32-bit ints (4.5x/4.2x faster)
- "%x" across all 32-bit ints (4.5x/3.8x faster)
- "%08x" across all 32-bit ints (4.3x/3.8x faster)
- "%f" across e-10 to e+10 floats (7.3x/6.0x faster)
- "%e" across e-10 to e+10 floats (8.1x/6.0x faster)
- "%g" across e-10 to e+10 floats (10.0x/7.1x faster)
- "%f" for values near e-300 (7.9x/6.5x faster)
- "%f" for values near e+300 (10.0x/9.1x faster)
- "%e" for values near e-300 (10.1x/7.0x faster)
- "%e" for values near e+300 (9.2x/6.0x faster)
- "%.320f" for values near e-300 (12.6x/11.2x faster)
- "%a" for random values (8.6x/4.3x faster)
- "%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster)
- "%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster)
- "%s%s%s" for 64 char strings (7.1x/7.3x faster)
- "...512 char string..." ( 35.0x/32.5x faster!)
- */
- #define snprintf snPrintf
- #define vsnprintf vsnPrintf
- #include <stdarg.h>
- //if len_max == 0 OR > INT_MAX, call is analogous to s(not n)printf
- s32 snPrintf(char* str_dst, size_t len_max, const char* str_fmt, ...);
- //^^ VV unlike normal snprintf, these'll always return a null-terminated string
- //if len_max == 0 OR > INT_MAX, call is analogous to vs(not n)printf
- s32 vsnPrintf(char* str_dst, size_t len_max, const char* str_fmt, va_list va);
- // Use these instead of malloc, free, or realloc!
- void* mem_alloc(size_t size);
- void mem_free(void* ptr_p); // ptr_p means: use &ptr instead of ptr
- void* mem_realloc(void* ptr_p, size_t newSize); // ptr_p is the same as in free
- size_t mem_getNumAllocations();
- size_t mem_setNumAllocations(size_t value);
- size_t mem_addNumAllocations(s32 amount);
- void* mem_set(void* ptr, s32 value, size_t size);
- void* mem_copy(void* destination, const void* source, size_t size);
- struct mem_Wrapper {
- void* ptr = nullptr;
- inline mem_Wrapper(size_t size){ ptr = mem_alloc(size); }
- inline mem_Wrapper(void* _ptr) : ptr(_ptr) {} // Existing mem_alloc
- inline ~mem_Wrapper(){ mem_free(&ptr); }; // Safe to use, even if ptr is null
- inline void* realloc(size_t newSize){ return mem_realloc(&ptr, newSize); }
- };
- /*********************************** INPUT ************************************/
- #define EVENT_ID(_id) ( (_id) & 0xFFFF0000 )
- #define SUBEVENT_ID(_id) ( (_id) & 0xFFFF )
- enum EventEnum {
- EVENT_NULL = 0x00000000,
- EVENT_COMMON = 0x00010000, // Event_Common (Event.common)
- // (Occurs when the window is destroyed!)
- EVENT_QUIT = 0x00020000, // N/A (N/A)
- EVENT_KEY = 0x00030000, // Event_Key (Event.key)
- EVENT_KEY_CHAR = EVENT_KEY | 0x0001,
- EVENT_KEY_UP = EVENT_KEY | 0x0002,
- EVENT_KEY_DOWN = EVENT_KEY | 0x0003,
- EVENT_MOUSE = 0x00040000, // Event_Mouse (Event.mouse)
- EVENT_MOUSE_MOVED = EVENT_MOUSE | 0x0001,
- EVENT_MOUSE_HWHEEL = EVENT_MOUSE | 0x0002,
- EVENT_MOUSE_VWHEEL = EVENT_MOUSE | 0x0003,
- EVENT_MOUSE_UP = EVENT_MOUSE | 0x0004,
- EVENT_MOUSE_DOWN = EVENT_MOUSE | 0x0005,
- // (Occurs once every time the cursor is trapped and released respectively!)
- EVENT_CURSOR = 0x00050000, // N/A (N/A)
- EVENT_CURSOR_TRAPPED = EVENT_CURSOR | 0x0001,
- EVENT_CURSOR_RELEASED = EVENT_CURSOR | 0x0002,
- EVENT_UNKNOWN = 0xFFFF0000,
- };
- /*+EVENT_COMMON+*/
- struct Event_Common { //16B
- u32 type;
- u32 _unused; // Unused by common, but not necessarily other event types
- u64 timestamp; // Performance counter is used; see "timeGetPerfCounter()"
- };
- /*-EVENT_COMMON-*/
- /*+EVENT_KEY+*/
- // Event_Key.kmods can use any combination of these OR'd (AKA |) together
- enum Event_Key_ModifierEnum { // (These are bitmasks)
- KMOD_NONE = 0x0000,
- KMOD_LSHIFT = 0x0001,
- KMOD_RSHIFT = 0x0002,
- KMOD_LCTRL = 0x0004,
- KMOD_RCTRL = 0x0008,
- KMOD_LALT = 0x0010,
- KMOD_RALT = 0x0020,
- KMOD_LGUI = 0x0040, // Windows key?
- KMOD_RGUI = 0x0080, //^^
- KMOD_LWIN = KMOD_LGUI,
- KMOD_RWIN = KMOD_RGUI,
- KMOD_NUMLOCK = 0x1000,
- KMOD_CAPSLOCK = 0x2000,
- KMOD_ALTGRAPH = 0x4000,
- KMOD_SCROLLOCK = 0x8000,
- KMOD_CTRL = ( KMOD_LCTRL | KMOD_RCTRL ),
- KMOD_SHIFT = ( KMOD_LSHIFT | KMOD_RSHIFT ),
- KMOD_ALT = ( KMOD_LALT | KMOD_RALT ),
- KMOD_GUI = ( KMOD_LGUI | KMOD_RGUI ),
- KMOD_WIN = ( KMOD_LWIN | KMOD_RWIN ),
- };
- enum Event_Key_PhysicalEnum {
- // TBD because I don't want to bother with scancode stuff right now
- };
- enum Event_Key_VirtualEnum {
- VKEY_NULL = 0x00,
- //(misc. mouse) = 0x01 -> 0x06
- //(reserved) = 0x07,
- VKEY_BACK = 0x08, //backspace key
- VKEY_BACKSPACE = VKEY_BACK,
- VKEY_TAB = 0x09,
- //(reserved) = 0x0A -> 0x0B,
- VKEY_CLEAR = 0x0C,
- VKEY_RETURN = 0x0D, //enter key
- VKEY_ENTER = VKEY_RETURN,
- //(unassigned) = 0x0E -> 0x0F,
- VKEY_SHIFT = 0x10,
- VKEY_CONTROL = 0x11, //ctrl key
- VKEY_CTRL = VKEY_CONTROL,
- VKEY_MENU = 0x12, //alt key
- VKEY_ALT = VKEY_MENU,
- VKEY_PAUSE = 0x13,
- VKEY_CAPITAL = 0x14, //caps lock key
- VKEY_CAPSLOCK = VKEY_CAPITAL,
- //(IME stuff) = 0x15 -> 0x1A,
- VKEY_ESCAPE = 0x1B, //esc key
- //(IME stuff) = 0x1C -> 0x1F,
- VKEY_SPACE = 0x20, //space bar key
- VKEY_PRIOR = 0x21, //page up key
- VKEY_PGUP = VKEY_PRIOR,
- VKEY_NEXT = 0x22, //page down key
- VKEY_PGDN = VKEY_NEXT,
- VKEY_END = 0x23,
- VKEY_HOME = 0x24,
- VKEY_LEFT = 0x25, //left arrow key
- VKEY_UP = 0x26, //up arrow key
- VKEY_RIGHT = 0x27, //right arrow key
- VKEY_DOWN = 0x28, //down arrow key
- VKEY_SELECT = 0x29,
- VKEY_PRINT = 0x2A,
- VKEY_EXECUTE = 0x2B,
- VKEY_SNAPSHOT = 0x2C, //print screen key
- VKEY_PRTSC = VKEY_SNAPSHOT,
- VKEY_INSERT = 0x2D, //ins key
- VKEY_DELETE = 0x2E, //del key
- VKEY_HELP = 0x2F, //help key
- VKEY_0 = 0x30, //'0'
- VKEY_1 = 0x31, //'1'
- VKEY_2 = 0x32, //'2'
- VKEY_3 = 0x33, //'3'
- VKEY_4 = 0x34, //'4'
- VKEY_5 = 0x35, //'5'
- VKEY_6 = 0x36, //'6'
- VKEY_7 = 0x37, //'7'
- VKEY_8 = 0x38, //'8'
- VKEY_9 = 0x39, //'9'
- //(undefined) = 0x3A -> 0x40,
- VKEY_A = 0x41, //'A'
- VKEY_B = 0x42, //'B'
- VKEY_C = 0x43, //'C'
- VKEY_D = 0x44, //'D'
- VKEY_E = 0x45, //'E'
- VKEY_F = 0x46, //'F'
- VKEY_G = 0x47, //'G'
- VKEY_H = 0x48, //'H'
- VKEY_I = 0x49, //'I'
- VKEY_J = 0x4A, //'J'
- VKEY_K = 0x4B, //'K'
- VKEY_L = 0x4C, //'L'
- VKEY_M = 0x4D, //'M'
- VKEY_N = 0x4E, //'N'
- VKEY_O = 0x4F, //'O'
- VKEY_P = 0x50, //'P'
- VKEY_Q = 0x51, //'Q'
- VKEY_R = 0x52, //'R'
- VKEY_S = 0x53, //'S'
- VKEY_T = 0x54, //'T'
- VKEY_U = 0x55, //'U'
- VKEY_V = 0x56, //'V'
- VKEY_W = 0x57, //'W'
- VKEY_X = 0x58, //'X'
- VKEY_Y = 0x59, //'Y'
- VKEY_Z = 0x5A, //'Z'
- VKEY_LWIN = 0x5B, //left windows key
- VKEY_RWIN = 0x5C, //right windows key
- VKEY_APPS = 0x5D, //applications key
- //(reserved) = 0x5E,
- VKEY_SLEEP = 0x5F, //computer sleep key
- VKEY_NUMPAD0 = 0x60,
- VKEY_NUMPAD1 = 0x61,
- VKEY_NUMPAD2 = 0x62,
- VKEY_NUMPAD3 = 0x63,
- VKEY_NUMPAD4 = 0x64,
- VKEY_NUMPAD5 = 0x65,
- VKEY_NUMPAD6 = 0x66,
- VKEY_NUMPAD7 = 0x67,
- VKEY_NUMPAD8 = 0x68,
- VKEY_NUMPAD9 = 0x69,
- VKEY_MULTIPLY = 0x6A, //numpad '*'
- VKEY_ADD = 0x6B, //numpad '+'
- VKEY_SEPARATOR = 0x6C, //numpad enter
- VKEY_SUBTRACT = 0x6D, //numpad '-'
- VKEY_DECIMAL = 0x6E, //numpad '.'
- VKEY_DIVIDE = 0x6F, //numpad '/'
- VKEY_F1 = 0x70,
- VKEY_F2 = 0x71,
- VKEY_F3 = 0x72,
- VKEY_F4 = 0x73,
- VKEY_F5 = 0x74,
- VKEY_F6 = 0x75,
- VKEY_F7 = 0x76,
- VKEY_F8 = 0x77,
- VKEY_F9 = 0x78,
- VKEY_F10 = 0x79,
- VKEY_F11 = 0x7A,
- VKEY_F12 = 0x7B,
- VKEY_F13 = 0x7C,
- VKEY_F14 = 0x7D,
- VKEY_F15 = 0x7E,
- VKEY_F16 = 0x7F,
- VKEY_F17 = 0x80,
- VKEY_F18 = 0x81,
- VKEY_F19 = 0x82,
- VKEY_F20 = 0x83,
- VKEY_F21 = 0x84,
- VKEY_F22 = 0x85,
- VKEY_F23 = 0x86,
- VKEY_F24 = 0x87,
- //(reserved) = 0x88 -> 0x8F,
- VKEY_NUMLOCK = 0x90,
- VKEY_SCROLL = 0x91, //scroll lock key
- VKEY_SCROLLOCK = VKEY_SCROLL,
- //(OEM-specific) = 0x92 -> 0x96,
- //(unassigned) = 0x97 -> 0x9F,
- //(l/r key variants) = 0xA0 -> 0xA5,
- //(browser keys) = 0xA6 -> 0xAC,
- VKEY_VOLUME_MUTE = 0xAD,
- VKEY_VOLUME_DOWN = 0xAE,
- VKEY_VOLUME_UP = 0xAF,
- VKEY_MEDIA_NEXT_TRACK = 0xB0,
- VKEY_MEDIA_PREV_TRACK = 0xB1,
- VKEY_MEDIA_STOP = 0xB2,
- VKEY_MEDIA_PLAY_PAUSE = 0xB3, //Play/Pause Media key
- //(launch keys) = 0xB4 -> 0xB7,
- //(reserved) = 0xB8 -> 0xB9,
- VKEY_OEM_1 = 0xBA, //misc. chars; varies by keyboard (';',':' on US standard)
- VKEY_SEMICOLON = VKEY_OEM_1,
- VKEY_OEM_PLUS = 0xBB, //'+' in any country/region
- VKEY_PLUS = VKEY_OEM_PLUS,
- VKEY_OEM_COMMA = 0xBC, //',' in any country/region
- VKEY_COMMA = VKEY_OEM_COMMA,
- VKEY_OEM_MINUS = 0xBD, //'-' in any country/region
- VKEY_MINUS = VKEY_OEM_MINUS,
- VKEY_OEM_PERIOD = 0xBE, //'.' in any country/region
- VKEY_PERIOD = VKEY_OEM_PERIOD,
- VKEY_OEM_2 = 0xBF, //misc. chars; varies by keyboard ('/','?' on US standard)
- VKEY_FSLASH = VKEY_OEM_2,
- VKEY_OEM_3 = 0xC0, //misc. chars; varies by keyboard ('`','~' on US standard)
- VKEY_BACKTICK = VKEY_OEM_3,
- //(reserved) = 0xC1 -> 0xDA,
- VKEY_OEM_4 = 0xDB, //misc. chars; varies by keyboard ('[','{' on US standard)
- VKEY_LBRACKET = VKEY_OEM_4,
- VKEY_OEM_5 = 0xDC, //misc. chars; varies by keyboard ('\\','|' on US standard)
- VKEY_BSLASH = VKEY_OEM_5,
- VKEY_OEM_6 = 0xDD, //misc. chars; varies by keyboard (']','}' on US standard)
- VKEY_RBRACKET = VKEY_OEM_6,
- VKEY_OEM_7 = 0xDE, //misc. chars; varies by keyboard ('\'','\"' on US standard)
- VKEY_APOSTROPHE = VKEY_OEM_7,
- VKEY_OEM_8 = 0xDF, //misc. chars; varies by keyboard
- //(reserved) = 0xE0,
- //(misc.) = 0xE1 -> 0xE7,
- //(unassigned) = 0xE8,
- //(misc.) = 0xE9 -> 0xFE,
- };
- // Mod[ifier]
- union Event_Key_Mod { //2B
- // IMPORTANT:
- // Due to me having terminal couldn't-care-less syndrome,
- // I haven't implemented differenciating between the
- // left and right variants of shift, control, et cetera,
- // so both variants are set/unset when either are pressed/unpressed.
- // (Except lgui and rgui, since that's easier to detect???)
- // (ALSO ALTGRAPH ISN'T IMPLEMENTED AT ALL THANKS MICROSOFT)
- struct {
- u16 lshift : 1;
- u16 rshift : 1;
- u16 lctrl : 1;
- u16 rctrl : 1;
- u16 lalt : 1;
- u16 ralt : 1;
- u16 lgui : 1;
- u16 rgui : 1;
- u16 _unused : 4;
- u16 numlock : 1;
- u16 capslock : 1;
- u16 altgraph : 1;
- u16 scrollock : 1;
- };
- u16 all;
- };
- // Short for "Key Symbol"
- struct Event_Key_Sym { //8B
- union {
- Event_Key_Mod kmod;
- u16 kmods;
- };
- u8 _unused;
- u8 pkey; // Physical key code (named .scancode in SDL's Keysym struct)
- u8 vkey; // Virtual key code (named .sym in SDL's Keysym struct)
- bool pressed;
- bool ischar; // 'is event KEY_CHAR?', otherwise it's KEY_UP or KEY_DOWN
- bool repeat; // Y'know that thing where in a text editor you hold down a key?
- };
- struct Event_Key { //24B
- u32 type;
- u32 _unused_0;
- u64 timestamp; // Performance counter is used; see "timeGetPerfCounter()"
- union {
- struct { // (Effectively a copy of Event_Key_Sym)
- u16 kmods;
- u8 _unused_1;
- u8 pkey;
- u8 vkey;
- bool pressed;
- bool ischar;
- bool repeat;
- };
- Event_Key_Sym sym;
- };
- };
- /*-EVENT_KEY-*/
- /*+EVENT_MOUSE+*/
- // Event_Mouse.button can use any combination of these OR'd (AKA |) together
- enum Event_Mouse_ButtonEnum { // (These are bitmasks)
- MBUTTON_LEFT = 0x01,
- MBUTTON_MIDDLE = 0x02,
- MBUTTON_RIGHT = 0x04,
- MBUTTON_X1 = 0x08, // Those 2 buttons on the sides of most mice nowadays
- MBUTTON_X2 = 0x10, //^^
- MBUTTON_CTRL = 0x20, // 'Is the control key currently pressed?'
- MBUTTON_SHIFT = 0x40, // 'Is the shift key currently pressed?'
- };
- // (EVENT_MOUSE_<H/V>WHEEL events use dx and dy!)
- struct Event_Mouse { //32B
- u32 type;
- u8 _unused;
- u8 button; // Flags for currently pressed buttons (Event_Mouse_ButtonEnum)
- bool pressed; // Will be true if button is nonzero
- bool dblClick; // 'Is double click?' (ignored if cursor is trapped)
- u64 timestamp;
- f32 x; // Coordinates relative to window
- f32 y; //^^
- f32 dx; // Delta x (coordinates relative to last recorded x position)
- f32 dy; // Delta y (coordinates relative to last recorded y position)
- // (IF THE CURSOR IS TRAPPED, DELTAS WILL BE GIVEN AS-IS,
- // WITHOUT BEING SCALED WITH RESPECT TO THE WINDOW'S CURRENT SIZE!)
- };
- /*-EVENT_MOUSE-*/
- union Event { //32B (assuming Event_Mouse is the largest event bytes-wise)
- u32 type;
- Event_Common common;
- Event_Key key;
- Event_Mouse mouse;
- };
- // Populates *event_p with the contents of the first event in the event queue.
- // Returns false if there were no events left in queue; true otherwise.
- // (Calling this exclusively in the main thread is recommended)
- bool pollEvent(Event* event_p = nullptr); // Burns events if event_p is nullptr
- // Returns true if the mouse cursor is clipped within the window, and is hidden
- bool is_cursor_trapped();
- /*********************************** AUDIO ************************************/
- // Don't edit this one, as it's the hardcoded max length of an audio buffer!
- #define AUDIO_SAMPLES_MAX 4096
- // Stereo audio samples as two 32-bit floats,
- // where each of the two channels can be between -1.0 to 1.0
- struct StereoF32 { f32 l,r; };
- // The length of the audio stream's buffer, in samples
- extern u32 audio_samples;
- // The audio's sample rate, in hertz
- extern u32 sample_rate;
- #include "sound_stuff.hpp"
- /*********************************** VIDEO ************************************/
- #define WIN_NAME "OpenGL Demo"
- // Used for setting pixels_palette.
- // This struct is analagous to Win32's own RGBQUAD struct,
- // but formatted to be a bit more readable and nicer-looking
- //
- // (Make sure to call update_palette() to apply any changes to the palette!)
- union Color24 {
- // Full pixel value. Since this is a union, this 32-bit value takes
- // up the same space as the four 8-bit values below.
- // The purpose of using a union like this is that by setting v,
- // you are setting b,g,r, and _ at the same time!
- u32 v;
- // Before the C11 standard, anonymous structs (or unions for that matter)
- // were compiler-specific extensions, but virtually all modern compilers
- // allow this type of syntax, where structs that are directly declaring
- // the contents of a type (as opposed to defining a type that can be
- // replicated) without giving it a name.
- //
- // In this case, this effectively packages these four bytes to be in this
- // order, rather than reside in the same space (this is a union, after all!)
- struct {
- u8 b;
- u8 g;
- u8 r;
- u8 _; // (Unused; this is just padding to the nearest multiple of 32-bits)
- };
- };
- void present_window();
- void close_window(); // Also triggers an EVENT_QUIT
- bool is_win_closed();
- // Returns the current size of the window's *client* area,
- // which is basically the space in the window where stuff is actually drawn
- Point2d get_win_size();
- // Useful for, say, drawing/swapping buffers
- // only when the window has input focus
- bool is_win_focused();
- void trap_cursor(bool enable, bool condition);
- /********************************** FILE IO ***********************************/
- struct BinaryData {
- union { // The everything union~
- u8 * data_u8;
- u16* data_u16;
- u32* data_u32;
- u64* data_u64;
- s8 * data_s8;
- s16* data_s16;
- s32* data_s32;
- s64* data_s64;
- f32* data_f32;
- f64* data_f64;
- char* data_char;
- void* data_void = nullptr;
- };
- // Even if size is 0, data will always have at least a single byte of valid
- // allocated memory. This is because there is always one more byte allocated
- // than is requested, to make sure that data is only ever nullptr if
- // construction fails! (This extra byte will always be set to 0.)
- const size_t size;
- BinaryData(const char* file_path);
- // This will allocate _size bytes for data, before copying src to data
- //
- // (It is safe to pass nullptr to src, though that would make the struct
- // instance sorta equivalent to a garbage-collected CoTaskMemAlloc().)
- BinaryData(const void* src, size_t _size);
- ~BinaryData();
- };
- // fileio_read allocates memory! use mem_free on the returned pointer after use!
- void* fileio_read(const char* file_path, size_t* dataSize_p);
- bool fileio_write(const char* file_path, const void* data,
- size_t data_size, bool append = false);
- #define FILEIO_SIZE_ERR 0xFFFFFFFFFFFFFFFF
- size_t fileio_size(const char* file_path);
- bool fileio_isreadonly(const char* file_path);
- bool fileio_exists(const char* file_path);
- bool fileio_delete(const char* file_path);
- /*********************** DRAW STUFF (NOT WIN32-RELATED) ***********************/
- #endif /* _PUBLIC_STUFF_HPP */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement