Advertisement
Kitomas

code for 2025-06-26 (3/4)

Jun 27th, 2025
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 48.33 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"opengl_metaballs_2025-06-26\src\win32\std.cpp":
  4. #include <public_stuff.hpp>
  5.  
  6. #ifndef STDLIB_USED
  7.  
  8.  
  9.  
  10.  
  11.  
  12. void* memSet(void* dst, int val, size_t len){
  13.   if(!len) return dst;
  14.  
  15.   u8* dst8 = (u8*)dst;
  16.   u8  val8 = (u8 )val;
  17.  
  18.  
  19.   size_t remainder = len%sizeof(u32);
  20.   len -= remainder;
  21.  
  22.   while((remainder--) > 0)
  23.     *(dst8++) = val8;
  24.  
  25.  
  26.   u32* dst32 = (u32*)dst8;
  27.   u32  val32 = val8;
  28.  
  29.   val32 |= val32<< 8;
  30.   val32 |= val32<<16;
  31.  
  32.   len /= sizeof(u32);
  33.  
  34.   while((len--) > 0)
  35.     *(dst32++) = val32;
  36.  
  37.  
  38.   return dst;
  39.  
  40. }
  41.  
  42.  
  43.  
  44. void* memCpy(void* dst, const void* src, size_t len){
  45.   if(!len) return dst;
  46.  
  47.   u8* dst8 = (u8*)dst;
  48.   u8* src8 = (u8*)src;
  49.  
  50.   while(len--) *(dst8++) = *(src8++);
  51.  
  52.   return dst;
  53.  
  54. }
  55.  
  56.  
  57.  
  58.  
  59.  
  60. //  (len_max does not include null-terminator!)
  61. //  (If !len_max, call is analogous to str(not n)len)
  62. size_t strnLen(const char* str, size_t len_max){
  63.   size_t len = 0;
  64.  
  65.   if(!len_max){
  66.     for(; str[len]; ++len);
  67.  
  68.   } else {
  69.     for(; str[len] && len<len_max; ++len);
  70.  
  71.   }
  72.  
  73.   return len;
  74.  
  75. }
  76.  
  77.  
  78.  
  79. char* strnCpy(char* str_dst, const char* str_src, size_t len_max){
  80.   char* _str_dst = str_dst; // Copy original state of str_dst
  81.  
  82.   if(!len_max){
  83.     while((*str_dst++ = *str_src++));
  84.  
  85.   } else {
  86.     size_t i = 0;
  87.     while(i++ != len_max && (*str_dst++ = *str_src++));
  88.  
  89.   }
  90.  
  91.  
  92.   *str_dst = 0; // Null-terminator
  93.  
  94.   return _str_dst;
  95.  
  96. }
  97.  
  98.  
  99.  
  100. char* strCat(char* dst, const char* src){
  101.   char* dst_start = dst;
  102.  
  103.   while(*dst) ++dst;
  104.   while((*dst++ = *src++));
  105.  
  106.   return dst_start;
  107.  
  108. }
  109.  
  110.  
  111.  
  112. // (len_max does not include null-terminator!)
  113. // (If !len_max, call is analogous to str(not n)cmp)
  114. s32 strnCmp(const char* str_a, const char* str_b, size_t len_max){
  115.   if(!len_max){
  116.     while(*str_a && (*str_a == *str_b))
  117.       ++str_a, ++str_b;
  118.  
  119.   } else {
  120.     --len_max;
  121.     while(*str_a && (*str_a == *str_b) && len_max)
  122.       ++str_a, ++str_b, --len_max;
  123.  
  124.   }
  125.  
  126.   return (*(const u8*)str_a) - (*(const u8*)str_b);
  127.  
  128. }
  129.  
  130.  
  131.  
  132.  
  133.  
  134. #define sinf_bhaskara_fmod(_x, _y) (   (_x) - (  (s64)((_x)/(_y)) * (_y)  )   )
  135.  
  136. // Custom sinf implementation; a little under 2% error iirc
  137. // (You could switch floats with doubles here, though the approximation's
  138. // lack of precision prevents that switch from being all that useful.)
  139. f32 sinF(f32 x){
  140.   // Keep x within the domain of >=0  ->  <pi,
  141.   // while preserving relevant info
  142.   bool negative = x<0.0f;
  143.   if(x < 0.0f) x = -x; //x = fabsf(x);
  144.   x = sinf_bhaskara_fmod(x, M_2PIf); //x %= 2pi
  145.   // 'If original value of x%(2pi) is between _ -> _, returned value will be _':
  146.    //>-2pi -> <=-pi,  >=0
  147.    //> -pi -> <=  0,  <=0
  148.    //>=  0 -> <  pi,  >=0
  149.    //>= pi -> < 2pi,  <=0
  150.   negative ^= x>=M_PIf;
  151.   if(x >= M_PIf) x -= M_PIf; //x %= pi
  152.  
  153.   // Uses Bhaskara I's sine approximation formula
  154.   f32 result = 16.0f*x * (M_PIf-x);
  155.   result /= 5.0f*M_PIf*M_PIf - result*0.25f;
  156.   return (negative) ? -result : result;
  157.  
  158. }
  159.  
  160.  
  161.  
  162.  
  163.  
  164. #endif /* STDLIB_USED */
  165. /******************************************************************************/
  166. /******************************************************************************/
  167. //"opengl_metaballs_2025-06-26\src\win32\video.cpp":
  168. // If nonzero, WM_PAINT will fill the client area with the selected color
  169. #define FILL_WINDOW_TOGGLE 0
  170.  
  171. // (This color is ignoredif FILL_WINDOW_TOGGLE != 1)
  172. #define FILL_WINDOW_COLOR RGB(0, 0, 0)
  173.  
  174.  
  175.  
  176. #include "_WindowProc.hpp"
  177.  
  178. #ifndef   INT_MAX
  179. #define   INT_MAX 2147483647
  180. #endif /* INT_MAX */
  181.  
  182.  
  183.  
  184.  
  185.  
  186. static const char win_class_name[] = "Fullscreen Window Class";
  187. static WNDCLASS   win_class = {0};
  188. HWND              win;
  189. HDC               win_dc;
  190. bool              win_closed = false;
  191. Point2d           win_size;
  192. bool              win_has_focus;
  193.  
  194.  
  195.  
  196.  
  197.  
  198. LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); // Forward declaration
  199.  
  200. int WindowInit(HINSTANCE hThisInst){
  201.   win_size.x = GetSystemMetrics(SM_CXSCREEN);
  202.   win_size.y = GetSystemMetrics(SM_CYSCREEN);
  203.  
  204.   win_class.style         = CS_DBLCLKS; // Allow double clicks
  205.   win_class.lpfnWndProc   = WindowProc;
  206.   win_class.hInstance     = hThisInst;
  207.   win_class.hCursor       = LoadCursorA(nullptr, IDC_ARROW);
  208.   win_class.lpszClassName = win_class_name;
  209.   RegisterClassA(&win_class);
  210.  
  211.   // (Window is intentionally hidden until initialization is done!)
  212.   win = CreateWindowExA(WS_EX_APPWINDOW,              // Extended Window Style
  213.                         win_class_name, WIN_NAME,     // Class Name + Win. Name
  214.                         WS_POPUP /*| WS_VISIBLE*/,    // Window style
  215.                         0, 0, win_size.x, win_size.y, // X, Y, Width, Height
  216.                         nullptr, nullptr, hThisInst, nullptr);
  217.  
  218.   if(win == nullptr) return -2;
  219.  
  220.   win_dc = GetDC(win);
  221.  
  222.   if(win_dc == nullptr) return -3;
  223.  
  224.   return 0;
  225.  
  226. }
  227.  
  228. void WindowQuit(){} // Currently unnecessary
  229.  
  230.  
  231.  
  232.  
  233.  
  234. // A thin wrapper
  235. void present_window(){
  236.   SwapBuffers(win_dc);
  237.  
  238. }
  239.  
  240.  
  241.  
  242. void close_window(){
  243.   if(win_closed) return;
  244.  
  245.   ShowWindow(win, SW_HIDE);
  246.  
  247.   ReleaseDC(win, win_dc);
  248.   DestroyWindow(win);
  249.   // These might not be necessary, due to the way uninitialization is set up
  250.   //UnregisterClassA
  251.   //DeleteCriticalSection
  252.  
  253.   win_closed = true;
  254.  
  255. }
  256.  
  257.  
  258.  
  259. bool is_win_closed(){
  260.   return win_closed;
  261.  
  262. }
  263.  
  264.  
  265.  
  266. Point2d get_win_size(){
  267.   return win_size;
  268.  
  269. }
  270.  
  271.  
  272.  
  273. bool is_win_focused(){
  274.   return win_has_focus;
  275.  
  276. }
  277.  
  278.  
  279.  
  280.  
  281.  
  282. extern CRITICAL_SECTION events_lock;
  283. extern Event            events_queue[65536];
  284. extern u16              events_next;
  285. extern u16              events_end;
  286.  
  287. extern Event_Key_Mod key_mods;
  288. extern bool          key_states[256];
  289.  
  290. extern Point2d mouse_position;
  291. extern bool    mouse_was_moved_before;
  292.  
  293. extern bool cursor_trapped;
  294. extern bool cursor_hidden;
  295.  
  296. static union {
  297.   RECT v;
  298.   struct { POINT topLeft, bottomRight; };
  299. } clipRect;
  300.  
  301. #include <hidusage.h>
  302.  
  303. static RAWINPUTDEVICE rid = {
  304.   .usUsagePage = HID_USAGE_PAGE_GENERIC,  // Generic desktop controls
  305.   .usUsage     = HID_USAGE_GENERIC_MOUSE, // Mouse
  306. //.dwFlags     = RIDEV_NOLEGACY,
  307.   .hwndTarget  = nullptr,
  308. };
  309.  
  310. MOUSE_ButtonStates mbutton_states; // Persistent mouse state
  311.  
  312.  
  313.  
  314.  
  315.  
  316. static void update_cursor_clip(){
  317.   LPRECT clipRect_p = nullptr;
  318.  
  319.   if(cursor_trapped){
  320.     clipRect_p = &clipRect.v;
  321.     GetClientRect(win, clipRect_p);
  322.     ClientToScreen(win, &clipRect.topLeft);
  323.     ClientToScreen(win, &clipRect.bottomRight);
  324.  
  325.   }
  326.  
  327.   ClipCursor(clipRect_p);
  328.  
  329. }
  330.  
  331.  
  332.  
  333.  
  334.  
  335. void trap_cursor(bool enable, bool condition){
  336.   if(!condition) return;
  337.  
  338.   if(enable != cursor_hidden){
  339.     cursor_hidden = enable;
  340.     ShowCursor(!enable); // Enabling makes it hidden, hence the '!'
  341.   }
  342.  
  343.   if(enable != cursor_trapped){
  344.     cursor_trapped = enable;
  345.     update_cursor_clip();
  346.  
  347.     if(enable) SetCapture(win);
  348.     else       ReleaseCapture();
  349.  
  350.     if(enable  &&  rid.hwndTarget == nullptr){
  351.       rid.dwFlags    = RIDEV_NOLEGACY;
  352.       rid.hwndTarget = win;
  353.       if(!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE))){
  354.         _printf("ERROR: failed to register mouse as a raw input device! "
  355.                 "(error code = 0x%08X)\n", (u32)GetLastError());
  356.         rid.hwndTarget = nullptr;
  357.       }
  358.     }
  359.     else if(!enable  &&  rid.hwndTarget != nullptr){
  360.       HWND hwndOld = rid.hwndTarget;
  361.       rid.dwFlags    = RIDEV_REMOVE;
  362.       rid.hwndTarget = nullptr;
  363.       if(!RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE))){
  364.         _printf("ERROR: failed to unregister mouse as a raw input device! "
  365.                 "(error code = 0x%08X)\n", (u32)GetLastError());
  366.         rid.hwndTarget = hwndOld;
  367.       }
  368.     }
  369.  
  370.     Event evt;
  371.     memSet(&evt, 0, sizeof(Event));
  372.     evt.type = (enable) ? EVENT_CURSOR_TRAPPED : EVENT_CURSOR_RELEASED;
  373.     AddToEventQueue(evt);
  374.  
  375.   }
  376.  
  377. }
  378.  
  379.  
  380.  
  381.  
  382.  
  383. static void add_event(Event& evt){
  384.   // I pray AddToEventQueue never fails ever
  385.   if(!AddToEventQueue(evt)){ _printf("ERROR: EVENT QUEUE IS FULL!!!\n"); }
  386.  
  387. }
  388.  
  389.  
  390.  
  391.  
  392.  
  393. // flag_which must be one of the "DOWN" flags (Ex.: RI_MOUSE_BUTTON_1_DOWN)
  394. // (Also, timestamp is assumed to have already been set inside evt!)
  395. static void send_raw_mbutton_press(Event& evt, u16 flags,
  396.                                    u16 flag_which, u8 button_which)
  397. {
  398.   if(flags&flag_which){ // Mouse down
  399.     evt.type=EVENT_MOUSE_DOWN;
  400.     evt.mouse.pressed = true;
  401.  
  402.     u8 button_old = evt.mouse.button;
  403.     evt.mouse.button = button_which;
  404.  
  405.     add_event(evt);
  406.     evt.mouse.button = button_old|button_which;
  407.     mbutton_states.value |= button_which;
  408.  
  409.   }
  410.  
  411.   if(flags&(flag_which<<1)){ // Mouse up
  412.     evt.type=EVENT_MOUSE_UP;
  413.     evt.mouse.pressed = false;
  414.  
  415.     u8 button_old = evt.mouse.button;
  416.     evt.mouse.button = button_which;
  417.  
  418.     add_event(evt);
  419.     evt.mouse.button = button_old&(~button_which);
  420.     mbutton_states.value &= ~button_which;
  421.  
  422.   }
  423.  
  424. }
  425.  
  426.  
  427.  
  428.  
  429.  
  430. LRESULT CALLBACK WindowProc(HWND winHandle, UINT message,
  431.                             WPARAM wParam, LPARAM lParam)
  432. {
  433.   LRESULT returnResult = 0;
  434.  
  435.   Event evt; // Will be populated by any call to HANDLE_EVENT_<?>()...
  436.   memSet(&evt, 0, sizeof(Event)); //(this is done BEFORE setting anything)
  437.   evt.type = EVENT_COMMON; //...otherwise it will stay common
  438.  
  439.   bool switchBool  = false; // Multipurpose
  440.   bool switchBool2 = true;  // ^^(switchBool2 intentionally initialized to true)
  441.   u32  switchFlags = 0;     // ^^
  442.  
  443.   bool addEvent = true;
  444.  
  445.  
  446.  
  447.   switch(message){
  448.     case WM_DESTROY:
  449.       PostQuitMessage(0);
  450.     case WM_QUIT:
  451.     {
  452.       if(win_closed) break;
  453.       evt.type = EVENT_QUIT;
  454.       win_closed = true;
  455.       trap_cursor(false, true);
  456.     } break;
  457.  
  458.  
  459.  
  460.     case WM_GETMINMAXINFO: // For enforcing a minimum window size (redundant)
  461.     {
  462.       u32 winStyleCurrent   = GetWindowLongA(winHandle, GWL_STYLE  );
  463.       u32 winStyleExCurrent = GetWindowLongA(winHandle, GWL_EXSTYLE);
  464.  
  465.       Point2d winSizeAdjusted = CalculateWindowSize(win_size.x, win_size.y,
  466.                                                     winStyleCurrent,
  467.                                                     winStyleExCurrent);
  468.  
  469.       // Set the MINMAXINFO struct provided by lParam
  470.       MINMAXINFO* mmi = (MINMAXINFO*)lParam;
  471.       mmi->ptMinTrackSize.x = winSizeAdjusted.x;
  472.       mmi->ptMinTrackSize.y = winSizeAdjusted.y;
  473.  
  474.     } break;
  475.  
  476.  
  477.  
  478.     case WM_SIZE: // Also redraw canvas if window is being resized
  479.       win_size.x = LOWORD(lParam);
  480.       win_size.y = HIWORD(lParam);
  481.       update_cursor_clip();
  482.     case WM_PAINT:
  483.     {
  484.       // Dummy paint handling just in case Windows needs it
  485.       // (optionally filling the window with black)
  486.  
  487.       PAINTSTRUCT p_s;
  488.       #if FILL_WINDOW_TOGGLE == 1
  489.         HDC hdc =
  490.       #endif
  491.       BeginPaint(winHandle, &p_s);
  492.  
  493.       #if FILL_WINDOW_TOGGLE == 1
  494.         HBRUSH hBlackBrush = CreateSolidBrush(FILL_WINDOW_COLOR);
  495.         FillRect(hdc, &p_s.rcPaint, hBlackBrush);
  496.         DeleteObject(hBlackBrush);
  497.       #endif
  498.  
  499.       EndPaint(winHandle, &p_s);
  500.  
  501.     } break;
  502.  
  503.  
  504.  
  505.     case WM_SETFOCUS:
  506.     {
  507.       win_has_focus = true;
  508.  
  509.     } break;
  510.  
  511.  
  512.  
  513.     case WM_KILLFOCUS:
  514.     {
  515.       // If a key is released outside the client area, its key up message
  516.       // is never sent, so here the key states are reset when unfocusing...
  517.       // ...but first, send a key up event for every currently pressed key
  518.  
  519.       // Call QPC only once, since the events technically happen simultaneously
  520.       QueryPerformanceCounter((LARGE_INTEGER*)&evt.key.timestamp);
  521.  
  522.       KEY_Params params = 0;
  523.       params.currUnpressed = 1;
  524.  
  525.       for(u32 chr=0; chr<256; ++chr){
  526.         // Send a KEY_UP only if the state was previously true
  527.         if(key_states[chr] == true){
  528.           params.scanCode = MapVirtualKeyA(chr, MAPVK_VK_TO_VSC);
  529.           HANDLE_KEY_CHARUPDOWN(evt, false, chr, params, 0);
  530.           add_event(evt);
  531.         }
  532.       }
  533.  
  534.       memSet(key_states, 0, sizeof(bool)*256); //NOW the states can be reset
  535.  
  536.       // Reset all key modifiers (except for toggles) too
  537.       key_mods.all &= 0xff00; // Non-toggles are stored in low byte
  538.  
  539.       mbutton_states.value = 0; // Reset mouse states as well
  540.  
  541.       trap_cursor(false, true);
  542.  
  543.       win_has_focus = false;
  544.  
  545.     } break;
  546.  
  547.  
  548.  
  549.     //EVENT_KEY_CHAR, EVENT_KEY_UP, EVENT_KEY_DOWN
  550.     case WM_CHAR:
  551.     case WM_SYSKEYUP:
  552.     case WM_SYSKEYDOWN:
  553.     case WM_KEYUP:
  554.     case WM_KEYDOWN:
  555.     case WM_SYSCHAR:
  556.     {
  557.       // Marshal relevant stuff to pass to event handler
  558.       bool    charEvent = message==WM_CHAR;
  559.       u8 virtualKeyCode = (u8) wParam;
  560.       KEY_Params params = (u32)lParam;
  561.  
  562.       // Set repeat flag
  563.       params.repeatCount = (!params.currUnpressed)    == true &&
  564.                            key_states[virtualKeyCode] == true;
  565.  
  566.       if(!charEvent){
  567.         // (Uncomment the last part of the line below if issues occur
  568.         //  related to missed key press events or something!)
  569.         bool keydown = message==WM_KEYDOWN;//|| message==WM_SYSKEYDOWN;
  570.         bool pressed = !params.currUnpressed;
  571.         key_states[virtualKeyCode] = pressed;
  572.  
  573.         // Update any relevant key modifiers
  574.         switch(virtualKeyCode){
  575.           case VKEY_SHIFT    : { key_mods.lshift = key_mods.rshift = pressed; } break;
  576.           case VKEY_CONTROL  : { key_mods.lctrl  = key_mods.rctrl  = pressed; } break;
  577.           case VKEY_ALT      : { key_mods.lalt   = key_mods.ralt   = pressed; } break;
  578.           case VKEY_LWIN     : { key_mods.lgui   = pressed; } break;
  579.           case VKEY_RWIN     : { key_mods.rgui   = pressed; } break;
  580.           case VKEY_NUMLOCK  : if(keydown){ key_mods.numlock^=1; } break;
  581.           case VKEY_CAPSLOCK : if(keydown){ key_mods.capslock^=1; } break;
  582.           case VKEY_SCROLLOCK: if(keydown){ key_mods.scrollock^=1; } break;
  583.           default:;
  584.         }
  585.  
  586.         if(     virtualKeyCode==VKEY_CTRL ) mbutton_states.ctrl  = pressed;
  587.         else if(virtualKeyCode==VKEY_SHIFT) mbutton_states.shift = pressed;
  588.  
  589.         bool repeat = params.repeatCount!=0;
  590.         trap_cursor(!cursor_trapped,
  591.                     virtualKeyCode==VKEY_ENTER && keydown && !repeat);
  592.  
  593.       }
  594.  
  595.       HANDLE_KEY_CHARUPDOWN(evt, charEvent, virtualKeyCode,
  596.                                     params,   key_mods.all);
  597.  
  598.     } break;
  599.  
  600.  
  601.  
  602.     //EVENT_MOUSE_MOVED
  603.     case WM_MOUSEMOVE:
  604.     {
  605.       // Get button states
  606.       MOUSE_ButtonStates buttonStates;
  607.       buttonStates.left   = (wParam&MK_LBUTTON ) != 0;
  608.       buttonStates.middle = (wParam&MK_MBUTTON ) != 0;
  609.       buttonStates.right  = (wParam&MK_RBUTTON ) != 0;
  610.       buttonStates.x1     = (wParam&MK_XBUTTON1) != 0;
  611.       buttonStates.x2     = (wParam&MK_XBUTTON2) != 0;
  612.       buttonStates.ctrl   = (wParam&MK_CONTROL ) != 0;
  613.       buttonStates.shift  = (wParam&MK_SHIFT   ) != 0;
  614.  
  615.       // Get new mouse position
  616.       Point2d mousePositionNew;
  617.       mousePositionNew.x =                GET_X_LPARAM(lParam);
  618.       mousePositionNew.y = win_size.y-1 - GET_Y_LPARAM(lParam);
  619.  
  620.       // If this is the first instance of WINEVENT_MOUSE_MOVE,
  621.       // there is no previous mouse position, so the delta should be 0 then
  622.       if(!mouse_was_moved_before){
  623.         mouse_position = mousePositionNew;
  624.         mouse_was_moved_before = true;
  625.       }
  626.  
  627.       HANDLE_MOUSE_MOVED(evt, buttonStates.value,
  628.                          mouse_position, mousePositionNew);
  629.  
  630.       mouse_position = mousePositionNew; // Set current position to new one
  631.  
  632.     } break;
  633.  
  634.  
  635.  
  636.     case WM_MOUSELEAVE:
  637.     {
  638.       // Indicates that the mouse will have yet to be moved inside client area
  639.       mouse_was_moved_before = false;
  640.     } break;
  641.  
  642.  
  643.  
  644.     //EVENT_MOUSE_HWHEEL, EVENT_MOUSE_VWHEEL
  645.     case WM_MOUSEHWHEEL:
  646.     case WM_MOUSEWHEEL:
  647.     {
  648.       bool verticalScroll = message==WM_MOUSEWHEEL;
  649.  
  650.       s16 scrollAmount = (s16)HIWORD(wParam);
  651.  
  652.       mbutton_states.left   = (wParam&MK_LBUTTON ) != 0;
  653.       mbutton_states.middle = (wParam&MK_MBUTTON ) != 0;
  654.       mbutton_states.right  = (wParam&MK_RBUTTON ) != 0;
  655.       mbutton_states.x1     = (wParam&MK_XBUTTON1) != 0;
  656.       mbutton_states.x2     = (wParam&MK_XBUTTON2) != 0;
  657.  
  658.       Point2d scrollMousePosition;
  659.       scrollMousePosition.x = GET_X_LPARAM(lParam);
  660.       scrollMousePosition.y = GET_Y_LPARAM(lParam);
  661.  
  662.       // The coordinates are, by default, relative to the screen
  663.       // and not the window (for some reason)
  664.       ScreenToClient(winHandle, (POINT*)&scrollMousePosition);
  665.  
  666.       HANDLE_MOUSE_HVWHEEL(evt, verticalScroll, scrollAmount,
  667.                            mbutton_states.value, scrollMousePosition);
  668.  
  669.     } break;
  670.  
  671.  
  672.  
  673.     //EVENT_MOUSE_UP, EVENT_MOUSE_DOWN
  674.      //switchBool  = evt.mouse.dblClick
  675.      //switchBool2 = evt.mouse.pressed
  676.      //switchFlags = evt.mouse.button
  677.     case WM_LBUTTONDBLCLK: switchBool  = true;  goto _notLButtonUp;
  678.     case WM_LBUTTONUP    : switchBool2 = false; _notLButtonUp:
  679.     case WM_LBUTTONDOWN  : switchFlags |= MBUTTON_LEFT; goto _handleMouseClick;
  680.  
  681.     case WM_MBUTTONDBLCLK: switchBool  = true;  goto _notMButtonUp;
  682.     case WM_MBUTTONUP    : switchBool2 = false; _notMButtonUp:
  683.     case WM_MBUTTONDOWN  : switchFlags |=MBUTTON_MIDDLE; goto _handleMouseClick;
  684.  
  685.     case WM_RBUTTONDBLCLK: switchBool  = true;  goto _notRButtonUp;
  686.     case WM_RBUTTONUP    : switchBool2 = false; _notRButtonUp:
  687.     case WM_RBUTTONDOWN  : switchFlags |= MBUTTON_RIGHT; goto _handleMouseClick;
  688.  
  689.     case WM_XBUTTONDBLCLK: switchBool  = true;  goto _notXButtonUp;
  690.     case WM_XBUTTONUP    : switchBool2 = false; _notXButtonUp:
  691.     case WM_XBUTTONDOWN  : if(wParam & MK_XBUTTON1) switchFlags |= MBUTTON_X1;
  692.                            else                     switchFlags |= MBUTTON_X2;
  693.     {
  694.       _handleMouseClick:
  695.  
  696.       Point2d clickPosition;
  697.       clickPosition.x = GET_X_LPARAM(lParam);
  698.       clickPosition.y = GET_Y_LPARAM(lParam);
  699.  
  700.       bool pressed      = switchBool2;
  701.       bool doubleClick  = switchBool;
  702.  
  703.            if(switchFlags&MBUTTON_LEFT  ) mbutton_states.left   = pressed;
  704.       else if(switchFlags&MBUTTON_MIDDLE) mbutton_states.middle = pressed;
  705.       else if(switchFlags&MBUTTON_RIGHT ) mbutton_states.right  = pressed;
  706.       else if(switchFlags&MBUTTON_X1    ) mbutton_states.x1     = pressed;
  707.       else if(switchFlags&MBUTTON_X2    ) mbutton_states.x2     = pressed;
  708.  
  709.       HANDLE_MOUSE_UPDOWN(evt, clickPosition,
  710.                           mbutton_states.value, pressed, doubleClick);
  711.  
  712.     } break;
  713.  
  714.  
  715.  
  716.     case WM_INPUT:
  717.     {
  718.       // First call to query for the data's size
  719.       UINT dataSize = 0;
  720.       GetRawInputData((HRAWINPUT)lParam, RID_INPUT, nullptr,
  721.                       &dataSize, sizeof(RAWINPUTHEADER));
  722.       RAWINPUT* data = (RAWINPUT*)alloca(dataSize);
  723.  
  724.       // Second call to get the actual data
  725.       if(GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data,
  726.                          &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
  727.       {
  728.         const RAWMOUSE& mouse = data->data.mouse;
  729.  
  730.         if(data->header.dwType != RIM_TYPEMOUSE  ||
  731.            mouse.usFlags != MOUSE_MOVE_RELATIVE)
  732.         {
  733.           addEvent = false; break;
  734.         }
  735.  
  736.         // Handle the actual event stuff
  737.         {
  738.           s32 _deltaWheel = mouse.usButtonData;
  739.           if(_deltaWheel >= 32768) _deltaWheel -= 65536; // Unsigned-to-signed
  740.  
  741.           const u16 flags      = mouse.usButtonFlags;
  742.           const f32 deltaWheel = (f32)_deltaWheel/WHEEL_DELTA;
  743.           const f32 deltaX     =  mouse.lLastX;
  744.           const f32 deltaY     = -mouse.lLastY; // GDI's bitmaps are *bottom-up*
  745.  
  746.           HANDLE_MOUSE_RAWINPUT(evt, flags, deltaWheel, deltaX, deltaY);
  747.         }
  748.  
  749.       } else {
  750.         _printf("ERROR: failed to get raw mouse input data! "
  751.                 "(error code = 0x%08X)\n", (u32)GetLastError());
  752.  
  753.       }
  754.  
  755.       // Any relevant raw input events will already have been sent by this point
  756.       addEvent = false;
  757.  
  758.     } break;
  759.  
  760.  
  761.  
  762.     default: returnResult = DefWindowProcA(winHandle, message, wParam, lParam);
  763.  
  764.   }
  765.  
  766.  
  767.  
  768.   if(evt.type != EVENT_COMMON  &&  evt.common.timestamp == 0  &&  addEvent)
  769.   {
  770.     // Idk how expensive QPC is, so I'll only call it if the event is valid
  771.     QueryPerformanceCounter((LARGE_INTEGER*)&evt.common.timestamp);
  772.     add_event(evt);
  773.   }
  774.  
  775.  
  776.  
  777.   return returnResult;
  778.  
  779. }
  780. /******************************************************************************/
  781. /******************************************************************************/
  782. //"opengl_metaballs_2025-06-26\include\public_stuff.hpp":
  783. #ifndef _PUBLIC_STUFF_HPP
  784. #define _PUBLIC_STUFF_HPP
  785.  
  786.  
  787.  
  788.  
  789.  
  790. // Comment out any misc. functions you don't plan on using
  791. //#define PRINT_EVENT_USED
  792. #define FRAND_USED // (Includes all types of frand)
  793.  
  794. //#define SOUND_STUFF_USED // 'Use the built-in sound effect mixer?'
  795.  
  796.  
  797.  
  798.  
  799.  
  800. // Comment this line out if you don't plan on using stdlib's implementations of:
  801. // memset
  802. // memcpy
  803. // strnlen
  804. // strncpy
  805. // strcat
  806. // strncmp
  807. #define STDLIB_USED
  808.  
  809. #if defined(FRAND_USED) && !defined(STDLIB_USED)
  810.   #define STDLIB_USED
  811. #endif
  812.  
  813.  
  814.  
  815. #ifdef STDLIB_USED
  816.   #include <string.h>
  817.   #include <math.h>
  818.   // The framework uses its own implementations for the following stdlib
  819.   // functions so that it doesn't require the C runtime libraries.
  820.   // However, if the user plans on using the standard library for their
  821.   // own purposes, having custom implementations would be redundant
  822.   #define memSet  memset
  823.   #define memCpy  memcpy
  824.   #define strnLen strnlen
  825.   #define strnCpy strncpy
  826.   #define strCat  strcat
  827.   #define strnCmp strncmp
  828.   // (sinF is only used for the example audio usage,
  829.   //  and that's commented out at first anyway!)
  830.   #define sinF    sinf
  831. #endif /* STDLIB_USED */
  832.   // (I don't currently have a custom implementation of this yet,
  833.   //  but I also don't want to refactor every call if I do end up making one)
  834.   #define strnCat strncat
  835.  
  836.  
  837.  
  838. // If you don't end up using anything else from stdio,
  839. // using this makes sure printf is only included in the debug build!
  840. // This is useful for minimizing size, since the command line is
  841. // only shown in the debug build anyway.
  842. #ifdef _DEBUG
  843.   #include <stdio.h>
  844.   #define _printf(...) printf(__VA_ARGS__)
  845. #else
  846.   #define _printf(...)
  847. #endif /* _DEBUG */
  848.  
  849.  
  850.  
  851.  
  852.  
  853. // Float-specified versions of math.h's pi constants,
  854. // with a slightly different naming convention
  855.  
  856. #ifndef   M_PI4f
  857. #define   M_PI4f 0.7853981633974483096156608f
  858. #endif /* M_PI2 */
  859.  
  860. #ifndef   M_PI2f
  861. #define   M_PI2f 1.5707963267948966192313216f
  862. #endif /* M_PI2 */
  863.  
  864. #ifndef   M_PIf
  865. #define   M_PIf  3.1415926535897932384626433f
  866. #endif /* M_PIf */
  867.  
  868. #ifndef   M_2PIf
  869. #define   M_2PIf 6.2831853071795864769252866f
  870. #endif /* M_2PIf */
  871.  
  872.  
  873.  
  874.  
  875.  
  876. #ifndef   MIN
  877. #define   MIN(a,b)  ( ((a)<(b)) ? (a) : (b) )
  878. #endif /* MIN(a,b) */
  879.  
  880. #ifndef   MAX
  881. #define   MAX(a,b)  ( ((a)>(b)) ? (a) : (b) )
  882. #endif /* MAX(a,b) */
  883.  
  884. #ifndef   MIN3
  885. #define   MIN3(_a, _b, _c) MIN(MIN(_a, _b), _c)
  886. #endif /* MIN3 */
  887.  
  888. #ifndef   MAX3
  889. #define   MAX3(_a, _b, _c) MAX(MAX(_a, _b), _c)
  890. #endif /* MAX3 */
  891.  
  892. #ifndef   CLAMP
  893. #define   CLAMP(n, mn, mx)  MIN(MAX(n,mn),mx)
  894. #endif /* CLAMP(n, mn, mx) */
  895.  
  896. // Precise version of linear interpolation
  897. #ifndef   LERP
  898. #define   LERP(_v0, _v1, _t)  (  (1.0-(_t)) * (_v0)  +  (_t) * (_v1)  )
  899. #endif /* LERP */
  900.  
  901. // Imprecise (but theoretically faster?) version
  902. #ifndef   LERP2
  903. #define   LERP2(_v0, _v1, _t)  ( (_v0) + (_t) * ((_v1)-(_v0))  )
  904. #endif /* LERP2 */
  905.  
  906. #ifndef   IN_BOUNDS
  907. #define   IN_BOUNDS(_x, _y, _w, _h) (  (_x) >= 0  &&  (_x) < (_w)  && \
  908.                                        (_y) >= 0  &&  (_y) < (_h)  )
  909. #endif /* IN_BOUNDS */
  910.  
  911. // For printing the results of a boolean value.
  912. // To use this, use the "%s" format specifier,
  913. // with this as the parameter
  914. #ifndef   BOOL_STR
  915. #define   BOOL_STR(_is_true) ( (_is_true) ? "true" : "false" )
  916. #endif /* BOOL_STR */
  917.  
  918.  
  919.  
  920.  
  921.  
  922. #ifdef __cplusplus
  923.   #include <cstddef>
  924.   #include <cstdint>
  925.   #include <climits>
  926. #else
  927.   #include <stdint.h>
  928. #endif /* __cplusplus */
  929.  
  930. typedef uint8_t  u8;
  931. typedef uint16_t u16;
  932. typedef uint32_t u32;
  933. typedef uint64_t u64;
  934.  
  935. typedef int8_t  s8;
  936. typedef int16_t s16;
  937. typedef int32_t s32;
  938. typedef int64_t s64;
  939.  
  940. typedef float  f32;
  941. typedef double f64;
  942.  
  943.  
  944.  
  945.  
  946.  
  947. // There's no real point in messing with this stuff
  948. // unless you know how they're useful.
  949. // Relevant documentation if you want to know how to use these:
  950. // PACKED       : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
  951. // NOINLINE     : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
  952. // DEPRECATED   : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute
  953. // FALLTHROUGH  : https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Statement-Attributes.html#index-fallthrough-statement-attribute
  954. // ALWAYS_INLINE: https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute
  955. #if defined(__GNUC__)
  956.   #define ATTR_PACKED        __attribute__((packed))
  957.   #define ATTR_NOINLINE      __attribute__((noinline))
  958.   #define ATTR_DEPRECATED    __attribute__((deprecated))
  959.   #define ATTR_FALLTHROUGH   __attribute__((fallthrough))
  960.   #define ATTR_ALWAYS_INLINE __attribute__((always_inline))
  961. #endif
  962.  
  963.  
  964.  
  965.  
  966.  
  967. /************************************ MISC ************************************/
  968.  
  969. struct Fpoint2d { f32 x, y; };
  970. struct Fpoint3d { f32 x, y, z; };
  971.  
  972. struct Point2d  { s32 x, y; };
  973. struct Point3d  { s32 x, y, z; };
  974.  
  975. struct Rect2d   { s32 x, y, w, h; };
  976.  
  977.  
  978.  
  979. // These are custom implementations for necessary functions.
  980. // They're only included if the std library isn't used,
  981. // since the framework has to use them for some things.
  982.  
  983. #ifndef STDLIB_USED
  984.  
  985. void* memSet(void* dst, int val, size_t len);
  986.  
  987. //(len_max does not include null-terminator!)
  988. //(if !len_max, call is analogous to str(not n)len)
  989. size_t strnLen(const char* str, size_t len_max);
  990.  
  991. char* strnCpy(char* str_dst, const char* str_src, size_t len_max);
  992.  
  993. char* strCat(char* dst, const char* src);
  994.  
  995. //(len_max does not include null-terminator!)
  996. //(if !len_max, call is analogous to str(not n)cmp)
  997. s32 strnCmp(const char* str_a, const char* str_b, size_t len_max);
  998.  
  999. f32 sinF(f32 x);
  1000. #define cosF(_x) sinF((_x)+M_PI2f)
  1001. #define tanF(_x) ( sinF(_x)/cosF(_x) )
  1002.  
  1003. #endif
  1004.  
  1005.  
  1006.  
  1007. enum MessageBoxEnum {
  1008.   // Return values
  1009.   MSGBOX_RTN_NULL     = 0x00000000, //showMessageBox failed
  1010.   MSGBOX_RTN_OK       = 0x00000001, //'ok' button was clicked
  1011.   MSGBOX_RTN_CANCEL   = 0x00000002, //'cancel' button was clicked
  1012.   MSGBOX_RTN_ABORT    = 0x00000003, //'abort' button was clicked
  1013.   MSGBOX_RTN_RETRY    = 0x00000004, //'retry' button was clicked
  1014.   MSGBOX_RTN_IGNORE   = 0x00000005, //'ignore' button was clicked
  1015.   MSGBOX_RTN_YES      = 0x00000006, //'yes' button was clicked
  1016.   MSGBOX_RTN_NO       = 0x00000007, //'no' button was clicked
  1017.   MSGBOX_RTN_TRYAGAIN = 0x0000000A, //'try again' button was clicked
  1018.   MSGBOX_RTN_CONTINUE = 0x0000000B, //'continue' button was clicked
  1019.  
  1020.   // Button types
  1021.   MSGBOX_BTN_OK                = 0x00000000,
  1022.   MSGBOX_BTN_OKCANCEL          = 0x00000001,
  1023.   MSGBOX_BTN_ABORTRETRYIGNORE  = 0x00000002,
  1024.   MSGBOX_BTN_YESNOCANCEL       = 0x00000003,
  1025.   MSGBOX_BTN_YESNO             = 0x00000004,
  1026.   MSGBOX_BTN_RETRYCANCEL       = 0x00000005,
  1027.   MSGBOX_BTN_CANCELTRYCONTINUE = 0x00000006,
  1028.  
  1029.   // Icon types
  1030.   MSGBOX_ICN_ERROR    = 0x000000010,
  1031.   MSGBOX_ICN_QUESTION = 0x000000020, //apparently deprecated, but still supported
  1032.   MSGBOX_ICN_WARNING  = 0x000000030,
  1033.   MSGBOX_ICN_INFO     = 0x000000040,
  1034.  
  1035. };
  1036.  
  1037. u32 showMessageBox(const char* text = nullptr, const char* title = nullptr,
  1038.                    u32 type = MSGBOX_BTN_OK|MSGBOX_ICN_INFO,
  1039.                    u32 defaultButton = 0);
  1040.  
  1041. u64 timeGetPerfCounter();
  1042. u64 timeGetPerfFreq();
  1043. f64 timeGetSeconds();
  1044.  
  1045. void timeSleep(u32 milliseconds);
  1046.  
  1047.  
  1048.  
  1049. #ifdef PRINT_EVENT_USED
  1050. #ifdef _DEBUG
  1051.   union Event; // Forward declaration
  1052.   void print_event(Event& evt);
  1053. #else
  1054.   #define print_event(_evt) {}
  1055. #endif /* _DEBUG */
  1056. #endif /* PRINT_EVENT_USED */
  1057.  
  1058.  
  1059.  
  1060. // Warning: this doesn't check if buffer is not nullptr,
  1061. // nor does it check if which_bit is inside buffer!
  1062. bool is_bit_set(const void* buffer, u32 which_bit);
  1063.  
  1064.  
  1065.  
  1066. #ifdef FRAND_USED
  1067. f64 frand();   // 0.0f -> 1.0f
  1068. f64 frand2();  //-1.0f -> 1.0f
  1069. f32 frandf();  // 0.0f -> 1.0f
  1070. f32 frandf2(); //-1.0f -> 1.0f
  1071. #endif /* FRAND_USED */
  1072.  
  1073.  
  1074.  
  1075. /* taken from stb_sprintf.h (what these 2 functions use under-the-hood):
  1076.  
  1077. 64-BIT INTS:
  1078. ============
  1079. This library also supports 64-bit integers and you can use MSVC style or
  1080. GCC style indicators (%I64d or %lld).  It supports the C99 specifiers
  1081. for size_t and ptr_diff_t (%jd %zd) as well.
  1082.  
  1083. EXTRAS:
  1084. =======
  1085. Like some GCCs, for integers and floats, you can use a ' (single quote)
  1086. specifier and commas will be inserted on the thousands: "%'d" on 12345
  1087. would print 12,345.
  1088.  
  1089. For integers and floats, you can use a "$" specifier and the number
  1090. will be converted to float and then divided to get kilo, mega, giga or
  1091. tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is
  1092. "2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn
  1093. 2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three
  1094. $:s: "%$$$d" -> "2.42 M". To remove the space between the number and the
  1095. suffix, add "_" specifier: "%_$d" -> "2.53M".
  1096.  
  1097. In addition to octal and hexadecimal conversions, you can print
  1098. integers in binary: "%b" for 256 would print 100.
  1099.  
  1100. PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC):
  1101. ===================================================================
  1102. "%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC)
  1103. "%24d" across all 32-bit ints (4.5x/4.2x faster)
  1104. "%x" across all 32-bit ints (4.5x/3.8x faster)
  1105. "%08x" across all 32-bit ints (4.3x/3.8x faster)
  1106. "%f" across e-10 to e+10 floats (7.3x/6.0x faster)
  1107. "%e" across e-10 to e+10 floats (8.1x/6.0x faster)
  1108. "%g" across e-10 to e+10 floats (10.0x/7.1x faster)
  1109. "%f" for values near e-300 (7.9x/6.5x faster)
  1110. "%f" for values near e+300 (10.0x/9.1x faster)
  1111. "%e" for values near e-300 (10.1x/7.0x faster)
  1112. "%e" for values near e+300 (9.2x/6.0x faster)
  1113. "%.320f" for values near e-300 (12.6x/11.2x faster)
  1114. "%a" for random values (8.6x/4.3x faster)
  1115. "%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster)
  1116. "%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster)
  1117. "%s%s%s" for 64 char strings (7.1x/7.3x faster)
  1118. "...512 char string..." ( 35.0x/32.5x faster!)
  1119.  
  1120. */
  1121.  
  1122. #define snprintf snPrintf
  1123. #define vsnprintf vsnPrintf
  1124. #include <stdarg.h>
  1125.  
  1126. //if len_max == 0 OR > INT_MAX, call is analogous to s(not n)printf
  1127. s32 snPrintf(char* str_dst, size_t len_max, const char* str_fmt, ...);
  1128.  
  1129. //^^ VV unlike normal snprintf, these'll always return a null-terminated string
  1130.  
  1131. //if len_max == 0 OR > INT_MAX, call is analogous to vs(not n)printf
  1132. s32 vsnPrintf(char* str_dst, size_t len_max, const char* str_fmt, va_list va);
  1133.  
  1134.  
  1135.  
  1136. // Use these instead of malloc, free, or realloc!
  1137. void* mem_alloc(size_t size);
  1138. void  mem_free(void* ptr_p); // ptr_p means: use &ptr instead of ptr
  1139. void* mem_realloc(void* ptr_p, size_t newSize); // ptr_p is the same as in free
  1140.  
  1141. size_t mem_getNumAllocations();
  1142. size_t mem_setNumAllocations(size_t value);
  1143. size_t mem_addNumAllocations(s32 amount);
  1144.  
  1145. void* mem_set(void* ptr, s32 value, size_t size);
  1146. void* mem_copy(void* destination, const void* source, size_t size);
  1147.  
  1148. struct mem_Wrapper {
  1149.   void* ptr = nullptr;
  1150.  
  1151.   inline mem_Wrapper(size_t size){ ptr = mem_alloc(size); }
  1152.   inline mem_Wrapper(void* _ptr) : ptr(_ptr) {} // Existing mem_alloc
  1153.   inline ~mem_Wrapper(){ mem_free(&ptr); }; // Safe to use, even if ptr is null
  1154.  
  1155.   inline void* realloc(size_t newSize){ return mem_realloc(&ptr, newSize); }
  1156.  
  1157. };
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163. /*********************************** INPUT ************************************/
  1164.  
  1165. #define EVENT_ID(_id) ( (_id) & 0xFFFF0000 )
  1166. #define SUBEVENT_ID(_id) ( (_id) & 0xFFFF )
  1167.  
  1168. enum EventEnum {
  1169.   EVENT_NULL            = 0x00000000,
  1170.  
  1171.   EVENT_COMMON          = 0x00010000, // Event_Common (Event.common)
  1172.  
  1173.   // (Occurs when the window is destroyed!)
  1174.   EVENT_QUIT            = 0x00020000, // N/A (N/A)
  1175.  
  1176.   EVENT_KEY             = 0x00030000, // Event_Key (Event.key)
  1177.   EVENT_KEY_CHAR        = EVENT_KEY   | 0x0001,
  1178.   EVENT_KEY_UP          = EVENT_KEY   | 0x0002,
  1179.   EVENT_KEY_DOWN        = EVENT_KEY   | 0x0003,
  1180.  
  1181.   EVENT_MOUSE           = 0x00040000, // Event_Mouse (Event.mouse)
  1182.   EVENT_MOUSE_MOVED     = EVENT_MOUSE | 0x0001,
  1183.   EVENT_MOUSE_HWHEEL    = EVENT_MOUSE | 0x0002,
  1184.   EVENT_MOUSE_VWHEEL    = EVENT_MOUSE | 0x0003,
  1185.   EVENT_MOUSE_UP        = EVENT_MOUSE | 0x0004,
  1186.   EVENT_MOUSE_DOWN      = EVENT_MOUSE | 0x0005,
  1187.  
  1188.   // (Occurs once every time the cursor is trapped and released respectively!)
  1189.   EVENT_CURSOR          = 0x00050000, // N/A (N/A)
  1190.   EVENT_CURSOR_TRAPPED  = EVENT_CURSOR | 0x0001,
  1191.   EVENT_CURSOR_RELEASED = EVENT_CURSOR | 0x0002,
  1192.  
  1193.   EVENT_UNKNOWN         = 0xFFFF0000,
  1194.  
  1195. };
  1196.  
  1197.  
  1198.  
  1199. /*+EVENT_COMMON+*/
  1200.  
  1201. struct Event_Common { //16B
  1202.   u32  type;
  1203.   u32 _unused; // Unused by common, but not necessarily other event types
  1204.   u64  timestamp; // Performance counter is used; see "timeGetPerfCounter()"
  1205. };
  1206.  
  1207. /*-EVENT_COMMON-*/
  1208.  
  1209.  
  1210.  
  1211. /*+EVENT_KEY+*/
  1212.  
  1213. // Event_Key.kmods can use any combination of these OR'd (AKA |) together
  1214. enum Event_Key_ModifierEnum { // (These are bitmasks)
  1215.   KMOD_NONE      = 0x0000,
  1216.   KMOD_LSHIFT    = 0x0001,
  1217.   KMOD_RSHIFT    = 0x0002,
  1218.   KMOD_LCTRL     = 0x0004,
  1219.   KMOD_RCTRL     = 0x0008,
  1220.   KMOD_LALT      = 0x0010,
  1221.   KMOD_RALT      = 0x0020,
  1222.   KMOD_LGUI      = 0x0040, // Windows key?
  1223.   KMOD_RGUI      = 0x0080,  //^^
  1224.     KMOD_LWIN    = KMOD_LGUI,
  1225.     KMOD_RWIN    = KMOD_RGUI,
  1226.   KMOD_NUMLOCK   = 0x1000,
  1227.   KMOD_CAPSLOCK  = 0x2000,
  1228.   KMOD_ALTGRAPH  = 0x4000,
  1229.   KMOD_SCROLLOCK = 0x8000,
  1230.   KMOD_CTRL      = ( KMOD_LCTRL  | KMOD_RCTRL  ),
  1231.   KMOD_SHIFT     = ( KMOD_LSHIFT | KMOD_RSHIFT ),
  1232.   KMOD_ALT       = ( KMOD_LALT   | KMOD_RALT   ),
  1233.   KMOD_GUI       = ( KMOD_LGUI   | KMOD_RGUI   ),
  1234.   KMOD_WIN       = ( KMOD_LWIN   | KMOD_RWIN   ),
  1235. };
  1236.  
  1237.  
  1238.  
  1239. enum Event_Key_PhysicalEnum {
  1240.   // TBD because I don't want to bother with scancode stuff right now
  1241. };
  1242.  
  1243.  
  1244.  
  1245. enum Event_Key_VirtualEnum {
  1246.   VKEY_NULL             = 0x00,
  1247.   //(misc. mouse)       = 0x01 -> 0x06
  1248.   //(reserved)          = 0x07,
  1249.   VKEY_BACK             = 0x08, //backspace key
  1250.     VKEY_BACKSPACE      = VKEY_BACK,
  1251.   VKEY_TAB              = 0x09,
  1252.   //(reserved)          = 0x0A -> 0x0B,
  1253.   VKEY_CLEAR            = 0x0C,
  1254.   VKEY_RETURN           = 0x0D, //enter key
  1255.     VKEY_ENTER          = VKEY_RETURN,
  1256.   //(unassigned)        = 0x0E -> 0x0F,
  1257.   VKEY_SHIFT            = 0x10,
  1258.   VKEY_CONTROL          = 0x11, //ctrl key
  1259.     VKEY_CTRL           = VKEY_CONTROL,
  1260.   VKEY_MENU             = 0x12, //alt key
  1261.     VKEY_ALT            = VKEY_MENU,
  1262.   VKEY_PAUSE            = 0x13,
  1263.   VKEY_CAPITAL          = 0x14, //caps lock key
  1264.     VKEY_CAPSLOCK       = VKEY_CAPITAL,
  1265.   //(IME stuff)         = 0x15 -> 0x1A,
  1266.   VKEY_ESCAPE           = 0x1B, //esc key
  1267.   //(IME stuff)         = 0x1C -> 0x1F,
  1268.   VKEY_SPACE            = 0x20, //space bar key
  1269.   VKEY_PRIOR            = 0x21, //page up key
  1270.     VKEY_PGUP           = VKEY_PRIOR,
  1271.   VKEY_NEXT             = 0x22, //page down key
  1272.     VKEY_PGDN           = VKEY_NEXT,
  1273.   VKEY_END              = 0x23,
  1274.   VKEY_HOME             = 0x24,
  1275.   VKEY_LEFT             = 0x25, //left arrow key
  1276.   VKEY_UP               = 0x26, //up arrow key
  1277.   VKEY_RIGHT            = 0x27, //right arrow key
  1278.   VKEY_DOWN             = 0x28, //down arrow key
  1279.   VKEY_SELECT           = 0x29,
  1280.   VKEY_PRINT            = 0x2A,
  1281.   VKEY_EXECUTE          = 0x2B,
  1282.   VKEY_SNAPSHOT         = 0x2C, //print screen key
  1283.     VKEY_PRTSC          = VKEY_SNAPSHOT,
  1284.   VKEY_INSERT           = 0x2D, //ins key
  1285.   VKEY_DELETE           = 0x2E, //del key
  1286.   VKEY_HELP             = 0x2F, //help key
  1287.   VKEY_0                = 0x30, //'0'
  1288.   VKEY_1                = 0x31, //'1'
  1289.   VKEY_2                = 0x32, //'2'
  1290.   VKEY_3                = 0x33, //'3'
  1291.   VKEY_4                = 0x34, //'4'
  1292.   VKEY_5                = 0x35, //'5'
  1293.   VKEY_6                = 0x36, //'6'
  1294.   VKEY_7                = 0x37, //'7'
  1295.   VKEY_8                = 0x38, //'8'
  1296.   VKEY_9                = 0x39, //'9'
  1297.   //(undefined)         = 0x3A -> 0x40,
  1298.   VKEY_A                = 0x41, //'A'
  1299.   VKEY_B                = 0x42, //'B'
  1300.   VKEY_C                = 0x43, //'C'
  1301.   VKEY_D                = 0x44, //'D'
  1302.   VKEY_E                = 0x45, //'E'
  1303.   VKEY_F                = 0x46, //'F'
  1304.   VKEY_G                = 0x47, //'G'
  1305.   VKEY_H                = 0x48, //'H'
  1306.   VKEY_I                = 0x49, //'I'
  1307.   VKEY_J                = 0x4A, //'J'
  1308.   VKEY_K                = 0x4B, //'K'
  1309.   VKEY_L                = 0x4C, //'L'
  1310.   VKEY_M                = 0x4D, //'M'
  1311.   VKEY_N                = 0x4E, //'N'
  1312.   VKEY_O                = 0x4F, //'O'
  1313.   VKEY_P                = 0x50, //'P'
  1314.   VKEY_Q                = 0x51, //'Q'
  1315.   VKEY_R                = 0x52, //'R'
  1316.   VKEY_S                = 0x53, //'S'
  1317.   VKEY_T                = 0x54, //'T'
  1318.   VKEY_U                = 0x55, //'U'
  1319.   VKEY_V                = 0x56, //'V'
  1320.   VKEY_W                = 0x57, //'W'
  1321.   VKEY_X                = 0x58, //'X'
  1322.   VKEY_Y                = 0x59, //'Y'
  1323.   VKEY_Z                = 0x5A, //'Z'
  1324.   VKEY_LWIN             = 0x5B, //left windows key
  1325.   VKEY_RWIN             = 0x5C, //right windows key
  1326.   VKEY_APPS             = 0x5D, //applications key
  1327.   //(reserved)          = 0x5E,
  1328.   VKEY_SLEEP            = 0x5F, //computer sleep key
  1329.   VKEY_NUMPAD0          = 0x60,
  1330.   VKEY_NUMPAD1          = 0x61,
  1331.   VKEY_NUMPAD2          = 0x62,
  1332.   VKEY_NUMPAD3          = 0x63,
  1333.   VKEY_NUMPAD4          = 0x64,
  1334.   VKEY_NUMPAD5          = 0x65,
  1335.   VKEY_NUMPAD6          = 0x66,
  1336.   VKEY_NUMPAD7          = 0x67,
  1337.   VKEY_NUMPAD8          = 0x68,
  1338.   VKEY_NUMPAD9          = 0x69,
  1339.   VKEY_MULTIPLY         = 0x6A, //numpad '*'
  1340.   VKEY_ADD              = 0x6B, //numpad '+'
  1341.   VKEY_SEPARATOR        = 0x6C, //numpad enter
  1342.   VKEY_SUBTRACT         = 0x6D, //numpad '-'
  1343.   VKEY_DECIMAL          = 0x6E, //numpad '.'
  1344.   VKEY_DIVIDE           = 0x6F, //numpad '/'
  1345.   VKEY_F1               = 0x70,
  1346.   VKEY_F2               = 0x71,
  1347.   VKEY_F3               = 0x72,
  1348.   VKEY_F4               = 0x73,
  1349.   VKEY_F5               = 0x74,
  1350.   VKEY_F6               = 0x75,
  1351.   VKEY_F7               = 0x76,
  1352.   VKEY_F8               = 0x77,
  1353.   VKEY_F9               = 0x78,
  1354.   VKEY_F10              = 0x79,
  1355.   VKEY_F11              = 0x7A,
  1356.   VKEY_F12              = 0x7B,
  1357.   VKEY_F13              = 0x7C,
  1358.   VKEY_F14              = 0x7D,
  1359.   VKEY_F15              = 0x7E,
  1360.   VKEY_F16              = 0x7F,
  1361.   VKEY_F17              = 0x80,
  1362.   VKEY_F18              = 0x81,
  1363.   VKEY_F19              = 0x82,
  1364.   VKEY_F20              = 0x83,
  1365.   VKEY_F21              = 0x84,
  1366.   VKEY_F22              = 0x85,
  1367.   VKEY_F23              = 0x86,
  1368.   VKEY_F24              = 0x87,
  1369.   //(reserved)          = 0x88 -> 0x8F,
  1370.   VKEY_NUMLOCK          = 0x90,
  1371.   VKEY_SCROLL           = 0x91, //scroll lock key
  1372.     VKEY_SCROLLOCK      = VKEY_SCROLL,
  1373.   //(OEM-specific)      = 0x92 -> 0x96,
  1374.   //(unassigned)        = 0x97 -> 0x9F,
  1375.   //(l/r key variants)  = 0xA0 -> 0xA5,
  1376.   //(browser keys)      = 0xA6 -> 0xAC,
  1377.   VKEY_VOLUME_MUTE      = 0xAD,
  1378.   VKEY_VOLUME_DOWN      = 0xAE,
  1379.   VKEY_VOLUME_UP        = 0xAF,
  1380.   VKEY_MEDIA_NEXT_TRACK = 0xB0,
  1381.   VKEY_MEDIA_PREV_TRACK = 0xB1,
  1382.   VKEY_MEDIA_STOP       = 0xB2,
  1383.   VKEY_MEDIA_PLAY_PAUSE = 0xB3, //Play/Pause Media key
  1384.   //(launch keys)       = 0xB4 -> 0xB7,
  1385.   //(reserved)          = 0xB8 -> 0xB9,
  1386.   VKEY_OEM_1            = 0xBA, //misc. chars; varies by keyboard (';',':' on US standard)
  1387.     VKEY_SEMICOLON      = VKEY_OEM_1,
  1388.   VKEY_OEM_PLUS         = 0xBB, //'+' in any country/region
  1389.     VKEY_PLUS           = VKEY_OEM_PLUS,
  1390.   VKEY_OEM_COMMA        = 0xBC, //',' in any country/region
  1391.     VKEY_COMMA          = VKEY_OEM_COMMA,
  1392.   VKEY_OEM_MINUS        = 0xBD, //'-' in any country/region
  1393.     VKEY_MINUS          = VKEY_OEM_MINUS,
  1394.   VKEY_OEM_PERIOD       = 0xBE, //'.' in any country/region
  1395.     VKEY_PERIOD         = VKEY_OEM_PERIOD,
  1396.   VKEY_OEM_2            = 0xBF, //misc. chars; varies by keyboard ('/','?' on US standard)
  1397.     VKEY_FSLASH         = VKEY_OEM_2,
  1398.   VKEY_OEM_3            = 0xC0, //misc. chars; varies by keyboard ('`','~' on US standard)
  1399.     VKEY_BACKTICK       = VKEY_OEM_3,
  1400.   //(reserved)          = 0xC1 -> 0xDA,
  1401.   VKEY_OEM_4            = 0xDB, //misc. chars; varies by keyboard ('[','{' on US standard)
  1402.     VKEY_LBRACKET       = VKEY_OEM_4,
  1403.   VKEY_OEM_5            = 0xDC, //misc. chars; varies by keyboard ('\\','|' on US standard)
  1404.     VKEY_BSLASH         = VKEY_OEM_5,
  1405.   VKEY_OEM_6            = 0xDD, //misc. chars; varies by keyboard (']','}' on US standard)
  1406.     VKEY_RBRACKET       = VKEY_OEM_6,
  1407.   VKEY_OEM_7            = 0xDE, //misc. chars; varies by keyboard ('\'','\"' on US standard)
  1408.     VKEY_APOSTROPHE     = VKEY_OEM_7,
  1409.   VKEY_OEM_8            = 0xDF, //misc. chars; varies by keyboard
  1410.   //(reserved)          = 0xE0,
  1411.   //(misc.)             = 0xE1 -> 0xE7,
  1412.   //(unassigned)        = 0xE8,
  1413.   //(misc.)             = 0xE9 -> 0xFE,
  1414.  
  1415. };
  1416.  
  1417.  
  1418.  
  1419. // Mod[ifier]
  1420. union Event_Key_Mod { //2B
  1421.   // IMPORTANT:
  1422.   // Due to me having terminal couldn't-care-less syndrome,
  1423.   // I haven't implemented differenciating between the
  1424.   // left and right variants of shift, control, et cetera,
  1425.   // so both variants are set/unset when either are pressed/unpressed.
  1426.   // (Except lgui and rgui, since that's easier to detect???)
  1427.   // (ALSO ALTGRAPH ISN'T IMPLEMENTED AT ALL THANKS MICROSOFT)
  1428.  
  1429.   struct {
  1430.     u16 lshift    : 1;
  1431.     u16 rshift    : 1;
  1432.     u16 lctrl     : 1;
  1433.     u16 rctrl     : 1;
  1434.     u16 lalt      : 1;
  1435.     u16 ralt      : 1;
  1436.     u16 lgui      : 1;
  1437.     u16 rgui      : 1;
  1438.     u16 _unused   : 4;
  1439.     u16 numlock   : 1;
  1440.     u16 capslock  : 1;
  1441.     u16 altgraph  : 1;
  1442.     u16 scrollock : 1;
  1443.   };
  1444.  
  1445.   u16 all;
  1446.  
  1447. };
  1448.  
  1449.  
  1450.  
  1451. // Short for "Key Symbol"
  1452. struct Event_Key_Sym { //8B
  1453.   union {
  1454.     Event_Key_Mod kmod;
  1455.     u16           kmods;
  1456.   };
  1457.  
  1458.   u8  _unused;
  1459.   u8   pkey; // Physical key code (named .scancode in SDL's Keysym struct)
  1460.   u8   vkey; // Virtual key code (named .sym in SDL's Keysym struct)
  1461.   bool pressed;
  1462.   bool ischar; // 'is event KEY_CHAR?', otherwise it's KEY_UP or KEY_DOWN
  1463.   bool repeat; // Y'know that thing where in a text editor you hold down a key?
  1464.  
  1465. };
  1466.  
  1467.  
  1468.  
  1469. struct Event_Key { //24B
  1470.   u32  type;
  1471.   u32 _unused_0;
  1472.   u64  timestamp; // Performance counter is used; see "timeGetPerfCounter()"
  1473.  
  1474.   union {
  1475.     struct { // (Effectively a copy of Event_Key_Sym)
  1476.       u16  kmods;
  1477.       u8  _unused_1;
  1478.       u8   pkey;
  1479.       u8   vkey;
  1480.       bool pressed;
  1481.       bool ischar;
  1482.       bool repeat;
  1483.     };
  1484.     Event_Key_Sym sym;
  1485.   };
  1486.  
  1487. };
  1488.  
  1489. /*-EVENT_KEY-*/
  1490.  
  1491.  
  1492.  
  1493. /*+EVENT_MOUSE+*/
  1494.  
  1495. // Event_Mouse.button can use any combination of these OR'd (AKA |) together
  1496. enum Event_Mouse_ButtonEnum { // (These are bitmasks)
  1497.   MBUTTON_LEFT   = 0x01,
  1498.   MBUTTON_MIDDLE = 0x02,
  1499.   MBUTTON_RIGHT  = 0x04,
  1500.   MBUTTON_X1     = 0x08, // Those 2 buttons on the sides of most mice nowadays
  1501.   MBUTTON_X2     = 0x10,  //^^
  1502.   MBUTTON_CTRL   = 0x20, // 'Is the control key currently pressed?'
  1503.   MBUTTON_SHIFT  = 0x40, // 'Is the shift key currently pressed?'
  1504. };
  1505.  
  1506. // (EVENT_MOUSE_<H/V>WHEEL events use dx and dy!)
  1507. struct Event_Mouse { //32B
  1508.   u32  type;
  1509.  
  1510.   u8  _unused;
  1511.   u8   button;   // Flags for currently pressed buttons (Event_Mouse_ButtonEnum)
  1512.   bool pressed;  // Will be true if button is nonzero
  1513.   bool dblClick; // 'Is double click?' (ignored if cursor is trapped)
  1514.  
  1515.   u64  timestamp;
  1516.  
  1517.   f32  x;  // Coordinates relative to window
  1518.   f32  y;   //^^
  1519.   f32  dx; // Delta x (coordinates relative to last recorded x position)
  1520.   f32  dy; // Delta y (coordinates relative to last recorded y position)
  1521.   // (IF THE CURSOR IS TRAPPED, DELTAS WILL BE GIVEN AS-IS,
  1522.   //  WITHOUT BEING SCALED WITH RESPECT TO THE WINDOW'S CURRENT SIZE!)
  1523.  
  1524. };
  1525.  
  1526. /*-EVENT_MOUSE-*/
  1527.  
  1528.  
  1529.  
  1530. union Event { //32B (assuming Event_Mouse is the largest event bytes-wise)
  1531.   u32          type;
  1532.  
  1533.   Event_Common common;
  1534.   Event_Key    key;
  1535.   Event_Mouse  mouse;
  1536.  
  1537. };
  1538.  
  1539.  
  1540.  
  1541. // Populates *event_p with the contents of the first event in the event queue.
  1542. // Returns false if there were no events left in queue; true otherwise.
  1543. // (Calling this exclusively in the main thread is recommended)
  1544. bool pollEvent(Event* event_p = nullptr); // Burns events if event_p is nullptr
  1545.  
  1546.  
  1547.  
  1548. // Returns true if the mouse cursor is clipped within the window, and is hidden
  1549. bool is_cursor_trapped();
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555. /*********************************** AUDIO ************************************/
  1556.  
  1557. // Don't edit this one, as it's the hardcoded max length of an audio buffer!
  1558. #define AUDIO_SAMPLES_MAX 4096
  1559.  
  1560.  
  1561.  
  1562. // Stereo audio samples as two 32-bit floats,
  1563. // where each of the two channels can be between -1.0 to 1.0
  1564. struct StereoF32 { f32 l,r; };
  1565.  
  1566.  
  1567.  
  1568. // The length of the audio stream's buffer, in samples
  1569. extern u32 audio_samples;
  1570.  
  1571. // The audio's sample rate, in hertz
  1572. extern u32 sample_rate;
  1573.  
  1574.  
  1575.  
  1576. #include "sound_stuff.hpp"
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582. /*********************************** VIDEO ************************************/
  1583.  
  1584. #define WIN_NAME "OpenGL Demo"
  1585.  
  1586.  
  1587.  
  1588. // Used for setting pixels_palette.
  1589. // This struct is analagous to Win32's own RGBQUAD struct,
  1590. // but formatted to be a bit more readable and nicer-looking
  1591. //
  1592. // (Make sure to call update_palette() to apply any changes to the palette!)
  1593. union Color24 {
  1594.   // Full pixel value. Since this is a union, this 32-bit value takes
  1595.   // up the same space as the four 8-bit values below.
  1596.   // The purpose of using a union like this is that by setting v,
  1597.   // you are setting b,g,r, and _ at the same time!
  1598.   u32 v;
  1599.  
  1600.   // Before the C11 standard, anonymous structs (or unions for that matter)
  1601.   // were compiler-specific extensions, but virtually all modern compilers
  1602.   // allow this type of syntax, where structs that are directly declaring
  1603.   // the contents of a type (as opposed to defining a type that can be
  1604.   // replicated) without giving it a name.
  1605.   //
  1606.   // In this case, this effectively packages these four bytes to be in this
  1607.   // order, rather than reside in the same space (this is a union, after all!)
  1608.   struct {
  1609.     u8 b;
  1610.     u8 g;
  1611.     u8 r;
  1612.     u8 _; // (Unused; this is just padding to the nearest multiple of 32-bits)
  1613.   };
  1614.  
  1615. };
  1616.  
  1617.  
  1618.  
  1619. void present_window();
  1620.  
  1621. void close_window(); // Also triggers an EVENT_QUIT
  1622.  
  1623. bool is_win_closed();
  1624.  
  1625. // Returns the current size of the window's *client* area,
  1626. // which is basically the space in the window where stuff is actually drawn
  1627. Point2d get_win_size();
  1628.  
  1629. // Useful for, say, drawing/swapping buffers
  1630. // only when the window has input focus
  1631. bool is_win_focused();
  1632.  
  1633. void trap_cursor(bool enable, bool condition);
  1634.  
  1635.  
  1636.  
  1637.  
  1638.  
  1639. /********************************** FILE IO ***********************************/
  1640.  
  1641. struct BinaryData {
  1642.   union { // The everything union~
  1643.     u8 *  data_u8;
  1644.     u16*  data_u16;
  1645.     u32*  data_u32;
  1646.     u64*  data_u64;
  1647.  
  1648.     s8 *  data_s8;
  1649.     s16*  data_s16;
  1650.     s32*  data_s32;
  1651.     s64*  data_s64;
  1652.  
  1653.     f32*  data_f32;
  1654.     f64*  data_f64;
  1655.  
  1656.     char* data_char;
  1657.     void* data_void = nullptr;
  1658.   };
  1659.  
  1660.   // Even if size is 0, data will always have at least a single byte of valid
  1661.   // allocated memory. This is because there is always one more byte allocated
  1662.   // than is requested, to make sure that data is only ever nullptr if
  1663.   // construction fails! (This extra byte will always be set to 0.)
  1664.   const size_t size;
  1665.  
  1666.  
  1667.   BinaryData(const char* file_path);
  1668.  
  1669.   // This will allocate _size bytes for data, before copying src to data
  1670.   //
  1671.   // (It is safe to pass nullptr to src, though that would make the struct
  1672.   //  instance sorta equivalent to a garbage-collected CoTaskMemAlloc().)
  1673.   BinaryData(const void* src, size_t _size);
  1674.  
  1675.   ~BinaryData();
  1676.  
  1677. };
  1678.  
  1679.  
  1680.  
  1681. // fileio_read allocates memory! use mem_free on the returned pointer after use!
  1682. void* fileio_read(const char* file_path, size_t* dataSize_p);
  1683.  
  1684. bool fileio_write(const char* file_path, const void* data,
  1685.                   size_t data_size, bool append = false);
  1686.  
  1687.  
  1688.  
  1689. #define FILEIO_SIZE_ERR 0xFFFFFFFFFFFFFFFF
  1690.  
  1691. size_t fileio_size(const char* file_path);
  1692.  
  1693. bool fileio_isreadonly(const char* file_path);
  1694.  
  1695. bool fileio_exists(const char* file_path);
  1696.  
  1697. bool fileio_delete(const char* file_path);
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703. /*********************** DRAW STUFF (NOT WIN32-RELATED) ***********************/
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709. #endif /* _PUBLIC_STUFF_HPP */
  1710.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement