mirror of
https://github.com/Drezil/imgui.git
synced 2025-11-09 01:21:24 +01:00
Compare commits
34 Commits
features/t
...
features/r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a02d500990 | ||
|
|
a7977d1e8b | ||
|
|
910d83951d | ||
|
|
f68e03d92e | ||
|
|
4c376cb3e5 | ||
|
|
304270a99a | ||
|
|
dd52a2854c | ||
|
|
abfa8487eb | ||
|
|
72da877c4c | ||
|
|
0d73bf3755 | ||
|
|
9b925d51bb | ||
|
|
1b069b5d32 | ||
|
|
0d535afb41 | ||
|
|
28ba54a32a | ||
|
|
fd06ed833b | ||
|
|
0cff5ac5a1 | ||
|
|
de451d4474 | ||
|
|
279db55840 | ||
|
|
3deb92c2c5 | ||
|
|
0f14933577 | ||
|
|
6315716f23 | ||
|
|
1e18da5c38 | ||
|
|
54fb051e52 | ||
|
|
fa2b318dd6 | ||
|
|
5659db5529 | ||
|
|
a61ca097a7 | ||
|
|
dca527be1b | ||
|
|
29d462ebce | ||
|
|
421e73e6db | ||
|
|
d9e60d29e1 | ||
|
|
5c8f8d0311 | ||
|
|
2dfa71fad5 | ||
|
|
7ff41a78f9 | ||
|
|
8d3906365d |
28
.github/workflows/build.yml
vendored
28
.github/workflows/build.yml
vendored
@@ -246,7 +246,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -Wextra -Werror -Wno-zero-as-null-pointer-constant -Wno-double-promotion -Wno-variadic-macros -Wno-empty-body -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -Wextra -Werror -Wno-zero-as-null-pointer-constant -Wno-double-promotion -Wno-variadic-macros -Wno-empty-body -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (freetype)
|
||||
run: |
|
||||
@@ -262,7 +262,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with ImWchar32)
|
||||
run: |
|
||||
@@ -274,7 +274,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
|
||||
run: |
|
||||
@@ -287,7 +287,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
|
||||
run: |
|
||||
@@ -299,7 +299,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_OBSOLETE_KEYIO)
|
||||
run: |
|
||||
@@ -311,7 +311,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_METRICS_WINDOW)
|
||||
run: |
|
||||
@@ -324,7 +324,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_DISABLE_FILE_FUNCTIONS)
|
||||
run: |
|
||||
@@ -336,7 +336,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IMGUI_USE_BGRA_PACKED_COLOR)
|
||||
run: |
|
||||
@@ -348,7 +348,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with IM_VEC2_CLASS_EXTRA and IM_VEC4_CLASS_EXTRA)
|
||||
run: |
|
||||
@@ -368,7 +368,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (without c++ runtime, Clang)
|
||||
run: |
|
||||
@@ -380,7 +380,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_glfw_opengl2
|
||||
run: make -C examples/example_glfw_opengl2
|
||||
@@ -397,7 +397,7 @@ jobs:
|
||||
run: make -C examples/example_sdl_opengl3
|
||||
|
||||
- name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES
|
||||
run: g++ -c -I. -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
|
||||
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
|
||||
|
||||
MacOS:
|
||||
runs-on: macos-latest
|
||||
@@ -420,7 +420,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (without c++ runtime)
|
||||
run: |
|
||||
@@ -431,7 +431,7 @@ jobs:
|
||||
#include "examples/example_null/main.cpp"
|
||||
|
||||
EOF
|
||||
clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
clang++ -I. -std=c++11 -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_glfw_opengl2
|
||||
run: make -C examples/example_glfw_opengl2
|
||||
|
||||
@@ -71,7 +71,7 @@ struct ImGui_ImplAllegro5_Data
|
||||
ALLEGRO_VERTEX_DECL* VertexDecl;
|
||||
char* ClipboardTextData;
|
||||
|
||||
ImGui_ImplAllegro5_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplAllegro5_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
@@ -456,8 +456,8 @@ static void ImGui_ImplAllegro5_UpdateKeyModifiers()
|
||||
}
|
||||
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ struct ImGui_ImplDX10_Data
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
ImGui_ImplDX10_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
ImGui_ImplDX10_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
|
||||
@@ -60,7 +60,7 @@ struct ImGui_ImplDX11_Data
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
ImGui_ImplDX11_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
|
||||
@@ -71,7 +71,7 @@ struct ImGui_ImplDX12_Data
|
||||
UINT numFramesInFlight;
|
||||
UINT frameIndex;
|
||||
|
||||
ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
|
||||
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
|
||||
@@ -46,7 +46,7 @@ struct ImGui_ImplDX9_Data
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
ImGui_ImplDX9_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
|
||||
@@ -105,7 +105,7 @@ struct ImGui_ImplGlfw_Data
|
||||
GLFWcharfun PrevUserCallbackChar;
|
||||
GLFWmonitorfun PrevUserCallbackMonitor;
|
||||
|
||||
ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
|
||||
@@ -269,7 +269,7 @@ void ImGui_ImplGLUT_MouseFunc(int glut_button, int state, int x, int y)
|
||||
if (glut_button == GLUT_LEFT_BUTTON) button = 0;
|
||||
if (glut_button == GLUT_RIGHT_BUTTON) button = 1;
|
||||
if (glut_button == GLUT_MIDDLE_BUTTON) button = 2;
|
||||
if (button != -1 && state == GLUT_DOWN || state == GLUT_UP)
|
||||
if (button != -1 && (state == GLUT_DOWN || state == GLUT_UP))
|
||||
io.AddMouseButtonEvent(button, state == GLUT_DOWN);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ struct ImGui_ImplOpenGL2_Data
|
||||
{
|
||||
GLuint FontTexture;
|
||||
|
||||
ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
|
||||
@@ -193,7 +193,7 @@ struct ImGui_ImplOpenGL3_Data
|
||||
GLsizeiptr IndexBufferSize;
|
||||
bool HasClipOrigin;
|
||||
|
||||
ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
|
||||
@@ -648,7 +648,7 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
wheel_dx = [event deltaX];
|
||||
wheel_dy = [event deltaY];
|
||||
}
|
||||
if (wheel_dx != 0.0 || wheel_dx != 0.0)
|
||||
if (wheel_dx != 0.0 || wheel_dy != 0.0)
|
||||
io.AddMouseWheelEvent((float)wheel_dx * 0.1f, (float)wheel_dy * 0.1f);
|
||||
|
||||
return io.WantCaptureMouse;
|
||||
|
||||
@@ -87,7 +87,7 @@ struct ImGui_ImplSDL2_Data
|
||||
char* ClipboardTextData;
|
||||
bool MouseCanUseGlobalState;
|
||||
|
||||
ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
@@ -237,8 +237,8 @@ static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
|
||||
}
|
||||
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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 you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
|
||||
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
|
||||
|
||||
@@ -42,7 +42,7 @@ struct ImGui_ImplSDLRenderer_Data
|
||||
{
|
||||
SDL_Renderer* SDLRenderer;
|
||||
SDL_Texture* FontTexture;
|
||||
ImGui_ImplSDLRenderer_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplSDLRenderer_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
|
||||
@@ -118,7 +118,7 @@ struct ImGui_ImplVulkan_Data
|
||||
|
||||
ImGui_ImplVulkan_Data()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
memset((void*)this, 0, sizeof(*this));
|
||||
BufferMemoryAlignment = 256;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -147,7 +147,7 @@ struct ImGui_ImplVulkanH_Window
|
||||
|
||||
ImGui_ImplVulkanH_Window()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
memset((void*)this, 0, sizeof(*this));
|
||||
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
|
||||
ClearEnable = true;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ struct ImGui_ImplWin32_Data
|
||||
PFN_XInputGetState XInputGetState;
|
||||
#endif
|
||||
|
||||
ImGui_ImplWin32_Data() { memset(this, 0, sizeof(*this)); }
|
||||
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||
@@ -488,10 +488,10 @@ static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam)
|
||||
#endif
|
||||
|
||||
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
|
||||
// Call from your application's message handler.
|
||||
// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
// When implementing your own backend, 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
|
||||
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
|
||||
|
||||
@@ -22,6 +22,8 @@ IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||
// Win32 message handler your application need to call.
|
||||
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||
|
||||
#if 0
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
@@ -39,8 +39,34 @@ Breaking changes:
|
||||
|
||||
Other Changes:
|
||||
|
||||
- IO: Fixed backward-compatibility regression introduced in 1.87: (#4921, #4858)
|
||||
- Direct accesses to io.KeysDown[] with legacy indices didn't work (with new backends).
|
||||
- Direct accesses to io.KeysDown[GetKeyIndex(XXX)] would access invalid data (with old/new backends).
|
||||
- Calling IsKeyDown() didn't have those problems, and is recommended as io.KeysDown[] is obsolete.
|
||||
- IO: Fixed input queue trickling of interleaved keys/chars events (which are frequent especially
|
||||
when holding down a key as OS submits chars repeat events) delaying key presses and mouse movements.
|
||||
In particular, using the input system for fast game-like actions (e.g. WASD camera move) would
|
||||
typically have been impacted, as well as holding a key while dragging mouse. Constraints have
|
||||
been lifted and are now only happening when e.g. an InputText() widget is active. (#4921, #4858)
|
||||
Not that even thought you shouldn't need to disable io.ConfigInputTrickleEventQueue, you can
|
||||
technically dynamically change its setting based on the context (e.g. disable only when hovering
|
||||
or interacting with a game/3D view).
|
||||
- Clipper: Fixed a regression in 1.86 when not calling clipper.End() and late destructing the
|
||||
clipper instance. High-level languages (Lua,Rust etc.) would typically be affected. (#4822)
|
||||
- IsItemHovered(): added ImGuiHoveredFlags_NoNavOverride to disable the behavior where the
|
||||
return value is overriden by focus when gamepad/keyboard navigation is active.
|
||||
- Tables: Fixed incorrect border height used for logic when resizing one of several synchronized
|
||||
instance of a same table ID, when instances have a different height. (#3955).
|
||||
- Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate.
|
||||
- ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label.
|
||||
- Stack Tool: Added option to copy item path to clipboard. (#4631)
|
||||
- Misc: Fixed IsAnyItemHovered() returning false when using navigation.
|
||||
- Misc: Added IMGUI_STB_SPRINTF_FILENAME to support custom path to stb_sprintf. (#5068, #2954) [@jakubtomsu]
|
||||
- Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan]
|
||||
- Misc: Updated stb_truetype.h from 1.20 to 1.26 (many fixes). (#5075)
|
||||
- Misc: Updated stb_textedit.h from 1.13 to 1.14 (our changes so this effectively is a no-op). (#5075)
|
||||
- Misc: Updated stb_rect_pack.h from 1.00 to 1.01 (minor). (#5075)
|
||||
- Misc: binary_to_compressed_c tool: Added -nostatic option. (#5021) [@podsvirov]
|
||||
- ImVector: Fixed erase() with empty range. (#5009) [@thedmd]
|
||||
- Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd]
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ See [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
|
||||
Sponsors
|
||||
--------
|
||||
|
||||
Ongoing Dear ImGui development is currently financially supported by users and private sponsors:
|
||||
Ongoing Dear ImGui development is currently financially supported in 2021-2022 by users and private sponsors:
|
||||
|
||||
*Platinum-chocolate sponsors*
|
||||
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1)
|
||||
@@ -204,12 +204,12 @@ Ongoing Dear ImGui development is currently financially supported by users and p
|
||||
- [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui), [Supercell](https://supercell.com)
|
||||
|
||||
*Chocolate sponsors*
|
||||
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [RAD Game Tools](http://www.radgametools.com/)
|
||||
- [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Epic](https://www.unrealengine.com/en-US/megagrants), [G3Dvu]().
|
||||
|
||||
*Salty-caramel sponsors*
|
||||
- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com)
|
||||
- [Kylotonn](https://www.kylotonn.com), [O-Net Communications (USA)](http://en.o-netcom.com), [Wonderland Engine](https://wonderlandengine.com/).
|
||||
|
||||
Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors.
|
||||
Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for sponsors of past years.
|
||||
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
|
||||
|
||||
**THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**
|
||||
|
||||
@@ -69,8 +69,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
ALLEGRO_EVENT ev;
|
||||
while (al_get_next_event(queue, &ev))
|
||||
|
||||
@@ -111,8 +111,8 @@ static void main_loop(void* arg)
|
||||
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -17,7 +17,7 @@ LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -f
|
||||
LIBS += -L/usr/local/lib -L/opt/homebrew/lib
|
||||
LIBS += -lglfw
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
||||
|
||||
@@ -88,8 +88,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
glfwPollEvents();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -80,8 +80,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
glfwPollEvents();
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
LINUX_GL_LIBS = -lGL
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -101,8 +101,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
glfwPollEvents();
|
||||
|
||||
|
||||
@@ -467,8 +467,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
glfwPollEvents();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glut.cpp $(IMGUI_DIR)/backends/imgui
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -94,8 +94,8 @@ void glut_display_func()
|
||||
}
|
||||
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -125,6 +125,7 @@ int main(int argc, char** argv)
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
// FIXME: Consider reworking this example to install our own GLUT funcs + forward calls ImGui_ImplGLUT_XXX ones, instead of using ImGui_ImplGLUT_InstallFuncs().
|
||||
ImGui_ImplGLUT_Init();
|
||||
ImGui_ImplGLUT_InstallFuncs();
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
@@ -17,7 +17,7 @@ SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
CXXFLAGS += -I$(IMGUI_DIR)
|
||||
CXXFLAGS += -std=c++11 -I$(IMGUI_DIR)
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
@@ -52,7 +52,7 @@ endif
|
||||
ifeq ($(UNAME_S), Darwin) #APPLE
|
||||
ECHO_MESSAGE = "Mac OS X"
|
||||
ifeq ($(WITH_EXTRA_WARNINGS), 1)
|
||||
CXXFLAGS += -Weverything -Wno-reserved-id-macro -Wno-c++98-compat-pedantic -Wno-padded -Wno-c++11-long-long -Wno-poison-system-directories
|
||||
CXXFLAGS += -Weverything -Wno-reserved-id-macro -Wno-c++98-compat-pedantic -Wno-padded -Wno-poison-system-directories
|
||||
endif
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
@@ -91,8 +91,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -17,7 +17,7 @@ LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -f
|
||||
LIBS += `sdl2-config --libs`
|
||||
LIBS += -L/usr/local/lib
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include
|
||||
CXXFLAGS += `sdl2-config --cflags`
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
||||
@@ -88,8 +88,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -22,7 +22,7 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -23,7 +23,7 @@ OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
LINUX_GL_LIBS = -lGL
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -101,8 +101,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -22,7 +22,7 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -460,8 +460,8 @@ int main(int, char**)
|
||||
{
|
||||
// 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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// - 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.
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
|
||||
@@ -82,10 +82,7 @@ int main(int, char**)
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// See the WndProc() function below for our to dispatch events to the Win32 backend.
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
@@ -215,6 +212,10 @@ void CleanupRenderTarget()
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// Win32 message handler
|
||||
// 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.
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
|
||||
@@ -82,10 +82,7 @@ int main(int, char**)
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// See the WndProc() function below for our to dispatch events to the Win32 backend.
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
@@ -219,6 +216,10 @@ void CleanupRenderTarget()
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// Win32 message handler
|
||||
// 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.
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
|
||||
@@ -120,10 +120,7 @@ int main(int, char**)
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// See the WndProc() function below for our to dispatch events to the Win32 backend.
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
@@ -435,6 +432,10 @@ FrameContext* WaitForNextFrameResources()
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// Win32 message handler
|
||||
// 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.
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
|
||||
@@ -80,10 +80,7 @@ int main(int, char**)
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (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.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// See the WndProc() function below for our to dispatch events to the Win32 backend.
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
@@ -209,6 +206,10 @@ void ResetDevice()
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// Win32 message handler
|
||||
// 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.
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
|
||||
@@ -62,12 +62,13 @@
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
|
||||
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
||||
// #define IMGUI_USE_STB_SPRINTF
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
//#define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
|
||||
170
imgui.cpp
170
imgui.cpp
@@ -1070,7 +1070,6 @@ ImGuiStyle::ImGuiStyle()
|
||||
AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
|
||||
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering.
|
||||
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
|
||||
RoundCornersUseTex = true; // Enable using textures instead of strokes to draw rounded corners/circles where possible.
|
||||
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
|
||||
CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
|
||||
|
||||
@@ -1251,7 +1250,7 @@ void ImGuiIO::ClearInputKeys()
|
||||
KeysData[n].DownDurationPrev = -1.0f;
|
||||
}
|
||||
KeyCtrl = KeyShift = KeyAlt = KeySuper = false;
|
||||
KeyMods = KeyModsPrev = ImGuiKeyModFlags_None;
|
||||
KeyMods = ImGuiKeyModFlags_None;
|
||||
for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++)
|
||||
NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f;
|
||||
}
|
||||
@@ -1322,8 +1321,10 @@ void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native
|
||||
// Build native->imgui map so old user code can still call key functions with native 0..511 values.
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
|
||||
if (ImGui::IsLegacyKey(legacy_key))
|
||||
KeyMap[legacy_key] = key;
|
||||
if (!ImGui::IsLegacyKey(legacy_key))
|
||||
return;
|
||||
KeyMap[legacy_key] = key;
|
||||
KeyMap[key] = legacy_key;
|
||||
#else
|
||||
IM_UNUSED(key);
|
||||
IM_UNUSED(native_legacy_index);
|
||||
@@ -1638,8 +1639,12 @@ const char* ImStrSkipBlank(const char* str)
|
||||
// designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.)
|
||||
#ifdef IMGUI_USE_STB_SPRINTF
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#ifdef IMGUI_STB_SPRINTF_FILENAME
|
||||
#include IMGUI_STB_SPRINTF_FILENAME
|
||||
#else
|
||||
#include "stb_sprintf.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(vsnprintf)
|
||||
#define vsnprintf _vsnprintf
|
||||
@@ -2566,15 +2571,14 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
|
||||
|
||||
void ImGuiListClipper::End()
|
||||
{
|
||||
// In theory here we should assert that we are already at the right position, but it seems saner to just seek at the end and not assert/crash the user.
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
|
||||
ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
|
||||
ItemsCount = -1;
|
||||
|
||||
// Restore temporary buffer and fix back pointers which may be invalidated when nesting
|
||||
if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
|
||||
{
|
||||
// In theory here we should assert that we are already at the right position, but it seems saner to just seek at the end and not assert/crash the user.
|
||||
if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
|
||||
ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
|
||||
|
||||
// Restore temporary buffer and fix back pointers which may be invalidated when nesting
|
||||
IM_ASSERT(data->ListClipper == this);
|
||||
data->StepNo = data->Ranges.Size;
|
||||
if (--g.ClipperTempDataStacked > 0)
|
||||
@@ -2584,6 +2588,7 @@ void ImGuiListClipper::End()
|
||||
}
|
||||
TempData = NULL;
|
||||
}
|
||||
ItemsCount = -1;
|
||||
}
|
||||
|
||||
void ImGuiListClipper::ForceDisplayRangeByIndices(int item_min, int item_max)
|
||||
@@ -2600,6 +2605,7 @@ bool ImGuiListClipper::Step()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
|
||||
IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
|
||||
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
if (table && table->IsInsideRow)
|
||||
@@ -2716,8 +2722,8 @@ bool ImGuiListClipper::Step()
|
||||
// Advance the cursor to the end of the list and then returns 'false' to end the loop.
|
||||
if (ItemsCount < INT_MAX)
|
||||
ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
|
||||
ItemsCount = -1;
|
||||
|
||||
End();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3475,7 +3481,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (g.NavDisableMouseHover && !g.NavDisableHighlight)
|
||||
if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
|
||||
{
|
||||
if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
|
||||
return false;
|
||||
@@ -3536,8 +3542,6 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
||||
return false;
|
||||
if (!IsMouseHoveringRect(bb.Min, bb.Max))
|
||||
return false;
|
||||
if (g.NavDisableMouseHover)
|
||||
return false;
|
||||
if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
|
||||
{
|
||||
g.HoveredIdDisabled = true;
|
||||
@@ -3573,6 +3577,9 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
||||
IM_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
if (g.NavDisableMouseHover)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3939,16 +3946,13 @@ static void ImGui::UpdateKeyboardInputs()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiIO& io = g.IO;
|
||||
|
||||
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools
|
||||
io.KeyMods = GetMergedKeyModFlags();
|
||||
|
||||
// Import legacy keys or verify they are not used
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
if (io.BackendUsingLegacyKeyArrays == 0)
|
||||
{
|
||||
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written too.
|
||||
for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++)
|
||||
IM_ASSERT(io.KeysDown[n] == false && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
|
||||
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written to externally.
|
||||
for (int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++)
|
||||
IM_ASSERT((io.KeysDown[n] == false || IsKeyDown(n)) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3971,6 +3975,8 @@ static void ImGui::UpdateKeyboardInputs()
|
||||
const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
|
||||
IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
|
||||
io.KeysData[key].Down = io.KeysDown[n];
|
||||
if (key != n)
|
||||
io.KeysDown[key] = io.KeysDown[n]; // Allow legacy code using io.KeysDown[GetKeyIndex()] with old backends
|
||||
io.BackendUsingLegacyKeyArrays = 1;
|
||||
}
|
||||
if (io.BackendUsingLegacyKeyArrays == 1)
|
||||
@@ -3983,6 +3989,9 @@ static void ImGui::UpdateKeyboardInputs()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools
|
||||
io.KeyMods = GetMergedKeyModFlags();
|
||||
|
||||
// Clear gamepad data if disabled
|
||||
if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
|
||||
for (int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++)
|
||||
@@ -4298,8 +4307,6 @@ void ImGui::NewFrame()
|
||||
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
|
||||
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
|
||||
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
|
||||
if (g.Style.RoundCornersUseTex && !(g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners))
|
||||
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_RoundCornersUseTex;
|
||||
|
||||
// Mark rendering data as invalid to prevent user who may have a handle on it to use it.
|
||||
for (int n = 0; n < g.Viewports.Size; n++)
|
||||
@@ -4472,11 +4479,11 @@ void ImGui::Initialize(ImGuiContext* context)
|
||||
ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
|
||||
ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
|
||||
ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
|
||||
g.SettingsHandlers.push_back(ini_handler);
|
||||
AddSettingsHandler(&ini_handler);
|
||||
}
|
||||
|
||||
// Add .ini handle for ImGuiTable type
|
||||
TableSettingsInstallHandler(context);
|
||||
TableSettingsAddSettingsHandler();
|
||||
|
||||
// Create default viewport
|
||||
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
|
||||
@@ -4867,7 +4874,6 @@ void ImGui::EndFrame()
|
||||
// Clear Input data for next frame
|
||||
g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f;
|
||||
g.IO.InputQueueCharacters.resize(0);
|
||||
g.IO.KeyModsPrev = g.IO.KeyMods; // doing it here is better than in NewFrame() as we'll tolerate backend writing to KeyMods. If we want to firmly disallow it we should detect it.
|
||||
memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs));
|
||||
|
||||
CallContextHooks(&g, ImGuiContextHookType_EndFramePost);
|
||||
@@ -5522,14 +5528,13 @@ struct ImGuiResizeGripDef
|
||||
ImVec2 CornerPosN;
|
||||
ImVec2 InnerDir;
|
||||
int AngleMin12, AngleMax12;
|
||||
ImDrawFlags CornerFlags;
|
||||
};
|
||||
static const ImGuiResizeGripDef resize_grip_def[4] =
|
||||
{
|
||||
{ ImVec2(1, 1), ImVec2(-1, -1), 0, 3, ImDrawFlags_RoundCornersBottomRight }, // Lower-right
|
||||
{ ImVec2(0, 1), ImVec2(+1, -1), 3, 6, ImDrawFlags_RoundCornersBottomLeft }, // Lower-left
|
||||
{ ImVec2(0, 0), ImVec2(+1, +1), 6, 9, ImDrawFlags_RoundCornersTopLeft }, // Upper-left (Unused)
|
||||
{ ImVec2(1, 0), ImVec2(-1, +1), 9,12, ImDrawFlags_RoundCornersTopRight }, // Upper-right (Unused)
|
||||
{ ImVec2(1, 1), ImVec2(-1, -1), 0, 3 }, // Lower-right
|
||||
{ ImVec2(0, 1), ImVec2(+1, -1), 3, 6 }, // Lower-left
|
||||
{ ImVec2(0, 0), ImVec2(+1, +1), 6, 9 }, // Upper-left (Unused)
|
||||
{ ImVec2(1, 0), ImVec2(-1, +1), 9, 12 } // Upper-right (Unused)
|
||||
};
|
||||
|
||||
// Data for resizing from borders
|
||||
@@ -5819,20 +5824,10 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
{
|
||||
const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
|
||||
const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
|
||||
|
||||
ImVec2 grip_corner = corner;
|
||||
grip_corner.x += grip.InnerDir.x * window_border_size;
|
||||
grip_corner.y += grip.InnerDir.y * window_border_size;
|
||||
|
||||
// Try and use a rounded texture to draw the grip
|
||||
if (!RenderWindowResizeGrip(window->DrawList, grip_corner, (unsigned int)window_rounding, (unsigned int)(resize_grip_draw_size - window_border_size), grip.CornerFlags, resize_grip_col[resize_grip_n]))
|
||||
{
|
||||
// Fall back to using geometry to draw the whole grip if texture-based draw failed
|
||||
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)));
|
||||
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size)));
|
||||
window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
|
||||
window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
|
||||
}
|
||||
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)));
|
||||
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size)));
|
||||
window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
|
||||
window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6851,8 +6846,6 @@ void ImGui::SetCurrentFont(ImFont* font)
|
||||
ImFontAtlas* atlas = g.Font->ContainerAtlas;
|
||||
g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
|
||||
g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
|
||||
g.DrawListSharedData.TexRoundCornerData = &atlas->TexRoundCornerData;
|
||||
g.DrawListSharedData.TexSquareCornerData = &atlas->TexSquareCornerData;
|
||||
g.DrawListSharedData.Font = g.Font;
|
||||
g.DrawListSharedData.FontSize = g.FontSize;
|
||||
}
|
||||
@@ -7673,14 +7666,8 @@ bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
|
||||
const float t = g.IO.MouseDownDuration[button];
|
||||
if (t == 0.0f)
|
||||
return true;
|
||||
|
||||
if (repeat && t > g.IO.KeyRepeatDelay)
|
||||
{
|
||||
// FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
|
||||
int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f);
|
||||
if (amount > 0)
|
||||
return true;
|
||||
}
|
||||
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7816,8 +7803,18 @@ static const char* GetInputSourceName(ImGuiInputSource source)
|
||||
return input_source_names[source];
|
||||
}
|
||||
|
||||
/*static void DebugLogInputEvent(const char* prefix, const ImGuiInputEvent* e)
|
||||
{
|
||||
if (e->Type == ImGuiInputEventType_MousePos) { IMGUI_DEBUG_LOG("%s: MousePos (%.1f %.1f)\n", prefix, e->MousePos.PosX, e->MousePos.PosY); return; }
|
||||
if (e->Type == ImGuiInputEventType_MouseButton) { IMGUI_DEBUG_LOG("%s: MouseButton %d %s\n", prefix, e->MouseButton.Button, e->MouseButton.Down ? "Down" : "Up"); return; }
|
||||
if (e->Type == ImGuiInputEventType_MouseWheel) { IMGUI_DEBUG_LOG("%s: MouseWheel (%.1f %.1f)\n", prefix, e->MouseWheel.WheelX, e->MouseWheel.WheelY); return; }
|
||||
if (e->Type == ImGuiInputEventType_Key) { IMGUI_DEBUG_LOG("%s: Key \"%s\" %s\n", prefix, ImGui::GetKeyName(e->Key.Key), e->Key.Down ? "Down" : "Up"); return; }
|
||||
if (e->Type == ImGuiInputEventType_Text) { IMGUI_DEBUG_LOG("%s: Text: %c (U+%08X)\n", prefix, e->Text.Char, e->Text.Char); return; }
|
||||
if (e->Type == ImGuiInputEventType_Focus) { IMGUI_DEBUG_LOG("%s: AppFocused %d\n", prefix, e->AppFocused.Focused); return; }
|
||||
}*/
|
||||
|
||||
// Process input queue
|
||||
// We always call this with the value of 'bool g.IO.ConfigInputTrickleEventQueue'.
|
||||
// - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost)
|
||||
// - trickle_fast_inputs = true : process as many events as possible (successive down/up/down/up will be trickled over several frames so nothing is lost) (new feature in 1.87)
|
||||
void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
||||
@@ -7825,7 +7822,12 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiIO& io = g.IO;
|
||||
|
||||
bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputed = false;
|
||||
// Only trickle chars<>key when working with InputText()
|
||||
// FIXME: InputText() could parse event trail?
|
||||
// FIXME: Could specialize chars<>keys trickling rules for control keys (those not typically associated to characters)
|
||||
const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1);
|
||||
|
||||
bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputted = false;
|
||||
int mouse_button_changed = 0x00;
|
||||
ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask;
|
||||
|
||||
@@ -7841,7 +7843,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
||||
if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y)
|
||||
{
|
||||
// Trickling Rule: Stop processing queued events if we already handled a mouse button change
|
||||
if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputed))
|
||||
if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
|
||||
break;
|
||||
io.MousePos = event_pos;
|
||||
mouse_moved = true;
|
||||
@@ -7881,7 +7883,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
||||
if (keydata->Down != e->Key.Down || keydata->AnalogValue != e->Key.AnalogValue)
|
||||
{
|
||||
// Trickling Rule: Stop processing queued events if we got multiple action on the same button
|
||||
if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputed || mouse_button_changed != 0))
|
||||
if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_changed_mask.TestBit(keydata_index) || text_inputted || mouse_button_changed != 0))
|
||||
break;
|
||||
keydata->Down = e->Key.Down;
|
||||
keydata->AnalogValue = e->Key.AnalogValue;
|
||||
@@ -7896,16 +7898,24 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
||||
if (key == ImGuiKey_ModSuper) { io.KeySuper = keydata->Down; }
|
||||
io.KeyMods = GetMergedKeyModFlags();
|
||||
}
|
||||
|
||||
// Allow legacy code using io.KeysDown[GetKeyIndex()] with new backends
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
io.KeysDown[key] = keydata->Down;
|
||||
if (io.KeyMap[key] != -1)
|
||||
io.KeysDown[io.KeyMap[key]] = keydata->Down;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (e->Type == ImGuiInputEventType_Text)
|
||||
{
|
||||
// Trickling Rule: Stop processing queued events if keys/mouse have been interacted with
|
||||
if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
|
||||
if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
|
||||
break;
|
||||
unsigned int c = e->Text.Char;
|
||||
io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
|
||||
text_inputed = true;
|
||||
if (trickle_interleaved_keys_and_text)
|
||||
text_inputted = true;
|
||||
}
|
||||
else if (e->Type == ImGuiInputEventType_Focus)
|
||||
{
|
||||
@@ -7924,6 +7934,11 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
|
||||
for (int n = 0; n < event_n; n++)
|
||||
g.InputEventsTrail.push_back(g.InputEventsQueue[n]);
|
||||
|
||||
// [DEBUG]
|
||||
/*if (event_n != 0)
|
||||
for (int n = 0; n < g.InputEventsQueue.Size; n++)
|
||||
DebugLogInputEvent(n < event_n ? "Processed" : "Remaining", &g.InputEventsQueue[n]);*/
|
||||
|
||||
// Remaining events will be processed on the next frame
|
||||
if (event_n == g.InputEventsQueue.Size)
|
||||
g.InputEventsQueue.resize(0);
|
||||
@@ -7988,7 +8003,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
||||
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
|
||||
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
|
||||
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < ImGuiKey_LegacyNativeKey_END && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
|
||||
|
||||
// Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP)
|
||||
if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1)
|
||||
@@ -8054,7 +8069,6 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
|
||||
IM_ASSERT(window->IsFallbackWindow);
|
||||
break;
|
||||
}
|
||||
IM_ASSERT(window == g.CurrentWindow);
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name);
|
||||
@@ -9720,6 +9734,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
|
||||
result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
result->InFlags = g.LastItemData.InFlags;
|
||||
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||
result->HasSelectionData = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasSelectionData) != 0; // FIXME: Bizarre but valid we are calling NavApplyItemToResult() before clering the NextItemData
|
||||
}
|
||||
|
||||
// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
|
||||
@@ -10476,6 +10491,7 @@ void ImGui::NavMoveRequestApplyResult()
|
||||
g.NavJustMovedToId = result->ID;
|
||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||
g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
|
||||
g.NavJustMovedToHasSelectionData = result->HasSelectionData;
|
||||
}
|
||||
|
||||
// Focus
|
||||
@@ -10812,7 +10828,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
// - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggling menu layer.
|
||||
// - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway.
|
||||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
|
||||
if (nav_keyboard_active && io.KeyMods == ImGuiKeyModFlags_Alt && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) == 0)
|
||||
if (nav_keyboard_active && IsKeyPressed(ImGuiKey_ModAlt))
|
||||
{
|
||||
g.NavWindowingToggleLayer = true;
|
||||
g.NavInputSource = ImGuiInputSource_Keyboard;
|
||||
@@ -10825,13 +10841,12 @@ static void ImGui::NavUpdateWindowing()
|
||||
g.NavWindowingToggleLayer = false;
|
||||
|
||||
// Apply layer toggle on release
|
||||
// Important: we don't assume that Alt was previously held in order to handle loss of focus when backend calls io.AddFocusEvent(false)
|
||||
// Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss.
|
||||
if (!(io.KeyMods & ImGuiKeyModFlags_Alt) && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) && g.NavWindowingToggleLayer)
|
||||
if (IsKeyReleased(ImGuiKey_ModAlt) && g.NavWindowingToggleLayer)
|
||||
if (g.ActiveId == 0 || g.ActiveIdAllowOverlap)
|
||||
if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
|
||||
apply_toggle_layer = true;
|
||||
if (!io.KeyAlt)
|
||||
if (!IsKeyDown(ImGuiKey_ModAlt))
|
||||
g.NavWindowingToggleLayer = false;
|
||||
}
|
||||
|
||||
@@ -11605,6 +11620,20 @@ ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name)
|
||||
return CreateNewWindowSettings(name);
|
||||
}
|
||||
|
||||
void ImGui::AddSettingsHandler(const ImGuiSettingsHandler* handler)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL);
|
||||
g.SettingsHandlers.push_back(*handler);
|
||||
}
|
||||
|
||||
void ImGui::RemoveSettingsHandler(const char* type_name)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name))
|
||||
g.SettingsHandlers.erase(handler);
|
||||
}
|
||||
|
||||
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -12163,19 +12192,20 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
{
|
||||
static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n)
|
||||
{
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); // Always using last submitted instance
|
||||
if (rect_type == TRT_OuterRect) { return table->OuterRect; }
|
||||
else if (rect_type == TRT_InnerRect) { return table->InnerRect; }
|
||||
else if (rect_type == TRT_WorkRect) { return table->WorkRect; }
|
||||
else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; }
|
||||
else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; }
|
||||
else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; }
|
||||
else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); }
|
||||
else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table_instance->LastOuterHeight); }
|
||||
else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); }
|
||||
else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
|
||||
else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate
|
||||
else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); }
|
||||
else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); } // Note: y1/y2 not always accurate
|
||||
else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); }
|
||||
IM_ASSERT(0);
|
||||
return ImRect();
|
||||
}
|
||||
@@ -12442,7 +12472,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
|
||||
|
||||
int active_id_using_key_input_count = 0;
|
||||
for (int n = 0; n < ImGuiKey_NamedKey_COUNT; n++)
|
||||
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
|
||||
active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask[n] ? 1 : 0;
|
||||
Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %d key(s)", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, active_id_using_key_input_count);
|
||||
Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame
|
||||
|
||||
131
imgui.h
131
imgui.h
@@ -65,7 +65,7 @@ Index of this file:
|
||||
// Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
|
||||
#define IMGUI_VERSION "1.88 WIP"
|
||||
#define IMGUI_VERSION_NUM 18704
|
||||
#define IMGUI_VERSION_NUM 18710
|
||||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
@@ -150,6 +150,7 @@ struct ImGuiIO; // Main configuration and I/O between your a
|
||||
struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
|
||||
struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions.
|
||||
struct ImGuiListClipper; // Helper to manually clip large list of items
|
||||
struct ImGuiMultiSelectData; // State for a BeginMultiSelect() block
|
||||
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
|
||||
struct ImGuiPayload; // User data payload for drag and drop operations
|
||||
struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function.
|
||||
@@ -191,6 +192,7 @@ typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: f
|
||||
typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
|
||||
typedef int ImGuiKeyModFlags; // -> enum ImGuiKeyModFlags_ // Flags: for io.KeyMods (Ctrl/Shift/Alt/Super)
|
||||
typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
|
||||
typedef int ImGuiMultiSelectFlags; // -> enum ImGuiMultiSelectFlags_// Flags: for BeginMultiSelect()
|
||||
typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
|
||||
typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
|
||||
typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
|
||||
@@ -612,6 +614,14 @@ namespace ImGui
|
||||
IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
|
||||
IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
|
||||
|
||||
// Multi-selection system for Selectable() and TreeNode() functions.
|
||||
// This enables standard multi-selection/range-selection idioms (CTRL+Click/Arrow, SHIFT+Click/Arrow, etc) in a way that allow items to be fully clipped (= not submitted at all) when not visible.
|
||||
// Read comments near ImGuiMultiSelectData for details.
|
||||
// When enabled, Selectable() and TreeNode() functions will return true when selection needs toggling.
|
||||
IMGUI_API ImGuiMultiSelectData* BeginMultiSelect(ImGuiMultiSelectFlags flags, void* range_ref, bool range_ref_is_selected);
|
||||
IMGUI_API ImGuiMultiSelectData* EndMultiSelect();
|
||||
IMGUI_API void SetNextItemSelectionData(void* item_data);
|
||||
|
||||
// Widgets: List Boxes
|
||||
// - This is essentially a thin wrapper to using BeginChild/EndChild with some stylistic changes.
|
||||
// - The BeginListBox()/EndListBox() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() or any items.
|
||||
@@ -835,6 +845,7 @@ namespace ImGui
|
||||
IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing.
|
||||
IMGUI_API bool IsItemDeactivatedAfterEdit(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item).
|
||||
IMGUI_API bool IsItemToggledOpen(); // was the last item open state toggled? set by TreeNode().
|
||||
IMGUI_API bool IsItemToggledSelection(); // was the last item selection state toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
|
||||
IMGUI_API bool IsAnyItemHovered(); // is any item hovered?
|
||||
IMGUI_API bool IsAnyItemActive(); // is any item active?
|
||||
IMGUI_API bool IsAnyItemFocused(); // is any item focused?
|
||||
@@ -1280,6 +1291,7 @@ enum ImGuiHoveredFlags_
|
||||
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
|
||||
ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 8, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window
|
||||
ImGuiHoveredFlags_AllowWhenDisabled = 1 << 9, // IsItemHovered() only: Return true even if the item is disabled
|
||||
ImGuiHoveredFlags_NoNavOverride = 1 << 10, // Disable using gamepad/keyboard navigation state when active, always query mouse.
|
||||
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
|
||||
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows
|
||||
};
|
||||
@@ -1421,7 +1433,7 @@ enum ImGuiKey_
|
||||
ImGuiKey_GamepadRStickLeft, // [Analog]
|
||||
ImGuiKey_GamepadRStickRight, // [Analog]
|
||||
|
||||
// Keyboard Modifiers
|
||||
// Keyboard Modifiers (explicitly submitted by backend via AddKeyEvent() calls)
|
||||
// - This is mirroring the data also written to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper, in a format allowing
|
||||
// them to be accessed via standard key API, allowing calls such as IsKeyPressed(), IsKeyReleased(), querying duration etc.
|
||||
// - Code polling every keys (e.g. an interface to detect a key press for input mapping) might want to ignore those
|
||||
@@ -1429,11 +1441,9 @@ enum ImGuiKey_
|
||||
// - In theory the value of keyboard modifiers should be roughly equivalent to a logical or of the equivalent left/right keys.
|
||||
// In practice: it's complicated; mods are often provided from different sources. Keyboard layout, IME, sticky keys and
|
||||
// backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user...
|
||||
ImGuiKey_ModCtrl,
|
||||
ImGuiKey_ModShift,
|
||||
ImGuiKey_ModAlt,
|
||||
ImGuiKey_ModSuper,
|
||||
ImGuiKey_ModCtrl, ImGuiKey_ModShift, ImGuiKey_ModAlt, ImGuiKey_ModSuper,
|
||||
|
||||
// End of list
|
||||
ImGuiKey_COUNT, // No valid ImGuiKey is ever greater than this value
|
||||
|
||||
// [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + a io.KeyMap[] array.
|
||||
@@ -1721,6 +1731,19 @@ enum ImGuiMouseCursor_
|
||||
ImGuiMouseCursor_COUNT
|
||||
};
|
||||
|
||||
// Flags for BeginMultiSelect().
|
||||
// This system is designed to allow mouse/keyboard multi-selection, including support for range-selection (SHIFT + click),
|
||||
// which is difficult to re-implement manually. If you disable multi-selection with ImGuiMultiSelectFlags_NoMultiSelect
|
||||
// (which is provided for consistency and flexibility), the whole BeginMultiSelect() system becomes largely overkill as
|
||||
// you can handle single-selection in a simpler manner by just calling Selectable() and reacting on clicks yourself.
|
||||
enum ImGuiMultiSelectFlags_
|
||||
{
|
||||
ImGuiMultiSelectFlags_None = 0,
|
||||
ImGuiMultiSelectFlags_NoMultiSelect = 1 << 0,
|
||||
ImGuiMultiSelectFlags_NoUnselect = 1 << 1, // Disable unselecting items with CTRL+Click, CTRL+Space etc.
|
||||
ImGuiMultiSelectFlags_NoSelectAll = 1 << 2 // Disable CTRL+A shortcut to set RequestSelectAll
|
||||
};
|
||||
|
||||
// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions
|
||||
// Represent a condition.
|
||||
// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
|
||||
@@ -1815,7 +1838,7 @@ struct ImVector
|
||||
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
||||
inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); }
|
||||
inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
|
||||
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; }
|
||||
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last >= it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; }
|
||||
inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
|
||||
inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
|
||||
inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; }
|
||||
@@ -1875,7 +1898,6 @@ struct ImGuiStyle
|
||||
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
|
||||
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering. Latched at the beginning of the frame (copied to ImDrawList).
|
||||
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
|
||||
bool RoundCornersUseTex; // Enable using textures instead of strokes to draw rounded corners/circles where possible.
|
||||
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
|
||||
float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
|
||||
ImVec4 Colors[ImGuiCol_COUNT];
|
||||
@@ -1904,13 +1926,13 @@ struct ImGuiKeyData
|
||||
struct ImGuiIO
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
// Configuration (fill once) // Default value
|
||||
// Configuration // Default value
|
||||
//------------------------------------------------------------------
|
||||
|
||||
ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
|
||||
ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
|
||||
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size)
|
||||
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
|
||||
ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame.
|
||||
float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. May change every frame.
|
||||
float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
|
||||
const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions.
|
||||
const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
|
||||
@@ -2008,7 +2030,7 @@ struct ImGuiIO
|
||||
// This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
|
||||
int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
|
||||
bool KeysDown[512]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys).
|
||||
bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@@ -2030,7 +2052,6 @@ struct ImGuiIO
|
||||
|
||||
// Other state maintained from data above + IO function calls
|
||||
ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame()
|
||||
ImGuiKeyModFlags KeyModsPrev; // Key mods flags (from previous frame)
|
||||
ImGuiKeyData KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this.
|
||||
bool WantCaptureMouseUnlessPopupClose; // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
|
||||
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
|
||||
@@ -2042,7 +2063,7 @@ struct ImGuiIO
|
||||
ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done.
|
||||
bool MouseReleased[5]; // Mouse button went from Down to !Down
|
||||
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
|
||||
bool MouseDownOwnedUnlessPopupClose[5]; //Track if button was clicked inside a dear imgui window.
|
||||
bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window.
|
||||
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
|
||||
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
|
||||
float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds)
|
||||
@@ -2320,6 +2341,61 @@ struct ImGuiListClipper
|
||||
#endif
|
||||
};
|
||||
|
||||
// Abstract:
|
||||
// - This system helps you implements standard multi-selection idioms (CTRL+Click/Arrow, SHIFT+Click/Arrow, etc) in a way that allow
|
||||
// selectable items to be fully clipped (= not submitted at all) when not visible. Clipping is typically provided by ImGuiListClipper.
|
||||
// Handling all of this in a single pass imgui is a little tricky, and this is why we provide those functionalities.
|
||||
// Note however that if you don't need SHIFT+Click/Arrow range-select + clipping, you can handle a simpler form of multi-selection
|
||||
// yourself, by reacting to click/presses on Selectable() items and checking keyboard modifiers.
|
||||
// The unusual complexity of this system is mostly caused by supporting SHIFT+Click/Arrow range-select with clipped elements.
|
||||
// - TreeNode() and Selectable() are supported.
|
||||
// - The work involved to deal with multi-selection differs whether you want to only submit visible items (and clip others) or submit all items
|
||||
// regardless of their visibility. Clipping items is more efficient and will allow you to deal with large lists (1k~100k items) with near zero
|
||||
// performance penalty, but requires a little more work on the code. If you only have a few hundreds elements in your possible selection set,
|
||||
// you may as well not bother with clipping, as the cost should be negligible (as least on Dear ImGui side).
|
||||
// If you are not sure, always start without clipping and you can work your way to the more optimized version afterwards.
|
||||
// - The void* RangeSrc/RangeDst value represent a selectable object. They are the values you pass to SetNextItemSelectionData().
|
||||
// Storing an integer index is the easiest thing to do, as SetRange requests will give you two end points and you will need to interpolate
|
||||
// between them to honor range selection. But the code never assume that sortable integers are used (you may store pointers to your object,
|
||||
// and then from the pointer have your own way of iterating from RangeSrc to RangeDst).
|
||||
// - In the spirit of Dear ImGui design, your code own the selection data. So this is designed to handle all kind of selection data:
|
||||
// e.g. instructive selection (store a bool inside each object), external array (store an array aside from your objects),
|
||||
// hash/map/set (store only selected items in a hash/map/set), or other structures (store indices in an interval tree), etc.
|
||||
// Usage flow:
|
||||
// 1) Call BeginMultiSelect() with the last saved value of ->RangeSrc and its selection state.
|
||||
// It is because you need to pass its selection state (and you own selection) that we don't store this value in Dear ImGui.
|
||||
// (For the initial frame or when resetting your selection state: you may use the value for your first item or a "null" value that matches the type stored in your void*).
|
||||
// 2) Honor Clear/SelectAll requests by updating your selection data. [Only required if you are using a clipper in step 4]
|
||||
// 3) Set RangeSrcPassedBy=true if the RangeSrc item is part of the items clipped before the first submitted/visible item. [Only required if you are using a clipper in step 4]
|
||||
// This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
|
||||
// If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrc) { data->RangeSrcPassedBy = true; }
|
||||
// 4) Submit your items with SetNextItemSelectionData() + Selectable()/TreeNode() calls.
|
||||
// Call IsItemToggledSelection() to query if the selection state has been toggled, if you need the info immediately for your display (before EndMultiSelect()).
|
||||
// When cannot return a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggle" event instead.
|
||||
// 5) Call EndMultiSelect(). Save the value of ->RangeSrc for the next frame (you may convert the value in a format that is safe for persistance)
|
||||
// 6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)
|
||||
// If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable() on a per-item basis.
|
||||
#define IMGUI_HAS_MULTI_SELECT // Multi-Select/Range-Select WIP branch // <-- This is currently _not_ in the top of imgui.h to prevent merge conflicts.
|
||||
struct ImGuiMultiSelectData
|
||||
{
|
||||
bool RequestClear; // Begin, End // Request user to clear selection
|
||||
bool RequestSelectAll; // Begin, End // Request user to select all
|
||||
bool RequestSetRange; // End // Request user to set or clear selection in the [RangeSrc..RangeDst] range
|
||||
bool RangeSrcPassedBy; // In loop // (If clipping) Need to be set by user if RangeSrc was part of the clipped set before submitting the visible items. Ignore if not clipping.
|
||||
bool RangeValue; // End // End: parameter from RequestSetRange request. True = Select Range, False = Unselect range.
|
||||
void* RangeSrc; // Begin, End // End: parameter from RequestSetRange request + you need to save this value so you can pass it again next frame. / Begin: this is the value you passed to BeginMultiSelect()
|
||||
void* RangeDst; // End // End: parameter from RequestSetRange request.
|
||||
int RangeDirection; // End // End: parameter from RequestSetRange request. +1 if RangeSrc came before RangeDst, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values.
|
||||
|
||||
ImGuiMultiSelectData() { Clear(); }
|
||||
void Clear()
|
||||
{
|
||||
RequestClear = RequestSelectAll = RequestSetRange = RangeSrcPassedBy = RangeValue = false;
|
||||
RangeSrc = RangeDst = NULL;
|
||||
RangeDirection = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Helpers macros to generate 32-bit encoded colors
|
||||
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
#define IM_COL32_R_SHIFT 16
|
||||
@@ -2345,13 +2421,13 @@ struct ImGuiListClipper
|
||||
// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed.
|
||||
struct ImColor
|
||||
{
|
||||
ImVec4 Value;
|
||||
ImVec4 Value;
|
||||
|
||||
ImColor() { Value.x = Value.y = Value.z = Value.w = 0.0f; }
|
||||
constexpr ImColor() { }
|
||||
constexpr ImColor(float r, float g, float b, float a = 1.0f) : Value(r, g, b, a) { }
|
||||
constexpr ImColor(const ImVec4& col) : Value(col) {}
|
||||
ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f / 255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }
|
||||
ImColor(ImU32 rgba) { float sc = 1.0f / 255.0f; Value.x = (float)((rgba >> IM_COL32_R_SHIFT) & 0xFF) * sc; Value.y = (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * sc; Value.z = (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * sc; Value.w = (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * sc; }
|
||||
ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; }
|
||||
ImColor(const ImVec4& col) { Value = col; }
|
||||
inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); }
|
||||
inline operator ImVec4() const { return Value; }
|
||||
|
||||
@@ -2485,8 +2561,7 @@ enum ImDrawListFlags_
|
||||
ImDrawListFlags_AntiAliasedLines = 1 << 0, // Enable anti-aliased lines/borders (*2 the number of triangles for 1.0f wide line or lines thin enough to be drawn using textures, otherwise *3 the number of triangles)
|
||||
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering.
|
||||
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_RoundCornersUseTex = 1 << 4 // Enable using textures instead of strokes to draw rounded corners/circles where possible.
|
||||
ImDrawListFlags_AllowVtxOffset = 1 << 3 // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
|
||||
};
|
||||
|
||||
// Draw command list
|
||||
@@ -2701,16 +2776,6 @@ struct ImFontGlyphRangesBuilder
|
||||
IMGUI_API void BuildRanges(ImVector<ImWchar>* out_ranges); // Output new ranges
|
||||
};
|
||||
|
||||
// Data for texture-based rounded corners for a given radius
|
||||
struct ImFontRoundedCornerData
|
||||
{
|
||||
ImVec4 TexUvFilled; // UV of filled round corner quad in the atlas (only valid when stroke width is 1)
|
||||
ImVec4 TexUvStroked; // UV of stroked round corner quad in the atlas
|
||||
float ParametricStrokeWidth; // Pre-calculated value for stroke width divided by the radius
|
||||
int RectId; // Rect ID in the atlas, or -1 if there is no data
|
||||
bool StrokedUsesAlternateUVs; // True if stroked drawing should use the alternate (i.e. other corner) UVs
|
||||
};
|
||||
|
||||
// See ImFontAtlas::AddCustomRectXXX functions.
|
||||
struct ImFontAtlasCustomRect
|
||||
{
|
||||
@@ -2730,8 +2795,7 @@ enum ImFontAtlasFlags_
|
||||
ImFontAtlasFlags_None = 0,
|
||||
ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two
|
||||
ImFontAtlasFlags_NoMouseCursors = 1 << 1, // Don't build software mouse cursors into the atlas (save a little texture memory)
|
||||
ImFontAtlasFlags_NoBakedLines = 1 << 2, // Don't build thick line textures into the atlas (save a little texture memory). The AntiAliasedLinesUseTex features uses them, otherwise they will be rendered using polygons (more expensive for CPU/GPU).
|
||||
ImFontAtlasFlags_NoBakedRoundCorners= 1 << 3 // Don't build round corners into the atlas.
|
||||
ImFontAtlasFlags_NoBakedLines = 1 << 2 // Don't build thick line textures into the atlas (save a little texture memory). The AntiAliasedLinesUseTex features uses them, otherwise they will be rendered using polygons (more expensive for CPU/GPU).
|
||||
};
|
||||
|
||||
// Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding:
|
||||
@@ -2845,9 +2909,6 @@ struct ImFontAtlas
|
||||
int PackIdMouseCursors; // Custom texture rectangle ID for white pixel and mouse cursors
|
||||
int PackIdLines; // Custom texture rectangle ID for baked anti-aliased lines
|
||||
|
||||
ImVector<ImFontRoundedCornerData> TexRoundCornerData; // Data for texture-based round corners indexed by radius/size (from 1 to ImFontAtlasRoundCornersMaxSize) and stroke width (from 1 to ImFontAtlasRoundCornersMaxStrokeWidth), with index = stroke_width_index + (radius_index * ImFontAtlasRoundCornersMaxStrokeWidth).
|
||||
ImVector<ImFontRoundedCornerData> TexSquareCornerData; // The same as TexRoundCornerData, but with square corners instead of rounded ones
|
||||
|
||||
// [Obsolete]
|
||||
//typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+
|
||||
//typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+
|
||||
|
||||
354
imgui_demo.cpp
354
imgui_demo.cpp
@@ -240,177 +240,6 @@ void ImGui::ShowUserGuide()
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void GetVtxIdxDelta(ImDrawList* dl, int* vtx, int *idx)
|
||||
{
|
||||
static int vtx_n, idx_n;
|
||||
static int vtx_o, idx_o;
|
||||
vtx_n = dl->VtxBuffer.Size;
|
||||
idx_n = dl->IdxBuffer.Size;
|
||||
|
||||
*vtx = vtx_n - vtx_o;
|
||||
*idx = idx_n - idx_o;
|
||||
|
||||
vtx_o = vtx_n;
|
||||
idx_o = idx_n;
|
||||
}
|
||||
|
||||
// https://github.com/ocornut/imgui/issues/1962
|
||||
static void TestTextureBasedRender()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
ImGui::Begin("tex_round_corners");
|
||||
|
||||
bool old_round_corners_use_tex = style.RoundCornersUseTex;
|
||||
style.RoundCornersUseTex ^= io.KeyShift;
|
||||
|
||||
if (ImGui::Checkbox("style.RoundCornersUseTex (hold SHIFT to toggle)", &style.RoundCornersUseTex))
|
||||
old_round_corners_use_tex = !old_round_corners_use_tex;
|
||||
|
||||
if (style.RoundCornersUseTex)
|
||||
ImGui::GetWindowDrawList()->Flags |= ImDrawListFlags_RoundCornersUseTex;
|
||||
else
|
||||
ImGui::GetWindowDrawList()->Flags &= ~ImDrawListFlags_RoundCornersUseTex;
|
||||
|
||||
static float radius = 16.0f; // ImFontAtlasRoundCornersMaxSize * 0.5f;
|
||||
static int segments = 20;
|
||||
static int ngon_segments = 6;
|
||||
|
||||
ImGui::SliderFloat("radius", &radius, 0.0f, 64.0f /*(float)ImFontAtlasRoundCornersMaxSize*/, "%.0f");
|
||||
|
||||
static int width = 180;
|
||||
static int height = 180;
|
||||
ImGui::SliderInt("width", &width, 1, 200);
|
||||
ImGui::SliderInt("height", &height, 1, 200);
|
||||
|
||||
static float stroke_width = 1.0f;
|
||||
|
||||
ImGui::SliderFloat("stroke_width", &stroke_width, 1.0f, 10.0f, "%.0f");
|
||||
|
||||
int vtx_n = 0;
|
||||
int idx_n = 0;
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::PushItemWidth(120);
|
||||
ImGui::SliderInt("segments", &segments, 0, 100);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
{
|
||||
ImGui::Button("##1", ImVec2(200, 200));
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImVec2 min = ImGui::GetItemRectMin();
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
draw_list->AddCircleFilled(ImVec2(min.x + size.x * 0.5f, min.y + size.y * 0.5f), radius, IM_COL32(255,0,255,255), segments);
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImGui::Text("AddCircleFilled\n %d vtx, %d idx", vtx_n, idx_n);
|
||||
}
|
||||
{
|
||||
ImGui::Button("##2", ImVec2(200, 200));
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImVec2 min = ImGui::GetItemRectMin();
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
draw_list->AddCircle(ImVec2(min.x + size.x * 0.5f, min.y + size.y * 0.5f), radius, IM_COL32(255,0,255,255), segments, stroke_width);
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImGui::Text("AddCircle\n %d vtx, %d idx", vtx_n, idx_n);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
|
||||
static ImDrawFlags corner_flags = ImDrawFlags_RoundCornersAll;
|
||||
ImGui::CheckboxFlags("TL", (unsigned int*)&corner_flags, ImDrawFlags_RoundCornersTopLeft);
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("TR", (unsigned int*)&corner_flags, ImDrawFlags_RoundCornersTopRight);
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("BL", (unsigned int*)&corner_flags, ImDrawFlags_RoundCornersBottomLeft);
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxFlags("BR", (unsigned int*)&corner_flags, ImDrawFlags_RoundCornersBottomRight);
|
||||
|
||||
{
|
||||
ImGui::Button("##3", ImVec2(200, 200));
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
ImVec2 r_min = ImVec2(ImGui::GetItemRectMin().x + ((size.x - width) * 0.5f), ImGui::GetItemRectMin().y + ((size.y - height) * 0.5f));
|
||||
ImVec2 r_max = ImVec2(r_min.x + width, r_min.y + height);
|
||||
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
draw_list->AddRectFilled(r_min, r_max, IM_COL32(255,0,255,255), radius, corner_flags ? corner_flags : ImDrawFlags_RoundCornersNone);
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImGui::Text("AddRectFilled\n %d vtx, %d idx", vtx_n, idx_n);
|
||||
}
|
||||
{
|
||||
ImGui::Button("##4", ImVec2(200, 200));
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
ImVec2 r_min = ImVec2(ImGui::GetItemRectMin().x + ((size.x - width) * 0.5f), ImGui::GetItemRectMin().y + ((size.y - height) * 0.5f));
|
||||
ImVec2 r_max = ImVec2(r_min.x + width, r_min.y + height);
|
||||
|
||||
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
draw_list->AddRect(r_min, r_max, IM_COL32(255,0,255,255), radius, corner_flags, stroke_width);
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImGui::Text("AddRect\n %d vtx, %d idx", vtx_n, idx_n);
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::PushItemWidth(120);
|
||||
ImGui::SliderInt("ngon_segments", &ngon_segments, 3, 16);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
{
|
||||
ImGui::Button("##3", ImVec2(200, 200));
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImVec2 min = ImGui::GetItemRectMin();
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
draw_list->AddNgonFilled(ImVec2(min.x + size.x * 0.5f, min.y + size.y * 0.5f), radius, IM_COL32(255, 0, 255, 255), ngon_segments);
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImGui::Text("AddNgonFilled\n %d vtx, %d idx", vtx_n, idx_n);
|
||||
}
|
||||
{
|
||||
ImGui::Button("##4", ImVec2(200, 200));
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImVec2 min = ImGui::GetItemRectMin();
|
||||
ImVec2 size = ImGui::GetItemRectSize();
|
||||
draw_list->AddNgon(ImVec2(min.x + size.x * 0.5f, min.y + size.y * 0.5f), radius, IM_COL32(255, 0, 255, 255), ngon_segments, stroke_width);
|
||||
GetVtxIdxDelta(draw_list, &vtx_n, &idx_n);
|
||||
ImGui::Text("AddNgon\n %d vtx, %d idx", vtx_n, idx_n);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("Style");
|
||||
ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 3.0f, "%.0f");
|
||||
ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 100.0f, "%.0f");
|
||||
ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 100.0f, "%.0f");
|
||||
|
||||
// Show atlas
|
||||
ImGui::Text("Atlas");
|
||||
ImFontAtlas* atlas = ImGui::GetIO().Fonts;
|
||||
ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
|
||||
|
||||
style.RoundCornersUseTex = old_round_corners_use_tex;
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Demo Window / ShowDemoWindow()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -580,8 +409,6 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
||||
ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
|
||||
ImGui::Spacing();
|
||||
|
||||
TestTextureBasedRender();
|
||||
|
||||
IMGUI_DEMO_MARKER("Help");
|
||||
if (ImGui::CollapsingHeader("Help"))
|
||||
{
|
||||
@@ -727,6 +554,43 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// [Advanced] Helper class to simulate storage of a multi-selection state, used by the advanced multi-selection demos.
|
||||
// We use ImGuiStorage (simple key->value storage) to avoid external dependencies but it's probably not optimal.
|
||||
// To store a single-selection:
|
||||
// - You only need a single variable and don't need any of this!
|
||||
// To store a multi-selection, in your real application you could:
|
||||
// - Use intrusively stored selection (e.g. 'bool IsSelected' inside your object). This is by far the simplest
|
||||
// way to store your selection data, but it means you cannot have multiple simultaneous views over your objects.
|
||||
// This is what may of the simpler demos in this file are using (so they are not using this class).
|
||||
// - Otherwise, any externally stored unordered_set/set/hash/map/interval trees (storing indices, objects id, etc.)
|
||||
// are generally appropriate. Even a large array of bool might work for you...
|
||||
// - If you need to handle extremely large selections, it might be advantageous to support a "negative" mode in
|
||||
// your storage, so "Select All" becomes "Negative=1, Clear" and then sparse unselect can add to the storage.
|
||||
// About RefItem:
|
||||
// - The MultiSelect API requires you to store information about the reference/pivot item (generally the last clicked item).
|
||||
struct ExampleSelection
|
||||
{
|
||||
ImGuiStorage Storage;
|
||||
int SelectionSize; // Number of selected items (== number of 1 in the Storage, maintained by this class)
|
||||
int RangeRef; // Reference/pivot item (generally last clicked item)
|
||||
|
||||
ExampleSelection() { RangeRef = 0; Clear(); }
|
||||
void Clear() { Storage.Clear(); SelectionSize = 0; }
|
||||
bool GetSelected(int n) const { return Storage.GetInt((ImGuiID)n, 0) != 0; }
|
||||
void SetSelected(int n, bool v) { int* p_int = Storage.GetIntRef((ImGuiID)n, 0); if (*p_int == (int)v) return; if (v) SelectionSize++; else SelectionSize--; *p_int = (bool)v; }
|
||||
int GetSelectionSize() const { return SelectionSize; }
|
||||
|
||||
// When using SelectAll() / SetRange() we assume that our objects ID are indices.
|
||||
// In this demo we always store selection using indices and never in another manner (e.g. object ID or pointers).
|
||||
// If your selection system is storing selection using object ID and you want to support Shift+Click range-selection,
|
||||
// you will need a way to iterate from one object to another given the ID you use.
|
||||
// You are likely to need some kind of data structure to convert 'view index' <> 'object ID'.
|
||||
// FIXME-MULTISELECT: Would be worth providing a demo of doing this.
|
||||
// FIXME-MULTISELECT: SetRange() is currently very inefficient since it doesn't take advantage of the fact that ImGuiStorage stores sorted key.
|
||||
void SetRange(int n1, int n2, bool v) { if (n2 < n1) { int tmp = n2; n2 = n1; n1 = tmp; } for (int n = n1; n <= n2; n++) SetSelected(n, v); }
|
||||
void SelectAll(int count) { Storage.Data.resize(count); for (int idx = 0; idx < count; idx++) Storage.Data[idx] = ImGuiStorage::ImGuiStoragePair((ImGuiID)idx, 1); SelectionSize = count; } // This could be using SetRange(), but it this way is faster.
|
||||
};
|
||||
|
||||
static void ShowDemoWindowWidgets()
|
||||
{
|
||||
IMGUI_DEMO_MARKER("Widgets");
|
||||
@@ -1371,7 +1235,7 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::TreePop();
|
||||
}
|
||||
IMGUI_DEMO_MARKER("Widgets/Selectables/Multiple Selection");
|
||||
if (ImGui::TreeNode("Selection State: Multiple Selection"))
|
||||
if (ImGui::TreeNode("Selection State: Multiple Selection (Simplified)"))
|
||||
{
|
||||
HelpMarker("Hold CTRL and click to select multiple items.");
|
||||
static bool selection[5] = { false, false, false, false, false };
|
||||
@@ -1388,6 +1252,126 @@ static void ShowDemoWindowWidgets()
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Selection State: Multiple Selection (Full)"))
|
||||
{
|
||||
// Demonstrate holding/updating multi-selection data and using the BeginMultiSelect/EndMultiSelect API to support range-selection and clipping.
|
||||
static ExampleSelection selection;
|
||||
const char* random_names[] =
|
||||
{
|
||||
"Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper",
|
||||
"Bitter Gourd", "Bok Choy", "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", "Calabash", "Capers", "Carrot", "Cassava",
|
||||
"Cauliflower", "Celery", "Celery Root", "Celcuce", "Chayote", "Celtuce", "Chayote", "Chinese Broccoli", "Corn", "Cucumber"
|
||||
};
|
||||
|
||||
// Test both Selectable() and TreeNode() widgets
|
||||
enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode };
|
||||
static bool use_columns = false;
|
||||
static WidgetType widget_type = WidgetType_TreeNode;
|
||||
if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; }
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; }
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Use 2 columns", &use_columns);
|
||||
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &ImGui::GetIO().ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
|
||||
ImGui::SameLine(); HelpMarker("Hold CTRL and click to select multiple items. Hold SHIFT to select a range. Keyboard is also supported.");
|
||||
|
||||
// Open a scrolling region
|
||||
const int ITEMS_COUNT = 1000;
|
||||
if (ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20)))
|
||||
{
|
||||
ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize());
|
||||
if (widget_type == WidgetType_TreeNode)
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
|
||||
|
||||
ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_None, (void*)(intptr_t)selection.RangeRef, selection.GetSelected(selection.RangeRef));
|
||||
if (multi_select_data->RequestClear) { selection.Clear(); }
|
||||
if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
|
||||
|
||||
if (use_columns)
|
||||
{
|
||||
ImGui::Columns(2);
|
||||
//ImGui::PushStyleVar(ImGuiStyleVar_FrtemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
|
||||
}
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(ITEMS_COUNT);
|
||||
while (clipper.Step())
|
||||
{
|
||||
if (clipper.DisplayStart > selection.RangeRef)
|
||||
multi_select_data->RangeSrcPassedBy = true;
|
||||
for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
|
||||
{
|
||||
ImGui::PushID(n);
|
||||
const char* category = random_names[n % IM_ARRAYSIZE(random_names)];
|
||||
char label[64];
|
||||
sprintf(label, "Object %05d (category: %s)", n, category);
|
||||
bool item_is_selected = selection.GetSelected(n);
|
||||
|
||||
// Emit a color button, to test that Shift+LeftArrow landing on an item that is not part
|
||||
// of the selection scope doesn't erroneously alter our selection (FIXME-TESTS: Add a test for that!).
|
||||
ImU32 dummy_col = (ImU32)ImGui::GetID(label);
|
||||
ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetNextItemSelectionData((void*)(intptr_t)n);
|
||||
if (widget_type == WidgetType_Selectable)
|
||||
{
|
||||
ImGui::Selectable(label, item_is_selected);
|
||||
if (ImGui::IsItemToggledSelection())
|
||||
selection.SetSelected(n, !item_is_selected);
|
||||
}
|
||||
else if (widget_type == WidgetType_TreeNode)
|
||||
{
|
||||
ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||
tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
||||
if (item_is_selected)
|
||||
tree_node_flags |= ImGuiTreeNodeFlags_Selected;
|
||||
bool open = ImGui::TreeNodeEx(label, tree_node_flags);
|
||||
if (ImGui::IsItemToggledSelection())
|
||||
selection.SetSelected(n, !item_is_selected);
|
||||
if (open)
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
// Right-click: context menu
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
ImGui::Text("(Testing Selectable inside an embedded popup)");
|
||||
ImGui::Selectable("Close");
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (use_columns)
|
||||
{
|
||||
ImGui::NextColumn();
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::InputText("###NoLabel", (char*)(void*)category, strlen(category), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
if (use_columns)
|
||||
ImGui::Columns(1);
|
||||
|
||||
// Apply multi-select requests
|
||||
multi_select_data = ImGui::EndMultiSelect();
|
||||
selection.RangeRef = (int)(intptr_t)multi_select_data->RangeSrc;
|
||||
if (multi_select_data->RequestClear) { selection.Clear(); }
|
||||
if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
|
||||
if (multi_select_data->RequestSetRange) { selection.SetRange((int)(intptr_t)multi_select_data->RangeSrc, (int)(intptr_t)multi_select_data->RangeDst, multi_select_data->RangeValue ? 1 : 0); }
|
||||
|
||||
if (widget_type == WidgetType_TreeNode)
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more text into the same line");
|
||||
if (ImGui::TreeNode("Rendering more text into the same line"))
|
||||
{
|
||||
@@ -4046,7 +4030,7 @@ static void ShowDemoWindowTables()
|
||||
sprintf(buf, "Hello %d,%d", column, row);
|
||||
if (contents_type == CT_Text)
|
||||
ImGui::TextUnformatted(buf);
|
||||
else if (contents_type)
|
||||
else if (contents_type == CT_FillButton)
|
||||
ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
|
||||
}
|
||||
}
|
||||
@@ -5839,12 +5823,18 @@ static void ShowDemoWindowMisc()
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Display ImGuiIO output flags
|
||||
ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
|
||||
ImGui::Text("WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
|
||||
ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
|
||||
ImGui::Text("WantTextInput: %d", io.WantTextInput);
|
||||
ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
|
||||
ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
|
||||
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Output");
|
||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||
if (ImGui::TreeNode("Output"))
|
||||
{
|
||||
ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
|
||||
ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
|
||||
ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
|
||||
ImGui::Text("io.WantTextInput: %d", io.WantTextInput);
|
||||
ImGui::Text("io.WantSetMousePos: %d", io.WantSetMousePos);
|
||||
ImGui::Text("io.NavActive: %d, io.NavVisible: %d", io.NavActive, io.NavVisible);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
// Display Mouse state
|
||||
IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Mouse State");
|
||||
@@ -5877,6 +5867,7 @@ static void ShowDemoWindowMisc()
|
||||
#else
|
||||
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
|
||||
const ImGuiKey key_first = 0;
|
||||
//ImGui::Text("Legacy raw:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
|
||||
#endif
|
||||
ImGui::Text("Keys down:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (%.02f secs)", ImGui::GetKeyName(key), key, ImGui::GetKeyData(key)->DownDuration); } }
|
||||
ImGui::Text("Keys pressed:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } }
|
||||
@@ -6448,7 +6439,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
|
||||
|
||||
ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
|
||||
ImGui::Checkbox("Rounded corner textures", &style.RoundCornersUseTex);
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
|
||||
if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
|
||||
|
||||
886
imgui_draw.cpp
886
imgui_draw.cpp
@@ -90,7 +90,7 @@ Index of this file:
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// [SECTION] STB libraries implementation
|
||||
// [SECTION] STB libraries implementation (for stb_truetype and stb_rect_pack)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Compile time options:
|
||||
@@ -1388,373 +1388,12 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
|
||||
PathStroke(col, 0, thickness);
|
||||
}
|
||||
|
||||
// Add instructions to draw a rectangle with rounded corners to the draw list
|
||||
// a is the top-left coordinate of the rectangle, b is the bottom-right
|
||||
// flags should contains a mask indicating which corners should be drawn rounded
|
||||
// Returns true if the rectangle was drawn, false for some reason it couldn't
|
||||
// be (in which case the caller should try again with the regular path drawing API)
|
||||
// We are using the textures generated by ImFontAtlasBuildRenderRoundCornersTexData()
|
||||
inline bool AddRoundCornerRect(ImDrawList* draw_list, const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, float thickness, ImDrawFlags flags, bool fill)
|
||||
{
|
||||
if (!(draw_list->Flags & ImDrawListFlags_RoundCornersUseTex)) // Disabled by the draw list flags
|
||||
return false;
|
||||
|
||||
#if 1
|
||||
flags = FixRectCornerFlags(flags);
|
||||
rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f);
|
||||
rounding = ImMin(rounding, ImFabs(b.y - a.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f);
|
||||
#endif
|
||||
|
||||
const ImDrawListSharedData* data = draw_list->_Data;
|
||||
IM_ASSERT_PARANOID(!(data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners)); // No data in font
|
||||
|
||||
// Filled rectangles have no stroke width
|
||||
const int stroke_width = fill ? 1 : (int)thickness;
|
||||
if (stroke_width <= 0 || (int)stroke_width > ImFontAtlasRoundCornersMaxStrokeWidth)
|
||||
return false; // We can't handle this
|
||||
|
||||
// If we have a >1 stroke width, we actually need to increase the radius appropriately as well to match how the geometry renderer does things
|
||||
const int rad = (int)rounding + (stroke_width - 1);
|
||||
|
||||
// We don't support zero radius
|
||||
if (rad <= 0 || rad > ImFontAtlasRoundCornersMaxSize)
|
||||
return false; // We can't handle this
|
||||
|
||||
// This is a very awkward special case - if two opposing corners are curved *and* the width/height of the rectangle is <= 2x radius, the non-curved corner overlaps with the curved one
|
||||
// Technically this is fixable but it's a major PITA to do so instead we just don't support that (hopefully very rare) case
|
||||
const ImDrawFlags corner_flags = (flags & ImDrawFlags_RoundCornersMask_);
|
||||
if ((((b.x - a.x) <= (rad * 2)) || ((b.y - a.y) <= (rad * 2))) &&
|
||||
((corner_flags == (ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight)) || (corner_flags == (ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft))))
|
||||
return false;
|
||||
|
||||
const int square_rad = stroke_width + (stroke_width - 1); // Radius to use for square corners and sides - because increasing stroke width grows the line on both sides, we need to do this slightly odd calculation
|
||||
|
||||
// Another awkward special case - if rectangle is smaller than the stroke width then we can get bits of one corner poking out from the other at small sizes when we draw a non-filled rect with a mix of rounded and square corners
|
||||
// (technically this test can be refined to check for possible left/right and top/bottom clashes independently, but it's almost certainly not worth the added complexity)
|
||||
if ((((b.x - a.x) <= square_rad) || ((b.y - a.y) <= square_rad)) && (!fill) &&
|
||||
(corner_flags != 0) && (corner_flags != ImDrawFlags_RoundCornersAll))
|
||||
return false;
|
||||
|
||||
const unsigned int index = (stroke_width - 1) + ((rad - 1) * ImFontAtlasRoundCornersMaxStrokeWidth);
|
||||
ImFontRoundedCornerData& round_corner_data = (*data->TexRoundCornerData)[index];
|
||||
const unsigned int square_index = (stroke_width - 1) + ((square_rad - 1) * ImFontAtlasRoundCornersMaxStrokeWidth);
|
||||
ImFontRoundedCornerData& square_corner_data = (*data->TexSquareCornerData)[square_index];
|
||||
|
||||
if ((round_corner_data.RectId < 0) || (square_corner_data.RectId < 0))
|
||||
return false; // No data for this configuration
|
||||
|
||||
ImTextureID tex_id = data->Font->ContainerAtlas->TexID;
|
||||
IM_ASSERT(tex_id == draw_list->_TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
|
||||
|
||||
// Calculate UVs for the three points we are interested in from the texture
|
||||
// - corner_uv[0] is the innermost point of the circle (solid for filled circles)
|
||||
// - corner_uv[1] is either straight down or across from it (depending on if we are using the filled or stroked version)
|
||||
// - corner_uv[2] is diagonally across from it
|
||||
// - corner_uv[1] is always solid (either inside the circle or on the line), whilst corner_uv[2] is always blank
|
||||
// This represents a 45 degree "wedge" of circle, which then gets mirrored here to produce a 90 degree curve
|
||||
// See ImFontAtlasBuildRenderRoundCornersTexData() for more details of the texture contents
|
||||
// If use_alternative_uvs is true then this means we are drawing a stroked texture that has been packed into the "filled"
|
||||
// corner of the area on the texture page, so we need to calculate UVs appropriately
|
||||
const ImVec4& round_uvs = fill ? round_corner_data.TexUvFilled : round_corner_data.TexUvStroked;
|
||||
const bool round_use_alternative_uvs = fill | round_corner_data.StrokedUsesAlternateUVs;
|
||||
const ImVec2 round_corner_uv[3] =
|
||||
{
|
||||
ImVec2(round_uvs.x, round_uvs.y),
|
||||
round_use_alternative_uvs ? ImVec2(round_uvs.x, round_uvs.w) : ImVec2(round_uvs.z, round_uvs.y),
|
||||
ImVec2(round_uvs.z, round_uvs.w)
|
||||
};
|
||||
|
||||
// Do the same for square corners
|
||||
const ImVec4& square_uvs = fill ? square_corner_data.TexUvFilled : square_corner_data.TexUvStroked;
|
||||
const bool square_use_alternative_uvs = fill | square_corner_data.StrokedUsesAlternateUVs;
|
||||
const ImVec2 square_corner_uv[3] =
|
||||
{
|
||||
ImVec2(square_uvs.x, square_uvs.y),
|
||||
square_use_alternative_uvs ? ImVec2(square_uvs.x, square_uvs.w) : ImVec2(square_uvs.z, square_uvs.y),
|
||||
ImVec2(square_uvs.z, square_uvs.w)
|
||||
};
|
||||
|
||||
// In this code A-D represent the four corners of the rectangle, going clockwise from the top-left:
|
||||
//
|
||||
// A---B
|
||||
// | |
|
||||
// D---C
|
||||
|
||||
const bool ba = (flags & ImDrawFlags_RoundCornersTopLeft) != 0;
|
||||
const bool bb = (flags & ImDrawFlags_RoundCornersTopRight) != 0;
|
||||
const bool bc = (flags & ImDrawFlags_RoundCornersBottomRight) != 0;
|
||||
const bool bd = (flags & ImDrawFlags_RoundCornersBottomLeft) != 0;
|
||||
|
||||
// Flags indicating which sides should use the rounded texture
|
||||
const bool side_rounded_l = fill && (ba || bd);
|
||||
const bool side_rounded_r = fill && (bb || bc);
|
||||
const bool side_rounded_t = fill && (ba || bb);
|
||||
const bool side_rounded_b = fill && (bd || bc);
|
||||
|
||||
// UVs to use for each corner and the edges
|
||||
const ImVec2* corner_uv_a = ba ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* corner_uv_b = bb ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* corner_uv_c = bc ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* corner_uv_d = bd ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* edge_uv_l = side_rounded_l ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* edge_uv_r = side_rounded_r ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* edge_uv_t = side_rounded_t ? round_corner_uv : square_corner_uv;
|
||||
const ImVec2* edge_uv_b = side_rounded_b ? round_corner_uv : square_corner_uv;
|
||||
|
||||
// The base vertices for the rectangle
|
||||
//
|
||||
// C are the corner vertices, I the interior ones,
|
||||
// and M the intermediate points on the edge of each
|
||||
// rounded section, as shown below:
|
||||
//
|
||||
// CA--MAY--------MBY--CB
|
||||
// | |
|
||||
// MAX IA--------IB MBX
|
||||
// | | | |
|
||||
// | | | |
|
||||
// MDX ID--------IC MCX
|
||||
// | |
|
||||
// CD--MDY--------MCY--CC
|
||||
|
||||
// Adjust size to account for the fact that wider strokes draw "outside the box"
|
||||
const float stroke_width_size_expansion = stroke_width - 1.0f;
|
||||
|
||||
// The thickness of each edge piece
|
||||
const int left_side_thickness = side_rounded_l ? rad : square_rad;
|
||||
const int right_side_thickness = side_rounded_r ? rad : square_rad;
|
||||
const int top_side_thickness = side_rounded_t ? rad : square_rad;
|
||||
const int bottom_side_thickness = side_rounded_b ? rad : square_rad;
|
||||
|
||||
// The sizes of the corner pieces
|
||||
const int size_a = ba ? rad : square_rad;
|
||||
const int size_b = bb ? rad : square_rad;
|
||||
const int size_c = bc ? rad : square_rad;
|
||||
const int size_d = bd ? rad : square_rad;
|
||||
|
||||
const ImVec2 ca(a.x - stroke_width_size_expansion, a.y - stroke_width_size_expansion), cb(b.x + stroke_width_size_expansion, a.y - stroke_width_size_expansion);
|
||||
const ImVec2 may(ca.x + size_a, ca.y), mby(cb.x - size_b, cb.y);
|
||||
const ImVec2 max(ca.x, ca.y + size_a), mbx(cb.x, cb.y + size_b);
|
||||
const ImVec2 ia(ca.x + size_a, ca.y + size_a), ib(cb.x - size_b, cb.y + size_b);
|
||||
|
||||
const ImVec2 cc(b.x + stroke_width_size_expansion, b.y + stroke_width_size_expansion), cd(a.x - stroke_width_size_expansion, b.y + stroke_width_size_expansion);
|
||||
const ImVec2 mdx(cd.x, cd.y - size_d), mcx(cc.x, cc.y - size_c);
|
||||
const ImVec2 mdy(cd.x + size_d, cd.y), mcy(cc.x - size_c, cc.y);
|
||||
const ImVec2 id(cd.x + size_d, cd.y - size_d), ic(cc.x - size_c, cc.y - size_c);
|
||||
|
||||
// Positions for edge vertices
|
||||
//
|
||||
// Each letter of the name refers to one of (t)op, (b)ottom, (l)eft or (r)ight
|
||||
// The first letter is the edge, and the second and third are the position on that edge, so for example:
|
||||
// tbr = (t)op edge, (b)ottom (r)ight vertex
|
||||
|
||||
const ImVec2 ttl = may;
|
||||
const ImVec2 ttr = mby;
|
||||
const ImVec2 tbr(mby.x, mby.y + (fill ? size_b : top_side_thickness));
|
||||
const ImVec2 tbl(may.x, may.y + (fill ? size_a : top_side_thickness));
|
||||
|
||||
const ImVec2 btl(mdy.x, mdy.y - (fill ? size_d : bottom_side_thickness));
|
||||
const ImVec2 btr(mcy.x, mcy.y - (fill ? size_c : bottom_side_thickness));
|
||||
const ImVec2 bbr = mcy;
|
||||
const ImVec2 bbl = mdy;
|
||||
|
||||
const ImVec2 ltl = max;
|
||||
const ImVec2 ltr(max.x + (fill ? size_a : left_side_thickness), max.y);
|
||||
const ImVec2 lbr(mdx.x + (fill ? size_d : left_side_thickness), mdx.y);
|
||||
const ImVec2 lbl = mdx;
|
||||
|
||||
const ImVec2 rtl(mbx.x - (fill ? size_b : right_side_thickness), mbx.y);
|
||||
const ImVec2 rtr = mbx;
|
||||
const ImVec2 rbr = mcx;
|
||||
const ImVec2 rbl(mcx.x - (fill ? size_c : right_side_thickness), mcx.y);
|
||||
|
||||
// Reserve enough space for the vertices/indices
|
||||
const int vtcs = fill ? (4 * 9) : (4 * 8);
|
||||
const int idcs = fill ? (6 * 9) : (6 * 8);
|
||||
draw_list->PrimReserve(idcs, vtcs);
|
||||
|
||||
const ImDrawIdx idx = (ImDrawIdx)draw_list->_VtxCurrentIdx;
|
||||
|
||||
// Snap a position to the nearest pixel to ensure correct rasterisation
|
||||
#define SNAP_POS(vec) (ImVec2(ImFloor((vec).x + 0.5f), ImFloor((vec).y + 0.5f)))
|
||||
|
||||
// Write a corner vertex to the draw list, with d being the vertex index,
|
||||
// p the position, c is the corner and i the index into the UV list
|
||||
#define VTX_WRITE_CORNER(d, p, c, i) \
|
||||
draw_list->_VtxWritePtr[d].pos = SNAP_POS(p); \
|
||||
draw_list->_VtxWritePtr[d].uv = corner_uv_##c[(i)]; \
|
||||
draw_list->_VtxWritePtr[d].col = col
|
||||
|
||||
// Write a vertex for one of the edge sections, with d being the vertex index,
|
||||
// p the position, e is the edge (t/l/b/r) and i the index into the UV list
|
||||
#define VTX_WRITE_EDGE(d, p, e, i) \
|
||||
draw_list->_VtxWritePtr[d].pos = SNAP_POS(p); \
|
||||
draw_list->_VtxWritePtr[d].uv = edge_uv_##e[(i)]; \
|
||||
draw_list->_VtxWritePtr[d].col = col
|
||||
|
||||
// Write a vertex for the center fill, with d being the vertex index and
|
||||
// p the position
|
||||
#define VTX_WRITE_FILL(d, p) \
|
||||
draw_list->_VtxWritePtr[d].pos = SNAP_POS(p); \
|
||||
draw_list->_VtxWritePtr[d].uv = round_corner_uv[0]; \
|
||||
draw_list->_VtxWritePtr[d].col = col
|
||||
|
||||
int dv = 0; // A count of the number of vertices we've written
|
||||
int di = 0; // The number of indices we have written
|
||||
|
||||
// Write a triangle using three indices
|
||||
#define IDX_WRITE_TRI(idx0, idx1, idx2) \
|
||||
draw_list->_IdxWritePtr[di] = (ImDrawIdx)(idx+(idx0)); \
|
||||
draw_list->_IdxWritePtr[di+1] = (ImDrawIdx)(idx+(idx1)); \
|
||||
draw_list->_IdxWritePtr[di+2] = (ImDrawIdx)(idx+(idx2)); \
|
||||
di += 3
|
||||
|
||||
// Top-left corner
|
||||
{
|
||||
VTX_WRITE_CORNER(dv + 0, ca, a, 2);
|
||||
VTX_WRITE_CORNER(dv + 1, may, a, 1);
|
||||
VTX_WRITE_CORNER(dv + 2, ia, a, 0);
|
||||
VTX_WRITE_CORNER(dv + 3, max, a, 1);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Top-right corner
|
||||
{
|
||||
VTX_WRITE_CORNER(dv + 0, cb, b, 2);
|
||||
VTX_WRITE_CORNER(dv + 1, mbx, b, 1);
|
||||
VTX_WRITE_CORNER(dv + 2, ib, b, 0);
|
||||
VTX_WRITE_CORNER(dv + 3, mby, b, 1);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Bottom-right corner
|
||||
{
|
||||
VTX_WRITE_CORNER(dv + 0, ic, c, 0);
|
||||
VTX_WRITE_CORNER(dv + 1, mcx, c, 1);
|
||||
VTX_WRITE_CORNER(dv + 2, cc, c, 2);
|
||||
VTX_WRITE_CORNER(dv + 3, mcy, c, 1);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Bottom-left corner
|
||||
{
|
||||
VTX_WRITE_CORNER(dv + 0, cd, d, 2);
|
||||
VTX_WRITE_CORNER(dv + 1, mdx, d, 1);
|
||||
VTX_WRITE_CORNER(dv + 2, id, d, 0);
|
||||
VTX_WRITE_CORNER(dv + 3, mdy, d, 1);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Top edge
|
||||
{
|
||||
VTX_WRITE_EDGE(dv + 0, ttl, t, 1);
|
||||
VTX_WRITE_EDGE(dv + 1, ttr, t, 1);
|
||||
VTX_WRITE_EDGE(dv + 2, tbr, t, 0);
|
||||
VTX_WRITE_EDGE(dv + 3, tbl, t, 0);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Right edge
|
||||
{
|
||||
VTX_WRITE_EDGE(dv + 0, rtl, r, 0);
|
||||
VTX_WRITE_EDGE(dv + 1, rtr, r, 1);
|
||||
VTX_WRITE_EDGE(dv + 2, rbr, r, 1);
|
||||
VTX_WRITE_EDGE(dv + 3, rbl, r, 0);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Bottom edge
|
||||
{
|
||||
VTX_WRITE_EDGE(dv + 0, btl, b, 0);
|
||||
VTX_WRITE_EDGE(dv + 1, btr, b, 0);
|
||||
VTX_WRITE_EDGE(dv + 2, bbr, b, 1);
|
||||
VTX_WRITE_EDGE(dv + 3, bbl, b, 1);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Left edge
|
||||
{
|
||||
VTX_WRITE_EDGE(dv + 0, ltl, l, 1);
|
||||
VTX_WRITE_EDGE(dv + 1, ltr, l, 0);
|
||||
VTX_WRITE_EDGE(dv + 2, lbr, l, 0);
|
||||
VTX_WRITE_EDGE(dv + 3, lbl, l, 1);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
// Fill
|
||||
if (fill)
|
||||
{
|
||||
VTX_WRITE_FILL(dv + 0, ia);
|
||||
VTX_WRITE_FILL(dv + 1, ib);
|
||||
VTX_WRITE_FILL(dv + 2, ic);
|
||||
VTX_WRITE_FILL(dv + 3, id);
|
||||
|
||||
IDX_WRITE_TRI(dv + 0, dv + 1, dv + 2);
|
||||
IDX_WRITE_TRI(dv + 0, dv + 2, dv + 3);
|
||||
dv += 4;
|
||||
}
|
||||
|
||||
draw_list->_VtxWritePtr += dv;
|
||||
draw_list->_VtxCurrentIdx += dv;
|
||||
draw_list->_IdxWritePtr += di;
|
||||
|
||||
IM_ASSERT_PARANOID(di == idcs);
|
||||
IM_ASSERT_PARANOID(dv == vtcs);
|
||||
|
||||
// Return any unused vertices/indices
|
||||
// (not required ATM as we always generate the right number)
|
||||
//draw_list->PrimUnreserve(idcs - di, vtcs - dv);
|
||||
|
||||
#undef SNAP_POS
|
||||
#undef IDX_WRITE_TRI
|
||||
#undef VTX_WRITE_CORNER
|
||||
#undef VTX_WRITE_EDGE
|
||||
#undef VTX_WRITE_FILL
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// p_min = upper-left, p_max = lower-right
|
||||
// Note we don't render 1 pixels sized rectangles properly.
|
||||
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
#if 1
|
||||
flags = FixRectCornerFlags(flags);
|
||||
rounding = ImMin(rounding, ImFabs(p_max.x - p_min.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f);
|
||||
rounding = ImMin(rounding, ImFabs(p_max.y - p_min.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f);
|
||||
#endif
|
||||
|
||||
// Try to use fast path if we can
|
||||
if (rounding > 0)
|
||||
if (AddRoundCornerRect(this, p_min, p_max, col, rounding, thickness, flags, /* fill */ false))
|
||||
return;
|
||||
|
||||
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
||||
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
|
||||
else
|
||||
@@ -1766,13 +1405,6 @@ void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 c
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
#if 1
|
||||
flags = FixRectCornerFlags(flags);
|
||||
rounding = ImMin(rounding, ImFabs(p_max.x - p_min.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f);
|
||||
rounding = ImMin(rounding, ImFabs(p_max.y - p_min.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f);
|
||||
#endif
|
||||
|
||||
if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
|
||||
{
|
||||
PrimReserve(6, 4);
|
||||
@@ -1780,10 +1412,6 @@ void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 c
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try fast path first
|
||||
if (AddRoundCornerRect(this, p_min, p_max, col, rounding, 1.0f, flags, /* fill */ true))
|
||||
return;
|
||||
|
||||
PathRect(p_min, p_max, rounding, flags);
|
||||
PathFillConvex(col);
|
||||
}
|
||||
@@ -1851,197 +1479,11 @@ void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImV
|
||||
PathFillConvex(col);
|
||||
}
|
||||
|
||||
// Draw a circle using the rounded corner textures
|
||||
// Returns true if the circle was drawn, or false if for some reason it could not be
|
||||
// (in which case the caller should try the regular circle drawing code)
|
||||
inline bool AddRoundCornerCircle(ImDrawList* draw_list, const ImVec2& center, float radius, float thickness, ImU32 col, bool fill)
|
||||
{
|
||||
if (!(draw_list->Flags & ImDrawListFlags_RoundCornersUseTex)) // Disabled by the draw list flags
|
||||
return false;
|
||||
|
||||
const ImDrawListSharedData* data = draw_list->_Data;
|
||||
ImTextureID tex_id = data->Font->ContainerAtlas->TexID;
|
||||
IM_ASSERT(tex_id == draw_list->_TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
|
||||
IM_ASSERT_PARANOID(!(data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners)); // No data in font
|
||||
|
||||
// Filled rectangles have no stroke width
|
||||
const int stroke_width = fill ? 1 : (int)thickness;
|
||||
|
||||
if ((stroke_width <= 0) ||
|
||||
(stroke_width > ImFontAtlasRoundCornersMaxStrokeWidth))
|
||||
return false; // We can't handle this
|
||||
|
||||
// If we have a >1 stroke width, we actually need to increase the radius appropriately as well to match how the geometry renderer does things
|
||||
const int rad = (int)radius + (stroke_width - 1);
|
||||
|
||||
// We don't support zero radius
|
||||
if ((rad <= 0) || (rad > ImFontAtlasRoundCornersMaxSize))
|
||||
return false; // We can't handle this
|
||||
|
||||
const unsigned int index = (stroke_width - 1) + ((rad - 1) * ImFontAtlasRoundCornersMaxStrokeWidth);
|
||||
ImFontRoundedCornerData& round_corner_data = (*data->TexRoundCornerData)[index];
|
||||
|
||||
if (round_corner_data.RectId < 0)
|
||||
return false; // No data for this configuration
|
||||
|
||||
// Calculate UVs for the three points we are interested in from the texture
|
||||
// corner_uv[0] is the innermost point of the circle (solid for filled circles)
|
||||
// corner_uv[1] is either straight down or across from it (depending on if we are using the filled or stroked version)
|
||||
// corner_uv[2] is diagonally across from it
|
||||
// corner_uv[1] is always solid (either inside the circle or on the line), whilst corner_uv[2] is always blank
|
||||
// This represents a 45 degree "wedge" of circle, which then gets mirrored here to produce a 90 degree curve
|
||||
// See ImFontAtlasBuildRenderRoundCornersTexData() for more details of the texture contents
|
||||
// If use_alternative_uvs is true then this means we are drawing a stroked texture that has been packed into the "filled"
|
||||
// corner of the rectangle, so we need to calculate UVs appropriately
|
||||
const ImVec4& uvs = fill ? round_corner_data.TexUvFilled : round_corner_data.TexUvStroked;
|
||||
const bool use_alternative_uvs = fill | round_corner_data.StrokedUsesAlternateUVs;
|
||||
const ImVec2 corner_uv[3] =
|
||||
{
|
||||
ImVec2(uvs.x, uvs.y),
|
||||
use_alternative_uvs ? ImVec2(uvs.x, uvs.w) : ImVec2(uvs.z, uvs.y),
|
||||
ImVec2(uvs.z, uvs.w)
|
||||
};
|
||||
|
||||
// Calculate the circle bounds
|
||||
const ImVec2& c = center;
|
||||
ImVec2 tl = ImVec2(c.x - rad, c.y - rad);
|
||||
ImVec2 br = ImVec2(c.x + rad, c.y + rad);
|
||||
|
||||
// Some useful constants for our calculations
|
||||
const float half_sqrt_two = 0.70710678f; // sqrtf(2.0f) * 0.5f
|
||||
const float width_offset_parametric = round_corner_data.ParametricStrokeWidth; // Stroke width in our parametric coordinate space
|
||||
|
||||
const int num_verts = fill ? 9 : 16; // Number of vertices we are going to write
|
||||
const int num_indices = fill ? 24 : 48; // Number of indices we are going to write
|
||||
|
||||
draw_list->PrimReserve(num_indices, num_verts);
|
||||
|
||||
// Write a vertex
|
||||
// - d is the vertex index to write to
|
||||
// - vert_pos is the vertex position
|
||||
// - uv_coord is the UV coordinate
|
||||
#define VTX_WRITE(d, vert_pos, uv_coord) \
|
||||
draw_list->_VtxWritePtr[d].pos = vert_pos; \
|
||||
draw_list->_VtxWritePtr[d].uv = uv_coord; \
|
||||
draw_list->_VtxWritePtr[d].col = col
|
||||
|
||||
// Edge vertices working around the circle clockwise from the left
|
||||
VTX_WRITE(0, ImVec2(tl.x, c.y), corner_uv[1]);
|
||||
VTX_WRITE(1, tl, corner_uv[2]);
|
||||
VTX_WRITE(2, ImVec2(c.x, tl.y), corner_uv[1]);
|
||||
VTX_WRITE(3, ImVec2(br.x, tl.y), corner_uv[2]);
|
||||
VTX_WRITE(4, ImVec2(br.x, c.y), corner_uv[1]);
|
||||
VTX_WRITE(5, br, corner_uv[2]);
|
||||
VTX_WRITE(6, ImVec2(c.x, br.y), corner_uv[1]);
|
||||
VTX_WRITE(7, ImVec2(tl.x, br.y), corner_uv[2]);
|
||||
|
||||
if (fill)
|
||||
{
|
||||
// The center
|
||||
VTX_WRITE(8, c, corner_uv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inside vertices on the diagonals of each quadrant
|
||||
const ImVec2 tlbi = ImVec2(ImLerp(c.x, tl.x, half_sqrt_two - width_offset_parametric), ImLerp(c.y, tl.y, half_sqrt_two - width_offset_parametric));
|
||||
const ImVec2 trbi = ImVec2(ImLerp(c.x, br.x, half_sqrt_two - width_offset_parametric), ImLerp(c.y, tl.y, half_sqrt_two - width_offset_parametric));
|
||||
const ImVec2 brbi = ImVec2(ImLerp(c.x, br.x, half_sqrt_two - width_offset_parametric), ImLerp(c.y, br.y, half_sqrt_two - width_offset_parametric));
|
||||
const ImVec2 blbi = ImVec2(ImLerp(c.x, tl.x, half_sqrt_two - width_offset_parametric), ImLerp(c.y, br.y, half_sqrt_two - width_offset_parametric));
|
||||
|
||||
// UV for the inside diagonal points
|
||||
ImVec2 uvbi = ImVec2(ImLerp(corner_uv[0].x, corner_uv[2].x, half_sqrt_two - width_offset_parametric), ImLerp(corner_uv[0].y, corner_uv[2].y, half_sqrt_two - width_offset_parametric));
|
||||
|
||||
// Left/right/top/bottom interior positions
|
||||
const ImVec2 lbi = ImVec2(ImLerp(tl.x, c.x, width_offset_parametric), c.y);
|
||||
const ImVec2 rbi = ImVec2(ImLerp(br.x, c.x, width_offset_parametric), c.y);
|
||||
const ImVec2 tbi = ImVec2(c.x, ImLerp(tl.y, c.y, width_offset_parametric));
|
||||
const ImVec2 bbi = ImVec2(c.x, ImLerp(br.y, c.y, width_offset_parametric));
|
||||
|
||||
// UV for the interior cardinal points
|
||||
ImVec2 uvi_cardinal = use_alternative_uvs ?
|
||||
ImVec2(corner_uv[0].x, ImLerp(corner_uv[2].y, corner_uv[0].y, width_offset_parametric)) :
|
||||
ImVec2(ImLerp(corner_uv[2].x, corner_uv[0].x, width_offset_parametric), corner_uv[0].y);
|
||||
|
||||
// Inner vertices, starting from the left
|
||||
VTX_WRITE(8, lbi, uvi_cardinal);
|
||||
VTX_WRITE(9, tlbi, uvbi);
|
||||
VTX_WRITE(10, tbi, uvi_cardinal);
|
||||
VTX_WRITE(11, trbi, uvbi);
|
||||
VTX_WRITE(12, rbi, uvi_cardinal);
|
||||
VTX_WRITE(13, brbi, uvbi);
|
||||
VTX_WRITE(14, bbi, uvi_cardinal);
|
||||
VTX_WRITE(15, blbi, uvbi);
|
||||
}
|
||||
|
||||
// Write indices for a triangle formed of three indices
|
||||
// d is the array index to write to
|
||||
#define IDX_WRITE_TRI(d, idx0, idx1, idx2) \
|
||||
draw_list->_IdxWritePtr[d+0] = (ImDrawIdx)(idx+idx0); \
|
||||
draw_list->_IdxWritePtr[d+1] = (ImDrawIdx)(idx+idx1); \
|
||||
draw_list->_IdxWritePtr[d+2] = (ImDrawIdx)(idx+idx2)
|
||||
|
||||
ImDrawIdx idx = (ImDrawIdx)draw_list->_VtxCurrentIdx;
|
||||
|
||||
if (fill)
|
||||
{
|
||||
// A simple fan of tris from the center
|
||||
IDX_WRITE_TRI(0, 8, 0, 1);
|
||||
IDX_WRITE_TRI(3, 8, 1, 2);
|
||||
IDX_WRITE_TRI(6, 8, 2, 3);
|
||||
IDX_WRITE_TRI(9, 8, 3, 4);
|
||||
IDX_WRITE_TRI(12, 8, 4, 5);
|
||||
IDX_WRITE_TRI(15, 8, 5, 6);
|
||||
IDX_WRITE_TRI(18, 8, 6, 7);
|
||||
IDX_WRITE_TRI(21, 8, 7, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// A ring of inner vertices that are tight to the circle, spanning out to the four corners
|
||||
// Top-left quadrant
|
||||
IDX_WRITE_TRI(0, 1, 0, 8);
|
||||
IDX_WRITE_TRI(3, 1, 8, 9);
|
||||
IDX_WRITE_TRI(6, 1, 9, 10);
|
||||
IDX_WRITE_TRI(9, 1, 10, 2);
|
||||
|
||||
// Top-right quadrant
|
||||
IDX_WRITE_TRI(12, 3, 2, 10);
|
||||
IDX_WRITE_TRI(15, 3, 10, 11);
|
||||
IDX_WRITE_TRI(18, 3, 11, 12);
|
||||
IDX_WRITE_TRI(21, 3, 12, 4);
|
||||
|
||||
// Bottom-right quadrant
|
||||
IDX_WRITE_TRI(24, 5, 4, 12);
|
||||
IDX_WRITE_TRI(27, 5, 12, 13);
|
||||
IDX_WRITE_TRI(30, 5, 13, 14);
|
||||
IDX_WRITE_TRI(33, 5, 14, 6);
|
||||
|
||||
// Bottom-left quadrant
|
||||
IDX_WRITE_TRI(36, 7, 6, 14);
|
||||
IDX_WRITE_TRI(39, 7, 14, 15);
|
||||
IDX_WRITE_TRI(42, 7, 15, 8);
|
||||
IDX_WRITE_TRI(45, 7, 8, 0);
|
||||
}
|
||||
|
||||
draw_list->_VtxWritePtr += num_verts;
|
||||
draw_list->_VtxCurrentIdx += num_verts;
|
||||
draw_list->_IdxWritePtr += num_indices;
|
||||
|
||||
#undef IDX_WRITE_TRI
|
||||
#undef VTX_WRITE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f)
|
||||
return;
|
||||
|
||||
// First try the fast texture-based renderer, and only if that can't handle this fall back to paths
|
||||
if (AddRoundCornerCircle(this, center, radius, thickness, col, false))
|
||||
return;
|
||||
|
||||
// Obtain segment count
|
||||
if (num_segments <= 0)
|
||||
{
|
||||
// Use arc with automatic segment count
|
||||
@@ -2066,10 +1508,6 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col,
|
||||
if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f)
|
||||
return;
|
||||
|
||||
// First try the fast texture-based renderer, and only if that can't handle this fall back to paths
|
||||
if (AddRoundCornerCircle(this, center, radius, 1.0f, col, true))
|
||||
return;
|
||||
|
||||
if (num_segments <= 0)
|
||||
{
|
||||
// Use arc with automatic segment count
|
||||
@@ -2092,7 +1530,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col,
|
||||
// Guaranteed to honor 'num_segments'
|
||||
void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0 || (num_segments <= 2) || (radius <= 0.0f))
|
||||
if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2)
|
||||
return;
|
||||
|
||||
// Because we are filling a closed shape we remove 1 from the count of segments/points
|
||||
@@ -2104,7 +1542,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_
|
||||
// Guaranteed to honor 'num_segments'
|
||||
void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0 || (num_segments <= 2) || (radius <= 0.0f))
|
||||
if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2)
|
||||
return;
|
||||
|
||||
// Because we are filling a closed shape we remove 1 from the count of segments/points
|
||||
@@ -2567,7 +2005,6 @@ void ImFontAtlas::ClearInputData()
|
||||
ConfigData.clear();
|
||||
CustomRects.clear();
|
||||
PackIdMouseCursors = PackIdLines = -1;
|
||||
TexRoundCornerData.clear();
|
||||
// Important: we leave TexReady untouched
|
||||
}
|
||||
|
||||
@@ -3200,8 +2637,8 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
|
||||
for (int i = 0; i < pack_rects.Size; i++)
|
||||
if (pack_rects[i].was_packed)
|
||||
{
|
||||
user_rects[i].X = pack_rects[i].x;
|
||||
user_rects[i].Y = pack_rects[i].y;
|
||||
user_rects[i].X = (unsigned short)pack_rects[i].x;
|
||||
user_rects[i].Y = (unsigned short)pack_rects[i].y;
|
||||
IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);
|
||||
atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);
|
||||
}
|
||||
@@ -3318,8 +2755,6 @@ static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas)
|
||||
}
|
||||
}
|
||||
|
||||
static void ImFontAtlasBuildRegisterRoundCornersCustomRects(ImFontAtlas* atlas);
|
||||
|
||||
// Note: this is called / shared by both the stb_truetype and the FreeType builder
|
||||
void ImFontAtlasBuildInit(ImFontAtlas* atlas)
|
||||
{
|
||||
@@ -3339,224 +2774,6 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
|
||||
if (!(atlas->Flags & ImFontAtlasFlags_NoBakedLines))
|
||||
atlas->PackIdLines = atlas->AddCustomRectRegular(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1);
|
||||
}
|
||||
|
||||
ImFontAtlasBuildRegisterRoundCornersCustomRects(atlas);
|
||||
}
|
||||
|
||||
const int FONT_ATLAS_ROUNDED_CORNER_TEX_PADDING = 2;
|
||||
const int FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING = 4; // Padding applied to the Y axis to separate the two halves of the image (this must be a multiple of two)
|
||||
|
||||
// Register the rectangles we need for the rounded corner images
|
||||
static void ImFontAtlasBuildRegisterRoundCornersCustomRects(ImFontAtlas* atlas)
|
||||
{
|
||||
if (atlas->TexRoundCornerData.Size > 0)
|
||||
return;
|
||||
if (atlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners)
|
||||
return;
|
||||
|
||||
const int pad = FONT_ATLAS_ROUNDED_CORNER_TEX_PADDING;
|
||||
const unsigned int max_radius = ImFontAtlasRoundCornersMaxSize;
|
||||
const unsigned int max_thickness = ImFontAtlasRoundCornersMaxStrokeWidth;
|
||||
|
||||
atlas->TexRoundCornerData.reserve(max_radius * max_thickness * 2);
|
||||
|
||||
// We do this twice, one for rounded corners and once for square corners
|
||||
for (int square = 0; square < 2; square++) // 1 for square corners
|
||||
{
|
||||
for (unsigned int radius_index = 0; radius_index < max_radius; radius_index++)
|
||||
{
|
||||
int spare_rect_id = -1; // The last rectangle ID we generated with a spare half
|
||||
for (unsigned int stroke_width_index = 0; stroke_width_index < max_thickness; stroke_width_index++)
|
||||
{
|
||||
const int width = radius_index + 1 + pad * 2;
|
||||
const int height = radius_index + 1 + FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING + pad * 2;
|
||||
|
||||
ImFontRoundedCornerData corner_data;
|
||||
if ((ImFontAtlasRoundCornersStrokeWidthMask & (1 << stroke_width_index)) && (ImFontAtlasRoundCornersSizeMask & (1ULL << radius_index)))
|
||||
{
|
||||
if (stroke_width_index == 0 || spare_rect_id < 0)
|
||||
{
|
||||
corner_data.RectId = atlas->AddCustomRectRegular(width, height);
|
||||
corner_data.StrokedUsesAlternateUVs = false;
|
||||
if (stroke_width_index != 0)
|
||||
spare_rect_id = corner_data.RectId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pack this into the spare half of the previous rect
|
||||
corner_data.RectId = spare_rect_id;
|
||||
corner_data.StrokedUsesAlternateUVs = true;
|
||||
spare_rect_id = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
corner_data.RectId = -1; // Set RectId to -1 if we don't want any data
|
||||
}
|
||||
|
||||
ImVector<ImFontRoundedCornerData>& data_list = square ? atlas->TexSquareCornerData : atlas->TexRoundCornerData;
|
||||
|
||||
IM_ASSERT_PARANOID(data_list.Size == (int)index);
|
||||
data_list.push_back(corner_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the actual pixel data for rounded corners in the atlas
|
||||
static void ImFontAtlasBuildRenderRoundCornersTexData(ImFontAtlas* atlas)
|
||||
{
|
||||
IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);
|
||||
if (atlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners)
|
||||
return;
|
||||
|
||||
// Render the texture
|
||||
const int w = atlas->TexWidth;
|
||||
const unsigned int max = ImFontAtlasRoundCornersMaxSize * ImFontAtlasRoundCornersMaxStrokeWidth;
|
||||
const int pad = FONT_ATLAS_ROUNDED_CORNER_TEX_PADDING;
|
||||
IM_ASSERT(atlas->TexRoundCornerData.Size == (int)max); // ImFontAtlasBuildRegisterRoundCornersCustomRects() will have created these for us
|
||||
IM_ASSERT(atlas->TexSquareCornerData.Size == (int)max);
|
||||
|
||||
const unsigned int max_radius = ImFontAtlasRoundCornersMaxSize;
|
||||
const unsigned int max_thickness = ImFontAtlasRoundCornersMaxStrokeWidth;
|
||||
|
||||
for (int square = 0; square < 2; square++) // 1 = Square corners instead of round
|
||||
{
|
||||
ImVector<ImFontRoundedCornerData>& data_list = square ? atlas->TexSquareCornerData : atlas->TexRoundCornerData;
|
||||
|
||||
data_list.reserve(max_radius * max_thickness);
|
||||
|
||||
for (unsigned int radius_index = 0; radius_index < max_radius; radius_index++)
|
||||
for (unsigned int stroke_width_index = 0; stroke_width_index < max_thickness; stroke_width_index++)
|
||||
{
|
||||
const unsigned int index = stroke_width_index + (radius_index * ImFontAtlasRoundCornersMaxStrokeWidth);
|
||||
const unsigned int radius = radius_index + 1;
|
||||
const float stroke_width = (float)stroke_width_index + 1;
|
||||
|
||||
ImFontRoundedCornerData& data = data_list[index];
|
||||
if (data.RectId < 0)
|
||||
continue; // We don't want to generate data for this
|
||||
|
||||
ImFontAtlasCustomRect& r = atlas->CustomRects[data.RectId];
|
||||
IM_ASSERT(r.IsPacked());
|
||||
IM_ASSERT(r.Width == radius + pad * 2 && r.Height == radius + FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING + pad * 2);
|
||||
|
||||
// If we are generating data for a stroke width > 0, then look for another stroke width sharing this rectangle
|
||||
float other_stroke_width = -1.0f;
|
||||
ImFontRoundedCornerData* other_data = NULL;
|
||||
|
||||
if (stroke_width_index > 0)
|
||||
{
|
||||
// We use the fact that we know shared pairs will always appear together to both make this check fast and skip trying
|
||||
// to generate the second half of the pair again when the main loop comes around
|
||||
stroke_width_index++;
|
||||
while (stroke_width_index < max_thickness)
|
||||
{
|
||||
const unsigned int candidate_index = stroke_width_index + (radius_index * ImFontAtlasRoundCornersMaxStrokeWidth);
|
||||
ImFontRoundedCornerData* candidate_data = &data_list[candidate_index];
|
||||
|
||||
if (candidate_data->RectId == data.RectId)
|
||||
{
|
||||
other_data = candidate_data;
|
||||
other_stroke_width = (float)stroke_width_index + 1;
|
||||
other_data->ParametricStrokeWidth = ((other_stroke_width > 1.0f) ? (other_stroke_width + 2.0f) : other_stroke_width) / (float)radius;
|
||||
break;
|
||||
}
|
||||
|
||||
stroke_width_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// What we're doing here is generating a rectangular image that contains the data for both the filled and
|
||||
// stroked variants of the corner with the radius specified. We do it like this because we only need 45 degrees
|
||||
// worth of curve (as each corner mirrors the texture to get the full 90 degrees), and hence with a little care
|
||||
// we can put both variants into one texture by using two triangular regions. In practice this is a little more
|
||||
// tricky than it first looks because if the two regions are packed tightly you get filtering errors where they meet,
|
||||
// so we offset one vertically from the other by FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING pixels.
|
||||
// The stroked version is at the top-right of the texture, and the filled version at the bottom-left.
|
||||
|
||||
// Pre-calculate the parametric stroke width (+2 to give space for texture filtering on non-single-pixel widths)
|
||||
data.ParametricStrokeWidth = ((stroke_width > 1.0f) ? (stroke_width + 2.0f) : stroke_width) / (float)radius;
|
||||
|
||||
for (int y = -pad; y < (int)(radius + FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING + pad); y++)
|
||||
for (int x = -pad; x < (int)(radius); x++)
|
||||
{
|
||||
// We want the pad area to essentially contain a clamped version of the 0th row/column, so
|
||||
// clamp here. Not doing this results in nasty filtering artifacts at low radii.
|
||||
const float sampling_offset = 0.25f; // Experimentally obtained offset to compensate for sampling point
|
||||
float cx = ImMax(x + sampling_offset, 0.0f);
|
||||
float cy = ImMax(y + sampling_offset, 0.0f);
|
||||
|
||||
// The X<Y region of the texture contains the data for filled corners, the X>Y region
|
||||
// the data for stroked ones. We add half of FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING so that
|
||||
// each side gets a buffer zone to avoid filtering artifacts.
|
||||
// For stroke widths > 1, we use the "filled" area to hold a second stroke width variant
|
||||
const bool filled = x < (y - (FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING >> 1));
|
||||
if (filled)
|
||||
{
|
||||
// The filled version starts a little further down the texture to give us the padding in the middle.
|
||||
cy = ImMax((float)y - FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING, 0.0f);
|
||||
}
|
||||
|
||||
const float dist = (square ? ImMax(cx, cy) : ImSqrt((float)(cx*cx + cy * cy))) - (float)(radius - (filled ? 0 : (stroke_width * 0.5f) + 0.5f));
|
||||
float alpha = 0.0f;
|
||||
if (filled)
|
||||
{
|
||||
if (stroke_width_index > 0)
|
||||
{
|
||||
if (other_data)
|
||||
{
|
||||
// Using the filled section to hold a second stroke width variant instead of filled if we are at a stroke width > 1
|
||||
const float other_dist = (square ? ImMax(cx, cy) : ImSqrt((float)(cx*cx + cy*cy))) - (float)(radius - ((other_stroke_width * 0.5f) + 0.5f));
|
||||
const float alpha1 = ImClamp(other_dist + other_stroke_width, 0.0f, 1.0f);
|
||||
const float alpha2 = ImClamp(other_dist, 0.0f, 1.0f);
|
||||
alpha = alpha1 - alpha2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = ImClamp(-dist, 0.0f, 1.0f); // Filled version
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const float alpha1 = ImClamp(dist + stroke_width, 0.0f, 1.0f);
|
||||
const float alpha2 = ImClamp(dist, 0.0f, 1.0f);
|
||||
alpha = alpha1 - alpha2;
|
||||
}
|
||||
|
||||
const unsigned int offset = (int)(r.X + pad + x) + (int)(r.Y + pad + y) * w;
|
||||
atlas->TexPixelsAlpha8[offset] = (unsigned char)(0xFF * ImSaturate(alpha));
|
||||
}
|
||||
|
||||
// We generate two sets of UVs for each rectangle, one for the filled portion and one for the unfilled bit.
|
||||
for (unsigned int stage = 0; stage < 2; stage++)
|
||||
{
|
||||
ImFontAtlasCustomRect stage_rect = r;
|
||||
|
||||
const bool filled = (stage == 0);
|
||||
stage_rect.X += pad;
|
||||
stage_rect.Y += pad + (filled ? FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING : 0);
|
||||
stage_rect.Width -= (pad * 2);
|
||||
stage_rect.Height -= (pad * 2) + FONT_ATLAS_ROUNDED_CORNER_TEX_CENTER_PADDING;
|
||||
|
||||
ImVec2 uv0, uv1;
|
||||
atlas->CalcCustomRectUV(&stage_rect, &uv0, &uv1);
|
||||
|
||||
if (stage == 0)
|
||||
{
|
||||
if (other_data)
|
||||
other_data->TexUvStroked = ImVec4(uv0.x, uv0.y, uv1.x, uv1.y);
|
||||
else
|
||||
data.TexUvFilled = ImVec4(uv0.x, uv0.y, uv1.x, uv1.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.TexUvStroked = ImVec4(uv0.x, uv0.y, uv1.x, uv1.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is called/shared by both the stb_truetype and the FreeType builder.
|
||||
@@ -3567,9 +2784,6 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
|
||||
ImFontAtlasBuildRenderDefaultTexData(atlas);
|
||||
ImFontAtlasBuildRenderLinesTexData(atlas);
|
||||
|
||||
// Render into our rounded corner data block
|
||||
ImFontAtlasBuildRenderRoundCornersTexData(atlas);
|
||||
|
||||
// Register custom rectangle glyphs
|
||||
for (int i = 0; i < atlas->CustomRects.Size; i++)
|
||||
{
|
||||
@@ -4525,7 +3739,6 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
// - RenderArrowPointingAt()
|
||||
// - RenderRectFilledRangeH()
|
||||
// - RenderRectFilledWithHole()
|
||||
// - RenderWindowResizeGrip()
|
||||
//-----------------------------------------------------------------------------
|
||||
// Function in need of a redesign (legacy mess)
|
||||
// - RenderColorRectWithAlphaCheckerboard()
|
||||
@@ -4665,7 +3878,7 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
|
||||
draw_list->PathFillConvex(col);
|
||||
}
|
||||
|
||||
void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding)
|
||||
void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding)
|
||||
{
|
||||
const bool fill_L = (inner.Min.x > outer.Min.x);
|
||||
const bool fill_R = (inner.Max.x < outer.Max.x);
|
||||
@@ -4681,92 +3894,6 @@ void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect
|
||||
if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomRight);
|
||||
}
|
||||
|
||||
// Add a resize grip using the rounded corner textures, if possible.
|
||||
// Returns false if rendering could not be performed, true otherwise
|
||||
// FIXME: Probably ok to move this to imgui_draw.cpp in 'Internal Render Helpers' section.
|
||||
bool ImGui::RenderWindowResizeGrip(ImDrawList* draw_list, const ImVec2& corner, unsigned int rad, unsigned int overall_grip_size, ImDrawFlags flags, ImU32 col)
|
||||
{
|
||||
// Texture path disabled by the draw list flags
|
||||
// Texture path disabled for radius 0 which cause issues with the UV lookup below
|
||||
const bool use_tex = (draw_list->Flags & ImDrawListFlags_RoundCornersUseTex) && (rad >= 1 && rad <= ImFontAtlasRoundCornersMaxSize);
|
||||
if (use_tex == false)
|
||||
return false;
|
||||
|
||||
ImFontAtlas* atlas = draw_list->_Data->Font->ContainerAtlas;
|
||||
IM_ASSERT(atlas->TexID == draw_list->_TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
|
||||
IM_ASSERT(ImIsPowerOfTwo(flags)); // Only allow a single corner to be specified here.
|
||||
IM_ASSERT_PARANOID((atlas->Flags & ImFontAtlasFlags_NoBakedRoundCorners) == 0);
|
||||
|
||||
// Calculate UVs for the three points we are interested in from the texture
|
||||
// - uv[0] is the mid-point from the corner towards the center of the circle (solid)
|
||||
// - uv[1] is a solid point on the edge of the circle
|
||||
// - uv[2] is the outer edge (blank, outside the circle)
|
||||
const unsigned int index = (rad - 1) * ImFontAtlasRoundCornersMaxStrokeWidth;
|
||||
const ImVec4& uvs = (*draw_list->_Data->TexRoundCornerData)[index].TexUvFilled;
|
||||
const ImVec2 uv[] =
|
||||
{
|
||||
ImVec2(ImLerp(uvs.x, uvs.z, 0.5f), ImLerp(uvs.y, uvs.w, 0.5f)),
|
||||
ImVec2(uvs.x, uvs.y),
|
||||
ImVec2(uvs.z, uvs.w),
|
||||
};
|
||||
|
||||
// Calculate the coordinates of the points at the inside of the rounded area of the corner, and the outside of the grip on the X/Y axes
|
||||
ImVec2 in_x = corner, in_y = corner, out_x = corner, out_y = corner;
|
||||
if (flags & (ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight))
|
||||
{
|
||||
in_y.y += rad;
|
||||
out_y.y += overall_grip_size;
|
||||
}
|
||||
else if (flags & (ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight))
|
||||
{
|
||||
in_y.y -= rad;
|
||||
out_y.y -= overall_grip_size;
|
||||
}
|
||||
|
||||
if (flags & (ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomLeft))
|
||||
{
|
||||
in_x.x += rad;
|
||||
out_x.x += overall_grip_size;
|
||||
}
|
||||
else if (flags & (ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight))
|
||||
{
|
||||
in_x.x -= rad;
|
||||
out_x.x -= overall_grip_size;
|
||||
}
|
||||
|
||||
// Calculate the mid-point on the diagonal
|
||||
const ImVec2 mid = ImVec2(ImLerp(in_x.x, in_y.x, 0.5f), ImLerp(in_x.y, in_y.y, 0.5f));
|
||||
|
||||
// Now write out the geometry
|
||||
const int num_verts = 6; // Number of vertices we are going to write
|
||||
const int num_indices = 12; // Number of indices we are going to write
|
||||
draw_list->PrimReserve(num_indices, num_verts);
|
||||
|
||||
unsigned int idx = draw_list->_VtxCurrentIdx;
|
||||
ImDrawVert* vtx_write_ptr = draw_list->_VtxWritePtr;
|
||||
ImDrawIdx* idx_write_ptr = draw_list->_IdxWritePtr;
|
||||
vtx_write_ptr[0].pos = mid; vtx_write_ptr[0].uv = uv[0]; vtx_write_ptr[0].col = col;
|
||||
vtx_write_ptr[1].pos = in_y; vtx_write_ptr[1].uv = uv[1]; vtx_write_ptr[1].col = col;
|
||||
vtx_write_ptr[2].pos = corner; vtx_write_ptr[2].uv = uv[2]; vtx_write_ptr[2].col = col;
|
||||
vtx_write_ptr[3].pos = in_x; vtx_write_ptr[3].uv = uv[1]; vtx_write_ptr[3].col = col;
|
||||
vtx_write_ptr[4].pos = out_x; vtx_write_ptr[4].uv = uv[1]; vtx_write_ptr[4].col = col;
|
||||
vtx_write_ptr[5].pos = out_y; vtx_write_ptr[5].uv = uv[1]; vtx_write_ptr[5].col = col;
|
||||
|
||||
// Curved section
|
||||
idx_write_ptr[0] = (ImDrawIdx)(idx); idx_write_ptr[1] = (ImDrawIdx)(idx + 1); idx_write_ptr[2] = (ImDrawIdx)(idx + 2);
|
||||
idx_write_ptr[3] = (ImDrawIdx)(idx); idx_write_ptr[4] = (ImDrawIdx)(idx + 2); idx_write_ptr[5] = (ImDrawIdx)(idx + 3);
|
||||
|
||||
// Outer section
|
||||
idx_write_ptr[6] = (ImDrawIdx)(idx + 4); idx_write_ptr[7] = (ImDrawIdx)(idx + 3); idx_write_ptr[8] = (ImDrawIdx)(idx + 5);
|
||||
idx_write_ptr[9] = (ImDrawIdx)(idx + 3); idx_write_ptr[10] = (ImDrawIdx)(idx + 5); idx_write_ptr[11] = (ImDrawIdx)(idx + 1);
|
||||
|
||||
draw_list->_VtxWritePtr += num_verts;
|
||||
draw_list->_VtxCurrentIdx += num_verts;
|
||||
draw_list->_IdxWritePtr += num_indices;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper for ColorPicker4()
|
||||
// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
|
||||
// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether.
|
||||
@@ -4808,7 +3935,6 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Decompression code
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -122,6 +122,7 @@ struct ImGuiGroupData; // Stacked storage data for BeginGroup()/End
|
||||
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
|
||||
struct ImGuiLastItemData; // Status storage for last submitted items
|
||||
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
|
||||
struct ImGuiMultiSelectState; // Multi-selection state
|
||||
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
|
||||
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
|
||||
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
|
||||
@@ -136,6 +137,7 @@ struct ImGuiTabBar; // Storage for a tab bar
|
||||
struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
|
||||
struct ImGuiTable; // Storage for a table
|
||||
struct ImGuiTableColumn; // Storage for one column of a table
|
||||
struct ImGuiTableInstanceData; // Storage for one instance of a same table
|
||||
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
|
||||
struct ImGuiTableSettings; // Storage for a table .ini settings
|
||||
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
|
||||
@@ -231,7 +233,7 @@ namespace ImStb
|
||||
#define IM_NEWLINE "\n"
|
||||
#endif
|
||||
#define IM_TABSIZE (4)
|
||||
#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
|
||||
#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
|
||||
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
|
||||
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
|
||||
#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
|
||||
@@ -547,11 +549,11 @@ struct ImBitArray
|
||||
ImBitArray() { ClearAllBits(); }
|
||||
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
|
||||
void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
|
||||
bool TestBit(int n) const { IM_ASSERT(n + OFFSET < BITCOUNT); return ImBitArrayTestBit(Storage, n + OFFSET); }
|
||||
void SetBit(int n) { IM_ASSERT(n + OFFSET < BITCOUNT); ImBitArraySetBit(Storage, n + OFFSET); }
|
||||
void ClearBit(int n) { IM_ASSERT(n + OFFSET < BITCOUNT); ImBitArrayClearBit(Storage, n + OFFSET); }
|
||||
void SetBitRange(int n, int n2) { ImBitArraySetBitRange(Storage, n + OFFSET, n2 + OFFSET); } // Works on range [n..n2)
|
||||
bool operator[](int n) const { IM_ASSERT(n + OFFSET < BITCOUNT); return ImBitArrayTestBit(Storage, n + OFFSET); }
|
||||
bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
|
||||
void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); }
|
||||
void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
|
||||
void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
|
||||
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
|
||||
};
|
||||
|
||||
// Helper: ImBitVector
|
||||
@@ -725,9 +727,6 @@ struct IMGUI_API ImDrawListSharedData
|
||||
ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead)
|
||||
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas
|
||||
|
||||
ImVector<ImFontRoundedCornerData>* TexRoundCornerData; // Data for texture-based rounded corners, indexed by radius
|
||||
ImVector<ImFontRoundedCornerData>* TexSquareCornerData; // Data for texture-based square corners, indexed by radius
|
||||
|
||||
ImDrawListSharedData();
|
||||
void SetCircleTessellationMaxError(float max_error);
|
||||
};
|
||||
@@ -1083,18 +1082,20 @@ struct ImGuiNextWindowData
|
||||
|
||||
enum ImGuiNextItemDataFlags_
|
||||
{
|
||||
ImGuiNextItemDataFlags_None = 0,
|
||||
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
|
||||
ImGuiNextItemDataFlags_HasOpen = 1 << 1
|
||||
ImGuiNextItemDataFlags_None = 0,
|
||||
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
|
||||
ImGuiNextItemDataFlags_HasOpen = 1 << 1,
|
||||
ImGuiNextItemDataFlags_HasSelectionData = 1 << 2
|
||||
};
|
||||
|
||||
struct ImGuiNextItemData
|
||||
{
|
||||
ImGuiNextItemDataFlags Flags;
|
||||
float Width; // Set by SetNextItemWidth()
|
||||
ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging)
|
||||
float Width; // Set by SetNextItemWidth()
|
||||
ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging)
|
||||
ImGuiCond OpenCond;
|
||||
bool OpenVal; // Set by SetNextItemOpen()
|
||||
bool OpenVal; // Set by SetNextItemOpen()
|
||||
void* SelectionData; // Set by SetNextItemSelectionData() (note that NULL/0 is a valid value)
|
||||
|
||||
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); }
|
||||
inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()!
|
||||
@@ -1337,9 +1338,10 @@ struct ImGuiNavItemData
|
||||
float DistBox; // Move // Best candidate box distance to current NavId
|
||||
float DistCenter; // Move // Best candidate center distance to current NavId
|
||||
float DistAxial; // Move // Best candidate axial distance to current NavId
|
||||
bool HasSelectionData; // Move // Copy of (NextItemData.Flags & ImGuiNextItemDataFlags_HasSelection)
|
||||
|
||||
ImGuiNavItemData() { Clear(); }
|
||||
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; }
|
||||
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; HasSelectionData = false; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1403,7 +1405,20 @@ struct ImGuiOldColumns
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef IMGUI_HAS_MULTI_SELECT
|
||||
// <this is filled in 'range_select' branch>
|
||||
|
||||
struct IMGUI_API ImGuiMultiSelectState
|
||||
{
|
||||
ImGuiID FocusScopeId; // Same as CurrentWindow->DC.FocusScopeIdCurrent (unless another selection scope was pushed manually)
|
||||
ImGuiID BackupFocusScopeId;
|
||||
ImGuiMultiSelectData In; // The In requests are set and returned by BeginMultiSelect()
|
||||
ImGuiMultiSelectData Out; // The Out requests are finalized and returned by EndMultiSelect()
|
||||
bool InRangeDstPassedBy; // (Internal) set by the the item that match NavJustMovedToId when InRequestRangeSetNav is set.
|
||||
bool InRequestSetRangeNav; // (Internal) set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
|
||||
|
||||
ImGuiMultiSelectState() { Clear(); }
|
||||
void Clear() { FocusScopeId = BackupFocusScopeId = 0; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
|
||||
};
|
||||
|
||||
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1659,6 +1674,7 @@ struct ImGuiContext
|
||||
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
|
||||
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
|
||||
ImGuiKeyModFlags NavJustMovedToKeyMods;
|
||||
bool NavJustMovedToHasSelectionData; // " (FIXME-NAV: We should maybe just store ImGuiNavMoveResult)
|
||||
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
||||
ImGuiActivateFlags NavNextActivateFlags;
|
||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
|
||||
@@ -1701,6 +1717,12 @@ struct ImGuiContext
|
||||
float NavWindowingHighlightAlpha;
|
||||
bool NavWindowingToggleLayer;
|
||||
|
||||
// Range-Select/Multi-Select
|
||||
ImGuiWindow* MultiSelectEnabledWindow; // FIXME-MULTISELECT: We currently don't support recursing/stacking multi-select
|
||||
ImGuiMultiSelectFlags MultiSelectFlags;
|
||||
ImGuiMultiSelectState MultiSelectState;
|
||||
ImGuiKeyModFlags MultiSelectKeyMods;
|
||||
|
||||
// Render
|
||||
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
|
||||
ImGuiMouseCursor MouseCursor;
|
||||
@@ -1871,6 +1893,7 @@ struct ImGuiContext
|
||||
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
||||
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
|
||||
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
|
||||
NavJustMovedToHasSelectionData = false;
|
||||
NavInputSource = ImGuiInputSource_None;
|
||||
NavLayer = ImGuiNavLayer_Main;
|
||||
NavIdIsAlive = false;
|
||||
@@ -1896,6 +1919,10 @@ struct ImGuiContext
|
||||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
||||
NavWindowingToggleLayer = false;
|
||||
|
||||
MultiSelectEnabledWindow = NULL;
|
||||
MultiSelectFlags = ImGuiMultiSelectFlags_None;
|
||||
MultiSelectKeyMods = ImGuiKeyModFlags_None;
|
||||
|
||||
DimBgRatio = 0.0f;
|
||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
|
||||
@@ -2293,6 +2320,15 @@ struct ImGuiTableCellData
|
||||
ImGuiTableColumnIdx Column; // Column number
|
||||
};
|
||||
|
||||
// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs, does that needs they could be moved to ImGuiTableTempData ?)
|
||||
struct ImGuiTableInstanceData
|
||||
{
|
||||
float LastOuterHeight; // Outer height from last frame // FIXME: multi-instance issue (#3955)
|
||||
float LastFirstRowHeight; // Height of first row from last frame // FIXME: possible multi-instance issue?
|
||||
|
||||
ImGuiTableInstanceData() { LastOuterHeight = LastFirstRowHeight = 0.0f; }
|
||||
};
|
||||
|
||||
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
|
||||
struct IMGUI_API ImGuiTable
|
||||
{
|
||||
@@ -2335,8 +2371,6 @@ struct IMGUI_API ImGuiTable
|
||||
float CellPaddingY;
|
||||
float CellSpacingX1; // Spacing between non-bordered cells
|
||||
float CellSpacingX2;
|
||||
float LastOuterHeight; // Outer height from last frame
|
||||
float LastFirstRowHeight; // Height of first row from last frame
|
||||
float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details.
|
||||
float ColumnsGivenWidth; // Sum of current column width
|
||||
float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window
|
||||
@@ -2356,6 +2390,8 @@ struct IMGUI_API ImGuiTable
|
||||
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
|
||||
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
|
||||
ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
|
||||
ImGuiTableInstanceData InstanceDataFirst;
|
||||
ImVector<ImGuiTableInstanceData> InstanceDataExtra; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableColumnSortSpecs SortSpecsSingle;
|
||||
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
|
||||
@@ -2534,6 +2570,8 @@ namespace ImGui
|
||||
IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name);
|
||||
IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);
|
||||
IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name);
|
||||
IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler);
|
||||
IMGUI_API void RemoveSettingsHandler(const char* type_name);
|
||||
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
|
||||
|
||||
// Scrolling
|
||||
@@ -2677,6 +2715,10 @@ namespace ImGui
|
||||
IMGUI_API void ClearDragDrop();
|
||||
IMGUI_API bool IsDragDropPayloadBeingAccepted();
|
||||
|
||||
// New Multi-Selection/Range-Selection API (FIXME-WIP)
|
||||
IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected);
|
||||
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed);
|
||||
|
||||
// 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().
|
||||
@@ -2711,6 +2753,7 @@ namespace ImGui
|
||||
IMGUI_API void TableDrawBorders(ImGuiTable* table);
|
||||
IMGUI_API void TableDrawContextMenu(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]; }
|
||||
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
|
||||
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
|
||||
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
|
||||
@@ -2736,7 +2779,7 @@ namespace ImGui
|
||||
IMGUI_API void TableSaveSettings(ImGuiTable* table);
|
||||
IMGUI_API void TableResetSettings(ImGuiTable* table);
|
||||
IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
|
||||
IMGUI_API void TableSettingsInstallHandler(ImGuiContext* context);
|
||||
IMGUI_API void TableSettingsAddSettingsHandler();
|
||||
IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
|
||||
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
|
||||
|
||||
@@ -2773,9 +2816,8 @@ namespace ImGui
|
||||
IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col);
|
||||
IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz);
|
||||
IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
|
||||
IMGUI_API bool RenderWindowResizeGrip(ImDrawList* draw_list, const ImVec2& corner, unsigned int rad, unsigned int overall_grip_size, ImDrawFlags flags, ImU32 col);
|
||||
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
|
||||
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding);
|
||||
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while]
|
||||
@@ -2876,6 +2918,7 @@ namespace ImGui
|
||||
|
||||
} // namespace ImGui
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImFontAtlas internal API
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2899,16 +2942,6 @@ IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas
|
||||
IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
|
||||
IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
|
||||
|
||||
// Note that stroke width increases effective radius, so (e.g.) a max radius circle will have to use the fallback path if stroke width is > 1. Note that ImFontAtlasRoundCornersSizeMask is 64 bits so this value can only go up to a maximum of 64 at present.
|
||||
const int ImFontAtlasRoundCornersMaxSize = 32; // Maximum size of rounded corner texture to generate in fonts
|
||||
// Bit mask for which radii will have texture generated for them, starting from radius 1. Only bits up to ImFontAtlasRoundCornersMaxSize are considered.
|
||||
const ImU64 ImFontAtlasRoundCornersSizeMask = (1ULL << ImFontAtlasRoundCornersMaxSize) - 1;
|
||||
const int ImFontAtlasRoundCornersMaxStrokeWidth = 4; // Maximum stroke width of rounded corner texture to generate in fonts
|
||||
// Bit mask for which stroke widths should have textures generated for them (the default of 0x0B means widths 1, 2 and 4)
|
||||
// Only bits up to ImFontAtlasRoundCornersMaxStrokeWidth are considered, and bit 0 (stroke width 1) must always be set
|
||||
// Optimally there should be an odd number of bits set, as the texture packing packs the data in pairs, with one half of one pair being occupied by the filled texture
|
||||
const ImU32 ImFontAtlasRoundCornersStrokeWidthMask = 0x0B;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Test Engine specific hooks (imgui_test_engine)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -361,6 +361,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
table->IsLayoutLocked = false;
|
||||
table->InnerWidth = inner_width;
|
||||
temp_data->UserOuterSize = outer_size;
|
||||
if (instance_no > 0 && table->InstanceDataExtra.Size < instance_no)
|
||||
table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
|
||||
|
||||
// When not using a child window, WorkRect.Max will grow as we append contents.
|
||||
if (use_child_window)
|
||||
@@ -933,9 +935,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
width_remaining_for_stretched_columns -= 1.0f;
|
||||
}
|
||||
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
table->HoveredColumnBody = -1;
|
||||
table->HoveredColumnBorder = -1;
|
||||
const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight));
|
||||
const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table_instance->LastOuterHeight));
|
||||
const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0);
|
||||
|
||||
// [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
|
||||
@@ -1096,7 +1099,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
// [Part 10] Hit testing on borders
|
||||
if (table->Flags & ImGuiTableFlags_Resizable)
|
||||
TableUpdateBorders(table);
|
||||
table->LastFirstRowHeight = 0.0f;
|
||||
table_instance->LastFirstRowHeight = 0.0f;
|
||||
table->IsLayoutLocked = true;
|
||||
table->IsUsingHeaders = false;
|
||||
|
||||
@@ -1141,10 +1144,11 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
|
||||
// use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not
|
||||
// really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
|
||||
// Actual columns highlight/render will be performed in EndTable() and not be affected.
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
|
||||
const float hit_y1 = table->OuterRect.Min.y;
|
||||
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table->LastOuterHeight);
|
||||
const float hit_y2_head = hit_y1 + table->LastFirstRowHeight;
|
||||
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight);
|
||||
const float hit_y2_head = hit_y1 + table_instance->LastFirstRowHeight;
|
||||
|
||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
||||
{
|
||||
@@ -1223,6 +1227,7 @@ void ImGui::EndTable()
|
||||
TableOpenContextMenu((int)table->HoveredColumnBody);
|
||||
|
||||
// Finalize table height
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
|
||||
inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
|
||||
inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
|
||||
@@ -1233,7 +1238,7 @@ void ImGui::EndTable()
|
||||
else if (!(flags & ImGuiTableFlags_NoHostExtendY))
|
||||
table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height
|
||||
table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y);
|
||||
table->LastOuterHeight = table->OuterRect.GetHeight();
|
||||
table_instance->LastOuterHeight = table->OuterRect.GetHeight();
|
||||
|
||||
// Setup inner scrolling range
|
||||
// FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y,
|
||||
@@ -1749,7 +1754,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount);
|
||||
const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest);
|
||||
if (table->CurrentRow == 0)
|
||||
table->LastFirstRowHeight = bg_y2 - bg_y1;
|
||||
TableGetInstanceData(table, table->InstanceCurrent)->LastFirstRowHeight = bg_y2 - bg_y1;
|
||||
|
||||
const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y);
|
||||
if (is_visible)
|
||||
@@ -2502,10 +2507,11 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
|
||||
|
||||
// Draw inner border and resizing feedback
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
const float border_size = TABLE_BORDER_SIZE;
|
||||
const float draw_y1 = table->InnerRect.Min.y;
|
||||
const float draw_y2_body = table->InnerRect.Max.y;
|
||||
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1;
|
||||
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastFirstRowHeight) : draw_y1;
|
||||
if (table->Flags & ImGuiTableFlags_BordersInnerV)
|
||||
{
|
||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
||||
@@ -3427,9 +3433,8 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::TableSettingsInstallHandler(ImGuiContext* context)
|
||||
void ImGui::TableSettingsAddSettingsHandler()
|
||||
{
|
||||
ImGuiContext& g = *context;
|
||||
ImGuiSettingsHandler ini_handler;
|
||||
ini_handler.TypeName = "Table";
|
||||
ini_handler.TypeHash = ImHashStr("Table");
|
||||
@@ -3438,7 +3443,7 @@ void ImGui::TableSettingsInstallHandler(ImGuiContext* context)
|
||||
ini_handler.ReadLineFn = TableSettingsHandler_ReadLine;
|
||||
ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll;
|
||||
ini_handler.WriteAllFn = TableSettingsHandler_WriteAll;
|
||||
g.SettingsHandlers.push_back(ini_handler);
|
||||
AddSettingsHandler(&ini_handler);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -3536,6 +3541,8 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
||||
GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
|
||||
if (!open)
|
||||
return;
|
||||
if (table->InstanceCurrent > 0)
|
||||
ImGui::Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1);
|
||||
bool clear_settings = SmallButton("Clear settings");
|
||||
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
|
||||
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
|
||||
|
||||
@@ -18,6 +18,7 @@ Index of this file:
|
||||
// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
|
||||
// [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
|
||||
// [SECTION] Widgets: Selectable
|
||||
// [SECTION] Widgets: Multi-Selection System
|
||||
// [SECTION] Widgets: ListBox
|
||||
// [SECTION] Widgets: PlotLines, PlotHistogram
|
||||
// [SECTION] Widgets: Value helpers
|
||||
@@ -843,9 +844,8 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
|
||||
// Render
|
||||
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
||||
ImVec2 center = bb.GetCenter();
|
||||
if (hovered || held)
|
||||
window->DrawList->AddCircleFilled(center/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12);
|
||||
window->DrawList->AddCircleFilled(bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12);
|
||||
RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
|
||||
|
||||
// Switch to moving the window after mouse is moved beyond the initial drag threshold
|
||||
@@ -3533,6 +3533,9 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
|
||||
// - InputText()
|
||||
// - InputTextWithHint()
|
||||
// - InputTextMultiline()
|
||||
// - InputTextGetCharInfo() [Internal]
|
||||
// - InputTextReindexLines() [Internal]
|
||||
// - InputTextReindexLinesRange() [Internal]
|
||||
// - InputTextEx() [Internal]
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@@ -4997,8 +5000,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
|
||||
if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
|
||||
{
|
||||
const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x;
|
||||
window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y);
|
||||
SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
TextEx(label, label_display_end);
|
||||
}
|
||||
|
||||
@@ -5899,8 +5901,6 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x;
|
||||
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
|
||||
const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
|
||||
if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
|
||||
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
|
||||
|
||||
// Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags.
|
||||
// Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support.
|
||||
@@ -5921,6 +5921,30 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
|
||||
const bool was_selected = selected;
|
||||
|
||||
// Multi-selection support (header)
|
||||
const bool is_multi_select = (g.MultiSelectEnabledWindow == window);
|
||||
if (is_multi_select)
|
||||
{
|
||||
MultiSelectItemHeader(id, &selected);
|
||||
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
|
||||
|
||||
// We absolutely need to distinguish open vs select so this is the default when multi-select is enabled.
|
||||
flags |= ImGuiTreeNodeFlags_OpenOnArrow;
|
||||
|
||||
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
|
||||
// Enabling this test makes actions using CTRL+SHIFT delay their effect on MouseUp which is annoying, but it allows drag and drop of multiple items.
|
||||
// FIXME-MULTISELECT: Consider opt-in for drag and drop behavior in ImGuiMultiSelectFlags?
|
||||
if (!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore))
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClick;
|
||||
else
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
|
||||
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
|
||||
}
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
|
||||
bool toggled = false;
|
||||
@@ -5928,7 +5952,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
{
|
||||
if (pressed && g.DragDropHoldJustPressedId != id)
|
||||
{
|
||||
if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id))
|
||||
if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id && !is_multi_select))
|
||||
toggled = true;
|
||||
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
|
||||
toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
|
||||
@@ -5960,16 +5984,27 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledOpen;
|
||||
}
|
||||
}
|
||||
|
||||
// Multi-selection support (footer)
|
||||
if (is_multi_select)
|
||||
{
|
||||
bool pressed_copy = pressed && !toggled;
|
||||
MultiSelectItemFooter(id, &selected, &pressed_copy);
|
||||
if (pressed)
|
||||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, interact_bb);
|
||||
}
|
||||
|
||||
if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
|
||||
SetItemAllowOverlap();
|
||||
|
||||
// In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger.
|
||||
if (selected != was_selected) //-V547
|
||||
if (selected != was_selected)
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
|
||||
|
||||
// Render
|
||||
const ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
||||
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin;
|
||||
if (is_multi_select)
|
||||
nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
|
||||
if (display_frame)
|
||||
{
|
||||
// Framed type
|
||||
@@ -6219,20 +6254,43 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }
|
||||
if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; }
|
||||
|
||||
// Multi-selection support (header)
|
||||
const bool is_multi_select = (g.MultiSelectEnabledWindow == window);
|
||||
const bool was_selected = selected;
|
||||
if (is_multi_select)
|
||||
{
|
||||
MultiSelectItemHeader(id, &selected);
|
||||
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
|
||||
|
||||
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
|
||||
// Enabling this test makes actions using CTRL+SHIFT delay their effect on the mouse release which is annoying, but it allows drag and drop of multiple items.
|
||||
if (!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore))
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClick;
|
||||
else
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||
}
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
||||
|
||||
// Auto-select when moved into
|
||||
// - This will be more fully fleshed in the range-select branch
|
||||
// - This is not exposed as it won't nicely work with some user side handling of shift/control
|
||||
// - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons
|
||||
// - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())
|
||||
// - (2) usage will fail with clipped items
|
||||
// The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
|
||||
if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent)
|
||||
if (g.NavJustMovedToId == id)
|
||||
selected = pressed = true;
|
||||
// Multi-selection support (footer)
|
||||
if (is_multi_select)
|
||||
{
|
||||
MultiSelectItemFooter(id, &selected, &pressed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Auto-select when moved into
|
||||
// - This will be more fully fleshed in the range-select branch
|
||||
// - This is not exposed as it won't nicely work with some user side handling of shift/control
|
||||
// - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons
|
||||
// - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())
|
||||
// - (2) usage will fail with clipped items
|
||||
// The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
|
||||
if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent)
|
||||
if (g.NavJustMovedToId == id)
|
||||
selected = pressed = true;
|
||||
}
|
||||
|
||||
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
|
||||
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
|
||||
@@ -6249,8 +6307,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
if (flags & ImGuiSelectableFlags_AllowItemOverlap)
|
||||
SetItemAllowOverlap();
|
||||
|
||||
// In this branch, Selectable() cannot toggle the selection so this will never trigger.
|
||||
if (selected != was_selected) //-V547
|
||||
if (selected != was_selected)
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
|
||||
|
||||
// Render
|
||||
@@ -6258,10 +6315,18 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
hovered = true;
|
||||
if (hovered || selected)
|
||||
{
|
||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
// FIXME-MULTISELECT, FIXME-STYLE: Color for 'selected' elements? ImGuiCol_HeaderSelected
|
||||
ImU32 col;
|
||||
if (selected && !hovered)
|
||||
col = GetColorU32(ImLerp(GetStyleColorVec4(ImGuiCol_Header), GetStyleColorVec4(ImGuiCol_HeaderHovered), 0.5f));
|
||||
else
|
||||
col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
|
||||
}
|
||||
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
|
||||
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding;
|
||||
if (is_multi_select)
|
||||
nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
|
||||
RenderNavHighlight(bb, id, nav_highlight_flags);
|
||||
|
||||
if (span_all_columns && window->DC.CurrentColumns)
|
||||
PopColumnsBackground();
|
||||
@@ -6277,6 +6342,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
if (disabled_item && !disabled_global)
|
||||
EndDisabled();
|
||||
|
||||
// Users of BeginMultiSelect() scope: call ImGui::IsItemToggledSelection() to retrieve selection toggle. Selectable() returns a pressed state!
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return pressed; //-V1020
|
||||
}
|
||||
@@ -6291,6 +6357,254 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// [SECTION] Widgets: Multi-Selection System
|
||||
//-------------------------------------------------------------------------
|
||||
// - BeginMultiSelect()
|
||||
// - EndMultiSelect()
|
||||
// - SetNextItemSelectionData()
|
||||
// - MultiSelectItemHeader() [Internal]
|
||||
// - MultiSelectItemFooter() [Internal]
|
||||
//-------------------------------------------------------------------------
|
||||
// FIXME: Shift+click on an item that has no multi-select data could treat selection the same as the last item with such data?
|
||||
// The problem is that this may conflict with other behaviors of those items?
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
ImGuiMultiSelectData* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void* range_ref, bool range_ref_is_selected)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
IM_ASSERT(g.MultiSelectEnabledWindow == NULL); // No recursion allowed yet (we could allow it if we deem it useful)
|
||||
IM_ASSERT(g.MultiSelectFlags == 0);
|
||||
IM_ASSERT(g.MultiSelectState.FocusScopeId == 0);
|
||||
|
||||
// FIXME: BeginFocusScope()
|
||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||
state->Clear();
|
||||
state->BackupFocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
state->FocusScopeId = window->DC.NavFocusScopeIdCurrent = window->IDStack.back();
|
||||
g.MultiSelectEnabledWindow = window;
|
||||
g.MultiSelectFlags = flags;
|
||||
|
||||
// Use copy of keyboard mods at the time of the request, otherwise we would requires mods to be held for an extra frame.
|
||||
g.MultiSelectKeyMods = g.NavJustMovedToId ? g.NavJustMovedToKeyMods : g.IO.KeyMods;
|
||||
|
||||
if ((flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0)
|
||||
{
|
||||
state->In.RangeSrc = state->Out.RangeSrc = range_ref;
|
||||
state->In.RangeValue = state->Out.RangeValue = range_ref_is_selected;
|
||||
}
|
||||
|
||||
// Auto clear when using Navigation to move within the selection (we compare SelectScopeId so it possible to use multiple lists inside a same window)
|
||||
// FIXME: Polling key mods after the fact (frame following the move request) is incorrect, but latching it would requires non-trivial change in MultiSelectItemFooter()
|
||||
if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == state->FocusScopeId && g.NavJustMovedToHasSelectionData)
|
||||
{
|
||||
if (g.MultiSelectKeyMods & ImGuiKeyModFlags_Shift)
|
||||
state->InRequestSetRangeNav = true;
|
||||
if ((g.MultiSelectKeyMods & (ImGuiKeyModFlags_Ctrl | ImGuiKeyModFlags_Shift)) == 0)
|
||||
state->In.RequestClear = true;
|
||||
}
|
||||
|
||||
// Select All helper shortcut
|
||||
// Note: we are comparing FocusScope so we don't need to be testing for IsWindowFocused()
|
||||
if (!(flags & ImGuiMultiSelectFlags_NoMultiSelect) && !(flags & ImGuiMultiSelectFlags_NoSelectAll))
|
||||
if (state->FocusScopeId == g.NavFocusScopeId && g.ActiveId == 0)
|
||||
if (g.IO.KeyCtrl && IsKeyPressed(GetKeyIndex(ImGuiKey_A)))
|
||||
state->In.RequestSelectAll = true;
|
||||
|
||||
#ifdef IMGUI_DEBUG_MULTISELECT
|
||||
if (state->In.RequestClear) printf("[%05d] BeginMultiSelect: RequestClear\n", g.FrameCount);
|
||||
if (state->In.RequestSelectAll) printf("[%05d] BeginMultiSelect: RequestSelectAll\n", g.FrameCount);
|
||||
#endif
|
||||
|
||||
return &state->In;
|
||||
}
|
||||
|
||||
ImGuiMultiSelectData* ImGui::EndMultiSelect()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||
|
||||
IM_ASSERT(g.MultiSelectState.FocusScopeId != 0);
|
||||
IM_ASSERT(g.MultiSelectState.FocusScopeId == window->DC.NavFocusScopeIdCurrent);
|
||||
|
||||
if (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)
|
||||
state->Out.RangeValue = true;
|
||||
g.MultiSelectState.FocusScopeId = 0;
|
||||
window->DC.NavFocusScopeIdCurrent = g.MultiSelectState.BackupFocusScopeId;
|
||||
g.MultiSelectEnabledWindow = NULL;
|
||||
g.MultiSelectFlags = ImGuiMultiSelectFlags_None;
|
||||
|
||||
#ifdef IMGUI_DEBUG_MULTISELECT
|
||||
if (state->Out.RequestClear) printf("[%05d] EndMultiSelect: RequestClear\n", g.FrameCount);
|
||||
if (state->Out.RequestSelectAll) printf("[%05d] EndMultiSelect: RequestSelectAll\n", g.FrameCount);
|
||||
if (state->Out.RequestSetRange) printf("[%05d] EndMultiSelect: RequestSetRange %p..%p = %d\n", g.FrameCount, state->Out.RangeSrc, state->Out.RangeDst, state->Out.RangeValue);
|
||||
#endif
|
||||
|
||||
return &state->Out;
|
||||
}
|
||||
|
||||
void ImGui::SetNextItemSelectionData(void* item_data)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_ASSERT(window->DC.NavFocusScopeIdCurrent != 0);
|
||||
g.NextItemData.SelectionData = item_data;
|
||||
g.NextItemData.FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
|
||||
// Note that the flag will be cleared by ItemAdd(), so it's only useful for Navigation code!
|
||||
// This designed so widgets can also cheaply set this before calling ItemAdd(), so we are not tied to MultiSelect api.
|
||||
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasSelectionData;
|
||||
}
|
||||
|
||||
void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||
|
||||
IM_UNUSED(window);
|
||||
IM_ASSERT(g.NextItemData.FocusScopeId == window->DC.NavFocusScopeIdCurrent && "Forgot to call SetNextItemSelectionData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope");
|
||||
void* item_data = g.NextItemData.SelectionData;
|
||||
|
||||
// Apply Clear/SelectAll requests requested by BeginMultiSelect().
|
||||
// This is only useful if the user hasn't processed them already, and this only works if the user isn't using the clipper.
|
||||
// If you are using a clipper (aka not submitting every element of the list) you need to process the Clear/SelectAll request after calling BeginMultiSelect()
|
||||
bool selected = *p_selected;
|
||||
if (state->In.RequestClear)
|
||||
selected = false;
|
||||
else if (state->In.RequestSelectAll)
|
||||
selected = true;
|
||||
|
||||
const bool is_range_src = (state->In.RangeSrc == item_data);
|
||||
if (is_range_src)
|
||||
state->In.RangeSrcPassedBy = true;
|
||||
|
||||
// When using SHIFT+Nav: because it can incur scrolling we cannot afford a frame of lag with the selection highlight (otherwise scrolling would happen before selection)
|
||||
// For this to work, IF the user is clipping items, they need to set RangeSrcPassedBy = true to notify the system.
|
||||
if (state->InRequestSetRangeNav)
|
||||
{
|
||||
IM_ASSERT(id != 0);
|
||||
IM_ASSERT((g.MultiSelectKeyMods & ImGuiKeyModFlags_Shift) != 0);
|
||||
const bool is_range_dst = !state->InRangeDstPassedBy && g.NavJustMovedToId == id; // Assume that g.NavJustMovedToId is not clipped.
|
||||
if (is_range_dst)
|
||||
state->InRangeDstPassedBy = true;
|
||||
if (is_range_src || is_range_dst || state->In.RangeSrcPassedBy != state->InRangeDstPassedBy)
|
||||
selected = state->In.RangeValue;
|
||||
else if ((g.MultiSelectKeyMods & ImGuiKeyModFlags_Ctrl) == 0)
|
||||
selected = false;
|
||||
}
|
||||
|
||||
*p_selected = selected;
|
||||
}
|
||||
|
||||
void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||
|
||||
void* item_data = g.NextItemData.SelectionData;
|
||||
g.NextItemData.FocusScopeId = 0;
|
||||
|
||||
bool selected = *p_selected;
|
||||
bool pressed = *p_pressed;
|
||||
const bool is_multiselect = (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoMultiSelect) == 0;
|
||||
bool is_ctrl = (g.MultiSelectKeyMods & ImGuiKeyModFlags_Ctrl) != 0;
|
||||
bool is_shift = (g.MultiSelectKeyMods & ImGuiKeyModFlags_Shift) != 0;
|
||||
|
||||
// Auto-select as you navigate a list
|
||||
if (g.NavJustMovedToId == id)
|
||||
{
|
||||
if (is_ctrl && is_shift)
|
||||
pressed = true;
|
||||
else if (!is_ctrl)
|
||||
selected = pressed = true;
|
||||
}
|
||||
|
||||
// Right-click handling: this could be moved at the Selectable() level.
|
||||
bool hovered = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
|
||||
if (hovered && IsMouseClicked(1))
|
||||
{
|
||||
if (g.ActiveId != 0 && g.ActiveId != id)
|
||||
ClearActiveID();
|
||||
SetFocusID(id, window);
|
||||
if (!pressed && !selected)
|
||||
{
|
||||
pressed = true;
|
||||
is_ctrl = is_shift = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// ACTION | Begin | Item Old | Item New | End
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// Keys Navigated, Ctrl=0, Shift=0 | In.Clear | Clear -> Sel=0 | Src=item, Pressed -> Sel=1 |
|
||||
// Keys Navigated, Ctrl=0, Shift=1 | n/a | n/a | Dst=item, Pressed -> Sel=1, Out.Clear, Out.SetRange=1 | Clear + SetRange
|
||||
// Keys Navigated, Ctrl=1, Shift=1 | n/a | n/a | Dst=item, Pressed -> Sel=Src, Out.Clear, Out.SetRange=Src | Clear + SetRange
|
||||
// Mouse Pressed, Ctrl=0, Shift=0 | n/a | n/a (Sel=1) | Src=item, Pressed -> Sel=1, Out.Clear, Out.SetRange=1 | Clear + SetRange
|
||||
// Mouse Pressed, Ctrl=0, Shift=1 | n/a | n/a | Dst=item, Pressed -> Sel=1, Out.Clear, Out.SetRange=1 | Clear + SetRange
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
ImGuiInputSource input_source = (g.NavJustMovedToId != 0 && g.NavWindow == window && g.NavJustMovedToId == g.LastItemData.ID) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
|
||||
if (is_shift && is_multiselect)
|
||||
{
|
||||
state->Out.RequestSetRange = true;
|
||||
state->Out.RangeDst = item_data;
|
||||
if (!is_ctrl)
|
||||
state->Out.RangeValue = true;
|
||||
state->Out.RangeDirection = state->In.RangeSrcPassedBy ? +1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
selected = (!is_ctrl || (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)) ? true : !selected;
|
||||
state->Out.RangeSrc = state->Out.RangeDst = item_data;
|
||||
state->Out.RangeValue = selected;
|
||||
}
|
||||
|
||||
if (input_source == ImGuiInputSource_Mouse)
|
||||
{
|
||||
// Mouse click without CTRL clears the selection, unless the clicked item is already selected
|
||||
bool preserve_existing_selection = g.DragDropActive;
|
||||
if (is_multiselect && !is_ctrl && !preserve_existing_selection)
|
||||
state->Out.RequestClear = true;
|
||||
if (is_multiselect && !is_shift && !preserve_existing_selection && state->Out.RequestClear)
|
||||
{
|
||||
// For toggle selection unless there is a Clear request, we can handle it completely locally without sending a RangeSet request.
|
||||
IM_ASSERT(state->Out.RangeSrc == state->Out.RangeDst); // Setup by block above
|
||||
state->Out.RequestSetRange = true;
|
||||
state->Out.RangeValue = selected;
|
||||
state->Out.RangeDirection = +1;
|
||||
}
|
||||
if (!is_multiselect)
|
||||
{
|
||||
// Clear selection, set single item range
|
||||
IM_ASSERT(state->Out.RangeSrc == item_data && state->Out.RangeDst == item_data); // Setup by block above
|
||||
state->Out.RequestClear = true;
|
||||
state->Out.RequestSetRange = true;
|
||||
}
|
||||
}
|
||||
else if (input_source == ImGuiInputSource_Nav)
|
||||
{
|
||||
if (is_multiselect && is_shift && !is_ctrl)
|
||||
state->Out.RequestClear = true;
|
||||
else if (!is_multiselect)
|
||||
state->Out.RequestClear = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)
|
||||
if (state->Out.RangeSrc == item_data && is_ctrl && is_shift && is_multiselect && !(g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect))
|
||||
state->Out.RangeValue = selected;
|
||||
|
||||
*p_selected = selected;
|
||||
*p_pressed = pressed;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// [SECTION] Widgets: ListBox
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -6925,7 +7239,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
if (!enabled)
|
||||
EndDisabled();
|
||||
|
||||
const bool hovered = (g.HoveredId == id) && enabled;
|
||||
const bool hovered = (g.HoveredId == id) && enabled && !g.NavDisableMouseHover;
|
||||
if (menuset_is_open)
|
||||
g.NavWindow = backed_nav_window;
|
||||
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.00.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Added STBRP__CDECL
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
|
||||
//
|
||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Before #including,
|
||||
//
|
||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||
//
|
||||
// in the file that you want to have the implementation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
@@ -41,6 +45,7 @@
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
@@ -81,11 +86,10 @@ typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
typedef int stbrp_coord;
|
||||
#else
|
||||
typedef unsigned short stbrp_coord;
|
||||
#endif
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
@@ -213,10 +217,9 @@ struct stbrp_context
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
// [DEAR IMGUI] Added STBRP__CDECL
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#define STBRP__CDECL __cdecl
|
||||
#define STBRP__CDECL __cdecl
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#define STBRP__CDECL
|
||||
@@ -262,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
#ifndef STBRP_LARGE_RECTS
|
||||
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||
#endif
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
@@ -283,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
context->extra[1].y = (1<<30);
|
||||
#else
|
||||
context->extra[1].y = 65535;
|
||||
#endif
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
@@ -433,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
STBRP_ASSERT(y <= best_y);
|
||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
@@ -529,7 +525,6 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
||||
return res;
|
||||
}
|
||||
|
||||
// [DEAR IMGUI] Added STBRP__CDECL
|
||||
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
@@ -541,7 +536,6 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
// [DEAR IMGUI] Added STBRP__CDECL
|
||||
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
@@ -549,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
#define STBRP__MAXVAL 0xffffffff
|
||||
#else
|
||||
#define STBRP__MAXVAL 0xffff
|
||||
#endif
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_textedit.h 1.13.
|
||||
// This is a slightly modified version of stb_textedit.h 1.14.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_textedit.h - v1.13 - public domain - Sean Barrett
|
||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||
// Development of this library was sponsored by RAD Game Tools
|
||||
//
|
||||
// This C header file implements the guts of a multi-line text-editing
|
||||
@@ -35,6 +35,7 @@
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.14 (2021-07-11) page up/down, various fixes
|
||||
// 1.13 (2019-02-07) fix bug in undo size management
|
||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
||||
@@ -58,6 +59,7 @@
|
||||
// Ulf Winklemann: move-by-word in 1.1
|
||||
// Fabian Giesen: secondary key inputs in 1.5
|
||||
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
|
||||
// Louis Schnellbach: page up/down in 1.14
|
||||
//
|
||||
// Bugfixes:
|
||||
// Scott Graham
|
||||
@@ -93,8 +95,8 @@
|
||||
// moderate sizes. The undo system does no memory allocations, so
|
||||
// it grows STB_TexteditState by the worst-case storage which is (in bytes):
|
||||
//
|
||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
|
||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
|
||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
|
||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
|
||||
//
|
||||
//
|
||||
// Implementation mode:
|
||||
@@ -716,10 +718,6 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
|
||||
state->has_preferred_x = 0;
|
||||
return 1;
|
||||
}
|
||||
// [DEAR IMGUI]
|
||||
//// remove the undo since we didn't actually insert the characters
|
||||
//if (state->undostate.undo_point)
|
||||
// --state->undostate.undo_point;
|
||||
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
|
||||
return 0;
|
||||
}
|
||||
|
||||
777
imstb_truetype.h
777
imstb_truetype.h
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
||||
// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
|
||||
|
||||
// Usage:
|
||||
// binary_to_compressed_c.exe [-base85] [-nocompress] <inputfile> <symbolname>
|
||||
// binary_to_compressed_c.exe [-base85] [-nocompress] [-nostatic] <inputfile> <symbolname>
|
||||
// Usage example:
|
||||
// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp
|
||||
// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp
|
||||
@@ -31,23 +31,25 @@ typedef unsigned int stb_uint;
|
||||
typedef unsigned char stb_uchar;
|
||||
stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len);
|
||||
|
||||
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression);
|
||||
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression, bool use_static);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
printf("Syntax: %s [-base85] [-nocompress] <inputfile> <symbolname>\n", argv[0]);
|
||||
printf("Syntax: %s [-base85] [-nocompress] [-nostatic] <inputfile> <symbolname>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int argn = 1;
|
||||
bool use_base85_encoding = false;
|
||||
bool use_compression = true;
|
||||
if (argv[argn][0] == '-')
|
||||
bool use_static = true;
|
||||
while (argn < (argc - 2) && argv[argn][0] == '-')
|
||||
{
|
||||
if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; }
|
||||
else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
|
||||
else if (strcmp(argv[argn], "-nostatic") == 0) { use_static = false; argn++; }
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]);
|
||||
@@ -55,7 +57,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression);
|
||||
bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression, use_static);
|
||||
if (!ret)
|
||||
fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
|
||||
return ret ? 0 : 1;
|
||||
@@ -67,7 +69,7 @@ char Encode85Byte(unsigned int x)
|
||||
return (x >= '\\') ? x + 1 : x;
|
||||
}
|
||||
|
||||
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression)
|
||||
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression, bool use_static)
|
||||
{
|
||||
// Read file
|
||||
FILE* f = fopen(filename, "rb");
|
||||
@@ -90,10 +92,11 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
FILE* out = stdout;
|
||||
fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
|
||||
fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
|
||||
const char* static_str = use_static ? "static " : "";
|
||||
const char* compressed_str = use_compression ? "compressed_" : "";
|
||||
if (use_base85_encoding)
|
||||
{
|
||||
fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
|
||||
fprintf(out, "%sconst char %s_%sdata_base85[%d+1] =\n \"", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
|
||||
char prev_c = 0;
|
||||
for (int src_i = 0; src_i < compressed_sz; src_i += 4)
|
||||
{
|
||||
@@ -112,8 +115,8 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz);
|
||||
fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
|
||||
fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz);
|
||||
fprintf(out, "%sconst unsigned int %s_%sdata[%d/4] =\n{", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
|
||||
int column = 0;
|
||||
for (int i = 0; i < compressed_sz; i += 4)
|
||||
{
|
||||
|
||||
@@ -368,7 +368,7 @@ struct ImFontBuildSrcGlyphFT
|
||||
uint32_t Codepoint;
|
||||
unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
|
||||
|
||||
ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); }
|
||||
ImFontBuildSrcGlyphFT() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
struct ImFontBuildSrcDataFT
|
||||
|
||||
Reference in New Issue
Block a user