mirror of https://github.com/WerWolv/ImHex
build: Update ImGui to v1.92.1 (#2325)
Update ImGui to the latest version and rewrite most of the font handling code
This commit is contained in:
parent
fa62a675dc
commit
d1840a2184
1
.gdbinit
1
.gdbinit
|
|
@ -7,6 +7,7 @@ skip -rfu ^ImGui::
|
||||||
|
|
||||||
# Trigger breakpoint when execution reaches triggerSafeShutdown()
|
# Trigger breakpoint when execution reaches triggerSafeShutdown()
|
||||||
break triggerSafeShutdown
|
break triggerSafeShutdown
|
||||||
|
break __glibcxx_assert_fail
|
||||||
|
|
||||||
# Print backtrace after execution jumped to an invalid address
|
# Print backtrace after execution jumped to an invalid address
|
||||||
define fixbt
|
define fixbt
|
||||||
|
|
|
||||||
|
|
@ -748,7 +748,7 @@ EXPORT_MODULE namespace hex {
|
||||||
struct GlyphRange { u16 begin, end; };
|
struct GlyphRange { u16 begin, end; };
|
||||||
struct Offset { float x, y; };
|
struct Offset { float x, y; };
|
||||||
|
|
||||||
struct Font {
|
struct MergeFont {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<u8> fontData;
|
std::vector<u8> fontData;
|
||||||
std::vector<GlyphRange> glyphRanges;
|
std::vector<GlyphRange> glyphRanges;
|
||||||
|
|
@ -758,10 +758,21 @@ EXPORT_MODULE namespace hex {
|
||||||
std::optional<u32> defaultSize;
|
std::optional<u32> defaultSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Font {
|
||||||
|
public:
|
||||||
|
explicit Font(UnlocalizedString fontName);
|
||||||
|
|
||||||
|
void push(float size = 0.0F) const;
|
||||||
|
void pop() const;
|
||||||
|
|
||||||
|
[[nodiscard]] operator ImFont*() const;
|
||||||
|
private:
|
||||||
|
UnlocalizedString m_fontName;
|
||||||
|
};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
const std::vector<Font>& getFonts();
|
const std::vector<MergeFont>& getMergeFonts();
|
||||||
|
|
||||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions();
|
std::map<UnlocalizedString, ImFont*>& getFontDefinitions();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -779,6 +790,9 @@ EXPORT_MODULE namespace hex {
|
||||||
void registerFont(const UnlocalizedString &fontName);
|
void registerFont(const UnlocalizedString &fontName);
|
||||||
ImFont* getFont(const UnlocalizedString &fontName);
|
ImFont* getFont(const UnlocalizedString &fontName);
|
||||||
|
|
||||||
|
void setDefaultFont(const Font& font);
|
||||||
|
const Font& getDefaultFont();
|
||||||
|
|
||||||
float getDpi();
|
float getDpi();
|
||||||
float pixelsToPoints(float pixels);
|
float pixelsToPoints(float pixels);
|
||||||
float pointsToPixels(float points);
|
float pointsToPixels(float points);
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,10 @@ namespace ImGuiExt {
|
||||||
return m_textureId != 0;
|
return m_textureId != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] operator ImTextureRef() const noexcept {
|
||||||
|
return m_textureId;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] operator ImTextureID() const noexcept {
|
[[nodiscard]] operator ImTextureID() const noexcept {
|
||||||
return m_textureId;
|
return m_textureId;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1006,35 +1006,48 @@ namespace hex {
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
static AutoReset<std::vector<Font>> s_fonts;
|
static AutoReset<std::vector<MergeFont>> s_fonts;
|
||||||
const std::vector<Font>& getFonts() {
|
const std::vector<MergeFont>& getMergeFonts() {
|
||||||
return *s_fonts;
|
return *s_fonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float s_fontSize = DefaultFontSize;
|
|
||||||
void setFontSize(float size) {
|
|
||||||
s_fontSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AutoReset<ImFontAtlas*> s_fontAtlas;
|
|
||||||
void setFontAtlas(ImFontAtlas* fontAtlas) {
|
|
||||||
s_fontAtlas = fontAtlas;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ImFont *s_boldFont = nullptr;
|
|
||||||
static ImFont *s_italicFont = nullptr;
|
|
||||||
void setFonts(ImFont *bold, ImFont *italic) {
|
|
||||||
s_boldFont = bold;
|
|
||||||
s_italicFont = italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AutoReset<std::map<UnlocalizedString, ImFont*>> s_fontDefinitions;
|
static AutoReset<std::map<UnlocalizedString, ImFont*>> s_fontDefinitions;
|
||||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions() {
|
std::map<UnlocalizedString, ImFont*>& getFontDefinitions() {
|
||||||
return *s_fontDefinitions;
|
return *s_fontDefinitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AutoReset<const Font*> s_defaultFont;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Font::Font(UnlocalizedString fontName) : m_fontName(std::move(fontName)) {
|
||||||
|
Fonts::registerFont(m_fontName);
|
||||||
|
|
||||||
|
if (impl::s_defaultFont == nullptr)
|
||||||
|
impl::s_defaultFont = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::push(float size) const {
|
||||||
|
auto font = getFont(m_fontName);
|
||||||
|
|
||||||
|
if (size <= 0.0F) {
|
||||||
|
size = font->LegacySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size *= System::getGlobalScale();
|
||||||
|
|
||||||
|
ImGui::PushFont(font, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::pop() const {
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::operator ImFont*() const {
|
||||||
|
return getFont(m_fontName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GlyphRange glyph(const char *glyph) {
|
GlyphRange glyph(const char *glyph) {
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
ImTextCharFromUtf8(&codepoint, glyph, nullptr);
|
ImTextCharFromUtf8(&codepoint, glyph, nullptr);
|
||||||
|
|
@ -1075,7 +1088,7 @@ namespace hex {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl::s_fonts->emplace_back(Font {
|
impl::s_fonts->emplace_back(MergeFont {
|
||||||
wolv::util::toUTF8String(path.filename()),
|
wolv::util::toUTF8String(path.filename()),
|
||||||
fontFile.readVector(),
|
fontFile.readVector(),
|
||||||
glyphRanges,
|
glyphRanges,
|
||||||
|
|
@ -1087,7 +1100,7 @@ namespace hex {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<bool> scalable, std::optional<u32> defaultSize) {
|
void loadFont(const std::string &name, const std::span<const u8> &data, const std::vector<GlyphRange> &glyphRanges, Offset offset, u32 flags, std::optional<bool> scalable, std::optional<u32> defaultSize) {
|
||||||
impl::s_fonts->emplace_back(Font {
|
impl::s_fonts->emplace_back(MergeFont {
|
||||||
name,
|
name,
|
||||||
{ data.begin(), data.end() },
|
{ data.begin(), data.end() },
|
||||||
glyphRanges,
|
glyphRanges,
|
||||||
|
|
@ -1098,14 +1111,6 @@ namespace hex {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
float getFontSize() {
|
|
||||||
return impl::s_fontSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImFontAtlas* getFontAtlas() {
|
|
||||||
return impl::s_fontAtlas;
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerFont(const UnlocalizedString &fontName) {
|
void registerFont(const UnlocalizedString &fontName) {
|
||||||
(*impl::s_fontDefinitions)[fontName] = nullptr;
|
(*impl::s_fontDefinitions)[fontName] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -1114,12 +1119,12 @@ namespace hex {
|
||||||
return (*impl::s_fontDefinitions)[fontName];
|
return (*impl::s_fontDefinitions)[fontName];
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFont* Bold() {
|
void setDefaultFont(const Font& font) {
|
||||||
return impl::s_boldFont;
|
impl::s_defaultFont = &font;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImFont* Italic() {
|
const Font& getDefaultFont() {
|
||||||
return impl::s_italicFont;
|
return **impl::s_defaultFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getDpi() {
|
float getDpi() {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ static bool s_constructingMenu = false;
|
||||||
static bool s_resetNeeded = true;
|
static bool s_resetNeeded = true;
|
||||||
|
|
||||||
void macosMenuBarInit(void) {
|
void macosMenuBarInit(void) {
|
||||||
|
s_menuStackSize = 0;
|
||||||
s_menuStack[0] = NSApp.mainMenu;
|
s_menuStack[0] = NSApp.mainMenu;
|
||||||
s_menuStackSize += 1;
|
s_menuStackSize += 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1019,7 +1019,7 @@ namespace ImGuiExt {
|
||||||
std::string drawString;
|
std::string drawString;
|
||||||
auto textEnd = text + strlen(text);
|
auto textEnd = text + strlen(text);
|
||||||
for (auto wrapPos = text; wrapPos != textEnd;) {
|
for (auto wrapPos = text; wrapPos != textEnd;) {
|
||||||
wrapPos = ImGui::GetFont()->CalcWordWrapPositionA(1, wrapPos, textEnd, availableSpace.x * 0.8F);
|
wrapPos = ImGui::GetFont()->CalcWordWrapPosition(1, wrapPos, textEnd, availableSpace.x * 0.8F);
|
||||||
drawString += std::string(text, wrapPos) + "\n";
|
drawString += std::string(text, wrapPos) + "\n";
|
||||||
text = wrapPos;
|
text = wrapPos;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,13 @@
|
||||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
// Issues:
|
// [X] Multiple Dear ImGui contexts support.
|
||||||
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
// Missing features or Issues:
|
||||||
|
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||||
|
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||||
|
// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
|
@ -63,5 +66,8 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int
|
||||||
|
|
||||||
// GLFW helpers
|
// GLFW helpers
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||||
|
IMGUI_IMPL_API float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window);
|
||||||
|
IMGUI_IMPL_API float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor);
|
||||||
|
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@
|
||||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
|
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||||
|
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
|
|
||||||
// About WebGL/ES:
|
// About WebGL/ES:
|
||||||
|
|
@ -30,18 +31,19 @@
|
||||||
#include "imgui.h" // IMGUI_IMPL_API
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
#ifndef IMGUI_DISABLE
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
||||||
// Backend API
|
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
|
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
|
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||||
|
|
||||||
// (Optional) Called by Init/NewFrame/Shutdown
|
// (Optional) Called by Init/NewFrame/Shutdown
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
|
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
|
|
||||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||||
|
|
||||||
|
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
||||||
|
|
||||||
// Configuration flags to add in your imconfig file:
|
// Configuration flags to add in your imconfig file:
|
||||||
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
|
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
|
||||||
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
|
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,13 @@
|
||||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
// Issues:
|
// [X] Multiple Dear ImGui contexts support.
|
||||||
// [ ] Platform: Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
// Missing features or Issues:
|
||||||
|
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||||
|
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||||
|
// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
|
@ -28,9 +31,16 @@
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2025-06-18: Added support for multiple Dear ImGui contexts. (#8676, #8239, #8069)
|
||||||
|
// 2025-06-11: Added ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window) and ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor) helper to facilitate making DPI-aware apps.
|
||||||
|
// 2025-05-15: [Docking] Add Platform_GetWindowFramebufferScale() handler, to allow varying Retina display density on multiple monitors.
|
||||||
|
// 2025-04-26: [Docking] Disable multi-viewports under Wayland. (#8587)
|
||||||
|
// 2025-03-10: Map GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 into ImGuiKey_Oem102.
|
||||||
|
// 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled.
|
||||||
|
// 2025-02-21: [Docking] Update monitors and work areas information every frame, as the later may change regardless of monitor changes. (#8415)
|
||||||
// 2024-11-05: [Docking] Added Linux workaround for spurious mouse up events emitted while dragging and creating new viewport. (#3158, #7733, #7922)
|
// 2024-11-05: [Docking] Added Linux workaround for spurious mouse up events emitted while dragging and creating new viewport. (#3158, #7733, #7922)
|
||||||
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
// 2024-08-22: Moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||||
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||||
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||||
// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn
|
// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn
|
||||||
|
|
@ -97,6 +107,8 @@
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// GLFW
|
// GLFW
|
||||||
|
|
@ -120,12 +132,12 @@
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <unistd.h> // for usleep()
|
#include <unistd.h> // for usleep()
|
||||||
|
// IMHEX PATCH BEGIN
|
||||||
|
#include <string_view> // for std::string_view
|
||||||
|
#include <cstdlib> // for std::getenv()
|
||||||
|
// IMHEX PATCH END
|
||||||
#endif
|
#endif
|
||||||
|
#include <stdio.h> // for snprintf()
|
||||||
#ifdef __linux__
|
|
||||||
#include <string_view>
|
|
||||||
#include <cstdlib>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
|
|
@ -172,6 +184,17 @@ static std::string clipboardContent;
|
||||||
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
|
#define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api
|
||||||
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
|
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
|
||||||
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
|
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
|
||||||
|
#define GLFW_HAS_GETPLATFORM (GLFW_VERSION_COMBINED >= 3400) // 3.4+ glfwGetPlatform()
|
||||||
|
|
||||||
|
// Map GLFWWindow* to ImGuiContext*.
|
||||||
|
// - Would be simpler if we could use glfwSetWindowUserPointer()/glfwGetWindowUserPointer(), but this is a single and shared resource.
|
||||||
|
// - Would be simpler if we could use e.g. std::map<> as well. But we don't.
|
||||||
|
// - This is not particularly optimized as we expect size to be small and queries to be rare.
|
||||||
|
struct ImGui_ImplGlfw_WindowToContext { GLFWwindow* Window; ImGuiContext* Context; };
|
||||||
|
static ImVector<ImGui_ImplGlfw_WindowToContext> g_ContextMap;
|
||||||
|
static void ImGui_ImplGlfw_ContextMap_Add(GLFWwindow* window, ImGuiContext* ctx) { g_ContextMap.push_back(ImGui_ImplGlfw_WindowToContext{ window, ctx }); }
|
||||||
|
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); return; } }
|
||||||
|
static ImGuiContext* ImGui_ImplGlfw_ContextMap_Get(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) return entry.Context; return nullptr; }
|
||||||
|
|
||||||
// GLFW data
|
// GLFW data
|
||||||
enum GlfwClientApi
|
enum GlfwClientApi
|
||||||
|
|
@ -183,6 +206,7 @@ enum GlfwClientApi
|
||||||
|
|
||||||
struct ImGui_ImplGlfw_Data
|
struct ImGui_ImplGlfw_Data
|
||||||
{
|
{
|
||||||
|
ImGuiContext* Context;
|
||||||
GLFWwindow* Window;
|
GLFWwindow* Window;
|
||||||
GlfwClientApi ClientApi;
|
GlfwClientApi ClientApi;
|
||||||
double Time;
|
double Time;
|
||||||
|
|
@ -194,7 +218,7 @@ struct ImGui_ImplGlfw_Data
|
||||||
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
||||||
bool InstalledCallbacks;
|
bool InstalledCallbacks;
|
||||||
bool CallbacksChainForAllWindows;
|
bool CallbacksChainForAllWindows;
|
||||||
bool WantUpdateMonitors;
|
char BackendPlatformName[32];
|
||||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
const char* CanvasSelector;
|
const char* CanvasSelector;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -222,10 +246,18 @@ struct ImGui_ImplGlfw_Data
|
||||||
// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.
|
// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.
|
||||||
// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.
|
// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.
|
||||||
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
||||||
|
namespace ImGui { extern ImGuiIO& GetIO(ImGuiContext*); }
|
||||||
static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
|
static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
|
||||||
{
|
{
|
||||||
|
// Get data for current context
|
||||||
return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||||
}
|
}
|
||||||
|
static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
// Get data for a given GLFW window, regardless of current context (since GLFW events are sent together)
|
||||||
|
ImGuiContext* ctx = ImGui_ImplGlfw_ContextMap_Get(window);
|
||||||
|
return (ImGui_ImplGlfw_Data*)ImGui::GetIO(ctx).BackendPlatformUserData;
|
||||||
|
}
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
static void ImGui_ImplGlfw_UpdateMonitors();
|
static void ImGui_ImplGlfw_UpdateMonitors();
|
||||||
|
|
@ -233,6 +265,7 @@ static void ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||||
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
|
||||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||||
{
|
{
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
|
|
@ -286,6 +319,8 @@ ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
|
||||||
case GLFW_KEY_EQUAL: return ImGuiKey_Equal;
|
case GLFW_KEY_EQUAL: return ImGuiKey_Equal;
|
||||||
case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket;
|
case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket;
|
||||||
case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash;
|
case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash;
|
||||||
|
case GLFW_KEY_WORLD_1: return ImGuiKey_Oem102;
|
||||||
|
case GLFW_KEY_WORLD_2: return ImGuiKey_Oem102;
|
||||||
case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket;
|
case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket;
|
||||||
case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent;
|
case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent;
|
||||||
case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock;
|
case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock;
|
||||||
|
|
@ -385,11 +420,9 @@ ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
|
||||||
|
|
||||||
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
|
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
|
||||||
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
|
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
|
||||||
static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window, int mods)
|
static void ImGui_ImplGlfw_UpdateKeyModifiers(ImGuiIO& io, GLFWwindow* window, int mods)
|
||||||
{
|
{
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static bool isX11 = [] {
|
static bool isX11 = [] {
|
||||||
const auto sessionType = std::getenv("XDG_SESSION_TYPE");
|
const auto sessionType = std::getenv("XDG_SESSION_TYPE");
|
||||||
|
|
@ -415,33 +448,31 @@ static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window, int mods)
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window)
|
static bool ImGui_ImplGlfw_ShouldChainCallback(ImGui_ImplGlfw_Data* bd, GLFWwindow* window)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
|
||||||
return bd->CallbacksChainForAllWindows ? true : (window == bd->Window);
|
return bd->CallbacksChainForAllWindows ? true : (window == bd->Window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
||||||
|
|
||||||
// Workaround for Linux: ignore mouse up events which are following an focus loss following a viewport creation
|
// Workaround for Linux: ignore mouse up events which are following an focus loss following a viewport creation
|
||||||
if (bd->MouseIgnoreButtonUp && action == GLFW_RELEASE)
|
if (bd->MouseIgnoreButtonUp && action == GLFW_RELEASE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(window, mods);
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
|
ImGui_ImplGlfw_UpdateKeyModifiers(io, window, mods);
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||||
io.AddMouseButtonEvent(button, action == GLFW_PRESS);
|
io.AddMouseButtonEvent(button, action == GLFW_PRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
|
|
@ -449,7 +480,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
|
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -489,21 +520,21 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||||
|
|
||||||
void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods)
|
void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackKey(window, keycode, scancode, action, mods);
|
bd->PrevUserCallbackKey(window, keycode, scancode, action, mods);
|
||||||
|
|
||||||
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(window, mods);
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
|
ImGui_ImplGlfw_UpdateKeyModifiers(io, window, mods);
|
||||||
|
|
||||||
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
||||||
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
||||||
|
|
||||||
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
|
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
|
||||||
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
|
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
|
||||||
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
||||||
|
|
@ -511,25 +542,25 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
||||||
|
|
||||||
void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
|
void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackWindowFocus(window, focused);
|
bd->PrevUserCallbackWindowFocus(window, focused);
|
||||||
|
|
||||||
// Workaround for Linux: when losing focus with MouseIgnoreButtonUpWaitForFocusLoss set, we will temporarily ignore subsequent Mouse Up events
|
// Workaround for Linux: when losing focus with MouseIgnoreButtonUpWaitForFocusLoss set, we will temporarily ignore subsequent Mouse Up events
|
||||||
bd->MouseIgnoreButtonUp = (bd->MouseIgnoreButtonUpWaitForFocusLoss && focused == 0);
|
bd->MouseIgnoreButtonUp = (bd->MouseIgnoreButtonUpWaitForFocusLoss && focused == 0);
|
||||||
bd->MouseIgnoreButtonUpWaitForFocusLoss = false;
|
bd->MouseIgnoreButtonUpWaitForFocusLoss = false;
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
io.AddFocusEvent(focused != 0);
|
io.AddFocusEvent(focused != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
|
void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackCursorPos(window, x, y);
|
bd->PrevUserCallbackCursorPos(window, x, y);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||||
{
|
{
|
||||||
int window_x, window_y;
|
int window_x, window_y;
|
||||||
|
|
@ -545,11 +576,11 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
|
||||||
// so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984)
|
// so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984)
|
||||||
void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
|
void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackCursorEnter(window, entered);
|
bd->PrevUserCallbackCursorEnter(window, entered);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
if (entered)
|
if (entered)
|
||||||
{
|
{
|
||||||
bd->MouseWindow = window;
|
bd->MouseWindow = window;
|
||||||
|
|
@ -565,32 +596,32 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
|
||||||
|
|
||||||
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
|
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
|
||||||
bd->PrevUserCallbackChar(window, c);
|
bd->PrevUserCallbackChar(window, c);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
io.AddInputCharacter(c);
|
io.AddInputCharacter(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
// This function is technically part of the API even if we stopped using the callback, so leaving it around.
|
||||||
bd->WantUpdateMonitors = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void* user_data)
|
||||||
{
|
{
|
||||||
// Mimic Emscripten_HandleWheel() in SDL.
|
// Mimic Emscripten_HandleWheel() in SDL.
|
||||||
// Corresponding equivalent in GLFW JS emulation layer has incorrect quantizing preventing small values. See #6096
|
// Corresponding equivalent in GLFW JS emulation layer has incorrect quantizing preventing small values. See #6096
|
||||||
|
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
||||||
float multiplier = 0.0f;
|
float multiplier = 0.0f;
|
||||||
if (ev->deltaMode == DOM_DELTA_PIXEL) { multiplier = 1.0f / 100.0f; } // 100 pixels make up a step.
|
if (ev->deltaMode == DOM_DELTA_PIXEL) { multiplier = 1.0f / 100.0f; } // 100 pixels make up a step.
|
||||||
else if (ev->deltaMode == DOM_DELTA_LINE) { multiplier = 1.0f / 3.0f; } // 3 lines make up a step.
|
else if (ev->deltaMode == DOM_DELTA_LINE) { multiplier = 1.0f / 3.0f; } // 3 lines make up a step.
|
||||||
else if (ev->deltaMode == DOM_DELTA_PAGE) { multiplier = 80.0f; } // A page makes up 80 steps.
|
else if (ev->deltaMode == DOM_DELTA_PAGE) { multiplier = 80.0f; } // A page makes up 80 steps.
|
||||||
float wheel_x = ev->deltaX * -multiplier;
|
float wheel_x = ev->deltaX * -multiplier;
|
||||||
float wheel_y = ev->deltaY * -multiplier;
|
float wheel_y = ev->deltaY * -multiplier;
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
io.AddMouseWheelEvent(wheel_x, wheel_y);
|
io.AddMouseWheelEvent(wheel_x, wheel_y);
|
||||||
//IMGUI_DEBUG_LOG("[Emsc] mode %d dx: %.2f, dy: %.2f, dz: %.2f --> feed %.2f %.2f\n", (int)ev->deltaMode, ev->deltaX, ev->deltaY, ev->deltaZ, wheel_x, wheel_y);
|
//IMGUI_DEBUG_LOG("[Emsc] mode %d dx: %.2f, dy: %.2f, dz: %.2f --> feed %.2f %.2f\n", (int)ev->deltaMode, ev->deltaX, ev->deltaY, ev->deltaZ, wheel_x, wheel_y);
|
||||||
return EM_TRUE;
|
return EM_TRUE;
|
||||||
|
|
@ -603,7 +634,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
|
||||||
|
|
||||||
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
|
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
IM_ASSERT(bd->InstalledCallbacks == false && "Callbacks already installed!");
|
IM_ASSERT(bd->InstalledCallbacks == false && "Callbacks already installed!");
|
||||||
IM_ASSERT(bd->Window == window);
|
IM_ASSERT(bd->Window == window);
|
||||||
|
|
||||||
|
|
@ -620,7 +651,7 @@ void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
|
||||||
|
|
||||||
void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)
|
void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||||
IM_ASSERT(bd->InstalledCallbacks == true && "Callbacks not installed!");
|
IM_ASSERT(bd->InstalledCallbacks == true && "Callbacks not installed!");
|
||||||
IM_ASSERT(bd->Window == window);
|
IM_ASSERT(bd->Window == window);
|
||||||
|
|
||||||
|
|
@ -670,24 +701,40 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
|
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
|
||||||
|
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
|
||||||
io.BackendPlatformUserData = (void*)bd;
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
io.BackendPlatformName = "imgui_impl_glfw";
|
io.BackendPlatformName = bd->BackendPlatformName;
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
|
||||||
|
bool has_viewports = false;
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
has_viewports = true;
|
||||||
|
#if GLFW_HAS_GETPLATFORM
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND)
|
||||||
|
has_viewports = false;
|
||||||
|
#endif
|
||||||
|
if (has_viewports)
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
|
||||||
#endif
|
#endif
|
||||||
#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED
|
#if GLFW_HAS_MOUSE_PASSTHROUGH || GLFW_HAS_WINDOW_HOVERED
|
||||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bd->Context = ImGui::GetCurrentContext();
|
||||||
bd->Window = window;
|
bd->Window = window;
|
||||||
bd->Time = 0.0;
|
bd->Time = 0.0;
|
||||||
bd->WantUpdateMonitors = true;
|
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
|
||||||
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(NULL, text); };
|
#if GLFW_VERSION_COMBINED < 3300
|
||||||
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(NULL); };
|
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window, text); };
|
||||||
|
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window); };
|
||||||
|
#else
|
||||||
|
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(nullptr, text); };
|
||||||
|
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(nullptr); };
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; };
|
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; };
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -749,11 +796,14 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||||
#else
|
#else
|
||||||
IM_UNUSED(main_viewport);
|
IM_UNUSED(main_viewport);
|
||||||
#endif
|
#endif
|
||||||
ImGui_ImplGlfw_InitMultiViewportSupport();
|
if (has_viewports)
|
||||||
|
ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||||
|
|
||||||
// Windows: register a WndProc hook so we can intercept some messages.
|
// Windows: register a WndProc hook so we can intercept some messages.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
bd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
|
HWND hwnd = (HWND)main_viewport->PlatformHandleRaw;
|
||||||
|
::SetPropA(hwnd, "IMGUI_BACKEND_DATA", bd);
|
||||||
|
bd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
|
||||||
IM_ASSERT(bd->PrevWndProc != nullptr);
|
IM_ASSERT(bd->PrevWndProc != nullptr);
|
||||||
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -764,7 +814,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||||
#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
|
#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
|
||||||
if (emscripten::glfw3::IsRuntimePlatformApple())
|
if (emscripten::glfw3::IsRuntimePlatformApple())
|
||||||
{
|
{
|
||||||
ImGui::GetIO().ConfigMacOSXBehaviors = true;
|
io.ConfigMacOSXBehaviors = true;
|
||||||
|
|
||||||
// Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used.
|
// Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used.
|
||||||
// This means that Meta + V only registers a single key-press, even if the keys are held.
|
// This means that Meta + V only registers a single key-press, even if the keys are held.
|
||||||
|
|
@ -815,6 +865,7 @@ void ImGui_ImplGlfw_Shutdown()
|
||||||
// Windows: restore our WndProc hook
|
// Windows: restore our WndProc hook
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
|
::SetPropA((HWND)main_viewport->PlatformHandleRaw, "IMGUI_BACKEND_DATA", nullptr);
|
||||||
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc);
|
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc);
|
||||||
bd->PrevWndProc = nullptr;
|
bd->PrevWndProc = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -822,6 +873,7 @@ void ImGui_ImplGlfw_Shutdown()
|
||||||
io.BackendPlatformName = nullptr;
|
io.BackendPlatformName = nullptr;
|
||||||
io.BackendPlatformUserData = nullptr;
|
io.BackendPlatformUserData = nullptr;
|
||||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport);
|
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport);
|
||||||
|
ImGui_ImplGlfw_ContextMap_Remove(bd->Window);
|
||||||
IM_DELETE(bd);
|
IM_DELETE(bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -933,7 +985,7 @@ static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0
|
||||||
static void ImGui_ImplGlfw_UpdateGamepads()
|
static void ImGui_ImplGlfw_UpdateGamepads()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
|
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs, but see #8075
|
||||||
return;
|
return;
|
||||||
|
|
||||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
|
|
@ -983,9 +1035,7 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_UpdateMonitors()
|
static void ImGui_ImplGlfw_UpdateMonitors()
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
bd->WantUpdateMonitors = false;
|
|
||||||
|
|
||||||
int monitors_count = 0;
|
int monitors_count = 0;
|
||||||
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
|
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
|
||||||
|
|
@ -1012,35 +1062,63 @@ static void ImGui_ImplGlfw_UpdateMonitors()
|
||||||
monitor.WorkSize = ImVec2((float)w, (float)h);
|
monitor.WorkSize = ImVec2((float)w, (float)h);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if GLFW_HAS_PER_MONITOR_DPI
|
float scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfw_monitors[n]);
|
||||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
if (scale == 0.0f)
|
||||||
float x_scale, y_scale;
|
|
||||||
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
|
||||||
if (x_scale == 0.0f)
|
|
||||||
continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0, see #7902.
|
continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0, see #7902.
|
||||||
monitor.DpiScale = x_scale;
|
monitor.DpiScale = scale;
|
||||||
#endif
|
|
||||||
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
||||||
platform_io.Monitors.push_back(monitor);
|
platform_io.Monitors.push_back(monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - On Windows the process needs to be marked DPI-aware!! SDL2 doesn't do it by default. You can call ::SetProcessDPIAware() or call ImGui_ImplWin32_EnableDpiAwareness() from Win32 backend.
|
||||||
|
// - Apple platforms use FramebufferScale so we always return 1.0f.
|
||||||
|
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
|
||||||
|
float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
#if GLFW_HAS_PER_MONITOR_DPI && !defined(__APPLE__)
|
||||||
|
float x_scale, y_scale;
|
||||||
|
glfwGetWindowContentScale(window, &x_scale, &y_scale);
|
||||||
|
return x_scale;
|
||||||
|
#else
|
||||||
|
IM_UNUSED(window);
|
||||||
|
return 1.0f;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
#if GLFW_HAS_PER_MONITOR_DPI && !defined(__APPLE__)
|
||||||
|
float x_scale, y_scale;
|
||||||
|
glfwGetMonitorContentScale(monitor, &x_scale, &y_scale);
|
||||||
|
return x_scale;
|
||||||
|
#else
|
||||||
|
IM_UNUSED(monitor);
|
||||||
|
return 1.0f;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window, ImVec2* out_size, ImVec2* out_framebuffer_scale)
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
int display_w, display_h;
|
||||||
|
glfwGetWindowSize(window, &w, &h);
|
||||||
|
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||||
|
if (out_size != nullptr)
|
||||||
|
*out_size = ImVec2((float)w, (float)h);
|
||||||
|
if (out_framebuffer_scale != nullptr)
|
||||||
|
*out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
void ImGui_ImplGlfw_NewFrame()
|
void ImGui_ImplGlfw_NewFrame()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?");
|
||||||
|
|
||||||
// Setup display size (every frame to accommodate for window resizing)
|
// Setup main viewport size (every frame to accommodate for window resizing)
|
||||||
int w, h;
|
ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale);
|
||||||
int display_w, display_h;
|
ImGui_ImplGlfw_UpdateMonitors();
|
||||||
glfwGetWindowSize(bd->Window, &w, &h);
|
|
||||||
glfwGetFramebufferSize(bd->Window, &display_w, &display_h);
|
|
||||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
|
||||||
if (w > 0 && h > 0)
|
|
||||||
io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h);
|
|
||||||
if (bd->WantUpdateMonitors)
|
|
||||||
ImGui_ImplGlfw_UpdateMonitors();
|
|
||||||
|
|
||||||
// Setup time step
|
// Setup time step
|
||||||
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
|
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
|
||||||
|
|
@ -1105,7 +1183,7 @@ void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow*, const char* canvas_s
|
||||||
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
||||||
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
||||||
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
||||||
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
emscripten_set_wheel_callback(bd->CanvasSelector, bd, false, ImGui_ImplEmscripten_WheelCallback);
|
||||||
}
|
}
|
||||||
#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3)
|
#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3)
|
||||||
// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call
|
// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call
|
||||||
|
|
@ -1127,10 +1205,10 @@ void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* c
|
||||||
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
|
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
|
||||||
//--------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Helper structure we store in the void* RendererUserData field of each ImGuiViewport to easily retrieve our backend data.
|
// Helper structure we store in the void* PlatformUserData field of each ImGuiViewport to easily retrieve our backend data.
|
||||||
struct ImGui_ImplGlfw_ViewportData
|
struct ImGui_ImplGlfw_ViewportData
|
||||||
{
|
{
|
||||||
GLFWwindow* Window;
|
GLFWwindow* Window; // Stored in ImGuiViewport::PlatformHandle
|
||||||
bool WindowOwned;
|
bool WindowOwned;
|
||||||
int IgnoreWindowPosEventFrame;
|
int IgnoreWindowPosEventFrame;
|
||||||
int IgnoreWindowSizeEventFrame;
|
int IgnoreWindowSizeEventFrame;
|
||||||
|
|
@ -1209,9 +1287,11 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
|
||||||
GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;
|
GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;
|
||||||
vd->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", nullptr, share_window);
|
vd->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", nullptr, share_window);
|
||||||
vd->WindowOwned = true;
|
vd->WindowOwned = true;
|
||||||
|
ImGui_ImplGlfw_ContextMap_Add(vd->Window, bd->Context);
|
||||||
viewport->PlatformHandle = (void*)vd->Window;
|
viewport->PlatformHandle = (void*)vd->Window;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);
|
viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);
|
||||||
|
::SetPropA((HWND)viewport->PlatformHandleRaw, "IMGUI_BACKEND_DATA", bd);
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
// REASON: The patch with #include <GLFW/glfw3native.h>
|
// REASON: The patch with #include <GLFW/glfw3native.h>
|
||||||
// #elif defined(__APPLE__)
|
// #elif defined(__APPLE__)
|
||||||
|
|
@ -1252,11 +1332,11 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
|
||||||
|
|
||||||
// Release any keys that were pressed in the window being destroyed and are still held down,
|
// Release any keys that were pressed in the window being destroyed and are still held down,
|
||||||
// because we will not receive any release events after window is destroyed.
|
// because we will not receive any release events after window is destroyed.
|
||||||
for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++) {
|
for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++)
|
||||||
if (bd->KeyOwnerWindows[i] == vd->Window)
|
if (bd->KeyOwnerWindows[i] == vd->Window)
|
||||||
ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.
|
ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.
|
||||||
}
|
|
||||||
|
|
||||||
|
ImGui_ImplGlfw_ContextMap_Remove(vd->Window);
|
||||||
glfwDestroyWindow(vd->Window);
|
glfwDestroyWindow(vd->Window);
|
||||||
}
|
}
|
||||||
vd->Window = nullptr;
|
vd->Window = nullptr;
|
||||||
|
|
@ -1280,12 +1360,10 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
|
||||||
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
|
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW hack: install hook for WM_NCHITTEST message handler
|
// GLFW hack: install WndProc for mouse source event and WM_NCHITTEST message handler.
|
||||||
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
|
|
||||||
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
|
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
|
||||||
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
|
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
|
||||||
::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !GLFW_HAS_FOCUS_ON_SHOW
|
#if !GLFW_HAS_FOCUS_ON_SHOW
|
||||||
// GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
|
// GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
|
||||||
|
|
@ -1329,7 +1407,7 @@ static ImVec2 ImGui_ImplGlfw_GetWindowSize(ImGuiViewport* viewport)
|
||||||
static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;
|
ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;
|
||||||
#if __APPLE__ && !GLFW_HAS_OSX_WINDOW_POS_FIX
|
#if defined(__APPLE__) && !GLFW_HAS_OSX_WINDOW_POS_FIX
|
||||||
// Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
|
// Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
|
||||||
// positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
|
// positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
|
||||||
// doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
|
// doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
|
||||||
|
|
@ -1343,6 +1421,14 @@ static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
||||||
glfwSetWindowSize(vd->Window, (int)size.x, (int)size.y);
|
glfwSetWindowSize(vd->Window, (int)size.x, (int)size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ImVec2 ImGui_ImplGlfw_GetWindowFramebufferScale(ImGuiViewport* viewport)
|
||||||
|
{
|
||||||
|
ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;
|
||||||
|
ImVec2 framebuffer_scale;
|
||||||
|
ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(vd->Window, nullptr, &framebuffer_scale);
|
||||||
|
return framebuffer_scale;
|
||||||
|
}
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* title)
|
static void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* title)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;
|
ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData;
|
||||||
|
|
@ -1441,6 +1527,7 @@ static void ImGui_ImplGlfw_InitMultiViewportSupport()
|
||||||
platform_io.Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos;
|
platform_io.Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos;
|
||||||
platform_io.Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize;
|
platform_io.Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize;
|
||||||
platform_io.Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize;
|
platform_io.Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize;
|
||||||
|
platform_io.Platform_GetWindowFramebufferScale = ImGui_ImplGlfw_GetWindowFramebufferScale;
|
||||||
platform_io.Platform_SetWindowFocus = ImGui_ImplGlfw_SetWindowFocus;
|
platform_io.Platform_SetWindowFocus = ImGui_ImplGlfw_SetWindowFocus;
|
||||||
platform_io.Platform_GetWindowFocus = ImGui_ImplGlfw_GetWindowFocus;
|
platform_io.Platform_GetWindowFocus = ImGui_ImplGlfw_GetWindowFocus;
|
||||||
platform_io.Platform_GetWindowMinimized = ImGui_ImplGlfw_GetWindowMinimized;
|
platform_io.Platform_GetWindowMinimized = ImGui_ImplGlfw_GetWindowMinimized;
|
||||||
|
|
@ -1484,7 +1571,9 @@ static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
|
||||||
}
|
}
|
||||||
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)::GetPropA(hWnd, "IMGUI_BACKEND_DATA");
|
||||||
|
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||||
|
|
||||||
WNDPROC prev_wndproc = bd->PrevWndProc;
|
WNDPROC prev_wndproc = bd->PrevWndProc;
|
||||||
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
|
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
|
||||||
if (viewport != NULL)
|
if (viewport != NULL)
|
||||||
|
|
@ -1500,7 +1589,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
|
||||||
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
|
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
|
||||||
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
|
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
|
||||||
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
|
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
|
||||||
ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
|
io.AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
|
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
|
||||||
|
|
@ -1517,6 +1606,7 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
return ::CallWindowProcW(prev_wndproc, hWnd, msg, wParam, lParam);
|
return ::CallWindowProcW(prev_wndproc, hWnd, msg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@
|
||||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
|
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||||
|
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
|
|
||||||
// About WebGL/ES:
|
// About WebGL/ES:
|
||||||
|
|
@ -23,7 +24,12 @@
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL3_CreateFontsTexture() and ImGui_ImplOpenGL3_DestroyFontsTexture().
|
||||||
|
// 2025-06-04: OpenGL: Made GLES 3.20 contexts not access GL_CONTEXT_PROFILE_MASK nor GL_PRIMITIVE_RESTART. (#8664)
|
||||||
|
// 2025-02-18: OpenGL: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406)
|
||||||
|
// 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||||
|
// 2024-06-28: OpenGL: ImGui_ImplOpenGL3_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL3_DestroyFontsTexture(). (#7748)
|
||||||
// 2024-05-07: OpenGL: Update loader for Linux to support EGL/GLVND. (#7562)
|
// 2024-05-07: OpenGL: Update loader for Linux to support EGL/GLVND. (#7562)
|
||||||
// 2024-04-16: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447)
|
// 2024-04-16: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447)
|
||||||
// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink.
|
// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink.
|
||||||
|
|
@ -53,7 +59,7 @@
|
||||||
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
|
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
|
||||||
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
|
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
|
||||||
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
|
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
|
||||||
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
|
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre-3.3 context which have the defines set by a loader.
|
||||||
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
|
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
|
||||||
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
|
// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
|
||||||
// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
|
// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
|
||||||
|
|
@ -113,10 +119,12 @@
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// IMHEX PATCH BEGIN
|
||||||
#if !defined(WINGDIAPI)
|
#if !defined(WINGDIAPI)
|
||||||
#define WINGDIAPI extern "C"
|
#define WINGDIAPI extern "C"
|
||||||
#define APIENTRY
|
#define APIENTRY
|
||||||
#endif
|
#endif
|
||||||
|
// IMHEX PATCH END
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#ifndef IMGUI_DISABLE
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
@ -130,6 +138,7 @@
|
||||||
// Clang/GCC warnings with -Weverything
|
// Clang/GCC warnings with -Weverything
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: ignore unknown flags
|
||||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||||
#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used
|
#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used
|
||||||
|
|
@ -141,6 +150,7 @@
|
||||||
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
||||||
#pragma GCC diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx'
|
#pragma GCC diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx'
|
||||||
#pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
|
#pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// GL includes
|
// GL includes
|
||||||
|
|
@ -168,9 +178,11 @@
|
||||||
// In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).
|
// In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).
|
||||||
// If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):
|
// If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):
|
||||||
// - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped
|
// - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped
|
||||||
|
// Typically you would run: python3 ./gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
|
||||||
// - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases
|
// - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases
|
||||||
// Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version.
|
// Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version.
|
||||||
#define IMGL3W_IMPL
|
#define IMGL3W_IMPL
|
||||||
|
#define IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||||
#include "imgui_impl_opengl3_loader.h"
|
#include "imgui_impl_opengl3_loader.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -230,7 +242,7 @@ struct ImGui_ImplOpenGL3_Data
|
||||||
bool GlProfileIsES3;
|
bool GlProfileIsES3;
|
||||||
bool GlProfileIsCompat;
|
bool GlProfileIsCompat;
|
||||||
GLint GlProfileMask;
|
GLint GlProfileMask;
|
||||||
GLuint FontTexture;
|
GLint MaxTextureSize;
|
||||||
GLuint ShaderHandle;
|
GLuint ShaderHandle;
|
||||||
GLint AttribLocationTex; // Uniforms location
|
GLint AttribLocationTex; // Uniforms location
|
||||||
GLint AttribLocationProjMtx;
|
GLint AttribLocationProjMtx;
|
||||||
|
|
@ -243,6 +255,7 @@ struct ImGui_ImplOpenGL3_Data
|
||||||
bool HasPolygonMode;
|
bool HasPolygonMode;
|
||||||
bool HasClipOrigin;
|
bool HasClipOrigin;
|
||||||
bool UseBufferSubData;
|
bool UseBufferSubData;
|
||||||
|
ImVector<char> TempBuffer;
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
|
|
@ -255,8 +268,8 @@ static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
static void ImGui_ImplOpenGL3_InitPlatformInterface();
|
static void ImGui_ImplOpenGL3_InitMultiViewportSupport();
|
||||||
static void ImGui_ImplOpenGL3_ShutdownPlatformInterface();
|
static void ImGui_ImplOpenGL3_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
// OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only)
|
// OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only)
|
||||||
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||||
|
|
@ -282,20 +295,31 @@ struct ImGui_ImplOpenGL3_VtxAttribState
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Functions
|
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
bool ImGui_ImplOpenGL3_InitLoader();
|
||||||
|
bool ImGui_ImplOpenGL3_InitLoader()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
|
||||||
|
|
||||||
// Initialize our loader
|
// Initialize our loader
|
||||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
|
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||||
if (imgl3wInit() != 0)
|
if (glGetIntegerv == nullptr && imgl3wInit() != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to initialize OpenGL loader!\n");
|
fprintf(stderr, "Failed to initialize OpenGL loader!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||||
|
|
||||||
|
// Initialize loader
|
||||||
|
if (!ImGui_ImplOpenGL3_InitLoader())
|
||||||
|
return false;
|
||||||
|
|
||||||
// Setup backend capabilities flags
|
// Setup backend capabilities flags
|
||||||
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
|
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
|
||||||
|
|
@ -303,13 +327,14 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
io.BackendRendererName = "imgui_impl_opengl3";
|
io.BackendRendererName = "imgui_impl_opengl3";
|
||||||
|
|
||||||
// Query for GL version (e.g. 320 for GL 3.2)
|
// Query for GL version (e.g. 320 for GL 3.2)
|
||||||
|
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
|
||||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||||
// GLES 2
|
// GLES 2
|
||||||
bd->GlVersion = 200;
|
bd->GlVersion = 200;
|
||||||
bd->GlProfileIsES2 = true;
|
bd->GlProfileIsES2 = true;
|
||||||
|
IM_UNUSED(gl_version_str);
|
||||||
#else
|
#else
|
||||||
// Desktop or GLES 3
|
// Desktop or GLES 3
|
||||||
const char* gl_version_str = (const char*)glGetString(GL_VERSION);
|
|
||||||
GLint major = 0;
|
GLint major = 0;
|
||||||
GLint minor = 0;
|
GLint minor = 0;
|
||||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||||
|
|
@ -317,11 +342,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
if (major == 0 && minor == 0)
|
if (major == 0 && minor == 0)
|
||||||
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||||
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
|
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
|
||||||
#if defined(GL_CONTEXT_PROFILE_MASK)
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &bd->MaxTextureSize);
|
||||||
if (bd->GlVersion >= 320)
|
|
||||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
|
|
||||||
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(IMGUI_IMPL_OPENGL_ES3)
|
#if defined(IMGUI_IMPL_OPENGL_ES3)
|
||||||
bd->GlProfileIsES3 = true;
|
bd->GlProfileIsES3 = true;
|
||||||
|
|
@ -330,6 +351,12 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
bd->GlProfileIsES3 = true;
|
bd->GlProfileIsES3 = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GL_CONTEXT_PROFILE_MASK)
|
||||||
|
if (!bd->GlProfileIsES3 && bd->GlVersion >= 320)
|
||||||
|
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
|
||||||
|
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
bd->UseBufferSubData = false;
|
bd->UseBufferSubData = false;
|
||||||
/*
|
/*
|
||||||
// Query vendor to enable glBufferSubData kludge
|
// Query vendor to enable glBufferSubData kludge
|
||||||
|
|
@ -342,14 +369,18 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_DEBUG
|
#ifdef IMGUI_IMPL_OPENGL_DEBUG
|
||||||
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
|
printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2/IsEs3 = %d/%d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||||
if (bd->GlVersion >= 320)
|
if (bd->GlVersion >= 320)
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
#endif
|
#endif
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
|
||||||
|
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = (int)bd->MaxTextureSize;
|
||||||
|
|
||||||
// Store GLSL version string so we can refer to it later in case we recreate shaders.
|
// Store GLSL version string so we can refer to it later in case we recreate shaders.
|
||||||
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
|
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
|
||||||
|
|
@ -390,8 +421,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
ImGui_ImplOpenGL3_InitMultiViewportSupport();
|
||||||
ImGui_ImplOpenGL3_InitPlatformInterface();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -402,11 +432,11 @@ void ImGui_ImplOpenGL3_Shutdown()
|
||||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_ShutdownPlatformInterface();
|
ImGui_ImplOpenGL3_ShutdownMultiViewportSupport();
|
||||||
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||||
io.BackendRendererName = nullptr;
|
io.BackendRendererName = nullptr;
|
||||||
io.BackendRendererUserData = nullptr;
|
io.BackendRendererUserData = nullptr;
|
||||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasViewports);
|
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports);
|
||||||
IM_DELETE(bd);
|
IM_DELETE(bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,8 +445,11 @@ void ImGui_ImplOpenGL3_NewFrame()
|
||||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
|
||||||
|
|
||||||
if (!bd->ShaderHandle)
|
if (!bd->ShaderHandle)
|
||||||
ImGui_ImplOpenGL3_CreateDeviceObjects();
|
if (!ImGui_ImplOpenGL3_CreateDeviceObjects())
|
||||||
|
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
|
|
@ -454,7 +487,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
||||||
if (bd->GlVersion >= 310)
|
if (!bd->GlProfileIsES3 && bd->GlVersion >= 310)
|
||||||
glDisable(GL_PRIMITIVE_RESTART);
|
glDisable(GL_PRIMITIVE_RESTART);
|
||||||
#endif
|
#endif
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||||
|
|
@ -535,8 +568,17 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
if (fb_width <= 0 || fb_height <= 0)
|
if (fb_width <= 0 || fb_height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||||
|
|
||||||
|
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||||
|
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||||
|
if (draw_data->Textures != nullptr)
|
||||||
|
for (ImTextureData* tex : *draw_data->Textures)
|
||||||
|
if (tex->Status != ImTextureStatus_OK)
|
||||||
|
ImGui_ImplOpenGL3_UpdateTexture(tex);
|
||||||
|
|
||||||
// Backup GL state
|
// Backup GL state
|
||||||
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
@ -573,7 +615,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
|
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
|
||||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
||||||
GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
|
GLboolean last_enable_primitive_restart = (!bd->GlProfileIsES3 && bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Setup desired GL state
|
// Setup desired GL state
|
||||||
|
|
@ -592,7 +634,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
// Render command lists
|
// Render command lists
|
||||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
{
|
{
|
||||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
const ImDrawList* draw_list = draw_data->CmdLists[n];
|
||||||
|
|
||||||
// Upload vertex/index buffers
|
// Upload vertex/index buffers
|
||||||
// - OpenGL drivers are in a very sorry state nowadays....
|
// - OpenGL drivers are in a very sorry state nowadays....
|
||||||
|
|
@ -602,8 +644,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
// - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code.
|
// - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code.
|
||||||
// We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path.
|
// We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path.
|
||||||
// - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues.
|
// - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues.
|
||||||
const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
|
const GLsizeiptr vtx_buffer_size = (GLsizeiptr)draw_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
|
||||||
const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
|
const GLsizeiptr idx_buffer_size = (GLsizeiptr)draw_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
|
||||||
if (bd->UseBufferSubData)
|
if (bd->UseBufferSubData)
|
||||||
{
|
{
|
||||||
if (bd->VertexBufferSize < vtx_buffer_size)
|
if (bd->VertexBufferSize < vtx_buffer_size)
|
||||||
|
|
@ -616,18 +658,18 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
bd->IndexBufferSize = idx_buffer_size;
|
bd->IndexBufferSize = idx_buffer_size;
|
||||||
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW));
|
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW));
|
||||||
}
|
}
|
||||||
GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data));
|
GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)draw_list->VtxBuffer.Data));
|
||||||
GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data));
|
GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)draw_list->IdxBuffer.Data));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW));
|
GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)draw_list->VtxBuffer.Data, GL_STREAM_DRAW));
|
||||||
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW));
|
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)draw_list->IdxBuffer.Data, GL_STREAM_DRAW));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||||
{
|
{
|
||||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||||
if (pcmd->UserCallback != nullptr)
|
if (pcmd->UserCallback != nullptr)
|
||||||
{
|
{
|
||||||
// User callback, registered via ImDrawList::AddCallback()
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
|
|
@ -635,7 +677,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||||
else
|
else
|
||||||
pcmd->UserCallback(cmd_list, pcmd);
|
pcmd->UserCallback(draw_list, pcmd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -692,7 +734,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
|
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
|
||||||
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
||||||
if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
|
if (!bd->GlProfileIsES3 && bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||||
|
|
@ -705,48 +747,82 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||||
(void)bd; // Not all compilation paths use this
|
(void)bd; // Not all compilation paths use this
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
static void ImGui_ImplOpenGL3_DestroyTexture(ImTextureData* tex)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
|
||||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
glDeleteTextures(1, &gl_tex_id);
|
||||||
|
|
||||||
// Build texture atlas
|
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||||
unsigned char* pixels;
|
tex->SetTexID(ImTextureID_Invalid);
|
||||||
int width, height;
|
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
|
||||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
|
||||||
GLint last_texture;
|
|
||||||
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
|
||||||
GL_CALL(glGenTextures(1, &bd->FontTexture));
|
|
||||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, bd->FontTexture));
|
|
||||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
|
||||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
|
||||||
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
|
||||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
|
||||||
#endif
|
|
||||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
|
||||||
|
|
||||||
// Store our identifier
|
|
||||||
io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
|
|
||||||
|
|
||||||
// Restore state
|
|
||||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplOpenGL3_DestroyFontsTexture()
|
void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
if (tex->Status == ImTextureStatus_WantCreate)
|
||||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
|
||||||
if (bd->FontTexture)
|
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &bd->FontTexture);
|
// Create and upload new texture to graphics system
|
||||||
io.Fonts->SetTexID(0);
|
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||||
bd->FontTexture = 0;
|
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
||||||
|
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||||
|
const void* pixels = tex->GetPixels();
|
||||||
|
GLuint gl_texture_id = 0;
|
||||||
|
|
||||||
|
// Upload texture to graphics system
|
||||||
|
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||||
|
GLint last_texture;
|
||||||
|
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||||
|
GL_CALL(glGenTextures(1, &gl_texture_id));
|
||||||
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_texture_id));
|
||||||
|
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
|
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
|
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||||
|
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||||
|
#endif
|
||||||
|
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||||
|
|
||||||
|
// Store identifiers
|
||||||
|
tex->SetTexID((ImTextureID)(intptr_t)gl_texture_id);
|
||||||
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
|
|
||||||
|
// Restore state
|
||||||
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
|
||||||
}
|
}
|
||||||
|
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||||
|
{
|
||||||
|
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||||
|
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||||
|
GLint last_texture;
|
||||||
|
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||||
|
|
||||||
|
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
|
||||||
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_tex_id));
|
||||||
|
#if 0// GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||||
|
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
|
||||||
|
for (ImTextureRect& r : tex->Updates)
|
||||||
|
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
|
||||||
|
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||||
|
#else
|
||||||
|
// GL ES doesn't have GL_UNPACK_ROW_LENGTH, so we need to (A) copy to a contiguous buffer or (B) upload line by line.
|
||||||
|
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||||
|
for (ImTextureRect& r : tex->Updates)
|
||||||
|
{
|
||||||
|
const int src_pitch = r.w * tex->BytesPerPixel;
|
||||||
|
bd->TempBuffer.resize(r.h * src_pitch);
|
||||||
|
char* out_p = bd->TempBuffer.Data;
|
||||||
|
for (int y = 0; y < r.h; y++, out_p += src_pitch)
|
||||||
|
memcpy(out_p, tex->GetPixelsAt(r.x, r.y + y), src_pitch);
|
||||||
|
IM_ASSERT(out_p == bd->TempBuffer.end());
|
||||||
|
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, bd->TempBuffer.Data));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
|
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); // Restore state
|
||||||
|
}
|
||||||
|
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||||
|
ImGui_ImplOpenGL3_DestroyTexture(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
|
// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
|
||||||
|
|
@ -796,7 +872,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
|
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
|
||||||
GLint last_pixel_unpack_buffer;
|
GLint last_pixel_unpack_buffer = 0;
|
||||||
if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); }
|
if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); }
|
||||||
#endif
|
#endif
|
||||||
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||||
|
|
@ -931,7 +1007,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||||
" Out_Color = Frag_Color;\n"
|
" Out_Color = Frag_Color;\n"
|
||||||
" SRC1_Color = vec4(texture(Texture, Frag_UV.st).rgb * Frag_Color.aaa,1.0);\n"
|
" SRC1_Color = vec4(texture(Texture, Frag_UV.st).rgb * Frag_Color.aaa,1.0);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// Select shaders matching our GLSL versions
|
// Select shaders matching our GLSL versions
|
||||||
|
|
@ -960,23 +1036,28 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||||
|
|
||||||
// Create shaders
|
// Create shaders
|
||||||
const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
|
const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
|
||||||
GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
|
GLuint vert_handle;
|
||||||
|
GL_CALL(vert_handle = glCreateShader(GL_VERTEX_SHADER));
|
||||||
glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
|
glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
|
||||||
glCompileShader(vert_handle);
|
glCompileShader(vert_handle);
|
||||||
CheckShader(vert_handle, "vertex shader");
|
if (!CheckShader(vert_handle, "vertex shader"))
|
||||||
|
return false;
|
||||||
|
|
||||||
const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
|
const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
|
||||||
GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
|
GLuint frag_handle;
|
||||||
|
GL_CALL(frag_handle = glCreateShader(GL_FRAGMENT_SHADER));
|
||||||
glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
|
glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
|
||||||
glCompileShader(frag_handle);
|
glCompileShader(frag_handle);
|
||||||
CheckShader(frag_handle, "fragment shader");
|
if (!CheckShader(frag_handle, "fragment shader"))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Link
|
// Link
|
||||||
bd->ShaderHandle = glCreateProgram();
|
bd->ShaderHandle = glCreateProgram();
|
||||||
glAttachShader(bd->ShaderHandle, vert_handle);
|
glAttachShader(bd->ShaderHandle, vert_handle);
|
||||||
glAttachShader(bd->ShaderHandle, frag_handle);
|
glAttachShader(bd->ShaderHandle, frag_handle);
|
||||||
glLinkProgram(bd->ShaderHandle);
|
glLinkProgram(bd->ShaderHandle);
|
||||||
CheckProgram(bd->ShaderHandle, "shader program");
|
if (!CheckProgram(bd->ShaderHandle, "shader program"))
|
||||||
|
return false;
|
||||||
|
|
||||||
glDetachShader(bd->ShaderHandle, vert_handle);
|
glDetachShader(bd->ShaderHandle, vert_handle);
|
||||||
glDetachShader(bd->ShaderHandle, frag_handle);
|
glDetachShader(bd->ShaderHandle, frag_handle);
|
||||||
|
|
@ -993,8 +1074,6 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||||
glGenBuffers(1, &bd->VboHandle);
|
glGenBuffers(1, &bd->VboHandle);
|
||||||
glGenBuffers(1, &bd->ElementsHandle);
|
glGenBuffers(1, &bd->ElementsHandle);
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
|
||||||
|
|
||||||
// Restore modified GL state
|
// Restore modified GL state
|
||||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||||
|
|
@ -1014,7 +1093,11 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||||
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
|
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
|
||||||
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
|
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
|
||||||
if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
|
if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
|
||||||
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
|
||||||
|
// Destroy all textures
|
||||||
|
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||||
|
if (tex->RefCount == 1)
|
||||||
|
ImGui_ImplOpenGL3_DestroyTexture(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
@ -1034,13 +1117,13 @@ static void ImGui_ImplOpenGL3_RenderWindow(ImGuiViewport* viewport, void*)
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(viewport->DrawData);
|
ImGui_ImplOpenGL3_RenderDrawData(viewport->DrawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplOpenGL3_InitPlatformInterface()
|
static void ImGui_ImplOpenGL3_InitMultiViewportSupport()
|
||||||
{
|
{
|
||||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL3_RenderWindow;
|
platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL3_RenderWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplOpenGL3_ShutdownPlatformInterface()
|
static void ImGui_ImplOpenGL3_ShutdownMultiViewportSupport()
|
||||||
{
|
{
|
||||||
ImGui::DestroyPlatformWindows();
|
ImGui::DestroyPlatformWindows();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.91.9b
|
// dear imgui, v1.92.1
|
||||||
// (internal structures/api)
|
// (internal structures/api)
|
||||||
|
|
||||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||||
|
|
@ -37,6 +37,7 @@ Index of this file:
|
||||||
// [SECTION] Tab bar, Tab item support
|
// [SECTION] Tab bar, Tab item support
|
||||||
// [SECTION] Table support
|
// [SECTION] Table support
|
||||||
// [SECTION] ImGui internal API
|
// [SECTION] ImGui internal API
|
||||||
|
// [SECTION] ImFontLoader
|
||||||
// [SECTION] ImFontAtlas internal API
|
// [SECTION] ImFontAtlas internal API
|
||||||
// [SECTION] Test Engine specific hooks (imgui_test_engine)
|
// [SECTION] Test Engine specific hooks (imgui_test_engine)
|
||||||
|
|
||||||
|
|
@ -132,7 +133,7 @@ Index of this file:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
// (other types which are not forwarded declared are: ImBitArray<>, ImSpan<>, ImSpanAllocator<>, ImPool<>, ImChunkStream<>)
|
// (other types which are not forwarded declared are: ImBitArray<>, ImSpan<>, ImSpanAllocator<>, ImStableVector<>, ImPool<>, ImChunkStream<>)
|
||||||
struct ImBitVector; // Store 1-bit per value
|
struct ImBitVector; // Store 1-bit per value
|
||||||
struct ImRect; // An axis-aligned rectangle (2 points)
|
struct ImRect; // An axis-aligned rectangle (2 points)
|
||||||
struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
||||||
|
|
@ -140,6 +141,9 @@ struct ImGuiTextIndex; // Maintain a line index for a text buffer.
|
||||||
// ImDrawList/ImFontAtlas
|
// ImDrawList/ImFontAtlas
|
||||||
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
|
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
|
||||||
struct ImDrawListSharedData; // Data shared between all ImDrawList instances
|
struct ImDrawListSharedData; // Data shared between all ImDrawList instances
|
||||||
|
struct ImFontAtlasBuilder; // Internal storage for incrementally packing and building a ImFontAtlas
|
||||||
|
struct ImFontAtlasPostProcessData; // Data available to potential texture post-processing functions
|
||||||
|
struct ImFontAtlasRectEntry; // Packed rectangle lookup entry
|
||||||
|
|
||||||
// ImGui
|
// ImGui
|
||||||
struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others)
|
struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others)
|
||||||
|
|
@ -213,6 +217,10 @@ typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // F
|
||||||
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
|
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
|
||||||
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
|
typedef int ImGuiWindowRefreshFlags; // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
|
||||||
|
|
||||||
|
// Table column indexing
|
||||||
|
typedef ImS16 ImGuiTableColumnIdx;
|
||||||
|
typedef ImU16 ImGuiTableDrawChannelIdx;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Context pointer
|
// [SECTION] Context pointer
|
||||||
// See implementation of this variable in imgui.cpp for comments and details.
|
// See implementation of this variable in imgui.cpp for comments and details.
|
||||||
|
|
@ -248,7 +256,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||||
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_FONT(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
|
||||||
#define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_DOCKING(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventDocking) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_DOCKING(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventDocking) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
#define IMGUI_DEBUG_LOG_VIEWPORT(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventViewport) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
#define IMGUI_DEBUG_LOG_VIEWPORT(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventViewport) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||||
|
|
@ -360,6 +368,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||||
// - Helper: ImBitArray
|
// - Helper: ImBitArray
|
||||||
// - Helper: ImBitVector
|
// - Helper: ImBitVector
|
||||||
// - Helper: ImSpan<>, ImSpanAllocator<>
|
// - Helper: ImSpan<>, ImSpanAllocator<>
|
||||||
|
// - Helper: ImStableVector<>
|
||||||
// - Helper: ImPool<>
|
// - Helper: ImPool<>
|
||||||
// - Helper: ImChunkStream<>
|
// - Helper: ImChunkStream<>
|
||||||
// - Helper: ImGuiTextIndex
|
// - Helper: ImGuiTextIndex
|
||||||
|
|
@ -391,6 +400,7 @@ IMGUI_API int ImStricmp(const char* str1, const char* str2);
|
||||||
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); // Case insensitive compare to a certain count.
|
IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); // Case insensitive compare to a certain count.
|
||||||
IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't).
|
IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't).
|
||||||
IMGUI_API char* ImStrdup(const char* str); // Duplicate a string.
|
IMGUI_API char* ImStrdup(const char* str); // Duplicate a string.
|
||||||
|
IMGUI_API void* ImMemdup(const void* src, size_t size); // Duplicate a chunk of memory.
|
||||||
IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); // Copy in provided buffer, recreate buffer if needed.
|
IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); // Copy in provided buffer, recreate buffer if needed.
|
||||||
IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); // Find first occurrence of 'c' in string range.
|
IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); // Find first occurrence of 'c' in string range.
|
||||||
IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line
|
IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line
|
||||||
|
|
@ -505,6 +515,8 @@ static inline float ImTrunc(float f)
|
||||||
static inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
|
static inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
|
||||||
static inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
|
static inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
|
||||||
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
||||||
|
static inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
|
||||||
|
static inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); }
|
||||||
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||||
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||||
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||||
|
|
@ -537,6 +549,14 @@ struct ImVec1
|
||||||
constexpr ImVec1(float _x) : x(_x) { }
|
constexpr ImVec1(float _x) : x(_x) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper: ImVec2i (2D vector, integer)
|
||||||
|
struct ImVec2i
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
constexpr ImVec2i() : x(0), y(0) {}
|
||||||
|
constexpr ImVec2i(int _x, int _y) : x(_x), y(_y) {}
|
||||||
|
};
|
||||||
|
|
||||||
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
|
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
|
||||||
struct ImVec2ih
|
struct ImVec2ih
|
||||||
{
|
{
|
||||||
|
|
@ -688,6 +708,39 @@ struct ImSpanAllocator
|
||||||
inline void GetSpan(int n, ImSpan<T>* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); }
|
inline void GetSpan(int n, ImSpan<T>* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper: ImStableVector<>
|
||||||
|
// Allocating chunks of BLOCK_SIZE items. Objects pointers are never invalidated when growing, only by clear().
|
||||||
|
// Important: does not destruct anything!
|
||||||
|
// Implemented only the minimum set of functions we need for it.
|
||||||
|
template<typename T, int BLOCK_SIZE>
|
||||||
|
struct ImStableVector
|
||||||
|
{
|
||||||
|
int Size = 0;
|
||||||
|
int Capacity = 0;
|
||||||
|
ImVector<T*> Blocks;
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
inline ~ImStableVector() { for (T* block : Blocks) IM_FREE(block); }
|
||||||
|
|
||||||
|
inline void clear() { Size = Capacity = 0; Blocks.clear_delete(); }
|
||||||
|
inline void resize(int new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
||||||
|
inline void reserve(int new_cap)
|
||||||
|
{
|
||||||
|
new_cap = IM_MEMALIGN(new_cap, BLOCK_SIZE);
|
||||||
|
int old_count = Capacity / BLOCK_SIZE;
|
||||||
|
int new_count = new_cap / BLOCK_SIZE;
|
||||||
|
if (new_count <= old_count)
|
||||||
|
return;
|
||||||
|
Blocks.resize(new_count);
|
||||||
|
for (int n = old_count; n < new_count; n++)
|
||||||
|
Blocks[n] = (T*)IM_ALLOC(sizeof(T) * BLOCK_SIZE);
|
||||||
|
Capacity = new_cap;
|
||||||
|
}
|
||||||
|
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; }
|
||||||
|
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; }
|
||||||
|
inline T* push_back(const T& v) { int i = Size; IM_ASSERT(i >= 0); if (Size == Capacity) reserve(Capacity + BLOCK_SIZE); void* ptr = &Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; memcpy(ptr, &v, sizeof(v)); Size++; return (T*)ptr; }
|
||||||
|
};
|
||||||
|
|
||||||
// Helper: ImPool<>
|
// Helper: ImPool<>
|
||||||
// Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer,
|
// Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer,
|
||||||
// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
|
// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
|
||||||
|
|
@ -796,17 +849,20 @@ IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStorag
|
||||||
// You may want to create your own instance of you try to ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
|
// You may want to create your own instance of you try to ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
|
||||||
struct IMGUI_API ImDrawListSharedData
|
struct IMGUI_API ImDrawListSharedData
|
||||||
{
|
{
|
||||||
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
|
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas (== FontAtlas->TexUvWhitePixel)
|
||||||
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas
|
const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas (== FontAtlas->TexUvLines)
|
||||||
ImFont* Font; // Current/default font (optional, for simplified AddText overload)
|
ImFontAtlas* FontAtlas; // Current font atlas
|
||||||
float FontSize; // Current/default font size (optional, for simplified AddText overload)
|
ImFont* Font; // Current font (used for simplified AddText overload)
|
||||||
float FontScale; // Current/default font scale (== FontSize / Font->FontSize)
|
float FontSize; // Current font size (used for for simplified AddText overload)
|
||||||
|
float FontScale; // Current font scale (== FontSize / Font->FontSize)
|
||||||
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
|
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
|
||||||
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
|
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
|
||||||
float InitialFringeScale; // Initial scale to apply to AA fringe
|
float InitialFringeScale; // Initial scale to apply to AA fringe
|
||||||
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
|
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
|
||||||
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
|
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
|
||||||
ImVector<ImVec2> TempBuffer; // Temporary write buffer
|
ImVector<ImVec2> TempBuffer; // Temporary write buffer
|
||||||
|
ImVector<ImDrawList*> DrawLists; // All draw lists associated to this ImDrawListSharedData
|
||||||
|
ImGuiContext* Context; // [OPTIONAL] Link to Dear ImGui context. 99% of ImDrawList/ImFontAtlas can function without an ImGui context, but this facilitate handling one legacy edge case.
|
||||||
|
|
||||||
// Lookup tables
|
// Lookup tables
|
||||||
ImVec2 ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
|
ImVec2 ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
|
||||||
|
|
@ -817,6 +873,7 @@ struct IMGUI_API ImDrawListSharedData
|
||||||
const ImVec4* ShadowRectUvs; // UV coordinates for shadow texture (10 entries)
|
const ImVec4* ShadowRectUvs; // UV coordinates for shadow texture (10 entries)
|
||||||
|
|
||||||
ImDrawListSharedData();
|
ImDrawListSharedData();
|
||||||
|
~ImDrawListSharedData();
|
||||||
void SetCircleTessellationMaxError(float max_error);
|
void SetCircleTessellationMaxError(float max_error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -828,6 +885,13 @@ struct ImDrawDataBuilder
|
||||||
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
|
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImFontStackData
|
||||||
|
{
|
||||||
|
ImFont* Font;
|
||||||
|
float FontSizeBeforeScaling; // ~~ style.FontSizeBase
|
||||||
|
float FontSizeAfterScaling; // ~~ g.FontSize
|
||||||
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Style support
|
// [SECTION] Style support
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -899,6 +963,7 @@ enum ImGuiItemFlagsPrivate_
|
||||||
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
|
ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
|
||||||
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
|
ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
|
||||||
ImGuiItemFlags_NoMarkEdited = 1 << 16, // false // Skip calling MarkItemEdited()
|
ImGuiItemFlags_NoMarkEdited = 1 << 16, // false // Skip calling MarkItemEdited()
|
||||||
|
ImGuiItemFlags_NoFocus = 1 << 17, // false // [EXPERIMENTAL: Not very well specced] Clicking doesn't take focus. Automatically sets ImGuiButtonFlags_NoFocus + ImGuiButtonFlags_NoNavFocus in ButtonBehavior().
|
||||||
|
|
||||||
// Controlled by widget code
|
// Controlled by widget code
|
||||||
ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
|
ImGuiItemFlags_Inputable = 1 << 20, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
|
||||||
|
|
@ -927,6 +992,7 @@ enum ImGuiItemStatusFlags_
|
||||||
ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
|
ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
|
||||||
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
|
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
|
||||||
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
|
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
|
||||||
|
//ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb.
|
||||||
|
|
||||||
// Additional status + semantic for ImGuiTestEngine
|
// Additional status + semantic for ImGuiTestEngine
|
||||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||||
|
|
@ -976,8 +1042,10 @@ enum ImGuiButtonFlagsPrivate_
|
||||||
ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
|
ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
|
||||||
ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
|
ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
|
||||||
ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
|
ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
|
||||||
|
ImGuiButtonFlags_NoFocus = 1 << 22, // [EXPERIMENTAL: Not very well specced]. Don't focus parent window when clicking.
|
||||||
ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold,
|
ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold,
|
||||||
ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease,
|
ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease,
|
||||||
|
//ImGuiButtonFlags_NoKeyModifiers = ImGuiButtonFlags_NoKeyModsAllowed, // Renamed in 1.91.4
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extend ImGuiComboFlags_
|
// Extend ImGuiComboFlags_
|
||||||
|
|
@ -1010,9 +1078,11 @@ enum ImGuiSelectableFlagsPrivate_
|
||||||
// Extend ImGuiTreeNodeFlags_
|
// Extend ImGuiTreeNodeFlags_
|
||||||
enum ImGuiTreeNodeFlagsPrivate_
|
enum ImGuiTreeNodeFlagsPrivate_
|
||||||
{
|
{
|
||||||
|
ImGuiTreeNodeFlags_NoNavFocus = 1 << 27,// Don't claim nav focus when interacting with this item (#8551)
|
||||||
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
|
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader()
|
||||||
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517)
|
ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517)
|
||||||
ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
|
ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
|
||||||
|
ImGuiTreeNodeFlags_DrawLinesMask_ = ImGuiTreeNodeFlags_DrawLinesNone | ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ImGuiSeparatorFlags_
|
enum ImGuiSeparatorFlags_
|
||||||
|
|
@ -1307,15 +1377,18 @@ struct ImGuiLastItemData
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store data emitted by TreeNode() for usage by TreePop()
|
// Store data emitted by TreeNode() for usage by TreePop()
|
||||||
// - To implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere: store the minimum amount of data
|
// - To implement ImGuiTreeNodeFlags_NavLeftJumpsToParent: store the minimum amount of data
|
||||||
// which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult().
|
// which we can't infer in TreePop(), to perform the equivalent of NavApplyItemToResult().
|
||||||
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
|
// Only stored when the node is a potential candidate for landing on a Left arrow jump.
|
||||||
struct ImGuiTreeNodeStackData
|
struct ImGuiTreeNodeStackData
|
||||||
{
|
{
|
||||||
ImGuiID ID;
|
ImGuiID ID;
|
||||||
ImGuiTreeNodeFlags TreeFlags;
|
ImGuiTreeNodeFlags TreeFlags;
|
||||||
ImGuiItemFlags ItemFlags; // Used for nav landing
|
ImGuiItemFlags ItemFlags; // Used for nav landing
|
||||||
ImRect NavRect; // Used for nav landing
|
ImRect NavRect; // Used for nav landing
|
||||||
|
float DrawLinesX1;
|
||||||
|
float DrawLinesToNodesY2;
|
||||||
|
ImGuiTableColumnIdx DrawLinesTableColumn;
|
||||||
};
|
};
|
||||||
|
|
||||||
// sizeof() = 20
|
// sizeof() = 20
|
||||||
|
|
@ -1634,6 +1707,7 @@ enum ImGuiNavRenderCursorFlags_
|
||||||
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
|
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
|
||||||
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
|
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
|
||||||
ImGuiNavHighlightFlags_NoRounding = ImGuiNavRenderCursorFlags_NoRounding, // Renamed in 1.91.4
|
ImGuiNavHighlightFlags_NoRounding = ImGuiNavRenderCursorFlags_NoRounding, // Renamed in 1.91.4
|
||||||
|
//ImGuiNavHighlightFlags_TypeThin = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.90.2
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2204,11 +2278,13 @@ struct ImGuiMetricsConfig
|
||||||
bool ShowDrawCmdMesh = true;
|
bool ShowDrawCmdMesh = true;
|
||||||
bool ShowDrawCmdBoundingBoxes = true;
|
bool ShowDrawCmdBoundingBoxes = true;
|
||||||
bool ShowTextEncodingViewer = false;
|
bool ShowTextEncodingViewer = false;
|
||||||
|
bool ShowTextureUsedRect = false;
|
||||||
bool ShowDockingNodes = false;
|
bool ShowDockingNodes = false;
|
||||||
int ShowWindowsRectsType = -1;
|
int ShowWindowsRectsType = -1;
|
||||||
int ShowTablesRectsType = -1;
|
int ShowTablesRectsType = -1;
|
||||||
int HighlightMonitorIdx = -1;
|
int HighlightMonitorIdx = -1;
|
||||||
ImGuiID HighlightViewportID = 0;
|
ImGuiID HighlightViewportID = 0;
|
||||||
|
bool ShowFontPreview = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImGuiStackLevelInfo
|
struct ImGuiStackLevelInfo
|
||||||
|
|
@ -2261,16 +2337,18 @@ struct ImGuiContextHook
|
||||||
struct ImGuiContext
|
struct ImGuiContext
|
||||||
{
|
{
|
||||||
bool Initialized;
|
bool Initialized;
|
||||||
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
|
|
||||||
ImGuiIO IO;
|
ImGuiIO IO;
|
||||||
ImGuiPlatformIO PlatformIO;
|
ImGuiPlatformIO PlatformIO;
|
||||||
ImGuiStyle Style;
|
ImGuiStyle Style;
|
||||||
ImGuiConfigFlags ConfigFlagsCurrFrame; // = g.IO.ConfigFlags at the time of NewFrame()
|
ImGuiConfigFlags ConfigFlagsCurrFrame; // = g.IO.ConfigFlags at the time of NewFrame()
|
||||||
ImGuiConfigFlags ConfigFlagsLastFrame;
|
ImGuiConfigFlags ConfigFlagsLastFrame;
|
||||||
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
|
ImVector<ImFontAtlas*> FontAtlases; // List of font atlases used by the context (generally only contains g.IO.Fonts aka the main font atlas)
|
||||||
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
|
ImFont* Font; // Currently bound font. (== FontStack.back().Font)
|
||||||
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
|
ImFontBaked* FontBaked; // Currently bound font at currently bound size. (== Font->GetFontBaked(FontSize))
|
||||||
float FontScale; // == FontSize / Font->FontSize
|
float FontSize; // Currently bound font size == line height (== FontSizeBase + externals scales applied in the UpdateCurrentFontSize() function).
|
||||||
|
float FontSizeBase; // Font size before scaling == style.FontSizeBase == value passed to PushFont() when specified.
|
||||||
|
float FontBakedScale; // == FontBaked->Size / FontSize. Scale factor over baked size. Rarely used nowadays, very often == 1.0f.
|
||||||
|
float FontRasterizerDensity; // Current font density. Used by all calls to GetFontBaked().
|
||||||
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
|
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
|
||||||
ImDrawListSharedData DrawListSharedData;
|
ImDrawListSharedData DrawListSharedData;
|
||||||
double Time;
|
double Time;
|
||||||
|
|
@ -2315,7 +2393,7 @@ struct ImGuiContext
|
||||||
ImVec2 WheelingAxisAvg;
|
ImVec2 WheelingAxisAvg;
|
||||||
|
|
||||||
// Item/widgets state and tracking information
|
// Item/widgets state and tracking information
|
||||||
ImGuiID DebugDrawIdConflicts; // Set when we detect multiple items with the same identifier
|
ImGuiID DebugDrawIdConflictsId; // Set when we detect multiple items with the same identifier
|
||||||
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
|
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
|
||||||
ImGuiID HoveredId; // Hovered widget, filled during the frame
|
ImGuiID HoveredId; // Hovered widget, filled during the frame
|
||||||
ImGuiID HoveredIdPreviousFrame;
|
ImGuiID HoveredIdPreviousFrame;
|
||||||
|
|
@ -2373,7 +2451,7 @@ struct ImGuiContext
|
||||||
ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
|
ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line)
|
||||||
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
|
ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
|
||||||
ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
|
ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
|
||||||
ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
|
ImVector<ImFontStackData> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
|
||||||
ImVector<ImGuiFocusScopeData> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin()
|
ImVector<ImGuiFocusScopeData> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin()
|
||||||
ImVector<ImGuiItemFlags> ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
|
ImVector<ImGuiItemFlags> ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
|
||||||
ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
|
ImVector<ImGuiGroupData> GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
|
||||||
|
|
@ -2404,18 +2482,19 @@ struct ImGuiContext
|
||||||
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
|
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
|
||||||
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
|
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
|
||||||
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
|
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
|
||||||
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
|
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID()
|
||||||
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
|
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
|
||||||
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
|
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
|
||||||
ImGuiActivateFlags NavActivateFlags;
|
ImGuiActivateFlags NavActivateFlags;
|
||||||
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
|
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
|
||||||
ImGuiID NavHighlightActivatedId;
|
ImGuiID NavHighlightActivatedId;
|
||||||
float NavHighlightActivatedTimer;
|
float NavHighlightActivatedTimer;
|
||||||
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
|
||||||
ImGuiActivateFlags NavNextActivateFlags;
|
ImGuiActivateFlags NavNextActivateFlags;
|
||||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
|
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
|
||||||
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
|
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
|
||||||
ImS8 NavCursorHideFrames;
|
ImS8 NavCursorHideFrames;
|
||||||
|
//ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606.
|
||||||
|
|
||||||
// Navigation: Init & Move Requests
|
// Navigation: Init & Move Requests
|
||||||
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
|
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
|
||||||
|
|
@ -2450,6 +2529,7 @@ struct ImGuiContext
|
||||||
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
|
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
|
||||||
|
|
||||||
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
||||||
|
bool ConfigNavWindowingWithGamepad; // = true. Enable CTRL+TAB by holding ImGuiKey_GamepadFaceLeft (== ImGuiKey_NavGamepadMenu). When false, the button may still be used to toggle Menu layer.
|
||||||
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
|
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
|
||||||
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
|
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
|
||||||
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
||||||
|
|
@ -2457,6 +2537,7 @@ struct ImGuiContext
|
||||||
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
|
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
|
||||||
float NavWindowingTimer;
|
float NavWindowingTimer;
|
||||||
float NavWindowingHighlightAlpha;
|
float NavWindowingHighlightAlpha;
|
||||||
|
ImGuiInputSource NavWindowingInputSource;
|
||||||
bool NavWindowingToggleLayer;
|
bool NavWindowingToggleLayer;
|
||||||
ImGuiKey NavWindowingToggleKey;
|
ImGuiKey NavWindowingToggleKey;
|
||||||
ImVec2 NavWindowingAccumDeltaPos;
|
ImVec2 NavWindowingAccumDeltaPos;
|
||||||
|
|
@ -2527,7 +2608,8 @@ struct ImGuiContext
|
||||||
// Widget state
|
// Widget state
|
||||||
ImGuiInputTextState InputTextState;
|
ImGuiInputTextState InputTextState;
|
||||||
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
|
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
|
||||||
ImFont InputTextPasswordFont;
|
ImFontBaked InputTextPasswordFontBackupBaked;
|
||||||
|
ImFontFlags InputTextPasswordFontBackupFlags;
|
||||||
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
|
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
|
||||||
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
||||||
int BeginMenuDepth;
|
int BeginMenuDepth;
|
||||||
|
|
@ -2559,12 +2641,12 @@ struct ImGuiContext
|
||||||
ImGuiTypingSelectState TypingSelectState; // State for GetTypingSelectRequest()
|
ImGuiTypingSelectState TypingSelectState; // State for GetTypingSelectRequest()
|
||||||
|
|
||||||
// Platform support
|
// Platform support
|
||||||
ImGuiPlatformImeData PlatformImeData; // Data updated by current frame
|
ImGuiPlatformImeData PlatformImeData; // Data updated by current frame. Will be applied at end of the frame. For some backends, this is required to have WantVisible=true in order to receive text message.
|
||||||
ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the platform_io.Platform_SetImeDataFn() handler.
|
ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the platform_io.Platform_SetImeDataFn() handler.
|
||||||
ImGuiID PlatformImeViewport;
|
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
// FIXME: We could provide an API to register one slot in an array held in ImGuiContext?
|
// FIXME: We could provide an API to register one slot in an array held in ImGuiContext?
|
||||||
|
ImVector<ImTextureData*> UserTextures; // List of textures created/managed by user or third-party extension. Automatically appended into platform_io.Textures[].
|
||||||
ImGuiDockContext DockContext;
|
ImGuiDockContext DockContext;
|
||||||
void (*DockNodeWindowMenuHandler)(ImGuiContext* ctx, ImGuiDockNode* node, ImGuiTabBar* tab_bar);
|
void (*DockNodeWindowMenuHandler)(ImGuiContext* ctx, ImGuiDockNode* node, ImGuiTabBar* tab_bar);
|
||||||
|
|
||||||
|
|
@ -2626,6 +2708,10 @@ struct ImGuiContext
|
||||||
ImGuiIDStackTool DebugIDStackTool;
|
ImGuiIDStackTool DebugIDStackTool;
|
||||||
ImGuiDebugAllocInfo DebugAllocInfo;
|
ImGuiDebugAllocInfo DebugAllocInfo;
|
||||||
ImGuiDockNode* DebugHoveredDockNode; // Hovered dock node.
|
ImGuiDockNode* DebugHoveredDockNode; // Hovered dock node.
|
||||||
|
#if defined(IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||||
|
ImGuiStorage DebugDrawIdConflictsAliveCount;
|
||||||
|
ImGuiStorage DebugDrawIdConflictsHighlightSet;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
float FramerateSecPerFrame[60]; // Calculate estimate of framerate for user over the last 60 frames..
|
float FramerateSecPerFrame[60]; // Calculate estimate of framerate for user over the last 60 frames..
|
||||||
|
|
@ -2634,7 +2720,7 @@ struct ImGuiContext
|
||||||
float FramerateSecPerFrameAccum;
|
float FramerateSecPerFrameAccum;
|
||||||
int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1.
|
int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1.
|
||||||
int WantCaptureKeyboardNextFrame; // "
|
int WantCaptureKeyboardNextFrame; // "
|
||||||
int WantTextInputNextFrame;
|
int WantTextInputNextFrame; // Copied in EndFrame() from g.PlatformImeData.WantTextInput. Needs to be set for some backends (SDL3) to emit character inputs.
|
||||||
ImVector<char> TempBuffer; // Temporary text buffer
|
ImVector<char> TempBuffer; // Temporary text buffer
|
||||||
char TempKeychordName[64];
|
char TempKeychordName[64];
|
||||||
|
|
||||||
|
|
@ -2680,7 +2766,8 @@ struct IMGUI_API ImGuiWindowTempData
|
||||||
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
|
ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
|
||||||
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
|
ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
|
||||||
int TreeDepth; // Current tree depth.
|
int TreeDepth; // Current tree depth.
|
||||||
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
|
ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary.
|
||||||
|
ImU32 TreeRecordsClippedNodesY2Mask; // Store whether we should keep recording Y2. Cleared when passing clip max. Equivalent TreeHasStackDataDepthMask value should always be set.
|
||||||
ImVector<ImGuiWindow*> ChildWindows;
|
ImVector<ImGuiWindow*> ChildWindows;
|
||||||
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
|
ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
|
||||||
ImGuiOldColumns* CurrentColumns; // Current columns set
|
ImGuiOldColumns* CurrentColumns; // Current columns set
|
||||||
|
|
@ -2800,7 +2887,6 @@ struct IMGUI_API ImGuiWindow
|
||||||
ImVector<ImGuiOldColumns> ColumnsStorage;
|
ImVector<ImGuiOldColumns> ColumnsStorage;
|
||||||
float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale()
|
float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale()
|
||||||
float FontWindowScaleParents;
|
float FontWindowScaleParents;
|
||||||
float FontDpiScale;
|
|
||||||
float FontRefSize; // This is a copy of window->CalcFontSize() at the time of Begin(), trying to phase out CalcFontSize() especially as it may be called on non-current window.
|
float FontRefSize; // This is a copy of window->CalcFontSize() at the time of Begin(), trying to phase out CalcFontSize() especially as it may be called on non-current window.
|
||||||
int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back)
|
int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back)
|
||||||
|
|
||||||
|
|
@ -2848,9 +2934,11 @@ public:
|
||||||
|
|
||||||
// We don't use g.FontSize because the window may be != g.CurrentWindow.
|
// We don't use g.FontSize because the window may be != g.CurrentWindow.
|
||||||
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
||||||
float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontBaseSize * FontWindowScale * FontDpiScale * FontWindowScaleParents; }
|
|
||||||
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); }
|
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); }
|
||||||
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); }
|
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); }
|
||||||
|
|
||||||
|
// [Obsolete] ImGuiWindow::CalcFontSize() was removed in 1.92.x because error-prone/misleading. You can use window->FontRefSize for a copy of g.FontSize at the time of the last Begin() call for this window.
|
||||||
|
//float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontSizeBase * FontWindowScale * FontDpiScale * FontWindowScaleParents;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -2941,11 +3029,7 @@ struct IMGUI_API ImGuiTabBar
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
|
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
|
||||||
#define IMGUI_TABLE_MAX_COLUMNS 512 // May be further lifted
|
#define IMGUI_TABLE_MAX_COLUMNS 512 // Arbitrary "safety" maximum, may be lifted in the future if needed. Must fit in ImGuiTableColumnIdx/ImGuiTableDrawChannelIdx.
|
||||||
|
|
||||||
// Our current column maximum is 64 but we may raise that in the future.
|
|
||||||
typedef ImS16 ImGuiTableColumnIdx;
|
|
||||||
typedef ImU16 ImGuiTableDrawChannelIdx;
|
|
||||||
|
|
||||||
// [Internal] sizeof() ~ 112
|
// [Internal] sizeof() ~ 112
|
||||||
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
|
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
|
||||||
|
|
@ -3144,7 +3228,7 @@ struct IMGUI_API ImGuiTable
|
||||||
bool IsSortSpecsDirty;
|
bool IsSortSpecsDirty;
|
||||||
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
|
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
|
||||||
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
|
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
|
||||||
bool DisableDefaultContextMenu; // Disable default context menu contents. You may submit your own using TableBeginContextMenuPopup()/EndPopup()
|
bool DisableDefaultContextMenu; // Disable default context menu. You may submit your own using TableBeginContextMenuPopup()/EndPopup()
|
||||||
bool IsSettingsRequestLoad;
|
bool IsSettingsRequestLoad;
|
||||||
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data.
|
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data.
|
||||||
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
|
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
|
||||||
|
|
@ -3278,9 +3362,18 @@ namespace ImGui
|
||||||
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
||||||
|
|
||||||
// Fonts, drawing
|
// Fonts, drawing
|
||||||
IMGUI_API void SetCurrentFont(ImFont* font);
|
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture
|
||||||
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
|
IMGUI_API void UnregisterUserTexture(ImTextureData* tex);
|
||||||
|
IMGUI_API void RegisterFontAtlas(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void SetCurrentFont(ImFont* font, float font_size_before_scaling, float font_size_after_scaling);
|
||||||
|
IMGUI_API void UpdateCurrentFontSize(float restore_font_size_after_scaling);
|
||||||
|
IMGUI_API void SetFontRasterizerDensity(float rasterizer_density);
|
||||||
|
inline float GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }
|
||||||
|
inline float GetRoundedFontSize(float size) { return IM_ROUND(size); }
|
||||||
|
IMGUI_API ImFont* GetDefaultFont();
|
||||||
IMGUI_API void PushPasswordFont();
|
IMGUI_API void PushPasswordFont();
|
||||||
|
IMGUI_API void PopPasswordFont();
|
||||||
inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { return GetForegroundDrawList(window->Viewport); }
|
inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { return GetForegroundDrawList(window->Viewport); }
|
||||||
IMGUI_API void AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
|
IMGUI_API void AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
|
||||||
|
|
||||||
|
|
@ -3290,7 +3383,7 @@ namespace ImGui
|
||||||
|
|
||||||
// NewFrame
|
// NewFrame
|
||||||
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
|
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
|
||||||
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
|
IMGUI_API void UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos);
|
||||||
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
|
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
|
||||||
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
||||||
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock);
|
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock);
|
||||||
|
|
@ -3422,7 +3515,7 @@ namespace ImGui
|
||||||
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||||
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
|
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
|
||||||
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiTreeNodeStackData* tree_node_data);
|
IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, const ImGuiTreeNodeStackData* tree_node_data);
|
||||||
IMGUI_API void NavMoveRequestCancel();
|
IMGUI_API void NavMoveRequestCancel();
|
||||||
IMGUI_API void NavMoveRequestApplyResult();
|
IMGUI_API void NavMoveRequestApplyResult();
|
||||||
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
|
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
|
||||||
|
|
@ -3438,7 +3531,7 @@ namespace ImGui
|
||||||
// This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are
|
// This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are
|
||||||
// much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones.
|
// much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones.
|
||||||
IMGUI_API void FocusItem(); // Focus last item (no selection/activation).
|
IMGUI_API void FocusItem(); // Focus last item (no selection/activation).
|
||||||
IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again.
|
IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again. Was called 'ActivateItem()' before 1.89.7.
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
|
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
|
||||||
|
|
@ -3640,6 +3733,8 @@ namespace ImGui
|
||||||
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
|
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
|
||||||
IMGUI_API void TablePushBackgroundChannel();
|
IMGUI_API void TablePushBackgroundChannel();
|
||||||
IMGUI_API void TablePopBackgroundChannel();
|
IMGUI_API void TablePopBackgroundChannel();
|
||||||
|
IMGUI_API void TablePushColumnChannel(int column_n);
|
||||||
|
IMGUI_API void TablePopColumnChannel();
|
||||||
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
|
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
|
||||||
|
|
||||||
// Tables: Internals
|
// Tables: Internals
|
||||||
|
|
@ -3718,7 +3813,7 @@ namespace ImGui
|
||||||
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
||||||
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
||||||
IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
||||||
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
|
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
|
||||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
|
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
|
||||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
||||||
|
|
@ -3739,11 +3834,15 @@ namespace ImGui
|
||||||
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding);
|
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding);
|
||||||
IMGUI_API ImDrawFlags CalcRoundingFlagsForRectInRect(const ImRect& r_in, const ImRect& r_outer, float threshold);
|
IMGUI_API ImDrawFlags CalcRoundingFlagsForRectInRect(const ImRect& r_in, const ImRect& r_outer, float threshold);
|
||||||
|
|
||||||
// Widgets
|
// Widgets: Text
|
||||||
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
|
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
|
||||||
|
IMGUI_API void TextAligned(float align_x, float size_x, const char* fmt, ...); // FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024)
|
||||||
|
IMGUI_API void TextAlignedV(float align_x, float size_x, const char* fmt, va_list args);
|
||||||
|
|
||||||
|
// Widgets
|
||||||
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||||
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
|
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
|
||||||
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
|
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
|
||||||
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
|
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
|
||||||
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
|
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
|
||||||
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
|
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
|
||||||
|
|
@ -3767,6 +3866,8 @@ namespace ImGui
|
||||||
|
|
||||||
// Widgets: Tree Nodes
|
// Widgets: Tree Nodes
|
||||||
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
|
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
|
||||||
|
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
|
||||||
|
IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data);
|
||||||
IMGUI_API void TreePushOverrideID(ImGuiID id);
|
IMGUI_API void TreePushOverrideID(ImGuiID id);
|
||||||
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
|
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
|
||||||
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
|
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
|
||||||
|
|
@ -3848,7 +3949,9 @@ namespace ImGui
|
||||||
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
|
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
|
||||||
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
|
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
|
||||||
IMGUI_API void DebugNodeFont(ImFont* font);
|
IMGUI_API void DebugNodeFont(ImFont* font);
|
||||||
|
IMGUI_API void DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
|
||||||
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
|
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
|
||||||
|
IMGUI_API void DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRect* highlight_rect = NULL); // ID used to facilitate persisting the "current" texture.
|
||||||
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
||||||
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
|
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
|
||||||
IMGUI_API void DebugNodeTable(ImGuiTable* table);
|
IMGUI_API void DebugNodeTable(ImGuiTable* table);
|
||||||
|
|
@ -3871,6 +3974,7 @@ namespace ImGui
|
||||||
//inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
|
//inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89
|
||||||
//inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
|
//inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
|
||||||
|
|
||||||
|
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
|
||||||
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
|
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():
|
||||||
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
|
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
|
||||||
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0'
|
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0'
|
||||||
|
|
@ -3882,31 +3986,192 @@ namespace ImGui
|
||||||
} // namespace ImGui
|
} // namespace ImGui
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] ImFontLoader
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Hooks and storage for a given font backend.
|
||||||
|
// This structure is likely to evolve as we add support for incremental atlas updates.
|
||||||
|
// Conceptually this could be public, but API is still going to be evolve.
|
||||||
|
struct ImFontLoader
|
||||||
|
{
|
||||||
|
const char* Name;
|
||||||
|
bool (*LoaderInit)(ImFontAtlas* atlas);
|
||||||
|
void (*LoaderShutdown)(ImFontAtlas* atlas);
|
||||||
|
bool (*FontSrcInit)(ImFontAtlas* atlas, ImFontConfig* src);
|
||||||
|
void (*FontSrcDestroy)(ImFontAtlas* atlas, ImFontConfig* src);
|
||||||
|
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint);
|
||||||
|
bool (*FontBakedInit)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
|
||||||
|
void (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
|
||||||
|
bool (*FontBakedLoadGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x);
|
||||||
|
|
||||||
|
// Size of backend data, Per Baked * Per Source. Buffers are managed by core to avoid excessive allocations.
|
||||||
|
// FIXME: At this point the two other types of buffers may be managed by core to be consistent?
|
||||||
|
size_t FontBakedSrcLoaderDataSize;
|
||||||
|
|
||||||
|
ImFontLoader() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef IMGUI_ENABLE_STB_TRUETYPE
|
||||||
|
IMGUI_API const ImFontLoader* ImFontAtlasGetFontLoaderForStbTruetype();
|
||||||
|
#endif
|
||||||
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
typedef ImFontLoader ImFontBuilderIO; // [renamed/changed in 1.92] The types are not actually compatible but we provide this as a compile-time error report helper.
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] ImFontAtlas internal API
|
// [SECTION] ImFontAtlas internal API
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// This structure is likely to evolve as we add support for incremental atlas updates.
|
#define IMGUI_FONT_SIZE_MAX (512.0f)
|
||||||
// Conceptually this could be in ImGuiPlatformIO, but we are far from ready to make this public.
|
#define IMGUI_FONT_SIZE_THRESHOLD_FOR_LOADADVANCEXONLYMODE (128.0f)
|
||||||
struct ImFontBuilderIO
|
|
||||||
|
// Helpers: ImTextureRef ==/!= operators provided as convenience
|
||||||
|
// (note that _TexID and _TexData are never set simultaneously)
|
||||||
|
inline bool operator==(const ImTextureRef& lhs, const ImTextureRef& rhs) { return lhs._TexID == rhs._TexID && lhs._TexData == rhs._TexData; }
|
||||||
|
inline bool operator!=(const ImTextureRef& lhs, const ImTextureRef& rhs) { return lhs._TexID != rhs._TexID || lhs._TexData != rhs._TexData; }
|
||||||
|
|
||||||
|
// Refer to ImFontAtlasPackGetRect() to better understand how this works.
|
||||||
|
#define ImFontAtlasRectId_IndexMask_ (0x000FFFFF) // 20-bits: index to access builder->RectsIndex[].
|
||||||
|
#define ImFontAtlasRectId_GenerationMask_ (0x3FF00000) // 10-bits: entry generation, so each ID is unique and get can safely detected old identifiers.
|
||||||
|
#define ImFontAtlasRectId_GenerationShift_ (20)
|
||||||
|
inline int ImFontAtlasRectId_GetIndex(ImFontAtlasRectId id) { return id & ImFontAtlasRectId_IndexMask_; }
|
||||||
|
inline int ImFontAtlasRectId_GetGeneration(ImFontAtlasRectId id) { return (id & ImFontAtlasRectId_GenerationMask_) >> ImFontAtlasRectId_GenerationShift_; }
|
||||||
|
inline ImFontAtlasRectId ImFontAtlasRectId_Make(int index_idx, int gen_idx) { IM_ASSERT(index_idx < ImFontAtlasRectId_IndexMask_ && gen_idx < (ImFontAtlasRectId_GenerationMask_ >> ImFontAtlasRectId_GenerationShift_)); return (ImFontAtlasRectId)(index_idx | (gen_idx << ImFontAtlasRectId_GenerationShift_)); }
|
||||||
|
|
||||||
|
// Packed rectangle lookup entry (we need an indirection to allow removing/reordering rectangles)
|
||||||
|
// User are returned ImFontAtlasRectId values which are meant to be persistent.
|
||||||
|
// We handle this with an indirection. While Rects[] may be in theory shuffled, compacted etc., RectsIndex[] cannot it is keyed by ImFontAtlasRectId.
|
||||||
|
// RectsIndex[] is used both as an index into Rects[] and an index into itself. This is basically a free-list. See ImFontAtlasBuildAllocRectIndexEntry() code.
|
||||||
|
// Having this also makes it easier to e.g. sort rectangles during repack.
|
||||||
|
struct ImFontAtlasRectEntry
|
||||||
{
|
{
|
||||||
bool (*FontBuilder_Build)(ImFontAtlas* atlas);
|
int TargetIndex : 20; // When Used: ImFontAtlasRectId -> into Rects[]. When unused: index to next unused RectsIndex[] slot to consume free-list.
|
||||||
|
int Generation : 10; // Increased each time the entry is reused for a new rectangle.
|
||||||
|
unsigned int IsUsed : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper for font builder
|
// Data available to potential texture post-processing functions
|
||||||
#ifdef IMGUI_ENABLE_STB_TRUETYPE
|
struct ImFontAtlasPostProcessData
|
||||||
IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype();
|
{
|
||||||
|
ImFontAtlas* FontAtlas;
|
||||||
|
ImFont* Font;
|
||||||
|
ImFontConfig* FontSrc;
|
||||||
|
ImFontBaked* FontBaked;
|
||||||
|
ImFontGlyph* Glyph;
|
||||||
|
|
||||||
|
// Pixel data
|
||||||
|
void* Pixels;
|
||||||
|
ImTextureFormat Format;
|
||||||
|
int Pitch;
|
||||||
|
int Width;
|
||||||
|
int Height;
|
||||||
|
};
|
||||||
|
|
||||||
|
// We avoid dragging imstb_rectpack.h into public header (partly because binding generators are having issues with it)
|
||||||
|
#ifdef IMGUI_STB_NAMESPACE
|
||||||
|
namespace IMGUI_STB_NAMESPACE { struct stbrp_node; }
|
||||||
|
typedef IMGUI_STB_NAMESPACE::stbrp_node stbrp_node_im;
|
||||||
|
#else
|
||||||
|
struct stbrp_node;
|
||||||
|
typedef stbrp_node stbrp_node_im;
|
||||||
|
#endif
|
||||||
|
struct stbrp_context_opaque { char data[80]; };
|
||||||
|
|
||||||
|
// Internal storage for incrementally packing and building a ImFontAtlas
|
||||||
|
struct ImFontAtlasBuilder
|
||||||
|
{
|
||||||
|
stbrp_context_opaque PackContext; // Actually 'stbrp_context' but we don't want to define this in the header file.
|
||||||
|
ImVector<stbrp_node_im> PackNodes;
|
||||||
|
ImVector<ImTextureRect> Rects;
|
||||||
|
ImVector<ImFontAtlasRectEntry> RectsIndex; // ImFontAtlasRectId -> index into Rects[]
|
||||||
|
ImVector<unsigned char> TempBuffer; // Misc scratch buffer
|
||||||
|
int RectsIndexFreeListStart;// First unused entry
|
||||||
|
int RectsPackedCount; // Number of packed rectangles.
|
||||||
|
int RectsPackedSurface; // Number of packed pixels. Used when compacting to heuristically find the ideal texture size.
|
||||||
|
int RectsDiscardedCount;
|
||||||
|
int RectsDiscardedSurface;
|
||||||
|
int FrameCount; // Current frame count
|
||||||
|
ImVec2i MaxRectSize; // Largest rectangle to pack (de-facto used as a "minimum texture size")
|
||||||
|
ImVec2i MaxRectBounds; // Bottom-right most used pixels
|
||||||
|
bool LockDisableResize; // Disable resizing texture
|
||||||
|
bool PreloadedAllGlyphsRanges; // Set when missing ImGuiBackendFlags_RendererHasTextures features forces atlas to preload everything.
|
||||||
|
|
||||||
|
// Cache of all ImFontBaked
|
||||||
|
ImStableVector<ImFontBaked,32> BakedPool;
|
||||||
|
ImGuiStorage BakedMap; // BakedId --> ImFontBaked*
|
||||||
|
int BakedDiscardedCount;
|
||||||
|
|
||||||
|
// Custom rectangle identifiers
|
||||||
|
ImFontAtlasRectId PackIdMouseCursors; // White pixel + mouse cursors. Also happen to be fallback in case of packing failure.
|
||||||
|
ImFontAtlasRectId PackIdLinesTexData;
|
||||||
|
|
||||||
|
ImFontAtlasBuilder() { memset(this, 0, sizeof(*this)); FrameCount = -1; RectsIndexFreeListStart = -1; PackIdMouseCursors = PackIdLinesTexData = -1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildDestroy(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildMain(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildSetupFontLoader(ImFontAtlas* atlas, const ImFontLoader* font_loader);
|
||||||
|
IMGUI_API void ImFontAtlasBuildUpdatePointers(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasBuildRenderBitmapFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char);
|
||||||
|
IMGUI_API void ImFontAtlasBuildClear(ImFontAtlas* atlas); // Clear output and custom rects
|
||||||
|
|
||||||
|
IMGUI_API ImTextureData* ImFontAtlasTextureAdd(ImFontAtlas* atlas, int w, int h);
|
||||||
|
IMGUI_API void ImFontAtlasTextureMakeSpace(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API void ImFontAtlasTextureRepack(ImFontAtlas* atlas, int w, int h);
|
||||||
|
IMGUI_API void ImFontAtlasTextureGrow(ImFontAtlas* atlas, int old_w = -1, int old_h = -1);
|
||||||
|
IMGUI_API void ImFontAtlasTextureCompact(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API ImVec2i ImFontAtlasTextureGetSizeEstimate(ImFontAtlas* atlas);
|
||||||
|
|
||||||
|
IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src);
|
||||||
|
IMGUI_API void ImFontAtlasBuildLegacyPreloadAllGlyphRanges(ImFontAtlas* atlas); // Legacy
|
||||||
|
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, ImFontBaked* baked, int* out_oversample_h, int* out_oversample_v);
|
||||||
|
IMGUI_API void ImFontAtlasBuildDiscardBakes(ImFontAtlas* atlas, int unused_frames);
|
||||||
|
|
||||||
|
IMGUI_API bool ImFontAtlasFontSourceInit(ImFontAtlas* atlas, ImFontConfig* src);
|
||||||
|
IMGUI_API void ImFontAtlasFontSourceAddToFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src);
|
||||||
|
IMGUI_API void ImFontAtlasFontDestroySourceData(ImFontAtlas* atlas, ImFontConfig* src);
|
||||||
|
IMGUI_API bool ImFontAtlasFontInitOutput(ImFontAtlas* atlas, ImFont* font); // Using FontDestroyOutput/FontInitOutput sequence useful notably if font loader params have changed
|
||||||
|
IMGUI_API void ImFontAtlasFontDestroyOutput(ImFontAtlas* atlas, ImFont* font);
|
||||||
|
IMGUI_API void ImFontAtlasFontDiscardBakes(ImFontAtlas* atlas, ImFont* font, int unused_frames);
|
||||||
|
|
||||||
|
IMGUI_API ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size, float rasterizer_density);
|
||||||
|
IMGUI_API ImFontBaked* ImFontAtlasBakedGetOrAdd(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density);
|
||||||
|
IMGUI_API ImFontBaked* ImFontAtlasBakedGetClosestMatch(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density);
|
||||||
|
IMGUI_API ImFontBaked* ImFontAtlasBakedAdd(ImFontAtlas* atlas, ImFont* font, float font_size, float font_rasterizer_density, ImGuiID baked_id);
|
||||||
|
IMGUI_API void ImFontAtlasBakedDiscard(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked);
|
||||||
|
IMGUI_API ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, const ImFontGlyph* in_glyph);
|
||||||
|
IMGUI_API void ImFontAtlasBakedAddFontGlyphAdvancedX(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, ImWchar codepoint, float advance_x);
|
||||||
|
IMGUI_API void ImFontAtlasBakedDiscardFontGlyph(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked, ImFontGlyph* glyph);
|
||||||
|
IMGUI_API void ImFontAtlasBakedSetFontGlyphBitmap(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, ImFontGlyph* glyph, ImTextureRect* r, const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch);
|
||||||
|
|
||||||
|
IMGUI_API void ImFontAtlasPackInit(ImFontAtlas* atlas);
|
||||||
|
IMGUI_API ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFontAtlasRectEntry* overwrite_entry = NULL);
|
||||||
|
IMGUI_API ImTextureRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
|
||||||
|
IMGUI_API ImTextureRect* ImFontAtlasPackGetRectSafe(ImFontAtlas* atlas, ImFontAtlasRectId id);
|
||||||
|
IMGUI_API void ImFontAtlasPackDiscardRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
|
||||||
|
|
||||||
|
IMGUI_API void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool renderer_has_textures);
|
||||||
|
IMGUI_API void ImFontAtlasAddDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
|
||||||
|
IMGUI_API void ImFontAtlasRemoveDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
|
||||||
|
IMGUI_API void ImFontAtlasUpdateDrawListsTextures(ImFontAtlas* atlas, ImTextureRef old_tex, ImTextureRef new_tex);
|
||||||
|
IMGUI_API void ImFontAtlasUpdateDrawListsSharedData(ImFontAtlas* atlas);
|
||||||
|
|
||||||
|
IMGUI_API void ImFontAtlasTextureBlockConvert(const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch, unsigned char* dst_pixels, ImTextureFormat dst_fmt, int dst_pitch, int w, int h);
|
||||||
|
IMGUI_API void ImFontAtlasTextureBlockPostProcess(ImFontAtlasPostProcessData* data);
|
||||||
|
IMGUI_API void ImFontAtlasTextureBlockPostProcessMultiply(ImFontAtlasPostProcessData* data, float multiply_factor);
|
||||||
|
IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h, ImU32 col);
|
||||||
|
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
|
||||||
|
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
|
||||||
|
|
||||||
|
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
|
||||||
|
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
|
||||||
|
IMGUI_API const char* ImTextureDataGetFormatName(ImTextureFormat format);
|
||||||
|
|
||||||
|
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||||
|
IMGUI_API void ImFontAtlasDebugLogTextureRequests(ImFontAtlas* atlas);
|
||||||
#endif
|
#endif
|
||||||
IMGUI_API void ImFontAtlasUpdateSourcesPointers(ImFontAtlas* atlas);
|
|
||||||
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
|
||||||
IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src, float ascent, float descent);
|
|
||||||
IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque);
|
|
||||||
IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
|
|
||||||
IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value);
|
|
||||||
IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value);
|
|
||||||
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);
|
|
||||||
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* src, int* out_oversample_h, int* out_oversample_v);
|
|
||||||
|
|
||||||
IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]);
|
IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@
|
||||||
// with previous char)
|
// with previous char)
|
||||||
// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
|
// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
|
||||||
// (return type is int, -1 means not valid to insert)
|
// (return type is int, -1 means not valid to insert)
|
||||||
|
// (not supported if you want to use UTF-8, see below)
|
||||||
// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
|
// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
|
||||||
// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
|
// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
|
||||||
// as manually wordwrapping for end-of-line positioning
|
// as manually wordwrapping for end-of-line positioning
|
||||||
|
|
@ -178,6 +179,13 @@
|
||||||
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
||||||
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
||||||
//
|
//
|
||||||
|
// To support UTF-8:
|
||||||
|
//
|
||||||
|
// STB_TEXTEDIT_GETPREVCHARINDEX returns index of previous character
|
||||||
|
// STB_TEXTEDIT_GETNEXTCHARINDEX returns index of next character
|
||||||
|
// Do NOT define STB_TEXTEDIT_KEYTOTEXT.
|
||||||
|
// Instead, call stb_textedit_text() directly for text contents.
|
||||||
|
//
|
||||||
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
||||||
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
||||||
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
||||||
|
|
@ -250,8 +258,10 @@
|
||||||
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||||
// transformed into text and stb_textedit_text() is automatically called.
|
// transformed into text and stb_textedit_text() is automatically called.
|
||||||
//
|
//
|
||||||
// text: [DEAR IMGUI] added 2024-09
|
// text: (added 2025)
|
||||||
// call this to text inputs sent to the textfield.
|
// call this to directly send text input the textfield, which is required
|
||||||
|
// for UTF-8 support, because stb_textedit_key() + STB_TEXTEDIT_KEYTOTEXT()
|
||||||
|
// cannot infer text length.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// When rendering, you can read the cursor position and selection state from
|
// When rendering, you can read the cursor position and selection state from
|
||||||
|
|
@ -400,6 +410,16 @@ typedef struct
|
||||||
#define IMSTB_TEXTEDIT_memmove memmove
|
#define IMSTB_TEXTEDIT_memmove memmove
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// [DEAR IMGUI]
|
||||||
|
// Functions must be implemented for UTF8 support
|
||||||
|
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
||||||
|
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
||||||
|
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
||||||
|
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(OBJ, IDX) ((IDX) - 1)
|
||||||
|
#endif
|
||||||
|
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||||
|
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(OBJ, IDX) ((IDX) + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
@ -648,17 +668,6 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [DEAR IMGUI]
|
|
||||||
// Functions must be implemented for UTF8 support
|
|
||||||
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
|
||||||
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
|
||||||
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
|
||||||
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
|
|
||||||
#endif
|
|
||||||
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
|
||||||
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||||
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||||
{
|
{
|
||||||
|
|
@ -668,9 +677,9 @@ static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||||
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||||
{
|
{
|
||||||
--c; // always move at least one character
|
c = IMSTB_TEXTEDIT_GETPREVCHARINDEX( str, c ); // always move at least one character
|
||||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
while (c >= 0 && !is_word_boundary(str, c))
|
||||||
--c;
|
c = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, c);
|
||||||
|
|
||||||
if( c < 0 )
|
if( c < 0 )
|
||||||
c = 0;
|
c = 0;
|
||||||
|
|
@ -684,9 +693,9 @@ static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c
|
||||||
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
|
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||||
{
|
{
|
||||||
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
++c; // always move at least one character
|
c = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, c); // always move at least one character
|
||||||
while( c < len && !is_word_boundary( str, c ) )
|
while( c < len && !is_word_boundary( str, c ) )
|
||||||
++c;
|
c = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, c);
|
||||||
|
|
||||||
if( c > len )
|
if( c > len )
|
||||||
c = len;
|
c = len;
|
||||||
|
|
@ -739,6 +748,7 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
||||||
#define STB_TEXTEDIT_KEYTYPE int
|
#define STB_TEXTEDIT_KEYTYPE int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// API key: process text input
|
||||||
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
||||||
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||||
{
|
{
|
||||||
|
|
@ -753,8 +763,7 @@ static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* sta
|
||||||
state->cursor += text_len;
|
state->cursor += text_len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
stb_textedit_delete_selection(str, state); // implicitly clamps
|
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
stb_text_makeundo_insert(state, state->cursor, text_len);
|
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||||
|
|
@ -771,6 +780,7 @@ retry:
|
||||||
switch (key) {
|
switch (key) {
|
||||||
default: {
|
default: {
|
||||||
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||||
|
// This is not suitable for UTF-8 support.
|
||||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||||
|
|
@ -918,8 +928,9 @@ retry:
|
||||||
state->cursor = start;
|
state->cursor = start;
|
||||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||||
x = row.x0;
|
x = row.x0;
|
||||||
for (i=0; i < row.num_chars; ++i) {
|
for (i=0; i < row.num_chars; ) {
|
||||||
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
||||||
|
int next = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||||
break;
|
break;
|
||||||
|
|
@ -927,7 +938,8 @@ retry:
|
||||||
x += dx;
|
x += dx;
|
||||||
if (x > goal_x)
|
if (x > goal_x)
|
||||||
break;
|
break;
|
||||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
i += next - state->cursor;
|
||||||
|
state->cursor = next;
|
||||||
}
|
}
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
|
||||||
|
|
@ -980,8 +992,9 @@ retry:
|
||||||
state->cursor = find.prev_first;
|
state->cursor = find.prev_first;
|
||||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||||
x = row.x0;
|
x = row.x0;
|
||||||
for (i=0; i < row.num_chars; ++i) {
|
for (i=0; i < row.num_chars; ) {
|
||||||
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
||||||
|
int next = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||||
break;
|
break;
|
||||||
|
|
@ -989,7 +1002,8 @@ retry:
|
||||||
x += dx;
|
x += dx;
|
||||||
if (x > goal_x)
|
if (x > goal_x)
|
||||||
break;
|
break;
|
||||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
i += next - state->cursor;
|
||||||
|
state->cursor = next;
|
||||||
}
|
}
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
|
||||||
|
|
@ -1002,8 +1016,13 @@ retry:
|
||||||
// go to previous line
|
// go to previous line
|
||||||
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
|
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
|
||||||
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
|
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
|
||||||
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
|
while (prev_scan > 0)
|
||||||
--prev_scan;
|
{
|
||||||
|
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, prev_scan);
|
||||||
|
if (STB_TEXTEDIT_GETCHAR(str, prev) == STB_TEXTEDIT_NEWLINE)
|
||||||
|
break;
|
||||||
|
prev_scan = prev;
|
||||||
|
}
|
||||||
find.first_char = find.prev_first;
|
find.first_char = find.prev_first;
|
||||||
find.prev_first = prev_scan;
|
find.prev_first = prev_scan;
|
||||||
}
|
}
|
||||||
|
|
@ -1082,7 +1101,7 @@ retry:
|
||||||
if (state->single_line)
|
if (state->single_line)
|
||||||
state->cursor = 0;
|
state->cursor = 0;
|
||||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||||
--state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1094,9 +1113,9 @@ retry:
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
stb_textedit_move_to_first(state);
|
stb_textedit_move_to_first(state);
|
||||||
if (state->single_line)
|
if (state->single_line)
|
||||||
state->cursor = n;
|
state->cursor = n;
|
||||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1110,7 +1129,7 @@ retry:
|
||||||
if (state->single_line)
|
if (state->single_line)
|
||||||
state->cursor = 0;
|
state->cursor = 0;
|
||||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||||
--state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||||
state->select_end = state->cursor;
|
state->select_end = state->cursor;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1125,7 +1144,7 @@ retry:
|
||||||
if (state->single_line)
|
if (state->single_line)
|
||||||
state->cursor = n;
|
state->cursor = n;
|
||||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
state->select_end = state->cursor;
|
state->select_end = state->cursor;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -4516,8 +4516,8 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||||
q2[0] = (float)x2;
|
q2[0] = (float)x2;
|
||||||
q2[1] = (float)y2;
|
q2[1] = (float)y2;
|
||||||
if (equal(q0,q1) || equal(q1,q2)) {
|
if (equal(q0,q1) || equal(q1,q2)) {
|
||||||
x0 = (int)verts[i-1].x;
|
x0 = (int)verts[i-1].x; //-V1048
|
||||||
y0 = (int)verts[i-1].y;
|
y0 = (int)verts[i-1].y; //-V1048
|
||||||
x1 = (int)verts[i ].x;
|
x1 = (int)verts[i ].x;
|
||||||
y1 = (int)verts[i ].y;
|
y1 = (int)verts[i ].y;
|
||||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
#ifndef IMGUI_DISABLE
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
||||||
// Usage:
|
// Usage:
|
||||||
// - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to enable support for imgui_freetype in imgui.
|
// - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to automatically enable support
|
||||||
|
// for imgui_freetype in imgui. It is equivalent to selecting the default loader with:
|
||||||
|
// io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader())
|
||||||
|
|
||||||
// Optional support for OpenType SVG fonts:
|
// Optional support for OpenType SVG fonts:
|
||||||
// - Add '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG' to use plutosvg (not provided). See #7927.
|
// - Add '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG' to use plutosvg (not provided). See #7927.
|
||||||
|
|
@ -14,46 +16,70 @@
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
struct ImFontAtlas;
|
struct ImFontAtlas;
|
||||||
struct ImFontBuilderIO;
|
struct ImFontLoader;
|
||||||
|
|
||||||
// Hinting greatly impacts visuals (and glyph sizes).
|
// Hinting greatly impacts visuals (and glyph sizes).
|
||||||
// - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
|
// - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
|
||||||
// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h
|
// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h
|
||||||
// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
|
// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
|
||||||
// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
|
// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
|
||||||
// You can set those flags globaly in ImFontAtlas::FontBuilderFlags
|
// You can set those flags globally in ImFontAtlas::FontLoaderFlags
|
||||||
// You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags
|
// You can set those flags on a per font basis in ImFontConfig::FontLoaderFlags
|
||||||
enum ImGuiFreeTypeBuilderFlags
|
typedef unsigned int ImGuiFreeTypeLoaderFlags;
|
||||||
|
enum ImGuiFreeTypeLoaderFlags_
|
||||||
{
|
{
|
||||||
ImGuiFreeTypeBuilderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
|
ImGuiFreeTypeLoaderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
|
||||||
ImGuiFreeTypeBuilderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter.
|
ImGuiFreeTypeLoaderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter.
|
||||||
ImGuiFreeTypeBuilderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
|
ImGuiFreeTypeLoaderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
|
||||||
ImGuiFreeTypeBuilderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
|
ImGuiFreeTypeLoaderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
|
||||||
ImGuiFreeTypeBuilderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
|
ImGuiFreeTypeLoaderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
|
||||||
ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
|
ImGuiFreeTypeLoaderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
|
||||||
ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
|
ImGuiFreeTypeLoaderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
|
||||||
ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
|
ImGuiFreeTypeLoaderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
|
||||||
ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
|
ImGuiFreeTypeLoaderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
|
||||||
ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9, // Enable FreeType bitmap glyphs
|
ImGuiFreeTypeLoaderFlags_Bitmap = 1 << 9, // Enable FreeType bitmap glyphs
|
||||||
ImGuiFreeTypeBuilderFlags_SubPixel = 1 << 10 // Atlas was generated with sub-pixel rendering enabled
|
// IMHEX PATCH BEGIN
|
||||||
|
ImGuiFreeTypeLoaderFlags_SubPixel = 1 << 10 // Atlas was generated with sub-pixel rendering enabled
|
||||||
|
// IMHEX PATCH END
|
||||||
|
|
||||||
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
ImGuiFreeTypeBuilderFlags_NoHinting = ImGuiFreeTypeLoaderFlags_NoHinting,
|
||||||
|
ImGuiFreeTypeBuilderFlags_NoAutoHint = ImGuiFreeTypeLoaderFlags_NoAutoHint,
|
||||||
|
ImGuiFreeTypeBuilderFlags_ForceAutoHint = ImGuiFreeTypeLoaderFlags_ForceAutoHint,
|
||||||
|
ImGuiFreeTypeBuilderFlags_LightHinting = ImGuiFreeTypeLoaderFlags_LightHinting,
|
||||||
|
ImGuiFreeTypeBuilderFlags_MonoHinting = ImGuiFreeTypeLoaderFlags_MonoHinting,
|
||||||
|
ImGuiFreeTypeBuilderFlags_Bold = ImGuiFreeTypeLoaderFlags_Bold,
|
||||||
|
ImGuiFreeTypeBuilderFlags_Oblique = ImGuiFreeTypeLoaderFlags_Oblique,
|
||||||
|
ImGuiFreeTypeBuilderFlags_Monochrome = ImGuiFreeTypeLoaderFlags_Monochrome,
|
||||||
|
ImGuiFreeTypeBuilderFlags_LoadColor = ImGuiFreeTypeLoaderFlags_LoadColor,
|
||||||
|
ImGuiFreeTypeBuilderFlags_Bitmap = ImGuiFreeTypeLoaderFlags_Bitmap,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Obsolete names (will be removed)
|
||||||
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
typedef ImGuiFreeTypeLoaderFlags_ ImGuiFreeTypeBuilderFlags_;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ImGuiFreeType
|
namespace ImGuiFreeType
|
||||||
{
|
{
|
||||||
// This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'.
|
// This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'.
|
||||||
// If you need to dynamically select between multiple builders:
|
// If you need to dynamically select between multiple builders:
|
||||||
// - you can manually assign this builder with 'atlas->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()'
|
// - you can manually assign this builder with 'atlas->SetFontLoader(ImGuiFreeType::GetFontLoader())'
|
||||||
// - prefer deep-copying this into your own ImFontBuilderIO instance if you use hot-reloading that messes up static data.
|
// - prefer deep-copying this into your own ImFontLoader instance if you use hot-reloading that messes up static data.
|
||||||
IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType();
|
IMGUI_API const ImFontLoader* GetFontLoader();
|
||||||
|
|
||||||
// Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()
|
// Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()
|
||||||
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired.
|
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired.
|
||||||
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr);
|
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr);
|
||||||
|
|
||||||
// Obsolete names (will be removed soon)
|
// Display UI to edit ImFontAtlas::FontLoaderFlags (shared) or ImFontConfig::FontLoaderFlags (single source)
|
||||||
|
IMGUI_API bool DebugEditFontLoaderFlags(ImGuiFreeTypeLoaderFlags* p_font_loader_flags);
|
||||||
|
|
||||||
|
// Obsolete names (will be removed)
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
//static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE'
|
//IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType(); // Renamed/changed in 1.92. Change 'io.Fonts->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()' to 'io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader())' if you need runtime selection.
|
||||||
|
//static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontLoaderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE'
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.91b
|
// dear imgui, v1.92.1
|
||||||
// (tables and columns code)
|
// (tables and columns code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -451,6 +451,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||||
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
|
// But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
|
||||||
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
|
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
|
||||||
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
|
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
|
||||||
|
table->InnerWindow->DC.TreeDepth++; // This is designed to always linking ImGuiTreeNodeFlags_DrawLines linking accross a table
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push a standardized ID for both child-using and not-child-using tables
|
// Push a standardized ID for both child-using and not-child-using tables
|
||||||
|
|
@ -1250,7 +1251,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||||
|
|
||||||
// [Part 11] Default context menu
|
// [Part 11] Default context menu
|
||||||
// - To append to this menu: you can call TableBeginContextMenuPopup()/.../EndPopup().
|
// - To append to this menu: you can call TableBeginContextMenuPopup()/.../EndPopup().
|
||||||
// - To modify or replace this: set table->IsContextPopupNoDefaultContents = true, then call TableBeginContextMenuPopup()/.../EndPopup().
|
// - To modify or replace this: set table->DisableDefaultContextMenu = true, then call TableBeginContextMenuPopup()/.../EndPopup().
|
||||||
// - You may call TableDrawDefaultContextMenu() with selected flags to display specific sections of the default menu,
|
// - You may call TableDrawDefaultContextMenu() with selected flags to display specific sections of the default menu,
|
||||||
// e.g. TableDrawDefaultContextMenu(table, table->Flags & ~ImGuiTableFlags_Hideable) will display everything EXCEPT columns visibility options.
|
// e.g. TableDrawDefaultContextMenu(table, table->Flags & ~ImGuiTableFlags_Hideable) will display everything EXCEPT columns visibility options.
|
||||||
if (table->DisableDefaultContextMenu == false && TableBeginContextMenuPopup(table))
|
if (table->DisableDefaultContextMenu == false && TableBeginContextMenuPopup(table))
|
||||||
|
|
@ -1510,6 +1511,7 @@ void ImGui::EndTable()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
table->InnerWindow->DC.TreeDepth--;
|
||||||
ItemSize(table->OuterRect.GetSize());
|
ItemSize(table->OuterRect.GetSize());
|
||||||
ItemAdd(table->OuterRect, 0);
|
ItemAdd(table->OuterRect, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -1951,7 +1953,10 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||||
IM_ASSERT(table->IsInsideRow);
|
IM_ASSERT(table->IsInsideRow);
|
||||||
|
|
||||||
if (table->CurrentColumn != -1)
|
if (table->CurrentColumn != -1)
|
||||||
|
{
|
||||||
TableEndCell(table);
|
TableEndCell(table);
|
||||||
|
table->CurrentColumn = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
if (g.LogEnabled)
|
if (g.LogEnabled)
|
||||||
|
|
@ -2191,6 +2196,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
|
||||||
g.LastItemData.StatusFlags = 0;
|
g.LastItemData.StatusFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also see TablePushColumnChannel()
|
||||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||||
{
|
{
|
||||||
// FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed.
|
// FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed.
|
||||||
|
|
@ -2464,10 +2470,38 @@ void ImGui::TablePopBackgroundChannel()
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
ImGuiTable* table = g.CurrentTable;
|
ImGuiTable* table = g.CurrentTable;
|
||||||
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
|
||||||
|
|
||||||
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
||||||
SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect);
|
SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect);
|
||||||
|
table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[table->CurrentColumn].DrawChannelCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also see TableBeginCell()
|
||||||
|
void ImGui::TablePushColumnChannel(int column_n)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiTable* table = g.CurrentTable;
|
||||||
|
|
||||||
|
// Optimization: avoid SetCurrentChannel() + PushClipRect()
|
||||||
|
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||||
|
return;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
const ImGuiTableColumn* column = &table->Columns[column_n];
|
||||||
|
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
|
||||||
|
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::TablePopColumnChannel()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiTable* table = g.CurrentTable;
|
||||||
|
|
||||||
|
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
||||||
|
if ((table->Flags & ImGuiTableFlags_NoClip) || (table->CurrentColumn == -1)) // Calling TreePop() after TableNextRow() is supported.
|
||||||
|
return;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
const ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||||
|
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
|
||||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3244,7 +3278,7 @@ void ImGui::TableHeader(const char* label)
|
||||||
// Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will
|
// Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will
|
||||||
// be merged into a single draw call.
|
// be merged into a single draw call.
|
||||||
//window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
|
//window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
|
||||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
|
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, bb.Max.y), ellipsis_max, label, label_end, &label_size);
|
||||||
|
|
||||||
const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
|
const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
|
||||||
if (text_clipped && hovered && g.ActiveId == 0)
|
if (text_clipped && hovered && g.ActiveId == 0)
|
||||||
|
|
@ -3341,7 +3375,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
||||||
ButtonBehavior(row_r, row_id, NULL, NULL);
|
ButtonBehavior(row_r, row_id, NULL, NULL);
|
||||||
KeepAliveID(row_id);
|
KeepAliveID(row_id);
|
||||||
|
|
||||||
const float ascent_scaled = g.Font->Ascent * g.FontScale; // FIXME: Standardize those scaling factors better
|
const float ascent_scaled = g.FontBaked->Ascent * g.FontBakedScale; // FIXME: Standardize those scaling factors better
|
||||||
const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
|
const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
|
||||||
const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
|
const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
|
||||||
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
|
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
|
||||||
|
|
@ -3396,7 +3430,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
||||||
ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height));
|
ImRect clip_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width, clip_height));
|
||||||
int vtx_idx_begin = draw_list->_VtxCurrentIdx;
|
int vtx_idx_begin = draw_list->_VtxCurrentIdx;
|
||||||
PushStyleColor(ImGuiCol_Text, request->TextColor);
|
PushStyleColor(ImGuiCol_Text, request->TextColor);
|
||||||
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, clip_r.Max.x, label_name, label_name_eol, &label_size);
|
RenderTextEllipsis(draw_list, clip_r.Min, clip_r.Max, clip_r.Max.x, label_name, label_name_eol, &label_size);
|
||||||
PopStyleColor();
|
PopStyleColor();
|
||||||
int vtx_idx_end = draw_list->_VtxCurrentIdx;
|
int vtx_idx_end = draw_list->_VtxCurrentIdx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// dear imgui, v1.91b
|
// dear imgui, v1.92.1
|
||||||
// (widgets code)
|
// (widgets code)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -339,6 +339,46 @@ void ImGui::TextWrappedV(const char* fmt, va_list args)
|
||||||
PopTextWrapPos();
|
PopTextWrapPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGui::TextAligned(float align_x, float size_x, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
TextAlignedV(align_x, size_x, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// align_x: 0.0f = left, 0.5f = center, 1.0f = right.
|
||||||
|
// size_x : 0.0f = shortcut for GetContentRegionAvail().x
|
||||||
|
// FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024)
|
||||||
|
void ImGui::TextAlignedV(float align_x, float size_x, const char* fmt, va_list args)
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* text, *text_end;
|
||||||
|
ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
|
||||||
|
const ImVec2 text_size = CalcTextSize(text, text_end);
|
||||||
|
size_x = CalcItemSize(ImVec2(size_x, 0.0f), 0.0f, text_size.y).x;
|
||||||
|
|
||||||
|
ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||||
|
ImVec2 pos_max(pos.x + size_x, window->ClipRect.Max.y);
|
||||||
|
ImVec2 size(ImMin(size_x, text_size.x), text_size.y);
|
||||||
|
window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, pos.x + text_size.x);
|
||||||
|
window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, pos.x + text_size.x);
|
||||||
|
if (align_x > 0.0f && text_size.x < size_x)
|
||||||
|
pos.x += ImTrunc((size_x - text_size.x) * align_x);
|
||||||
|
RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, text_end, &text_size);
|
||||||
|
|
||||||
|
const ImVec2 backup_max_pos = window->DC.CursorMaxPos;
|
||||||
|
ItemSize(size);
|
||||||
|
ItemAdd(ImRect(pos, pos + size), 0);
|
||||||
|
window->DC.CursorMaxPos.x = backup_max_pos.x; // Cancel out extending content size because right-aligned text would otherwise mess it up.
|
||||||
|
|
||||||
|
if (size_x < text_size.x && IsItemHovered(ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_ForTooltip))
|
||||||
|
SetTooltip("%.*s", (int)(text_end - text), text);
|
||||||
|
}
|
||||||
|
|
||||||
void ImGui::LabelText(const char* label, const char* fmt, ...)
|
void ImGui::LabelText(const char* label, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
@ -494,7 +534,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
|
||||||
// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
|
// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
|
||||||
// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
|
// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
|
||||||
// - Since v1.91.2 (Sept 2024) we included io.ConfigDebugHighlightIdConflicts feature.
|
// - Since v1.91.2 (Sept 2024) we included io.ConfigDebugHighlightIdConflicts feature.
|
||||||
// One idiom which was previously valid which will now emit a warning is when using multiple overlayed ButtonBehavior()
|
// One idiom which was previously valid which will now emit a warning is when using multiple overlaid ButtonBehavior()
|
||||||
// with same ID and different MouseButton (see #8030). You can fix it by:
|
// with same ID and different MouseButton (see #8030). You can fix it by:
|
||||||
// (1) switching to use a single ButtonBehavior() with multiple _MouseButton flags.
|
// (1) switching to use a single ButtonBehavior() with multiple _MouseButton flags.
|
||||||
// or (2) surrounding those calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
|
// or (2) surrounding those calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
|
||||||
|
|
@ -508,6 +548,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||||
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
|
ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
|
||||||
if (flags & ImGuiButtonFlags_AllowOverlap)
|
if (flags & ImGuiButtonFlags_AllowOverlap)
|
||||||
item_flags |= ImGuiItemFlags_AllowOverlap;
|
item_flags |= ImGuiItemFlags_AllowOverlap;
|
||||||
|
if (item_flags & ImGuiItemFlags_NoFocus)
|
||||||
|
flags |= ImGuiButtonFlags_NoFocus | ImGuiButtonFlags_NoNavFocus;
|
||||||
|
|
||||||
// Default only reacts to left mouse button
|
// Default only reacts to left mouse button
|
||||||
if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
|
if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
|
||||||
|
|
@ -531,7 +573,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
bool hovered = ItemHoverable(bb, id, item_flags);
|
bool hovered = ItemHoverable(bb, id, item_flags);
|
||||||
|
|
||||||
// Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button
|
// Special mode for Drag and Drop used by openables (tree nodes, tabs etc.)
|
||||||
|
// where holding the button pressed for a long time while drag a payload item triggers the button.
|
||||||
if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
|
if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
|
||||||
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||||
{
|
{
|
||||||
|
|
@ -583,7 +626,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||||
SetFocusID(id, window);
|
SetFocusID(id, window);
|
||||||
FocusWindow(window);
|
FocusWindow(window);
|
||||||
}
|
}
|
||||||
else
|
else if (!(flags & ImGuiButtonFlags_NoFocus))
|
||||||
{
|
{
|
||||||
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
||||||
}
|
}
|
||||||
|
|
@ -601,7 +644,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||||
SetFocusID(id, window);
|
SetFocusID(id, window);
|
||||||
FocusWindow(window);
|
FocusWindow(window);
|
||||||
}
|
}
|
||||||
else
|
else if (!(flags & ImGuiButtonFlags_NoFocus))
|
||||||
{
|
{
|
||||||
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
|
||||||
}
|
}
|
||||||
|
|
@ -867,11 +910,12 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
|
||||||
if (hovered)
|
if (hovered)
|
||||||
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
|
window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
|
||||||
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
|
RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
|
||||||
ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
|
||||||
ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
|
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
|
||||||
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
|
||||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
|
const float cross_thickness = 1.0f; // FIXME-DPI
|
||||||
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
|
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
|
||||||
|
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, cross_thickness);
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
@ -1068,9 +1112,9 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
|
||||||
return held;
|
return held;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
// - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
||||||
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
|
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
|
||||||
void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
@ -1088,28 +1132,28 @@ void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, c
|
||||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize);
|
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize);
|
||||||
if (bg_col.w > 0.0f)
|
if (bg_col.w > 0.0f)
|
||||||
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
|
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
|
||||||
window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
|
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
|
||||||
{
|
{
|
||||||
ImageWithBg(user_texture_id, image_size, uv0, uv1);
|
ImageWithBg(tex_ref, image_size, uv0, uv1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.91.9 (February 2025) removed 'tint_col' and 'border_col' parameters, made border size not depend on color value. (#8131, #8238)
|
// 1.91.9 (February 2025) removed 'tint_col' and 'border_col' parameters, made border size not depend on color value. (#8131, #8238)
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
|
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
PushStyleVar(ImGuiStyleVar_ImageBorderSize, (border_col.w > 0.0f) ? ImMax(1.0f, g.Style.ImageBorderSize) : 0.0f); // Preserve legacy behavior where border is always visible when border_col's Alpha is >0.0f
|
PushStyleVar(ImGuiStyleVar_ImageBorderSize, (border_col.w > 0.0f) ? ImMax(1.0f, g.Style.ImageBorderSize) : 0.0f); // Preserve legacy behavior where border is always visible when border_col's Alpha is >0.0f
|
||||||
PushStyleColor(ImGuiCol_Border, border_col);
|
PushStyleColor(ImGuiCol_Border, border_col);
|
||||||
ImageWithBg(user_texture_id, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col);
|
ImageWithBg(tex_ref, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col);
|
||||||
PopStyleColor();
|
PopStyleColor();
|
||||||
PopStyleVar();
|
PopStyleVar();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
@ -1131,21 +1175,21 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2&
|
||||||
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
|
RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
|
||||||
if (bg_col.w > 0.0f)
|
if (bg_col.w > 0.0f)
|
||||||
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
|
window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
|
||||||
window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
|
// - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
|
||||||
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design?
|
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design?
|
||||||
bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
bool ImGui::ImageButton(const char* str_id, ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
if (window->SkipItems)
|
if (window->SkipItems)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ImageButtonEx(window->GetID(str_id), user_texture_id, image_size, uv0, uv1, bg_col, tint_col);
|
return ImageButtonEx(window->GetID(str_id), tex_ref, image_size, uv0, uv1, bg_col, tint_col);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
|
@ -1483,8 +1527,8 @@ bool ImGui::TextLink(const char* label)
|
||||||
ColorConvertHSVtoRGB(h, s, v, line_colf.x, line_colf.y, line_colf.z);
|
ColorConvertHSVtoRGB(h, s, v, line_colf.x, line_colf.y, line_colf.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
float line_y = bb.Max.y + ImFloor(g.Font->Descent * g.FontScale * 0.20f);
|
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
|
||||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode.
|
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||||
|
|
||||||
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
||||||
RenderText(bb.Min, label, label_end);
|
RenderText(bb.Min, label, label_end);
|
||||||
|
|
@ -1494,14 +1538,14 @@ bool ImGui::TextLink(const char* label)
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::TextLinkOpenURL(const char* label, const char* url)
|
bool ImGui::TextLinkOpenURL(const char* label, const char* url)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (url == NULL)
|
if (url == NULL)
|
||||||
url = label;
|
url = label;
|
||||||
if (TextLink(label))
|
bool pressed = TextLink(label);
|
||||||
if (g.PlatformIO.Platform_OpenInShellFn != NULL)
|
if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||||
g.PlatformIO.Platform_OpenInShellFn(&g, url);
|
g.PlatformIO.Platform_OpenInShellFn(&g, url);
|
||||||
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
|
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
|
||||||
if (BeginPopupContextItem())
|
if (BeginPopupContextItem())
|
||||||
{
|
{
|
||||||
|
|
@ -1509,6 +1553,7 @@ void ImGui::TextLinkOpenURL(const char* label, const char* url)
|
||||||
SetClipboardText(url);
|
SetClipboardText(url);
|
||||||
EndPopup();
|
EndPopup();
|
||||||
}
|
}
|
||||||
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
@ -1695,7 +1740,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
||||||
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
||||||
if (g.LogEnabled)
|
if (g.LogEnabled)
|
||||||
LogSetNextTextDecoration("---", NULL);
|
LogSetNextTextDecoration("---", NULL);
|
||||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, bb.Max.x, label, label_end, &label_size);
|
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3896,7 +3941,7 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, si
|
||||||
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
|
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only used in the path where the multiline widget is inactivate.
|
// This is only used in the path where the multiline widget is inactive.
|
||||||
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
|
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
|
||||||
{
|
{
|
||||||
int line_count = 0;
|
int line_count = 0;
|
||||||
|
|
@ -3920,9 +3965,10 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char**
|
||||||
static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining, ImVec2* out_offset, bool stop_on_new_line)
|
static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining, ImVec2* out_offset, bool stop_on_new_line)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *ctx;
|
ImGuiContext& g = *ctx;
|
||||||
ImFont* font = g.Font;
|
//ImFont* font = g.Font;
|
||||||
|
ImFontBaked* baked = g.FontBaked;
|
||||||
const float line_height = g.FontSize;
|
const float line_height = g.FontSize;
|
||||||
const float scale = line_height / font->FontSize;
|
const float scale = line_height / baked->Size;
|
||||||
|
|
||||||
ImVec2 text_size = ImVec2(0, 0);
|
ImVec2 text_size = ImVec2(0, 0);
|
||||||
float line_width = 0.0f;
|
float line_width = 0.0f;
|
||||||
|
|
@ -3948,8 +3994,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
|
||||||
if (c == '\r')
|
if (c == '\r')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const float char_width = ((int)c < font->IndexAdvanceX.Size ? font->IndexAdvanceX.Data[c] : font->FallbackAdvanceX) * scale;
|
line_width += baked->GetCharAdvance((ImWchar)c) * scale;
|
||||||
line_width += char_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text_size.x < line_width)
|
if (text_size.x < line_width)
|
||||||
|
|
@ -3976,7 +4021,7 @@ namespace ImStb
|
||||||
{
|
{
|
||||||
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; }
|
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; }
|
||||||
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
|
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
|
||||||
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
|
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.FontBaked->GetCharAdvance((ImWchar)c) * g.FontBakedScale; }
|
||||||
static char STB_TEXTEDIT_NEWLINE = '\n';
|
static char STB_TEXTEDIT_NEWLINE = '\n';
|
||||||
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
|
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
|
||||||
{
|
{
|
||||||
|
|
@ -4244,23 +4289,24 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||||
if (new_text == new_text_end)
|
if (new_text == new_text_end)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ImGuiContext& g = *Ctx;
|
||||||
|
ImGuiInputTextState* obj = &g.InputTextState;
|
||||||
|
IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID);
|
||||||
|
|
||||||
// Grow internal buffer if needed
|
// Grow internal buffer if needed
|
||||||
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||||
const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
|
const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text);
|
||||||
if (new_text_len + BufTextLen >= BufSize)
|
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && (Flags & ImGuiInputTextFlags_ReadOnly) == 0)
|
||||||
{
|
{
|
||||||
if (!is_resizable)
|
if (!is_resizable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGuiContext& g = *Ctx;
|
IM_ASSERT(Buf == obj->TextA.Data);
|
||||||
ImGuiInputTextState* edit_state = &g.InputTextState;
|
|
||||||
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
|
|
||||||
IM_ASSERT(Buf == edit_state->TextA.Data);
|
|
||||||
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
|
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
|
||||||
edit_state->TextA.resize(new_buf_size + 1);
|
obj->TextA.resize(new_buf_size + 1);
|
||||||
edit_state->TextSrc = edit_state->TextA.Data;
|
obj->TextSrc = obj->TextA.Data;
|
||||||
Buf = edit_state->TextA.Data;
|
Buf = obj->TextA.Data;
|
||||||
BufSize = edit_state->BufCapacity = new_buf_size;
|
BufSize = obj->BufCapacity = new_buf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BufTextLen != pos)
|
if (BufTextLen != pos)
|
||||||
|
|
@ -4278,18 +4324,29 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||||
void ImGui::PushPasswordFont()
|
void ImGui::PushPasswordFont()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImFont* in_font = g.Font;
|
ImFontBaked* backup = &g.InputTextPasswordFontBackupBaked;
|
||||||
ImFont* out_font = &g.InputTextPasswordFont;
|
IM_ASSERT(backup->IndexAdvanceX.Size == 0 && backup->IndexLookup.Size == 0);
|
||||||
ImFontGlyph* glyph = in_font->FindGlyph('*');
|
ImFontGlyph* glyph = g.FontBaked->FindGlyph('*');
|
||||||
out_font->FontSize = in_font->FontSize;
|
g.InputTextPasswordFontBackupFlags = g.Font->Flags;
|
||||||
out_font->Scale = in_font->Scale;
|
backup->FallbackGlyphIndex = g.FontBaked->FallbackGlyphIndex;
|
||||||
out_font->Ascent = in_font->Ascent;
|
backup->FallbackAdvanceX = g.FontBaked->FallbackAdvanceX;
|
||||||
out_font->Descent = in_font->Descent;
|
backup->IndexLookup.swap(g.FontBaked->IndexLookup);
|
||||||
out_font->ContainerAtlas = in_font->ContainerAtlas;
|
backup->IndexAdvanceX.swap(g.FontBaked->IndexAdvanceX);
|
||||||
out_font->FallbackGlyph = glyph;
|
g.Font->Flags |= ImFontFlags_NoLoadGlyphs;
|
||||||
out_font->FallbackAdvanceX = glyph->AdvanceX;
|
g.FontBaked->FallbackGlyphIndex = g.FontBaked->Glyphs.index_from_ptr(glyph);
|
||||||
IM_ASSERT(out_font->Glyphs.Size == 0 && out_font->IndexAdvanceX.Size == 0 && out_font->IndexLookup.Size == 0);
|
g.FontBaked->FallbackAdvanceX = glyph->AdvanceX;
|
||||||
PushFont(out_font);
|
}
|
||||||
|
|
||||||
|
void ImGui::PopPasswordFont()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImFontBaked* backup = &g.InputTextPasswordFontBackupBaked;
|
||||||
|
g.Font->Flags = g.InputTextPasswordFontBackupFlags;
|
||||||
|
g.FontBaked->FallbackGlyphIndex = backup->FallbackGlyphIndex;
|
||||||
|
g.FontBaked->FallbackAdvanceX = backup->FallbackAdvanceX;
|
||||||
|
g.FontBaked->IndexLookup.swap(backup->IndexLookup);
|
||||||
|
g.FontBaked->IndexAdvanceX.swap(backup->IndexAdvanceX);
|
||||||
|
IM_ASSERT(backup->IndexAdvanceX.Size == 0 && backup->IndexLookup.Size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return false to discard a character.
|
// Return false to discard a character.
|
||||||
|
|
@ -4653,7 +4710,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
{
|
{
|
||||||
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
|
// Declare some inputs, the other are registered and polled via Shortcut() routing system.
|
||||||
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combinaison into individual shortcuts.
|
// FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts.
|
||||||
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
|
const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
|
||||||
for (ImGuiKey key : always_owned_keys)
|
for (ImGuiKey key : always_owned_keys)
|
||||||
SetKeyOwner(key, id);
|
SetKeyOwner(key, id);
|
||||||
|
|
@ -5166,8 +5223,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
// Otherwise request text input ahead for next frame.
|
// Otherwise request text input ahead for next frame.
|
||||||
if (g.ActiveId == id && clear_active_id)
|
if (g.ActiveId == id && clear_active_id)
|
||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
else if (g.ActiveId == id)
|
|
||||||
g.WantTextInputNextFrame = 1;
|
|
||||||
|
|
||||||
// Render frame
|
// Render frame
|
||||||
if (!is_multiline)
|
if (!is_multiline)
|
||||||
|
|
@ -5193,7 +5248,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
if (new_is_displaying_hint != is_displaying_hint)
|
if (new_is_displaying_hint != is_displaying_hint)
|
||||||
{
|
{
|
||||||
if (is_password && !is_displaying_hint)
|
if (is_password && !is_displaying_hint)
|
||||||
PopFont();
|
PopPasswordFont();
|
||||||
is_displaying_hint = new_is_displaying_hint;
|
is_displaying_hint = new_is_displaying_hint;
|
||||||
if (is_password && !is_displaying_hint)
|
if (is_password && !is_displaying_hint)
|
||||||
PushPasswordFont();
|
PushPasswordFont();
|
||||||
|
|
@ -5318,7 +5373,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImVec2 rect_size = InputTextCalcTextSize(&g, p, text_selected_end, &p, NULL, true);
|
ImVec2 rect_size = InputTextCalcTextSize(&g, p, text_selected_end, &p, NULL, true);
|
||||||
if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
|
if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.FontBaked->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
|
||||||
ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
|
ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
|
||||||
rect.ClipWith(clip_rect);
|
rect.ClipWith(clip_rect);
|
||||||
if (rect.Overlaps(clip_rect))
|
if (rect.Overlaps(clip_rect))
|
||||||
|
|
@ -5345,15 +5400,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
|
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031)
|
||||||
|
|
||||||
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
||||||
if (!is_readonly)
|
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
||||||
|
// As per #6341, make sure we don't set that on the deactivating frame.
|
||||||
|
if (!is_readonly && g.ActiveId == id)
|
||||||
{
|
{
|
||||||
g.PlatformImeData.WantVisible = true;
|
ImGuiPlatformImeData* ime_data = &g.PlatformImeData; // (this is a public struct, passed to io.Platform_SetImeDataFn() handler)
|
||||||
g.PlatformImeData.InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
|
ime_data->WantVisible = true;
|
||||||
g.PlatformImeData.InputLineHeight = g.FontSize;
|
ime_data->WantTextInput = true;
|
||||||
g.PlatformImeViewport = window->Viewport->ID;
|
ime_data->InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
|
||||||
|
ime_data->InputLineHeight = g.FontSize;
|
||||||
|
ime_data->ViewportId = window->Viewport->ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5380,7 +5439,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_password && !is_displaying_hint)
|
if (is_password && !is_displaying_hint)
|
||||||
PopFont();
|
PopPasswordFont();
|
||||||
|
|
||||||
if (is_multiline)
|
if (is_multiline)
|
||||||
{
|
{
|
||||||
|
|
@ -5432,7 +5491,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
|
||||||
Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
|
Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
|
||||||
DebugLocateItemOnHover(state->ID);
|
DebugLocateItemOnHover(state->ID);
|
||||||
Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->TextLen, stb_state->cursor, stb_state->select_start, stb_state->select_end);
|
Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->TextLen, stb_state->cursor, stb_state->select_start, stb_state->select_end);
|
||||||
Text("BufCapacityA: %d", state->BufCapacity);
|
Text("BufCapacity: %d", state->BufCapacity);
|
||||||
Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state->TextA.Size, state->TextA.Capacity);
|
Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state->TextA.Size, state->TextA.Capacity);
|
||||||
Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
|
Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
|
||||||
Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
|
Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
|
||||||
|
|
@ -6214,7 +6273,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||||
if (g.Style.FrameBorderSize > 0.0f)
|
if (g.Style.FrameBorderSize > 0.0f)
|
||||||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||||
else
|
else
|
||||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border
|
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drag and Drop Source
|
// Drag and Drop Source
|
||||||
|
|
@ -6396,6 +6455,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
|
||||||
// - TreeNodeV()
|
// - TreeNodeV()
|
||||||
// - TreeNodeEx()
|
// - TreeNodeEx()
|
||||||
// - TreeNodeExV()
|
// - TreeNodeExV()
|
||||||
|
// - TreeNodeStoreStackData() [Internal]
|
||||||
// - TreeNodeBehavior() [Internal]
|
// - TreeNodeBehavior() [Internal]
|
||||||
// - TreePush()
|
// - TreePush()
|
||||||
// - TreePop()
|
// - TreePop()
|
||||||
|
|
@ -6554,18 +6614,26 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
|
||||||
|
|
||||||
// Store ImGuiTreeNodeStackData for just submitted node.
|
// Store ImGuiTreeNodeStackData for just submitted node.
|
||||||
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase.
|
// Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase.
|
||||||
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
|
static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
|
||||||
g.TreeNodeStack.resize(g.TreeNodeStack.Size + 1);
|
g.TreeNodeStack.resize(g.TreeNodeStack.Size + 1);
|
||||||
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
|
ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||||
tree_node_data->ID = g.LastItemData.ID;
|
tree_node_data->ID = g.LastItemData.ID;
|
||||||
tree_node_data->TreeFlags = flags;
|
tree_node_data->TreeFlags = flags;
|
||||||
tree_node_data->ItemFlags = g.LastItemData.ItemFlags;
|
tree_node_data->ItemFlags = g.LastItemData.ItemFlags;
|
||||||
tree_node_data->NavRect = g.LastItemData.NavRect;
|
tree_node_data->NavRect = g.LastItemData.NavRect;
|
||||||
|
|
||||||
|
// Initially I tried to latch value for GetColorU32(ImGuiCol_TreeLines) but it's not a good trade-off for very large trees.
|
||||||
|
const bool draw_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) != 0;
|
||||||
|
tree_node_data->DrawLinesX1 = draw_lines ? (x1 + g.FontSize * 0.5f + g.Style.FramePadding.x) : +FLT_MAX;
|
||||||
|
tree_node_data->DrawLinesTableColumn = (draw_lines && g.CurrentTable) ? (ImGuiTableColumnIdx)g.CurrentTable->CurrentColumn : -1;
|
||||||
|
tree_node_data->DrawLinesToNodesY2 = -FLT_MAX;
|
||||||
window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
|
window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
|
||||||
|
if (flags & ImGuiTreeNodeFlags_DrawLinesToNodes)
|
||||||
|
window->DC.TreeRecordsClippedNodesY2Mask |= (1 << window->DC.TreeDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When using public API, currently 'id == storage_id' is always true, but we separate the values to facilitate advanced user code doing storage queries outside of UI loop.
|
// When using public API, currently 'id == storage_id' is always true, but we separate the values to facilitate advanced user code doing storage queries outside of UI loop.
|
||||||
|
|
@ -6635,14 +6703,18 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
|
||||||
g.LastItemData.DisplayRect = frame_bb;
|
g.LastItemData.DisplayRect = frame_bb;
|
||||||
|
|
||||||
// If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled:
|
// If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsToParent enabled:
|
||||||
// Store data for the current depth to allow returning to this node from any child item.
|
// Store data for the current depth to allow returning to this node from any child item.
|
||||||
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
||||||
// It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle.
|
// It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsToParent by default or move it to ImGuiStyle.
|
||||||
bool store_tree_node_stack_data = false;
|
bool store_tree_node_stack_data = false;
|
||||||
|
if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0)
|
||||||
|
flags |= g.Style.TreeLinesFlags;
|
||||||
|
const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y) && (g.Style.TreeLinesSize > 0.0f);
|
||||||
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
if (!(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||||
{
|
{
|
||||||
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && is_open && !g.NavIdIsAlive)
|
store_tree_node_stack_data = draw_tree_lines;
|
||||||
|
if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsToParent) && !g.NavIdIsAlive)
|
||||||
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||||
store_tree_node_stack_data = true;
|
store_tree_node_stack_data = true;
|
||||||
}
|
}
|
||||||
|
|
@ -6650,8 +6722,15 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||||
if (!is_visible)
|
if (!is_visible)
|
||||||
{
|
{
|
||||||
if (store_tree_node_stack_data && is_open)
|
if ((flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeRecordsClippedNodesY2Mask & (1 << (window->DC.TreeDepth - 1))))
|
||||||
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
{
|
||||||
|
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||||
|
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway.
|
||||||
|
if (frame_bb.Min.y >= window->ClipRect.Max.y)
|
||||||
|
window->DC.TreeRecordsClippedNodesY2Mask &= ~(1 << (window->DC.TreeDepth - 1)); // Done
|
||||||
|
}
|
||||||
|
if (is_open && store_tree_node_stack_data)
|
||||||
|
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
|
||||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||||
TreePushOverrideID(id);
|
TreePushOverrideID(id);
|
||||||
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||||
|
|
@ -6697,6 +6776,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
|
button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
|
||||||
else
|
else
|
||||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||||
|
if (flags & ImGuiTreeNodeFlags_NoNavFocus)
|
||||||
|
button_flags |= ImGuiButtonFlags_NoNavFocus;
|
||||||
|
|
||||||
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
|
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
|
||||||
const bool was_selected = selected;
|
const bool was_selected = selected;
|
||||||
|
|
@ -6783,6 +6864,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
||||||
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
||||||
|
if (span_all_columns && !span_all_columns_label)
|
||||||
|
TablePopBackgroundChannel();
|
||||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
|
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||||
else if (!is_leaf)
|
else if (!is_leaf)
|
||||||
|
|
@ -6803,6 +6886,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
||||||
}
|
}
|
||||||
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
|
||||||
|
if (span_all_columns && !span_all_columns_label)
|
||||||
|
TablePopBackgroundChannel();
|
||||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||||
else if (!is_leaf)
|
else if (!is_leaf)
|
||||||
|
|
@ -6811,8 +6896,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
LogSetNextTextDecoration(">", NULL);
|
LogSetNextTextDecoration(">", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (span_all_columns && !span_all_columns_label)
|
if (draw_tree_lines)
|
||||||
TablePopBackgroundChannel();
|
TreeNodeDrawLineToChildNode(ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.5f));
|
||||||
|
|
||||||
// Label
|
// Label
|
||||||
if (display_frame)
|
if (display_frame)
|
||||||
|
|
@ -6824,8 +6909,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
TablePopBackgroundChannel();
|
TablePopBackgroundChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (store_tree_node_stack_data && is_open)
|
if (is_open && store_tree_node_stack_data)
|
||||||
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()
|
||||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||||
TreePushOverrideID(id); // Could use TreePush(label) but this avoid computing twice
|
TreePushOverrideID(id); // Could use TreePush(label) but this avoid computing twice
|
||||||
|
|
||||||
|
|
@ -6833,6 +6918,64 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||||
return is_open;
|
return is_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw horizontal line from our parent node
|
||||||
|
// This is only called for visible child nodes so we are not too fussy anymore about performances
|
||||||
|
void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
if (window->DC.TreeDepth == 0 || (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||||
|
float x1 = ImTrunc(parent_data->DrawLinesX1);
|
||||||
|
float x2 = ImTrunc(target_pos.x - g.Style.ItemInnerSpacing.x);
|
||||||
|
float y = ImTrunc(target_pos.y);
|
||||||
|
float rounding = (g.Style.TreeLinesRounding > 0.0f) ? ImMin(x2 - x1, g.Style.TreeLinesRounding) : 0.0f;
|
||||||
|
parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, y - rounding);
|
||||||
|
if (x1 >= x2)
|
||||||
|
return;
|
||||||
|
if (rounding > 0.0f)
|
||||||
|
{
|
||||||
|
x1 += 0.5f + rounding;
|
||||||
|
window->DrawList->PathArcToFast(ImVec2(x1, y - rounding), rounding, 6, 3);
|
||||||
|
if (x1 < x2)
|
||||||
|
window->DrawList->PathLineTo(ImVec2(x2, y));
|
||||||
|
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), ImDrawFlags_None, g.Style.TreeLinesSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw vertical line of the hierarchy
|
||||||
|
void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
float y1 = ImMax(data->NavRect.Max.y, window->ClipRect.Min.y);
|
||||||
|
float y2 = data->DrawLinesToNodesY2;
|
||||||
|
if (data->TreeFlags & ImGuiTreeNodeFlags_DrawLinesFull)
|
||||||
|
{
|
||||||
|
float y2_full = window->DC.CursorPos.y;
|
||||||
|
if (g.CurrentTable)
|
||||||
|
y2_full = ImMax(g.CurrentTable->RowPosY2, y2_full);
|
||||||
|
y2_full = ImTrunc(y2_full - g.Style.ItemSpacing.y - g.FontSize * 0.5f);
|
||||||
|
if (y2 + (g.Style.ItemSpacing.y + g.Style.TreeLinesRounding) < y2_full) // FIXME: threshold to use ToNodes Y2 instead of Full Y2 when close by ItemSpacing.y
|
||||||
|
y2 = y2_full;
|
||||||
|
}
|
||||||
|
y2 = ImMin(y2, window->ClipRect.Max.y);
|
||||||
|
if (y2 <= y1)
|
||||||
|
return;
|
||||||
|
float x = ImTrunc(data->DrawLinesX1);
|
||||||
|
if (data->DrawLinesTableColumn != -1)
|
||||||
|
TablePushColumnChannel(data->DrawLinesTableColumn);
|
||||||
|
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||||
|
if (data->DrawLinesTableColumn != -1)
|
||||||
|
TablePopColumnChannel();
|
||||||
|
}
|
||||||
|
|
||||||
void ImGui::TreePush(const char* str_id)
|
void ImGui::TreePush(const char* str_id)
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
@ -6867,18 +7010,23 @@ void ImGui::TreePop()
|
||||||
window->DC.TreeDepth--;
|
window->DC.TreeDepth--;
|
||||||
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
|
ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
|
||||||
|
|
||||||
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask) // Only set during request
|
if (window->DC.TreeHasStackDataDepthMask & tree_depth_mask)
|
||||||
{
|
{
|
||||||
ImGuiTreeNodeStackData* data = &g.TreeNodeStack.back();
|
const ImGuiTreeNodeStackData* data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1];
|
||||||
IM_ASSERT(data->ID == window->IDStack.back());
|
IM_ASSERT(data->ID == window->IDStack.back());
|
||||||
if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere)
|
|
||||||
{
|
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsToParent is enabled)
|
||||||
// Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
|
if (data->TreeFlags & ImGuiTreeNodeFlags_NavLeftJumpsToParent)
|
||||||
if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
|
||||||
NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data);
|
NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data);
|
||||||
}
|
|
||||||
|
// Draw hierarchy lines
|
||||||
|
if (data->DrawLinesX1 != +FLT_MAX && window->DC.CursorPos.y >= window->ClipRect.Min.y)
|
||||||
|
TreeNodeDrawLineToTreePop(data);
|
||||||
|
|
||||||
g.TreeNodeStack.pop_back();
|
g.TreeNodeStack.pop_back();
|
||||||
window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask;
|
window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask;
|
||||||
|
window->DC.TreeRecordsClippedNodesY2Mask &= ~tree_depth_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
|
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
|
||||||
|
|
@ -7493,7 +7641,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
|
||||||
ImRect box_select_r = bs->BoxSelectRectCurr;
|
ImRect box_select_r = bs->BoxSelectRectCurr;
|
||||||
box_select_r.ClipWith(scope_rect);
|
box_select_r.ClipWith(scope_rect);
|
||||||
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||||
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT: Styling
|
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||||
|
|
||||||
// Scroll
|
// Scroll
|
||||||
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
|
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
|
||||||
|
|
@ -7697,7 +7845,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||||
if (ms->IsFocused)
|
if (ms->IsFocused)
|
||||||
{
|
{
|
||||||
// We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here.
|
// We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here.
|
||||||
if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at begining of the scope (see tests for easy failure)
|
if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at beginning of the scope (see tests for easy failure)
|
||||||
{
|
{
|
||||||
IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId.
|
IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId.
|
||||||
storage->RangeSrcItem = ImGuiSelectionUserData_Invalid;
|
storage->RangeSrcItem = ImGuiSelectionUserData_Invalid;
|
||||||
|
|
@ -8783,7 +8931,6 @@ bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, Im
|
||||||
}
|
}
|
||||||
|
|
||||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
|
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
|
||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
SetNextWindowViewport(viewport->ID); // Enforce viewport so we don't create our own viewport when ImGuiConfigFlags_ViewportsNoMerge is set.
|
SetNextWindowViewport(viewport->ID); // Enforce viewport so we don't create our own viewport when ImGuiConfigFlags_ViewportsNoMerge is set.
|
||||||
PushStyleColor(ImGuiCol_WindowShadow, ImVec4(0, 0, 0, 0));
|
PushStyleColor(ImGuiCol_WindowShadow, ImVec4(0, 0, 0, 0));
|
||||||
|
|
@ -10505,13 +10652,12 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Render text label (with clipping + alpha gradient) + unsaved marker
|
// Render text label (with clipping + alpha gradient) + unsaved marker
|
||||||
ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
|
ImRect text_ellipsis_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
|
||||||
ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
|
|
||||||
|
|
||||||
// Return clipped state ignoring the close button
|
// Return clipped state ignoring the close button
|
||||||
if (out_text_clipped)
|
if (out_text_clipped)
|
||||||
{
|
{
|
||||||
*out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x;
|
*out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_ellipsis_clip_bb.Max.x;
|
||||||
//draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255));
|
//draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -10557,15 +10703,22 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||||
// This is all rather complicated
|
// This is all rather complicated
|
||||||
// (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position)
|
// (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position)
|
||||||
// FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist..
|
// FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist..
|
||||||
float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;
|
float ellipsis_max_x = text_ellipsis_clip_bb.Max.x;
|
||||||
if (close_button_visible || unsaved_marker_visible)
|
if (close_button_visible || unsaved_marker_visible)
|
||||||
{
|
{
|
||||||
text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f);
|
const bool visible_without_hover = unsaved_marker_visible || (is_contents_visible ? g.Style.TabCloseButtonMinWidthSelected : g.Style.TabCloseButtonMinWidthUnselected) < 0.0f;
|
||||||
text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;
|
if (visible_without_hover)
|
||||||
ellipsis_max_x = text_pixel_clip_bb.Max.x;
|
{
|
||||||
|
text_ellipsis_clip_bb.Max.x -= button_sz * 0.90f;
|
||||||
|
ellipsis_max_x -= button_sz * 0.90f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text_ellipsis_clip_bb.Max.x -= button_sz * 1.00f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LogSetNextTextDecoration("/", "\\");
|
LogSetNextTextDecoration("/", "\\");
|
||||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
|
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, NULL, &label_size);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (!is_contents_visible)
|
if (!is_contents_visible)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -354,7 +354,7 @@ void ImDrawListGrowChannels(ImDrawList* draw_list, const int num_channels)
|
||||||
{
|
{
|
||||||
ImDrawCmd draw_cmd;
|
ImDrawCmd draw_cmd;
|
||||||
draw_cmd.ClipRect = draw_list->_ClipRectStack.back();
|
draw_cmd.ClipRect = draw_list->_ClipRectStack.back();
|
||||||
draw_cmd.TextureId = draw_list->_TextureIdStack.back();
|
draw_cmd.TexRef = draw_list->_TextureStack.back();
|
||||||
channel._CmdBuffer.push_back(draw_cmd);
|
channel._CmdBuffer.push_back(draw_cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -912,7 +912,11 @@ IMPLOT_TMP void PlotDigital(const char* label_id, const T* xs, const T* ys, int
|
||||||
IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0);
|
IMPLOT_API void PlotDigitalG(const char* label_id, ImPlotGetter getter, void* data, int count, ImPlotDigitalFlags flags=0);
|
||||||
|
|
||||||
// Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down).
|
// Plots an axis-aligned image. #bounds_min/bounds_max are in plot coordinates (y-up) and #uv0/uv1 are in texture coordinates (y-down).
|
||||||
IMPLOT_API void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0);
|
#ifdef IMGUI_HAS_TEXTURES
|
||||||
|
IMPLOT_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), ImPlotImageFlags flags = 0);
|
||||||
|
#else
|
||||||
|
IMPLOT_API void PlotImage(const char* label_id, ImTextureID tex_ref, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, const ImVec2& uv0=ImVec2(0,0), const ImVec2& uv1=ImVec2(1,1), const ImVec4& tint_col=ImVec4(1,1,1,1), ImPlotImageFlags flags=0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Plots a centered text label at point x,y with an optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...).
|
// Plots a centered text label at point x,y with an optional pixel offset. Text color can be changed with ImPlot::PushStyleColor(ImPlotCol_InlayText, ...).
|
||||||
IMPLOT_API void PlotText(const char* text, double x, double y, const ImVec2& pix_offset=ImVec2(0,0), ImPlotTextFlags flags=0);
|
IMPLOT_API void PlotText(const char* text, double x, double y, const ImVec2& pix_offset=ImVec2(0,0), ImPlotTextFlags flags=0);
|
||||||
|
|
|
||||||
|
|
@ -339,11 +339,18 @@ void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char *te
|
||||||
if (!text_end)
|
if (!text_end)
|
||||||
text_end = text_begin + strlen(text_begin);
|
text_end = text_begin + strlen(text_begin);
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
|
||||||
|
#ifdef IMGUI_HAS_TEXTURES
|
||||||
|
ImFontBaked* font = g.Font->GetFontBaked(g.FontSize);
|
||||||
|
const float scale = g.FontSize / font->Size;
|
||||||
|
#else
|
||||||
ImFont* font = g.Font;
|
ImFont* font = g.Font;
|
||||||
|
const float scale = g.FontSize / font->FontSize;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Align to be pixel perfect
|
// Align to be pixel perfect
|
||||||
pos.x = ImFloor(pos.x);
|
pos.x = ImFloor(pos.x);
|
||||||
pos.y = ImFloor(pos.y);
|
pos.y = ImFloor(pos.y);
|
||||||
const float scale = g.FontSize / font->FontSize;
|
|
||||||
const char* s = text_begin;
|
const char* s = text_begin;
|
||||||
int chars_exp = (int)(text_end - s);
|
int chars_exp = (int)(text_end - s);
|
||||||
int chars_rnd = 0;
|
int chars_rnd = 0;
|
||||||
|
|
@ -3064,7 +3071,11 @@ void EndPlot() {
|
||||||
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.Items.ID);
|
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.Items.ID);
|
||||||
if (IO.MouseWheel != 0.0f) {
|
if (IO.MouseWheel != 0.0f) {
|
||||||
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
|
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
|
||||||
|
#if IMGUI_VERSION_NUM < 19172
|
||||||
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
|
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
|
||||||
|
#else
|
||||||
|
float font_size = ImGui::GetCurrentWindow()->FontRefSize;
|
||||||
|
#endif
|
||||||
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
|
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
|
||||||
legend.Scroll.x += scroll_step * IO.MouseWheel;
|
legend.Scroll.x += scroll_step * IO.MouseWheel;
|
||||||
legend.Scroll.y += scroll_step * IO.MouseWheel;
|
legend.Scroll.y += scroll_step * IO.MouseWheel;
|
||||||
|
|
@ -3583,7 +3594,11 @@ void EndSubplots() {
|
||||||
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, subplot.Items.ID);
|
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, subplot.Items.ID);
|
||||||
if (IO.MouseWheel != 0.0f) {
|
if (IO.MouseWheel != 0.0f) {
|
||||||
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
|
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
|
||||||
|
#if IMGUI_VERSION_NUM < 19172
|
||||||
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
|
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
|
||||||
|
#else
|
||||||
|
float font_size = ImGui::GetCurrentWindow()->FontRefSize;
|
||||||
|
#endif
|
||||||
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
|
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
|
||||||
legend.Scroll.x += scroll_step * IO.MouseWheel;
|
legend.Scroll.x += scroll_step * IO.MouseWheel;
|
||||||
legend.Scroll.y += scroll_step * IO.MouseWheel;
|
legend.Scroll.y += scroll_step * IO.MouseWheel;
|
||||||
|
|
|
||||||
|
|
@ -867,7 +867,14 @@ void Demo_Images() {
|
||||||
ImGui::SliderFloat2("UV1", &uv1.x, -2, 2, "%.1f");
|
ImGui::SliderFloat2("UV1", &uv1.x, -2, 2, "%.1f");
|
||||||
ImGui::ColorEdit4("Tint",&tint.x);
|
ImGui::ColorEdit4("Tint",&tint.x);
|
||||||
if (ImPlot::BeginPlot("##image")) {
|
if (ImPlot::BeginPlot("##image")) {
|
||||||
ImPlot::PlotImage("my image",ImGui::GetIO().Fonts->TexID, bmin, bmax, uv0, uv1, tint);
|
#ifdef IMGUI_HAS_TEXTURES
|
||||||
|
// We use the font atlas ImTextureRef for this demo, but in your real code when you submit
|
||||||
|
// an image that you have loaded yourself, you would normally have a ImTextureID which works
|
||||||
|
// just as well (as ImTextureRef can be constructed from ImTextureID).
|
||||||
|
ImPlot::PlotImage("my image", ImGui::GetIO().Fonts->TexRef, bmin, bmax, uv0, uv1, tint);
|
||||||
|
#else
|
||||||
|
ImPlot::PlotImage("my image", ImGui::GetIO().Fonts->TexID, bmin, bmax, uv0, uv1, tint);
|
||||||
|
#endif
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2750,15 +2750,19 @@ void PlotDigitalG(const char* label_id, ImPlotGetter getter_func, void* data, in
|
||||||
// [SECTION] PlotImage
|
// [SECTION] PlotImage
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) {
|
#ifdef IMGUI_HAS_TEXTURES
|
||||||
if (BeginItemEx(label_id, FitterRect(bmin,bmax))) {
|
void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) {
|
||||||
|
#else
|
||||||
|
void PlotImage(const char* label_id, ImTextureID tex_ref, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) {
|
||||||
|
#endif
|
||||||
|
if (BeginItemEx(label_id, FitterRect(bmin,bmax))) {
|
||||||
ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col);
|
ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col);
|
||||||
GetCurrentItem()->Color = tint_col32;
|
GetCurrentItem()->Color = tint_col32;
|
||||||
ImDrawList& draw_list = *GetPlotDrawList();
|
ImDrawList& draw_list = *GetPlotDrawList();
|
||||||
ImVec2 p1 = PlotToPixels(bmin.x, bmax.y,IMPLOT_AUTO,IMPLOT_AUTO);
|
ImVec2 p1 = PlotToPixels(bmin.x, bmax.y,IMPLOT_AUTO,IMPLOT_AUTO);
|
||||||
ImVec2 p2 = PlotToPixels(bmax.x, bmin.y,IMPLOT_AUTO,IMPLOT_AUTO);
|
ImVec2 p2 = PlotToPixels(bmax.x, bmin.y,IMPLOT_AUTO,IMPLOT_AUTO);
|
||||||
PushPlotClipRect();
|
PushPlotClipRect();
|
||||||
draw_list.AddImage(user_texture_id, p1, p2, uv0, uv1, tint_col32);
|
draw_list.AddImage(tex_ref, p1, p2, uv0, uv1, tint_col32);
|
||||||
PopPlotClipRect();
|
PopPlotClipRect();
|
||||||
EndItem();
|
EndItem();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// ImPlot3D v0.1
|
// ImPlot3D v0.3 WIP
|
||||||
// implot3d.h
|
// implot3d.h
|
||||||
// Date: 2024-11-16
|
// Date: 2024-11-16
|
||||||
// Author: Breno Cunha Queiroz (brenocq.com)
|
// Author: Breno Cunha Queiroz (brenocq.com)
|
||||||
|
|
@ -45,7 +45,8 @@
|
||||||
#define IMPLOT3D_API
|
#define IMPLOT3D_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IMPLOT3D_VERSION "0.1" // ImPlot3D version
|
#define IMPLOT3D_VERSION "0.3 WIP" // ImPlot3D version
|
||||||
|
#define IMPLOT3D_VERSION_NUM 300 // Integer encoded version
|
||||||
#define IMPLOT3D_AUTO -1 // Deduce variable automatically
|
#define IMPLOT3D_AUTO -1 // Deduce variable automatically
|
||||||
#define IMPLOT3D_AUTO_COL ImVec4(0, 0, 0, -1) // Deduce color automatically
|
#define IMPLOT3D_AUTO_COL ImVec4(0, 0, 0, -1) // Deduce color automatically
|
||||||
#define IMPLOT3D_TMP template <typename T> IMPLOT3D_API
|
#define IMPLOT3D_TMP template <typename T> IMPLOT3D_API
|
||||||
|
|
@ -83,9 +84,16 @@ typedef int ImPlot3DTriangleFlags; // -> ImPlot3DTriangleFlags_ // Flags: Triang
|
||||||
typedef int ImPlot3DQuadFlags; // -> ImPlot3DQuadFlags_ // Flags: QuadFplot flags
|
typedef int ImPlot3DQuadFlags; // -> ImPlot3DQuadFlags_ // Flags: QuadFplot flags
|
||||||
typedef int ImPlot3DSurfaceFlags; // -> ImPlot3DSurfaceFlags_ // Flags: Surface plot flags
|
typedef int ImPlot3DSurfaceFlags; // -> ImPlot3DSurfaceFlags_ // Flags: Surface plot flags
|
||||||
typedef int ImPlot3DMeshFlags; // -> ImPlot3DMeshFlags_ // Flags: Mesh plot flags
|
typedef int ImPlot3DMeshFlags; // -> ImPlot3DMeshFlags_ // Flags: Mesh plot flags
|
||||||
|
typedef int ImPlot3DImageFlags; // -> ImPlot3DImageFlags_ // Flags: Image plot flags
|
||||||
typedef int ImPlot3DLegendFlags; // -> ImPlot3DLegendFlags_ // Flags: Legend flags
|
typedef int ImPlot3DLegendFlags; // -> ImPlot3DLegendFlags_ // Flags: Legend flags
|
||||||
typedef int ImPlot3DAxisFlags; // -> ImPlot3DAxisFlags_ // Flags: Axis flags
|
typedef int ImPlot3DAxisFlags; // -> ImPlot3DAxisFlags_ // Flags: Axis flags
|
||||||
|
|
||||||
|
// Fallback for ImGui versions before v1.92: define ImTextureRef as ImTextureID
|
||||||
|
// You can `#define IMPLOT3D_NO_IMTEXTUREREF` to avoid this fallback
|
||||||
|
#if !defined(IMGUI_HAS_TEXTURES) && !defined(IMPLOT3D_NO_IMTEXTUREREF)
|
||||||
|
typedef ImTextureID ImTextureRef;
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Flags & Enumerations
|
// [SECTION] Flags & Enumerations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -195,6 +203,9 @@ enum ImPlot3DTriangleFlags_ {
|
||||||
ImPlot3DTriangleFlags_None = 0, // Default
|
ImPlot3DTriangleFlags_None = 0, // Default
|
||||||
ImPlot3DTriangleFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
ImPlot3DTriangleFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
||||||
ImPlot3DTriangleFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
ImPlot3DTriangleFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
||||||
|
ImPlot3DTriangleFlags_NoLines = 1 << 10, // No lines will be rendered
|
||||||
|
ImPlot3DTriangleFlags_NoFill = 1 << 11, // No fill will be rendered
|
||||||
|
ImPlot3DTriangleFlags_NoMarkers = 1 << 12, // No markers will be rendered
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for PlotQuad
|
// Flags for PlotQuad
|
||||||
|
|
@ -202,6 +213,9 @@ enum ImPlot3DQuadFlags_ {
|
||||||
ImPlot3DQuadFlags_None = 0, // Default
|
ImPlot3DQuadFlags_None = 0, // Default
|
||||||
ImPlot3DQuadFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
ImPlot3DQuadFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
||||||
ImPlot3DQuadFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
ImPlot3DQuadFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
||||||
|
ImPlot3DQuadFlags_NoLines = 1 << 10, // No lines will be rendered
|
||||||
|
ImPlot3DQuadFlags_NoFill = 1 << 11, // No fill will be rendered
|
||||||
|
ImPlot3DQuadFlags_NoMarkers = 1 << 12, // No markers will be rendered
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for PlotSurface
|
// Flags for PlotSurface
|
||||||
|
|
@ -209,6 +223,9 @@ enum ImPlot3DSurfaceFlags_ {
|
||||||
ImPlot3DSurfaceFlags_None = 0, // Default
|
ImPlot3DSurfaceFlags_None = 0, // Default
|
||||||
ImPlot3DSurfaceFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
ImPlot3DSurfaceFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
||||||
ImPlot3DSurfaceFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
ImPlot3DSurfaceFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
||||||
|
ImPlot3DSurfaceFlags_NoLines = 1 << 10, // No lines will be rendered
|
||||||
|
ImPlot3DSurfaceFlags_NoFill = 1 << 11, // No fill will be rendered
|
||||||
|
ImPlot3DSurfaceFlags_NoMarkers = 1 << 12, // No markers will be rendered
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for PlotMesh
|
// Flags for PlotMesh
|
||||||
|
|
@ -216,6 +233,16 @@ enum ImPlot3DMeshFlags_ {
|
||||||
ImPlot3DMeshFlags_None = 0, // Default
|
ImPlot3DMeshFlags_None = 0, // Default
|
||||||
ImPlot3DMeshFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
ImPlot3DMeshFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
||||||
ImPlot3DMeshFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
ImPlot3DMeshFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
||||||
|
ImPlot3DMeshFlags_NoLines = 1 << 10, // No lines will be rendered
|
||||||
|
ImPlot3DMeshFlags_NoFill = 1 << 11, // No fill will be rendered
|
||||||
|
ImPlot3DMeshFlags_NoMarkers = 1 << 12, // No markers will be rendered
|
||||||
|
};
|
||||||
|
|
||||||
|
// Flags for PlotImage
|
||||||
|
enum ImPlot3DImageFlags_ {
|
||||||
|
ImPlot3DImageFlags_None = 0, // Default
|
||||||
|
ImPlot3DImageFlags_NoLegend = ImPlot3DItemFlags_NoLegend,
|
||||||
|
ImPlot3DImageFlags_NoFit = ImPlot3DItemFlags_NoFit,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for legends
|
// Flags for legends
|
||||||
|
|
@ -250,6 +277,7 @@ enum ImPlot3DAxisFlags_ {
|
||||||
ImPlot3DAxisFlags_LockMax = 1 << 5, // The axis maximum value will be locked when panning/zooming
|
ImPlot3DAxisFlags_LockMax = 1 << 5, // The axis maximum value will be locked when panning/zooming
|
||||||
ImPlot3DAxisFlags_AutoFit = 1 << 6, // Axis will be auto-fitting to data extents
|
ImPlot3DAxisFlags_AutoFit = 1 << 6, // Axis will be auto-fitting to data extents
|
||||||
ImPlot3DAxisFlags_Invert = 1 << 7, // The axis will be inverted
|
ImPlot3DAxisFlags_Invert = 1 << 7, // The axis will be inverted
|
||||||
|
ImPlot3DAxisFlags_PanStretch = 1 << 8, // Panning in a locked or constrained state will cause the axis to stretch if possible
|
||||||
ImPlot3DAxisFlags_Lock = ImPlot3DAxisFlags_LockMin | ImPlot3DAxisFlags_LockMax,
|
ImPlot3DAxisFlags_Lock = ImPlot3DAxisFlags_LockMin | ImPlot3DAxisFlags_LockMax,
|
||||||
ImPlot3DAxisFlags_NoDecorations = ImPlot3DAxisFlags_NoLabel | ImPlot3DAxisFlags_NoGridLines | ImPlot3DAxisFlags_NoTickLabels,
|
ImPlot3DAxisFlags_NoDecorations = ImPlot3DAxisFlags_NoLabel | ImPlot3DAxisFlags_NoGridLines | ImPlot3DAxisFlags_NoTickLabels,
|
||||||
};
|
};
|
||||||
|
|
@ -362,21 +390,44 @@ IMPLOT3D_API void SetupAxis(ImAxis3D axis, const char* label = nullptr, ImPlot3D
|
||||||
|
|
||||||
IMPLOT3D_API void SetupAxisLimits(ImAxis3D axis, double v_min, double v_max, ImPlot3DCond cond = ImPlot3DCond_Once);
|
IMPLOT3D_API void SetupAxisLimits(ImAxis3D axis, double v_min, double v_max, ImPlot3DCond cond = ImPlot3DCond_Once);
|
||||||
|
|
||||||
IMPLOT3D_API void SetupAxisFormat(ImAxis3D idx, ImPlot3DFormatter formatter, void* data = nullptr);
|
IMPLOT3D_API void SetupAxisFormat(ImAxis3D axis, ImPlot3DFormatter formatter, void* data = nullptr);
|
||||||
|
|
||||||
// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true
|
// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true
|
||||||
IMPLOT3D_API void SetupAxisTicks(ImAxis3D axis, const double* values, int n_ticks, const char* const labels[] = nullptr, bool keep_default = false);
|
IMPLOT3D_API void SetupAxisTicks(ImAxis3D axis, const double* values, int n_ticks, const char* const labels[] = nullptr, bool keep_default = false);
|
||||||
|
|
||||||
// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true
|
// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true
|
||||||
IMPLOT3D_API void SetupAxisTicks(ImAxis3D axis, double v_min, double v_max, int n_ticks, const char* const labels[] = nullptr, bool keep_default = false);
|
IMPLOT3D_API void SetupAxisTicks(ImAxis3D axis, double v_min, double v_max, int n_ticks, const char* const labels[] = nullptr,
|
||||||
|
bool keep_default = false);
|
||||||
|
|
||||||
|
// Sets an axis' limits constraints
|
||||||
|
IMPLOT3D_API void SetupAxisLimitsConstraints(ImAxis3D axis, double v_min, double v_max);
|
||||||
|
|
||||||
|
// Sets an axis' zoom constraints
|
||||||
|
IMPLOT3D_API void SetupAxisZoomConstraints(ImAxis3D axis, double z_min, double z_max);
|
||||||
|
|
||||||
// Sets the label and/or flags for primary X/Y/Z axes (shorthand for three calls to SetupAxis)
|
// Sets the label and/or flags for primary X/Y/Z axes (shorthand for three calls to SetupAxis)
|
||||||
IMPLOT3D_API void SetupAxes(const char* x_label, const char* y_label, const char* z_label, ImPlot3DAxisFlags x_flags = 0, ImPlot3DAxisFlags y_flags = 0, ImPlot3DAxisFlags z_flags = 0);
|
IMPLOT3D_API void SetupAxes(const char* x_label, const char* y_label, const char* z_label, ImPlot3DAxisFlags x_flags = 0,
|
||||||
|
ImPlot3DAxisFlags y_flags = 0, ImPlot3DAxisFlags z_flags = 0);
|
||||||
|
|
||||||
// Sets the X/Y/Z axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits)
|
// Sets the X/Y/Z axes range limits. If ImPlot3DCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits)
|
||||||
IMPLOT3D_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, double z_min, double z_max, ImPlot3DCond cond = ImPlot3DCond_Once);
|
IMPLOT3D_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, double z_min, double z_max,
|
||||||
|
ImPlot3DCond cond = ImPlot3DCond_Once);
|
||||||
|
|
||||||
// Sets the plot box X/Y/Z scale. A scale of 1.0 is the default. Values greater than 1.0 enlarge the plot, while values between 0.0 and 1.0 shrink it.
|
// Sets the plot box rotation given the elevation and azimuth angles in degrees. If ImPlot3DCond_Always is used, the rotation will be locked
|
||||||
|
IMPLOT3D_API void SetupBoxRotation(float elevation, float azimuth, bool animate = false, ImPlot3DCond cond = ImPlot3DCond_Once);
|
||||||
|
|
||||||
|
// Sets the plot box rotation given a quaternion. If ImPlot3DCond_Always is used, the rotation will be locked
|
||||||
|
IMPLOT3D_API void SetupBoxRotation(ImPlot3DQuat rotation, bool animate = false, ImPlot3DCond cond = ImPlot3DCond_Once);
|
||||||
|
|
||||||
|
// Sets the plot box initial rotation given the elevation and azimuth angles in degrees. The initial rotation is the rotation the plot goes back to
|
||||||
|
// when a left mouse button double click happens
|
||||||
|
IMPLOT3D_API void SetupBoxInitialRotation(float elevation, float azimuth);
|
||||||
|
|
||||||
|
// Sets the plot box initial rotation given a quaternion. The initial rotation is the rotation the plot goes back to when a left mouse button double
|
||||||
|
// click happens
|
||||||
|
IMPLOT3D_API void SetupBoxInitialRotation(ImPlot3DQuat rotation);
|
||||||
|
|
||||||
|
// Sets the plot box X/Y/Z scale. A scale of 1.0 is the default. Values greater than 1.0 enlarge the plot, while values between 0.0 and 1.0 shrink it
|
||||||
IMPLOT3D_API void SetupBoxScale(float x, float y, float z);
|
IMPLOT3D_API void SetupBoxScale(float x, float y, float z);
|
||||||
|
|
||||||
IMPLOT3D_API void SetupLegend(ImPlot3DLocation location, ImPlot3DLegendFlags flags = 0);
|
IMPLOT3D_API void SetupLegend(ImPlot3DLocation location, ImPlot3DLegendFlags flags = 0);
|
||||||
|
|
@ -385,18 +436,46 @@ IMPLOT3D_API void SetupLegend(ImPlot3DLocation location, ImPlot3DLegendFlags fla
|
||||||
// [SECTION] Plot Items
|
// [SECTION] Plot Items
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
IMPLOT3D_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags = 0, int offset = 0, int stride = sizeof(T));
|
IMPLOT3D_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags = 0, int offset = 0,
|
||||||
|
int stride = sizeof(T));
|
||||||
|
|
||||||
IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags = 0, int offset = 0, int stride = sizeof(T));
|
IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags = 0, int offset = 0,
|
||||||
|
int stride = sizeof(T));
|
||||||
|
|
||||||
IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags = 0, int offset = 0, int stride = sizeof(T));
|
IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags = 0,
|
||||||
|
int offset = 0, int stride = sizeof(T));
|
||||||
|
|
||||||
IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags = 0, int offset = 0, int stride = sizeof(T));
|
IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags = 0, int offset = 0,
|
||||||
|
int stride = sizeof(T));
|
||||||
|
|
||||||
// Plot the surface defined by a grid of vertices. The grid is defined by the x and y arrays, and the z array contains the height of each vertex. A total of x_count * y_count vertices are expected for each array. Leave #scale_min and #scale_max both at 0 for automatic color scaling, or set them to a predefined range.
|
// Plot the surface defined by a grid of vertices. The grid is defined by the x and y arrays, and the z array contains the height of each vertex. A
|
||||||
IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min = 0.0, double scale_max = 0.0, ImPlot3DSurfaceFlags flags = 0, int offset = 0, int stride = sizeof(T));
|
// total of x_count * y_count vertices are expected for each array. Leave #scale_min and #scale_max both at 0 for automatic color scaling, or set them
|
||||||
|
// to a predefined range
|
||||||
|
IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min = 0.0,
|
||||||
|
double scale_max = 0.0, ImPlot3DSurfaceFlags flags = 0, int offset = 0, int stride = sizeof(T));
|
||||||
|
|
||||||
IMPLOT3D_API void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, ImPlot3DMeshFlags flags = 0);
|
IMPLOT3D_API void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count,
|
||||||
|
ImPlot3DMeshFlags flags = 0);
|
||||||
|
|
||||||
|
// Plots a rectangular image in 3D defined by its center and two direction vectors (axes).
|
||||||
|
// #center is the center of the rectangle in plot coordinates.
|
||||||
|
// #axis_u and #axis_v define the local axes and half-extents of the rectangle in 3D space.
|
||||||
|
// The rectangle is formed by moving from the center along ±axis_u and ±axis_v.
|
||||||
|
// #uv0 and #uv1 define the texture mapping.
|
||||||
|
// #tint_col can be used to tint the image.
|
||||||
|
IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& center, const ImPlot3DPoint& axis_u,
|
||||||
|
const ImPlot3DPoint& axis_v, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1),
|
||||||
|
const ImVec4& tint_col = ImVec4(1, 1, 1, 1), ImPlot3DImageFlags flags = 0);
|
||||||
|
|
||||||
|
// Plots an image using four arbitrary 3D points that define a quad in space.
|
||||||
|
// Each corner (p0 to p3) corresponds to a corner in the image, and #uv0 to #uv3 are the texture coordinates for each.
|
||||||
|
// This overload allows full control over orientation, shape, and distortion.
|
||||||
|
// Note: The quad is internally split into two triangles, so non-rectangular quads may produce rendering artifacts
|
||||||
|
// since distortion is interpolated per triangle rather than over the full quad.
|
||||||
|
IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& p0, const ImPlot3DPoint& p1, const ImPlot3DPoint& p2,
|
||||||
|
const ImPlot3DPoint& p3, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 0),
|
||||||
|
const ImVec2& uv2 = ImVec2(1, 1), const ImVec2& uv3 = ImVec2(0, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1),
|
||||||
|
ImPlot3DImageFlags flags = 0);
|
||||||
|
|
||||||
// Plots a centered text label at point x,y,z. It is possible to set the text angle in radians and offset in pixels
|
// Plots a centered text label at point x,y,z. It is possible to set the text angle in radians and offset in pixels
|
||||||
IMPLOT3D_API void PlotText(const char* text, float x, float y, float z, float angle = 0.0f, const ImVec2& pix_offset = ImVec2(0, 0));
|
IMPLOT3D_API void PlotText(const char* text, float x, float y, float z, float angle = 0.0f, const ImVec2& pix_offset = ImVec2(0, 0));
|
||||||
|
|
@ -430,6 +509,7 @@ IMPLOT3D_API ImDrawList* GetPlotDrawList();
|
||||||
|
|
||||||
// Get current style
|
// Get current style
|
||||||
IMPLOT3D_API ImPlot3DStyle& GetStyle();
|
IMPLOT3D_API ImPlot3DStyle& GetStyle();
|
||||||
|
IMPLOT3D_API void SetStyle(const ImPlot3DStyle& style);
|
||||||
|
|
||||||
// Set color styles
|
// Set color styles
|
||||||
IMPLOT3D_API void StyleColorsAuto(ImPlot3DStyle* dst = nullptr); // Set colors with ImGui style
|
IMPLOT3D_API void StyleColorsAuto(ImPlot3DStyle* dst = nullptr); // Set colors with ImGui style
|
||||||
|
|
@ -457,7 +537,8 @@ IMPLOT3D_API void SetNextLineStyle(const ImVec4& col = IMPLOT3D_AUTO_COL, float
|
||||||
// Set the fill color for the next item only
|
// Set the fill color for the next item only
|
||||||
IMPLOT3D_API void SetNextFillStyle(const ImVec4& col = IMPLOT3D_AUTO_COL, float alpha_mod = IMPLOT3D_AUTO);
|
IMPLOT3D_API void SetNextFillStyle(const ImVec4& col = IMPLOT3D_AUTO_COL, float alpha_mod = IMPLOT3D_AUTO);
|
||||||
// Set the marker style for the next item only
|
// Set the marker style for the next item only
|
||||||
IMPLOT3D_API void SetNextMarkerStyle(ImPlot3DMarker marker = IMPLOT3D_AUTO, float size = IMPLOT3D_AUTO, const ImVec4& fill = IMPLOT3D_AUTO_COL, float weight = IMPLOT3D_AUTO, const ImVec4& outline = IMPLOT3D_AUTO_COL);
|
IMPLOT3D_API void SetNextMarkerStyle(ImPlot3DMarker marker = IMPLOT3D_AUTO, float size = IMPLOT3D_AUTO, const ImVec4& fill = IMPLOT3D_AUTO_COL,
|
||||||
|
float weight = IMPLOT3D_AUTO, const ImVec4& outline = IMPLOT3D_AUTO_COL);
|
||||||
|
|
||||||
// Get color
|
// Get color
|
||||||
IMPLOT3D_API ImVec4 GetStyleColorVec4(ImPlot3DCol idx);
|
IMPLOT3D_API ImVec4 GetStyleColorVec4(ImPlot3DCol idx);
|
||||||
|
|
@ -492,9 +573,11 @@ IMPLOT3D_API const char* GetColormapName(ImPlot3DColormap cmap);
|
||||||
// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid
|
// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid
|
||||||
IMPLOT3D_API ImPlot3DColormap GetColormapIndex(const char* name);
|
IMPLOT3D_API ImPlot3DColormap GetColormapIndex(const char* name);
|
||||||
|
|
||||||
// Temporarily switch to one of the built-in (i.e. ImPlot3DColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to call PopColormap!
|
// Temporarily switch to one of the built-in (i.e. ImPlot3DColormap_XXX) or user-added colormaps (i.e. a return value of AddColormap). Don't forget to
|
||||||
|
// call PopColormap!
|
||||||
IMPLOT3D_API void PushColormap(ImPlot3DColormap cmap);
|
IMPLOT3D_API void PushColormap(ImPlot3DColormap cmap);
|
||||||
// Push a colormap by string name. Use built-in names such as "Default", "Deep", "Jet", etc. or a string you provided to AddColormap. Don't forget to call PopColormap!
|
// Push a colormap by string name. Use built-in names such as "Default", "Deep", "Jet", etc. or a string you provided to AddColormap. Don't forget to
|
||||||
|
// call PopColormap!
|
||||||
IMPLOT3D_API void PushColormap(const char* name);
|
IMPLOT3D_API void PushColormap(const char* name);
|
||||||
// Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count
|
// Undo temporary colormap modification(s). Undo multiple pushes at once by increasing count
|
||||||
IMPLOT3D_API void PopColormap(int count = 1);
|
IMPLOT3D_API void PopColormap(int count = 1);
|
||||||
|
|
@ -517,10 +600,15 @@ IMPLOT3D_API ImVec4 SampleColormap(float t, ImPlot3DColormap cmap = IMPLOT3D_AUT
|
||||||
|
|
||||||
// Shows the ImPlot3D demo window
|
// Shows the ImPlot3D demo window
|
||||||
IMPLOT3D_API void ShowDemoWindow(bool* p_open = nullptr);
|
IMPLOT3D_API void ShowDemoWindow(bool* p_open = nullptr);
|
||||||
|
// Shows all ImPlot3D demos, without enclosing window
|
||||||
|
IMPLOT3D_API void ShowAllDemos();
|
||||||
|
|
||||||
// Shows ImPlot3D style editor block (not a window)
|
// Shows ImPlot3D style editor block (not a window)
|
||||||
IMPLOT3D_API void ShowStyleEditor(ImPlot3DStyle* ref = nullptr);
|
IMPLOT3D_API void ShowStyleEditor(ImPlot3DStyle* ref = nullptr);
|
||||||
|
|
||||||
|
// Shows ImPlot3D metrics/debug information window.
|
||||||
|
IMPLOT3D_API void ShowMetricsWindow(bool* p_popen = nullptr);
|
||||||
|
|
||||||
} // namespace ImPlot3D
|
} // namespace ImPlot3D
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -591,7 +679,8 @@ struct ImPlot3DPoint {
|
||||||
IMPLOT3D_API bool IsNaN() const;
|
IMPLOT3D_API bool IsNaN() const;
|
||||||
|
|
||||||
#ifdef IMPLOT3D_POINT_CLASS_EXTRA
|
#ifdef IMPLOT3D_POINT_CLASS_EXTRA
|
||||||
IMPLOT3D_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImPlot3DPoint
|
IMPLOT3D_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math
|
||||||
|
// types and ImPlot3DPoint
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -669,6 +758,9 @@ struct ImPlot3DQuat {
|
||||||
// Set quaternion from two vectors
|
// Set quaternion from two vectors
|
||||||
IMPLOT3D_API static ImPlot3DQuat FromTwoVectors(const ImPlot3DPoint& v0, const ImPlot3DPoint& v1);
|
IMPLOT3D_API static ImPlot3DQuat FromTwoVectors(const ImPlot3DPoint& v0, const ImPlot3DPoint& v1);
|
||||||
|
|
||||||
|
// Set quaternion given elevation and azimuth angles in radians
|
||||||
|
IMPLOT3D_API static ImPlot3DQuat FromElAz(float elevation, float azimuth);
|
||||||
|
|
||||||
// Get quaternion length
|
// Get quaternion length
|
||||||
IMPLOT3D_API float Length() const;
|
IMPLOT3D_API float Length() const;
|
||||||
|
|
||||||
|
|
@ -701,7 +793,8 @@ struct ImPlot3DQuat {
|
||||||
IMPLOT3D_API float Dot(const ImPlot3DQuat& rhs) const;
|
IMPLOT3D_API float Dot(const ImPlot3DQuat& rhs) const;
|
||||||
|
|
||||||
#ifdef IMPLOT3D_QUAT_CLASS_EXTRA
|
#ifdef IMPLOT3D_QUAT_CLASS_EXTRA
|
||||||
IMPLOT3D_QUAT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImPlot3DQuat
|
IMPLOT3D_QUAT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math
|
||||||
|
// types and ImPlot3DQuat
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -727,10 +820,13 @@ struct ImPlot3DStyle {
|
||||||
ImVec2 LegendSpacing; // Spacing between legend entries
|
ImVec2 LegendSpacing; // Spacing between legend entries
|
||||||
// Colors
|
// Colors
|
||||||
ImVec4 Colors[ImPlot3DCol_COUNT];
|
ImVec4 Colors[ImPlot3DCol_COUNT];
|
||||||
|
inline ImVec4 GetColor(ImPlot3DCol idx) const { return Colors[idx]; }
|
||||||
|
inline void SetColor(ImPlot3DCol idx, const ImVec4& col) { Colors[idx] = col; }
|
||||||
// Colormap
|
// Colormap
|
||||||
ImPlot3DColormap Colormap; // The current colormap. Set this to either an ImPlot3DColormap_ enum or an index returned by AddColormap
|
ImPlot3DColormap Colormap; // The current colormap. Set this to either an ImPlot3DColormap_ enum or an index returned by AddColormap
|
||||||
// Constructor
|
// Constructor
|
||||||
IMPLOT3D_API ImPlot3DStyle();
|
IMPLOT3D_API ImPlot3DStyle();
|
||||||
|
ImPlot3DStyle(const ImPlot3DStyle& other) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// ImPlot3D v0.1
|
// ImPlot3D v0.3 WIP
|
||||||
// implot3d_internal.h
|
// implot3d_internal.h
|
||||||
// Date: 2024-11-17
|
// Date: 2024-11-17
|
||||||
// Author: Breno Cunha Queiroz (brenocq.com)
|
// Author: Breno Cunha Queiroz (brenocq.com)
|
||||||
|
|
@ -53,13 +53,10 @@ namespace ImPlot3D {
|
||||||
// Computes the common (base-10) logarithm
|
// Computes the common (base-10) logarithm
|
||||||
static inline float ImLog10(float x) { return log10f(x); }
|
static inline float ImLog10(float x) { return log10f(x); }
|
||||||
// Returns true if flag is set
|
// Returns true if flag is set
|
||||||
template <typename TSet, typename TFlag>
|
template <typename TSet, typename TFlag> static inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
|
||||||
static inline bool ImHasFlag(TSet set, TFlag flag) { return (set & flag) == flag; }
|
|
||||||
// Flips a flag in a flagset
|
// Flips a flag in a flagset
|
||||||
template <typename TSet, typename TFlag>
|
template <typename TSet, typename TFlag> static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
|
||||||
static inline void ImFlipFlag(TSet& set, TFlag flag) { ImHasFlag(set, flag) ? set &= ~flag : set |= flag; }
|
template <typename T> static inline T ImRemap01(T x, T x0, T x1) { return (x1 - x0) ? ((x - x0) / (x1 - x0)) : 0; }
|
||||||
template <typename T>
|
|
||||||
static inline T ImRemap01(T x, T x0, T x1) { return (x - x0) / (x1 - x0); }
|
|
||||||
// Returns true if val is NAN
|
// Returns true if val is NAN
|
||||||
static inline bool ImNan(float val) { return isnan(val); }
|
static inline bool ImNan(float val) { return isnan(val); }
|
||||||
// Returns true if val is NAN or INFINITY
|
// Returns true if val is NAN or INFINITY
|
||||||
|
|
@ -67,14 +64,13 @@ static inline bool ImNanOrInf(float val) { return !(val >= -FLT_MAX && val <= FL
|
||||||
// Turns NANs to 0s
|
// Turns NANs to 0s
|
||||||
static inline double ImConstrainNan(float val) { return ImNan(val) ? 0 : val; }
|
static inline double ImConstrainNan(float val) { return ImNan(val) ? 0 : val; }
|
||||||
// Turns infinity to floating point maximums
|
// Turns infinity to floating point maximums
|
||||||
static inline double ImConstrainInf(double val) { return val >= FLT_MAX ? FLT_MAX : val <= -FLT_MAX ? -FLT_MAX
|
static inline double ImConstrainInf(double val) { return val >= FLT_MAX ? FLT_MAX : val <= -FLT_MAX ? -FLT_MAX : val; }
|
||||||
: val; }
|
|
||||||
// True if two numbers are approximately equal using units in the last place.
|
// True if two numbers are approximately equal using units in the last place.
|
||||||
static inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) { return ImAbs(v1 - v2) < FLT_EPSILON * ImAbs(v1 + v2) * ulp || ImAbs(v1 - v2) < FLT_MIN; }
|
static inline bool ImAlmostEqual(double v1, double v2, int ulp = 2) {
|
||||||
// Set alpha channel of 32-bit color from float in range [0.0 1.0]
|
return ImAbs(v1 - v2) < FLT_EPSILON * ImAbs(v1 + v2) * ulp || ImAbs(v1 - v2) < FLT_MIN;
|
||||||
static inline ImU32 ImAlphaU32(ImU32 col, float alpha) {
|
|
||||||
return col & ~((ImU32)((1.0f - alpha) * 255) << IM_COL32_A_SHIFT);
|
|
||||||
}
|
}
|
||||||
|
// Set alpha channel of 32-bit color from float in range [0.0 1.0]
|
||||||
|
static inline ImU32 ImAlphaU32(ImU32 col, float alpha) { return col & ~((ImU32)((1.0f - alpha) * 255) << IM_COL32_A_SHIFT); }
|
||||||
// Mix color a and b by factor s in [0 256]
|
// Mix color a and b by factor s in [0 256]
|
||||||
static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
|
static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
|
||||||
#ifdef IMPLOT3D_MIX64
|
#ifdef IMPLOT3D_MIX64
|
||||||
|
|
@ -98,8 +94,7 @@ static inline ImU32 ImMixU32(ImU32 a, ImU32 b, ImU32 s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fills a buffer with n samples linear interpolated from vmin to vmax
|
// Fills a buffer with n samples linear interpolated from vmin to vmax
|
||||||
template <typename T>
|
template <typename T> void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
|
||||||
void FillRange(ImVector<T>& buffer, int n, T vmin, T vmax) {
|
|
||||||
buffer.resize(n);
|
buffer.resize(n);
|
||||||
T step = (vmax - vmin) / (n - 1);
|
T step = (vmax - vmin) / (n - 1);
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
|
|
@ -126,30 +121,49 @@ typedef void (*ImPlot3DLocator)(ImPlot3DTicker& ticker, const ImPlot3DRange& ran
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
struct ImDrawList3D {
|
struct ImDrawList3D {
|
||||||
ImVector<ImDrawIdx> IdxBuffer; // Index buffer
|
// [Internal] Define which texture should be used when rendering triangles.
|
||||||
ImVector<ImDrawVert> VtxBuffer; // Vertex buffer
|
struct ImTextureBufferItem {
|
||||||
ImVector<float> ZBuffer; // Z buffer. Depth value for each triangle
|
ImTextureRef TexRef;
|
||||||
unsigned int _VtxCurrentIdx; // [Internal] current vertex index
|
unsigned int VtxIdx;
|
||||||
ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
|
};
|
||||||
ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
|
|
||||||
float* _ZWritePtr; // [Internal] point within ZBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
|
ImVector<ImDrawIdx> IdxBuffer; // Index buffer
|
||||||
ImDrawListFlags _Flags; // [Internal] draw list flags
|
ImVector<ImDrawVert> VtxBuffer; // Vertex buffer
|
||||||
ImDrawListSharedData* _SharedData; // [Internal] shared draw list data
|
ImVector<float> ZBuffer; // Z buffer. Depth value for each triangle
|
||||||
|
unsigned int _VtxCurrentIdx; // [Internal] current vertex index
|
||||||
|
ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
|
||||||
|
ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
|
||||||
|
float* _ZWritePtr; // [Internal] point within ZBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
|
||||||
|
ImDrawListFlags _Flags; // [Internal] draw list flags
|
||||||
|
ImVector<ImTextureBufferItem> _TextureBuffer; // [Internal] buffer for SetTexture/ResetTexture
|
||||||
|
ImDrawListSharedData* _SharedData; // [Internal] shared draw list data
|
||||||
|
|
||||||
ImDrawList3D() {
|
ImDrawList3D() {
|
||||||
_VtxCurrentIdx = 0;
|
|
||||||
_VtxWritePtr = nullptr;
|
|
||||||
_IdxWritePtr = nullptr;
|
|
||||||
_ZWritePtr = nullptr;
|
|
||||||
_Flags = ImDrawListFlags_None;
|
_Flags = ImDrawListFlags_None;
|
||||||
_SharedData = nullptr;
|
_SharedData = nullptr;
|
||||||
|
ResetBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimReserve(int idx_count, int vtx_count);
|
void PrimReserve(int idx_count, int vtx_count);
|
||||||
void PrimUnreserve(int idx_count, int vtx_count);
|
void PrimUnreserve(int idx_count, int vtx_count);
|
||||||
|
|
||||||
|
void SetTexture(ImTextureRef tex_ref);
|
||||||
|
void ResetTexture();
|
||||||
|
|
||||||
void SortedMoveToImGuiDrawList();
|
void SortedMoveToImGuiDrawList();
|
||||||
|
|
||||||
|
void ResetBuffers() {
|
||||||
|
IdxBuffer.clear();
|
||||||
|
VtxBuffer.clear();
|
||||||
|
ZBuffer.clear();
|
||||||
|
_VtxCurrentIdx = 0;
|
||||||
|
_VtxWritePtr = VtxBuffer.Data;
|
||||||
|
_IdxWritePtr = IdxBuffer.Data;
|
||||||
|
_ZWritePtr = ZBuffer.Data;
|
||||||
|
_TextureBuffer.clear();
|
||||||
|
ResetTexture();
|
||||||
|
}
|
||||||
|
|
||||||
constexpr static unsigned int MaxIdx() { return sizeof(ImDrawIdx) == 2 ? 65535 : 4294967295; }
|
constexpr static unsigned int MaxIdx() { return sizeof(ImDrawIdx) == 2 ? 65535 : 4294967295; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -345,9 +359,7 @@ struct ImPlot3DItemGroup {
|
||||||
ImPlot3DLegend Legend;
|
ImPlot3DLegend Legend;
|
||||||
int ColormapIdx;
|
int ColormapIdx;
|
||||||
|
|
||||||
ImPlot3DItemGroup() {
|
ImPlot3DItemGroup() { ColormapIdx = 0; }
|
||||||
ColormapIdx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetItemCount() const { return ItemPool.GetBufSize(); }
|
int GetItemCount() const { return ItemPool.GetBufSize(); }
|
||||||
ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); }
|
ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); }
|
||||||
|
|
@ -388,9 +400,7 @@ struct ImPlot3DTicker {
|
||||||
ImVector<ImPlot3DTick> Ticks;
|
ImVector<ImPlot3DTick> Ticks;
|
||||||
ImGuiTextBuffer TextBuffer;
|
ImGuiTextBuffer TextBuffer;
|
||||||
|
|
||||||
ImPlot3DTicker() {
|
ImPlot3DTicker() { Reset(); }
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImPlot3DTick& AddTick(double value, bool major, bool show_label, const char* label) {
|
ImPlot3DTick& AddTick(double value, bool major, bool show_label, const char* label) {
|
||||||
ImPlot3DTick tick(value, major, show_label);
|
ImPlot3DTick tick(value, major, show_label);
|
||||||
|
|
@ -420,22 +430,16 @@ struct ImPlot3DTicker {
|
||||||
return Ticks.back();
|
return Ticks.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetText(int idx) const {
|
const char* GetText(int idx) const { return TextBuffer.Buf.Data + Ticks[idx].TextOffset; }
|
||||||
return TextBuffer.Buf.Data + Ticks[idx].TextOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GetText(const ImPlot3DTick& tick) const {
|
const char* GetText(const ImPlot3DTick& tick) const { return GetText(tick.Idx); }
|
||||||
return GetText(tick.Idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
Ticks.shrink(0);
|
Ticks.shrink(0);
|
||||||
TextBuffer.Buf.shrink(0);
|
TextBuffer.Buf.shrink(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TickCount() const {
|
int TickCount() const { return Ticks.Size; }
|
||||||
return Ticks.Size;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Holds axis information
|
// Holds axis information
|
||||||
|
|
@ -454,6 +458,9 @@ struct ImPlot3DAxis {
|
||||||
// Fit data
|
// Fit data
|
||||||
bool FitThisFrame;
|
bool FitThisFrame;
|
||||||
ImPlot3DRange FitExtents;
|
ImPlot3DRange FitExtents;
|
||||||
|
// Constraints
|
||||||
|
ImPlot3DRange ConstraintRange;
|
||||||
|
ImPlot3DRange ConstraintZoom;
|
||||||
// User input
|
// User input
|
||||||
bool Hovered;
|
bool Hovered;
|
||||||
bool Held;
|
bool Held;
|
||||||
|
|
@ -472,34 +479,54 @@ struct ImPlot3DAxis {
|
||||||
ShowDefaultTicks = true;
|
ShowDefaultTicks = true;
|
||||||
// Fit data
|
// Fit data
|
||||||
FitThisFrame = true;
|
FitThisFrame = true;
|
||||||
FitExtents.Min = HUGE_VAL;
|
FitExtents = ImPlot3DRange(HUGE_VAL, -HUGE_VAL);
|
||||||
FitExtents.Max = -HUGE_VAL;
|
// Constraints
|
||||||
|
ConstraintRange = ImPlot3DRange(-INFINITY, INFINITY);
|
||||||
|
ConstraintZoom = ImPlot3DRange(FLT_MIN, INFINITY);
|
||||||
// User input
|
// User input
|
||||||
Hovered = false;
|
Hovered = false;
|
||||||
Held = false;
|
Held = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Reset() {
|
inline void Reset() {
|
||||||
|
RangeCond = ImPlot3DCond_None;
|
||||||
|
// Ticks
|
||||||
|
Ticker.Reset();
|
||||||
Formatter = nullptr;
|
Formatter = nullptr;
|
||||||
FormatterData = nullptr;
|
FormatterData = nullptr;
|
||||||
Locator = nullptr;
|
Locator = nullptr;
|
||||||
ShowDefaultTicks = true;
|
ShowDefaultTicks = true;
|
||||||
FitExtents.Min = HUGE_VAL;
|
// Fit data
|
||||||
FitExtents.Max = -HUGE_VAL;
|
FitExtents = ImPlot3DRange(HUGE_VAL, -HUGE_VAL);
|
||||||
Ticker.Reset();
|
// Constraints
|
||||||
|
ConstraintRange = ImPlot3DRange(-INFINITY, INFINITY);
|
||||||
|
ConstraintZoom = ImPlot3DRange(FLT_MIN, INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetRange(double v1, double v2) {
|
inline void SetRange(double v1, double v2) {
|
||||||
Range.Min = (float)ImMin(v1, v2);
|
Range.Min = (float)ImMin(v1, v2);
|
||||||
Range.Max = (float)ImMax(v1, v2);
|
Range.Max = (float)ImMax(v1, v2);
|
||||||
|
Constrain();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool SetMin(double _min, bool force = false) {
|
inline bool SetMin(double _min, bool force = false) {
|
||||||
if (!force && IsLockedMin())
|
if (!force && IsLockedMin())
|
||||||
return false;
|
return false;
|
||||||
_min = ImPlot3D::ImConstrainNan((float)ImPlot3D::ImConstrainInf(_min));
|
_min = ImPlot3D::ImConstrainNan((float)ImPlot3D::ImConstrainInf(_min));
|
||||||
|
|
||||||
|
// Constraints
|
||||||
|
if (_min < ConstraintRange.Min)
|
||||||
|
_min = ConstraintRange.Min;
|
||||||
|
double zoom = Range.Max - _min;
|
||||||
|
if (zoom < ConstraintZoom.Min)
|
||||||
|
_min = Range.Max - ConstraintZoom.Min;
|
||||||
|
if (zoom > ConstraintZoom.Max)
|
||||||
|
_min = Range.Max - ConstraintZoom.Max;
|
||||||
|
|
||||||
|
// Ensure min is less than max
|
||||||
if (_min >= Range.Max)
|
if (_min >= Range.Max)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Range.Min = (float)_min;
|
Range.Min = (float)_min;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -508,12 +535,45 @@ struct ImPlot3DAxis {
|
||||||
if (!force && IsLockedMax())
|
if (!force && IsLockedMax())
|
||||||
return false;
|
return false;
|
||||||
_max = ImPlot3D::ImConstrainNan((float)ImPlot3D::ImConstrainInf(_max));
|
_max = ImPlot3D::ImConstrainNan((float)ImPlot3D::ImConstrainInf(_max));
|
||||||
|
|
||||||
|
// Constraints
|
||||||
|
if (_max > ConstraintRange.Max)
|
||||||
|
_max = ConstraintRange.Max;
|
||||||
|
double zoom = _max - Range.Min;
|
||||||
|
if (zoom < ConstraintZoom.Min)
|
||||||
|
_max = Range.Min + ConstraintZoom.Min;
|
||||||
|
if (zoom > ConstraintZoom.Max)
|
||||||
|
_max = Range.Min + ConstraintZoom.Max;
|
||||||
|
|
||||||
|
// Ensure max is greater than min
|
||||||
if (_max <= Range.Min)
|
if (_max <= Range.Min)
|
||||||
return false;
|
return false;
|
||||||
Range.Max = (float)_max;
|
Range.Max = (float)_max;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Constrain() {
|
||||||
|
Range.Min = (float)ImPlot3D::ImConstrainNan((float)ImPlot3D::ImConstrainInf((double)Range.Min));
|
||||||
|
Range.Max = (float)ImPlot3D::ImConstrainNan((float)ImPlot3D::ImConstrainInf((double)Range.Max));
|
||||||
|
if (Range.Min < ConstraintRange.Min)
|
||||||
|
Range.Min = ConstraintRange.Min;
|
||||||
|
if (Range.Max > ConstraintRange.Max)
|
||||||
|
Range.Max = ConstraintRange.Max;
|
||||||
|
float zoom = Range.Size();
|
||||||
|
if (zoom < ConstraintZoom.Min) {
|
||||||
|
float delta = (ConstraintZoom.Min - zoom) * 0.5f;
|
||||||
|
Range.Min -= delta;
|
||||||
|
Range.Max += delta;
|
||||||
|
}
|
||||||
|
if (zoom > ConstraintZoom.Max) {
|
||||||
|
float delta = (zoom - ConstraintZoom.Max) * 0.5f;
|
||||||
|
Range.Min += delta;
|
||||||
|
Range.Max -= delta;
|
||||||
|
}
|
||||||
|
if (Range.Max <= Range.Min)
|
||||||
|
Range.Max = Range.Min + FLT_EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool IsRangeLocked() const { return RangeCond == ImPlot3DCond_Always; }
|
inline bool IsRangeLocked() const { return RangeCond == ImPlot3DCond_Always; }
|
||||||
inline bool IsLockedMin() const { return IsRangeLocked() || ImPlot3D::ImHasFlag(Flags, ImPlot3DAxisFlags_LockMin); }
|
inline bool IsLockedMin() const { return IsRangeLocked() || ImPlot3D::ImHasFlag(Flags, ImPlot3DAxisFlags_LockMin); }
|
||||||
inline bool IsLockedMax() const { return IsRangeLocked() || ImPlot3D::ImHasFlag(Flags, ImPlot3DAxisFlags_LockMax); }
|
inline bool IsLockedMax() const { return IsRangeLocked() || ImPlot3D::ImHasFlag(Flags, ImPlot3DAxisFlags_LockMax); }
|
||||||
|
|
@ -522,6 +582,19 @@ struct ImPlot3DAxis {
|
||||||
inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
|
inline bool IsInputLockedMax() const { return IsLockedMax() || IsAutoFitting(); }
|
||||||
inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
|
inline bool IsInputLocked() const { return IsLocked() || IsAutoFitting(); }
|
||||||
|
|
||||||
|
inline bool IsPanLocked(bool increasing) {
|
||||||
|
if (ImPlot3D::ImHasFlag(Flags, ImPlot3DAxisFlags_PanStretch)) {
|
||||||
|
return IsInputLocked();
|
||||||
|
} else {
|
||||||
|
if (IsLockedMin() || IsLockedMax() || IsAutoFitting())
|
||||||
|
return false;
|
||||||
|
if (increasing)
|
||||||
|
return Range.Max == ConstraintRange.Max;
|
||||||
|
else
|
||||||
|
return Range.Min == ConstraintRange.Min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void SetLabel(const char* label) {
|
inline void SetLabel(const char* label) {
|
||||||
Label.Buf.shrink(0);
|
Label.Buf.shrink(0);
|
||||||
if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label)
|
if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label)
|
||||||
|
|
@ -552,7 +625,9 @@ struct ImPlot3DPlot {
|
||||||
ImRect CanvasRect; // Frame rectangle reduced by padding
|
ImRect CanvasRect; // Frame rectangle reduced by padding
|
||||||
ImRect PlotRect; // Bounding rectangle for the actual plot area
|
ImRect PlotRect; // Bounding rectangle for the actual plot area
|
||||||
// Rotation & axes & box
|
// Rotation & axes & box
|
||||||
ImPlot3DQuat Rotation; // Current rotation quaternion
|
ImPlot3DQuat InitialRotation; // Initial rotation quaternion
|
||||||
|
ImPlot3DQuat Rotation; // Current rotation quaternion
|
||||||
|
ImPlot3DCond RotationCond;
|
||||||
ImPlot3DAxis Axes[3]; // X, Y, Z axes
|
ImPlot3DAxis Axes[3]; // X, Y, Z axes
|
||||||
ImPlot3DPoint BoxScale; // Scale factor for plot box X, Y, Z axes
|
ImPlot3DPoint BoxScale; // Scale factor for plot box X, Y, Z axes
|
||||||
// Animation
|
// Animation
|
||||||
|
|
@ -568,7 +643,6 @@ struct ImPlot3DPlot {
|
||||||
bool FitThisFrame;
|
bool FitThisFrame;
|
||||||
// Items
|
// Items
|
||||||
ImPlot3DItemGroup Items;
|
ImPlot3DItemGroup Items;
|
||||||
ImPlot3DItem* CurrentItem;
|
|
||||||
// 3D draw list
|
// 3D draw list
|
||||||
ImDrawList3D DrawList;
|
ImDrawList3D DrawList;
|
||||||
// Misc
|
// Misc
|
||||||
|
|
@ -579,7 +653,9 @@ struct ImPlot3DPlot {
|
||||||
PreviousFlags = Flags = ImPlot3DFlags_None;
|
PreviousFlags = Flags = ImPlot3DFlags_None;
|
||||||
JustCreated = true;
|
JustCreated = true;
|
||||||
Initialized = false;
|
Initialized = false;
|
||||||
|
InitialRotation = ImPlot3DQuat(-0.513269f, -0.212596f, -0.318184f, 0.76819f);
|
||||||
Rotation = ImPlot3DQuat(0.0f, 0.0f, 0.0f, 1.0f);
|
Rotation = ImPlot3DQuat(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
RotationCond = ImPlot3DCond_None;
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
Axes[i] = ImPlot3DAxis();
|
Axes[i] = ImPlot3DAxis();
|
||||||
BoxScale = ImPlot3DPoint(1.0f, 1.0f, 1.0f);
|
BoxScale = ImPlot3DPoint(1.0f, 1.0f, 1.0f);
|
||||||
|
|
@ -590,7 +666,6 @@ struct ImPlot3DPlot {
|
||||||
HeldEdgeIdx = -1;
|
HeldEdgeIdx = -1;
|
||||||
HeldPlaneIdx = -1;
|
HeldPlaneIdx = -1;
|
||||||
FitThisFrame = true;
|
FitThisFrame = true;
|
||||||
CurrentItem = nullptr;
|
|
||||||
ContextClick = false;
|
ContextClick = false;
|
||||||
OpenContextThisFrame = false;
|
OpenContextThisFrame = false;
|
||||||
}
|
}
|
||||||
|
|
@ -602,6 +677,7 @@ struct ImPlot3DPlot {
|
||||||
}
|
}
|
||||||
inline bool HasTitle() const { return !Title.empty() && !ImPlot3D::ImHasFlag(Flags, ImPlot3DFlags_NoTitle); }
|
inline bool HasTitle() const { return !Title.empty() && !ImPlot3D::ImHasFlag(Flags, ImPlot3DFlags_NoTitle); }
|
||||||
inline const char* GetTitle() const { return Title.Buf.Data; }
|
inline const char* GetTitle() const { return Title.Buf.Data; }
|
||||||
|
inline bool IsRotationLocked() const { return RotationCond == ImPlot3DCond_Always; }
|
||||||
|
|
||||||
void ExtendFit(const ImPlot3DPoint& point);
|
void ExtendFit(const ImPlot3DPoint& point);
|
||||||
ImPlot3DPoint RangeMin() const;
|
ImPlot3DPoint RangeMin() const;
|
||||||
|
|
@ -615,6 +691,7 @@ struct ImPlot3DContext {
|
||||||
ImPool<ImPlot3DPlot> Plots;
|
ImPool<ImPlot3DPlot> Plots;
|
||||||
ImPlot3DPlot* CurrentPlot;
|
ImPlot3DPlot* CurrentPlot;
|
||||||
ImPlot3DItemGroup* CurrentItems;
|
ImPlot3DItemGroup* CurrentItems;
|
||||||
|
ImPlot3DItem* CurrentItem;
|
||||||
ImPlot3DNextItemData NextItemData;
|
ImPlot3DNextItemData NextItemData;
|
||||||
ImPlot3DStyle Style;
|
ImPlot3DStyle Style;
|
||||||
ImVector<ImGuiColorMod> ColorModifiers;
|
ImVector<ImGuiColorMod> ColorModifiers;
|
||||||
|
|
@ -649,6 +726,12 @@ IMPLOT3D_API bool IsColorAuto(ImPlot3DCol idx);
|
||||||
IMPLOT3D_API ImVec4 GetAutoColor(ImPlot3DCol idx);
|
IMPLOT3D_API ImVec4 GetAutoColor(ImPlot3DCol idx);
|
||||||
IMPLOT3D_API const char* GetStyleColorName(ImPlot3DCol idx);
|
IMPLOT3D_API const char* GetStyleColorName(ImPlot3DCol idx);
|
||||||
|
|
||||||
|
// Returns white or black text given background color
|
||||||
|
static inline ImU32 CalcTextColor(const ImVec4& bg) {
|
||||||
|
return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE;
|
||||||
|
}
|
||||||
|
static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
|
||||||
|
|
||||||
// Get styling data for next item (call between BeginItem/EndItem)
|
// Get styling data for next item (call between BeginItem/EndItem)
|
||||||
IMPLOT3D_API const ImPlot3DNextItemData& GetItemData();
|
IMPLOT3D_API const ImPlot3DNextItemData& GetItemData();
|
||||||
|
|
||||||
|
|
@ -658,6 +741,10 @@ IMPLOT3D_API ImU32 GetColormapColorU32(int idx, ImPlot3DColormap cmap);
|
||||||
// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired
|
// Returns the next unused colormap color and advances the colormap. Can be used to skip colors if desired
|
||||||
IMPLOT3D_API ImU32 NextColormapColorU32();
|
IMPLOT3D_API ImU32 NextColormapColorU32();
|
||||||
|
|
||||||
|
// Render a colormap bar
|
||||||
|
IMPLOT3D_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed,
|
||||||
|
bool continuous);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Item Utils
|
// [SECTION] Item Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -668,6 +755,9 @@ IMPLOT3D_API void EndItem();
|
||||||
// Register or get an existing item from the current plot
|
// Register or get an existing item from the current plot
|
||||||
IMPLOT3D_API ImPlot3DItem* RegisterOrGetItem(const char* label_id, ImPlot3DItemFlags flags, bool* just_created = nullptr);
|
IMPLOT3D_API ImPlot3DItem* RegisterOrGetItem(const char* label_id, ImPlot3DItemFlags flags, bool* just_created = nullptr);
|
||||||
|
|
||||||
|
// Gets the current item from ImPlot3DContext
|
||||||
|
IMPLOT3D_API ImPlot3DItem* GetCurrentItem();
|
||||||
|
|
||||||
// Busts the cache for every item for every plot in the current context
|
// Busts the cache for every item for every plot in the current context
|
||||||
IMPLOT3D_API void BustItemCache();
|
IMPLOT3D_API void BustItemCache();
|
||||||
|
|
||||||
|
|
@ -678,7 +768,7 @@ IMPLOT3D_API void AddTextRotated(ImDrawList* draw_list, ImVec2 pos, float angle,
|
||||||
// [SECTION] Plot Utils
|
// [SECTION] Plot Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Gets the current plot from the current ImPlot3DContext
|
// Gets the current plot from ImPlot3DContext
|
||||||
IMPLOT3D_API ImPlot3DPlot* GetCurrentPlot();
|
IMPLOT3D_API ImPlot3DPlot* GetCurrentPlot();
|
||||||
|
|
||||||
// Busts the cache for every plot in the current context
|
// Busts the cache for every plot in the current context
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,5 @@
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// ImPlot3D v0.1
|
// ImPlot3D v0.3 WIP
|
||||||
// implot3d_demo.cpp
|
// implot3d_demo.cpp
|
||||||
// Date: 2024-11-17
|
// Date: 2024-11-17
|
||||||
// Author: Breno Cunha Queiroz (brenocq.com)
|
// Author: Breno Cunha Queiroz (brenocq.com)
|
||||||
|
|
@ -47,6 +47,8 @@ namespace ImPlot3D {
|
||||||
// [SECTION] Helpers
|
// [SECTION] Helpers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define CHECKBOX_FLAG(flags, flag) ImGui::CheckboxFlags(#flag, (unsigned int*)&flags, flag)
|
||||||
|
|
||||||
static void HelpMarker(const char* desc) {
|
static void HelpMarker(const char* desc) {
|
||||||
ImGui::TextDisabled("(?)");
|
ImGui::TextDisabled("(?)");
|
||||||
if (ImGui::BeginItemTooltip()) {
|
if (ImGui::BeginItemTooltip()) {
|
||||||
|
|
@ -196,6 +198,12 @@ void DemoTrianglePlots() {
|
||||||
|
|
||||||
// Now we have 18 vertices in xs, ys, zs forming the pyramid
|
// Now we have 18 vertices in xs, ys, zs forming the pyramid
|
||||||
|
|
||||||
|
// Triangle flags
|
||||||
|
static ImPlot3DTriangleFlags flags = ImPlot3DTriangleFlags_None;
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DTriangleFlags_NoLines);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DTriangleFlags_NoFill);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DTriangleFlags_NoMarkers);
|
||||||
|
|
||||||
if (ImPlot3D::BeginPlot("Triangle Plots")) {
|
if (ImPlot3D::BeginPlot("Triangle Plots")) {
|
||||||
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -0.5, 1.5);
|
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -0.5, 1.5);
|
||||||
|
|
||||||
|
|
@ -205,7 +213,7 @@ void DemoTrianglePlots() {
|
||||||
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, ImPlot3D::GetColormapColor(2), IMPLOT3D_AUTO, ImPlot3D::GetColormapColor(2));
|
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, ImPlot3D::GetColormapColor(2), IMPLOT3D_AUTO, ImPlot3D::GetColormapColor(2));
|
||||||
|
|
||||||
// Plot pyramid
|
// Plot pyramid
|
||||||
ImPlot3D::PlotTriangle("Pyramid", xs, ys, zs, 6 * 3); // 6 triangles, 3 vertices each = 18
|
ImPlot3D::PlotTriangle("Pyramid", xs, ys, zs, 6 * 3, flags); // 6 triangles, 3 vertices each = 18
|
||||||
ImPlot3D::EndPlot();
|
ImPlot3D::EndPlot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -254,6 +262,12 @@ void DemoQuadPlots() {
|
||||||
xs[23] = -1; ys[23] = 1; zs[23] = -1;
|
xs[23] = -1; ys[23] = 1; zs[23] = -1;
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
// Quad flags
|
||||||
|
static ImPlot3DQuadFlags flags = ImPlot3DQuadFlags_None;
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DQuadFlags_NoLines);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DQuadFlags_NoFill);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DQuadFlags_NoMarkers);
|
||||||
|
|
||||||
if (ImPlot3D::BeginPlot("Quad Plots")) {
|
if (ImPlot3D::BeginPlot("Quad Plots")) {
|
||||||
ImPlot3D::SetupAxesLimits(-1.5f, 1.5f, -1.5f, 1.5f, -1.5f, 1.5f);
|
ImPlot3D::SetupAxesLimits(-1.5f, 1.5f, -1.5f, 1.5f, -1.5f, 1.5f);
|
||||||
|
|
||||||
|
|
@ -262,21 +276,21 @@ void DemoQuadPlots() {
|
||||||
ImPlot3D::SetNextFillStyle(colorX);
|
ImPlot3D::SetNextFillStyle(colorX);
|
||||||
ImPlot3D::SetNextLineStyle(colorX, 2);
|
ImPlot3D::SetNextLineStyle(colorX, 2);
|
||||||
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorX, IMPLOT3D_AUTO, colorX);
|
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorX, IMPLOT3D_AUTO, colorX);
|
||||||
ImPlot3D::PlotQuad("X", &xs[0], &ys[0], &zs[0], 8);
|
ImPlot3D::PlotQuad("X", &xs[0], &ys[0], &zs[0], 8, flags);
|
||||||
|
|
||||||
// Render +y and -y faces
|
// Render +y and -y faces
|
||||||
static ImVec4 colorY(0.2f, 0.8f, 0.2f, 0.8f); // Green
|
static ImVec4 colorY(0.2f, 0.8f, 0.2f, 0.8f); // Green
|
||||||
ImPlot3D::SetNextFillStyle(colorY);
|
ImPlot3D::SetNextFillStyle(colorY);
|
||||||
ImPlot3D::SetNextLineStyle(colorY, 2);
|
ImPlot3D::SetNextLineStyle(colorY, 2);
|
||||||
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorY, IMPLOT3D_AUTO, colorY);
|
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorY, IMPLOT3D_AUTO, colorY);
|
||||||
ImPlot3D::PlotQuad("Y", &xs[8], &ys[8], &zs[8], 8);
|
ImPlot3D::PlotQuad("Y", &xs[8], &ys[8], &zs[8], 8, flags);
|
||||||
|
|
||||||
// Render +z and -z faces
|
// Render +z and -z faces
|
||||||
static ImVec4 colorZ(0.2f, 0.2f, 0.8f, 0.8f); // Blue
|
static ImVec4 colorZ(0.2f, 0.2f, 0.8f, 0.8f); // Blue
|
||||||
ImPlot3D::SetNextFillStyle(colorZ);
|
ImPlot3D::SetNextFillStyle(colorZ);
|
||||||
ImPlot3D::SetNextLineStyle(colorZ, 2);
|
ImPlot3D::SetNextLineStyle(colorZ, 2);
|
||||||
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorZ, IMPLOT3D_AUTO, colorZ);
|
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorZ, IMPLOT3D_AUTO, colorZ);
|
||||||
ImPlot3D::PlotQuad("Z", &xs[16], &ys[16], &zs[16], 8);
|
ImPlot3D::PlotQuad("Z", &xs[16], &ys[16], &zs[16], 8, flags);
|
||||||
|
|
||||||
ImPlot3D::EndPlot();
|
ImPlot3D::EndPlot();
|
||||||
}
|
}
|
||||||
|
|
@ -307,8 +321,7 @@ void DemoSurfacePlots() {
|
||||||
ImGui::Text("Fill color");
|
ImGui::Text("Fill color");
|
||||||
static int selected_fill = 1; // Colormap by default
|
static int selected_fill = 1; // Colormap by default
|
||||||
static ImVec4 solid_color = ImVec4(0.8f, 0.8f, 0.2f, 0.6f);
|
static ImVec4 solid_color = ImVec4(0.8f, 0.8f, 0.2f, 0.6f);
|
||||||
const char* colormaps[] = {"Viridis", "Plasma", "Hot", "Cool", "Pink", "Jet",
|
const char* colormaps[] = {"Viridis", "Plasma", "Hot", "Cool", "Pink", "Jet", "Twilight", "RdBu", "BrBG", "PiYG", "Spectral", "Greys"};
|
||||||
"Twilight", "RdBu", "BrBG", "PiYG", "Spectral", "Greys"};
|
|
||||||
static int sel_colormap = 5; // Jet by default
|
static int sel_colormap = 5; // Jet by default
|
||||||
{
|
{
|
||||||
ImGui::Indent();
|
ImGui::Indent();
|
||||||
|
|
@ -347,22 +360,34 @@ void DemoSurfacePlots() {
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select flags
|
||||||
|
static ImPlot3DSurfaceFlags flags = ImPlot3DSurfaceFlags_NoMarkers;
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DSurfaceFlags_NoLines);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DSurfaceFlags_NoFill);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DSurfaceFlags_NoMarkers);
|
||||||
|
|
||||||
// Begin the plot
|
// Begin the plot
|
||||||
if (selected_fill == 1)
|
if (selected_fill == 1)
|
||||||
ImPlot3D::PushColormap(colormaps[sel_colormap]);
|
ImPlot3D::PushColormap(colormaps[sel_colormap]);
|
||||||
if (ImPlot3D::BeginPlot("Surface Plots", ImVec2(-1, 400), ImPlot3DFlags_NoClip)) {
|
if (ImPlot3D::BeginPlot("Surface Plots", ImVec2(-1, 400), ImPlot3DFlags_NoClip)) {
|
||||||
// Set styles
|
|
||||||
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1.5, 1.5);
|
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1.5, 1.5);
|
||||||
|
|
||||||
|
// Set fill style
|
||||||
ImPlot3D::PushStyleVar(ImPlot3DStyleVar_FillAlpha, 0.8f);
|
ImPlot3D::PushStyleVar(ImPlot3DStyleVar_FillAlpha, 0.8f);
|
||||||
if (selected_fill == 0)
|
if (selected_fill == 0)
|
||||||
ImPlot3D::SetNextFillStyle(solid_color);
|
ImPlot3D::SetNextFillStyle(solid_color);
|
||||||
|
|
||||||
|
// Set line style
|
||||||
ImPlot3D::SetNextLineStyle(ImPlot3D::GetColormapColor(1));
|
ImPlot3D::SetNextLineStyle(ImPlot3D::GetColormapColor(1));
|
||||||
|
|
||||||
|
// Set marker style
|
||||||
|
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, IMPLOT3D_AUTO, ImPlot3D::GetColormapColor(2));
|
||||||
|
|
||||||
// Plot the surface
|
// Plot the surface
|
||||||
if (custom_range)
|
if (custom_range)
|
||||||
ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, (double)range_min, (double)range_max);
|
ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, (double)range_min, (double)range_max, flags);
|
||||||
else
|
else
|
||||||
ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N);
|
ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, 0.0, 0.0, flags);
|
||||||
|
|
||||||
// End the plot
|
// End the plot
|
||||||
ImPlot3D::PopStyleVar();
|
ImPlot3D::PopStyleVar();
|
||||||
|
|
@ -376,55 +401,112 @@ void DemoMeshPlots() {
|
||||||
static int mesh_id = 0;
|
static int mesh_id = 0;
|
||||||
ImGui::Combo("Mesh", &mesh_id, "Duck\0Sphere\0Cube\0\0");
|
ImGui::Combo("Mesh", &mesh_id, "Duck\0Sphere\0Cube\0\0");
|
||||||
|
|
||||||
// Choose fill color
|
|
||||||
static bool set_fill_color = true;
|
|
||||||
static ImVec4 fill_color = ImVec4(0.8f, 0.8f, 0.2f, 0.6f);
|
|
||||||
ImGui::Checkbox("Fill Color", &set_fill_color);
|
|
||||||
if (set_fill_color) {
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::ColorEdit4("##MeshFillColor", (float*)&fill_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose line color
|
// Choose line color
|
||||||
static bool set_line_color = true;
|
static ImVec4 line_color = ImVec4(0.5f, 0.5f, 0.2f, 0.6f);
|
||||||
static ImVec4 line_color = ImVec4(0.2f, 0.2f, 0.2f, 0.8f);
|
ImGui::ColorEdit4("Line Color##Mesh", (float*)&line_color);
|
||||||
ImGui::Checkbox("Line Color", &set_line_color);
|
|
||||||
if (set_line_color) {
|
// Choose fill color
|
||||||
ImGui::SameLine();
|
static ImVec4 fill_color = ImVec4(0.8f, 0.8f, 0.2f, 0.6f);
|
||||||
ImGui::ColorEdit4("##MeshLineColor", (float*)&line_color);
|
ImGui::ColorEdit4("Fill Color##Mesh", (float*)&fill_color);
|
||||||
}
|
|
||||||
|
|
||||||
// Choose marker color
|
// Choose marker color
|
||||||
static bool set_marker_color = false;
|
static ImVec4 marker_color = ImVec4(0.5f, 0.5f, 0.2f, 0.6f);
|
||||||
static ImVec4 marker_color = ImVec4(0.2f, 0.2f, 0.2f, 0.8f);
|
ImGui::ColorEdit4("Marker Color##Mesh", (float*)&marker_color);
|
||||||
ImGui::Checkbox("Marker Color", &set_marker_color);
|
|
||||||
if (set_marker_color) {
|
// Mesh flags
|
||||||
ImGui::SameLine();
|
static ImPlot3DMeshFlags flags = ImPlot3DMeshFlags_NoMarkers;
|
||||||
ImGui::ColorEdit4("##MeshMarkerColor", (float*)&marker_color);
|
CHECKBOX_FLAG(flags, ImPlot3DMeshFlags_NoLines);
|
||||||
}
|
CHECKBOX_FLAG(flags, ImPlot3DMeshFlags_NoFill);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DMeshFlags_NoMarkers);
|
||||||
|
|
||||||
if (ImPlot3D::BeginPlot("Mesh Plots")) {
|
if (ImPlot3D::BeginPlot("Mesh Plots")) {
|
||||||
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1, 1);
|
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1, 1);
|
||||||
|
|
||||||
// Set colors
|
// Set fill style
|
||||||
if (set_fill_color)
|
ImPlot3D::SetNextFillStyle(fill_color);
|
||||||
ImPlot3D::SetNextFillStyle(fill_color);
|
|
||||||
else {
|
// Set line style
|
||||||
// If not set as transparent, the fill color will be determined by the colormap
|
ImPlot3D::SetNextLineStyle(line_color);
|
||||||
ImPlot3D::SetNextFillStyle(ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
|
||||||
}
|
// Set marker style
|
||||||
if (set_line_color)
|
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, marker_color, IMPLOT3D_AUTO, marker_color);
|
||||||
ImPlot3D::SetNextLineStyle(line_color);
|
|
||||||
if (set_marker_color)
|
|
||||||
ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, marker_color, IMPLOT3D_AUTO, marker_color);
|
|
||||||
|
|
||||||
// Plot mesh
|
// Plot mesh
|
||||||
if (mesh_id == 0)
|
if (mesh_id == 0)
|
||||||
ImPlot3D::PlotMesh("Duck", duck_vtx, duck_idx, DUCK_VTX_COUNT, DUCK_IDX_COUNT);
|
ImPlot3D::PlotMesh("Duck", duck_vtx, duck_idx, DUCK_VTX_COUNT, DUCK_IDX_COUNT, flags);
|
||||||
else if (mesh_id == 1)
|
else if (mesh_id == 1)
|
||||||
ImPlot3D::PlotMesh("Sphere", sphere_vtx, sphere_idx, SPHERE_VTX_COUNT, SPHERE_IDX_COUNT);
|
ImPlot3D::PlotMesh("Sphere", sphere_vtx, sphere_idx, SPHERE_VTX_COUNT, SPHERE_IDX_COUNT, flags);
|
||||||
else if (mesh_id == 2)
|
else if (mesh_id == 2)
|
||||||
ImPlot3D::PlotMesh("Cube", cube_vtx, cube_idx, CUBE_VTX_COUNT, CUBE_IDX_COUNT);
|
ImPlot3D::PlotMesh("Cube", cube_vtx, cube_idx, CUBE_VTX_COUNT, CUBE_IDX_COUNT, flags);
|
||||||
|
|
||||||
|
ImPlot3D::EndPlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoImagePlots() {
|
||||||
|
ImGui::BulletText("Below we are displaying the font texture, which is the only texture we have\naccess to in this demo.");
|
||||||
|
ImGui::BulletText("Use the 'ImTextureID' type as storage to pass pointers or identifiers to your\nown texture data.");
|
||||||
|
ImGui::BulletText("See ImGui Wiki page 'Image Loading and Displaying Examples'.");
|
||||||
|
|
||||||
|
static ImVec4 tint1(1, 1, 1, 1);
|
||||||
|
static ImVec4 tint2(1, 1, 1, 1);
|
||||||
|
|
||||||
|
static ImPlot3DPoint center1(0, 0, 1);
|
||||||
|
static ImPlot3DPoint axis_u1(1, 0, 0);
|
||||||
|
static ImPlot3DPoint axis_v1(0, 1, 0);
|
||||||
|
static ImVec2 uv0_1(0, 0), uv1_1(1, 1);
|
||||||
|
|
||||||
|
static ImPlot3DPoint p0(-1, -1, 0);
|
||||||
|
static ImPlot3DPoint p1(1, -1, 0);
|
||||||
|
static ImPlot3DPoint p2(1, 1, 0);
|
||||||
|
static ImPlot3DPoint p3(-1, 1, 0);
|
||||||
|
static ImVec2 uv0(0, 0), uv1(1, 0), uv2(1, 1), uv3(0, 1);
|
||||||
|
|
||||||
|
// Spacing
|
||||||
|
ImGui::Dummy(ImVec2(0, 10));
|
||||||
|
|
||||||
|
// Image 1 Controls
|
||||||
|
if (ImGui::TreeNodeEx("Image 1 Controls: Center + Axes")) {
|
||||||
|
ImGui::SliderFloat3("Center", ¢er1.x, -2, 2, "%.1f");
|
||||||
|
ImGui::SliderFloat3("Axis U", &axis_u1.x, -2, 2, "%.1f");
|
||||||
|
ImGui::SliderFloat3("Axis V", &axis_v1.x, -2, 2, "%.1f");
|
||||||
|
ImGui::SliderFloat2("UV0", &uv0_1.x, 0, 1, "%.2f");
|
||||||
|
ImGui::SliderFloat2("UV1", &uv1_1.x, 0, 1, "%.2f");
|
||||||
|
ImGui::ColorEdit4("Tint", &tint1.x);
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Image 2 Controls
|
||||||
|
if (ImGui::TreeNodeEx("Image 2 Controls: Full Quad")) {
|
||||||
|
ImGui::SliderFloat3("P0", &p0.x, -2, 2, "%.1f");
|
||||||
|
ImGui::SliderFloat3("P1", &p1.x, -2, 2, "%.1f");
|
||||||
|
ImGui::SliderFloat3("P2", &p2.x, -2, 2, "%.1f");
|
||||||
|
ImGui::SliderFloat3("P3", &p3.x, -2, 2, "%.1f");
|
||||||
|
|
||||||
|
ImGui::SliderFloat2("UV0", &uv0.x, 0, 1, "%.2f");
|
||||||
|
ImGui::SliderFloat2("UV1", &uv1.x, 0, 1, "%.2f");
|
||||||
|
ImGui::SliderFloat2("UV2", &uv2.x, 0, 1, "%.2f");
|
||||||
|
ImGui::SliderFloat2("UV3", &uv3.x, 0, 1, "%.2f");
|
||||||
|
|
||||||
|
ImGui::ColorEdit4("Tint##2", &tint2.x);
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plot
|
||||||
|
if (ImPlot3D::BeginPlot("Image Plot", ImVec2(-1, 0), ImPlot3DFlags_NoClip)) {
|
||||||
|
#ifdef IMGUI_HAS_TEXTURES
|
||||||
|
// We use the font atlas ImTextureRef for this demo, but in your real code when you submit
|
||||||
|
// an image that you have loaded yourself, you would normally have a ImTextureID which works
|
||||||
|
// just as well (as ImTextureRef can be constructed from ImTextureID).
|
||||||
|
ImTextureRef tex = ImGui::GetIO().Fonts->TexRef;
|
||||||
|
#else
|
||||||
|
ImTextureID tex = ImGui::GetIO().Fonts->TexID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ImPlot3D::PlotImage("Image 1", tex, center1, axis_u1, axis_v1, uv0_1, uv1_1, tint1);
|
||||||
|
ImPlot3D::PlotImage("Image 2", tex, p0, p1, p2, p3, uv0, uv1, uv2, uv3, tint2);
|
||||||
|
|
||||||
ImPlot3D::EndPlot();
|
ImPlot3D::EndPlot();
|
||||||
}
|
}
|
||||||
|
|
@ -470,7 +552,8 @@ void DemoMarkersAndText() {
|
||||||
|
|
||||||
if (ImPlot3D::BeginPlot("##MarkerStyles", ImVec2(-1, 0), ImPlot3DFlags_CanvasOnly)) {
|
if (ImPlot3D::BeginPlot("##MarkerStyles", ImVec2(-1, 0), ImPlot3DFlags_CanvasOnly)) {
|
||||||
|
|
||||||
ImPlot3D::SetupAxes(nullptr, nullptr, nullptr, ImPlot3DAxisFlags_NoDecorations, ImPlot3DAxisFlags_NoDecorations, ImPlot3DAxisFlags_NoDecorations);
|
ImPlot3D::SetupAxes(nullptr, nullptr, nullptr, ImPlot3DAxisFlags_NoDecorations, ImPlot3DAxisFlags_NoDecorations,
|
||||||
|
ImPlot3DAxisFlags_NoDecorations);
|
||||||
ImPlot3D::SetupAxesLimits(-0.5, 1.5, -0.5, 1.5, 0, ImPlot3DMarker_COUNT + 1);
|
ImPlot3D::SetupAxesLimits(-0.5, 1.5, -0.5, 1.5, 0, ImPlot3DMarker_COUNT + 1);
|
||||||
|
|
||||||
float xs[2] = {0, 0};
|
float xs[2] = {0, 0};
|
||||||
|
|
@ -565,8 +648,54 @@ void DemoBoxScale() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DemoBoxRotation() {
|
||||||
|
float origin[2] = {0.0f, 0.0f};
|
||||||
|
float axis[2] = {0.0f, 1.0f};
|
||||||
|
|
||||||
|
// Sliders for rotation angles
|
||||||
|
static float elevation = 45.0f;
|
||||||
|
static float azimuth = -135.0f;
|
||||||
|
static bool animate = false;
|
||||||
|
ImGui::Text("Rotation");
|
||||||
|
bool changed = false;
|
||||||
|
if (ImGui::SliderFloat("Elevation", &elevation, -90.0f, 90.0f, "%.1f degrees"))
|
||||||
|
changed = true;
|
||||||
|
if (ImGui::SliderFloat("Azimuth", &azimuth, -180.0f, 180.0f, "%.1f degrees"))
|
||||||
|
changed = true;
|
||||||
|
ImGui::Checkbox("Animate", &animate);
|
||||||
|
|
||||||
|
ImGui::Text("Initial Rotation");
|
||||||
|
ImGui::SameLine();
|
||||||
|
HelpMarker("The rotation will be reset to the initial rotation when you double right-click");
|
||||||
|
static float init_elevation = 45.0f;
|
||||||
|
static float init_azimuth = -135.0f;
|
||||||
|
ImGui::SliderFloat("Initial Elevation", &init_elevation, -90.0f, 90.0f, "%.1f degrees");
|
||||||
|
ImGui::SliderFloat("Initial Azimuth", &init_azimuth, -180.0f, 180.0f, "%.1f degrees");
|
||||||
|
|
||||||
|
if (ImPlot3D::BeginPlot("##BoxRotation")) {
|
||||||
|
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1, 1, ImPlot3DCond_Always);
|
||||||
|
|
||||||
|
// Set initial rotation
|
||||||
|
ImPlot3D::SetupBoxInitialRotation(init_elevation, init_azimuth);
|
||||||
|
|
||||||
|
// Set the rotation using the specified elevation and azimuth
|
||||||
|
if (changed)
|
||||||
|
ImPlot3D::SetupBoxRotation(elevation, azimuth, animate, ImPlot3DCond_Always);
|
||||||
|
|
||||||
|
// Plot axis lines
|
||||||
|
ImPlot3D::SetNextLineStyle(ImVec4(0.8f, 0.2f, 0.2f, 1));
|
||||||
|
ImPlot3D::PlotLine("X-Axis", axis, origin, origin, 2);
|
||||||
|
ImPlot3D::SetNextLineStyle(ImVec4(0.2f, 0.8f, 0.2f, 1));
|
||||||
|
ImPlot3D::PlotLine("Y-Axis", origin, axis, origin, 2);
|
||||||
|
ImPlot3D::SetNextLineStyle(ImVec4(0.2f, 0.2f, 0.8f, 1));
|
||||||
|
ImPlot3D::PlotLine("Z-Axis", origin, origin, axis, 2);
|
||||||
|
|
||||||
|
ImPlot3D::EndPlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DemoTickLabels() {
|
void DemoTickLabels() {
|
||||||
static bool custom_ticks = false;
|
static bool custom_ticks = true;
|
||||||
static bool custom_labels = true;
|
static bool custom_labels = true;
|
||||||
ImGui::Checkbox("Show Custom Ticks", &custom_ticks);
|
ImGui::Checkbox("Show Custom Ticks", &custom_ticks);
|
||||||
if (custom_ticks) {
|
if (custom_ticks) {
|
||||||
|
|
@ -588,6 +717,26 @@ void DemoTickLabels() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DemoAxisConstraints() {
|
||||||
|
static float limit_constraints[2] = {-10, 10};
|
||||||
|
static float zoom_constraints[2] = {1, 20};
|
||||||
|
static ImPlot3DAxisFlags flags;
|
||||||
|
ImGui::DragFloat2("Limits Constraints", limit_constraints, 0.01f);
|
||||||
|
ImGui::DragFloat2("Zoom Constraints", zoom_constraints, 0.01f);
|
||||||
|
CHECKBOX_FLAG(flags, ImPlot3DAxisFlags_PanStretch);
|
||||||
|
if (ImPlot3D::BeginPlot("##AxisConstraints", ImVec2(-1, 0))) {
|
||||||
|
ImPlot3D::SetupAxes("X", "Y", "Z", flags, flags, flags);
|
||||||
|
ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1, 1);
|
||||||
|
ImPlot3D::SetupAxisLimitsConstraints(ImAxis3D_X, limit_constraints[0], limit_constraints[1]);
|
||||||
|
ImPlot3D::SetupAxisLimitsConstraints(ImAxis3D_Y, limit_constraints[0], limit_constraints[1]);
|
||||||
|
ImPlot3D::SetupAxisLimitsConstraints(ImAxis3D_Z, limit_constraints[0], limit_constraints[1]);
|
||||||
|
ImPlot3D::SetupAxisZoomConstraints(ImAxis3D_X, zoom_constraints[0], zoom_constraints[1]);
|
||||||
|
ImPlot3D::SetupAxisZoomConstraints(ImAxis3D_Y, zoom_constraints[0], zoom_constraints[1]);
|
||||||
|
ImPlot3D::SetupAxisZoomConstraints(ImAxis3D_Z, zoom_constraints[0], zoom_constraints[1]);
|
||||||
|
ImPlot3D::EndPlot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Custom
|
// [SECTION] Custom
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -624,14 +773,8 @@ void DemoCustomRendering() {
|
||||||
|
|
||||||
// Draw box
|
// Draw box
|
||||||
ImPlot3DPoint corners[8] = {
|
ImPlot3DPoint corners[8] = {
|
||||||
ImPlot3DPoint(0, 0, 0),
|
ImPlot3DPoint(0, 0, 0), ImPlot3DPoint(1, 0, 0), ImPlot3DPoint(1, 1, 0), ImPlot3DPoint(0, 1, 0),
|
||||||
ImPlot3DPoint(1, 0, 0),
|
ImPlot3DPoint(0, 0, 1), ImPlot3DPoint(1, 0, 1), ImPlot3DPoint(1, 1, 1), ImPlot3DPoint(0, 1, 1),
|
||||||
ImPlot3DPoint(1, 1, 0),
|
|
||||||
ImPlot3DPoint(0, 1, 0),
|
|
||||||
ImPlot3DPoint(0, 0, 1),
|
|
||||||
ImPlot3DPoint(1, 0, 1),
|
|
||||||
ImPlot3DPoint(1, 1, 1),
|
|
||||||
ImPlot3DPoint(0, 1, 1),
|
|
||||||
};
|
};
|
||||||
ImVec2 corners_px[8];
|
ImVec2 corners_px[8];
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
|
|
@ -720,18 +863,57 @@ void DemoHeader(const char* label, void (*demo)()) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowAllDemos() {
|
||||||
|
ImGui::Text("ImPlot3D says olá! (%s)", IMPLOT3D_VERSION);
|
||||||
|
ImGui::Spacing();
|
||||||
|
if (ImGui::BeginTabBar("ImPlot3DDemoTabs")) {
|
||||||
|
if (ImGui::BeginTabItem("Plots")) {
|
||||||
|
DemoHeader("Line Plots", DemoLinePlots);
|
||||||
|
DemoHeader("Scatter Plots", DemoScatterPlots);
|
||||||
|
DemoHeader("Triangle Plots", DemoTrianglePlots);
|
||||||
|
DemoHeader("Quad Plots", DemoQuadPlots);
|
||||||
|
DemoHeader("Surface Plots", DemoSurfacePlots);
|
||||||
|
DemoHeader("Mesh Plots", DemoMeshPlots);
|
||||||
|
DemoHeader("Realtime Plots", DemoRealtimePlots);
|
||||||
|
DemoHeader("Image Plots", DemoImagePlots);
|
||||||
|
DemoHeader("Markers and Text", DemoMarkersAndText);
|
||||||
|
DemoHeader("NaN Values", DemoNaNValues);
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
if (ImGui::BeginTabItem("Axes")) {
|
||||||
|
DemoHeader("Box Scale", DemoBoxScale);
|
||||||
|
DemoHeader("Box Rotation", DemoBoxRotation);
|
||||||
|
DemoHeader("Tick Labels", DemoTickLabels);
|
||||||
|
DemoHeader("Axis Constraints", DemoAxisConstraints);
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
if (ImGui::BeginTabItem("Custom")) {
|
||||||
|
DemoHeader("Custom Styles", DemoCustomStyles);
|
||||||
|
DemoHeader("Custom Rendering", DemoCustomRendering);
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
if (ImGui::BeginTabItem("Help")) {
|
||||||
|
DemoHelp();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ShowDemoWindow(bool* p_open) {
|
void ShowDemoWindow(bool* p_open) {
|
||||||
|
static bool show_implot3d_metrics = false;
|
||||||
static bool show_implot3d_style_editor = false;
|
static bool show_implot3d_style_editor = false;
|
||||||
static bool show_imgui_metrics = false;
|
static bool show_imgui_metrics = false;
|
||||||
static bool show_imgui_style_editor = false;
|
static bool show_imgui_style_editor = false;
|
||||||
static bool show_imgui_demo = false;
|
static bool show_imgui_demo = false;
|
||||||
|
|
||||||
|
if (show_implot3d_metrics)
|
||||||
|
ImPlot3D::ShowMetricsWindow(&show_implot3d_metrics);
|
||||||
if (show_implot3d_style_editor) {
|
if (show_implot3d_style_editor) {
|
||||||
ImGui::Begin("Style Editor (ImPlot3D)", &show_implot3d_style_editor);
|
ImGui::Begin("Style Editor (ImPlot3D)", &show_implot3d_style_editor);
|
||||||
ImPlot3D::ShowStyleEditor();
|
ImPlot3D::ShowStyleEditor();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_imgui_style_editor) {
|
if (show_imgui_style_editor) {
|
||||||
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
|
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
|
||||||
ImGui::ShowStyleEditor();
|
ImGui::ShowStyleEditor();
|
||||||
|
|
@ -747,6 +929,7 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
ImGui::Begin("ImPlot3D Demo", p_open, ImGuiWindowFlags_MenuBar);
|
ImGui::Begin("ImPlot3D Demo", p_open, ImGuiWindowFlags_MenuBar);
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
if (ImGui::BeginMenu("Tools")) {
|
if (ImGui::BeginMenu("Tools")) {
|
||||||
|
ImGui::MenuItem("Metrics", nullptr, &show_implot3d_metrics);
|
||||||
ImGui::MenuItem("Style Editor", nullptr, &show_implot3d_style_editor);
|
ImGui::MenuItem("Style Editor", nullptr, &show_implot3d_style_editor);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::MenuItem("ImGui Metrics", nullptr, &show_imgui_metrics);
|
ImGui::MenuItem("ImGui Metrics", nullptr, &show_imgui_metrics);
|
||||||
|
|
@ -756,40 +939,7 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
}
|
}
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
ShowAllDemos();
|
||||||
ImGui::Text("ImPlot3D says olá! (%s)", IMPLOT3D_VERSION);
|
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("ImPlot3DDemoTabs")) {
|
|
||||||
if (ImGui::BeginTabItem("Plots")) {
|
|
||||||
DemoHeader("Line Plots", DemoLinePlots);
|
|
||||||
DemoHeader("Scatter Plots", DemoScatterPlots);
|
|
||||||
DemoHeader("Triangle Plots", DemoTrianglePlots);
|
|
||||||
DemoHeader("Quad Plots", DemoQuadPlots);
|
|
||||||
DemoHeader("Surface Plots", DemoSurfacePlots);
|
|
||||||
DemoHeader("Mesh Plots", DemoMeshPlots);
|
|
||||||
DemoHeader("Realtime Plots", DemoRealtimePlots);
|
|
||||||
DemoHeader("Markers and Text", DemoMarkersAndText);
|
|
||||||
DemoHeader("NaN Values", DemoNaNValues);
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginTabItem("Axes")) {
|
|
||||||
DemoHeader("Box Scale", DemoBoxScale);
|
|
||||||
DemoHeader("Tick Labels", DemoTickLabels);
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginTabItem("Custom")) {
|
|
||||||
DemoHeader("Custom Styles", DemoCustomStyles);
|
|
||||||
DemoHeader("Custom Rendering", DemoCustomRendering);
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginTabItem("Help")) {
|
|
||||||
DemoHelp();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
ImGui::EndTabBar();
|
|
||||||
}
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -811,43 +961,6 @@ bool ShowStyleSelector(const char* label) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const ImRect& bounds, bool vert, bool reversed, bool continuous) {
|
|
||||||
const int n = continuous ? size - 1 : size;
|
|
||||||
ImU32 col1, col2;
|
|
||||||
if (vert) {
|
|
||||||
const float step = bounds.GetHeight() / n;
|
|
||||||
ImRect rect(bounds.Min.x, bounds.Min.y, bounds.Max.x, bounds.Min.y + step);
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
if (reversed) {
|
|
||||||
col1 = colors[size - i - 1];
|
|
||||||
col2 = continuous ? colors[size - i - 2] : col1;
|
|
||||||
} else {
|
|
||||||
col1 = colors[i];
|
|
||||||
col2 = continuous ? colors[i + 1] : col1;
|
|
||||||
}
|
|
||||||
DrawList.AddRectFilledMultiColor(rect.Min, rect.Max, col1, col1, col2, col2);
|
|
||||||
rect.TranslateY(step);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const float step = bounds.GetWidth() / n;
|
|
||||||
ImRect rect(bounds.Min.x, bounds.Min.y, bounds.Min.x + step, bounds.Max.y);
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
if (reversed) {
|
|
||||||
col1 = colors[size - i - 1];
|
|
||||||
col2 = continuous ? colors[size - i - 2] : col1;
|
|
||||||
} else {
|
|
||||||
col1 = colors[i];
|
|
||||||
col2 = continuous ? colors[i + 1] : col1;
|
|
||||||
}
|
|
||||||
DrawList.AddRectFilledMultiColor(rect.Min, rect.Max, col1, col2, col2, col1);
|
|
||||||
rect.TranslateX(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299f + bg.y * 0.587f + bg.z * 0.114f) > 0.5f ? IM_COL32_BLACK : IM_COL32_WHITE; }
|
|
||||||
static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
|
|
||||||
|
|
||||||
bool ColormapButton(const char* label, const ImVec2& size_arg, ImPlot3DColormap cmap) {
|
bool ColormapButton(const char* label, const ImVec2& size_arg, ImPlot3DColormap cmap) {
|
||||||
ImGuiContext& G = *GImGui;
|
ImGuiContext& G = *GImGui;
|
||||||
const ImGuiStyle& style = G.Style;
|
const ImGuiStyle& style = G.Style;
|
||||||
|
|
@ -920,9 +1033,8 @@ void ShowStyleEditor(ImPlot3DStyle* ref) {
|
||||||
if (ImGui::Button("Revert Ref"))
|
if (ImGui::Button("Revert Ref"))
|
||||||
style = *ref;
|
style = *ref;
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
HelpMarker(
|
HelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
|
||||||
"Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
|
"Use \"Export\" below to save them somewhere.");
|
||||||
"Use \"Export\" below to save them somewhere.");
|
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
|
@ -958,8 +1070,8 @@ void ShowStyleEditor(ImPlot3DStyle* ref) {
|
||||||
const ImVec4& col = style.Colors[i];
|
const ImVec4& col = style.Colors[i];
|
||||||
const char* name = ImPlot3D::GetStyleColorName(i);
|
const char* name = ImPlot3D::GetStyleColorName(i);
|
||||||
if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
|
if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
|
||||||
ImGui::LogText("colors[ImPlot3DCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);\n",
|
ImGui::LogText("colors[ImPlot3DCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);\n", name, 15 - (int)strlen(name), "", col.x,
|
||||||
name, 15 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
|
col.y, col.z, col.w);
|
||||||
}
|
}
|
||||||
ImGui::LogFinish();
|
ImGui::LogFinish();
|
||||||
}
|
}
|
||||||
|
|
@ -973,6 +1085,17 @@ void ShowStyleEditor(ImPlot3DStyle* ref) {
|
||||||
filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
|
filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
|
||||||
|
|
||||||
static ImGuiColorEditFlags alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
|
static ImGuiColorEditFlags alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
|
||||||
|
#if IMGUI_VERSION_NUM < 19173
|
||||||
|
if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None))
|
||||||
|
alpha_flags = ImGuiColorEditFlags_None;
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview))
|
||||||
|
alpha_flags = ImGuiColorEditFlags_AlphaPreview;
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf))
|
||||||
|
alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
|
||||||
|
ImGui::SameLine();
|
||||||
|
#else
|
||||||
if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_AlphaOpaque))
|
if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_AlphaOpaque))
|
||||||
alpha_flags = ImGuiColorEditFlags_AlphaOpaque;
|
alpha_flags = ImGuiColorEditFlags_AlphaOpaque;
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
@ -982,10 +1105,10 @@ void ShowStyleEditor(ImPlot3DStyle* ref) {
|
||||||
if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf))
|
if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf))
|
||||||
alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
|
alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
HelpMarker(
|
#endif
|
||||||
"In the color list:\n"
|
HelpMarker("In the color list:\n"
|
||||||
"Left-click on color square to open color picker,\n"
|
"Left-click on color square to open color picker,\n"
|
||||||
"Right-click to open edit options menu.");
|
"Right-click to open edit options menu.");
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// ImPlot3D v0.1
|
// ImPlot3D v0.3 WIP
|
||||||
// implot3d_items.cpp
|
// implot3d_items.cpp
|
||||||
// Date: 2024-11-26
|
// Date: 2024-11-26
|
||||||
// Author: Breno Cunha Queiroz (brenocq.com)
|
// Author: Breno Cunha Queiroz (brenocq.com)
|
||||||
|
|
@ -25,6 +25,10 @@
|
||||||
// [SECTION] PlotScatter
|
// [SECTION] PlotScatter
|
||||||
// [SECTION] PlotLine
|
// [SECTION] PlotLine
|
||||||
// [SECTION] PlotTriangle
|
// [SECTION] PlotTriangle
|
||||||
|
// [SECTION] PlotQuad
|
||||||
|
// [SECTION] PlotSurface
|
||||||
|
// [SECTION] PlotMesh
|
||||||
|
// [SECTION] PlotImage
|
||||||
// [SECTION] PlotText
|
// [SECTION] PlotText
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
@ -67,14 +71,14 @@
|
||||||
#endif
|
#endif
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#define IMPLOT3D_NORMALIZE2F(VX, VY) \
|
#define IMPLOT3D_NORMALIZE2F(VX, VY) \
|
||||||
do { \
|
do { \
|
||||||
float d2 = VX * VX + VY * VY; \
|
float d2 = VX * VX + VY * VY; \
|
||||||
if (d2 > 0.0f) { \
|
if (d2 > 0.0f) { \
|
||||||
float inv_len = ImRsqrt(d2); \
|
float inv_len = ImRsqrt(d2); \
|
||||||
VX *= inv_len; \
|
VX *= inv_len; \
|
||||||
VY *= inv_len; \
|
VY *= inv_len; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
IMPLOT3D_INLINE void GetLineRenderProps(const ImDrawList3D& draw_list_3d, float& half_weight, ImVec2& tex_uv0, ImVec2& tex_uv1) {
|
IMPLOT3D_INLINE void GetLineRenderProps(const ImDrawList3D& draw_list_3d, float& half_weight, ImVec2& tex_uv0, ImVec2& tex_uv1) {
|
||||||
|
|
@ -109,7 +113,8 @@ IMPLOT3D_INLINE void GetLineRenderProps(const ImDrawList3D& draw_list_3d, float&
|
||||||
// As an example, you could use the compile time define given by the line below in order to support only float and double.
|
// As an example, you could use the compile time define given by the line below in order to support only float and double.
|
||||||
// -DIMPLOT3D_CUSTOM_NUMERIC_TYPES="(float)(double)"
|
// -DIMPLOT3D_CUSTOM_NUMERIC_TYPES="(float)(double)"
|
||||||
// In order to support all known C++ types, use:
|
// In order to support all known C++ types, use:
|
||||||
// -DIMPLOT3D_CUSTOM_NUMERIC_TYPES="(signed char)(unsigned char)(signed short)(unsigned short)(signed int)(unsigned int)(signed long)(unsigned long)(signed long long)(unsigned long long)(float)(double)(long double)"
|
// -DIMPLOT3D_CUSTOM_NUMERIC_TYPES="(signed char)(unsigned char)(signed short)(unsigned short)(signed int)(unsigned int)(signed long)(unsigned
|
||||||
|
// long)(signed long long)(unsigned long long)(float)(double)(long double)"
|
||||||
|
|
||||||
#ifdef IMPLOT3D_CUSTOM_NUMERIC_TYPES
|
#ifdef IMPLOT3D_CUSTOM_NUMERIC_TYPES
|
||||||
#define IMPLOT3D_NUMERIC_TYPES IMPLOT3D_CUSTOM_NUMERIC_TYPES
|
#define IMPLOT3D_NUMERIC_TYPES IMPLOT3D_CUSTOM_NUMERIC_TYPES
|
||||||
|
|
@ -148,6 +153,8 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolo
|
||||||
// Register item
|
// Register item
|
||||||
bool just_created;
|
bool just_created;
|
||||||
ImPlot3DItem* item = RegisterOrGetItem(label_id, flags, &just_created);
|
ImPlot3DItem* item = RegisterOrGetItem(label_id, flags, &just_created);
|
||||||
|
// Set current item
|
||||||
|
gp.CurrentItem = item;
|
||||||
|
|
||||||
// Set/override item color
|
// Set/override item color
|
||||||
if (recolor_from != -1) {
|
if (recolor_from != -1) {
|
||||||
|
|
@ -165,10 +172,20 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolo
|
||||||
ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color);
|
ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color);
|
||||||
n.IsAutoLine = IsColorAuto(n.Colors[ImPlot3DCol_Line]) && IsColorAuto(ImPlot3DCol_Line);
|
n.IsAutoLine = IsColorAuto(n.Colors[ImPlot3DCol_Line]) && IsColorAuto(ImPlot3DCol_Line);
|
||||||
n.IsAutoFill = IsColorAuto(n.Colors[ImPlot3DCol_Fill]) && IsColorAuto(ImPlot3DCol_Fill);
|
n.IsAutoFill = IsColorAuto(n.Colors[ImPlot3DCol_Fill]) && IsColorAuto(ImPlot3DCol_Fill);
|
||||||
n.Colors[ImPlot3DCol_Line] = IsColorAuto(n.Colors[ImPlot3DCol_Line]) ? (IsColorAuto(ImPlot3DCol_Line) ? item_color : gp.Style.Colors[ImPlot3DCol_Line]) : n.Colors[ImPlot3DCol_Line];
|
n.Colors[ImPlot3DCol_Line] = IsColorAuto(n.Colors[ImPlot3DCol_Line])
|
||||||
n.Colors[ImPlot3DCol_Fill] = IsColorAuto(n.Colors[ImPlot3DCol_Fill]) ? (IsColorAuto(ImPlot3DCol_Fill) ? item_color : gp.Style.Colors[ImPlot3DCol_Fill]) : n.Colors[ImPlot3DCol_Fill];
|
? (IsColorAuto(ImPlot3DCol_Line) ? item_color : gp.Style.Colors[ImPlot3DCol_Line])
|
||||||
n.Colors[ImPlot3DCol_MarkerOutline] = IsColorAuto(n.Colors[ImPlot3DCol_MarkerOutline]) ? (IsColorAuto(ImPlot3DCol_MarkerOutline) ? n.Colors[ImPlot3DCol_Line] : gp.Style.Colors[ImPlot3DCol_MarkerOutline]) : n.Colors[ImPlot3DCol_MarkerOutline];
|
: n.Colors[ImPlot3DCol_Line];
|
||||||
n.Colors[ImPlot3DCol_MarkerFill] = IsColorAuto(n.Colors[ImPlot3DCol_MarkerFill]) ? (IsColorAuto(ImPlot3DCol_MarkerFill) ? n.Colors[ImPlot3DCol_Line] : gp.Style.Colors[ImPlot3DCol_MarkerFill]) : n.Colors[ImPlot3DCol_MarkerFill];
|
n.Colors[ImPlot3DCol_Fill] = IsColorAuto(n.Colors[ImPlot3DCol_Fill])
|
||||||
|
? (IsColorAuto(ImPlot3DCol_Fill) ? item_color : gp.Style.Colors[ImPlot3DCol_Fill])
|
||||||
|
: n.Colors[ImPlot3DCol_Fill];
|
||||||
|
n.Colors[ImPlot3DCol_MarkerOutline] =
|
||||||
|
IsColorAuto(n.Colors[ImPlot3DCol_MarkerOutline])
|
||||||
|
? (IsColorAuto(ImPlot3DCol_MarkerOutline) ? n.Colors[ImPlot3DCol_Line] : gp.Style.Colors[ImPlot3DCol_MarkerOutline])
|
||||||
|
: n.Colors[ImPlot3DCol_MarkerOutline];
|
||||||
|
n.Colors[ImPlot3DCol_MarkerFill] =
|
||||||
|
IsColorAuto(n.Colors[ImPlot3DCol_MarkerFill])
|
||||||
|
? (IsColorAuto(ImPlot3DCol_MarkerFill) ? n.Colors[ImPlot3DCol_Line] : gp.Style.Colors[ImPlot3DCol_MarkerFill])
|
||||||
|
: n.Colors[ImPlot3DCol_MarkerFill];
|
||||||
|
|
||||||
// Set size & weight
|
// Set size & weight
|
||||||
n.LineWeight = n.LineWeight < 0.0f ? style.LineWeight : n.LineWeight;
|
n.LineWeight = n.LineWeight < 0.0f ? style.LineWeight : n.LineWeight;
|
||||||
|
|
@ -222,6 +239,7 @@ bool BeginItemEx(const char* label_id, const _Getter& getter, ImPlot3DItemFlags
|
||||||
void EndItem() {
|
void EndItem() {
|
||||||
ImPlot3DContext& gp = *GImPlot3D;
|
ImPlot3DContext& gp = *GImPlot3D;
|
||||||
gp.NextItemData.Reset();
|
gp.NextItemData.Reset();
|
||||||
|
gp.CurrentItem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImPlot3DItem* RegisterOrGetItem(const char* label_id, ImPlot3DItemFlags flags, bool* just_created) {
|
ImPlot3DItem* RegisterOrGetItem(const char* label_id, ImPlot3DItemFlags flags, bool* just_created) {
|
||||||
|
|
@ -248,6 +266,11 @@ ImPlot3DItem* RegisterOrGetItem(const char* label_id, ImPlot3DItemFlags flags, b
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImPlot3DItem* GetCurrentItem() {
|
||||||
|
ImPlot3DContext& gp = *GImPlot3D;
|
||||||
|
return gp.CurrentItem;
|
||||||
|
}
|
||||||
|
|
||||||
void BustItemCache() {
|
void BustItemCache() {
|
||||||
ImPlot3DContext& gp = *GImPlot3D;
|
ImPlot3DContext& gp = *GImPlot3D;
|
||||||
for (int p = 0; p < gp.Plots.GetBufSize(); ++p) {
|
for (int p = 0; p < gp.Plots.GetBufSize(); ++p) {
|
||||||
|
|
@ -284,7 +307,8 @@ void SetNextMarkerStyle(ImPlot3DMarker marker, float size, const ImVec4& fill, f
|
||||||
// [SECTION] Draw Utils
|
// [SECTION] Draw Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
IMPLOT3D_INLINE void PrimLine(ImDrawList3D& draw_list_3d, const ImVec2& P1, const ImVec2& P2, float half_weight, ImU32 col, const ImVec2& tex_uv0, const ImVec2 tex_uv1, float z) {
|
IMPLOT3D_INLINE void PrimLine(ImDrawList3D& draw_list_3d, const ImVec2& P1, const ImVec2& P2, float half_weight, ImU32 col, const ImVec2& tex_uv0,
|
||||||
|
const ImVec2& tex_uv1, float z) {
|
||||||
float dx = P2.x - P1.x;
|
float dx = P2.x - P1.x;
|
||||||
float dy = P2.y - P1.y;
|
float dy = P2.y - P1.y;
|
||||||
IMPLOT3D_NORMALIZE2F(dx, dy);
|
IMPLOT3D_NORMALIZE2F(dx, dy);
|
||||||
|
|
@ -327,30 +351,31 @@ IMPLOT3D_INLINE void PrimLine(ImDrawList3D& draw_list_3d, const ImVec2& P1, cons
|
||||||
float GetPointDepth(ImPlot3DPoint p) {
|
float GetPointDepth(ImPlot3DPoint p) {
|
||||||
ImPlot3DContext& gp = *GImPlot3D;
|
ImPlot3DContext& gp = *GImPlot3D;
|
||||||
ImPlot3DPlot& plot = *gp.CurrentPlot;
|
ImPlot3DPlot& plot = *gp.CurrentPlot;
|
||||||
|
|
||||||
|
// Adjust for inverted axes before rotation
|
||||||
|
if (ImHasFlag(plot.Axes[0].Flags, ImPlot3DAxisFlags_Invert))
|
||||||
|
p.x = -p.x;
|
||||||
|
if (ImHasFlag(plot.Axes[1].Flags, ImPlot3DAxisFlags_Invert))
|
||||||
|
p.y = -p.y;
|
||||||
|
if (ImHasFlag(plot.Axes[2].Flags, ImPlot3DAxisFlags_Invert))
|
||||||
|
p.z = -p.z;
|
||||||
|
|
||||||
ImPlot3DPoint p_rot = plot.Rotation * p;
|
ImPlot3DPoint p_rot = plot.Rotation * p;
|
||||||
return p_rot.z;
|
return p_rot.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RendererBase {
|
struct RendererBase {
|
||||||
RendererBase(int prims, int idx_consumed, int vtx_consumed) : Prims(prims),
|
RendererBase(int prims, int idx_consumed, int vtx_consumed) : Prims(prims), IdxConsumed(idx_consumed), VtxConsumed(vtx_consumed) {}
|
||||||
IdxConsumed(idx_consumed),
|
|
||||||
VtxConsumed(vtx_consumed) {}
|
|
||||||
const unsigned int Prims; // Number of primitives to render
|
const unsigned int Prims; // Number of primitives to render
|
||||||
const unsigned int IdxConsumed; // Number of indices consumed per primitive
|
const unsigned int IdxConsumed; // Number of indices consumed per primitive
|
||||||
const unsigned int VtxConsumed; // Number of vertices consumed per primitive
|
const unsigned int VtxConsumed; // Number of vertices consumed per primitive
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererMarkersFill : RendererBase {
|
||||||
struct RendererMarkersFill : RendererBase {
|
RendererMarkersFill(const _Getter& getter, const ImVec2* marker, int count, float size, ImU32 col)
|
||||||
RendererMarkersFill(const _Getter& getter, const ImVec2* marker, int count, float size, ImU32 col) : RendererBase(getter.Count, (count - 2) * 3, count),
|
: RendererBase(getter.Count, (count - 2) * 3, count), Getter(getter), Marker(marker), Count(count), Size(size), Col(col) {}
|
||||||
Getter(getter),
|
|
||||||
Marker(marker),
|
void Init(ImDrawList3D& draw_list_3d) const { UV = draw_list_3d._SharedData->TexUvWhitePixel; }
|
||||||
Count(count),
|
|
||||||
Size(size),
|
|
||||||
Col(col) {}
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
|
||||||
UV = draw_list_3d._SharedData->TexUvWhitePixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
ImPlot3DPoint p_plot = Getter(prim);
|
ImPlot3DPoint p_plot = Getter(prim);
|
||||||
|
|
@ -388,13 +413,12 @@ struct RendererMarkersFill : RendererBase {
|
||||||
mutable ImVec2 UV;
|
mutable ImVec2 UV;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererMarkersLine : RendererBase {
|
||||||
struct RendererMarkersLine : RendererBase {
|
RendererMarkersLine(const _Getter& getter, const ImVec2* marker, int count, float size, float weight, ImU32 col)
|
||||||
RendererMarkersLine(const _Getter& getter, const ImVec2* marker, int count, float size, float weight, ImU32 col) : RendererBase(getter.Count, count / 2 * 6, count / 2 * 4), Getter(getter), Marker(marker), Count(count), HalfWeight(ImMax(1.0f, weight) * 0.5f), Size(size), Col(col) {}
|
: RendererBase(getter.Count, count / 2 * 6, count / 2 * 4), Getter(getter), Marker(marker), Count(count),
|
||||||
|
HalfWeight(ImMax(1.0f, weight) * 0.5f), Size(size), Col(col) {}
|
||||||
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
void Init(ImDrawList3D& draw_list_3d) const { GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1); }
|
||||||
GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
ImPlot3DPoint p_plot = Getter(prim);
|
ImPlot3DPoint p_plot = Getter(prim);
|
||||||
|
|
@ -419,20 +443,14 @@ struct RendererMarkersLine : RendererBase {
|
||||||
mutable ImVec2 UV1;
|
mutable ImVec2 UV1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererLineStrip : RendererBase {
|
||||||
struct RendererLineStrip : RendererBase {
|
|
||||||
RendererLineStrip(const _Getter& getter, ImU32 col, float weight)
|
RendererLineStrip(const _Getter& getter, ImU32 col, float weight)
|
||||||
: RendererBase(getter.Count - 1, 6, 4),
|
: RendererBase(getter.Count - 1, 6, 4), Getter(getter), Col(col), HalfWeight(ImMax(1.0f, weight) * 0.5f) {
|
||||||
Getter(getter),
|
|
||||||
Col(col),
|
|
||||||
HalfWeight(ImMax(1.0f, weight) * 0.5f) {
|
|
||||||
// Initialize the first point in plot coordinates
|
// Initialize the first point in plot coordinates
|
||||||
P1_plot = Getter(0);
|
P1_plot = Getter(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
void Init(ImDrawList3D& draw_list_3d) const { GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1); }
|
||||||
GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
ImPlot3DPoint P2_plot = Getter(prim + 1);
|
ImPlot3DPoint P2_plot = Getter(prim + 1);
|
||||||
|
|
@ -463,20 +481,14 @@ struct RendererLineStrip : RendererBase {
|
||||||
mutable ImVec2 UV1;
|
mutable ImVec2 UV1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererLineStripSkip : RendererBase {
|
||||||
struct RendererLineStripSkip : RendererBase {
|
|
||||||
RendererLineStripSkip(const _Getter& getter, ImU32 col, float weight)
|
RendererLineStripSkip(const _Getter& getter, ImU32 col, float weight)
|
||||||
: RendererBase(getter.Count - 1, 6, 4),
|
: RendererBase(getter.Count - 1, 6, 4), Getter(getter), Col(col), HalfWeight(ImMax(1.0f, weight) * 0.5f) {
|
||||||
Getter(getter),
|
|
||||||
Col(col),
|
|
||||||
HalfWeight(ImMax(1.0f, weight) * 0.5f) {
|
|
||||||
// Initialize the first point in plot coordinates
|
// Initialize the first point in plot coordinates
|
||||||
P1_plot = Getter(0);
|
P1_plot = Getter(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
void Init(ImDrawList3D& draw_list_3d) const { GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1); }
|
||||||
GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
// Get the next point in plot coordinates
|
// Get the next point in plot coordinates
|
||||||
|
|
@ -484,8 +496,7 @@ struct RendererLineStripSkip : RendererBase {
|
||||||
bool visible = false;
|
bool visible = false;
|
||||||
|
|
||||||
// Check for NaNs in P1_plot and P2_plot
|
// Check for NaNs in P1_plot and P2_plot
|
||||||
if (!ImNan(P1_plot.x) && !ImNan(P1_plot.y) && !ImNan(P1_plot.z) &&
|
if (!ImNan(P1_plot.x) && !ImNan(P1_plot.y) && !ImNan(P1_plot.z) && !ImNan(P2_plot.x) && !ImNan(P2_plot.y) && !ImNan(P2_plot.z)) {
|
||||||
!ImNan(P2_plot.x) && !ImNan(P2_plot.y) && !ImNan(P2_plot.z)) {
|
|
||||||
|
|
||||||
// Clip the line segment to the culling box
|
// Clip the line segment to the culling box
|
||||||
ImPlot3DPoint P1_clipped, P2_clipped;
|
ImPlot3DPoint P1_clipped, P2_clipped;
|
||||||
|
|
@ -515,17 +526,11 @@ struct RendererLineStripSkip : RendererBase {
|
||||||
mutable ImVec2 UV1;
|
mutable ImVec2 UV1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererLineSegments : RendererBase {
|
||||||
struct RendererLineSegments : RendererBase {
|
|
||||||
RendererLineSegments(const _Getter& getter, ImU32 col, float weight)
|
RendererLineSegments(const _Getter& getter, ImU32 col, float weight)
|
||||||
: RendererBase(getter.Count / 2, 6, 4),
|
: RendererBase(getter.Count / 2, 6, 4), Getter(getter), Col(col), HalfWeight(ImMax(1.0f, weight) * 0.5f) {}
|
||||||
Getter(getter),
|
|
||||||
Col(col),
|
|
||||||
HalfWeight(ImMax(1.0f, weight) * 0.5f) {}
|
|
||||||
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
void Init(ImDrawList3D& draw_list_3d) const { GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1); }
|
||||||
GetLineRenderProps(draw_list_3d, HalfWeight, UV0, UV1);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
// Get the segment's endpoints in plot coordinates
|
// Get the segment's endpoints in plot coordinates
|
||||||
|
|
@ -533,8 +538,7 @@ struct RendererLineSegments : RendererBase {
|
||||||
ImPlot3DPoint P2_plot = Getter(prim * 2 + 1);
|
ImPlot3DPoint P2_plot = Getter(prim * 2 + 1);
|
||||||
|
|
||||||
// Check for NaNs in P1_plot and P2_plot
|
// Check for NaNs in P1_plot and P2_plot
|
||||||
if (!ImNan(P1_plot.x) && !ImNan(P1_plot.y) && !ImNan(P1_plot.z) &&
|
if (!ImNan(P1_plot.x) && !ImNan(P1_plot.y) && !ImNan(P1_plot.z) && !ImNan(P2_plot.x) && !ImNan(P2_plot.y) && !ImNan(P2_plot.z)) {
|
||||||
!ImNan(P2_plot.x) && !ImNan(P2_plot.y) && !ImNan(P2_plot.z)) {
|
|
||||||
|
|
||||||
// Clip the line segment to the culling box
|
// Clip the line segment to the culling box
|
||||||
ImPlot3DPoint P1_clipped, P2_clipped;
|
ImPlot3DPoint P1_clipped, P2_clipped;
|
||||||
|
|
@ -560,14 +564,10 @@ struct RendererLineSegments : RendererBase {
|
||||||
mutable ImVec2 UV1;
|
mutable ImVec2 UV1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererTriangleFill : RendererBase {
|
||||||
struct RendererTriangleFill : RendererBase {
|
RendererTriangleFill(const _Getter& getter, ImU32 col) : RendererBase(getter.Count / 3, 3, 3), Getter(getter), Col(col) {}
|
||||||
RendererTriangleFill(const _Getter& getter, ImU32 col) : RendererBase(getter.Count / 3, 3, 3),
|
|
||||||
Getter(getter),
|
void Init(ImDrawList3D& draw_list_3d) const { UV = draw_list_3d._SharedData->TexUvWhitePixel; }
|
||||||
Col(col) {}
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
|
||||||
UV = draw_list_3d._SharedData->TexUvWhitePixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
ImPlot3DPoint p_plot[3];
|
ImPlot3DPoint p_plot[3];
|
||||||
|
|
@ -576,7 +576,7 @@ struct RendererTriangleFill : RendererBase {
|
||||||
p_plot[2] = Getter(3 * prim + 2);
|
p_plot[2] = Getter(3 * prim + 2);
|
||||||
|
|
||||||
// Check if the triangle is outside the culling box
|
// Check if the triangle is outside the culling box
|
||||||
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]))
|
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]) && !cull_box.Contains(p_plot[2]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Project the triangle vertices to screen space
|
// Project the triangle vertices to screen space
|
||||||
|
|
@ -620,14 +620,10 @@ struct RendererTriangleFill : RendererBase {
|
||||||
const ImU32 Col;
|
const ImU32 Col;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererQuadFill : RendererBase {
|
||||||
struct RendererQuadFill : RendererBase {
|
RendererQuadFill(const _Getter& getter, ImU32 col) : RendererBase(getter.Count / 4, 6, 4), Getter(getter), Col(col) {}
|
||||||
RendererQuadFill(const _Getter& getter, ImU32 col) : RendererBase(getter.Count / 4, 6, 4),
|
|
||||||
Getter(getter),
|
void Init(ImDrawList3D& draw_list_3d) const { UV = draw_list_3d._SharedData->TexUvWhitePixel; }
|
||||||
Col(col) {}
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
|
||||||
UV = draw_list_3d._SharedData->TexUvWhitePixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
ImPlot3DPoint p_plot[4];
|
ImPlot3DPoint p_plot[4];
|
||||||
|
|
@ -637,8 +633,7 @@ struct RendererQuadFill : RendererBase {
|
||||||
p_plot[3] = Getter(4 * prim + 3);
|
p_plot[3] = Getter(4 * prim + 3);
|
||||||
|
|
||||||
// Check if the quad is outside the culling box
|
// Check if the quad is outside the culling box
|
||||||
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]) &&
|
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]) && !cull_box.Contains(p_plot[2]) && !cull_box.Contains(p_plot[3]))
|
||||||
!cull_box.Contains(p_plot[2]) && !cull_box.Contains(p_plot[3]))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Project the quad vertices to screen space
|
// Project the quad vertices to screen space
|
||||||
|
|
@ -682,9 +677,10 @@ struct RendererQuadFill : RendererBase {
|
||||||
|
|
||||||
draw_list_3d._IdxWritePtr += 6;
|
draw_list_3d._IdxWritePtr += 6;
|
||||||
|
|
||||||
// Add depth values for the two triangles
|
// Add depth value for the quad
|
||||||
draw_list_3d._ZWritePtr[0] = GetPointDepth((p_plot[0] + p_plot[1] + p_plot[2]) / 3.0f);
|
float z = GetPointDepth((p_plot[0] + p_plot[1] + p_plot[2] + p_plot[3]) / 4.0f);
|
||||||
draw_list_3d._ZWritePtr[1] = GetPointDepth((p_plot[0] + p_plot[2] + p_plot[3]) / 3.0f);
|
draw_list_3d._ZWritePtr[0] = z;
|
||||||
|
draw_list_3d._ZWritePtr[1] = z;
|
||||||
draw_list_3d._ZWritePtr += 2;
|
draw_list_3d._ZWritePtr += 2;
|
||||||
|
|
||||||
// Update vertex count
|
// Update vertex count
|
||||||
|
|
@ -698,15 +694,93 @@ struct RendererQuadFill : RendererBase {
|
||||||
const ImU32 Col;
|
const ImU32 Col;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Getter>
|
template <class _Getter> struct RendererQuadImage : RendererBase {
|
||||||
struct RendererSurfaceFill : RendererBase {
|
RendererQuadImage(const _Getter& getter, ImTextureRef tex_ref, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3,
|
||||||
RendererSurfaceFill(const _Getter& getter, int x_count, int y_count, ImU32 col, double scale_min, double scale_max) : RendererBase((x_count - 1) * (y_count - 1), 6, 4),
|
ImU32 col)
|
||||||
Getter(getter),
|
: RendererBase(getter.Count / 4, 6, 4), Getter(getter), TexRef(tex_ref), UV0(uv0), UV1(uv1), UV2(uv2), UV3(uv3), Col(col) {}
|
||||||
XCount(x_count),
|
|
||||||
YCount(y_count),
|
void Init(ImDrawList3D& draw_list_3d) const {}
|
||||||
Col(col),
|
|
||||||
ScaleMin(scale_min),
|
IMPLOT3D_INLINE bool Render(ImDrawList3D& draw_list_3d, const ImPlot3DBox& cull_box, int prim) const {
|
||||||
ScaleMax(scale_max) {}
|
ImPlot3DPoint p_plot[4];
|
||||||
|
p_plot[0] = Getter(4 * prim);
|
||||||
|
p_plot[1] = Getter(4 * prim + 1);
|
||||||
|
p_plot[2] = Getter(4 * prim + 2);
|
||||||
|
p_plot[3] = Getter(4 * prim + 3);
|
||||||
|
|
||||||
|
// Check if the quad is outside the culling box
|
||||||
|
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]) && !cull_box.Contains(p_plot[2]) && !cull_box.Contains(p_plot[3]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Set texture ID to be used when rendering this quad
|
||||||
|
draw_list_3d.SetTexture(TexRef);
|
||||||
|
|
||||||
|
// Project the quad vertices to screen space
|
||||||
|
ImVec2 p[4];
|
||||||
|
p[0] = PlotToPixels(p_plot[0]);
|
||||||
|
p[1] = PlotToPixels(p_plot[1]);
|
||||||
|
p[2] = PlotToPixels(p_plot[2]);
|
||||||
|
p[3] = PlotToPixels(p_plot[3]);
|
||||||
|
|
||||||
|
// Add vertices for two triangles
|
||||||
|
draw_list_3d._VtxWritePtr[0].pos.x = p[0].x;
|
||||||
|
draw_list_3d._VtxWritePtr[0].pos.y = p[0].y;
|
||||||
|
draw_list_3d._VtxWritePtr[0].uv = UV0;
|
||||||
|
draw_list_3d._VtxWritePtr[0].col = Col;
|
||||||
|
|
||||||
|
draw_list_3d._VtxWritePtr[1].pos.x = p[1].x;
|
||||||
|
draw_list_3d._VtxWritePtr[1].pos.y = p[1].y;
|
||||||
|
draw_list_3d._VtxWritePtr[1].uv = UV1;
|
||||||
|
draw_list_3d._VtxWritePtr[1].col = Col;
|
||||||
|
|
||||||
|
draw_list_3d._VtxWritePtr[2].pos.x = p[2].x;
|
||||||
|
draw_list_3d._VtxWritePtr[2].pos.y = p[2].y;
|
||||||
|
draw_list_3d._VtxWritePtr[2].uv = UV2;
|
||||||
|
draw_list_3d._VtxWritePtr[2].col = Col;
|
||||||
|
|
||||||
|
draw_list_3d._VtxWritePtr[3].pos.x = p[3].x;
|
||||||
|
draw_list_3d._VtxWritePtr[3].pos.y = p[3].y;
|
||||||
|
draw_list_3d._VtxWritePtr[3].uv = UV3;
|
||||||
|
draw_list_3d._VtxWritePtr[3].col = Col;
|
||||||
|
|
||||||
|
draw_list_3d._VtxWritePtr += 4;
|
||||||
|
|
||||||
|
// Add indices for two triangles
|
||||||
|
draw_list_3d._IdxWritePtr[0] = (ImDrawIdx)(draw_list_3d._VtxCurrentIdx);
|
||||||
|
draw_list_3d._IdxWritePtr[1] = (ImDrawIdx)(draw_list_3d._VtxCurrentIdx + 1);
|
||||||
|
draw_list_3d._IdxWritePtr[2] = (ImDrawIdx)(draw_list_3d._VtxCurrentIdx + 2);
|
||||||
|
|
||||||
|
draw_list_3d._IdxWritePtr[3] = (ImDrawIdx)(draw_list_3d._VtxCurrentIdx);
|
||||||
|
draw_list_3d._IdxWritePtr[4] = (ImDrawIdx)(draw_list_3d._VtxCurrentIdx + 2);
|
||||||
|
draw_list_3d._IdxWritePtr[5] = (ImDrawIdx)(draw_list_3d._VtxCurrentIdx + 3);
|
||||||
|
|
||||||
|
draw_list_3d._IdxWritePtr += 6;
|
||||||
|
|
||||||
|
// Add depth value for the quad
|
||||||
|
float z = GetPointDepth((p_plot[0] + p_plot[1] + p_plot[2] + p_plot[3]) / 4.0f);
|
||||||
|
draw_list_3d._ZWritePtr[0] = z;
|
||||||
|
draw_list_3d._ZWritePtr[1] = z;
|
||||||
|
draw_list_3d._ZWritePtr += 2;
|
||||||
|
|
||||||
|
// Update vertex count
|
||||||
|
draw_list_3d._VtxCurrentIdx += 4;
|
||||||
|
|
||||||
|
// Reset texture ID
|
||||||
|
draw_list_3d.ResetTexture();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Getter& Getter;
|
||||||
|
const ImTextureRef TexRef;
|
||||||
|
const ImVec2 UV0, UV1, UV2, UV3;
|
||||||
|
const ImU32 Col;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class _Getter> struct RendererSurfaceFill : RendererBase {
|
||||||
|
RendererSurfaceFill(const _Getter& getter, int x_count, int y_count, ImU32 col, double scale_min, double scale_max)
|
||||||
|
: RendererBase((x_count - 1) * (y_count - 1), 6, 4), Getter(getter), XCount(x_count), YCount(y_count), Col(col), ScaleMin(scale_min),
|
||||||
|
ScaleMax(scale_max) {}
|
||||||
|
|
||||||
void Init(ImDrawList3D& draw_list_3d) const {
|
void Init(ImDrawList3D& draw_list_3d) const {
|
||||||
UV = draw_list_3d._SharedData->TexUvWhitePixel;
|
UV = draw_list_3d._SharedData->TexUvWhitePixel;
|
||||||
|
|
@ -735,8 +809,7 @@ struct RendererSurfaceFill : RendererBase {
|
||||||
p_plot[3] = Getter(x + (y + 1) * XCount);
|
p_plot[3] = Getter(x + (y + 1) * XCount);
|
||||||
|
|
||||||
// Check if the quad is outside the culling box
|
// Check if the quad is outside the culling box
|
||||||
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]) &&
|
if (!cull_box.Contains(p_plot[0]) && !cull_box.Contains(p_plot[1]) && !cull_box.Contains(p_plot[2]) && !cull_box.Contains(p_plot[3]))
|
||||||
!cull_box.Contains(p_plot[2]) && !cull_box.Contains(p_plot[3]))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compute colors
|
// Compute colors
|
||||||
|
|
@ -824,27 +897,20 @@ struct RendererSurfaceFill : RendererBase {
|
||||||
// [SECTION] Indexers
|
// [SECTION] Indexers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> IMPLOT3D_INLINE T IndexData(const T* data, int idx, int count, int offset, int stride) {
|
||||||
IMPLOT3D_INLINE T IndexData(const T* data, int idx, int count, int offset, int stride) {
|
|
||||||
const int s = ((offset == 0) << 0) | ((stride == sizeof(T)) << 1);
|
const int s = ((offset == 0) << 0) | ((stride == sizeof(T)) << 1);
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case 3: return data[idx];
|
case 3: return data[idx];
|
||||||
case 2: return data[(offset + idx) % count];
|
case 2: return data[(offset + idx) % count];
|
||||||
case 1: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx)) * stride);
|
case 1: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx))*stride);
|
||||||
case 0: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((offset + idx) % count) * stride);
|
case 0: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((offset + idx) % count) * stride);
|
||||||
default: return T(0);
|
default: return T(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct IndexerIdx {
|
||||||
struct IndexerIdx {
|
IndexerIdx(const T* data, int count, int offset = 0, int stride = sizeof(T)) : Data(data), Count(count), Offset(offset), Stride(stride) {}
|
||||||
IndexerIdx(const T* data, int count, int offset = 0, int stride = sizeof(T)) : Data(data),
|
template <typename I> IMPLOT3D_INLINE double operator()(I idx) const { return (double)IndexData(Data, idx, Count, Offset, Stride); }
|
||||||
Count(count),
|
|
||||||
Offset(offset),
|
|
||||||
Stride(stride) {}
|
|
||||||
template <typename I> IMPLOT3D_INLINE double operator()(I idx) const {
|
|
||||||
return (double)IndexData(Data, idx, Count, Offset, Stride);
|
|
||||||
}
|
|
||||||
const T* Data;
|
const T* Data;
|
||||||
int Count;
|
int Count;
|
||||||
int Offset;
|
int Offset;
|
||||||
|
|
@ -855,8 +921,7 @@ struct IndexerIdx {
|
||||||
// [SECTION] Getters
|
// [SECTION] Getters
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename _IndexerX, typename _IndexerY, typename _IndexerZ>
|
template <typename _IndexerX, typename _IndexerY, typename _IndexerZ> struct GetterXYZ {
|
||||||
struct GetterXYZ {
|
|
||||||
GetterXYZ(_IndexerX x, _IndexerY y, _IndexerZ z, int count) : IndexerX(x), IndexerY(y), IndexerZ(z), Count(count) {}
|
GetterXYZ(_IndexerX x, _IndexerY y, _IndexerZ z, int count) : IndexerX(x), IndexerY(y), IndexerZ(z), Count(count) {}
|
||||||
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
||||||
return ImPlot3DPoint((float)IndexerX(idx), (float)IndexerY(idx), (float)IndexerZ(idx));
|
return ImPlot3DPoint((float)IndexerX(idx), (float)IndexerY(idx), (float)IndexerZ(idx));
|
||||||
|
|
@ -867,8 +932,7 @@ struct GetterXYZ {
|
||||||
const int Count;
|
const int Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> struct GetterLoop {
|
||||||
struct GetterLoop {
|
|
||||||
GetterLoop(_Getter getter) : Getter(getter), Count(getter.Count + 1) {}
|
GetterLoop(_Getter getter) : Getter(getter), Count(getter.Count + 1) {}
|
||||||
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
||||||
idx = idx % (Count - 1);
|
idx = idx % (Count - 1);
|
||||||
|
|
@ -878,8 +942,7 @@ struct GetterLoop {
|
||||||
const int Count;
|
const int Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> struct GetterTriangleLines {
|
||||||
struct GetterTriangleLines {
|
|
||||||
GetterTriangleLines(_Getter getter) : Getter(getter), Count(getter.Count * 2) {}
|
GetterTriangleLines(_Getter getter) : Getter(getter), Count(getter.Count * 2) {}
|
||||||
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
||||||
idx = ((idx % 6 + 1) / 2) % 3 + idx / 6 * 3;
|
idx = ((idx % 6 + 1) / 2) % 3 + idx / 6 * 3;
|
||||||
|
|
@ -889,8 +952,7 @@ struct GetterTriangleLines {
|
||||||
const int Count;
|
const int Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> struct GetterQuadLines {
|
||||||
struct GetterQuadLines {
|
|
||||||
GetterQuadLines(_Getter getter) : Getter(getter), Count(getter.Count * 2) {}
|
GetterQuadLines(_Getter getter) : Getter(getter), Count(getter.Count * 2) {}
|
||||||
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
||||||
idx = ((idx % 8 + 1) / 2) % 4 + idx / 8 * 4;
|
idx = ((idx % 8 + 1) / 2) % 4 + idx / 8 * 4;
|
||||||
|
|
@ -900,10 +962,8 @@ struct GetterQuadLines {
|
||||||
const int Count;
|
const int Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> struct GetterSurfaceLines {
|
||||||
struct GetterSurfaceLines {
|
GetterSurfaceLines(_Getter getter, int x_count, int y_count) : Getter(getter), XCount(x_count), YCount(y_count) {
|
||||||
GetterSurfaceLines(_Getter getter, int x_count, int y_count)
|
|
||||||
: Getter(getter), XCount(x_count), YCount(y_count) {
|
|
||||||
int horizontal_segments = (XCount - 1) * YCount;
|
int horizontal_segments = (XCount - 1) * YCount;
|
||||||
int vertical_segments = (YCount - 1) * XCount;
|
int vertical_segments = (YCount - 1) * XCount;
|
||||||
int segments = horizontal_segments + vertical_segments;
|
int segments = horizontal_segments + vertical_segments;
|
||||||
|
|
@ -946,9 +1006,7 @@ struct GetterSurfaceLines {
|
||||||
|
|
||||||
struct Getter3DPoints {
|
struct Getter3DPoints {
|
||||||
Getter3DPoints(const ImPlot3DPoint* points, int count) : Points(points), Count(count) {}
|
Getter3DPoints(const ImPlot3DPoint* points, int count) : Points(points), Count(count) {}
|
||||||
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const {
|
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I idx) const { return Points[idx]; }
|
||||||
return Points[idx];
|
|
||||||
}
|
|
||||||
const ImPlot3DPoint* Points;
|
const ImPlot3DPoint* Points;
|
||||||
const int Count;
|
const int Count;
|
||||||
};
|
};
|
||||||
|
|
@ -957,8 +1015,7 @@ struct GetterMeshTriangles {
|
||||||
GetterMeshTriangles(const ImPlot3DPoint* vtx, const unsigned int* idx, int idx_count)
|
GetterMeshTriangles(const ImPlot3DPoint* vtx, const unsigned int* idx, int idx_count)
|
||||||
: Vtx(vtx), Idx(idx), IdxCount(idx_count), TriCount(idx_count / 3), Count(idx_count) {}
|
: Vtx(vtx), Idx(idx), IdxCount(idx_count), TriCount(idx_count / 3), Count(idx_count) {}
|
||||||
|
|
||||||
template <typename I>
|
template <typename I> IMPLOT3D_INLINE ImPlot3DPoint operator()(I i) const {
|
||||||
IMPLOT3D_INLINE ImPlot3DPoint operator()(I i) const {
|
|
||||||
unsigned int vi = Idx[i];
|
unsigned int vi = Idx[i];
|
||||||
return Vtx[vi];
|
return Vtx[vi];
|
||||||
}
|
}
|
||||||
|
|
@ -975,8 +1032,7 @@ struct GetterMeshTriangles {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Renders primitive shapes
|
/// Renders primitive shapes
|
||||||
template <template <class> class _Renderer, class _Getter, typename... Args>
|
template <template <class> class _Renderer, class _Getter, typename... Args> void RenderPrimitives(const _Getter& getter, Args... args) {
|
||||||
void RenderPrimitives(const _Getter& getter, Args... args) {
|
|
||||||
_Renderer<_Getter> renderer(getter, args...);
|
_Renderer<_Getter> renderer(getter, args...);
|
||||||
ImPlot3DPlot& plot = *GetCurrentPlot();
|
ImPlot3DPlot& plot = *GetCurrentPlot();
|
||||||
ImDrawList3D& draw_list_3d = plot.DrawList;
|
ImDrawList3D& draw_list_3d = plot.DrawList;
|
||||||
|
|
@ -1011,46 +1067,64 @@ void RenderPrimitives(const _Getter& getter, Args... args) {
|
||||||
// [SECTION] Markers
|
// [SECTION] Markers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static const ImVec2 MARKER_FILL_CIRCLE[10] = {ImVec2(1.0f, 0.0f), ImVec2(0.809017f, 0.58778524f), ImVec2(0.30901697f, 0.95105654f), ImVec2(-0.30901703f, 0.9510565f), ImVec2(-0.80901706f, 0.5877852f), ImVec2(-1.0f, 0.0f), ImVec2(-0.80901694f, -0.58778536f), ImVec2(-0.3090171f, -0.9510565f), ImVec2(0.30901712f, -0.9510565f), ImVec2(0.80901694f, -0.5877853f)};
|
static const ImVec2 MARKER_FILL_CIRCLE[10] = {ImVec2(1.0f, 0.0f),
|
||||||
static const ImVec2 MARKER_FILL_SQUARE[4] = {ImVec2(SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, SQRT_1_2)};
|
ImVec2(0.809017f, 0.58778524f),
|
||||||
|
ImVec2(0.30901697f, 0.95105654f),
|
||||||
|
ImVec2(-0.30901703f, 0.9510565f),
|
||||||
|
ImVec2(-0.80901706f, 0.5877852f),
|
||||||
|
ImVec2(-1.0f, 0.0f),
|
||||||
|
ImVec2(-0.80901694f, -0.58778536f),
|
||||||
|
ImVec2(-0.3090171f, -0.9510565f),
|
||||||
|
ImVec2(0.30901712f, -0.9510565f),
|
||||||
|
ImVec2(0.80901694f, -0.5877853f)};
|
||||||
|
static const ImVec2 MARKER_FILL_SQUARE[4] = {ImVec2(SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, -SQRT_1_2),
|
||||||
|
ImVec2(-SQRT_1_2, SQRT_1_2)};
|
||||||
static const ImVec2 MARKER_FILL_DIAMOND[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};
|
static const ImVec2 MARKER_FILL_DIAMOND[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)};
|
||||||
static const ImVec2 MARKER_FILL_UP[3] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(-SQRT_3_2, 0.5f)};
|
static const ImVec2 MARKER_FILL_UP[3] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(-SQRT_3_2, 0.5f)};
|
||||||
static const ImVec2 MARKER_FILL_DOWN[3] = {ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f)};
|
static const ImVec2 MARKER_FILL_DOWN[3] = {ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f)};
|
||||||
static const ImVec2 MARKER_FILL_LEFT[3] = {ImVec2(-1, 0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2)};
|
static const ImVec2 MARKER_FILL_LEFT[3] = {ImVec2(-1, 0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2)};
|
||||||
static const ImVec2 MARKER_FILL_RIGHT[3] = {ImVec2(1, 0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2)};
|
static const ImVec2 MARKER_FILL_RIGHT[3] = {ImVec2(1, 0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2)};
|
||||||
static const ImVec2 MARKER_LINE_CIRCLE[20] = {
|
static const ImVec2 MARKER_LINE_CIRCLE[20] = {ImVec2(1.0f, 0.0f),
|
||||||
ImVec2(1.0f, 0.0f),
|
ImVec2(0.809017f, 0.58778524f),
|
||||||
ImVec2(0.809017f, 0.58778524f),
|
ImVec2(0.809017f, 0.58778524f),
|
||||||
ImVec2(0.809017f, 0.58778524f),
|
ImVec2(0.30901697f, 0.95105654f),
|
||||||
ImVec2(0.30901697f, 0.95105654f),
|
ImVec2(0.30901697f, 0.95105654f),
|
||||||
ImVec2(0.30901697f, 0.95105654f),
|
ImVec2(-0.30901703f, 0.9510565f),
|
||||||
ImVec2(-0.30901703f, 0.9510565f),
|
ImVec2(-0.30901703f, 0.9510565f),
|
||||||
ImVec2(-0.30901703f, 0.9510565f),
|
ImVec2(-0.80901706f, 0.5877852f),
|
||||||
ImVec2(-0.80901706f, 0.5877852f),
|
ImVec2(-0.80901706f, 0.5877852f),
|
||||||
ImVec2(-0.80901706f, 0.5877852f),
|
ImVec2(-1.0f, 0.0f),
|
||||||
ImVec2(-1.0f, 0.0f),
|
ImVec2(-1.0f, 0.0f),
|
||||||
ImVec2(-1.0f, 0.0f),
|
ImVec2(-0.80901694f, -0.58778536f),
|
||||||
ImVec2(-0.80901694f, -0.58778536f),
|
ImVec2(-0.80901694f, -0.58778536f),
|
||||||
ImVec2(-0.80901694f, -0.58778536f),
|
ImVec2(-0.3090171f, -0.9510565f),
|
||||||
ImVec2(-0.3090171f, -0.9510565f),
|
ImVec2(-0.3090171f, -0.9510565f),
|
||||||
ImVec2(-0.3090171f, -0.9510565f),
|
ImVec2(0.30901712f, -0.9510565f),
|
||||||
ImVec2(0.30901712f, -0.9510565f),
|
ImVec2(0.30901712f, -0.9510565f),
|
||||||
ImVec2(0.30901712f, -0.9510565f),
|
ImVec2(0.80901694f, -0.5877853f),
|
||||||
ImVec2(0.80901694f, -0.5877853f),
|
ImVec2(0.80901694f, -0.5877853f),
|
||||||
ImVec2(0.80901694f, -0.5877853f),
|
ImVec2(1.0f, 0.0f)};
|
||||||
ImVec2(1.0f, 0.0f)};
|
static const ImVec2 MARKER_LINE_SQUARE[8] = {ImVec2(SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2),
|
||||||
static const ImVec2 MARKER_LINE_SQUARE[8] = {ImVec2(SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, SQRT_1_2), ImVec2(-SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, SQRT_1_2)};
|
ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, SQRT_1_2),
|
||||||
static const ImVec2 MARKER_LINE_DIAMOND[8] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(-1, 0), ImVec2(0, 1), ImVec2(0, 1), ImVec2(1, 0)};
|
ImVec2(-SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, SQRT_1_2)};
|
||||||
static const ImVec2 MARKER_LINE_UP[6] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(0, -1), ImVec2(-SQRT_3_2, 0.5f), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, 0.5f)};
|
static const ImVec2 MARKER_LINE_DIAMOND[8] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, -1), ImVec2(-1, 0),
|
||||||
static const ImVec2 MARKER_LINE_DOWN[6] = {ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f), ImVec2(-SQRT_3_2, -0.5f), ImVec2(SQRT_3_2, -0.5f)};
|
ImVec2(-1, 0), ImVec2(0, 1), ImVec2(0, 1), ImVec2(1, 0)};
|
||||||
static const ImVec2 MARKER_LINE_LEFT[6] = {ImVec2(-1, 0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2), ImVec2(0.5, -SQRT_3_2), ImVec2(-1, 0)};
|
static const ImVec2 MARKER_LINE_UP[6] = {ImVec2(SQRT_3_2, 0.5f), ImVec2(0, -1), ImVec2(0, -1),
|
||||||
static const ImVec2 MARKER_LINE_RIGHT[6] = {ImVec2(1, 0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(1, 0)};
|
ImVec2(-SQRT_3_2, 0.5f), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, 0.5f)};
|
||||||
static const ImVec2 MARKER_LINE_ASTERISK[6] = {ImVec2(-SQRT_3_2, -0.5f), ImVec2(SQRT_3_2, 0.5f), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, -0.5f), ImVec2(0, -1), ImVec2(0, 1)};
|
static const ImVec2 MARKER_LINE_DOWN[6] = {ImVec2(SQRT_3_2, -0.5f), ImVec2(0, 1), ImVec2(0, 1), ImVec2(-SQRT_3_2, -0.5f),
|
||||||
|
ImVec2(-SQRT_3_2, -0.5f), ImVec2(SQRT_3_2, -0.5f)};
|
||||||
|
static const ImVec2 MARKER_LINE_LEFT[6] = {ImVec2(-1, 0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, SQRT_3_2),
|
||||||
|
ImVec2(0.5, -SQRT_3_2), ImVec2(0.5, -SQRT_3_2), ImVec2(-1, 0)};
|
||||||
|
static const ImVec2 MARKER_LINE_RIGHT[6] = {
|
||||||
|
ImVec2(1, 0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(1, 0)};
|
||||||
|
static const ImVec2 MARKER_LINE_ASTERISK[6] = {ImVec2(-SQRT_3_2, -0.5f), ImVec2(SQRT_3_2, 0.5f), ImVec2(-SQRT_3_2, 0.5f),
|
||||||
|
ImVec2(SQRT_3_2, -0.5f), ImVec2(0, -1), ImVec2(0, 1)};
|
||||||
static const ImVec2 MARKER_LINE_PLUS[4] = {ImVec2(-1, 0), ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, 1)};
|
static const ImVec2 MARKER_LINE_PLUS[4] = {ImVec2(-1, 0), ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, 1)};
|
||||||
static const ImVec2 MARKER_LINE_CROSS[4] = {ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2), ImVec2(-SQRT_1_2, SQRT_1_2)};
|
static const ImVec2 MARKER_LINE_CROSS[4] = {ImVec2(-SQRT_1_2, -SQRT_1_2), ImVec2(SQRT_1_2, SQRT_1_2), ImVec2(SQRT_1_2, -SQRT_1_2),
|
||||||
|
ImVec2(-SQRT_1_2, SQRT_1_2)};
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> void RenderMarkers(const _Getter& getter, ImPlot3DMarker marker, float size, bool rend_fill, ImU32 col_fill,
|
||||||
void RenderMarkers(const _Getter& getter, ImPlot3DMarker marker, float size, bool rend_fill, ImU32 col_fill, bool rend_line, ImU32 col_line, float weight) {
|
bool rend_line, ImU32 col_line, float weight) {
|
||||||
if (rend_fill) {
|
if (rend_fill) {
|
||||||
switch (marker) {
|
switch (marker) {
|
||||||
case ImPlot3DMarker_Circle: RenderPrimitives<RendererMarkersFill>(getter, MARKER_FILL_CIRCLE, 10, size, col_fill); break;
|
case ImPlot3DMarker_Circle: RenderPrimitives<RendererMarkersFill>(getter, MARKER_FILL_CIRCLE, 10, size, col_fill); break;
|
||||||
|
|
@ -1082,8 +1156,7 @@ void RenderMarkers(const _Getter& getter, ImPlot3DMarker marker, float size, boo
|
||||||
// [SECTION] PlotScatter
|
// [SECTION] PlotScatter
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename Getter>
|
template <typename Getter> void PlotScatterEx(const char* label_id, const Getter& getter, ImPlot3DScatterFlags flags) {
|
||||||
void PlotScatterEx(const char* label_id, const Getter& getter, ImPlot3DScatterFlags flags) {
|
|
||||||
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_MarkerOutline)) {
|
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_MarkerOutline)) {
|
||||||
const ImPlot3DNextItemData& n = GetItemData();
|
const ImPlot3DNextItemData& n = GetItemData();
|
||||||
ImPlot3DMarker marker = n.Marker == ImPlot3DMarker_None ? ImPlot3DMarker_Circle : n.Marker;
|
ImPlot3DMarker marker = n.Marker == ImPlot3DMarker_None ? ImPlot3DMarker_Circle : n.Marker;
|
||||||
|
|
@ -1099,12 +1172,14 @@ template <typename T>
|
||||||
void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags, int offset, int stride) {
|
void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags, int offset, int stride) {
|
||||||
if (count < 1)
|
if (count < 1)
|
||||||
return;
|
return;
|
||||||
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride), IndexerIdx<T>(zs, count, offset, stride), count);
|
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride),
|
||||||
|
IndexerIdx<T>(zs, count, offset, stride), count);
|
||||||
return PlotScatterEx(label_id, getter, flags);
|
return PlotScatterEx(label_id, getter, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSTANTIATE_MACRO(T) \
|
#define INSTANTIATE_MACRO(T) \
|
||||||
template IMPLOT3D_API void PlotScatter<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags, int offset, int stride);
|
template IMPLOT3D_API void PlotScatter<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags, \
|
||||||
|
int offset, int stride);
|
||||||
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
#undef INSTANTIATE_MACRO
|
#undef INSTANTIATE_MACRO
|
||||||
|
|
||||||
|
|
@ -1112,8 +1187,7 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
// [SECTION] PlotLine
|
// [SECTION] PlotLine
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> void PlotLineEx(const char* label_id, const _Getter& getter, ImPlot3DLineFlags flags) {
|
||||||
void PlotLineEx(const char* label_id, const _Getter& getter, ImPlot3DLineFlags flags) {
|
|
||||||
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Line)) {
|
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Line)) {
|
||||||
const ImPlot3DNextItemData& n = GetItemData();
|
const ImPlot3DNextItemData& n = GetItemData();
|
||||||
if (getter.Count >= 2 && n.RenderLine) {
|
if (getter.Count >= 2 && n.RenderLine) {
|
||||||
|
|
@ -1146,12 +1220,14 @@ void PlotLineEx(const char* label_id, const _Getter& getter, ImPlot3DLineFlags f
|
||||||
IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags, int offset, int stride) {
|
IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags, int offset, int stride) {
|
||||||
if (count < 2)
|
if (count < 2)
|
||||||
return;
|
return;
|
||||||
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride), IndexerIdx<T>(zs, count, offset, stride), count);
|
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride),
|
||||||
|
IndexerIdx<T>(zs, count, offset, stride), count);
|
||||||
return PlotLineEx(label_id, getter, flags);
|
return PlotLineEx(label_id, getter, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSTANTIATE_MACRO(T) \
|
#define INSTANTIATE_MACRO(T) \
|
||||||
template IMPLOT3D_API void PlotLine<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags, int offset, int stride);
|
template IMPLOT3D_API void PlotLine<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags, \
|
||||||
|
int offset, int stride);
|
||||||
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
#undef INSTANTIATE_MACRO
|
#undef INSTANTIATE_MACRO
|
||||||
|
|
||||||
|
|
@ -1159,25 +1235,24 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
// [SECTION] PlotTriangle
|
// [SECTION] PlotTriangle
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> void PlotTriangleEx(const char* label_id, const _Getter& getter, ImPlot3DTriangleFlags flags) {
|
||||||
void PlotTriangleEx(const char* label_id, const _Getter& getter, ImPlot3DTriangleFlags flags) {
|
|
||||||
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) {
|
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) {
|
||||||
const ImPlot3DNextItemData& n = GetItemData();
|
const ImPlot3DNextItemData& n = GetItemData();
|
||||||
|
|
||||||
// Render fill
|
// Render fill
|
||||||
if (getter.Count >= 3 && n.RenderFill) {
|
if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoFill)) {
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
||||||
RenderPrimitives<RendererTriangleFill>(getter, col_fill);
|
RenderPrimitives<RendererTriangleFill>(getter, col_fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render lines
|
// Render lines
|
||||||
if (getter.Count >= 2 && n.RenderLine) {
|
if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoLines)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
||||||
RenderPrimitives<RendererLineSegments>(GetterTriangleLines<_Getter>(getter), col_line, n.LineWeight);
|
RenderPrimitives<RendererLineSegments>(GetterTriangleLines<_Getter>(getter), col_line, n.LineWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render markers
|
// Render markers
|
||||||
if (n.Marker != ImPlot3DMarker_None) {
|
if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoMarkers)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
||||||
RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
||||||
|
|
@ -1187,15 +1262,18 @@ void PlotTriangleEx(const char* label_id, const _Getter& getter, ImPlot3DTriangl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags, int offset, int stride) {
|
IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags, int offset,
|
||||||
|
int stride) {
|
||||||
if (count < 3)
|
if (count < 3)
|
||||||
return;
|
return;
|
||||||
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride), IndexerIdx<T>(zs, count, offset, stride), count);
|
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride),
|
||||||
|
IndexerIdx<T>(zs, count, offset, stride), count);
|
||||||
return PlotTriangleEx(label_id, getter, flags);
|
return PlotTriangleEx(label_id, getter, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSTANTIATE_MACRO(T) \
|
#define INSTANTIATE_MACRO(T) \
|
||||||
template IMPLOT3D_API void PlotTriangle<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags, int offset, int stride);
|
template IMPLOT3D_API void PlotTriangle<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags, \
|
||||||
|
int offset, int stride);
|
||||||
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
#undef INSTANTIATE_MACRO
|
#undef INSTANTIATE_MACRO
|
||||||
|
|
||||||
|
|
@ -1203,25 +1281,24 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
// [SECTION] PlotQuad
|
// [SECTION] PlotQuad
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> void PlotQuadEx(const char* label_id, const _Getter& getter, ImPlot3DQuadFlags flags) {
|
||||||
void PlotQuadEx(const char* label_id, const _Getter& getter, ImPlot3DQuadFlags flags) {
|
|
||||||
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) {
|
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) {
|
||||||
const ImPlot3DNextItemData& n = GetItemData();
|
const ImPlot3DNextItemData& n = GetItemData();
|
||||||
|
|
||||||
// Render fill
|
// Render fill
|
||||||
if (getter.Count >= 4 && n.RenderFill) {
|
if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(flags, ImPlot3DQuadFlags_NoFill)) {
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
||||||
RenderPrimitives<RendererQuadFill>(getter, col_fill);
|
RenderPrimitives<RendererQuadFill>(getter, col_fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render lines
|
// Render lines
|
||||||
if (getter.Count >= 2 && n.RenderLine) {
|
if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DQuadFlags_NoLines)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
||||||
RenderPrimitives<RendererLineSegments>(GetterQuadLines<_Getter>(getter), col_line, n.LineWeight);
|
RenderPrimitives<RendererLineSegments>(GetterQuadLines<_Getter>(getter), col_line, n.LineWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render markers
|
// Render markers
|
||||||
if (n.Marker != ImPlot3DMarker_None) {
|
if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DQuadFlags_NoMarkers)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
||||||
RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
||||||
|
|
@ -1234,12 +1311,14 @@ void PlotQuadEx(const char* label_id, const _Getter& getter, ImPlot3DQuadFlags f
|
||||||
IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags, int offset, int stride) {
|
IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags, int offset, int stride) {
|
||||||
if (count < 3)
|
if (count < 3)
|
||||||
return;
|
return;
|
||||||
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride), IndexerIdx<T>(zs, count, offset, stride), count);
|
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride),
|
||||||
|
IndexerIdx<T>(zs, count, offset, stride), count);
|
||||||
return PlotQuadEx(label_id, getter, flags);
|
return PlotQuadEx(label_id, getter, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSTANTIATE_MACRO(T) \
|
#define INSTANTIATE_MACRO(T) \
|
||||||
template IMPLOT3D_API void PlotQuad<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags, int offset, int stride);
|
template IMPLOT3D_API void PlotQuad<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags, \
|
||||||
|
int offset, int stride);
|
||||||
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
#undef INSTANTIATE_MACRO
|
#undef INSTANTIATE_MACRO
|
||||||
|
|
||||||
|
|
@ -1247,25 +1326,25 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
// [SECTION] PlotSurface
|
// [SECTION] PlotSurface
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename _Getter>
|
template <typename _Getter> void PlotSurfaceEx(const char* label_id, const _Getter& getter, int x_count, int y_count, double scale_min,
|
||||||
void PlotSurfaceEx(const char* label_id, const _Getter& getter, int x_count, int y_count, double scale_min, double scale_max, ImPlot3DSurfaceFlags flags) {
|
double scale_max, ImPlot3DSurfaceFlags flags) {
|
||||||
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) {
|
if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) {
|
||||||
const ImPlot3DNextItemData& n = GetItemData();
|
const ImPlot3DNextItemData& n = GetItemData();
|
||||||
|
|
||||||
// Render fill
|
// Render fill
|
||||||
if (getter.Count >= 4 && n.RenderFill) {
|
if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoFill)) {
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
||||||
RenderPrimitives<RendererSurfaceFill>(getter, x_count, y_count, col_fill, scale_min, scale_max);
|
RenderPrimitives<RendererSurfaceFill>(getter, x_count, y_count, col_fill, scale_min, scale_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render lines
|
// Render lines
|
||||||
if (getter.Count >= 2 && n.RenderLine) {
|
if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoLines)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
||||||
RenderPrimitives<RendererLineSegments>(GetterSurfaceLines<_Getter>(getter, x_count, y_count), col_line, n.LineWeight);
|
RenderPrimitives<RendererLineSegments>(GetterSurfaceLines<_Getter>(getter, x_count, y_count), col_line, n.LineWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render markers
|
// Render markers
|
||||||
if (n.Marker != ImPlot3DMarker_None) {
|
if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoMarkers)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
||||||
RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
||||||
|
|
@ -1275,19 +1354,26 @@ void PlotSurfaceEx(const char* label_id, const _Getter& getter, int x_count, int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min, double scale_max, ImPlot3DSurfaceFlags flags, int offset, int stride) {
|
IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min,
|
||||||
|
double scale_max, ImPlot3DSurfaceFlags flags, int offset, int stride) {
|
||||||
int count = x_count * y_count;
|
int count = x_count * y_count;
|
||||||
if (count < 4)
|
if (count < 4)
|
||||||
return;
|
return;
|
||||||
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride), IndexerIdx<T>(zs, count, offset, stride), count);
|
GetterXYZ<IndexerIdx<T>, IndexerIdx<T>, IndexerIdx<T>> getter(IndexerIdx<T>(xs, count, offset, stride), IndexerIdx<T>(ys, count, offset, stride),
|
||||||
|
IndexerIdx<T>(zs, count, offset, stride), count);
|
||||||
return PlotSurfaceEx(label_id, getter, x_count, y_count, scale_min, scale_max, flags);
|
return PlotSurfaceEx(label_id, getter, x_count, y_count, scale_min, scale_max, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSTANTIATE_MACRO(T) \
|
#define INSTANTIATE_MACRO(T) \
|
||||||
template IMPLOT3D_API void PlotSurface<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min, double scale_max, ImPlot3DSurfaceFlags flags, int offset, int stride);
|
template IMPLOT3D_API void PlotSurface<T>(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, \
|
||||||
|
double scale_min, double scale_max, ImPlot3DSurfaceFlags flags, int offset, int stride);
|
||||||
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
|
||||||
#undef INSTANTIATE_MACRO
|
#undef INSTANTIATE_MACRO
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] PlotMesh
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, ImPlot3DMeshFlags flags) {
|
void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, ImPlot3DMeshFlags flags) {
|
||||||
Getter3DPoints getter(vtx, vtx_count); // Get vertices
|
Getter3DPoints getter(vtx, vtx_count); // Get vertices
|
||||||
GetterMeshTriangles getter_triangles(vtx, idx, idx_count); // Get triangle vertices
|
GetterMeshTriangles getter_triangles(vtx, idx, idx_count); // Get triangle vertices
|
||||||
|
|
@ -1295,19 +1381,19 @@ void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int
|
||||||
const ImPlot3DNextItemData& n = GetItemData();
|
const ImPlot3DNextItemData& n = GetItemData();
|
||||||
|
|
||||||
// Render fill
|
// Render fill
|
||||||
if (getter.Count >= 3 && n.RenderFill) {
|
if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(flags, ImPlot3DMeshFlags_NoFill)) {
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]);
|
||||||
RenderPrimitives<RendererTriangleFill>(getter_triangles, col_fill);
|
RenderPrimitives<RendererTriangleFill>(getter_triangles, col_fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render lines
|
// Render lines
|
||||||
if (getter.Count >= 2 && n.RenderLine && !n.IsAutoLine) {
|
if (getter.Count >= 2 && n.RenderLine && !n.IsAutoLine && !ImHasFlag(flags, ImPlot3DMeshFlags_NoLines)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]);
|
||||||
RenderPrimitives<RendererLineSegments>(GetterTriangleLines<GetterMeshTriangles>(getter_triangles), col_line, n.LineWeight);
|
RenderPrimitives<RendererLineSegments>(GetterTriangleLines<GetterMeshTriangles>(getter_triangles), col_line, n.LineWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render markers
|
// Render markers
|
||||||
if (n.Marker != ImPlot3DMarker_None) {
|
if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DMeshFlags_NoMarkers)) {
|
||||||
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]);
|
||||||
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]);
|
||||||
RenderMarkers(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
RenderMarkers(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight);
|
||||||
|
|
@ -1317,6 +1403,57 @@ void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] PlotImage
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& center, const ImPlot3DPoint& axis_u,
|
||||||
|
const ImPlot3DPoint& axis_v, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlot3DImageFlags flags) {
|
||||||
|
// Compute corners from center and axes
|
||||||
|
ImPlot3DPoint p0 = center - axis_u - axis_v; // Bottom-left
|
||||||
|
ImPlot3DPoint p1 = center + axis_u - axis_v; // Bottom-right
|
||||||
|
ImPlot3DPoint p2 = center + axis_u + axis_v; // Top-right
|
||||||
|
ImPlot3DPoint p3 = center - axis_u + axis_v; // Top-left
|
||||||
|
|
||||||
|
// Map ImPlot-style 2-point UVs into full 4-corner UVs
|
||||||
|
ImVec2 uv_0 = uv0;
|
||||||
|
ImVec2 uv_1 = ImVec2(uv1.x, uv0.y);
|
||||||
|
ImVec2 uv_2 = uv1;
|
||||||
|
ImVec2 uv_3 = ImVec2(uv0.x, uv1.y);
|
||||||
|
|
||||||
|
// Delegate to full quad version
|
||||||
|
PlotImage(label_id, tex_ref, p0, p1, p2, p3, uv_0, uv_1, uv_2, uv_3, tint_col, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& p0, const ImPlot3DPoint& p1, const ImPlot3DPoint& p2,
|
||||||
|
const ImPlot3DPoint& p3, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3,
|
||||||
|
const ImVec4& tint_col, ImPlot3DImageFlags flags) {
|
||||||
|
ImPlot3DContext& gp = *GImPlot3D;
|
||||||
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotImage() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
SetupLock();
|
||||||
|
|
||||||
|
ImPlot3DPoint corners[4] = {p0, p1, p2, p3};
|
||||||
|
Getter3DPoints getter(corners, 4);
|
||||||
|
|
||||||
|
// Invert Y from UVs
|
||||||
|
ImVec2 uv_0 = ImVec2(uv0.x, 1 - uv0.y);
|
||||||
|
ImVec2 uv_1 = ImVec2(uv1.x, 1 - uv1.y);
|
||||||
|
ImVec2 uv_2 = ImVec2(uv2.x, 1 - uv2.y);
|
||||||
|
ImVec2 uv_3 = ImVec2(uv3.x, 1 - uv3.y);
|
||||||
|
|
||||||
|
if (BeginItemEx(label_id, getter, flags)) {
|
||||||
|
ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col);
|
||||||
|
GetCurrentItem()->Color = tint_col32;
|
||||||
|
|
||||||
|
// Render image
|
||||||
|
bool is_transparent = (tint_col32 & IM_COL32_A_MASK) == 0;
|
||||||
|
if (!is_transparent)
|
||||||
|
RenderPrimitives<RendererQuadImage>(getter, tex_ref, uv_0, uv_1, uv_2, uv_3, tint_col32);
|
||||||
|
|
||||||
|
EndItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] PlotText
|
// [SECTION] PlotText
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -530,7 +530,6 @@ namespace hex::init {
|
||||||
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
|
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
|
||||||
cfg.SizePixels = ImHexApi::Fonts::DefaultFontSize;
|
cfg.SizePixels = ImHexApi::Fonts::DefaultFontSize;
|
||||||
io.Fonts->AddFontDefault(&cfg);
|
io.Fonts->AddFontDefault(&cfg);
|
||||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't save window settings for the splash screen
|
// Don't save window settings for the splash screen
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ namespace hex {
|
||||||
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
|
||||||
glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE);
|
glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE);
|
||||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||||||
|
glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::initNative() {
|
void Window::initNative() {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
#include <implot3d_internal.h>
|
#include <implot3d_internal.h>
|
||||||
#include <imnodes.h>
|
#include <imnodes.h>
|
||||||
#include <imnodes_internal.h>
|
#include <imnodes_internal.h>
|
||||||
|
|
||||||
#if defined(IMGUI_TEST_ENGINE)
|
#if defined(IMGUI_TEST_ENGINE)
|
||||||
#include <imgui_te_engine.h>
|
#include <imgui_te_engine.h>
|
||||||
#include <imgui_te_ui.h>
|
#include <imgui_te_ui.h>
|
||||||
|
|
@ -352,61 +353,12 @@ namespace hex {
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplGlfw_NewFrame();
|
||||||
|
|
||||||
// Create font textures if necessary
|
|
||||||
{
|
|
||||||
const auto &fontDefinitions = ImHexApi::Fonts::impl::getFontDefinitions();
|
|
||||||
auto ¤tFont = ImGui::GetIO().Fonts;
|
|
||||||
for (const auto &[name, font] : fontDefinitions) {
|
|
||||||
// If the texture for this atlas has been built already, don't do it again
|
|
||||||
if (font == nullptr || font->ContainerAtlas == nullptr || font->ContainerAtlas->TexID != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
currentFont = font->ContainerAtlas;
|
|
||||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
|
||||||
|
|
||||||
for (ImFontConfig& fontCfg : font->ContainerAtlas->Sources) {
|
|
||||||
if (fontCfg.FontData && fontCfg.FontDataOwnedByAtlas) {
|
|
||||||
IM_FREE(fontCfg.FontData);
|
|
||||||
fontCfg.FontData = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentFont->ClearTexData();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto font = ImHexApi::Fonts::getFont("hex.fonts.font.default");
|
|
||||||
|
|
||||||
if (font == nullptr) {
|
|
||||||
const auto &io = ImGui::GetIO();
|
|
||||||
io.Fonts->Clear();
|
|
||||||
|
|
||||||
ImFontConfig cfg;
|
|
||||||
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
|
|
||||||
cfg.SizePixels = ImHexApi::Fonts::DefaultFontSize;
|
|
||||||
font = io.Fonts->AddFontDefault(&cfg);
|
|
||||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
|
||||||
|
|
||||||
for (ImFontConfig& fontCfg : font->ContainerAtlas->Sources) {
|
|
||||||
if (fontCfg.FontData && fontCfg.FontDataOwnedByAtlas) {
|
|
||||||
IM_FREE(fontCfg.FontData);
|
|
||||||
fontCfg.FontData = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
io.Fonts->ClearTexData();
|
|
||||||
} else {
|
|
||||||
currentFont = font->ContainerAtlas;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SetCurrentFont(font);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start new ImGui Frame
|
// Start new ImGui Frame
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
|
ImHexApi::Fonts::getDefaultFont().push();
|
||||||
|
|
||||||
#if defined(IMGUI_TEST_ENGINE)
|
#if defined(IMGUI_TEST_ENGINE)
|
||||||
if (ImGuiExt::ImGuiTestEngine::isEnabled())
|
if (ImGuiExt::ImGuiTestEngine::isEnabled())
|
||||||
ImGuiTestEngine_ShowTestEngineWindows(m_testEngine, nullptr);
|
ImGuiTestEngine_ShowTestEngineWindows(m_testEngine, nullptr);
|
||||||
|
|
@ -802,6 +754,8 @@ namespace hex {
|
||||||
|
|
||||||
this->endNativeWindowFrame();
|
this->endNativeWindowFrame();
|
||||||
|
|
||||||
|
ImHexApi::Fonts::getDefaultFont().pop();
|
||||||
|
|
||||||
// Finalize ImGui frame
|
// Finalize ImGui frame
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
||||||
|
|
@ -968,7 +922,7 @@ namespace hex {
|
||||||
void Window::unlockFrameRate() {
|
void Window::unlockFrameRate() {
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(m_wakeupMutex);
|
std::scoped_lock lock(m_wakeupMutex);
|
||||||
m_remainingUnlockedTime = std::chrono::seconds(2);
|
m_remainingUnlockedTime = std::chrono::seconds(2LL);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->forceNewFrame();
|
this->forceNewFrame();
|
||||||
|
|
@ -1255,7 +1209,7 @@ namespace hex {
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(m_sleepMutex);
|
std::scoped_lock lock(m_sleepMutex);
|
||||||
|
|
||||||
if (m_remainingUnlockedTime > std::chrono::nanoseconds(0)) {
|
if (m_remainingUnlockedTime > std::chrono::nanoseconds(0LL)) {
|
||||||
m_remainingUnlockedTime -= iterationTime;
|
m_remainingUnlockedTime -= iterationTime;
|
||||||
} else {
|
} else {
|
||||||
targetFps = 5;
|
targetFps = 5;
|
||||||
|
|
@ -1314,9 +1268,6 @@ namespace hex {
|
||||||
|
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard;
|
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
io.ConfigWindowsMoveFromTitleBarOnly = true;
|
io.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||||
io.FontGlobalScale = 1.0F;
|
|
||||||
|
|
||||||
ImGui::GetCurrentContext()->FontAtlasOwnedByContext = false;
|
|
||||||
|
|
||||||
if (glfwGetPrimaryMonitor() != nullptr) {
|
if (glfwGetPrimaryMonitor() != nullptr) {
|
||||||
if (ImHexApi::System::isMutliWindowModeEnabled())
|
if (ImHexApi::System::isMutliWindowModeEnabled())
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,5 @@ namespace hex::plugin::builtin {
|
||||||
ImHexApi::System::addStartupTask("Load Window Settings", false, loadWindowSettings);
|
ImHexApi::System::addStartupTask("Load Window Settings", false, loadWindowSettings);
|
||||||
ImHexApi::System::addStartupTask("Configuring UI scale", false, configureUIScale);
|
ImHexApi::System::addStartupTask("Configuring UI scale", false, configureUIScale);
|
||||||
ImHexApi::System::addStartupTask("Checking for updates", true, checkForUpdates);
|
ImHexApi::System::addStartupTask("Checking for updates", true, checkForUpdates);
|
||||||
ImHexApi::System::addStartupTask("Loading fonts", true, fonts::setupFonts);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -341,9 +341,9 @@ namespace hex::plugin::builtin {
|
||||||
m_focusedSubWindowName = name;
|
m_focusedSubWindowName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PushFont(fonts::CodeEditor());
|
fonts::CodeEditor().push();
|
||||||
m_textEditor.get(provider).Render("##pattern_editor", textEditorSize, false);
|
m_textEditor.get(provider).Render("##pattern_editor", textEditorSize, false);
|
||||||
ImGui::PopFont();
|
fonts::CodeEditor().pop();
|
||||||
|
|
||||||
m_textEditorHoverBox = ImRect(windowPosition,windowPosition+textEditorSize);
|
m_textEditorHoverBox = ImRect(windowPosition,windowPosition+textEditorSize);
|
||||||
m_consoleHoverBox = ImRect(ImVec2(windowPosition.x,windowPosition.y+textEditorSize.y),windowPosition+availableSize);
|
m_consoleHoverBox = ImRect(ImVec2(windowPosition.x,windowPosition.y+textEditorSize.y),windowPosition+availableSize);
|
||||||
|
|
@ -1087,9 +1087,9 @@ namespace hex::plugin::builtin {
|
||||||
m_consoleNeedsUpdate = false;
|
m_consoleNeedsUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PushFont(fonts::CodeEditor());
|
fonts::CodeEditor().push();
|
||||||
m_consoleEditor.get(provider).Render("##console", size, true);
|
m_consoleEditor.get(provider).Render("##console", size, true);
|
||||||
ImGui::PopFont();
|
fonts::CodeEditor().pop();
|
||||||
|
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().FramePadding.y + 1_scaled);
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().FramePadding.y + 1_scaled);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,7 @@ namespace hex::plugin::builtin {
|
||||||
ImGui::OpenPopup("WindowingMenu");
|
ImGui::OpenPopup("WindowingMenu");
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
if (!isMacosFullScreenModeEnabled(window))
|
if (!isMacosFullScreenModeEnabled(window))
|
||||||
ImGui::SetCursorPosX(68_scaled);
|
ImGui::SetCursorPosX(75_scaled);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ add_imhex_plugin(
|
||||||
fonts
|
fonts
|
||||||
SOURCES
|
SOURCES
|
||||||
source/library_fonts.cpp
|
source/library_fonts.cpp
|
||||||
source/font_loader.cpp
|
|
||||||
source/fonts.cpp
|
source/fonts.cpp
|
||||||
source/font_settings.cpp
|
source/font_settings.cpp
|
||||||
INCLUDES
|
INCLUDES
|
||||||
|
|
|
||||||
|
|
@ -1,298 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <imgui_internal.h>
|
|
||||||
#include <imgui_freetype.h>
|
|
||||||
#include <ft2build.h>
|
|
||||||
#include FT_FREETYPE_H
|
|
||||||
#include FT_LCD_FILTER_H
|
|
||||||
#include FT_BITMAP_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include <hex/api/task_manager.hpp>
|
|
||||||
|
|
||||||
#include <romfs/romfs.hpp>
|
|
||||||
|
|
||||||
#include <wolv/io/file.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace hex::fonts {
|
|
||||||
|
|
||||||
class Font {
|
|
||||||
public:
|
|
||||||
Font() = default;
|
|
||||||
|
|
||||||
float getDescent() const {
|
|
||||||
return m_font->Descent;
|
|
||||||
}
|
|
||||||
|
|
||||||
float calculateFontDescend(FT_Library ft, float fontSize) const {
|
|
||||||
if (ft == nullptr) {
|
|
||||||
log::fatal("FreeType not initialized");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Face face;
|
|
||||||
if (FT_New_Memory_Face(ft, reinterpret_cast<const FT_Byte *>(m_font->Sources->FontData), m_font->Sources->FontDataSize, 0, &face) != 0) {
|
|
||||||
log::fatal("Failed to load face");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the expected font size
|
|
||||||
auto size = fontSize;
|
|
||||||
if (m_font->FontSize > 0.0F)
|
|
||||||
size = m_font->FontSize * std::max(1.0F, std::floor(ImHexApi::System::getGlobalScale()));
|
|
||||||
else
|
|
||||||
size = std::max(1.0F, std::floor(size / ImHexApi::Fonts::DefaultFontSize)) * ImHexApi::Fonts::DefaultFontSize * std::floor(ImHexApi::System::getGlobalScale());
|
|
||||||
|
|
||||||
FT_Size_RequestRec req;
|
|
||||||
req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
|
|
||||||
req.width = 0;
|
|
||||||
req.height = (uint32_t)(IM_ROUND(size) * 64.0F);
|
|
||||||
req.horiResolution = 0;
|
|
||||||
req.vertResolution = 0;
|
|
||||||
FT_Request_Size(face, &req);
|
|
||||||
|
|
||||||
return face->size->metrics.ascender / 64.0F;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImFont* getFont() { return m_font; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit Font(ImFont *font) : m_font(font) { }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class FontAtlas;
|
|
||||||
|
|
||||||
ImFont *m_font;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FontAtlas {
|
|
||||||
public:
|
|
||||||
FontAtlas() : m_fontAtlas(IM_NEW(ImFontAtlas)) {
|
|
||||||
enableUnicodeCharacters(false);
|
|
||||||
|
|
||||||
// Set the default configuration for the font atlas
|
|
||||||
m_defaultConfig.OversampleH = m_defaultConfig.OversampleV = 1;
|
|
||||||
m_defaultConfig.PixelSnapH = true;
|
|
||||||
m_defaultConfig.MergeMode = false;
|
|
||||||
|
|
||||||
// Make sure the font atlas doesn't get too large, otherwise weaker GPUs might reject it
|
|
||||||
m_fontAtlas->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
|
|
||||||
m_fontAtlas->TexDesiredWidth = 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontAtlas(const FontAtlas &) = delete;
|
|
||||||
FontAtlas &operator=(const FontAtlas &) = delete;
|
|
||||||
|
|
||||||
FontAtlas(FontAtlas &&other) noexcept {
|
|
||||||
m_fontAtlas = other.m_fontAtlas;
|
|
||||||
other.m_fontAtlas = nullptr;
|
|
||||||
|
|
||||||
m_defaultConfig = other.m_defaultConfig;
|
|
||||||
m_fontSizes = std::move(other.m_fontSizes);
|
|
||||||
m_fontConfigs = std::move(other.m_fontConfigs);
|
|
||||||
m_glyphRange = std::move(other.m_glyphRange);
|
|
||||||
m_fontData = std::move(other.m_fontData);
|
|
||||||
}
|
|
||||||
|
|
||||||
FontAtlas& operator=(FontAtlas &&other) noexcept {
|
|
||||||
if (this != &other) {
|
|
||||||
if (m_fontAtlas != nullptr) {
|
|
||||||
IM_DELETE(m_fontAtlas);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fontAtlas = other.m_fontAtlas;
|
|
||||||
other.m_fontAtlas = nullptr;
|
|
||||||
|
|
||||||
m_defaultConfig = other.m_defaultConfig;
|
|
||||||
m_fontSizes = std::move(other.m_fontSizes);
|
|
||||||
m_fontConfigs = std::move(other.m_fontConfigs);
|
|
||||||
m_glyphRange = std::move(other.m_glyphRange);
|
|
||||||
m_fontData = std::move(other.m_fontData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~FontAtlas() {
|
|
||||||
if (m_fontAtlas != nullptr) {
|
|
||||||
m_fontAtlas->Locked = false;
|
|
||||||
if (ImGui::GetIO().Fonts != m_fontAtlas) {
|
|
||||||
IM_DELETE(m_fontAtlas);
|
|
||||||
}
|
|
||||||
m_fontAtlas = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Font addDefaultFont() {
|
|
||||||
auto &config = m_fontConfigs.emplace_back(m_defaultConfig);
|
|
||||||
config.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Monochrome | ImGuiFreeTypeBuilderFlags_MonoHinting;
|
|
||||||
config.SizePixels = std::max(1.0F, std::floor(ImHexApi::System::getGlobalScale() * ImHexApi::System::getBackingScaleFactor() * 13.0F));
|
|
||||||
|
|
||||||
auto font = m_fontAtlas->AddFontDefault(&config);
|
|
||||||
|
|
||||||
font->Scale = 1.0 / std::floor(ImHexApi::System::getBackingScaleFactor());
|
|
||||||
|
|
||||||
m_fontSizes.emplace_back(false, config.SizePixels);
|
|
||||||
|
|
||||||
m_defaultConfig.MergeMode = true;
|
|
||||||
|
|
||||||
return Font(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font addFontFromMemory(const std::vector<u8> &fontData, float fontSize, bool scalable, ImVec2 offset, const ImVector<ImWchar> &glyphRange = {}) {
|
|
||||||
auto &storedFontData = m_fontData.emplace_back(fontData);
|
|
||||||
if (storedFontData.empty()) {
|
|
||||||
log::fatal("Failed to load font data");
|
|
||||||
return Font();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &config = m_fontConfigs.emplace_back(m_defaultConfig);
|
|
||||||
config.FontDataOwnedByAtlas = false;
|
|
||||||
|
|
||||||
config.GlyphOffset = { offset.x, offset.y };
|
|
||||||
auto font = m_fontAtlas->AddFontFromMemoryTTF(storedFontData.data(), int(storedFontData.size()), fontSize, &config, !glyphRange.empty() ? glyphRange.Data : m_glyphRange.Data);
|
|
||||||
font->Scale = 1.0 / ImHexApi::System::getBackingScaleFactor();
|
|
||||||
|
|
||||||
m_fontSizes.emplace_back(scalable, fontSize);
|
|
||||||
|
|
||||||
m_defaultConfig.MergeMode = true;
|
|
||||||
|
|
||||||
return Font(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font addFontFromRomFs(const std::fs::path &path, float fontSize, bool scalable, ImVec2 offset, const ImVector<ImWchar> &glyphRange = {}) {
|
|
||||||
auto data = romfs::get(path).span<u8>();
|
|
||||||
return addFontFromMemory({ data.begin(), data.end() }, fontSize, scalable, offset, glyphRange);
|
|
||||||
}
|
|
||||||
|
|
||||||
Font addFontFromFile(const std::fs::path &path, float fontSize, bool scalable, ImVec2 offset, const ImVector<ImWchar> &glyphRange = {}) {
|
|
||||||
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
|
||||||
|
|
||||||
auto data = file.readVector();
|
|
||||||
return addFontFromMemory(data, fontSize, scalable, offset, glyphRange);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBold(bool enabled) {
|
|
||||||
if (enabled)
|
|
||||||
m_defaultConfig.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Bold;
|
|
||||||
else
|
|
||||||
m_defaultConfig.FontBuilderFlags &= ~ImGuiFreeTypeBuilderFlags_Bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setItalic(bool enabled) {
|
|
||||||
if (enabled)
|
|
||||||
m_defaultConfig.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Oblique;
|
|
||||||
else
|
|
||||||
m_defaultConfig.FontBuilderFlags &= ~ImGuiFreeTypeBuilderFlags_Oblique;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAntiAliasing(bool enabled) {
|
|
||||||
if (enabled)
|
|
||||||
m_defaultConfig.FontBuilderFlags &= ~(ImGuiFreeTypeBuilderFlags_Monochrome | ImGuiFreeTypeBuilderFlags_MonoHinting);
|
|
||||||
else
|
|
||||||
m_defaultConfig.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_Monochrome | ImGuiFreeTypeBuilderFlags_MonoHinting;
|
|
||||||
}
|
|
||||||
|
|
||||||
void enableUnicodeCharacters(bool enabled) {
|
|
||||||
ImFontGlyphRangesBuilder glyphRangesBuilder;
|
|
||||||
|
|
||||||
{
|
|
||||||
constexpr static std::array<ImWchar, 3> controlCodeRange = { 0x0001, 0x001F, 0 };
|
|
||||||
constexpr static std::array<ImWchar, 3> extendedAsciiRange = { 0x007F, 0x00FF, 0 };
|
|
||||||
constexpr static std::array<ImWchar, 3> latinExtendedARange = { 0x0100, 0x017F, 0 };
|
|
||||||
|
|
||||||
glyphRangesBuilder.AddRanges(controlCodeRange.data());
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesDefault());
|
|
||||||
glyphRangesBuilder.AddRanges(extendedAsciiRange.data());
|
|
||||||
glyphRangesBuilder.AddRanges(latinExtendedARange.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
constexpr static ImWchar fullUnicodeRanges[] = {
|
|
||||||
0x0080, 0x00FF, // Latin-1 Supplement
|
|
||||||
0x0100, 0xFFEF, // Remaining BMP (excluding specials)
|
|
||||||
0x10000, 0x1FFFF, // Plane 1
|
|
||||||
0x20000, 0x2FFFF, // Plane 2
|
|
||||||
0 // null-terminated
|
|
||||||
};
|
|
||||||
|
|
||||||
glyphRangesBuilder.AddRanges(fullUnicodeRanges);
|
|
||||||
} else {
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesJapanese());
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesChineseFull());
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesCyrillic());
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesKorean());
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesThai());
|
|
||||||
glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesVietnamese());
|
|
||||||
glyphRangesBuilder.AddText("⌘⌥⌃⇧⏎⇥⌫⇪");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_glyphRange.clear();
|
|
||||||
glyphRangesBuilder.BuildRanges(&m_glyphRange);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool build() const {
|
|
||||||
return m_fontAtlas->Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] ImFontAtlas* getAtlas() {
|
|
||||||
return m_fontAtlas;
|
|
||||||
}
|
|
||||||
|
|
||||||
float calculateFontDescend( FT_Library ft, const ImHexApi::Fonts::Font &font, float fontSize) const {
|
|
||||||
if (ft == nullptr) {
|
|
||||||
log::fatal("FreeType not initialized");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
FT_Face face;
|
|
||||||
if (FT_New_Memory_Face(ft, reinterpret_cast<const FT_Byte *>(font.fontData.data()), font.fontData.size(), 0, &face) != 0) {
|
|
||||||
log::fatal("Failed to load face");
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
FT_Size_RequestRec req;
|
|
||||||
req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
|
|
||||||
req.width = 0;
|
|
||||||
req.height = (uint32_t)(IM_ROUND(fontSize) * 64.0F);
|
|
||||||
req.horiResolution = 0;
|
|
||||||
req.vertResolution = 0;
|
|
||||||
FT_Request_Size(face, &req);
|
|
||||||
|
|
||||||
return face->size->metrics.descender / 64.0F;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
m_fontData.clear();
|
|
||||||
m_glyphRange.clear();
|
|
||||||
m_fontSizes.clear();
|
|
||||||
m_fontConfigs.clear();
|
|
||||||
m_fontAtlas->Clear();
|
|
||||||
m_defaultConfig.MergeMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateFontScaling(float newScaling) {
|
|
||||||
for (int i = 0; i < m_fontAtlas->Sources.size(); i += 1) {
|
|
||||||
const auto &[scalable, fontSize] = m_fontSizes[i];
|
|
||||||
auto &configData = m_fontAtlas->Sources[i];
|
|
||||||
|
|
||||||
if (!scalable) {
|
|
||||||
configData.SizePixels = fontSize * std::floor(newScaling);
|
|
||||||
} else {
|
|
||||||
configData.SizePixels = fontSize * newScaling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ImFontAtlas* m_fontAtlas = nullptr;
|
|
||||||
std::vector<std::pair<bool, float>> m_fontSizes;
|
|
||||||
ImFontConfig m_defaultConfig;
|
|
||||||
std::list<ImFontConfig> m_fontConfigs;
|
|
||||||
ImVector<ImWchar> m_glyphRange;
|
|
||||||
|
|
||||||
std::list<std::vector<u8>> m_fontData;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -4,6 +4,13 @@
|
||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
|
|
||||||
namespace hex::fonts {
|
namespace hex::fonts {
|
||||||
|
|
||||||
|
enum class AntialiasingType {
|
||||||
|
None,
|
||||||
|
Grayscale,
|
||||||
|
Lcd
|
||||||
|
};
|
||||||
|
|
||||||
class AntialiasPicker : public ContentRegistry::Settings::Widgets::DropDown {
|
class AntialiasPicker : public ContentRegistry::Settings::Widgets::DropDown {
|
||||||
public:
|
public:
|
||||||
AntialiasPicker() : DropDown(
|
AntialiasPicker() : DropDown(
|
||||||
|
|
@ -59,7 +66,7 @@ namespace hex::fonts {
|
||||||
[[nodiscard]] float getFontSize() const;
|
[[nodiscard]] float getFontSize() const;
|
||||||
[[nodiscard]] bool isBold() const;
|
[[nodiscard]] bool isBold() const;
|
||||||
[[nodiscard]] bool isItalic() const;
|
[[nodiscard]] bool isItalic() const;
|
||||||
[[nodiscard]] const std::string antiAliasingType() const;
|
[[nodiscard]] AntialiasingType getAntialiasingType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool drawPopup();
|
bool drawPopup();
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
namespace hex::fonts {
|
namespace hex::fonts {
|
||||||
|
|
||||||
const static auto Default = []{ return ImHexApi::Fonts::getFont("hex.fonts.font.default"); };
|
[[nodiscard]] const ImHexApi::Fonts::Font& Default();
|
||||||
const static auto HexEditor = []{ return ImHexApi::Fonts::getFont("hex.fonts.font.hex_editor"); };
|
[[nodiscard]] const ImHexApi::Fonts::Font& HexEditor();
|
||||||
const static auto CodeEditor = []{ return ImHexApi::Fonts::getFont("hex.fonts.font.code_editor"); };
|
[[nodiscard]] const ImHexApi::Fonts::Font& CodeEditor();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,263 +0,0 @@
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <imgui_internal.h>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include <hex/api/imhex_api.hpp>
|
|
||||||
#include <hex/api/content_registry.hpp>
|
|
||||||
|
|
||||||
#include <hex/helpers/logger.hpp>
|
|
||||||
#include <hex/helpers/fs.hpp>
|
|
||||||
#include <hex/helpers/utils.hpp>
|
|
||||||
#include <hex/helpers/freetype.hpp>
|
|
||||||
|
|
||||||
#include <wolv/utils/string.hpp>
|
|
||||||
#include <freetype/freetype.h>
|
|
||||||
#include "imgui_impl_opengl3_loader.h"
|
|
||||||
|
|
||||||
#include <font_atlas.hpp>
|
|
||||||
|
|
||||||
namespace hex::fonts {
|
|
||||||
|
|
||||||
bool BuildSubPixelAtlas(FontAtlas *fontAtlas) {
|
|
||||||
FT_Library ft = nullptr;
|
|
||||||
if (FT_Init_FreeType(&ft) != 0) {
|
|
||||||
log::fatal("Failed to initialize FreeType");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Face face;
|
|
||||||
auto io = ImGui::GetIO();
|
|
||||||
io.Fonts = fontAtlas->getAtlas();
|
|
||||||
|
|
||||||
if (io.Fonts->Sources.Size <= 0) {
|
|
||||||
log::fatal("No font data found");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
ImVector<ImS32> customRectIds;
|
|
||||||
std::map<ImS32, ft::Bitmap> customRectBitmaps;
|
|
||||||
for (const auto &config : io.Fonts->Sources) {
|
|
||||||
const auto &fontName = config.Name;
|
|
||||||
|
|
||||||
if (hex::equalsIgnoreCase(fontName, "nonscalable")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FT_New_Memory_Face(ft, static_cast<const FT_Byte *>(config.FontData), config.FontDataSize, 0, &face) != 0) {
|
|
||||||
log::fatal("Failed to load face");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Size_RequestRec request;
|
|
||||||
request.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
|
|
||||||
request.width = 0;
|
|
||||||
request.height = (uint32_t)(IM_ROUND(config.SizePixels) * 64.0F);
|
|
||||||
request.horiResolution = 0;
|
|
||||||
request.vertResolution = 0;
|
|
||||||
FT_Request_Size(face, &request);
|
|
||||||
|
|
||||||
FT_UInt glyphIndex;
|
|
||||||
FT_ULong charCode = FT_Get_First_Char(face, &glyphIndex);
|
|
||||||
|
|
||||||
while (glyphIndex != 0) {
|
|
||||||
if (FT_Load_Glyph(face, glyphIndex, FT_LOAD_TARGET_LCD | FT_LOAD_TARGET_LIGHT | FT_LOAD_RENDER) != 0) {
|
|
||||||
IM_ASSERT(true && "Failed to load glyph");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ft::Bitmap bitmap = ft::Bitmap(face->glyph->bitmap.width, face->glyph->bitmap.rows, face->glyph->bitmap.pitch, face->glyph->bitmap.buffer);
|
|
||||||
if (face->glyph->bitmap.width * face->glyph->bitmap.rows == 0) {
|
|
||||||
charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto width = bitmap.getWidth() / 3.0F;
|
|
||||||
const auto height = bitmap.getHeight();
|
|
||||||
const auto slot = face->glyph;
|
|
||||||
const auto size = face->size;
|
|
||||||
|
|
||||||
auto offset = ImVec2(face->glyph->bitmap_left, -face->glyph->bitmap_top);
|
|
||||||
offset.x += config.GlyphOffset.x;
|
|
||||||
offset.y += size->metrics.ascender / 64.0F;
|
|
||||||
|
|
||||||
const ImS32 advance = slot->advance.x / 64.0F;
|
|
||||||
|
|
||||||
ImS32 rectId = io.Fonts->AddCustomRectFontGlyph(io.Fonts->Fonts[0], charCode, width, height, advance, offset);
|
|
||||||
customRectIds.push_back(rectId);
|
|
||||||
customRectBitmaps.insert(std::make_pair(rectId, bitmap));
|
|
||||||
|
|
||||||
charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
|
|
||||||
}
|
|
||||||
FT_Done_Face(face);
|
|
||||||
}
|
|
||||||
|
|
||||||
fontAtlas->getAtlas()->FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_SubPixel;
|
|
||||||
if (!fontAtlas->build())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ImU8 *textureColors = nullptr;
|
|
||||||
ImS32 textureWidth, textureHeight;
|
|
||||||
|
|
||||||
fontAtlas->getAtlas()->GetTexDataAsRGBA32(&textureColors, &textureWidth, &textureHeight);
|
|
||||||
auto *texturePixels = reinterpret_cast<ImU32 *>(textureColors);
|
|
||||||
for (auto rect_id: customRectIds) {
|
|
||||||
if (const ImFontAtlasCustomRect *rect = io.Fonts->GetCustomRectByIndex(rect_id)) {
|
|
||||||
if (rect->X == 0xFFFF || rect->Y == 0xFFFF || !customRectBitmaps.contains(rect_id))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto &bitmap = customRectBitmaps.at(rect_id);
|
|
||||||
ImU32 imageWidth = bitmap.getWidth() / 3;
|
|
||||||
ImU32 imageHeight = bitmap.getHeight();
|
|
||||||
const auto &bitmapBuffer = bitmap.getData();
|
|
||||||
|
|
||||||
for (ImU32 y = 0; y < imageHeight; y++) {
|
|
||||||
ImU32 *pixel = texturePixels + (rect->Y + y) * textureWidth + (rect->X);
|
|
||||||
for (ImU32 x = 0; x < imageWidth; x++) {
|
|
||||||
const ImU8 *bitmapPixel = &bitmapBuffer[y * bitmap.getPitch() + 3 * x];
|
|
||||||
*pixel++ = ft::RGBA::addAlpha(*bitmapPixel, *(bitmapPixel + 1), *(bitmapPixel + 2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i64 i = 0; i < textureWidth * textureHeight; i++) {
|
|
||||||
if (texturePixels[i] == 0x00FFFFFF) {
|
|
||||||
texturePixels[i] = 0x00000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ft != nullptr) {
|
|
||||||
FT_Done_FreeType(ft);
|
|
||||||
ft = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool buildFontAtlas(FontAtlas *fontAtlas, std::fs::path fontPath, bool pixelPerfectFont, float fontSize, bool loadUnicodeCharacters, bool bold, bool italic,const std::string &antiAliasType) {
|
|
||||||
if (fontAtlas == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool antialias = antiAliasType == "grayscale";
|
|
||||||
bool monochrome = antiAliasType == "none";
|
|
||||||
FT_Library ft = nullptr;
|
|
||||||
if (FT_Init_FreeType(&ft) != 0) {
|
|
||||||
log::fatal("Failed to initialize FreeType");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fontAtlas->reset();
|
|
||||||
u32 fontIndex = 0;
|
|
||||||
auto io = ImGui::GetIO();
|
|
||||||
io.Fonts = fontAtlas->getAtlas();
|
|
||||||
|
|
||||||
// Check if Unicode support is enabled in the settings and that the user doesn't use the No GPU version on Windows
|
|
||||||
// The Mesa3D software renderer on Windows identifies itself as "VMware, Inc."
|
|
||||||
bool shouldLoadUnicode = ContentRegistry::Settings::read<bool>("hex.fonts.setting.font", "hex.fonts.setting.font.load_all_unicode_chars", false) && ImHexApi::System::getGPUVendor() != "VMware, Inc.";
|
|
||||||
|
|
||||||
if (!loadUnicodeCharacters)
|
|
||||||
shouldLoadUnicode = false;
|
|
||||||
|
|
||||||
fontAtlas->enableUnicodeCharacters(shouldLoadUnicode);
|
|
||||||
|
|
||||||
// If a custom font is set in the settings, load the rest of the settings as well
|
|
||||||
if (!pixelPerfectFont) {
|
|
||||||
fontAtlas->setBold(bold);
|
|
||||||
fontAtlas->setItalic(italic);
|
|
||||||
if (antialias || monochrome)
|
|
||||||
fontAtlas->setAntiAliasing(antialias);
|
|
||||||
} else {
|
|
||||||
fontPath.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to load the custom font if one was set
|
|
||||||
std::optional<Font> defaultFont;
|
|
||||||
if (!fontPath.empty()) {
|
|
||||||
defaultFont = fontAtlas->addFontFromFile(fontPath, fontSize, true, ImVec2());
|
|
||||||
std::string defaultFontName = defaultFont.has_value() ? fontPath.filename().string() : "Custom Font";
|
|
||||||
memcpy(fontAtlas->getAtlas()->Sources[fontIndex].Name, defaultFontName.c_str(), defaultFontName.size());
|
|
||||||
fontIndex += 1;
|
|
||||||
if ((antialias || monochrome) && !fontAtlas->build()) {
|
|
||||||
log::error("Failed to load custom font '{}'! Falling back to default font", wolv::util::toUTF8String(fontPath));
|
|
||||||
defaultFont.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's no custom font set, or it failed to load, fall back to the default font
|
|
||||||
if (!defaultFont.has_value()) {
|
|
||||||
if (pixelPerfectFont) {
|
|
||||||
defaultFont = fontAtlas->addDefaultFont();
|
|
||||||
std::string defaultFontName = "Proggy Clean";
|
|
||||||
memcpy(fontAtlas->getAtlas()->Sources[fontIndex].Name, defaultFontName.c_str(), defaultFontName.size());
|
|
||||||
fontIndex += 1;
|
|
||||||
} else {
|
|
||||||
defaultFont = fontAtlas->addFontFromRomFs("fonts/JetBrainsMono.ttf", fontSize, true, ImVec2());
|
|
||||||
std::string defaultFontName = "JetBrains Mono";
|
|
||||||
memcpy(fontAtlas->getAtlas()->Sources[fontIndex].Name, defaultFontName.c_str(), defaultFontName.size());
|
|
||||||
fontIndex += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Add all the built-in fonts
|
|
||||||
{
|
|
||||||
static std::list<ImVector<ImWchar>> glyphRanges;
|
|
||||||
glyphRanges.clear();
|
|
||||||
|
|
||||||
for (auto &font : ImHexApi::Fonts::impl::getFonts()) {
|
|
||||||
// Construct the glyph range for the font
|
|
||||||
ImVector<ImWchar> glyphRange;
|
|
||||||
if (!font.glyphRanges.empty()) {
|
|
||||||
for (const auto &range : font.glyphRanges) {
|
|
||||||
glyphRange.push_back(range.begin);
|
|
||||||
glyphRange.push_back(range.end);
|
|
||||||
}
|
|
||||||
glyphRange.push_back(0x00);
|
|
||||||
}
|
|
||||||
glyphRanges.push_back(glyphRange);
|
|
||||||
|
|
||||||
// Calculate the glyph offset for the font
|
|
||||||
|
|
||||||
// Load the font
|
|
||||||
if (font.defaultSize.has_value())
|
|
||||||
fontSize = font.defaultSize.value() * ImHexApi::System::getBackingScaleFactor();
|
|
||||||
|
|
||||||
ImVec2 offset = { font.offset.x, font.offset.y };
|
|
||||||
|
|
||||||
bool scalable = font.scalable.value_or(true);
|
|
||||||
if (scalable) {
|
|
||||||
offset.y += ImCeil(3_scaled);
|
|
||||||
}
|
|
||||||
|
|
||||||
fontAtlas->addFontFromMemory(font.fontData, fontSize, !font.defaultSize.has_value(), offset, glyphRanges.back());
|
|
||||||
|
|
||||||
if (!scalable) {
|
|
||||||
std::string fontName = "NonScalable";
|
|
||||||
auto nameSize = fontName.size();
|
|
||||||
memcpy(fontAtlas->getAtlas()->Sources[fontIndex].Name, fontName.c_str(), nameSize);
|
|
||||||
} else {
|
|
||||||
auto nameSize = font.name.size();
|
|
||||||
memcpy(fontAtlas->getAtlas()->Sources[fontIndex].Name, font.name.c_str(), nameSize);
|
|
||||||
}
|
|
||||||
fontIndex += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ft != nullptr) {
|
|
||||||
FT_Done_FreeType(ft);
|
|
||||||
ft = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (antialias || monochrome) {
|
|
||||||
if (!fontAtlas->build()) {
|
|
||||||
log::fatal("Failed to load font!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return BuildSubPixelAtlas(fontAtlas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -198,10 +198,20 @@ namespace hex::fonts {
|
||||||
return m_italic.isChecked();
|
return m_italic.isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::string FontSelector::antiAliasingType() const {
|
[[nodiscard]] AntialiasingType FontSelector::getAntialiasingType() const {
|
||||||
if (isPixelPerfectFont())
|
if (isPixelPerfectFont())
|
||||||
return "none";
|
return AntialiasingType::None;
|
||||||
return m_antiAliased.getValue();
|
|
||||||
|
auto value = m_antiAliased.getValue();
|
||||||
|
if (value == "none")
|
||||||
|
return AntialiasingType::None;
|
||||||
|
else if (value == "grayscale")
|
||||||
|
return AntialiasingType::Grayscale;
|
||||||
|
else if (value == "subpixel")
|
||||||
|
return AntialiasingType::Lcd;
|
||||||
|
else
|
||||||
|
return AntialiasingType::Grayscale;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include <hex/api/imhex_api.hpp>
|
#include <hex/api/imhex_api.hpp>
|
||||||
|
|
||||||
|
#include <fonts/fonts.hpp>
|
||||||
|
|
||||||
#include <romfs/romfs.hpp>
|
#include <romfs/romfs.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
@ -9,6 +11,13 @@
|
||||||
|
|
||||||
namespace hex::fonts {
|
namespace hex::fonts {
|
||||||
|
|
||||||
|
static auto s_defaultFont = ImHexApi::Fonts::Font("hex.fonts.font.default");
|
||||||
|
const ImHexApi::Fonts::Font& Default() { return s_defaultFont; }
|
||||||
|
static auto s_hexEditorFont = ImHexApi::Fonts::Font("hex.fonts.font.hex_editor");
|
||||||
|
const ImHexApi::Fonts::Font& HexEditor() { return s_hexEditorFont; }
|
||||||
|
static auto s_codeEditorFont = ImHexApi::Fonts::Font("hex.fonts.font.code_editor");
|
||||||
|
const ImHexApi::Fonts::Font& CodeEditor() { return s_codeEditorFont; }
|
||||||
|
|
||||||
void registerFonts() {
|
void registerFonts() {
|
||||||
using namespace ImHexApi::Fonts;
|
using namespace ImHexApi::Fonts;
|
||||||
|
|
||||||
|
|
@ -24,7 +33,7 @@ namespace hex::fonts {
|
||||||
{
|
{
|
||||||
{ ICON_MIN_VS, ICON_MAX_VS }
|
{ ICON_MIN_VS, ICON_MAX_VS }
|
||||||
},
|
},
|
||||||
{ -1_scaled, -1_scaled });
|
{ -1, -2 });
|
||||||
|
|
||||||
ImHexApi::Fonts::loadFont("Unifont", romfs::get("fonts/unifont.otf").span<u8>(), { }, {}, 0, false, 16);
|
ImHexApi::Fonts::loadFont("Unifont", romfs::get("fonts/unifont.otf").span<u8>(), { }, {}, 0, false, 16);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,55 +5,81 @@
|
||||||
#include <hex/helpers/logger.hpp>
|
#include <hex/helpers/logger.hpp>
|
||||||
|
|
||||||
#include <romfs/romfs.hpp>
|
#include <romfs/romfs.hpp>
|
||||||
#include <font_atlas.hpp>
|
|
||||||
#include <font_settings.hpp>
|
#include <font_settings.hpp>
|
||||||
|
#include <imgui_freetype.h>
|
||||||
|
#include <fonts/fonts.hpp>
|
||||||
|
#include <hex/api/task_manager.hpp>
|
||||||
|
#include <hex/api/events/events_lifecycle.hpp>
|
||||||
|
|
||||||
namespace hex::fonts {
|
namespace hex::fonts {
|
||||||
|
|
||||||
void registerFonts();
|
void registerFonts();
|
||||||
|
void loadFont(const ContentRegistry::Settings::Widgets::Widget &widget, const UnlocalizedString &name, ImFont **imguiFont) {
|
||||||
bool buildFontAtlas(FontAtlas *fontAtlas, std::fs::path fontPath, bool pixelPerfectFont, float fontSize, bool loadUnicodeCharacters, bool bold, bool italic,const std::string &antialias);
|
|
||||||
|
|
||||||
static AutoReset<std::map<UnlocalizedString, std::unique_ptr<FontAtlas>>> s_fontAtlases;
|
|
||||||
|
|
||||||
void loadFont(const ContentRegistry::Settings::Widgets::Widget &widget, const UnlocalizedString &name, ImFont **font, float scale) {
|
|
||||||
const auto &settings = static_cast<const FontSelector&>(widget);
|
const auto &settings = static_cast<const FontSelector&>(widget);
|
||||||
auto atlas = std::make_unique<FontAtlas>();
|
|
||||||
|
|
||||||
const bool atlasBuilt = buildFontAtlas(
|
auto atlas = ImGui::GetIO().Fonts;
|
||||||
atlas.get(),
|
|
||||||
settings.getFontPath(),
|
|
||||||
settings.isPixelPerfectFont(),
|
|
||||||
settings.getFontSize() * scale,
|
|
||||||
true,
|
|
||||||
settings.isBold(),
|
|
||||||
settings.isItalic(),
|
|
||||||
settings.antiAliasingType()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!atlasBuilt) {
|
{
|
||||||
buildFontAtlas(
|
auto &font = *imguiFont;
|
||||||
atlas.get(),
|
|
||||||
"",
|
|
||||||
false,
|
|
||||||
settings.getFontSize() * scale,
|
|
||||||
false,
|
|
||||||
settings.isBold(),
|
|
||||||
settings.isItalic(),
|
|
||||||
settings.antiAliasingType()
|
|
||||||
);
|
|
||||||
|
|
||||||
log::error("Failed to load font {}! Reverting back to default font!", name.get());
|
if (font != nullptr) {
|
||||||
|
atlas->RemoveFont(font);
|
||||||
|
|
||||||
|
font = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*font = atlas->getAtlas()->Fonts[0];
|
ImFontConfig config;
|
||||||
|
config.MergeMode = false;
|
||||||
|
config.FontDataOwnedByAtlas = false;
|
||||||
|
config.SizePixels = settings.getFontSize();
|
||||||
|
|
||||||
(*s_fontAtlases)[name] = std::move(atlas);
|
std::memcpy(config.Name, name.get().c_str(), std::min(name.get().size(), sizeof(config.Name) - 1));
|
||||||
|
|
||||||
|
if (settings.isBold())
|
||||||
|
config.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_Bold;
|
||||||
|
if (settings.isItalic())
|
||||||
|
config.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_Oblique;
|
||||||
|
switch (settings.getAntialiasingType()) {
|
||||||
|
case AntialiasingType::None:
|
||||||
|
config.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_Monochrome | ImGuiFreeTypeLoaderFlags_MonoHinting;
|
||||||
|
break;
|
||||||
|
case AntialiasingType::Grayscale:
|
||||||
|
break;
|
||||||
|
case AntialiasingType::Lcd:
|
||||||
|
config.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_SubPixel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto fontPath = settings.getFontPath();
|
||||||
|
if (!fontPath.empty())
|
||||||
|
*imguiFont = atlas->AddFontFromFileTTF(fontPath.string().c_str(), 0.0F, &config);
|
||||||
|
|
||||||
|
if (*imguiFont == nullptr) {
|
||||||
|
if (settings.isPixelPerfectFont())
|
||||||
|
*imguiFont = atlas->AddFontDefault();
|
||||||
|
else {
|
||||||
|
static auto jetbrainsFont = romfs::get("fonts/JetBrainsMono.ttf");
|
||||||
|
*imguiFont = atlas->AddFontFromMemoryTTF(const_cast<u8 *>(jetbrainsFont.data<u8>()), jetbrainsFont.size(), 0.0F, &config);
|
||||||
|
|
||||||
|
if (*imguiFont == nullptr) {
|
||||||
|
log::error("Failed to load font '{}', using default font instead", name.get());
|
||||||
|
*imguiFont = atlas->AddFontDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.MergeMode = true;
|
||||||
|
for (auto &extraFont : ImHexApi::Fonts::impl::getMergeFonts()) {
|
||||||
|
config.GlyphOffset = { extraFont.offset.x, -extraFont.offset.y };
|
||||||
|
config.GlyphOffset *= ImHexApi::System::getGlobalScale();
|
||||||
|
atlas->AddFontFromMemoryTTF(const_cast<u8 *>(extraFont.fontData.data()), extraFont.fontData.size(), 0.0F, &config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setupFonts() {
|
bool setupFonts() {
|
||||||
ContentRegistry::Settings::add<ContentRegistry::Settings::Widgets::Checkbox>("hex.fonts.setting.font", "hex.fonts.setting.font.glyphs", "hex.fonts.setting.font.load_all_unicode_chars", false).requiresRestart();
|
|
||||||
|
|
||||||
for (auto &[name, font] : ImHexApi::Fonts::impl::getFontDefinitions()) {
|
for (auto &[name, font] : ImHexApi::Fonts::impl::getFontDefinitions()) {
|
||||||
auto &widget = addFontSettingsWidget(name)
|
auto &widget = addFontSettingsWidget(name)
|
||||||
.setChangedCallback([name, &font, firstLoad = true](auto &widget) mutable {
|
.setChangedCallback([name, &font, firstLoad = true](auto &widget) mutable {
|
||||||
|
|
@ -62,15 +88,12 @@ namespace hex::fonts {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskManager::doLater([&name, &font, &widget] {
|
TaskManager::doLater([name, &font, &widget] {
|
||||||
loadFont(widget, name, &font, ImHexApi::System::getGlobalScale() * ImHexApi::System::getBackingScaleFactor());
|
loadFont(widget, name, &font);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
loadFont(widget.getWidget(), name, &font, ImHexApi::System::getGlobalScale() * ImHexApi::System::getBackingScaleFactor());
|
loadFont(widget.getWidget(), name, &font);
|
||||||
EventDPIChanged::subscribe(font, [&widget, name, &font](float, float newScaling) {
|
|
||||||
loadFont(widget.getWidget(), name, &font, ImHexApi::System::getGlobalScale() * newScaling);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -87,4 +110,9 @@ IMHEX_LIBRARY_SETUP("Fonts") {
|
||||||
hex::ImHexApi::Fonts::registerFont("hex.fonts.font.code_editor");
|
hex::ImHexApi::Fonts::registerFont("hex.fonts.font.code_editor");
|
||||||
|
|
||||||
hex::fonts::registerFonts();
|
hex::fonts::registerFonts();
|
||||||
|
|
||||||
|
hex::EventImHexStartupFinished::subscribe([] {
|
||||||
|
hex::fonts::setupFonts();
|
||||||
|
hex::ImHexApi::Fonts::setDefaultFont(hex::fonts::Default());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1291,9 +1291,9 @@ namespace hex::ui {
|
||||||
if (tableSize.y <= 0)
|
if (tableSize.y <= 0)
|
||||||
tableSize.y = height;
|
tableSize.y = height;
|
||||||
|
|
||||||
ImGui::PushFont(fonts::HexEditor());
|
fonts::HexEditor().push();
|
||||||
this->drawEditor(tableSize);
|
this->drawEditor(tableSize);
|
||||||
ImGui::PopFont();
|
fonts::HexEditor().pop();
|
||||||
|
|
||||||
if (tableSize.y > 0)
|
if (tableSize.y > 0)
|
||||||
this->drawFooter(footerSize);
|
this->drawFooter(footerSize);
|
||||||
|
|
|
||||||
|
|
@ -462,13 +462,13 @@ namespace hex::ui {
|
||||||
using enum TreeStyle;
|
using enum TreeStyle;
|
||||||
default:
|
default:
|
||||||
case Default:
|
case Default:
|
||||||
retVal = ImGui::TreeNodeEx("##TreeNode", ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_OpenOnArrow);
|
retVal = ImGui::TreeNodeEx("##TreeNode", ImGuiTreeNodeFlags_DrawLinesToNodes | ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_OpenOnArrow);
|
||||||
break;
|
break;
|
||||||
case AutoExpanded:
|
case AutoExpanded:
|
||||||
retVal = ImGui::TreeNodeEx("##TreeNode", ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_OpenOnArrow);
|
retVal = ImGui::TreeNodeEx("##TreeNode", ImGuiTreeNodeFlags_DrawLinesToNodes | ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_OpenOnArrow);
|
||||||
break;
|
break;
|
||||||
case Flattened:
|
case Flattened:
|
||||||
retVal = ImGui::TreeNodeEx("##TreeNode", ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
|
retVal = ImGui::TreeNodeEx("##TreeNode", ImGuiTreeNodeFlags_DrawLinesToNodes | ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
@ -1086,7 +1086,7 @@ namespace hex::ui {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{
|
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{
|
||||||
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", m_treeStyle == TreeStyle::Flattened ? this->getDisplayName(pattern).c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
|
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", m_treeStyle == TreeStyle::Flattened ? this->getDisplayName(pattern).c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_DrawLinesToNodes | ImGuiTreeNodeFlags_SpanFullWidth);
|
||||||
});
|
});
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
|
@ -1342,7 +1342,7 @@ namespace hex::ui {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushID(id);
|
ImGui::PushID(id);
|
||||||
if (ImGui::TreeNodeEx("hex.ui.pattern_drawer.favorites"_lang, ImGuiTreeNodeFlags_SpanFullWidth)) {
|
if (ImGui::TreeNodeEx("hex.ui.pattern_drawer.favorites"_lang, ImGuiTreeNodeFlags_DrawLinesToNodes | ImGuiTreeNodeFlags_SpanFullWidth)) {
|
||||||
for (auto &[path, pattern] : m_favorites) {
|
for (auto &[path, pattern] : m_favorites) {
|
||||||
if (pattern == nullptr)
|
if (pattern == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1369,7 +1369,7 @@ namespace hex::ui {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushID(id);
|
ImGui::PushID(id);
|
||||||
if (ImGui::TreeNodeEx(groupName.c_str(), ImGuiTreeNodeFlags_SpanFullWidth)) {
|
if (ImGui::TreeNodeEx(groupName.c_str(), ImGuiTreeNodeFlags_DrawLinesToNodes | ImGuiTreeNodeFlags_SpanFullWidth)) {
|
||||||
for (auto &groupPattern: groupPatterns) {
|
for (auto &groupPattern: groupPatterns) {
|
||||||
if (groupPattern == nullptr)
|
if (groupPattern == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue