aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-08-19 15:09:39 +0100
committergingerBill <bill@gingerbill.org>2021-08-19 15:09:39 +0100
commit9ae4de2ab8de61d130924b6ecf6c079f65f45720 (patch)
tree07b49f22b01dcc91e164132a32a1559410519222 /src
parent7845769d4b417fdd321740c5404016dbc3119d43 (diff)
Remove unused code from gb.h (which means it is heavily modified now)
Diffstat (limited to 'src')
-rw-r--r--src/gb/gb.h2271
1 files changed, 2 insertions, 2269 deletions
diff --git a/src/gb/gb.h b/src/gb/gb.h
index c374da066..a67e0a076 100644
--- a/src/gb/gb.h
+++ b/src/gb/gb.h
@@ -4,126 +4,8 @@
This is a single header file with a bunch of useful stuff
to replace the C/C++ standard library
-===========================================================================
- YOU MUST
-
- #define GB_IMPLEMENTATION
-
- in EXACTLY _one_ C or C++ file that includes this header, BEFORE the
- include like this:
-
- #define GB_IMPLEMENTATION
- #include "gb.h"
-
- All other files should just #include "gb.h" without #define
-
-
- If you want the platform layer, YOU MUST
-
- #define GB_PLATFORM
-
- BEFORE the include like this:
-
- #define GB_PLATFORM
- #include "gb.h"
-
-===========================================================================
-
-LICENSE
- This software is dual-licensed to the public domain and under the following
- license: you are granted a perpetual, irrevocable license to copy, modify,
- publish, and distribute this file as you see fit.
-
-WARNING
- - This library is _slightly_ experimental and features may not work as expected.
- - This also means that many functions are not documented.
-
-CREDITS
- Written by Ginger Bill
-
-TODOS
- - Remove CRT dependency for people who want that
- - But do I really?
- - Or make it only depend on the really needed stuff?
- - Older compiler support?
- - How old do you wanna go?
- - Only support C90+extension and C99 not pure C89.
- - File handling
- - All files to be UTF-8 (even on windows)
- - Better Virtual Memory handling
- - Generic Heap Allocator (tcmalloc/dlmalloc/?)
- - Fixed Heap Allocator
- - Better UTF support and conversion
- - Free List, best fit rather than first fit
- - More date & time functions
-
-VERSION HISTORY
- 0.33 - Minor fixes
- 0.32 - Minor fixes
- 0.31 - Add gb_file_remove
- 0.30 - Changes to gbThread (and gbMutex on Windows)
- 0.29 - Add extras for gbString
- 0.28 - Handle UCS2 correctly in Win32 part
- 0.27 - OSX fixes and Linux gbAffinity
- 0.26d - Minor changes to how gbFile works
- 0.26c - gb_str_to_f* fix
- 0.26b - Minor fixes
- 0.26a - gbString Fix
- 0.26 - Default allocator flags and generic hash table
- 0.25a - Fix UTF-8 stuff
- 0.25 - OS X gbPlatform Support (missing some things)
- 0.24b - Compile on OSX (excluding platform part)
- 0.24a - Minor additions
- 0.24 - Enum convention change
- 0.23 - Optional Windows.h removal (because I'm crazy)
- 0.22a - Remove gbVideoMode from gb_platform_init_*
- 0.22 - gbAffinity - (Missing Linux version)
- 0.21 - Platform Layer Restructuring
- 0.20 - Improve file io
- 0.19 - Clipboard Text
- 0.18a - Controller vibration
- 0.18 - Raw keyboard and mouse input for WIN32
- 0.17d - Fixed printf bug for strings
- 0.17c - Compile as 32 bit
- 0.17b - Change formating style because why not?
- 0.17a - Dropped C90 Support (For numerous reasons)
- 0.17 - Instantiated Hash Table
- 0.16a - Minor code layout changes
- 0.16 - New file API and improved platform layer
- 0.15d - Linux Experimental Support (DON'T USE IT PLEASE)
- 0.15c - Linux Experimental Support (DON'T USE IT)
- 0.15b - C90 Support
- 0.15a - gb_atomic(32|64)_spin_(lock|unlock)
- 0.15 - Recursive "Mutex"; Key States; gbRandom
- 0.14 - Better File Handling and better printf (WIN32 Only)
- 0.13 - Highly experimental platform layer (WIN32 Only)
- 0.12b - Fix minor file bugs
- 0.12a - Compile as C++
- 0.12 - New File Handing System! No stdio or stdlib! (WIN32 Only)
- 0.11a - Add string precision and width (experimental)
- 0.11 - Started making stdio & stdlib optional (Not tested much)
- 0.10c - Fix gb_endian_swap32()
- 0.10b - Probable timing bug for gb_time_now()
- 0.10a - Work on multiple compilers
- 0.10 - Scratch Memory Allocator
- 0.09a - Faster Mutex and the Free List is slightly improved
- 0.09 - Basic Virtual Memory System and Dreadful Free List allocator
- 0.08a - Fix *_appendv bug
- 0.08 - Huge Overhaul!
- 0.07a - Fix alignment in gb_heap_allocator_proc
- 0.07 - Hash Table and Hashing Functions
- 0.06c - Better Documentation
- 0.06b - OS X Support
- 0.06a - Linux Support
- 0.06 - Windows GCC Support and MSVC x86 Support
- 0.05b - Formatting
- 0.05a - Minor function name changes
- 0.05 - Radix Sort for unsigned integers (TODO: Other primitives)
- 0.04 - Better UTF support and search/sort procs
- 0.03 - Completely change procedure naming convention
- 0.02a - Bug fixes
- 0.02 - Change naming convention and gbArray(Type)
- 0.01 - Initial Version
+ IMPORTANT NOTE: THIS IS A HEAVILY MODIFIED VERSION OF THE ORIGINAL
+ DO NO REPLACE IT WITH THE ORIGINAL
*/
@@ -2179,374 +2061,6 @@ GB_DEF u64 gb_endian_swap64(u64 i);
GB_DEF isize gb_count_set_bits(u64 mask);
-////////////////////////////////////////////////////////////////
-//
-// Platform Stuff
-//
-//
-
-#if defined(GB_PLATFORM)
-
-// NOTE(bill):
-// Coordiate system - +ve x - left to right
-// - +ve y - bottom to top
-// - Relative to window
-
-// TODO(bill): Proper documentation for this with code examples
-
-// Window Support - Complete
-// OS X Support - Missing:
-// * Sofware framebuffer
-// * (show|hide) window
-// * show_cursor
-// * toggle (fullscreen|borderless)
-// * set window position
-// * Clipboard
-// * GameControllers
-// Linux Support - None
-// Other OS Support - None
-
-#ifndef GB_MAX_GAME_CONTROLLER_COUNT
-#define GB_MAX_GAME_CONTROLLER_COUNT 4
-#endif
-
-typedef enum gbKeyType {
- gbKey_Unknown = 0, // Unhandled key
-
- // NOTE(bill): Allow the basic printable keys to be aliased with their chars
- gbKey_0 = '0',
- gbKey_1,
- gbKey_2,
- gbKey_3,
- gbKey_4,
- gbKey_5,
- gbKey_6,
- gbKey_7,
- gbKey_8,
- gbKey_9,
-
- gbKey_A = 'A',
- gbKey_B,
- gbKey_C,
- gbKey_D,
- gbKey_E,
- gbKey_F,
- gbKey_G,
- gbKey_H,
- gbKey_I,
- gbKey_J,
- gbKey_K,
- gbKey_L,
- gbKey_M,
- gbKey_N,
- gbKey_O,
- gbKey_P,
- gbKey_Q,
- gbKey_R,
- gbKey_S,
- gbKey_T,
- gbKey_U,
- gbKey_V,
- gbKey_W,
- gbKey_X,
- gbKey_Y,
- gbKey_Z,
-
- gbKey_Lbracket = '[',
- gbKey_Rbracket = ']',
- gbKey_Semicolon = ';',
- gbKey_Comma = ',',
- gbKey_Period = '.',
- gbKey_Quote = '\'',
- gbKey_Slash = '/',
- gbKey_Backslash = '\\',
- gbKey_Grave = '`',
- gbKey_Equals = '=',
- gbKey_Minus = '-',
- gbKey_Space = ' ',
-
- gbKey__Pad = 128, // NOTE(bill): make sure ASCII is reserved
-
- gbKey_Escape, // Escape
- gbKey_Lcontrol, // Left Control
- gbKey_Lshift, // Left Shift
- gbKey_Lalt, // Left Alt
- gbKey_Lsystem, // Left OS specific: window (Windows and Linux), apple/cmd (MacOS X), ...
- gbKey_Rcontrol, // Right Control
- gbKey_Rshift, // Right Shift
- gbKey_Ralt, // Right Alt
- gbKey_Rsystem, // Right OS specific: window (Windows and Linux), apple/cmd (MacOS X), ...
- gbKey_Menu, // Menu
- gbKey_Return, // Return
- gbKey_Backspace, // Backspace
- gbKey_Tab, // Tabulation
- gbKey_Pageup, // Page up
- gbKey_Pagedown, // Page down
- gbKey_End, // End
- gbKey_Home, // Home
- gbKey_Insert, // Insert
- gbKey_Delete, // Delete
- gbKey_Plus, // +
- gbKey_Subtract, // -
- gbKey_Multiply, // *
- gbKey_Divide, // /
- gbKey_Left, // Left arrow
- gbKey_Right, // Right arrow
- gbKey_Up, // Up arrow
- gbKey_Down, // Down arrow
- gbKey_Numpad0, // Numpad 0
- gbKey_Numpad1, // Numpad 1
- gbKey_Numpad2, // Numpad 2
- gbKey_Numpad3, // Numpad 3
- gbKey_Numpad4, // Numpad 4
- gbKey_Numpad5, // Numpad 5
- gbKey_Numpad6, // Numpad 6
- gbKey_Numpad7, // Numpad 7
- gbKey_Numpad8, // Numpad 8
- gbKey_Numpad9, // Numpad 9
- gbKey_NumpadDot, // Numpad .
- gbKey_NumpadEnter, // Numpad Enter
- gbKey_F1, // F1
- gbKey_F2, // F2
- gbKey_F3, // F3
- gbKey_F4, // F4
- gbKey_F5, // F5
- gbKey_F6, // F6
- gbKey_F7, // F7
- gbKey_F8, // F8
- gbKey_F9, // F8
- gbKey_F10, // F10
- gbKey_F11, // F11
- gbKey_F12, // F12
- gbKey_F13, // F13
- gbKey_F14, // F14
- gbKey_F15, // F15
- gbKey_Pause, // Pause
-
- gbKey_Count,
-} gbKeyType;
-
-/* TODO(bill): Change name? */
-typedef u8 gbKeyState;
-typedef enum gbKeyStateFlag {
- gbKeyState_Down = GB_BIT(0),
- gbKeyState_Pressed = GB_BIT(1),
- gbKeyState_Released = GB_BIT(2)
-} gbKeyStateFlag;
-
-GB_DEF void gb_key_state_update(gbKeyState *s, b32 is_down);
-
-typedef enum gbMouseButtonType {
- gbMouseButton_Left,
- gbMouseButton_Middle,
- gbMouseButton_Right,
- gbMouseButton_X1,
- gbMouseButton_X2,
-
- gbMouseButton_Count
-} gbMouseButtonType;
-
-typedef enum gbControllerAxisType {
- gbControllerAxis_LeftX,
- gbControllerAxis_LeftY,
- gbControllerAxis_RightX,
- gbControllerAxis_RightY,
- gbControllerAxis_LeftTrigger,
- gbControllerAxis_RightTrigger,
-
- gbControllerAxis_Count
-} gbControllerAxisType;
-
-typedef enum gbControllerButtonType {
- gbControllerButton_Up,
- gbControllerButton_Down,
- gbControllerButton_Left,
- gbControllerButton_Right,
- gbControllerButton_A,
- gbControllerButton_B,
- gbControllerButton_X,
- gbControllerButton_Y,
- gbControllerButton_LeftShoulder,
- gbControllerButton_RightShoulder,
- gbControllerButton_Back,
- gbControllerButton_Start,
- gbControllerButton_LeftThumb,
- gbControllerButton_RightThumb,
-
- gbControllerButton_Count
-} gbControllerButtonType;
-
-typedef struct gbGameController {
- b16 is_connected, is_analog;
-
- f32 axes[gbControllerAxis_Count];
- gbKeyState buttons[gbControllerButton_Count];
-} gbGameController;
-
-#if defined(GB_SYSTEM_WINDOWS)
- typedef struct _XINPUT_GAMEPAD XINPUT_GAMEPAD;
- typedef struct _XINPUT_STATE XINPUT_STATE;
- typedef struct _XINPUT_VIBRATION XINPUT_VIBRATION;
-
- #define GB_XINPUT_GET_STATE(name) unsigned long __stdcall name(unsigned long dwUserIndex, XINPUT_STATE *pState)
- typedef GB_XINPUT_GET_STATE(gbXInputGetStateProc);
-
- #define GB_XINPUT_SET_STATE(name) unsigned long __stdcall name(unsigned long dwUserIndex, XINPUT_VIBRATION *pVibration)
- typedef GB_XINPUT_SET_STATE(gbXInputSetStateProc);
-#endif
-
-
-typedef enum gbWindowFlag {
- gbWindow_Fullscreen = GB_BIT(0),
- gbWindow_Hidden = GB_BIT(1),
- gbWindow_Borderless = GB_BIT(2),
- gbWindow_Resizable = GB_BIT(3),
- gbWindow_Minimized = GB_BIT(4),
- gbWindow_Maximized = GB_BIT(5),
- gbWindow_FullscreenDesktop = gbWindow_Fullscreen | gbWindow_Borderless,
-} gbWindowFlag;
-
-typedef enum gbRendererType {
- gbRenderer_Opengl,
- gbRenderer_Software,
-
- gbRenderer_Count,
-} gbRendererType;
-
-
-
-#if defined(GB_SYSTEM_WINDOWS) && !defined(_WINDOWS_)
-typedef struct tagBITMAPINFOHEADER {
- unsigned long biSize;
- long biWidth;
- long biHeight;
- u16 biPlanes;
- u16 biBitCount;
- unsigned long biCompression;
- unsigned long biSizeImage;
- long biXPelsPerMeter;
- long biYPelsPerMeter;
- unsigned long biClrUsed;
- unsigned long biClrImportant;
-} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
-typedef struct tagRGBQUAD {
- u8 rgbBlue;
- u8 rgbGreen;
- u8 rgbRed;
- u8 rgbReserved;
-} RGBQUAD;
-typedef struct tagBITMAPINFO {
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[1];
-} BITMAPINFO, *PBITMAPINFO;
-#endif
-
-typedef struct gbPlatform {
- b32 is_initialized;
-
- void *window_handle;
- i32 window_x, window_y;
- i32 window_width, window_height;
- u32 window_flags;
- b16 window_is_closed, window_has_focus;
-
-#if defined(GB_SYSTEM_WINDOWS)
- void *win32_dc;
-#elif defined(GB_SYSTEM_OSX)
- void *osx_autorelease_pool; // TODO(bill): Is this really needed?
-#endif
-
- gbRendererType renderer_type;
- union {
- struct {
- void * context;
- i32 major;
- i32 minor;
- b16 core, compatible;
- gbDllHandle dll_handle;
- } opengl;
-
- // NOTE(bill): Software rendering
- struct {
-#if defined(GB_SYSTEM_WINDOWS)
- BITMAPINFO win32_bmi;
-#endif
- void * memory;
- isize memory_size;
- i32 pitch;
- i32 bits_per_pixel;
- } sw_framebuffer;
- };
-
- gbKeyState keys[gbKey_Count];
- struct {
- gbKeyState control;
- gbKeyState alt;
- gbKeyState shift;
- } key_modifiers;
-
- Rune char_buffer[256];
- isize char_buffer_count;
-
- b32 mouse_clip;
- i32 mouse_x, mouse_y;
- i32 mouse_dx, mouse_dy; // NOTE(bill): Not raw mouse movement
- i32 mouse_raw_dx, mouse_raw_dy; // NOTE(bill): Raw mouse movement
- f32 mouse_wheel_delta;
- gbKeyState mouse_buttons[gbMouseButton_Count];
-
- gbGameController game_controllers[GB_MAX_GAME_CONTROLLER_COUNT];
-
- f64 curr_time;
- f64 dt_for_frame;
- b32 quit_requested;
-
-#if defined(GB_SYSTEM_WINDOWS)
- struct {
- gbXInputGetStateProc *get_state;
- gbXInputSetStateProc *set_state;
- } xinput;
-#endif
-} gbPlatform;
-
-
-typedef struct gbVideoMode {
- i32 width, height;
- i32 bits_per_pixel;
-} gbVideoMode;
-
-GB_DEF gbVideoMode gb_video_mode (i32 width, i32 height, i32 bits_per_pixel);
-GB_DEF b32 gb_video_mode_is_valid (gbVideoMode mode);
-GB_DEF gbVideoMode gb_video_mode_get_desktop (void);
-GB_DEF isize gb_video_mode_get_fullscreen_modes(gbVideoMode *modes, isize max_mode_count); // NOTE(bill): returns mode count
-GB_DEF GB_COMPARE_PROC(gb_video_mode_cmp); // NOTE(bill): Sort smallest to largest (Ascending)
-GB_DEF GB_COMPARE_PROC(gb_video_mode_dsc_cmp); // NOTE(bill): Sort largest to smallest (Descending)
-
-
-// NOTE(bill): Software rendering
-GB_DEF b32 gb_platform_init_with_software (gbPlatform *p, char const *window_title, i32 width, i32 height, u32 window_flags);
-// NOTE(bill): OpenGL Rendering
-GB_DEF b32 gb_platform_init_with_opengl (gbPlatform *p, char const *window_title, i32 width, i32 height, u32 window_flags, i32 major, i32 minor, b32 core, b32 compatible);
-GB_DEF void gb_platform_update (gbPlatform *p);
-GB_DEF void gb_platform_display (gbPlatform *p);
-GB_DEF void gb_platform_destroy (gbPlatform *p);
-GB_DEF void gb_platform_show_cursor (gbPlatform *p, b32 show);
-GB_DEF void gb_platform_set_mouse_position (gbPlatform *p, i32 x, i32 y);
-GB_DEF void gb_platform_set_controller_vibration (gbPlatform *p, isize index, f32 left_motor, f32 right_motor);
-GB_DEF b32 gb_platform_has_clipboard_text (gbPlatform *p);
-GB_DEF void gb_platform_set_clipboard_text (gbPlatform *p, char const *str);
-GB_DEF char *gb_platform_get_clipboard_text (gbPlatform *p, gbAllocator a);
-GB_DEF void gb_platform_set_window_position (gbPlatform *p, i32 x, i32 y);
-GB_DEF void gb_platform_set_window_title (gbPlatform *p, char const *title, ...) GB_PRINTF_ARGS(2);
-GB_DEF void gb_platform_toggle_fullscreen (gbPlatform *p, b32 fullscreen_desktop);
-GB_DEF void gb_platform_toggle_borderless (gbPlatform *p);
-GB_DEF void gb_platform_make_opengl_context_current(gbPlatform *p);
-GB_DEF void gb_platform_show_window (gbPlatform *p);
-GB_DEF void gb_platform_hide_window (gbPlatform *p);
-
-
-#endif // GB_PLATFORM
-
#if defined(__cplusplus)
}
#endif
@@ -9311,1787 +8825,6 @@ gb_inline isize gb_count_set_bits(u64 mask) {
}
-
-
-
-
-////////////////////////////////////////////////////////////////
-//
-// Platform
-//
-//
-
-#if defined(GB_PLATFORM)
-
-gb_inline void gb_key_state_update(gbKeyState *s, b32 is_down) {
- b32 was_down = (*s & gbKeyState_Down) != 0;
- is_down = is_down != 0; // NOTE(bill): Make sure it's a boolean
- GB_MASK_SET(*s, is_down, gbKeyState_Down);
- GB_MASK_SET(*s, !was_down && is_down, gbKeyState_Pressed);
- GB_MASK_SET(*s, was_down && !is_down, gbKeyState_Released);
-}
-
-#if defined(GB_SYSTEM_WINDOWS)
-
-#ifndef ERROR_DEVICE_NOT_CONNECTED
-#define ERROR_DEVICE_NOT_CONNECTED 1167
-#endif
-
-GB_XINPUT_GET_STATE(gbXInputGetState_Stub) {
- gb_unused(dwUserIndex); gb_unused(pState);
- return ERROR_DEVICE_NOT_CONNECTED;
-}
-GB_XINPUT_SET_STATE(gbXInputSetState_Stub) {
- gb_unused(dwUserIndex); gb_unused(pVibration);
- return ERROR_DEVICE_NOT_CONNECTED;
-}
-
-
-gb_internal gb_inline f32 gb__process_xinput_stick_value(i16 value, i16 dead_zone_threshold) {
- f32 result = 0;
-
- if (value < -dead_zone_threshold) {
- result = cast(f32) (value + dead_zone_threshold) / (32768.0f - dead_zone_threshold);
- } else if (value > dead_zone_threshold) {
- result = cast(f32) (value - dead_zone_threshold) / (32767.0f - dead_zone_threshold);
- }
-
- return result;
-}
-
-gb_internal void gb__platform_resize_dib_section(gbPlatform *p, i32 width, i32 height) {
- if ((p->renderer_type == gbRenderer_Software) &&
- !(p->window_width == width && p->window_height == height)) {
- BITMAPINFO bmi = {0};
-
- if (width == 0 || height == 0) {
- return;
- }
-
- p->window_width = width;
- p->window_height = height;
-
- // TODO(bill): Is this slow to get the desktop mode everytime?
- p->sw_framebuffer.bits_per_pixel = gb_video_mode_get_desktop().bits_per_pixel;
- p->sw_framebuffer.pitch = (p->sw_framebuffer.bits_per_pixel * width / 8);
-
- bmi.bmiHeader.biSize = gb_size_of(bmi.bmiHeader);
- bmi.bmiHeader.biWidth = width;
- bmi.bmiHeader.biHeight = height; // NOTE(bill): -ve is top-down, +ve is bottom-up
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = cast(u16)p->sw_framebuffer.bits_per_pixel;
- bmi.bmiHeader.biCompression = 0 /*BI_RGB*/;
-
- p->sw_framebuffer.win32_bmi = bmi;
-
-
- if (p->sw_framebuffer.memory) {
- gb_vm_free(gb_virtual_memory(p->sw_framebuffer.memory, p->sw_framebuffer.memory_size));
- }
-
- {
- isize memory_size = p->sw_framebuffer.pitch * height;
- gbVirtualMemory vm = gb_vm_alloc(0, memory_size);
- p->sw_framebuffer.memory = vm.data;
- p->sw_framebuffer.memory_size = vm.size;
- }
- }
-}
-
-
-gb_internal gbKeyType gb__win32_from_vk(unsigned int key) {
- // NOTE(bill): Letters and numbers are defined the same for VK_* and GB_*
- if (key >= 'A' && key < 'Z') return cast(gbKeyType)key;
- if (key >= '0' && key < '9') return cast(gbKeyType)key;
- switch (key) {
- case VK_ESCAPE: return gbKey_Escape;
-
- case VK_LCONTROL: return gbKey_Lcontrol;
- case VK_LSHIFT: return gbKey_Lshift;
- case VK_LMENU: return gbKey_Lalt;
- case VK_LWIN: return gbKey_Lsystem;
- case VK_RCONTROL: return gbKey_Rcontrol;
- case VK_RSHIFT: return gbKey_Rshift;
- case VK_RMENU: return gbKey_Ralt;
- case VK_RWIN: return gbKey_Rsystem;
- case VK_MENU: return gbKey_Menu;
-
- case VK_OEM_4: return gbKey_Lbracket;
- case VK_OEM_6: return gbKey_Rbracket;
- case VK_OEM_1: return gbKey_Semicolon;
- case VK_OEM_COMMA: return gbKey_Comma;
- case VK_OEM_PERIOD: return gbKey_Period;
- case VK_OEM_7: return gbKey_Quote;
- case VK_OEM_2: return gbKey_Slash;
- case VK_OEM_5: return gbKey_Backslash;
- case VK_OEM_3: return gbKey_Grave;
- case VK_OEM_PLUS: return gbKey_Equals;
- case VK_OEM_MINUS: return gbKey_Minus;
-
- case VK_SPACE: return gbKey_Space;
- case VK_RETURN: return gbKey_Return;
- case VK_BACK: return gbKey_Backspace;
- case VK_TAB: return gbKey_Tab;
-
- case VK_PRIOR: return gbKey_Pageup;
- case VK_NEXT: return gbKey_Pagedown;
- case VK_END: return gbKey_End;
- case VK_HOME: return gbKey_Home;
- case VK_INSERT: return gbKey_Insert;
- case VK_DELETE: return gbKey_Delete;
-
- case VK_ADD: return gbKey_Plus;
- case VK_SUBTRACT: return gbKey_Subtract;
- case VK_MULTIPLY: return gbKey_Multiply;
- case VK_DIVIDE: return gbKey_Divide;
-
- case VK_LEFT: return gbKey_Left;
- case VK_RIGHT: return gbKey_Right;
- case VK_UP: return gbKey_Up;
- case VK_DOWN: return gbKey_Down;
-
- case VK_NUMPAD0: return gbKey_Numpad0;
- case VK_NUMPAD1: return gbKey_Numpad1;
- case VK_NUMPAD2: return gbKey_Numpad2;
- case VK_NUMPAD3: return gbKey_Numpad3;
- case VK_NUMPAD4: return gbKey_Numpad4;
- case VK_NUMPAD5: return gbKey_Numpad5;
- case VK_NUMPAD6: return gbKey_Numpad6;
- case VK_NUMPAD7: return gbKey_Numpad7;
- case VK_NUMPAD8: return gbKey_Numpad8;
- case VK_NUMPAD9: return gbKey_Numpad9;
- case VK_SEPARATOR: return gbKey_NumpadEnter;
- case VK_DECIMAL: return gbKey_NumpadDot;
-
- case VK_F1: return gbKey_F1;
- case VK_F2: return gbKey_F2;
- case VK_F3: return gbKey_F3;
- case VK_F4: return gbKey_F4;
- case VK_F5: return gbKey_F5;
- case VK_F6: return gbKey_F6;
- case VK_F7: return gbKey_F7;
- case VK_F8: return gbKey_F8;
- case VK_F9: return gbKey_F9;
- case VK_F10: return gbKey_F10;
- case VK_F11: return gbKey_F11;
- case VK_F12: return gbKey_F12;
- case VK_F13: return gbKey_F13;
- case VK_F14: return gbKey_F14;
- case VK_F15: return gbKey_F15;
-
- case VK_PAUSE: return gbKey_Pause;
- }
- return gbKey_Unknown;
-}
-LRESULT CALLBACK gb__win32_window_callback(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
- // NOTE(bill): Silly callbacks
- gbPlatform *platform = cast(gbPlatform *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
- b32 window_has_focus = (platform != NULL) && platform->window_has_focus;
-
- if (msg == WM_CREATE) { // NOTE(bill): Doesn't need the platform
- // NOTE(bill): https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx
- RAWINPUTDEVICE rid[2] = {0};
-
- // NOTE(bill): Keyboard
- rid[0].usUsagePage = 0x01;
- rid[0].usUsage = 0x06;
- rid[0].dwFlags = 0x00000030/*RIDEV_NOLEGACY*/; // NOTE(bill): Do not generate legacy messages such as WM_KEYDOWN
- rid[0].hwndTarget = hWnd;
-
- // NOTE(bill): Mouse
- rid[1].usUsagePage = 0x01;
- rid[1].usUsage = 0x02;
- rid[1].dwFlags = 0; // NOTE(bill): adds HID mouse and also allows legacy mouse messages to allow for window movement etc.
- rid[1].hwndTarget = hWnd;
-
- if (RegisterRawInputDevices(rid, gb_count_of(rid), gb_size_of(rid[0])) == false) {
- DWORD err = GetLastError();
- GB_PANIC("Failed to initialize raw input device for win32."
- "Err: %u", err);
- }
- }
-
- if (!platform) {
- return DefWindowProcW(hWnd, msg, wParam, lParam);
- }
-
- switch (msg) {
- case WM_CLOSE:
- case WM_DESTROY:
- platform->window_is_closed = true;
- return 0;
-
- case WM_QUIT: {
- platform->quit_requested = true;
- } break;
-
- case WM_UNICHAR: {
- if (window_has_focus) {
- if (wParam == '\r') {
- wParam = '\n';
- }
- // TODO(bill): Does this need to be thread-safe?
- platform->char_buffer[platform->char_buffer_count++] = cast(Rune)wParam;
- }
- } break;
-
-
- case WM_INPUT: {
- RAWINPUT raw = {0};
- unsigned int size = gb_size_of(RAWINPUT);
-
- if (!GetRawInputData(cast(HRAWINPUT)lParam, RID_INPUT, &raw, &size, gb_size_of(RAWINPUTHEADER))) {
- return 0;
- }
- switch (raw.header.dwType) {
- case RIM_TYPEKEYBOARD: {
- // NOTE(bill): Many thanks to https://blog.molecular-matters.com/2011/09/05/properly-handling-keyboard-input/
- // for the
- RAWKEYBOARD *raw_kb = &raw.data.keyboard;
- unsigned int vk = raw_kb->VKey;
- unsigned int scan_code = raw_kb->MakeCode;
- unsigned int flags = raw_kb->Flags;
- // NOTE(bill): e0 and e1 are escape sequences used for certain special keys, such as PRINT and PAUSE/BREAK.
- // NOTE(bill): http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
- b32 is_e0 = (flags & RI_KEY_E0) != 0;
- b32 is_e1 = (flags & RI_KEY_E1) != 0;
- b32 is_up = (flags & RI_KEY_BREAK) != 0;
- b32 is_down = !is_up;
-
- // TODO(bill): Should I handle scan codes?
-
- if (vk == 255) {
- // NOTE(bill): Discard "fake keys"
- return 0;
- } else if (vk == VK_SHIFT) {
- // NOTE(bill): Correct left/right shift
- vk = MapVirtualKeyW(scan_code, MAPVK_VSC_TO_VK_EX);
- } else if (vk == VK_NUMLOCK) {
- // NOTE(bill): Correct PAUSE/BREAK and NUM LOCK and set the extended bit
- scan_code = MapVirtualKeyW(vk, MAPVK_VK_TO_VSC) | 0x100;
- }
-
- if (is_e1) {
- // NOTE(bill): Escaped sequences, turn vk into the correct scan code
- // except for VK_PAUSE (it's a bug)
- if (vk == VK_PAUSE) {
- scan_code = 0x45;
- } else {
- scan_code = MapVirtualKeyW(vk, MAPVK_VK_TO_VSC);
- }
- }
-
- switch (vk) {
- case VK_CONTROL: vk = (is_e0) ? VK_RCONTROL : VK_LCONTROL; break;
- case VK_MENU: vk = (is_e0) ? VK_RMENU : VK_LMENU; break;
-
- case VK_RETURN: if (is_e0) vk = VK_SEPARATOR; break; // NOTE(bill): Numpad return
- case VK_DELETE: if (!is_e0) vk = VK_DECIMAL; break; // NOTE(bill): Numpad dot
- case VK_INSERT: if (!is_e0) vk = VK_NUMPAD0; break;
- case VK_HOME: if (!is_e0) vk = VK_NUMPAD7; break;
- case VK_END: if (!is_e0) vk = VK_NUMPAD1; break;
- case VK_PRIOR: if (!is_e0) vk = VK_NUMPAD9; break;
- case VK_NEXT: if (!is_e0) vk = VK_NUMPAD3; break;
-
- // NOTE(bill): The standard arrow keys will always have their e0 bit set, but the
- // corresponding keys on the NUMPAD will not.
- case VK_LEFT: if (!is_e0) vk = VK_NUMPAD4; break;
- case VK_RIGHT: if (!is_e0) vk = VK_NUMPAD6; break;
- case VK_UP: if (!is_e0) vk = VK_NUMPAD8; break;
- case VK_DOWN: if (!is_e0) vk = VK_NUMPAD2; break;
-
- // NUMPAD 5 doesn't have its e0 bit set
- case VK_CLEAR: if (!is_e0) vk = VK_NUMPAD5; break;
- }
-
- // NOTE(bill): Set appropriate key state flags
- gb_key_state_update(&platform->keys[gb__win32_from_vk(vk)], is_down);
-
- } break;
- case RIM_TYPEMOUSE: {
- RAWMOUSE *raw_mouse = &raw.data.mouse;
- u16 flags = raw_mouse->usButtonFlags;
- long dx = +raw_mouse->lLastX;
- long dy = -raw_mouse->lLastY;
-
- if (flags & RI_MOUSE_WHEEL) {
- platform->mouse_wheel_delta = cast(i16)raw_mouse->usButtonData;
- }
-
- platform->mouse_raw_dx = dx;
- platform->mouse_raw_dy = dy;
- } break;
- }
- } break;
-
- default: break;
- }
-
- return DefWindowProcW(hWnd, msg, wParam, lParam);
-}
-
-
-typedef void *wglCreateContextAttribsARB_Proc(void *hDC, void *hshareContext, int const *attribList);
-
-
-b32 gb__platform_init(gbPlatform *p, char const *window_title, gbVideoMode mode, gbRendererType type, u32 window_flags) {
- WNDCLASSEXW wc = {gb_size_of(WNDCLASSEXW)};
- DWORD ex_style = 0, style = 0;
- RECT wr;
- u16 title_buffer[256] = {0}; // TODO(bill): gb_local_persist this?
-
- wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC
- wc.lpfnWndProc = gb__win32_window_callback;
- wc.hbrBackground = cast(HBRUSH)GetStockObject(0/*WHITE_BRUSH*/);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = L"gb-win32-wndclass"; // TODO(bill): Is this enough?
- wc.hInstance = GetModuleHandleW(NULL);
-
- if (RegisterClassExW(&wc) == 0) {
- MessageBoxW(NULL, L"Failed to register the window class", L"ERROR", MB_OK | MB_ICONEXCLAMATION);
- return false;
- }
-
- if ((window_flags & gbWindow_Fullscreen) && !(window_flags & gbWindow_Borderless)) {
- DEVMODEW screen_settings = {gb_size_of(DEVMODEW)};
- screen_settings.dmPelsWidth = mode.width;
- screen_settings.dmPelsHeight = mode.height;
- screen_settings.dmBitsPerPel = mode.bits_per_pixel;
- screen_settings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
-
- if (ChangeDisplaySettingsW(&screen_settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
- if (MessageBoxW(NULL, L"The requested fullscreen mode is not supported by\n"
- L"your video card. Use windowed mode instead?",
- L"",
- MB_YESNO|MB_ICONEXCLAMATION) == IDYES) {
- window_flags &= ~gbWindow_Fullscreen;
- } else {
- mode = gb_video_mode_get_desktop();
- screen_settings.dmPelsWidth = mode.width;
- screen_settings.dmPelsHeight = mode.height;
- screen_settings.dmBitsPerPel = mode.bits_per_pixel;
- ChangeDisplaySettingsW(&screen_settings, CDS_FULLSCREEN);
- }
- }
- }
-
-
- // ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
- // style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
-
- style |= WS_VISIBLE;
-
- if (window_flags & gbWindow_Hidden) style &= ~WS_VISIBLE;
- if (window_flags & gbWindow_Resizable) style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
- if (window_flags & gbWindow_Maximized) style |= WS_MAXIMIZE;
- if (window_flags & gbWindow_Minimized) style |= WS_MINIMIZE;
-
- // NOTE(bill): Completely ignore the given mode and just change it
- if (window_flags & gbWindow_FullscreenDesktop) {
- mode = gb_video_mode_get_desktop();
- }
-
- if ((window_flags & gbWindow_Fullscreen) || (window_flags & gbWindow_Borderless)) {
- style |= WS_POPUP;
- } else {
- style |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
- }
-
-
- wr.left = 0;
- wr.top = 0;
- wr.right = mode.width;
- wr.bottom = mode.height;
- AdjustWindowRect(&wr, style, false);
-
- p->window_flags = window_flags;
- p->window_handle = CreateWindowExW(ex_style,
- wc.lpszClassName,
- cast(wchar_t const *)gb_utf8_to_ucs2(title_buffer, gb_size_of(title_buffer), window_title),
- style,
- CW_USEDEFAULT, CW_USEDEFAULT,
- wr.right - wr.left, wr.bottom - wr.top,
- 0, 0,
- GetModuleHandleW(NULL),
- NULL);
-
- if (!p->window_handle) {
- MessageBoxW(NULL, L"Window creation failed", L"Error", MB_OK|MB_ICONEXCLAMATION);
- return false;
- }
-
- p->win32_dc = GetDC(cast(HWND)p->window_handle);
-
- p->renderer_type = type;
- switch (p->renderer_type) {
- case gbRenderer_Opengl: {
- wglCreateContextAttribsARB_Proc *wglCreateContextAttribsARB;
- i32 attribs[8] = {0};
- isize c = 0;
-
- PIXELFORMATDESCRIPTOR pfd = {gb_size_of(PIXELFORMATDESCRIPTOR)};
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = 32;
- pfd.cAlphaBits = 8;
- pfd.cDepthBits = 24;
- pfd.cStencilBits = 8;
- pfd.iLayerType = PFD_MAIN_PLANE;
-
- SetPixelFormat(cast(HDC)p->win32_dc, ChoosePixelFormat(cast(HDC)p->win32_dc, &pfd), NULL);
- p->opengl.context = cast(void *)wglCreateContext(cast(HDC)p->win32_dc);
- wglMakeCurrent(cast(HDC)p->win32_dc, cast(HGLRC)p->opengl.context);
-
- if (p->opengl.major > 0) {
- attribs[c++] = 0x2091; // WGL_CONTEXT_MAJOR_VERSION_ARB
- attribs[c++] = gb_max(p->opengl.major, 1);
- }
- if (p->opengl.major > 0 && p->opengl.minor >= 0) {
- attribs[c++] = 0x2092; // WGL_CONTEXT_MINOR_VERSION_ARB
- attribs[c++] = gb_max(p->opengl.minor, 0);
- }
-
- if (p->opengl.core) {
- attribs[c++] = 0x9126; // WGL_CONTEXT_PROFILE_MASK_ARB
- attribs[c++] = 0x0001; // WGL_CONTEXT_CORE_PROFILE_BIT_ARB
- } else if (p->opengl.compatible) {
- attribs[c++] = 0x9126; // WGL_CONTEXT_PROFILE_MASK_ARB
- attribs[c++] = 0x0002; // WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
- }
- attribs[c++] = 0; // NOTE(bill): tells the proc that this is the end of attribs
-
- wglCreateContextAttribsARB = cast(wglCreateContextAttribsARB_Proc *)wglGetProcAddress("wglCreateContextAttribsARB");
- if (wglCreateContextAttribsARB) {
- HGLRC rc = cast(HGLRC)wglCreateContextAttribsARB(p->win32_dc, 0, attribs);
- if (rc && wglMakeCurrent(cast(HDC)p->win32_dc, rc)) {
- p->opengl.context = rc;
- } else {
- // TODO(bill): Handle errors from GetLastError
- // ERROR_INVALID_VERSION_ARB 0x2095
- // ERROR_INVALID_PROFILE_ARB 0x2096
- }
- }
-
- } break;
-
- case gbRenderer_Software:
- gb__platform_resize_dib_section(p, mode.width, mode.height);
- break;
-
- default:
- GB_PANIC("Unknown window type");
- break;
- }
-
- SetForegroundWindow(cast(HWND)p->window_handle);
- SetFocus(cast(HWND)p->window_handle);
- SetWindowLongPtrW(cast(HWND)p->window_handle, GWLP_USERDATA, cast(LONG_PTR)p);
-
- p->window_width = mode.width;
- p->window_height = mode.height;
-
- if (p->renderer_type == gbRenderer_Opengl) {
- p->opengl.dll_handle = gb_dll_load("opengl32.dll");
- }
-
- { // Load XInput
- // TODO(bill): What other dlls should I look for?
- gbDllHandle xinput_library = gb_dll_load("xinput1_4.dll");
- p->xinput.get_state = gbXInputGetState_Stub;
- p->xinput.set_state = gbXInputSetState_Stub;
-
- if (!xinput_library) xinput_library = gb_dll_load("xinput9_1_0.dll");
- if (!xinput_library) xinput_library = gb_dll_load("xinput1_3.dll");
- if (!xinput_library) {
- // TODO(bill): Proper Diagnostic
- gb_printf_err("XInput could not be loaded. Controllers will not work!\n");
- } else {
- p->xinput.get_state = cast(gbXInputGetStateProc *)gb_dll_proc_address(xinput_library, "XInputGetState");
- p->xinput.set_state = cast(gbXInputSetStateProc *)gb_dll_proc_address(xinput_library, "XInputSetState");
- }
- }
-
- // Init keys
- gb_zero_array(p->keys, gb_count_of(p->keys));
-
- p->is_initialized = true;
- return true;
-}
-
-gb_inline b32 gb_platform_init_with_software(gbPlatform *p, char const *window_title,
- i32 width, i32 height, u32 window_flags) {
- gbVideoMode mode;
- mode.width = width;
- mode.height = height;
- mode.bits_per_pixel = 32;
- return gb__platform_init(p, window_title, mode, gbRenderer_Software, window_flags);
-}
-
-gb_inline b32 gb_platform_init_with_opengl(gbPlatform *p, char const *window_title,
- i32 width, i32 height, u32 window_flags, i32 major, i32 minor, b32 core, b32 compatible) {
- gbVideoMode mode;
- mode.width = width;
- mode.height = height;
- mode.bits_per_pixel = 32;
- p->opengl.major = major;
- p->opengl.minor = minor;
- p->opengl.core = cast(b16)core;
- p->opengl.compatible = cast(b16)compatible;
- return gb__platform_init(p, window_title, mode, gbRenderer_Opengl, window_flags);
-}
-
-#ifndef _XINPUT_H_
-typedef struct _XINPUT_GAMEPAD {
- u16 wButtons;
- u8 bLeftTrigger;
- u8 bRightTrigger;
- u16 sThumbLX;
- u16 sThumbLY;
- u16 sThumbRX;
- u16 sThumbRY;
-} XINPUT_GAMEPAD;
-
-typedef struct _XINPUT_STATE {
- DWORD dwPacketNumber;
- XINPUT_GAMEPAD Gamepad;
-} XINPUT_STATE;
-
-typedef struct _XINPUT_VIBRATION {
- u16 wLeftMotorSpeed;
- u16 wRightMotorSpeed;
-} XINPUT_VIBRATION;
-
-#define XINPUT_GAMEPAD_DPAD_UP 0x00000001
-#define XINPUT_GAMEPAD_DPAD_DOWN 0x00000002
-#define XINPUT_GAMEPAD_DPAD_LEFT 0x00000004
-#define XINPUT_GAMEPAD_DPAD_RIGHT 0x00000008
-#define XINPUT_GAMEPAD_START 0x00000010
-#define XINPUT_GAMEPAD_BACK 0x00000020
-#define XINPUT_GAMEPAD_LEFT_THUMB 0x00000040
-#define XINPUT_GAMEPAD_RIGHT_THUMB 0x00000080
-#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
-#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
-#define XINPUT_GAMEPAD_A 0x1000
-#define XINPUT_GAMEPAD_B 0x2000
-#define XINPUT_GAMEPAD_X 0x4000
-#define XINPUT_GAMEPAD_Y 0x8000
-#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
-#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
-#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
-#endif
-
-#ifndef XUSER_MAX_COUNT
-#define XUSER_MAX_COUNT 4
-#endif
-
-void gb_platform_update(gbPlatform *p) {
- isize i;
-
- { // NOTE(bill): Set window state
- // TODO(bill): Should this be moved to gb__win32_window_callback ?
- RECT window_rect;
- i32 x, y, w, h;
-
- GetClientRect(cast(HWND)p->window_handle, &window_rect);
- x = window_rect.left;
- y = window_rect.top;
- w = window_rect.right - window_rect.left;
- h = window_rect.bottom - window_rect.top;
-
- if ((p->window_width != w) || (p->window_height != h)) {
- if (p->renderer_type == gbRenderer_Software) {
- gb__platform_resize_dib_section(p, w, h);
- }
- }
-
-
- p->window_x = x;
- p->window_y = y;
- p->window_width = w;
- p->window_height = h;
- GB_MASK_SET(p->window_flags, IsIconic(cast(HWND)p->window_handle) != 0, gbWindow_Minimized);
-
- p->window_has_focus = GetFocus() == cast(HWND)p->window_handle;
- }
-
- { // NOTE(bill): Set mouse position
- POINT mouse_pos;
- DWORD win_button_id[gbMouseButton_Count] = {
- VK_LBUTTON,
- VK_MBUTTON,
- VK_RBUTTON,
- VK_XBUTTON1,
- VK_XBUTTON2,
- };
-
- // NOTE(bill): This needs to be GetAsyncKeyState as RAWMOUSE doesn't aways work for some odd reason
- // TODO(bill): Try and get RAWMOUSE to work for key presses
- for (i = 0; i < gbMouseButton_Count; i++) {
- gb_key_state_update(p->mouse_buttons+i, GetAsyncKeyState(win_button_id[i]) < 0);
- }
-
- GetCursorPos(&mouse_pos);
- ScreenToClient(cast(HWND)p->window_handle, &mouse_pos);
- {
- i32 x = mouse_pos.x;
- i32 y = p->window_height-1 - mouse_pos.y;
- p->mouse_dx = x - p->mouse_x;
- p->mouse_dy = y - p->mouse_y;
- p->mouse_x = x;
- p->mouse_y = y;
- }
-
- if (p->mouse_clip) {
- b32 update = false;
- i32 x = p->mouse_x;
- i32 y = p->mouse_y;
- if (p->mouse_x < 0) {
- x = 0;
- update = true;
- } else if (p->mouse_y > p->window_height-1) {
- y = p->window_height-1;
- update = true;
- }
-
- if (p->mouse_y < 0) {
- y = 0;
- update = true;
- } else if (p->mouse_x > p->window_width-1) {
- x = p->window_width-1;
- update = true;
- }
-
- if (update) {
- gb_platform_set_mouse_position(p, x, y);
- }
- }
-
-
- }
-
-
- // NOTE(bill): Set Key/Button states
- if (p->window_has_focus) {
- p->char_buffer_count = 0; // TODO(bill): Reset buffer count here or else where?
-
- // NOTE(bill): Need to update as the keys only get updates on events
- for (i = 0; i < gbKey_Count; i++) {
- b32 is_down = (p->keys[i] & gbKeyState_Down) != 0;
- gb_key_state_update(&p->keys[i], is_down);
- }
-
- p->key_modifiers.control = p->keys[gbKey_Lcontrol] | p->keys[gbKey_Rcontrol];
- p->key_modifiers.alt = p->keys[gbKey_Lalt] | p->keys[gbKey_Ralt];
- p->key_modifiers.shift = p->keys[gbKey_Lshift] | p->keys[gbKey_Rshift];
-
- }
-
- { // NOTE(bill): Set Controller states
- isize max_controller_count = XUSER_MAX_COUNT;
- if (max_controller_count > gb_count_of(p->game_controllers)) {
- max_controller_count = gb_count_of(p->game_controllers);
- }
-
- for (i = 0; i < max_controller_count; i++) {
- gbGameController *controller = &p->game_controllers[i];
- XINPUT_STATE controller_state = {0};
- if (p->xinput.get_state(cast(DWORD)i, &controller_state) != 0) {
- // NOTE(bill): The controller is not available
- controller->is_connected = false;
- } else {
- // NOTE(bill): This controller is plugged in
- // TODO(bill): See if ControllerState.dwPacketNumber increments too rapidly
- XINPUT_GAMEPAD *pad = &controller_state.Gamepad;
-
- controller->is_connected = true;
-
- // TODO(bill): This is a square deadzone, check XInput to verify that the deadzone is "round" and do round deadzone processing.
- controller->axes[gbControllerAxis_LeftX] = gb__process_xinput_stick_value(pad->sThumbLX, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
- controller->axes[gbControllerAxis_LeftY] = gb__process_xinput_stick_value(pad->sThumbLY, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
- controller->axes[gbControllerAxis_RightX] = gb__process_xinput_stick_value(pad->sThumbRX, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
- controller->axes[gbControllerAxis_RightY] = gb__process_xinput_stick_value(pad->sThumbRY, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
-
- controller->axes[gbControllerAxis_LeftTrigger] = cast(f32)pad->bLeftTrigger / 255.0f;
- controller->axes[gbControllerAxis_RightTrigger] = cast(f32)pad->bRightTrigger / 255.0f;
-
-
- if ((controller->axes[gbControllerAxis_LeftX] != 0.0f) ||
- (controller->axes[gbControllerAxis_LeftY] != 0.0f)) {
- controller->is_analog = true;
- }
-
- #define GB__PROCESS_DIGITAL_BUTTON(button_type, xinput_button) \
- gb_key_state_update(&controller->buttons[button_type], (pad->wButtons & xinput_button) == xinput_button)
-
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_A, XINPUT_GAMEPAD_A);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_B, XINPUT_GAMEPAD_B);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_X, XINPUT_GAMEPAD_X);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Y, XINPUT_GAMEPAD_Y);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_LeftShoulder, XINPUT_GAMEPAD_LEFT_SHOULDER);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_RightShoulder, XINPUT_GAMEPAD_RIGHT_SHOULDER);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Start, XINPUT_GAMEPAD_START);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Back, XINPUT_GAMEPAD_BACK);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Left, XINPUT_GAMEPAD_DPAD_LEFT);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Right, XINPUT_GAMEPAD_DPAD_RIGHT);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Down, XINPUT_GAMEPAD_DPAD_DOWN);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_Up, XINPUT_GAMEPAD_DPAD_UP);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_LeftThumb, XINPUT_GAMEPAD_LEFT_THUMB);
- GB__PROCESS_DIGITAL_BUTTON(gbControllerButton_RightThumb, XINPUT_GAMEPAD_RIGHT_THUMB);
- #undef GB__PROCESS_DIGITAL_BUTTON
- }
- }
- }
-
- { // NOTE(bill): Process pending messages
- MSG message;
- for (;;) {
- BOOL is_okay = PeekMessageW(&message, 0, 0, 0, PM_REMOVE);
- if (!is_okay) break;
-
- switch (message.message) {
- case WM_QUIT:
- p->quit_requested = true;
- break;
-
- default:
- TranslateMessage(&message);
- DispatchMessageW(&message);
- break;
- }
- }
- }
-}
-
-void gb_platform_display(gbPlatform *p) {
- if (p->renderer_type == gbRenderer_Opengl) {
- SwapBuffers(cast(HDC)p->win32_dc);
- } else if (p->renderer_type == gbRenderer_Software) {
- StretchDIBits(cast(HDC)p->win32_dc,
- 0, 0, p->window_width, p->window_height,
- 0, 0, p->window_width, p->window_height,
- p->sw_framebuffer.memory,
- &p->sw_framebuffer.win32_bmi,
- DIB_RGB_COLORS, SRCCOPY);
- } else {
- GB_PANIC("Invalid window rendering type");
- }
-
- {
- f64 prev_time = p->curr_time;
- f64 curr_time = gb_time_now();
- p->dt_for_frame = curr_time - prev_time;
- p->curr_time = curr_time;
- }
-}
-
-
-void gb_platform_destroy(gbPlatform *p) {
- if (p->renderer_type == gbRenderer_Opengl) {
- wglDeleteContext(cast(HGLRC)p->opengl.context);
- } else if (p->renderer_type == gbRenderer_Software) {
- gb_vm_free(gb_virtual_memory(p->sw_framebuffer.memory, p->sw_framebuffer.memory_size));
- }
-
- DestroyWindow(cast(HWND)p->window_handle);
-}
-
-void gb_platform_show_cursor(gbPlatform *p, b32 show) {
- gb_unused(p);
- ShowCursor(show);
-}
-
-void gb_platform_set_mouse_position(gbPlatform *p, i32 x, i32 y) {
- POINT point;
- point.x = cast(LONG)x;
- point.y = cast(LONG)(p->window_height-1 - y);
- ClientToScreen(cast(HWND)p->window_handle, &point);
- SetCursorPos(point.x, point.y);
-
- p->mouse_x = point.x;
- p->mouse_y = p->window_height-1 - point.y;
-}
-
-
-
-void gb_platform_set_controller_vibration(gbPlatform *p, isize index, f32 left_motor, f32 right_motor) {
- if (gb_is_between(index, 0, GB_MAX_GAME_CONTROLLER_COUNT-1)) {
- XINPUT_VIBRATION vibration = {0};
- left_motor = gb_clamp01(left_motor);
- right_motor = gb_clamp01(right_motor);
- vibration.wLeftMotorSpeed = cast(WORD)(65535 * left_motor);
- vibration.wRightMotorSpeed = cast(WORD)(65535 * right_motor);
-
- p->xinput.set_state(cast(DWORD)index, &vibration);
- }
-}
-
-
-void gb_platform_set_window_position(gbPlatform *p, i32 x, i32 y) {
- RECT rect;
- i32 width, height;
-
- GetClientRect(cast(HWND)p->window_handle, &rect);
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
- MoveWindow(cast(HWND)p->window_handle, x, y, width, height, false);
-}
-
-void gb_platform_set_window_title(gbPlatform *p, char const *title, ...) {
- u16 buffer[256] = {0};
- char str[512] = {0};
- va_list va;
- va_start(va, title);
- gb_snprintf_va(str, gb_size_of(str), title, va);
- va_end(va);
-
- if (str[0] != '\0') {
- SetWindowTextW(cast(HWND)p->window_handle, cast(wchar_t const *)gb_utf8_to_ucs2(buffer, gb_size_of(buffer), str));
- }
-}
-
-void gb_platform_toggle_fullscreen(gbPlatform *p, b32 fullscreen_desktop) {
- // NOTE(bill): From the man himself, Raymond Chen! (Modified for my need.)
- HWND handle = cast(HWND)p->window_handle;
- DWORD style = cast(DWORD)GetWindowLongW(handle, GWL_STYLE);
- WINDOWPLACEMENT placement;
-
- if (style & WS_OVERLAPPEDWINDOW) {
- MONITORINFO monitor_info = {gb_size_of(monitor_info)};
- if (GetWindowPlacement(handle, &placement) &&
- GetMonitorInfoW(MonitorFromWindow(handle, 1), &monitor_info)) {
- style &= ~WS_OVERLAPPEDWINDOW;
- if (fullscreen_desktop) {
- style &= ~WS_CAPTION;
- style |= WS_POPUP;
- }
- SetWindowLongW(handle, GWL_STYLE, style);
- SetWindowPos(handle, HWND_TOP,
- monitor_info.rcMonitor.left, monitor_info.rcMonitor.top,
- monitor_info.rcMonitor.right - monitor_info.rcMonitor.left,
- monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top,
- SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
-
- if (fullscreen_desktop) {
- p->window_flags |= gbWindow_FullscreenDesktop;
- } else {
- p->window_flags |= gbWindow_Fullscreen;
- }
- }
- } else {
- style &= ~WS_POPUP;
- style |= WS_OVERLAPPEDWINDOW | WS_CAPTION;
- SetWindowLongW(handle, GWL_STYLE, style);
- SetWindowPlacement(handle, &placement);
- SetWindowPos(handle, 0, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
- SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
-
- p->window_flags &= ~gbWindow_Fullscreen;
- }
-}
-
-void gb_platform_toggle_borderless(gbPlatform *p) {
- HWND handle = cast(HWND)p->window_handle;
- DWORD style = GetWindowLongW(handle, GWL_STYLE);
- b32 is_borderless = (style & WS_POPUP) != 0;
-
- GB_MASK_SET(style, is_borderless, WS_OVERLAPPEDWINDOW | WS_CAPTION);
- GB_MASK_SET(style, !is_borderless, WS_POPUP);
-
- SetWindowLongW(handle, GWL_STYLE, style);
-
- GB_MASK_SET(p->window_flags, !is_borderless, gbWindow_Borderless);
-}
-
-
-
-gb_inline void gb_platform_make_opengl_context_current(gbPlatform *p) {
- if (p->renderer_type == gbRenderer_Opengl) {
- wglMakeCurrent(cast(HDC)p->win32_dc, cast(HGLRC)p->opengl.context);
- }
-}
-
-gb_inline void gb_platform_show_window(gbPlatform *p) {
- ShowWindow(cast(HWND)p->window_handle, SW_SHOW);
- p->window_flags &= ~gbWindow_Hidden;
-}
-
-gb_inline void gb_platform_hide_window(gbPlatform *p) {
- ShowWindow(cast(HWND)p->window_handle, SW_HIDE);
- p->window_flags |= gbWindow_Hidden;
-}
-
-gb_inline gbVideoMode gb_video_mode_get_desktop(void) {
- DEVMODEW win32_mode = {gb_size_of(win32_mode)};
- EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &win32_mode);
- return gb_video_mode(win32_mode.dmPelsWidth, win32_mode.dmPelsHeight, win32_mode.dmBitsPerPel);
-}
-
-isize gb_video_mode_get_fullscreen_modes(gbVideoMode *modes, isize max_mode_count) {
- DEVMODEW win32_mode = {gb_size_of(win32_mode)};
- i32 count;
- for (count = 0;
- count < max_mode_count && EnumDisplaySettingsW(NULL, count, &win32_mode);
- count++) {
- modes[count] = gb_video_mode(win32_mode.dmPelsWidth, win32_mode.dmPelsHeight, win32_mode.dmBitsPerPel);
- }
-
- gb_sort_array(modes, count, gb_video_mode_dsc_cmp);
- return count;
-}
-
-
-
-b32 gb_platform_has_clipboard_text(gbPlatform *p) {
- b32 result = false;
-
- if (IsClipboardFormatAvailable(1/*CF_TEXT*/) &&
- OpenClipboard(cast(HWND)p->window_handle)) {
- HANDLE mem = GetClipboardData(1/*CF_TEXT*/);
- if (mem) {
- char *str = cast(char *)GlobalLock(mem);
- if (str && str[0] != '\0') {
- result = true;
- }
- GlobalUnlock(mem);
- } else {
- return false;
- }
-
- CloseClipboard();
- }
-
- return result;
-}
-
-// TODO(bill): Handle UTF-8
-void gb_platform_set_clipboard_text(gbPlatform *p, char const *str) {
- if (OpenClipboard(cast(HWND)p->window_handle)) {
- isize i, len = gb_strlen(str)+1;
-
- HANDLE mem = cast(HANDLE)GlobalAlloc(0x0002/*GMEM_MOVEABLE*/, len);
- if (mem) {
- char *dst = cast(char *)GlobalLock(mem);
- if (dst) {
- for (i = 0; str[i]; i++) {
- // TODO(bill): Does this cause a buffer overflow?
- // NOTE(bill): Change \n to \r\n 'cause windows
- if (str[i] == '\n' && (i == 0 || str[i-1] != '\r')) {
- *dst++ = '\r';
- }
- *dst++ = str[i];
- }
- *dst = 0;
- }
- GlobalUnlock(mem);
- }
-
- EmptyClipboard();
- if (!SetClipboardData(1/*CF_TEXT*/, mem)) {
- return;
- }
- CloseClipboard();
- }
-}
-
-// TODO(bill): Handle UTF-8
-char *gb_platform_get_clipboard_text(gbPlatform *p, gbAllocator a) {
- char *text = NULL;
-
- if (IsClipboardFormatAvailable(1/*CF_TEXT*/) &&
- OpenClipboard(cast(HWND)p->window_handle)) {
- HANDLE mem = GetClipboardData(1/*CF_TEXT*/);
- if (mem) {
- char *str = cast(char *)GlobalLock(mem);
- text = gb_alloc_str(a, str);
- GlobalUnlock(mem);
- } else {
- return NULL;
- }
-
- CloseClipboard();
- }
-
- return text;
-}
-
-#elif defined(GB_SYSTEM_OSX)
-
-#include <CoreGraphics/CoreGraphics.h>
-#include <objc/objc.h>
-#include <objc/message.h>
-#include <objc/NSObjCRuntime.h>
-
-#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
- #define NSIntegerEncoding "q"
- #define NSUIntegerEncoding "L"
-#else
- #define NSIntegerEncoding "i"
- #define NSUIntegerEncoding "I"
-#endif
-
-#ifdef __OBJC__
- #import <Cocoa/Cocoa.h>
-#else
- typedef CGPoint NSPoint;
- typedef CGSize NSSize;
- typedef CGRect NSRect;
-
- extern id NSApp;
- extern id const NSDefaultRunLoopMode;
-#endif
-
-#if defined(__OBJC__) && __has_feature(objc_arc)
-#error TODO(bill): Cannot compile as objective-c code just yet!
-#endif
-
-// ABI is a bit different between platforms
-#ifdef __arm64__
-#define abi_objc_msgSend_stret objc_msgSend
-#else
-#define abi_objc_msgSend_stret objc_msgSend_stret
-#endif
-#ifdef __i386__
-#define abi_objc_msgSend_fpret objc_msgSend_fpret
-#else
-#define abi_objc_msgSend_fpret objc_msgSend
-#endif
-
-#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend)
-#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend)
-#define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend)
-#define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend)
-#define objc_msgSend_id_char_const ((id (*)(id, SEL, char const *))objc_msgSend)
-
-gb_internal NSUInteger gb__osx_application_should_terminate(id self, SEL _sel, id sender) {
- // NOTE(bill): Do nothing
- return 0;
-}
-
-gb_internal void gb__osx_window_will_close(id self, SEL _sel, id notification) {
- NSUInteger value = true;
- object_setInstanceVariable(self, "closed", cast(void *)value);
-}
-
-gb_internal void gb__osx_window_did_become_key(id self, SEL _sel, id notification) {
- gbPlatform *p = NULL;
- object_getInstanceVariable(self, "gbPlatform", cast(void **)&p);
- if (p) {
- // TODO(bill):
- }
-}
-
-b32 gb__platform_init(gbPlatform *p, char const *window_title, gbVideoMode mode, gbRendererType type, u32 window_flags) {
- if (p->is_initialized) {
- return true;
- }
- // Init Platform
- { // Initial OSX State
- Class appDelegateClass;
- b32 resultAddProtoc, resultAddMethod;
- id dgAlloc, dg, menubarAlloc, menubar;
- id appMenuItemAlloc, appMenuItem;
- id appMenuAlloc, appMenu;
-
- #if defined(ARC_AVAILABLE)
- #error TODO(bill): This code should be compiled as C for now
- #else
- id poolAlloc = objc_msgSend_id(cast(id)objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
- p->osx_autorelease_pool = objc_msgSend_id(poolAlloc, sel_registerName("init"));
- #endif
-
- objc_msgSend_id(cast(id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
- ((void (*)(id, SEL, NSInteger))objc_msgSend)(NSApp, sel_registerName("setActivationPolicy:"), 0);
-
- appDelegateClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
- resultAddProtoc = class_addProtocol(appDelegateClass, objc_getProtocol("NSApplicationDelegate"));
- assert(resultAddProtoc);
- resultAddMethod = class_addMethod(appDelegateClass, sel_registerName("applicationShouldTerminate:"), cast(IMP)gb__osx_application_should_terminate, NSUIntegerEncoding "@:@");
- assert(resultAddMethod);
- dgAlloc = objc_msgSend_id(cast(id)appDelegateClass, sel_registerName("alloc"));
- dg = objc_msgSend_id(dgAlloc, sel_registerName("init"));
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(dg, sel_registerName("autorelease"));
- #endif
-
- objc_msgSend_void_id(NSApp, sel_registerName("setDelegate:"), dg);
- objc_msgSend_void(NSApp, sel_registerName("finishLaunching"));
-
- menubarAlloc = objc_msgSend_id(cast(id)objc_getClass("NSMenu"), sel_registerName("alloc"));
- menubar = objc_msgSend_id(menubarAlloc, sel_registerName("init"));
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(menubar, sel_registerName("autorelease"));
- #endif
-
- appMenuItemAlloc = objc_msgSend_id(cast(id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
- appMenuItem = objc_msgSend_id(appMenuItemAlloc, sel_registerName("init"));
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(appMenuItem, sel_registerName("autorelease"));
- #endif
-
- objc_msgSend_void_id(menubar, sel_registerName("addItem:"), appMenuItem);
- ((id (*)(id, SEL, id))objc_msgSend)(NSApp, sel_registerName("setMainMenu:"), menubar);
-
- appMenuAlloc = objc_msgSend_id(cast(id)objc_getClass("NSMenu"), sel_registerName("alloc"));
- appMenu = objc_msgSend_id(appMenuAlloc, sel_registerName("init"));
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(appMenu, sel_registerName("autorelease"));
- #endif
-
- {
- id processInfo = objc_msgSend_id(cast(id)objc_getClass("NSProcessInfo"), sel_registerName("processInfo"));
- id appName = objc_msgSend_id(processInfo, sel_registerName("processName"));
-
- id quitTitlePrefixString = objc_msgSend_id_char_const(cast(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "Quit ");
- id quitTitle = ((id (*)(id, SEL, id))objc_msgSend)(quitTitlePrefixString, sel_registerName("stringByAppendingString:"), appName);
-
- id quitMenuItemKey = objc_msgSend_id_char_const(cast(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "q");
- id quitMenuItemAlloc = objc_msgSend_id(cast(id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
- id quitMenuItem = ((id (*)(id, SEL, id, SEL, id))objc_msgSend)(quitMenuItemAlloc, sel_registerName("initWithTitle:action:keyEquivalent:"), quitTitle, sel_registerName("terminate:"), quitMenuItemKey);
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(quitMenuItem, sel_registerName("autorelease"));
- #endif
-
- objc_msgSend_void_id(appMenu, sel_registerName("addItem:"), quitMenuItem);
- objc_msgSend_void_id(appMenuItem, sel_registerName("setSubmenu:"), appMenu);
- }
- }
-
- { // Init Window
- NSRect rect = {{0, 0}, {cast(CGFloat)mode.width, cast(CGFloat)mode.height}};
- id windowAlloc, window, wdgAlloc, wdg, contentView, titleString;
- Class WindowDelegateClass;
- b32 resultAddProtoc, resultAddIvar, resultAddMethod;
-
- windowAlloc = objc_msgSend_id(cast(id)objc_getClass("NSWindow"), sel_registerName("alloc"));
- window = ((id (*)(id, SEL, NSRect, NSUInteger, NSUInteger, BOOL))objc_msgSend)(windowAlloc, sel_registerName("initWithContentRect:styleMask:backing:defer:"), rect, 15, 2, NO);
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(window, sel_registerName("autorelease"));
- #endif
-
- // when we are not using ARC, than window will be added to autorelease pool
- // so if we close it by hand (pressing red button), we don't want it to be released for us
- // so it will be released by autorelease pool later
- objc_msgSend_void_bool(window, sel_registerName("setReleasedWhenClosed:"), NO);
-
- WindowDelegateClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "WindowDelegate", 0);
- resultAddProtoc = class_addProtocol(WindowDelegateClass, objc_getProtocol("NSWindowDelegate"));
- GB_ASSERT(resultAddProtoc);
- resultAddIvar = class_addIvar(WindowDelegateClass, "closed", gb_size_of(NSUInteger), rint(log2(gb_size_of(NSUInteger))), NSUIntegerEncoding);
- GB_ASSERT(resultAddIvar);
- resultAddIvar = class_addIvar(WindowDelegateClass, "gbPlatform", gb_size_of(void *), rint(log2(gb_size_of(void *))), "ˆv");
- GB_ASSERT(resultAddIvar);
- resultAddMethod = class_addMethod(WindowDelegateClass, sel_registerName("windowWillClose:"), cast(IMP)gb__osx_window_will_close, "v@:@");
- GB_ASSERT(resultAddMethod);
- resultAddMethod = class_addMethod(WindowDelegateClass, sel_registerName("windowDidBecomeKey:"), cast(IMP)gb__osx_window_did_become_key, "v@:@");
- GB_ASSERT(resultAddMethod);
- wdgAlloc = objc_msgSend_id(cast(id)WindowDelegateClass, sel_registerName("alloc"));
- wdg = objc_msgSend_id(wdgAlloc, sel_registerName("init"));
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(wdg, sel_registerName("autorelease"));
- #endif
-
- objc_msgSend_void_id(window, sel_registerName("setDelegate:"), wdg);
-
- contentView = objc_msgSend_id(window, sel_registerName("contentView"));
-
- {
- NSPoint point = {20, 20};
- ((void (*)(id, SEL, NSPoint))objc_msgSend)(window, sel_registerName("cascadeTopLeftFromPoint:"), point);
- }
-
- titleString = objc_msgSend_id_char_const(cast(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), window_title);
- objc_msgSend_void_id(window, sel_registerName("setTitle:"), titleString);
-
- if (type == gbRenderer_Opengl) {
- // TODO(bill): Make sure this works correctly
- u32 opengl_hex_version = (p->opengl.major << 12) | (p->opengl.minor << 8);
- u32 gl_attribs[] = {
- 8, 24, // NSOpenGLPFAColorSize, 24,
- 11, 8, // NSOpenGLPFAAlphaSize, 8,
- 5, // NSOpenGLPFADoubleBuffer,
- 73, // NSOpenGLPFAAccelerated,
- //72, // NSOpenGLPFANoRecovery,
- //55, 1, // NSOpenGLPFASampleBuffers, 1,
- //56, 4, // NSOpenGLPFASamples, 4,
- 99, opengl_hex_version, // NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
- 0
- };
-
- id pixel_format_alloc, pixel_format;
- id opengl_context_alloc, opengl_context;
-
- pixel_format_alloc = objc_msgSend_id(cast(id)objc_getClass("NSOpenGLPixelFormat"), sel_registerName("alloc"));
- pixel_format = ((id (*)(id, SEL, const uint32_t*))objc_msgSend)(pixel_format_alloc, sel_registerName("initWithAttributes:"), gl_attribs);
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(pixel_format, sel_registerName("autorelease"));
- #endif
-
- opengl_context_alloc = objc_msgSend_id(cast(id)objc_getClass("NSOpenGLContext"), sel_registerName("alloc"));
- opengl_context = ((id (*)(id, SEL, id, id))objc_msgSend)(opengl_context_alloc, sel_registerName("initWithFormat:shareContext:"), pixel_format, nil);
- #ifndef ARC_AVAILABLE
- objc_msgSend_void(opengl_context, sel_registerName("autorelease"));
- #endif
-
- objc_msgSend_void_id(opengl_context, sel_registerName("setView:"), contentView);
- objc_msgSend_void_id(window, sel_registerName("makeKeyAndOrderFront:"), window);
- objc_msgSend_void_bool(window, sel_registerName("setAcceptsMouseMovedEvents:"), YES);
-
-
- p->window_handle = cast(void *)window;
- p->opengl.context = cast(void *)opengl_context;
- } else {
- GB_PANIC("TODO(bill): Software rendering");
- }
-
- {
- id blackColor = objc_msgSend_id(cast(id)objc_getClass("NSColor"), sel_registerName("blackColor"));
- objc_msgSend_void_id(window, sel_registerName("setBackgroundColor:"), blackColor);
- objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), YES);
- }
- object_setInstanceVariable(wdg, "gbPlatform", cast(void *)p);
-
- p->is_initialized = true;
- }
-
- return true;
-}
-
-// NOTE(bill): Software rendering
-b32 gb_platform_init_with_software(gbPlatform *p, char const *window_title, i32 width, i32 height, u32 window_flags) {
- GB_PANIC("TODO(bill): Software rendering in not yet implemented on OS X\n");
- return gb__platform_init(p, window_title, gb_video_mode(width, height, 32), gbRenderer_Software, window_flags);
-}
-// NOTE(bill): OpenGL Rendering
-b32 gb_platform_init_with_opengl(gbPlatform *p, char const *window_title, i32 width, i32 height, u32 window_flags,
- i32 major, i32 minor, b32 core, b32 compatible) {
-
- p->opengl.major = major;
- p->opengl.minor = minor;
- p->opengl.core = core;
- p->opengl.compatible = compatible;
- return gb__platform_init(p, window_title, gb_video_mode(width, height, 32), gbRenderer_Opengl, window_flags);
-}
-
-// NOTE(bill): Reverse engineering can be fun!!!
-gb_internal gbKeyType gb__osx_from_key_code(u16 key_code) {
- switch (key_code) {
- default: return gbKey_Unknown;
- // NOTE(bill): WHO THE FUCK DESIGNED THIS VIRTUAL KEY CODE SYSTEM?!
- // THEY ARE FUCKING IDIOTS!
- case 0x1d: return gbKey_0;
- case 0x12: return gbKey_1;
- case 0x13: return gbKey_2;
- case 0x14: return gbKey_3;
- case 0x15: return gbKey_4;
- case 0x17: return gbKey_5;
- case 0x16: return gbKey_6;
- case 0x1a: return gbKey_7;
- case 0x1c: return gbKey_8;
- case 0x19: return gbKey_9;
-
- case 0x00: return gbKey_A;
- case 0x0b: return gbKey_B;
- case 0x08: return gbKey_C;
- case 0x02: return gbKey_D;
- case 0x0e: return gbKey_E;
- case 0x03: return gbKey_F;
- case 0x05: return gbKey_G;
- case 0x04: return gbKey_H;
- case 0x22: return gbKey_I;
- case 0x26: return gbKey_J;
- case 0x28: return gbKey_K;
- case 0x25: return gbKey_L;
- case 0x2e: return gbKey_M;
- case 0x2d: return gbKey_N;
- case 0x1f: return gbKey_O;
- case 0x23: return gbKey_P;
- case 0x0c: return gbKey_Q;
- case 0x0f: return gbKey_R;
- case 0x01: return gbKey_S;
- case 0x11: return gbKey_T;
- case 0x20: return gbKey_U;
- case 0x09: return gbKey_V;
- case 0x0d: return gbKey_W;
- case 0x07: return gbKey_X;
- case 0x10: return gbKey_Y;
- case 0x06: return gbKey_Z;
-
- case 0x21: return gbKey_Lbracket;
- case 0x1e: return gbKey_Rbracket;
- case 0x29: return gbKey_Semicolon;
- case 0x2b: return gbKey_Comma;
- case 0x2f: return gbKey_Period;
- case 0x27: return gbKey_Quote;
- case 0x2c: return gbKey_Slash;
- case 0x2a: return gbKey_Backslash;
- case 0x32: return gbKey_Grave;
- case 0x18: return gbKey_Equals;
- case 0x1b: return gbKey_Minus;
- case 0x31: return gbKey_Space;
-
- case 0x35: return gbKey_Escape; // Escape
- case 0x3b: return gbKey_Lcontrol; // Left Control
- case 0x38: return gbKey_Lshift; // Left Shift
- case 0x3a: return gbKey_Lalt; // Left Alt
- case 0x37: return gbKey_Lsystem; // Left OS specific: window (Windows and Linux), apple/cmd (MacOS X), ...
- case 0x3e: return gbKey_Rcontrol; // Right Control
- case 0x3c: return gbKey_Rshift; // Right Shift
- case 0x3d: return gbKey_Ralt; // Right Alt
- // case 0x37: return gbKey_Rsystem; // Right OS specific: window (Windows and Linux), apple/cmd (MacOS X), ...
- case 0x6e: return gbKey_Menu; // Menu
- case 0x24: return gbKey_Return; // Return
- case 0x33: return gbKey_Backspace; // Backspace
- case 0x30: return gbKey_Tab; // Tabulation
- case 0x74: return gbKey_Pageup; // Page up
- case 0x79: return gbKey_Pagedown; // Page down
- case 0x77: return gbKey_End; // End
- case 0x73: return gbKey_Home; // Home
- case 0x72: return gbKey_Insert; // Insert
- case 0x75: return gbKey_Delete; // Delete
- case 0x45: return gbKey_Plus; // +
- case 0x4e: return gbKey_Subtract; // -
- case 0x43: return gbKey_Multiply; // *
- case 0x4b: return gbKey_Divide; // /
- case 0x7b: return gbKey_Left; // Left arrow
- case 0x7c: return gbKey_Right; // Right arrow
- case 0x7e: return gbKey_Up; // Up arrow
- case 0x7d: return gbKey_Down; // Down arrow
- case 0x52: return gbKey_Numpad0; // Numpad 0
- case 0x53: return gbKey_Numpad1; // Numpad 1
- case 0x54: return gbKey_Numpad2; // Numpad 2
- case 0x55: return gbKey_Numpad3; // Numpad 3
- case 0x56: return gbKey_Numpad4; // Numpad 4
- case 0x57: return gbKey_Numpad5; // Numpad 5
- case 0x58: return gbKey_Numpad6; // Numpad 6
- case 0x59: return gbKey_Numpad7; // Numpad 7
- case 0x5b: return gbKey_Numpad8; // Numpad 8
- case 0x5c: return gbKey_Numpad9; // Numpad 9
- case 0x41: return gbKey_NumpadDot; // Numpad .
- case 0x4c: return gbKey_NumpadEnter; // Numpad Enter
- case 0x7a: return gbKey_F1; // F1
- case 0x78: return gbKey_F2; // F2
- case 0x63: return gbKey_F3; // F3
- case 0x76: return gbKey_F4; // F4
- case 0x60: return gbKey_F5; // F5
- case 0x61: return gbKey_F6; // F6
- case 0x62: return gbKey_F7; // F7
- case 0x64: return gbKey_F8; // F8
- case 0x65: return gbKey_F9; // F8
- case 0x6d: return gbKey_F10; // F10
- case 0x67: return gbKey_F11; // F11
- case 0x6f: return gbKey_F12; // F12
- case 0x69: return gbKey_F13; // F13
- case 0x6b: return gbKey_F14; // F14
- case 0x71: return gbKey_F15; // F15
- // case : return gbKey_Pause; // Pause // NOTE(bill): Not possible on OS X
- }
-}
-
-gb_internal void gb__osx_on_cocoa_event(gbPlatform *p, id event, id window) {
- if (!event) {
- return;
- } else if (objc_msgSend_id(window, sel_registerName("delegate"))) {
- NSUInteger event_type = ((NSUInteger (*)(id, SEL))objc_msgSend)(event, sel_registerName("type"));
- switch (event_type) {
- case 1: gb_key_state_update(&p->mouse_buttons[gbMouseButton_Left], true); break; // NSLeftMouseDown
- case 2: gb_key_state_update(&p->mouse_buttons[gbMouseButton_Left], false); break; // NSLeftMouseUp
- case 3: gb_key_state_update(&p->mouse_buttons[gbMouseButton_Right], true); break; // NSRightMouseDown
- case 4: gb_key_state_update(&p->mouse_buttons[gbMouseButton_Right], false); break; // NSRightMouseUp
- case 25: { // NSOtherMouseDown
- // TODO(bill): Test thoroughly
- NSInteger number = ((NSInteger (*)(id, SEL))objc_msgSend)(event, sel_registerName("buttonNumber"));
- if (number == 2) gb_key_state_update(&p->mouse_buttons[gbMouseButton_Middle], true);
- if (number == 3) gb_key_state_update(&p->mouse_buttons[gbMouseButton_X1], true);
- if (number == 4) gb_key_state_update(&p->mouse_buttons[gbMouseButton_X2], true);
- } break;
- case 26: { // NSOtherMouseUp
- NSInteger number = ((NSInteger (*)(id, SEL))objc_msgSend)(event, sel_registerName("buttonNumber"));
- if (number == 2) gb_key_state_update(&p->mouse_buttons[gbMouseButton_Middle], false);
- if (number == 3) gb_key_state_update(&p->mouse_buttons[gbMouseButton_X1], false);
- if (number == 4) gb_key_state_update(&p->mouse_buttons[gbMouseButton_X2], false);
-
- } break;
-
- // TODO(bill): Scroll wheel
- case 22: { // NSScrollWheel
- CGFloat dx = ((CGFloat (*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("scrollingDeltaX"));
- CGFloat dy = ((CGFloat (*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("scrollingDeltaY"));
- BOOL precision_scrolling = ((BOOL (*)(id, SEL))objc_msgSend)(event, sel_registerName("hasPreciseScrollingDeltas"));
- if (precision_scrolling) {
- dx *= 0.1f;
- dy *= 0.1f;
- }
- // TODO(bill): Handle sideways
- p->mouse_wheel_delta = dy;
- // p->mouse_wheel_dy = dy;
- // gb_printf("%f %f\n", dx, dy);
- } break;
-
- case 12: { // NSFlagsChanged
- #if 0
- // TODO(bill): Reverse engineer this properly
- NSUInteger modifiers = ((NSUInteger (*)(id, SEL))objc_msgSend)(event, sel_registerName("modifierFlags"));
- u32 upper_mask = (modifiers & 0xffff0000ul) >> 16;
- b32 shift = (upper_mask & 0x02) != 0;
- b32 control = (upper_mask & 0x04) != 0;
- b32 alt = (upper_mask & 0x08) != 0;
- b32 command = (upper_mask & 0x10) != 0;
- #endif
-
- // gb_printf("%u\n", keys.mask);
- // gb_printf("%x\n", cast(u32)modifiers);
- } break;
-
- case 10: { // NSKeyDown
- u16 key_code;
-
- id input_text = objc_msgSend_id(event, sel_registerName("characters"));
- char const *input_text_utf8 = ((char const *(*)(id, SEL))objc_msgSend)(input_text, sel_registerName("UTF8String"));
- p->char_buffer_count = gb_strnlen(input_text_utf8, gb_size_of(p->char_buffer));
- gb_memcopy(p->char_buffer, input_text_utf8, p->char_buffer_count);
-
- key_code = ((unsigned short (*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
- gb_key_state_update(&p->keys[gb__osx_from_key_code(key_code)], true);
- } break;
-
- case 11: { // NSKeyUp
- u16 key_code = ((unsigned short (*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
- gb_key_state_update(&p->keys[gb__osx_from_key_code(key_code)], false);
- } break;
-
- default: break;
- }
-
- objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), event);
- }
-}
-
-
-void gb_platform_update(gbPlatform *p) {
- id window, key_window, content_view;
- NSRect original_frame;
-
- window = cast(id)p->window_handle;
- key_window = objc_msgSend_id(NSApp, sel_registerName("keyWindow"));
- p->window_has_focus = key_window == window; // TODO(bill): Is this right
-
-
- if (p->window_has_focus) {
- isize i;
- p->char_buffer_count = 0; // TODO(bill): Reset buffer count here or else where?
-
- // NOTE(bill): Need to update as the keys only get updates on events
- for (i = 0; i < gbKey_Count; i++) {
- b32 is_down = (p->keys[i] & gbKeyState_Down) != 0;
- gb_key_state_update(&p->keys[i], is_down);
- }
-
- for (i = 0; i < gbMouseButton_Count; i++) {
- b32 is_down = (p->mouse_buttons[i] & gbKeyState_Down) != 0;
- gb_key_state_update(&p->mouse_buttons[i], is_down);
- }
-
- }
-
- { // Handle Events
- id distant_past = objc_msgSend_id(cast(id)objc_getClass("NSDate"), sel_registerName("distantPast"));
- id event = ((id (*)(id, SEL, NSUInteger, id, id, BOOL))objc_msgSend)(NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), NSUIntegerMax, distant_past, NSDefaultRunLoopMode, YES);
- gb__osx_on_cocoa_event(p, event, window);
- }
-
- if (p->window_has_focus) {
- p->key_modifiers.control = p->keys[gbKey_Lcontrol] | p->keys[gbKey_Rcontrol];
- p->key_modifiers.alt = p->keys[gbKey_Lalt] | p->keys[gbKey_Ralt];
- p->key_modifiers.shift = p->keys[gbKey_Lshift] | p->keys[gbKey_Rshift];
- }
-
- { // Check if window is closed
- id wdg = objc_msgSend_id(window, sel_registerName("delegate"));
- if (!wdg) {
- p->window_is_closed = false;
- } else {
- NSUInteger value = 0;
- object_getInstanceVariable(wdg, "closed", cast(void **)&value);
- p->window_is_closed = (value != 0);
- }
- }
-
-
-
- content_view = objc_msgSend_id(window, sel_registerName("contentView"));
- original_frame = ((NSRect (*)(id, SEL))abi_objc_msgSend_stret)(content_view, sel_registerName("frame"));
-
- { // Window
- NSRect frame = original_frame;
- frame = ((NSRect (*)(id, SEL, NSRect))abi_objc_msgSend_stret)(content_view, sel_registerName("convertRectToBacking:"), frame);
- p->window_width = frame.size.width;
- p->window_height = frame.size.height;
- frame = ((NSRect (*)(id, SEL, NSRect))abi_objc_msgSend_stret)(window, sel_registerName("convertRectToScreen:"), frame);
- p->window_x = frame.origin.x;
- p->window_y = frame.origin.y;
- }
-
- { // Mouse
- NSRect frame = original_frame;
- NSPoint mouse_pos = ((NSPoint (*)(id, SEL))objc_msgSend)(window, sel_registerName("mouseLocationOutsideOfEventStream"));
- mouse_pos.x = gb_clamp(mouse_pos.x, 0, frame.size.width-1);
- mouse_pos.y = gb_clamp(mouse_pos.y, 0, frame.size.height-1);
-
- {
- i32 x = mouse_pos.x;
- i32 y = mouse_pos.y;
- p->mouse_dx = x - p->mouse_x;
- p->mouse_dy = y - p->mouse_y;
- p->mouse_x = x;
- p->mouse_y = y;
- }
-
- if (p->mouse_clip) {
- b32 update = false;
- i32 x = p->mouse_x;
- i32 y = p->mouse_y;
- if (p->mouse_x < 0) {
- x = 0;
- update = true;
- } else if (p->mouse_y > p->window_height-1) {
- y = p->window_height-1;
- update = true;
- }
-
- if (p->mouse_y < 0) {
- y = 0;
- update = true;
- } else if (p->mouse_x > p->window_width-1) {
- x = p->window_width-1;
- update = true;
- }
-
- if (update) {
- gb_platform_set_mouse_position(p, x, y);
- }
- }
- }
-
- { // TODO(bill): Controllers
-
- }
-
- // TODO(bill): Is this in the correct place?
- objc_msgSend_void(NSApp, sel_registerName("updateWindows"));
- if (p->renderer_type == gbRenderer_Opengl) {
- objc_msgSend_void(cast(id)p->opengl.context, sel_registerName("update"));
- gb_platform_make_opengl_context_current(p);
- }
-}
-
-void gb_platform_display(gbPlatform *p) {
- // TODO(bill): Do more
- if (p->renderer_type == gbRenderer_Opengl) {
- gb_platform_make_opengl_context_current(p);
- objc_msgSend_void(cast(id)p->opengl.context, sel_registerName("flushBuffer"));
- } else if (p->renderer_type == gbRenderer_Software) {
- // TODO(bill):
- } else {
- GB_PANIC("Invalid window rendering type");
- }
-
- {
- f64 prev_time = p->curr_time;
- f64 curr_time = gb_time_now();
- p->dt_for_frame = curr_time - prev_time;
- p->curr_time = curr_time;
- }
-}
-
-void gb_platform_destroy(gbPlatform *p) {
- gb_platform_make_opengl_context_current(p);
-
- objc_msgSend_void(cast(id)p->window_handle, sel_registerName("close"));
-
- #if defined(ARC_AVAILABLE)
- // TODO(bill): autorelease pool
- #else
- objc_msgSend_void(cast(id)p->osx_autorelease_pool, sel_registerName("drain"));
- #endif
-}
-
-void gb_platform_show_cursor(gbPlatform *p, b32 show) {
- if (show ) {
- // objc_msgSend_void(class_registerName("NSCursor"), sel_registerName("unhide"));
- } else {
- // objc_msgSend_void(class_registerName("NSCursor"), sel_registerName("hide"));
- }
-}
-
-void gb_platform_set_mouse_position(gbPlatform *p, i32 x, i32 y) {
- // TODO(bill):
- CGPoint pos = {cast(CGFloat)x, cast(CGFloat)y};
- pos.x += p->window_x;
- pos.y += p->window_y;
- CGWarpMouseCursorPosition(pos);
-}
-
-void gb_platform_set_controller_vibration(gbPlatform *p, isize index, f32 left_motor, f32 right_motor) {
- // TODO(bill):
-}
-
-b32 gb_platform_has_clipboard_text(gbPlatform *p) {
- // TODO(bill):
- return false;
-}
-
-void gb_platform_set_clipboard_text(gbPlatform *p, char const *str) {
- // TODO(bill):
-}
-
-char *gb_platform_get_clipboard_text(gbPlatform *p, gbAllocator a) {
- // TODO(bill):
- return NULL;
-}
-
-void gb_platform_set_window_position(gbPlatform *p, i32 x, i32 y) {
- // TODO(bill):
-}
-
-void gb_platform_set_window_title(gbPlatform *p, char const *title, ...) {
- id title_string;
- char buf[256] = {0};
- va_list va;
- va_start(va, title);
- gb_snprintf_va(buf, gb_count_of(buf), title, va);
- va_end(va);
-
- title_string = objc_msgSend_id_char_const(cast(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), buf);
- objc_msgSend_void_id(cast(id)p->window_handle, sel_registerName("setTitle:"), title_string);
-}
-
-void gb_platform_toggle_fullscreen(gbPlatform *p, b32 fullscreen_desktop) {
- // TODO(bill):
-}
-
-void gb_platform_toggle_borderless(gbPlatform *p) {
- // TODO(bill):
-}
-
-void gb_platform_make_opengl_context_current(gbPlatform *p) {
- objc_msgSend_void(cast(id)p->opengl.context, sel_registerName("makeCurrentContext"));
-}
-
-void gb_platform_show_window(gbPlatform *p) {
- // TODO(bill):
-}
-
-void gb_platform_hide_window(gbPlatform *p) {
- // TODO(bill):
-}
-
-i32 gb__osx_mode_bits_per_pixel(CGDisplayModeRef mode) {
- i32 bits_per_pixel = 0;
- CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(mode);
- if(CFStringCompare(pixel_encoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- bits_per_pixel = 32;
- } else if(CFStringCompare(pixel_encoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- bits_per_pixel = 16;
- } else if(CFStringCompare(pixel_encoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- bits_per_pixel = 8;
- }
- CFRelease(pixel_encoding);
-
- return bits_per_pixel;
-}
-
-i32 gb__osx_display_bits_per_pixel(CGDirectDisplayID display) {
- CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display);
- i32 bits_per_pixel = gb__osx_mode_bits_per_pixel(mode);
- CGDisplayModeRelease(mode);
- return bits_per_pixel;
-}
-
-gbVideoMode gb_video_mode_get_desktop(void) {
- CGDirectDisplayID display = CGMainDisplayID();
- return gb_video_mode(CGDisplayPixelsWide(display),
- CGDisplayPixelsHigh(display),
- gb__osx_display_bits_per_pixel(display));
-}
-
-
-isize gb_video_mode_get_fullscreen_modes(gbVideoMode *modes, isize max_mode_count) {
- CFArrayRef cg_modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL);
- CFIndex i, count;
- if (cg_modes == NULL) {
- return 0;
- }
-
- count = gb_min(CFArrayGetCount(cg_modes), max_mode_count);
- for (i = 0; i < count; i++) {
- CGDisplayModeRef cg_mode = cast(CGDisplayModeRef)CFArrayGetValueAtIndex(cg_modes, i);
- modes[i] = gb_video_mode(CGDisplayModeGetWidth(cg_mode),
- CGDisplayModeGetHeight(cg_mode),
- gb__osx_mode_bits_per_pixel(cg_mode));
- }
-
- CFRelease(cg_modes);
-
- gb_sort_array(modes, count, gb_video_mode_dsc_cmp);
- return cast(isize)count;
-}
-
-#endif
-
-
-// TODO(bill): OSX Platform Layer
-// NOTE(bill): Use this as a guide so there is no need for Obj-C https://github.com/jimon/osx_app_in_plain_c
-
-gb_inline gbVideoMode gb_video_mode(i32 width, i32 height, i32 bits_per_pixel) {
- gbVideoMode m;
- m.width = width;
- m.height = height;
- m.bits_per_pixel = bits_per_pixel;
- return m;
-}
-
-gb_inline b32 gb_video_mode_is_valid(gbVideoMode mode) {
- gb_local_persist gbVideoMode modes[256] = {0};
- gb_local_persist isize mode_count = 0;
- gb_local_persist b32 is_set = false;
- isize i;
-
- if (!is_set) {
- mode_count = gb_video_mode_get_fullscreen_modes(modes, gb_count_of(modes));
- is_set = true;
- }
-
- for (i = 0; i < mode_count; i++) {
- gb_printf("%d %d\n", modes[i].width, modes[i].height);
- }
-
- return gb_binary_search_array(modes, mode_count, &mode, gb_video_mode_cmp) >= 0;
-}
-
-GB_COMPARE_PROC(gb_video_mode_cmp) {
- gbVideoMode const *x = cast(gbVideoMode const *)a;
- gbVideoMode const *y = cast(gbVideoMode const *)b;
-
- if (x->bits_per_pixel == y->bits_per_pixel) {
- if (x->width == y->width) {
- return x->height < y->height ? -1 : x->height > y->height;
- }
- return x->width < y->width ? -1 : x->width > y->width;
- }
- return x->bits_per_pixel < y->bits_per_pixel ? -1 : +1;
-}
-
-GB_COMPARE_PROC(gb_video_mode_dsc_cmp) {
- return gb_video_mode_cmp(b, a);
-}
-
-#endif // defined(GB_PLATFORM)
-
-
-
-
#if defined(GB_COMPILER_MSVC)
#pragma warning(pop)
#endif