forked from mirrors/principia
Update Imgui to f5384544cb350dd2444c27c153ac563b91cf09da
This commit is contained in:
parent
c4e0a1ee01
commit
c72b8f6646
18 changed files with 11489 additions and 6298 deletions
|
|
@ -15,7 +15,8 @@
|
|||
#pragma once
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
// - If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
// - Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
|
|
@ -48,7 +49,7 @@
|
|||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert.
|
||||
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean/ProggyVector), remove ~9 KB + ~17 KB from output binary. AddFontDefaultXXX() functions will assert.
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Enable Test Engine / Automation features.
|
||||
|
|
@ -83,13 +84,13 @@
|
|||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// Note that imgui_freetype.cpp may be used _without_ this define, if you manually call ImFontAtlas::SetFontLoader(). The define is simply a convenience.
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg.
|
||||
// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions.
|
||||
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
|
||||
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
||||
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||
|
|
@ -130,6 +131,10 @@
|
|||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set.
|
||||
// (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use)
|
||||
//#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
|
|
|
|||
3330
lib/imgui/imgui.cpp
3330
lib/imgui/imgui.cpp
File diff suppressed because it is too large
Load diff
1201
lib/imgui/imgui.h
1201
lib/imgui/imgui.h
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
|
|
@ -4,8 +4,9 @@
|
|||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// 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) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
|
|
@ -22,6 +23,13 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792)
|
||||
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures (#8802) + restore non-WebGL/ES update path that doesn't require a CPU-side copy.
|
||||
// 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)
|
||||
|
|
@ -53,7 +61,7 @@
|
|||
// 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-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-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.
|
||||
|
|
@ -169,6 +177,7 @@
|
|||
// - 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.
|
||||
#define IMGL3W_IMPL
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
#include "imgui_impl_opengl3_loader.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -228,7 +237,7 @@ struct ImGui_ImplOpenGL3_Data
|
|||
bool GlProfileIsES3;
|
||||
bool GlProfileIsCompat;
|
||||
GLint GlProfileMask;
|
||||
GLuint FontTexture;
|
||||
GLint MaxTextureSize;
|
||||
GLuint ShaderHandle;
|
||||
GLint AttribLocationTex; // Uniforms location
|
||||
GLint AttribLocationProjMtx;
|
||||
|
|
@ -239,8 +248,10 @@ struct ImGui_ImplOpenGL3_Data
|
|||
GLsizeiptr VertexBufferSize;
|
||||
GLsizeiptr IndexBufferSize;
|
||||
bool HasPolygonMode;
|
||||
bool HasBindSampler;
|
||||
bool HasClipOrigin;
|
||||
bool UseBufferSubData;
|
||||
ImVector<char> TempBuffer;
|
||||
|
||||
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
|
@ -276,6 +287,29 @@ struct ImGui_ImplOpenGL3_VtxAttribState
|
|||
};
|
||||
#endif
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
bool ImGui_ImplOpenGL3_InitLoader();
|
||||
bool ImGui_ImplOpenGL3_InitLoader()
|
||||
{
|
||||
// Lazily initialize our loader if not already done
|
||||
// (to facilitate handling multiple DLL boundaries and multiple context shutdowns we call this from all main entry points)
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
if (glGetIntegerv == nullptr && imgl3wInit() != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize OpenGL loader!\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ImGui_ImplOpenGL3_ShutdownLoader()
|
||||
{
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
imgl3wShutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||
{
|
||||
|
|
@ -283,14 +317,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Initialize our loader
|
||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
|
||||
if (imgl3wInit() != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize OpenGL loader!\n");
|
||||
// Initialize loader
|
||||
if (!ImGui_ImplOpenGL3_InitLoader())
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
|
||||
|
|
@ -303,6 +332,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
// GLES 2
|
||||
bd->GlVersion = 200;
|
||||
bd->GlProfileIsES2 = true;
|
||||
IM_UNUSED(gl_version_str);
|
||||
#else
|
||||
// Desktop or GLES 3
|
||||
GLint major = 0;
|
||||
|
|
@ -312,11 +342,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
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>"
|
||||
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
|
||||
#if defined(GL_CONTEXT_PROFILE_MASK)
|
||||
if (bd->GlVersion >= 320)
|
||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
|
||||
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
|
||||
#endif
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &bd->MaxTextureSize);
|
||||
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
bd->GlProfileIsES3 = true;
|
||||
|
|
@ -325,6 +351,12 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
bd->GlProfileIsES3 = true;
|
||||
#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;
|
||||
/*
|
||||
// Query vendor to enable glBufferSubData kludge
|
||||
|
|
@ -344,6 +376,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
if (bd->GlVersion >= 320)
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
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.
|
||||
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
|
||||
|
|
@ -359,7 +395,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
glsl_version = "#version 130";
|
||||
#endif
|
||||
}
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
|
||||
strcpy(bd->GlslVersionString, glsl_version);
|
||||
strcat(bd->GlslVersionString, "\n");
|
||||
|
||||
|
|
@ -371,6 +407,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
// Detect extensions we support
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||
bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
|
||||
#endif
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
bd->HasBindSampler = (bd->GlVersion >= 330 || bd->GlProfileIsES3);
|
||||
#endif
|
||||
bd->HasClipOrigin = (bd->GlVersion >= 450);
|
||||
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
|
||||
|
|
@ -392,12 +431,17 @@ void ImGui_ImplOpenGL3_Shutdown()
|
|||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
|
||||
ImGui_ImplOpenGL3_ShutdownLoader();
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_NewFrame()
|
||||
|
|
@ -405,10 +449,10 @@ void ImGui_ImplOpenGL3_NewFrame()
|
|||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
if (!bd->ShaderHandle)
|
||||
ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
if (!bd->FontTexture)
|
||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||
if (!ImGui_ImplOpenGL3_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
||||
}
|
||||
|
||||
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
|
||||
|
|
@ -424,7 +468,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||
glDisable(GL_STENCIL_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
|
||||
if (bd->GlVersion >= 310)
|
||||
if (!bd->GlProfileIsES3 && bd->GlVersion >= 310)
|
||||
glDisable(GL_PRIMITIVE_RESTART);
|
||||
#endif
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||
|
|
@ -465,7 +509,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
|
||||
if (bd->HasBindSampler)
|
||||
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
||||
#endif
|
||||
|
||||
|
|
@ -496,15 +540,24 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
|
||||
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
|
||||
GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
|
||||
GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
|
||||
GLuint last_sampler; if (bd->HasBindSampler) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
|
||||
#endif
|
||||
GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
|
||||
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||
|
|
@ -534,7 +587,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
|
||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||
#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
|
||||
|
||||
// Setup desired GL state
|
||||
|
|
@ -551,10 +604,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
const ImDrawList* draw_list = draw_data->CmdLists[n];
|
||||
|
||||
// Upload vertex/index buffers
|
||||
// - OpenGL drivers are in a very sorry state nowadays....
|
||||
// During 2021 we attempted to switch from glBufferData() to orphaning+glBufferSubData() following reports
|
||||
|
|
@ -631,7 +682,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
|
||||
if (bd->HasBindSampler)
|
||||
glBindSampler(0, last_sampler);
|
||||
#endif
|
||||
glActiveTexture(last_active_texture);
|
||||
|
|
@ -653,7 +704,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_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||
#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
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
|
||||
|
|
@ -666,50 +717,90 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
(void)bd; // Not all compilation paths use this
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
||||
static void ImGui_ImplOpenGL3_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
|
||||
glDeleteTextures(1, &gl_tex_id);
|
||||
|
||||
// Build texture atlas
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
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));
|
||||
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, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||
|
||||
// Store identifier
|
||||
io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
|
||||
|
||||
// Restore state
|
||||
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
|
||||
|
||||
return true;
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_DestroyFontsTexture()
|
||||
void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
if (bd->FontTexture)
|
||||
// FIXME: Consider backing up and restoring
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
glDeleteTextures(1, &bd->FontTexture);
|
||||
io.Fonts->SetTexID(0);
|
||||
bd->FontTexture = 0;
|
||||
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#endif
|
||||
#ifdef GL_UNPACK_ALIGNMENT
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == 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));
|
||||
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 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.
|
||||
|
|
@ -752,6 +843,7 @@ static bool CheckProgram(GLuint handle, const char* desc)
|
|||
|
||||
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
||||
// Backup GL state
|
||||
|
|
@ -901,21 +993,24 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
|||
GL_CALL(vert_handle = glCreateShader(GL_VERTEX_SHADER));
|
||||
glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
|
||||
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 };
|
||||
GLuint frag_handle;
|
||||
GL_CALL(frag_handle = glCreateShader(GL_FRAGMENT_SHADER));
|
||||
glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
|
||||
glCompileShader(frag_handle);
|
||||
CheckShader(frag_handle, "fragment shader");
|
||||
if (!CheckShader(frag_handle, "fragment shader"))
|
||||
return false;
|
||||
|
||||
// Link
|
||||
bd->ShaderHandle = glCreateProgram();
|
||||
glAttachShader(bd->ShaderHandle, vert_handle);
|
||||
glAttachShader(bd->ShaderHandle, frag_handle);
|
||||
glLinkProgram(bd->ShaderHandle);
|
||||
CheckProgram(bd->ShaderHandle, "shader program");
|
||||
if (!CheckProgram(bd->ShaderHandle, "shader program"))
|
||||
return false;
|
||||
|
||||
glDetachShader(bd->ShaderHandle, vert_handle);
|
||||
glDetachShader(bd->ShaderHandle, frag_handle);
|
||||
|
|
@ -932,8 +1027,6 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
|||
glGenBuffers(1, &bd->VboHandle);
|
||||
glGenBuffers(1, &bd->ElementsHandle);
|
||||
|
||||
ImGui_ImplOpenGL3_CreateFontsTexture();
|
||||
|
||||
// Restore modified GL state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
|
|
@ -949,11 +1042,16 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
|||
|
||||
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
|
||||
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@
|
|||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// 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) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
|
|
@ -36,11 +37,12 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
|||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// (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 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:
|
||||
//#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)
|
||||
|
|
|
|||
|
|
@ -166,7 +166,9 @@ typedef khronos_uint8_t GLubyte;
|
|||
#define GL_SCISSOR_BOX 0x0C10
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
|
|
@ -178,6 +180,7 @@ typedef khronos_uint8_t GLubyte;
|
|||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
|
|
@ -224,11 +227,13 @@ typedef khronos_float_t GLclampf;
|
|||
typedef double GLclampd;
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
|
|
@ -396,9 +401,15 @@ GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum
|
|||
#ifndef GL_VERSION_3_3
|
||||
#define GL_VERSION_3_3 1
|
||||
#define GL_SAMPLER_BINDING 0x8919
|
||||
typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
|
||||
typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
|
||||
GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
|
||||
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
|
||||
GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_3 */
|
||||
#ifndef GL_VERSION_4_1
|
||||
|
|
@ -473,12 +484,13 @@ typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
|
|||
/* gl3w api */
|
||||
GL3W_API int imgl3wInit(void);
|
||||
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
|
||||
GL3W_API void imgl3wShutdown(void);
|
||||
GL3W_API int imgl3wIsSupported(int major, int minor);
|
||||
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
|
||||
|
||||
/* gl3w internal state */
|
||||
union ImGL3WProcs {
|
||||
GL3WglProc ptr[59];
|
||||
GL3WglProc ptr[63];
|
||||
struct {
|
||||
PFNGLACTIVETEXTUREPROC ActiveTexture;
|
||||
PFNGLATTACHSHADERPROC AttachShader;
|
||||
|
|
@ -498,6 +510,7 @@ union ImGL3WProcs {
|
|||
PFNGLCREATESHADERPROC CreateShader;
|
||||
PFNGLDELETEBUFFERSPROC DeleteBuffers;
|
||||
PFNGLDELETEPROGRAMPROC DeleteProgram;
|
||||
PFNGLDELETESAMPLERSPROC DeleteSamplers;
|
||||
PFNGLDELETESHADERPROC DeleteShader;
|
||||
PFNGLDELETETEXTURESPROC DeleteTextures;
|
||||
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
|
||||
|
|
@ -510,6 +523,7 @@ union ImGL3WProcs {
|
|||
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
|
||||
PFNGLFLUSHPROC Flush;
|
||||
PFNGLGENBUFFERSPROC GenBuffers;
|
||||
PFNGLGENSAMPLERSPROC GenSamplers;
|
||||
PFNGLGENTEXTURESPROC GenTextures;
|
||||
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
|
||||
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
|
||||
|
|
@ -530,10 +544,12 @@ union ImGL3WProcs {
|
|||
PFNGLPIXELSTOREIPROC PixelStorei;
|
||||
PFNGLPOLYGONMODEPROC PolygonMode;
|
||||
PFNGLREADPIXELSPROC ReadPixels;
|
||||
PFNGLSAMPLERPARAMETERIPROC SamplerParameteri;
|
||||
PFNGLSCISSORPROC Scissor;
|
||||
PFNGLSHADERSOURCEPROC ShaderSource;
|
||||
PFNGLTEXIMAGE2DPROC TexImage2D;
|
||||
PFNGLTEXPARAMETERIPROC TexParameteri;
|
||||
PFNGLTEXSUBIMAGE2DPROC TexSubImage2D;
|
||||
PFNGLUNIFORM1IPROC Uniform1i;
|
||||
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
|
||||
PFNGLUSEPROGRAMPROC UseProgram;
|
||||
|
|
@ -563,6 +579,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
|||
#define glCreateShader imgl3wProcs.gl.CreateShader
|
||||
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
|
||||
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
|
||||
#define glDeleteSamplers imgl3wProcs.gl.DeleteSamplers
|
||||
#define glDeleteShader imgl3wProcs.gl.DeleteShader
|
||||
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
|
||||
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
|
||||
|
|
@ -575,6 +592,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
|||
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
|
||||
#define glFlush imgl3wProcs.gl.Flush
|
||||
#define glGenBuffers imgl3wProcs.gl.GenBuffers
|
||||
#define glGenSamplers imgl3wProcs.gl.GenSamplers
|
||||
#define glGenTextures imgl3wProcs.gl.GenTextures
|
||||
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
|
||||
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
|
||||
|
|
@ -595,10 +613,12 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
|||
#define glPixelStorei imgl3wProcs.gl.PixelStorei
|
||||
#define glPolygonMode imgl3wProcs.gl.PolygonMode
|
||||
#define glReadPixels imgl3wProcs.gl.ReadPixels
|
||||
#define glSamplerParameteri imgl3wProcs.gl.SamplerParameteri
|
||||
#define glScissor imgl3wProcs.gl.Scissor
|
||||
#define glShaderSource imgl3wProcs.gl.ShaderSource
|
||||
#define glTexImage2D imgl3wProcs.gl.TexImage2D
|
||||
#define glTexParameteri imgl3wProcs.gl.TexParameteri
|
||||
#define glTexSubImage2D imgl3wProcs.gl.TexSubImage2D
|
||||
#define glUniform1i imgl3wProcs.gl.Uniform1i
|
||||
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
|
||||
#define glUseProgram imgl3wProcs.gl.UseProgram
|
||||
|
|
@ -626,7 +646,7 @@ extern "C" {
|
|||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
static HMODULE libgl;
|
||||
static HMODULE libgl = NULL;
|
||||
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
|
||||
static GL3WglGetProcAddr wgl_get_proc_address;
|
||||
|
||||
|
|
@ -639,7 +659,7 @@ static int open_libgl(void)
|
|||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { FreeLibrary(libgl); }
|
||||
static void close_libgl(void) { FreeLibrary(libgl); libgl = NULL; }
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
|
|
@ -651,7 +671,7 @@ static GL3WglProc get_proc(const char *proc)
|
|||
#elif defined(__APPLE__)
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *libgl;
|
||||
static void *libgl = NULL;
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
|
||||
|
|
@ -660,7 +680,7 @@ static int open_libgl(void)
|
|||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { dlclose(libgl); }
|
||||
static void close_libgl(void) { dlclose(libgl); libgl = NULL; }
|
||||
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
|
|
@ -694,7 +714,11 @@ static void close_libgl(void)
|
|||
|
||||
static int is_library_loaded(const char* name, void** lib)
|
||||
{
|
||||
#if defined(__HAIKU__)
|
||||
*lib = NULL; // no support for RTLD_NOLOAD on Haiku.
|
||||
#else
|
||||
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||
#endif
|
||||
return *lib != NULL;
|
||||
}
|
||||
|
||||
|
|
@ -812,6 +836,7 @@ static int parse_version(void)
|
|||
}
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc);
|
||||
static void clear_procs();
|
||||
|
||||
int imgl3wInit(void)
|
||||
{
|
||||
|
|
@ -828,6 +853,12 @@ int imgl3wInit2(GL3WGetProcAddressProc proc)
|
|||
return parse_version();
|
||||
}
|
||||
|
||||
void imgl3wShutdown(void)
|
||||
{
|
||||
close_libgl();
|
||||
clear_procs();
|
||||
}
|
||||
|
||||
int imgl3wIsSupported(int major, int minor)
|
||||
{
|
||||
if (major < 2)
|
||||
|
|
@ -858,6 +889,7 @@ static const char *proc_names[] = {
|
|||
"glCreateShader",
|
||||
"glDeleteBuffers",
|
||||
"glDeleteProgram",
|
||||
"glDeleteSamplers",
|
||||
"glDeleteShader",
|
||||
"glDeleteTextures",
|
||||
"glDeleteVertexArrays",
|
||||
|
|
@ -870,6 +902,7 @@ static const char *proc_names[] = {
|
|||
"glEnableVertexAttribArray",
|
||||
"glFlush",
|
||||
"glGenBuffers",
|
||||
"glGenSamplers",
|
||||
"glGenTextures",
|
||||
"glGenVertexArrays",
|
||||
"glGetAttribLocation",
|
||||
|
|
@ -890,10 +923,12 @@ static const char *proc_names[] = {
|
|||
"glPixelStorei",
|
||||
"glPolygonMode",
|
||||
"glReadPixels",
|
||||
"glSamplerParameteri",
|
||||
"glScissor",
|
||||
"glShaderSource",
|
||||
"glTexImage2D",
|
||||
"glTexParameteri",
|
||||
"glTexSubImage2D",
|
||||
"glUniform1i",
|
||||
"glUniformMatrix4fv",
|
||||
"glUseProgram",
|
||||
|
|
@ -910,6 +945,13 @@ static void load_procs(GL3WGetProcAddressProc proc)
|
|||
imgl3wProcs.ptr[i] = proc(proc_names[i]);
|
||||
}
|
||||
|
||||
static void clear_procs()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = nullptr;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +1,22 @@
|
|||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
// TL;DR; this is using the ImGuiInputTextFlags_CallbackResize facility,
|
||||
// which also demonstrated in 'Dear ImGui Demo->Widgets->Text Input->Resize Callback'.
|
||||
|
||||
// Changelog:
|
||||
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
|
||||
// Usage:
|
||||
// {
|
||||
// #include "misc/cpp/imgui_stdlib.h"
|
||||
// #include "misc/cpp/imgui_stdlib.cpp" // <-- If you want to include implementation without messing with your project/build.
|
||||
// [...]
|
||||
// std::string my_string;
|
||||
// ImGui::InputText("my string", &my_string);
|
||||
// }
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntactic sugar) on Wiki:
|
||||
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
|
||||
|
||||
#include "imgui.h"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
// TL;DR; this is using the ImGuiInputTextFlags_CallbackResize facility,
|
||||
// which also demonstrated in 'Dear ImGui Demo->Widgets->Text Input->Resize Callback'.
|
||||
|
||||
// Changelog:
|
||||
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
|
||||
|
||||
// Usage:
|
||||
// {
|
||||
// #include "misc/cpp/imgui_stdlib.h"
|
||||
// #include "misc/cpp/imgui_stdlib.cpp" // <-- If you want to include implementation without messing with your project/build.
|
||||
// [...]
|
||||
// std::string my_string;
|
||||
// ImGui::InputText("my string", &my_string);
|
||||
// }
|
||||
|
||||
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
|
||||
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// dear imgui, v1.91.8
|
||||
// dear imgui, v1.92.6 WIP
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
|
|
@ -24,9 +24,9 @@ Index of this file:
|
|||
*/
|
||||
|
||||
// Navigating this file:
|
||||
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
|
||||
// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
|
||||
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
|
||||
// - In Visual Studio: Ctrl+Comma ("Edit.GoToAll") can follow symbols inside comments, whereas Ctrl+F12 ("Edit.GoToImplementation") cannot.
|
||||
// - In Visual Studio w/ Visual Assist installed: Alt+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
|
||||
// - In VS Code, CLion, etc.: Ctrl+Click can follow symbols inside comments.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Commentary
|
||||
|
|
@ -221,6 +221,7 @@ Index of this file:
|
|||
#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
|
||||
#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
|
||||
#pragma clang diagnostic ignored "-Wformat" // warning: format specifies type 'int' but the argument has type 'unsigned int'
|
||||
#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
|
||||
|
|
@ -230,6 +231,7 @@ Index of this file:
|
|||
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
|
||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
|
||||
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
|
||||
#pragma clang diagnostic ignored "-Wswitch-default" // warning: 'switch' missing 'default' label
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
|
|
@ -333,13 +335,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
// - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[].
|
||||
const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
|
||||
const ImVec2 avail_size = GetContentRegionAvail();
|
||||
const ImVec2 actual_outer_size = ImTrunc(CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f));
|
||||
const ImVec2 actual_outer_size = ImTrunc(CalcItemSize(outer_size, ImMax(avail_size.x, IMGUI_WINDOW_HARD_MIN_SIZE), use_child_window ? ImMax(avail_size.y, IMGUI_WINDOW_HARD_MIN_SIZE) : 0.0f));
|
||||
const ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size);
|
||||
const bool outer_window_is_measuring_size = (outer_window->AutoFitFramesX > 0) || (outer_window->AutoFitFramesY > 0); // Doesn't apply to AlwaysAutoResize windows!
|
||||
if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size)
|
||||
{
|
||||
ItemSize(outer_rect);
|
||||
ItemAdd(outer_rect, id);
|
||||
g.NextWindowData.ClearFlags();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -415,12 +418,15 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
|
||||
// Reset scroll if we are reactivating it
|
||||
if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
|
||||
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) == 0)
|
||||
if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasScroll) == 0)
|
||||
SetNextWindowScroll(ImVec2(0.0f, 0.0f));
|
||||
|
||||
// Create scrolling region (without border and zero window padding)
|
||||
ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
|
||||
BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags);
|
||||
ImGuiChildFlags child_child_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : ImGuiChildFlags_None;
|
||||
ImGuiWindowFlags child_window_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) ? g.NextWindowData.WindowFlags : ImGuiWindowFlags_None;
|
||||
if (flags & ImGuiTableFlags_ScrollX)
|
||||
child_window_flags |= ImGuiWindowFlags_HorizontalScrollbar;
|
||||
BeginChildEx(name, instance_id, outer_rect.GetSize(), child_child_flags, child_window_flags);
|
||||
table->InnerWindow = g.CurrentWindow;
|
||||
table->WorkRect = table->InnerWindow->WorkRect;
|
||||
table->OuterRect = table->InnerWindow->Rect();
|
||||
|
|
@ -431,7 +437,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
if (table->InnerWindow->SkipItems && outer_window_is_measuring_size)
|
||||
table->InnerWindow->SkipItems = false;
|
||||
|
||||
// When using multiple instances, ensure they have the same amount of horizontal decorations (aka vertical scrollbar) so stretched columns can be aligned)
|
||||
// When using multiple instances, ensure they have the same amount of horizontal decorations (aka vertical scrollbar) so stretched columns can be aligned
|
||||
if (instance_no == 0)
|
||||
{
|
||||
table->HasScrollbarYPrev = table->HasScrollbarYCurr;
|
||||
|
|
@ -445,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().
|
||||
table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
|
||||
table->HasScrollbarYPrev = table->HasScrollbarYCurr = false;
|
||||
table->InnerWindow->DC.TreeDepth++; // This is designed to always linking ImGuiTreeNodeFlags_DrawLines linking across a table
|
||||
}
|
||||
|
||||
// Push a standardized ID for both child-using and not-child-using tables
|
||||
|
|
@ -457,6 +464,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
table->HostIndentX = inner_window->DC.Indent.x;
|
||||
table->HostClipRect = inner_window->ClipRect;
|
||||
table->HostSkipItems = inner_window->SkipItems;
|
||||
temp_data->WindowID = inner_window->ID;
|
||||
temp_data->HostBackupWorkRect = inner_window->WorkRect;
|
||||
temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
||||
temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
||||
|
|
@ -535,7 +543,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
|
||||
// Make table current
|
||||
g.CurrentTable = table;
|
||||
outer_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX();
|
||||
inner_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX();
|
||||
outer_window->DC.CurrentTableIdx = table_idx;
|
||||
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
|
||||
inner_window->DC.CurrentTableIdx = table_idx;
|
||||
|
|
@ -556,9 +564,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
const int old_columns_count = table->Columns.size();
|
||||
if (old_columns_count != 0 && old_columns_count != columns_count)
|
||||
{
|
||||
// Attempt to preserve width on column count change (#4046)
|
||||
// Attempt to preserve width and other settings on column count/specs change (#4046)
|
||||
old_columns_to_preserve = table->Columns.Data;
|
||||
old_columns_raw_data = table->RawData;
|
||||
old_columns_raw_data = table->RawData; // Free at end of function
|
||||
table->RawData = NULL;
|
||||
}
|
||||
if (table->RawData == NULL)
|
||||
|
|
@ -573,6 +581,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
// Initialize
|
||||
table->SettingsOffset = -1;
|
||||
table->IsSortSpecsDirty = true;
|
||||
table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934)
|
||||
table->InstanceInteracted = -1;
|
||||
table->ContextPopupColumn = -1;
|
||||
table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1;
|
||||
|
|
@ -583,7 +592,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
ImGuiTableColumn* column = &table->Columns[n];
|
||||
if (old_columns_to_preserve && n < old_columns_count)
|
||||
{
|
||||
// FIXME: We don't attempt to preserve column order in this path.
|
||||
*column = old_columns_to_preserve[n];
|
||||
}
|
||||
else
|
||||
|
|
@ -593,8 +601,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||
column->WidthAuto = width_auto;
|
||||
column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
|
||||
column->IsEnabled = column->IsUserEnabled = column->IsUserEnabledNextFrame = true;
|
||||
column->DisplayOrder = (ImGuiTableColumnIdx)n;
|
||||
}
|
||||
column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
|
||||
table->DisplayOrderToIndex[n] = column->DisplayOrder;
|
||||
}
|
||||
}
|
||||
if (old_columns_raw_data)
|
||||
|
|
@ -938,7 +947,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||
// (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
|
||||
// large height (= first frame scrollbar display very off + clipper would skip lots of items).
|
||||
// This is merely making the side-effect less extreme, but doesn't properly fixes it.
|
||||
// FIXME: Move this to ->WidthGiven to avoid temporary lossyless?
|
||||
// FIXME: Move this to ->WidthGiven to avoid temporary lossyness?
|
||||
// FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller.
|
||||
if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto)
|
||||
column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale?
|
||||
|
|
@ -972,7 +981,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||
// [Part 4] Apply final widths based on requested widths
|
||||
const ImRect work_rect = table->WorkRect;
|
||||
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
|
||||
const float width_removed = (table->HasScrollbarYPrev && !table->InnerWindow->ScrollbarY) ? g.Style.ScrollbarSize : 0.0f; // To synchronize decoration width of synched tables with mismatching scrollbar state (#5920)
|
||||
const float width_removed = (table->HasScrollbarYPrev && !table->InnerWindow->ScrollbarY) ? g.Style.ScrollbarSize : 0.0f; // To synchronize decoration width of synced tables with mismatching scrollbar state (#5920)
|
||||
const float width_avail = ImMax(1.0f, (((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth()) - width_removed);
|
||||
const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests;
|
||||
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
|
||||
|
|
@ -1182,7 +1191,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||
}
|
||||
|
||||
// In case the table is visible (e.g. decorations) but all columns clipped, we keep a column visible.
|
||||
// Else if give no chance to a clipper-savy user to submit rows and therefore total contents height used by scrollbar.
|
||||
// Else if give no chance to a clipper-savvy user to submit rows and therefore total contents height used by scrollbar.
|
||||
if (has_at_least_one_column_requesting_output == false)
|
||||
{
|
||||
table->Columns[table->LeftMostEnabledColumn].IsRequestOutput = true;
|
||||
|
|
@ -1243,7 +1252,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||
|
||||
// [Part 11] Default context menu
|
||||
// - 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,
|
||||
// e.g. TableDrawDefaultContextMenu(table, table->Flags & ~ImGuiTableFlags_Hideable) will display everything EXCEPT columns visibility options.
|
||||
if (table->DisableDefaultContextMenu == false && TableBeginContextMenuPopup(table))
|
||||
|
|
@ -1358,7 +1367,7 @@ void ImGui::EndTable()
|
|||
ImGuiWindow* inner_window = table->InnerWindow;
|
||||
ImGuiWindow* outer_window = table->OuterWindow;
|
||||
ImGuiTableTempData* temp_data = table->TempData;
|
||||
IM_ASSERT(inner_window == g.CurrentWindow);
|
||||
IM_ASSERT(inner_window == g.CurrentWindow && inner_window->ID == temp_data->WindowID);
|
||||
IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
|
||||
|
||||
if (table->IsInsideRow)
|
||||
|
|
@ -1374,7 +1383,7 @@ void ImGui::EndTable()
|
|||
inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
|
||||
inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
|
||||
inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
|
||||
const float inner_content_max_y = table->RowPosY2;
|
||||
const float inner_content_max_y = ImCeil(table->RowPosY2); // Rounding final position is important as we currently don't round row height ('Demo->Tables->Outer Size' demo uses non-integer heights)
|
||||
IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y);
|
||||
if (inner_window != outer_window)
|
||||
inner_window->DC.CursorMaxPos.y = inner_content_max_y;
|
||||
|
|
@ -1385,7 +1394,7 @@ void ImGui::EndTable()
|
|||
|
||||
// Setup inner scrolling range
|
||||
// FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y,
|
||||
// but since the later is likely to be impossible to do we'd rather update both axises together.
|
||||
// but since the later is likely to be impossible to do we'd rather update both axes together.
|
||||
if (table->Flags & ImGuiTableFlags_ScrollX)
|
||||
{
|
||||
const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
|
||||
|
|
@ -1503,6 +1512,7 @@ void ImGui::EndTable()
|
|||
}
|
||||
else
|
||||
{
|
||||
table->InnerWindow->DC.TreeDepth--;
|
||||
ItemSize(table->OuterRect.GetSize());
|
||||
ItemAdd(table->OuterRect, 0);
|
||||
}
|
||||
|
|
@ -1550,7 +1560,7 @@ void ImGui::EndTable()
|
|||
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
|
||||
IM_ASSERT(g.TablesTempDataStacked > 0);
|
||||
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
|
||||
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
|
||||
g.CurrentTable = temp_data && (temp_data->WindowID == outer_window->ID) ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
|
||||
if (g.CurrentTable)
|
||||
{
|
||||
g.CurrentTable->TempData = temp_data;
|
||||
|
|
@ -1560,6 +1570,31 @@ void ImGui::EndTable()
|
|||
NavUpdateCurrentWindowIsScrollPushableX();
|
||||
}
|
||||
|
||||
// Called in TableSetupColumn() when initializing and in TableLoadSettings() for defaults before applying stored settings.
|
||||
// 'init_mask' specify which fields to initialize.
|
||||
static void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags init_mask)
|
||||
{
|
||||
ImGuiTableColumnFlags flags = column->Flags;
|
||||
if (init_mask & ImGuiTableFlags_Resizable)
|
||||
{
|
||||
float init_width_or_weight = column->InitStretchWeightOrWidth;
|
||||
column->WidthRequest = ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f;
|
||||
column->StretchWeight = (init_width_or_weight > 0.0f && (flags & ImGuiTableColumnFlags_WidthStretch)) ? init_width_or_weight : -1.0f;
|
||||
if (init_width_or_weight > 0.0f) // Disable auto-fit if an explicit width/weight has been specified
|
||||
column->AutoFitQueue = 0x00;
|
||||
}
|
||||
if (init_mask & ImGuiTableFlags_Reorderable)
|
||||
column->DisplayOrder = (ImGuiTableColumnIdx)table->Columns.index_from_ptr(column);
|
||||
if (init_mask & ImGuiTableFlags_Hideable)
|
||||
column->IsUserEnabled = column->IsUserEnabledNextFrame = (flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1;
|
||||
if (init_mask & ImGuiTableFlags_Sortable)
|
||||
{
|
||||
// Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs.
|
||||
column->SortOrder = (flags & ImGuiTableColumnFlags_DefaultSort) ? 0 : -1;
|
||||
column->SortDirection = (flags & ImGuiTableColumnFlags_DefaultSort) ? ((flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending)) : (ImS8)ImGuiSortDirection_None;
|
||||
}
|
||||
}
|
||||
|
||||
// See "COLUMNS SIZING POLICIES" comments at the top of this file
|
||||
// If (init_width_or_weight <= 0.0f) it is ignored
|
||||
void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id)
|
||||
|
|
@ -1588,7 +1623,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
|||
IM_ASSERT(init_width_or_weight <= 0.0f && "Can only specify width/weight if sizing policy is set explicitly in either Table or Column.");
|
||||
|
||||
// When passing a width automatically enforce WidthFixed policy
|
||||
// (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable)
|
||||
// (whereas TableSetupColumnFlags would default to WidthAuto if table is not resizable)
|
||||
if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f)
|
||||
if ((table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || (table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
|
||||
flags |= ImGuiTableColumnFlags_WidthFixed;
|
||||
|
|
@ -1606,27 +1641,10 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
|||
column->InitStretchWeightOrWidth = init_width_or_weight;
|
||||
if (table->IsInitializing)
|
||||
{
|
||||
// Init width or weight
|
||||
ImGuiTableFlags init_flags = ~table->SettingsLoadedFlags;
|
||||
if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f)
|
||||
{
|
||||
if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f)
|
||||
column->WidthRequest = init_width_or_weight;
|
||||
if (flags & ImGuiTableColumnFlags_WidthStretch)
|
||||
column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f;
|
||||
|
||||
// Disable auto-fit if an explicit width/weight has been specified
|
||||
if (init_width_or_weight > 0.0f)
|
||||
column->AutoFitQueue = 0x00;
|
||||
}
|
||||
|
||||
// Init default visibility/sort state
|
||||
if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0)
|
||||
column->IsUserEnabled = column->IsUserEnabledNextFrame = false;
|
||||
if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0)
|
||||
{
|
||||
column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs.
|
||||
column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending);
|
||||
}
|
||||
init_flags |= ImGuiTableFlags_Resizable;
|
||||
TableInitColumnDefaults(table, column, init_flags);
|
||||
}
|
||||
|
||||
// Store name (append with zero-terminator in contiguous buffer)
|
||||
|
|
@ -1635,7 +1653,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
|||
if (label != NULL && label[0] != 0)
|
||||
{
|
||||
column->NameOffset = (ImS16)table->ColumnsNames.size();
|
||||
table->ColumnsNames.append(label, label + strlen(label) + 1);
|
||||
table->ColumnsNames.append(label, label + ImStrlen(label) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1808,6 +1826,11 @@ void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n
|
|||
ImGuiContext& g = *GImGui;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
IM_ASSERT(target != ImGuiTableBgTarget_None);
|
||||
if (table == NULL)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (color == IM_COL32_DISABLE)
|
||||
color = 0;
|
||||
|
|
@ -1936,7 +1959,10 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
|||
IM_ASSERT(table->IsInsideRow);
|
||||
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
TableEndCell(table);
|
||||
table->CurrentColumn = -1;
|
||||
}
|
||||
|
||||
// Logging
|
||||
if (g.LogEnabled)
|
||||
|
|
@ -2029,10 +2055,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
|||
}
|
||||
|
||||
// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
|
||||
// We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and
|
||||
// get the new cursor position.
|
||||
// - We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark
|
||||
// end of row and get the new cursor position.
|
||||
if (unfreeze_rows_request)
|
||||
{
|
||||
IM_ASSERT(table->FreezeRowsRequest > 0);
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
table->Columns[column_n].NavLayerCurrent = table->NavLayer;
|
||||
const float y0 = ImMax(table->RowPosY2 + 1, table->InnerClipRect.Min.y);
|
||||
|
|
@ -2101,7 +2128,11 @@ bool ImGui::TableSetColumnIndex(int column_n)
|
|||
{
|
||||
if (table->CurrentColumn != -1)
|
||||
TableEndCell(table);
|
||||
IM_ASSERT(column_n >= 0 && table->ColumnsCount);
|
||||
if ((column_n >= 0 && column_n < table->ColumnsCount) == false)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(column_n >= 0 && column_n < table->ColumnsCount, "TableSetColumnIndex() invalid column index!");
|
||||
return false;
|
||||
}
|
||||
TableBeginCell(table, column_n);
|
||||
}
|
||||
|
||||
|
|
@ -2172,6 +2203,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
|
|||
g.LastItemData.StatusFlags = 0;
|
||||
}
|
||||
|
||||
// Also see TablePushColumnChannel()
|
||||
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.
|
||||
|
|
@ -2426,6 +2458,11 @@ void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
|
|||
// - TableDrawBorders() [Internal]
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
||||
// FIXME: This could be abstracted and merged with PushColumnsBackground(), by creating a generic struct
|
||||
// with storage for backup cliprect + backup channel + storage for splitter pointer, new clip rect.
|
||||
// This would slightly simplify caller code.
|
||||
|
||||
// Bg2 is used by Selectable (and possibly other widgets) to render to the background.
|
||||
// Unlike our Bg0/1 channel which we uses for RowBg/CellBg/Borders and where we guarantee all shapes to be CPU-clipped, the Bg2 channel being widgets-facing will rely on regular ClipRect.
|
||||
void ImGui::TablePushBackgroundChannel()
|
||||
|
|
@ -2445,10 +2482,38 @@ void ImGui::TablePopBackgroundChannel()
|
|||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||
|
||||
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -2466,7 +2531,7 @@ void ImGui::TablePopBackgroundChannel()
|
|||
// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call)
|
||||
// - Clip --> 2+D+N channels
|
||||
// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero)
|
||||
// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero)
|
||||
// - FreezeRows || FreezeColumns --> 3+D+N*2 (unless scrolling value is zero)
|
||||
// Where D is 1 if any column is clipped or hidden (dummy channel) otherwise 0.
|
||||
void ImGui::TableSetupDrawChannels(ImGuiTable* table)
|
||||
{
|
||||
|
|
@ -2559,7 +2624,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
|||
const int size_for_masks_bitarrays_one = (int)ImBitArrayGetStorageSizeInBytes(max_draw_channels);
|
||||
g.TempBuffer.reserve(size_for_masks_bitarrays_one * 5);
|
||||
memset(g.TempBuffer.Data, 0, size_for_masks_bitarrays_one * 5);
|
||||
for (int n = 0; n < IM_ARRAYSIZE(merge_groups); n++)
|
||||
for (int n = 0; n < IM_COUNTOF(merge_groups); n++)
|
||||
merge_groups[n].ChannelsMask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * n));
|
||||
ImBitArrayPtr remaining_mask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * 4));
|
||||
|
||||
|
|
@ -2616,7 +2681,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
|||
// [DEBUG] Display merge groups
|
||||
#if 0
|
||||
if (g.IO.KeyShift)
|
||||
for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
|
||||
for (int merge_group_n = 0; merge_group_n < IM_COUNTOF(merge_groups); merge_group_n++)
|
||||
{
|
||||
MergeGroup* merge_group = &merge_groups[merge_group_n];
|
||||
if (merge_group->ChannelsCount == 0)
|
||||
|
|
@ -2644,7 +2709,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
|||
int remaining_count = splitter->_Count - (has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS);
|
||||
//ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect;
|
||||
ImRect host_rect = table->HostClipRect;
|
||||
for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
|
||||
for (int merge_group_n = 0; merge_group_n < IM_COUNTOF(merge_groups); merge_group_n++)
|
||||
{
|
||||
if (int merge_channels_count = merge_groups[merge_group_n].ChannelsCount)
|
||||
{
|
||||
|
|
@ -2759,8 +2824,13 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
|||
continue;
|
||||
|
||||
// Draw in outer window so right-most column won't be clipped
|
||||
// Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling.
|
||||
float draw_y2 = (is_hovered || is_resized || is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) == 0) ? draw_y2_body : draw_y2_head;
|
||||
float draw_y2 = draw_y2_head;
|
||||
if (is_frozen_separator)
|
||||
draw_y2 = draw_y2_body;
|
||||
else if ((table->Flags & ImGuiTableFlags_NoBordersInBodyUntilResize) != 0 && (is_hovered || is_resized))
|
||||
draw_y2 = draw_y2_body;
|
||||
else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0)
|
||||
draw_y2 = draw_y2_body;
|
||||
if (draw_y2 > draw_y1)
|
||||
inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size);
|
||||
}
|
||||
|
|
@ -2823,9 +2893,7 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
|
|||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
IM_ASSERT(table != NULL);
|
||||
|
||||
if (!(table->Flags & ImGuiTableFlags_Sortable))
|
||||
if (table == NULL || !(table->Flags & ImGuiTableFlags_Sortable))
|
||||
return NULL;
|
||||
|
||||
// Require layout (in case TableHeadersRow() hasn't been called) as it may alter IsSortSpecsDirty in some paths.
|
||||
|
|
@ -3134,7 +3202,7 @@ void ImGui::TableHeader(const char* label)
|
|||
sort_arrow = true;
|
||||
if (column->SortOrder > 0)
|
||||
{
|
||||
ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
|
||||
ImFormatString(sort_order_suf, IM_COUNTOF(sort_order_suf), "%d", column->SortOrder + 1);
|
||||
w_sort_text = g.Style.ItemInnerSpacing.x + CalcTextSize(sort_order_suf).x;
|
||||
}
|
||||
}
|
||||
|
|
@ -3225,7 +3293,7 @@ void ImGui::TableHeader(const char* label)
|
|||
// Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will
|
||||
// be merged into a single draw call.
|
||||
//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);
|
||||
if (text_clipped && hovered && g.ActiveId == 0)
|
||||
|
|
@ -3322,7 +3390,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
|||
ButtonBehavior(row_r, row_id, NULL, NULL);
|
||||
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 ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
|
||||
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
|
||||
|
|
@ -3358,7 +3426,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
|
|||
|
||||
// Left<>Right alignment
|
||||
float line_off_curr_x = flip_label ? (label_lines - 1) * line_off_step_x : 0.0f;
|
||||
float line_off_for_align_x = ImMax((((column->MaxX - column->MinX) - padding.x * 2.0f) - (label_lines * line_off_step_x)), 0.0f) * align.x;
|
||||
float line_off_for_align_x = ImFloor(ImMax((((column->MaxX - column->MinX) - padding.x * 2.0f) - (label_lines * line_off_step_x)), 0.0f) * align.x);
|
||||
line_off_curr_x += line_off_for_align_x - line_off_for_ascent_x;
|
||||
|
||||
// Register header width
|
||||
|
|
@ -3377,7 +3445,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));
|
||||
int vtx_idx_begin = draw_list->_VtxCurrentIdx;
|
||||
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();
|
||||
int vtx_idx_end = draw_list->_VtxCurrentIdx;
|
||||
|
||||
|
|
@ -3714,9 +3782,16 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
|
|||
table->SettingsLoadedFlags = settings->SaveFlags;
|
||||
table->RefScale = settings->RefScale;
|
||||
|
||||
// Initialize default columns settings
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
TableInitColumnDefaults(table, column, ~0);
|
||||
column->AutoFitQueue = 0x00;
|
||||
}
|
||||
|
||||
// Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn
|
||||
ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings();
|
||||
ImU64 display_order_mask = 0;
|
||||
for (int data_n = 0; data_n < settings->ColumnsCount; data_n++, column_settings++)
|
||||
{
|
||||
int column_n = column_settings->Index;
|
||||
|
|
@ -3730,29 +3805,54 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
|
|||
column->StretchWeight = column_settings->WidthOrWeight;
|
||||
else
|
||||
column->WidthRequest = column_settings->WidthOrWeight;
|
||||
column->AutoFitQueue = 0x00;
|
||||
}
|
||||
if (settings->SaveFlags & ImGuiTableFlags_Reorderable)
|
||||
column->DisplayOrder = column_settings->DisplayOrder;
|
||||
else
|
||||
column->DisplayOrder = (ImGuiTableColumnIdx)column_n;
|
||||
display_order_mask |= (ImU64)1 << column->DisplayOrder;
|
||||
column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled;
|
||||
if ((settings->SaveFlags & ImGuiTableFlags_Hideable) && column_settings->IsEnabled != -1)
|
||||
column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled == 1;
|
||||
column->SortOrder = column_settings->SortOrder;
|
||||
column->SortDirection = column_settings->SortDirection;
|
||||
}
|
||||
|
||||
// Validate and fix invalid display order data
|
||||
const ImU64 expected_display_order_mask = (settings->ColumnsCount == 64) ? ~0 : ((ImU64)1 << settings->ColumnsCount) - 1;
|
||||
if (display_order_mask != expected_display_order_mask)
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
table->Columns[column_n].DisplayOrder = (ImGuiTableColumnIdx)column_n;
|
||||
|
||||
// Rebuild index
|
||||
// Fix display order and build index
|
||||
if (settings->SaveFlags & ImGuiTableFlags_Reorderable)
|
||||
TableFixDisplayOrder(table);
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n;
|
||||
}
|
||||
|
||||
struct ImGuiTableFixDisplayOrderColumnData
|
||||
{
|
||||
ImGuiTableColumnIdx Idx;
|
||||
ImGuiTable* Table; // This is unfortunate but we don't have userdata in qsort api.
|
||||
};
|
||||
|
||||
// Sort by DisplayOrder and then Index
|
||||
static int IMGUI_CDECL TableFixDisplayOrderComparer(const void* lhs, const void* rhs)
|
||||
{
|
||||
const ImGuiTable* table = ((const ImGuiTableFixDisplayOrderColumnData*)lhs)->Table;
|
||||
const ImGuiTableColumnIdx lhs_idx = ((const ImGuiTableFixDisplayOrderColumnData*)lhs)->Idx;
|
||||
const ImGuiTableColumnIdx rhs_idx = ((const ImGuiTableFixDisplayOrderColumnData*)rhs)->Idx;
|
||||
const int order_delta = (table->Columns[lhs_idx].DisplayOrder - table->Columns[rhs_idx].DisplayOrder);
|
||||
return (order_delta > 0) ? +1 : (order_delta < 0) ? -1 : (lhs_idx > rhs_idx) ? +1 : -1;
|
||||
}
|
||||
|
||||
// Fix invalid display order data: compact values (0,1,3 -> 0,1,2); preserve relative order (0,3,1 -> 0,2,1); deduplicate (0,4,1,1 -> 0,3,1,2)
|
||||
void ImGui::TableFixDisplayOrder(ImGuiTable* table)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.TempBuffer.reserve((int)(sizeof(ImGuiTableFixDisplayOrderColumnData) * table->ColumnsCount)); // FIXME: Maybe wrap those two lines as a helper.
|
||||
ImGuiTableFixDisplayOrderColumnData* fdo_columns = (ImGuiTableFixDisplayOrderColumnData*)(void*)g.TempBuffer.Data;
|
||||
for (int n = 0; n < table->ColumnsCount; n++)
|
||||
{
|
||||
fdo_columns[n].Idx = (ImGuiTableColumnIdx)n;
|
||||
fdo_columns[n].Table = table;
|
||||
}
|
||||
ImQsort(fdo_columns, (size_t)table->ColumnsCount, sizeof(ImGuiTableFixDisplayOrderColumnData), TableFixDisplayOrderComparer);
|
||||
for (int n = 0; n < table->ColumnsCount; n++)
|
||||
table->Columns[fdo_columns[n].Idx].DisplayOrder = (ImGuiTableColumnIdx)n;
|
||||
}
|
||||
|
||||
static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
|
||||
{
|
||||
ImGuiContext& g = *ctx;
|
||||
|
|
@ -3833,8 +3933,7 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
|||
const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0;
|
||||
const bool save_order = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0;
|
||||
const bool save_sort = (settings->SaveFlags & ImGuiTableFlags_Sortable) != 0;
|
||||
if (!save_size && !save_visible && !save_order && !save_sort)
|
||||
continue;
|
||||
// We need to save the [Table] entry even if all the bools are false, since this records a table with "default settings".
|
||||
|
||||
buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve
|
||||
buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount);
|
||||
|
|
@ -3881,7 +3980,7 @@ void ImGui::TableSettingsAddSettingsHandler()
|
|||
// - TableGcCompactSettings() [Internal]
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Remove Table (currently only used by TestEngine)
|
||||
// Remove Table data (currently only used by TestEngine)
|
||||
void ImGui::TableRemove(ImGuiTable* table)
|
||||
{
|
||||
//IMGUI_DEBUG_PRINT("TableRemove() id=0x%08X\n", table->ID);
|
||||
|
|
@ -3960,9 +4059,9 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
|||
bool open = TreeNode(table, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
|
||||
if (!is_active) { PopStyleColor(); }
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
|
||||
if (IsItemVisible() && table->HoveredColumnBody != -1)
|
||||
GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
|
||||
if (!open)
|
||||
return;
|
||||
if (table->InstanceCurrent > 0)
|
||||
|
|
@ -3995,7 +4094,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
|||
ImGuiTableColumn* column = &table->Columns[n];
|
||||
const char* name = TableGetColumnName(table, n);
|
||||
char buf[512];
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf),
|
||||
ImFormatString(buf, IM_COUNTOF(buf),
|
||||
"Column %d order %d '%s': offset %+.2f to %+.2f%s\n"
|
||||
"Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n"
|
||||
"WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n"
|
||||
|
|
@ -4016,7 +4115,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
|||
if (IsItemHovered())
|
||||
{
|
||||
ImRect r(column->MinX, table->OuterRect.Min.y, column->MaxX, table->OuterRect.Max.y);
|
||||
GetForegroundDrawList()->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255));
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255));
|
||||
}
|
||||
}
|
||||
if (ImGuiTableSettings* settings = TableGetBoundSettings(table))
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,8 @@
|
|||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
||||
// - Added name to struct or it may be forward declared in our code.
|
||||
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
// - Changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion.
|
||||
// Grep for [DEAR IMGUI] to find some changes.
|
||||
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
||||
|
||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// !!!! (2025-10-23) changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion.
|
||||
// 1.14 (2021-07-11) page up/down, various fixes
|
||||
// 1.13 (2019-02-07) fix bug in undo size management
|
||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||
|
|
@ -141,12 +143,14 @@
|
|||
// with previous char)
|
||||
// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
|
||||
// (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_NEWLINE the character returned by _GETCHAR() we recognize
|
||||
// as manually wordwrapping for end-of-line positioning
|
||||
//
|
||||
// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
|
||||
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
|
||||
// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) try to insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
|
||||
// returns number of characters actually inserted. [DEAR IMGUI]
|
||||
//
|
||||
// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
|
||||
//
|
||||
|
|
@ -178,6 +182,13 @@
|
|||
// 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
|
||||
//
|
||||
// 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
|
||||
// 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,
|
||||
|
|
@ -250,8 +261,10 @@
|
|||
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||
// transformed into text and stb_textedit_text() is automatically called.
|
||||
//
|
||||
// text: [DEAR IMGUI] added 2024-09
|
||||
// call this to text inputs sent to the textfield.
|
||||
// text: (added 2025)
|
||||
// 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
|
||||
|
|
@ -400,6 +413,16 @@ typedef struct
|
|||
#define IMSTB_TEXTEDIT_memmove memmove
|
||||
#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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -407,7 +430,7 @@ typedef struct
|
|||
//
|
||||
|
||||
// traverse the layout to locate the nearest character to a display position
|
||||
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
||||
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y, int* out_side_on_line)
|
||||
{
|
||||
StbTexteditRow r;
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
|
|
@ -417,6 +440,7 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
|||
r.x0 = r.x1 = 0;
|
||||
r.ymin = r.ymax = 0;
|
||||
r.num_chars = 0;
|
||||
*out_side_on_line = 0;
|
||||
|
||||
// search rows to find one that straddles 'y'
|
||||
while (i < n) {
|
||||
|
|
@ -436,7 +460,10 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
|||
|
||||
// below all text, return 'after' last character
|
||||
if (i >= n)
|
||||
{
|
||||
*out_side_on_line = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
// check if it's before the beginning of the line
|
||||
if (x < r.x0)
|
||||
|
|
@ -449,6 +476,7 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
|||
for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) {
|
||||
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
||||
if (x < prev_x+w) {
|
||||
*out_side_on_line = (k == 0) ? 0 : 1;
|
||||
if (x < prev_x+w/2)
|
||||
return k+i;
|
||||
else
|
||||
|
|
@ -460,6 +488,7 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
|||
}
|
||||
|
||||
// if the last character is a newline, return that. otherwise return 'after' the last character
|
||||
*out_side_on_line = 1;
|
||||
if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE)
|
||||
return i+r.num_chars-1;
|
||||
else
|
||||
|
|
@ -471,6 +500,7 @@ static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *st
|
|||
{
|
||||
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
||||
// goes off the top or bottom of the text
|
||||
int side_on_line;
|
||||
if( state->single_line )
|
||||
{
|
||||
StbTexteditRow r;
|
||||
|
|
@ -478,16 +508,18 @@ static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *st
|
|||
y = r.ymin;
|
||||
}
|
||||
|
||||
state->cursor = stb_text_locate_coord(str, x, y);
|
||||
state->cursor = stb_text_locate_coord(str, x, y, &side_on_line);
|
||||
state->select_start = state->cursor;
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
str->LastMoveDirectionLR = (ImS8)(side_on_line ? ImGuiDir_Right : ImGuiDir_Left);
|
||||
}
|
||||
|
||||
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
|
||||
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||
{
|
||||
int p = 0;
|
||||
int side_on_line;
|
||||
|
||||
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
||||
// goes off the top or bottom of the text
|
||||
|
|
@ -501,8 +533,9 @@ static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *sta
|
|||
if (state->select_start == state->select_end)
|
||||
state->select_start = state->cursor;
|
||||
|
||||
p = stb_text_locate_coord(str, x, y);
|
||||
p = stb_text_locate_coord(str, x, y, &side_on_line);
|
||||
state->cursor = state->select_end = p;
|
||||
str->LastMoveDirectionLR = (ImS8)(side_on_line ? ImGuiDir_Right : ImGuiDir_Left);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -552,6 +585,8 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
|
|||
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||
if (n < i + r.num_chars)
|
||||
break;
|
||||
if (str->LastMoveDirectionLR == ImGuiDir_Right && str->Stb->cursor > 0 && str->Stb->cursor == i + r.num_chars && STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] Wrapping point handling
|
||||
break;
|
||||
if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line
|
||||
break; // [DEAR IMGUI]
|
||||
prev_start = i;
|
||||
|
|
@ -648,15 +683,33 @@ 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)
|
||||
// [DEAR IMGUI] Extracted this function so we can more easily add support for word-wrapping.
|
||||
#ifndef STB_TEXTEDIT_MOVELINESTART
|
||||
static int stb_textedit_move_line_start(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int cursor)
|
||||
{
|
||||
if (state->single_line)
|
||||
return 0;
|
||||
while (cursor > 0) {
|
||||
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, cursor);
|
||||
if (STB_TEXTEDIT_GETCHAR(str, prev) == STB_TEXTEDIT_NEWLINE)
|
||||
break;
|
||||
cursor = prev;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
#define STB_TEXTEDIT_MOVELINESTART stb_textedit_move_line_start
|
||||
#endif
|
||||
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
|
||||
#ifndef STB_TEXTEDIT_MOVELINEEND
|
||||
static int stb_textedit_move_line_end(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int cursor)
|
||||
{
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
if (state->single_line)
|
||||
return n;
|
||||
while (cursor < n && STB_TEXTEDIT_GETCHAR(str, cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, cursor);
|
||||
return cursor;
|
||||
}
|
||||
#define STB_TEXTEDIT_MOVELINEEND stb_textedit_move_line_end
|
||||
#endif
|
||||
|
||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||
|
|
@ -668,9 +721,9 @@ static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
|||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
--c; // always move at least one character
|
||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
||||
--c;
|
||||
c = IMSTB_TEXTEDIT_GETPREVCHARINDEX( str, c ); // always move at least one character
|
||||
while (c >= 0 && !is_word_boundary(str, c))
|
||||
c = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, c);
|
||||
|
||||
if( c < 0 )
|
||||
c = 0;
|
||||
|
|
@ -684,9 +737,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 )
|
||||
{
|
||||
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 ) )
|
||||
++c;
|
||||
c = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, c);
|
||||
|
||||
if( c > len )
|
||||
c = len;
|
||||
|
|
@ -725,7 +778,8 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
|||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_delete_selection(str,state);
|
||||
// try to insert the characters
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
|
||||
len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len);
|
||||
if (len) {
|
||||
stb_text_makeundo_insert(state, state->cursor, len);
|
||||
state->cursor += len;
|
||||
state->has_preferred_x = 0;
|
||||
|
|
@ -739,6 +793,7 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
|||
#define STB_TEXTEDIT_KEYTYPE int
|
||||
#endif
|
||||
|
||||
// API key: process text input
|
||||
// [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)
|
||||
{
|
||||
|
|
@ -749,14 +804,15 @@ static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* sta
|
|||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||
text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len);
|
||||
if (text_len) {
|
||||
state->cursor += text_len;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||
text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len);
|
||||
if (text_len) {
|
||||
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||
state->cursor += text_len;
|
||||
state->has_preferred_x = 0;
|
||||
|
|
@ -771,6 +827,7 @@ retry:
|
|||
switch (key) {
|
||||
default: {
|
||||
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||
// This is not suitable for UTF-8 support.
|
||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||
if (c > 0) {
|
||||
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||
|
|
@ -911,15 +968,16 @@ retry:
|
|||
|
||||
// [DEAR IMGUI]
|
||||
// going down while being on the last line shouldn't bring us to that line end
|
||||
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
break;
|
||||
//if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
// break;
|
||||
|
||||
// now find character position down a row
|
||||
state->cursor = start;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
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);
|
||||
int next = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
break;
|
||||
|
|
@ -927,10 +985,13 @@ retry:
|
|||
x += dx;
|
||||
if (x > goal_x)
|
||||
break;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
i += next - state->cursor;
|
||||
state->cursor = next;
|
||||
}
|
||||
stb_textedit_clamp(str, state);
|
||||
|
||||
if (state->cursor == find.first_char + find.length)
|
||||
str->LastMoveDirectionLR = ImGuiDir_Left;
|
||||
state->has_preferred_x = 1;
|
||||
state->preferred_x = goal_x;
|
||||
|
||||
|
|
@ -980,8 +1041,9 @@ retry:
|
|||
state->cursor = find.prev_first;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
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);
|
||||
int next = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
break;
|
||||
|
|
@ -989,10 +1051,15 @@ retry:
|
|||
x += dx;
|
||||
if (x > goal_x)
|
||||
break;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
i += next - state->cursor;
|
||||
state->cursor = next;
|
||||
}
|
||||
stb_textedit_clamp(str, state);
|
||||
|
||||
if (state->cursor == find.first_char)
|
||||
str->LastMoveDirectionLR = ImGuiDir_Right;
|
||||
else if (state->cursor == find.prev_first)
|
||||
str->LastMoveDirectionLR = ImGuiDir_Left;
|
||||
state->has_preferred_x = 1;
|
||||
state->preferred_x = goal_x;
|
||||
|
||||
|
|
@ -1002,10 +1069,15 @@ retry:
|
|||
// go to previous line
|
||||
// (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;
|
||||
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
--prev_scan;
|
||||
while (prev_scan > 0)
|
||||
{
|
||||
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.prev_first = prev_scan;
|
||||
find.prev_first = STB_TEXTEDIT_MOVELINESTART(str, state, prev_scan);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1079,10 +1151,7 @@ retry:
|
|||
case STB_TEXTEDIT_K_LINESTART:
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_move_to_first(state);
|
||||
if (state->single_line)
|
||||
state->cursor = 0;
|
||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||
--state->cursor;
|
||||
state->cursor = STB_TEXTEDIT_MOVELINESTART(str, state, state->cursor);
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
|
|
@ -1090,13 +1159,9 @@ retry:
|
|||
case STB_TEXTEDIT_K_LINEEND2:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_LINEEND: {
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_move_to_first(state);
|
||||
if (state->single_line)
|
||||
state->cursor = n;
|
||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
++state->cursor;
|
||||
stb_textedit_move_to_last(str, state);
|
||||
state->cursor = STB_TEXTEDIT_MOVELINEEND(str, state, state->cursor);
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1107,10 +1172,7 @@ retry:
|
|||
case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
if (state->single_line)
|
||||
state->cursor = 0;
|
||||
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
|
||||
--state->cursor;
|
||||
state->cursor = STB_TEXTEDIT_MOVELINESTART(str, state, state->cursor);
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
|
@ -1119,13 +1181,9 @@ retry:
|
|||
case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
|
||||
#endif
|
||||
case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
if (state->single_line)
|
||||
state->cursor = n;
|
||||
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
|
||||
++state->cursor;
|
||||
state->cursor = STB_TEXTEDIT_MOVELINEEND(str, state, state->cursor);
|
||||
state->select_end = state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
|
@ -1300,7 +1358,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
|||
// check type of recorded action:
|
||||
if (u.insert_length) {
|
||||
// easy case: was a deletion, so we need to insert n characters
|
||||
STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
|
||||
u.insert_length = STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
|
||||
s->undo_char_point -= u.insert_length;
|
||||
}
|
||||
|
||||
|
|
@ -1351,7 +1409,7 @@ static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
|||
|
||||
if (r.insert_length) {
|
||||
// easy case: need to insert n characters
|
||||
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
|
||||
r.insert_length = STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
|
||||
s->redo_char_point += r.insert_length;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4516,8 +4516,8 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
|||
q2[0] = (float)x2;
|
||||
q2[1] = (float)y2;
|
||||
if (equal(q0,q1) || equal(q1,q2)) {
|
||||
x0 = (int)verts[i-1].x;
|
||||
y0 = (int)verts[i-1].y;
|
||||
x0 = (int)verts[i-1].x; //-V1048
|
||||
y0 = (int)verts[i-1].y; //-V1048
|
||||
x1 = (int)verts[i ].x;
|
||||
y1 = (int)verts[i ].y;
|
||||
if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ static uint32_t __always_zero = 0;
|
|||
);
|
||||
|
||||
ImVec2 size = ImVec2(0., 133.);
|
||||
if (ImGui::BeginChild(ImGui::GetID("###x-table-frame"), size, false, FRAME_FLAGS | ImGuiWindowFlags_NavFlattened)) {
|
||||
if (ImGui::BeginChild(ImGui::GetID("###x-table-frame"), size, ImGuiChildFlags_NavFlattened, FRAME_FLAGS)) {
|
||||
if (ImGui::BeginTable("###x-table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_NoSavedSettings)) {
|
||||
ImGui::TableSetupColumn("###", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Object");
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ namespace UiLevelManager {
|
|||
ImGui::Separator();
|
||||
|
||||
//Actual level list
|
||||
ImGui::BeginChild("save_list_child", ImVec2(0., 500.), false, FRAME_FLAGS | ImGuiWindowFlags_NavFlattened);
|
||||
if (ImGui::BeginTable("save_list", 5, ImGuiTableFlags_NoSavedSettings | ImGuiWindowFlags_NavFlattened | ImGuiTableFlags_Borders)) {
|
||||
ImGui::BeginChild("save_list_child", ImVec2(0., 500.), ImGuiChildFlags_NavFlattened, FRAME_FLAGS);
|
||||
if (ImGui::BeginTable("save_list", 5, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) {
|
||||
//Setup table columns
|
||||
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ namespace UiQuickadd {
|
|||
}
|
||||
|
||||
const float area_height = ImGui::GetTextLineHeightWithSpacing() * 7.25f + ImGui::GetStyle().FramePadding.y * 2.0f;
|
||||
if (ImGui::BeginChildFrame(ImGui::GetID("qsbox"), ImVec2(-FLT_MIN, area_height), ImGuiWindowFlags_NavFlattened)) {
|
||||
if (ImGui::BeginChild(ImGui::GetID("qsbox"), ImVec2(-FLT_MIN, area_height), ImGuiChildFlags_FrameStyle)) {
|
||||
for (int i = 0; i < search_results.size(); i++) {
|
||||
ImGui::PushID(i);
|
||||
SearchItem item = haystack[search_results[i]];
|
||||
|
|
@ -155,7 +155,7 @@ namespace UiQuickadd {
|
|||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue