mirror of
https://github.com/ocornut/imgui.git
synced 2026-07-07 09:59:41 +00:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f7d8086fe | ||
|
|
0e479b9554 | ||
|
|
776bf2ab0d | ||
|
|
4f1ea369ea | ||
|
|
a977144955 | ||
|
|
e616ace74d | ||
|
|
5c2160ac85 | ||
|
|
5fb77dfde1 | ||
|
|
f7e8343ee9 | ||
|
|
7d43c74b59 | ||
|
|
8fc25800e0 | ||
|
|
6824e2c2e4 | ||
|
|
e9ea19086b | ||
|
|
caddd26fb9 | ||
|
|
fc6395365d | ||
|
|
93dd4c1567 | ||
|
|
279d04f7a3 | ||
|
|
0edad6d097 | ||
|
|
e408733ecc | ||
|
|
9e6c0416fe | ||
|
|
c66d9a8190 | ||
|
|
76f5be2749 | ||
|
|
60fbdbb8d8 | ||
|
|
ac6f9683b5 | ||
|
|
1c1241136a | ||
|
|
0e355af09e | ||
|
|
26432cfdc6 | ||
|
|
be374fa598 | ||
|
|
e74453760b | ||
|
|
ec69495ca8 | ||
|
|
b522576054 | ||
|
|
570c0e03b7 | ||
|
|
b9cf21733d | ||
|
|
7930405c73 | ||
|
|
f2fcdfe97f | ||
|
|
2f94e7dc13 | ||
|
|
b2377d616d | ||
|
|
d15966ff6c | ||
|
|
9a5c070308 | ||
|
|
73a6610e81 | ||
|
|
7aaf10f15b | ||
|
|
13fc81fc82 | ||
|
|
2064059a7f | ||
|
|
b47a3898b4 | ||
|
|
138c0e6c7d | ||
|
|
b46a37eac9 | ||
|
|
e6147a3993 | ||
|
|
721da6a34c | ||
|
|
360183924b | ||
|
|
2aaa6d8173 | ||
|
|
3240201de2 | ||
|
|
94a3dcc5fa | ||
|
|
fea6f4603a | ||
|
|
d43c3f929c | ||
|
|
36ea9728d1 | ||
|
|
2e0f949039 | ||
|
|
924f57181b | ||
|
|
e5ff2d07d7 | ||
|
|
b10137f92f | ||
|
|
aa377352ef | ||
|
|
4312c4399f | ||
|
|
f1dd18b75c | ||
|
|
5220a3f48d | ||
|
|
6acba3b47d | ||
|
|
fc5e2f28fe | ||
|
|
7950c96f0e | ||
|
|
14278db024 | ||
|
|
c4eaac6d48 | ||
|
|
5a42cddcd2 | ||
|
|
995e4a65ff | ||
|
|
a054a016e2 | ||
|
|
045a0907f4 | ||
|
|
5aa0393a15 | ||
|
|
f241419b78 | ||
|
|
3495e329f3 | ||
|
|
3b99fc4883 | ||
|
|
70f02b0558 | ||
|
|
cac16b0d16 | ||
|
|
1d33ea939f | ||
|
|
75f985998b | ||
|
|
12b7977555 | ||
|
|
33bb693b4c | ||
|
|
783eba926f | ||
|
|
ac07da2b5b | ||
|
|
243097ca8f | ||
|
|
fbcf95193f | ||
|
|
24a80f74a4 | ||
|
|
904b663184 | ||
|
|
3e7b79aa17 | ||
|
|
e41d691da1 | ||
|
|
93e396ffb7 | ||
|
|
068e055510 | ||
|
|
db161b84c9 | ||
|
|
4088a4f40c | ||
|
|
46a050fff2 | ||
|
|
c7767926ce | ||
|
|
310c719a1f | ||
|
|
b2546a5c93 | ||
|
|
e0f5f9a14c |
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
@@ -25,8 +25,8 @@ jobs:
|
|||||||
working-directory: ${{ github.workspace }}/imgui
|
working-directory: ${{ github.workspace }}/imgui
|
||||||
|
|
||||||
env:
|
env:
|
||||||
VS_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\
|
VS_PATH: C:\Program Files\Microsoft Visual Studio\18\Enterprise
|
||||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\18\Enterprise\MSBuild\Current\Bin\
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
@@ -116,7 +116,7 @@ jobs:
|
|||||||
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
|
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
|
||||||
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
||||||
|
|
||||||
# Win64 examples are more frequently compilted than the Win32 examples.
|
# Win64 examples are more frequently compiled than the Win32 examples.
|
||||||
# More of the Win32 examples requires 'workflow_run' to reduce waste.
|
# More of the Win32 examples requires 'workflow_run' to reduce waste.
|
||||||
- name: Build Win32 example_glfw_opengl2
|
- name: Build Win32 example_glfw_opengl2
|
||||||
shell: cmd
|
shell: cmd
|
||||||
@@ -160,6 +160,7 @@ jobs:
|
|||||||
- name: Build Win32 example_sdl3_opengl3
|
- name: Build Win32 example_sdl3_opengl3
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||||
|
if: github.event_name == 'workflow_run'
|
||||||
|
|
||||||
- name: Build Win32 example_sdl3_sdlgpu3
|
- name: Build Win32 example_sdl3_sdlgpu3
|
||||||
shell: cmd
|
shell: cmd
|
||||||
@@ -200,6 +201,7 @@ jobs:
|
|||||||
- name: Build Win64 example_glfw_opengl3
|
- name: Build Win64 example_glfw_opengl3
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||||
|
if: github.event_name == 'workflow_run'
|
||||||
|
|
||||||
- name: Build Win64 example_glfw_vulkan
|
- name: Build Win64 example_glfw_vulkan
|
||||||
shell: cmd
|
shell: cmd
|
||||||
@@ -228,6 +230,7 @@ jobs:
|
|||||||
- name: Build Win64 example_sdl2_directx11
|
- name: Build Win64 example_sdl2_directx11
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||||
|
if: github.event_name == 'workflow_run'
|
||||||
|
|
||||||
- name: Build Win64 example_sdl3_opengl3
|
- name: Build Win64 example_sdl3_opengl3
|
||||||
shell: cmd
|
shell: cmd
|
||||||
@@ -572,6 +575,9 @@ jobs:
|
|||||||
- name: Build macOS example_sdl2_metal
|
- name: Build macOS example_sdl2_metal
|
||||||
run: make -C examples/example_sdl2_metal
|
run: make -C examples/example_sdl2_metal
|
||||||
|
|
||||||
|
#- name: Build macOS example_sdl3_metal4
|
||||||
|
# run: make -C examples/example_sdl3_metal4
|
||||||
|
|
||||||
- name: Build macOS example_sdl2_opengl2
|
- name: Build macOS example_sdl2_opengl2
|
||||||
run: make -C examples/example_sdl2_opengl2
|
run: make -C examples/example_sdl2_opengl2
|
||||||
if: github.event_name == 'workflow_run'
|
if: github.event_name == 'workflow_run'
|
||||||
@@ -651,8 +657,12 @@ jobs:
|
|||||||
name: Build - Android
|
name: Build - Android
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
#- name: Setup Gradle
|
||||||
|
# uses: gradle/actions/setup-gradle@v6
|
||||||
|
# with:
|
||||||
|
# gradle-version: '8.14.5'
|
||||||
|
|
||||||
|
- uses: actions/checkout@v6
|
||||||
- name: Build example_android_opengl3
|
- name: Build example_android_opengl3
|
||||||
run: |
|
run: |
|
||||||
cd examples/example_android_opengl3/android
|
cd examples/example_android_opengl3/android
|
||||||
@@ -667,7 +677,7 @@ jobs:
|
|||||||
working-directory: ${{ github.workspace }}/imgui
|
working-directory: ${{ github.workspace }}/imgui
|
||||||
|
|
||||||
env:
|
env:
|
||||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\18\Enterprise\MSBuild\Current\Bin\
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|||||||
4
.github/workflows/static-analysis.yml
vendored
4
.github/workflows/static-analysis.yml
vendored
@@ -23,9 +23,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
if [[ "$PVS_STUDIO_LICENSE" != "" ]];
|
if [[ "$PVS_STUDIO_LICENSE" != "" ]];
|
||||||
then
|
then
|
||||||
wget -q https://files.viva64.com/etc/pubkey.txt
|
wget -q https://files.pvs-studio.com/etc/pubkey.txt
|
||||||
sudo apt-key add pubkey.txt
|
sudo apt-key add pubkey.txt
|
||||||
sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.viva64.com/etc/viva64.list
|
sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.pvs-studio.com/etc/viva64.list
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y pvs-studio
|
sudo apt-get install -y pvs-studio
|
||||||
pvs-studio-analyzer credentials -o pvs-studio.lic $PVS_STUDIO_LICENSE
|
pvs-studio-analyzer credentials -o pvs-studio.lic $PVS_STUDIO_LICENSE
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -72,6 +72,7 @@ examples/example_sdl2_opengl3/example_sdl2_opengl3
|
|||||||
examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2
|
examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2
|
||||||
examples/example_sdl2_vulkan/example_sdl2_vulkan
|
examples/example_sdl2_vulkan/example_sdl2_vulkan
|
||||||
examples/example_sdl3_metal/example_sdl3_metal
|
examples/example_sdl3_metal/example_sdl3_metal
|
||||||
|
examples/example_sdl3_metal4/example_sdl3_metal4
|
||||||
examples/example_sdl3_opengl3/example_sdl3_opengl3
|
examples/example_sdl3_opengl3/example_sdl3_opengl3
|
||||||
examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3
|
examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3
|
||||||
examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3
|
examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ struct ImGui_ImplGlfw_Data
|
|||||||
bool IsWayland;
|
bool IsWayland;
|
||||||
bool InstalledCallbacks;
|
bool InstalledCallbacks;
|
||||||
bool CallbacksChainForAllWindows;
|
bool CallbacksChainForAllWindows;
|
||||||
char BackendPlatformName[32];
|
char BackendPlatformName[40];
|
||||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
const char* CanvasSelector;
|
const char* CanvasSelector;
|
||||||
#endif
|
#endif
|
||||||
@@ -676,7 +676,13 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
|
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
|
||||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
|
bd->Context = ImGui::GetCurrentContext();
|
||||||
|
bd->Window = window;
|
||||||
|
bd->Time = 0.0;
|
||||||
|
bd->IsWayland = ImGui_ImplGlfw_IsWayland();
|
||||||
|
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
|
||||||
|
|
||||||
|
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)%s", GLFW_VERSION_COMBINED, bd->IsWayland ? " (Wayland)" : "");
|
||||||
io.BackendPlatformUserData = (void*)bd;
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
io.BackendPlatformName = bd->BackendPlatformName;
|
io.BackendPlatformName = bd->BackendPlatformName;
|
||||||
#if GLFW_HAS_CREATECURSOR
|
#if GLFW_HAS_CREATECURSOR
|
||||||
@@ -684,12 +690,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
#endif
|
#endif
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
|
||||||
bd->Context = ImGui::GetCurrentContext();
|
|
||||||
bd->Window = window;
|
|
||||||
bd->Time = 0.0;
|
|
||||||
bd->IsWayland = ImGui_ImplGlfw_IsWayland();
|
|
||||||
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
|
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
#if GLFW_VERSION_COMBINED < 3300
|
#if GLFW_VERSION_COMBINED < 3300
|
||||||
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window, text); };
|
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window, text); };
|
||||||
|
|||||||
58
backends/imgui_impl_metal4.h
Normal file
58
backends/imgui_impl_metal4.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// dear imgui: Renderer Backend for Metal 4
|
||||||
|
// This needs to be used along with a Platform Backend (e.g. OSX)
|
||||||
|
// Metal 4 requires Apple Silicon and macOS 26+.
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Renderer: User texture binding. Use 'MTLTexture.gpuResourceID' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
|
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||||
|
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
|
// Missing features or Issues:
|
||||||
|
// [ ] Metal-cpp support.
|
||||||
|
// [ ] Texture view pool support? Reevaluate which type to use for ImtextureID.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// ObjC API
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
|
||||||
|
@class MTL4RenderPassDescriptor;
|
||||||
|
@protocol MTLDevice, MTL4CommandBuffer, MTL4RenderCommandEncoder, MTL4CommandQueue;
|
||||||
|
|
||||||
|
// framesInFlight must match the number of frames your application keeps in flight (e.g. the size of your own
|
||||||
|
// command buffer/allocator ring). The backend uses it to size its own per-frame-in-flight resources (constant
|
||||||
|
// buffer, vertex/index buffer cache) so the CPU never overwrites a slot the GPU may still be reading.
|
||||||
|
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQueue, int framesInFlight);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplMetal4_Shutdown();
|
||||||
|
// frameInFlightIndex must match the slot you use to index your own per-frame-in-flight resources
|
||||||
|
// (e.g. the same index used to pick your command buffer/allocator), and must be < framesInFlight passed to Init().
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplMetal4_NewFrame(MTL4RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplMetal4_RenderDrawData(ImDrawData* drawData,
|
||||||
|
id<MTL4CommandBuffer> commandBuffer,
|
||||||
|
id<MTL4RenderCommandEncoder> commandEncoder);
|
||||||
|
|
||||||
|
// Called by Init/NewFrame/Shutdown
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplMetal4_CreateDeviceObjects(id<MTLDevice> device);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplMetal4_DestroyDeviceObjects();
|
||||||
|
|
||||||
|
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
708
backends/imgui_impl_metal4.mm
Normal file
708
backends/imgui_impl_metal4.mm
Normal file
@@ -0,0 +1,708 @@
|
|||||||
|
// dear imgui: Renderer Backend for Metal 4
|
||||||
|
// This needs to be used along with a Platform Backend (e.g. OSX)
|
||||||
|
// Metal 4 requires Apple Silicon and macOS 26+.
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
|
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||||
|
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
|
// Missing features or Issues:
|
||||||
|
// [ ] Metal-cpp support.
|
||||||
|
// [ ] Texture view pool support? Reevaluate which type to use for ImtextureID.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458)
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#ifndef IMGUI_DISABLE
|
||||||
|
#include "imgui_impl_metal4.h"
|
||||||
|
#import <time.h>
|
||||||
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
|
#pragma mark - Support classes and structs
|
||||||
|
|
||||||
|
struct ImGui_Metal4_ConstantData
|
||||||
|
{
|
||||||
|
float ModelViewProjectionMatrix[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface MetalBuffer : NSObject
|
||||||
|
@property (nonatomic, strong) id<MTLBuffer> buffer;
|
||||||
|
@property (nonatomic, assign) double lastReuseTime;
|
||||||
|
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
|
||||||
|
@end
|
||||||
|
|
||||||
|
// An object that encapsulates the data necessary to uniquely identify a
|
||||||
|
// render pipeline state. These are used as cache keys.
|
||||||
|
@interface FramebufferDescriptor : NSObject<NSCopying>
|
||||||
|
@property (nonatomic, assign) unsigned long sampleCount;
|
||||||
|
@property (nonatomic, assign) MTLPixelFormat colorPixelFormat;
|
||||||
|
@property (nonatomic, assign) MTLPixelFormat depthPixelFormat;
|
||||||
|
@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat;
|
||||||
|
- (instancetype)initWithRenderPassDescriptor:(MTL4RenderPassDescriptor*)renderPassDescriptor;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface MetalTexture : NSObject
|
||||||
|
@property (nonatomic, strong) id<MTLTexture> metalTexture;
|
||||||
|
- (instancetype)initWithTexture:(id<MTLTexture>)metalTexture;
|
||||||
|
@end
|
||||||
|
|
||||||
|
// A singleton that stores long-lived objects that are needed by the Metal
|
||||||
|
// renderer backend. Stores the render pipeline state cache and the default
|
||||||
|
// font texture, and manages the reusable buffer cache.
|
||||||
|
@interface MetalContext : NSObject
|
||||||
|
@property (nonatomic, strong) id<MTLDevice> device;
|
||||||
|
@property (nonatomic, strong) id<MTL4CommandQueue> commandQueue;
|
||||||
|
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
||||||
|
@property (nonatomic, strong) id<MTL4ArgumentTable> argumentTable;
|
||||||
|
@property (nonatomic, strong) id<MTLSamplerState> samplerStateLinear;
|
||||||
|
@property (nonatomic, strong) id<MTLSamplerState> samplerStateNearest;
|
||||||
|
@property (nonatomic, strong) id<MTLResidencySet> residencySet;
|
||||||
|
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor;
|
||||||
|
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache;
|
||||||
|
@property (nonatomic, assign) NSUInteger framesInFlight;
|
||||||
|
@property (nonatomic, assign) NSUInteger currentFrameSlot;
|
||||||
|
@property (nonatomic, strong) NSArray<id<MTLBuffer>>* constantBuffers;
|
||||||
|
@property (nonatomic, assign) ImGui_Metal4_ConstantData** constantBufferContentsArray;
|
||||||
|
@property (nonatomic, strong) NSMutableArray<NSMutableArray<MetalBuffer*>*>* bufferCaches;
|
||||||
|
@property (nonatomic, strong) NSObject* bufferCacheLock;
|
||||||
|
@property (nonatomic, assign) double lastBufferCachePurge;
|
||||||
|
- (id<MTLBuffer>)currentConstantBuffer;
|
||||||
|
- (ImGui_Metal4_ConstantData*)currentConstantBufferContents;
|
||||||
|
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
|
||||||
|
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device;
|
||||||
|
@end
|
||||||
|
|
||||||
|
struct ImGui_ImplMetal4_Data
|
||||||
|
{
|
||||||
|
MetalContext* SharedMetalContext;
|
||||||
|
id<MTL4RenderCommandEncoder> RenderCommandEncoder;
|
||||||
|
|
||||||
|
ImGui_ImplMetal4_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ImGui_ImplMetal4_Data* ImGui_ImplMetal4_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal4_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; }
|
||||||
|
static void ImGui_ImplMetal4_DestroyBackendData(){ IM_DELETE(ImGui_ImplMetal4_GetBackendData()); }
|
||||||
|
|
||||||
|
static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); }
|
||||||
|
|
||||||
|
#pragma mark - Dear ImGui Metal Backend API
|
||||||
|
|
||||||
|
void ImGui_ImplMetal4_NewFrame(MTL4RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex)
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
IM_ASSERT(bd != nil && "Context or backend not initialized! Did you call ImGui_ImplMetal4_Init()?");
|
||||||
|
IM_ASSERT(frameInFlightIndex < bd->SharedMetalContext.framesInFlight && "frameInFlightIndex out of range! See framesInFlight passed to ImGui_ImplMetal4_Init().");
|
||||||
|
#ifdef IMGUI_IMPL_METAL_CPP
|
||||||
|
bd->SharedMetalContext.framebufferDescriptor = [[[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]autorelease];
|
||||||
|
#else
|
||||||
|
bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
|
||||||
|
#endif
|
||||||
|
bd->SharedMetalContext.currentFrameSlot = (NSUInteger)frameInFlightIndex;
|
||||||
|
if (bd->SharedMetalContext.depthStencilState == nil)
|
||||||
|
ImGui_ImplMetal4_CreateDeviceObjects(bd->SharedMetalContext.device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplMetal4_SetupRenderState(ImDrawData* draw_data, id<MTL4CommandBuffer> commandBuffer,
|
||||||
|
id<MTL4RenderCommandEncoder> commandEncoder, id<MTLRenderPipelineState> renderPipelineState,
|
||||||
|
MetalBuffer* vertexBuffer, size_t vertexBufferOffset)
|
||||||
|
{
|
||||||
|
IM_UNUSED(commandBuffer);
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
[commandEncoder setCullMode:MTLCullModeNone];
|
||||||
|
[commandEncoder setDepthStencilState:bd->SharedMetalContext.depthStencilState];
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||||
|
// draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||||
|
MTLViewport viewport =
|
||||||
|
{
|
||||||
|
.originX = 0.0,
|
||||||
|
.originY = 0.0,
|
||||||
|
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x),
|
||||||
|
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y),
|
||||||
|
.znear = 0.0,
|
||||||
|
.zfar = 1.0
|
||||||
|
};
|
||||||
|
[commandEncoder setViewport:viewport];
|
||||||
|
|
||||||
|
float L = draw_data->DisplayPos.x;
|
||||||
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||||
|
float T = draw_data->DisplayPos.y;
|
||||||
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||||
|
float N = (float)viewport.znear;
|
||||||
|
float F = (float)viewport.zfar;
|
||||||
|
const float ortho_projection[4][4] =
|
||||||
|
{
|
||||||
|
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
|
||||||
|
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
|
||||||
|
};
|
||||||
|
ImGui_Metal4_ConstantData* constantBufferContents = [bd->SharedMetalContext currentConstantBufferContents];
|
||||||
|
memcpy(constantBufferContents->ModelViewProjectionMatrix, ortho_projection, sizeof(ortho_projection));
|
||||||
|
|
||||||
|
id<MTL4ArgumentTable> argumentTable = bd->SharedMetalContext.argumentTable;
|
||||||
|
[argumentTable setAddress:[bd->SharedMetalContext currentConstantBuffer].gpuAddress atIndex:1];
|
||||||
|
[argumentTable setAddress:(vertexBuffer.buffer.gpuAddress + vertexBufferOffset) attributeStride:sizeof(ImDrawVert) atIndex:0];
|
||||||
|
[argumentTable setSamplerState:bd->SharedMetalContext.samplerStateLinear.gpuResourceID atIndex:0];
|
||||||
|
[commandEncoder setArgumentTable:argumentTable atStages:MTLRenderStageVertex | MTLRenderStageFragment];
|
||||||
|
[commandEncoder setRenderPipelineState:renderPipelineState];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplMetal4_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||||
|
static void ImGui_ImplMetal4_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData(); [bd->SharedMetalContext.argumentTable setSamplerState:bd->SharedMetalContext.samplerStateLinear.gpuResourceID atIndex:0]; }
|
||||||
|
static void ImGui_ImplMetal4_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData(); [bd->SharedMetalContext.argumentTable setSamplerState:bd->SharedMetalContext.samplerStateNearest.gpuResourceID atIndex:0]; }
|
||||||
|
|
||||||
|
void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, id<MTL4CommandBuffer> commandBuffer, id<MTL4RenderCommandEncoder> commandEncoder)
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
MetalContext* ctx = bd->SharedMetalContext;
|
||||||
|
|
||||||
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||||
|
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||||
|
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||||
|
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||||
|
if (draw_data->Textures != nullptr)
|
||||||
|
for (ImTextureData* tex : *draw_data->Textures)
|
||||||
|
if (tex->Status != ImTextureStatus_OK)
|
||||||
|
ImGui_ImplMetal4_UpdateTexture(tex);
|
||||||
|
|
||||||
|
// Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
|
||||||
|
// The hit rate for this cache should be very near 100%.
|
||||||
|
id<MTLRenderPipelineState> renderPipelineState = ctx.renderPipelineStateCache[ctx.framebufferDescriptor];
|
||||||
|
if (renderPipelineState == nil)
|
||||||
|
{
|
||||||
|
// No luck; make a new render pipeline state
|
||||||
|
renderPipelineState = [ctx renderPipelineStateForFramebufferDescriptor:ctx.framebufferDescriptor device:commandBuffer.device];
|
||||||
|
|
||||||
|
// Cache render pipeline state for later reuse
|
||||||
|
ctx.renderPipelineStateCache[ctx.framebufferDescriptor] = renderPipelineState;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vertexBufferLength = (size_t)draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||||
|
size_t indexBufferLength = (size_t)draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||||
|
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
|
||||||
|
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
||||||
|
|
||||||
|
bd->RenderCommandEncoder = commandEncoder;
|
||||||
|
ImGui_ImplMetal4_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
|
||||||
|
|
||||||
|
// Will project scissor/clipping rectangles into framebuffer space
|
||||||
|
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||||
|
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||||
|
|
||||||
|
// Before rendering command lists, commit residency set
|
||||||
|
[bd->SharedMetalContext.residencySet commit];
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
size_t vertexBufferOffset = 0;
|
||||||
|
size_t indexBufferOffset = 0;
|
||||||
|
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||||
|
{
|
||||||
|
memcpy((char*)vertexBuffer.buffer.contents + vertexBufferOffset, draw_list->VtxBuffer.Data, (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||||
|
memcpy((char*)indexBuffer.buffer.contents + indexBufferOffset, draw_list->IdxBuffer.Data, (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||||
|
|
||||||
|
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback)
|
||||||
|
{
|
||||||
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
|
if (pcmd->UserCallback == ImGui_ImplMetal4_DrawCallback_ResetRenderState)
|
||||||
|
ImGui_ImplMetal4_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, vertexBufferOffset);
|
||||||
|
else
|
||||||
|
pcmd->UserCallback(draw_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Project scissor/clipping rectangles into framebuffer space
|
||||||
|
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||||
|
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||||
|
|
||||||
|
// Clamp to viewport as setScissorRect() won't accept values that are off bounds
|
||||||
|
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||||
|
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||||
|
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||||
|
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||||
|
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||||
|
continue;
|
||||||
|
if (pcmd->ElemCount == 0) // drawIndexedPrimitives() validation doesn't accept this
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Apply scissor/clipping rectangle
|
||||||
|
MTLScissorRect scissorRect =
|
||||||
|
{
|
||||||
|
.x = NSUInteger(clip_min.x),
|
||||||
|
.y = NSUInteger(clip_min.y),
|
||||||
|
.width = NSUInteger(clip_max.x - clip_min.x),
|
||||||
|
.height = NSUInteger(clip_max.y - clip_min.y)
|
||||||
|
};
|
||||||
|
[commandEncoder setScissorRect:scissorRect];
|
||||||
|
|
||||||
|
// Bind texture, Draw
|
||||||
|
ImTextureID tex_id = pcmd->GetTexID();
|
||||||
|
if (tex_id != ImTextureID_Invalid)
|
||||||
|
{
|
||||||
|
id<MTLTexture> texture = (__bridge id<MTLTexture>)(void*)(intptr_t)tex_id;
|
||||||
|
[bd->SharedMetalContext.argumentTable setTexture:texture.gpuResourceID atIndex:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
[bd->SharedMetalContext.argumentTable setAddress:(vertexBuffer.buffer.gpuAddress + vertexBufferOffset + (pcmd->VtxOffset * sizeof(ImDrawVert))) attributeStride:sizeof(ImDrawVert) atIndex:0];
|
||||||
|
|
||||||
|
size_t indexBufferCmdOffset = indexBufferOffset + (pcmd->IdxOffset * sizeof(ImDrawIdx));
|
||||||
|
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||||
|
indexCount:pcmd->ElemCount
|
||||||
|
indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
|
||||||
|
indexBuffer:indexBuffer.buffer.gpuAddress + indexBufferCmdOffset
|
||||||
|
indexBufferLength:indexBuffer.buffer.length - indexBufferCmdOffset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vertexBufferOffset += (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||||
|
indexBufferOffset += (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetalContext* sharedMetalContext = bd->SharedMetalContext;
|
||||||
|
@synchronized(sharedMetalContext.bufferCacheLock)
|
||||||
|
{
|
||||||
|
NSMutableArray<MetalBuffer*>* slotCache = sharedMetalContext.bufferCaches[sharedMetalContext.currentFrameSlot];
|
||||||
|
[slotCache addObject:vertexBuffer];
|
||||||
|
[slotCache addObject:indexBuffer];
|
||||||
|
}
|
||||||
|
bd->RenderCommandEncoder = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplMetal4_DestroyTexture(ImTextureData* tex)
|
||||||
|
{
|
||||||
|
if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
|
||||||
|
{
|
||||||
|
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
|
||||||
|
backend_tex.metalTexture = nil;
|
||||||
|
|
||||||
|
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||||
|
tex->SetTexID(ImTextureID_Invalid);
|
||||||
|
tex->BackendUserData = nullptr;
|
||||||
|
}
|
||||||
|
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex)
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
if (tex->Status == ImTextureStatus_WantCreate)
|
||||||
|
{
|
||||||
|
// Create and upload new texture to graphics system
|
||||||
|
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||||
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||||
|
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||||
|
|
||||||
|
// We are retrieving and uploading the font atlas as a 4-channels RGBA texture here.
|
||||||
|
// In theory we could call GetTexDataAsAlpha8() and upload a 1-channel texture to save on memory access bandwidth.
|
||||||
|
// However, using a shader designed for 1-channel texture would make it less obvious to use the ImTextureID facility to render users own textures.
|
||||||
|
// You can make that change in your implementation.
|
||||||
|
MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||||
|
width:(NSUInteger)tex->Width
|
||||||
|
height:(NSUInteger)tex->Height
|
||||||
|
mipmapped:NO];
|
||||||
|
textureDescriptor.usage = MTLTextureUsageShaderRead;
|
||||||
|
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||||
|
|
||||||
|
id <MTLTexture> texture = [bd->SharedMetalContext.device newTextureWithDescriptor:textureDescriptor];
|
||||||
|
[bd->SharedMetalContext.residencySet addAllocation:texture];
|
||||||
|
[texture replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)tex->Width, (NSUInteger)tex->Height) mipmapLevel:0 withBytes:tex->Pixels bytesPerRow:(NSUInteger)tex->Width * 4];
|
||||||
|
MetalTexture* backend_tex = [[MetalTexture alloc] initWithTexture:texture];
|
||||||
|
|
||||||
|
// Store identifiers
|
||||||
|
tex->SetTexID((ImTextureID)(intptr_t)texture);
|
||||||
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
|
tex->BackendUserData = (__bridge_retained void*)(backend_tex);
|
||||||
|
}
|
||||||
|
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||||
|
{
|
||||||
|
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||||
|
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||||
|
MetalTexture* backend_tex = (__bridge MetalTexture*)(tex->BackendUserData);
|
||||||
|
for (ImTextureRect& r : tex->Updates)
|
||||||
|
{
|
||||||
|
[backend_tex.metalTexture replaceRegion:MTLRegionMake2D((NSUInteger)r.x, (NSUInteger)r.y, (NSUInteger)r.w, (NSUInteger)r.h)
|
||||||
|
mipmapLevel:0
|
||||||
|
withBytes:tex->GetPixelsAt(r.x, r.y)
|
||||||
|
bytesPerRow:(NSUInteger)tex->Width * 4];
|
||||||
|
}
|
||||||
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
|
}
|
||||||
|
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_DestroyTexture(tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplMetal4_CreateDeviceObjects(id<MTLDevice> device)
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
|
||||||
|
MTLResidencySetDescriptor* residencySetDescriptor = [[MTLResidencySetDescriptor alloc] init];
|
||||||
|
residencySetDescriptor.initialCapacity = 1000;
|
||||||
|
|
||||||
|
NSError* error = nil;
|
||||||
|
bd->SharedMetalContext.residencySet = [device newResidencySetWithDescriptor:residencySetDescriptor error:&error];
|
||||||
|
IM_ASSERT(bd->SharedMetalContext.residencySet != nil && error == nil);
|
||||||
|
|
||||||
|
[bd->SharedMetalContext.commandQueue addResidencySet:bd->SharedMetalContext.residencySet];
|
||||||
|
|
||||||
|
MTLDepthStencilDescriptor* depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init];
|
||||||
|
depthStencilDescriptor.depthWriteEnabled = NO;
|
||||||
|
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||||
|
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
||||||
|
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
|
||||||
|
samplerDescriptor.supportArgumentBuffers = YES;
|
||||||
|
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||||
|
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||||
|
samplerDescriptor.mipFilter = MTLSamplerMipFilterLinear;
|
||||||
|
bd->SharedMetalContext.samplerStateLinear = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||||
|
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
|
||||||
|
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
|
||||||
|
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
|
||||||
|
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||||
|
|
||||||
|
NSMutableArray<id<MTLBuffer>>* constantBuffers = [NSMutableArray array];
|
||||||
|
ImGui_Metal4_ConstantData** constantBufferContentsArray = (ImGui_Metal4_ConstantData**)malloc(sizeof(ImGui_Metal4_ConstantData*) * bd->SharedMetalContext.framesInFlight);
|
||||||
|
for (NSUInteger i = 0; i < bd->SharedMetalContext.framesInFlight; i++)
|
||||||
|
{
|
||||||
|
id<MTLBuffer> constantBuffer = [device newBufferWithLength:sizeof(ImGui_Metal4_ConstantData) options:MTLResourceStorageModeShared];
|
||||||
|
[constantBuffers addObject:constantBuffer];
|
||||||
|
constantBufferContentsArray[i] = (ImGui_Metal4_ConstantData*)constantBuffer.contents;
|
||||||
|
[bd->SharedMetalContext.residencySet addAllocation:constantBuffer];
|
||||||
|
}
|
||||||
|
bd->SharedMetalContext.constantBuffers = constantBuffers;
|
||||||
|
bd->SharedMetalContext.constantBufferContentsArray = constantBufferContentsArray;
|
||||||
|
|
||||||
|
MTL4ArgumentTableDescriptor* argumentTableDescriptor = [[MTL4ArgumentTableDescriptor alloc] init];
|
||||||
|
argumentTableDescriptor.maxBufferBindCount = 8;
|
||||||
|
argumentTableDescriptor.maxTextureBindCount = 8;
|
||||||
|
argumentTableDescriptor.maxSamplerStateBindCount = 8;
|
||||||
|
argumentTableDescriptor.supportAttributeStrides = YES; // required: vertex buffer is bound via setAddress:stride:atIndex: for stage_in fetch
|
||||||
|
|
||||||
|
bd->SharedMetalContext.argumentTable = [device newArgumentTableWithDescriptor:argumentTableDescriptor error:&error];
|
||||||
|
IM_ASSERT(bd->SharedMetalContext.argumentTable != nil && error == nil);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplMetal4_DestroyDeviceObjects()
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
|
||||||
|
// Destroy all textures
|
||||||
|
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||||
|
if (tex->RefCount == 1)
|
||||||
|
ImGui_ImplMetal4_DestroyTexture(tex);
|
||||||
|
|
||||||
|
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||||
|
bd->SharedMetalContext.samplerStateLinear = nil;
|
||||||
|
bd->SharedMetalContext.samplerStateNearest = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQueue, int framesInFlight)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||||
|
IM_ASSERT(framesInFlight > 0 && "framesInFlight must be at least 1!");
|
||||||
|
|
||||||
|
ImGui_ImplMetal4_Data* bd = IM_NEW(ImGui_ImplMetal4_Data)();
|
||||||
|
io.BackendRendererUserData = (void*)bd;
|
||||||
|
io.BackendRendererName = "imgui_impl_metal4";
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||||
|
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal4_DrawCallback_ResetRenderState;
|
||||||
|
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplMetal4_DrawCallback_SetSamplerLinear;
|
||||||
|
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplMetal4_DrawCallback_SetSamplerNearest;
|
||||||
|
|
||||||
|
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||||
|
bd->SharedMetalContext.device = device;
|
||||||
|
bd->SharedMetalContext.commandQueue = commandQueue;
|
||||||
|
bd->SharedMetalContext.framesInFlight = (NSUInteger)framesInFlight;
|
||||||
|
NSMutableArray<NSMutableArray<MetalBuffer*>*>* bufferCaches = [NSMutableArray array];
|
||||||
|
for (NSUInteger i = 0; i < framesInFlight; i++)
|
||||||
|
[bufferCaches addObject:[NSMutableArray array]];
|
||||||
|
bd->SharedMetalContext.bufferCaches = bufferCaches;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplMetal4_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||||
|
IM_UNUSED(bd);
|
||||||
|
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
|
||||||
|
ImGui_ImplMetal4_DestroyDeviceObjects();
|
||||||
|
ImGui_ImplMetal4_DestroyBackendData();
|
||||||
|
|
||||||
|
io.BackendRendererName = nullptr;
|
||||||
|
io.BackendRendererUserData = nullptr;
|
||||||
|
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||||
|
platform_io.ClearRendererHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation MetalBuffer
|
||||||
|
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
_buffer = buffer;
|
||||||
|
_lastReuseTime = GetMachAbsoluteTimeInSeconds();
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark - FramebufferDescriptor implementation
|
||||||
|
|
||||||
|
@implementation FramebufferDescriptor
|
||||||
|
- (instancetype)initWithRenderPassDescriptor:(MTL4RenderPassDescriptor*)renderPassDescriptor
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
_sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount;
|
||||||
|
_colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat;
|
||||||
|
_depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat;
|
||||||
|
_stencilPixelFormat = renderPassDescriptor.stencilAttachment.texture.pixelFormat;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (nonnull id)copyWithZone:(nullable NSZone*)zone
|
||||||
|
{
|
||||||
|
FramebufferDescriptor* copy = [[FramebufferDescriptor allocWithZone:zone] init];
|
||||||
|
copy.sampleCount = self.sampleCount;
|
||||||
|
copy.colorPixelFormat = self.colorPixelFormat;
|
||||||
|
copy.depthPixelFormat = self.depthPixelFormat;
|
||||||
|
copy.stencilPixelFormat = self.stencilPixelFormat;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)hash
|
||||||
|
{
|
||||||
|
NSUInteger sc = _sampleCount & 0x3;
|
||||||
|
NSUInteger cf = _colorPixelFormat & 0x3FF;
|
||||||
|
NSUInteger df = _depthPixelFormat & 0x3FF;
|
||||||
|
NSUInteger sf = _stencilPixelFormat & 0x3FF;
|
||||||
|
NSUInteger hash = (sf << 22) | (df << 12) | (cf << 2) | sc;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)object
|
||||||
|
{
|
||||||
|
FramebufferDescriptor* other = object;
|
||||||
|
if (![other isKindOfClass:[FramebufferDescriptor class]])
|
||||||
|
return NO;
|
||||||
|
return other.sampleCount == self.sampleCount &&
|
||||||
|
other.colorPixelFormat == self.colorPixelFormat &&
|
||||||
|
other.depthPixelFormat == self.depthPixelFormat &&
|
||||||
|
other.stencilPixelFormat == self.stencilPixelFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark - MetalTexture implementation
|
||||||
|
|
||||||
|
@implementation MetalTexture
|
||||||
|
- (instancetype)initWithTexture:(id<MTLTexture>)metalTexture
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
self.metalTexture = metalTexture;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#pragma mark - MetalContext implementation
|
||||||
|
|
||||||
|
@implementation MetalContext
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
self.renderPipelineStateCache = [NSMutableDictionary dictionary];
|
||||||
|
self.bufferCacheLock = [[NSObject alloc] init];
|
||||||
|
_lastBufferCachePurge = GetMachAbsoluteTimeInSeconds();
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
free(_constantBufferContentsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<MTLBuffer>)currentConstantBuffer
|
||||||
|
{
|
||||||
|
return self.constantBuffers[self.currentFrameSlot];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ImGui_Metal4_ConstantData*)currentConstantBufferContents
|
||||||
|
{
|
||||||
|
return self.constantBufferContentsArray[self.currentFrameSlot];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
|
||||||
|
{
|
||||||
|
double now = GetMachAbsoluteTimeInSeconds();
|
||||||
|
NSMutableArray<MetalBuffer*>* slotCache = self.bufferCaches[self.currentFrameSlot];
|
||||||
|
|
||||||
|
@synchronized(self.bufferCacheLock)
|
||||||
|
{
|
||||||
|
// Purge old buffers that haven't been useful for a while
|
||||||
|
if (now - self.lastBufferCachePurge > 1.0)
|
||||||
|
{
|
||||||
|
for (NSMutableArray<MetalBuffer*>* cache in self.bufferCaches)
|
||||||
|
{
|
||||||
|
NSMutableArray* survivors = [NSMutableArray array];
|
||||||
|
for (MetalBuffer* candidate in cache)
|
||||||
|
if (candidate.lastReuseTime > self.lastBufferCachePurge)
|
||||||
|
[survivors addObject:candidate];
|
||||||
|
[cache setArray:survivors];
|
||||||
|
}
|
||||||
|
self.lastBufferCachePurge = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we have a buffer we can reuse, from this frame-in-flight slot's own cache
|
||||||
|
MetalBuffer* bestCandidate = nil;
|
||||||
|
for (MetalBuffer* candidate in slotCache)
|
||||||
|
if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
|
||||||
|
bestCandidate = candidate;
|
||||||
|
|
||||||
|
if (bestCandidate != nil)
|
||||||
|
{
|
||||||
|
[slotCache removeObject:bestCandidate];
|
||||||
|
bestCandidate.lastReuseTime = now;
|
||||||
|
return bestCandidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No luck; make a new buffer
|
||||||
|
id<MTLBuffer> backing = [device newBufferWithLength:length options:MTLResourceStorageModeShared];
|
||||||
|
[self.residencySet addAllocation:backing];
|
||||||
|
return [[MetalBuffer alloc] initWithBuffer:backing];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* shaderCode = R"(
|
||||||
|
#include <metal_stdlib>
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct Uniforms {
|
||||||
|
float4x4 projectionMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexIn {
|
||||||
|
float2 position [[attribute(0)]];
|
||||||
|
float2 texCoords [[attribute(1)]];
|
||||||
|
uchar4 color [[attribute(2)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexOut {
|
||||||
|
float4 position [[position]];
|
||||||
|
float2 texCoords;
|
||||||
|
float4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex VertexOut vertex_main(VertexIn in [[stage_in]],
|
||||||
|
constant Uniforms &uniforms [[buffer(1)]])
|
||||||
|
{
|
||||||
|
VertexOut out;
|
||||||
|
out.position = uniforms.projectionMatrix * float4(in.position, 0, 1);
|
||||||
|
out.texCoords = in.texCoords;
|
||||||
|
out.color = float4(in.color) / float4(255.0);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment half4 fragment_main(VertexOut in [[stage_in]],
|
||||||
|
texture2d<half, access::sample> texture [[texture(0)]],
|
||||||
|
sampler textureSampler [[sampler(0)]])
|
||||||
|
{
|
||||||
|
half4 texColor = texture.sample(textureSampler, in.texCoords);
|
||||||
|
return half4(in.color) * texColor;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device
|
||||||
|
{
|
||||||
|
NSError* error = nil;
|
||||||
|
|
||||||
|
id<MTLLibrary> library = [device newLibraryWithSource:[NSString stringWithUTF8String:shaderCode] options:nil error:&error];
|
||||||
|
if (library == nil)
|
||||||
|
{
|
||||||
|
NSLog(@"Error: failed to create Metal library: %@", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
id<MTLFunction> vertexFunction = [library newFunctionWithName:@"vertex_main"];
|
||||||
|
id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"fragment_main"];
|
||||||
|
|
||||||
|
if (vertexFunction == nil || fragmentFunction == nil)
|
||||||
|
{
|
||||||
|
NSLog(@"Error: failed to find Metal shader functions in library: %@", error);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLVertexDescriptor* vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
|
||||||
|
vertexDescriptor.attributes[0].offset = offsetof(ImDrawVert, pos);
|
||||||
|
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; // position
|
||||||
|
vertexDescriptor.attributes[0].bufferIndex = 0;
|
||||||
|
vertexDescriptor.attributes[1].offset = offsetof(ImDrawVert, uv);
|
||||||
|
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat2; // texCoords
|
||||||
|
vertexDescriptor.attributes[1].bufferIndex = 0;
|
||||||
|
vertexDescriptor.attributes[2].offset = offsetof(ImDrawVert, col);
|
||||||
|
vertexDescriptor.attributes[2].format = MTLVertexFormatUChar4; // color
|
||||||
|
vertexDescriptor.attributes[2].bufferIndex = 0;
|
||||||
|
vertexDescriptor.layouts[0].stepRate = 1;
|
||||||
|
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||||
|
vertexDescriptor.layouts[0].stride = sizeof(ImDrawVert);
|
||||||
|
|
||||||
|
MTLRenderPipelineDescriptor* pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
|
pipelineDescriptor.vertexFunction = vertexFunction;
|
||||||
|
pipelineDescriptor.fragmentFunction = fragmentFunction;
|
||||||
|
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
|
||||||
|
pipelineDescriptor.rasterSampleCount = self.framebufferDescriptor.sampleCount;
|
||||||
|
pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
|
||||||
|
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
|
||||||
|
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||||
|
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
|
||||||
|
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||||
|
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||||
|
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||||
|
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||||
|
pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat;
|
||||||
|
pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;
|
||||||
|
|
||||||
|
id<MTLRenderPipelineState> renderPipelineState = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
|
||||||
|
if (error != nil)
|
||||||
|
NSLog(@"Error: failed to create Metal pipeline state: %@", error);
|
||||||
|
|
||||||
|
return renderPipelineState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
@@ -23,7 +23,10 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2026-06-17: OpenGL: Expose selected render state in ImGui_ImplOpenGL3_RenderState, Allowing to dynamically select between use of glBindSampler() and glTexParameter(). You can access in 'void* platform_io.Renderer_RenderState' during rendering.
|
||||||
|
// 2026-06-03: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577)
|
||||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||||
|
// (Breaking): this change prioritize using glBindSampler() when available, which would override glTexParameter() settings you may have set on custom textures.
|
||||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||||
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
||||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||||
@@ -253,8 +256,6 @@ struct ImGui_ImplOpenGL3_Data
|
|||||||
bool HasBindSampler;
|
bool HasBindSampler;
|
||||||
bool HasClipOrigin;
|
bool HasClipOrigin;
|
||||||
bool UseBufferSubData;
|
bool UseBufferSubData;
|
||||||
bool UseTexParameterToSetSampler;
|
|
||||||
GLuint NextSampler; // Used if !HasBindSampler && UseTexParameterToSetSampler.
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||||
GLuint TexSamplers[2]; // Used if HasBindSimpler. (0=linear, 1=nearest)
|
GLuint TexSamplers[2]; // Used if HasBindSimpler. (0=linear, 1=nearest)
|
||||||
#endif
|
#endif
|
||||||
@@ -330,7 +331,7 @@ void ImGui_ImplOpenGL3_NewFrame()
|
|||||||
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
|
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplOpenGL3_RenderState* render_state, int fb_width, int fb_height, GLuint vertex_array_object)
|
||||||
{
|
{
|
||||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||||
|
|
||||||
@@ -384,8 +385,11 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||||||
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||||
if (bd->HasBindSampler)
|
if (render_state->UseBindSampler)
|
||||||
glBindSampler(0, bd->TexSamplers[0]); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
{
|
||||||
|
render_state->CurrentSampler = bd->TexSamplers[0];
|
||||||
|
glBindSampler(0, render_state->CurrentSampler); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
(void)vertex_array_object;
|
(void)vertex_array_object;
|
||||||
@@ -406,13 +410,42 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||||||
|
|
||||||
// Draw callbacks
|
// Draw callbacks
|
||||||
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||||
|
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*)
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState();
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[0]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; } }
|
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[1]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; } }
|
if (bd->HasBindSampler)
|
||||||
#else
|
{
|
||||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
|
render_state->CurrentSampler = bd->TexSamplers[0];
|
||||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
|
render_state->UseTexParameterFilter = false;
|
||||||
|
glBindSampler(0, render_state->CurrentSampler);
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
render_state->UseTexParameterFilter = true;
|
||||||
|
render_state->CurrentTexParameterFilter = GL_LINEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*)
|
||||||
|
{
|
||||||
|
ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState();
|
||||||
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||||
|
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||||
|
if (bd->HasBindSampler)
|
||||||
|
{
|
||||||
|
render_state->CurrentSampler = bd->TexSamplers[1];
|
||||||
|
render_state->UseTexParameterFilter = false;
|
||||||
|
glBindSampler(0, render_state->CurrentSampler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
render_state->UseTexParameterFilter = true;
|
||||||
|
render_state->CurrentTexParameterFilter = GL_NEAREST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// OpenGL3 Render function.
|
// OpenGL3 Render function.
|
||||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
||||||
@@ -482,7 +515,17 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||||||
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||||
GL_CALL(glGenVertexArrays(1, &vertex_array_object));
|
GL_CALL(glGenVertexArrays(1, &vertex_array_object));
|
||||||
#endif
|
#endif
|
||||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
|
||||||
|
// Setup render state structure (for callbacks and custom texture bindings)
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
ImGui_ImplOpenGL3_RenderState render_state;
|
||||||
|
render_state.UseBindSampler = bd->HasBindSampler;
|
||||||
|
render_state.UseTexParameterFilter = false;
|
||||||
|
render_state.CurrentSampler = 0;
|
||||||
|
render_state.CurrentTexParameterFilter = 0;
|
||||||
|
platform_io.Renderer_RenderState = &render_state;
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_SetupRenderState(draw_data, &render_state, fb_width, fb_height, vertex_array_object);
|
||||||
|
|
||||||
// Will project scissor/clipping rectangles into framebuffer space
|
// Will project scissor/clipping rectangles into framebuffer space
|
||||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||||
@@ -529,7 +572,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||||||
{
|
{
|
||||||
// User callback, registered via ImDrawList::AddCallback()
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
if (pcmd->UserCallback == ImGui_ImplOpenGL3_DrawCallback_ResetRenderState)
|
if (pcmd->UserCallback == ImGui_ImplOpenGL3_DrawCallback_ResetRenderState)
|
||||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
ImGui_ImplOpenGL3_SetupRenderState(draw_data, &render_state, fb_width, fb_height, vertex_array_object);
|
||||||
else
|
else
|
||||||
pcmd->UserCallback(draw_list, pcmd);
|
pcmd->UserCallback(draw_list, pcmd);
|
||||||
}
|
}
|
||||||
@@ -548,11 +591,11 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
|
||||||
|
|
||||||
// Emulate sampler change (even though it is technically part of texture data)
|
// Emulate sampler change (even though it is technically part of texture data)
|
||||||
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
|
// As a sort of hack/workaround, we only start writing using glTexParameter() if sampler is ever changed explicitly.
|
||||||
if (!bd->HasBindSampler && bd->UseTexParameterToSetSampler)
|
if (render_state.UseTexParameterFilter)
|
||||||
{
|
{
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, render_state.CurrentTexParameterFilter);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, render_state.CurrentTexParameterFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||||
@@ -564,6 +607,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
platform_io.Renderer_RenderState = nullptr;
|
||||||
|
|
||||||
// Destroy the temporary VAO
|
// Destroy the temporary VAO
|
||||||
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||||
@@ -1048,7 +1092,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
glsl_version = "#version 150";
|
glsl_version = "#version 150";
|
||||||
#else
|
#else
|
||||||
glsl_version = "#version 130";
|
if (bd->GlVersion >= 410)
|
||||||
|
glsl_version = "#version 410";
|
||||||
|
else
|
||||||
|
glsl_version = "#version 130";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
|
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
|
||||||
|
|||||||
@@ -65,4 +65,17 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// [BETA] Selected render state data shared with callbacks.
|
||||||
|
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplOpenGL3_RenderDrawData() call.
|
||||||
|
// (Please open an issue if you feel you need access to more data)
|
||||||
|
struct ImGui_ImplOpenGL3_RenderState
|
||||||
|
{
|
||||||
|
bool UseBindSampler;
|
||||||
|
bool UseTexParameterFilter;
|
||||||
|
unsigned int CurrentSampler; // (GLuint) Used if UseBindSampler == true, otherwise always 0
|
||||||
|
unsigned int CurrentTexParameterFilter; // (GLuint) Used if UseTexParameterToSetSampler == true
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState() { return (ImGui_ImplOpenGL3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState; }
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
|
|||||||
@@ -147,7 +147,8 @@ struct ImGui_ImplSDL2_Data
|
|||||||
SDL_Renderer* Renderer;
|
SDL_Renderer* Renderer;
|
||||||
Uint64 Time;
|
Uint64 Time;
|
||||||
char* ClipboardTextData;
|
char* ClipboardTextData;
|
||||||
char BackendPlatformName[48];
|
char BackendPlatformName[64];
|
||||||
|
bool IsWayland;
|
||||||
|
|
||||||
// Mouse handling
|
// Mouse handling
|
||||||
Uint32 MouseWindowID;
|
Uint32 MouseWindowID;
|
||||||
@@ -499,11 +500,12 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
SDL_version ver_runtime;
|
SDL_version ver_runtime;
|
||||||
SDL_VERSION(&ver_compiled);
|
SDL_VERSION(&ver_compiled);
|
||||||
SDL_GetVersion(&ver_runtime);
|
SDL_GetVersion(&ver_runtime);
|
||||||
|
const char* sdl_video_driver = SDL_GetCurrentVideoDriver();
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
|
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
|
||||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl2 (%u.%u.%u, %u.%u.%u)",
|
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl2 (%u.%u.%u, %u.%u.%u) (%s)",
|
||||||
ver_compiled.major, ver_compiled.minor, ver_compiled.patch, ver_runtime.major, ver_runtime.minor, ver_runtime.patch);
|
ver_compiled.major, ver_compiled.minor, ver_compiled.patch, ver_runtime.major, ver_runtime.minor, ver_runtime.patch, sdl_video_driver);
|
||||||
io.BackendPlatformUserData = (void*)bd;
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
io.BackendPlatformName = bd->BackendPlatformName;
|
io.BackendPlatformName = bd->BackendPlatformName;
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
@@ -512,16 +514,16 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
bd->Window = window;
|
bd->Window = window;
|
||||||
bd->WindowID = SDL_GetWindowID(window);
|
bd->WindowID = SDL_GetWindowID(window);
|
||||||
bd->Renderer = renderer;
|
bd->Renderer = renderer;
|
||||||
|
bd->IsWayland = strcmp(sdl_video_driver, "Wayland") == 0;
|
||||||
|
|
||||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||||
bd->MouseCanUseGlobalState = false;
|
bd->MouseCanUseGlobalState = false;
|
||||||
bd->MouseCaptureMode = ImGui_ImplSDL2_MouseCaptureMode_Disabled;
|
bd->MouseCaptureMode = ImGui_ImplSDL2_MouseCaptureMode_Disabled;
|
||||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
|
||||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||||
for (const char* item : capture_and_global_state_whitelist)
|
for (const char* item : capture_and_global_state_whitelist)
|
||||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
if (strncmp(sdl_video_driver, item, strlen(item)) == 0)
|
||||||
{
|
{
|
||||||
bd->MouseCanUseGlobalState = true;
|
bd->MouseCanUseGlobalState = true;
|
||||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL2_MouseCaptureMode_Enabled;
|
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL2_MouseCaptureMode_Enabled;
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ struct ImGui_ImplSDL3_Data
|
|||||||
SDL_Renderer* Renderer;
|
SDL_Renderer* Renderer;
|
||||||
Uint64 Time;
|
Uint64 Time;
|
||||||
char* ClipboardTextData;
|
char* ClipboardTextData;
|
||||||
char BackendPlatformName[48];
|
char BackendPlatformName[64];
|
||||||
|
bool IsWayland;
|
||||||
|
|
||||||
// IME handling
|
// IME handling
|
||||||
SDL_Window* ImeWindow;
|
SDL_Window* ImeWindow;
|
||||||
@@ -502,11 +503,13 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
||||||
|
|
||||||
const int ver_linked = SDL_GetVersion();
|
const int ver_linked = SDL_GetVersion();
|
||||||
|
const char* sdl_video_driver = SDL_GetCurrentVideoDriver();
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)();
|
ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)();
|
||||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl3 (%d.%d.%d; %d.%d.%d)",
|
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl3 (%d.%d.%d; %d.%d.%d) (%s)",
|
||||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION, SDL_VERSIONNUM_MAJOR(ver_linked), SDL_VERSIONNUM_MINOR(ver_linked), SDL_VERSIONNUM_MICRO(ver_linked));
|
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION, SDL_VERSIONNUM_MAJOR(ver_linked), SDL_VERSIONNUM_MINOR(ver_linked), SDL_VERSIONNUM_MICRO(ver_linked),
|
||||||
|
sdl_video_driver);
|
||||||
io.BackendPlatformUserData = (void*)bd;
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
io.BackendPlatformName = bd->BackendPlatformName;
|
io.BackendPlatformName = bd->BackendPlatformName;
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
@@ -515,16 +518,16 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||||||
bd->Window = window;
|
bd->Window = window;
|
||||||
bd->WindowID = SDL_GetWindowID(window);
|
bd->WindowID = SDL_GetWindowID(window);
|
||||||
bd->Renderer = renderer;
|
bd->Renderer = renderer;
|
||||||
|
bd->IsWayland = strcmp(sdl_video_driver, "wayland") == 0;
|
||||||
|
|
||||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||||
bd->MouseCanUseGlobalState = false;
|
bd->MouseCanUseGlobalState = false;
|
||||||
bd->MouseCaptureMode = ImGui_ImplSDL3_MouseCaptureMode_Disabled;
|
bd->MouseCaptureMode = ImGui_ImplSDL3_MouseCaptureMode_Disabled;
|
||||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
|
||||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||||
for (const char* item : capture_and_global_state_whitelist)
|
for (const char* item : capture_and_global_state_whitelist)
|
||||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
if (strncmp(sdl_video_driver, item, strlen(item)) == 0)
|
||||||
{
|
{
|
||||||
bd->MouseCanUseGlobalState = true;
|
bd->MouseCanUseGlobalState = true;
|
||||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL3_MouseCaptureMode_Enabled;
|
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL3_MouseCaptureMode_Enabled;
|
||||||
|
|||||||
@@ -537,8 +537,17 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
|
|||||||
|
|
||||||
// Draw callbacks
|
// Draw callbacks
|
||||||
static void ImGui_ImplVulkan_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
static void ImGui_ImplVulkan_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }
|
static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->RenderState->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }
|
||||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }
|
static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->RenderState->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }
|
||||||
|
|
||||||
|
// If you want to use your own sampler, you can create your own callback, access ImGui_ImplVulkan_RenderState for command-buffer and pipeline layout, e.g.
|
||||||
|
/*
|
||||||
|
void ImGui_ImplVulkan_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImDrawCmd* cmd)
|
||||||
|
{
|
||||||
|
ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||||
|
vkCmdBindDescriptorSets(render_state->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, render_state->PipelineLayout, 1, 1, (VkDescriptorSet*)cmd->UserCallbackData, 0, nullptr);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Render function
|
// Render function
|
||||||
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
|
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_vers
|
|||||||
|
|
||||||
// [BETA] Selected render state data shared with callbacks.
|
// [BETA] Selected render state data shared with callbacks.
|
||||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.
|
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.
|
||||||
|
// ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||||
// (Please open an issue if you feel you need access to more data)
|
// (Please open an issue if you feel you need access to more data)
|
||||||
struct ImGui_ImplVulkan_RenderState
|
struct ImGui_ImplVulkan_RenderState
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2026-05-19: DPI: ImGui_ImplWin32_EnableDpiAwareness() helper uses SetProcessDpiAwarenessContext() instead of SetThreadDpiAwarenessContext(), fixes DPI scaling issues with e.g. OpenGL. (#9403)
|
||||||
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
|
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
|
||||||
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
|
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
|
||||||
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
|
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
|
||||||
@@ -886,6 +887,7 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
|
|||||||
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
||||||
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
||||||
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
||||||
|
typedef BOOL(WINAPI* PFN_SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1703+ (Creators Update)
|
||||||
|
|
||||||
// Helper function to enable DPI awareness without setting up a manifest
|
// Helper function to enable DPI awareness without setting up a manifest
|
||||||
void ImGui_ImplWin32_EnableDpiAwareness()
|
void ImGui_ImplWin32_EnableDpiAwareness()
|
||||||
@@ -893,7 +895,12 @@ void ImGui_ImplWin32_EnableDpiAwareness()
|
|||||||
if (_IsWindows10OrGreater())
|
if (_IsWindows10OrGreater())
|
||||||
{
|
{
|
||||||
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
|
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
|
||||||
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
|
if (PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContextFn = (PFN_SetProcessDpiAwarenessContext)::GetProcAddress(user32_dll, "SetProcessDpiAwarenessContext")) // Windows 10 v1703+
|
||||||
|
{
|
||||||
|
SetProcessDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) // Windows 10 v1607+
|
||||||
{
|
{
|
||||||
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ List of Renderer Backends:
|
|||||||
imgui_impl_dx11.cpp ; DirectX11
|
imgui_impl_dx11.cpp ; DirectX11
|
||||||
imgui_impl_dx12.cpp ; DirectX12
|
imgui_impl_dx12.cpp ; DirectX12
|
||||||
imgui_impl_metal.mm ; Metal (ObjC or C++)
|
imgui_impl_metal.mm ; Metal (ObjC or C++)
|
||||||
|
imgui_impl_metal4.mm ; Metal 4 (ObjC or C++)
|
||||||
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy fixed pipeline. Don't use with modern OpenGL code!)
|
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy fixed pipeline. Don't use with modern OpenGL code!)
|
||||||
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2/3, WebGL
|
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2/3, WebGL
|
||||||
imgui_impl_sdlgpu3.cpp ; SDL_GPU (portable 3D graphics API of SDL3)
|
imgui_impl_sdlgpu3.cpp ; SDL_GPU (portable 3D graphics API of SDL3)
|
||||||
|
|||||||
@@ -35,6 +35,136 @@ HOW TO UPDATE?
|
|||||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||||
- Please report any issue!
|
- Please report any issue!
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
VERSION 1.92.9 WIP (In Progress)
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Breaking Changes:
|
||||||
|
|
||||||
|
- TreeNode: commented out legacy name `ImGuiTreeNodeFlags_SpanTextWidth` which
|
||||||
|
was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`.
|
||||||
|
- ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in
|
||||||
|
of directly poking to style.ColorEditFlags. More consistent and easier to discover
|
||||||
|
|
||||||
|
|
||||||
|
Other Changes:
|
||||||
|
|
||||||
|
- Windows:
|
||||||
|
- Clicking on a window's empty-space to move/focus a window checks
|
||||||
|
for lack of mouse button ownership. This gives an additional opportunity
|
||||||
|
for user code to bypass it without using a clickable item. (#9382)
|
||||||
|
- Clicking on a window's empty-space to move/focus a window checks
|
||||||
|
for lack of queued focus request. (#9382)
|
||||||
|
- Fixed double-click collapse toggle not owning the mouse button. If a
|
||||||
|
`SetNextWindowPos()` with pivot was queued in the same frame, the second
|
||||||
|
click could trigger another item in the same window. (#9439) [@Cleroth]
|
||||||
|
- InputText:
|
||||||
|
- Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409)
|
||||||
|
This is automatically scaled by `style.ScaleAllSizes()`.
|
||||||
|
- Tables:
|
||||||
|
- Redesigned/rewrote code to reconcile columns and settings on topology changes. (#9108)
|
||||||
|
- When a column label is passed to TableSetupColumn(), the underlying identifier
|
||||||
|
is used to match live columns data and .ini settings data when changing.
|
||||||
|
This makes it possible to add/remove columns from a table without losing
|
||||||
|
neither live data neither .ini settings data.
|
||||||
|
- PS: Note that this is distinct from toggling column visibility or reordering
|
||||||
|
columns, which was always possible. The new matching makes it easier to create
|
||||||
|
tables that are entirely customized by user or code, without losing state.
|
||||||
|
- Columns without identifiers or with duplicate identifiers are matched
|
||||||
|
sequentially, matching old behavior.
|
||||||
|
- Column ID are stored in .ini file.
|
||||||
|
- Code is being tested both for live topology changes and for loading .ini
|
||||||
|
data with mismatched topology.
|
||||||
|
- Context Menu: added a "Reset" sub-menu with a "Reset Visibility" option.
|
||||||
|
(which is greyed out when using default settings)
|
||||||
|
- Headers: fixed label being clipped early to reserve space for a sort marker
|
||||||
|
even when no sort marker is displayed. Auto-fitting a column still accounts
|
||||||
|
for the possible marker, so that sorting after an auto-fit doesn't clip the label.
|
||||||
|
- Multi-Select
|
||||||
|
- Reworked ImGuiMultiSelectFlags_NoAutoSelect as it carried side-effects that
|
||||||
|
were hardcoded/designed to use multi-selection on checkboxes. (#9391)
|
||||||
|
Specifically removed those undocumented behaviors from _NoAutoSelect:
|
||||||
|
- Clicking a selected/checked item always unselect/uncheck.
|
||||||
|
- Shift+Click inverts targets value and copy to range.
|
||||||
|
- Shift+Keyboard copy selection source value to range.
|
||||||
|
Those behaviors are still happening on checkboxes used within multi-selection.
|
||||||
|
- Fonts:
|
||||||
|
- Added `IMGUI_DISABLE_DEFAULT_FONT_BITMAP`/`IMGUI_DISABLE_DEFAULT_FONT_VECTOR` to
|
||||||
|
disable embedding either fonts separately. (#9407)
|
||||||
|
- Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point
|
||||||
|
imprecisions altering the result by 1 even at relatively small width. (#791)
|
||||||
|
- Better document the fact that ImFontAtlas::Clear()/ClearFonts() functions are
|
||||||
|
unlikely to be useful nowadays. Better recover to an edge case of mistakenly
|
||||||
|
calling ClearFonts() during rendering.
|
||||||
|
- Fixed an issue where passing a manually created ImFontAtlas to CreateContext() would
|
||||||
|
incorrectly destroy it in DestroyContext() when ref-count gets back to zero. (#9426)
|
||||||
|
- Destroying an ImGui context using a ImFontAtlas checks that the later has no references.
|
||||||
|
- Nav:
|
||||||
|
- Fixed context menu activation with gamepad erroneously testing for _NavEnableKeyboard
|
||||||
|
instead of _NavEnableGamepad. (#9454, #8803, #9270) [@Clownacy]
|
||||||
|
- TreeNode:
|
||||||
|
- Fixed nav cursor rendering with rounding even though tree nodes don't have it. (#7589)
|
||||||
|
- Inputs:
|
||||||
|
- Added GetItemClickedCountWithSingleClickDelay() helper for easy disambiguation
|
||||||
|
between single-click and double-click for actions that needs single-click to do
|
||||||
|
something other than selection. (#8337)
|
||||||
|
- Returns 1 on single-click but delayed by io.MouseSingleClickDelay.
|
||||||
|
- Returns 2 on double-click, and 2+ on subsequent repeated cicks.
|
||||||
|
- Added io.MouseSingleClickDelay to configure default delayed single click delay when
|
||||||
|
using GetItemClickedCountWithSingleClickDelay() or IsMouseReleasedWithDelay(). (#8337)
|
||||||
|
Note that io.MouseSingleClickDelay is always > io.MouseDoubleClickTime.
|
||||||
|
- Style:
|
||||||
|
- Added style.MenuItemRounding, ImGuiStyleVar_MenuItemRounding. (#7589, #9375, #9453)
|
||||||
|
- Added style.SelectableRounding, ImGuiStyleVar_SelectableRounding. (#7589, #9375, #9453)
|
||||||
|
The use of this is discouraged because it can easily create problems rendering e.g.
|
||||||
|
contiguous selection.
|
||||||
|
- Scale the NavCursor border thickness when using large values with `ScallAllSizes()`.
|
||||||
|
- Settings:
|
||||||
|
- Windows/Tables settings entries can now record the last used date in YYYYMMDD format,
|
||||||
|
allowing tools to run to e.g. delete entries that haven't been used in X months. (#9460)
|
||||||
|
- Added bool io.ConfigIniSettingsSaveLastUsedDate to disable saving that info. (#9460)
|
||||||
|
- Added int io.ConfigIniSettingsAutoDiscardMonths to enable a mode where unused settings
|
||||||
|
are automatically discard after xx months. (#9460)
|
||||||
|
- Added a trimming tool under Metrics->Settings, along with a yet-unexposed function.
|
||||||
|
- The current system date is fed through ImGuiPlatformIO::Platform_SessionDate,
|
||||||
|
which is automatically set by a call to time() done during context creation. (#9460)
|
||||||
|
- Added IMGUI_DISABLE_TIME_FUNCTIONS to disable setting platform_io.Platform_SessionDate.
|
||||||
|
A custom backend may still set it manually. (#9460)
|
||||||
|
- DrawList:
|
||||||
|
- Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091)
|
||||||
|
- Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText()
|
||||||
|
coordinates for a given scope. (#3437, #9417, #2291)
|
||||||
|
- ColorButton:
|
||||||
|
- Small rendering tweak/optimization for the alpha checkerboard.
|
||||||
|
- Demo:
|
||||||
|
- Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced'
|
||||||
|
demo for clarity (manual reimplementation of basic selection).
|
||||||
|
- Misc:
|
||||||
|
- Added IM_DEBUG_BREAK() handler for GCC+AArch64/ARM64. [@tom-seddon]
|
||||||
|
- Backends:
|
||||||
|
- Metal4:
|
||||||
|
- Added new Metal 4 backend (forked from Metal 3 backend). (#9458, #9451) [@AmelieHeinrich]
|
||||||
|
Note that Metal-cpp is not yet supported.
|
||||||
|
- OpenGL3:
|
||||||
|
- GLSL version detection assume GLSL 410 when GL context is 4.1.
|
||||||
|
Fixes an issue running on macOS with Wine. [#9427, #6577) [@perminovVS]
|
||||||
|
- Expose selected render state in ImGui_ImplOpenGL3_RenderState, allowing to
|
||||||
|
dynamically select between use of glBindSampler() and glTexParameter(). (#9378)
|
||||||
|
- Win32:
|
||||||
|
- Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()`
|
||||||
|
when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends
|
||||||
|
to spawn multiple-thread to manage OpenGL. (#9403)
|
||||||
|
- Examples:
|
||||||
|
- Android: update to AGP 9.2.0 to support Gradle 9.6.0.
|
||||||
|
- OpenGL3+GLFW/SDL2/SDL3: allow Wine compatibility by passing empty GLSL version
|
||||||
|
string to ImGui_ImplOpenGL3_Init() to let backend decide of a GLSL version based
|
||||||
|
on actual GL version obtained. (#9427, #6577) [@perminovVS]
|
||||||
|
- OpenGL3+Win32: rework context creation to allow Wine compatibility. (#9427, #6577) [@perminovVS]
|
||||||
|
- SDL2/SDL3: use `SDL_GetWindowSizeInPixels()` to create frame-buffers. Fixes issues
|
||||||
|
with non-fractional framebuffer size on Wayland. (#8761, #9124) [@billtran1632001]
|
||||||
|
- SDL3+Metal4: added new example. (#9458, #9451) [@AmelieHeinrich]
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
VERSION 1.92.8 (Released 2026-05-12)
|
VERSION 1.92.8 (Released 2026-05-12)
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@@ -64,9 +194,13 @@ Breaking Changes:
|
|||||||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||||
|
- Reminder: you do NOT need to specify `ImDrawFlags_RoundCornersAll` for rounding, it is already the default!
|
||||||
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
|
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
|
||||||
which is part of our new standard draw callbacks. (#9378)
|
which is part of our new standard draw callbacks. (#9378)
|
||||||
Redirecting the earlier value into the later one when set, so both old and new code should work.
|
Redirecting the earlier value into the later one when set, so both old and new code should work.
|
||||||
|
- DrawList: changed value of `ImDrawFlags_Closed`. It was previously advertised as "always == 1" when introduced
|
||||||
|
in 1.82 (2021/02), in order to facilitate backward compatibility with the legacy `bool closed` flag. This
|
||||||
|
guarantee has been removed. The bit is reserved, and `AddPolyline()`, `PathStroke()` will assert when it is used.
|
||||||
- Backends:
|
- Backends:
|
||||||
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
|
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
|
||||||
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
|
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
|
||||||
@@ -81,6 +215,8 @@ Breaking Changes:
|
|||||||
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
|
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
|
||||||
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
|
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
|
||||||
If there is a legit need/request for them or any render state we can always add them back.
|
If there is a legit need/request for them or any render state we can always add them back.
|
||||||
|
- OpenGL3: the new sampler support system prioritize using glBindSampler() when available,
|
||||||
|
which would override glTexParameter() settings you may have set on custom textures. (#9378)
|
||||||
|
|
||||||
Other Changes:
|
Other Changes:
|
||||||
|
|
||||||
@@ -97,6 +233,15 @@ Other Changes:
|
|||||||
#5999, #6452, #5156, #7342, #7592, #7511)
|
#5999, #6452, #5156, #7342, #7592, #7511)
|
||||||
- Made `AddCallback()` user data default to Null for convenience.
|
- Made `AddCallback()` user data default to Null for convenience.
|
||||||
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
|
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
|
||||||
|
The new functions are more optimal and will be part of a larger effort in 1.93 to fix
|
||||||
|
inconsistencies and improve the DrawList API. In the current API, `AddLine()` adds a "magic" +0.5f
|
||||||
|
offset and then center the line, whereas AddLineH()/AddLineV() use the right side of the line to expand.
|
||||||
|
For thickness=1.0f lines this is equivalent:
|
||||||
|
`AddLine({10,3}, {20,3}, ...)` --> `AddLineH(x1=10, x2=20, y=3, ...)`.
|
||||||
|
`AddLine({3,10}, {3,20}, ...)` --> `AddLineV(x=3, y1=10, y2=20, ...)`.
|
||||||
|
For larger integer thickness, AddLine() will center but may be blurry, AddLineH()/AddLineV()
|
||||||
|
will expand "inside" (to the right side) and will always be sharp.
|
||||||
|
A subsequent release will expand on those concepts and add new options.
|
||||||
- InputText:
|
- InputText:
|
||||||
- InputTextMultiline: fixed an issue processing deactivation logic when an active
|
- InputTextMultiline: fixed an issue processing deactivation logic when an active
|
||||||
multi-line edit is clipped due to being out of view.
|
multi-line edit is clipped due to being out of view.
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ SDL3 + DirectX11 examples, Windows only. <BR>
|
|||||||
SDL3 + Metal example, Mac only. <BR>
|
SDL3 + Metal example, Mac only. <BR>
|
||||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm <BR>
|
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm <BR>
|
||||||
|
|
||||||
|
[example_sdl3_metal4/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_metal/) <BR>
|
||||||
|
SDL3 + Metal4 example, Mac only. <BR>
|
||||||
|
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal4.mm <BR>
|
||||||
|
|
||||||
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/) <BR>
|
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/) <BR>
|
||||||
SDL3 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
|
SDL3 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
|
||||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_opengl3.cpp <BR>
|
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_opengl3.cpp <BR>
|
||||||
|
|||||||
@@ -77,6 +77,17 @@ Some solutions:
|
|||||||
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
|
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
|
||||||
- Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
|
- Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
|
||||||
|
|
||||||
|
### (5) Reduce texture resizes/copy on startup
|
||||||
|
|
||||||
|
🆕 Since 1.92, the ImFontAtlas is initially created using a 512x128 texture, then grows as glyphs and fonts are used. Atlas growth leads to alloc+copy, and both the old and new sized textures are present in memory for a short time (typically one frame). If you use known fonts and want to reduce initial growth, you may set `TexMinWidth` and `TexMinHeight` during initializaton.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
ImFontAtlas* atlas = io.Fonts;
|
||||||
|
atlas->TexMinWidth = 1024;
|
||||||
|
atlas->TexMinHeight = 1024;
|
||||||
|
atlas->AddFont(...);
|
||||||
|
```
|
||||||
|
|
||||||
##### [Return to Index](#index)
|
##### [Return to Index](#index)
|
||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
|
|||||||
|
|
||||||
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
|
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
|
||||||
|
|
||||||
C++20 users wishing to use a module may the use [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
|
C++20 users wishing to use a module may use the [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
|
||||||
|
|
||||||
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
|
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ Integrating Dear ImGui within your custom engine is a matter of mainly 1) wiring
|
|||||||
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
|
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
|
||||||
|
|
||||||
Officially maintained backends (in repository):
|
Officially maintained backends (in repository):
|
||||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal 3/4, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
||||||
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
|
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
|
||||||
- Frameworks: Allegro5, Emscripten.
|
- Frameworks: Allegro5, Emscripten.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -25,9 +24,6 @@ android {
|
|||||||
sourceCompatibility JavaVersion.VERSION_11
|
sourceCompatibility JavaVersion.VERSION_11
|
||||||
targetCompatibility JavaVersion.VERSION_11
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '11'
|
|
||||||
}
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
path file('../../CMakeLists.txt')
|
path file('../../CMakeLists.txt')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.12.0"
|
agp = "9.2.0"
|
||||||
kotlin = "2.0.21"
|
kotlin = "2.3.21"
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
@@ -41,29 +41,26 @@ int main(int, char**)
|
|||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Decide GL+GLSL versions
|
// Select GL version + let the backend select a GLSL version
|
||||||
|
const char* glsl_version = nullptr;
|
||||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||||
const char* glsl_version = "#version 100";
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||||
const char* glsl_version = "#version 300 es";
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// GL 3.2 + GLSL 150
|
// GL 3.2 + generally GLSL 150
|
||||||
const char* glsl_version = "#version 150";
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
||||||
#else
|
#else
|
||||||
// GL 3.0 + GLSL 130
|
// GL 3.0 + generally GLSL 130
|
||||||
const char* glsl_version = "#version 130";
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||||
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||||
|
|
||||||
# Building for desktop with WGVK (MUCH EASIER)
|
# Building for desktop with WGVK (MUCH EASIER)
|
||||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
# 1. git clone https://github.com/manuel5975p/WGVK wgvk
|
||||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
@@ -37,7 +37,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
set(CMAKE_CXX_STANDARD 20) # Dawn requires C++20
|
||||||
|
|
||||||
# Dear ImGui
|
# Dear ImGui
|
||||||
set(IMGUI_DIR ../../)
|
set(IMGUI_DIR ../../)
|
||||||
|
|||||||
@@ -39,31 +39,28 @@ int main(int, char**)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide GL+GLSL versions
|
// Select GL version + let the backend select a GLSL version
|
||||||
|
const char* glsl_version = nullptr;
|
||||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||||
const char* glsl_version = "#version 100";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||||
const char* glsl_version = "#version 300 es";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// GL 3.2 Core + GLSL 150
|
// GL 3.2 Core + generally GLSL 150
|
||||||
const char* glsl_version = "#version 150";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||||
#else
|
#else
|
||||||
// GL 3.0 + GLSL 130
|
// GL 3.0 + generally GLSL 130
|
||||||
const char* glsl_version = "#version 130";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Create Framebuffers
|
// Create Framebuffers
|
||||||
int w, h;
|
int w, h;
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||||
SetupVulkanWindow(wd, surface, w, h);
|
SetupVulkanWindow(wd, surface, w, h);
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Resize swap chain?
|
// Resize swap chain?
|
||||||
int fb_width, fb_height;
|
int fb_width, fb_height;
|
||||||
SDL_GetWindowSize(window, &fb_width, &fb_height);
|
SDL_GetWindowSizeInPixels(window, &fb_width, &fb_height);
|
||||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||||
{
|
{
|
||||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||||
|
|
||||||
# Building for desktop with WGVK (MUCH EASIER)
|
# Building for desktop with WGVK (MUCH EASIER)
|
||||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
# 1. git clone https://github.com/manuel5975p/WGVK wgvk
|
||||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
@@ -37,7 +37,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
set(CMAKE_CXX_STANDARD 10) # Dawn requires C++20
|
||||||
|
|
||||||
# Dear ImGui
|
# Dear ImGui
|
||||||
set(IMGUI_DIR ../../)
|
set(IMGUI_DIR ../../)
|
||||||
|
|||||||
48
examples/example_sdl3_metal4/Makefile
Normal file
48
examples/example_sdl3_metal4/Makefile
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#
|
||||||
|
# You will need SDL3 (http://www.libsdl.org):
|
||||||
|
# brew install sdl3
|
||||||
|
#
|
||||||
|
|
||||||
|
#CXX = g++
|
||||||
|
#CXX = clang++
|
||||||
|
|
||||||
|
EXE = example_sdl3_metal4
|
||||||
|
IMGUI_DIR = ../..
|
||||||
|
SOURCES = main.mm
|
||||||
|
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||||
|
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_metal4.mm
|
||||||
|
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||||
|
|
||||||
|
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
|
||||||
|
LIBS += `pkg-config --libs sdl3`
|
||||||
|
LIBS += -L/usr/local/lib -L/opt/local/lib
|
||||||
|
|
||||||
|
CXXFLAGS += `pkg-config --cflags sdl3`
|
||||||
|
CXXFLAGS += -I/usr/local/include -I/opt/local/include
|
||||||
|
CXXFLAGS += -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||||
|
CXXFLAGS += -Wall -Wformat
|
||||||
|
CFLAGS = $(CXXFLAGS)
|
||||||
|
|
||||||
|
%.o:%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
%.o:$(IMGUI_DIR)/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
%.o:$(IMGUI_DIR)/backends/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
%.o:%.mm
|
||||||
|
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
|
||||||
|
|
||||||
|
%.o:$(IMGUI_DIR)/backends/%.mm
|
||||||
|
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
|
||||||
|
|
||||||
|
all: $(EXE)
|
||||||
|
@echo Build complete
|
||||||
|
|
||||||
|
$(EXE): $(OBJS)
|
||||||
|
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXE) $(OBJS)
|
||||||
240
examples/example_sdl3_metal4/main.mm
Normal file
240
examples/example_sdl3_metal4/main.mm
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
// Dear ImGui: standalone example application for SDL3 + Metal 4
|
||||||
|
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
|
||||||
|
// (Metal 4 requires Apple Silicon and macOS 26+.)
|
||||||
|
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_sdl3.h"
|
||||||
|
#include "imgui_impl_metal4.h"
|
||||||
|
#include <stdio.h> // printf, fprintf
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#import <Metal/Metal.h>
|
||||||
|
#import <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
|
#define FRAMES_IN_FLIGHT 3
|
||||||
|
|
||||||
|
// Main code
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
// Setup SDL
|
||||||
|
// [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function]
|
||||||
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
|
||||||
|
{
|
||||||
|
printf("Error: SDL_Init(): %s\n", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SDL window graphics context
|
||||||
|
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||||
|
SDL_WindowFlags window_flags = SDL_WINDOW_METAL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||||
|
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Metal4 example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||||
|
if (window == nullptr)
|
||||||
|
{
|
||||||
|
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||||
|
SDL_ShowWindow(window);
|
||||||
|
|
||||||
|
// Create Metal device _before_ creating the view/layer
|
||||||
|
id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
|
||||||
|
if (!metalDevice)
|
||||||
|
{
|
||||||
|
printf("Error: failed to create Metal device.\n");
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
SDL_MetalView view = SDL_Metal_CreateView(window);
|
||||||
|
CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_Metal_GetLayer(view);
|
||||||
|
layer.device = metalDevice;
|
||||||
|
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
|
|
||||||
|
id<MTL4CommandQueue> commandQueue = [layer.device newMTL4CommandQueue];
|
||||||
|
id<MTLSharedEvent> sharedEvent = [layer.device newSharedEvent];
|
||||||
|
MTL4RenderPassDescriptor* renderPassDescriptor = [MTL4RenderPassDescriptor new];
|
||||||
|
|
||||||
|
[commandQueue addResidencySet:layer.residencySet];
|
||||||
|
|
||||||
|
id<MTL4CommandBuffer> commandBuffers[FRAMES_IN_FLIGHT];
|
||||||
|
id<MTL4CommandAllocator> commandAllocators[FRAMES_IN_FLIGHT];
|
||||||
|
for (int i = 0; i < FRAMES_IN_FLIGHT; i++)
|
||||||
|
{
|
||||||
|
commandAllocators[i] = [layer.device newCommandAllocator];
|
||||||
|
commandBuffers[i] = [layer.device newCommandBuffer];
|
||||||
|
}
|
||||||
|
uint32_t frameIndex = 0;
|
||||||
|
uint32_t frameInFlight = 0;
|
||||||
|
|
||||||
|
// Setup Dear ImGui context
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||||
|
|
||||||
|
// Setup Dear ImGui style
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
//ImGui::StyleColorsLight();
|
||||||
|
|
||||||
|
// Setup scaling
|
||||||
|
ImGuiStyle& style = ImGui::GetStyle();
|
||||||
|
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||||
|
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||||
|
|
||||||
|
// Setup Platform/Renderer backends
|
||||||
|
ImGui_ImplMetal4_Init(layer.device, commandQueue, FRAMES_IN_FLIGHT);
|
||||||
|
ImGui_ImplSDL3_InitForMetal(window);
|
||||||
|
|
||||||
|
// Load Fonts
|
||||||
|
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||||
|
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||||
|
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||||
|
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||||
|
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||||
|
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||||
|
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||||
|
//style.FontSizeBase = 20.0f;
|
||||||
|
//io.Fonts->AddFontDefaultVector();
|
||||||
|
//io.Fonts->AddFontDefaultBitmap();
|
||||||
|
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||||
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||||
|
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||||
|
//IM_ASSERT(font != nullptr);
|
||||||
|
|
||||||
|
// Our state
|
||||||
|
bool show_demo_window = true;
|
||||||
|
bool show_another_window = false;
|
||||||
|
float clear_color[4] = { 0.45f, 0.55f, 0.60f, 1.00f };
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
bool done = false;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
@autoreleasepool
|
||||||
|
{
|
||||||
|
// Poll and handle events (inputs, window resize, etc.)
|
||||||
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||||
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
|
// [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function]
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||||
|
if (event.type == SDL_EVENT_QUIT)
|
||||||
|
done = true;
|
||||||
|
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
|
||||||
|
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||||
|
{
|
||||||
|
SDL_Delay(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||||
|
|
||||||
|
layer.drawableSize = CGSizeMake(width, height);
|
||||||
|
id<CAMetalDrawable> drawable = [layer nextDrawable];
|
||||||
|
|
||||||
|
uint64_t waitValue = (frameIndex >= FRAMES_IN_FLIGHT) ? (frameIndex - FRAMES_IN_FLIGHT + 1) : 0;
|
||||||
|
[sharedEvent waitUntilSignaledValue:waitValue timeoutMS:1000];
|
||||||
|
[commandAllocators[frameInFlight] reset];
|
||||||
|
[commandBuffers[frameInFlight] beginCommandBufferWithAllocator:commandAllocators[frameInFlight]];
|
||||||
|
|
||||||
|
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
|
||||||
|
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
|
||||||
|
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
|
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||||
|
id <MTL4RenderCommandEncoder> renderEncoder = [commandBuffers[frameInFlight] renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||||
|
[renderEncoder pushDebugGroup:@"ImGui demo"];
|
||||||
|
|
||||||
|
// Start the Dear ImGui frame
|
||||||
|
ImGui_ImplMetal4_NewFrame(renderPassDescriptor, frameInFlight);
|
||||||
|
ImGui_ImplSDL3_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||||
|
if (show_demo_window)
|
||||||
|
ImGui::ShowDemoWindow(&show_demo_window);
|
||||||
|
|
||||||
|
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||||
|
{
|
||||||
|
static float f = 0.0f;
|
||||||
|
static int counter = 0;
|
||||||
|
|
||||||
|
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||||
|
|
||||||
|
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||||
|
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||||
|
ImGui::Checkbox("Another Window", &show_another_window);
|
||||||
|
|
||||||
|
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||||
|
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||||
|
|
||||||
|
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||||
|
counter++;
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("counter = %d", counter);
|
||||||
|
|
||||||
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Show another simple window.
|
||||||
|
if (show_another_window)
|
||||||
|
{
|
||||||
|
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||||
|
ImGui::Text("Hello from another window!");
|
||||||
|
if (ImGui::Button("Close Me"))
|
||||||
|
show_another_window = false;
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
ImGui::Render();
|
||||||
|
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||||
|
ImGui_ImplMetal4_RenderDrawData(draw_data, commandBuffers[frameInFlight], renderEncoder);
|
||||||
|
|
||||||
|
[renderEncoder popDebugGroup];
|
||||||
|
[renderEncoder endEncoding];
|
||||||
|
[commandBuffers[frameInFlight] endCommandBuffer];
|
||||||
|
|
||||||
|
id<MTL4CommandBuffer> to_commit[] = { commandBuffers[frameInFlight] };
|
||||||
|
|
||||||
|
[commandQueue waitForDrawable:drawable];
|
||||||
|
[commandQueue commit:to_commit count:1];
|
||||||
|
|
||||||
|
[commandQueue signalEvent:sharedEvent value:frameIndex + 1];
|
||||||
|
[commandQueue signalDrawable:drawable];
|
||||||
|
[drawable present];
|
||||||
|
|
||||||
|
frameIndex++;
|
||||||
|
frameInFlight = (frameInFlight + 1) % FRAMES_IN_FLIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function]
|
||||||
|
ImGui_ImplMetal4_Shutdown();
|
||||||
|
ImGui_ImplSDL3_Shutdown();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -33,31 +33,28 @@ int main(int, char**)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide GL+GLSL versions
|
// Select GL version + let the backend select a GLSL version
|
||||||
|
const char* glsl_version = nullptr;
|
||||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||||
const char* glsl_version = "#version 100";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||||
const char* glsl_version = "#version 300 es";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// GL 3.2 Core + GLSL 150
|
// GL 3.2 Core + generally GLSL 150
|
||||||
const char* glsl_version = "#version 150";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||||
#else
|
#else
|
||||||
// GL 3.0 + GLSL 130
|
// GL 3.0 + generally GLSL 130
|
||||||
const char* glsl_version = "#version 130";
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Create Framebuffers
|
// Create Framebuffers
|
||||||
int w, h;
|
int w, h;
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||||
SetupVulkanWindow(wd, surface, w, h);
|
SetupVulkanWindow(wd, surface, w, h);
|
||||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||||
@@ -477,7 +477,7 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Resize swap chain?
|
// Resize swap chain?
|
||||||
int fb_width, fb_height;
|
int fb_width, fb_height;
|
||||||
SDL_GetWindowSize(window, &fb_width, &fb_height);
|
SDL_GetWindowSizeInPixels(window, &fb_width, &fb_height);
|
||||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||||
{
|
{
|
||||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
|
# * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe]
|
||||||
|
|
||||||
# Building for desktop with WGVK (MUCH EASIER)
|
# Building for desktop with WGVK (MUCH EASIER)
|
||||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
# 1. git clone https://github.com/manuel5975p/WGVK wgvk
|
||||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||||
# 3. cmake --build build
|
# 3. cmake --build build
|
||||||
# The resulting binary will be found at one of the following locations:
|
# The resulting binary will be found at one of the following locations:
|
||||||
@@ -37,7 +37,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
set(CMAKE_CXX_STANDARD 20) # Dawn requires C++20
|
||||||
|
|
||||||
# Dear ImGui
|
# Dear ImGui
|
||||||
set(IMGUI_DIR ../../)
|
set(IMGUI_DIR ../../)
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ int main(int, char**)
|
|||||||
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
|
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
|
||||||
// React to changes in screen size
|
// React to changes in screen size
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSize(window, &width, &height);
|
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||||
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
if (width != wgpu_surface_width || height != wgpu_surface_height)
|
||||||
ResizeSurface(width, height);
|
ResizeSurface(width, height);
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,13 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
// Data stored per platform window
|
// Data stored per platform window
|
||||||
struct WGL_WindowData { HDC hDC; };
|
struct WGL_WindowData { HDC hDC; };
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
static HGLRC g_hRC;
|
static HGLRC g_hRC; // Rendering context
|
||||||
static WGL_WindowData g_MainWindow;
|
static WGL_WindowData g_MainWindow;
|
||||||
static int g_Width;
|
static int g_Width;
|
||||||
static int g_Height;
|
static int g_Height;
|
||||||
@@ -208,8 +209,57 @@ bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data)
|
|||||||
::ReleaseDC(hWnd, hDc);
|
::ReleaseDC(hWnd, hDc);
|
||||||
|
|
||||||
data->hDC = ::GetDC(hWnd);
|
data->hDC = ::GetDC(hWnd);
|
||||||
if (!g_hRC)
|
if (g_hRC)
|
||||||
g_hRC = wglCreateContext(data->hDC);
|
return true;
|
||||||
|
|
||||||
|
// Create legacy context
|
||||||
|
HGLRC tempRC = wglCreateContext(data->hDC);
|
||||||
|
if (!tempRC) { ::ReleaseDC(hWnd, data->hDC); return false; }
|
||||||
|
if (!wglMakeCurrent(data->hDC, tempRC))
|
||||||
|
{
|
||||||
|
wglDeleteContext(tempRC);
|
||||||
|
::ReleaseDC(hWnd, data->hDC);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get context version
|
||||||
|
GLint major = 0, minor = 0;
|
||||||
|
glGetIntegerv(0x821B, &major); // GL_MAJOR_VERSION
|
||||||
|
glGetIntegerv(0x821C, &minor); // GL_MINOR_VERSION
|
||||||
|
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
|
||||||
|
if (major == 0 && minor == 0)
|
||||||
|
sscanf_s(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||||
|
const GLuint gl_version = (GLuint)(major * 100 + minor * 10);
|
||||||
|
|
||||||
|
// Keep temporary context: already OpenGL 3.0+.
|
||||||
|
g_hRC = tempRC;
|
||||||
|
if (gl_version >= 300)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
|
||||||
|
const PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||||
|
|
||||||
|
// GL 3.0
|
||||||
|
const int attribs[] =
|
||||||
|
{
|
||||||
|
0x2091, 3, // WGL_CONTEXT_MAJOR_VERSION_ARB
|
||||||
|
0x2092, 0, // WGL_CONTEXT_MINOR_VERSION_ARB
|
||||||
|
0x9126, 0x0001, // WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
|
||||||
|
0
|
||||||
|
};
|
||||||
|
HGLRC newRC = nullptr;
|
||||||
|
if (wglCreateContextAttribsARB)
|
||||||
|
newRC = wglCreateContextAttribsARB(data->hDC, 0, attribs);
|
||||||
|
|
||||||
|
// If we managed to create 3.0+ context: use that one and destroy the temporary OpenGL 2.x compatibility context.
|
||||||
|
if (newRC)
|
||||||
|
{
|
||||||
|
wglMakeCurrent(nullptr, nullptr);
|
||||||
|
wglDeleteContext(tempRC);
|
||||||
|
g_hRC = newRC;
|
||||||
|
wglMakeCurrent(data->hDC, g_hRC);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,17 +43,20 @@
|
|||||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||||
|
//#define IMGUI_DISABLE_TIME_FUNCTIONS // Don't setup default platform_io.Platform_SessionDate value using time(), localtime_r().
|
||||||
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||||
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean/ProggyForever), remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
|
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean + ProggyForever). Remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FONT_BITMAP // Disable default embedded bitmap font (ProggyClean). Remove ~9 KB from output binary. AddFontDefaultBitmap() will assert.
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FONT_VECTOR // Disable default embedded vector font (ProggyForever), Remove ~14 KB from output binary. AddFontDefaultVector() will assert.
|
||||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||||
|
|
||||||
//---- Enable Test Engine / Automation features.
|
//---- Enable Test Engine / Automation features.
|
||||||
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_imconfig.h", see Test Engine for details.
|
||||||
|
|
||||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||||
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
||||||
|
|||||||
277
imgui.cpp
277
imgui.cpp
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (main code and documentation)
|
// (main code and documentation)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
@@ -395,6 +395,8 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
|||||||
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
||||||
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||||
|
|
||||||
|
- 2026/07/06 (1.92.9) - ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in favor of directly poking to style.ColorEditFlags. More consistent and easier to discover.
|
||||||
|
- 2026/06/02 (1.92.9) - TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead.
|
||||||
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
|
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
|
||||||
- Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);
|
- Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);
|
||||||
- After: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);
|
- After: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);
|
||||||
@@ -416,6 +418,8 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
|||||||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||||
|
- 2026/05/07 (1.92.8) - DrawList: changed value of `ImDrawFlags_Closed`. It was previously advertised as "always == 1" when introduced in 1.82 (2021/02), in order to facilitate backward compatibility with the legacy `bool closed` flag.
|
||||||
|
This guarantee has been removed. The bit is reserved and `AddPolyline()`, `PathStroke()` will assert when it is used.
|
||||||
- 2026/04/23 (1.92.8) - DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`, which is part of our new standard draw callbacks. (#9378)
|
- 2026/04/23 (1.92.8) - DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`, which is part of our new standard draw callbacks. (#9378)
|
||||||
- 2026/04/22 (1.92.8) - Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler.
|
- 2026/04/22 (1.92.8) - Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler.
|
||||||
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||||
@@ -1240,6 +1244,12 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
|||||||
// System includes
|
// System includes
|
||||||
#include <stdio.h> // vsnprintf, sscanf, printf
|
#include <stdio.h> // vsnprintf, sscanf, printf
|
||||||
#include <stdint.h> // intptr_t
|
#include <stdint.h> // intptr_t
|
||||||
|
#ifndef IMGUI_DISABLE_TIME_FUNCTIONS
|
||||||
|
#include <time.h> // time(), localtime_r()/localtime_s()
|
||||||
|
#if defined(_WIN32)
|
||||||
|
static tm* localtime_r(const time_t* timep, tm* result) { return localtime_s(result, timep) == 0 ? result : NULL; }
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled
|
// [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled
|
||||||
#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
|
#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
|
||||||
@@ -1356,6 +1366,7 @@ static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
|
static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
|
||||||
|
static void WindowSettingsHandler_Cleanup(ImGuiContext*, ImGuiSettingsHandler*, ImGuiSettingsCleanupArgs* args);
|
||||||
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
|
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
|
||||||
static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
|
static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
|
||||||
static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
|
static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
|
||||||
@@ -1516,7 +1527,7 @@ ImGuiStyle::ImGuiStyle()
|
|||||||
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
||||||
LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
|
LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
|
||||||
ImageRounding = 0.0f; // Rounding of Image() calls.
|
ImageRounding = 0.0f; // Rounding of Image() calls.
|
||||||
ImageBorderSize = 0.0f; // Thickness of border around tabs.
|
ImageBorderSize = 0.0f; // Thickness of border around Image() calls.
|
||||||
TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
||||||
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
||||||
TabMinWidthBase = 1.0f; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
|
TabMinWidthBase = 1.0f; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
|
||||||
@@ -1530,6 +1541,8 @@ ImGuiStyle::ImGuiStyle()
|
|||||||
TreeLinesFlags = ImGuiTreeNodeFlags_DrawLinesNone;
|
TreeLinesFlags = ImGuiTreeNodeFlags_DrawLinesNone;
|
||||||
TreeLinesSize = 1.0f; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
TreeLinesSize = 1.0f; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
||||||
TreeLinesRounding = 0.0f; // Radius of lines connecting child nodes to the vertical line.
|
TreeLinesRounding = 0.0f; // Radius of lines connecting child nodes to the vertical line.
|
||||||
|
MenuItemRounding = 0.0f; // Radius of MenuItem, BeginMenu rounding.
|
||||||
|
SelectableRounding = 0.0f; // Radius of selectable rounding. MODIFYING THIS IS DISCOURAGED. CONTIGUOUS SELECTIONS WILL NOT LOOK RIGHT. (#7589)
|
||||||
DragDropTargetRounding = 0.0f; // Radius of the drag and drop target frame.
|
DragDropTargetRounding = 0.0f; // Radius of the drag and drop target frame.
|
||||||
DragDropTargetBorderSize = 2.0f; // Thickness of the drag and drop target border.
|
DragDropTargetBorderSize = 2.0f; // Thickness of the drag and drop target border.
|
||||||
DragDropTargetPadding = 3.0f; // Size to expand the drag and drop target from actual target item size.
|
DragDropTargetPadding = 3.0f; // Size to expand the drag and drop target from actual target item size.
|
||||||
@@ -1537,6 +1550,7 @@ ImGuiStyle::ImGuiStyle()
|
|||||||
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
||||||
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
|
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
|
||||||
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
||||||
|
InputTextCursorSize = 1.0f; // Thickness of cursor/caret in InputText().
|
||||||
SeparatorSize = 1.0f; // Thickness of border in Separator().
|
SeparatorSize = 1.0f; // Thickness of border in Separator().
|
||||||
SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText().
|
SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText().
|
||||||
SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
||||||
@@ -1608,10 +1622,13 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
|||||||
TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
|
TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
|
||||||
TreeLinesSize = ImTrunc(TreeLinesSize * scale_factor);
|
TreeLinesSize = ImTrunc(TreeLinesSize * scale_factor);
|
||||||
TreeLinesRounding = ImTrunc(TreeLinesRounding * scale_factor);
|
TreeLinesRounding = ImTrunc(TreeLinesRounding * scale_factor);
|
||||||
|
MenuItemRounding = ImTrunc(MenuItemRounding * scale_factor);
|
||||||
|
SelectableRounding = ImTrunc(SelectableRounding * scale_factor);
|
||||||
DragDropTargetRounding = ImTrunc(DragDropTargetRounding * scale_factor);
|
DragDropTargetRounding = ImTrunc(DragDropTargetRounding * scale_factor);
|
||||||
DragDropTargetBorderSize = ImTrunc(DragDropTargetBorderSize * scale_factor);
|
DragDropTargetBorderSize = ImTrunc(DragDropTargetBorderSize * scale_factor);
|
||||||
DragDropTargetPadding = ImTrunc(DragDropTargetPadding * scale_factor);
|
DragDropTargetPadding = ImTrunc(DragDropTargetPadding * scale_factor);
|
||||||
ColorMarkerSize = ImTrunc(ColorMarkerSize * scale_factor);
|
ColorMarkerSize = ImTrunc(ColorMarkerSize * scale_factor);
|
||||||
|
InputTextCursorSize = ImTrunc(InputTextCursorSize * scale_factor);
|
||||||
SeparatorSize = ImTrunc(SeparatorSize * scale_factor);
|
SeparatorSize = ImTrunc(SeparatorSize * scale_factor);
|
||||||
SeparatorTextBorderSize = ImTrunc(SeparatorTextBorderSize * scale_factor);
|
SeparatorTextBorderSize = ImTrunc(SeparatorTextBorderSize * scale_factor);
|
||||||
SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
|
SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
|
||||||
@@ -1653,8 +1670,8 @@ ImGuiIO::ImGuiIO()
|
|||||||
ConfigNavCursorVisibleAuto = true;
|
ConfigNavCursorVisibleAuto = true;
|
||||||
ConfigNavCursorVisibleAlways = false;
|
ConfigNavCursorVisibleAlways = false;
|
||||||
|
|
||||||
// Miscellaneous options
|
// Widget options
|
||||||
MouseDrawCursor = false;
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag
|
ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag
|
||||||
#else
|
#else
|
||||||
@@ -1664,11 +1681,21 @@ ImGuiIO::ImGuiIO()
|
|||||||
ConfigInputTextCursorBlink = true;
|
ConfigInputTextCursorBlink = true;
|
||||||
ConfigInputTextEnterKeepActive = false;
|
ConfigInputTextEnterKeepActive = false;
|
||||||
ConfigDragClickToInputText = false;
|
ConfigDragClickToInputText = false;
|
||||||
|
ColorEditFlags = ImGuiColorEditFlags_DefaultOptions_; // Current settings for ColorEdit/ColorPicker widgets. May be further edited by users, unless you also set ImGuiColorEditFlags_NoOptions.
|
||||||
ConfigWindowsResizeFromEdges = true;
|
ConfigWindowsResizeFromEdges = true;
|
||||||
ConfigWindowsMoveFromTitleBarOnly = false;
|
ConfigWindowsMoveFromTitleBarOnly = false;
|
||||||
ConfigWindowsCopyContentsWithCtrlC = false;
|
ConfigWindowsCopyContentsWithCtrlC = false;
|
||||||
ConfigScrollbarScrollByPage = true;
|
ConfigScrollbarScrollByPage = true;
|
||||||
|
|
||||||
|
// Ini Settings options
|
||||||
|
ConfigIniSettingsSaveLastUsedDate = true;
|
||||||
|
ConfigIniSettingsAutoDiscardMonths = 0;
|
||||||
|
ConfigDebugIniSettings = false;
|
||||||
|
|
||||||
|
// Miscellaneous options
|
||||||
|
MouseDrawCursor = false;
|
||||||
ConfigMemoryCompactTimer = 60.0f;
|
ConfigMemoryCompactTimer = 60.0f;
|
||||||
|
|
||||||
ConfigDebugIsDebuggerPresent = false;
|
ConfigDebugIsDebuggerPresent = false;
|
||||||
ConfigDebugHighlightIdConflicts = true;
|
ConfigDebugHighlightIdConflicts = true;
|
||||||
ConfigDebugHighlightIdConflictsShowItemPicker = true;
|
ConfigDebugHighlightIdConflictsShowItemPicker = true;
|
||||||
@@ -1683,6 +1710,7 @@ ImGuiIO::ImGuiIO()
|
|||||||
// Inputs Behaviors
|
// Inputs Behaviors
|
||||||
MouseDoubleClickTime = 0.30f;
|
MouseDoubleClickTime = 0.30f;
|
||||||
MouseDoubleClickMaxDist = 6.0f;
|
MouseDoubleClickMaxDist = 6.0f;
|
||||||
|
MouseSingleClickDelay = 0.50f;
|
||||||
MouseDragThreshold = 6.0f;
|
MouseDragThreshold = 6.0f;
|
||||||
KeyRepeatDelay = 0.275f;
|
KeyRepeatDelay = 0.275f;
|
||||||
KeyRepeatRate = 0.050f;
|
KeyRepeatRate = 0.050f;
|
||||||
@@ -3680,6 +3708,8 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
|
|||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign
|
||||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize
|
||||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
|
||||||
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, MenuItemRounding)}, // ImGuiStyleVar_MenuItemRounding
|
||||||
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableRounding)}, // ImGuiStyleVar_SelectableRounding
|
||||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DragDropTargetRounding)}, // ImGuiStyleVar_DragDropTargetRounding
|
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DragDropTargetRounding)}, // ImGuiStyleVar_DragDropTargetRounding
|
||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
||||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
|
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
|
||||||
@@ -4021,7 +4051,7 @@ void ImGui::RenderColorComponentMarker(const ImRect& bb, ImU32 col, float roundi
|
|||||||
RenderRectFilledInRangeH(window->DrawList, bb, col, bb.Min.x, ImMin(bb.Min.x + g.Style.ColorMarkerSize, bb.Max.x), rounding);
|
RenderRectFilledInRangeH(window->DrawList, bb, col, bb.Min.x, ImMin(bb.Min.x + g.Style.ColorMarkerSize, bb.Max.x), rounding);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags)
|
void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags, float rounding)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (id != g.NavId)
|
if (id != g.NavId)
|
||||||
@@ -4037,17 +4067,24 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
|
|||||||
if (window->DC.NavHideHighlightOneFrame)
|
if (window->DC.NavHideHighlightOneFrame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float rounding = (flags & ImGuiNavRenderCursorFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
if (rounding < 0.0f && (flags & ImGuiNavRenderCursorFlags_NoRounding))
|
||||||
|
rounding = 0.0f;
|
||||||
|
#endif
|
||||||
|
if (rounding < 0.0f)
|
||||||
|
rounding = g.Style.FrameRounding;
|
||||||
|
|
||||||
ImRect display_rect = bb;
|
ImRect display_rect = bb;
|
||||||
display_rect.ClipWith(window->ClipRect);
|
display_rect.ClipWith(window->ClipRect);
|
||||||
const float thickness = 2.0f;
|
const float scale_factor = GetScale(); // FIXME-DPI
|
||||||
|
const float thickness = (float)(int)ImMax(2.0f, 1.5f * scale_factor);
|
||||||
if (flags & ImGuiNavRenderCursorFlags_Compact)
|
if (flags & ImGuiNavRenderCursorFlags_Compact)
|
||||||
{
|
{
|
||||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
|
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const float distance = 3.0f + thickness * 0.5f;
|
const float distance = (float)(int)(3.0f + thickness * 0.5f);
|
||||||
display_rect.Expand(ImVec2(distance, distance));
|
display_rect.Expand(ImVec2(distance, distance));
|
||||||
bool fully_visible = window->ClipRect.Contains(display_rect);
|
bool fully_visible = window->ClipRect.Contains(display_rect);
|
||||||
if (!fully_visible)
|
if (!fully_visible)
|
||||||
@@ -4156,7 +4193,10 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
|
|||||||
{ ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" },
|
{ ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" },
|
||||||
{ ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" },
|
{ ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" },
|
||||||
{ ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" },
|
{ ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" },
|
||||||
|
{ ImGuiLocKey_TableReset, "Reset" },
|
||||||
|
//{ ImGuiLocKey_TableResetAll, "Reset to default###ResetAll" },
|
||||||
{ ImGuiLocKey_TableResetOrder, "Reset order###ResetOrder" },
|
{ ImGuiLocKey_TableResetOrder, "Reset order###ResetOrder" },
|
||||||
|
{ ImGuiLocKey_TableResetVisibility, "Reset visibility###ResetVisibility" },
|
||||||
{ ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" },
|
{ ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" },
|
||||||
{ ImGuiLocKey_WindowingPopup, "(Popup)" },
|
{ ImGuiLocKey_WindowingPopup, "(Popup)" },
|
||||||
{ ImGuiLocKey_WindowingUntitled, "(Untitled)" },
|
{ ImGuiLocKey_WindowingUntitled, "(Untitled)" },
|
||||||
@@ -4213,6 +4253,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
ActiveIdIsAlive = 0;
|
ActiveIdIsAlive = 0;
|
||||||
ActiveIdTimer = 0.0f;
|
ActiveIdTimer = 0.0f;
|
||||||
ActiveIdIsJustActivated = false;
|
ActiveIdIsJustActivated = false;
|
||||||
|
ActiveIdWasSelected = ActiveIdWasSoleSelected = false;
|
||||||
ActiveIdAllowOverlap = false;
|
ActiveIdAllowOverlap = false;
|
||||||
ActiveIdNoClearOnFocusLoss = false;
|
ActiveIdNoClearOnFocusLoss = false;
|
||||||
ActiveIdHasBeenPressedBefore = false;
|
ActiveIdHasBeenPressedBefore = false;
|
||||||
@@ -4229,6 +4270,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
|
memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
|
||||||
LastActiveId = 0;
|
LastActiveId = 0;
|
||||||
LastActiveIdTimer = 0.0f;
|
LastActiveIdTimer = 0.0f;
|
||||||
|
LastActiveIdWasSelected = LastActiveIdWasSoleSelected = false;
|
||||||
|
|
||||||
LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
|
LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
|
||||||
|
|
||||||
@@ -4323,7 +4365,6 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
|||||||
TempInputId = 0;
|
TempInputId = 0;
|
||||||
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
|
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
|
||||||
BeginMenuDepth = BeginComboDepth = 0;
|
BeginMenuDepth = BeginComboDepth = 0;
|
||||||
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
|
|
||||||
ColorEditCurrentID = ColorEditSavedID = 0;
|
ColorEditCurrentID = ColorEditSavedID = 0;
|
||||||
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
|
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
|
||||||
ColorEditSavedColor = 0;
|
ColorEditSavedColor = 0;
|
||||||
@@ -4411,6 +4452,7 @@ void ImGui::Initialize()
|
|||||||
ini_handler.TypeName = "Window";
|
ini_handler.TypeName = "Window";
|
||||||
ini_handler.TypeHash = ImHashStr("Window");
|
ini_handler.TypeHash = ImHashStr("Window");
|
||||||
ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
|
ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
|
||||||
|
ini_handler.CleanupFn = WindowSettingsHandler_Cleanup;
|
||||||
ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
|
ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
|
||||||
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
|
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
|
||||||
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
|
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
|
||||||
@@ -4428,6 +4470,14 @@ void ImGui::Initialize()
|
|||||||
g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
|
g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
|
||||||
g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
|
g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
|
||||||
|
|
||||||
|
// Setup session starting date
|
||||||
|
#ifndef IMGUI_DISABLE_TIME_FUNCTIONS
|
||||||
|
const time_t session_time = time(NULL);
|
||||||
|
struct tm session_datetime = {};
|
||||||
|
if (localtime_r(&session_time, &session_datetime))
|
||||||
|
g.PlatformIO.Platform_SessionDate = (session_datetime.tm_year + 1900) * 10000 + (session_datetime.tm_mon + 1) * 100 + session_datetime.tm_mday;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create default viewport
|
// Create default viewport
|
||||||
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
|
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
|
||||||
viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID;
|
viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID;
|
||||||
@@ -4471,10 +4521,14 @@ void ImGui::Shutdown()
|
|||||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||||
{
|
{
|
||||||
UnregisterFontAtlas(atlas);
|
UnregisterFontAtlas(atlas);
|
||||||
if (atlas->RefCount == 0)
|
if (atlas->OwnerContext == &g)
|
||||||
{
|
{
|
||||||
atlas->Locked = false;
|
IM_ASSERT(atlas->RefCount == 0 && "Destroying context owning a ImFontAtlas which is still used elsewhere!");
|
||||||
IM_DELETE(atlas);
|
if (atlas->RefCount == 0)
|
||||||
|
{
|
||||||
|
atlas->Locked = false;
|
||||||
|
IM_DELETE(atlas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.DrawListSharedData.TempBuffer.clear();
|
g.DrawListSharedData.TempBuffer.clear();
|
||||||
@@ -5357,14 +5411,15 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|||||||
|
|
||||||
// Click on empty space to focus window and start moving
|
// Click on empty space to focus window and start moving
|
||||||
// (after we're done with all our widgets)
|
// (after we're done with all our widgets)
|
||||||
if (g.IO.MouseClicked[0])
|
if (IsMouseClicked(0, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner))
|
||||||
{
|
{
|
||||||
// Handle the edge case of a popup being closed while clicking in its empty space.
|
// Handle the edge case of a popup being closed while clicking in its empty space.
|
||||||
// If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
|
// If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
|
||||||
ImGuiWindow* hovered_root = hovered_window ? hovered_window->RootWindow : NULL;
|
ImGuiWindow* hovered_root = hovered_window ? hovered_window->RootWindow : NULL;
|
||||||
const bool is_closed_popup = hovered_root && (hovered_root->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(hovered_root->PopupId, ImGuiPopupFlags_AnyPopupLevel);
|
const bool is_closed_popup = hovered_root && (hovered_root->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(hovered_root->PopupId, ImGuiPopupFlags_AnyPopupLevel);
|
||||||
|
const bool is_queued_focus_request = g.NavMoveSubmitted && (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi);
|
||||||
|
|
||||||
if (hovered_window != NULL && !is_closed_popup)
|
if (hovered_window != NULL && !is_closed_popup && !is_queued_focus_request)
|
||||||
{
|
{
|
||||||
StartMouseMovingWindow(hovered_window); //-V595
|
StartMouseMovingWindow(hovered_window); //-V595
|
||||||
|
|
||||||
@@ -5395,7 +5450,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|||||||
// With right mouse button we close popups without changing focus based on where the mouse is aimed
|
// With right mouse button we close popups without changing focus based on where the mouse is aimed
|
||||||
// Instead, focus will be restored to the window under the bottom-most closed popup.
|
// Instead, focus will be restored to the window under the bottom-most closed popup.
|
||||||
// (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger)
|
// (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger)
|
||||||
if (g.IO.MouseClicked[1] && g.HoveredId == 0)
|
if (g.HoveredId == 0 && IsMouseClicked(1, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner))
|
||||||
{
|
{
|
||||||
// Find the top-most window between HoveredWindow and the top-most Modal Window.
|
// Find the top-most window between HoveredWindow and the top-most Modal Window.
|
||||||
// This is where we can trim the popup stack.
|
// This is where we can trim the popup stack.
|
||||||
@@ -5539,6 +5594,7 @@ void ImGui::NewFrame()
|
|||||||
|
|
||||||
g.Time += g.IO.DeltaTime;
|
g.Time += g.IO.DeltaTime;
|
||||||
g.FrameCount += 1;
|
g.FrameCount += 1;
|
||||||
|
g.SessionDate = ImGuiPackedDate(g.PlatformIO.Platform_SessionDate);
|
||||||
g.TooltipOverrideCount = 0;
|
g.TooltipOverrideCount = 0;
|
||||||
g.WindowsActiveCount = 0;
|
g.WindowsActiveCount = 0;
|
||||||
g.MenusIdSubmittedThisFrame.resize(0);
|
g.MenusIdSubmittedThisFrame.resize(0);
|
||||||
@@ -5607,6 +5663,11 @@ void ImGui::NewFrame()
|
|||||||
// Update ActiveId data (clear reference to active widget if the widget isn't alive anymore)
|
// Update ActiveId data (clear reference to active widget if the widget isn't alive anymore)
|
||||||
if (g.ActiveId)
|
if (g.ActiveId)
|
||||||
g.ActiveIdTimer += g.IO.DeltaTime;
|
g.ActiveIdTimer += g.IO.DeltaTime;
|
||||||
|
if (g.ActiveId && g.ActiveId == g.LastActiveId)
|
||||||
|
{
|
||||||
|
g.LastActiveIdWasSelected = g.ActiveIdWasSelected;
|
||||||
|
g.LastActiveIdWasSoleSelected = g.ActiveIdWasSoleSelected;
|
||||||
|
}
|
||||||
g.LastActiveIdTimer += g.IO.DeltaTime;
|
g.LastActiveIdTimer += g.IO.DeltaTime;
|
||||||
g.ActiveIdPreviousFrame = g.ActiveId;
|
g.ActiveIdPreviousFrame = g.ActiveId;
|
||||||
g.ActiveIdIsAlive = 0;
|
g.ActiveIdIsAlive = 0;
|
||||||
@@ -5742,8 +5803,11 @@ void ImGui::NewFrame()
|
|||||||
if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
|
if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
|
||||||
TableGcCompactTransientBuffers(g.Tables.GetByIndex(i));
|
TableGcCompactTransientBuffers(g.Tables.GetByIndex(i));
|
||||||
for (ImGuiTableTempData& table_temp_data : g.TablesTempData)
|
for (ImGuiTableTempData& table_temp_data : g.TablesTempData)
|
||||||
|
{
|
||||||
|
table_temp_data.ReconcileColumnsRequests.clear(); // Unusual: clear every frame because this is rarely used.
|
||||||
if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
|
if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
|
||||||
TableGcCompactTransientBuffers(&table_temp_data);
|
TableGcCompactTransientBuffers(&table_temp_data);
|
||||||
|
}
|
||||||
if (g.GcCompactAll)
|
if (g.GcCompactAll)
|
||||||
GcCompactTransientMiscBuffers();
|
GcCompactTransientMiscBuffers();
|
||||||
g.GcCompactAll = false;
|
g.GcCompactAll = false;
|
||||||
@@ -6194,11 +6258,9 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex
|
|||||||
ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
|
ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
|
||||||
|
|
||||||
// Round
|
// Round
|
||||||
// FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out.
|
// (see 7b0bf230, 4622fa4b6, #791 for details about this.)
|
||||||
// FIXME: Investigate using ceilf or e.g.
|
// FIXME: Add a way to disable this.
|
||||||
// - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
|
text_size.x = ImCeilFast(text_size.x);
|
||||||
// - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html
|
|
||||||
text_size.x = IM_TRUNC(text_size.x + 0.99999f);
|
|
||||||
|
|
||||||
return text_size;
|
return text_size;
|
||||||
}
|
}
|
||||||
@@ -6317,11 +6379,12 @@ bool ImGui::IsItemToggledOpen()
|
|||||||
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false;
|
return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call after a Selectable() or TreeNode() involved in multi-selection.
|
// Call after a Selectable() or TreeNode() items inside a BeginMultiSelect()/EndMultiSelect() scope.
|
||||||
// Useful if you need the per-item information before reaching EndMultiSelect(), e.g. for rendering purpose.
|
// - Useful if you need the per-item information before reaching EndMultiSelect(), e.g. for rendering purpose.
|
||||||
// This is only meant to be called inside a BeginMultiSelect()/EndMultiSelect() block.
|
// Outside of a multi-select block:
|
||||||
// (Outside of multi-select, it would be misleading/ambiguous to report this signal, as widgets
|
// - It would be misleading/ambiguous to report this signal, as widgets return e.g. a pressed event,
|
||||||
// return e.g. a pressed event and user code is in charge of altering selection in ways we cannot predict.)
|
// and user code is in charge of altering selection in ways we cannot predict.
|
||||||
|
// Prefer using 'if (IsItemClicked() && !IsItemToggledOpen())' for a manual reimplementation of selection.
|
||||||
bool ImGui::IsItemToggledSelection()
|
bool ImGui::IsItemToggledSelection()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@@ -6656,6 +6719,7 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s
|
|||||||
{
|
{
|
||||||
// Initial window state with e.g. default/arbitrary window position
|
// Initial window state with e.g. default/arbitrary window position
|
||||||
// Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
|
// Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
window->Pos = main_viewport->Pos + ImVec2(60, 60);
|
window->Pos = main_viewport->Pos + ImVec2(60, 60);
|
||||||
window->Size = window->SizeFull = ImVec2(0, 0);
|
window->Size = window->SizeFull = ImVec2(0, 0);
|
||||||
@@ -6663,6 +6727,7 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s
|
|||||||
|
|
||||||
if (settings != NULL)
|
if (settings != NULL)
|
||||||
{
|
{
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
|
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
|
||||||
ApplyWindowSettings(window, settings);
|
ApplyWindowSettings(window, settings);
|
||||||
}
|
}
|
||||||
@@ -7706,7 +7771,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
ImRect title_bar_rect = window->TitleBarRect();
|
ImRect title_bar_rect = window->TitleBarRect();
|
||||||
if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && g.ActiveId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
|
if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && g.ActiveId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
|
||||||
if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
|
if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
|
||||||
|
{
|
||||||
window->WantCollapseToggle = true;
|
window->WantCollapseToggle = true;
|
||||||
|
SetKeyOwner(ImGuiKey_MouseLeft, window->MoveId); // Claim input the same way ButtonBehavior() does. Prevent a same-frame move from triggering other items. (#9439)
|
||||||
|
}
|
||||||
if (window->WantCollapseToggle)
|
if (window->WantCollapseToggle)
|
||||||
{
|
{
|
||||||
window->Collapsed = !window->Collapsed;
|
window->Collapsed = !window->Collapsed;
|
||||||
@@ -8975,6 +9043,8 @@ static void ImGui::UpdateTexturesNewFrame()
|
|||||||
IM_ASSERT(atlas->RendererHasTextures == has_textures);
|
IM_ASSERT(atlas->RendererHasTextures == has_textures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (ImTextureData* tex : g.UserTextures)
|
||||||
|
ImTextureDataUpdateNewFrame(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a single texture list
|
// Build a single texture list
|
||||||
@@ -9036,7 +9106,7 @@ ImFont* ImGui::GetDefaultFont()
|
|||||||
return g.IO.FontDefault ? g.IO.FontDefault : atlas->Fonts[0];
|
return g.IO.FontDefault ? g.IO.FontDefault : atlas->Fonts[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates.
|
// EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates. Textures logic will be automatically be updated in NewFrame().
|
||||||
void ImGui::RegisterUserTexture(ImTextureData* tex)
|
void ImGui::RegisterUserTexture(ImTextureData* tex)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@@ -9391,6 +9461,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
|
|||||||
// - IsMouseReleased()
|
// - IsMouseReleased()
|
||||||
// - IsMouseDoubleClicked()
|
// - IsMouseDoubleClicked()
|
||||||
// - GetMouseClickedCount()
|
// - GetMouseClickedCount()
|
||||||
|
// - GetItemClickedCountWithSingleClickDelay()
|
||||||
// - IsMouseHoveringRect() [Internal]
|
// - IsMouseHoveringRect() [Internal]
|
||||||
// - IsMouseDragPastThreshold() [Internal]
|
// - IsMouseDragPastThreshold() [Internal]
|
||||||
// - IsMouseDragging()
|
// - IsMouseDragging()
|
||||||
@@ -9970,6 +10041,8 @@ bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
|
|||||||
return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id)
|
return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Prefer higher-level helper GetItemClickedCountWithSingleClickDelay()
|
||||||
// Use if you absolutely need to distinguish single-click from double-click by introducing a delay.
|
// Use if you absolutely need to distinguish single-click from double-click by introducing a delay.
|
||||||
// Generally use with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount == 1' test.
|
// Generally use 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.
|
// This is a very rarely used UI idiom, but some apps use this: e.g. MS Explorer single click on an icon to rename.
|
||||||
@@ -9977,8 +10050,12 @@ bool ImGui::IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay)
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
|
IM_ASSERT(button >= 0 && button < IM_COUNTOF(g.IO.MouseDown));
|
||||||
|
if (IsMouseDown(button))
|
||||||
|
return false;
|
||||||
|
if (delay < 0.0f)
|
||||||
|
delay = g.IO.MouseSingleClickDelay;
|
||||||
const float time_since_release = (float)(g.Time - g.IO.MouseReleasedTime[button]);
|
const float time_since_release = (float)(g.Time - g.IO.MouseReleasedTime[button]);
|
||||||
return !IsMouseDown(button) && (time_since_release - g.IO.DeltaTime < delay) && (time_since_release >= delay);
|
return (time_since_release - g.IO.DeltaTime < delay) && (time_since_release >= delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
|
bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
|
||||||
@@ -10002,6 +10079,62 @@ int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
|
|||||||
return g.IO.MouseClickedCount[button];
|
return g.IO.MouseClickedCount[button];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: This is close to what BeginDragDropSource() is doing, maybe rework.
|
||||||
|
static ImGuiID LastItemOverlayButtonForNullId(ImGuiMouseButton mouse_button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
IM_ASSERT(g.LastItemData.ID == 0);
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
ImGuiID id = window->GetIDFromRectangle(g.LastItemData.Rect);
|
||||||
|
if (g.IO.MouseClicked[mouse_button] && ImGui::ItemHoverable(g.LastItemData.Rect, id, g.LastItemData.ItemFlags))
|
||||||
|
{
|
||||||
|
ImGui::SetActiveID(id, window);
|
||||||
|
ImGui::FocusWindow(window);
|
||||||
|
}
|
||||||
|
else if (g.ActiveId == id)
|
||||||
|
{
|
||||||
|
ImGui::KeepAliveID(id);
|
||||||
|
if (!g.IO.MouseDown[mouse_button])
|
||||||
|
ImGui::ClearActiveID();
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [BETA] Building block for disambiguation between single-click and double-click.
|
||||||
|
// - Returns 1 on single-click but delayed by io.MouseSingleClickDelay (which is always > io.MouseDoubleClickTime) after mouse release.
|
||||||
|
// - Returns 2+ on double-click and subsequent repeated clicks.
|
||||||
|
// In order use that to replicate Windows Explorer's "click on label to rename after a delay",
|
||||||
|
// When the function returns 1 for a delayed single click, you can add with further tests:
|
||||||
|
// - If you want to test that the mouse position AT THE TIME of the click (before the delay): you can use the 'io.MouseClickedPos[mouse_button]' position.
|
||||||
|
// - If you want to test that the mouse position is still over the item at the end of delay: you can use '&& IsItemHovered()'.
|
||||||
|
// - If you want to test that the item was selected or the sole selection AT THE TIME of the click (before the delay): you can test for 'g.LastActiveIdWasSelected' or 'g.LastActiveIdWasSoleSelected'.
|
||||||
|
// e.g.
|
||||||
|
// int click_count = ImGui::GetItemClickedCountWithSingleClickDelay(mouse_button);
|
||||||
|
// if (click_count == 1 && ImGui::GetCurrentContext()->LastActiveIdWasSoleSelected)
|
||||||
|
// StartRename();
|
||||||
|
// if (click_count == 2)
|
||||||
|
// Launch();
|
||||||
|
int ImGui::GetItemClickedCountWithSingleClickDelay(ImGuiMouseButton mouse_button, float delay)
|
||||||
|
{
|
||||||
|
// Action: double-click and subsequent clicks
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.IO.MouseClickedCount[mouse_button] >= 2 && IsItemClicked(mouse_button))
|
||||||
|
return g.IO.MouseClickedCount[mouse_button];
|
||||||
|
|
||||||
|
// Action: second click, delayed
|
||||||
|
ImGuiID id = g.LastItemData.ID;
|
||||||
|
if (id == 0)
|
||||||
|
id = LastItemOverlayButtonForNullId(mouse_button);
|
||||||
|
if (g.LastActiveId == id)
|
||||||
|
{
|
||||||
|
if (delay >= 0.0f)
|
||||||
|
delay = ImMax(delay, g.IO.MouseDoubleClickTime + 0.01f);
|
||||||
|
if (IsMouseReleasedWithDelay(mouse_button, delay) && g.IO.MouseClickedLastCount[mouse_button] == 1)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Test if mouse cursor is hovering given rectangle
|
// Test if mouse cursor is hovering given rectangle
|
||||||
// NB- Rectangle is clipped by our current clip setting
|
// NB- Rectangle is clipped by our current clip setting
|
||||||
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
|
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
|
||||||
@@ -10948,7 +11081,13 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
|||||||
IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f && "Invalid style setting!"); // Required otherwise cannot resize from borders.
|
IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f && "Invalid style setting!"); // Required otherwise cannot resize from borders.
|
||||||
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
|
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
|
||||||
IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right);
|
IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right);
|
||||||
|
IM_ASSERT(ImIsPowerOfTwo(g.IO.ColorEditFlags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected
|
||||||
|
IM_ASSERT(ImIsPowerOfTwo(g.IO.ColorEditFlags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected
|
||||||
|
IM_ASSERT(ImIsPowerOfTwo(g.IO.ColorEditFlags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected
|
||||||
|
IM_ASSERT(ImIsPowerOfTwo(g.IO.ColorEditFlags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected
|
||||||
|
|
||||||
IM_ASSERT(g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesNone || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesFull || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesToNodes);
|
IM_ASSERT(g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesNone || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesFull || g.Style.TreeLinesFlags == ImGuiTreeNodeFlags_DrawLinesToNodes);
|
||||||
|
IM_ASSERT(g.IO.MouseSingleClickDelay > g.IO.MouseDoubleClickTime);
|
||||||
|
|
||||||
// Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
|
// Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
|
||||||
if (g.IO.ConfigErrorRecovery)
|
if (g.IO.ConfigErrorRecovery)
|
||||||
@@ -13797,13 +13936,13 @@ static void ImGui::NavUpdate()
|
|||||||
// FIXME-NAV: Now that keys are separated maybe we can get rid of NavInputSource?
|
// FIXME-NAV: Now that keys are separated maybe we can get rid of NavInputSource?
|
||||||
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
|
||||||
const ImGuiKey nav_gamepad_keys_to_change_source[] = { ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown };
|
const ImGuiKey nav_gamepad_keys_to_change_source[] = { ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown };
|
||||||
if (nav_gamepad_active)
|
if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad)
|
||||||
for (ImGuiKey key : nav_gamepad_keys_to_change_source)
|
for (ImGuiKey key : nav_gamepad_keys_to_change_source)
|
||||||
if (IsKeyDown(key))
|
if (IsKeyDown(key))
|
||||||
g.NavInputSource = ImGuiInputSource_Gamepad;
|
g.NavInputSource = ImGuiInputSource_Gamepad;
|
||||||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||||
const ImGuiKey nav_keyboard_keys_to_change_source[] = { ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow };
|
const ImGuiKey nav_keyboard_keys_to_change_source[] = { ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow };
|
||||||
if (nav_keyboard_active)
|
if (nav_keyboard_active && g.NavInputSource != ImGuiInputSource_Keyboard)
|
||||||
for (ImGuiKey key : nav_keyboard_keys_to_change_source)
|
for (ImGuiKey key : nav_keyboard_keys_to_change_source)
|
||||||
if (IsKeyDown(key))
|
if (IsKeyDown(key))
|
||||||
g.NavInputSource = ImGuiInputSource_Keyboard;
|
g.NavInputSource = ImGuiInputSource_Keyboard;
|
||||||
@@ -14343,7 +14482,7 @@ static void ImGui::NavUpdateContextMenuRequest()
|
|||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
g.NavOpenContextMenuItemId = g.NavOpenContextMenuWindowId = 0;
|
g.NavOpenContextMenuItemId = g.NavOpenContextMenuWindowId = 0;
|
||||||
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||||
const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0;
|
||||||
if ((!nav_keyboard_active && !nav_gamepad_active) || g.NavWindow == NULL)
|
if ((!nav_keyboard_active && !nav_gamepad_active) || g.NavWindow == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -15569,6 +15708,19 @@ void ImGui::ClearIniSettings()
|
|||||||
handler.ClearAllFn(&g, &handler);
|
handler.ClearAllFn(&g, &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGui::CleanupIniSettings(ImGuiSettingsCleanupArgs* args)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.PlatformIO.Platform_SessionDate == 0)
|
||||||
|
return;
|
||||||
|
ImGuiPackedDate discard_older_than_date_p = g.PlatformIO.Platform_SessionDate;
|
||||||
|
discard_older_than_date_p.SubtractMonths(args->DiscardOlderThanMonths);
|
||||||
|
args->_DiscardOlderThanDate = discard_older_than_date_p.Unpack();
|
||||||
|
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
|
||||||
|
if (handler.CleanupFn != NULL)
|
||||||
|
handler.CleanupFn(&g, &handler, args);
|
||||||
|
}
|
||||||
|
|
||||||
void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
|
void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
|
||||||
{
|
{
|
||||||
size_t file_data_size = 0;
|
size_t file_data_size = 0;
|
||||||
@@ -15647,6 +15799,9 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
|
|||||||
memcpy(buf, ini_data, ini_size);
|
memcpy(buf, ini_data, ini_size);
|
||||||
|
|
||||||
// Call post-read handlers
|
// Call post-read handlers
|
||||||
|
ImGuiSettingsCleanupArgs cleanup_args;
|
||||||
|
if (g.IO.ConfigIniSettingsAutoDiscardMonths > 0)
|
||||||
|
cleanup_args.DiscardOlderThanMonths = g.IO.ConfigIniSettingsAutoDiscardMonths;
|
||||||
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
|
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
|
||||||
if (handler.ApplyAllFn != NULL)
|
if (handler.ApplyAllFn != NULL)
|
||||||
handler.ApplyAllFn(&g, &handler);
|
handler.ApplyAllFn(&g, &handler);
|
||||||
@@ -15743,6 +15898,18 @@ static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
g.SettingsWindows.clear();
|
g.SettingsWindows.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void WindowSettingsHandler_Cleanup(ImGuiContext* ctx, ImGuiSettingsHandler*, ImGuiSettingsCleanupArgs* args)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *ctx;
|
||||||
|
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
|
||||||
|
{
|
||||||
|
if (args->_DiscardOlderThanDate != 0 && settings->LastUsedDate.Unpack() < args->_DiscardOlderThanDate)
|
||||||
|
settings->WantDelete = true;
|
||||||
|
if (args->SetCurrentSessionDateToAll || (args->SetCurrentSessionDateWhenMissingDate && settings->LastUsedDate.IsValid() == false))
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
|
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
|
||||||
{
|
{
|
||||||
ImGuiID id = ImHashStr(name);
|
ImGuiID id = ImHashStr(name);
|
||||||
@@ -15765,6 +15932,7 @@ static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
|||||||
else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); }
|
else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); }
|
||||||
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
|
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
|
||||||
else if (sscanf(line, "IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); }
|
else if (sscanf(line, "IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); }
|
||||||
|
else if (sscanf(line, "LastUsed=%d", &i) == 1) { settings->LastUsedDate = i; return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply to existing windows (if any)
|
// Apply to existing windows (if any)
|
||||||
@@ -15794,6 +15962,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
if (!settings)
|
if (!settings)
|
||||||
{
|
{
|
||||||
settings = ImGui::CreateNewWindowSettings(window->Name);
|
settings = ImGui::CreateNewWindowSettings(window->Name);
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
|
window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
|
||||||
}
|
}
|
||||||
IM_ASSERT(settings->ID == window->ID);
|
IM_ASSERT(settings->ID == window->ID);
|
||||||
@@ -15802,6 +15971,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
settings->IsChild = (window->Flags & ImGuiWindowFlags_ChildWindow) != 0;
|
settings->IsChild = (window->Flags & ImGuiWindowFlags_ChildWindow) != 0;
|
||||||
settings->Collapsed = window->Collapsed;
|
settings->Collapsed = window->Collapsed;
|
||||||
settings->WantDelete = false;
|
settings->WantDelete = false;
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to text buffer
|
// Write to text buffer
|
||||||
@@ -15811,7 +15981,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
if (settings->WantDelete)
|
if (settings->WantDelete)
|
||||||
continue;
|
continue;
|
||||||
const char* settings_name = settings->GetName();
|
const char* settings_name = settings->GetName();
|
||||||
buf->appendf("[%s][%s]\n", handler->TypeName, settings_name);
|
buf->appendf("[%s][%s]\n", handler->TypeName, settings_name); // [Window][name]
|
||||||
if (settings->IsChild)
|
if (settings->IsChild)
|
||||||
{
|
{
|
||||||
buf->appendf("IsChild=1\n");
|
buf->appendf("IsChild=1\n");
|
||||||
@@ -15824,6 +15994,9 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
if (settings->Collapsed)
|
if (settings->Collapsed)
|
||||||
buf->appendf("Collapsed=1\n");
|
buf->appendf("Collapsed=1\n");
|
||||||
}
|
}
|
||||||
|
if (g.IO.ConfigIniSettingsSaveLastUsedDate)
|
||||||
|
if (int last_used_date = settings->LastUsedDate.Unpack())
|
||||||
|
buf->appendf("LastUsed=%08d\n", last_used_date);
|
||||||
buf->append("\n");
|
buf->append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16596,6 +16769,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiIO& io = g.IO;
|
ImGuiIO& io = g.IO;
|
||||||
|
ImGuiPlatformIO& platform_io = g.PlatformIO;
|
||||||
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
|
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
|
||||||
if (cfg->ShowDebugLog)
|
if (cfg->ShowDebugLog)
|
||||||
ShowDebugLogWindow(&cfg->ShowDebugLog);
|
ShowDebugLogWindow(&cfg->ShowDebugLog);
|
||||||
@@ -16928,8 +17102,36 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|||||||
Text("\"%s\"", g.IO.IniFilename);
|
Text("\"%s\"", g.IO.IniFilename);
|
||||||
else
|
else
|
||||||
TextUnformatted("<NULL>");
|
TextUnformatted("<NULL>");
|
||||||
Checkbox("io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
|
|
||||||
Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer);
|
Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer);
|
||||||
|
|
||||||
|
int highlight_older_than_date = 0;
|
||||||
|
Text("SessionDate: %d", platform_io.Platform_SessionDate);
|
||||||
|
BeginDisabled(platform_io.Platform_SessionDate == 0);
|
||||||
|
Checkbox("Highlight Entries Older Than", &cfg->SettingsHighlightOldEntries);
|
||||||
|
SetNextItemWidth(GetFontSize() * 8);
|
||||||
|
SameLine();
|
||||||
|
SliderInt("Months", &cfg->SettingsDiscardMonths, 1, 24);
|
||||||
|
if (cfg->SettingsHighlightOldEntries && cfg->SettingsDiscardMonths > 0)
|
||||||
|
{
|
||||||
|
ImGuiPackedDate cutoff_date = platform_io.Platform_SessionDate;
|
||||||
|
cutoff_date.SubtractMonths(cfg->SettingsDiscardMonths);
|
||||||
|
highlight_older_than_date = cutoff_date.Unpack();
|
||||||
|
SameLine();
|
||||||
|
ImGuiSettingsCleanupArgs cleanup_args;
|
||||||
|
cleanup_args.DiscardOlderThanMonths = cfg->SettingsDiscardMonths;
|
||||||
|
if (Button("Discard"))
|
||||||
|
CleanupIniSettings(&cleanup_args);
|
||||||
|
}
|
||||||
|
EndDisabled();
|
||||||
|
Checkbox("io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
|
||||||
|
|
||||||
|
struct ScopedHighlightOlderThan
|
||||||
|
{
|
||||||
|
bool Highlight;
|
||||||
|
ScopedHighlightOlderThan(int cutoff_date, ImGuiPackedDate in_date) { Highlight = cutoff_date != 0 && in_date.Unpack() < cutoff_date; if (Highlight) PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); }
|
||||||
|
~ScopedHighlightOlderThan() { if (Highlight) PopStyleColor(); }
|
||||||
|
};
|
||||||
|
|
||||||
if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size))
|
if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size))
|
||||||
{
|
{
|
||||||
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
|
for (ImGuiSettingsHandler& handler : g.SettingsHandlers)
|
||||||
@@ -16939,14 +17141,20 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|||||||
if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
|
if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
|
||||||
{
|
{
|
||||||
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
|
for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
|
||||||
|
{
|
||||||
|
ScopedHighlightOlderThan scoped_highlight(highlight_older_than_date, settings->LastUsedDate);
|
||||||
DebugNodeWindowSettings(settings);
|
DebugNodeWindowSettings(settings);
|
||||||
|
}
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
|
if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
|
||||||
{
|
{
|
||||||
for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
|
for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
|
||||||
DebugNodeTableSettings(settings);
|
{
|
||||||
|
ScopedHighlightOlderThan scoped_highlight(highlight_older_than_date, settings->LastUsedDate);
|
||||||
|
DebugNodeTableSettings(settings, NULL);
|
||||||
|
}
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17761,7 +17969,7 @@ void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
|
|||||||
{
|
{
|
||||||
if (settings->WantDelete)
|
if (settings->WantDelete)
|
||||||
BeginDisabled();
|
BeginDisabled();
|
||||||
Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
|
BulletText("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
|
||||||
settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
|
settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
|
||||||
if (settings->WantDelete)
|
if (settings->WantDelete)
|
||||||
EndDisabled();
|
EndDisabled();
|
||||||
@@ -17899,6 +18107,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
|||||||
ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav);
|
ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav);
|
||||||
ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup);
|
ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup);
|
||||||
ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection);
|
ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection);
|
||||||
|
ShowDebugLogFlag("Table", ImGuiDebugLogFlags_EventTable);
|
||||||
ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting);
|
ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting);
|
||||||
|
|
||||||
if (SmallButton("Clear"))
|
if (SmallButton("Clear"))
|
||||||
|
|||||||
123
imgui.h
123
imgui.h
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (headers)
|
// (headers)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
// Library Version
|
// Library Version
|
||||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||||
#define IMGUI_VERSION "1.92.8"
|
#define IMGUI_VERSION "1.92.9 WIP"
|
||||||
#define IMGUI_VERSION_NUM 19280
|
#define IMGUI_VERSION_NUM 19285
|
||||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||||
|
|
||||||
@@ -613,7 +613,8 @@ namespace ImGui
|
|||||||
IMGUI_API ImGuiID GetID(int int_id);
|
IMGUI_API ImGuiID GetID(int int_id);
|
||||||
|
|
||||||
// Widgets: Text
|
// Widgets: Text
|
||||||
IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text.
|
// - Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text): which will automatically bypass the formatter.
|
||||||
|
IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified.
|
||||||
IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text
|
IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text
|
||||||
IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1);
|
IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1);
|
||||||
IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
|
IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
|
||||||
@@ -648,7 +649,7 @@ namespace ImGui
|
|||||||
// Widgets: Images
|
// Widgets: Images
|
||||||
// - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
// - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
||||||
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
|
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
|
||||||
// - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side.
|
// - Image() adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side.
|
||||||
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
|
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
|
||||||
// - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function.
|
// - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function.
|
||||||
IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1));
|
IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1));
|
||||||
@@ -736,7 +737,6 @@ namespace ImGui
|
|||||||
IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
|
IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
|
||||||
IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);
|
IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);
|
||||||
IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed.
|
IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed.
|
||||||
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.
|
|
||||||
|
|
||||||
// Widgets: Trees
|
// Widgets: Trees
|
||||||
// - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents.
|
// - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents.
|
||||||
@@ -808,7 +808,7 @@ namespace ImGui
|
|||||||
// - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar.
|
// - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar.
|
||||||
// - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it.
|
// - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it.
|
||||||
// - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it.
|
// - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it.
|
||||||
// - Not that MenuItem() keyboardshortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment.
|
// - Note that MenuItem() keyboard shortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment.
|
||||||
IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window).
|
IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window).
|
||||||
IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true!
|
IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true!
|
||||||
IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar.
|
IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar.
|
||||||
@@ -837,7 +837,7 @@ namespace ImGui
|
|||||||
|
|
||||||
// Popups, Modals
|
// Popups, Modals
|
||||||
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
|
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
|
||||||
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
|
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing Escape (call 'Shortcut(ImGuiKey_Escape)' to claim a higher-priority shortcut).
|
||||||
// - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls.
|
// - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls.
|
||||||
// - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time.
|
// - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time.
|
||||||
// - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
|
// - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
|
||||||
@@ -908,14 +908,15 @@ namespace ImGui
|
|||||||
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
|
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
|
||||||
|
|
||||||
// Tables: Headers & Columns declaration
|
// Tables: Headers & Columns declaration
|
||||||
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc.
|
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, various other flags etc.
|
||||||
|
// (the trailing 'ImGuiID user_data', which used to be referred to as 'ImGuiID user_id', is merely user data that is blindly copied in ImGuiTableColumnSortSpecs).
|
||||||
// - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column.
|
// - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column.
|
||||||
// Headers are required to perform: reordering, sorting, and opening the context menu.
|
// Headers are required to perform: reordering, sorting, and opening the context menu.
|
||||||
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
|
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
|
||||||
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
|
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
|
||||||
// some advanced use cases (e.g. adding custom widgets in header row).
|
// some advanced use cases (e.g. adding custom widgets in header row).
|
||||||
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them.
|
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them.
|
||||||
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
|
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_data = 0);
|
||||||
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
|
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
|
||||||
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
|
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
|
||||||
IMGUI_API void TableHeadersRow(); // submit a row with headers cells based on data provided to TableSetupColumn() + submit context menu
|
IMGUI_API void TableHeadersRow(); // submit a row with headers cells based on data provided to TableSetupColumn() + submit context menu
|
||||||
@@ -1024,6 +1025,7 @@ namespace ImGui
|
|||||||
IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space)
|
IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space)
|
||||||
IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
|
IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
|
||||||
IMGUI_API ImGuiItemFlags GetItemFlags(); // get generic flags of last item
|
IMGUI_API ImGuiItemFlags GetItemFlags(); // get generic flags of last item
|
||||||
|
IMGUI_API int GetItemClickedCountWithSingleClickDelay(ImGuiMouseButton mouse_button = 0, float delay = -1.0f); // [BETA] building block for disambiguation between single-click and double-click. Returns 1 on single-click but delayed by io.MouseSingleClickDelay after mouse release. Returns 2+ on double-click or repeated clicks.
|
||||||
|
|
||||||
// Viewports
|
// Viewports
|
||||||
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
|
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
|
||||||
@@ -1106,7 +1108,7 @@ namespace ImGui
|
|||||||
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1.
|
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1.
|
||||||
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down)
|
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down)
|
||||||
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true)
|
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true)
|
||||||
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_API bool IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay=-1.f);// delayed mouse release. Use sparingly. Prefer higher-level helper GetItemClickedCountWithSingleClickDelay(). Generally used with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount==1' test.
|
||||||
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0).
|
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0).
|
||||||
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
|
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
|
||||||
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
|
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
|
||||||
@@ -1330,7 +1332,7 @@ enum ImGuiTreeNodeFlags_
|
|||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0
|
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0
|
||||||
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
|
//ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
|
||||||
//ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
|
//ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -1854,6 +1856,8 @@ enum ImGuiStyleVar_
|
|||||||
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
|
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
|
||||||
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
|
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
|
||||||
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
||||||
|
ImGuiStyleVar_MenuItemRounding, // float MenuItemRounding
|
||||||
|
ImGuiStyleVar_SelectableRounding, // float SelectableRounding
|
||||||
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
|
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
|
||||||
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
||||||
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
||||||
@@ -1913,8 +1917,9 @@ enum ImGuiColorEditFlags_
|
|||||||
ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format.
|
ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format.
|
||||||
ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format.
|
ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format.
|
||||||
|
|
||||||
// Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to
|
// Defaults Options copied to style.ColorEditFlags during initialization.
|
||||||
// override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup.
|
// The intent is that you probably don't want to override them in most of your calls.
|
||||||
|
// Let the user choose via the option menu and/or modify style.ColorEditFlags directly during startup if you want.
|
||||||
ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,
|
ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,
|
||||||
|
|
||||||
// [Internal] Masks
|
// [Internal] Masks
|
||||||
@@ -2158,7 +2163,7 @@ struct ImGuiTableSortSpecs
|
|||||||
// Sorting specification for one column of a table (sizeof == 12 bytes)
|
// Sorting specification for one column of a table (sizeof == 12 bytes)
|
||||||
struct ImGuiTableColumnSortSpecs
|
struct ImGuiTableColumnSortSpecs
|
||||||
{
|
{
|
||||||
ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
|
ImGuiID ColumnUserID; // User data for the column (if specified by a TableSetupColumn() call in the 'ImGuiID user_data' field). FIXME: Should be called 'UserData'..
|
||||||
ImS16 ColumnIndex; // Index of the column
|
ImS16 ColumnIndex; // Index of the column
|
||||||
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
|
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
|
||||||
ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
|
ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
|
||||||
@@ -2331,6 +2336,8 @@ struct ImGuiStyle
|
|||||||
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
|
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
|
||||||
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
||||||
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
|
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
|
||||||
|
float MenuItemRounding; // Radius of MenuItem, BeginMenu rounding.
|
||||||
|
float SelectableRounding; // Radius of Selectable rounding. MODIFYING THIS IS DISCOURAGED. CONTIGUOUS SELECTIONS WILL NOT LOOK RIGHT. (#7589)
|
||||||
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
|
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
|
||||||
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
|
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
|
||||||
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
|
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
|
||||||
@@ -2338,6 +2345,7 @@ struct ImGuiStyle
|
|||||||
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
||||||
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
|
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
|
||||||
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
||||||
|
float InputTextCursorSize; // Thickness of cursor/caret in InputText().
|
||||||
float SeparatorSize; // Thickness of border in Separator(). Must be >= 1.0f.
|
float SeparatorSize; // Thickness of border in Separator(). Must be >= 1.0f.
|
||||||
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
|
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
|
||||||
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
||||||
@@ -2428,24 +2436,33 @@ struct ImGuiIO
|
|||||||
bool ConfigNavCursorVisibleAuto; // = true // Using directional navigation key makes the cursor visible. Mouse click hides the cursor.
|
bool ConfigNavCursorVisibleAuto; // = true // Using directional navigation key makes the cursor visible. Mouse click hides the cursor.
|
||||||
bool ConfigNavCursorVisibleAlways; // = false // Navigation cursor is always visible.
|
bool ConfigNavCursorVisibleAlways; // = false // Navigation cursor is always visible.
|
||||||
|
|
||||||
// Miscellaneous options
|
// Widget options
|
||||||
// (you can visualize and interact with all options in 'Demo->Configuration')
|
|
||||||
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
|
|
||||||
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
|
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
|
||||||
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
|
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
|
||||||
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
|
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
|
||||||
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
|
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
|
||||||
|
ImGuiColorEditFlags ColorEditFlags; // // Current settings for ColorEdit/ColorPicker widgets. Must have one bit of ImGuiColorEditFlags_DisplayMask_, one bit of ImGuiColorEditFlags_DataTypeMask_, one bit of ImGuiColorEditFlags_PickerMask_, one bit of ImGuiColorEditFlags_InputMask_. Defaults to ImGuiColorEditFlags_DefaultOptions_. May be further edited by users, unless you also set ImGuiColorEditFlags_NoOptions.
|
||||||
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
|
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
|
||||||
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
|
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
|
||||||
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
|
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
|
||||||
bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] Ctrl+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order.
|
bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] Ctrl+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order.
|
||||||
bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
|
bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
|
||||||
|
|
||||||
|
// Ini Settings options
|
||||||
|
bool ConfigIniSettingsSaveLastUsedDate;// = true // Enable loading/saving last used day (YYYYMMDD) in some .ini struct, making things easier to audit and allowing custom tools to cleanup old data.
|
||||||
|
int ConfigIniSettingsAutoDiscardMonths; // = 0 // [BETA] Set number of months after which unused .ini entries are discarded on load. Require platform_io.Platform_SessionDate to be set. For systems supporting the feature, .ini entries without a LastUsed field will always be discarded! Please report if you are using this.
|
||||||
|
bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
|
||||||
|
|
||||||
|
// Miscellaneous options
|
||||||
|
// (you can visualize and interact with all options in 'Demo->Configuration')
|
||||||
|
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
|
||||||
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
|
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
|
||||||
|
|
||||||
// Inputs Behaviors
|
// Inputs Behaviors
|
||||||
// (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
|
// (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
|
||||||
float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
|
float MouseDoubleClickTime; // = 0.30f // Time for consecutive clicks to account as a double-click, in seconds.
|
||||||
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
|
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click or multiple clicks, in pixels.
|
||||||
|
float MouseSingleClickDelay; // = 0.60f // Time for a delayed click when using GetItemClickedCountWithSingleClickDelay() or IsMouseReleasedWithDelay(), in seconds. Must be > io.MouseDoubleClickTime.
|
||||||
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
|
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
|
||||||
float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
|
float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
|
||||||
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
|
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
|
||||||
@@ -2498,9 +2515,6 @@ struct ImGuiIO
|
|||||||
// - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
|
// - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
|
||||||
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys()/io.ClearInputMouse() in input processing.
|
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys()/io.ClearInputMouse() in input processing.
|
||||||
|
|
||||||
// Option to audit .ini data
|
|
||||||
bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Platform Identifiers
|
// Platform Identifiers
|
||||||
// (the imgui_impl_xxxx backend files are setting those up for you)
|
// (the imgui_impl_xxxx backend files are setting those up for you)
|
||||||
@@ -2612,7 +2626,7 @@ struct ImGuiIO
|
|||||||
//void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
|
//void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92 (June 2025)
|
float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92.0 (June 2025)
|
||||||
|
|
||||||
// Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO.
|
// Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO.
|
||||||
// As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete).
|
// As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete).
|
||||||
@@ -3049,6 +3063,7 @@ enum ImGuiMultiSelectFlags_
|
|||||||
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.
|
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.
|
||||||
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
|
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
|
||||||
ImGuiMultiSelectFlags_SelectOnMask_ = ImGuiMultiSelectFlags_SelectOnAuto | ImGuiMultiSelectFlags_SelectOnClickAlways | ImGuiMultiSelectFlags_SelectOnClickRelease,
|
ImGuiMultiSelectFlags_SelectOnMask_ = ImGuiMultiSelectFlags_SelectOnAuto | ImGuiMultiSelectFlags_SelectOnClickAlways | ImGuiMultiSelectFlags_SelectOnClickRelease,
|
||||||
|
ImGuiMultiSelectFlags_CheckboxMode_ = 1 << 20, // [Internal]
|
||||||
|
|
||||||
// Obsolete names
|
// Obsolete names
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
@@ -3245,20 +3260,27 @@ struct ImDrawListSplitter
|
|||||||
enum ImDrawFlags_
|
enum ImDrawFlags_
|
||||||
{
|
{
|
||||||
ImDrawFlags_None = 0,
|
ImDrawFlags_None = 0,
|
||||||
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
|
|
||||||
ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
|
// Rounding for AddRect(), AddRectFilled(), PathRect()
|
||||||
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
|
// - When not specified, we defaults to ImDrawFlags_RoundCornersAll! So you only need to use those flags if you want another configuration.
|
||||||
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
|
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // Round top-left corner only (when rounding > 0.0f, we default to all corners).
|
||||||
ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
|
ImDrawFlags_RoundCornersTopRight = 1 << 5, // Round top-right corner only (when rounding > 0.0f, we default to all corners).
|
||||||
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
|
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // Round bottom-left corner only (when rounding > 0.0f, we default to all corners).
|
||||||
|
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // Round bottom-right corner only (when rounding > 0.0f, we default to all corners).
|
||||||
|
ImDrawFlags_RoundCornersNone = 1 << 8, // Disable rounding even if `float rounding > 0.0f`. This is NOT zero, NOT an implicit flag!
|
||||||
|
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, // (Default!!)
|
||||||
|
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified!
|
||||||
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
|
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
|
||||||
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
||||||
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
|
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
|
||||||
ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
|
ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
|
||||||
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
|
||||||
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
|
|
||||||
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
|
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
|
||||||
ImDrawFlags_InvalidMask_ = (ImDrawFlags)0x8000000F,
|
|
||||||
|
// Stroke options
|
||||||
|
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed.
|
||||||
|
//ImDrawFlags_Closed = 1 << 0, // Prior to 1.92.8 (May 2026), ImDrawFlags_Closed was guaranteed to be == 1<<0 == 1 for legacy compatibility reason. Hardcoded use of 1 or true should be replaced.
|
||||||
|
|
||||||
|
ImDrawFlags_InvalidMask_ = ~0x7FFFFFF0, // == 0x8000000F,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
|
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
|
||||||
@@ -3270,6 +3292,7 @@ enum ImDrawListFlags_
|
|||||||
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
|
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
|
||||||
ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
|
ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
|
||||||
ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
|
ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
|
||||||
|
ImDrawListFlags_TextNoPixelSnap = 1 << 4, // Disable automatically snapping AddText() calls to pixel boundaries.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Draw command list
|
// Draw command list
|
||||||
@@ -3421,8 +3444,8 @@ struct ImDrawList
|
|||||||
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
|
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
|
||||||
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
|
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
|
||||||
#else
|
#else
|
||||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
||||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
|
void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
|
||||||
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
||||||
#endif
|
#endif
|
||||||
//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)
|
//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)
|
||||||
@@ -3503,7 +3526,7 @@ enum ImTextureStatus
|
|||||||
// You may use ImTextureData::Updates[] for the list, or ImTextureData::UpdateBox for a single bounding box.
|
// You may use ImTextureData::Updates[] for the list, or ImTextureData::UpdateBox for a single bounding box.
|
||||||
struct ImTextureRect
|
struct ImTextureRect
|
||||||
{
|
{
|
||||||
unsigned short x, y; // Upper-left coordinates of rectangle to update
|
unsigned short x, y; // Upper-left coordinates of rectangle to update, within the parent Pixels[] array.
|
||||||
unsigned short w, h; // Size of rectangle to update (in pixels)
|
unsigned short w, h; // Size of rectangle to update (in pixels)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3525,7 +3548,7 @@ struct ImTextureData
|
|||||||
int Width; // w r // Texture width
|
int Width; // w r // Texture width
|
||||||
int Height; // w r // Texture height
|
int Height; // w r // Texture height
|
||||||
int BytesPerPixel; // w r // 4 or 1
|
int BytesPerPixel; // w r // 4 or 1
|
||||||
unsigned char* Pixels; // w r // Pointer to buffer holding 'Width*Height' pixels and 'Width*Height*BytesPerPixels' bytes.
|
unsigned char* Pixels; // w r // Pointer to whole texture buffer holding 'Width*Height' pixels and 'Width*Height*BytesPerPixels' bytes.
|
||||||
ImTextureRect UsedRect; // w r // Bounding box encompassing all past and queued Updates[].
|
ImTextureRect UsedRect; // w r // Bounding box encompassing all past and queued Updates[].
|
||||||
ImTextureRect UpdateRect; // w r // Bounding box encompassing all queued Updates[].
|
ImTextureRect UpdateRect; // w r // Bounding box encompassing all queued Updates[].
|
||||||
ImVector<ImTextureRect> Updates; // w r // Array of individual updates.
|
ImVector<ImTextureRect> Updates; // w r // Array of individual updates.
|
||||||
@@ -3535,7 +3558,7 @@ struct ImTextureData
|
|||||||
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
|
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()?
|
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear()/ClearFonts()?
|
||||||
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
|
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
|
||||||
~ImTextureData() { DestroyPixels(); }
|
~ImTextureData() { DestroyPixels(); }
|
||||||
IMGUI_API void Create(ImTextureFormat format, int w, int h);
|
IMGUI_API void Create(ImTextureFormat format, int w, int h);
|
||||||
@@ -3689,14 +3712,16 @@ struct ImFontAtlas
|
|||||||
IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
|
IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
|
||||||
IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
|
IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
|
||||||
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
|
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
|
||||||
IMGUI_API void RemoveFont(ImFont* font);
|
IMGUI_API void RemoveFont(ImFont* font); // Remove a font
|
||||||
|
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
|
||||||
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
|
|
||||||
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards!
|
|
||||||
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
|
|
||||||
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
|
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
|
||||||
|
|
||||||
// As we are transitioning toward a new font system, we expect to obsolete those soon:
|
// Clearing the atlas/fonts has little use nowadays, unless you want to batch remove all fonts.
|
||||||
|
// - Since 1.92, you can call ClearFonts() mid-frame, if you load new fonts afterwards.
|
||||||
|
// - As we are transitioning toward our new font system the semantic for those functions gets increasingly misleading and are often a source of issues.
|
||||||
|
// TL;DR; most likely, don't use any of those functions. We expect to obsolete/rework them.
|
||||||
|
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
|
||||||
|
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. New fonts and textures will be recreated afterwards.
|
||||||
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
|
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
|
||||||
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
|
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
|
||||||
|
|
||||||
@@ -3915,7 +3940,7 @@ struct ImFont
|
|||||||
IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL);
|
IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL);
|
||||||
IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0);
|
IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0);
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); }
|
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// [Internal] Don't use!
|
// [Internal] Don't use!
|
||||||
@@ -4017,7 +4042,11 @@ struct ImGuiPlatformIO
|
|||||||
|
|
||||||
// Optional: Platform locale
|
// Optional: Platform locale
|
||||||
// [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point
|
// [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point
|
||||||
ImWchar Platform_LocaleDecimalPoint; // '.'
|
ImWchar Platform_LocaleDecimalPoint; // '.'
|
||||||
|
|
||||||
|
// Optional: Platform time/date
|
||||||
|
// This is automatically filled on startup. Used to store a "last used date" in some .ini structures. Facilitate creating tools to clean up old/unused data.
|
||||||
|
int Platform_SessionDate; // Integer storing YYYYMMDD e.g. 20261231 corresponding to the beginning of application session.
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Input - Interface with Renderer Backend
|
// Input - Interface with Renderer Backend
|
||||||
@@ -4073,6 +4102,8 @@ struct ImGuiPlatformImeData
|
|||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
namespace ImGui
|
namespace ImGui
|
||||||
{
|
{
|
||||||
|
// OBSOLETED in 1.92.9 (from July 2026)
|
||||||
|
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // set current options for if you want to select a default format, picker type, etc. User will be able to change those settings, unless you pass the _NoOptions flag to your calls.
|
||||||
// OBSOLETED in 1.92.0 (from June 2025)
|
// OBSOLETED in 1.92.0 (from June 2025)
|
||||||
inline void PushFont(ImFont* font) { PushFont(font, font ? font->LegacySize : 0.0f); }
|
inline void PushFont(ImFont* font) { PushFont(font, font ? font->LegacySize : 0.0f); }
|
||||||
IMGUI_API void SetWindowFontScale(float scale); // Set font scale factor for current window. Prefer using PushFont(NULL, style.FontSizeBase * factor) or use style.FontScaleMain to scale all windows.
|
IMGUI_API void SetWindowFontScale(float scale); // Set font scale factor for current window. Prefer using PushFont(NULL, style.FontSizeBase * factor) or use style.FontScaleMain to scale all windows.
|
||||||
|
|||||||
128
imgui_demo.cpp
128
imgui_demo.cpp
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (demo code)
|
// (demo code)
|
||||||
|
|
||||||
// Help:
|
// Help:
|
||||||
@@ -538,6 +538,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
|||||||
ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
|
ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
|
||||||
ImGui::Text("Also see Style->Rendering for rendering options.");
|
ImGui::Text("Also see Style->Rendering for rendering options.");
|
||||||
|
|
||||||
|
ImGui::SeparatorText("Settings");
|
||||||
|
ImGui::Checkbox("io.ConfigIniSettingsSaveLastUsedDate", &io.ConfigIniSettingsSaveLastUsedDate);
|
||||||
|
|
||||||
// Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
|
// Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
|
||||||
ImGui::SeparatorText("Error Handling");
|
ImGui::SeparatorText("Error Handling");
|
||||||
|
|
||||||
@@ -1331,7 +1334,7 @@ static void DemoWindowWidgetsColorAndPickers()
|
|||||||
ImGui::SameLine(); HelpMarker(
|
ImGui::SameLine(); HelpMarker(
|
||||||
"ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
|
"ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
|
||||||
"but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
|
"but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
|
||||||
"if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
|
"if you don't specify a display mode.\n\nYou can change the defaults using style.ColorEditFlags.");
|
||||||
|
|
||||||
ImGuiColorEditFlags flags = base_flags | color_picker_flags;
|
ImGuiColorEditFlags flags = base_flags | color_picker_flags;
|
||||||
if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
|
if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
|
||||||
@@ -1344,14 +1347,14 @@ static void DemoWindowWidgetsColorAndPickers()
|
|||||||
|
|
||||||
ImGui::Text("Set defaults in code:");
|
ImGui::Text("Set defaults in code:");
|
||||||
ImGui::SameLine(); HelpMarker(
|
ImGui::SameLine(); HelpMarker(
|
||||||
"SetColorEditOptions() is designed to allow you to set boot-time default.\n"
|
"io.ColorEditFlags is designed to allow you to set boot-time default.\n"
|
||||||
"We don't have Push/Pop functions because you can force options on a per-widget basis if needed, "
|
"We don't have Push/Pop functions because you can force options on a per-widget basis if needed, "
|
||||||
"and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid "
|
"and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid "
|
||||||
"encouraging you to persistently save values that aren't forward-compatible.");
|
"encouraging you to persistently save values that aren't forward-compatible.");
|
||||||
if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
|
if (ImGui::Button("Overwrite default: Uint8 + HSV + Hue Bar"))
|
||||||
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
|
ImGui::GetIO().ColorEditFlags = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar;
|
||||||
if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
|
if (ImGui::Button("Overwrite default: Float + HDR + Hue Wheel"))
|
||||||
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
|
ImGui::GetIO().ColorEditFlags = ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel;
|
||||||
|
|
||||||
// Always display a small version of both types of pickers
|
// Always display a small version of both types of pickers
|
||||||
// (that's in order to make it more visible in the demo to people who are skimming quickly through it)
|
// (that's in order to make it more visible in the demo to people who are skimming quickly through it)
|
||||||
@@ -4121,7 +4124,7 @@ static void DemoWindowWidgetsTooltips()
|
|||||||
ImGui::BeginDisabled();
|
ImGui::BeginDisabled();
|
||||||
ImGui::Button("Disabled item", sz);
|
ImGui::Button("Disabled item", sz);
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
|
||||||
ImGui::SetTooltip("I am a a tooltip for a disabled item.");
|
ImGui::SetTooltip("I am a tooltip for a disabled item.");
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
@@ -4138,9 +4141,9 @@ static void DemoWindowWidgetsTreeNodes()
|
|||||||
{
|
{
|
||||||
IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
|
IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
|
||||||
// See see "Examples -> Property Editor" (ShowExampleAppPropertyEditor() function) for a fancier, data-driven tree.
|
// See see "Examples -> Property Editor" (ShowExampleAppPropertyEditor() function) for a fancier, data-driven tree.
|
||||||
if (ImGui::TreeNode("Basic trees"))
|
if (ImGui::TreeNode("Basic Trees"))
|
||||||
{
|
{
|
||||||
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees");
|
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic Trees");
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
// Use SetNextItemOpen() so set the default state of a node to be open. We could
|
// Use SetNextItemOpen() so set the default state of a node to be open. We could
|
||||||
@@ -4164,9 +4167,9 @@ static void DemoWindowWidgetsTreeNodes()
|
|||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::TreeNode("Hierarchy lines"))
|
if (ImGui::TreeNode("Hierarchy Lines"))
|
||||||
{
|
{
|
||||||
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Hierarchy lines");
|
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Hierarchy Lines");
|
||||||
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DefaultOpen;
|
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DefaultOpen;
|
||||||
HelpMarker("Default option for DrawLinesXXX is stored in style.TreeLinesFlags");
|
HelpMarker("Default option for DrawLinesXXX is stored in style.TreeLinesFlags");
|
||||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesNone", &base_flags, ImGuiTreeNodeFlags_DrawLinesNone);
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesNone", &base_flags, ImGuiTreeNodeFlags_DrawLinesNone);
|
||||||
@@ -4203,15 +4206,57 @@ static void DemoWindowWidgetsTreeNodes()
|
|||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
|
if (ImGui::TreeNode("Selectable Nodes"))
|
||||||
{
|
{
|
||||||
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes");
|
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Selectable Nodes");
|
||||||
HelpMarker(
|
HelpMarker(
|
||||||
"This is a more typical looking tree with selectable nodes.\n"
|
"Manually implemented selectable nodes.\n"
|
||||||
"Click to select, Ctrl+Click to toggle, click on arrows or double-click to open.");
|
"Click to select, Ctrl+Click to toggle, click on arrows or double-click to open.\n\n"
|
||||||
|
"You may also use the multi-select API (see 'Demo->Widgets->Selection State & Multi-Select') for more advanced multi-selection features.");
|
||||||
|
|
||||||
|
// Hold in 'selection_mask' a simple representation of what may be user-side selection state.
|
||||||
|
// - You may retain selection state inside or outside your objects in whatever format you see fit.
|
||||||
|
// You may use ImGuiSelectionBasicStorage which is conceptually close to a set<> of identifiers.
|
||||||
|
// - We record which node was clicked and then apply selection at the end of the loop.
|
||||||
|
// - This is a manual and simplified reimplementation of multi-selection, which the full
|
||||||
|
// BeginMultiSelect() API implements better, but which is not trivial to wire for trees.
|
||||||
|
static int selection_mask = 0x00;
|
||||||
|
int node_clicked_idx = -1;
|
||||||
|
for (int node_n = 0; node_n < 6; node_n++)
|
||||||
|
{
|
||||||
|
// Disable the default "open on single-click behavior" + set Selected flag according to our selection.
|
||||||
|
// To alter selection we use if 'IsItemClicked() && !IsItemToggledOpen()', so clicking on an arrow doesn't alter selection.
|
||||||
|
// In a BeginMultiSelect()/EndMultiSelect() we could use IsItemToggledSelection() but here we reimplement and use our own logic.
|
||||||
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||||
|
if (selection_mask & (1 << node_n))
|
||||||
|
flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
|
|
||||||
|
bool is_open = ImGui::TreeNodeEx((void*)(intptr_t)node_n, flags, "Selectable Node %d", node_n);
|
||||||
|
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
|
||||||
|
node_clicked_idx = node_n;
|
||||||
|
if (is_open)
|
||||||
|
{
|
||||||
|
ImGui::BulletText("<Node contents here>");
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node_clicked_idx != -1)
|
||||||
|
{
|
||||||
|
// Update selection state (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
|
||||||
|
if (ImGui::GetIO().KeyCtrl)
|
||||||
|
selection_mask ^= (1 << node_clicked_idx); // Ctrl+Click to toggle
|
||||||
|
else //if (!(selection_mask & (1 << node_clicked_idx))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
|
||||||
|
selection_mask = (1 << node_clicked_idx); // Click to single-select
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::TreeNode("Advanced"))
|
||||||
|
{
|
||||||
|
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced");
|
||||||
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
|
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||||
static bool align_label_with_current_x_position = false;
|
static bool align_label_with_current_x_position = false;
|
||||||
static bool test_drag_and_drop = false;
|
static bool use_drag_and_drop = false;
|
||||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
|
||||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
|
||||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
|
||||||
@@ -4229,44 +4274,30 @@ static void DemoWindowWidgetsTreeNodes()
|
|||||||
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesToNodes", &base_flags, ImGuiTreeNodeFlags_DrawLinesToNodes);
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesToNodes", &base_flags, ImGuiTreeNodeFlags_DrawLinesToNodes);
|
||||||
|
|
||||||
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
|
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
|
||||||
ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
|
ImGui::Checkbox("Make Tree Nodes as drag & drop sources", &use_drag_and_drop);
|
||||||
ImGui::Text("Hello!");
|
|
||||||
if (align_label_with_current_x_position)
|
if (align_label_with_current_x_position)
|
||||||
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
|
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
|
||||||
|
|
||||||
// 'selection_mask' is dumb representation of what may be user-side selection state.
|
for (int node_n = 0; node_n < 6; node_n++)
|
||||||
// You may retain selection state inside or outside your objects in whatever format you see fit.
|
|
||||||
// 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
|
|
||||||
/// of the loop. May be a pointer to your own node type, etc.
|
|
||||||
static int selection_mask = (1 << 2);
|
|
||||||
int node_clicked = -1;
|
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
{
|
{
|
||||||
// Disable the default "open on single-click behavior" + set Selected flag according to our selection.
|
|
||||||
// To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection.
|
|
||||||
ImGuiTreeNodeFlags node_flags = base_flags;
|
ImGuiTreeNodeFlags node_flags = base_flags;
|
||||||
const bool is_selected = (selection_mask & (1 << i)) != 0;
|
if (node_n < 3)
|
||||||
if (is_selected)
|
|
||||||
node_flags |= ImGuiTreeNodeFlags_Selected;
|
|
||||||
if (i < 3)
|
|
||||||
{
|
{
|
||||||
// Items 0..2 are Tree Node
|
// Items 0..2 are Tree Node
|
||||||
bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
|
bool is_open = ImGui::TreeNodeEx((void*)(intptr_t)node_n, node_flags, "Selectable Node %d", node_n);
|
||||||
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
|
if (use_drag_and_drop && ImGui::BeginDragDropSource())
|
||||||
node_clicked = i;
|
|
||||||
if (test_drag_and_drop && ImGui::BeginDragDropSource())
|
|
||||||
{
|
{
|
||||||
ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
|
ImGui::SetDragDropPayload("MY_TREENODE_PAYLOAD_TYPE", NULL, 0);
|
||||||
ImGui::Text("This is a drag and drop source");
|
ImGui::Text("This is a drag and drop source");
|
||||||
ImGui::EndDragDropSource();
|
ImGui::EndDragDropSource();
|
||||||
}
|
}
|
||||||
if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth))
|
if (node_n == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth))
|
||||||
{
|
{
|
||||||
// Item 2 has an additional inline button to help demonstrate SpanLabelWidth.
|
// Item 2 has an additional inline button to help demonstrate SpanLabelWidth.
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::SmallButton("button")) {}
|
if (ImGui::SmallButton("button")) {}
|
||||||
}
|
}
|
||||||
if (node_open)
|
if (is_open)
|
||||||
{
|
{
|
||||||
ImGui::BulletText("Blah blah\nBlah Blah");
|
ImGui::BulletText("Blah blah\nBlah Blah");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -4280,26 +4311,15 @@ static void DemoWindowWidgetsTreeNodes()
|
|||||||
// The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
|
// The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
|
||||||
// use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
|
// use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
|
||||||
node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
|
node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
|
||||||
ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
|
ImGui::TreeNodeEx((void*)(intptr_t)node_n, node_flags, "Selectable Leaf %d", node_n);
|
||||||
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
|
if (use_drag_and_drop && ImGui::BeginDragDropSource())
|
||||||
node_clicked = i;
|
|
||||||
if (test_drag_and_drop && ImGui::BeginDragDropSource())
|
|
||||||
{
|
{
|
||||||
ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
|
ImGui::SetDragDropPayload("MY_TREENODE_PAYLOAD_TYPE", NULL, 0);
|
||||||
ImGui::Text("This is a drag and drop source");
|
ImGui::Text("This is a drag and drop source");
|
||||||
ImGui::EndDragDropSource();
|
ImGui::EndDragDropSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node_clicked != -1)
|
|
||||||
{
|
|
||||||
// Update selection state
|
|
||||||
// (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
|
|
||||||
if (ImGui::GetIO().KeyCtrl)
|
|
||||||
selection_mask ^= (1 << node_clicked); // Ctrl+Click to toggle
|
|
||||||
else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
|
|
||||||
selection_mask = (1 << node_clicked); // Click to single-select
|
|
||||||
}
|
|
||||||
if (align_label_with_current_x_position)
|
if (align_label_with_current_x_position)
|
||||||
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
|
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
@@ -8539,6 +8559,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
|||||||
SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
|
SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
|
||||||
SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
|
SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
|
||||||
SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
|
SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
|
||||||
|
SliderFloat("MenuItemRounding", &style.MenuItemRounding, 0.0f, 12.0f, "%.0f");
|
||||||
|
// NB: SelectableRounding is intentionally NOT made visible here. We don't want to encourage people using that.
|
||||||
|
|
||||||
SeparatorText("Scrollbar");
|
SeparatorText("Scrollbar");
|
||||||
SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
|
SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
|
||||||
|
|||||||
243
imgui_draw.cpp
243
imgui_draw.cpp
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (drawing and font code)
|
// (drawing and font code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -402,7 +402,6 @@ ImDrawListSharedData::ImDrawListSharedData()
|
|||||||
const float a = ((float)i * 2 * IM_PI) / (float)IM_COUNTOF(ArcFastVtx);
|
const float a = ((float)i * 2 * IM_PI) / (float)IM_COUNTOF(ArcFastVtx);
|
||||||
ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a));
|
ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a));
|
||||||
}
|
}
|
||||||
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImDrawListSharedData::~ImDrawListSharedData()
|
ImDrawListSharedData::~ImDrawListSharedData()
|
||||||
@@ -412,17 +411,17 @@ ImDrawListSharedData::~ImDrawListSharedData()
|
|||||||
|
|
||||||
void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
|
void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
|
||||||
{
|
{
|
||||||
if (CircleSegmentMaxError == max_error)
|
if (CircleTessellationMaxError == max_error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IM_ASSERT(max_error > 0.0f);
|
IM_ASSERT(max_error > 0.0f);
|
||||||
CircleSegmentMaxError = max_error;
|
CircleTessellationMaxError = max_error;
|
||||||
for (int i = 0; i < IM_COUNTOF(CircleSegmentCounts); i++)
|
for (int i = 0; i < IM_COUNTOF(CircleSegmentCounts); i++)
|
||||||
{
|
{
|
||||||
const float radius = (float)i;
|
const float radius = (float)i;
|
||||||
CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX);
|
CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleTessellationMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX);
|
||||||
}
|
}
|
||||||
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
|
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleTessellationMaxError);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImDrawList::ImDrawList(ImDrawListSharedData* shared_data)
|
ImDrawList::ImDrawList(ImDrawListSharedData* shared_data)
|
||||||
@@ -656,11 +655,11 @@ void ImDrawList::_OnChangedVtxOffset()
|
|||||||
int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
|
int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
|
||||||
{
|
{
|
||||||
// Automatic segment count
|
// Automatic segment count
|
||||||
const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy
|
const int radius_idx = (int)(radius + 0.999f); // ceil to never reduce accuracy
|
||||||
if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts))
|
if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts))
|
||||||
return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
|
return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
|
||||||
else
|
else
|
||||||
return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
|
return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleTessellationMaxError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
// 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)
|
||||||
@@ -823,7 +822,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
|
|||||||
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
|
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
|
||||||
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
|
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
|
||||||
const bool thick_line = (thickness > _FringeScale);
|
const bool thick_line = (thickness > _FringeScale);
|
||||||
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?");
|
|
||||||
|
// If this assert triggers on legacy code:
|
||||||
|
// - 1.92.8 (2025/05): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
|
||||||
|
// - 1.92.8 (2025/05): changed value of ImDrawList_Closed which was previously guaranteed to be == 1. Hardcoded use of 1 or true should be replaced.
|
||||||
|
// Read more details near AddRect() + see "API BREAKING CHANGES" section for 1.82, 1.90 and 1.92.8.
|
||||||
|
IM_ASSERT_USER_ERROR_RET((flags & ImDrawFlags_InvalidMask_) == 0, "Incorrect parameter. Did you swap 'thickness' and 'flags'?");
|
||||||
|
|
||||||
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
||||||
{
|
{
|
||||||
@@ -1475,27 +1479,24 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
|
|||||||
{
|
{
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
if ((col & IM_COL32_A_MASK) == 0)
|
||||||
return;
|
return;
|
||||||
PathLineTo(p1 + ImVec2(0.5f, 0.5f));
|
const ImVec2 points[2] = { ImVec2(p1.x + 0.5f, p1.y + 0.5f), ImVec2(p2.x + 0.5f, p2.y + 0.5f) };
|
||||||
PathLineTo(p2 + ImVec2(0.5f, 0.5f));
|
AddPolyline(points, 2, col, thickness);
|
||||||
PathStroke(col, thickness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness)
|
void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness)
|
||||||
{
|
{
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
if ((col & IM_COL32_A_MASK) == 0)
|
||||||
return;
|
return;
|
||||||
PathLineTo(ImVec2(min_x + 0.5f, y + 0.5f)); // Same as AddLine() above.
|
const ImVec2 points[2] = { ImVec2(min_x + 0.5f, y + 0.5f), ImVec2(max_x + 0.5f, y + 0.5f) }; // Same as AddLine() above.
|
||||||
PathLineTo(ImVec2(max_x + 0.5f, y + 0.5f));
|
AddPolyline(points, 2, col, thickness);
|
||||||
PathStroke(col, thickness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness)
|
void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness)
|
||||||
{
|
{
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
if ((col & IM_COL32_A_MASK) == 0)
|
||||||
return;
|
return;
|
||||||
PathLineTo(ImVec2(x + 0.5f, min_y + 0.5f)); // Same as AddLine() above.
|
const ImVec2 points[2] = { ImVec2(x + 0.5f, min_y + 0.5f), ImVec2(x + 0.5f, max_y + 0.5f) }; // Same as AddLine() above.
|
||||||
PathLineTo(ImVec2(x + 0.5f, max_y + 0.5f));
|
AddPolyline(points, 2, col, thickness);
|
||||||
PathStroke(col, thickness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// p_min = upper-left, p_max = lower-right
|
// p_min = upper-left, p_max = lower-right
|
||||||
@@ -1503,14 +1504,15 @@ void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float th
|
|||||||
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags)
|
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags)
|
||||||
{
|
{
|
||||||
// If this assert triggers on legacy code:
|
// If this assert triggers on legacy code:
|
||||||
// - 1.92.8 (2025/04): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
|
// - 1.92.8 (2025/05): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
|
||||||
|
// - 1.92.8 (2025/05): changed value of ImDrawList_Closed which was previously guaranteed to be == 1. Hardcoded use of 1 or true should be replaced.
|
||||||
// - 1.82.0 (2021/03): changed ImDrawCornerFlags to ImDrawFlags_RoundCornersXXX values.
|
// - 1.82.0 (2021/03): changed ImDrawCornerFlags to ImDrawFlags_RoundCornersXXX values.
|
||||||
// If you used hard-coded 1 to 15 or ~0 in flags to configure corner rounding use the new flags!
|
// If you used hard-coded 1 to 15 or ~0 in flags to configure corner rounding use the new flags!
|
||||||
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
|
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
|
||||||
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
|
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
|
||||||
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'.
|
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'.
|
||||||
// See "API BREAKING CHANGES" section for 1.82 and 1.90.
|
// See "API BREAKING CHANGES" section for 1.82, 1.90 and 1.92.8.
|
||||||
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
|
IM_ASSERT_USER_ERROR_RET((flags & ImDrawFlags_InvalidMask_) == 0, "Incorrect parameter. Did you swap 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
|
||||||
|
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
if ((col & IM_COL32_A_MASK) == 0)
|
||||||
return;
|
return;
|
||||||
@@ -2560,8 +2562,6 @@ void ImTextureData::DestroyPixels()
|
|||||||
// - ImFontAtlasBuildPreloadAllGlyphRanges()
|
// - ImFontAtlasBuildPreloadAllGlyphRanges()
|
||||||
// - ImFontAtlasBuildUpdatePointers()
|
// - ImFontAtlasBuildUpdatePointers()
|
||||||
// - ImFontAtlasBuildRenderBitmapFromString()
|
// - ImFontAtlasBuildRenderBitmapFromString()
|
||||||
// - ImFontAtlasBuildUpdateBasicTexData()
|
|
||||||
// - ImFontAtlasBuildUpdateLinesTexData()
|
|
||||||
// - ImFontAtlasBuildAddFont()
|
// - ImFontAtlasBuildAddFont()
|
||||||
// - ImFontAtlasBuildSetupFontBakedEllipsis()
|
// - ImFontAtlasBuildSetupFontBakedEllipsis()
|
||||||
// - ImFontAtlasBuildSetupFontBakedBlanks()
|
// - ImFontAtlasBuildSetupFontBakedBlanks()
|
||||||
@@ -2578,13 +2578,14 @@ void ImTextureData::DestroyPixels()
|
|||||||
// - ImFontAtlasUpdateDrawListsSharedData()
|
// - ImFontAtlasUpdateDrawListsSharedData()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// - ImFontAtlasBuildSetTexture()
|
// - ImFontAtlasBuildSetTexture()
|
||||||
// - ImFontAtlasBuildAddTexture()
|
// - ImFontAtlasBuildUpdateTexData()
|
||||||
// - ImFontAtlasBuildMakeSpace()
|
// - ImFontAtlasTextureAdd()
|
||||||
// - ImFontAtlasBuildRepackTexture()
|
// - ImFontAtlasTextureRepack()
|
||||||
// - ImFontAtlasBuildGrowTexture()
|
// - ImFontAtlasTextureGrow()
|
||||||
// - ImFontAtlasBuildRepackOrGrowTexture()
|
// - ImFontAtlasTextureMakeSpace()
|
||||||
// - ImFontAtlasBuildGetTextureSizeEstimate()
|
// - ImFontAtlasTextureGetSizeEstimate()
|
||||||
// - ImFontAtlasBuildCompactTexture()
|
// - ImFontAtlasBuildClear()
|
||||||
|
// - ImFontAtlasTextureCompact()
|
||||||
// - ImFontAtlasBuildInit()
|
// - ImFontAtlasBuildInit()
|
||||||
// - ImFontAtlasBuildDestroy()
|
// - ImFontAtlasBuildDestroy()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -2689,6 +2690,7 @@ ImFontAtlas::~ImFontAtlas()
|
|||||||
// Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates.
|
// Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates.
|
||||||
void ImFontAtlas::Clear()
|
void ImFontAtlas::Clear()
|
||||||
{
|
{
|
||||||
|
IMGUI_DEBUG_LOG_FONT("[font] ImFontAtlas::Clear()\n");
|
||||||
bool backup_renderer_has_textures = RendererHasTextures;
|
bool backup_renderer_has_textures = RendererHasTextures;
|
||||||
RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't.
|
RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't.
|
||||||
ClearFonts();
|
ClearFonts();
|
||||||
@@ -2699,6 +2701,7 @@ void ImFontAtlas::Clear()
|
|||||||
void ImFontAtlas::ClearFonts()
|
void ImFontAtlas::ClearFonts()
|
||||||
{
|
{
|
||||||
// FIXME-NEWATLAS: Illegal to remove currently bound font.
|
// FIXME-NEWATLAS: Illegal to remove currently bound font.
|
||||||
|
IMGUI_DEBUG_LOG_FONT("[font] ImFontAtlas::ClearFonts()\n");
|
||||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||||
for (ImFont* font : Fonts)
|
for (ImFont* font : Fonts)
|
||||||
ImFontAtlasBuildNotifySetFont(this, font, NULL);
|
ImFontAtlasBuildNotifySetFont(this, font, NULL);
|
||||||
@@ -2774,6 +2777,28 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
|
|||||||
IM_ASSERT(atlas->Builder == NULL || atlas->Builder->FrameCount < frame_count); // Protection against being called twice.
|
IM_ASSERT(atlas->Builder == NULL || atlas->Builder->FrameCount < frame_count); // Protection against being called twice.
|
||||||
atlas->RendererHasTextures = renderer_has_textures;
|
atlas->RendererHasTextures = renderer_has_textures;
|
||||||
|
|
||||||
|
// Update texture status and discard old textures.
|
||||||
|
// (we do this first thing to handle an edge case: if user mistakenly calls ClearFonts()+SetStatus(OK) during
|
||||||
|
// rendering, it would ImFontAtlasBuildMain() rebuilding before tex->Updates[] gets a chance to be cleared)
|
||||||
|
// (if somehow we need to move this back lower in the function, we could manually call the code to clear Updates[]).
|
||||||
|
for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++)
|
||||||
|
{
|
||||||
|
// Update and remove if requested
|
||||||
|
ImTextureData* tex = atlas->TexList[tex_n];
|
||||||
|
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
|
||||||
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
|
||||||
|
|
||||||
|
bool remove_from_list = ImTextureDataUpdateNewFrame(tex);
|
||||||
|
if (remove_from_list)
|
||||||
|
{
|
||||||
|
IM_ASSERT(atlas->TexData != tex);
|
||||||
|
tex->DestroyPixels();
|
||||||
|
IM_DELETE(tex);
|
||||||
|
atlas->TexList.erase(atlas->TexList.begin() + tex_n);
|
||||||
|
tex_n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check that font atlas was built or backend support texture reload in which case we can build now
|
// Check that font atlas was built or backend support texture reload in which case we can build now
|
||||||
if (atlas->RendererHasTextures)
|
if (atlas->RendererHasTextures)
|
||||||
{
|
{
|
||||||
@@ -2813,61 +2838,49 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
|
|||||||
builder->BakedPool.Size -= builder->BakedDiscardedCount;
|
builder->BakedPool.Size -= builder->BakedDiscardedCount;
|
||||||
builder->BakedDiscardedCount = 0;
|
builder->BakedDiscardedCount = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update texture status
|
bool ImTextureDataUpdateNewFrame(ImTextureData* tex)
|
||||||
for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++)
|
{
|
||||||
|
bool remove_from_list = false;
|
||||||
|
if (tex->Status == ImTextureStatus_OK)
|
||||||
{
|
{
|
||||||
ImTextureData* tex = atlas->TexList[tex_n];
|
tex->Updates.resize(0);
|
||||||
bool remove_from_list = false;
|
tex->UpdateRect.x = tex->UpdateRect.y = (unsigned short)~0;
|
||||||
if (tex->Status == ImTextureStatus_OK)
|
tex->UpdateRect.w = tex->UpdateRect.h = 0;
|
||||||
{
|
|
||||||
tex->Updates.resize(0);
|
|
||||||
tex->UpdateRect.x = tex->UpdateRect.y = (unsigned short)~0;
|
|
||||||
tex->UpdateRect.w = tex->UpdateRect.h = 0;
|
|
||||||
}
|
|
||||||
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
|
|
||||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
|
|
||||||
|
|
||||||
// Request destroy
|
|
||||||
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
|
|
||||||
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
|
|
||||||
if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_Destroyed && tex->Status != ImTextureStatus_WantDestroy)
|
|
||||||
{
|
|
||||||
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
|
|
||||||
tex->Status = ImTextureStatus_WantDestroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a texture has never reached the backend, they don't need to know about it.
|
|
||||||
// (note: backends between 1.92.0 and 1.92.4 could set an already destroyed texture to ImTextureStatus_WantDestroy
|
|
||||||
// when invalidating graphics objects twice, which would previously remove it from the list and crash.)
|
|
||||||
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
|
|
||||||
tex->Status = ImTextureStatus_Destroyed;
|
|
||||||
|
|
||||||
// Process texture being destroyed
|
|
||||||
if (tex->Status == ImTextureStatus_Destroyed)
|
|
||||||
{
|
|
||||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
|
|
||||||
if (tex->WantDestroyNextFrame)
|
|
||||||
remove_from_list = true; // Destroy was scheduled by us
|
|
||||||
else
|
|
||||||
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend: recreate it (e.g. freed resources mid-run)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
|
|
||||||
// We allow the texture staying in _WantDestroy state and increment a counter which the backend can use to take its decision.
|
|
||||||
if (tex->Status == ImTextureStatus_WantDestroy)
|
|
||||||
tex->UnusedFrames++;
|
|
||||||
|
|
||||||
// Destroy and remove
|
|
||||||
if (remove_from_list)
|
|
||||||
{
|
|
||||||
IM_ASSERT(atlas->TexData != tex);
|
|
||||||
tex->DestroyPixels();
|
|
||||||
IM_DELETE(tex);
|
|
||||||
atlas->TexList.erase(atlas->TexList.begin() + tex_n);
|
|
||||||
tex_n--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Request destroy
|
||||||
|
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
|
||||||
|
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
|
||||||
|
if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_Destroyed && tex->Status != ImTextureStatus_WantDestroy)
|
||||||
|
{
|
||||||
|
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
|
||||||
|
tex->Status = ImTextureStatus_WantDestroy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a texture has never reached the backend, they don't need to know about it.
|
||||||
|
// (note: backends between 1.92.0 and 1.92.4 could set an already destroyed texture to ImTextureStatus_WantDestroy
|
||||||
|
// when invalidating graphics objects twice, which would previously remove it from the list and crash.)
|
||||||
|
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
|
||||||
|
tex->Status = ImTextureStatus_Destroyed;
|
||||||
|
|
||||||
|
// Process texture being destroyed
|
||||||
|
if (tex->Status == ImTextureStatus_Destroyed)
|
||||||
|
{
|
||||||
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
|
||||||
|
if (tex->WantDestroyNextFrame)
|
||||||
|
remove_from_list = true; // Destroy was scheduled by us
|
||||||
|
else
|
||||||
|
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend: recreate it (e.g. freed resources mid-run)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
|
||||||
|
// We allow the texture staying in _WantDestroy state and increment a counter which the backend can use to take its decision.
|
||||||
|
if (tex->Status == ImTextureStatus_WantDestroy)
|
||||||
|
tex->UnusedFrames++;
|
||||||
|
|
||||||
|
return remove_from_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImFontAtlasTextureBlockConvert(const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch, unsigned char* dst_pixels, ImTextureFormat dst_fmt, int dst_pitch, int w, int h)
|
void ImFontAtlasTextureBlockConvert(const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch, unsigned char* dst_pixels, ImTextureFormat dst_fmt, int dst_pitch, int w, int h)
|
||||||
@@ -3143,8 +3156,10 @@ static void Decode85(const unsigned char* src, unsigned char* dst)
|
|||||||
dst += 4;
|
dst += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef IMGUI_DISABLE_DEFAULT_FONT
|
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
|
||||||
static const char* GetDefaultCompressedFontDataProggyClean(int* out_size);
|
static const char* GetDefaultCompressedFontDataProggyClean(int* out_size);
|
||||||
|
#endif
|
||||||
|
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
|
||||||
static const char* GetDefaultCompressedFontDataProggyForever(int* out_size);
|
static const char* GetDefaultCompressedFontDataProggyForever(int* out_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3169,7 +3184,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg)
|
|||||||
// If you want a similar font which may be better scaled, consider using AddFontDefaultVector().
|
// If you want a similar font which may be better scaled, consider using AddFontDefaultVector().
|
||||||
ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
|
ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
|
||||||
{
|
{
|
||||||
#ifndef IMGUI_DISABLE_DEFAULT_FONT
|
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
|
||||||
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
||||||
if (!font_cfg_template)
|
if (!font_cfg_template)
|
||||||
font_cfg.PixelSnapH = true; // Prevents sub-integer scaling factors at lower-level layers.
|
font_cfg.PixelSnapH = true; // Prevents sub-integer scaling factors at lower-level layers.
|
||||||
@@ -3190,14 +3205,14 @@ ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
|
|||||||
IM_ASSERT(0 && "Function is disabled in this build.");
|
IM_ASSERT(0 && "Function is disabled in this build.");
|
||||||
IM_UNUSED(font_cfg_template);
|
IM_UNUSED(font_cfg_template);
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a minimal version of ProggyForever, designed to match our good old ProggyClean, but nicely scalable.
|
// Load a minimal version of ProggyForever, designed to match our good old ProggyClean, but nicely scalable.
|
||||||
// (See build script in https://github.com/ocornut/proggyforever for details)
|
// (See build script in https://github.com/ocornut/proggyforever for details)
|
||||||
ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
|
ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
|
||||||
{
|
{
|
||||||
#ifndef IMGUI_DISABLE_DEFAULT_FONT
|
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
|
||||||
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
||||||
if (!font_cfg_template)
|
if (!font_cfg_template)
|
||||||
font_cfg.PixelSnapH = true; // Precisely match ProggyClean, but prevents sub-integer scaling factors at lower-level layers.
|
font_cfg.PixelSnapH = true; // Precisely match ProggyClean, but prevents sub-integer scaling factors at lower-level layers.
|
||||||
@@ -3218,7 +3233,7 @@ ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
|
|||||||
IM_ASSERT(0 && "Function is disabled in this build.");
|
IM_ASSERT(0 && "Function is disabled in this build.");
|
||||||
IM_UNUSED(font_cfg_template);
|
IM_UNUSED(font_cfg_template);
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
|
ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
|
||||||
@@ -3574,7 +3589,7 @@ void ImFontAtlasBuildRenderBitmapFromString(ImFontAtlas* atlas, int x, int y, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImFontAtlasBuildUpdateBasicTexData(ImFontAtlas* atlas)
|
static void ImFontAtlasBuildUpdateTexDataBasic(ImFontAtlas* atlas)
|
||||||
{
|
{
|
||||||
// Pack and store identifier so we can refresh UV coordinates on texture resize.
|
// Pack and store identifier so we can refresh UV coordinates on texture resize.
|
||||||
// FIXME-NEWATLAS: User/custom rects where user code wants to store UV coordinates will need to do the same thing.
|
// FIXME-NEWATLAS: User/custom rects where user code wants to store UV coordinates will need to do the same thing.
|
||||||
@@ -3608,7 +3623,7 @@ static void ImFontAtlasBuildUpdateBasicTexData(ImFontAtlas* atlas)
|
|||||||
atlas->TexUvWhitePixel = ImVec2((r.x + 0.5f) * atlas->TexUvScale.x, (r.y + 0.5f) * atlas->TexUvScale.y);
|
atlas->TexUvWhitePixel = ImVec2((r.x + 0.5f) * atlas->TexUvScale.x, (r.y + 0.5f) * atlas->TexUvScale.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImFontAtlasBuildUpdateLinesTexData(ImFontAtlas* atlas)
|
static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
|
||||||
{
|
{
|
||||||
if (atlas->Flags & ImFontAtlasFlags_NoBakedLines)
|
if (atlas->Flags & ImFontAtlasFlags_NoBakedLines)
|
||||||
return;
|
return;
|
||||||
@@ -4057,6 +4072,12 @@ static void ImFontAtlasBuildSetTexture(ImFontAtlas* atlas, ImTextureData* tex)
|
|||||||
ImFontAtlasUpdateDrawListsTextures(atlas, old_tex_ref, atlas->TexRef);
|
ImFontAtlasUpdateDrawListsTextures(atlas, old_tex_ref, atlas->TexRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ImFontAtlasBuildUpdateTexData(ImFontAtlas* atlas)
|
||||||
|
{
|
||||||
|
ImFontAtlasBuildUpdateTexDataBasic(atlas);
|
||||||
|
ImFontAtlasBuildUpdateTexDataLines(atlas);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new texture, discard previous one
|
// Create a new texture, discard previous one
|
||||||
ImTextureData* ImFontAtlasTextureAdd(ImFontAtlas* atlas, int w, int h)
|
ImTextureData* ImFontAtlasTextureAdd(ImFontAtlas* atlas, int w, int h)
|
||||||
{
|
{
|
||||||
@@ -4171,8 +4192,7 @@ void ImFontAtlasTextureRepack(ImFontAtlas* atlas, int w, int h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update other cached UV
|
// Update other cached UV
|
||||||
ImFontAtlasBuildUpdateLinesTexData(atlas);
|
ImFontAtlasBuildUpdateTexData(atlas);
|
||||||
ImFontAtlasBuildUpdateBasicTexData(atlas);
|
|
||||||
|
|
||||||
builder->LockDisableResize = false;
|
builder->LockDisableResize = false;
|
||||||
ImFontAtlasUpdateDrawListsSharedData(atlas);
|
ImFontAtlasUpdateDrawListsSharedData(atlas);
|
||||||
@@ -4321,8 +4341,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
|
|||||||
ImFontAtlasPackInit(atlas);
|
ImFontAtlasPackInit(atlas);
|
||||||
|
|
||||||
// Add required texture data
|
// Add required texture data
|
||||||
ImFontAtlasBuildUpdateLinesTexData(atlas);
|
ImFontAtlasBuildUpdateTexData(atlas);
|
||||||
ImFontAtlasBuildUpdateBasicTexData(atlas);
|
|
||||||
|
|
||||||
// Register fonts
|
// Register fonts
|
||||||
ImFontAtlasBuildUpdatePointers(atlas);
|
ImFontAtlasBuildUpdatePointers(atlas);
|
||||||
@@ -4351,6 +4370,8 @@ void ImFontAtlasBuildDestroy(ImFontAtlas* atlas)
|
|||||||
atlas->Builder = NULL;
|
atlas->Builder = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ImFontAtlasPackInit(ImFontAtlas * atlas)
|
void ImFontAtlasPackInit(ImFontAtlas * atlas)
|
||||||
{
|
{
|
||||||
ImTextureData* tex = atlas->TexData;
|
ImTextureData* tex = atlas->TexData;
|
||||||
@@ -5747,8 +5768,13 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im
|
|||||||
if (glyph->Colored)
|
if (glyph->Colored)
|
||||||
col |= ~IM_COL32_A_MASK;
|
col |= ~IM_COL32_A_MASK;
|
||||||
float scale = (size >= 0.0f) ? (size / baked->Size) : 1.0f;
|
float scale = (size >= 0.0f) ? (size / baked->Size) : 1.0f;
|
||||||
float x = IM_TRUNC(pos.x);
|
float x = pos.x;
|
||||||
float y = IM_TRUNC(pos.y);
|
float y = pos.y;
|
||||||
|
if ((draw_list->Flags & ImDrawListFlags_TextNoPixelSnap) == 0)
|
||||||
|
{
|
||||||
|
x = IM_TRUNC(x);
|
||||||
|
y = IM_TRUNC(y);
|
||||||
|
}
|
||||||
|
|
||||||
float x1 = x + glyph->X0 * scale;
|
float x1 = x + glyph->X0 * scale;
|
||||||
float x2 = x + glyph->X1 * scale;
|
float x2 = x + glyph->X1 * scale;
|
||||||
@@ -5780,12 +5806,17 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im
|
|||||||
// DO NOT CALL DIRECTLY THIS WILL CHANGE WILDLY IN 2026. Use ImDrawList::AddText().
|
// DO NOT CALL DIRECTLY THIS WILL CHANGE WILDLY IN 2026. Use ImDrawList::AddText().
|
||||||
void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags)
|
void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags)
|
||||||
{
|
{
|
||||||
// Align to be pixel perfect
|
|
||||||
begin:
|
begin:
|
||||||
float x = IM_TRUNC(pos.x);
|
// Align to be pixel perfect
|
||||||
float y = IM_TRUNC(pos.y);
|
float x = pos.x;
|
||||||
|
float y = pos.y;
|
||||||
if (y > clip_rect.w)
|
if (y > clip_rect.w)
|
||||||
return;
|
return;
|
||||||
|
if ((draw_list->Flags & ImDrawListFlags_TextNoPixelSnap) == 0)
|
||||||
|
{
|
||||||
|
x = IM_TRUNC(x);
|
||||||
|
y = IM_TRUNC(y);
|
||||||
|
}
|
||||||
|
|
||||||
if (!text_end)
|
if (!text_end)
|
||||||
text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
|
text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
|
||||||
@@ -6171,8 +6202,8 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
|
|||||||
flags = ImDrawFlags_RoundCornersDefault_;
|
flags = ImDrawFlags_RoundCornersDefault_;
|
||||||
if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
|
if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
|
||||||
{
|
{
|
||||||
ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
|
ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
|
||||||
ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
|
ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
|
||||||
draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
|
draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
|
||||||
|
|
||||||
int yi = 0;
|
int yi = 0;
|
||||||
@@ -6181,12 +6212,12 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
|
|||||||
float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);
|
float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);
|
||||||
if (y2 <= y1)
|
if (y2 <= y1)
|
||||||
continue;
|
continue;
|
||||||
for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
|
for (float x = p_min.x + grid_off.x + ((yi ^ 1) & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
|
||||||
{
|
{
|
||||||
float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
|
float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
|
||||||
if (x2 <= x1)
|
if (x2 <= x1)
|
||||||
continue;
|
continue;
|
||||||
ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone;
|
ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; // FIXME: Could use CalcRoundingFlagsForRectInRect()
|
||||||
if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; }
|
if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; }
|
||||||
if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; }
|
if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; }
|
||||||
|
|
||||||
@@ -6328,7 +6359,7 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
|
|||||||
// Download and more information at https://github.com/bluescan/proggyfonts
|
// Download and more information at https://github.com/bluescan/proggyfonts
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_DEFAULT_FONT
|
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
|
||||||
|
|
||||||
// File: 'ProggyClean.ttf' (41208 bytes)
|
// File: 'ProggyClean.ttf' (41208 bytes)
|
||||||
// Exported using binary_to_compressed_c.exe -u8 "ProggyClean.ttf" proggy_clean_ttf
|
// Exported using binary_to_compressed_c.exe -u8 "ProggyClean.ttf" proggy_clean_ttf
|
||||||
@@ -6508,6 +6539,7 @@ static const char* GetDefaultCompressedFontDataProggyClean(int* out_size)
|
|||||||
*out_size = proggy_clean_ttf_compressed_size;
|
*out_size = proggy_clean_ttf_compressed_size;
|
||||||
return (const char*)proggy_clean_ttf_compressed_data;
|
return (const char*)proggy_clean_ttf_compressed_data;
|
||||||
}
|
}
|
||||||
|
#endif // #if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Default font data (ProggyForever-Regular-minimal.ttf)
|
// [SECTION] Default font data (ProggyForever-Regular-minimal.ttf)
|
||||||
@@ -6516,6 +6548,8 @@ static const char* GetDefaultCompressedFontDataProggyClean(int* out_size)
|
|||||||
// MIT license / Copyright (c) 2026 Disco Hello, Copyright (c) 2019,2023 Tristan Grimmer
|
// MIT license / Copyright (c) 2026 Disco Hello, Copyright (c) 2019,2023 Tristan Grimmer
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
|
||||||
|
|
||||||
// File: 'output/ProggyForever-Regular-minimal.ttf' (18556 bytes)
|
// File: 'output/ProggyForever-Regular-minimal.ttf' (18556 bytes)
|
||||||
// Exported using binary_to_compressed_c.exe -u8 "output/ProggyForever-Regular-minimal.ttf" proggy_forever_minimal_ttf
|
// Exported using binary_to_compressed_c.exe -u8 "output/ProggyForever-Regular-minimal.ttf" proggy_forever_minimal_ttf
|
||||||
static const unsigned int proggy_forever_minimal_ttf_compressed_size = 14562;
|
static const unsigned int proggy_forever_minimal_ttf_compressed_size = 14562;
|
||||||
@@ -6770,7 +6804,6 @@ static const char* GetDefaultCompressedFontDataProggyForever(int* out_size)
|
|||||||
*out_size = proggy_forever_minimal_ttf_compressed_size;
|
*out_size = proggy_forever_minimal_ttf_compressed_size;
|
||||||
return (const char*)proggy_forever_minimal_ttf_compressed_data;
|
return (const char*)proggy_forever_minimal_ttf_compressed_data;
|
||||||
}
|
}
|
||||||
|
#endif // #if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
|
||||||
#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
|
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
|
|||||||
295
imgui_internal.h
295
imgui_internal.h
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (internal structures/api)
|
// (internal structures/api)
|
||||||
|
|
||||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||||
@@ -35,7 +35,7 @@ Index of this file:
|
|||||||
// [SECTION] ImGuiContext (main imgui context)
|
// [SECTION] ImGuiContext (main imgui context)
|
||||||
// [SECTION] ImGuiWindowTempData, ImGuiWindow
|
// [SECTION] ImGuiWindowTempData, ImGuiWindow
|
||||||
// [SECTION] Tab bar, Tab item support
|
// [SECTION] Tab bar, Tab item support
|
||||||
// [SECTION] Table support
|
// [SECTION] Table support + internal API
|
||||||
// [SECTION] ImGui internal API
|
// [SECTION] ImGui internal API
|
||||||
// [SECTION] ImFontLoader
|
// [SECTION] ImFontLoader
|
||||||
// [SECTION] ImFontAtlas internal API
|
// [SECTION] ImFontAtlas internal API
|
||||||
@@ -98,6 +98,7 @@ Index of this file:
|
|||||||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
||||||
#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn'
|
#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn'
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
|
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
|
||||||
|
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
|
||||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
|
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
|
||||||
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
|
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
@@ -138,6 +139,7 @@ Index of this file:
|
|||||||
struct ImBitVector; // Store 1-bit per value
|
struct ImBitVector; // Store 1-bit per value
|
||||||
struct ImRect; // An axis-aligned rectangle (2 points)
|
struct ImRect; // An axis-aligned rectangle (2 points)
|
||||||
struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
||||||
|
struct ImGuiPackedDate; // A date in YYYYMMDD format packed into 16-bits
|
||||||
|
|
||||||
// ImDrawList/ImFontAtlas
|
// ImDrawList/ImFontAtlas
|
||||||
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
|
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
|
||||||
@@ -247,6 +249,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
|||||||
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
|
#define IMGUI_DEBUG_LOG_TABLE(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventTable) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
|
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
|
||||||
@@ -321,6 +324,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
|||||||
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
|
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
|
||||||
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
|
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
|
||||||
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0")
|
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0")
|
||||||
|
#elif defined(__GNUC__) && defined(__aarch64__)
|
||||||
|
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xd4200000") // GDB needs 'set $pc=($pc+4)' to skip this :(
|
||||||
#else
|
#else
|
||||||
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
|
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
|
||||||
#endif
|
#endif
|
||||||
@@ -531,6 +536,7 @@ inline float ImFloor(float f) { return
|
|||||||
inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
||||||
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
|
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
|
||||||
inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only.
|
inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only.
|
||||||
|
inline float ImCeilFast(float f) { int i = (int)f; return (float)(i + (f > (float)i)); } // Consider using the the bit-hack version (search for "0x1p120f").
|
||||||
inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||||
inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||||
inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||||
@@ -688,6 +694,8 @@ struct ImSpan
|
|||||||
|
|
||||||
inline void set(T* data, int size) { Data = data; DataEnd = data + size; }
|
inline void set(T* data, int size) { Data = data; DataEnd = data + size; }
|
||||||
inline void set(T* data, T* data_end) { Data = data; DataEnd = data_end; }
|
inline void set(T* data, T* data_end) { Data = data; DataEnd = data_end; }
|
||||||
|
inline void clear() { Data = DataEnd = NULL; }
|
||||||
|
inline bool empty() const { return Data == DataEnd; }
|
||||||
inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); }
|
inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); }
|
||||||
inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); }
|
inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); }
|
||||||
inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
|
inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
|
||||||
@@ -827,6 +835,22 @@ struct ImGuiTextIndex
|
|||||||
void append(const char* base, int old_size, int new_size);
|
void append(const char* base, int old_size, int new_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper: ImGuiPackedDate (sizeof() == 2)
|
||||||
|
// Store a date in a way that is efficient to read/write in text form. If we stored e.g. number of days since Epoch we'd need costlier back and forth.
|
||||||
|
// This is specifically designed to be able to prune old .ini data.
|
||||||
|
struct ImGuiPackedDate
|
||||||
|
{
|
||||||
|
ImU16 Year : 7; // Year since 2000 // We can change to another offset e.g. 1970 but this is easier to watch in debugger.
|
||||||
|
ImU16 Month : 4; // Month (1-12)
|
||||||
|
ImU16 Day : 5; // Day (1-31)
|
||||||
|
|
||||||
|
ImGuiPackedDate() { Year = Month = Day = 0; }
|
||||||
|
ImGuiPackedDate(int yyyymmdd) { Year = (ImU16)((yyyymmdd / 10000) - 2000); Month = (ImU16)((yyyymmdd / 100) % 100); Day = (ImU16)(yyyymmdd % 100); } // Pack
|
||||||
|
bool IsValid() { return (Year && Month && Day); }
|
||||||
|
int Unpack() const { return (Year && Month && Day) ? ((Year + 2000) * 10000) + (Month * 100) + Day : 0; } // Unpack
|
||||||
|
void SubtractMonths(int m) { while (m > 0) { Year -= Month == 1; Month = (Month == 1) ? 12 : Month - 1; m--; } } // FIXME-OPT: Stupid but enough for what we do with it.
|
||||||
|
};
|
||||||
|
|
||||||
// Helper: ImGuiStorage
|
// Helper: ImGuiStorage
|
||||||
IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key);
|
IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key);
|
||||||
|
|
||||||
@@ -872,7 +896,7 @@ struct IMGUI_API ImDrawListSharedData
|
|||||||
float FontSize; // Current font size (used for for simplified AddText overload)
|
float FontSize; // Current font size (used for for simplified AddText overload)
|
||||||
float FontScale; // Current font scale (== FontSize / Font->FontSize)
|
float FontScale; // Current font scale (== FontSize / Font->FontSize)
|
||||||
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
|
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
|
||||||
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
|
float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
|
||||||
float InitialFringeScale; // Initial scale to apply to AA fringe
|
float InitialFringeScale; // Initial scale to apply to AA fringe
|
||||||
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
|
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
|
||||||
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
|
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
|
||||||
@@ -1702,6 +1726,7 @@ enum ImGuiActivateFlags_
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Early work-in-progress API for ScrollToItem()
|
// Early work-in-progress API for ScrollToItem()
|
||||||
|
// FIXME: Missing flags to request making both edges visible when possible.
|
||||||
enum ImGuiScrollFlags_
|
enum ImGuiScrollFlags_
|
||||||
{
|
{
|
||||||
ImGuiScrollFlags_None = 0,
|
ImGuiScrollFlags_None = 0,
|
||||||
@@ -1721,8 +1746,8 @@ enum ImGuiNavRenderCursorFlags_
|
|||||||
ImGuiNavRenderCursorFlags_None = 0,
|
ImGuiNavRenderCursorFlags_None = 0,
|
||||||
ImGuiNavRenderCursorFlags_Compact = 1 << 1, // Compact highlight, no padding/distance from focused item
|
ImGuiNavRenderCursorFlags_Compact = 1 << 1, // Compact highlight, no padding/distance from focused item
|
||||||
ImGuiNavRenderCursorFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) even when g.NavCursorVisible == false, aka even when using the mouse.
|
ImGuiNavRenderCursorFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) even when g.NavCursorVisible == false, aka even when using the mouse.
|
||||||
ImGuiNavRenderCursorFlags_NoRounding = 1 << 3,
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
ImGuiNavRenderCursorFlags_NoRounding = 1 << 3,
|
||||||
ImGuiNavHighlightFlags_None = ImGuiNavRenderCursorFlags_None, // Renamed in 1.91.4
|
ImGuiNavHighlightFlags_None = ImGuiNavRenderCursorFlags_None, // Renamed in 1.91.4
|
||||||
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
|
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
|
||||||
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
|
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
|
||||||
@@ -1933,6 +1958,7 @@ struct IMGUI_API ImGuiMultiSelectTempData
|
|||||||
bool NavIdPassedBy;
|
bool NavIdPassedBy;
|
||||||
bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem.
|
bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem.
|
||||||
bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set.
|
bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set.
|
||||||
|
bool IsSoleOrUnknownSelectionSize;
|
||||||
|
|
||||||
ImGuiMultiSelectTempData() { Clear(); }
|
ImGuiMultiSelectTempData() { Clear(); }
|
||||||
void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
|
void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
|
||||||
@@ -2007,18 +2033,27 @@ struct ImGuiViewportP : public ImGuiViewport
|
|||||||
// (this is designed to be stored in a ImChunkStream buffer, with the variable-length Name following our structure)
|
// (this is designed to be stored in a ImChunkStream buffer, with the variable-length Name following our structure)
|
||||||
struct ImGuiWindowSettings
|
struct ImGuiWindowSettings
|
||||||
{
|
{
|
||||||
ImGuiID ID;
|
ImGuiID ID;
|
||||||
ImVec2ih Pos;
|
ImVec2ih Pos;
|
||||||
ImVec2ih Size;
|
ImVec2ih Size;
|
||||||
bool Collapsed;
|
ImGuiPackedDate LastUsedDate;
|
||||||
bool IsChild;
|
bool Collapsed : 1;
|
||||||
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
bool IsChild : 1;
|
||||||
bool WantDelete; // Set to invalidate/delete the settings entry
|
bool WantApply : 1; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
||||||
|
bool WantDelete : 1; // Set to invalidate/delete the settings entry
|
||||||
|
|
||||||
ImGuiWindowSettings() { memset((void*)this, 0, sizeof(*this)); }
|
ImGuiWindowSettings() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
char* GetName() { return (char*)(this + 1); }
|
char* GetName() { return (char*)(this + 1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImGuiSettingsCleanupArgs
|
||||||
|
{
|
||||||
|
int DiscardOlderThanMonths = 0; // Enable to discard entries older than XX months.
|
||||||
|
bool SetCurrentSessionDateToAll = false; // Enable to write current SessionDate to all supporting entries. // Let us know in #9460 if you use this.
|
||||||
|
bool SetCurrentSessionDateWhenMissingDate = false; // Enable to write current SessionDate to all supporting entries missing a date. // Let us know in #9460 if you use this.
|
||||||
|
int _DiscardOlderThanDate = 0; // [Internal]
|
||||||
|
};
|
||||||
|
|
||||||
struct ImGuiSettingsHandler
|
struct ImGuiSettingsHandler
|
||||||
{
|
{
|
||||||
const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
|
const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
|
||||||
@@ -2029,6 +2064,7 @@ struct ImGuiSettingsHandler
|
|||||||
void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry
|
void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry
|
||||||
void (*ApplyAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called after reading (in registration order)
|
void (*ApplyAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called after reading (in registration order)
|
||||||
void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf'
|
void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf'
|
||||||
|
void (*CleanupFn) (ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiSettingsCleanupArgs* args);// Cleanup/patch settings
|
||||||
void* UserData;
|
void* UserData;
|
||||||
|
|
||||||
ImGuiSettingsHandler() { memset((void*)this, 0, sizeof(*this)); }
|
ImGuiSettingsHandler() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
@@ -2045,7 +2081,10 @@ enum ImGuiLocKey : int
|
|||||||
ImGuiLocKey_TableSizeOne,
|
ImGuiLocKey_TableSizeOne,
|
||||||
ImGuiLocKey_TableSizeAllFit,
|
ImGuiLocKey_TableSizeAllFit,
|
||||||
ImGuiLocKey_TableSizeAllDefault,
|
ImGuiLocKey_TableSizeAllDefault,
|
||||||
|
ImGuiLocKey_TableReset,
|
||||||
|
//ImGuiLocKey_TableResetAll,
|
||||||
ImGuiLocKey_TableResetOrder,
|
ImGuiLocKey_TableResetOrder,
|
||||||
|
ImGuiLocKey_TableResetVisibility,
|
||||||
ImGuiLocKey_WindowingMainMenuBar,
|
ImGuiLocKey_WindowingMainMenuBar,
|
||||||
ImGuiLocKey_WindowingPopup,
|
ImGuiLocKey_WindowingPopup,
|
||||||
ImGuiLocKey_WindowingUntitled,
|
ImGuiLocKey_WindowingUntitled,
|
||||||
@@ -2099,8 +2138,9 @@ enum ImGuiDebugLogFlags_
|
|||||||
ImGuiDebugLogFlags_EventInputRouting = 1 << 9,
|
ImGuiDebugLogFlags_EventInputRouting = 1 << 9,
|
||||||
ImGuiDebugLogFlags_EventDocking = 1 << 10, // Unused in this branch
|
ImGuiDebugLogFlags_EventDocking = 1 << 10, // Unused in this branch
|
||||||
ImGuiDebugLogFlags_EventViewport = 1 << 11, // Unused in this branch
|
ImGuiDebugLogFlags_EventViewport = 1 << 11, // Unused in this branch
|
||||||
|
ImGuiDebugLogFlags_EventTable = 1 << 12,
|
||||||
|
|
||||||
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventFont | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
|
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventTable | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventFont | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
|
||||||
ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY
|
ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY
|
||||||
ImGuiDebugLogFlags_OutputToDebugger = 1 << 21, // Also send output to Debugger Console [Windows only]
|
ImGuiDebugLogFlags_OutputToDebugger = 1 << 21, // Also send output to Debugger Console [Windows only]
|
||||||
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 22, // Also send output to Dear ImGui Test Engine
|
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 22, // Also send output to Dear ImGui Test Engine
|
||||||
@@ -2138,6 +2178,8 @@ struct ImGuiMetricsConfig
|
|||||||
int ShowTablesRectsType = -1;
|
int ShowTablesRectsType = -1;
|
||||||
int HighlightMonitorIdx = -1;
|
int HighlightMonitorIdx = -1;
|
||||||
ImGuiID HighlightViewportID = 0;
|
ImGuiID HighlightViewportID = 0;
|
||||||
|
int SettingsDiscardMonths = 6;
|
||||||
|
bool SettingsHighlightOldEntries = false;
|
||||||
bool ShowFontPreview = true;
|
bool ShowFontPreview = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2270,6 +2312,8 @@ struct ImGuiContext
|
|||||||
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
|
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
|
||||||
float ActiveIdTimer;
|
float ActiveIdTimer;
|
||||||
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
|
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
|
||||||
|
bool ActiveIdWasSelected; // Active ID was selected at the time of activating
|
||||||
|
bool ActiveIdWasSoleSelected; // Active ID was sole selection at the time of activating
|
||||||
bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
|
bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
|
||||||
bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused.
|
bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused.
|
||||||
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
|
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
|
||||||
@@ -2286,6 +2330,8 @@ struct ImGuiContext
|
|||||||
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
|
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
|
||||||
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
|
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
|
||||||
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
|
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
|
||||||
|
bool LastActiveIdWasSelected;
|
||||||
|
bool LastActiveIdWasSoleSelected;
|
||||||
|
|
||||||
// Key/Input Ownership + Shortcut Routing system
|
// Key/Input Ownership + Shortcut Routing system
|
||||||
// - The idea is that instead of "eating" a given key, we can link to an owner.
|
// - The idea is that instead of "eating" a given key, we can link to an owner.
|
||||||
@@ -2482,7 +2528,6 @@ struct ImGuiContext
|
|||||||
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
||||||
int BeginMenuDepth;
|
int BeginMenuDepth;
|
||||||
int BeginComboDepth;
|
int BeginComboDepth;
|
||||||
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
|
|
||||||
ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others).
|
ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others).
|
||||||
ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for
|
ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for
|
||||||
float ColorEditSavedHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips
|
float ColorEditSavedHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips
|
||||||
@@ -2517,6 +2562,7 @@ struct ImGuiContext
|
|||||||
ImVector<ImTextureData*> UserTextures; // List of textures created/managed by user or third-party extension. Automatically appended into platform_io.Textures[].
|
ImVector<ImTextureData*> UserTextures; // List of textures created/managed by user or third-party extension. Automatically appended into platform_io.Textures[].
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
|
ImGuiPackedDate SessionDate; // Packed copy of platform_io.Platform_SessionDate, when valid.
|
||||||
bool SettingsLoaded;
|
bool SettingsLoaded;
|
||||||
float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero
|
float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero
|
||||||
ImGuiTextBuffer SettingsIniData; // In memory .ini settings
|
ImGuiTextBuffer SettingsIniData; // In memory .ini settings
|
||||||
@@ -2876,13 +2922,13 @@ struct IMGUI_API ImGuiTabBar
|
|||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Table support
|
// [SECTION] Table support + internal API
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
|
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
|
||||||
#define IMGUI_TABLE_MAX_COLUMNS 512 // Arbitrary "safety" maximum, may be lifted in the future if needed. Must fit in ImGuiTableColumnIdx/ImGuiTableDrawChannelIdx.
|
#define IMGUI_TABLE_MAX_COLUMNS 512 // Arbitrary "safety" maximum, may be lifted in the future if needed. Must fit in ImGuiTableColumnIdx/ImGuiTableDrawChannelIdx.
|
||||||
|
|
||||||
// [Internal] sizeof() ~ 112
|
// [Internal] sizeof() ~ 120
|
||||||
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
|
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
|
||||||
// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping.
|
// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping.
|
||||||
// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped".
|
// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped".
|
||||||
@@ -2898,7 +2944,8 @@ struct ImGuiTableColumn
|
|||||||
float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially.
|
float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially.
|
||||||
float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_).
|
float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_).
|
||||||
ImRect ClipRect; // Clipping rectangle for the column
|
ImRect ClipRect; // Clipping rectangle for the column
|
||||||
ImGuiID UserID; // Optional, value passed to TableSetupColumn()
|
ImGuiID ID; // Hash of column name (ignoring top of ID stack), used for .ini persistence when available.
|
||||||
|
ImGuiID UserData; // (Optional) User data value passed to TableSetupColumn()
|
||||||
float WorkMinX; // Contents region min ~(MinX + CellPaddingX + CellSpacingX1) == cursor start position when entering column
|
float WorkMinX; // Contents region min ~(MinX + CellPaddingX + CellSpacingX1) == cursor start position when entering column
|
||||||
float WorkMaxX; // Contents region max ~(MaxX - CellPaddingX - CellSpacingX2)
|
float WorkMaxX; // Contents region max ~(MaxX - CellPaddingX - CellSpacingX2)
|
||||||
float ItemWidth; // Current item width for the column, preserved across rows
|
float ItemWidth; // Current item width for the column, preserved across rows
|
||||||
@@ -2922,10 +2969,14 @@ struct ImGuiTableColumn
|
|||||||
bool IsVisibleY;
|
bool IsVisibleY;
|
||||||
bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.
|
bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.
|
||||||
bool IsSkipItems; // Do we want item submissions to this column to be completely ignored (no layout will happen).
|
bool IsSkipItems; // Do we want item submissions to this column to be completely ignored (no layout will happen).
|
||||||
bool IsPreserveWidthAuto;
|
bool IsPreserveWidthAuto : 1;
|
||||||
|
bool IsJustCreated : 1;
|
||||||
|
bool IsLoadedSettings : 1;
|
||||||
|
bool IsNeedReconcileSrc : 1;
|
||||||
|
bool IsNeedReconcileDst : 1;
|
||||||
ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte
|
ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte
|
||||||
ImU8 AutoFitQueue; // Queue of 8 values for the next 8 frames to request auto-fit
|
ImU8 AutoFitQueue : 4; // Queue of 4 values for the next 4 frames to request auto-fit
|
||||||
ImU8 CannotSkipItemsQueue; // Queue of 8 values for the next 8 frames to disable Clipped/SkipItem
|
ImU8 CannotSkipItemsQueue : 4; // Queue of 4 values for the next 4 frames to disable Clipped/SkipItem
|
||||||
ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
|
ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
|
||||||
ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3)
|
ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3)
|
||||||
ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each)
|
ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each)
|
||||||
@@ -2940,10 +2991,28 @@ struct ImGuiTableColumn
|
|||||||
PrevEnabledColumn = NextEnabledColumn = -1;
|
PrevEnabledColumn = NextEnabledColumn = -1;
|
||||||
SortOrder = -1;
|
SortOrder = -1;
|
||||||
SortDirection = ImGuiSortDirection_None;
|
SortDirection = ImGuiSortDirection_None;
|
||||||
|
IsJustCreated = true;
|
||||||
DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU8)-1;
|
DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU8)-1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Passed to TableSetupColumn()
|
||||||
|
// sizeof() ~ 24+120 bytes
|
||||||
|
struct ImGuiTableReconcileColumnData
|
||||||
|
{
|
||||||
|
// Setup data
|
||||||
|
ImGuiID ID;
|
||||||
|
ImS16 NameOffset;
|
||||||
|
ImGuiTableColumnFlags Flags;
|
||||||
|
float InitWidthOrWeight;
|
||||||
|
ImGuiID UserData;
|
||||||
|
|
||||||
|
// Reconcile data
|
||||||
|
ImGuiTableColumnIdx ColumnNewIdx; // Index in the current table.
|
||||||
|
ImGuiTableColumnIdx ColumnOldIdx; // Index in the previous frame table.
|
||||||
|
ImGuiTableColumn ColumnOldData; // Full backup of the column. Could be avoided by storing 1 of them and applying reconcile in the right order. Not worth bothering.
|
||||||
|
};
|
||||||
|
|
||||||
// Transient cell data stored per row.
|
// Transient cell data stored per row.
|
||||||
// sizeof() ~ 6 bytes
|
// sizeof() ~ 6 bytes
|
||||||
struct ImGuiTableCellData
|
struct ImGuiTableCellData
|
||||||
@@ -3077,6 +3146,7 @@ struct IMGUI_API ImGuiTable
|
|||||||
bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row.
|
bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row.
|
||||||
bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow().
|
bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow().
|
||||||
bool IsInitializing;
|
bool IsInitializing;
|
||||||
|
bool IsReconcileMode;
|
||||||
bool IsSortSpecsDirty;
|
bool IsSortSpecsDirty;
|
||||||
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
|
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
|
||||||
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
|
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
|
||||||
@@ -3084,8 +3154,10 @@ struct IMGUI_API ImGuiTable
|
|||||||
bool IsSettingsRequestLoad;
|
bool IsSettingsRequestLoad;
|
||||||
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSettings data.
|
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSettings data.
|
||||||
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
|
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
|
||||||
bool IsResetAllRequest;
|
bool IsDefaultVisibility; // Set when enabled/visibility is unchanged from default
|
||||||
|
bool IsResetAllRequest; // Set to queue a call to TableResetSettings() in BeginTable()
|
||||||
bool IsResetDisplayOrderRequest;
|
bool IsResetDisplayOrderRequest;
|
||||||
|
bool IsResetVisibilityRequest;
|
||||||
bool IsUnfrozenRows; // Set when we got past the frozen row.
|
bool IsUnfrozenRows; // Set when we got past the frozen row.
|
||||||
bool IsDefaultSizingPolicy; // Set if user didn't explicitly set a sizing policy in BeginTable()
|
bool IsDefaultSizingPolicy; // Set if user didn't explicitly set a sizing policy in BeginTable()
|
||||||
bool IsActiveIdAliveBeforeTable;
|
bool IsActiveIdAliveBeforeTable;
|
||||||
@@ -3103,14 +3175,19 @@ struct IMGUI_API ImGuiTable
|
|||||||
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
|
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
|
||||||
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
|
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
|
||||||
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs.
|
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs.
|
||||||
// sizeof() ~ 136 bytes.
|
// sizeof() ~ 176 bytes.
|
||||||
struct IMGUI_API ImGuiTableTempData
|
struct IMGUI_API ImGuiTableTempData
|
||||||
{
|
{
|
||||||
ImGuiID WindowID; // Shortcut to g.Tables[TableIndex]->OuterWindow->ID.
|
ImGuiID WindowID; // Shortcut to g.Tables[TableIndex]->OuterWindow->ID.
|
||||||
int TableIndex; // Index in g.Tables.Buf[] pool
|
int TableIndex; // Index in g.Tables.Buf[] pool
|
||||||
float LastTimeActive; // Last timestamp this structure was used
|
float LastTimeActive; // Last timestamp this structure was used
|
||||||
float AngledHeadersExtraWidth; // Used in EndTable()
|
float AngledHeadersExtraWidth; // Used in EndTable()
|
||||||
ImVector<ImGuiTableHeaderData> AngledHeadersRequests; // Used in TableAngledHeadersRow()
|
ImVector<ImGuiTableHeaderData> AngledHeadersRequests; // Used in TableAngledHeadersRow() // FIXME: Single instance is enough?
|
||||||
|
|
||||||
|
// Topology change
|
||||||
|
ImVector<ImGuiTableReconcileColumnData> ReconcileColumnsRequests; // Used in TableSetupColumn(), TableUpdateLayout(). Cleared every frame.
|
||||||
|
void* OldColumnsRawData; // Used in BeginTable() -> TableUpdateLayout() when resizing.
|
||||||
|
ImSpan<ImGuiTableColumn> OldColumnsData;
|
||||||
|
|
||||||
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
|
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
|
||||||
ImDrawListSplitter DrawSplitter;
|
ImDrawListSplitter DrawSplitter;
|
||||||
@@ -3131,23 +3208,25 @@ struct IMGUI_API ImGuiTableTempData
|
|||||||
struct ImGuiTableColumnSettings
|
struct ImGuiTableColumnSettings
|
||||||
{
|
{
|
||||||
float WidthOrWeight;
|
float WidthOrWeight;
|
||||||
ImGuiID UserID;
|
ImGuiID ID;
|
||||||
ImGuiTableColumnIdx Index;
|
ImGuiTableColumnIdx Index;
|
||||||
ImGuiTableColumnIdx DisplayOrder;
|
ImGuiTableColumnIdx DisplayOrder;
|
||||||
ImGuiTableColumnIdx SortOrder;
|
ImGuiTableColumnIdx SortOrder;
|
||||||
ImU8 SortDirection : 2;
|
ImU8 SortDirection : 2;
|
||||||
ImS8 IsEnabled : 2; // "Visible" in ini file
|
ImS8 IsEnabled : 2; // "Visible" in .ini file
|
||||||
ImU8 IsStretch : 1;
|
ImU8 IsStretch : 1;
|
||||||
|
bool IsLoaded : 1; // Using during loading to mark finding a matching column.
|
||||||
|
|
||||||
ImGuiTableColumnSettings()
|
ImGuiTableColumnSettings()
|
||||||
{
|
{
|
||||||
WidthOrWeight = 0.0f;
|
WidthOrWeight = 0.0f;
|
||||||
UserID = 0;
|
ID = 0;
|
||||||
Index = -1;
|
Index = -1;
|
||||||
DisplayOrder = SortOrder = -1;
|
DisplayOrder = SortOrder = -1;
|
||||||
SortDirection = ImGuiSortDirection_None;
|
SortDirection = ImGuiSortDirection_None;
|
||||||
IsEnabled = -1;
|
IsEnabled = -1;
|
||||||
IsStretch = 0;
|
IsStretch = 0;
|
||||||
|
IsLoaded = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3159,12 +3238,94 @@ struct ImGuiTableSettings
|
|||||||
float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
|
float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
|
||||||
ImGuiTableColumnIdx ColumnsCount;
|
ImGuiTableColumnIdx ColumnsCount;
|
||||||
ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher
|
ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher
|
||||||
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
ImGuiPackedDate LastUsedDate;
|
||||||
|
bool WantApply : 1; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
||||||
|
|
||||||
ImGuiTableSettings() { memset((void*)this, 0, sizeof(*this)); }
|
ImGuiTableSettings() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
|
ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
// Tables: Candidates for public API
|
||||||
|
IMGUI_API void TableOpenContextMenu(int column_n = -1);
|
||||||
|
IMGUI_API void TableSetColumnWidth(int column_n, float width);
|
||||||
|
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
|
||||||
|
IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet.
|
||||||
|
IMGUI_API float TableGetHeaderRowHeight();
|
||||||
|
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
|
||||||
|
IMGUI_API void TablePushBackgroundChannel();
|
||||||
|
IMGUI_API void TablePopBackgroundChannel();
|
||||||
|
IMGUI_API void TablePushColumnChannel(int column_n);
|
||||||
|
IMGUI_API void TablePopColumnChannel();
|
||||||
|
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
|
||||||
|
|
||||||
|
// Tables: Internals
|
||||||
|
inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
|
||||||
|
IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
|
||||||
|
IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
|
||||||
|
IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count);
|
||||||
|
IMGUI_API void TableApplyQueuedRequests(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableSetupDrawChannels(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableReconcileColumns(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableUpdateBorders(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect);
|
||||||
|
IMGUI_API void TableDrawBorders(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display);
|
||||||
|
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
|
||||||
|
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
|
||||||
|
inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; }
|
||||||
|
IMGUI_API void TableFixDisplayOrder(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags init_mask);
|
||||||
|
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
|
||||||
|
IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column);
|
||||||
|
IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column);
|
||||||
|
IMGUI_API void TableBeginRow(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableEndRow(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n);
|
||||||
|
IMGUI_API void TableEndCell(ImGuiTable* table);
|
||||||
|
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
|
||||||
|
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
|
||||||
|
IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
|
||||||
|
IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n);
|
||||||
|
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
|
||||||
|
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
||||||
|
IMGUI_API void TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
||||||
|
IMGUI_API void TableRemove(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
|
||||||
|
IMGUI_API void TableGcCompactSettings();
|
||||||
|
|
||||||
|
// Tables: Settings
|
||||||
|
IMGUI_API void TableLoadSettings(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableLoadSettingsForColumns(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableLoadSettingsForColumn(ImGuiTableColumn* column, ImGuiTableColumnSettings* column_settings, ImGuiTableFlags load_flags);
|
||||||
|
IMGUI_API void TableSaveSettings(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableResetSettings(ImGuiTable* table);
|
||||||
|
IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
|
||||||
|
IMGUI_API void TableSettingsAddSettingsHandler();
|
||||||
|
IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
|
||||||
|
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
|
||||||
|
|
||||||
|
// Legacy Columns API (this is not exposed because we will encourage transitioning to the Tables API)
|
||||||
|
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
|
||||||
|
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
|
||||||
|
IMGUI_API void EndColumns(); // close columns
|
||||||
|
IMGUI_API void PushColumnClipRect(int column_index);
|
||||||
|
IMGUI_API void PushColumnsBackground();
|
||||||
|
IMGUI_API void PopColumnsBackground();
|
||||||
|
IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
|
||||||
|
IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
|
||||||
|
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm);
|
||||||
|
IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] ImGui internal API
|
// [SECTION] ImGui internal API
|
||||||
// No guarantee of forward compatibility here!
|
// No guarantee of forward compatibility here!
|
||||||
@@ -3262,6 +3423,7 @@ namespace ImGui
|
|||||||
IMGUI_API void MarkIniSettingsDirty();
|
IMGUI_API void MarkIniSettingsDirty();
|
||||||
IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
|
IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
|
||||||
IMGUI_API void ClearIniSettings();
|
IMGUI_API void ClearIniSettings();
|
||||||
|
IMGUI_API void CleanupIniSettings(ImGuiSettingsCleanupArgs* args); // [BETA] Expected to turn into a public API. Please report if you are using this!
|
||||||
IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler);
|
IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler);
|
||||||
IMGUI_API void RemoveSettingsHandler(const char* type_name);
|
IMGUI_API void RemoveSettingsHandler(const char* type_name);
|
||||||
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
|
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
|
||||||
@@ -3512,86 +3674,12 @@ namespace ImGui
|
|||||||
|
|
||||||
// Multi-Select API
|
// Multi-Select API
|
||||||
IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags);
|
IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags);
|
||||||
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed);
|
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed, ImGuiMultiSelectFlags extra_flags = 0);
|
||||||
IMGUI_API void MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected);
|
IMGUI_API void MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected);
|
||||||
IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item);
|
IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item);
|
||||||
inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; }
|
inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; }
|
||||||
inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); }
|
inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); }
|
||||||
|
|
||||||
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
|
|
||||||
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
|
|
||||||
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
|
|
||||||
IMGUI_API void EndColumns(); // close columns
|
|
||||||
IMGUI_API void PushColumnClipRect(int column_index);
|
|
||||||
IMGUI_API void PushColumnsBackground();
|
|
||||||
IMGUI_API void PopColumnsBackground();
|
|
||||||
IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
|
|
||||||
IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
|
|
||||||
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm);
|
|
||||||
IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset);
|
|
||||||
|
|
||||||
// Tables: Candidates for public API
|
|
||||||
IMGUI_API void TableOpenContextMenu(int column_n = -1);
|
|
||||||
IMGUI_API void TableSetColumnWidth(int column_n, float width);
|
|
||||||
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
|
|
||||||
IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet.
|
|
||||||
IMGUI_API float TableGetHeaderRowHeight();
|
|
||||||
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
|
|
||||||
IMGUI_API void TablePushBackgroundChannel();
|
|
||||||
IMGUI_API void TablePopBackgroundChannel();
|
|
||||||
IMGUI_API void TablePushColumnChannel(int column_n);
|
|
||||||
IMGUI_API void TablePopColumnChannel();
|
|
||||||
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
|
|
||||||
|
|
||||||
// Tables: Internals
|
|
||||||
inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
|
|
||||||
IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
|
|
||||||
IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
|
|
||||||
IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count);
|
|
||||||
IMGUI_API void TableBeginApplyRequests(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableSetupDrawChannels(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableUpdateBorders(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect);
|
|
||||||
IMGUI_API void TableDrawBorders(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display);
|
|
||||||
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
|
|
||||||
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
|
|
||||||
inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; }
|
|
||||||
IMGUI_API void TableFixDisplayOrder(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
|
|
||||||
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
|
|
||||||
IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column);
|
|
||||||
IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column);
|
|
||||||
IMGUI_API void TableBeginRow(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableEndRow(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n);
|
|
||||||
IMGUI_API void TableEndCell(ImGuiTable* table);
|
|
||||||
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
|
|
||||||
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
|
|
||||||
IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
|
|
||||||
IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n);
|
|
||||||
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
|
|
||||||
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
|
||||||
IMGUI_API void TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
|
||||||
IMGUI_API void TableRemove(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
|
|
||||||
IMGUI_API void TableGcCompactSettings();
|
|
||||||
|
|
||||||
// Tables: Settings
|
|
||||||
IMGUI_API void TableLoadSettings(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableSaveSettings(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableResetSettings(ImGuiTable* table);
|
|
||||||
IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
|
|
||||||
IMGUI_API void TableSettingsAddSettingsHandler();
|
|
||||||
IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
|
|
||||||
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
|
|
||||||
|
|
||||||
// Tab Bars
|
// Tab Bars
|
||||||
inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
|
inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
|
||||||
IMGUI_API ImGuiTabBar* TabBarFindByID(ImGuiID id);
|
IMGUI_API ImGuiTabBar* TabBarFindByID(ImGuiID id);
|
||||||
@@ -3628,7 +3716,7 @@ namespace ImGui
|
|||||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||||
IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding);
|
IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding);
|
||||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
||||||
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None); // Navigation highlight
|
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None, float rounding = -1.0f); // Navigation highlight
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4
|
inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4
|
||||||
#endif
|
#endif
|
||||||
@@ -3769,7 +3857,7 @@ namespace ImGui
|
|||||||
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
||||||
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
|
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
|
||||||
IMGUI_API void DebugNodeTable(ImGuiTable* table);
|
IMGUI_API void DebugNodeTable(ImGuiTable* table);
|
||||||
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
|
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings, ImGuiTable* table);
|
||||||
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state);
|
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state);
|
||||||
IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state);
|
IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state);
|
||||||
IMGUI_API void DebugNodeMultiSelectState(ImGuiMultiSelectState* state);
|
IMGUI_API void DebugNodeMultiSelectState(ImGuiMultiSelectState* state);
|
||||||
@@ -3979,6 +4067,7 @@ IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex,
|
|||||||
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
|
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
|
||||||
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
|
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
|
||||||
|
|
||||||
|
IMGUI_API bool ImTextureDataUpdateNewFrame(ImTextureData* tex);
|
||||||
IMGUI_API void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h);
|
IMGUI_API void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h);
|
||||||
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
|
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
|
||||||
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
|
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
|
||||||
|
|||||||
552
imgui_tables.cpp
552
imgui_tables.cpp
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (tables and columns code)
|
// (tables and columns code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -40,13 +40,15 @@ Index of this file:
|
|||||||
// | TableBeginInitMemory() - first time table is used
|
// | TableBeginInitMemory() - first time table is used
|
||||||
// | TableResetSettings() - on settings reset
|
// | TableResetSettings() - on settings reset
|
||||||
// | TableLoadSettings() - on settings load
|
// | TableLoadSettings() - on settings load
|
||||||
// | TableBeginApplyRequests() - apply queued resizing/reordering/hiding requests
|
//-----------------------------------------------------------------------------
|
||||||
// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame)
|
|
||||||
// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width
|
|
||||||
// - TableSetupColumn() user submit columns details (optional)
|
// - TableSetupColumn() user submit columns details (optional)
|
||||||
// - TableSetupScrollFreeze() user submit scroll freeze information (optional)
|
// - TableSetupScrollFreeze() user submit scroll freeze information (optional)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// - TableUpdateLayout() [Internal] followup to BeginTable(): setup everything: widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow().
|
// - TableUpdateLayout() [Internal] followup to BeginTable(): setup everything: widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow().
|
||||||
|
// | TableApplyQueuedRequests() - apply queued resizing/reordering/hiding requests
|
||||||
|
// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame)
|
||||||
|
// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width
|
||||||
|
// | - TableSetColumnDisplayOrder() - apply reordering a column
|
||||||
// | TableSetupDrawChannels() - setup ImDrawList channels
|
// | TableSetupDrawChannels() - setup ImDrawList channels
|
||||||
// | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission
|
// | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission
|
||||||
// | TableBeginContextMenuPopup()
|
// | TableBeginContextMenuPopup()
|
||||||
@@ -252,7 +254,7 @@ Index of this file:
|
|||||||
// - BeginTable()
|
// - BeginTable()
|
||||||
// - BeginTableEx() [Internal]
|
// - BeginTableEx() [Internal]
|
||||||
// - TableBeginInitMemory() [Internal]
|
// - TableBeginInitMemory() [Internal]
|
||||||
// - TableBeginApplyRequests() [Internal]
|
// - TableApplyQueuedRequests() [Internal]
|
||||||
// - TableSetupColumnFlags() [Internal]
|
// - TableSetupColumnFlags() [Internal]
|
||||||
// - TableUpdateLayout() [Internal]
|
// - TableUpdateLayout() [Internal]
|
||||||
// - TableUpdateBorders() [Internal]
|
// - TableUpdateBorders() [Internal]
|
||||||
@@ -361,6 +363,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData());
|
g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData());
|
||||||
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1];
|
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1];
|
||||||
temp_data->TableIndex = table_idx;
|
temp_data->TableIndex = table_idx;
|
||||||
|
temp_data->ReconcileColumnsRequests.resize(0); // FIXME: Use shrink(0) everywhere?
|
||||||
table->DrawSplitter = &table->TempData->DrawSplitter;
|
table->DrawSplitter = &table->TempData->DrawSplitter;
|
||||||
table->DrawSplitter->Clear();
|
table->DrawSplitter->Clear();
|
||||||
|
|
||||||
@@ -372,6 +375,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
const int previous_frame_active = table->LastFrameActive;
|
const int previous_frame_active = table->LastFrameActive;
|
||||||
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
|
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
|
||||||
const ImGuiTableFlags previous_flags = table->Flags;
|
const ImGuiTableFlags previous_flags = table->Flags;
|
||||||
|
const bool is_new_table = (previous_frame_active == -1);
|
||||||
table->ID = id;
|
table->ID = id;
|
||||||
table->Flags = flags;
|
table->Flags = flags;
|
||||||
table->LastFrameActive = g.FrameCount;
|
table->LastFrameActive = g.FrameCount;
|
||||||
@@ -561,29 +565,36 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
table->MemoryCompacted = false;
|
table->MemoryCompacted = false;
|
||||||
|
|
||||||
// Setup memory buffer (clear data if columns count changed)
|
// Setup memory buffer (clear data if columns count changed)
|
||||||
ImGuiTableColumn* old_columns_to_preserve = NULL;
|
|
||||||
void* old_columns_raw_data = NULL;
|
|
||||||
const int old_columns_count = table->Columns.size();
|
const int old_columns_count = table->Columns.size();
|
||||||
if (old_columns_count != 0 && old_columns_count != columns_count)
|
if (old_columns_count != 0 && old_columns_count != columns_count)
|
||||||
{
|
{
|
||||||
// Attempt to preserve width and other settings on column count/specs change (#4046)
|
// Attempt to preserve width and other settings on column count/specs change (#4046, #9108)
|
||||||
old_columns_to_preserve = table->Columns.Data;
|
IMGUI_DEBUG_LOG_TABLE("[table] Table 0x%08X column count %d -> %d, recreating storage.\n", table->ID, old_columns_count, columns_count);
|
||||||
old_columns_raw_data = table->RawData; // Free at end of function
|
IM_ASSERT(temp_data->OldColumnsRawData == NULL);
|
||||||
|
temp_data->OldColumnsRawData = table->RawData; // Freed during layout
|
||||||
|
temp_data->OldColumnsData = table->Columns;
|
||||||
|
for (ImGuiTableColumn& src_column : table->TempData->OldColumnsData)
|
||||||
|
src_column.IsNeedReconcileSrc = true;
|
||||||
table->RawData = NULL;
|
table->RawData = NULL;
|
||||||
}
|
}
|
||||||
if (table->RawData == NULL)
|
if (table->RawData == NULL)
|
||||||
{
|
{
|
||||||
TableBeginInitMemory(table, columns_count);
|
TableBeginInitMemory(table, columns_count);
|
||||||
table->IsInitializing = table->IsSettingsRequestLoad = true;
|
table->IsInitializing = true;
|
||||||
}
|
}
|
||||||
if (table->IsResetAllRequest)
|
if (table->IsResetAllRequest)
|
||||||
TableResetSettings(table);
|
TableResetSettings(table);
|
||||||
if (table->IsInitializing)
|
if (table->IsInitializing)
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
table->SettingsOffset = -1;
|
if (is_new_table)
|
||||||
|
{
|
||||||
|
table->SettingsOffset = -1;
|
||||||
|
table->IsSettingsRequestLoad = true;
|
||||||
|
}
|
||||||
table->IsSortSpecsDirty = true;
|
table->IsSortSpecsDirty = true;
|
||||||
table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934)
|
table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934)
|
||||||
|
table->IsReconcileMode = false;
|
||||||
table->InstanceInteracted = -1;
|
table->InstanceInteracted = -1;
|
||||||
table->ContextPopupColumn = -1;
|
table->ContextPopupColumn = -1;
|
||||||
table->ReorderColumn = table->ReorderColumnDstOrder = table->ResizedColumn = table->LastResizedColumn = -1;
|
table->ReorderColumn = table->ReorderColumnDstOrder = table->ResizedColumn = table->LastResizedColumn = -1;
|
||||||
@@ -592,9 +603,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
for (int n = 0; n < columns_count; n++)
|
for (int n = 0; n < columns_count; n++)
|
||||||
{
|
{
|
||||||
ImGuiTableColumn* column = &table->Columns[n];
|
ImGuiTableColumn* column = &table->Columns[n];
|
||||||
if (old_columns_to_preserve && n < old_columns_count)
|
if (temp_data->OldColumnsData.Data && n < temp_data->OldColumnsData.size())
|
||||||
{
|
{
|
||||||
*column = old_columns_to_preserve[n];
|
*column = temp_data->OldColumnsData[n];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -608,28 +619,11 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
table->DisplayOrderToIndex[n] = column->DisplayOrder;
|
table->DisplayOrderToIndex[n] = column->DisplayOrder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (old_columns_raw_data)
|
|
||||||
IM_FREE(old_columns_raw_data);
|
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
if (table->IsSettingsRequestLoad)
|
if (table->IsSettingsRequestLoad)
|
||||||
TableLoadSettings(table);
|
TableLoadSettings(table);
|
||||||
|
|
||||||
// Handle DPI/font resize
|
|
||||||
// This is designed to facilitate DPI changes with the assumption that e.g. style.CellPadding has been scaled as well.
|
|
||||||
// It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition.
|
|
||||||
// FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory.
|
|
||||||
// This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path.
|
|
||||||
const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ?
|
|
||||||
if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit)
|
|
||||||
{
|
|
||||||
const float scale_factor = new_ref_scale_unit / table->RefScale;
|
|
||||||
//IMGUI_DEBUG_PRINT("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor);
|
|
||||||
for (int n = 0; n < columns_count; n++)
|
|
||||||
table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor;
|
|
||||||
}
|
|
||||||
table->RefScale = new_ref_scale_unit;
|
|
||||||
|
|
||||||
// Disable output until user calls TableNextRow() or TableNextColumn() leading to the TableUpdateLayout() call..
|
// Disable output until user calls TableNextRow() or TableNextColumn() leading to the TableUpdateLayout() call..
|
||||||
// This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user.
|
// This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user.
|
||||||
// Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
|
// Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
|
||||||
@@ -639,10 +633,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
// At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn()
|
// At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn()
|
||||||
if (table->ColumnsNames.Buf.Size > 0)
|
if (table->ColumnsNames.Buf.Size > 0)
|
||||||
table->ColumnsNames.Buf.resize(0);
|
table->ColumnsNames.Buf.resize(0);
|
||||||
|
|
||||||
// Apply queued resizing/reordering/hiding requests
|
|
||||||
TableBeginApplyRequests(table);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +668,7 @@ void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply queued resizing/reordering/hiding requests
|
// Apply queued resizing/reordering/hiding requests
|
||||||
void ImGui::TableBeginApplyRequests(ImGuiTable* table)
|
void ImGui::TableApplyQueuedRequests(ImGuiTable* table)
|
||||||
{
|
{
|
||||||
// Handle resizing request
|
// Handle resizing request
|
||||||
// (We process this in the TableBegin() of the first instance of each table)
|
// (We process this in the TableBegin() of the first instance of each table)
|
||||||
@@ -719,7 +710,7 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
|
|||||||
// table->ReorderColumn = -1;
|
// table->ReorderColumn = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle display order reset request
|
// Handle display order / visibility reset requests
|
||||||
if (table->IsResetDisplayOrderRequest)
|
if (table->IsResetDisplayOrderRequest)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < table->ColumnsCount; n++)
|
for (int n = 0; n < table->ColumnsCount; n++)
|
||||||
@@ -727,6 +718,13 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
|
|||||||
table->IsResetDisplayOrderRequest = false;
|
table->IsResetDisplayOrderRequest = false;
|
||||||
table->IsSettingsDirty = true;
|
table->IsSettingsDirty = true;
|
||||||
}
|
}
|
||||||
|
if (table->IsResetVisibilityRequest)
|
||||||
|
{
|
||||||
|
for (ImGuiTableColumn& column : table->Columns)
|
||||||
|
column.IsUserEnabled = column.IsUserEnabledNextFrame = (column.Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1;
|
||||||
|
table->IsResetVisibilityRequest = false;
|
||||||
|
table->IsSettingsDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply immediately. See TableQueueSetColumnDisplayOrder() for additional checks/constraints.
|
// Apply immediately. See TableQueueSetColumnDisplayOrder() for additional checks/constraints.
|
||||||
@@ -782,8 +780,9 @@ void ImGui::TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int
|
|||||||
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
|
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
|
||||||
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)-1;
|
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)-1;
|
||||||
dst_order = TableGetMaxDisplayOrderAllowed(table, src_order, dst_order);
|
dst_order = TableGetMaxDisplayOrderAllowed(table, src_order, dst_order);
|
||||||
if (dst_order != src_order)
|
if (table->IsLayoutLocked && dst_order == src_order) // We allow calling the function before layout w/ reconcile so don't early out.
|
||||||
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)dst_order;
|
return;
|
||||||
|
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)dst_order;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust flags: default width mode + stretch columns are not allowed when auto extending
|
// Adjust flags: default width mode + stretch columns are not allowed when auto extending
|
||||||
@@ -849,13 +848,61 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
|
|||||||
void ImGui::TableUpdateLayout(ImGuiTable* table)
|
void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiTableTempData* temp_data = table->TempData;
|
||||||
IM_ASSERT(table->IsLayoutLocked == false);
|
IM_ASSERT(table->IsLayoutLocked == false);
|
||||||
|
const int columns_count = table->ColumnsCount;
|
||||||
|
|
||||||
|
// Reconcile moved columns
|
||||||
|
if (temp_data->ReconcileColumnsRequests.Size > 0)
|
||||||
|
TableReconcileColumns(table);
|
||||||
|
if (temp_data->OldColumnsRawData)
|
||||||
|
{
|
||||||
|
IM_FREE(temp_data->OldColumnsRawData);
|
||||||
|
temp_data->OldColumnsRawData = NULL;
|
||||||
|
temp_data->OldColumnsData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply columns settings
|
||||||
|
if (table->IsSettingsRequestLoad)
|
||||||
|
TableLoadSettingsForColumns(table);
|
||||||
|
if (table->IsInitializing || table->IsSettingsRequestLoad)
|
||||||
|
{
|
||||||
|
for (ImGuiTableColumn& column : table->Columns)
|
||||||
|
{
|
||||||
|
ImGuiTableFlags init_flags;
|
||||||
|
if (table->IsSettingsRequestLoad)
|
||||||
|
init_flags = column.IsLoadedSettings ? ~table->SettingsLoadedFlags : ~0;
|
||||||
|
else
|
||||||
|
init_flags = column.IsJustCreated ? ~0 : 0;
|
||||||
|
TableInitColumnDefaults(table, &column, init_flags);
|
||||||
|
}
|
||||||
|
TableFixDisplayOrder(table); // Call even for non _Reorderable table as we loaded .ini data.
|
||||||
|
table->IsSettingsRequestLoad = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply queued resizing/reordering/hiding requests
|
||||||
|
TableApplyQueuedRequests(table);
|
||||||
|
|
||||||
|
// Handle DPI/font resize
|
||||||
|
// This is designed to facilitate DPI changes with the assumption that e.g. style.CellPadding has been scaled as well.
|
||||||
|
// It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition.
|
||||||
|
// FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory.
|
||||||
|
// This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path.
|
||||||
|
const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ?
|
||||||
|
if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit)
|
||||||
|
{
|
||||||
|
const float scale_factor = new_ref_scale_unit / table->RefScale;
|
||||||
|
IMGUI_DEBUG_LOG_TABLE("[table] 0x%08X RefScale %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScale, new_ref_scale_unit, scale_factor);
|
||||||
|
for (int n = 0; n < columns_count; n++)
|
||||||
|
table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor;
|
||||||
|
}
|
||||||
|
table->RefScale = new_ref_scale_unit;
|
||||||
|
|
||||||
const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
|
const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
|
||||||
table->IsDefaultDisplayOrder = true;
|
table->IsDefaultDisplayOrder = table->IsDefaultVisibility = true;
|
||||||
table->ColumnsEnabledCount = 0;
|
table->ColumnsEnabledCount = 0;
|
||||||
ImBitArrayClearAllBits(table->EnabledMaskByIndex, table->ColumnsCount);
|
ImBitArrayClearAllBits(table->EnabledMaskByIndex, columns_count);
|
||||||
ImBitArrayClearAllBits(table->EnabledMaskByDisplayOrder, table->ColumnsCount);
|
ImBitArrayClearAllBits(table->EnabledMaskByDisplayOrder, columns_count);
|
||||||
table->LeftMostEnabledColumn = -1;
|
table->LeftMostEnabledColumn = -1;
|
||||||
table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
|
table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
|
||||||
|
|
||||||
@@ -868,11 +915,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
bool has_resizable = false;
|
bool has_resizable = false;
|
||||||
float stretch_sum_width_auto = 0.0f;
|
float stretch_sum_width_auto = 0.0f;
|
||||||
float fixed_max_width_auto = 0.0f;
|
float fixed_max_width_auto = 0.0f;
|
||||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
for (int order_n = 0; order_n < columns_count; order_n++)
|
||||||
{
|
{
|
||||||
const int column_n = table->DisplayOrderToIndex[order_n];
|
const int column_n = table->DisplayOrderToIndex[order_n];
|
||||||
if (column_n != order_n)
|
|
||||||
table->IsDefaultDisplayOrder = false;
|
|
||||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||||
|
|
||||||
// Clear column setup if not submitted by user. Currently we make it mandatory to call TableSetupColumn() every frame.
|
// Clear column setup if not submitted by user. Currently we make it mandatory to call TableSetupColumn() every frame.
|
||||||
@@ -882,7 +927,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
{
|
{
|
||||||
TableSetupColumnFlags(table, column, ImGuiTableColumnFlags_None);
|
TableSetupColumnFlags(table, column, ImGuiTableColumnFlags_None);
|
||||||
column->NameOffset = -1;
|
column->NameOffset = -1;
|
||||||
column->UserID = 0;
|
column->ID = column->UserData = 0;
|
||||||
column->InitStretchWeightOrWidth = -1.0f;
|
column->InitStretchWeightOrWidth = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,6 +940,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
table->IsSettingsDirty = true;
|
table->IsSettingsDirty = true;
|
||||||
}
|
}
|
||||||
column->IsEnabled = column->IsUserEnabled && (column->Flags & ImGuiTableColumnFlags_Disabled) == 0;
|
column->IsEnabled = column->IsUserEnabled && (column->Flags & ImGuiTableColumnFlags_Disabled) == 0;
|
||||||
|
column->IsJustCreated = false;
|
||||||
|
|
||||||
|
if (column->IsEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1))
|
||||||
|
table->IsDefaultVisibility = false;
|
||||||
|
if (column_n != order_n)
|
||||||
|
table->IsDefaultDisplayOrder = false;
|
||||||
|
|
||||||
if (column->SortOrder != -1 && !column->IsEnabled)
|
if (column->SortOrder != -1 && !column->IsEnabled)
|
||||||
table->IsSortSpecsDirty = true;
|
table->IsSortSpecsDirty = true;
|
||||||
@@ -967,7 +1018,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding.
|
float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding.
|
||||||
float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns.
|
float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns.
|
||||||
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
|
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
|
||||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
for (int column_n = 0; column_n < columns_count; column_n++)
|
||||||
{
|
{
|
||||||
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
|
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
|
||||||
continue;
|
continue;
|
||||||
@@ -1031,7 +1082,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests;
|
const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests;
|
||||||
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
|
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
|
||||||
table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
|
table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
|
||||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
for (int column_n = 0; column_n < columns_count; column_n++)
|
||||||
{
|
{
|
||||||
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
|
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
|
||||||
continue;
|
continue;
|
||||||
@@ -1058,7 +1109,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
// [Part 5] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
|
// [Part 5] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
|
||||||
// Using right-to-left distribution (more likely to match resizing cursor).
|
// Using right-to-left distribution (more likely to match resizing cursor).
|
||||||
if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths))
|
if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths))
|
||||||
for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--)
|
for (int order_n = columns_count - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--)
|
||||||
{
|
{
|
||||||
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
|
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
|
||||||
continue;
|
continue;
|
||||||
@@ -1098,8 +1149,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
|
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
|
||||||
ImRect host_clip_rect = table->InnerClipRect;
|
ImRect host_clip_rect = table->InnerClipRect;
|
||||||
//host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2;
|
//host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2;
|
||||||
ImBitArrayClearAllBits(table->VisibleMaskByIndex, table->ColumnsCount);
|
ImBitArrayClearAllBits(table->VisibleMaskByIndex, columns_count);
|
||||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
for (int order_n = 0; order_n < columns_count; order_n++)
|
||||||
{
|
{
|
||||||
const int column_n = table->DisplayOrderToIndex[order_n];
|
const int column_n = table->DisplayOrderToIndex[order_n];
|
||||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||||
@@ -1247,7 +1298,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
|
const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
|
||||||
if (is_hovering_table && table->HoveredColumnBody == -1)
|
if (is_hovering_table && table->HoveredColumnBody == -1)
|
||||||
if (mouse_skewed_x >= unused_x1)
|
if (mouse_skewed_x >= unused_x1)
|
||||||
table->HoveredColumnBody = (ImGuiTableColumnIdx)table->ColumnsCount;
|
table->HoveredColumnBody = (ImGuiTableColumnIdx)columns_count;
|
||||||
if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable))
|
if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable))
|
||||||
table->Flags &= ~ImGuiTableFlags_Resizable;
|
table->Flags &= ~ImGuiTableFlags_Resizable;
|
||||||
|
|
||||||
@@ -1289,7 +1340,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
table->HighlightColumnHeader = -1;
|
table->HighlightColumnHeader = -1;
|
||||||
if (table->IsContextPopupOpen && table->ContextPopupColumn != -1 && table->InstanceInteracted == table->InstanceCurrent)
|
if (table->IsContextPopupOpen && table->ContextPopupColumn != -1 && table->InstanceInteracted == table->InstanceCurrent)
|
||||||
table->HighlightColumnHeader = table->ContextPopupColumn;
|
table->HighlightColumnHeader = table->ContextPopupColumn;
|
||||||
else if ((table->Flags & ImGuiTableFlags_HighlightHoveredColumn) && table->HoveredColumnBody != -1 && table->HoveredColumnBody != table->ColumnsCount && table->HoveredColumnBorder == -1)
|
else if ((table->Flags & ImGuiTableFlags_HighlightHoveredColumn) && table->HoveredColumnBody != -1 && table->HoveredColumnBody != columns_count && table->HoveredColumnBorder == -1)
|
||||||
if (g.ActiveId == 0 || (table->IsActiveIdInTable || g.DragDropActive))
|
if (g.ActiveId == 0 || (table->IsActiveIdInTable || g.DragDropActive))
|
||||||
table->HighlightColumnHeader = table->HoveredColumnBody;
|
table->HighlightColumnHeader = table->HoveredColumnBody;
|
||||||
|
|
||||||
@@ -1629,9 +1680,9 @@ void ImGui::EndTable()
|
|||||||
NavUpdateCurrentWindowIsScrollPushableX();
|
NavUpdateCurrentWindowIsScrollPushableX();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called in TableSetupColumn() when initializing and in TableLoadSettings() for defaults before applying stored settings.
|
// Called in TableUpdateLayout() when initializing/after loading settings.
|
||||||
// 'init_mask' specify which fields to initialize.
|
// 'init_mask' specify which fields to initialize.
|
||||||
static void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags init_mask)
|
void ImGui::TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags init_mask)
|
||||||
{
|
{
|
||||||
ImGuiTableColumnFlags flags = column->Flags;
|
ImGuiTableColumnFlags flags = column->Flags;
|
||||||
if (init_mask & ImGuiTableFlags_Resizable)
|
if (init_mask & ImGuiTableFlags_Resizable)
|
||||||
@@ -1643,7 +1694,7 @@ static void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column,
|
|||||||
column->AutoFitQueue = 0x00;
|
column->AutoFitQueue = 0x00;
|
||||||
}
|
}
|
||||||
if (init_mask & ImGuiTableFlags_Reorderable)
|
if (init_mask & ImGuiTableFlags_Reorderable)
|
||||||
column->DisplayOrder = (ImGuiTableColumnIdx)table->Columns.index_from_ptr(column);
|
column->DisplayOrder = (ImGuiTableColumnIdx)((table->Flags & ImGuiTableFlags_Reorderable) ? -1 : table->Columns.index_from_ptr(column));
|
||||||
if (init_mask & ImGuiTableFlags_Hideable)
|
if (init_mask & ImGuiTableFlags_Hideable)
|
||||||
column->IsUserEnabled = column->IsUserEnabledNextFrame = (flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1;
|
column->IsUserEnabled = column->IsUserEnabledNextFrame = (flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1;
|
||||||
if (init_mask & ImGuiTableFlags_Sortable)
|
if (init_mask & ImGuiTableFlags_Sortable)
|
||||||
@@ -1656,17 +1707,9 @@ static void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column,
|
|||||||
|
|
||||||
// See "COLUMNS SIZING POLICIES" comments at the top of this file
|
// See "COLUMNS SIZING POLICIES" comments at the top of this file
|
||||||
// If (init_width_or_weight <= 0.0f) it is ignored
|
// If (init_width_or_weight <= 0.0f) it is ignored
|
||||||
void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id)
|
static void TableSetupColumnApply(ImGuiTable* table, int idx, ImGuiID id, ImS16 name_offset, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_data)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiTableColumn* column = &table->Columns[idx];
|
||||||
ImGuiTable* table = g.CurrentTable;
|
|
||||||
IM_ASSERT_USER_ERROR_RET(table != NULL, "Call should only be done while in BeginTable() scope!");
|
|
||||||
IM_ASSERT_USER_ERROR_RET(table->DeclColumnsCount < table->ColumnsCount, "TableSetupColumn(): called too many times!");
|
|
||||||
IM_ASSERT_USER_ERROR_RET(table->IsLayoutLocked == false, "TableSetupColumn(): need to call before first row!"); // Table layout is locked when submitting a row or when calling BeginMultiSelect() with box-select.
|
|
||||||
IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
|
|
||||||
|
|
||||||
ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];
|
|
||||||
table->DeclColumnsCount++;
|
|
||||||
|
|
||||||
// Assert when passing a width or weight if policy is entirely left to default, to avoid storing width into weight and vice-versa.
|
// Assert when passing a width or weight if policy is entirely left to default, to avoid storing width into weight and vice-versa.
|
||||||
// Give a grace to users of ImGuiTableFlags_ScrollX.
|
// Give a grace to users of ImGuiTableFlags_ScrollX.
|
||||||
@@ -1685,27 +1728,127 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
|||||||
}
|
}
|
||||||
|
|
||||||
TableSetupColumnFlags(table, column, flags);
|
TableSetupColumnFlags(table, column, flags);
|
||||||
column->UserID = user_id;
|
column->ID = id;
|
||||||
flags = column->Flags;
|
column->UserData = user_data;
|
||||||
|
column->NameOffset = name_offset;
|
||||||
// Initialize defaults
|
|
||||||
column->InitStretchWeightOrWidth = init_width_or_weight;
|
column->InitStretchWeightOrWidth = init_width_or_weight;
|
||||||
if (table->IsInitializing)
|
}
|
||||||
{
|
|
||||||
ImGuiTableFlags init_flags = ~table->SettingsLoadedFlags;
|
void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_data)
|
||||||
if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f)
|
{
|
||||||
init_flags |= ImGuiTableFlags_Resizable;
|
ImGuiContext& g = *GImGui;
|
||||||
TableInitColumnDefaults(table, column, init_flags);
|
ImGuiTable* table = g.CurrentTable;
|
||||||
}
|
IM_ASSERT_USER_ERROR_RET(table != NULL, "Call should only be done while in BeginTable() scope!");
|
||||||
|
IM_ASSERT_USER_ERROR_RET(table->DeclColumnsCount < table->ColumnsCount, "TableSetupColumn(): called too many times!");
|
||||||
|
IM_ASSERT_USER_ERROR_RET(table->IsLayoutLocked == false, "TableSetupColumn(): need to call before first row!"); // Table layout is locked when submitting a row or when calling BeginMultiSelect() with box-select.
|
||||||
|
IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
|
||||||
|
|
||||||
// Store name (append with zero-terminator in contiguous buffer)
|
// Store name (append with zero-terminator in contiguous buffer)
|
||||||
// FIXME: If we recorded the number of \n in names we could compute header row height
|
// FIXME: If we recorded the number of \n in names we could compute header row height
|
||||||
column->NameOffset = -1;
|
ImS16 name_offset = -1;
|
||||||
if (label != NULL && label[0] != 0)
|
if (label != NULL && label[0] != 0)
|
||||||
{
|
{
|
||||||
column->NameOffset = (ImS16)table->ColumnsNames.size();
|
name_offset = (ImS16)table->ColumnsNames.size();
|
||||||
table->ColumnsNames.append(label, label + ImStrlen(label) + 1);
|
table->ColumnsNames.append(label, label + ImStrlen(label) + 1);
|
||||||
}
|
}
|
||||||
|
const ImGuiID column_id = (label != NULL && label[0] != 0) ? ImHashStr(label) : 0;
|
||||||
|
|
||||||
|
// When ID changed or a column moved: defer the request until layout where we will process full reconcile.
|
||||||
|
const int column_idx = table->DeclColumnsCount++;
|
||||||
|
ImGuiTableColumn* column = &table->Columns[column_idx];
|
||||||
|
|
||||||
|
// If topology change goes into reconcile mode
|
||||||
|
if (table->IsReconcileMode == false && column->ID != column_id)
|
||||||
|
{
|
||||||
|
table->IsReconcileMode = true;
|
||||||
|
table->TempData->ReconcileColumnsRequests.reserve(table->ColumnsCount - column_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast/common path
|
||||||
|
if (table->IsReconcileMode == false)
|
||||||
|
{
|
||||||
|
TableSetupColumnApply(table, column_idx, column_id, name_offset, flags, init_width_or_weight, user_data);
|
||||||
|
column->IsNeedReconcileSrc = column->IsNeedReconcileDst = false;
|
||||||
|
if (column_idx < table->TempData->OldColumnsData.size())
|
||||||
|
table->TempData->OldColumnsData[column_idx].IsNeedReconcileSrc = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconcile path: defer applying data to TableUpdateLayout() -> TableReconcileMovedColumns() -> TableSetupColumnApply().
|
||||||
|
// On column count change: search the previous columns:
|
||||||
|
// - the live Columns[] array is truncated on shrink, so a moved column may only exist in old data.
|
||||||
|
// - the live Columns[] array may already be partially reset.
|
||||||
|
table->TempData->ReconcileColumnsRequests.push_back(ImGuiTableReconcileColumnData());
|
||||||
|
ImGuiTableReconcileColumnData& reconcile_data = table->TempData->ReconcileColumnsRequests.back();
|
||||||
|
reconcile_data.ID = column_id;
|
||||||
|
reconcile_data.NameOffset = name_offset;
|
||||||
|
reconcile_data.Flags = flags;
|
||||||
|
reconcile_data.InitWidthOrWeight = init_width_or_weight;
|
||||||
|
reconcile_data.UserData = user_data;
|
||||||
|
reconcile_data.ColumnNewIdx = (ImGuiTableColumnIdx)column_idx;
|
||||||
|
reconcile_data.ColumnOldIdx = (ImGuiTableColumnIdx)-1;
|
||||||
|
column->NameOffset = name_offset; // Allow TableGetColumnName() to work before layout
|
||||||
|
column->IsNeedReconcileSrc = column->IsNeedReconcileDst = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: This was written to be similar to the logic in TableLoadSettingsForColumns().
|
||||||
|
void ImGui::TableReconcileColumns(ImGuiTable* table)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiTableTempData* temp_data = table->TempData;
|
||||||
|
IM_UNUSED(g);
|
||||||
|
IMGUI_DEBUG_LOG_TABLE("[table] Reconcile columns for table 0x%08X\n", table->ID);
|
||||||
|
|
||||||
|
ImSpan<ImGuiTableColumn>& dst_columns = table->Columns;
|
||||||
|
ImSpan<ImGuiTableColumn>& src_columns = table->TempData->OldColumnsData.empty() ? table->Columns : table->TempData->OldColumnsData;
|
||||||
|
|
||||||
|
// Find matches for named columns.
|
||||||
|
int matches = 0;
|
||||||
|
ImVector<ImGuiTableReconcileColumnData>& reconcile_requests = temp_data->ReconcileColumnsRequests;
|
||||||
|
for (ImGuiTableReconcileColumnData& reconcile_data : reconcile_requests)
|
||||||
|
if (reconcile_data.ID != 0)
|
||||||
|
for (ImGuiTableColumn& src_column : src_columns)
|
||||||
|
if (src_column.ID == reconcile_data.ID && src_column.IsNeedReconcileSrc)
|
||||||
|
{
|
||||||
|
ImGuiTableColumn& dst_column = dst_columns[reconcile_data.ColumnNewIdx];
|
||||||
|
IM_ASSERT(src_column.IsNeedReconcileSrc && dst_column.IsNeedReconcileDst);
|
||||||
|
src_column.IsNeedReconcileSrc = dst_column.IsNeedReconcileDst = false;
|
||||||
|
reconcile_data.ColumnOldIdx = (ImGuiTableColumnIdx)src_columns.index_from_ptr(&src_column);
|
||||||
|
reconcile_data.ColumnOldData = src_column;
|
||||||
|
matches++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remaining entries are matched sequentially.
|
||||||
|
int dst_idx = 0; // index in reconcile array
|
||||||
|
if (matches != reconcile_requests.Size)
|
||||||
|
for (ImGuiTableColumn& src_column : src_columns)
|
||||||
|
{
|
||||||
|
if (!src_column.IsNeedReconcileSrc)
|
||||||
|
continue;
|
||||||
|
while (dst_idx < reconcile_requests.Size && reconcile_requests[dst_idx].ColumnOldIdx != (ImGuiTableColumnIdx)-1)
|
||||||
|
dst_idx++;
|
||||||
|
if (dst_idx == reconcile_requests.Size)
|
||||||
|
break;
|
||||||
|
ImGuiTableReconcileColumnData& reconcile_data = reconcile_requests[dst_idx];
|
||||||
|
ImGuiTableColumn& dst_column = dst_columns[reconcile_data.ColumnNewIdx];
|
||||||
|
IM_ASSERT(src_column.IsNeedReconcileSrc && dst_column.IsNeedReconcileDst);
|
||||||
|
src_column.IsNeedReconcileSrc = dst_column.IsNeedReconcileDst = false;
|
||||||
|
reconcile_data.ColumnOldIdx = (ImGuiTableColumnIdx)src_columns.index_from_ptr(&src_column);
|
||||||
|
reconcile_data.ColumnOldData = src_column;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply in the final pass. Because it is possible that src_columns == table->Columns we went through a temporary copy.
|
||||||
|
for (ImGuiTableReconcileColumnData& reconcile_data : reconcile_requests)
|
||||||
|
{
|
||||||
|
table->Columns[reconcile_data.ColumnNewIdx] = reconcile_data.ColumnOldData; // When old column was not found clear anyway with default-constructed data (which will set IsJustCreated=true)
|
||||||
|
TableSetupColumnApply(table, reconcile_data.ColumnNewIdx, reconcile_data.ID, reconcile_data.NameOffset, reconcile_data.Flags, reconcile_data.InitWidthOrWeight, reconcile_data.UserData);
|
||||||
|
IMGUI_DEBUG_LOG_TABLE("[table] - old %d -> new %d \"%s\"\n", reconcile_data.ColumnOldIdx, reconcile_data.ColumnNewIdx, TableGetColumnName(table, reconcile_data.ColumnNewIdx)); // Log at the end so NameOffset was copied.
|
||||||
|
}
|
||||||
|
TableFixDisplayOrder(table);
|
||||||
|
table->IsSettingsDirty = true; // FIXME-RECONCILE: Necessary?
|
||||||
|
table->IsReconcileMode = false;
|
||||||
|
reconcile_requests.resize(0); // GC-ed once in NewFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Public]
|
// [Public]
|
||||||
@@ -3081,7 +3224,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
|
|||||||
continue;
|
continue;
|
||||||
IM_ASSERT(column->SortOrder < table->SortSpecsCount);
|
IM_ASSERT(column->SortOrder < table->SortSpecsCount);
|
||||||
ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder];
|
ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder];
|
||||||
sort_spec->ColumnUserID = column->UserID;
|
sort_spec->ColumnUserID = column->UserData;
|
||||||
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
|
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
|
||||||
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
|
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
|
||||||
sort_spec->SortDirection = (ImGuiSortDirection)column->SortDirection;
|
sort_spec->SortDirection = (ImGuiSortDirection)column->SortDirection;
|
||||||
@@ -3252,7 +3395,7 @@ void ImGui::TableHeader(const char* label)
|
|||||||
if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
|
if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
|
||||||
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
|
TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
|
||||||
}
|
}
|
||||||
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding);
|
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact, 0.0f);
|
||||||
if (held)
|
if (held)
|
||||||
table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
|
table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
|
||||||
window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
|
window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
|
||||||
@@ -3277,7 +3420,9 @@ void ImGui::TableHeader(const char* label)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort order arrow
|
// Sort order arrow
|
||||||
const float ellipsis_max = ImMax(cell_r.Max.x - w_arrow - w_sort_text, label_pos.x);
|
// - Only clip label for a visible arrow. Auto-fit still accounts for a possible arrow, but when
|
||||||
|
// manually sized smaller we don't clip the label for the sake of an arrow that isn't displayed.
|
||||||
|
const float ellipsis_max = ImMax(cell_r.Max.x - (sort_arrow ? w_arrow + w_sort_text : 0.0f), label_pos.x);
|
||||||
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
|
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
|
||||||
{
|
{
|
||||||
if (column->SortOrder != -1)
|
if (column->SortOrder != -1)
|
||||||
@@ -3597,17 +3742,20 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
|
|||||||
want_separator = true;
|
want_separator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ordering
|
// Reset Order/Visibility etc.
|
||||||
if (flags_for_section_to_display & ImGuiTableFlags_Reorderable)
|
if (flags_for_section_to_display & (ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
|
||||||
{
|
if (BeginMenu(LocalizeGetMsg(ImGuiLocKey_TableReset)))
|
||||||
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableResetOrder), NULL, false, !table->IsDefaultDisplayOrder))
|
{
|
||||||
table->IsResetDisplayOrderRequest = true;
|
//if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableResetAll))) // FIXME: Hiding because altering Sort Order + requesting auto-fit simultaneously has a tendency to exhibit a sizing glitch.
|
||||||
want_separator = true;
|
// table->IsResetAllRequest = true;
|
||||||
}
|
if (flags_for_section_to_display & ImGuiTableFlags_Reorderable)
|
||||||
|
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableResetOrder), NULL, false, !table->IsDefaultDisplayOrder)) // PS: cannot be hidden because it would mess with drag reordering.
|
||||||
// Reset all (should work but seems unnecessary/noisy to expose?)
|
table->IsResetDisplayOrderRequest = true;
|
||||||
//if (MenuItem("Reset all"))
|
if (flags_for_section_to_display & ImGuiTableFlags_Hideable)
|
||||||
// table->IsResetAllRequest = true;
|
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableResetVisibility), NULL, false, !table->IsDefaultVisibility))
|
||||||
|
table->IsResetVisibilityRequest = true;
|
||||||
|
EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
// Sorting
|
// Sorting
|
||||||
// (modify TableOpenContextMenu() to add _Sortable flag if enabling this)
|
// (modify TableOpenContextMenu() to add _Sortable flag if enabling this)
|
||||||
@@ -3692,6 +3840,7 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
|
|||||||
// - TableResetSettings()
|
// - TableResetSettings()
|
||||||
// - TableSaveSettings() [Internal]
|
// - TableSaveSettings() [Internal]
|
||||||
// - TableLoadSettings() [Internal]
|
// - TableLoadSettings() [Internal]
|
||||||
|
// - TableLoadSettingsForColumns() [Internal]
|
||||||
// - TableSettingsHandler_ClearAll() [Internal]
|
// - TableSettingsHandler_ClearAll() [Internal]
|
||||||
// - TableSettingsHandler_ApplyAll() [Internal]
|
// - TableSettingsHandler_ApplyAll() [Internal]
|
||||||
// - TableSettingsHandler_ReadOpen() [Internal]
|
// - TableSettingsHandler_ReadOpen() [Internal]
|
||||||
@@ -3726,6 +3875,8 @@ static size_t TableSettingsCalcChunkSize(int columns_count)
|
|||||||
ImGuiTableSettings* ImGui::TableSettingsCreate(ImGuiID id, int columns_count)
|
ImGuiTableSettings* ImGui::TableSettingsCreate(ImGuiID id, int columns_count)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
//ImGuiTableSettings* old_settings = TableSettingsFindByID(id); // Comment out sanity check to avoid unnecessary lookups.
|
||||||
|
//IM_ASSERT(old_settings == NULL || old_settings->ColumnsCountMax < columns_count);
|
||||||
ImGuiTableSettings* settings = g.SettingsTables.alloc_chunk(TableSettingsCalcChunkSize(columns_count));
|
ImGuiTableSettings* settings = g.SettingsTables.alloc_chunk(TableSettingsCalcChunkSize(columns_count));
|
||||||
TableSettingsInit(settings, id, columns_count, columns_count);
|
TableSettingsInit(settings, id, columns_count, columns_count);
|
||||||
return settings;
|
return settings;
|
||||||
@@ -3745,16 +3896,12 @@ ImGuiTableSettings* ImGui::TableSettingsFindByID(ImGuiID id)
|
|||||||
// Get settings for a given table, NULL if none
|
// Get settings for a given table, NULL if none
|
||||||
ImGuiTableSettings* ImGui::TableGetBoundSettings(ImGuiTable* table)
|
ImGuiTableSettings* ImGui::TableGetBoundSettings(ImGuiTable* table)
|
||||||
{
|
{
|
||||||
if (table->SettingsOffset != -1)
|
if (table->SettingsOffset == -1)
|
||||||
{
|
return NULL;
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiTableSettings* settings = g.SettingsTables.ptr_from_offset(table->SettingsOffset);
|
ImGuiTableSettings* settings = g.SettingsTables.ptr_from_offset(table->SettingsOffset);
|
||||||
IM_ASSERT(settings->ID == table->ID);
|
IM_ASSERT(settings->ID == table->ID);
|
||||||
if (settings->ColumnsCountMax >= table->ColumnsCount)
|
return settings;
|
||||||
return settings; // OK
|
|
||||||
settings->ID = 0; // Invalidate storage, we won't fit because of a count change
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore initial state of table (with or without saved settings)
|
// Restore initial state of table (with or without saved settings)
|
||||||
@@ -3775,12 +3922,18 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
|||||||
// Bind or create settings data
|
// Bind or create settings data
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiTableSettings* settings = TableGetBoundSettings(table);
|
ImGuiTableSettings* settings = TableGetBoundSettings(table);
|
||||||
|
if (settings != NULL && table->ColumnsCount > settings->ColumnsCountMax)
|
||||||
|
{
|
||||||
|
settings->ID = 0; // Invalidate storage, we won't fit because of a count change
|
||||||
|
settings = NULL;
|
||||||
|
}
|
||||||
if (settings == NULL)
|
if (settings == NULL)
|
||||||
{
|
{
|
||||||
settings = TableSettingsCreate(table->ID, table->ColumnsCount);
|
settings = TableSettingsCreate(table->ID, table->ColumnsCount);
|
||||||
table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings);
|
table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings);
|
||||||
}
|
}
|
||||||
settings->ColumnsCount = (ImGuiTableColumnIdx)table->ColumnsCount;
|
settings->ColumnsCount = (ImGuiTableColumnIdx)table->ColumnsCount;
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
|
|
||||||
// Serialize ImGuiTable/ImGuiTableColumn into ImGuiTableSettings/ImGuiTableColumnSettings
|
// Serialize ImGuiTable/ImGuiTableColumn into ImGuiTableSettings/ImGuiTableColumnSettings
|
||||||
IM_ASSERT(settings->ID == table->ID);
|
IM_ASSERT(settings->ID == table->ID);
|
||||||
@@ -3793,6 +3946,7 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
|||||||
for (int n = 0; n < table->ColumnsCount; n++, column++, column_settings++)
|
for (int n = 0; n < table->ColumnsCount; n++, column++, column_settings++)
|
||||||
{
|
{
|
||||||
const float width_or_weight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? column->StretchWeight : column->WidthRequest;
|
const float width_or_weight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? column->StretchWeight : column->WidthRequest;
|
||||||
|
column_settings->ID = column->ID;
|
||||||
column_settings->WidthOrWeight = width_or_weight;
|
column_settings->WidthOrWeight = width_or_weight;
|
||||||
column_settings->Index = (ImGuiTableColumnIdx)n;
|
column_settings->Index = (ImGuiTableColumnIdx)n;
|
||||||
column_settings->DisplayOrder = column->DisplayOrder;
|
column_settings->DisplayOrder = column->DisplayOrder;
|
||||||
@@ -3824,9 +3978,11 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
|||||||
void ImGui::TableLoadSettings(ImGuiTable* table)
|
void ImGui::TableLoadSettings(ImGuiTable* table)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
table->IsSettingsRequestLoad = false;
|
|
||||||
if (table->Flags & ImGuiTableFlags_NoSavedSettings)
|
if (table->Flags & ImGuiTableFlags_NoSavedSettings)
|
||||||
|
{
|
||||||
|
table->IsSettingsRequestLoad = false; // Done
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Bind settings
|
// Bind settings
|
||||||
ImGuiTableSettings* settings;
|
ImGuiTableSettings* settings;
|
||||||
@@ -3846,44 +4002,84 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
|
|||||||
|
|
||||||
table->SettingsLoadedFlags = settings->SaveFlags;
|
table->SettingsLoadedFlags = settings->SaveFlags;
|
||||||
table->RefScale = settings->RefScale;
|
table->RefScale = settings->RefScale;
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
|
// TableUpdateLayout() will then call TableLoadSettingsForColumns() to apply the data.
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize default columns settings
|
// NB: This was written to be similar to the logic in TableReconcileColumns().
|
||||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
void ImGui::TableLoadSettingsForColumns(ImGuiTable* table)
|
||||||
{
|
{
|
||||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
for (ImGuiTableColumn& column : table->Columns)
|
||||||
TableInitColumnDefaults(table, column, ~0);
|
column.IsLoadedSettings = false;
|
||||||
column->AutoFitQueue = 0x00;
|
ImGuiTableSettings* settings = TableGetBoundSettings(table);
|
||||||
}
|
if (settings == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
table->SettingsLoadedFlags |= ImGuiTableFlags_Reorderable; // We handle above in code above.
|
||||||
|
|
||||||
// Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn
|
// Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn
|
||||||
ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings();
|
ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings();
|
||||||
for (int data_n = 0; data_n < settings->ColumnsCount; data_n++, column_settings++)
|
|
||||||
|
// Fast path
|
||||||
|
int matches = 0;
|
||||||
|
for (int n = 0; n < table->ColumnsCount; n++)
|
||||||
{
|
{
|
||||||
int column_n = column_settings->Index;
|
if (n >= settings->ColumnsCount || column_settings[n].ID != table->Columns[n].ID)
|
||||||
if (column_n < 0 || column_n >= table->ColumnsCount)
|
break;
|
||||||
continue;
|
TableLoadSettingsForColumn(&table->Columns[n], &column_settings[n], settings->SaveFlags);
|
||||||
|
matches++;
|
||||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
|
||||||
if (settings->SaveFlags & ImGuiTableFlags_Resizable)
|
|
||||||
{
|
|
||||||
if (column_settings->IsStretch)
|
|
||||||
column->StretchWeight = column_settings->WidthOrWeight;
|
|
||||||
else
|
|
||||||
column->WidthRequest = column_settings->WidthOrWeight;
|
|
||||||
}
|
|
||||||
if (settings->SaveFlags & ImGuiTableFlags_Reorderable)
|
|
||||||
column->DisplayOrder = column_settings->DisplayOrder;
|
|
||||||
if ((settings->SaveFlags & ImGuiTableFlags_Hideable) && column_settings->IsEnabled != -1)
|
|
||||||
column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled == 1;
|
|
||||||
column->SortOrder = column_settings->SortOrder;
|
|
||||||
column->SortDirection = column_settings->SortDirection;
|
|
||||||
}
|
}
|
||||||
|
if (matches == settings->ColumnsCount)
|
||||||
|
return;
|
||||||
|
const int settings_start_n = matches; // Small optimization
|
||||||
|
for (int n = settings_start_n; n < settings->ColumnsCount; n++)
|
||||||
|
column_settings[n].IsLoaded = false;
|
||||||
|
|
||||||
// Fix display order and build index
|
// Find matches for named columns
|
||||||
if (settings->SaveFlags & ImGuiTableFlags_Reorderable)
|
for (ImGuiTableColumn& column : table->Columns)
|
||||||
TableFixDisplayOrder(table);
|
if (column.ID != 0 && !column.IsLoadedSettings)
|
||||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
for (int n = settings_start_n; n < settings->ColumnsCount; n++)
|
||||||
table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n;
|
if (column_settings[n].ID == column.ID && !column_settings[n].IsLoaded)
|
||||||
|
{
|
||||||
|
TableLoadSettingsForColumn(&column, &column_settings[n], settings->SaveFlags);
|
||||||
|
matches++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remaining entries are matched sequentially
|
||||||
|
int dst_idx = 0;
|
||||||
|
for (int n = settings_start_n; n < settings->ColumnsCount; n++)
|
||||||
|
if (!column_settings[n].IsLoaded)
|
||||||
|
{
|
||||||
|
while (dst_idx < table->ColumnsCount && table->Columns[dst_idx].IsLoadedSettings)
|
||||||
|
dst_idx++;
|
||||||
|
if (dst_idx >= table->ColumnsCount)
|
||||||
|
break;
|
||||||
|
TableLoadSettingsForColumn(&table->Columns[dst_idx], &column_settings[n], settings->SaveFlags);
|
||||||
|
dst_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::TableLoadSettingsForColumn(ImGuiTableColumn* column, ImGuiTableColumnSettings* column_settings, ImGuiTableFlags load_flags)
|
||||||
|
{
|
||||||
|
column->IsLoadedSettings = true;
|
||||||
|
column_settings->IsLoaded = true;
|
||||||
|
if (load_flags & ImGuiTableFlags_Resizable)
|
||||||
|
{
|
||||||
|
if (column_settings->IsStretch)
|
||||||
|
column->StretchWeight = column_settings->WidthOrWeight;
|
||||||
|
else
|
||||||
|
column->WidthRequest = column_settings->WidthOrWeight;
|
||||||
|
column->AutoFitQueue = 0x00;
|
||||||
|
}
|
||||||
|
if (load_flags & ImGuiTableFlags_Reorderable)
|
||||||
|
column->DisplayOrder = column_settings->DisplayOrder;
|
||||||
|
else
|
||||||
|
column->DisplayOrder = column_settings->Index; // Because default depends on previous Index, we need to set that up and cannot rely on TableInitColumnDefaults()
|
||||||
|
if ((load_flags & ImGuiTableFlags_Hideable) && column_settings->IsEnabled != -1)
|
||||||
|
column->IsUserEnabled = column->IsUserEnabledNextFrame = (column_settings->IsEnabled == 1);
|
||||||
|
column->SortOrder = column_settings->SortOrder;
|
||||||
|
column->SortDirection = column_settings->SortDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImGuiTableFixDisplayOrderColumnData
|
struct ImGuiTableFixDisplayOrderColumnData
|
||||||
@@ -3898,7 +4094,8 @@ static int IMGUI_CDECL TableFixDisplayOrderComparer(const void* lhs, const void*
|
|||||||
const ImGuiTable* table = ((const ImGuiTableFixDisplayOrderColumnData*)lhs)->Table;
|
const ImGuiTable* table = ((const ImGuiTableFixDisplayOrderColumnData*)lhs)->Table;
|
||||||
const ImGuiTableColumnIdx lhs_idx = ((const ImGuiTableFixDisplayOrderColumnData*)lhs)->Idx;
|
const ImGuiTableColumnIdx lhs_idx = ((const ImGuiTableFixDisplayOrderColumnData*)lhs)->Idx;
|
||||||
const ImGuiTableColumnIdx rhs_idx = ((const ImGuiTableFixDisplayOrderColumnData*)rhs)->Idx;
|
const ImGuiTableColumnIdx rhs_idx = ((const ImGuiTableFixDisplayOrderColumnData*)rhs)->Idx;
|
||||||
const int order_delta = (table->Columns[lhs_idx].DisplayOrder - table->Columns[rhs_idx].DisplayOrder);
|
// Assume ImGuiTableColumnIdx == signed short, to turn -1 into a large value so that it always sort after.
|
||||||
|
const int order_delta = ((unsigned short)table->Columns[lhs_idx].DisplayOrder - (unsigned short)table->Columns[rhs_idx].DisplayOrder);
|
||||||
return (order_delta > 0) ? +1 : (order_delta < 0) ? -1 : (lhs_idx > rhs_idx) ? +1 : -1;
|
return (order_delta > 0) ? +1 : (order_delta < 0) ? -1 : (lhs_idx > rhs_idx) ? +1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3916,6 +4113,8 @@ void ImGui::TableFixDisplayOrder(ImGuiTable* table)
|
|||||||
ImQsort(fdo_columns, (size_t)table->ColumnsCount, sizeof(ImGuiTableFixDisplayOrderColumnData), TableFixDisplayOrderComparer);
|
ImQsort(fdo_columns, (size_t)table->ColumnsCount, sizeof(ImGuiTableFixDisplayOrderColumnData), TableFixDisplayOrderComparer);
|
||||||
for (int n = 0; n < table->ColumnsCount; n++)
|
for (int n = 0; n < table->ColumnsCount; n++)
|
||||||
table->Columns[fdo_columns[n].Idx].DisplayOrder = (ImGuiTableColumnIdx)n;
|
table->Columns[fdo_columns[n].Idx].DisplayOrder = (ImGuiTableColumnIdx)n;
|
||||||
|
for (int n = 0; n < table->ColumnsCount; n++)
|
||||||
|
table->DisplayOrderToIndex[table->Columns[n].DisplayOrder] = (ImGuiTableColumnIdx)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
||||||
@@ -3927,6 +4126,21 @@ static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
|||||||
g.SettingsTables.clear();
|
g.SettingsTables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TableSettingsHandler_Cleanup(ImGuiContext* ctx, ImGuiSettingsHandler*, ImGuiSettingsCleanupArgs* args)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *ctx;
|
||||||
|
for (int i = 0; i != g.Tables.GetMapSize(); i++)
|
||||||
|
if (ImGuiTable* table = g.Tables.TryGetMapData(i))
|
||||||
|
table->SettingsOffset = -1;
|
||||||
|
for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
|
||||||
|
{
|
||||||
|
if (args->_DiscardOlderThanDate != 0 && settings->LastUsedDate.Unpack() < args->_DiscardOlderThanDate)
|
||||||
|
settings->ID = 0;
|
||||||
|
if (args->SetCurrentSessionDateToAll || (args->SetCurrentSessionDateWhenMissingDate && settings->LastUsedDate.IsValid() == false))
|
||||||
|
settings->LastUsedDate = g.SessionDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply to existing windows (if any)
|
// Apply to existing windows (if any)
|
||||||
static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
||||||
{
|
{
|
||||||
@@ -3966,6 +4180,7 @@ static void TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
|||||||
int column_n = 0, r = 0, n = 0;
|
int column_n = 0, r = 0, n = 0;
|
||||||
|
|
||||||
if (sscanf(line, "RefScale=%f", &f) == 1) { settings->RefScale = f; return; }
|
if (sscanf(line, "RefScale=%f", &f) == 1) { settings->RefScale = f; return; }
|
||||||
|
if (sscanf(line, "LastUsed=%d", &n) == 1) { settings->LastUsedDate = n; return; }
|
||||||
|
|
||||||
if (sscanf(line, "Column %d%n", &column_n, &r) == 1)
|
if (sscanf(line, "Column %d%n", &column_n, &r) == 1)
|
||||||
{
|
{
|
||||||
@@ -3975,12 +4190,13 @@ static void TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
|||||||
char c = 0;
|
char c = 0;
|
||||||
ImGuiTableColumnSettings* column = settings->GetColumnSettings() + column_n;
|
ImGuiTableColumnSettings* column = settings->GetColumnSettings() + column_n;
|
||||||
column->Index = (ImGuiTableColumnIdx)column_n;
|
column->Index = (ImGuiTableColumnIdx)column_n;
|
||||||
if (sscanf(line, "UserID=0x%08X%n", (ImU32*)&n, &r)==1) { line = ImStrSkipBlank(line + r); column->UserID = (ImGuiID)n; }
|
if (sscanf(line, "UserID=0x%08X%n", (ImU32*)&n, &r)==1) { line = ImStrSkipBlank(line + r); } // FIXME-LEGACY: Removed 2025/11/12, was never properly set.
|
||||||
if (sscanf(line, "Width=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = (float)n; column->IsStretch = 0; settings->SaveFlags |= ImGuiTableFlags_Resizable; }
|
if (sscanf(line, "Width=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = (float)n; column->IsStretch = 0; settings->SaveFlags |= ImGuiTableFlags_Resizable; }
|
||||||
if (sscanf(line, "Weight=%f%n", &f, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = f; column->IsStretch = 1; settings->SaveFlags |= ImGuiTableFlags_Resizable; }
|
if (sscanf(line, "Weight=%f%n", &f, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = f; column->IsStretch = 1; settings->SaveFlags |= ImGuiTableFlags_Resizable; }
|
||||||
if (sscanf(line, "Visible=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->IsEnabled = (ImU8)n; settings->SaveFlags |= ImGuiTableFlags_Hideable; }
|
if (sscanf(line, "Visible=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->IsEnabled = (ImU8)n; settings->SaveFlags |= ImGuiTableFlags_Hideable; }
|
||||||
if (sscanf(line, "Order=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->DisplayOrder = (ImGuiTableColumnIdx)n; settings->SaveFlags |= ImGuiTableFlags_Reorderable; }
|
if (sscanf(line, "Order=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->DisplayOrder = (ImGuiTableColumnIdx)n; settings->SaveFlags |= ImGuiTableFlags_Reorderable; }
|
||||||
if (sscanf(line, "Sort=%d%c%n", &n, &c, &r) == 2) { line = ImStrSkipBlank(line + r); column->SortOrder = (ImGuiTableColumnIdx)n; column->SortDirection = (c == '^') ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; settings->SaveFlags |= ImGuiTableFlags_Sortable; }
|
if (sscanf(line, "Sort=%d%c%n", &n, &c, &r) == 2) { line = ImStrSkipBlank(line + r); column->SortOrder = (ImGuiTableColumnIdx)n; column->SortDirection = (c == '^') ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; settings->SaveFlags |= ImGuiTableFlags_Sortable; }
|
||||||
|
if (sscanf(line, "ID=0x%08X%n", (ImU32*)&n, &r) == 1) { line = ImStrSkipBlank(line + r); column->ID = (ImGuiID)n; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4008,18 +4224,21 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
|||||||
for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++)
|
for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++)
|
||||||
{
|
{
|
||||||
// "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v"
|
// "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v"
|
||||||
bool save_column = column->UserID != 0 || save_size || save_visible || save_order || (save_sort && column->SortOrder != -1);
|
bool save_column = save_size || save_visible || save_order || (save_sort && column->SortOrder != -1);
|
||||||
if (!save_column)
|
if (!save_column)
|
||||||
continue;
|
continue;
|
||||||
buf->appendf("Column %-2d", column_n);
|
buf->appendf("Column %-2d", column_n);
|
||||||
if (column->UserID != 0) { buf->appendf(" UserID=%08X", column->UserID); }
|
|
||||||
if (save_size && column->IsStretch) { buf->appendf(" Weight=%.4f", column->WidthOrWeight); }
|
if (save_size && column->IsStretch) { buf->appendf(" Weight=%.4f", column->WidthOrWeight); }
|
||||||
if (save_size && !column->IsStretch) { buf->appendf(" Width=%d", (int)column->WidthOrWeight); }
|
if (save_size && !column->IsStretch) { buf->appendf(" Width=%d", (int)column->WidthOrWeight); }
|
||||||
if (save_visible) { buf->appendf(" Visible=%d", column->IsEnabled); }
|
if (save_visible) { buf->appendf(" Visible=%d", column->IsEnabled); }
|
||||||
if (save_order) { buf->appendf(" Order=%d", column->DisplayOrder); }
|
if (save_order) { buf->appendf(" Order=%d", column->DisplayOrder); }
|
||||||
if (save_sort && column->SortOrder != -1) { buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); }
|
if (save_sort && column->SortOrder != -1) { buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); }
|
||||||
|
if (column->ID != 0) { buf->appendf(" ID=0x%08X", column->ID); }
|
||||||
buf->append("\n");
|
buf->append("\n");
|
||||||
}
|
}
|
||||||
|
if (g.IO.ConfigIniSettingsSaveLastUsedDate)
|
||||||
|
if (int last_used_date = settings->LastUsedDate.Unpack())
|
||||||
|
buf->appendf("LastUsed=%08d\n", last_used_date);
|
||||||
buf->append("\n");
|
buf->append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4030,6 +4249,7 @@ void ImGui::TableSettingsAddSettingsHandler()
|
|||||||
ini_handler.TypeName = "Table";
|
ini_handler.TypeName = "Table";
|
||||||
ini_handler.TypeHash = ImHashStr("Table");
|
ini_handler.TypeHash = ImHashStr("Table");
|
||||||
ini_handler.ClearAllFn = TableSettingsHandler_ClearAll;
|
ini_handler.ClearAllFn = TableSettingsHandler_ClearAll;
|
||||||
|
ini_handler.CleanupFn = TableSettingsHandler_Cleanup;
|
||||||
ini_handler.ReadOpenFn = TableSettingsHandler_ReadOpen;
|
ini_handler.ReadOpenFn = TableSettingsHandler_ReadOpen;
|
||||||
ini_handler.ReadLineFn = TableSettingsHandler_ReadLine;
|
ini_handler.ReadLineFn = TableSettingsHandler_ReadLine;
|
||||||
ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll;
|
ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll;
|
||||||
@@ -4075,11 +4295,12 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
|
|||||||
|
|
||||||
void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data)
|
void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data)
|
||||||
{
|
{
|
||||||
|
temp_data->AngledHeadersRequests.clear();
|
||||||
temp_data->DrawSplitter.ClearFreeMemory();
|
temp_data->DrawSplitter.ClearFreeMemory();
|
||||||
temp_data->LastTimeActive = -1.0f;
|
temp_data->LastTimeActive = -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compact and remove unused settings data (currently only used by TestEngine)
|
// Compact and remove unused or resize settings data (only TestEngine mark unused, but resizing table down can lead to compaction)
|
||||||
void ImGui::TableGcCompactSettings()
|
void ImGui::TableGcCompactSettings()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@@ -4095,6 +4316,9 @@ void ImGui::TableGcCompactSettings()
|
|||||||
if (settings->ID != 0)
|
if (settings->ID != 0)
|
||||||
memcpy(new_chunk_stream.alloc_chunk(TableSettingsCalcChunkSize(settings->ColumnsCount)), settings, TableSettingsCalcChunkSize(settings->ColumnsCount));
|
memcpy(new_chunk_stream.alloc_chunk(TableSettingsCalcChunkSize(settings->ColumnsCount)), settings, TableSettingsCalcChunkSize(settings->ColumnsCount));
|
||||||
g.SettingsTables.swap(new_chunk_stream);
|
g.SettingsTables.swap(new_chunk_stream);
|
||||||
|
for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
|
||||||
|
if (ImGuiTable* table = g.Tables.TryGetMapData(table_n))
|
||||||
|
table->SettingsOffset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4102,6 +4326,7 @@ void ImGui::TableGcCompactSettings()
|
|||||||
// [SECTION] Tables: Debugging
|
// [SECTION] Tables: Debugging
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// - DebugNodeTable() [Internal]
|
// - DebugNodeTable() [Internal]
|
||||||
|
// - DebugNodeTableSettings() [Internal]
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||||
@@ -4165,13 +4390,13 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
|||||||
"WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n"
|
"WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n"
|
||||||
"MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n"
|
"MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n"
|
||||||
"ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n"
|
"ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n"
|
||||||
"Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s..",
|
"Sort: %d%s, UserData: 0x%08X, Flags: 0x%04X: %s%s%s..",
|
||||||
n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "",
|
n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "",
|
||||||
column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen,
|
column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen,
|
||||||
column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f,
|
column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f,
|
||||||
column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x,
|
column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x,
|
||||||
column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX,
|
column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX,
|
||||||
column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags,
|
column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserData, column->Flags,
|
||||||
(column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "",
|
(column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "",
|
||||||
(column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "",
|
(column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "",
|
||||||
(column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : "");
|
(column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : "");
|
||||||
@@ -4184,34 +4409,45 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGuiTableSettings* settings = TableGetBoundSettings(table))
|
if (ImGuiTableSettings* settings = TableGetBoundSettings(table))
|
||||||
DebugNodeTableSettings(settings);
|
DebugNodeTableSettings(settings, table);
|
||||||
if (clear_settings)
|
if (clear_settings)
|
||||||
table->IsResetAllRequest = true;
|
table->IsResetAllRequest = true; // Queue a call to TableResetSettings()
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings)
|
void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings, ImGuiTable* table)
|
||||||
{
|
{
|
||||||
if (!TreeNode((void*)(intptr_t)settings->ID, "Settings 0x%08X (%d columns)", settings->ID, settings->ColumnsCount))
|
if (settings->ID == 0)
|
||||||
return;
|
PushID(settings);
|
||||||
BulletText("SaveFlags: 0x%08X", settings->SaveFlags);
|
const bool open = TreeNode((void*)(intptr_t)settings->ID, "Settings 0x%08X (%d columns)", settings->ID, settings->ColumnsCount);
|
||||||
BulletText("ColumnsCount: %d (max %d)", settings->ColumnsCount, settings->ColumnsCountMax);
|
const bool hovered = IsItemHovered();
|
||||||
for (int n = 0; n < settings->ColumnsCount; n++)
|
if (hovered && table == NULL && settings->ID != 0)
|
||||||
|
table = TableFindByID(settings->ID);
|
||||||
|
if (hovered && table != NULL)
|
||||||
|
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
|
||||||
|
if (open)
|
||||||
{
|
{
|
||||||
ImGuiTableColumnSettings* column_settings = &settings->GetColumnSettings()[n];
|
BulletText("SaveFlags: 0x%08X", settings->SaveFlags);
|
||||||
ImGuiSortDirection sort_dir = (column_settings->SortOrder != -1) ? (ImGuiSortDirection)column_settings->SortDirection : ImGuiSortDirection_None;
|
BulletText("ColumnsCount: %d (max %d)", settings->ColumnsCount, settings->ColumnsCountMax);
|
||||||
BulletText("Column %d Order %d SortOrder %d %s Vis %d %s %7.3f UserID 0x%08X",
|
for (int n = 0; n < settings->ColumnsCount; n++)
|
||||||
n, column_settings->DisplayOrder, column_settings->SortOrder,
|
{
|
||||||
(sort_dir == ImGuiSortDirection_Ascending) ? "Asc" : (sort_dir == ImGuiSortDirection_Descending) ? "Des" : "---",
|
ImGuiTableColumnSettings* column_settings = &settings->GetColumnSettings()[n];
|
||||||
column_settings->IsEnabled, column_settings->IsStretch ? "Weight" : "Width ", column_settings->WidthOrWeight, column_settings->UserID);
|
ImGuiSortDirection sort_dir = (column_settings->SortOrder != -1) ? (ImGuiSortDirection)column_settings->SortDirection : ImGuiSortDirection_None;
|
||||||
|
BulletText("Column %d Order %d SortOrder %2d %s Vis %d %s %7.3f ID 0x%08X",
|
||||||
|
n, column_settings->DisplayOrder, column_settings->SortOrder,
|
||||||
|
(sort_dir == ImGuiSortDirection_Ascending) ? "Asc" : (sort_dir == ImGuiSortDirection_Descending) ? "Des" : "---",
|
||||||
|
column_settings->IsEnabled, column_settings->IsStretch ? "Weight" : "Width ", column_settings->WidthOrWeight, column_settings->ID);
|
||||||
|
}
|
||||||
|
TreePop();
|
||||||
}
|
}
|
||||||
TreePop();
|
if (settings->ID == 0)
|
||||||
|
PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // #ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
#else // #ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||||
|
|
||||||
void ImGui::DebugNodeTable(ImGuiTable*) {}
|
void ImGui::DebugNodeTable(ImGuiTable*) {}
|
||||||
void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {}
|
void ImGui::DebugNodeTableSettings(ImGuiTableSettings*, ImGuiTable*) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// dear imgui, v1.92.8
|
// dear imgui, v1.92.9 WIP
|
||||||
// (widgets code)
|
// (widgets code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -266,6 +266,8 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text),
|
||||||
|
// which will automatically bypass the formatter.
|
||||||
void ImGui::TextUnformatted(const char* text, const char* text_end)
|
void ImGui::TextUnformatted(const char* text, const char* text_end)
|
||||||
{
|
{
|
||||||
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
|
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
|
||||||
@@ -1272,7 +1274,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
|||||||
|
|
||||||
// Range-Selection/Multi-selection support (footer)
|
// Range-Selection/Multi-selection support (footer)
|
||||||
if (is_multi_select)
|
if (is_multi_select)
|
||||||
MultiSelectItemFooter(id, &checked, &pressed);
|
MultiSelectItemFooter(id, &checked, &pressed, ImGuiMultiSelectFlags_CheckboxMode_);
|
||||||
else if (pressed)
|
else if (pressed)
|
||||||
checked = !checked;
|
checked = !checked;
|
||||||
|
|
||||||
@@ -1575,7 +1577,7 @@ bool ImGui::TextLinkOpenURL(const char* label, const char* url)
|
|||||||
bool pressed = TextLink(label);
|
bool pressed = TextLink(label);
|
||||||
if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||||
g.PlatformIO.Platform_OpenInShellFn(&g, url);
|
g.PlatformIO.Platform_OpenInShellFn(&g, url);
|
||||||
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
|
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when it is the same as the label.
|
||||||
if (BeginPopupContextItem())
|
if (BeginPopupContextItem())
|
||||||
{
|
{
|
||||||
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink)))
|
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink)))
|
||||||
@@ -1746,14 +1748,14 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
|||||||
const float separator_thickness = style.SeparatorTextBorderSize;
|
const float separator_thickness = style.SeparatorTextBorderSize;
|
||||||
const ImVec2 min_size(label_size.x + extra_w + padding.x * 2.0f, ImMax(label_size.y + padding.y * 2.0f, separator_thickness));
|
const ImVec2 min_size(label_size.x + extra_w + padding.x * 2.0f, ImMax(label_size.y + padding.y * 2.0f, separator_thickness));
|
||||||
const ImRect bb(pos, ImVec2(window->WorkRect.Max.x, pos.y + min_size.y));
|
const ImRect bb(pos, ImVec2(window->WorkRect.Max.x, pos.y + min_size.y));
|
||||||
const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.99999f); //ImMax(padding.y, ImTrunc((style.SeparatorTextSize - label_size.y) * 0.5f));
|
const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.999f); //ImMax(padding.y, ImTrunc((style.SeparatorTextSize - label_size.y) * 0.5f));
|
||||||
ItemSize(min_size, text_baseline_y);
|
ItemSize(min_size, text_baseline_y);
|
||||||
if (!ItemAdd(bb, id))
|
if (!ItemAdd(bb, id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float sep1_x1 = pos.x;
|
const float sep1_x1 = pos.x;
|
||||||
const float sep2_x2 = bb.Max.x;
|
const float sep2_x2 = bb.Max.x;
|
||||||
const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.99999f);
|
const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.999f);
|
||||||
|
|
||||||
const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f);
|
const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f);
|
||||||
const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN
|
const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN
|
||||||
@@ -5641,7 +5643,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||||
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
|
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), style.InputTextCursorSize);
|
||||||
|
|
||||||
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
||||||
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
||||||
@@ -5749,7 +5751,6 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
|
|||||||
// - RenderColorRectWithAlphaCheckerboard() [Internal]
|
// - RenderColorRectWithAlphaCheckerboard() [Internal]
|
||||||
// - ColorPicker4()
|
// - ColorPicker4()
|
||||||
// - ColorButton()
|
// - ColorButton()
|
||||||
// - SetColorEditOptions()
|
|
||||||
// - ColorTooltip() [Internal]
|
// - ColorTooltip() [Internal]
|
||||||
// - ColorEditOptionsPopup() [Internal]
|
// - ColorEditOptionsPopup() [Internal]
|
||||||
// - ColorPickerOptionsPopup() [Internal]
|
// - ColorPickerOptionsPopup() [Internal]
|
||||||
@@ -5821,14 +5822,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
|||||||
|
|
||||||
// Read stored options
|
// Read stored options
|
||||||
if (!(flags & ImGuiColorEditFlags_DisplayMask_))
|
if (!(flags & ImGuiColorEditFlags_DisplayMask_))
|
||||||
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_);
|
flags |= (g.IO.ColorEditFlags & ImGuiColorEditFlags_DisplayMask_);
|
||||||
if (!(flags & ImGuiColorEditFlags_DataTypeMask_))
|
if (!(flags & ImGuiColorEditFlags_DataTypeMask_))
|
||||||
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_);
|
flags |= (g.IO.ColorEditFlags & ImGuiColorEditFlags_DataTypeMask_);
|
||||||
if (!(flags & ImGuiColorEditFlags_PickerMask_))
|
if (!(flags & ImGuiColorEditFlags_PickerMask_))
|
||||||
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_);
|
flags |= (g.IO.ColorEditFlags & ImGuiColorEditFlags_PickerMask_);
|
||||||
if (!(flags & ImGuiColorEditFlags_InputMask_))
|
if (!(flags & ImGuiColorEditFlags_InputMask_))
|
||||||
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_);
|
flags |= (g.IO.ColorEditFlags & ImGuiColorEditFlags_InputMask_);
|
||||||
flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));
|
flags |= (g.IO.ColorEditFlags & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
|
||||||
|
|
||||||
@@ -6097,13 +6098,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
|||||||
|
|
||||||
// Read stored options
|
// Read stored options
|
||||||
if (!(flags & ImGuiColorEditFlags_PickerMask_))
|
if (!(flags & ImGuiColorEditFlags_PickerMask_))
|
||||||
flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;
|
flags |= ((g.IO.ColorEditFlags & ImGuiColorEditFlags_PickerMask_) ? g.IO.ColorEditFlags : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;
|
||||||
if (!(flags & ImGuiColorEditFlags_InputMask_))
|
if (!(flags & ImGuiColorEditFlags_InputMask_))
|
||||||
flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;
|
flags |= ((g.IO.ColorEditFlags & ImGuiColorEditFlags_InputMask_) ? g.IO.ColorEditFlags : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
|
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
|
||||||
if (!(flags & ImGuiColorEditFlags_NoOptions))
|
if (!(flags & ImGuiColorEditFlags_NoOptions))
|
||||||
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
|
flags |= (g.IO.ColorEditFlags & ImGuiColorEditFlags_AlphaBar);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
|
int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
|
||||||
@@ -6523,25 +6524,18 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
|||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize/override default color options
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
// FIXME: Could be moved to a simple IO field.
|
// This allowed passing 0 to set default, whereas NewFrame() will assert if one of missing. Abide to old logic.
|
||||||
void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
|
void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0)
|
if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_; }
|
||||||
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_;
|
if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_; }
|
||||||
if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0)
|
if ((flags & ImGuiColorEditFlags_PickerMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_; }
|
||||||
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_;
|
if ((flags & ImGuiColorEditFlags_InputMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_; }
|
||||||
if ((flags & ImGuiColorEditFlags_PickerMask_) == 0)
|
g.IO.ColorEditFlags = flags;
|
||||||
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_;
|
|
||||||
if ((flags & ImGuiColorEditFlags_InputMask_) == 0)
|
|
||||||
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_;
|
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected
|
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected
|
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected
|
|
||||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected
|
|
||||||
g.ColorEditOptions = flags;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
|
// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
|
||||||
void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
|
void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
|
||||||
@@ -6589,7 +6583,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
|
|||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
|
PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
|
||||||
ImGuiColorEditFlags opts = g.ColorEditOptions;
|
ImGuiColorEditFlags opts = g.IO.ColorEditFlags;
|
||||||
if (allow_opt_inputs)
|
if (allow_opt_inputs)
|
||||||
{
|
{
|
||||||
if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB;
|
if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB;
|
||||||
@@ -6629,7 +6623,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
|
|||||||
EndPopup();
|
EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
g.ColorEditOptions = opts;
|
g.IO.ColorEditFlags = opts;
|
||||||
PopItemFlag();
|
PopItemFlag();
|
||||||
EndPopup();
|
EndPopup();
|
||||||
}
|
}
|
||||||
@@ -6657,7 +6651,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
|
|||||||
if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
|
if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
|
||||||
ImVec2 backup_pos = GetCursorScreenPos();
|
ImVec2 backup_pos = GetCursorScreenPos();
|
||||||
if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
|
if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
|
||||||
g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_);
|
g.IO.ColorEditFlags = (g.IO.ColorEditFlags & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_);
|
||||||
SetCursorScreenPos(backup_pos);
|
SetCursorScreenPos(backup_pos);
|
||||||
ImVec4 previewing_ref_col;
|
ImVec4 previewing_ref_col;
|
||||||
memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));
|
memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));
|
||||||
@@ -6669,7 +6663,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
|
|||||||
if (allow_opt_alpha_bar)
|
if (allow_opt_alpha_bar)
|
||||||
{
|
{
|
||||||
if (allow_opt_picker) Separator();
|
if (allow_opt_picker) Separator();
|
||||||
CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
|
CheckboxFlags("Alpha Bar", &g.IO.ColorEditFlags, ImGuiColorEditFlags_AlphaBar);
|
||||||
}
|
}
|
||||||
PopItemFlag();
|
PopItemFlag();
|
||||||
EndPopup();
|
EndPopup();
|
||||||
@@ -7114,9 +7108,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|||||||
if (hovered || selected)
|
if (hovered || selected)
|
||||||
{
|
{
|
||||||
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false, 0.0f);
|
||||||
}
|
}
|
||||||
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
RenderNavCursor(frame_bb, id, nav_render_cursor_flags, 0.0f);
|
||||||
if (span_all_columns && !span_all_columns_label)
|
if (span_all_columns && !span_all_columns_label)
|
||||||
TablePopBackgroundChannel();
|
TablePopBackgroundChannel();
|
||||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||||
@@ -7487,6 +7481,11 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
|||||||
|
|
||||||
if (selected != was_selected)
|
if (selected != was_selected)
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
|
||||||
|
if (g.ActiveId == id && g.ActiveIdIsJustActivated)
|
||||||
|
{
|
||||||
|
g.ActiveIdWasSelected = was_selected;
|
||||||
|
g.ActiveIdWasSoleSelected = was_selected && (!is_multi_select || g.CurrentMultiSelect->IsSoleOrUnknownSelectionSize);
|
||||||
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
if (is_visible)
|
if (is_visible)
|
||||||
@@ -7496,14 +7495,14 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
|||||||
{
|
{
|
||||||
// Between 1.91.0 and 1.91.4 we made selected Selectable use an arbitrary lerp between _Header and _HeaderHovered. Removed that now. (#8106)
|
// Between 1.91.0 and 1.91.4 we made selected Selectable use an arbitrary lerp between _Header and _HeaderHovered. Removed that now. (#8106)
|
||||||
ImU32 col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
ImU32 col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||||
RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
|
RenderFrame(bb.Min, bb.Max, col, false, style.SelectableRounding);
|
||||||
}
|
}
|
||||||
if (g.NavId == id)
|
if (g.NavId == id)
|
||||||
{
|
{
|
||||||
ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding;
|
ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact;
|
||||||
if (is_multi_select)
|
if (is_multi_select)
|
||||||
nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
|
nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
|
||||||
RenderNavCursor(bb, id, nav_render_cursor_flags);
|
RenderNavCursor(bb, id, nav_render_cursor_flags, style.SelectableRounding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8114,6 +8113,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
|||||||
storage->LastSelectionSize = 0;
|
storage->LastSelectionSize = 0;
|
||||||
}
|
}
|
||||||
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
|
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
|
||||||
|
ms->IsSoleOrUnknownSelectionSize = (storage->LastSelectionSize == 1) || (storage->LastSelectionSize == -1);
|
||||||
//ms->PrevSubmittedItem = ImGuiSelectionUserData_Invalid;
|
//ms->PrevSubmittedItem = ImGuiSelectionUserData_Invalid;
|
||||||
|
|
||||||
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
|
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
|
||||||
@@ -8305,7 +8305,7 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
|
|||||||
// - Altering selection based on Ctrl/Shift modifiers, both for keyboard and mouse.
|
// - Altering selection based on Ctrl/Shift modifiers, both for keyboard and mouse.
|
||||||
// - Record current selection state for RangeSrc
|
// - Record current selection state for RangeSrc
|
||||||
// This is all rather complex, best to run and refer to "widgets_multiselect_xxx" tests in imgui_test_suite.
|
// This is all rather complex, best to run and refer to "widgets_multiselect_xxx" tests in imgui_test_suite.
|
||||||
void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed, ImGuiMultiSelectFlags extra_flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
@@ -8325,7 +8325,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|||||||
|
|
||||||
ImGuiSelectionUserData item_data = g.NextItemData.SelectionUserData;
|
ImGuiSelectionUserData item_data = g.NextItemData.SelectionUserData;
|
||||||
|
|
||||||
ImGuiMultiSelectFlags flags = ms->Flags;
|
ImGuiMultiSelectFlags flags = ms->Flags | extra_flags;
|
||||||
const bool is_singleselect = (flags & ImGuiMultiSelectFlags_SingleSelect) != 0;
|
const bool is_singleselect = (flags & ImGuiMultiSelectFlags_SingleSelect) != 0;
|
||||||
bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0;
|
bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0;
|
||||||
bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0;
|
bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0;
|
||||||
@@ -8479,7 +8479,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|||||||
//IM_ASSERT(storage->HasRangeSrc && storage->HasRangeValue);
|
//IM_ASSERT(storage->HasRangeSrc && storage->HasRangeValue);
|
||||||
if (storage->RangeSrcItem == ImGuiSelectionUserData_Invalid)
|
if (storage->RangeSrcItem == ImGuiSelectionUserData_Invalid)
|
||||||
storage->RangeSrcItem = item_data;
|
storage->RangeSrcItem = item_data;
|
||||||
if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0)
|
if ((flags & ImGuiMultiSelectFlags_CheckboxMode_) == 0)
|
||||||
{
|
{
|
||||||
// Shift+Arrow always select
|
// Shift+Arrow always select
|
||||||
// Ctrl+Shift+Arrow copy source selection state (already stored by BeginMultiSelect() in storage->RangeSelected)
|
// Ctrl+Shift+Arrow copy source selection state (already stored by BeginMultiSelect() in storage->RangeSelected)
|
||||||
@@ -8499,7 +8499,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Ctrl inverts selection, otherwise always select
|
// Ctrl inverts selection, otherwise always select
|
||||||
if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0)
|
if ((flags & ImGuiMultiSelectFlags_CheckboxMode_) == 0)
|
||||||
selected = is_ctrl ? !selected : true;
|
selected = is_ctrl ? !selected : true;
|
||||||
else
|
else
|
||||||
selected = !selected;
|
selected = !selected;
|
||||||
@@ -8950,7 +8950,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
|||||||
// Tooltip on hover
|
// Tooltip on hover
|
||||||
if (hovered && inner_bb.Contains(g.IO.MousePos))
|
if (hovered && inner_bb.Contains(g.IO.MousePos))
|
||||||
{
|
{
|
||||||
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
|
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.999f);
|
||||||
const int v_idx = (int)(t * item_count);
|
const int v_idx = (int)(t * item_count);
|
||||||
IM_ASSERT(v_idx >= 0 && v_idx < values_count);
|
IM_ASSERT(v_idx >= 0 && v_idx < values_count);
|
||||||
|
|
||||||
@@ -9348,7 +9348,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
const ImGuiStyle& style = g.Style;
|
ImGuiStyle& style = g.Style;
|
||||||
const ImGuiID id = window->GetID(label);
|
const ImGuiID id = window->GetID(label);
|
||||||
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
|
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
|
||||||
|
|
||||||
@@ -9380,7 +9380,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
// This is only done for items for the menu set and not the full parent window.
|
// This is only done for items for the menu set and not the full parent window.
|
||||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||||
if (menuset_is_open)
|
if (menuset_is_open)
|
||||||
PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true);
|
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoWindowHoverableCheck;
|
||||||
|
|
||||||
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
|
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
|
||||||
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
|
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
|
||||||
@@ -9393,6 +9393,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
|
|
||||||
bool pressed;
|
bool pressed;
|
||||||
|
|
||||||
|
const float backup_rounding = style.SelectableRounding;
|
||||||
|
style.SelectableRounding = style.MenuItemRounding;
|
||||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick;
|
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick;
|
||||||
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||||
@@ -9428,6 +9430,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
|
RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
|
||||||
popup_pos = ImVec2(pos.x, text_pos.y - style.WindowPadding.y);
|
popup_pos = ImVec2(pos.x, text_pos.y - style.WindowPadding.y);
|
||||||
}
|
}
|
||||||
|
style.SelectableRounding = backup_rounding;
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
EndDisabled();
|
EndDisabled();
|
||||||
|
|
||||||
@@ -9440,8 +9443,6 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
|
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
|
||||||
if (menuset_is_open)
|
|
||||||
PopItemFlag();
|
|
||||||
|
|
||||||
bool want_open = false;
|
bool want_open = false;
|
||||||
bool want_open_nav_init = false;
|
bool want_open_nav_init = false;
|
||||||
@@ -9604,7 +9605,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
// See BeginMenuEx() for comments about this.
|
// See BeginMenuEx() for comments about this.
|
||||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||||
if (menuset_is_open)
|
if (menuset_is_open)
|
||||||
PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true);
|
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoWindowHoverableCheck;
|
||||||
|
|
||||||
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
|
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
|
||||||
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
|
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
|
||||||
@@ -9614,6 +9615,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
BeginDisabled();
|
BeginDisabled();
|
||||||
|
|
||||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||||
|
const float backup_rounding = style.SelectableRounding;
|
||||||
|
style.SelectableRounding = style.MenuItemRounding;
|
||||||
const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover;
|
const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover;
|
||||||
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||||
@@ -9636,7 +9639,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.)
|
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.)
|
||||||
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
|
||||||
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
|
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
|
||||||
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
|
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); // FIXME: Always accounted for, even in a menu with none, because 'selected' has no neutral setting.
|
||||||
float min_w = offsets->DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
float min_w = offsets->DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
||||||
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||||
ImVec2 text_pos(pos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
ImVec2 text_pos(pos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
@@ -9657,6 +9660,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
|
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
style.SelectableRounding = backup_rounding;
|
||||||
|
|
||||||
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
|
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
|
||||||
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
|
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
|
||||||
@@ -9672,8 +9676,6 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|||||||
if (!enabled)
|
if (!enabled)
|
||||||
EndDisabled();
|
EndDisabled();
|
||||||
PopID();
|
PopID();
|
||||||
if (menuset_is_open)
|
|
||||||
PopItemFlag();
|
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
@@ -10871,13 +10873,9 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
|
|||||||
IM_UNUSED(flags);
|
IM_UNUSED(flags);
|
||||||
IM_ASSERT(width > 0.0f);
|
IM_ASSERT(width > 0.0f);
|
||||||
const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f));
|
const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f));
|
||||||
const float y1 = bb.Min.y + 1.0f;
|
const float y1 = bb.Min.y + 1.0f; // Leave a bit of room in title bars.
|
||||||
const float y2 = bb.Max.y - g.Style.TabBarBorderSize;
|
const float y2 = bb.Max.y - g.Style.TabBarBorderSize;
|
||||||
draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
|
draw_list->AddRectFilled(bb.Min, ImVec2(bb.Max.x, y2), col, rounding, ImDrawFlags_RoundCornersTop);
|
||||||
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
|
|
||||||
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
|
|
||||||
draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
|
|
||||||
draw_list->PathFillConvex(col);
|
|
||||||
if (g.Style.TabBorderSize > 0.0f)
|
if (g.Style.TabBorderSize > 0.0f)
|
||||||
{
|
{
|
||||||
draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
|
draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
|
||||||
|
|||||||
Reference in New Issue
Block a user