From ac382d1fa6aae6e5afe3acc964bcfc96ad19672c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 6 May 2026 22:52:40 -0700 Subject: [PATCH 1/7] Creating SDL3 scaffolding. --- .gitmodules | 3 + third_party/SDL | 1 + third_party/SDL_build_config.h | 627 +++++++++++++++++++ vsprojects/SDL/SDL.vcxproj | 460 ++++++++++++++ vsprojects/SDL/SDL.vcxproj.filters | 963 +++++++++++++++++++++++++++++ vsprojects/pcsx-redux.sln | 18 +- 6 files changed, 2070 insertions(+), 2 deletions(-) create mode 160000 third_party/SDL create mode 100644 third_party/SDL_build_config.h create mode 100644 vsprojects/SDL/SDL.vcxproj create mode 100644 vsprojects/SDL/SDL.vcxproj.filters diff --git a/.gitmodules b/.gitmodules index 82423b8f4..72c8e91b8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -100,3 +100,6 @@ [submodule "third_party/psxlua"] path = third_party/psxlua url = https://github.com/grumpycoders/psxlua.git +[submodule "third_party/SDL"] + path = third_party/SDL + url = https://github.com/libsdl-org/SDL.git diff --git a/third_party/SDL b/third_party/SDL new file mode 160000 index 000000000..d9d553670 --- /dev/null +++ b/third_party/SDL @@ -0,0 +1 @@ +Subproject commit d9d5536704d585616d4db3c8ba3c4ff6fc2757e1 diff --git a/third_party/SDL_build_config.h b/third_party/SDL_build_config.h new file mode 100644 index 000000000..5a7c4db19 --- /dev/null +++ b/third_party/SDL_build_config.h @@ -0,0 +1,627 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2026 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_build_config.h + * + * This is a set of defines to configure the SDL features + */ + +#ifndef SDL_build_config_h_ +#define SDL_build_config_h_ + +/* General platform specific identifiers */ +#include + +/* #undef SDL_PLATFORM_PRIVATE */ + +#ifdef SDL_PLATFORM_PRIVATE +#include "SDL_begin_config_private.h" +#endif + +/* #undef HAVE_GCC_ATOMICS */ +/* #undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET */ + +/* #undef SDL_DISABLE_ALLOCA */ + +/* Useful headers */ +#define HAVE_FLOAT_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_STDINT_H 1 + +/* Comment this if you want to build without any C library requirements */ +#define HAVE_LIBC 1 +#ifdef HAVE_LIBC + +/* Useful headers */ +/* #undef HAVE_ALLOCA_H */ +/* #undef HAVE_ICONV_H */ +#define HAVE_INTTYPES_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_MALLOC_H 1 +#define HAVE_MATH_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_STDIO_H 1 +#define HAVE_STDLIB_H 1 +/* #undef HAVE_STRINGS_H */ +#define HAVE_STRING_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_WCHAR_H 1 +/* #undef HAVE_PTHREAD_NP_H */ + +/* C library functions */ +/* #undef HAVE_DLOPEN */ +#define HAVE_MALLOC 1 +/* #undef HAVE_FDATASYNC */ +#define HAVE_GETENV 1 +/* #undef HAVE_GETHOSTNAME */ +/* #undef HAVE_SETENV */ +#define HAVE_PUTENV 1 +/* #undef HAVE_UNSETENV */ +#define HAVE_ABS 1 +/* #undef HAVE_BCOPY */ +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_WCSLEN 1 +#define HAVE_WCSNLEN 1 +/* #undef HAVE_WCSLCPY */ +/* #undef HAVE_WCSLCAT */ +#define HAVE_WCSSTR 1 +#define HAVE_WCSCMP 1 +#define HAVE_WCSNCMP 1 +#define HAVE_WCSTOL 1 +#define HAVE_STRLEN 1 +#define HAVE_STRNLEN 1 +/* #undef HAVE_STRLCPY */ +/* #undef HAVE_STRLCAT */ +#define HAVE_STRPBRK 1 +#define HAVE__STRREV 1 +/* #undef HAVE_INDEX */ +/* #undef HAVE_RINDEX */ +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +/* #undef HAVE_STRNSTR */ +/* #undef HAVE_STRTOK_R */ +#define HAVE_ITOA 1 +#define HAVE__LTOA 1 +/* #undef HAVE__UITOA */ +#define HAVE__ULTOA 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE__I64TOA 1 +#define HAVE__UI64TOA 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_ACOS 1 +#define HAVE_ACOSF 1 +#define HAVE_ASIN 1 +#define HAVE_ASINF 1 +#define HAVE_ATAN 1 +#define HAVE_ATANF 1 +#define HAVE_ATAN2 1 +#define HAVE_ATAN2F 1 +#define HAVE_CEIL 1 +#define HAVE_CEILF 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COPYSIGNF 1 +#define HAVE__COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_EXP 1 +#define HAVE_EXPF 1 +#define HAVE_FABS 1 +#define HAVE_FABSF 1 +#define HAVE_FLOOR 1 +#define HAVE_FLOORF 1 +#define HAVE_FMOD 1 +#define HAVE_FMODF 1 +#define HAVE_ISINF 1 +/* #undef HAVE_ISINFF */ +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +/* #undef HAVE_ISNANF */ +#define HAVE_ISNAN_FLOAT_MACRO 1 +#define HAVE_LOG 1 +#define HAVE_LOGF 1 +#define HAVE_LOG10 1 +#define HAVE_LOG10F 1 +#define HAVE_LROUND 1 +#define HAVE_LROUNDF 1 +#define HAVE_MODF 1 +#define HAVE_MODFF 1 +#define HAVE_POW 1 +#define HAVE_POWF 1 +#define HAVE_ROUND 1 +#define HAVE_ROUNDF 1 +#define HAVE_SCALBN 1 +#define HAVE_SCALBNF 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_TRUNC 1 +#define HAVE_TRUNCF 1 +#define HAVE__FSEEKI64 1 +/* #undef HAVE_FOPEN64 */ +/* #undef HAVE_FSEEKO */ +/* #undef HAVE_FSEEKO64 */ +/* #undef HAVE_MEMFD_CREATE */ +/* #undef HAVE_POSIX_FALLOCATE */ +/* #undef HAVE_SIGACTION */ +/* #undef HAVE_SIGTIMEDWAIT */ +/* #undef HAVE_SA_SIGACTION */ +/* #undef HAVE_ST_MTIM */ +/* #undef HAVE_SETJMP */ +/* #undef HAVE_NANOSLEEP */ +/* #undef HAVE_GMTIME_R */ +/* #undef HAVE_LOCALTIME_R */ +/* #undef HAVE_NL_LANGINFO */ +/* #undef HAVE_SYSCONF */ +/* #undef HAVE_SYSCTLBYNAME */ +/* #undef HAVE_CLOCK_GETTIME */ +/* #undef HAVE_GETPAGESIZE */ +/* #undef HAVE_ICONV */ +/* #undef SDL_USE_LIBICONV */ +/* #undef HAVE_PTHREAD_SETNAME_NP */ +/* #undef HAVE_PTHREAD_SET_NAME_NP */ +/* #undef HAVE_SEM_TIMEDWAIT */ +/* #undef HAVE_GETAUXVAL */ +/* #undef HAVE_ELF_AUX_INFO */ +/* #undef HAVE_PPOLL */ +#define HAVE__EXIT 1 +/* #undef HAVE_GETRESUID */ +/* #undef HAVE_GETRESGID */ + +#endif /* HAVE_LIBC */ + +/* #undef HAVE_DBUS_DBUS_H */ +/* #undef HAVE_FCITX */ +/* #undef HAVE_IBUS_IBUS_H */ +/* #undef HAVE_INOTIFY_INIT1 */ +/* #undef HAVE_INOTIFY */ +/* #undef HAVE_LIBUSB */ +/* #undef HAVE_O_CLOEXEC */ + +/* #undef HAVE_LINUX_INPUT_H */ +/* #undef HAVE_LIBUDEV_H */ +/* #undef HAVE_LIBDECOR_H */ +/* #undef HAVE_LIBURING_H */ +/* #undef HAVE_FRIBIDI_H */ +/* #undef SDL_FRIBIDI_DYNAMIC */ +/* #undef HAVE_LIBTHAI_H */ +/* #undef SDL_LIBTHAI_DYNAMIC */ + +#define HAVE_DDRAW_H 1 +#define HAVE_DSOUND_H 1 +#define HAVE_DINPUT_H 1 +#define HAVE_XINPUT_H 1 +#define HAVE_WINDOWS_GAMING_INPUT_H 1 +#define HAVE_GAMEINPUT_H 1 +#define HAVE_DXGI_H 1 +#define HAVE_DXGI1_5_H 1 +#define HAVE_DXGI1_6_H 1 + +#define HAVE_MMDEVICEAPI_H 1 +#define HAVE_TPCSHRD_H 1 +#define HAVE_ROAPI_H 1 +#define HAVE_SHELLSCALINGAPI_H 1 + +/* #undef USE_POSIX_SPAWN */ +/* #undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR */ +/* #undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP */ + +/* #undef SDL_DISABLE_DLOPEN_NOTES */ + +/* SDL internal assertion support */ +/* #undef SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED */ +#ifdef SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED +#define SDL_DEFAULT_ASSERT_LEVEL +#endif + +/* Allow disabling of major subsystems */ +/* #undef SDL_AUDIO_DISABLED */ +/* #undef SDL_VIDEO_DISABLED */ +/* #undef SDL_GPU_DISABLED */ +/* #undef SDL_RENDER_DISABLED */ +/* #undef SDL_CAMERA_DISABLED */ +/* #undef SDL_JOYSTICK_DISABLED */ +/* #undef SDL_HAPTIC_DISABLED */ +/* #undef SDL_HIDAPI_DISABLED */ +/* #undef SDL_POWER_DISABLED */ +/* #undef SDL_SENSOR_DISABLED */ +/* #undef SDL_DIALOG_DISABLED */ +/* #undef SDL_THREADS_DISABLED */ + +/* Enable various audio drivers */ +/* #undef SDL_AUDIO_DRIVER_ALSA */ +/* #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_OPENSLES */ +/* #undef SDL_AUDIO_DRIVER_AAUDIO */ +/* #undef SDL_AUDIO_DRIVER_COREAUDIO */ +#define SDL_AUDIO_DRIVER_DISK 1 +#define SDL_AUDIO_DRIVER_DSOUND 1 +#define SDL_AUDIO_DRIVER_DUMMY 1 +/* #undef SDL_AUDIO_DRIVER_EMSCRIPTEN */ +/* #undef SDL_AUDIO_DRIVER_HAIKU */ +/* #undef SDL_AUDIO_DRIVER_JACK */ +/* #undef SDL_AUDIO_DRIVER_JACK_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_NETBSD */ +/* #undef SDL_AUDIO_DRIVER_OSS */ +/* #undef SDL_AUDIO_DRIVER_PIPEWIRE */ +/* #undef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_PULSEAUDIO */ +/* #undef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_SNDIO */ +/* #undef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC */ +#define SDL_AUDIO_DRIVER_WASAPI 1 +/* #undef SDL_AUDIO_DRIVER_VITA */ +/* #undef SDL_AUDIO_DRIVER_PSP */ +/* #undef SDL_AUDIO_DRIVER_PS2 */ +/* #undef SDL_AUDIO_DRIVER_N3DS */ +/* #undef SDL_AUDIO_DRIVER_NGAGE */ +/* #undef SDL_AUDIO_DRIVER_QNX */ + +/* #undef SDL_AUDIO_DRIVER_PRIVATE */ + +/* Enable various input drivers */ +/* #undef SDL_INPUT_LINUXEV */ +/* #undef SDL_INPUT_LINUXKD */ +/* #undef SDL_INPUT_FBSDKBIO */ +/* #undef SDL_INPUT_WSCONS */ +/* #undef SDL_HAVE_MACHINE_JOYSTICK_H */ +/* #undef SDL_JOYSTICK_ANDROID */ +#define SDL_JOYSTICK_DINPUT 1 +/* #undef SDL_JOYSTICK_DUMMY */ +/* #undef SDL_JOYSTICK_EMSCRIPTEN */ +#define SDL_JOYSTICK_GAMEINPUT 1 +/* #undef SDL_JOYSTICK_HAIKU */ +#define SDL_JOYSTICK_HIDAPI 1 +/* #undef SDL_JOYSTICK_IOKIT */ +/* #undef SDL_JOYSTICK_LINUX */ +/* #undef SDL_JOYSTICK_MFI */ +/* #undef SDL_JOYSTICK_N3DS */ +/* #undef SDL_JOYSTICK_PS2 */ +/* #undef SDL_JOYSTICK_PSP */ +#define SDL_JOYSTICK_RAWINPUT 1 +/* #undef SDL_JOYSTICK_USBHID */ +#define SDL_JOYSTICK_VIRTUAL 1 +/* #undef SDL_JOYSTICK_VITA */ +#define SDL_JOYSTICK_WGI 1 +#define SDL_JOYSTICK_XINPUT 1 + +/* #undef SDL_JOYSTICK_PRIVATE */ + +/* #undef SDL_HAPTIC_DUMMY */ +/* #undef SDL_HAPTIC_LINUX */ +/* #undef SDL_HAPTIC_IOKIT */ +#define SDL_HAPTIC_DINPUT 1 +/* #undef SDL_HAPTIC_ANDROID */ + +/* #undef SDL_HAPTIC_PRIVATE */ + +/* #undef SDL_LIBUSB_DYNAMIC */ +/* #undef SDL_UDEV_DYNAMIC */ + +/* Enable various process implementations */ +/* #undef SDL_PROCESS_DUMMY */ +/* #undef SDL_PROCESS_POSIX */ +#define SDL_PROCESS_WINDOWS 1 + +/* #undef SDL_PROCESS_PRIVATE */ + +/* Enable various sensor drivers */ +/* #undef SDL_SENSOR_ANDROID */ +/* #undef SDL_SENSOR_COREMOTION */ +#define SDL_SENSOR_WINDOWS 1 +/* #undef SDL_SENSOR_DUMMY */ +/* #undef SDL_SENSOR_VITA */ +/* #undef SDL_SENSOR_N3DS */ +/* #undef SDL_SENSOR_EMSCRIPTEN */ + +/* #undef SDL_SENSOR_PRIVATE */ + +/* Enable various shared object loading systems */ +/* #undef SDL_LOADSO_DLOPEN */ +/* #undef SDL_LOADSO_DUMMY */ +#define SDL_LOADSO_WINDOWS 1 + +/* #undef SDL_LOADSO_PRIVATE */ + +/* Enable various threading systems */ +#define SDL_THREAD_GENERIC_COND_SUFFIX 1 +#define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1 +/* #undef SDL_THREAD_PTHREAD */ +/* #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX */ +/* #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP */ +#define SDL_THREAD_WINDOWS 1 +/* #undef SDL_THREAD_VITA */ +/* #undef SDL_THREAD_PSP */ +/* #undef SDL_THREAD_PS2 */ +/* #undef SDL_THREAD_N3DS */ + +/* #undef SDL_THREAD_PRIVATE */ + +/* Enable various RTC systems */ +/* #undef SDL_TIME_UNIX */ +#define SDL_TIME_WINDOWS 1 +/* #undef SDL_TIME_VITA */ +/* #undef SDL_TIME_PSP */ +/* #undef SDL_TIME_PS2 */ +/* #undef SDL_TIME_N3DS */ +/* #undef SDL_TIME_NGAGE */ + +/* #undef SDL_TIME_PRIVATE */ + +/* Enable various timer systems */ +/* #undef SDL_TIMER_HAIKU */ +/* #undef SDL_TIMER_UNIX */ +#define SDL_TIMER_WINDOWS 1 +/* #undef SDL_TIMER_VITA */ +/* #undef SDL_TIMER_PSP */ +/* #undef SDL_TIMER_PS2 */ +/* #undef SDL_TIMER_N3DS */ + +/* #undef SDL_TIMER_PRIVATE */ + +/* Enable various video drivers */ +/* #undef SDL_VIDEO_DRIVER_ANDROID */ +/* #undef SDL_VIDEO_DRIVER_COCOA */ +#define SDL_VIDEO_DRIVER_DUMMY 1 +/* #undef SDL_VIDEO_DRIVER_EMSCRIPTEN */ +/* #undef SDL_VIDEO_DRIVER_HAIKU */ +/* #undef SDL_VIDEO_DRIVER_KMSDRM */ +/* #undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC */ +/* #undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM */ +/* #undef SDL_VIDEO_DRIVER_N3DS */ +/* #undef SDL_VIDEO_DRIVER_NGAGE */ +#define SDL_VIDEO_DRIVER_OFFSCREEN 1 +/* #undef SDL_VIDEO_DRIVER_PS2 */ +/* #undef SDL_VIDEO_DRIVER_PSP */ +/* #undef SDL_VIDEO_DRIVER_RISCOS */ +/* #undef SDL_VIDEO_DRIVER_ROCKCHIP */ +/* #undef SDL_VIDEO_DRIVER_RPI */ +/* #undef SDL_VIDEO_DRIVER_UIKIT */ +/* #undef SDL_VIDEO_DRIVER_VITA */ +/* #undef SDL_VIDEO_DRIVER_VIVANTE */ +/* #undef SDL_VIDEO_DRIVER_VIVANTE_VDK */ +/* #undef SDL_VIDEO_DRIVER_OPENVR */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON */ +#define SDL_VIDEO_DRIVER_WINDOWS 1 +/* #undef SDL_VIDEO_DRIVER_X11 */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XTEST */ +/* #undef SDL_VIDEO_DRIVER_X11_HAS_XKBLIB */ +/* #undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */ +/* #undef SDL_VIDEO_DRIVER_X11_XCURSOR */ +/* #undef SDL_VIDEO_DRIVER_X11_XDBE */ +/* #undef SDL_VIDEO_DRIVER_X11_XFIXES */ +/* #undef SDL_VIDEO_DRIVER_X11_XINPUT2 */ +/* #undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */ +/* #undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO */ +/* #undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_GESTURE */ +/* #undef SDL_VIDEO_DRIVER_X11_XRANDR */ +/* #undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER */ +/* #undef SDL_VIDEO_DRIVER_X11_XSHAPE */ +/* #undef SDL_VIDEO_DRIVER_X11_XSYNC */ +/* #undef SDL_VIDEO_DRIVER_X11_XTEST */ +/* #undef SDL_VIDEO_DRIVER_QNX */ + +/* #undef SDL_VIDEO_DRIVER_PRIVATE */ + +#define SDL_VIDEO_RENDER_D3D 1 +#define SDL_VIDEO_RENDER_D3D11 1 +#define SDL_VIDEO_RENDER_D3D12 1 +#define SDL_VIDEO_RENDER_GPU 1 +/* #undef SDL_VIDEO_RENDER_METAL */ +#define SDL_VIDEO_RENDER_VULKAN 1 +#define SDL_VIDEO_RENDER_OGL 1 +#define SDL_VIDEO_RENDER_OGL_ES2 1 +/* #undef SDL_VIDEO_RENDER_NGAGE */ +/* #undef SDL_VIDEO_RENDER_PS2 */ +/* #undef SDL_VIDEO_RENDER_PSP */ +/* #undef SDL_VIDEO_RENDER_VITA_GXM */ + +/* #undef SDL_VIDEO_RENDER_PRIVATE */ + +/* Enable OpenGL support */ +#define SDL_VIDEO_OPENGL 1 +/* #undef SDL_VIDEO_OPENGL_ES */ +#define SDL_VIDEO_OPENGL_ES2 1 +/* #undef SDL_VIDEO_OPENGL_CGL */ +/* #undef SDL_VIDEO_OPENGL_GLX */ +#define SDL_VIDEO_OPENGL_WGL 1 +#define SDL_VIDEO_OPENGL_EGL 1 + +/* #undef SDL_VIDEO_STATIC_ANGLE */ + +/* Enable Vulkan support */ +#define SDL_VIDEO_VULKAN 1 + +/* Enable Metal support */ +/* #undef SDL_VIDEO_METAL */ + +/* Enable GPU support */ +/* #undef SDL_GPU_D3D11 */ +#define SDL_GPU_D3D12 1 +#define SDL_GPU_VULKAN 1 +/* #undef SDL_GPU_METAL */ + +/* #undef SDL_GPU_PRIVATE */ + +/* Enable system power support */ +/* #undef SDL_POWER_ANDROID */ +/* #undef SDL_POWER_LINUX */ +#define SDL_POWER_WINDOWS 1 +/* #undef SDL_POWER_MACOSX */ +/* #undef SDL_POWER_UIKIT */ +/* #undef SDL_POWER_HAIKU */ +/* #undef SDL_POWER_EMSCRIPTEN */ +/* #undef SDL_POWER_HARDWIRED */ +/* #undef SDL_POWER_VITA */ +/* #undef SDL_POWER_PSP */ +/* #undef SDL_POWER_N3DS */ + +/* #undef SDL_POWER_PRIVATE */ + +/* Enable system filesystem support */ +/* #undef SDL_FILESYSTEM_ANDROID */ +/* #undef SDL_FILESYSTEM_HAIKU */ +/* #undef SDL_FILESYSTEM_COCOA */ +/* #undef SDL_FILESYSTEM_DUMMY */ +/* #undef SDL_FILESYSTEM_RISCOS */ +/* #undef SDL_FILESYSTEM_UNIX */ +#define SDL_FILESYSTEM_WINDOWS 1 +/* #undef SDL_FILESYSTEM_EMSCRIPTEN */ +/* #undef SDL_FILESYSTEM_VITA */ +/* #undef SDL_FILESYSTEM_PSP */ +/* #undef SDL_FILESYSTEM_PS2 */ +/* #undef SDL_FILESYSTEM_N3DS */ + +/* #undef SDL_FILESYSTEM_PRIVATE */ + +/* Enable system storage support */ +#define SDL_STORAGE_STEAM 1 + +/* #undef SDL_STORAGE_PRIVATE */ + +/* Enable system FSops support */ +/* #undef SDL_FSOPS_POSIX */ +#define SDL_FSOPS_WINDOWS 1 +/* #undef SDL_FSOPS_DUMMY */ + +/* #undef SDL_FSOPS_PRIVATE */ + +/* Enable camera subsystem */ +#define SDL_CAMERA_DRIVER_DUMMY 1 +/* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK 1 */ +/* #undef SDL_CAMERA_DRIVER_V4L2 */ +/* #undef SDL_CAMERA_DRIVER_COREMEDIA */ +/* #undef SDL_CAMERA_DRIVER_ANDROID */ +/* #undef SDL_CAMERA_DRIVER_EMSCRIPTEN */ +#define SDL_CAMERA_DRIVER_MEDIAFOUNDATION 1 +/* #undef SDL_CAMERA_DRIVER_PIPEWIRE */ +/* #undef SDL_CAMERA_DRIVER_PIPEWIRE_DYNAMIC */ +/* #undef SDL_CAMERA_DRIVER_VITA */ + +/* #undef SDL_CAMERA_DRIVER_PRIVATE */ + +/* Enable dialog subsystem */ +/* #undef SDL_DIALOG_DUMMY */ + +/* Enable tray subsystem */ +/* #undef SDL_TRAY_DUMMY */ + +/* Enable assembly routines */ +/* #undef SDL_ALTIVEC_BLITTERS */ + +/* Whether SDL_DYNAMIC_API needs dlopen */ +/* #undef DYNAPI_NEEDS_DLOPEN */ + +/* Enable ime support */ +/* #undef SDL_USE_IME */ +/* #undef SDL_DISABLE_WINDOWS_IME */ +/* #undef SDL_GDK_TEXTINPUT */ + +/* Platform specific definitions */ +/* #undef SDL_IPHONE_KEYBOARD */ +/* #undef SDL_IPHONE_LAUNCHSCREEN */ + +/* #undef SDL_VIDEO_VITA_PIB */ +/* #undef SDL_VIDEO_VITA_PVR */ +/* #undef SDL_VIDEO_VITA_PVR_OGL */ + +/* #undef SDL_EMSCRIPTEN_PERSISTENT_PATH_STRING */ + +/* xkbcommon version info */ +#define SDL_XKBCOMMON_VERSION_MAJOR +#define SDL_XKBCOMMON_VERSION_MINOR +#define SDL_XKBCOMMON_VERSION_PATCH + +/* Libdecor version info */ +#define SDL_LIBDECOR_VERSION_MAJOR +#define SDL_LIBDECOR_VERSION_MINOR +#define SDL_LIBDECOR_VERSION_PATCH + +#if !defined(HAVE_STDINT_H) && !defined(_STDINT_H_) +/* Most everything except Visual Studio 2008 and earlier has stdint.h now */ +#if defined(_MSC_VER) && (_MSC_VER < 1600) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else +typedef unsigned int uintptr_t; +#endif +#endif +#endif /* Visual Studio 2008 */ +#endif /* !_STDINT_H_ && !HAVE_STDINT_H */ + +/* Configure use of intrinsics */ +/* #undef SDL_DISABLE_SSE */ +/* #undef SDL_DISABLE_SSE2 */ +/* #undef SDL_DISABLE_SSE3 */ +/* #undef SDL_DISABLE_SSE4_1 */ +/* #undef SDL_DISABLE_SSE4_2 */ +/* #undef SDL_DISABLE_AVX */ +/* #undef SDL_DISABLE_AVX2 */ +/* #undef SDL_DISABLE_AVX512F */ +#define SDL_DISABLE_MMX 1 +#define SDL_DISABLE_LSX 1 +#define SDL_DISABLE_LASX 1 +#define SDL_DISABLE_NEON 1 + +#ifdef SDL_PLATFORM_PRIVATE +#include "SDL_end_config_private.h" +#endif + +#endif /* SDL_build_config_h_ */ diff --git a/vsprojects/SDL/SDL.vcxproj b/vsprojects/SDL/SDL.vcxproj new file mode 100644 index 000000000..6188a5855 --- /dev/null +++ b/vsprojects/SDL/SDL.vcxproj @@ -0,0 +1,460 @@ + + + + + Debug + x64 + + + ReleaseWithClangCL + x64 + + + ReleaseWithTracy + x64 + + + Release + x64 + + + + 18.0 + Win32Proj + {13621b3d-871a-46a0-935f-d92a585ae034} + SDL + 10.0 + + + + StaticLibrary + true + v145 + Unicode + + + StaticLibrary + false + v145 + true + Unicode + + + StaticLibrary + false + v145 + true + Unicode + + + StaticLibrary + false + ClangCL + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + $(SolutionDir)..\third_party\SDL\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + $(SolutionDir)..\third_party\SDL\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + $(SolutionDir)..\third_party\SDL\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + $(SolutionDir)..\third_party\SDL\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vsprojects/SDL/SDL.vcxproj.filters b/vsprojects/SDL/SDL.vcxproj.filters new file mode 100644 index 000000000..0b6d3d927 --- /dev/null +++ b/vsprojects/SDL/SDL.vcxproj.filters @@ -0,0 +1,963 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/vsprojects/pcsx-redux.sln b/vsprojects/pcsx-redux.sln index 556e4fe6f..8aa9a3cc5 100644 --- a/vsprojects/pcsx-redux.sln +++ b/vsprojects/pcsx-redux.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32126.317 +# Visual Studio Version 18 +VisualStudioVersion = 18.5.11723.231 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "main", "main\main.vcxproj", "{36D6F879-F4CB-477E-BB87-33D867EDDB0A}" EndProject @@ -110,6 +110,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uriparser", "uriparser\uriparser.vcxproj", "{6ACDC81A-F4D8-4C2D-8CCD-DB72A88FEBED}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "authoring", "authoring\authoring.vcxproj", "{74766710-2FA8-4400-B035-321B4A7ACD9C}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PEGTL", "PEGTL", "{EC169519-2509-4F22-9AAF-0BD6BD85BBE0}" ProjectSection(SolutionItems) = preProject ..\third_party\PEGTL\include\tao\pegtl.hpp = ..\third_party\PEGTL\include\tao\pegtl.hpp @@ -324,6 +325,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "icu", "icu", "{ACCFF71D-6BB ..\third_party\PEGTL\include\tao\pegtl\contrib\icu\utf8.hpp = ..\third_party\PEGTL\include\tao\pegtl\contrib\icu\utf8.hpp EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL", "SDL\SDL.vcxproj", "{13621B3D-871A-46A0-935F-D92A585AE034}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -743,6 +746,16 @@ Global {74766710-2FA8-4400-B035-321B4A7ACD9C}.ReleaseWithClangCL|x64.Build.0 = ReleaseWithClangCL|x64 {74766710-2FA8-4400-B035-321B4A7ACD9C}.ReleaseWithTracy|x64.ActiveCfg = Release|x64 {74766710-2FA8-4400-B035-321B4A7ACD9C}.ReleaseWithTracy|x64.Build.0 = Release|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.Debug|x64.ActiveCfg = Debug|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.Debug|x64.Build.0 = Debug|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.Release|x64.ActiveCfg = Release|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.Release|x64.Build.0 = Release|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.ReleaseCLI|x64.ActiveCfg = ReleaseWithClangCL|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.ReleaseCLI|x64.Build.0 = ReleaseWithClangCL|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.ReleaseWithClangCL|x64.ActiveCfg = ReleaseWithClangCL|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.ReleaseWithClangCL|x64.Build.0 = ReleaseWithClangCL|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.ReleaseWithTracy|x64.ActiveCfg = ReleaseWithTracy|x64 + {13621B3D-871A-46A0-935F-D92A585AE034}.ReleaseWithTracy|x64.Build.0 = ReleaseWithTracy|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -797,6 +810,7 @@ Global {F3837DDD-BF8B-497F-B876-9934BF472AB3} = {AF31872E-C7A9-4320-A974-649B7A6D20AB} {59A85D5E-C5BB-4402-BDFE-DDE140CADC27} = {F3837DDD-BF8B-497F-B876-9934BF472AB3} {ACCFF71D-6BB0-4B55-9ADA-476E2A7F071F} = {F3837DDD-BF8B-497F-B876-9934BF472AB3} + {13621B3D-871A-46A0-935F-D92A585AE034} = {64A05F50-3203-42CC-B632-09D6EE6EA856} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AC54A867-F976-4B3D-A6EF-F57EB764DCD4} From b4ab385ffa078a92af5072c05b67315fcb85c4e8 Mon Sep 17 00:00:00 2001 From: Nicolas 'Pixel' Noble Date: Wed, 6 May 2026 23:35:01 -0700 Subject: [PATCH 2/7] Phase 1: Replace MiniAudio with SDL3 audio backend. Drops in SDL_AudioStream (pull callback model) as the SPU output backend, preserving the public API surface (feedStreamData, getCurrentFrames, waitForGoal, getBackends, getDevices, reinit) so the SPU and XA paths are unchanged. NullSync is preserved via a dedicated timer thread, since SDL3 only allows one audio driver loaded per process and we can't run a real device alongside a null one the way MiniAudio did. Backend and Device settings are read but the names won't round-trip from prior MiniAudio values (case differences, WinMM->wmme, SDL's device-name format). Settings silently reset to Default on first launch; users re-pick from SPU configuration as needed. Linux/macOS pull SDL3 from system packages (libsdl3-dev / brew); Windows builds it from the third_party/SDL submodule already wired in 2e945f6c. The vsprojects side of this change is still pending. Signed-off-by: Nicolas 'Pixel' Noble --- Makefile | 2 +- src/spu/interface.h | 4 +- src/spu/miniaudio.cc | 245 ---------------------- src/spu/sdlaudio.cc | 306 ++++++++++++++++++++++++++++ src/spu/{miniaudio.h => sdlaudio.h} | 56 +++-- src/spu/spu.cc | 4 +- src/spu/xa.cc | 10 +- 7 files changed, 350 insertions(+), 277 deletions(-) delete mode 100644 src/spu/miniaudio.cc create mode 100644 src/spu/sdlaudio.cc rename src/spu/{miniaudio.h => sdlaudio.h} (79%) diff --git a/Makefile b/Makefile index 0f3218340..3bfba2358 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ UNAME_M := $(shell uname -m) rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) CC_IS_CLANG := $(shell $(CC) --version | grep -q clang && echo true || echo false) -PACKAGES := capstone freetype2 glfw3 libavcodec libavformat libavutil libswresample libcurl libuv zlib +PACKAGES := capstone freetype2 glfw3 libavcodec libavformat libavutil libswresample libcurl libuv sdl3 zlib OPTIONAL_PACKAGES := md4c fmt libllhttp libluv liburiparser OPTIONAL_LIBRARIES := multipart ucl diff --git a/src/spu/interface.h b/src/spu/interface.h index 77643ab6a..088ce0c85 100644 --- a/src/spu/interface.h +++ b/src/spu/interface.h @@ -28,7 +28,7 @@ #include "core/sstate.h" #include "json.hpp" #include "spu/adsr.h" -#include "spu/miniaudio.h" +#include "spu/sdlaudio.h" #include "spu/types.h" #include "support/settings.h" @@ -285,7 +285,7 @@ class impl final : public SPUInterface { int &gvalr(int pos) { return gauss_window[4 + ((gauss_ptr + pos) & 3)]; } ADSR m_adsr; - MiniAudio m_audioOut = {settings}; + SDLAudio m_audioOut = {settings}; xa_decode_t m_cdda; // debug window diff --git a/src/spu/miniaudio.cc b/src/spu/miniaudio.cc deleted file mode 100644 index b67f04589..000000000 --- a/src/spu/miniaudio.cc +++ /dev/null @@ -1,245 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2021 PCSX-Redux authors * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -#include "spu/miniaudio.h" - -#include -#include - -#include "core/system.h" -#include "spu/interface.h" - -#define MINIAUDIO_IMPLEMENTATION -#include "miniaudio/miniaudio.h" - -PCSX::SPU::MiniAudio::MiniAudio(PCSX::SPU::SettingsType& settings) - : m_settings(settings), m_listener(g_system->m_eventBus) { - for (unsigned i = 0; i <= ma_backend_null; i++) { - ma_backend b = ma_backend(i); - if (ma_is_backend_enabled(b)) { - m_backends.push_back(ma_get_backend_name(b)); - } - } - m_listener.listen([this](const auto& event) { - if (ma_device_start(&m_device) != MA_SUCCESS) { - uninit(); - init(true); - } - if (!m_settings.get()) return; - if (ma_device_start(&m_deviceNull) != MA_SUCCESS) { - throw std::runtime_error("Unable to start NULL audio device"); - } - }); - m_listener.listen([this](const auto& event) { - if (ma_device_stop(&m_device) != MA_SUCCESS) { - throw std::runtime_error("Unable to stop audio device"); - }; - if (!ma_device_is_started(&m_deviceNull)) return; - if (ma_device_stop(&m_deviceNull) != MA_SUCCESS) { - throw std::runtime_error("Unable to stop NULL audio device"); - }; - }); - m_listener.listen([this](const auto& event) { init(event.safe); }); -} - -void PCSX::SPU::MiniAudio::init(bool safe) { - // First, initialize NULL device - ma_backend nullContext = ma_backend_null; - if (ma_context_init(&nullContext, 1, NULL, &m_contextNull) != MA_SUCCESS) { - throw std::runtime_error("Error initializing NULL miniaudio context"); - } - - m_configNull = ma_device_config_init(ma_device_type_playback); - m_configNull.playback.format = ma_format_f32; - m_configNull.playback.channels = 2; - m_configNull.sampleRate = 44100; - m_configNull.periodSizeInFrames = 64; - m_configNull.periods = 2; - m_configNull.pUserData = this; - - m_configNull.dataCallback = [](ma_device* device, void* output, const void* input, ma_uint32 frameCount) { - MiniAudio* self = reinterpret_cast(device->pUserData); - self->callbackNull(device, reinterpret_cast(output), frameCount); - }; - - if (ma_device_init(&m_contextNull, &m_configNull, &m_deviceNull) != MA_SUCCESS) { - throw std::runtime_error("Unable to initialize NULL audio device"); - } - - // Then probe for actual device, and initialize it - ma_backend backends[ma_backend_null + 1]; - unsigned count = 0; - if (safe) { - backends[0] = ma_backend_null; - count = 1; - } else { - bool found = false; - for (unsigned i = 0; i <= ma_backend_null; i++) { - ma_backend b = ma_backend(i); - if (!ma_is_backend_enabled(b)) continue; - backends[count++] = b; - if (ma_get_backend_name(b) == m_settings.get().value) { - found = true; - count = 1; - backends[0] = b; - break; - } - } - if (!found) { - m_settings.get().reset(); - } - } - if (ma_context_init(backends, count, NULL, &m_context) != MA_SUCCESS) { - throw std::runtime_error("Error initializing miniaudio context"); - } - - m_devices.clear(); - struct UserContext { - MiniAudio* miniAudio; - ma_device_config& config; - bool found = false; - }; - UserContext userContext = {this, m_config}; - - ma_context_enumerate_devices( - &m_context, - [](ma_context* pContext, ma_device_type deviceType, const ma_device_info* pInfo, void* pUserData) -> ma_bool32 { - if (deviceType != ma_device_type_playback) return true; - UserContext* userContext = reinterpret_cast(pUserData); - userContext->miniAudio->m_devices.push_back(pInfo->name); - if (pInfo->name == userContext->miniAudio->m_settings.get().value) { - userContext->config.playback.pDeviceID = &pInfo->id; - userContext->found = true; - } - return true; - }, - &userContext); - - if (!userContext.found) { - m_settings.get().reset(); - } - - m_config = ma_device_config_init(ma_device_type_playback); - m_config.playback.format = ma_format_f32; - m_config.playback.channels = 2; - m_config.sampleRate = 44100; - m_config.periodSizeInFrames = 64; - m_config.periods = 2; - m_config.pUserData = this; - m_config.aaudio.usage = ma_aaudio_usage_game; - m_config.wasapi.noAutoConvertSRC = true; - - m_config.dataCallback = [](ma_device* device, void* output, const void* input, ma_uint32 frameCount) { - MiniAudio* self = reinterpret_cast(device->pUserData); - self->callback(device, reinterpret_cast(output), frameCount); - }; - - if (ma_device_init(&m_context, &m_config, &m_device) != MA_SUCCESS) { - if (safe) { - throw std::runtime_error("Unable to initialize NULL audio device"); - } - uninit(); - init(true); - } -} - -void PCSX::SPU::MiniAudio::uninit() { - ma_device_uninit(&m_device); - ma_device_uninit(&m_deviceNull); - ma_context_uninit(&m_context); -} - -void PCSX::SPU::MiniAudio::maybeRestart() { - if (!g_system->running()) return; - - if (ma_device_start(&m_device) != MA_SUCCESS) { - uninit(); - init(true); - } - if (!m_settings.get()) return; - if (ma_device_start(&m_deviceNull) != MA_SUCCESS) { - throw std::runtime_error("Unable to start NULL audio device"); - } -} - -void PCSX::SPU::MiniAudio::callback(ma_device* device, float* output, ma_uint32 frameCount) { - if (frameCount > VoiceStream::BUFFER_SIZE) { - throw std::runtime_error("Too many frames requested by miniaudio"); - } - static std::array buffers; - const bool mono = m_settings.get(); - const bool muted = m_settings.get(); - - static_assert(STREAMS == 2); - - for (unsigned i = 0; i < STREAMS; i++) { - size_t a = i == 0 ? m_voicesStream.dequeue(buffers[i].data(), frameCount) - : m_audioStream.dequeue(buffers[i].data(), frameCount); - for (size_t f = (muted ? 0 : a); f < frameCount; f++) { - // maybe warn about underflow? tho it's fine if it happens on stream 1 (cdda) - buffers[i][f] = {}; - } - } - - for (ma_uint32 f = 0; f < frameCount; f++) { - float l = 0.0f, r = 0.0f; - for (unsigned i = 0; i < STREAMS; i++) { - l += static_cast(buffers[i][f].L) / static_cast(std::numeric_limits::max()); - r += static_cast(buffers[i][f].R) / static_cast(std::numeric_limits::max()); - } - - if (mono) { - const float lr = (l + r) * 0.5f; - output[f * 2 + 0] = lr; - output[f * 2 + 1] = lr; - } else { - output[f * 2 + 0] = l; - output[f * 2 + 1] = r; - } - } - - if (m_settings.get()) return; - - callbackNull(device, output, frameCount); -} - -void PCSX::SPU::MiniAudio::callbackNull(ma_device* device, float* output, ma_uint32 frameCount) { - m_frameCount.store(frameCount); - - auto total = m_frames.fetch_add(frameCount); - -#if HAS_ATOMIC_WAIT - auto goalpost = m_goalpost.load(); - if (goalpost == m_previousGoalpost) return; - - if (((int32_t)(goalpost - total)) > 0) return; - m_previousGoalpost = goalpost; - m_triggered++; - m_triggered.notify_one(); -#else - std::unique_lock l(m_mu); - auto goalpost = m_goalpost; - if (goalpost == m_previousGoalpost) return; - - if (((int32_t)(goalpost - total)) > 0) return; - m_previousGoalpost = goalpost; - m_triggered++; - m_cv.notify_one(); -#endif -} diff --git a/src/spu/sdlaudio.cc b/src/spu/sdlaudio.cc new file mode 100644 index 000000000..23e71fce8 --- /dev/null +++ b/src/spu/sdlaudio.cc @@ -0,0 +1,306 @@ +/*************************************************************************** + * Copyright (C) 2026 PCSX-Redux authors * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#include "spu/sdlaudio.h" + +#include +#include +#include +#include +#include +#include + +#include "core/system.h" +#include "spu/interface.h" + +PCSX::SPU::SDLAudio::SDLAudio(PCSX::SPU::SettingsType& settings) + : m_settings(settings), m_listener(g_system->m_eventBus) { + // Enumerate compiled-in drivers. This is static information available before + // SDL_InitSubSystem(SDL_INIT_AUDIO), so we can present the list in the UI without + // forcing an early audio init. + int n = SDL_GetNumAudioDrivers(); + for (int i = 0; i < n; i++) { + const char* name = SDL_GetAudioDriver(i); + if (name) m_backends.emplace_back(name); + } + + m_listener.listen([this](const auto& event) { + if (!m_audioInitialized) return; + if (!SDL_ResumeAudioDevice(m_device)) { + uninit(); + init(true); + } + if (m_settings.get()) startNullThread(); + }); + m_listener.listen([this](const auto& event) { + if (!m_audioInitialized) return; + SDL_PauseAudioDevice(m_device); + stopNullThread(); + }); + m_listener.listen([this](const auto& event) { init(event.safe); }); +} + +void PCSX::SPU::SDLAudio::init(bool safe) { + // Pick the audio driver. SDL_HINT_AUDIO_DRIVER must be set before SDL_InitSubSystem. + if (safe) { + SDL_SetHint(SDL_HINT_AUDIO_DRIVER, "dummy"); + } else { + const std::string& wanted = m_settings.get().value; + bool found = false; + for (const auto& b : m_backends) { + if (b == wanted) { + SDL_SetHint(SDL_HINT_AUDIO_DRIVER, b.c_str()); + found = true; + break; + } + } + if (!found) { + m_settings.get().reset(); + // Empty string lets SDL pick whatever default it likes. + SDL_SetHint(SDL_HINT_AUDIO_DRIVER, ""); + } + } + + // Suggest a small period to keep latency low. SDL treats this as a hint; the actual + // callback chunk size may differ, which is why streamCallback handles arbitrary sizes. + SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, "64"); + + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) { + if (safe) { + throw std::runtime_error(std::string("Unable to initialize SDL audio: ") + SDL_GetError()); + } + uninit(); + init(true); + return; + } + m_audioInitialized = true; + + // Enumerate playback devices and locate the user's saved choice, if any. + m_devices.clear(); + SDL_AudioDeviceID chosen = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; + bool deviceFound = false; + int devCount = 0; + SDL_AudioDeviceID* ids = SDL_GetAudioPlaybackDevices(&devCount); + if (ids) { + const std::string& wantedDev = m_settings.get().value; + for (int i = 0; i < devCount; i++) { + const char* name = SDL_GetAudioDeviceName(ids[i]); + if (!name) continue; + m_devices.emplace_back(name); + if (name == wantedDev) { + chosen = ids[i]; + deviceFound = true; + } + } + SDL_free(ids); + } + if (!deviceFound) { + m_settings.get().reset(); + } + + SDL_AudioSpec spec; + spec.format = SDL_AUDIO_F32; + spec.channels = kChannels; + spec.freq = kSampleRate; + + m_device = SDL_OpenAudioDevice(chosen, &spec); + if (m_device == 0) { + if (safe) { + throw std::runtime_error(std::string("Unable to open SDL audio device: ") + SDL_GetError()); + } + uninit(); + init(true); + return; + } + + m_stream = SDL_CreateAudioStream(&spec, &spec); + if (!m_stream) { + const std::string err = SDL_GetError(); + SDL_CloseAudioDevice(m_device); + m_device = 0; + if (safe) { + throw std::runtime_error("Unable to create SDL audio stream: " + err); + } + uninit(); + init(true); + return; + } + + auto trampoline = [](void* userdata, SDL_AudioStream* stream, int additional, int /*total*/) { + static_cast(userdata)->streamCallback(stream, additional); + }; + if (!SDL_SetAudioStreamGetCallback(m_stream, trampoline, this)) { + const std::string err = SDL_GetError(); + SDL_DestroyAudioStream(m_stream); + m_stream = nullptr; + SDL_CloseAudioDevice(m_device); + m_device = 0; + throw std::runtime_error("Unable to set SDL audio stream callback: " + err); + } + + if (!SDL_BindAudioStream(m_device, m_stream)) { + const std::string err = SDL_GetError(); + SDL_DestroyAudioStream(m_stream); + m_stream = nullptr; + SDL_CloseAudioDevice(m_device); + m_device = 0; + throw std::runtime_error("Unable to bind SDL audio stream: " + err); + } + + // Devices come up in the resumed state; pause until execution actually starts so + // we don't burn cycles streaming silence at boot. + SDL_PauseAudioDevice(m_device); +} + +void PCSX::SPU::SDLAudio::uninit() { + stopNullThread(); + if (m_stream) { + SDL_DestroyAudioStream(m_stream); + m_stream = nullptr; + } + if (m_device) { + SDL_CloseAudioDevice(m_device); + m_device = 0; + } + if (m_audioInitialized) { + SDL_QuitSubSystem(SDL_INIT_AUDIO); + m_audioInitialized = false; + } +} + +void PCSX::SPU::SDLAudio::maybeRestart() { + if (!g_system->running()) return; + if (!m_audioInitialized) return; + if (!SDL_ResumeAudioDevice(m_device)) { + uninit(); + init(true); + return; + } + if (m_settings.get()) startNullThread(); +} + +void PCSX::SPU::SDLAudio::streamCallback(SDL_AudioStream* stream, int additionalBytes) { + constexpr int kFrameSizeBytes = sizeof(float) * kChannels; + int requested = additionalBytes / kFrameSizeBytes; + if (requested <= 0) return; + + const bool mono = m_settings.get(); + const bool muted = m_settings.get(); + + static_assert(STREAMS == 2); + + // SDL doesn't promise a fixed callback chunk size, so feed in slices that fit our + // mixing scratch buffer. + while (requested > 0) { + const uint32_t chunk = std::min(requested, VoiceStream::BUFFER_SIZE); + + for (unsigned i = 0; i < STREAMS; i++) { + size_t a = (i == 0) ? m_voicesStream.dequeue(m_mixBuffers[i].data(), chunk) + : m_audioStream.dequeue(m_mixBuffers[i].data(), chunk); + for (size_t f = (muted ? 0 : a); f < chunk; f++) { + // Same as the previous backend: silently zero-fill on underflow. + // CDDA underflow on stream 1 is expected and fine. + m_mixBuffers[i][f] = {}; + } + } + + for (uint32_t f = 0; f < chunk; f++) { + float l = 0.0f, r = 0.0f; + for (unsigned i = 0; i < STREAMS; i++) { + l += static_cast(m_mixBuffers[i][f].L) / + static_cast(std::numeric_limits::max()); + r += static_cast(m_mixBuffers[i][f].R) / + static_cast(std::numeric_limits::max()); + } + + if (mono) { + const float lr = (l + r) * 0.5f; + m_outputBuffer[f * 2 + 0] = lr; + m_outputBuffer[f * 2 + 1] = lr; + } else { + m_outputBuffer[f * 2 + 0] = l; + m_outputBuffer[f * 2 + 1] = r; + } + } + + SDL_PutAudioStreamData(stream, m_outputBuffer.data(), chunk * kFrameSizeBytes); + + // When NullSync is off, the real audio callback is the timing source. When it's + // on, the dedicated null thread drives timing instead. + if (!m_settings.get()) { + advanceFrames(chunk); + } + + requested -= chunk; + } +} + +void PCSX::SPU::SDLAudio::advanceFrames(uint32_t frameCount) { + m_frameCount.store(frameCount); + + auto total = m_frames.fetch_add(frameCount); + +#if HAS_ATOMIC_WAIT + auto goalpost = m_goalpost.load(); + if (goalpost == m_previousGoalpost) return; + + if (((int32_t)(goalpost - total)) > 0) return; + m_previousGoalpost = goalpost; + m_triggered++; + m_triggered.notify_one(); +#else + std::unique_lock l(m_mu); + auto goalpost = m_goalpost; + if (goalpost == m_previousGoalpost) return; + + if (((int32_t)(goalpost - total)) > 0) return; + m_previousGoalpost = goalpost; + m_triggered++; + m_cv.notify_one(); +#endif +} + +void PCSX::SPU::SDLAudio::startNullThread() { + if (m_nullThreadActive) return; + m_nullThreadStop.store(false); + m_nullThreadActive = true; + m_nullThread = std::thread([this]() { nullThreadLoop(); }); +} + +void PCSX::SPU::SDLAudio::stopNullThread() { + if (!m_nullThreadActive) return; + m_nullThreadStop.store(true); + if (m_nullThread.joinable()) m_nullThread.join(); + m_nullThreadActive = false; +} + +void PCSX::SPU::SDLAudio::nullThreadLoop() { + using namespace std::chrono; + // 64 frames at 44100 Hz ~= 1.451 ms per tick. We pretend to consume that many frames + // each tick, mirroring what miniaudio's null backend used to do for a stable timing + // source independent of the real device's bursty callbacks. + constexpr double periodSeconds = static_cast(kPeriodFrames) / kSampleRate; + const auto periodNs = duration_cast(duration(periodSeconds)); + auto next = steady_clock::now(); + while (!m_nullThreadStop.load()) { + next += periodNs; + std::this_thread::sleep_until(next); + advanceFrames(kPeriodFrames); + } +} diff --git a/src/spu/miniaudio.h b/src/spu/sdlaudio.h similarity index 79% rename from src/spu/miniaudio.h rename to src/spu/sdlaudio.h index f2c0d5a24..725ad9c50 100644 --- a/src/spu/miniaudio.h +++ b/src/spu/sdlaudio.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2021 PCSX-Redux authors * + * Copyright (C) 2026 PCSX-Redux authors * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -23,18 +23,15 @@ #include #include +#include +#include +#include #include +#include #include -#define MA_NO_CUSTOM -#define MA_NO_DECODING -#define MA_NO_ENCODING -#define MA_NO_FLAC -#define MA_NO_GENERATION -#define MA_NO_MP3 -#define MA_NO_WAV +#include -#include "miniaudio/miniaudio.h" #include "spu/settings.h" #include "support/circular.h" #include "support/eventbus.h" @@ -48,14 +45,14 @@ namespace PCSX { namespace SPU { -class MiniAudio { +class SDLAudio { public: struct Frame { int16_t L = 0, R = 0; }; - MiniAudio(SettingsType& settings); - ~MiniAudio() { uninit(); } - ma_uint32 getFrameCount() { return m_frameCount.load(); } + SDLAudio(SettingsType& settings); + ~SDLAudio() { uninit(); } + uint32_t getFrameCount() { return m_frameCount.load(); } void reinit() { uninit(); init(); @@ -108,25 +105,40 @@ class MiniAudio { private: static constexpr unsigned STREAMS = 2; + static constexpr int kSampleRate = 44100; + static constexpr int kChannels = 2; + static constexpr int kPeriodFrames = 64; + SettingsType& m_settings; - void callback(ma_device* device, float* output, ma_uint32 frameCount); - void callbackNull(ma_device* device, float* output, ma_uint32 frameCount); + + void streamCallback(SDL_AudioStream* stream, int additionalBytes); + void advanceFrames(uint32_t frameCount); void init(bool safe = false); void uninit(); void maybeRestart(); + void startNullThread(); + void stopNullThread(); + void nullThreadLoop(); + + SDL_AudioDeviceID m_device = 0; + SDL_AudioStream* m_stream = nullptr; + bool m_audioInitialized = false; + + std::thread m_nullThread; + std::atomic m_nullThreadStop{false}; + bool m_nullThreadActive = false; - ma_context m_context; - ma_device_config m_config; - ma_device m_device; - ma_context m_contextNull; - ma_device_config m_configNull; - ma_device m_deviceNull; EventBus::Listener m_listener; typedef Circular VoiceStream; VoiceStream m_voicesStream; Circular m_audioStream; typedef std::array Buffer; + + // Mixing scratch space, only ever touched from the SDL audio thread. + std::array m_mixBuffers; + std::array m_outputBuffer; + std::atomic m_frames = 0; #if HAS_ATOMIC_WAIT std::atomic m_goalpost = 0; @@ -142,7 +154,7 @@ class MiniAudio { std::vector m_backends; std::vector m_devices; - std::atomic m_frameCount; + std::atomic m_frameCount{0}; }; } // namespace SPU diff --git a/src/spu/spu.cc b/src/spu/spu.cc index 0a86a0a9e..d5e47e449 100644 --- a/src/spu/spu.cc +++ b/src/spu/spu.cc @@ -797,8 +797,8 @@ void PCSX::SPU::impl::MainThread() { bool done = false; while (!done) { done = - m_audioOut.feedStreamData(reinterpret_cast(pSpuBuffer), - (((uint8_t *)pS) - ((uint8_t *)pSpuBuffer)) / sizeof(MiniAudio::Frame)); + m_audioOut.feedStreamData(reinterpret_cast(pSpuBuffer), + (((uint8_t *)pS) - ((uint8_t *)pSpuBuffer)) / sizeof(SDLAudio::Frame)); if (bEndThread) { bThreadEnded = 1; return; diff --git a/src/spu/xa.cc b/src/spu/xa.cc index ad7871a55..15ed48c2d 100644 --- a/src/spu/xa.cc +++ b/src/spu/xa.cc @@ -43,8 +43,8 @@ static uint16_t hiword(uint32_t v) { return (v >> 16) & 0xffff; } void PCSX::SPU::impl::FeedXA(xa_decode_t *xap) { int sinc, spos, i, iSize, vl, vr, voldiv = 4 - settings.get(); - MiniAudio::Frame XABuffer[32 * 1024]; - MiniAudio::Frame *XAFeed = XABuffer; + SDLAudio::Frame XABuffer[32 * 1024]; + SDLAudio::Frame *XAFeed = XABuffer; if (!bSPUIsOpen) return; @@ -94,7 +94,7 @@ void PCSX::SPU::impl::FeedXA(xa_decode_t *xap) { } } - MiniAudio::Frame f; + SDLAudio::Frame f; int16_t rawSampleL = static_cast(l & 0xffff); int16_t rawSampleR = static_cast(l >> 16); if (pMixIrq) { @@ -138,7 +138,7 @@ void PCSX::SPU::impl::FeedXA(xa_decode_t *xap) { l = s; } - MiniAudio::Frame f; + SDLAudio::Frame f; int16_t rawSampleL = static_cast(l & 0xffff); int16_t rawSampleR = static_cast(l >> 16); // Write the CD-XA samples (left/right) to a temporary buffer. Wrap around if necessary. @@ -159,5 +159,5 @@ void PCSX::SPU::impl::FeedXA(xa_decode_t *xap) { } if (pMixIrq) cbMtx.unlock(); - m_audioOut.feedStreamData(reinterpret_cast(XABuffer), (XAFeed - XABuffer), 1); + m_audioOut.feedStreamData(reinterpret_cast(XABuffer), (XAFeed - XABuffer), 1); } From 9fc2bdbd7366e90d9008ca6014331c9b2bd5fccf Mon Sep 17 00:00:00 2001 From: Nicolas Pixel Noble Date: Thu, 7 May 2026 08:11:13 -0700 Subject: [PATCH 3/7] Windows build. --- vsprojects/SPU/SPU.vcxproj | 4 ++-- vsprojects/SPU/SPU.vcxproj.filters | 6 +++--- vsprojects/mainthunk/mainthunk.vcxproj | 3 +++ vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj | 3 +++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/vsprojects/SPU/SPU.vcxproj b/vsprojects/SPU/SPU.vcxproj index 5fafd8667..482347ac2 100644 --- a/vsprojects/SPU/SPU.vcxproj +++ b/vsprojects/SPU/SPU.vcxproj @@ -119,9 +119,9 @@ - + @@ -130,8 +130,8 @@ - + diff --git a/vsprojects/SPU/SPU.vcxproj.filters b/vsprojects/SPU/SPU.vcxproj.filters index 9af191668..516acdc20 100644 --- a/vsprojects/SPU/SPU.vcxproj.filters +++ b/vsprojects/SPU/SPU.vcxproj.filters @@ -42,7 +42,7 @@ Source Files - + Source Files @@ -65,10 +65,10 @@ Header Files - + Header Files - + Header Files diff --git a/vsprojects/mainthunk/mainthunk.vcxproj b/vsprojects/mainthunk/mainthunk.vcxproj index 7b1bad211..a5401ce56 100644 --- a/vsprojects/mainthunk/mainthunk.vcxproj +++ b/vsprojects/mainthunk/mainthunk.vcxproj @@ -270,6 +270,9 @@ {b68e9c60-8362-4a32-ac2e-4f0c2673f3e1} + + {13621b3d-871a-46a0-935f-d92a585ae034} + {660a9963-15e0-4b91-a5cf-bed493e862ec} diff --git a/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj b/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj index 818db4e73..eb0b31041 100644 --- a/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj +++ b/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj @@ -221,6 +221,9 @@ {b68e9c60-8362-4a32-ac2e-4f0c2673f3e1} + + {13621b3d-871a-46a0-935f-d92a585ae034} + {660a9963-15e0-4b91-a5cf-bed493e862ec} From b6e9bd0efa0e9441daaf79057efff11b3aecd239 Mon Sep 17 00:00:00 2001 From: Nicolas 'Pixel' Noble Date: Thu, 7 May 2026 08:41:47 -0700 Subject: [PATCH 4/7] Phase 2: Replace GLFW gamepad input with SDL3. Swaps the gamepad polling backend in core/pad.cc to SDL_Gamepad, inheriting SDL's gamecontrollerdb.txt mapping pipeline so controllers GLFW didn't recognize (PS5, recent Xbox revs, etc.) work out of the box. Hot-plug detection moves to draining SDL_EVENT_GAMEPAD_ADDED/ REMOVED on each poll, replacing GLFW's joystick callback. Settings defaults migrated from GLFW_GAMEPAD_BUTTON_* to SDL_GAMEPAD_BUTTON_*. Synthetic LEFT_TRIGGER/RIGHT_TRIGGER/INVALID sentinels move to PCSX_GAMEPAD_BUTTON_* values that don't collide with SDL's enum. The in-tree UI doesn't expose per-button rebinding, so the only users affected by the enum-format change are those who hand-edited their config JSON; their saved Controller_Pad* values will not round-trip and will need to be re-set to defaults. Keyboard input still flows through imgui_impl_glfw -> ImGui::IsKeyDown, so Keyboard_* settings continue to use GLFW_KEY_* constants. Keyboard moves with the window/ImGui-backend swap in Phase 3. Rumble plumbing deferred per directive. SDL event polling for gamepad hotplug currently lives inline in Pad::getButtons(); will move to the central event pump when Phase 3 takes ownership of the event loop. Signed-off-by: Nicolas 'Pixel' Noble --- src/core/pad.cc | 233 ++++++++++++++++++++++++++++++------------------ 1 file changed, 148 insertions(+), 85 deletions(-) diff --git a/src/core/pad.cc b/src/core/pad.cc index efb2af7a3..8e283afd3 100644 --- a/src/core/pad.cc +++ b/src/core/pad.cc @@ -22,6 +22,7 @@ #include "core/pad.h" #include +#include #include #include @@ -69,13 +70,18 @@ class PadsImpl : public PCSX::Pads { private: PCSX::EventBus::Listener m_listener; - // This is a list of all of the valid GLFW gamepad IDs that we have found querying GLFW. - // A value of -1 means that there is no gamepad at that index. - int m_gamepadsMap[16] = {0}; - - static constexpr int GLFW_GAMEPAD_BUTTON_LEFT_TRIGGER = GLFW_GAMEPAD_BUTTON_LAST + 1; - static constexpr int GLFW_GAMEPAD_BUTTON_RIGHT_TRIGGER = GLFW_GAMEPAD_BUTTON_LAST + 2; - static constexpr int GLFW_GAMEPAD_BUTTON_INVALID = GLFW_GAMEPAD_BUTTON_LAST + 3; + // Open SDL gamepad handles, one per slot we've discovered. nullptr means the + // slot is unused. The slot index doubles as the user-visible "controller ID" + // saved in SettingControllerID. + SDL_Gamepad* m_gamepads[16] = {nullptr}; + + // Triggers are reported as axes by SDL but pad bindings treat them as + // virtual buttons. INVALID is encoded as SDL_GAMEPAD_BUTTON_INVALID (-1) so + // raw SDL queries naturally short-circuit. The trigger sentinels live above + // SDL_GAMEPAD_BUTTON_COUNT to avoid collisions with future enum entries. + static constexpr int PCSX_GAMEPAD_BUTTON_LEFT_TRIGGER = 100; + static constexpr int PCSX_GAMEPAD_BUTTON_RIGHT_TRIGGER = 101; + static constexpr int PCSX_GAMEPAD_BUTTON_INVALID = SDL_GAMEPAD_BUTTON_INVALID; // settings block // Pad keyboard bindings @@ -97,24 +103,28 @@ class PadsImpl : public PCSX::Pads { typedef PCSX::Setting Keyboard_PadR3; typedef PCSX::Setting Keyboard_AnalogMode; - // Pad controller bindings - typedef PCSX::Setting Controller_PadUp; - typedef PCSX::Setting Controller_PadRight; - typedef PCSX::Setting Controller_PadDown; - typedef PCSX::Setting Controller_PadLeft; - typedef PCSX::Setting Controller_PadCross; - typedef PCSX::Setting + // Pad controller bindings. Defaults reference SDL gamepad button enums + // (PS-style face buttons via SDL_GAMEPAD_BUTTON_SOUTH/EAST/WEST/NORTH). + // Existing user configs that hand-edited these values to GLFW button enums + // will not round-trip; the in-tree UI does not expose per-button rebinding, + // so the impact is limited to hand-rolled JSON. + typedef PCSX::Setting Controller_PadUp; + typedef PCSX::Setting Controller_PadRight; + typedef PCSX::Setting Controller_PadDown; + typedef PCSX::Setting Controller_PadLeft; + typedef PCSX::Setting Controller_PadCross; + typedef PCSX::Setting Controller_PadTriangle; - typedef PCSX::Setting Controller_PadSquare; - typedef PCSX::Setting Controller_PadCircle; - typedef PCSX::Setting Controller_PadSelect; - typedef PCSX::Setting Controller_PadStart; - typedef PCSX::Setting Controller_PadL1; - typedef PCSX::Setting Controller_PadL2; - typedef PCSX::Setting Controller_PadL3; - typedef PCSX::Setting Controller_PadR1; - typedef PCSX::Setting Controller_PadR2; - typedef PCSX::Setting Controller_PadR3; + typedef PCSX::Setting Controller_PadSquare; + typedef PCSX::Setting Controller_PadCircle; + typedef PCSX::Setting Controller_PadSelect; + typedef PCSX::Setting Controller_PadStart; + typedef PCSX::Setting Controller_PadL1; + typedef PCSX::Setting Controller_PadL2; + typedef PCSX::Setting Controller_PadL3; + typedef PCSX::Setting Controller_PadR1; + typedef PCSX::Setting Controller_PadR2; + typedef PCSX::Setting Controller_PadR3; typedef PCSX::Setting SettingInputType; // These typestrings are kind of odd, but it's best not to change so as not to break old config files @@ -165,7 +175,11 @@ class PadsImpl : public PCSX::Pads { uint8_t poll(uint8_t value, uint32_t& padState); uint8_t doDualshockCommand(uint32_t& padState); void getButtons(); - bool isControllerButtonPressed(int button, GLFWgamepadstate* state); + struct GamepadState { + bool buttons[SDL_GAMEPAD_BUTTON_COUNT]; + float axes[SDL_GAMEPAD_AXIS_COUNT]; // normalized to [-1, 1] like GLFW reported + }; + bool isControllerButtonPressed(int button, const GamepadState& state); bool isControllerConnected() { return m_settings.get(); } json getCfg(); @@ -183,7 +197,7 @@ class PadsImpl : public PCSX::Pads { PadType m_type; PadData m_data; - int m_padID = -1; + SDL_Gamepad* m_gamepad = nullptr; int m_buttonToWait = -1; bool m_changed = false; @@ -426,11 +440,9 @@ static ImGuiKey GlfwKeyToImGuiKey(int key) { void PadsImpl::init() { s_pads = this; - scanGamepads(); - glfwSetJoystickCallback([](int jid, int event) { - s_pads->scanGamepads(); - s_pads->map(); - }); + if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD)) { + PCSX::g_system->log(PCSX::LogClass::UI, "SDL_InitSubSystem(SDL_INIT_GAMEPAD) failed: %s\n", SDL_GetError()); + } PCSX::g_system->findResource( [](const std::filesystem::path& filename) -> bool { PCSX::IO database(new PCSX::PosixFile(filename)); @@ -441,17 +453,27 @@ void PadsImpl::init() { size_t dbsize = database->size(); auto dbStr = database->readString(dbsize); - int ret = glfwUpdateGamepadMappings(dbStr.c_str()); - - return ret; + // Wrap the in-memory buffer as an SDL_IOStream so SDL parses the + // mapping DB using the same routine it uses for files. + SDL_IOStream* io = SDL_IOFromConstMem(dbStr.data(), dbStr.size()); + if (!io) return false; + int ret = SDL_AddGamepadMappingsFromIO(io, true /* closeio */); + return ret > 0; }, "gamecontrollerdb.txt", "resources", std::filesystem::path("third_party") / "SDL_GameControllerDB"); + scanGamepads(); reset(); map(); } void PadsImpl::shutdown() { - glfwSetJoystickCallback(nullptr); + for (auto& g : m_gamepads) { + if (g) { + SDL_CloseGamepad(g); + g = nullptr; + } + } + SDL_QuitSubSystem(SDL_INIT_GAMEPAD); s_pads = nullptr; } @@ -464,16 +486,23 @@ PadsImpl::PadsImpl() : m_listener(PCSX::g_system->m_eventBus) { } void PadsImpl::scanGamepads() { - static_assert((1 + GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1) <= sizeof(m_gamepadsMap) / sizeof(m_gamepadsMap[0])); - for (auto& m : m_gamepadsMap) { - m = -1; - } - unsigned index = 0; - for (int i = GLFW_JOYSTICK_1; i < GLFW_JOYSTICK_LAST; i++) { - if (glfwJoystickPresent(i) && glfwJoystickIsGamepad(i)) { - m_gamepadsMap[index++] = i; + // Close any currently-open handles so re-scans (e.g. after hotplug) don't + // leak. m_gamepad pointers in each Pad become stale here; the caller is + // expected to follow up with map() to re-resolve them. + for (auto& g : m_gamepads) { + if (g) { + SDL_CloseGamepad(g); + g = nullptr; } } + int count = 0; + SDL_JoystickID* ids = SDL_GetGamepads(&count); + if (!ids) return; + const unsigned slots = sizeof(m_gamepads) / sizeof(m_gamepads[0]); + for (int i = 0; i < count && static_cast(i) < slots; i++) { + m_gamepads[i] = SDL_OpenGamepad(ids[i]); + } + SDL_free(ids); } void PadsImpl::reset() { @@ -497,7 +526,9 @@ void PadsImpl::map() { } void PadsImpl::Pad::map() { - m_padID = s_pads->m_gamepadsMap[m_settings.get()]; + int id = m_settings.get(); + const unsigned slots = sizeof(s_pads->m_gamepads) / sizeof(s_pads->m_gamepads[0]); + m_gamepad = (id >= 0 && static_cast(id) < slots) ? s_pads->m_gamepads[id] : nullptr; m_type = m_settings.get(); // L3/R3 are only avalable on analog controllers @@ -509,8 +540,8 @@ void PadsImpl::Pad::map() { } else { m_scancodes[1] = 255; m_scancodes[2] = 255; - m_padMapping[1] = GLFW_GAMEPAD_BUTTON_INVALID; - m_padMapping[2] = GLFW_GAMEPAD_BUTTON_INVALID; + m_padMapping[1] = PCSX_GAMEPAD_BUTTON_INVALID; + m_padMapping[2] = PCSX_GAMEPAD_BUTTON_INVALID; } // keyboard mappings @@ -549,18 +580,18 @@ void PadsImpl::Pad::map() { static constexpr float THRESHOLD = 0.85f; // Certain buttons on controllers are actually axis that can be pressed, half-pressed, etc. -bool PadsImpl::Pad::isControllerButtonPressed(int button, GLFWgamepadstate* state) { +bool PadsImpl::Pad::isControllerButtonPressed(int button, const GamepadState& state) { int mapped = m_padMapping[button]; switch (mapped) { - case GLFW_GAMEPAD_BUTTON_LEFT_TRIGGER: - return state->axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER] >= THRESHOLD; - case GLFW_GAMEPAD_BUTTON_RIGHT_TRIGGER: - return state->axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER] >= THRESHOLD; - case GLFW_GAMEPAD_BUTTON_INVALID: + case PCSX_GAMEPAD_BUTTON_LEFT_TRIGGER: + return state.axes[SDL_GAMEPAD_AXIS_LEFT_TRIGGER] >= THRESHOLD; + case PCSX_GAMEPAD_BUTTON_RIGHT_TRIGGER: + return state.axes[SDL_GAMEPAD_AXIS_RIGHT_TRIGGER] >= THRESHOLD; + case PCSX_GAMEPAD_BUTTON_INVALID: return false; default: - return state->buttons[mapped]; - break; + if (mapped < 0 || mapped >= SDL_GAMEPAD_BUTTON_COUNT) return false; + return state.buttons[mapped]; } } @@ -574,8 +605,8 @@ void PadsImpl::Pad::getButtons() { return; } - GLFWgamepadstate state; - int hasPad = GLFW_FALSE; + GamepadState state{}; + bool hasPad = false; const auto& inputType = m_settings.get(); auto getKeyboardButtons = [this]() -> uint16_t { @@ -595,12 +626,37 @@ void PadsImpl::Pad::getButtons() { return; } - if ((m_padID >= GLFW_JOYSTICK_1) && (m_padID <= GLFW_JOYSTICK_LAST)) { - hasPad = glfwGetGamepadState(m_padID, &state); - if (!hasPad) { - const char* guid = glfwGetJoystickGUID(m_padID); - PCSX::g_system->printf("Gamepad error: GUID %s likely has no database mapping, disabling pad\n", guid); - m_padID = -1; + // Drive SDL's internal gamepad state and pluck out hotplug events. Other + // SDL events stay in the queue (gui.cc still owns the rest of the input + // surface today). Move this to the central event pump when Phase 3 lands. + SDL_PumpEvents(); + { + SDL_Event scratch[16]; + int drained = SDL_PeepEvents(scratch, 16, SDL_GETEVENT, SDL_EVENT_GAMEPAD_ADDED, SDL_EVENT_GAMEPAD_REMOVED); + if (drained > 0) { + s_pads->scanGamepads(); + s_pads->map(); + } + } + + if (m_gamepad) { + if (!SDL_GamepadConnected(m_gamepad)) { + const SDL_JoystickID jid = SDL_GetGamepadID(m_gamepad); + PCSX::g_system->printf("Gamepad error: joystick id %u disconnected, disabling pad\n", + static_cast(jid)); + m_gamepad = nullptr; + } else { + for (int i = 0; i < SDL_GAMEPAD_BUTTON_COUNT; i++) { + state.buttons[i] = SDL_GetGamepadButton(m_gamepad, static_cast(i)); + } + // SDL reports axes as int16_t [-32768, 32767]. Triggers are signed but + // only ever positive in practice. Normalize to [-1, 1] to match the + // shape the rest of this code was built around. + for (int i = 0; i < SDL_GAMEPAD_AXIS_COUNT; i++) { + int16_t raw = SDL_GetGamepadAxis(m_gamepad, static_cast(i)); + state.axes[i] = raw < 0 ? raw / 32768.0f : raw / 32767.0f; + } + hasPad = true; } } @@ -617,13 +673,13 @@ void PadsImpl::Pad::getButtons() { bool buttons[16]; for (unsigned i = 0; i < 16; i++) { - buttons[i] = isControllerButtonPressed(i, &state); + buttons[i] = isControllerButtonPressed(i, state); } // For digital gamepads, make the PS1 dpad controllable with our gamepad's left analog stick if (m_type == PadType::Digital) { - float x = state.axes[GLFW_GAMEPAD_AXIS_LEFT_X]; - float y = -state.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]; + float x = state.axes[SDL_GAMEPAD_AXIS_LEFTX]; + float y = -state.axes[SDL_GAMEPAD_AXIS_LEFTY]; float ds = x * x + y * y; if (ds >= THRESHOLD * THRESHOLD) { float d = std::sqrt(ds); @@ -667,10 +723,10 @@ void PadsImpl::Pad::getButtons() { const float scaledValue = std::clamp(axis * scale, -1.0f, 1.0f); return (uint8_t)(std::clamp(std::round(((scaledValue + 1.0f) / 2.0f) * 255.0f), 0.0f, 255.0f)); }; - pad.leftJoyX = axisToUint8(state.axes[GLFW_GAMEPAD_AXIS_LEFT_X]); - pad.leftJoyY = axisToUint8(state.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]); - pad.rightJoyX = axisToUint8(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_X]); - pad.rightJoyY = axisToUint8(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y]); + pad.leftJoyX = axisToUint8(state.axes[SDL_GAMEPAD_AXIS_LEFTX]); + pad.leftJoyY = axisToUint8(state.axes[SDL_GAMEPAD_AXIS_LEFTY]); + pad.rightJoyX = axisToUint8(state.axes[SDL_GAMEPAD_AXIS_RIGHTX]); + pad.rightJoyY = axisToUint8(state.axes[SDL_GAMEPAD_AXIS_RIGHTY]); } uint16_t result = 0; @@ -1111,27 +1167,34 @@ bool PadsImpl::Pad::configure() { const char* preview = _("No gamepad selected or connected"); auto& id = m_settings.get().value; - int glfwjid = id >= 0 ? s_pads->m_gamepadsMap[id] : -1; - - std::vector gamepadsNames; - - for (auto& m : s_pads->m_gamepadsMap) { - if (m == -1) { - continue; - } - const char* name = glfwGetGamepadName(m); - gamepadsNames.push_back(name); - if (m == glfwjid) { - preview = name; - } + SDL_Gamepad* selected = (id >= 0 && static_cast(id) < + sizeof(s_pads->m_gamepads) / sizeof(s_pads->m_gamepads[0])) + ? s_pads->m_gamepads[id] + : nullptr; + + // Slot index -> displayable name. Empty slots are skipped during render but + // we keep the slot index so the user's saved SettingControllerID continues + // to refer to the same physical position. + struct Entry { + int slot; + const char* name; + }; + std::vector gamepads; + for (unsigned i = 0; i < sizeof(s_pads->m_gamepads) / sizeof(s_pads->m_gamepads[0]); i++) { + SDL_Gamepad* g = s_pads->m_gamepads[i]; + if (!g) continue; + const char* name = SDL_GetGamepadName(g); + if (!name) name = ""; + gamepads.push_back({static_cast(i), name}); + if (g == selected) preview = name; } if (ImGui::BeginCombo(_("Gamepad"), preview)) { - for (int i = 0; i < gamepadsNames.size(); i++) { - const auto gamepadName = fmt::format("{}##{}", gamepadsNames[i], i); + for (const auto& entry : gamepads) { + const auto gamepadName = fmt::format("{}##{}", entry.name, entry.slot); if (ImGui::Selectable(gamepadName.c_str())) { changed = true; - id = i; + id = entry.slot; map(); } } From fae2c450138098a7d0d41e7b244a8aa23a3b76df Mon Sep 17 00:00:00 2001 From: Nicolas 'Pixel' Noble Date: Fri, 8 May 2026 21:17:54 -0700 Subject: [PATCH 5/7] Phase 3: Replace GLFW with SDL3 for window, GL context, ImGui backend, keyboard input, and high-DPI plumbing. Window/GL: SDL_CreateWindow + SDL_GL_CreateContext replace GLFW's combined glfwCreateWindow. The 3.2-core / 3.0-fallback retry now covers context creation since SDL splits window and context, and destroys+recreates both on first failure rather than just the window. SDL_WINDOW_HIGH_PIXEL_DENSITY makes the window/pixel split meaningful on macOS Retina and Windows per-monitor DPI. Event loop: GLFW callback installation (install_callbacks=true on the imgui_impl_glfw side) replaced with an explicit SDL_PollEvent loop in startFrame() that hands every event to ImGui_ImplSDL3_ProcessEvent first, then dispatches close/resize/drop/key locally. Fixes the recurring high-DPI bug: GLFW didn't fire when crossing monitors with different DPI on Windows; SDL3 fires SDL_EVENT_WINDOW_DISPLAY_CHANGED, which we now route to changeScale + a font rebuild. ImGui backend: imgui_impl_glfw -> imgui_impl_sdl3, viewport callback hooks (Platform_CreateWindow / OnChangedViewport / DestroyWindow) preserved; the per-window key callback that the GLFW backend needed is gone since the SDL3 backend dispatches via ProcessEvent. Input mode: SDL_SetWindowRelativeMouseMode collapses GLFW's two-step (CURSOR_DISABLED + RAW_MOUSE_MOTION) into one call. SDL3 fullscreen with no mode set produces borderless desktop, matching GLFW's glfwSetWindowMonitor(..., GLFW_DONT_CARE). Keyboard: pad bindings now store SDL_Scancode values; SdlScancodeToImGuiKey replaces GlfwKeyToImGuiKey, sdlScancodeToString replaces glfwKeyToString using SDL_GetScancodeName for the layout-aware label. The keyboard event signal carries SDL_Scancode in Events::Keyboard.scancode and the rebinding UI reads .scancode (not .key) so writes and reads agree on the integer's meaning. NanoVG: cleanup ordering corrected so sub-contexts and the main context are deleted while their owning GL context is still live; the GLFW-era code freed them after glfwDestroyWindow, technically leaking GPU resources. Migration impact - keyboard bindings: settings serialize every field including defaults, so all existing pcsx.json files carry seventeen Keyboard_* keys with GLFW_KEY_* integers saved. After this change those values get interpreted as SDL_Scancode integers, which produces nonsense bindings on first launch with the new build. Per directive, no in-place migration is provided; users will need to either delete the pad config block from their pcsx.json or rebind in the SPU/Pad configuration UI once. This is a one-time cost on the upgrade path. Stale GLFW includes removed from src/gui/widgets/assembly.cc and src/gui/widgets/zep.cc (no API calls were ever made through them, just stray includes). Makefile: glfw3 dropped from PACKAGES, imgui_impl_glfw.cpp swapped for imgui_impl_sdl3.cpp in SRCS. Phase 4 (cleaning up the unused miniaudio submodule and any final references) lands separately. Signed-off-by: Nicolas 'Pixel' Noble --- Makefile | 4 +- src/core/pad.cc | 407 ++++++++++++++---------------------- src/gui/gui.cc | 255 +++++++++++++--------- src/gui/gui.h | 23 +- src/gui/widgets/assembly.cc | 2 - src/gui/widgets/zep.cc | 1 - 6 files changed, 324 insertions(+), 368 deletions(-) diff --git a/Makefile b/Makefile index 3bfba2358..71545ca23 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ UNAME_M := $(shell uname -m) rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) CC_IS_CLANG := $(shell $(CC) --version | grep -q clang && echo true || echo false) -PACKAGES := capstone freetype2 glfw3 libavcodec libavformat libavutil libswresample libcurl libuv sdl3 zlib +PACKAGES := capstone freetype2 libavcodec libavformat libavutil libswresample libcurl libuv sdl3 zlib OPTIONAL_PACKAGES := md4c fmt libllhttp libluv liburiparser OPTIONAL_LIBRARIES := multipart ucl @@ -124,7 +124,7 @@ SRCS += third_party/gl3w/GL/gl3w-throwers.cc SRCS += $(wildcard third_party/iec-60908b/*.c) SRCS += third_party/ImFileDialog/ImFileDialog.cpp SRCS += third_party/imgui/backends/imgui_impl_opengl3.cpp -SRCS += third_party/imgui/backends/imgui_impl_glfw.cpp +SRCS += third_party/imgui/backends/imgui_impl_sdl3.cpp SRCS += third_party/imgui/misc/cpp/imgui_stdlib.cpp SRCS += third_party/imgui/misc/freetype/imgui_freetype.cpp SRCS += third_party/imgui_lua_bindings/imgui_lua_bindings.cpp diff --git a/src/core/pad.cc b/src/core/pad.cc index 8e283afd3..595031b4c 100644 --- a/src/core/pad.cc +++ b/src/core/pad.cc @@ -17,11 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ -#define GLFW_INCLUDE_NONE #define _USE_MATH_DEFINES #include "core/pad.h" -#include #include #include @@ -85,23 +83,23 @@ class PadsImpl : public PCSX::Pads { // settings block // Pad keyboard bindings - typedef PCSX::Setting Keyboard_PadUp; - typedef PCSX::Setting Keyboard_PadRight; - typedef PCSX::Setting Keyboard_PadDown; - typedef PCSX::Setting Keyboard_PadLeft; - typedef PCSX::Setting Keyboard_PadCross; - typedef PCSX::Setting Keyboard_PadTriangle; - typedef PCSX::Setting Keyboard_PadSquare; - typedef PCSX::Setting Keyboard_PadCircle; - typedef PCSX::Setting Keyboard_PadSelect; - typedef PCSX::Setting Keyboard_PadStart; - typedef PCSX::Setting Keyboard_PadL1; - typedef PCSX::Setting Keyboard_PadL2; - typedef PCSX::Setting Keyboard_PadL3; - typedef PCSX::Setting Keyboard_PadR1; - typedef PCSX::Setting Keyboard_PadR2; - typedef PCSX::Setting Keyboard_PadR3; - typedef PCSX::Setting Keyboard_AnalogMode; + typedef PCSX::Setting Keyboard_PadUp; + typedef PCSX::Setting Keyboard_PadRight; + typedef PCSX::Setting Keyboard_PadDown; + typedef PCSX::Setting Keyboard_PadLeft; + typedef PCSX::Setting Keyboard_PadCross; + typedef PCSX::Setting Keyboard_PadTriangle; + typedef PCSX::Setting Keyboard_PadSquare; + typedef PCSX::Setting Keyboard_PadCircle; + typedef PCSX::Setting Keyboard_PadSelect; + typedef PCSX::Setting Keyboard_PadStart; + typedef PCSX::Setting Keyboard_PadL1; + typedef PCSX::Setting Keyboard_PadL2; + typedef PCSX::Setting Keyboard_PadL3; + typedef PCSX::Setting Keyboard_PadR1; + typedef PCSX::Setting Keyboard_PadR2; + typedef PCSX::Setting Keyboard_PadR3; + typedef PCSX::Setting Keyboard_AnalogMode; // Pad controller bindings. Defaults reference SDL gamepad button enums // (PS-style face buttons via SDL_GAMEPAD_BUTTON_SOUTH/EAST/WEST/NORTH). @@ -221,220 +219,114 @@ class PadsImpl : public PCSX::Pads { static PadsImpl* s_pads = nullptr; -static ImGuiKey GlfwKeyToImGuiKey(int key) { - switch (key) { - case GLFW_KEY_TAB: - return ImGuiKey_Tab; - case GLFW_KEY_LEFT: - return ImGuiKey_LeftArrow; - case GLFW_KEY_RIGHT: - return ImGuiKey_RightArrow; - case GLFW_KEY_UP: - return ImGuiKey_UpArrow; - case GLFW_KEY_DOWN: - return ImGuiKey_DownArrow; - case GLFW_KEY_PAGE_UP: - return ImGuiKey_PageUp; - case GLFW_KEY_PAGE_DOWN: - return ImGuiKey_PageDown; - case GLFW_KEY_HOME: - return ImGuiKey_Home; - case GLFW_KEY_END: - return ImGuiKey_End; - case GLFW_KEY_INSERT: - return ImGuiKey_Insert; - case GLFW_KEY_DELETE: - return ImGuiKey_Delete; - case GLFW_KEY_BACKSPACE: - return ImGuiKey_Backspace; - case GLFW_KEY_SPACE: - return ImGuiKey_Space; - case GLFW_KEY_ENTER: - return ImGuiKey_Enter; - case GLFW_KEY_ESCAPE: - return ImGuiKey_Escape; - case GLFW_KEY_APOSTROPHE: - return ImGuiKey_Apostrophe; - case GLFW_KEY_COMMA: - return ImGuiKey_Comma; - case GLFW_KEY_MINUS: - return ImGuiKey_Minus; - case GLFW_KEY_PERIOD: - return ImGuiKey_Period; - case GLFW_KEY_SLASH: - return ImGuiKey_Slash; - case GLFW_KEY_SEMICOLON: - return ImGuiKey_Semicolon; - case GLFW_KEY_EQUAL: - return ImGuiKey_Equal; - case GLFW_KEY_LEFT_BRACKET: - return ImGuiKey_LeftBracket; - case GLFW_KEY_BACKSLASH: - return ImGuiKey_Backslash; - case GLFW_KEY_RIGHT_BRACKET: - return ImGuiKey_RightBracket; - case GLFW_KEY_GRAVE_ACCENT: - return ImGuiKey_GraveAccent; - case GLFW_KEY_CAPS_LOCK: - return ImGuiKey_CapsLock; - case GLFW_KEY_SCROLL_LOCK: - return ImGuiKey_ScrollLock; - case GLFW_KEY_NUM_LOCK: - return ImGuiKey_NumLock; - case GLFW_KEY_PRINT_SCREEN: - return ImGuiKey_PrintScreen; - case GLFW_KEY_PAUSE: - return ImGuiKey_Pause; - case GLFW_KEY_KP_0: - return ImGuiKey_Keypad0; - case GLFW_KEY_KP_1: - return ImGuiKey_Keypad1; - case GLFW_KEY_KP_2: - return ImGuiKey_Keypad2; - case GLFW_KEY_KP_3: - return ImGuiKey_Keypad3; - case GLFW_KEY_KP_4: - return ImGuiKey_Keypad4; - case GLFW_KEY_KP_5: - return ImGuiKey_Keypad5; - case GLFW_KEY_KP_6: - return ImGuiKey_Keypad6; - case GLFW_KEY_KP_7: - return ImGuiKey_Keypad7; - case GLFW_KEY_KP_8: - return ImGuiKey_Keypad8; - case GLFW_KEY_KP_9: - return ImGuiKey_Keypad9; - case GLFW_KEY_KP_DECIMAL: - return ImGuiKey_KeypadDecimal; - case GLFW_KEY_KP_DIVIDE: - return ImGuiKey_KeypadDivide; - case GLFW_KEY_KP_MULTIPLY: - return ImGuiKey_KeypadMultiply; - case GLFW_KEY_KP_SUBTRACT: - return ImGuiKey_KeypadSubtract; - case GLFW_KEY_KP_ADD: - return ImGuiKey_KeypadAdd; - case GLFW_KEY_KP_ENTER: - return ImGuiKey_KeypadEnter; - case GLFW_KEY_KP_EQUAL: - return ImGuiKey_KeypadEqual; - case GLFW_KEY_LEFT_SHIFT: - return ImGuiKey_LeftShift; - case GLFW_KEY_LEFT_CONTROL: - return ImGuiKey_LeftCtrl; - case GLFW_KEY_LEFT_ALT: - return ImGuiKey_LeftAlt; - case GLFW_KEY_LEFT_SUPER: - return ImGuiKey_LeftSuper; - case GLFW_KEY_RIGHT_SHIFT: - return ImGuiKey_RightShift; - case GLFW_KEY_RIGHT_CONTROL: - return ImGuiKey_RightCtrl; - case GLFW_KEY_RIGHT_ALT: - return ImGuiKey_RightAlt; - case GLFW_KEY_RIGHT_SUPER: - return ImGuiKey_RightSuper; - case GLFW_KEY_MENU: - return ImGuiKey_Menu; - case GLFW_KEY_0: - return ImGuiKey_0; - case GLFW_KEY_1: - return ImGuiKey_1; - case GLFW_KEY_2: - return ImGuiKey_2; - case GLFW_KEY_3: - return ImGuiKey_3; - case GLFW_KEY_4: - return ImGuiKey_4; - case GLFW_KEY_5: - return ImGuiKey_5; - case GLFW_KEY_6: - return ImGuiKey_6; - case GLFW_KEY_7: - return ImGuiKey_7; - case GLFW_KEY_8: - return ImGuiKey_8; - case GLFW_KEY_9: - return ImGuiKey_9; - case GLFW_KEY_A: - return ImGuiKey_A; - case GLFW_KEY_B: - return ImGuiKey_B; - case GLFW_KEY_C: - return ImGuiKey_C; - case GLFW_KEY_D: - return ImGuiKey_D; - case GLFW_KEY_E: - return ImGuiKey_E; - case GLFW_KEY_F: - return ImGuiKey_F; - case GLFW_KEY_G: - return ImGuiKey_G; - case GLFW_KEY_H: - return ImGuiKey_H; - case GLFW_KEY_I: - return ImGuiKey_I; - case GLFW_KEY_J: - return ImGuiKey_J; - case GLFW_KEY_K: - return ImGuiKey_K; - case GLFW_KEY_L: - return ImGuiKey_L; - case GLFW_KEY_M: - return ImGuiKey_M; - case GLFW_KEY_N: - return ImGuiKey_N; - case GLFW_KEY_O: - return ImGuiKey_O; - case GLFW_KEY_P: - return ImGuiKey_P; - case GLFW_KEY_Q: - return ImGuiKey_Q; - case GLFW_KEY_R: - return ImGuiKey_R; - case GLFW_KEY_S: - return ImGuiKey_S; - case GLFW_KEY_T: - return ImGuiKey_T; - case GLFW_KEY_U: - return ImGuiKey_U; - case GLFW_KEY_V: - return ImGuiKey_V; - case GLFW_KEY_W: - return ImGuiKey_W; - case GLFW_KEY_X: - return ImGuiKey_X; - case GLFW_KEY_Y: - return ImGuiKey_Y; - case GLFW_KEY_Z: - return ImGuiKey_Z; - case GLFW_KEY_F1: - return ImGuiKey_F1; - case GLFW_KEY_F2: - return ImGuiKey_F2; - case GLFW_KEY_F3: - return ImGuiKey_F3; - case GLFW_KEY_F4: - return ImGuiKey_F4; - case GLFW_KEY_F5: - return ImGuiKey_F5; - case GLFW_KEY_F6: - return ImGuiKey_F6; - case GLFW_KEY_F7: - return ImGuiKey_F7; - case GLFW_KEY_F8: - return ImGuiKey_F8; - case GLFW_KEY_F9: - return ImGuiKey_F9; - case GLFW_KEY_F10: - return ImGuiKey_F10; - case GLFW_KEY_F11: - return ImGuiKey_F11; - case GLFW_KEY_F12: - return ImGuiKey_F12; - default: - return ImGuiKey_None; +static ImGuiKey SdlScancodeToImGuiKey(int scancode) { + switch (scancode) { + case SDL_SCANCODE_TAB: return ImGuiKey_Tab; + case SDL_SCANCODE_LEFT: return ImGuiKey_LeftArrow; + case SDL_SCANCODE_RIGHT: return ImGuiKey_RightArrow; + case SDL_SCANCODE_UP: return ImGuiKey_UpArrow; + case SDL_SCANCODE_DOWN: return ImGuiKey_DownArrow; + case SDL_SCANCODE_PAGEUP: return ImGuiKey_PageUp; + case SDL_SCANCODE_PAGEDOWN: return ImGuiKey_PageDown; + case SDL_SCANCODE_HOME: return ImGuiKey_Home; + case SDL_SCANCODE_END: return ImGuiKey_End; + case SDL_SCANCODE_INSERT: return ImGuiKey_Insert; + case SDL_SCANCODE_DELETE: return ImGuiKey_Delete; + case SDL_SCANCODE_BACKSPACE: return ImGuiKey_Backspace; + case SDL_SCANCODE_SPACE: return ImGuiKey_Space; + case SDL_SCANCODE_RETURN: return ImGuiKey_Enter; + case SDL_SCANCODE_ESCAPE: return ImGuiKey_Escape; + case SDL_SCANCODE_APOSTROPHE: return ImGuiKey_Apostrophe; + case SDL_SCANCODE_COMMA: return ImGuiKey_Comma; + case SDL_SCANCODE_MINUS: return ImGuiKey_Minus; + case SDL_SCANCODE_PERIOD: return ImGuiKey_Period; + case SDL_SCANCODE_SLASH: return ImGuiKey_Slash; + case SDL_SCANCODE_SEMICOLON: return ImGuiKey_Semicolon; + case SDL_SCANCODE_EQUALS: return ImGuiKey_Equal; + case SDL_SCANCODE_LEFTBRACKET: return ImGuiKey_LeftBracket; + case SDL_SCANCODE_BACKSLASH: return ImGuiKey_Backslash; + case SDL_SCANCODE_RIGHTBRACKET: return ImGuiKey_RightBracket; + case SDL_SCANCODE_GRAVE: return ImGuiKey_GraveAccent; + case SDL_SCANCODE_CAPSLOCK: return ImGuiKey_CapsLock; + case SDL_SCANCODE_SCROLLLOCK: return ImGuiKey_ScrollLock; + case SDL_SCANCODE_NUMLOCKCLEAR: return ImGuiKey_NumLock; + case SDL_SCANCODE_PRINTSCREEN: return ImGuiKey_PrintScreen; + case SDL_SCANCODE_PAUSE: return ImGuiKey_Pause; + case SDL_SCANCODE_KP_0: return ImGuiKey_Keypad0; + case SDL_SCANCODE_KP_1: return ImGuiKey_Keypad1; + case SDL_SCANCODE_KP_2: return ImGuiKey_Keypad2; + case SDL_SCANCODE_KP_3: return ImGuiKey_Keypad3; + case SDL_SCANCODE_KP_4: return ImGuiKey_Keypad4; + case SDL_SCANCODE_KP_5: return ImGuiKey_Keypad5; + case SDL_SCANCODE_KP_6: return ImGuiKey_Keypad6; + case SDL_SCANCODE_KP_7: return ImGuiKey_Keypad7; + case SDL_SCANCODE_KP_8: return ImGuiKey_Keypad8; + case SDL_SCANCODE_KP_9: return ImGuiKey_Keypad9; + case SDL_SCANCODE_KP_PERIOD: return ImGuiKey_KeypadDecimal; + case SDL_SCANCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide; + case SDL_SCANCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; + case SDL_SCANCODE_KP_MINUS: return ImGuiKey_KeypadSubtract; + case SDL_SCANCODE_KP_PLUS: return ImGuiKey_KeypadAdd; + case SDL_SCANCODE_KP_ENTER: return ImGuiKey_KeypadEnter; + case SDL_SCANCODE_KP_EQUALS: return ImGuiKey_KeypadEqual; + case SDL_SCANCODE_LSHIFT: return ImGuiKey_LeftShift; + case SDL_SCANCODE_LCTRL: return ImGuiKey_LeftCtrl; + case SDL_SCANCODE_LALT: return ImGuiKey_LeftAlt; + case SDL_SCANCODE_LGUI: return ImGuiKey_LeftSuper; + case SDL_SCANCODE_RSHIFT: return ImGuiKey_RightShift; + case SDL_SCANCODE_RCTRL: return ImGuiKey_RightCtrl; + case SDL_SCANCODE_RALT: return ImGuiKey_RightAlt; + case SDL_SCANCODE_RGUI: return ImGuiKey_RightSuper; + case SDL_SCANCODE_MENU: return ImGuiKey_Menu; + case SDL_SCANCODE_0: return ImGuiKey_0; + case SDL_SCANCODE_1: return ImGuiKey_1; + case SDL_SCANCODE_2: return ImGuiKey_2; + case SDL_SCANCODE_3: return ImGuiKey_3; + case SDL_SCANCODE_4: return ImGuiKey_4; + case SDL_SCANCODE_5: return ImGuiKey_5; + case SDL_SCANCODE_6: return ImGuiKey_6; + case SDL_SCANCODE_7: return ImGuiKey_7; + case SDL_SCANCODE_8: return ImGuiKey_8; + case SDL_SCANCODE_9: return ImGuiKey_9; + case SDL_SCANCODE_A: return ImGuiKey_A; + case SDL_SCANCODE_B: return ImGuiKey_B; + case SDL_SCANCODE_C: return ImGuiKey_C; + case SDL_SCANCODE_D: return ImGuiKey_D; + case SDL_SCANCODE_E: return ImGuiKey_E; + case SDL_SCANCODE_F: return ImGuiKey_F; + case SDL_SCANCODE_G: return ImGuiKey_G; + case SDL_SCANCODE_H: return ImGuiKey_H; + case SDL_SCANCODE_I: return ImGuiKey_I; + case SDL_SCANCODE_J: return ImGuiKey_J; + case SDL_SCANCODE_K: return ImGuiKey_K; + case SDL_SCANCODE_L: return ImGuiKey_L; + case SDL_SCANCODE_M: return ImGuiKey_M; + case SDL_SCANCODE_N: return ImGuiKey_N; + case SDL_SCANCODE_O: return ImGuiKey_O; + case SDL_SCANCODE_P: return ImGuiKey_P; + case SDL_SCANCODE_Q: return ImGuiKey_Q; + case SDL_SCANCODE_R: return ImGuiKey_R; + case SDL_SCANCODE_S: return ImGuiKey_S; + case SDL_SCANCODE_T: return ImGuiKey_T; + case SDL_SCANCODE_U: return ImGuiKey_U; + case SDL_SCANCODE_V: return ImGuiKey_V; + case SDL_SCANCODE_W: return ImGuiKey_W; + case SDL_SCANCODE_X: return ImGuiKey_X; + case SDL_SCANCODE_Y: return ImGuiKey_Y; + case SDL_SCANCODE_Z: return ImGuiKey_Z; + case SDL_SCANCODE_F1: return ImGuiKey_F1; + case SDL_SCANCODE_F2: return ImGuiKey_F2; + case SDL_SCANCODE_F3: return ImGuiKey_F3; + case SDL_SCANCODE_F4: return ImGuiKey_F4; + case SDL_SCANCODE_F5: return ImGuiKey_F5; + case SDL_SCANCODE_F6: return ImGuiKey_F6; + case SDL_SCANCODE_F7: return ImGuiKey_F7; + case SDL_SCANCODE_F8: return ImGuiKey_F8; + case SDL_SCANCODE_F9: return ImGuiKey_F9; + case SDL_SCANCODE_F10: return ImGuiKey_F10; + case SDL_SCANCODE_F11: return ImGuiKey_F11; + case SDL_SCANCODE_F12: return ImGuiKey_F12; + default: return ImGuiKey_None; } } @@ -613,7 +505,7 @@ void PadsImpl::Pad::getButtons() { if (!ImGui::GetCurrentContext()) return 0xffff; uint16_t result = 0; for (unsigned i = 0; i < 16; i++) { - auto key = GlfwKeyToImGuiKey(m_scancodes[i]); + auto key = SdlScancodeToImGuiKey(m_scancodes[i]); if (key == ImGuiKey_None) continue; result |= (ImGui::IsKeyDown(key)) << i; } @@ -936,10 +828,10 @@ uint8_t PadsImpl::Pad::read() { bool PadsImpl::configure(PCSX::GUI* gui) { // Check for analog mode toggle key for (auto& pad : m_pads) { - if (pad.m_type == PadType::Analog && pad.m_settings.get() != GLFW_KEY_UNKNOWN) { + if (pad.m_type == PadType::Analog && pad.m_settings.get() != SDL_SCANCODE_UNKNOWN) { const int key = pad.m_settings.get(); - if ((key != ImGuiKey_None) && ImGui::IsKeyReleased(GlfwKeyToImGuiKey(key))) { + if ((key != ImGuiKey_None) && ImGui::IsKeyReleased(SdlScancodeToImGuiKey(key))) { pad.m_analogMode = !pad.m_analogMode; } } @@ -994,33 +886,34 @@ bool PadsImpl::configure(PCSX::GUI* gui) { return changed; } -// GLFW doesn't support converting some of the most common keys to strings -static std::string glfwKeyToString(int key) { - // define strings for some common keys that are not supported by glfwGetKeyName - switch (key) { - case GLFW_KEY_UP: +// SDL_GetScancodeName covers ASCII letters/digits but not the common navigation +// keys; we provide friendlier localized labels for those, and fall back to +// SDL_GetScancodeName for the rest. +static std::string sdlScancodeToString(int scancode) { + switch (scancode) { + case SDL_SCANCODE_UP: return _("Keyboard Up"); - case GLFW_KEY_RIGHT: + case SDL_SCANCODE_RIGHT: return _("Keyboard Right"); - case GLFW_KEY_DOWN: + case SDL_SCANCODE_DOWN: return _("Keyboard Down"); - case GLFW_KEY_LEFT: + case SDL_SCANCODE_LEFT: return _("Keyboard Left"); - case GLFW_KEY_BACKSPACE: + case SDL_SCANCODE_BACKSPACE: return _("Keyboard Backspace"); - case GLFW_KEY_ENTER: + case SDL_SCANCODE_RETURN: return _("Keyboard Enter"); - case GLFW_KEY_SPACE: + case SDL_SCANCODE_SPACE: return _("Keyboard Space"); - case GLFW_KEY_ESCAPE: + case SDL_SCANCODE_ESCAPE: return _("Keyboard Escape"); - case GLFW_KEY_UNKNOWN: + case SDL_SCANCODE_UNKNOWN: return _("Unbound"); }; - auto keyName = glfwGetKeyName(key, 0); - if (keyName == nullptr) { - return fmt::format(f_("Unknown keyboard key {}"), key); + const char* keyName = SDL_GetScancodeName(static_cast(scancode)); + if (!keyName || keyName[0] == '\0') { + return fmt::format(f_("Unknown keyboard key {}"), scancode); } auto str = std::string(keyName); @@ -1032,7 +925,11 @@ void PadsImpl::Pad::keyboardEvent(const PCSX::Events::Keyboard& event) { if (m_buttonToWait == -1) { return; } - getButtonFromGUIIndex(m_buttonToWait) = event.key; + // Bindings are stored as SDL_Scancode values to match the runtime lookup + // path (SdlScancodeToImGuiKey) and the SDL_SCANCODE_* setting defaults. + // event.key is an SDL_Keycode (layout-aware codepoint); event.scancode is + // the layout-independent physical-key id we actually want. + getButtonFromGUIIndex(m_buttonToWait) = event.scancode; m_buttonToWait = -1; m_changed = true; map(); @@ -1131,7 +1028,7 @@ bool PadsImpl::Pad::configure() { } // The name of the mapped key - const auto keyName = fmt::format("{}##{}", glfwKeyToString(getButtonFromGUIIndex(i)), i); + const auto keyName = fmt::format("{}##{}", sdlScancodeToString(getButtonFromGUIIndex(i)), i); if (ImGui::Button(keyName.c_str(), ImVec2{-1, 0})) { m_buttonToWait = i; } @@ -1154,7 +1051,7 @@ bool PadsImpl::Pad::configure() { } // The name of the mapped key - const auto keyName = fmt::format("{}##{}", glfwKeyToString(getButtonFromGUIIndex(absI)), absI); + const auto keyName = fmt::format("{}##{}", sdlScancodeToString(getButtonFromGUIIndex(absI)), absI); if (ImGui::Button(keyName.c_str(), ImVec2{-1, 0})) { m_buttonToWait = absI; } diff --git a/src/gui/gui.cc b/src/gui/gui.cc index bf158f6be..874d56418 100644 --- a/src/gui/gui.cc +++ b/src/gui/gui.cc @@ -24,11 +24,10 @@ #endif // And only then we can load the rest -#define GLFW_INCLUDE_NONE #define IMGUI_DEFINE_MATH_OPERATORS #define NANOVG_GLES3_IMPLEMENTATION #include -#include +#include #include extern "C" { #include @@ -71,8 +70,8 @@ extern "C" { #include "gui/resources.h" #include "gui/shaders/crt-lottes.h" #include "imgui.h" -#include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" +#include "imgui_impl_sdl3.h" #include "imgui_internal.h" #include "imgui_stdlib.h" #include "json.hpp" @@ -201,10 +200,9 @@ extern "C" void pcsxStaticImguiAssert(int exp, const char* msg) { if (!exp) thrower(msg); } -static GLFWwindow* getGLFWwindowFromImGuiViewport(ImGuiViewport* viewport) { - // absolutely horrendous hack, but the only way we have to grab the - // GLFWwindow pointer from an ImGuiViewport without changing the backend... - return *reinterpret_cast(viewport->PlatformUserData); +static SDL_Window* getSDLWindowFromImGuiViewport(ImGuiViewport* viewport) { + // imgui_impl_sdl3 stores the SDL_Window* directly in PlatformHandle. + return static_cast(viewport->PlatformHandle); } PCSX::GUI* PCSX::g_gui = nullptr; @@ -212,31 +210,24 @@ PCSX::GUI* PCSX::g_gui = nullptr; void PCSX::GUI::setFullscreen(bool fullscreen) { m_fullscreen = fullscreen; if (fullscreen) { - glfwGetWindowPos(m_window, &m_glfwPosX, &m_glfwPosY); - glfwGetWindowSize(m_window, &m_glfwSizeX, &m_glfwSizeY); - const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - glfwSetWindowMonitor(m_window, glfwGetPrimaryMonitor(), 0, 0, mode->width, mode->height, GLFW_DONT_CARE); + // Snapshot windowed pos/size before the transition so we can restore them. + SDL_GetWindowPosition(m_window, &m_windowPosX, &m_windowPosY); + SDL_GetWindowSize(m_window, &m_windowSizeX, &m_windowSizeY); + // No fullscreen mode set -> SDL gives us borderless desktop fullscreen, + // which is the shape glfwSetWindowMonitor(..., GLFW_DONT_CARE) produced. + SDL_SetWindowFullscreenMode(m_window, nullptr); + SDL_SetWindowFullscreen(m_window, true); } else { - glfwSetWindowMonitor(m_window, nullptr, m_glfwPosX, m_glfwPosY, m_glfwSizeX, m_glfwSizeY, GLFW_DONT_CARE); + SDL_SetWindowFullscreen(m_window, false); + SDL_SetWindowPosition(m_window, m_windowPosX, m_windowPosY); + SDL_SetWindowSize(m_window, m_windowSizeX, m_windowSizeY); } } void PCSX::GUI::setRawMouseMotion() { - if (isRawMouseMotionEnabled()) { - if (glfwRawMouseMotionSupported()) { - glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - glfwSetInputMode(m_window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); - } - } else { - glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - } -} - -static PCSX::GUI* s_this = nullptr; - -static void drop_callback(GLFWwindow* window, int count, const char** paths) { - if (count != 1) return; - s_this->magicOpen(paths[0]); + // SDL3 relative-mouse-mode covers cursor-hide + raw motion in one call, + // collapsing GLFW's two-step (CURSOR_DISABLED + RAW_MOUSE_MOTION) flow. + SDL_SetWindowRelativeMouseMode(m_window, isRawMouseMotionEnabled()); } void LoadImguiBindings(lua_State* lState); @@ -541,66 +532,91 @@ void PCSX::GUI::init(std::function applyArguments) { } }); - glfwSetErrorCallback([](int error, const char* description) { - g_system->log(LogClass::UI, "Glfw Error %d: %s\n", error, description); - }); - if (!glfwInit()) { - throw std::runtime_error("Failed to initialize GLFW"); + if (!SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { + throw std::runtime_error(std::string("Failed to initialize SDL: ") + SDL_GetError()); } m_listener.listen([this](const auto& event) { saveCfg(); }); m_listener.listen([this](const auto& event) { - glfwSwapInterval(m_idleSwapInterval); - glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + SDL_GL_SetSwapInterval(m_idleSwapInterval); + SDL_SetWindowRelativeMouseMode(m_window, false); }); m_listener.listen([this](const auto& event) { m_enableSplashScreen = false; - glfwSwapInterval(0); + SDL_GL_SetSwapInterval(0); setRawMouseMotion(); }); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); m_hasCoreProfile = true; - m_window = glfwCreateWindow(1280, 800, "PCSX-Redux", nullptr, nullptr); + // SDL_WINDOW_HIGH_PIXEL_DENSITY makes window-coords vs pixel-coords meaningful + // on macOS Retina + Windows per-monitor DPI; required for the changeScale path. + const SDL_WindowFlags windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY; + m_window = SDL_CreateWindow("PCSX-Redux", 1280, 800, windowFlags); + if (m_window) { + m_glContext = SDL_GL_CreateContext(m_window); + } - if (!m_window) { + // SDL splits window and GL context creation, so the 3.0 fallback has to + // cover both: a 3.2-core context can fail to materialize even after the + // window itself succeeded. On platforms where the pixel format binds at + // window creation (Win32 WGL is the strict case) a clean retry needs a + // fresh window too, so we destroy and recreate both. + if (!m_window || !m_glContext) { g_system->log(LogClass::UI, - "GLFW failed to create window with OpenGL core profile 3.2, retrying with any 3.0 profile\n"); - glfwDefaultWindowHints(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + "SDL failed to create OpenGL 3.2 core context, retrying with any 3.0 profile\n"); + if (m_glContext) { + SDL_GL_DestroyContext(m_glContext); + m_glContext = nullptr; + } + if (m_window) { + SDL_DestroyWindow(m_window); + m_window = nullptr; + } + + SDL_GL_ResetAttributes(); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + // No profile mask -> any profile. + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); m_hasCoreProfile = false; - m_window = glfwCreateWindow(1280, 800, "PCSX-Redux", nullptr, nullptr); + m_window = SDL_CreateWindow("PCSX-Redux", 1280, 800, windowFlags); + if (m_window) { + m_glContext = SDL_GL_CreateContext(m_window); + } } if (!m_window) { - throw std::runtime_error("Unable to create main window. Check OpenGL drivers."); + throw std::runtime_error(std::string("Unable to create main window: ") + SDL_GetError()); + } + if (!m_glContext) { + throw std::runtime_error(std::string("Unable to create GL context: ") + SDL_GetError()); } - glfwMakeContextCurrent(m_window); - glfwSwapInterval(0); + SDL_GL_MakeCurrent(m_window, m_glContext); + SDL_GL_SetSwapInterval(0); - s_this = this; - glfwSetDropCallback(m_window, drop_callback); - glfwSetWindowSizeCallback(m_window, [](GLFWwindow*, int, int) { s_this->m_setupScreenSize = true; }); + // Drop and resize events flow through SDL_PollEvent in startFrame() now. + // ImGui_ImplSDL3_ProcessEvent gets first crack at every event for + // mouse/keyboard/text dispatch. Resources::loadIcon([this](const uint8_t* data, uint32_t size) { clip::image img; if (!img.import_from_png(data, size)) return; int x = img.spec().width; int y = img.spec().height; - GLFWimage image; - image.width = x; - image.height = y; - image.pixels = reinterpret_cast(img.data()); - glfwSetWindowIcon(m_window, 1, &image); + // SDL_CreateSurfaceFrom needs a non-const pixel pointer; clip::image::data() + // is non-const, so the cast below is benign. + SDL_Surface* iconSurface = SDL_CreateSurfaceFrom(x, y, SDL_PIXELFORMAT_RGBA32, img.data(), x * 4); + if (iconSurface) { + SDL_SetWindowIcon(m_window, iconSurface); + SDL_DestroySurface(iconSurface); + } }); result = gl3wInit(); @@ -657,12 +673,12 @@ void PCSX::GUI::init(std::function applyArguments) { } if ((settings.get().value > 0) && (settings.get().value > 0)) { - glfwSetWindowPos(m_window, settings.get(), settings.get()); + SDL_SetWindowPosition(m_window, settings.get(), settings.get()); } if (settings.get().value) { - glfwMaximizeWindow(m_window); + SDL_MaximizeWindow(m_window); } else { - glfwSetWindowSize(m_window, windowSizeX, windowSizeY); + SDL_SetWindowSize(m_window, windowSizeX, windowSizeY); } } else { saveCfg(); @@ -687,7 +703,7 @@ void PCSX::GUI::init(std::function applyArguments) { const auto currentTheme = emuSettings.get().value; // On boot: reload GUI theme applyTheme(currentTheme); } - if (!g_system->running()) glfwSwapInterval(m_idleSwapInterval); + if (!g_system->running()) SDL_GL_SetSwapInterval(m_idleSwapInterval); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; @@ -698,7 +714,7 @@ void PCSX::GUI::init(std::function applyArguments) { io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; // io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; - ImGui_ImplGlfw_InitForOpenGL(m_window, true); + ImGui_ImplSDL3_InitForOpenGL(m_window, m_glContext); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); io.SetClipboardTextFn = [](void*, const char* text) -> void { clip::set_text(text); }; io.GetClipboardTextFn = [](void*) -> const char* { @@ -709,8 +725,9 @@ void PCSX::GUI::init(std::function applyArguments) { m_createWindowOldCallback = platform_io.Platform_CreateWindow; platform_io.Platform_CreateWindow = [](ImGuiViewport* viewport) { if (g_gui->m_createWindowOldCallback) g_gui->m_createWindowOldCallback(viewport); - auto window = getGLFWwindowFromImGuiViewport(viewport); - glfwSetKeyCallback(window, glfwKeyCallbackTrampoline); + // imgui_impl_sdl3 dispatches keyboard/mouse via ImGui_ImplSDL3_ProcessEvent + // applied to every polled event in startFrame(), so we don't need a + // per-window key callback the way the GLFW backend did. auto id = viewport->ID; g_gui->m_nvgSubContextes[id] = nvgCreateSubContextGL(g_gui->m_nvgContext); }; @@ -730,7 +747,6 @@ void PCSX::GUI::init(std::function applyArguments) { } if (g_gui->m_destroyWindowOldCallback) g_gui->m_destroyWindowOldCallback(viewport); }; - glfwSetKeyCallback(m_window, glfwKeyCallbackTrampoline); // Some bad GPU drivers (*cough* Intel) don't like mixed shaders versions, // and will silently fail to execute them. // This is just a bad heuristic to try and keep it the same version. @@ -866,15 +882,28 @@ void PCSX::GUI::init(std::function applyArguments) { void PCSX::GUI::close() { ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); + ImGui_ImplSDL3_Shutdown(); ImGui::DestroyContext(); - glfwDestroyWindow(m_window); - glfwTerminate(); + // Tear down all GL-backed resources (NanoVG sub/main contexts) BEFORE + // dropping the GL context they live in. The previous (GLFW-era) ordering + // freed NanoVG after glfwDestroyWindow, which technically leaked GPU + // resources because their owning context was already gone; SDL's explicit + // context handle makes the correct ordering easy to enforce. for (auto& subContext : m_nvgSubContextes) { nvgDeleteSubContextGL(subContext.second); } m_nvgSubContextes.clear(); nvgDeleteGLES3(m_nvgContext); + m_nvgContext = nullptr; + if (m_glContext) { + SDL_GL_DestroyContext(m_glContext); + m_glContext = nullptr; + } + if (m_window) { + SDL_DestroyWindow(m_window); + m_window = nullptr; + } + SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS); } void PCSX::GUI::saveCfg() { @@ -885,16 +914,17 @@ void PCSX::GUI::saveCfg() { std::ofstream cfg(cfgTmpPath); json j; - if (m_fullscreen || glfwGetWindowAttrib(m_window, GLFW_ICONIFIED) > 0) { - m_glfwPosX = settings.get(); - m_glfwPosY = settings.get(); - m_glfwSizeX = settings.get(); - m_glfwSizeY = settings.get(); - m_glfwMaximized = settings.get(); + const SDL_WindowFlags flags = SDL_GetWindowFlags(m_window); + if (m_fullscreen || (flags & SDL_WINDOW_MINIMIZED)) { + m_windowPosX = settings.get(); + m_windowPosY = settings.get(); + m_windowSizeX = settings.get(); + m_windowSizeY = settings.get(); + m_windowMaximized = settings.get(); } else { - glfwGetWindowPos(m_window, &m_glfwPosX, &m_glfwPosY); - glfwGetWindowSize(m_window, &m_glfwSizeX, &m_glfwSizeY); - m_glfwMaximized = glfwGetWindowAttrib(m_window, GLFW_MAXIMIZED) != 0; + SDL_GetWindowPosition(m_window, &m_windowPosX, &m_windowPosY); + SDL_GetWindowSize(m_window, &m_windowSizeX, &m_windowSizeY); + m_windowMaximized = (flags & SDL_WINDOW_MAXIMIZED) != 0; } j["imgui"] = ImGui::SaveIniSettingsToMemory(nullptr); @@ -910,22 +940,55 @@ void PCSX::GUI::saveCfg() { } } -void PCSX::GUI::glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { - ImGui_ImplGlfw_KeyCallback(window, key, scancode, action, mods); - g_system->m_eventBus->signal(Events::Keyboard{key, scancode, action, mods}); -} - void PCSX::GUI::startFrame() { ZoneScoped; tick(); - if (glfwWindowShouldClose(m_window)) g_system->quit(); - glfwPollEvents(); + SDL_Event event; + while (SDL_PollEvent(&event)) { + ImGui_ImplSDL3_ProcessEvent(&event); + switch (event.type) { + case SDL_EVENT_QUIT: + g_system->quit(); + break; + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + if (event.window.windowID == SDL_GetWindowID(m_window)) g_system->quit(); + break; + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + if (event.window.windowID == SDL_GetWindowID(m_window)) m_setupScreenSize = true; + break; + case SDL_EVENT_WINDOW_DISPLAY_CHANGED: + // Force a font/scale rebuild when the window crosses to a display + // with different DPI. This is the case GLFW didn't fire and is the + // recurring high-DPI bug we're fixing in this phase. + if (event.window.windowID == SDL_GetWindowID(m_window)) { + changeScale(SDL_GetWindowDisplayScale(m_window)); + m_setupScreenSize = true; + } + break; + case SDL_EVENT_DROP_FILE: + // SDL hands us a UTF-8 path that's owned by SDL and freed when + // the event is consumed; magicOpen copies what it needs. + if (event.drop.data) magicOpen(event.drop.data); + break; + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: { + const int action = event.type == SDL_EVENT_KEY_DOWN ? 1 : 0; + g_system->m_eventBus->signal(Events::Keyboard{ + static_cast(event.key.key), static_cast(event.key.scancode), action, + static_cast(event.key.mod)}); + break; + } + default: + break; + } + } if (m_setupScreenSize) { const float renderRatio = settings.get() ? 9.0f / 16.0f : 3.0f / 4.0f; int w, h; - glfwGetFramebufferSize(m_window, &w, &h); + SDL_GetWindowSizeInPixels(m_window, &w, &h); // Make width/height be 1 at minimum w = std::max(w, 1); h = std::max(h, 1); @@ -991,7 +1054,7 @@ void PCSX::GUI::startFrame() { } ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); + ImGui_ImplSDL3_NewFrame(); ImGui::NewFrame(); MarkDown::newFrame(); if (io.WantSaveIniSettings) { @@ -1994,8 +2057,8 @@ the update and manually apply it.)"))); float pxRatio; auto vg = m_nvgContext; if (vg) { - glfwGetWindowSize(m_window, &winWidth, &winHeight); - glfwGetFramebufferSize(m_window, &fbWidth, &fbHeight); + SDL_GetWindowSize(m_window, &winWidth, &winHeight); + SDL_GetWindowSizeInPixels(m_window, &fbWidth, &fbHeight); pxRatio = (float)fbWidth / (float)winWidth; nvgSwitchMainContextGL(vg); nvgBeginFrame(vg, winWidth, winHeight, pxRatio); @@ -2038,11 +2101,11 @@ the update and manually apply it.)"))); if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, nullptr); if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, nullptr); if (vg) { - auto window = getGLFWwindowFromImGuiViewport(viewport); + auto window = getSDLWindowFromImGuiViewport(viewport); auto nvgSubContext = m_nvgSubContextes.find(viewport->ID); if (nvgSubContext != m_nvgSubContextes.end()) { - glfwGetWindowSize(window, &winWidth, &winHeight); - glfwGetFramebufferSize(window, &fbWidth, &fbHeight); + SDL_GetWindowSize(window, &winWidth, &winHeight); + SDL_GetWindowSizeInPixels(window, &fbWidth, &fbHeight); pxRatio = (float)fbWidth / (float)winWidth; nvgSwitchSubContextGL(vg, nvgSubContext->second); nvgBeginFrame(vg, winWidth, winHeight, pxRatio); @@ -2072,9 +2135,9 @@ the update and manually apply it.)"))); if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, nullptr); if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, nullptr); } - glfwMakeContextCurrent(m_window); + SDL_GL_MakeCurrent(m_window, m_glContext); } - glfwSwapBuffers(m_window); + SDL_GL_SwapWindow(m_window); L.getfieldtable("nvg", LUA_GLOBALSINDEX); L.push("_gui"); @@ -2110,7 +2173,7 @@ bool PCSX::GUI::configure() { if (ImGui::Begin(_("Emulation Configuration"), &m_showCfg)) { if (ImGui::SliderInt(_("Idle Swap Interval"), &m_idleSwapInterval, 0, 10)) { changed = true; - if (!g_system->running()) glfwSwapInterval(m_idleSwapInterval); + if (!g_system->running()) SDL_GL_SetSwapInterval(m_idleSwapInterval); } ImGui::Separator(); if (ImGui::Button(_("Reset Scaler"))) { diff --git a/src/gui/gui.h b/src/gui/gui.h index f04b73420..b6eec7a08 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -75,7 +75,9 @@ #define GL_SHADER_VERSION "#version 300 es\n" #endif -struct GLFWwindow; +struct SDL_Window; +struct SDL_GLContextState; +typedef SDL_GLContextState* SDL_GLContext; struct NVGcontext; namespace PCSX { @@ -175,10 +177,6 @@ class GUI final : public UI { void (*m_createWindowOldCallback)(ImGuiViewport *viewport) = nullptr; void (*m_onChangedViewportOldCallback)(ImGuiViewport *viewport) = nullptr; void (*m_destroyWindowOldCallback)(ImGuiViewport *viewport) = nullptr; - static void glfwKeyCallbackTrampoline(GLFWwindow *window, int key, int scancode, int action, int mods) { - g_gui->glfwKeyCallback(window, key, scancode, action, mods); - } - void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); void glErrorCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message); void changeScale(float scale); bool m_onlyLogGLErrors = false; @@ -298,13 +296,14 @@ class GUI final : public UI { const ImVec2 &getRenderSize() { return m_renderSize; } private: - GLFWwindow *m_window = nullptr; + SDL_Window *m_window = nullptr; + SDL_GLContext m_glContext = nullptr; bool m_hasCoreProfile = false; - int &m_glfwPosX = settings.get().value; - int &m_glfwPosY = settings.get().value; - int &m_glfwSizeX = settings.get().value; - int &m_glfwSizeY = settings.get().value; - bool &m_glfwMaximized = settings.get().value; + int &m_windowPosX = settings.get().value; + int &m_windowPosY = settings.get().value; + int &m_windowSizeX = settings.get().value; + int &m_windowSizeY = settings.get().value; + bool &m_windowMaximized = settings.get().value; GLuint m_VRAMTexture = 0; NVGcontext *m_nvgContext = nullptr; std::map m_nvgSubContextes; @@ -316,7 +315,7 @@ class GUI final : public UI { int m_currentTexture = 0; ImVec4 m_backgroundColor = ImColor(114, 144, 154); - ImVec2 m_framebufferSize = ImVec2(1, 1); // Size of GLFW window framebuffer + ImVec2 m_framebufferSize = ImVec2(1, 1); // Size of the SDL window framebuffer (in pixels) ImVec2 m_renderSize = ImVec2(1, 1); ImVec2 m_outputWindowSize = ImVec2(1, 1); diff --git a/src/gui/widgets/assembly.cc b/src/gui/widgets/assembly.cc index f2af92a9f..4bdeee812 100644 --- a/src/gui/widgets/assembly.cc +++ b/src/gui/widgets/assembly.cc @@ -17,11 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ -#define GLFW_INCLUDE_NONE #include "gui/widgets/assembly.h" #include -#include #include #include diff --git a/src/gui/widgets/zep.cc b/src/gui/widgets/zep.cc index f40cf3c72..b28d76aad 100644 --- a/src/gui/widgets/zep.cc +++ b/src/gui/widgets/zep.cc @@ -20,7 +20,6 @@ #include "gui/widgets/zep.h" #include -#include #include "gui/gui.h" #include "zep/regress.h" From 32f03a8ea879115f1ac566a52a22efeded1e200d Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 8 May 2026 21:37:09 -0700 Subject: [PATCH 6/7] MSVC cleanup. --- vsprojects/core/core.vcxproj | 2 -- vsprojects/core/packages.config | 1 - vsprojects/gui/gui.vcxproj | 2 -- vsprojects/gui/packages.config | 1 - vsprojects/imgui-glfw-ogl3/packages.config | 4 ---- .../imgui-sdl3-ogl3.vcxproj} | 17 +++-------------- .../imgui-sdl3-ogl3.vcxproj.filters} | 15 ++++++--------- vsprojects/mainthunk/mainthunk.vcxproj | 4 +--- vsprojects/mainthunk/packages.config | 1 - vsprojects/pcsx-redux.sln | 2 +- vsprojects/tests/pcsxrunner/packages.config | 1 - vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj | 4 +--- 12 files changed, 12 insertions(+), 42 deletions(-) delete mode 100644 vsprojects/imgui-glfw-ogl3/packages.config rename vsprojects/{imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj => imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj} (91%) rename vsprojects/{imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj.filters => imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj.filters} (97%) diff --git a/vsprojects/core/core.vcxproj b/vsprojects/core/core.vcxproj index 9cf1a2bcf..2d6c0b992 100644 --- a/vsprojects/core/core.vcxproj +++ b/vsprojects/core/core.vcxproj @@ -237,14 +237,12 @@ - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - \ No newline at end of file diff --git a/vsprojects/core/packages.config b/vsprojects/core/packages.config index 9dd9bcb83..08d3f42a2 100644 --- a/vsprojects/core/packages.config +++ b/vsprojects/core/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/vsprojects/gui/gui.vcxproj b/vsprojects/gui/gui.vcxproj index 9b0b398e9..1e587ad15 100644 --- a/vsprojects/gui/gui.vcxproj +++ b/vsprojects/gui/gui.vcxproj @@ -212,7 +212,6 @@ - @@ -220,7 +219,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - diff --git a/vsprojects/gui/packages.config b/vsprojects/gui/packages.config index 333f96535..c7a7d620a 100644 --- a/vsprojects/gui/packages.config +++ b/vsprojects/gui/packages.config @@ -1,6 +1,5 @@  - \ No newline at end of file diff --git a/vsprojects/imgui-glfw-ogl3/packages.config b/vsprojects/imgui-glfw-ogl3/packages.config deleted file mode 100644 index 5f7ab861f..000000000 --- a/vsprojects/imgui-glfw-ogl3/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/vsprojects/imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj b/vsprojects/imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj similarity index 91% rename from vsprojects/imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj rename to vsprojects/imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj index 9bde53850..06e6722e1 100644 --- a/vsprojects/imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj +++ b/vsprojects/imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj @@ -141,8 +141,8 @@ - + @@ -153,8 +153,8 @@ - + @@ -164,17 +164,6 @@ - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + \ No newline at end of file diff --git a/vsprojects/imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj.filters b/vsprojects/imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj.filters similarity index 97% rename from vsprojects/imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj.filters rename to vsprojects/imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj.filters index aa8da0d1b..783943fd8 100644 --- a/vsprojects/imgui-glfw-ogl3/imgui-glfw-ogl3.vcxproj.filters +++ b/vsprojects/imgui-sdl3-ogl3/imgui-sdl3-ogl3.vcxproj.filters @@ -30,9 +30,6 @@ Source Files - - Source Files - Source Files @@ -48,6 +45,9 @@ Source Files + + Source Files + @@ -71,9 +71,6 @@ Header Files - - Header Files - Header Files @@ -83,8 +80,8 @@ Header Files - - - + + Header Files + \ No newline at end of file diff --git a/vsprojects/mainthunk/mainthunk.vcxproj b/vsprojects/mainthunk/mainthunk.vcxproj index a5401ce56..01833b5b8 100644 --- a/vsprojects/mainthunk/mainthunk.vcxproj +++ b/vsprojects/mainthunk/mainthunk.vcxproj @@ -231,7 +231,7 @@ {2bf92257-03c6-43fe-85e8-918166a07a26} - + {b86f9380-6228-4b11-87ad-29fdabf95abb} @@ -314,7 +314,6 @@ - @@ -323,7 +322,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - diff --git a/vsprojects/mainthunk/packages.config b/vsprojects/mainthunk/packages.config index 94be7c9ba..0d541c81b 100644 --- a/vsprojects/mainthunk/packages.config +++ b/vsprojects/mainthunk/packages.config @@ -1,6 +1,5 @@  - diff --git a/vsprojects/pcsx-redux.sln b/vsprojects/pcsx-redux.sln index 8aa9a3cc5..0b9a099c9 100644 --- a/vsprojects/pcsx-redux.sln +++ b/vsprojects/pcsx-redux.sln @@ -25,7 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GPU", "GPU", "{60F01E36-B838-4AA0-8057-8324E0E39526}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui-glfw-ogl3", "imgui-glfw-ogl3\imgui-glfw-ogl3.vcxproj", "{B86F9380-6228-4B11-87AD-29FDABF95ABB}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui-sdl3-ogl3", "imgui-sdl3-ogl3\imgui-sdl3-ogl3.vcxproj", "{B86F9380-6228-4B11-87AD-29FDABF95ABB}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gui", "gui\gui.vcxproj", "{6EC7FDF3-1418-40BD-8584-1EEA34AC3E3E}" EndProject diff --git a/vsprojects/tests/pcsxrunner/packages.config b/vsprojects/tests/pcsxrunner/packages.config index 333f96535..c7a7d620a 100644 --- a/vsprojects/tests/pcsxrunner/packages.config +++ b/vsprojects/tests/pcsxrunner/packages.config @@ -1,6 +1,5 @@  - \ No newline at end of file diff --git a/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj b/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj index eb0b31041..5e9a3e1e9 100644 --- a/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj +++ b/vsprojects/tests/pcsxrunner/pcsxrunner.vcxproj @@ -182,7 +182,7 @@ {2bf92257-03c6-43fe-85e8-918166a07a26} - + {b86f9380-6228-4b11-87ad-29fdabf95abb} @@ -272,7 +272,6 @@ - @@ -280,7 +279,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - From 6fc54b7a4c74d0dd11f620de94dd020ae81ecbc6 Mon Sep 17 00:00:00 2001 From: Nicolas 'Pixel' Noble Date: Sat, 9 May 2026 09:40:26 -0700 Subject: [PATCH 7/7] Bump ImGui submodule to v1.92.7-docking. This is the largest ImGui breaking-change set since 2015. The bump is motivated by a multi-viewport regression that surfaced in Phase 3: the main window stayed underneath all other viewports when focused. v1.92 includes fixes for several multi-viewport ordering issues and also reworks the font system in ways our pre-1.92 dynamic-DPI scaffold no longer needs. ImGui v1.91.5-docking -> v1.92.7-docking. Project-side adjustments: - forced-includes/imgui.h: define IM_ASSERT_USER_ERROR_RET and IM_ASSERT_USER_ERROR_RETV alongside the existing IM_ASSERT_USER_ERROR override. v1.92 added the new variants under the same #ifndef guard, so once we redirect the base macro we have to provide all three. - gui.cc / gui.h: PushFont takes a required size argument in v1.92. useMainFont/useMonoFont now pass the active font's LegacySize so the per-scale font map continues to drive rendering size, matching pre-1.92 PushFont(font) semantics. Dropped ImGui_ImplOpenGL3_Create /DestroyFontsTexture and ImFontAtlas::Build() which v1.92 retired in favor of the dynamic-texture protocol. The reload pass now also sets Style.FontSizeBase to the active main font's LegacySize so default-context frames render at the right size on DPI flip. changeScale refreshes io.FontDefault and Style.FontSizeBase on every scale change, not only the first one. - ram-viewer: ImFont::FindGlyph moved onto a per-size ImFontBaked, queried via font->GetFontBaked(GetFontSize()). Pre-fetch hex-glyph UVs and the font atlas TexRef in drawRAM() before ImGui::Render() rather than inside the AddCallback render closure, so the custom shader doesn't sample with stale UVs after a same-frame atlas grow. ImFont::ContainerAtlas was removed; we go through ImGui::GetIO() ->Fonts->TexRef.GetTexID() instead. - vram-viewer, ram-viewer: IM_OFFSETOF -> offsetof. - shader-editor: ImDrawCmd::TextureId -> TexRef.GetTexID(). Third-party touch-ups: - ImFileDialog: ImFont::FontSize -> LegacySize at the loaded-size call sites; ImGuiContext::FontSize (a different field, still extant) left alone. - imgui_lua_bindings: extend the perl generator's argument-type regex to accept ImTextureRef (constructs implicitly from ImTextureID, so the existing IM_TEXTURE_ID_ARG path still works at the call site). Regenerated imgui_iterator.inl from imgui.h via the project's documented procedure; restores Image / ImageWithBg / ImageButton bindings the prior generator dropped on v1.92's signatures. - third_party/imgui_md (forked to grumpycoders/imgui_md): TexID -> TexRef.GetTexID() on the font-atlas demo image; .gitmodules URL updated. - third_party/zep (already a grumpycoders fork): m_pFont->FontSize -> LegacySize. Signed-off-by: Nicolas 'Pixel' Noble --- .gitmodules | 2 +- src/forced-includes/imgui.h | 28 +- src/gui/gui.cc | 41 +- src/gui/gui.h | 16 +- src/gui/widgets/ram-viewer.cc | 71 +-- src/gui/widgets/ram-viewer.h | 10 + src/gui/widgets/shader-editor.cc | 5 +- src/gui/widgets/vram-viewer.cc | 4 +- third_party/ImFileDialog/ImFileDialog.cpp | 5 +- third_party/imgui | 2 +- .../generate_imgui_bindings.pl | 9 +- .../imgui_lua_bindings/imgui_iterator.inl | 456 ++++++++++++------ third_party/imgui_md | 2 +- third_party/zep | 2 +- 14 files changed, 443 insertions(+), 210 deletions(-) diff --git a/.gitmodules b/.gitmodules index 72c8e91b8..e23d86014 100644 --- a/.gitmodules +++ b/.gitmodules @@ -72,7 +72,7 @@ url = https://github.com/mity/md4c.git [submodule "third_party/imgui_md"] path = third_party/imgui_md - url = https://github.com/mekhontsev/imgui_md.git + url = https://github.com/grumpycoders/imgui_md.git [submodule "third_party/multipart-parser-c"] path = third_party/multipart-parser-c url = https://github.com/iafonov/multipart-parser-c diff --git a/src/forced-includes/imgui.h b/src/forced-includes/imgui.h index 165249bd3..416294456 100644 --- a/src/forced-includes/imgui.h +++ b/src/forced-includes/imgui.h @@ -30,7 +30,31 @@ void pcsxStaticImguiAssert(int exp, const char* expression); } #endif -#define IM_ASSERT_USER_ERROR(EXP, MSG) \ - if (!(EXP)) pcsxStaticImguiUserError((MSG)) +// imgui_internal.h gates IM_ASSERT_USER_ERROR_RET and IM_ASSERT_USER_ERROR_RETV +// behind the same #ifndef IM_ASSERT_USER_ERROR guard, so once we redirect the +// base macro we have to provide the recoverable-error variants as well. +// pcsxStaticImguiUserError throws by default, so the return statements after +// it are unreachable in normal operation but required for syntactic +// correctness when the user handler is replaced with a non-throwing one. +#define IM_ASSERT_USER_ERROR(EXP, MSG) \ + do { \ + if (!(EXP)) pcsxStaticImguiUserError((MSG)); \ + } while (0) + +#define IM_ASSERT_USER_ERROR_RET(EXP, MSG) \ + do { \ + if (!(EXP)) { \ + pcsxStaticImguiUserError((MSG)); \ + return; \ + } \ + } while (0) + +#define IM_ASSERT_USER_ERROR_RETV(EXP, RETV, MSG) \ + do { \ + if (!(EXP)) { \ + pcsxStaticImguiUserError((MSG)); \ + return (RETV); \ + } \ + } while (0) #define IM_ASSERT(EXP) pcsxStaticImguiAssert(!!(EXP), "ImGui assert: " #EXP " is false") diff --git a/src/gui/gui.cc b/src/gui/gui.cc index 874d56418..fd19655e8 100644 --- a/src/gui/gui.cc +++ b/src/gui/gui.cc @@ -1030,7 +1030,13 @@ void PCSX::GUI::startFrame() { auto scales = m_allScales; if (scales.empty()) scales.emplace(1.0f); - ImGui_ImplOpenGL3_DestroyFontsTexture(); + // ImGui v1.92 retired ImGui_ImplOpenGL3_{Destroy,Create}FontsTexture and + // ImFontAtlas::Build() in favour of the dynamic-texture protocol; the + // backend pulls fresh glyphs from the atlas as it grows. We still + // rebuild the per-scale font map below so each pinned scale has a + // matching ImFont with the right LegacySize ready for PushFont; actual + // per-size glyph data is allocated lazily inside ImFontBaked when those + // fonts are first rendered. m_mainFonts.clear(); m_monoFonts.clear(); @@ -1048,9 +1054,13 @@ void PCSX::GUI::startFrame() { m_monoFonts[scale] = loadFont(MAKEU8("NotoMono-Regular.ttf"), settings.get().value * scale, io, nullptr, false, false); } - io.Fonts->Build(); - io.FontDefault = m_mainFonts.begin()->second; - ImGui_ImplOpenGL3_CreateFontsTexture(); + // Pick the font matching the current DPI scale as the default; in + // v1.92 ImGui draws frames at Style.FontSizeBase unless overridden by + // PushFont, so we have to push that size up to match or the default + // frame text would render at the smallest pinned scale. + ImFont* mainFont = getMainFont(); + io.FontDefault = mainFont; + if (mainFont) ImGui::GetStyle().FontSizeBase = mainFont->LegacySize; } ImGui_ImplOpenGL3_NewFrame(); @@ -2976,6 +2986,25 @@ ImFont* PCSX::GUI::findClosestFont(const std::map& fonts) { void PCSX::GUI::changeScale(float scale) { if (scale <= 0.0f) return; m_currentScale = scale; - m_allScales.emplace(scale); - ImGui::SetCurrentFont(getMainFont()); + // Track this scale so the font reload pass bakes glyphs pre-sized for it; + // if it's a previously-unseen scale, request a reload so the per-scale font + // map gets a matching entry. v1.92's dynamic font system also handles + // unbaked sizes lazily via PushFont(font, size), but the pre-baked path + // still avoids a same-frame atlas grow on viewport DPI flips. + if (m_allScales.insert(scale).second) { + m_reloadFonts = true; + return; + } + // Already-pinned scale: no font reload needed, but the default frame font + // and base size still have to track the new closest-scale match. v1.92 + // draws default-context frames at Style.FontSizeBase, so we have to keep + // it in sync with the active main font's LegacySize on every DPI flip, + // not only the first one. + if (ImGui::GetCurrentContext()) { + ImFont* mainFont = getMainFont(); + if (mainFont) { + ImGui::GetIO().FontDefault = mainFont; + ImGui::GetStyle().FontSizeBase = mainFont->LegacySize; + } + } } \ No newline at end of file diff --git a/src/gui/gui.h b/src/gui/gui.h index b6eec7a08..ee64fa714 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -493,8 +493,20 @@ class GUI final : public UI { Widgets::ShaderEditor m_offscreenShaderEditor = {"offscreen"}; ImFont *getMainFont() { return findClosestFont(m_mainFonts); } ImFont *getMonoFont() { return findClosestFont(m_monoFonts); } - void useMainFont() { ImGui::PushFont(getMainFont()); } - void useMonoFont() { ImGui::PushFont(getMonoFont()); } + // ImGui v1.92's PushFont takes a size. We pass the closest-matching font's + // LegacySize (the size that was passed to AddFontFromFileTTF) so the + // per-scale font map continues to drive rendering size, matching pre-1.92 + // PushFont(font) semantics. Passing 0.0f instead would mean "keep current + // size" which would render the larger DPI-baked font at the previous + // smaller base size, defeating the per-scale map entirely. + void useMainFont() { + ImFont *f = getMainFont(); + ImGui::PushFont(f, f ? f->LegacySize : 0.0f); + } + void useMonoFont() { + ImFont *f = getMonoFont(); + ImGui::PushFont(f, f ? f->LegacySize : 0.0f); + } bool &allowMouseCaptureToggle() { return settings.get().value; } bool &isRawMouseMotionEnabled() { return settings.get().value; } diff --git a/src/gui/widgets/ram-viewer.cc b/src/gui/widgets/ram-viewer.cc index 3536e76fd..bef757635 100644 --- a/src/gui/widgets/ram-viewer.cc +++ b/src/gui/widgets/ram-viewer.cc @@ -343,32 +343,11 @@ void PCSX::Widgets::RAMViewer::imguiCB(const ImDrawList *parentList, const ImDra glUniform1i(m_locShowHex, m_showHex); glUniform1i(m_locShowGreyscale, m_showGreyscale); - // Extract glyph UV rects for hex digits from ImGui font atlas - ImFont *font = ImGui::GetFont(); - float glyphUVs[16 * 4]; - float glyphAspect = 0.5f; // default fallback - static const char hexChars[] = "0123456789ABCDEF"; - for (int i = 0; i < 16; i++) { - const ImFontGlyph *g = font->FindGlyph(hexChars[i]); - if (g) { - glyphUVs[i * 4 + 0] = g->U0; - glyphUVs[i * 4 + 1] = g->V0; - glyphUVs[i * 4 + 2] = g->U1; - glyphUVs[i * 4 + 3] = g->V1; - if (i == 0) { - float gw = g->X1 - g->X0; - float gh = g->Y1 - g->Y0; - if (gh > 0.0f) glyphAspect = gw / gh; - } - } else { - glyphUVs[i * 4 + 0] = 0.0f; - glyphUVs[i * 4 + 1] = 0.0f; - glyphUVs[i * 4 + 2] = 0.0f; - glyphUVs[i * 4 + 3] = 0.0f; - } - } - glUniform4fv(m_locGlyphUVs, 16, glyphUVs); - glUniform1f(m_locGlyphAspect, glyphAspect); + // Glyph UV rects + aspect are now pre-fetched in drawRAM() before the + // ImGui render pass; consume the cached snapshot here so we don't grow + // the font atlas mid-render and end up sampling with stale UVs. + glUniform4fv(m_locGlyphUVs, 16, m_glyphUVs); + glUniform1f(m_locGlyphAspect, m_glyphAspect); // Bind textures glUniform1i(m_locRAMTexture, 0); @@ -388,17 +367,17 @@ void PCSX::Widgets::RAMViewer::imguiCB(const ImDrawList *parentList, const ImDra glActiveTexture(GL_TEXTURE3); logger->bindExecHeatmap(); glActiveTexture(GL_TEXTURE4); - GLuint fontTexID = (GLuint)(intptr_t)font->ContainerAtlas->TexID; - glBindTexture(GL_TEXTURE_2D, fontTexID); + // Pre-fetched in drawRAM(); see m_fontTexID notes in ram-viewer.h. + glBindTexture(GL_TEXTURE_2D, m_fontTexID); glActiveTexture(GL_TEXTURE0); // Set vertex attributes to match ImGui vertex layout glEnableVertexAttribArray(m_locVtxPos); glVertexAttribPointer(m_locVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), - (GLvoid *)IM_OFFSETOF(ImDrawVert, pos)); + (GLvoid *)offsetof(ImDrawVert, pos)); glEnableVertexAttribArray(m_locVtxUV); glVertexAttribPointer(m_locVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), - (GLvoid *)IM_OFFSETOF(ImDrawVert, uv)); + (GLvoid *)offsetof(ImDrawVert, uv)); } void PCSX::Widgets::RAMViewer::drawRAM(GUI *gui) { @@ -410,6 +389,38 @@ void PCSX::Widgets::RAMViewer::drawRAM(GUI *gui) { m_origin = ImGui::GetCursorScreenPos(); m_mousePos = ImGui::GetIO().MousePos; + // Pre-fetch hex-glyph UVs from ImFontBaked at the current font size BEFORE + // ImGui renders. Doing this from inside the AddCallback render closure + // could grow the atlas after the backend has already staged its texture + // upload for the frame, leading the custom shader to sample with stale + // UVs. The render callback only consumes the cached snapshot. + { + ImFont *font = ImGui::GetFont(); + ImFontBaked *baked = font ? font->GetFontBaked(ImGui::GetFontSize()) : nullptr; + m_glyphAspect = 0.5f; // default fallback if FindGlyph misses + static const char hexChars[] = "0123456789ABCDEF"; + for (int i = 0; i < 16; i++) { + const ImFontGlyph *g = baked ? baked->FindGlyph(hexChars[i]) : nullptr; + if (g) { + m_glyphUVs[i * 4 + 0] = g->U0; + m_glyphUVs[i * 4 + 1] = g->V0; + m_glyphUVs[i * 4 + 2] = g->U1; + m_glyphUVs[i * 4 + 3] = g->V1; + if (i == 0) { + float gw = g->X1 - g->X0; + float gh = g->Y1 - g->Y0; + if (gh > 0.0f) m_glyphAspect = gw / gh; + } + } else { + m_glyphUVs[i * 4 + 0] = 0.0f; + m_glyphUVs[i * 4 + 1] = 0.0f; + m_glyphUVs[i * 4 + 2] = 0.0f; + m_glyphUVs[i * 4 + 3] = 0.0f; + } + } + m_fontTexID = (GLuint)(intptr_t)ImGui::GetIO().Fonts->TexRef.GetTexID(); + } + ImDrawList *drawList = ImGui::GetWindowDrawList(); drawList->AddCallback( [](const ImDrawList *parentList, const ImDrawCmd *cmd) { diff --git a/src/gui/widgets/ram-viewer.h b/src/gui/widgets/ram-viewer.h index 1e0a062a9..0549c67fd 100644 --- a/src/gui/widgets/ram-viewer.h +++ b/src/gui/widgets/ram-viewer.h @@ -78,6 +78,16 @@ class RAMViewer : public ZoomableImage { int m_locFontAtlas; int m_locGlyphUVs; int m_locGlyphAspect; + + // Cached hex-glyph atlas state, populated during drawRAM() (which runs + // before the ImGui render pass), then consumed inside imguiCB() during + // the actual draw. Pulling glyphs out of ImFontBaked from inside the + // render callback could grow the atlas after the backend has already + // staged its texture upload for the frame, leaving us sampling with + // stale UVs; pre-fetching avoids that race. + float m_glyphUVs[16 * 4] = {0}; + float m_glyphAspect = 0.5f; + GLuint m_fontTexID = 0; int m_locShowHex; int m_locShowGreyscale; diff --git a/src/gui/widgets/shader-editor.cc b/src/gui/widgets/shader-editor.cc index 9ef9e2fe1..dc309f141 100644 --- a/src/gui/widgets/shader-editor.cc +++ b/src/gui/widgets/shader-editor.cc @@ -752,7 +752,10 @@ void PCSX::Widgets::ShaderEditor::renderWithImgui(GUI *gui, ImTextureID textureI } void PCSX::Widgets::ShaderEditor::imguiCB(const ImDrawList *parentList, const ImDrawCmd *cmd) { - GLuint textureID = static_cast(cmd->TextureId); + // ImGui v1.92 renamed ImDrawCmd::TextureId to ImDrawCmd::TexRef (an + // ImTextureRef). GetTexID() returns the underlying ImTextureID we + // previously read directly. + GLuint textureID = static_cast(cmd->TexRef.GetTexID()); GLfloat projMtx[4][4]; if (m_imguiProjMtxLoc == -1) { diff --git a/src/gui/widgets/vram-viewer.cc b/src/gui/widgets/vram-viewer.cc index 70688f92d..a390602b5 100644 --- a/src/gui/widgets/vram-viewer.cc +++ b/src/gui/widgets/vram-viewer.cc @@ -553,10 +553,10 @@ void PCSX::Widgets::VRAMViewer::imguiCB(const ImDrawList *parentList, const ImDr glUniform1i(m_attribLocationTex, 0); glEnableVertexAttribArray(m_attribLocationVtxPos); glVertexAttribPointer(m_attribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), - (GLvoid *)IM_OFFSETOF(ImDrawVert, pos)); + (GLvoid *)offsetof(ImDrawVert, pos)); glEnableVertexAttribArray(m_attribLocationVtxUV); glVertexAttribPointer(m_attribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), - (GLvoid *)IM_OFFSETOF(ImDrawVert, uv)); + (GLvoid *)offsetof(ImDrawVert, uv)); glUniform4f(m_attribLocationWrittenColor, m_writtenColor.x, m_writtenColor.y, m_writtenColor.z, m_writtenColor.w); glUniform1i(m_attribLocationWrittenHeatmap, 1); glUniform1i(m_attribLocationWrittenHighlight, 3); diff --git a/third_party/ImFileDialog/ImFileDialog.cpp b/third_party/ImFileDialog/ImFileDialog.cpp index 300309e61..0b72e3ec0 100644 --- a/third_party/ImFileDialog/ImFileDialog.cpp +++ b/third_party/ImFileDialog/ImFileDialog.cpp @@ -28,7 +28,10 @@ #include #endif -#define ICON_SIZE ImGui::GetFont()->FontSize + 3 +#define ICON_SIZE ImGui::GetFont()->LegacySize + 3 +// GImGui->FontSize is the current rendering size on the global ImGui context; +// it survived ImGui v1.92 (only ImFont::FontSize was removed in favor of +// LegacySize). The original macro queried the live size, not the loaded one. #define GUI_ELEMENT_SIZE std::max(GImGui->FontSize + 10.f, 24.f) #define DEFAULT_ICON_SIZE 32 #define PI 3.141592f diff --git a/third_party/imgui b/third_party/imgui index 368123ab0..b1bcb12a6 160000 --- a/third_party/imgui +++ b/third_party/imgui @@ -1 +1 @@ -Subproject commit 368123ab06b2b573d585e52f84cd782c5c006697 +Subproject commit b1bcb12a624af7509894c8e77dd47416997777fa diff --git a/third_party/imgui_lua_bindings/generate_imgui_bindings.pl b/third_party/imgui_lua_bindings/generate_imgui_bindings.pl index 6c9a333ee..24dc839ca 100755 --- a/third_party/imgui_lua_bindings/generate_imgui_bindings.pl +++ b/third_party/imgui_lua_bindings/generate_imgui_bindings.pl @@ -312,10 +312,11 @@ sub generateImguiGeneric { push(@before, "UINT_ARG($name)"); } push(@funcArgs, $name); - #ImTextureID or const ImTextureID& - # const ImTextureID& is the same thing as var - # as lua is concerned - } elsif ($args[$i] =~ m/^ *(ImTextureID|const ImTextureID&) ([^ =\[]*) *$/) { + #ImTextureID, const ImTextureID&, or ImTextureRef (ImGui v1.92+) + # const ImTextureID& is the same thing as ImTextureID as far as lua is concerned. + # ImTextureRef in v1.92 wraps an ImTextureID and constructs implicitly from one, + # so we pull the Lua arg as ImTextureID and let C++ wrap it at the call site. + } elsif ($args[$i] =~ m/^ *(ImTextureID|const ImTextureID&|ImTextureRef) ([^ =\[]*) *$/) { my $name = $2; push(@before, "IM_TEXTURE_ID_ARG($name)"); push(@funcArgs, $name); diff --git a/third_party/imgui_lua_bindings/imgui_iterator.inl b/third_party/imgui_lua_bindings/imgui_iterator.inl index 1b3219a97..511821e01 100644 --- a/third_party/imgui_lua_bindings/imgui_iterator.inl +++ b/third_party/imgui_lua_bindings/imgui_iterator.inl @@ -2,6 +2,8 @@ //struct ImVec4 +//struct ImTextureRef + //namespace ImGui // IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); @@ -28,7 +30,7 @@ POP_END_STACK(0) END_IMGUI_FUNC // IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData(). //Not allowed to use this function -// IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. +// IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). Call ImGui_ImplXXXX_RenderDrawData() function in your Renderer Backend to render. // Unsupported return type ImDrawData* // IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_FUNCTION(ShowDemoWindow) @@ -249,11 +251,6 @@ END_IMGUI_FUNC IMGUI_FUNCTION(SetWindowFocus) CALL_FUNCTION_NO_RET(SetWindowFocus) END_IMGUI_FUNC -// IMGUI_API void SetWindowFontScale(float scale); // [OBSOLETE] set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). -IMGUI_FUNCTION(SetWindowFontScale) -NUMBER_ARG(scale) -CALL_FUNCTION_NO_RET(SetWindowFontScale, scale) -END_IMGUI_FUNC // IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_FUNCTION(SetWindowPos_3) LABEL_ARG(name) @@ -332,12 +329,21 @@ NUMBER_ARG(local_y) OPTIONAL_NUMBER_ARG(center_y_ratio, 0.5f) CALL_FUNCTION_NO_RET(SetScrollFromPosY, local_y, center_y_ratio) END_IMGUI_FUNC -// IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font +// IMGUI_API void PushFont(ImFont* font, float font_size_base_unscaled); // Use NULL as a shortcut to keep current font. Use 0.0f to keep current size. // Unsupported arg type ImFont* font // IMGUI_API void PopFont(); IMGUI_FUNCTION(PopFont) CALL_FUNCTION_NO_RET(PopFont) END_IMGUI_FUNC +// IMGUI_API ImFont* GetFont(); // get current font +// Unsupported return type ImFont* +// IMGUI_API float GetFontSize(); // get current scaled font size (= height in pixels). AFTER global scale factors applied. *IMPORTANT* DO NOT PASS THIS VALUE TO PushFont()! Use ImGui::GetStyle().FontSizeBase to get value before global scale factors. +IMGUI_FUNCTION(GetFontSize) +CALL_FUNCTION(GetFontSize, float) +PUSH_NUMBER(ret) +END_IMGUI_FUNC +// IMGUI_API ImFontBaked* GetFontBaked(); // get current font bound at current size // == GetFont()->GetFontBaked(GetFontSize()) +// Unsupported return type ImFontBaked* // IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); // modify a style color. always use this if you modify the style after NewFrame(). IMGUI_FUNCTION(PushStyleColor) INT_ARG(idx) @@ -421,13 +427,6 @@ END_IMGUI_FUNC IMGUI_FUNCTION(PopTextWrapPos) CALL_FUNCTION_NO_RET(PopTextWrapPos) END_IMGUI_FUNC -// IMGUI_API ImFont* GetFont(); // get current font -// Unsupported return type ImFont* -// IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied -IMGUI_FUNCTION(GetFontSize) -CALL_FUNCTION(GetFontSize, float) -PUSH_NUMBER(ret) -END_IMGUI_FUNC // IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a white pixel, useful to draw custom shapes via the ImDrawList API IMGUI_FUNCTION(GetFontTexUvWhitePixel) CALL_FUNCTION(GetFontTexUvWhitePixel, ImVec2) @@ -650,7 +649,7 @@ END_IMGUI_FUNC // Unsupported arg type ...) IM_FMTARGS(1 // IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); // Unsupported arg type va_list args) IM_FMTLIST(1 -// IMGUI_API void SeparatorText(const char* label); // currently: formatted text with an horizontal line +// IMGUI_API void SeparatorText(const char* label); // currently: formatted text with a horizontal line IMGUI_FUNCTION(SeparatorText) LABEL_ARG(label) CALL_FUNCTION_NO_RET(SeparatorText, label) @@ -737,32 +736,41 @@ LABEL_ARG(label) CALL_FUNCTION(TextLink, bool, label) PUSH_BOOL(ret) END_IMGUI_FUNC -// IMGUI_API void TextLinkOpenURL(const char* label, const char* url = NULL); // hyperlink text button, automatically open file/url when clicked +// IMGUI_API bool TextLinkOpenURL(const char* label, const char* url = NULL); // hyperlink text button, automatically open file/url when clicked IMGUI_FUNCTION(TextLinkOpenURL) LABEL_ARG(label) OPTIONAL_LABEL_ARG(url, NULL) -CALL_FUNCTION_NO_RET(TextLinkOpenURL, label, url) +CALL_FUNCTION(TextLinkOpenURL, bool, label, url) +PUSH_BOOL(ret) END_IMGUI_FUNC -// IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2 0 0, const ImVec2& uv1 = ImVec2 1 1, const ImVec4& tint_col = ImVec4 1 1 1 1, const ImVec4& border_col = ImVec4 0 0 0 0); +// IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2 0 0, const ImVec2& uv1 = ImVec2 1 1); IMGUI_FUNCTION(Image) -IM_TEXTURE_ID_ARG(user_texture_id) +IM_TEXTURE_ID_ARG(tex_ref) IM_VEC_2_ARG(image_size) OPTIONAL_IM_VEC_2_ARG(uv0, 0, 0) OPTIONAL_IM_VEC_2_ARG(uv1, 1, 1) +CALL_FUNCTION_NO_RET(Image, tex_ref, image_size, uv0, uv1) +END_IMGUI_FUNC +// IMGUI_API void ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2 0 0, const ImVec2& uv1 = ImVec2 1 1, const ImVec4& bg_col = ImVec4 0 0 0 0, const ImVec4& tint_col = ImVec4 1 1 1 1); +IMGUI_FUNCTION(ImageWithBg) +IM_TEXTURE_ID_ARG(tex_ref) +IM_VEC_2_ARG(image_size) +OPTIONAL_IM_VEC_2_ARG(uv0, 0, 0) +OPTIONAL_IM_VEC_2_ARG(uv1, 1, 1) +OPTIONAL_IM_VEC_4_ARG(bg_col, 0, 0, 0, 0) OPTIONAL_IM_VEC_4_ARG(tint_col, 1, 1, 1, 1) -OPTIONAL_IM_VEC_4_ARG(border_col, 0, 0, 0, 0) -CALL_FUNCTION_NO_RET(Image, user_texture_id, image_size, uv0, uv1, tint_col, border_col) +CALL_FUNCTION_NO_RET(ImageWithBg, tex_ref, image_size, uv0, uv1, bg_col, tint_col) END_IMGUI_FUNC -// IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2 0 0, const ImVec2& uv1 = ImVec2 1 1, const ImVec4& bg_col = ImVec4 0 0 0 0, const ImVec4& tint_col = ImVec4 1 1 1 1); +// IMGUI_API bool ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2 0 0, const ImVec2& uv1 = ImVec2 1 1, const ImVec4& bg_col = ImVec4 0 0 0 0, const ImVec4& tint_col = ImVec4 1 1 1 1); IMGUI_FUNCTION(ImageButton) LABEL_ARG(str_id) -IM_TEXTURE_ID_ARG(user_texture_id) +IM_TEXTURE_ID_ARG(tex_ref) IM_VEC_2_ARG(image_size) OPTIONAL_IM_VEC_2_ARG(uv0, 0, 0) OPTIONAL_IM_VEC_2_ARG(uv1, 1, 1) OPTIONAL_IM_VEC_4_ARG(bg_col, 0, 0, 0, 0) OPTIONAL_IM_VEC_4_ARG(tint_col, 1, 1, 1, 1) -CALL_FUNCTION(ImageButton, bool, str_id, user_texture_id, image_size, uv0, uv1, bg_col, tint_col) +CALL_FUNCTION(ImageButton, bool, str_id, tex_ref, image_size, uv0, uv1, bg_col, tint_col) PUSH_BOOL(ret) END_IMGUI_FUNC // IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); @@ -1050,7 +1058,7 @@ CALL_FUNCTION(TreeNode, bool, label) IF_RET_ADD_END_STACK(6) PUSH_BOOL(ret) END_IMGUI_FUNC -// IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). +// IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorrelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). // Unsupported arg type ...) IM_FMTARGS(2 // IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " // Unsupported arg type const void* ptr_id @@ -1122,6 +1130,12 @@ IMGUI_FUNCTION(SetNextItemStorageID) UINT_ARG(storage_id) CALL_FUNCTION_NO_RET(SetNextItemStorageID, storage_id) END_IMGUI_FUNC +// IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); // retrieve tree node open/close state. +IMGUI_FUNCTION(TreeNodeGetOpen) +UINT_ARG(storage_id) +CALL_FUNCTION(TreeNodeGetOpen, bool, storage_id) +PUSH_BOOL(ret) +END_IMGUI_FUNC // IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2 0 0); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_FUNCTION(Selectable) LABEL_ARG(label) @@ -1342,36 +1356,36 @@ UINT_ARG(id) OPTIONAL_INT_ARG(popup_flags, 0) CALL_FUNCTION_NO_RET(OpenPopup, id, popup_flags) END_IMGUI_FUNC -// IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) +// IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_FUNCTION(OpenPopupOnItemClick) OPTIONAL_LABEL_ARG(str_id, NULL) -OPTIONAL_INT_ARG(popup_flags, 1) +OPTIONAL_INT_ARG(popup_flags, 0) CALL_FUNCTION_NO_RET(OpenPopupOnItemClick, str_id, popup_flags) END_IMGUI_FUNC // IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. IMGUI_FUNCTION(CloseCurrentPopup) CALL_FUNCTION_NO_RET(CloseCurrentPopup) END_IMGUI_FUNC -// IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! +// IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_FUNCTION(BeginPopupContextItem) OPTIONAL_LABEL_ARG(str_id, NULL) -OPTIONAL_INT_ARG(popup_flags, 1) +OPTIONAL_INT_ARG(popup_flags, 0) CALL_FUNCTION(BeginPopupContextItem, bool, str_id, popup_flags) IF_RET_ADD_END_STACK(13) PUSH_BOOL(ret) END_IMGUI_FUNC -// IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window. +// IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0);// open+begin popup when clicked on current window. IMGUI_FUNCTION(BeginPopupContextWindow) OPTIONAL_LABEL_ARG(str_id, NULL) -OPTIONAL_INT_ARG(popup_flags, 1) +OPTIONAL_INT_ARG(popup_flags, 0) CALL_FUNCTION(BeginPopupContextWindow, bool, str_id, popup_flags) IF_RET_ADD_END_STACK(13) PUSH_BOOL(ret) END_IMGUI_FUNC -// IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows). +// IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked in void (where there are no windows). IMGUI_FUNCTION(BeginPopupContextVoid) OPTIONAL_LABEL_ARG(str_id, NULL) -OPTIONAL_INT_ARG(popup_flags, 1) +OPTIONAL_INT_ARG(popup_flags, 0) CALL_FUNCTION(BeginPopupContextVoid, bool, str_id, popup_flags) IF_RET_ADD_END_STACK(13) PUSH_BOOL(ret) @@ -1399,7 +1413,7 @@ IMGUI_FUNCTION(EndTable) CALL_FUNCTION_NO_RET(EndTable) POP_END_STACK(14) END_IMGUI_FUNC -// IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. +// IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. 'min_row_height' include the minimum top and bottom padding aka CellPadding.y * 2.0f. IMGUI_FUNCTION(TableNextRow) OPTIONAL_INT_ARG(row_flags, 0) OPTIONAL_NUMBER_ARG(min_row_height, 0.0f) @@ -1455,7 +1469,7 @@ IMGUI_FUNCTION(TableGetColumnIndex) CALL_FUNCTION(TableGetColumnIndex, int) PUSH_NUMBER(ret) END_IMGUI_FUNC -// IMGUI_API int TableGetRowIndex(); // return current row index. +// IMGUI_API int TableGetRowIndex(); // return current row index (header rows are accounted for) IMGUI_FUNCTION(TableGetRowIndex) CALL_FUNCTION(TableGetRowIndex, int) PUSH_NUMBER(ret) @@ -1584,7 +1598,7 @@ CALL_FUNCTION_NO_RET(SetNextWindowDockID, dock_id, cond) END_IMGUI_FUNC // IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (control docking compatibility + provide hints to platform backend via custom viewport flags and platform parent/child relationship) // Unsupported arg type const ImGuiWindowClass* window_class -// IMGUI_API ImGuiID GetWindowDockID(); +// IMGUI_API ImGuiID GetWindowDockID(); // get dock id of current window, or 0 if not associated to any docking node. IMGUI_FUNCTION(GetWindowDockID) CALL_FUNCTION(GetWindowDockID, unsigned int) PUSH_NUMBER(ret) @@ -1674,7 +1688,7 @@ END_IMGUI_FUNC IMGUI_FUNCTION(PopClipRect) CALL_FUNCTION_NO_RET(PopClipRect) END_IMGUI_FUNC -// IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. +// IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a newly appearing window. IMGUI_FUNCTION(SetItemDefaultFocus) CALL_FUNCTION_NO_RET(SetItemDefaultFocus) END_IMGUI_FUNC @@ -1683,7 +1697,12 @@ IMGUI_FUNCTION(SetKeyboardFocusHere) OPTIONAL_INT_ARG(offset, 0) CALL_FUNCTION_NO_RET(SetKeyboardFocusHere, offset) END_IMGUI_FUNC -// IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this. +// IMGUI_API void SetNavCursorVisible(bool visible); // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse. +IMGUI_FUNCTION(SetNavCursorVisible) +BOOL_ARG(visible) +CALL_FUNCTION_NO_RET(SetNavCursorVisible, visible) +END_IMGUI_FUNC +// IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Typically useful with InvisibleButton(), Selectable(), TreeNode() covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this. IMGUI_FUNCTION(SetNextItemAllowOverlap) CALL_FUNCTION_NO_RET(SetNextItemAllowOverlap) END_IMGUI_FUNC @@ -1777,6 +1796,8 @@ CALL_FUNCTION(GetItemRectSize, ImVec2) PUSH_NUMBER(ret.x) PUSH_NUMBER(ret.y) END_IMGUI_FUNC +// IMGUI_API ImGuiItemFlags GetItemFlags(); // get generic flags of last item +// Unsupported return type ImGuiItemFlags // IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. This can never be NULL. // Unsupported return type ImGuiViewport* // IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport = NULL); // get background draw list for the given viewport or viewport associated to the current window. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. @@ -1845,7 +1866,7 @@ END_IMGUI_FUNC // Unsupported arg type float& out_b // IMGUI_API bool IsKeyDown(ImGuiKey key); // is key being held. // Unsupported arg type ImGuiKey key -// IMGUI_API bool IsKeyPressed(ImGuiKey key, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate +// IMGUI_API bool IsKeyPressed(ImGuiKey key, bool repeat = true); // was key pressed (went from !Down to Down)? Repeat rate uses io.KeyRepeatDelay / KeyRepeatRate. // Unsupported arg type ImGuiKey key // IMGUI_API bool IsKeyReleased(ImGuiKey key); // was key released (went from Down to !Down)? // Unsupported arg type ImGuiKey key @@ -1853,7 +1874,7 @@ END_IMGUI_FUNC // Unsupported arg type ImGuiKeyChord key_chord // IMGUI_API int GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate // Unsupported arg type ImGuiKey key -// IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared. +// IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names are provided for debugging purpose and are not meant to be saved persistently nor compared. // Unsupported arg type ImGuiKey key // IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call. IMGUI_FUNCTION(SetNextFrameWantCaptureKeyboard) @@ -1893,6 +1914,13 @@ INT_ARG(button) CALL_FUNCTION(IsMouseDoubleClicked, bool, button) PUSH_BOOL(ret) END_IMGUI_FUNC +// IMGUI_API bool IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay); // delayed mouse release (use very sparingly!). Generally used with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount==1' test. This is a very rarely used UI idiom, but some apps use this: e.g. MS Explorer single click on an icon to rename. +IMGUI_FUNCTION(IsMouseReleasedWithDelay) +INT_ARG(button) +NUMBER_ARG(delay) +CALL_FUNCTION(IsMouseReleasedWithDelay, bool, button, delay) +PUSH_BOOL(ret) +END_IMGUI_FUNC // IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0). IMGUI_FUNCTION(GetMouseClickedCount) INT_ARG(button) @@ -1953,7 +1981,7 @@ IMGUI_FUNCTION(SetMouseCursor) INT_ARG(cursor_type) CALL_FUNCTION_NO_RET(SetMouseCursor, cursor_type) END_IMGUI_FUNC -// IMGUI_API void SetNextFrameWantCaptureMouse(bool want_capture_mouse); // Override io.WantCaptureMouse flag next frame (said flag is left for your application to handle, typical when true it instucts your app to ignore inputs). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse;" after the next NewFrame() call. +// IMGUI_API void SetNextFrameWantCaptureMouse(bool want_capture_mouse); // Override io.WantCaptureMouse flag next frame (said flag is left for your application to handle, typical when true it instructs your app to ignore inputs). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse;" after the next NewFrame() call. IMGUI_FUNCTION(SetNextFrameWantCaptureMouse) BOOL_ARG(want_capture_mouse) CALL_FUNCTION_NO_RET(SetNextFrameWantCaptureMouse, want_capture_mouse) @@ -2020,20 +2048,20 @@ END_IMGUI_FUNC // Unsupported arg type size_t size // IMGUI_API void MemFree(void* ptr); // Unsupported arg type void* ptr -// IMGUI_API void UpdatePlatformWindows(); // call in main loop. will call CreateWindow/ResizeWindow/etc. platform functions for each secondary viewport, and DestroyWindow for each inactive viewport. +// IMGUI_API void UpdatePlatformWindows(); // call in main loop. will call CreateWindow/ResizeWindow/etc. platform functions for each secondary viewport, and DestroyWindow for each inactive viewport. IMGUI_FUNCTION(UpdatePlatformWindows) CALL_FUNCTION_NO_RET(UpdatePlatformWindows) END_IMGUI_FUNC -// IMGUI_API void RenderPlatformWindowsDefault(void* platform_render_arg = NULL, void* renderer_render_arg = NULL); // call in main loop. will call RenderWindow/SwapBuffers platform functions for each secondary viewport which doesn't have the ImGuiViewportFlags_Minimized flag set. May be reimplemented by user for custom rendering needs. +// IMGUI_API void RenderPlatformWindowsDefault(void* platform_render_arg = NULL, void* renderer_render_arg = NULL); // call in main loop. will call RenderWindow/SwapBuffers platform functions for each secondary viewport which doesn't have the ImGuiViewportFlags_Minimized flag set. May be reimplemented by user for custom rendering needs. // Unsupported arg type void* platform_render_arg = NULL // Unsupported arg type void* renderer_render_arg = NULL -// IMGUI_API void DestroyPlatformWindows(); // call DestroyWindow platform functions for all viewports. call from backend Shutdown() if you need to close platform windows before imgui shutdown. otherwise will be called by DestroyContext(). +// IMGUI_API void DestroyPlatformWindows(); // call DestroyWindow platform functions for all viewports. call from backend Shutdown() if you need to close platform windows before imgui shutdown. otherwise will be called by DestroyContext(). IMGUI_FUNCTION(DestroyPlatformWindows) CALL_FUNCTION_NO_RET(DestroyPlatformWindows) END_IMGUI_FUNC -// IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID id); // this is a helper for backends. +// IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID viewport_id); // this is a helper for backends. // Unsupported return type ImGuiViewport* -// IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); // this is a helper for backends. the type platform_handle is decided by the backend (e.g. HWND, MyWindow*, GLFWwindow* etc.) +// IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); // this is a helper for backends. the type platform_handle is decided by the backend (e.g. HWND, MyWindow*, GLFWwindow* etc.) // Unsupported return type ImGuiViewport* // Unsupported arg type void* platform_handle END_STACK_START @@ -2095,9 +2123,9 @@ MAKE_ENUM(ImGuiWindowFlags_NoBringToFrontOnFocus,NoBringToFrontOnFocus) MAKE_ENUM(ImGuiWindowFlags_AlwaysVerticalScrollbar,AlwaysVerticalScrollbar) // ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) MAKE_ENUM(ImGuiWindowFlags_AlwaysHorizontalScrollbar,AlwaysHorizontalScrollbar) -// ImGuiWindowFlags_NoNavInputs = 1 << 16, // No gamepad/keyboard navigation within the window +// ImGuiWindowFlags_NoNavInputs = 1 << 16, // No keyboard/gamepad navigation within the window MAKE_ENUM(ImGuiWindowFlags_NoNavInputs,NoNavInputs) -// ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) +// ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with keyboard/gamepad navigation (e.g. skipped by Ctrl+Tab) MAKE_ENUM(ImGuiWindowFlags_NoNavFocus,NoNavFocus) // ImGuiWindowFlags_UnsavedDocument = 1 << 18, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. MAKE_ENUM(ImGuiWindowFlags_UnsavedDocument,UnsavedDocument) @@ -2109,6 +2137,8 @@ MAKE_ENUM(ImGuiWindowFlags_NoNav,NoNav) MAKE_ENUM(ImGuiWindowFlags_NoDecoration,NoDecoration) // ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, MAKE_ENUM(ImGuiWindowFlags_NoInputs,NoInputs) +// ImGuiWindowFlags_DockNodeHost = 1 << 23, // Don't use! For internal use by Begin()/NewFrame() +MAKE_ENUM(ImGuiWindowFlags_DockNodeHost,DockNodeHost) // ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() MAKE_ENUM(ImGuiWindowFlags_ChildWindow,ChildWindow) // ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() @@ -2119,12 +2149,6 @@ MAKE_ENUM(ImGuiWindowFlags_Popup,Popup) MAKE_ENUM(ImGuiWindowFlags_Modal,Modal) // ImGuiWindowFlags_ChildMenu = 1 << 28, // Don't use! For internal use by BeginMenu() MAKE_ENUM(ImGuiWindowFlags_ChildMenu,ChildMenu) -// ImGuiWindowFlags_DockNodeHost = 1 << 29, // Don't use! For internal use by Begin()/NewFrame() -MAKE_ENUM(ImGuiWindowFlags_DockNodeHost,DockNodeHost) -// ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. -MAKE_ENUM(ImGuiWindowFlags_AlwaysUseWindowPadding,AlwaysUseWindowPadding) -// ImGuiWindowFlags_NavFlattened = 1 << 31, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call. -MAKE_ENUM(ImGuiWindowFlags_NavFlattened,NavFlattened) END_ENUM(WindowFlags) //enum ImGuiChildFlags_ @@ -2147,10 +2171,8 @@ MAKE_ENUM(ImGuiChildFlags_AutoResizeY,AutoResizeY) MAKE_ENUM(ImGuiChildFlags_AlwaysAutoResize,AlwaysAutoResize) // ImGuiChildFlags_FrameStyle = 1 << 7, // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding. MAKE_ENUM(ImGuiChildFlags_FrameStyle,FrameStyle) -// ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. +// ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow keyboard/gamepad navigation to cross over parent border to this child or between sibling child windows. MAKE_ENUM(ImGuiChildFlags_NavFlattened,NavFlattened) -// ImGuiChildFlags_Border = ImGuiChildFlags_Borders, // Renamed in 1.91.1 (August 2024) for consistency. -MAKE_ENUM(ImGuiChildFlags_Border,Border) END_ENUM(ChildFlags) //enum ImGuiItemFlags_ @@ -2167,6 +2189,10 @@ MAKE_ENUM(ImGuiItemFlags_NoNavDefaultFocus,NoNavDefaultFocus) MAKE_ENUM(ImGuiItemFlags_ButtonRepeat,ButtonRepeat) // ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window. MAKE_ENUM(ImGuiItemFlags_AutoClosePopups,AutoClosePopups) +// ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set. +MAKE_ENUM(ImGuiItemFlags_AllowDuplicateId,AllowDuplicateId) +// ImGuiItemFlags_Disabled = 1 << 6, // false // [Internal] Disable interactions. DOES NOT affect visuals. This is used by BeginDisabled()/EndDisabled() and only provided here so you can read back via GetItemFlags(). +MAKE_ENUM(ImGuiItemFlags_Disabled,Disabled) END_ENUM(ItemFlags) //enum ImGuiInputTextFlags_ @@ -2185,11 +2211,11 @@ MAKE_ENUM(ImGuiInputTextFlags_CharsUppercase,CharsUppercase) MAKE_ENUM(ImGuiInputTextFlags_CharsNoBlank,CharsNoBlank) // ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field MAKE_ENUM(ImGuiInputTextFlags_AllowTabInput,AllowTabInput) -// ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function. +// ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead! MAKE_ENUM(ImGuiInputTextFlags_EnterReturnsTrue,EnterReturnsTrue) // ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert) MAKE_ENUM(ImGuiInputTextFlags_EscapeClearsAll,EscapeClearsAll) -// ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). +// ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode: validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). Note that Shift+Enter always enter a new line either way. MAKE_ENUM(ImGuiInputTextFlags_CtrlEnterForNewLine,CtrlEnterForNewLine) // ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode MAKE_ENUM(ImGuiInputTextFlags_ReadOnly,ReadOnly) @@ -2207,18 +2233,22 @@ MAKE_ENUM(ImGuiInputTextFlags_DisplayEmptyRefVal,DisplayEmptyRefVal) MAKE_ENUM(ImGuiInputTextFlags_NoHorizontalScroll,NoHorizontalScroll) // ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). MAKE_ENUM(ImGuiInputTextFlags_NoUndoRedo,NoUndoRedo) -// ImGuiInputTextFlags_CallbackCompletion = 1 << 17, // Callback on pressing TAB (for completion handling) +// ImGuiInputTextFlags_ElideLeft = 1 << 17, // When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only! +MAKE_ENUM(ImGuiInputTextFlags_ElideLeft,ElideLeft) +// ImGuiInputTextFlags_CallbackCompletion = 1 << 18, // Callback on pressing TAB (for completion handling) MAKE_ENUM(ImGuiInputTextFlags_CallbackCompletion,CallbackCompletion) -// ImGuiInputTextFlags_CallbackHistory = 1 << 18, // Callback on pressing Up/Down arrows (for history handling) +// ImGuiInputTextFlags_CallbackHistory = 1 << 19, // Callback on pressing Up/Down arrows (for history handling) MAKE_ENUM(ImGuiInputTextFlags_CallbackHistory,CallbackHistory) -// ImGuiInputTextFlags_CallbackAlways = 1 << 19, // Callback on each iteration. User code may query cursor position, modify text buffer. +// ImGuiInputTextFlags_CallbackAlways = 1 << 20, // Callback on each iteration. User code may query cursor position, modify text buffer. MAKE_ENUM(ImGuiInputTextFlags_CallbackAlways,CallbackAlways) -// ImGuiInputTextFlags_CallbackCharFilter = 1 << 20, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. +// ImGuiInputTextFlags_CallbackCharFilter = 1 << 21, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. MAKE_ENUM(ImGuiInputTextFlags_CallbackCharFilter,CallbackCharFilter) -// ImGuiInputTextFlags_CallbackResize = 1 << 21, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) +// ImGuiInputTextFlags_CallbackResize = 1 << 22, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) MAKE_ENUM(ImGuiInputTextFlags_CallbackResize,CallbackResize) -// ImGuiInputTextFlags_CallbackEdit = 1 << 22, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) +// ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active. MAKE_ENUM(ImGuiInputTextFlags_CallbackEdit,CallbackEdit) +// ImGuiInputTextFlags_WordWrap = 1 << 24, // InputTextMultiline(): word-wrap lines that are too long. +MAKE_ENUM(ImGuiInputTextFlags_WordWrap,WordWrap) END_ENUM(InputTextFlags) //enum ImGuiTreeNodeFlags_ @@ -2229,7 +2259,7 @@ MAKE_ENUM(ImGuiTreeNodeFlags_None,None) MAKE_ENUM(ImGuiTreeNodeFlags_Selected,Selected) // ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader) MAKE_ENUM(ImGuiTreeNodeFlags_Framed,Framed) -// ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one +// ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap(). MAKE_ENUM(ImGuiTreeNodeFlags_AllowOverlap,AllowOverlap) // ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack MAKE_ENUM(ImGuiTreeNodeFlags_NoTreePushOnOpen,NoTreePushOnOpen) @@ -2241,7 +2271,7 @@ MAKE_ENUM(ImGuiTreeNodeFlags_DefaultOpen,DefaultOpen) MAKE_ENUM(ImGuiTreeNodeFlags_OpenOnDoubleClick,OpenOnDoubleClick) // ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Open when clicking on the arrow part (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined. MAKE_ENUM(ImGuiTreeNodeFlags_OpenOnArrow,OpenOnArrow) -// ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). +// ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). Note: will always open a tree/id scope and return true. If you never use that scope, add ImGuiTreeNodeFlags_NoTreePushOnOpen. MAKE_ENUM(ImGuiTreeNodeFlags_Leaf,Leaf) // ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag! MAKE_ENUM(ImGuiTreeNodeFlags_Bullet,Bullet) @@ -2251,27 +2281,37 @@ MAKE_ENUM(ImGuiTreeNodeFlags_FramePadding,FramePadding) MAKE_ENUM(ImGuiTreeNodeFlags_SpanAvailWidth,SpanAvailWidth) // ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area). MAKE_ENUM(ImGuiTreeNodeFlags_SpanFullWidth,SpanFullWidth) -// ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. -MAKE_ENUM(ImGuiTreeNodeFlags_SpanTextWidth,SpanTextWidth) -// ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (text will still fit in current column) +// ImGuiTreeNodeFlags_SpanLabelWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. +MAKE_ENUM(ImGuiTreeNodeFlags_SpanLabelWidth,SpanLabelWidth) +// ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (label will still fit in current column) MAKE_ENUM(ImGuiTreeNodeFlags_SpanAllColumns,SpanAllColumns) -// ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 15, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) -MAKE_ENUM(ImGuiTreeNodeFlags_NavLeftJumpsBackHere,NavLeftJumpsBackHere) +// ImGuiTreeNodeFlags_LabelSpanAllColumns = 1 << 15, // Label will span all columns of its container table +MAKE_ENUM(ImGuiTreeNodeFlags_LabelSpanAllColumns,LabelSpanAllColumns) +// ImGuiTreeNodeFlags_NavLeftJumpsToParent = 1 << 17, // Nav: left arrow moves back to parent. This is processed in TreePop() when there's an unfulfilled Left nav request remaining. +MAKE_ENUM(ImGuiTreeNodeFlags_NavLeftJumpsToParent,NavLeftJumpsToParent) // ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, MAKE_ENUM(ImGuiTreeNodeFlags_CollapsingHeader,CollapsingHeader) -// ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 -MAKE_ENUM(ImGuiTreeNodeFlags_AllowItemOverlap,AllowItemOverlap) +// ImGuiTreeNodeFlags_DrawLinesNone = 1 << 18, // No lines drawn +MAKE_ENUM(ImGuiTreeNodeFlags_DrawLinesNone,DrawLinesNone) +// ImGuiTreeNodeFlags_DrawLinesFull = 1 << 19, // Horizontal lines to child nodes. Vertical line drawn down to TreePop() position: cover full contents. Faster (for large trees). +MAKE_ENUM(ImGuiTreeNodeFlags_DrawLinesFull,DrawLinesFull) +// ImGuiTreeNodeFlags_DrawLinesToNodes = 1 << 20, // Horizontal lines to child nodes. Vertical line drawn down to bottom-most child node. Slower (for large trees). +MAKE_ENUM(ImGuiTreeNodeFlags_DrawLinesToNodes,DrawLinesToNodes) +// ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0 +MAKE_ENUM(ImGuiTreeNodeFlags_NavLeftJumpsBackHere,NavLeftJumpsBackHere) +// ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7 +MAKE_ENUM(ImGuiTreeNodeFlags_SpanTextWidth,SpanTextWidth) END_ENUM(TreeNodeFlags) //enum ImGuiPopupFlags_ START_ENUM(PopupFlags) // ImGuiPopupFlags_None = 0, MAKE_ENUM(ImGuiPopupFlags_None,None) -// ImGuiPopupFlags_MouseButtonLeft = 0, // For BeginPopupContext*(): open on Left Mouse release. Guaranteed to always be == 0 (same as ImGuiMouseButton_Left) +// ImGuiPopupFlags_MouseButtonLeft = 1 << 2, // For BeginPopupContext*(): open on Left Mouse release. Only one button allowed! MAKE_ENUM(ImGuiPopupFlags_MouseButtonLeft,MouseButtonLeft) -// ImGuiPopupFlags_MouseButtonRight = 1, // For BeginPopupContext*(): open on Right Mouse release. Guaranteed to always be == 1 (same as ImGuiMouseButton_Right) +// ImGuiPopupFlags_MouseButtonRight = 2 << 2, // For BeginPopupContext*(): open on Right Mouse release. Only one button allowed! (default) MAKE_ENUM(ImGuiPopupFlags_MouseButtonRight,MouseButtonRight) -// ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle) +// ImGuiPopupFlags_MouseButtonMiddle = 3 << 2, // For BeginPopupContext*(): open on Middle Mouse release. Only one button allowed! MAKE_ENUM(ImGuiPopupFlags_MouseButtonMiddle,MouseButtonMiddle) // ImGuiPopupFlags_NoReopen = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't reopen same popup if already open (won't reposition, won't reinitialize navigation) MAKE_ENUM(ImGuiPopupFlags_NoReopen,NoReopen) @@ -2299,14 +2339,14 @@ MAKE_ENUM(ImGuiSelectableFlags_SpanAllColumns,SpanAllColumns) MAKE_ENUM(ImGuiSelectableFlags_AllowDoubleClick,AllowDoubleClick) // ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text MAKE_ENUM(ImGuiSelectableFlags_Disabled,Disabled) -// ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one +// ImGuiSelectableFlags_AllowOverlap = 1 << 4, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap(). MAKE_ENUM(ImGuiSelectableFlags_AllowOverlap,AllowOverlap) // ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered MAKE_ENUM(ImGuiSelectableFlags_Highlight,Highlight) +// ImGuiSelectableFlags_SelectOnNav = 1 << 6, // Auto-select when moved into, unless Ctrl is held. Automatic when in a BeginMultiSelect() block. +MAKE_ENUM(ImGuiSelectableFlags_SelectOnNav,SelectOnNav) // ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0 MAKE_ENUM(ImGuiSelectableFlags_DontClosePopups,DontClosePopups) -// ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7 -MAKE_ENUM(ImGuiSelectableFlags_AllowItemOverlap,AllowItemOverlap) END_ENUM(SelectableFlags) //enum ImGuiComboFlags_ @@ -2349,10 +2389,14 @@ MAKE_ENUM(ImGuiTabBarFlags_NoTabListScrollingButtons,NoTabListScrollingButtons) MAKE_ENUM(ImGuiTabBarFlags_NoTooltip,NoTooltip) // ImGuiTabBarFlags_DrawSelectedOverline = 1 << 6, // Draw selected overline markers over selected tab MAKE_ENUM(ImGuiTabBarFlags_DrawSelectedOverline,DrawSelectedOverline) -// ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 7, // Resize tabs when they don't fit -MAKE_ENUM(ImGuiTabBarFlags_FittingPolicyResizeDown,FittingPolicyResizeDown) -// ImGuiTabBarFlags_FittingPolicyScroll = 1 << 8, // Add scroll buttons when tabs don't fit +// ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling buttons. +MAKE_ENUM(ImGuiTabBarFlags_FittingPolicyMixed,FittingPolicyMixed) +// ImGuiTabBarFlags_FittingPolicyShrink = 1 << 8, // Shrink down tabs when they don't fit +MAKE_ENUM(ImGuiTabBarFlags_FittingPolicyShrink,FittingPolicyShrink) +// ImGuiTabBarFlags_FittingPolicyScroll = 1 << 9, // Enable scrolling buttons when tabs don't fit MAKE_ENUM(ImGuiTabBarFlags_FittingPolicyScroll,FittingPolicyScroll) +// ImGuiTabBarFlags_FittingPolicyResizeDown = ImGuiTabBarFlags_FittingPolicyShrink, // Renamed in 1.92.2 +MAKE_ENUM(ImGuiTabBarFlags_FittingPolicyResizeDown,FittingPolicyResizeDown) END_ENUM(TabBarFlags) //enum ImGuiTabItemFlags_ @@ -2421,7 +2465,7 @@ MAKE_ENUM(ImGuiHoveredFlags_AllowWhenOverlappedByItem,AllowWhenOverlappedByItem) MAKE_ENUM(ImGuiHoveredFlags_AllowWhenOverlappedByWindow,AllowWhenOverlappedByWindow) // ImGuiHoveredFlags_AllowWhenDisabled = 1 << 10, // IsItemHovered() only: Return true even if the item is disabled MAKE_ENUM(ImGuiHoveredFlags_AllowWhenDisabled,AllowWhenDisabled) -// ImGuiHoveredFlags_NoNavOverride = 1 << 11, // IsItemHovered() only: Disable using gamepad/keyboard navigation state when active, always query mouse +// ImGuiHoveredFlags_NoNavOverride = 1 << 11, // IsItemHovered() only: Disable using keyboard/gamepad navigation state when active, always query mouse MAKE_ENUM(ImGuiHoveredFlags_NoNavOverride,NoNavOverride) // ImGuiHoveredFlags_AllowWhenOverlapped = ImGuiHoveredFlags_AllowWhenOverlappedByItem | ImGuiHoveredFlags_AllowWhenOverlappedByWindow, MAKE_ENUM(ImGuiHoveredFlags_AllowWhenOverlapped,AllowWhenOverlapped) @@ -2493,6 +2537,8 @@ MAKE_ENUM(ImGuiDragDropFlags_AcceptBeforeDelivery,AcceptBeforeDelivery) MAKE_ENUM(ImGuiDragDropFlags_AcceptNoDrawDefaultRect,AcceptNoDrawDefaultRect) // ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site. MAKE_ENUM(ImGuiDragDropFlags_AcceptNoPreviewTooltip,AcceptNoPreviewTooltip) +// ImGuiDragDropFlags_AcceptDrawAsHovered = 1 << 13, // Accepting item will render as if hovered. Useful for e.g. a Button() used as a drop target. +MAKE_ENUM(ImGuiDragDropFlags_AcceptDrawAsHovered,AcceptDrawAsHovered) // ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect, // For peeking ahead and inspecting the payload before delivery. MAKE_ENUM(ImGuiDragDropFlags_AcceptPeekOnly,AcceptPeekOnly) // ImGuiDragDropFlags_SourceAutoExpirePayload = ImGuiDragDropFlags_PayloadAutoExpire, // Renamed in 1.90.9 @@ -2523,6 +2569,8 @@ MAKE_ENUM(ImGuiDataType_Float,Float) MAKE_ENUM(ImGuiDataType_Double,Double) // ImGuiDataType_Bool, // bool (provided for user convenience, not supported by scalar widgets) MAKE_ENUM(ImGuiDataType_Bool,Bool) +// ImGuiDataType_String, // char* (provided for user convenience, not supported by scalar widgets) +MAKE_ENUM(ImGuiDataType_String,String) // ImGuiDataType_COUNT MAKE_ENUM(ImGuiDataType_COUNT,COUNT) END_ENUM(DataType) @@ -2549,7 +2597,7 @@ MAKE_ENUM(ImGuiInputFlags_RouteGlobal,RouteGlobal) MAKE_ENUM(ImGuiInputFlags_RouteAlways,RouteAlways) // ImGuiInputFlags_RouteOverFocused = 1 << 14, // Option: global route: higher priority than focused route (unless active item in focused route). MAKE_ENUM(ImGuiInputFlags_RouteOverFocused,RouteOverFocused) -// ImGuiInputFlags_RouteOverActive = 1 << 15, // Option: global route: higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active. +// ImGuiInputFlags_RouteOverActive = 1 << 15, // Option: global route: higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. Ctrl+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active. MAKE_ENUM(ImGuiInputFlags_RouteOverActive,RouteOverActive) // ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, // Option: global route: will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. MAKE_ENUM(ImGuiInputFlags_RouteUnlessBgFocused,RouteUnlessBgFocused) @@ -2558,21 +2606,15 @@ MAKE_ENUM(ImGuiInputFlags_RouteFromRootWindow,RouteFromRootWindow) // ImGuiInputFlags_Tooltip = 1 << 18, // Automatically display a tooltip when hovering item [BETA] Unsure of right api (opt-in/opt-out) MAKE_ENUM(ImGuiInputFlags_Tooltip,Tooltip) END_ENUM(InputFlags) -//enum ImGuiNavInput - //enum ImGuiConfigFlags_ START_ENUM(ConfigFlags) // ImGuiConfigFlags_None = 0, MAKE_ENUM(ImGuiConfigFlags_None,None) -// ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + space/enter to activate. +// ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + Space/Enter to activate. Note: some features such as basic Tabbing and CtrL+Tab are enabled by regardless of this flag (and may be disabled via other means, see #4828, #9218). MAKE_ENUM(ImGuiConfigFlags_NavEnableKeyboard,NavEnableKeyboard) // ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. Backend also needs to set ImGuiBackendFlags_HasGamepad. MAKE_ENUM(ImGuiConfigFlags_NavEnableGamepad,NavEnableGamepad) -// ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth. -MAKE_ENUM(ImGuiConfigFlags_NavEnableSetMousePos,NavEnableSetMousePos) -// ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set. -MAKE_ENUM(ImGuiConfigFlags_NavNoCaptureKeyboard,NavNoCaptureKeyboard) // ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct dear imgui to disable mouse inputs and interactions. MAKE_ENUM(ImGuiConfigFlags_NoMouse,NoMouse) // ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead. @@ -2583,14 +2625,18 @@ MAKE_ENUM(ImGuiConfigFlags_NoKeyboard,NoKeyboard) MAKE_ENUM(ImGuiConfigFlags_DockingEnable,DockingEnable) // ImGuiConfigFlags_ViewportsEnable = 1 << 10, // Viewport enable flags (require both ImGuiBackendFlags_PlatformHasViewports + ImGuiBackendFlags_RendererHasViewports set by the respective backends) MAKE_ENUM(ImGuiConfigFlags_ViewportsEnable,ViewportsEnable) -// ImGuiConfigFlags_DpiEnableScaleViewports= 1 << 14, // [BETA: Don't use] FIXME-DPI: Reposition and resize imgui windows when the DpiScale of a viewport changed (mostly useful for the main viewport hosting other window). Note that resizing the main window itself is up to your application. -MAKE_ENUM(ImGuiConfigFlags_DpiEnableScaleViewports,DpiEnableScaleViewports) -// ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 15, // [BETA: Don't use] FIXME-DPI: Request bitmap-scaled fonts to match DpiScale. This is a very low-quality workaround. The correct way to handle DPI is _currently_ to replace the atlas and/or fonts in the Platform_OnChangedViewport callback, but this is all early work in progress. -MAKE_ENUM(ImGuiConfigFlags_DpiEnableScaleFonts,DpiEnableScaleFonts) // ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. MAKE_ENUM(ImGuiConfigFlags_IsSRGB,IsSRGB) // ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Application is using a touch screen instead of a mouse. MAKE_ENUM(ImGuiConfigFlags_IsTouchScreen,IsTouchScreen) +// ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavMoveSetMousePos +MAKE_ENUM(ImGuiConfigFlags_NavEnableSetMousePos,NavEnableSetMousePos) +// ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavCaptureKeyboard +MAKE_ENUM(ImGuiConfigFlags_NavNoCaptureKeyboard,NavNoCaptureKeyboard) +// ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 14, // [moved/renamed in 1.92.0] -> use bool io.ConfigDpiScaleFonts +MAKE_ENUM(ImGuiConfigFlags_DpiEnableScaleFonts,DpiEnableScaleFonts) +// ImGuiConfigFlags_DpiEnableScaleViewports= 1 << 15, // [moved/renamed in 1.92.0] -> use bool io.ConfigDpiScaleViewports +MAKE_ENUM(ImGuiConfigFlags_DpiEnableScaleViewports,DpiEnableScaleViewports) END_ENUM(ConfigFlags) //enum ImGuiBackendFlags_ @@ -2601,16 +2647,20 @@ MAKE_ENUM(ImGuiBackendFlags_None,None) MAKE_ENUM(ImGuiBackendFlags_HasGamepad,HasGamepad) // ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Backend Platform supports honoring GetMouseCursor() value to change the OS cursor shape. MAKE_ENUM(ImGuiBackendFlags_HasMouseCursors,HasMouseCursors) -// ImGuiBackendFlags_HasSetMousePos = 1 << 2, // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set). +// ImGuiBackendFlags_HasSetMousePos = 1 << 2, // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if io.ConfigNavMoveSetMousePos is set). MAKE_ENUM(ImGuiBackendFlags_HasSetMousePos,HasSetMousePos) // ImGuiBackendFlags_RendererHasVtxOffset = 1 << 3, // Backend Renderer supports ImDrawCmd::VtxOffset. This enables output of large meshes (64K+ vertices) while still using 16-bit indices. MAKE_ENUM(ImGuiBackendFlags_RendererHasVtxOffset,RendererHasVtxOffset) -// ImGuiBackendFlags_PlatformHasViewports = 1 << 10, // Backend Platform supports multiple viewports. +// ImGuiBackendFlags_RendererHasTextures = 1 << 4, // Backend Renderer supports ImTextureData requests to create/update/destroy textures. This enables incremental texture updates and texture reloads. See https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md for instructions on how to upgrade your custom backend. +MAKE_ENUM(ImGuiBackendFlags_RendererHasTextures,RendererHasTextures) +// ImGuiBackendFlags_RendererHasViewports = 1 << 10, // Backend Renderer supports multiple viewports. +MAKE_ENUM(ImGuiBackendFlags_RendererHasViewports,RendererHasViewports) +// ImGuiBackendFlags_PlatformHasViewports = 1 << 11, // Backend Platform supports multiple viewports. MAKE_ENUM(ImGuiBackendFlags_PlatformHasViewports,PlatformHasViewports) -// ImGuiBackendFlags_HasMouseHoveredViewport=1 << 11, // Backend Platform supports calling io.AddMouseViewportEvent() with the viewport under the mouse. IF POSSIBLE, ignore viewports with the ImGuiViewportFlags_NoInputs flag (Win32 backend, GLFW 3.30+ backend can do this, SDL backend cannot). If this cannot be done, Dear ImGui needs to use a flawed heuristic to find the viewport under. +// ImGuiBackendFlags_HasMouseHoveredViewport=1 << 12, // Backend Platform supports calling io.AddMouseViewportEvent() with the viewport under the mouse. IF POSSIBLE, ignore viewports with the ImGuiViewportFlags_NoInputs flag (Win32 backend, GLFW 3.30+ backend can do this, SDL backend cannot). If this cannot be done, Dear ImGui needs to use a flawed heuristic to find the viewport under. MAKE_ENUM(ImGuiBackendFlags_HasMouseHoveredViewport,HasMouseHoveredViewport) -// ImGuiBackendFlags_RendererHasViewports = 1 << 12, // Backend Renderer supports multiple viewports. -MAKE_ENUM(ImGuiBackendFlags_RendererHasViewports,RendererHasViewports) +// ImGuiBackendFlags_HasParentViewport = 1 << 13, // Backend Platform supports honoring viewport->ParentViewport/ParentViewportId value, by applying the corresponding parent/child relation at the Platform level. +MAKE_ENUM(ImGuiBackendFlags_HasParentViewport,HasParentViewport) END_ENUM(BackendFlags) //enum ImGuiCol_ @@ -2681,6 +2731,8 @@ MAKE_ENUM(ImGuiCol_ResizeGrip,ResizeGrip) MAKE_ENUM(ImGuiCol_ResizeGripHovered,ResizeGripHovered) // ImGuiCol_ResizeGripActive, MAKE_ENUM(ImGuiCol_ResizeGripActive,ResizeGripActive) +// ImGuiCol_InputTextCursor, // InputText cursor/caret +MAKE_ENUM(ImGuiCol_InputTextCursor,InputTextCursor) // ImGuiCol_TabHovered, // Tab background, when hovered MAKE_ENUM(ImGuiCol_TabHovered,TabHovered) // ImGuiCol_Tab, // Tab background, when tab-bar is focused & tab is unselected @@ -2719,15 +2771,21 @@ MAKE_ENUM(ImGuiCol_TableRowBg,TableRowBg) MAKE_ENUM(ImGuiCol_TableRowBgAlt,TableRowBgAlt) // ImGuiCol_TextLink, // Hyperlink color MAKE_ENUM(ImGuiCol_TextLink,TextLink) -// ImGuiCol_TextSelectedBg, +// ImGuiCol_TextSelectedBg, // Selected text inside an InputText MAKE_ENUM(ImGuiCol_TextSelectedBg,TextSelectedBg) -// ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target +// ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines +MAKE_ENUM(ImGuiCol_TreeLines,TreeLines) +// ImGuiCol_DragDropTarget, // Rectangle border highlighting a drop target MAKE_ENUM(ImGuiCol_DragDropTarget,DragDropTarget) -// ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item -MAKE_ENUM(ImGuiCol_NavHighlight,NavHighlight) -// ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB +// ImGuiCol_DragDropTargetBg, // Rectangle background highlighting a drop target +MAKE_ENUM(ImGuiCol_DragDropTargetBg,DragDropTargetBg) +// ImGuiCol_UnsavedMarker, // Unsaved Document marker (in window title and tabs) +MAKE_ENUM(ImGuiCol_UnsavedMarker,UnsavedMarker) +// ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible +MAKE_ENUM(ImGuiCol_NavCursor,NavCursor) +// ImGuiCol_NavWindowingHighlight, // Highlight window when using Ctrl+Tab MAKE_ENUM(ImGuiCol_NavWindowingHighlight,NavWindowingHighlight) -// ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active +// ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the Ctrl+Tab window list, when active MAKE_ENUM(ImGuiCol_NavWindowingDimBg,NavWindowingDimBg) // ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active MAKE_ENUM(ImGuiCol_ModalWindowDimBg,ModalWindowDimBg) @@ -2739,6 +2797,8 @@ MAKE_ENUM(ImGuiCol_TabActive,TabActive) MAKE_ENUM(ImGuiCol_TabUnfocused,TabUnfocused) // ImGuiCol_TabUnfocusedActive = ImGuiCol_TabDimmedSelected, // [renamed in 1.90.9] MAKE_ENUM(ImGuiCol_TabUnfocusedActive,TabUnfocusedActive) +// ImGuiCol_NavHighlight = ImGuiCol_NavCursor, // [renamed in 1.91.4] +MAKE_ENUM(ImGuiCol_NavHighlight,NavHighlight) END_ENUM(Col) //enum ImGuiStyleVar_ @@ -2783,14 +2843,24 @@ MAKE_ENUM(ImGuiStyleVar_CellPadding,CellPadding) MAKE_ENUM(ImGuiStyleVar_ScrollbarSize,ScrollbarSize) // ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding MAKE_ENUM(ImGuiStyleVar_ScrollbarRounding,ScrollbarRounding) +// ImGuiStyleVar_ScrollbarPadding, // float ScrollbarPadding +MAKE_ENUM(ImGuiStyleVar_ScrollbarPadding,ScrollbarPadding) // ImGuiStyleVar_GrabMinSize, // float GrabMinSize MAKE_ENUM(ImGuiStyleVar_GrabMinSize,GrabMinSize) // ImGuiStyleVar_GrabRounding, // float GrabRounding MAKE_ENUM(ImGuiStyleVar_GrabRounding,GrabRounding) +// ImGuiStyleVar_ImageRounding, // float ImageRounding +MAKE_ENUM(ImGuiStyleVar_ImageRounding,ImageRounding) +// ImGuiStyleVar_ImageBorderSize, // float ImageBorderSize +MAKE_ENUM(ImGuiStyleVar_ImageBorderSize,ImageBorderSize) // ImGuiStyleVar_TabRounding, // float TabRounding MAKE_ENUM(ImGuiStyleVar_TabRounding,TabRounding) // ImGuiStyleVar_TabBorderSize, // float TabBorderSize MAKE_ENUM(ImGuiStyleVar_TabBorderSize,TabBorderSize) +// ImGuiStyleVar_TabMinWidthBase, // float TabMinWidthBase +MAKE_ENUM(ImGuiStyleVar_TabMinWidthBase,TabMinWidthBase) +// ImGuiStyleVar_TabMinWidthShrink, // float TabMinWidthShrink +MAKE_ENUM(ImGuiStyleVar_TabMinWidthShrink,TabMinWidthShrink) // ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize MAKE_ENUM(ImGuiStyleVar_TabBarBorderSize,TabBarBorderSize) // ImGuiStyleVar_TabBarOverlineSize, // float TabBarOverlineSize @@ -2799,10 +2869,16 @@ MAKE_ENUM(ImGuiStyleVar_TabBarOverlineSize,TabBarOverlineSize) MAKE_ENUM(ImGuiStyleVar_TableAngledHeadersAngle,TableAngledHeadersAngle) // ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign MAKE_ENUM(ImGuiStyleVar_TableAngledHeadersTextAlign,TableAngledHeadersTextAlign) +// ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize +MAKE_ENUM(ImGuiStyleVar_TreeLinesSize,TreeLinesSize) +// ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding +MAKE_ENUM(ImGuiStyleVar_TreeLinesRounding,TreeLinesRounding) // ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign MAKE_ENUM(ImGuiStyleVar_ButtonTextAlign,ButtonTextAlign) // ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign MAKE_ENUM(ImGuiStyleVar_SelectableTextAlign,SelectableTextAlign) +// ImGuiStyleVar_SeparatorSize, // float SeparatorSize +MAKE_ENUM(ImGuiStyleVar_SeparatorSize,SeparatorSize) // ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize MAKE_ENUM(ImGuiStyleVar_SeparatorTextBorderSize,SeparatorTextBorderSize) // ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign @@ -2825,6 +2901,10 @@ MAKE_ENUM(ImGuiButtonFlags_MouseButtonLeft,MouseButtonLeft) MAKE_ENUM(ImGuiButtonFlags_MouseButtonRight,MouseButtonRight) // ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button MAKE_ENUM(ImGuiButtonFlags_MouseButtonMiddle,MouseButtonMiddle) +// ImGuiButtonFlags_EnableNav = 1 << 3, // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default. +MAKE_ENUM(ImGuiButtonFlags_EnableNav,EnableNav) +// ImGuiButtonFlags_AllowOverlap = 1 << 12, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap(). +MAKE_ENUM(ImGuiButtonFlags_AllowOverlap,AllowOverlap) END_ENUM(ButtonFlags) //enum ImGuiColorEditFlags_ @@ -2847,16 +2927,20 @@ MAKE_ENUM(ImGuiColorEditFlags_NoTooltip,NoTooltip) MAKE_ENUM(ImGuiColorEditFlags_NoLabel,NoLabel) // ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead. MAKE_ENUM(ImGuiColorEditFlags_NoSidePreview,NoSidePreview) -// ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. +// ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target/source. ColorButton: disable drag and drop source. MAKE_ENUM(ImGuiColorEditFlags_NoDragDrop,NoDragDrop) // ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) MAKE_ENUM(ImGuiColorEditFlags_NoBorder,NoBorder) -// ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. -MAKE_ENUM(ImGuiColorEditFlags_AlphaBar,AlphaBar) -// ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. -MAKE_ENUM(ImGuiColorEditFlags_AlphaPreview,AlphaPreview) -// ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. +// ImGuiColorEditFlags_NoColorMarkers = 1 << 11, // // ColorEdit: disable rendering R/G/B/A color marker. May also be disabled globally by setting style.ColorMarkerSize = 0. +MAKE_ENUM(ImGuiColorEditFlags_NoColorMarkers,NoColorMarkers) +// ImGuiColorEditFlags_AlphaOpaque = 1 << 12, // // ColorEdit, ColorPicker, ColorButton: disable alpha in the preview,. Contrary to _NoAlpha it may still be edited when calling ColorEdit4()/ColorPicker4(). For ColorButton() this does the same as _NoAlpha. +MAKE_ENUM(ImGuiColorEditFlags_AlphaOpaque,AlphaOpaque) +// ImGuiColorEditFlags_AlphaNoBg = 1 << 13, // // ColorEdit, ColorPicker, ColorButton: disable rendering a checkerboard background behind transparent color. +MAKE_ENUM(ImGuiColorEditFlags_AlphaNoBg,AlphaNoBg) +// ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 14, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half transparent preview. MAKE_ENUM(ImGuiColorEditFlags_AlphaPreviewHalf,AlphaPreviewHalf) +// ImGuiColorEditFlags_AlphaBar = 1 << 18, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. +MAKE_ENUM(ImGuiColorEditFlags_AlphaBar,AlphaBar) // ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well). MAKE_ENUM(ImGuiColorEditFlags_HDR,HDR) // ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex. @@ -2877,22 +2961,32 @@ MAKE_ENUM(ImGuiColorEditFlags_PickerHueWheel,PickerHueWheel) MAKE_ENUM(ImGuiColorEditFlags_InputRGB,InputRGB) // ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format. MAKE_ENUM(ImGuiColorEditFlags_InputHSV,InputHSV) +// ImGuiColorEditFlags_AlphaPreview = 0, // Removed in 1.91.8. This is the default now. Will display a checkerboard unless ImGuiColorEditFlags_AlphaNoBg is set. +MAKE_ENUM(ImGuiColorEditFlags_AlphaPreview,AlphaPreview) END_ENUM(ColorEditFlags) //enum ImGuiSliderFlags_ START_ENUM(SliderFlags) -// ImGuiSliderFlags_None = 0, +// ImGuiSliderFlags_None = 0, MAKE_ENUM(ImGuiSliderFlags_None,None) -// ImGuiSliderFlags_AlwaysClamp = 1 << 4, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds. -MAKE_ENUM(ImGuiSliderFlags_AlwaysClamp,AlwaysClamp) -// ImGuiSliderFlags_Logarithmic = 1 << 5, // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits. +// ImGuiSliderFlags_Logarithmic = 1 << 5, // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits. MAKE_ENUM(ImGuiSliderFlags_Logarithmic,Logarithmic) -// ImGuiSliderFlags_NoRoundToFormat = 1 << 6, // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits). +// ImGuiSliderFlags_NoRoundToFormat = 1 << 6, // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits). MAKE_ENUM(ImGuiSliderFlags_NoRoundToFormat,NoRoundToFormat) -// ImGuiSliderFlags_NoInput = 1 << 7, // Disable CTRL+Click or Enter key allowing to input text directly into the widget. +// ImGuiSliderFlags_NoInput = 1 << 7, // Disable Ctrl+Click or Enter key allowing to input text directly into the widget. MAKE_ENUM(ImGuiSliderFlags_NoInput,NoInput) -// ImGuiSliderFlags_WrapAround = 1 << 8, // Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions for now. +// ImGuiSliderFlags_WrapAround = 1 << 8, // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now. MAKE_ENUM(ImGuiSliderFlags_WrapAround,WrapAround) +// ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with Ctrl+Click. By default Ctrl+Click allows going out of bounds. +MAKE_ENUM(ImGuiSliderFlags_ClampOnInput,ClampOnInput) +// ImGuiSliderFlags_ClampZeroRange = 1 << 10, // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it. +MAKE_ENUM(ImGuiSliderFlags_ClampZeroRange,ClampZeroRange) +// ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic. +MAKE_ENUM(ImGuiSliderFlags_NoSpeedTweaks,NoSpeedTweaks) +// ImGuiSliderFlags_ColorMarkers = 1 << 12, // DragScalarN(), SliderScalarN(): Draw R/G/B/A color markers on each component. +MAKE_ENUM(ImGuiSliderFlags_ColorMarkers,ColorMarkers) +// ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange, +MAKE_ENUM(ImGuiSliderFlags_AlwaysClamp,AlwaysClamp) END_ENUM(SliderFlags) //enum ImGuiMouseButton_ @@ -2927,6 +3021,10 @@ MAKE_ENUM(ImGuiMouseCursor_ResizeNESW,ResizeNESW) MAKE_ENUM(ImGuiMouseCursor_ResizeNWSE,ResizeNWSE) // ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) MAKE_ENUM(ImGuiMouseCursor_Hand,Hand) +// ImGuiMouseCursor_Wait, // When waiting for something to process/load. +MAKE_ENUM(ImGuiMouseCursor_Wait,Wait) +// ImGuiMouseCursor_Progress, // When waiting for something to process/load, but application is still interactive. +MAKE_ENUM(ImGuiMouseCursor_Progress,Progress) // ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle. MAKE_ENUM(ImGuiMouseCursor_NotAllowed,NotAllowed) // ImGuiMouseCursor_COUNT @@ -2955,15 +3053,15 @@ START_ENUM(TableFlags) MAKE_ENUM(ImGuiTableFlags_None,None) // ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns. MAKE_ENUM(ImGuiTableFlags_Resizable,Resizable) -// ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) +// ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row. (Need calling TableSetupColumn() + TableHeadersRow() to display headers, or using ImGuiTableFlags_ContextMenuInBody to access context-menu without headers). MAKE_ENUM(ImGuiTableFlags_Reorderable,Reorderable) // ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu. MAKE_ENUM(ImGuiTableFlags_Hideable,Hideable) // ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate. MAKE_ENUM(ImGuiTableFlags_Sortable,Sortable) -// ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. +// ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width, visibility and sort settings in the .ini file. MAKE_ENUM(ImGuiTableFlags_NoSavedSettings,NoSavedSettings) -// ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). +// ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will also display table context menu. By default it is available in TableHeadersRow(). MAKE_ENUM(ImGuiTableFlags_ContextMenuInBody,ContextMenuInBody) // ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually) MAKE_ENUM(ImGuiTableFlags_RowBg,RowBg) @@ -3126,6 +3224,14 @@ END_ENUM(TableBgTarget) //struct ImGuiStorage +//enum ImGuiListClipperFlags_ + +START_ENUM(ListClipperFlags) +// ImGuiListClipperFlags_None = 0, +MAKE_ENUM(ImGuiListClipperFlags_None,None) +// ImGuiListClipperFlags_NoSetTableRowCounters = 1 << 0, // [Internal] Disabled modifying table row counters. Avoid assumption that 1 clipper item == 1 table row. +MAKE_ENUM(ImGuiListClipperFlags_NoSetTableRowCounters,NoSetTableRowCounters) +END_ENUM(ListClipperFlags) //struct ImGuiListClipper //struct ImColor @@ -3137,7 +3243,7 @@ START_ENUM(MultiSelectFlags) MAKE_ENUM(ImGuiMultiSelectFlags_None,None) // ImGuiMultiSelectFlags_SingleSelect = 1 << 0, // Disable selecting more than one item. This is available to allow single-selection code to share same code/logic if desired. It essentially disables the main purpose of BeginMultiSelect() tho! MAKE_ENUM(ImGuiMultiSelectFlags_SingleSelect,SingleSelect) -// ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable CTRL+A shortcut to select all. +// ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable Ctrl+A shortcut to select all. MAKE_ENUM(ImGuiMultiSelectFlags_NoSelectAll,NoSelectAll) // ImGuiMultiSelectFlags_NoRangeSelect = 1 << 2, // Disable Shift+selection mouse/keyboard support (useful for unordered 2D selection). With BoxSelect is also ensure contiguous SetRange requests are not combined into one. This allows not handling interpolation in SetRange requests. MAKE_ENUM(ImGuiMultiSelectFlags_NoRangeSelect,NoRangeSelect) @@ -3151,7 +3257,7 @@ MAKE_ENUM(ImGuiMultiSelectFlags_NoAutoClearOnReselect,NoAutoClearOnReselect) MAKE_ENUM(ImGuiMultiSelectFlags_BoxSelect1d,BoxSelect1d) // ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items. MAKE_ENUM(ImGuiMultiSelectFlags_BoxSelect2d,BoxSelect2d) -// ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope. +// ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting and moving mouse near edges of scope. MAKE_ENUM(ImGuiMultiSelectFlags_BoxSelectNoScroll,BoxSelectNoScroll) // ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused. MAKE_ENUM(ImGuiMultiSelectFlags_ClearOnEscape,ClearOnEscape) @@ -3161,12 +3267,18 @@ MAKE_ENUM(ImGuiMultiSelectFlags_ClearOnClickVoid,ClearOnClickVoid) MAKE_ENUM(ImGuiMultiSelectFlags_ScopeWindow,ScopeWindow) // ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window. MAKE_ENUM(ImGuiMultiSelectFlags_ScopeRect,ScopeRect) -// ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, // Apply selection on mouse down when clicking on unselected item. (Default) -MAKE_ENUM(ImGuiMultiSelectFlags_SelectOnClick,SelectOnClick) -// ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection. +// ImGuiMultiSelectFlags_SelectOnAuto = 1 << 13, // Apply selection on mouse down when clicking on unselected item, on mouse up when clicking on selected item. (Default) +MAKE_ENUM(ImGuiMultiSelectFlags_SelectOnAuto,SelectOnAuto) +// ImGuiMultiSelectFlags_SelectOnClickAlways = 1 << 14, // Apply selection on mouse down when clicking on any items. Prevents Drag and Drop from being used on multiple-selection, but allows e.g. BoxSelect to always reselect even when clicking inside an existing selection. (Excel style behavior) +MAKE_ENUM(ImGuiMultiSelectFlags_SelectOnClickAlways,SelectOnClickAlways) +// ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 15, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection. MAKE_ENUM(ImGuiMultiSelectFlags_SelectOnClickRelease,SelectOnClickRelease) // ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one. MAKE_ENUM(ImGuiMultiSelectFlags_NavWrapX,NavWrapX) +// ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus. +MAKE_ENUM(ImGuiMultiSelectFlags_NoSelectOnRightClick,NoSelectOnRightClick) +// ImGuiMultiSelectFlags_SelectOnClick = ImGuiMultiSelectFlags_SelectOnAuto, // RENAMED in 1.92.6 +MAKE_ENUM(ImGuiMultiSelectFlags_SelectOnClick,SelectOnClick) END_ENUM(MultiSelectFlags) //struct ImGuiMultiSelectIO @@ -3194,6 +3306,11 @@ END_ENUM(MultiSelectFlags) //struct ImDrawList +// IMGUI_API ImDrawList(ImDrawListSharedData* shared_data); +// Unsupported return type ImDrawLis +// Unsupported arg type ImDrawListSharedData* shared_data +// IMGUI_API ~ImDrawList(); +// Unsupported return type ~ImDrawLis // IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_FUNCTION_DRAW_LIST(PushClipRect) IM_VEC_2_ARG(clip_rect_min) @@ -3209,14 +3326,14 @@ END_IMGUI_FUNC IMGUI_FUNCTION_DRAW_LIST(PopClipRect) DRAW_LIST_CALL_FUNCTION_NO_RET(PopClipRect) END_IMGUI_FUNC -// IMGUI_API void PushTextureID(ImTextureID texture_id); -IMGUI_FUNCTION_DRAW_LIST(PushTextureID) -IM_TEXTURE_ID_ARG(texture_id) -DRAW_LIST_CALL_FUNCTION_NO_RET(PushTextureID, texture_id) +// IMGUI_API void PushTexture(ImTextureRef tex_ref); +IMGUI_FUNCTION_DRAW_LIST(PushTexture) +IM_TEXTURE_ID_ARG(tex_ref) +DRAW_LIST_CALL_FUNCTION_NO_RET(PushTexture, tex_ref) END_IMGUI_FUNC -// IMGUI_API void PopTextureID(); -IMGUI_FUNCTION_DRAW_LIST(PopTextureID) -DRAW_LIST_CALL_FUNCTION_NO_RET(PopTextureID) +// IMGUI_API void PopTexture(); +IMGUI_FUNCTION_DRAW_LIST(PopTexture) +DRAW_LIST_CALL_FUNCTION_NO_RET(PopTexture) END_IMGUI_FUNC // inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2 cr.x cr.y; } // Unsupported arg type ) const { const ImVec4& cr = _ClipRectStack.back( @@ -3356,8 +3473,8 @@ LABEL_ARG(text_begin) OPTIONAL_LABEL_ARG(text_end, NULL) DRAW_LIST_CALL_FUNCTION_NO_RET(AddText, pos, col, text_begin, text_end) END_IMGUI_FUNC -// IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); -// Unsupported arg type const ImFont* font +// IMGUI_API void AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); +// Unsupported arg type ImFont* font // Unsupported arg type const ImVec4* cpu_fine_clip_rect = NULL // IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_FUNCTION_DRAW_LIST(AddBezierCubic) @@ -3386,19 +3503,19 @@ END_IMGUI_FUNC // Unsupported arg type const ImVec2* points // IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col); // Unsupported arg type const ImVec2* points -// IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2 0 0, const ImVec2& uv_max = ImVec2 1 1, ImU32 col = IM_COL32_WHITE); +// IMGUI_API void AddImage(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2 0 0, const ImVec2& uv_max = ImVec2 1 1, ImU32 col = IM_COL32_WHITE); IMGUI_FUNCTION_DRAW_LIST(AddImage) -IM_TEXTURE_ID_ARG(user_texture_id) +IM_TEXTURE_ID_ARG(tex_ref) IM_VEC_2_ARG(p_min) IM_VEC_2_ARG(p_max) OPTIONAL_IM_VEC_2_ARG(uv_min, 0, 0) OPTIONAL_IM_VEC_2_ARG(uv_max, 1, 1) OPTIONAL_UINT_ARG(col, IM_COL32_WHITE) -DRAW_LIST_CALL_FUNCTION_NO_RET(AddImage, user_texture_id, p_min, p_max, uv_min, uv_max, col) +DRAW_LIST_CALL_FUNCTION_NO_RET(AddImage, tex_ref, p_min, p_max, uv_min, uv_max, col) END_IMGUI_FUNC -// IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2 0 0, const ImVec2& uv2 = ImVec2 1 0, const ImVec2& uv3 = ImVec2 1 1, const ImVec2& uv4 = ImVec2 0 1, ImU32 col = IM_COL32_WHITE); +// IMGUI_API void AddImageQuad(ImTextureRef tex_ref, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2 0 0, const ImVec2& uv2 = ImVec2 1 0, const ImVec2& uv3 = ImVec2 1 1, const ImVec2& uv4 = ImVec2 0 1, ImU32 col = IM_COL32_WHITE); IMGUI_FUNCTION_DRAW_LIST(AddImageQuad) -IM_TEXTURE_ID_ARG(user_texture_id) +IM_TEXTURE_ID_ARG(tex_ref) IM_VEC_2_ARG(p1) IM_VEC_2_ARG(p2) IM_VEC_2_ARG(p3) @@ -3408,11 +3525,11 @@ OPTIONAL_IM_VEC_2_ARG(uv2, 1, 0) OPTIONAL_IM_VEC_2_ARG(uv3, 1, 1) OPTIONAL_IM_VEC_2_ARG(uv4, 0, 1) OPTIONAL_UINT_ARG(col, IM_COL32_WHITE) -DRAW_LIST_CALL_FUNCTION_NO_RET(AddImageQuad, user_texture_id, p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) +DRAW_LIST_CALL_FUNCTION_NO_RET(AddImageQuad, tex_ref, p1, p2, p3, p4, uv1, uv2, uv3, uv4, col) END_IMGUI_FUNC -// IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); +// IMGUI_API void AddImageRounded(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); IMGUI_FUNCTION_DRAW_LIST(AddImageRounded) -IM_TEXTURE_ID_ARG(user_texture_id) +IM_TEXTURE_ID_ARG(tex_ref) IM_VEC_2_ARG(p_min) IM_VEC_2_ARG(p_max) IM_VEC_2_ARG(uv_min) @@ -3420,7 +3537,7 @@ IM_VEC_2_ARG(uv_max) UINT_ARG(col) NUMBER_ARG(rounding) OPTIONAL_INT_ARG(flags, 0) -DRAW_LIST_CALL_FUNCTION_NO_RET(AddImageRounded, user_texture_id, p_min, p_max, uv_min, uv_max, col, rounding, flags) +DRAW_LIST_CALL_FUNCTION_NO_RET(AddImageRounded, tex_ref, p_min, p_max, uv_min, uv_max, col, rounding, flags) END_IMGUI_FUNC // inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } // Unsupported arg type const ImVec2& pos) { _Path.push_back(pos @@ -3492,9 +3609,10 @@ OPTIONAL_NUMBER_ARG(rounding, 0.0f) OPTIONAL_INT_ARG(flags, 0) DRAW_LIST_CALL_FUNCTION_NO_RET(PathRect, rect_min, rect_max, rounding, flags) END_IMGUI_FUNC -// IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. +// IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size = 0); // Unsupported arg type ImDrawCallback callback -// Unsupported arg type void* callback_data +// Unsupported arg type void* userdata +// Unsupported arg type size_t userdata_size = 0 // IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible IMGUI_FUNCTION_DRAW_LIST(AddDrawCmd) DRAW_LIST_CALL_FUNCTION_NO_RET(AddDrawCmd) @@ -3550,6 +3668,10 @@ DRAW_LIST_CALL_FUNCTION_NO_RET(PrimQuadUV, a, b, c, d, uv_a, uv_b, uv_c, uv_d, c END_IMGUI_FUNC // inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index // Unsupported arg type ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx +// inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0 +// Unsupported arg type ImTextureRef tex_ref) { PushTexture(tex_ref +// inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0 +// Unsupported arg type ) { PopTexture( // //inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2 radius_x radius_y, col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024) // Unsupported arg type float thickness = 1.0f) { AddEllipse(center // Unsupported arg type ImVec2 radius_x radius_y @@ -3570,7 +3692,7 @@ END_IMGUI_FUNC // Unsupported arg type a_min // Unsupported arg type a_max // Unsupported arg type num_segments -// //inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021) +// //inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021) // Unsupported arg type int num_segments = 0) { AddBezierCubic(p1 // Unsupported arg type p2 // Unsupported arg type p3 @@ -3578,11 +3700,13 @@ END_IMGUI_FUNC // Unsupported arg type col // Unsupported arg type thickness // Unsupported arg type num_segments -// //inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021) +// //inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021) // Unsupported arg type int num_segments = 0) { PathBezierCubicCurveTo(p2 // Unsupported arg type p3 // Unsupported arg type p4 // Unsupported arg type num_segments +// IMGUI_API void _SetDrawListSharedData(ImDrawListSharedData* data); +// Unsupported arg type ImDrawListSharedData* data // IMGUI_API void _ResetForNewFrame(); IMGUI_FUNCTION_DRAW_LIST(_ResetForNewFrame) DRAW_LIST_CALL_FUNCTION_NO_RET(_ResetForNewFrame) @@ -3603,18 +3727,18 @@ END_IMGUI_FUNC IMGUI_FUNCTION_DRAW_LIST(_OnChangedClipRect) DRAW_LIST_CALL_FUNCTION_NO_RET(_OnChangedClipRect) END_IMGUI_FUNC -// IMGUI_API void _OnChangedTextureID(); -IMGUI_FUNCTION_DRAW_LIST(_OnChangedTextureID) -DRAW_LIST_CALL_FUNCTION_NO_RET(_OnChangedTextureID) +// IMGUI_API void _OnChangedTexture(); +IMGUI_FUNCTION_DRAW_LIST(_OnChangedTexture) +DRAW_LIST_CALL_FUNCTION_NO_RET(_OnChangedTexture) END_IMGUI_FUNC // IMGUI_API void _OnChangedVtxOffset(); IMGUI_FUNCTION_DRAW_LIST(_OnChangedVtxOffset) DRAW_LIST_CALL_FUNCTION_NO_RET(_OnChangedVtxOffset) END_IMGUI_FUNC -// IMGUI_API void _SetTextureID(ImTextureID texture_id); -IMGUI_FUNCTION_DRAW_LIST(_SetTextureID) -IM_TEXTURE_ID_ARG(texture_id) -DRAW_LIST_CALL_FUNCTION_NO_RET(_SetTextureID, texture_id) +// IMGUI_API void _SetTexture(ImTextureRef tex_ref); +IMGUI_FUNCTION_DRAW_LIST(_SetTexture) +IM_TEXTURE_ID_ARG(tex_ref) +DRAW_LIST_CALL_FUNCTION_NO_RET(_SetTexture, tex_ref) END_IMGUI_FUNC // IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step); IMGUI_FUNCTION_DRAW_LIST(_PathArcToFastEx) @@ -3636,20 +3760,36 @@ DRAW_LIST_CALL_FUNCTION_NO_RET(_PathArcToN, center, radius, a_min, a_max, num_se END_IMGUI_FUNC //struct ImDrawData +//enum ImTextureFormat + +//enum ImTextureStatus + +//struct ImTextureRect + +//struct ImTextureData + //struct ImFontConfig //struct ImFontGlyph //struct ImFontGlyphRangesBuilder -//struct ImFontAtlasCustomRect +//struct ImFontAtlasRect //enum ImFontAtlasFlags_ //struct ImFontAtlas +//struct ImFontBaked + +//enum ImFontFlags_ + //struct ImFont +//inline ImTextureID ImTextureRef::GetTexID() const + +//inline ImTextureID ImDrawCmd::GetTexID() const + //enum ImGuiViewportFlags_ START_ENUM(ViewportFlags) diff --git a/third_party/imgui_md b/third_party/imgui_md index 8ca75c5f7..193314702 160000 --- a/third_party/imgui_md +++ b/third_party/imgui_md @@ -1 +1 @@ -Subproject commit 8ca75c5f7663f314821e3d0b2c51011792bee68f +Subproject commit 193314702e08c9e338a0b9d9346cb93ed4d8b758 diff --git a/third_party/zep b/third_party/zep index 86ea3c701..312c0e6ec 160000 --- a/third_party/zep +++ b/third_party/zep @@ -1 +1 @@ -Subproject commit 86ea3c7019f45ccd4a13503bf7d98a396e8f0193 +Subproject commit 312c0e6ec7a95427f6efab176b712051a3baa801