Compare commits

...

12 Commits

Author SHA1 Message Date
Rekai Nyangadzayi Musuka 5149d4b1de fix: ensure that main.zig is removed 2023-06-19 10:51:43 -05:00
Rekai Nyangadzayi Musuka 11337f53c6 fix: restore import for glfw w/ opengl3 backend
rebase unalived that specific line. Whoops
2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 159eaf8c50 feat: prefer SDL.h instead of SDL/SDL.h on all supported platforms 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka ca6d7f02a4 chore: explicitly link SDL2
TODO: What happens on Windows? macOS?
2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 90390053e7 fix: vcpkg stores SDL.h under SDL2 folder
macOS and Linux seem to not, so in order to get CI working again I
should make use of the preprocessor.

FIXME: I think this makes vcpkg a **hard** requirement which perhaps
isn't ideal if I want ZBA to be as easy to build as possible. I should
try ensuring that building w/out vcpkg works as well
2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka a9bdeed635 feat: add sdl2-opengl3 backend impl 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 709389942d chore: handle all cases of enum 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 7bc8b8c014 chore: combine render() and draw() in backend 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 1f42a3a6c7 feat: add backend impl for glfw+opengl3 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 4a4c574f31 feat: add glfw+opengl3 backend option to build.zig 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka 0c69830356 chore: add necessary imgui files for opengl3 2023-06-19 10:44:57 -05:00
Rekai Nyangadzayi Musuka fc608f4798 chore: update to zgui v1.89.6 2023-06-19 10:44:38 -05:00
25 changed files with 3821 additions and 886 deletions

View File

@ -1,4 +1,4 @@
# zgui v0.9.6 - dear imgui (1.89.4) bindings # zgui v1.89.6 - dear imgui bindings
Easy to use, hand-crafted API with default arguments, named parameters and Zig style text formatting. For a test application please see [here](https://github.com/michal-z/zig-gamedev/tree/main/samples/gui_test_wgpu). Easy to use, hand-crafted API with default arguments, named parameters and Zig style text formatting. For a test application please see [here](https://github.com/michal-z/zig-gamedev/tree/main/samples/gui_test_wgpu).

View File

@ -4,6 +4,8 @@ pub const Backend = enum {
no_backend, no_backend,
glfw_wgpu, glfw_wgpu,
win32_dx12, win32_dx12,
glfw_opengl3,
sdl2_opengl3,
}; };
pub const Options = struct { pub const Options = struct {
@ -38,7 +40,7 @@ pub fn package(
const zgui_options = step.createModule(); const zgui_options = step.createModule();
const zgui = b.createModule(.{ const zgui = b.createModule(.{
.source_file = .{ .path = thisDir() ++ "/src/main.zig" }, .source_file = .{ .path = thisDir() ++ "/src/gui.zig" },
.dependencies = &.{ .dependencies = &.{
.{ .name = "zgui_options", .module = zgui_options }, .{ .name = "zgui_options", .module = zgui_options },
}, },
@ -92,12 +94,42 @@ pub fn package(
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_glfw.cpp", cflags); zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_glfw.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_wgpu.cpp", cflags); zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_wgpu.cpp", cflags);
}, },
.glfw_opengl3 => {
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_glfw.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_opengl3.cpp", cflags);
},
.win32_dx12 => { .win32_dx12 => {
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_win32.cpp", cflags); zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_win32.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_dx12.cpp", cflags); zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_dx12.cpp", cflags);
zgui_c_cpp.linkSystemLibraryName("d3dcompiler_47"); zgui_c_cpp.linkSystemLibraryName("d3dcompiler_47");
zgui_c_cpp.linkSystemLibraryName("dwmapi"); zgui_c_cpp.linkSystemLibraryName("dwmapi");
}, },
.sdl2_opengl3 => {
if (target.isWindows()) blk: {
// see: https://github.com/MasterQ32/SDL.zig/blob/37f4ba9e31bea895fa19ef8b90d1f51111e52e67/Sdk.zig#L182-L199
zgui_c_cpp.addVcpkgPaths(if (args.options.shared) .dynamic else .static) catch break :blk;
const vcpkg_triplet = zgui_c_cpp.target.vcpkgTriplet(b.allocator, if (args.options.shared) .Dynamic else .Static) catch |e| {
std.debug.panic("failed to determing vcpkg triplet: {}", .{e});
};
defer b.allocator.free(vcpkg_triplet);
const include_path = b.pathJoin(&.{ b.vcpkg_root.found, "installed", vcpkg_triplet, "include", "SDL2" });
zgui_c_cpp.include_dirs.append(.{ .raw_path = include_path }) catch @panic("out of memory");
const bin_path = zgui_c_cpp.vcpkg_bin_path orelse @panic("vcpkg paths were found, so vcpkg_bin_path should be set ");
const dll_path = std.fs.path.join(b.allocator, &.{ bin_path, "SDL2.dll" }) catch @panic("out of memory");
std.fs.cwd().access(dll_path, .{}) catch break :blk;
b.installBinFile(dll_path, "SDL2.dll");
}
zgui_c_cpp.linkSystemLibrary("SDL2");
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_sdl.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_opengl3.cpp", cflags);
},
.no_backend => {}, .no_backend => {},
} }

View File

@ -0,0 +1,897 @@
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 2.x 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// 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: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes).
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-09-27: OpenGL: Added ability to '#define IMGUI_IMPL_OPENGL_DEBUG'.
// 2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127).
// 2022-05-13: OpenGL: Fix state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states.
// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state.
// 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader.
// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version.
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
// 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-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.
// 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
// 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader.
// 2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader.
// 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders.
// 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility.
// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call.
// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
// 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN.
// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.
// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a nullptr pointer.
// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".
// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
//----------------------------------------
// OpenGL GLSL GLSL
// version version string
//----------------------------------------
// 2.0 110 "#version 110"
// 2.1 120 "#version 120"
// 3.0 130 "#version 130"
// 3.1 140 "#version 140"
// 3.2 150 "#version 150"
// 3.3 330 "#version 330 core"
// 4.0 400 "#version 400 core"
// 4.1 410 "#version 410 core"
// 4.2 420 "#version 410 core"
// 4.3 430 "#version 430 core"
// ES 2.0 100 "#version 100" = WebGL 1.0
// ES 3.0 300 "#version 300 es" = WebGL 2.0
//----------------------------------------
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t
#else
#include <stdint.h> // intptr_t
#endif
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
// Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types
#endif
// GL includes
#if defined(IMGUI_IMPL_OPENGL_ES2)
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
#include <OpenGLES/ES2/gl.h> // Use GL ES 2
#else
#include <GLES2/gl2.h> // Use GL ES 2
#endif
#if defined(__EMSCRIPTEN__)
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif
#include <GLES2/gl2ext.h>
#endif
#elif defined(IMGUI_IMPL_OPENGL_ES3)
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
#include <OpenGLES/ES3/gl.h> // Use GL ES 3
#else
#include <GLES3/gl3.h> // Use GL ES 3
#endif
#elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
// Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w.
// In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).
// If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):
// - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped
// - 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
#include "imgui_impl_opengl3_loader.h"
#endif
// Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension
#ifndef IMGUI_IMPL_OPENGL_ES2
#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
#elif defined(__EMSCRIPTEN__)
#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
#define glBindVertexArray glBindVertexArrayOES
#define glGenVertexArrays glGenVertexArraysOES
#define glDeleteVertexArrays glDeleteVertexArraysOES
#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
#endif
// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have.
#ifdef GL_POLYGON_MODE
#define IMGUI_IMPL_HAS_POLYGON_MODE
#endif
// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
#endif
// Desktop GL 3.3+ has glBindSampler()
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
#endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif
// Desktop GL use extension detection
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
#endif
// [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG
#include <stdio.h>
#define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check
#else
#define GL_CALL(_CALL) _CALL // Call without error check
#endif
// OpenGL Data
struct ImGui_ImplOpenGL3_Data
{
GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings.
GLuint FontTexture;
GLuint ShaderHandle;
GLint AttribLocationTex; // Uniforms location
GLint AttribLocationProjMtx;
GLuint AttribLocationVtxPos; // Vertex attributes location
GLuint AttribLocationVtxUV;
GLuint AttribLocationVtxColor;
unsigned int VboHandle, ElementsHandle;
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
bool HasClipOrigin;
bool UseBufferSubData;
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
// OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only)
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
struct ImGui_ImplOpenGL3_VtxAttribState
{
GLint Enabled, Size, Type, Normalized, Stride;
GLvoid* Ptr;
void GetState(GLint index)
{
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &Enabled);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &Size);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &Type);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &Normalized);
glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &Stride);
glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &Ptr);
}
void SetState(GLint index)
{
glVertexAttribPointer(index, Size, Type, (GLboolean)Normalized, Stride, Ptr);
if (Enabled) glEnableVertexAttribArray(index); else glDisableVertexAttribArray(index);
}
};
#endif
// Functions
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
{
ImGuiIO& io = ImGui::GetIO();
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");
return false;
}
#endif
// Setup backend capabilities flags
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl3";
// Query for GL version (e.g. 320 for GL 3.2)
#if !defined(IMGUI_IMPL_OPENGL_ES2)
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
{
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
const char* gl_version = (const char*)glGetString(GL_VERSION);
sscanf(gl_version, "%d.%d", &major, &minor);
}
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
bd->UseBufferSubData = false;
/*
// Query vendor to enable glBufferSubData kludge
#ifdef _WIN32
if (const char* vendor = (const char*)glGetString(GL_VENDOR))
if (strncmp(vendor, "Intel", 5) == 0)
bd->UseBufferSubData = true;
#endif
*/
#else
bd->GlVersion = 200; // GLES 2
#endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (bd->GlVersion >= 320)
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
#endif
// 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.
if (glsl_version == nullptr)
{
#if defined(IMGUI_IMPL_OPENGL_ES2)
glsl_version = "#version 100";
#elif defined(IMGUI_IMPL_OPENGL_ES3)
glsl_version = "#version 300 es";
#elif defined(__APPLE__)
glsl_version = "#version 150";
#else
glsl_version = "#version 130";
#endif
}
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
strcpy(bd->GlslVersionString, glsl_version);
strcat(bd->GlslVersionString, "\n");
// Make an arbitrary GL call (we don't actually need the result)
// IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
GLint current_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
// Detect extensions we support
bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++)
{
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0)
bd->HasClipOrigin = true;
}
#endif
return true;
}
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();
ImGui_ImplOpenGL3_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
IM_DELETE(bd);
}
void ImGui_ImplOpenGL3_NewFrame()
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?");
if (!bd->ShaderHandle)
ImGui_ImplOpenGL3_CreateDeviceObjects();
}
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (bd->GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART);
#endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
#if defined(GL_CLIP_ORIGIN)
bool clip_origin_lower_left = true;
if (bd->HasClipOrigin)
{
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
if (current_clip_origin == GL_UPPER_LEFT)
clip_origin_lower_left = false;
}
#endif
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
float L = draw_data->DisplayPos.x;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
#if defined(GL_CLIP_ORIGIN)
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif
const float ortho_projection[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
};
glUseProgram(bd->ShaderHandle);
glUniform1i(bd->AttribLocationTex, 0);
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->GlVersion >= 330)
glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
#endif
(void)vertex_array_object;
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(vertex_array_object);
#endif
// Bind vertex/index buffers and setup attributes for ImDrawVert
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle));
GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
}
// OpenGL3 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0)
return;
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// 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) { 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
// This is part of VAO on OpenGL 3.0+ and OpenGL ES 3.0+.
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_pos; last_vtx_attrib_state_pos.GetState(bd->AttribLocationVtxPos);
ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_uv; last_vtx_attrib_state_uv.GetState(bd->AttribLocationVtxUV);
ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_color; last_vtx_attrib_state_color.GetState(bd->AttribLocationVtxColor);
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
#endif
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
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;
#endif
// Setup desired GL state
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
// The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
GLuint vertex_array_object = 0;
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GL_CALL(glGenVertexArrays(1, &vertex_array_object));
#endif
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_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
// of leaks on Intel GPU when using multi-viewports on Windows.
// - After this we kept hearing of various display corruptions issues. We started disabling on non-Intel GPU, but issues still got reported on Intel.
// - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code.
// We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path.
// - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues.
const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
if (bd->UseBufferSubData)
{
if (bd->VertexBufferSize < vtx_buffer_size)
{
bd->VertexBufferSize = vtx_buffer_size;
GL_CALL(glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, nullptr, GL_STREAM_DRAW));
}
if (bd->IndexBufferSize < idx_buffer_size)
{
bd->IndexBufferSize = idx_buffer_size;
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW));
}
GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data));
GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data));
}
else
{
GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW));
GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW));
}
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != nullptr)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
GL_CALL(glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)));
// Bind texture, Draw
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
if (bd->GlVersion >= 320)
GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset));
else
#endif
GL_CALL(glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
}
}
}
// Destroy the temporary VAO
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GL_CALL(glDeleteVertexArrays(1, &vertex_array_object));
#endif
// Restore modified GL state
glUseProgram(last_program);
glBindTexture(GL_TEXTURE_2D, last_texture);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
if (bd->GlVersion >= 330)
glBindSampler(0, last_sampler);
#endif
glActiveTexture(last_active_texture);
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(last_vertex_array_object);
#endif
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
last_vtx_attrib_state_pos.SetState(bd->AttribLocationVtxPos);
last_vtx_attrib_state_uv.SetState(bd->AttribLocationVtxUV);
last_vtx_attrib_state_color.SetState(bd->AttribLocationVtxColor);
#endif
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
#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); }
#endif
#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
#endif
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
(void)bd; // Not all compilation paths use this
}
bool ImGui_ImplOpenGL3_CreateFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// 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));
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
#endif
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store our identifier
io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
// Restore state
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
return true;
}
void ImGui_ImplOpenGL3_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
if (bd->FontTexture)
{
glDeleteTextures(1, &bd->FontTexture);
io.Fonts->SetTexID(0);
bd->FontTexture = 0;
}
}
// 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.
static bool CheckShader(GLuint handle, const char* desc)
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
GLint status = 0, log_length = 0;
glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString);
if (log_length > 1)
{
ImVector<char> buf;
buf.resize((int)(log_length + 1));
glGetShaderInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin());
fprintf(stderr, "%s\n", buf.begin());
}
return (GLboolean)status == GL_TRUE;
}
// If you get an error please report on GitHub. You may try different GL context version or GLSL version.
static bool CheckProgram(GLuint handle, const char* desc)
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
GLint status = 0, log_length = 0;
glGetProgramiv(handle, GL_LINK_STATUS, &status);
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString);
if (log_length > 1)
{
ImVector<char> buf;
buf.resize((int)(log_length + 1));
glGetProgramInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin());
fprintf(stderr, "%s\n", buf.begin());
}
return (GLboolean)status == GL_TRUE;
}
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
{
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
// Backup GL state
GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
#endif
// Parse GLSL version string
int glsl_version = 130;
sscanf(bd->GlslVersionString, "#version %d", &glsl_version);
const GLchar* vertex_shader_glsl_120 =
"uniform mat4 ProjMtx;\n"
"attribute vec2 Position;\n"
"attribute vec2 UV;\n"
"attribute vec4 Color;\n"
"varying vec2 Frag_UV;\n"
"varying vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";
const GLchar* vertex_shader_glsl_130 =
"uniform mat4 ProjMtx;\n"
"in vec2 Position;\n"
"in vec2 UV;\n"
"in vec4 Color;\n"
"out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";
const GLchar* vertex_shader_glsl_300_es =
"precision highp float;\n"
"layout (location = 0) in vec2 Position;\n"
"layout (location = 1) in vec2 UV;\n"
"layout (location = 2) in vec4 Color;\n"
"uniform mat4 ProjMtx;\n"
"out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";
const GLchar* vertex_shader_glsl_410_core =
"layout (location = 0) in vec2 Position;\n"
"layout (location = 1) in vec2 UV;\n"
"layout (location = 2) in vec4 Color;\n"
"uniform mat4 ProjMtx;\n"
"out vec2 Frag_UV;\n"
"out vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
"}\n";
const GLchar* fragment_shader_glsl_120 =
"#ifdef GL_ES\n"
" precision mediump float;\n"
"#endif\n"
"uniform sampler2D Texture;\n"
"varying vec2 Frag_UV;\n"
"varying vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
"}\n";
const GLchar* fragment_shader_glsl_130 =
"uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n"
"out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";
const GLchar* fragment_shader_glsl_300_es =
"precision mediump float;\n"
"uniform sampler2D Texture;\n"
"in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n"
"layout (location = 0) out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";
const GLchar* fragment_shader_glsl_410_core =
"in vec2 Frag_UV;\n"
"in vec4 Frag_Color;\n"
"uniform sampler2D Texture;\n"
"layout (location = 0) out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";
// Select shaders matching our GLSL versions
const GLchar* vertex_shader = nullptr;
const GLchar* fragment_shader = nullptr;
if (glsl_version < 130)
{
vertex_shader = vertex_shader_glsl_120;
fragment_shader = fragment_shader_glsl_120;
}
else if (glsl_version >= 410)
{
vertex_shader = vertex_shader_glsl_410_core;
fragment_shader = fragment_shader_glsl_410_core;
}
else if (glsl_version == 300)
{
vertex_shader = vertex_shader_glsl_300_es;
fragment_shader = fragment_shader_glsl_300_es;
}
else
{
vertex_shader = vertex_shader_glsl_130;
fragment_shader = fragment_shader_glsl_130;
}
// Create shaders
const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
glCompileShader(vert_handle);
CheckShader(vert_handle, "vertex shader");
const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
glCompileShader(frag_handle);
CheckShader(frag_handle, "fragment shader");
// Link
bd->ShaderHandle = glCreateProgram();
glAttachShader(bd->ShaderHandle, vert_handle);
glAttachShader(bd->ShaderHandle, frag_handle);
glLinkProgram(bd->ShaderHandle);
CheckProgram(bd->ShaderHandle, "shader program");
glDetachShader(bd->ShaderHandle, vert_handle);
glDetachShader(bd->ShaderHandle, frag_handle);
glDeleteShader(vert_handle);
glDeleteShader(frag_handle);
bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture");
bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx");
bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position");
bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV");
bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color");
// Create buffers
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);
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(last_vertex_array);
#endif
return true;
}
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
{
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();
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

View File

@ -0,0 +1,57 @@
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
// - Desktop GL: 2.x 3.x 4.x
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
// 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: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// About GLSL version:
// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
extern "C" {
// Backend API
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
IMGUI_IMPL_API void ImGui_ImplOpenGL3_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();
}
// Specific OpenGL ES versions
//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten
//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
#if !defined(IMGUI_IMPL_OPENGL_ES2) \
&& !defined(IMGUI_IMPL_OPENGL_ES3)
// Try to detect GLES on matching platforms
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
#elif defined(__EMSCRIPTEN__) || defined(__amigaos4__)
#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
#else
// Otherwise imgui_impl_opengl3_loader.h will be used.
#endif
#endif

View File

@ -0,0 +1,794 @@
//-----------------------------------------------------------------------------
// About imgui_impl_opengl3_loader.h:
//
// We embed our own OpenGL loader to not require user to provide their own or to have to use ours,
// which proved to be endless problems for users.
// Our loader is custom-generated, based on gl3w but automatically filtered to only include
// enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small.
//
// YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY.
// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
//
// IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions):
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCUDING 'imgui_impl_opengl3_loader.h'
// IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER.
// (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS)
// YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT.
// BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp
// WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT.
//
// Regenerate with:
// python gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
//
// More info:
// https://github.com/dearimgui/gl3w_stripped
// https://github.com/ocornut/imgui/issues/4445
//-----------------------------------------------------------------------------
/*
* This file was generated with gl3w_gen.py, part of imgl3w
* (hosted at https://github.com/dearimgui/gl3w_stripped)
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __gl3w_h_
#define __gl3w_h_
// Adapted from KHR/khrplatform.h to avoid including entire file.
#ifndef __khrplatform_h_
typedef float khronos_float_t;
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
#ifdef _WIN64
typedef signed long long int khronos_intptr_t;
typedef signed long long int khronos_ssize_t;
#else
typedef signed long int khronos_intptr_t;
typedef signed long int khronos_ssize_t;
#endif
#if defined(_MSC_VER) && !defined(__clang__)
typedef signed __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
#include <stdint.h>
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#else
typedef signed long long khronos_int64_t;
typedef unsigned long long khronos_uint64_t;
#endif
#endif // __khrplatform_h_
#ifndef __gl_glcorearb_h_
#define __gl_glcorearb_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright 2013-2020 The Khronos Group Inc.
** SPDX-License-Identifier: MIT
**
** This header is generated from the Khronos OpenGL / OpenGL ES XML
** API Registry. The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
** https://github.com/KhronosGroup/OpenGL-Registry
*/
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#endif
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef APIENTRYP
#define APIENTRYP APIENTRY *
#endif
#ifndef GLAPI
#define GLAPI extern
#endif
/* glcorearb.h is for use with OpenGL core profile implementations.
** It should should be placed in the same directory as gl.h and
** included as <GL/glcorearb.h>.
**
** glcorearb.h includes only APIs in the latest OpenGL core profile
** implementation together with APIs in newer ARB extensions which
** can be supported by the core profile. It does not, and never will
** include functionality removed from the core profile, such as
** fixed-function vertex and fragment processing.
**
** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or
** <GL/glext.h> in the same source file.
*/
/* Generated C header for:
* API: gl
* Profile: core
* Versions considered: .*
* Versions emitted: .*
* Default extensions included: glcore
* Additional extensions included: _nomatch_^
* Extensions removed: _nomatch_^
*/
#ifndef GL_VERSION_1_0
typedef void GLvoid;
typedef unsigned int GLenum;
typedef khronos_float_t GLfloat;
typedef int GLint;
typedef int GLsizei;
typedef unsigned int GLbitfield;
typedef double GLdouble;
typedef unsigned int GLuint;
typedef unsigned char GLboolean;
typedef khronos_uint8_t GLubyte;
#define GL_COLOR_BUFFER_BIT 0x00004000
#define GL_FALSE 0
#define GL_TRUE 1
#define GL_TRIANGLES 0x0004
#define GL_ONE 1
#define GL_SRC_ALPHA 0x0302
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
#define GL_FRONT_AND_BACK 0x0408
#define GL_POLYGON_MODE 0x0B40
#define GL_CULL_FACE 0x0B44
#define GL_DEPTH_TEST 0x0B71
#define GL_STENCIL_TEST 0x0B90
#define GL_VIEWPORT 0x0BA2
#define GL_BLEND 0x0BE2
#define GL_SCISSOR_BOX 0x0C10
#define GL_SCISSOR_TEST 0x0C11
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#define GL_PACK_ALIGNMENT 0x0D05
#define GL_TEXTURE_2D 0x0DE1
#define GL_UNSIGNED_BYTE 0x1401
#define GL_UNSIGNED_SHORT 0x1403
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_RGBA 0x1908
#define GL_FILL 0x1B02
#define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01
#define GL_VERSION 0x1F02
#define GL_EXTENSIONS 0x1F03
#define GL_LINEAR 0x2601
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
GLAPI void APIENTRY glClear (GLbitfield mask);
GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
GLAPI void APIENTRY glDisable (GLenum cap);
GLAPI void APIENTRY glEnable (GLenum cap);
GLAPI void APIENTRY glFlush (void);
GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
GLAPI GLenum APIENTRY glGetError (void);
GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);
GLAPI const GLubyte *APIENTRY glGetString (GLenum name);
GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
#endif
#endif /* GL_VERSION_1_0 */
#ifndef GL_VERSION_1_1
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 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 glBindTexture (GLenum target, GLuint texture);
GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
#endif
#endif /* GL_VERSION_1_1 */
#ifndef GL_VERSION_1_3
#define GL_TEXTURE0 0x84C0
#define GL_ACTIVE_TEXTURE 0x84E0
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glActiveTexture (GLenum texture);
#endif
#endif /* GL_VERSION_1_3 */
#ifndef GL_VERSION_1_4
#define GL_BLEND_DST_RGB 0x80C8
#define GL_BLEND_SRC_RGB 0x80C9
#define GL_BLEND_DST_ALPHA 0x80CA
#define GL_BLEND_SRC_ALPHA 0x80CB
#define GL_FUNC_ADD 0x8006
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
GLAPI void APIENTRY glBlendEquation (GLenum mode);
#endif
#endif /* GL_VERSION_1_4 */
#ifndef GL_VERSION_1_5
typedef khronos_ssize_t GLsizeiptr;
typedef khronos_intptr_t GLintptr;
#define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
#define GL_STREAM_DRAW 0x88E0
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
#endif
#endif /* GL_VERSION_1_5 */
#ifndef GL_VERSION_2_0
typedef char GLchar;
typedef khronos_int16_t GLshort;
typedef khronos_int8_t GLbyte;
typedef khronos_uint16_t GLushort;
#define GL_BLEND_EQUATION_RGB 0x8009
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
#define GL_BLEND_EQUATION_ALPHA 0x883D
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_COMPILE_STATUS 0x8B81
#define GL_LINK_STATUS 0x8B82
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_CURRENT_PROGRAM 0x8B8D
#define GL_UPPER_LEFT 0x8CA2
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
GLAPI void APIENTRY glCompileShader (GLuint shader);
GLAPI GLuint APIENTRY glCreateProgram (void);
GLAPI GLuint APIENTRY glCreateShader (GLenum type);
GLAPI void APIENTRY glDeleteProgram (GLuint program);
GLAPI void APIENTRY glDeleteShader (GLuint shader);
GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
GLAPI void APIENTRY glLinkProgram (GLuint program);
GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
GLAPI void APIENTRY glUseProgram (GLuint program);
GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
#endif
#endif /* GL_VERSION_2_0 */
#ifndef GL_VERSION_3_0
typedef khronos_uint16_t GLhalf;
#define GL_MAJOR_VERSION 0x821B
#define GL_MINOR_VERSION 0x821C
#define GL_NUM_EXTENSIONS 0x821D
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#define GL_VERTEX_ARRAY_BINDING 0x85B5
typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
GLAPI void APIENTRY glBindVertexArray (GLuint array);
GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
#endif
#endif /* GL_VERSION_3_0 */
#ifndef GL_VERSION_3_1
#define GL_VERSION_3_1 1
#define GL_PRIMITIVE_RESTART 0x8F9D
#endif /* GL_VERSION_3_1 */
#ifndef GL_VERSION_3_2
#define GL_VERSION_3_2 1
typedef struct __GLsync *GLsync;
typedef khronos_uint64_t GLuint64;
typedef khronos_int64_t GLint64;
typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
#endif
#endif /* GL_VERSION_3_2 */
#ifndef GL_VERSION_3_3
#define GL_VERSION_3_3 1
#define GL_SAMPLER_BINDING 0x8919
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
#endif
#endif /* GL_VERSION_3_3 */
#ifndef GL_VERSION_4_1
typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
#endif /* GL_VERSION_4_1 */
#ifndef GL_VERSION_4_3
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
#endif /* GL_VERSION_4_3 */
#ifndef GL_VERSION_4_5
#define GL_CLIP_ORIGIN 0x935C
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
#endif /* GL_VERSION_4_5 */
#ifndef GL_ARB_bindless_texture
typedef khronos_uint64_t GLuint64EXT;
#endif /* GL_ARB_bindless_texture */
#ifndef GL_ARB_cl_event
struct _cl_context;
struct _cl_event;
#endif /* GL_ARB_cl_event */
#ifndef GL_ARB_clip_control
#define GL_ARB_clip_control 1
#endif /* GL_ARB_clip_control */
#ifndef GL_ARB_debug_output
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
#endif /* GL_ARB_debug_output */
#ifndef GL_EXT_EGL_image_storage
typedef void *GLeglImageOES;
#endif /* GL_EXT_EGL_image_storage */
#ifndef GL_EXT_direct_state_access
typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
#endif /* GL_EXT_direct_state_access */
#ifndef GL_NV_draw_vulkan_image
typedef void (APIENTRY *GLVULKANPROCNV)(void);
#endif /* GL_NV_draw_vulkan_image */
#ifndef GL_NV_gpu_shader5
typedef khronos_int64_t GLint64EXT;
#endif /* GL_NV_gpu_shader5 */
#ifndef GL_NV_vertex_buffer_unified_memory
typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
#endif /* GL_NV_vertex_buffer_unified_memory */
#ifdef __cplusplus
}
#endif
#endif
#ifndef GL3W_API
#define GL3W_API
#endif
#ifndef __gl_h_
#define __gl_h_
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define GL3W_OK 0
#define GL3W_ERROR_INIT -1
#define GL3W_ERROR_LIBRARY_OPEN -2
#define GL3W_ERROR_OPENGL_VERSION -3
typedef void (*GL3WglProc)(void);
typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
/* gl3w api */
GL3W_API int imgl3wInit(void);
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
GL3W_API int imgl3wIsSupported(int major, int minor);
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
/* gl3w internal state */
union GL3WProcs {
GL3WglProc ptr[58];
struct {
PFNGLACTIVETEXTUREPROC ActiveTexture;
PFNGLATTACHSHADERPROC AttachShader;
PFNGLBINDBUFFERPROC BindBuffer;
PFNGLBINDSAMPLERPROC BindSampler;
PFNGLBINDTEXTUREPROC BindTexture;
PFNGLBINDVERTEXARRAYPROC BindVertexArray;
PFNGLBLENDEQUATIONPROC BlendEquation;
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
PFNGLBUFFERDATAPROC BufferData;
PFNGLBUFFERSUBDATAPROC BufferSubData;
PFNGLCLEARPROC Clear;
PFNGLCLEARCOLORPROC ClearColor;
PFNGLCOMPILESHADERPROC CompileShader;
PFNGLCREATEPROGRAMPROC CreateProgram;
PFNGLCREATESHADERPROC CreateShader;
PFNGLDELETEBUFFERSPROC DeleteBuffers;
PFNGLDELETEPROGRAMPROC DeleteProgram;
PFNGLDELETESHADERPROC DeleteShader;
PFNGLDELETETEXTURESPROC DeleteTextures;
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
PFNGLDETACHSHADERPROC DetachShader;
PFNGLDISABLEPROC Disable;
PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
PFNGLDRAWELEMENTSPROC DrawElements;
PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;
PFNGLENABLEPROC Enable;
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
PFNGLFLUSHPROC Flush;
PFNGLGENBUFFERSPROC GenBuffers;
PFNGLGENTEXTURESPROC GenTextures;
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
PFNGLGETERRORPROC GetError;
PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;
PFNGLGETPROGRAMIVPROC GetProgramiv;
PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;
PFNGLGETSHADERIVPROC GetShaderiv;
PFNGLGETSTRINGPROC GetString;
PFNGLGETSTRINGIPROC GetStringi;
PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv;
PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv;
PFNGLISENABLEDPROC IsEnabled;
PFNGLLINKPROGRAMPROC LinkProgram;
PFNGLPIXELSTOREIPROC PixelStorei;
PFNGLPOLYGONMODEPROC PolygonMode;
PFNGLREADPIXELSPROC ReadPixels;
PFNGLSCISSORPROC Scissor;
PFNGLSHADERSOURCEPROC ShaderSource;
PFNGLTEXIMAGE2DPROC TexImage2D;
PFNGLTEXPARAMETERIPROC TexParameteri;
PFNGLUNIFORM1IPROC Uniform1i;
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
PFNGLUSEPROGRAMPROC UseProgram;
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
PFNGLVIEWPORTPROC Viewport;
} gl;
};
GL3W_API extern union GL3WProcs imgl3wProcs;
/* OpenGL functions */
#define glActiveTexture imgl3wProcs.gl.ActiveTexture
#define glAttachShader imgl3wProcs.gl.AttachShader
#define glBindBuffer imgl3wProcs.gl.BindBuffer
#define glBindSampler imgl3wProcs.gl.BindSampler
#define glBindTexture imgl3wProcs.gl.BindTexture
#define glBindVertexArray imgl3wProcs.gl.BindVertexArray
#define glBlendEquation imgl3wProcs.gl.BlendEquation
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
#define glBufferData imgl3wProcs.gl.BufferData
#define glBufferSubData imgl3wProcs.gl.BufferSubData
#define glClear imgl3wProcs.gl.Clear
#define glClearColor imgl3wProcs.gl.ClearColor
#define glCompileShader imgl3wProcs.gl.CompileShader
#define glCreateProgram imgl3wProcs.gl.CreateProgram
#define glCreateShader imgl3wProcs.gl.CreateShader
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
#define glDeleteShader imgl3wProcs.gl.DeleteShader
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
#define glDetachShader imgl3wProcs.gl.DetachShader
#define glDisable imgl3wProcs.gl.Disable
#define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray
#define glDrawElements imgl3wProcs.gl.DrawElements
#define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex
#define glEnable imgl3wProcs.gl.Enable
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
#define glFlush imgl3wProcs.gl.Flush
#define glGenBuffers imgl3wProcs.gl.GenBuffers
#define glGenTextures imgl3wProcs.gl.GenTextures
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
#define glGetError imgl3wProcs.gl.GetError
#define glGetIntegerv imgl3wProcs.gl.GetIntegerv
#define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog
#define glGetProgramiv imgl3wProcs.gl.GetProgramiv
#define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog
#define glGetShaderiv imgl3wProcs.gl.GetShaderiv
#define glGetString imgl3wProcs.gl.GetString
#define glGetStringi imgl3wProcs.gl.GetStringi
#define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation
#define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv
#define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv
#define glIsEnabled imgl3wProcs.gl.IsEnabled
#define glLinkProgram imgl3wProcs.gl.LinkProgram
#define glPixelStorei imgl3wProcs.gl.PixelStorei
#define glPolygonMode imgl3wProcs.gl.PolygonMode
#define glReadPixels imgl3wProcs.gl.ReadPixels
#define glScissor imgl3wProcs.gl.Scissor
#define glShaderSource imgl3wProcs.gl.ShaderSource
#define glTexImage2D imgl3wProcs.gl.TexImage2D
#define glTexParameteri imgl3wProcs.gl.TexParameteri
#define glUniform1i imgl3wProcs.gl.Uniform1i
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
#define glUseProgram imgl3wProcs.gl.UseProgram
#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer
#define glViewport imgl3wProcs.gl.Viewport
#ifdef __cplusplus
}
#endif
#endif
#ifdef IMGL3W_IMPL
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
static HMODULE libgl;
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
static GL3WglGetProcAddr wgl_get_proc_address;
static int open_libgl(void)
{
libgl = LoadLibraryA("opengl32.dll");
if (!libgl)
return GL3W_ERROR_LIBRARY_OPEN;
wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
return GL3W_OK;
}
static void close_libgl(void) { FreeLibrary(libgl); }
static GL3WglProc get_proc(const char *proc)
{
GL3WglProc res;
res = (GL3WglProc)wgl_get_proc_address(proc);
if (!res)
res = (GL3WglProc)GetProcAddress(libgl, proc);
return res;
}
#elif defined(__APPLE__)
#include <dlfcn.h>
static void *libgl;
static int open_libgl(void)
{
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
if (!libgl)
return GL3W_ERROR_LIBRARY_OPEN;
return GL3W_OK;
}
static void close_libgl(void) { dlclose(libgl); }
static GL3WglProc get_proc(const char *proc)
{
GL3WglProc res;
*(void **)(&res) = dlsym(libgl, proc);
return res;
}
#else
#include <dlfcn.h>
static void *libgl;
static GL3WglProc (*glx_get_proc_address)(const GLubyte *);
static int open_libgl(void)
{
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
if (!libgl)
return GL3W_ERROR_LIBRARY_OPEN;
*(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
return GL3W_OK;
}
static void close_libgl(void) { dlclose(libgl); }
static GL3WglProc get_proc(const char *proc)
{
GL3WglProc res;
res = glx_get_proc_address((const GLubyte *)proc);
if (!res)
*(void **)(&res) = dlsym(libgl, proc);
return res;
}
#endif
static struct { int major, minor; } version;
static int parse_version(void)
{
if (!glGetIntegerv)
return GL3W_ERROR_INIT;
glGetIntegerv(GL_MAJOR_VERSION, &version.major);
glGetIntegerv(GL_MINOR_VERSION, &version.minor);
if (version.major < 3)
return GL3W_ERROR_OPENGL_VERSION;
return GL3W_OK;
}
static void load_procs(GL3WGetProcAddressProc proc);
int imgl3wInit(void)
{
int res = open_libgl();
if (res)
return res;
atexit(close_libgl);
return imgl3wInit2(get_proc);
}
int imgl3wInit2(GL3WGetProcAddressProc proc)
{
load_procs(proc);
return parse_version();
}
int imgl3wIsSupported(int major, int minor)
{
if (major < 3)
return 0;
if (version.major == major)
return version.minor >= minor;
return version.major >= major;
}
GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }
static const char *proc_names[] = {
"glActiveTexture",
"glAttachShader",
"glBindBuffer",
"glBindSampler",
"glBindTexture",
"glBindVertexArray",
"glBlendEquation",
"glBlendEquationSeparate",
"glBlendFuncSeparate",
"glBufferData",
"glBufferSubData",
"glClear",
"glClearColor",
"glCompileShader",
"glCreateProgram",
"glCreateShader",
"glDeleteBuffers",
"glDeleteProgram",
"glDeleteShader",
"glDeleteTextures",
"glDeleteVertexArrays",
"glDetachShader",
"glDisable",
"glDisableVertexAttribArray",
"glDrawElements",
"glDrawElementsBaseVertex",
"glEnable",
"glEnableVertexAttribArray",
"glFlush",
"glGenBuffers",
"glGenTextures",
"glGenVertexArrays",
"glGetAttribLocation",
"glGetError",
"glGetIntegerv",
"glGetProgramInfoLog",
"glGetProgramiv",
"glGetShaderInfoLog",
"glGetShaderiv",
"glGetString",
"glGetStringi",
"glGetUniformLocation",
"glGetVertexAttribPointerv",
"glGetVertexAttribiv",
"glIsEnabled",
"glLinkProgram",
"glPixelStorei",
"glPolygonMode",
"glReadPixels",
"glScissor",
"glShaderSource",
"glTexImage2D",
"glTexParameteri",
"glUniform1i",
"glUniformMatrix4fv",
"glUseProgram",
"glVertexAttribPointer",
"glViewport",
};
GL3W_API union GL3WProcs imgl3wProcs;
static void load_procs(GL3WGetProcAddressProc proc)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(proc_names); i++)
imgl3wProcs.ptr[i] = proc(proc_names[i]);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,572 @@
// dear imgui: Platform Backend for SDL2
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
// (Prefer SDL 2.0.5+ for full feature support.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-09-26: Inputs: Disable SDL 2.0.22 new "auto capture" (SDL_HINT_MOUSE_AUTO_CAPTURE) which prevents drag and drop across windows for multi-viewport support + don't capture when drag and dropping. (#5710)
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
// 2022-03-22: Inputs: Fix mouse position issues when dragging outside of boundaries. SDL_CaptureMouse() erroneously still gives out LEAVE events when hovering OS decorations.
// 2022-03-22: Inputs: Added support for extra mouse buttons (SDL_BUTTON_X1/SDL_BUTTON_X2).
// 2022-02-04: Added SDL_Renderer* parameter to ImGui_ImplSDL2_InitForSDLRenderer(), so we can use SDL_GetRendererOutputSize() instead of SDL_GL_GetDrawableSize() when bound to a SDL_Renderer.
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
// 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates.
// 2022-01-12: Update mouse inputs using SDL_MOUSEMOTION/SDL_WINDOWEVENT_LEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
// 2022-01-12: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
// 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
#include "imgui.h"
#include "imgui_impl_sdl.h"
// SDL
#include <SDL.h>
#include <SDL_syswm.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__)
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
#else
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
#endif
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
// SDL Data
struct ImGui_ImplSDL2_Data
{
SDL_Window* Window;
SDL_Renderer* Renderer;
Uint64 Time;
int MouseButtonsDown;
SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
int PendingMouseLeaveFrame;
char* ClipboardTextData;
bool MouseCanUseGlobalState;
ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
}
// Functions
static const char* ImGui_ImplSDL2_GetClipboardText(void*)
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
bd->ClipboardTextData = SDL_GetClipboardText();
return bd->ClipboardTextData;
}
static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
{
SDL_SetClipboardText(text);
}
static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
{
switch (keycode)
{
case SDLK_TAB: return ImGuiKey_Tab;
case SDLK_LEFT: return ImGuiKey_LeftArrow;
case SDLK_RIGHT: return ImGuiKey_RightArrow;
case SDLK_UP: return ImGuiKey_UpArrow;
case SDLK_DOWN: return ImGuiKey_DownArrow;
case SDLK_PAGEUP: return ImGuiKey_PageUp;
case SDLK_PAGEDOWN: return ImGuiKey_PageDown;
case SDLK_HOME: return ImGuiKey_Home;
case SDLK_END: return ImGuiKey_End;
case SDLK_INSERT: return ImGuiKey_Insert;
case SDLK_DELETE: return ImGuiKey_Delete;
case SDLK_BACKSPACE: return ImGuiKey_Backspace;
case SDLK_SPACE: return ImGuiKey_Space;
case SDLK_RETURN: return ImGuiKey_Enter;
case SDLK_ESCAPE: return ImGuiKey_Escape;
case SDLK_QUOTE: return ImGuiKey_Apostrophe;
case SDLK_COMMA: return ImGuiKey_Comma;
case SDLK_MINUS: return ImGuiKey_Minus;
case SDLK_PERIOD: return ImGuiKey_Period;
case SDLK_SLASH: return ImGuiKey_Slash;
case SDLK_SEMICOLON: return ImGuiKey_Semicolon;
case SDLK_EQUALS: return ImGuiKey_Equal;
case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket;
case SDLK_BACKSLASH: return ImGuiKey_Backslash;
case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket;
case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent;
case SDLK_CAPSLOCK: return ImGuiKey_CapsLock;
case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock;
case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock;
case SDLK_PRINTSCREEN: return ImGuiKey_PrintScreen;
case SDLK_PAUSE: return ImGuiKey_Pause;
case SDLK_KP_0: return ImGuiKey_Keypad0;
case SDLK_KP_1: return ImGuiKey_Keypad1;
case SDLK_KP_2: return ImGuiKey_Keypad2;
case SDLK_KP_3: return ImGuiKey_Keypad3;
case SDLK_KP_4: return ImGuiKey_Keypad4;
case SDLK_KP_5: return ImGuiKey_Keypad5;
case SDLK_KP_6: return ImGuiKey_Keypad6;
case SDLK_KP_7: return ImGuiKey_Keypad7;
case SDLK_KP_8: return ImGuiKey_Keypad8;
case SDLK_KP_9: return ImGuiKey_Keypad9;
case SDLK_KP_PERIOD: return ImGuiKey_KeypadDecimal;
case SDLK_KP_DIVIDE: return ImGuiKey_KeypadDivide;
case SDLK_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
case SDLK_KP_MINUS: return ImGuiKey_KeypadSubtract;
case SDLK_KP_PLUS: return ImGuiKey_KeypadAdd;
case SDLK_KP_ENTER: return ImGuiKey_KeypadEnter;
case SDLK_KP_EQUALS: return ImGuiKey_KeypadEqual;
case SDLK_LCTRL: return ImGuiKey_LeftCtrl;
case SDLK_LSHIFT: return ImGuiKey_LeftShift;
case SDLK_LALT: return ImGuiKey_LeftAlt;
case SDLK_LGUI: return ImGuiKey_LeftSuper;
case SDLK_RCTRL: return ImGuiKey_RightCtrl;
case SDLK_RSHIFT: return ImGuiKey_RightShift;
case SDLK_RALT: return ImGuiKey_RightAlt;
case SDLK_RGUI: return ImGuiKey_RightSuper;
case SDLK_APPLICATION: return ImGuiKey_Menu;
case SDLK_0: return ImGuiKey_0;
case SDLK_1: return ImGuiKey_1;
case SDLK_2: return ImGuiKey_2;
case SDLK_3: return ImGuiKey_3;
case SDLK_4: return ImGuiKey_4;
case SDLK_5: return ImGuiKey_5;
case SDLK_6: return ImGuiKey_6;
case SDLK_7: return ImGuiKey_7;
case SDLK_8: return ImGuiKey_8;
case SDLK_9: return ImGuiKey_9;
case SDLK_a: return ImGuiKey_A;
case SDLK_b: return ImGuiKey_B;
case SDLK_c: return ImGuiKey_C;
case SDLK_d: return ImGuiKey_D;
case SDLK_e: return ImGuiKey_E;
case SDLK_f: return ImGuiKey_F;
case SDLK_g: return ImGuiKey_G;
case SDLK_h: return ImGuiKey_H;
case SDLK_i: return ImGuiKey_I;
case SDLK_j: return ImGuiKey_J;
case SDLK_k: return ImGuiKey_K;
case SDLK_l: return ImGuiKey_L;
case SDLK_m: return ImGuiKey_M;
case SDLK_n: return ImGuiKey_N;
case SDLK_o: return ImGuiKey_O;
case SDLK_p: return ImGuiKey_P;
case SDLK_q: return ImGuiKey_Q;
case SDLK_r: return ImGuiKey_R;
case SDLK_s: return ImGuiKey_S;
case SDLK_t: return ImGuiKey_T;
case SDLK_u: return ImGuiKey_U;
case SDLK_v: return ImGuiKey_V;
case SDLK_w: return ImGuiKey_W;
case SDLK_x: return ImGuiKey_X;
case SDLK_y: return ImGuiKey_Y;
case SDLK_z: return ImGuiKey_Z;
case SDLK_F1: return ImGuiKey_F1;
case SDLK_F2: return ImGuiKey_F2;
case SDLK_F3: return ImGuiKey_F3;
case SDLK_F4: return ImGuiKey_F4;
case SDLK_F5: return ImGuiKey_F5;
case SDLK_F6: return ImGuiKey_F6;
case SDLK_F7: return ImGuiKey_F7;
case SDLK_F8: return ImGuiKey_F8;
case SDLK_F9: return ImGuiKey_F9;
case SDLK_F10: return ImGuiKey_F10;
case SDLK_F11: return ImGuiKey_F11;
case SDLK_F12: return ImGuiKey_F12;
}
return ImGuiKey_None;
}
static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
{
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(ImGuiMod_Ctrl, (sdl_key_mods & KMOD_CTRL) != 0);
io.AddKeyEvent(ImGuiMod_Shift, (sdl_key_mods & KMOD_SHIFT) != 0);
io.AddKeyEvent(ImGuiMod_Alt, (sdl_key_mods & KMOD_ALT) != 0);
io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0);
}
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
switch (event->type)
{
case SDL_MOUSEMOTION:
{
io.AddMousePosEvent((float)event->motion.x, (float)event->motion.y);
return true;
}
case SDL_MOUSEWHEEL:
{
float wheel_x = (event->wheel.x > 0) ? 1.0f : (event->wheel.x < 0) ? -1.0f : 0.0f;
float wheel_y = (event->wheel.y > 0) ? 1.0f : (event->wheel.y < 0) ? -1.0f : 0.0f;
io.AddMouseWheelEvent(wheel_x, wheel_y);
return true;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
int mouse_button = -1;
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; }
if (event->button.button == SDL_BUTTON_MIDDLE) { mouse_button = 2; }
if (event->button.button == SDL_BUTTON_X1) { mouse_button = 3; }
if (event->button.button == SDL_BUTTON_X2) { mouse_button = 4; }
if (mouse_button == -1)
break;
io.AddMouseButtonEvent(mouse_button, (event->type == SDL_MOUSEBUTTONDOWN));
bd->MouseButtonsDown = (event->type == SDL_MOUSEBUTTONDOWN) ? (bd->MouseButtonsDown | (1 << mouse_button)) : (bd->MouseButtonsDown & ~(1 << mouse_button));
return true;
}
case SDL_TEXTINPUT:
{
io.AddInputCharactersUTF8(event->text.text);
return true;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
ImGuiKey key = ImGui_ImplSDL2_KeycodeToImGuiKey(event->key.keysym.sym);
io.AddKeyEvent(key, (event->type == SDL_KEYDOWN));
io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions.
return true;
}
case SDL_WINDOWEVENT:
{
// - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
// - However we won't get a correct LEAVE event for a captured window.
// - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late,
// causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why
// we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details.
Uint8 window_event = event->window.event;
if (window_event == SDL_WINDOWEVENT_ENTER)
bd->PendingMouseLeaveFrame = 0;
if (window_event == SDL_WINDOWEVENT_LEAVE)
bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1;
if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED)
io.AddFocusEvent(true);
else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
io.AddFocusEvent(false);
return true;
}
}
return false;
}
static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
bool mouse_can_use_global_state = false;
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
const char* sdl_backend = SDL_GetCurrentVideoDriver();
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
mouse_can_use_global_state = true;
#endif
// Setup backend capabilities flags
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = "imgui_impl_sdl";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->Window = window;
bd->Renderer = renderer;
bd->MouseCanUseGlobalState = mouse_can_use_global_state;
io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
io.ClipboardUserData = nullptr;
// Load mouse cursors
bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
// Set platform dependent data in viewport
#ifdef _WIN32
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info))
ImGui::GetMainViewport()->PlatformHandleRaw = (void*)info.info.win.window;
#else
(void)window;
#endif
// From 2.0.5: Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
// (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
// It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
// you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
#ifdef SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif
// From 2.0.22: Disable auto-capture, this is preventing drag and drop across multiple windows (see #5710)
#ifdef SDL_HINT_MOUSE_AUTO_CAPTURE
SDL_SetHint(SDL_HINT_MOUSE_AUTO_CAPTURE, "0");
#endif
return true;
}
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
{
IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
return ImGui_ImplSDL2_Init(window, nullptr);
}
bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
{
#if !SDL_HAS_VULKAN
IM_ASSERT(0 && "Unsupported");
#endif
return ImGui_ImplSDL2_Init(window, nullptr);
}
bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
{
#if !defined(_WIN32)
IM_ASSERT(0 && "Unsupported");
#endif
return ImGui_ImplSDL2_Init(window, nullptr);
}
bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
{
return ImGui_ImplSDL2_Init(window, nullptr);
}
bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer)
{
return ImGui_ImplSDL2_Init(window, renderer);
}
void ImGui_ImplSDL2_Shutdown()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
if (bd->ClipboardTextData)
SDL_free(bd->ClipboardTextData);
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
SDL_FreeCursor(bd->MouseCursors[cursor_n]);
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
IM_DELETE(bd);
}
static void ImGui_ImplSDL2_UpdateMouseData()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiIO& io = ImGui::GetIO();
// We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
SDL_CaptureMouse((bd->MouseButtonsDown != 0 && ImGui::GetDragDropPayload() == nullptr) ? SDL_TRUE : SDL_FALSE);
SDL_Window* focused_window = SDL_GetKeyboardFocus();
const bool is_app_focused = (bd->Window == focused_window);
#else
const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
#endif
if (is_app_focused)
{
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
// (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0)
{
int window_x, window_y, mouse_x_global, mouse_y_global;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
SDL_GetWindowPosition(bd->Window, &window_x, &window_y);
io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
}
}
}
static void ImGui_ImplSDL2_UpdateMouseCursor()
{
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return;
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
SDL_ShowCursor(SDL_FALSE);
}
else
{
// Show OS mouse cursor
SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
SDL_ShowCursor(SDL_TRUE);
}
}
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
return;
// Get gamepad
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
SDL_GameController* game_controller = SDL_GameControllerOpen(0);
if (!game_controller)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
// Update gamepad inputs
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_NO) { io.AddKeyEvent(KEY_NO, SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0); }
#define MAP_ANALOG(KEY_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); vn = IM_SATURATE(vn); io.AddKeyAnalogEvent(KEY_NO, vn > 0.1f, vn); }
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
MAP_BUTTON(ImGuiKey_GamepadDpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
MAP_BUTTON(ImGuiKey_GamepadL1, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
MAP_BUTTON(ImGuiKey_GamepadR1, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
MAP_ANALOG(ImGuiKey_GamepadL2, SDL_CONTROLLER_AXIS_TRIGGERLEFT, 0.0f, 32767);
MAP_ANALOG(ImGuiKey_GamepadR2, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 0.0f, 32767);
MAP_BUTTON(ImGuiKey_GamepadL3, SDL_CONTROLLER_BUTTON_LEFTSTICK);
MAP_BUTTON(ImGuiKey_GamepadR3, SDL_CONTROLLER_BUTTON_RIGHTSTICK);
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadLStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadLStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, SDL_CONTROLLER_AXIS_RIGHTX, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickRight, SDL_CONTROLLER_AXIS_RIGHTX, +thumb_dead_zone, +32767);
MAP_ANALOG(ImGuiKey_GamepadRStickUp, SDL_CONTROLLER_AXIS_RIGHTY, -thumb_dead_zone, -32768);
MAP_ANALOG(ImGuiKey_GamepadRStickDown, SDL_CONTROLLER_AXIS_RIGHTY, +thumb_dead_zone, +32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
void ImGui_ImplSDL2_NewFrame()
{
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplSDL2_Init()?");
ImGuiIO& io = ImGui::GetIO();
// Setup display size (every frame to accommodate for window resizing)
int w, h;
int display_w, display_h;
SDL_GetWindowSize(bd->Window, &w, &h);
if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED)
w = h = 0;
if (bd->Renderer != nullptr)
SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h);
else
SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
if (w > 0 && h > 0)
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
static Uint64 frequency = SDL_GetPerformanceFrequency();
Uint64 current_time = SDL_GetPerformanceCounter();
io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
bd->Time = current_time;
if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame >= ImGui::GetFrameCount() && bd->MouseButtonsDown == 0)
{
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
bd->PendingMouseLeaveFrame = 0;
}
ImGui_ImplSDL2_UpdateMouseData();
ImGui_ImplSDL2_UpdateMouseCursor();
// Update game controllers (if enabled and available)
ImGui_ImplSDL2_UpdateGamepads();
}

View File

@ -0,0 +1,38 @@
// dear imgui: Platform Backend for SDL2
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// Missing features:
// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct SDL_Window;
struct SDL_Renderer;
typedef union SDL_Event SDL_Event;
extern "C" {
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (headers) // (headers)
// Help: // Help:
// - Read FAQ at http://dearimgui.org/faq // - Read FAQ at http://dearimgui.com/faq
// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
// Read imgui.cpp for details, links and comments. // Read imgui.cpp for details, links and comments.
// Resources: // Resources:
// - FAQ http://dearimgui.org/faq // - FAQ http://dearimgui.com/faq
// - Homepage & latest https://github.com/ocornut/imgui // - Homepage & latest https://github.com/ocornut/imgui
// - Releases & changelog https://github.com/ocornut/imgui/releases // - Releases & changelog https://github.com/ocornut/imgui/releases
// - Gallery https://github.com/ocornut/imgui/issues/5886 (please post your screenshots/video there!) // - Gallery https://github.com/ocornut/imgui/issues/6478 (please post your screenshots/video there!)
// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Issues & support https://github.com/ocornut/imgui/issues // - Issues & support https://github.com/ocornut/imgui/issues
@ -21,9 +21,9 @@
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.89.4" #define IMGUI_VERSION "1.89.6"
#define IMGUI_VERSION_NUM 18940 #define IMGUI_VERSION_NUM 18960
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*
@ -167,6 +167,7 @@ struct ImGuiViewport; // A Platform Window (always only one in 'ma
// In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value) enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value)
enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen)
typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
@ -255,8 +256,8 @@ struct ImVec2
float x, y; float x, y;
constexpr ImVec2() : x(0.0f), y(0.0f) { } constexpr ImVec2() : x(0.0f), y(0.0f) { }
constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { } constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { }
float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine.
float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; }
#ifdef IM_VEC2_CLASS_EXTRA #ifdef IM_VEC2_CLASS_EXTRA
IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2.
#endif #endif
@ -460,7 +461,7 @@ namespace ImGui
IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets)
// ID stack/scopes // ID stack/scopes
// Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui. // Read the FAQ (docs/FAQ.md or http://dearimgui.com/faq) for more details about how ID are handled in dear imgui.
// - Those questions are answered and impacted by understanding of the ID stack system: // - Those questions are answered and impacted by understanding of the ID stack system:
// - "Q: Why is my widget not reacting when I click on it?" // - "Q: Why is my widget not reacting when I click on it?"
// - "Q: How can I have widgets with an empty label?" // - "Q: How can I have widgets with an empty label?"
@ -1407,7 +1408,7 @@ enum ImGuiKey : int
ImGuiKey_KeypadEqual, ImGuiKey_KeypadEqual,
// Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION // Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION
// (download controller mapping PNG/PSD at http://dearimgui.org/controls_sheets) // (download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets)
ImGuiKey_GamepadStart, // Menu (Xbox) + (Switch) Start/Options (PS) ImGuiKey_GamepadStart, // Menu (Xbox) + (Switch) Start/Options (PS)
ImGuiKey_GamepadBack, // View (Xbox) - (Switch) Share (PS) ImGuiKey_GamepadBack, // View (Xbox) - (Switch) Share (PS)
ImGuiKey_GamepadFaceLeft, // X (Xbox) Y (Switch) Square (PS) // Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows) ImGuiKey_GamepadFaceLeft, // X (Xbox) Y (Switch) Square (PS) // Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows)
@ -1715,6 +1716,18 @@ enum ImGuiMouseCursor_
ImGuiMouseCursor_COUNT ImGuiMouseCursor_COUNT
}; };
// Enumeration for AddMouseSourceEvent() actual source of Mouse Input data.
// Historically we use "Mouse" terminology everywhere to indicate pointer data, e.g. MousePos, IsMousePressed(), io.AddMousePosEvent()
// But that "Mouse" data can come from different source which occasionally may be useful for application to know about.
// You can submit a change of pointer type using io.AddMouseSourceEvent().
enum ImGuiMouseSource : int
{
ImGuiMouseSource_Mouse = 0, // Input is coming from an actual mouse.
ImGuiMouseSource_TouchScreen, // Input is coming from a touch screen (no hovering prior to initial press, less precise initial press aiming, dual-axis wheeling possible).
ImGuiMouseSource_Pen, // Input is coming from a pressure/magnetic pen (often used in conjunction with high-sampling rates).
ImGuiMouseSource_COUNT
};
// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions // Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions
// Represent a condition. // Represent a condition.
// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. // Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
@ -1939,11 +1952,15 @@ struct ImGuiIO
// Debug options // Debug options
// - tools to test correct Begin/End and BeginChild/EndChild behaviors. // - tools to test correct Begin/End and BeginChild/EndChild behaviors.
// - presently Begn()/End() and BeginChild()EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() // - presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX()
// this is inconsistent with other BeginXXX functions and create confusion for many users. // this is inconsistent with other BeginXXX functions and create confusion for many users.
// - we expect to update the API eventually. In the meanwhile we provided tools to facilitate checking user-code behavior. // - we expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior.
bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows. bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows.
bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running. bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running.
// - option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.
// - backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
// - consider using e.g. Win32's IsDebuggerPresent() as an additional filter (or see ImOsIsDebuggerPresent() in imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version).
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing.
//------------------------------------------------------------------ //------------------------------------------------------------------
// Platform Functions // Platform Functions
@ -1982,6 +1999,7 @@ struct ImGuiIO
IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered) IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered)
IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change
IMGUI_API void AddMouseWheelEvent(float wheel_x, float wheel_y); // Queue a mouse wheel update. wheel_y<0: scroll down, wheel_y>0: scroll up, wheel_x<0: scroll right, wheel_x>0: scroll left. IMGUI_API void AddMouseWheelEvent(float wheel_x, float wheel_y); // Queue a mouse wheel update. wheel_y<0: scroll down, wheel_y>0: scroll up, wheel_x<0: scroll right, wheel_x>0: scroll left.
IMGUI_API void AddMouseSourceEvent(ImGuiMouseSource source); // Queue a mouse source change (Mouse/TouchScreen/Pen)
IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window) IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window)
IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input
IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate
@ -2035,6 +2053,7 @@ struct ImGuiIO
bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll. float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll.
float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends. float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends.
ImGuiMouseSource MouseSource; // Mouse actual input peripheral (Mouse/TouchScreen/Pen).
bool KeyCtrl; // Keyboard modifier down: Control bool KeyCtrl; // Keyboard modifier down: Control
bool KeyShift; // Keyboard modifier down: Shift bool KeyShift; // Keyboard modifier down: Shift
bool KeyAlt; // Keyboard modifier down: Alt bool KeyAlt; // Keyboard modifier down: Alt
@ -2054,6 +2073,7 @@ struct ImGuiIO
bool MouseReleased[5]; // Mouse button went from Down to !Down bool MouseReleased[5]; // Mouse button went from Down to !Down
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window. bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window.
bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system.
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds) float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds)
@ -2324,11 +2344,13 @@ struct ImGuiListClipper
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
// Call ForceDisplayRangeByIndices() before first call to Step() if you need a range of items to be displayed regardless of visibility. // Call IncludeRangeByIndices() *BEFORE* first call to Step() if you need a range of items to not be clipped, regardless of their visibility.
IMGUI_API void ForceDisplayRangeByIndices(int item_min, int item_max); // item_max is exclusive e.g. use (42, 42+1) to make item 42 always visible BUT due to alignment/padding of certain items it is likely that an extra item may be included on either end of the display range. // (Due to alignment / padding of certain items it is possible that an extra item may be included on either end of the display range).
IMGUI_API void IncludeRangeByIndices(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79] inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeRangeByIndices(item_begin, item_end); } // [renamed in 1.89.6]
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
#endif #endif
}; };
@ -2336,7 +2358,6 @@ struct ImGuiListClipper
// - It is important that we are keeping those disabled by default so they don't leak in user space. // - It is important that we are keeping those disabled by default so they don't leak in user space.
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h) // - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
// - You can use '#define IMGUI_DEFINE_MATH_OPERATORS' to import our operators, provided as a courtesy. // - You can use '#define IMGUI_DEFINE_MATH_OPERATORS' to import our operators, provided as a courtesy.
// - We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself.
#ifdef IMGUI_DEFINE_MATH_OPERATORS #ifdef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF IM_MSVC_RUNTIME_CHECKS_OFF
@ -2346,6 +2367,7 @@ static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); } static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
static inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
@ -2812,7 +2834,8 @@ struct ImFontAtlas
//------------------------------------------- //-------------------------------------------
// Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list)
// NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details. // NB: Make sure that your string are UTF-8 and NOT in your local code page.
// Read https://github.com/ocornut/imgui/blob/master/docs/FONTS.md/#about-utf-8-encoding for details.
// NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data. // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data.
IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
IMGUI_API const ImWchar* GetGlyphRangesGreek(); // Default + Greek and Coptic IMGUI_API const ImWchar* GetGlyphRangesGreek(); // Default + Greek and Coptic
@ -3019,12 +3042,12 @@ namespace ImGui
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper. IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper.
// OBSOLETED in 1.85 (from August 2021) // OBSOLETED in 1.85 (from August 2021)
static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; }
// OBSOLETED in 1.81 (from February 2021)
IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items
static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
static inline void ListBoxFooter() { EndListBox(); }
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
//-- OBSOLETED in 1.81 (from February 2021)
//static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
//static inline bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1) { float height = GetTextLineHeightWithSpacing() * ((height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f) + GetStyle().FramePadding.y * 2.0f; return BeginListBox(label, ImVec2(0.0f, height)); } // Helper to calculate size from items_count and height_in_items
//static inline void ListBoxFooter() { EndListBox(); }
//-- OBSOLETED in 1.79 (from August 2020) //-- OBSOLETED in 1.79 (from August 2020)
//static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! //static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry!
//-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. //-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details.

View File

@ -1,8 +1,8 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (demo code) // (demo code)
// Help: // Help:
// - Read FAQ at http://dearimgui.org/faq // - Read FAQ at http://dearimgui.com/faq
// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
// Read imgui.cpp for more details, documentation and comments. // Read imgui.cpp for more details, documentation and comments.
@ -398,23 +398,21 @@ void ImGui::ShowDemoWindow(bool* p_open)
IMGUI_DEMO_MARKER("Help"); IMGUI_DEMO_MARKER("Help");
if (ImGui::CollapsingHeader("Help")) if (ImGui::CollapsingHeader("Help"))
{ {
ImGui::Text("ABOUT THIS DEMO:"); ImGui::SeparatorText("ABOUT THIS DEMO:");
ImGui::BulletText("Sections below are demonstrating many aspects of the library."); ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
ImGui::BulletText("The \"Examples\" menu above leads to more demo contents."); ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n" ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
"and Metrics/Debugger (general purpose Dear ImGui debugging tool)."); "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
ImGui::Separator();
ImGui::Text("PROGRAMMER GUIDE:"); ImGui::SeparatorText("PROGRAMMER GUIDE:");
ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!"); ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
ImGui::BulletText("See comments in imgui.cpp."); ImGui::BulletText("See comments in imgui.cpp.");
ImGui::BulletText("See example applications in the examples/ folder."); ImGui::BulletText("See example applications in the examples/ folder.");
ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/"); ImGui::BulletText("Read the FAQ at http://www.dearimgui.com/faq/");
ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls."); ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls."); ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
ImGui::Separator();
ImGui::Text("USER GUIDE:"); ImGui::SeparatorText("USER GUIDE:");
ImGui::ShowUserGuide(); ImGui::ShowUserGuide();
} }
@ -471,6 +469,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover"); ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover");
ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop); ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop);
ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running."); ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss);
ImGui::SameLine(); HelpMarker("Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.");
ImGui::TreePop(); ImGui::TreePop();
ImGui::Spacing(); ImGui::Spacing();
@ -483,13 +483,13 @@ void ImGui::ShowDemoWindow(bool* p_open)
"Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n" "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
"Here we expose them as read-only fields to avoid breaking interactions with your backend."); "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
// Make a local copy to avoid modifying actual backend flags. // FIXME: Maybe we need a BeginReadonly() equivalent to keep label bright?
// FIXME: We don't use BeginDisabled() to keep label bright, maybe we need a BeginReadonly() equivalent.. ImGui::BeginDisabled();
ImGuiBackendFlags backend_flags = io.BackendFlags; ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &io.BackendFlags, ImGuiBackendFlags_HasGamepad);
ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad); ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors); ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos);
ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &backend_flags, ImGuiBackendFlags_HasSetMousePos); ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset);
ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset); ImGui::EndDisabled();
ImGui::TreePop(); ImGui::TreePop();
ImGui::Spacing(); ImGui::Spacing();
} }
@ -631,7 +631,7 @@ static void ShowDemoWindowWidgets()
ImGui::Text("Tooltips:"); ImGui::Text("Tooltips:");
ImGui::SameLine(); ImGui::SameLine();
ImGui::SmallButton("Button"); ImGui::SmallButton("Basic");
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip"); ImGui::SetTooltip("I am a tooltip");
@ -744,7 +744,7 @@ static void ShowDemoWindowWidgets()
static int elem = Element_Fire; static int elem = Element_Fire;
const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" }; const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown"; const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here.
ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer."); ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
} }
@ -1390,7 +1390,15 @@ static void ShowDemoWindowWidgets()
{ {
struct TextFilters struct TextFilters
{ {
// Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i' // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback)
static int FilterCasingSwap(ImGuiInputTextCallbackData* data)
{
if (data->EventChar >= 'a' && data->EventChar <= 'z') { data->EventChar = data->EventChar - 'A' - 'a'; } // Lowercase becomes uppercase
else if (data->EventChar >= 'A' && data->EventChar <= 'Z') { data->EventChar = data->EventChar + 'a' - 'A'; } // Uppercase becomes lowercase
return 0;
}
// Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out)
static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
{ {
if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
@ -1399,12 +1407,13 @@ static void ShowDemoWindowWidgets()
} }
}; };
static char buf1[64] = ""; ImGui::InputText("default", buf1, 64); static char buf1[32] = ""; ImGui::InputText("default", buf1, 32);
static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal); static char buf2[32] = ""; ImGui::InputText("decimal", buf2, 32, ImGuiInputTextFlags_CharsDecimal);
static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase); static char buf4[32] = ""; ImGui::InputText("uppercase", buf4, 32, ImGuiInputTextFlags_CharsUppercase);
static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank); static char buf5[32] = ""; ImGui::InputText("no blank", buf5, 32, ImGuiInputTextFlags_CharsNoBlank);
static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
static char buf7[32] = ""; ImGui::InputText("\"imgui\"", buf7, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
ImGui::TreePop(); ImGui::TreePop();
} }
@ -5713,8 +5722,6 @@ static void ShowDemoWindowColumns()
ImGui::TreePop(); ImGui::TreePop();
} }
namespace ImGui { extern ImGuiKeyData* GetKeyData(ImGuiKey key); }
static void ShowDemoWindowInputs() static void ShowDemoWindowInputs()
{ {
IMGUI_DEMO_MARKER("Inputs & Focus"); IMGUI_DEMO_MARKER("Inputs & Focus");
@ -5749,7 +5756,7 @@ static void ShowDemoWindowInputs()
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
ImGuiKey start_key = (ImGuiKey)0; ImGuiKey start_key = (ImGuiKey)0;
#endif #endif
ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); ImGui::SameLine(); ImGui::Text("(%.02f)", ImGui::GetKeyData(key)->DownDuration); } ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
@ -7443,7 +7450,7 @@ static void ShowExampleAppFullscreen(bool* p_open)
static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings; static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
// We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.) // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
// Based on your use case you may want one of the other. // Based on your use case you may want one or the other.
const ImGuiViewport* viewport = ImGui::GetMainViewport(); const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos); ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size); ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (drawing and font code) // (drawing and font code)
/* /*
@ -2553,13 +2553,10 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
// 9. Setup ImFont and glyphs for runtime // 9. Setup ImFont and glyphs for runtime
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
{ {
ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
if (src_tmp.GlyphsCount == 0)
continue;
// When merging fonts with MergeMode=true: // When merging fonts with MergeMode=true:
// - We can have multiple input fonts writing into a same destination font. // - We can have multiple input fonts writing into a same destination font.
// - dst_font->ConfigData is != from cfg which is our source configuration. // - dst_font->ConfigData is != from cfg which is our source configuration.
ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
ImFontConfig& cfg = atlas->ConfigData[src_i]; ImFontConfig& cfg = atlas->ConfigData[src_i];
ImFont* dst_font = cfg.DstFont; ImFont* dst_font = cfg.DstFont;
@ -2623,6 +2620,9 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
ImVector<ImFontAtlasCustomRect>& user_rects = atlas->CustomRects; ImVector<ImFontAtlasCustomRect>& user_rects = atlas->CustomRects;
IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong. IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong.
#ifdef __GNUC__
if (user_rects.Size < 1) { __builtin_unreachable(); } // Workaround for GCC bug if IM_ASSERT() is defined to conditionally throw (see #5343)
#endif
ImVector<stbrp_rect> pack_rects; ImVector<stbrp_rect> pack_rects;
pack_rects.resize(user_rects.Size); pack_rects.resize(user_rects.Size);
@ -3200,7 +3200,25 @@ void ImFont::BuildLookupTable()
SetGlyphVisible((ImWchar)' ', false); SetGlyphVisible((ImWchar)' ', false);
SetGlyphVisible((ImWchar)'\t', false); SetGlyphVisible((ImWchar)'\t', false);
// Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // Setup Fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackGlyph = &Glyphs.back();
FallbackChar = (ImWchar)FallbackGlyph->Codepoint;
}
}
FallbackAdvanceX = FallbackGlyph->AdvanceX;
for (int i = 0; i < max_codepoint + 1; i++)
if (IndexAdvanceX[i] < 0.0f)
IndexAdvanceX[i] = FallbackAdvanceX;
// Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
// However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
// FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots. // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.
const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
@ -3221,25 +3239,6 @@ void ImFont::BuildLookupTable()
EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f; EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f;
EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f; EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f;
} }
// Setup fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));
FallbackGlyph = FindGlyphNoFallback(FallbackChar);
if (FallbackGlyph == NULL)
{
FallbackGlyph = &Glyphs.back();
FallbackChar = (ImWchar)FallbackGlyph->Codepoint;
}
}
FallbackAdvanceX = FallbackGlyph->AdvanceX;
for (int i = 0; i < max_codepoint + 1; i++)
if (IndexAdvanceX[i] < 0.0f)
IndexAdvanceX[i] = FallbackAdvanceX;
} }
// API is designed this way to avoid exposing the 4K page size // API is designed this way to avoid exposing the 4K page size
@ -3790,6 +3789,7 @@ void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir d
void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col)
{ {
// FIXME-OPT: This should be baked in font.
draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8);
} }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@ -130,6 +130,7 @@ struct ImGuiDataVarInfo; // Variable information (e.g. to avoid style
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a deactivating InputText() while another is stealing active id
struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiLastItemData; // Status storage for last submitted items
struct ImGuiLocEntry; // A localization entry. struct ImGuiLocEntry; // A localization entry.
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
@ -163,6 +164,7 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
// Flags // Flags
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow();
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc. typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc.
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
@ -229,6 +231,7 @@ namespace ImStb
#define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
@ -476,7 +479,6 @@ IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, c
IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w); IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; }
IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy);
// Helper: ImVec1 (1D vector) // Helper: ImVec1 (1D vector)
// (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches) // (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches)
@ -901,7 +903,17 @@ enum ImGuiSeparatorFlags_
ImGuiSeparatorFlags_None = 0, ImGuiSeparatorFlags_None = 0,
ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
ImGuiSeparatorFlags_Vertical = 1 << 1, ImGuiSeparatorFlags_Vertical = 1 << 1,
ImGuiSeparatorFlags_SpanAllColumns = 1 << 2, ImGuiSeparatorFlags_SpanAllColumns = 1 << 2, // Make separator cover all columns of a legacy Columns() set.
};
// Flags for FocusWindow(). This is not called ImGuiFocusFlags to avoid confusion with public-facing ImGuiFocusedFlags.
// FIXME: Once we finishing replacing more uses of GetTopMostPopupModal()+IsWindowWithinBeginStackOf()
// and FindBlockingModal() with this, we may want to change the flag to be opt-out instead of opt-in.
enum ImGuiFocusRequestFlags_
{
ImGuiFocusRequestFlags_None = 0,
ImGuiFocusRequestFlags_RestoreFocusedChild = 1 << 0, // Find last focused child (if any) and focus it instead.
ImGuiFocusRequestFlags_UnlessBelowModal = 1 << 1, // Do not set focus if the window is below a modal.
}; };
enum ImGuiTextFlags_ enum ImGuiTextFlags_
@ -1048,6 +1060,15 @@ struct IMGUI_API ImGuiMenuColumns
void CalcNextTotalWidth(bool update_offsets); void CalcNextTotalWidth(bool update_offsets);
}; };
// Internal temporary state for deactivating InputText() instances.
struct IMGUI_API ImGuiInputTextDeactivatedState
{
ImGuiID ID; // widget id owning the text state (which just got deactivated)
ImVector<char> TextA; // text buffer
ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); }
void ClearFreeMemory() { ID = 0; TextA.clear(); }
};
// Internal state of the currently focused/edited text input box // Internal state of the currently focused/edited text input box
// For a given item ID, access with ImGui::GetInputTextState() // For a given item ID, access with ImGui::GetInputTextState()
struct IMGUI_API ImGuiInputTextState struct IMGUI_API ImGuiInputTextState
@ -1254,19 +1275,18 @@ enum ImGuiInputEventType
enum ImGuiInputSource enum ImGuiInputSource
{ {
ImGuiInputSource_None = 0, ImGuiInputSource_None = 0,
ImGuiInputSource_Mouse, ImGuiInputSource_Mouse, // Note: may be Mouse or TouchScreen or Pen. See io.MouseSource to distinguish them.
ImGuiInputSource_Keyboard, ImGuiInputSource_Keyboard,
ImGuiInputSource_Gamepad, ImGuiInputSource_Gamepad,
ImGuiInputSource_Clipboard, // Currently only used by InputText() ImGuiInputSource_Clipboard, // Currently only used by InputText()
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
ImGuiInputSource_COUNT ImGuiInputSource_COUNT
}; };
// FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension? // FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension?
// Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor' // Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor'
struct ImGuiInputEventMousePos { float PosX, PosY; }; struct ImGuiInputEventMousePos { float PosX, PosY; ImGuiMouseSource MouseSource; };
struct ImGuiInputEventMouseWheel { float WheelX, WheelY; }; struct ImGuiInputEventMouseWheel { float WheelX, WheelY; ImGuiMouseSource MouseSource; };
struct ImGuiInputEventMouseButton { int Button; bool Down; }; struct ImGuiInputEventMouseButton { int Button; bool Down; ImGuiMouseSource MouseSource; };
struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; }; struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; };
struct ImGuiInputEventText { unsigned int Char; }; struct ImGuiInputEventText { unsigned int Char; };
struct ImGuiInputEventAppFocused { bool Focused; }; struct ImGuiInputEventAppFocused { bool Focused; };
@ -1275,6 +1295,7 @@ struct ImGuiInputEvent
{ {
ImGuiInputEventType Type; ImGuiInputEventType Type;
ImGuiInputSource Source; ImGuiInputSource Source;
ImU32 EventId; // Unique, sequential increasing integer to identify an event (if you need to correlate them to other data).
union union
{ {
ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos
@ -1383,6 +1404,7 @@ enum ImGuiInputFlags_
// [SECTION] Clipper support // [SECTION] Clipper support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Note that Max is exclusive, so perhaps should be using a Begin/End convention.
struct ImGuiListClipperRange struct ImGuiListClipperRange
{ {
int Min; int Min;
@ -1451,6 +1473,7 @@ enum ImGuiNavMoveFlags_
ImGuiNavMoveFlags_LoopY = 1 << 1, ImGuiNavMoveFlags_LoopY = 1 << 1,
ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness
ImGuiNavMoveFlags_WrapMask_ = ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_WrapY,
ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown) ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
@ -1660,8 +1683,9 @@ enum ImGuiDebugLogFlags_
ImGuiDebugLogFlags_EventPopup = 1 << 2, ImGuiDebugLogFlags_EventPopup = 1 << 2,
ImGuiDebugLogFlags_EventNav = 1 << 3, ImGuiDebugLogFlags_EventNav = 1 << 3,
ImGuiDebugLogFlags_EventClipper = 1 << 4, ImGuiDebugLogFlags_EventClipper = 1 << 4,
ImGuiDebugLogFlags_EventIO = 1 << 5, ImGuiDebugLogFlags_EventSelection = 1 << 5,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventIO, ImGuiDebugLogFlags_EventIO = 1 << 6,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO,
ImGuiDebugLogFlags_OutputToTTY = 1 << 10, // Also send output to TTY ImGuiDebugLogFlags_OutputToTTY = 1 << 10, // Also send output to TTY
}; };
@ -1730,8 +1754,6 @@ struct ImGuiContext
bool Initialized; bool Initialized;
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
ImGuiIO IO; ImGuiIO IO;
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be tricked/written into IO structure.
ImVector<ImGuiInputEvent> InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail.
ImGuiStyle Style; ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
@ -1748,6 +1770,12 @@ struct ImGuiContext
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data void* TestEngine; // Test engine user data
// Inputs
ImVector<ImGuiInputEvent> InputEventsQueue; // Input events which will be trickled/written into IO structure.
ImVector<ImGuiInputEvent> InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail.
ImGuiMouseSource InputEventsNextMouseSource;
ImU32 InputEventsNextEventId;
// Windows state // Windows state
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front. ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front.
@ -1786,7 +1814,7 @@ struct ImGuiContext
bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdHasBeenEditedThisFrame;
ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
ImGuiWindow* ActiveIdWindow; ImGuiWindow* ActiveIdWindow;
ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
int ActiveIdMouseButton; int ActiveIdMouseButton;
ImGuiID ActiveIdPreviousFrame; ImGuiID ActiveIdPreviousFrame;
bool ActiveIdPreviousFrameIsAlive; bool ActiveIdPreviousFrameIsAlive;
@ -1842,7 +1870,7 @@ struct ImGuiContext
ImGuiKeyChord NavJustMovedToKeyMods; ImGuiKeyChord NavJustMovedToKeyMods;
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags; ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
@ -1853,8 +1881,7 @@ struct ImGuiContext
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
bool NavInitRequest; // Init request for appearing window to select first item bool NavInitRequest; // Init request for appearing window to select first item
bool NavInitRequestFromMove; bool NavInitRequestFromMove;
ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) ImGuiNavItemData NavInitResult; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window)
bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame() bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame()
bool NavMoveScoringItems; // Move request submitted, still scoring incoming items bool NavMoveScoringItems; // Move request submitted, still scoring incoming items
bool NavMoveForwardToNextFrame; bool NavMoveForwardToNextFrame;
@ -1936,6 +1963,7 @@ struct ImGuiContext
// Widget state // Widget state
ImVec2 MouseLastValidPos; ImVec2 MouseLastValidPos;
ImGuiInputTextState InputTextState; ImGuiInputTextState InputTextState;
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
@ -2031,6 +2059,9 @@ struct ImGuiContext
TestEngineHookItems = false; TestEngineHookItems = false;
TestEngine = NULL; TestEngine = NULL;
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
InputEventsNextEventId = 1;
WindowsActiveCount = 0; WindowsActiveCount = 0;
CurrentWindow = NULL; CurrentWindow = NULL;
HoveredWindow = NULL; HoveredWindow = NULL;
@ -2080,7 +2111,7 @@ struct ImGuiContext
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiMod_None; NavJustMovedToKeyMods = ImGuiMod_None;
NavInputSource = ImGuiInputSource_None; NavInputSource = ImGuiInputSource_Keyboard;
NavLayer = ImGuiNavLayer_Main; NavLayer = ImGuiNavLayer_Main;
NavIdIsAlive = false; NavIdIsAlive = false;
NavMousePosDirty = false; NavMousePosDirty = false;
@ -2089,7 +2120,6 @@ struct ImGuiContext
NavAnyRequest = false; NavAnyRequest = false;
NavInitRequest = false; NavInitRequest = false;
NavInitRequestFromMove = false; NavInitRequestFromMove = false;
NavInitResultId = 0;
NavMoveSubmitted = false; NavMoveSubmitted = false;
NavMoveScoringItems = false; NavMoveScoringItems = false;
NavMoveForwardToNextFrame = false; NavMoveForwardToNextFrame = false;
@ -2206,14 +2236,15 @@ struct IMGUI_API ImGuiWindowTempData
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
ImVec1 GroupOffset; ImVec1 GroupOffset;
ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensentate and fix the most common use case of large scroll area. ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensate and fix the most common use case of large scroll area.
// Keyboard/Gamepad navigation // Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
short NavLayersActiveMask; // Which layers have been written to (result from previous frame) short NavLayersActiveMask; // Which layers have been written to (result from previous frame)
short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame) short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame)
bool NavIsScrollPushableX; // Set when current work location may be scrolled horizontally when moving left / right. This is generally always true UNLESS within a column.
bool NavHideHighlightOneFrame; bool NavHideHighlightOneFrame;
bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) bool NavWindowHasScrollY; // Set per window when scrolling can be used (== ScrollMax.y > 0.0f)
// Miscellaneous // Miscellaneous
bool MenuBarAppending; // FIXME: Remove this bool MenuBarAppending; // FIXME: Remove this
@ -2333,6 +2364,7 @@ struct IMGUI_API ImGuiWindow
ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
ImVec2 NavPreferredScoringPosRel[ImGuiNavLayer_COUNT]; // Preferred X/Y position updated when moving on a given axis, reset to FLT_MAX.
ImGuiID NavRootFocusScopeId; // Focus Scope ID at the time of Begin() ImGuiID NavRootFocusScopeId; // Focus Scope ID at the time of Begin()
int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy
@ -2445,7 +2477,7 @@ struct IMGUI_API ImGuiTabBar
typedef ImS16 ImGuiTableColumnIdx; typedef ImS16 ImGuiTableColumnIdx;
typedef ImU16 ImGuiTableDrawChannelIdx; typedef ImU16 ImGuiTableDrawChannelIdx;
// [Internal] sizeof() ~ 104 // [Internal] sizeof() ~ 112
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api. // We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping. // We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping.
// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped". // This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped".
@ -2491,7 +2523,7 @@ struct ImGuiTableColumn
ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3) ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3)
ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each) ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each)
ImU8 SortDirectionsAvailList; // Ordered of available sort directions (2-bits each) ImU8 SortDirectionsAvailList; // Ordered list of available sort directions (2-bits each, total 8-bits)
ImGuiTableColumn() ImGuiTableColumn()
{ {
@ -2526,6 +2558,7 @@ struct ImGuiTableInstanceData
}; };
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData // FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData
// sizeof() ~ 580 bytes + heap allocs described in TableBeginInitMemory()
struct IMGUI_API ImGuiTable struct IMGUI_API ImGuiTable
{ {
ImGuiID ID; ImGuiID ID;
@ -2641,6 +2674,7 @@ struct IMGUI_API ImGuiTable
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table). // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. // - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics. // - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
// sizeof() ~ 112 bytes.
struct IMGUI_API ImGuiTableTempData struct IMGUI_API ImGuiTableTempData
{ {
int TableIndex; // Index in g.Tables.Buf[] pool int TableIndex; // Index in g.Tables.Buf[] pool
@ -2728,10 +2762,11 @@ namespace ImGui
IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window); IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window);
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); }
// Windows: Display Order and Focus Order // Windows: Display Order and Focus Order
IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0);
IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window); IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags);
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
@ -2818,6 +2853,7 @@ namespace ImGui
inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min. inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min.
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags = 0);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
@ -2850,6 +2886,7 @@ namespace ImGui
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
IMGUI_API ImGuiWindow* FindBlockingModal(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
@ -2873,6 +2910,8 @@ namespace ImGui
IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestCancel();
IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestApplyResult();
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis);
IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX();
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavWindow(ImGuiWindow* window);
IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
@ -2887,9 +2926,9 @@ namespace ImGui
inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; }
inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; }
inline ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); } inline ImGuiKeyChord ConvertShortcutMod(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; IM_ASSERT_PARANOID(key_chord & ImGuiMod_Shortcut); return (key_chord & ~ImGuiMod_Shortcut) | (g.IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); }
inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key) inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *ctx;
if (key == ImGuiMod_Ctrl) return ImGuiKey_ReservedForModCtrl; if (key == ImGuiMod_Ctrl) return ImGuiKey_ReservedForModCtrl;
if (key == ImGuiMod_Shift) return ImGuiKey_ReservedForModShift; if (key == ImGuiMod_Shift) return ImGuiKey_ReservedForModShift;
if (key == ImGuiMod_Alt) return ImGuiKey_ReservedForModAlt; if (key == ImGuiMod_Alt) return ImGuiKey_ReservedForModAlt;
@ -2898,7 +2937,8 @@ namespace ImGui
return key; return key;
} }
IMGUI_API ImGuiKeyData* GetKeyData(ImGuiKey key); IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key);
inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); }
IMGUI_API void GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size); IMGUI_API void GetKeyChordName(ImGuiKeyChord key_chord, char* out_buf, int out_buf_size);
inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); } inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); }
IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
@ -2922,9 +2962,10 @@ namespace ImGui
// Please open a GitHub Issue to submit your usage scenario or if there's a use case you need solved. // Please open a GitHub Issue to submit your usage scenario or if there's a use case you need solved.
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key); IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id' IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id'
inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &GImGui->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; } inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(ctx, key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }
// [EXPERIMENTAL] High-Level: Input Access functions w/ support for Key/Input Ownership // [EXPERIMENTAL] High-Level: Input Access functions w/ support for Key/Input Ownership
// - Important: legacy IsKeyPressed(ImGuiKey, bool repeat=true) _DEFAULTS_ to repeat, new IsKeyPressed() requires _EXPLICIT_ ImGuiInputFlags_Repeat flag. // - Important: legacy IsKeyPressed(ImGuiKey, bool repeat=true) _DEFAULTS_ to repeat, new IsKeyPressed() requires _EXPLICIT_ ImGuiInputFlags_Repeat flag.
@ -3087,7 +3128,7 @@ namespace ImGui
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width); IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value);
@ -3132,6 +3173,7 @@ namespace ImGui
// InputText // InputText
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags); IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags);
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); }

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (tables and columns code) // (tables and columns code)
/* /*
@ -80,20 +80,20 @@ Index of this file:
// - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge. // - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge.
// - outer_size.x > 0.0f -> Set Fixed width. // - outer_size.x > 0.0f -> Set Fixed width.
// Y with ScrollX/ScrollY disabled: we output table directly in current window // Y with ScrollX/ScrollY disabled: we output table directly in current window
// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful is parent window can vertically scroll. // - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful if parent window can vertically scroll.
// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set) // - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set)
// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set) // - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set)
// Y with ScrollX/ScrollY enabled: using a child window for scrolling // Y with ScrollX/ScrollY enabled: using a child window for scrolling
// - outer_size.y < 0.0f -> Bottom-align. Not meaningful is parent window can vertically scroll. // - outer_size.y < 0.0f -> Bottom-align. Not meaningful if parent window can vertically scroll.
// - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window. // - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window.
// - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis. // - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Outer size is also affected by the NoHostExtendX/NoHostExtendY flags. // Outer size is also affected by the NoHostExtendX/NoHostExtendY flags.
// Important to that note how the two flags have slightly different behaviors! // Important to note how the two flags have slightly different behaviors!
// - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. // - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
// - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible. // - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible.
// In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height. // In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height.
// This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not easily noticeable) // This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not useful and not easily noticeable).
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About 'inner_width': // About 'inner_width':
// With ScrollX disabled: // With ScrollX disabled:
@ -112,15 +112,16 @@ Index of this file:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// COLUMNS SIZING POLICIES // COLUMNS SIZING POLICIES
// (Reference: ImGuiTableFlags_SizingXXX flags and ImGuiTableColumnFlags_WidthXXX flags)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About overriding column sizing policy and width/weight with TableSetupColumn(): // About overriding column sizing policy and width/weight with TableSetupColumn():
// We use a default parameter of 'init_width_or_weight == -1'. // We use a default parameter of -1 for 'init_width'/'init_weight'.
// - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic // - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic
// - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom // - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom
// - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f // - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f
// - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom // - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom
// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f) // Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f)
// and you can fit a 100.0f wide item in it without clipping and with full padding. // and you can fit a 100.0f wide item in it without clipping and with padding honored.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) // About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag)
// - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width // - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width
@ -134,10 +135,10 @@ Index of this file:
// - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place! // - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place!
// that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in. // that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in.
// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents. // - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents.
// - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths. // - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weights/widths.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About using column width: // About using column width:
// If a column is manual resizable or has a width specified with TableSetupColumn(): // If a column is manually resizable or has a width specified with TableSetupColumn():
// - you may use GetContentRegionAvail().x to query the width available in a given column. // - you may use GetContentRegionAvail().x to query the width available in a given column.
// - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width. // - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width.
// If the column is not resizable and has no width specified with TableSetupColumn(): // If the column is not resizable and has no width specified with TableSetupColumn():
@ -151,7 +152,7 @@ Index of this file:
// TABLES CLIPPING/CULLING // TABLES CLIPPING/CULLING
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About clipping/culling of Rows in Tables: // About clipping/culling of Rows in Tables:
// - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows. // - For large numbers of rows, it is recommended you use ImGuiListClipper to submit only visible rows.
// ImGuiListClipper is reliant on the fact that rows are of equal height. // ImGuiListClipper is reliant on the fact that rows are of equal height.
// See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper. // See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper.
// - Note that auto-resizing columns don't play well with using the clipper. // - Note that auto-resizing columns don't play well with using the clipper.
@ -168,7 +169,7 @@ Index of this file:
// - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.). // - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.).
// //
// [A] [B] [C] // [A] [B] [C]
// TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() return false, user can skip submitting items but only if the column doesn't contribute to row height. // TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() returns false, user can skip submitting items but only if the column doesn't contribute to row height.
// SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output. // SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output.
// ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way. // ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way.
// ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway). // ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway).
@ -319,7 +320,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (flags & ImGuiTableFlags_ScrollX) if (flags & ImGuiTableFlags_ScrollX)
IM_ASSERT(inner_width >= 0.0f); IM_ASSERT(inner_width >= 0.0f);
// If an outer size is specified ahead we will be able to early out when not visible. Exact clipping rules may evolve. // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve.
const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
const ImVec2 avail_size = GetContentRegionAvail(); const ImVec2 avail_size = GetContentRegionAvail();
ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
@ -366,7 +367,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
if (table->InstanceDataExtra.Size < instance_no) if (table->InstanceDataExtra.Size < instance_no)
table->InstanceDataExtra.push_back(ImGuiTableInstanceData()); table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instance" followed by (int)instance_no in ID stack. instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instances" followed by (int)instance_no in ID stack.
} }
else else
{ {
@ -477,12 +478,13 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->IsUnfrozenRows = true; table->IsUnfrozenRows = true;
table->DeclColumnsCount = 0; table->DeclColumnsCount = 0;
// Using opaque colors facilitate overlapping elements of the grid // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong); table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight);
// Make table current // Make table current
g.CurrentTable = table; g.CurrentTable = table;
outer_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX();
outer_window->DC.CurrentTableIdx = table_idx; outer_window->DC.CurrentTableIdx = table_idx;
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
inner_window->DC.CurrentTableIdx = table_idx; inner_window->DC.CurrentTableIdx = table_idx;
@ -490,7 +492,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0) if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
table->IsResetDisplayOrderRequest = true; table->IsResetDisplayOrderRequest = true;
// Mark as used // Mark as used to avoid GC
if (table_idx >= g.TablesLastTimeActive.Size) if (table_idx >= g.TablesLastTimeActive.Size)
g.TablesLastTimeActive.resize(table_idx + 1, -1.0f); g.TablesLastTimeActive.resize(table_idx + 1, -1.0f);
g.TablesLastTimeActive[table_idx] = (float)g.Time; g.TablesLastTimeActive[table_idx] = (float)g.Time;
@ -583,13 +585,13 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
} }
// For reference, the average total _allocation count_ for a table is: // For reference, the average total _allocation count_ for a table is:
// + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables) // + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables[])
// + 1 (for table->RawData allocated below) // + 1 (for table->RawData allocated below)
// + 1 (for table->ColumnsNames, if names are used) // + 1 (for table->ColumnsNames, if names are used)
// Shared allocations per number of nested tables // Shared allocations for the maximum number of simultaneously nested tables (generally a very small number)
// + 1 (for table->Splitter._Channels) // + 1 (for table->Splitter._Channels)
// + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels) // + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels)
// Where active_channels_count is variable but often == columns_count or columns_count + 1, see TableSetupDrawChannels() for details. // Where active_channels_count is variable but often == columns_count or == columns_count + 1, see TableSetupDrawChannels() for details.
// Unused channels don't perform their +2 allocations. // Unused channels don't perform their +2 allocations.
void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count) void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
{ {
@ -616,7 +618,7 @@ void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
void ImGui::TableBeginApplyRequests(ImGuiTable* table) void ImGui::TableBeginApplyRequests(ImGuiTable* table)
{ {
// Handle resizing request // Handle resizing request
// (We process this at the first TableBegin of the frame) // (We process this in the TableBegin() of the first instance of each table)
// FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling? // FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling?
if (table->InstanceCurrent == 0) if (table->InstanceCurrent == 0)
{ {
@ -661,8 +663,7 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir; table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir;
IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir); IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir);
// Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[], // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[]. Rebuild later from the former.
// rebuild the later from the former.
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n; table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n;
table->ReorderColumnDir = 0; table->ReorderColumnDir = 0;
@ -736,8 +737,8 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
} }
} }
// Layout columns for the frame. This is in essence the followup to BeginTable(). // Layout columns for the frame. This is in essence the followup to BeginTable() and this is our largest function.
// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first. // Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() and other TableSetupXXXXX() functions to be called first.
// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns. // FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns.
// Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns? // Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns?
void ImGui::TableUpdateLayout(ImGuiTable* table) void ImGui::TableUpdateLayout(ImGuiTable* table)
@ -1144,7 +1145,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
EndPopup(); EndPopup();
} }
// [Part 12] Sanitize and build sort specs before we have a change to use them for display. // [Part 12] Sanitize and build sort specs before we have a chance to use them for display.
// This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change) // This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change)
if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable)) if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable))
TableSortSpecsBuild(table); TableSortSpecsBuild(table);
@ -1165,9 +1166,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
} }
// Process hit-testing on resizing borders. Actual size change will be applied in EndTable() // Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
// - Set table->HoveredColumnBorder with a short delay/timer to reduce feedback noise // - Set table->HoveredColumnBorder with a short delay/timer to reduce visual feedback noise.
// - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize widgets // - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize
// overlapping the same area. // widgets overlapping the same area.
void ImGui::TableUpdateBorders(ImGuiTable* table) void ImGui::TableUpdateBorders(ImGuiTable* table)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1436,6 +1437,7 @@ void ImGui::EndTable()
g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter; g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter;
} }
outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
NavUpdateCurrentWindowIsScrollPushableX();
} }
// See "COLUMN SIZING POLICIES" comments at the top of this file // See "COLUMN SIZING POLICIES" comments at the top of this file
@ -1641,7 +1643,7 @@ ImGuiID ImGui::TableGetColumnResizeID(ImGuiTable* table, int column_n, int insta
return instance_id + 1 + column_n; // FIXME: #6140: still not ideal return instance_id + 1 + column_n; // FIXME: #6140: still not ideal
} }
// Return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered. // Return -1 when table is not hovered. return columns_count if hovering the unused space at the right of the right-most visible column.
int ImGui::TableGetHoveredColumn() int ImGui::TableGetHoveredColumn()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1978,6 +1980,7 @@ bool ImGui::TableNextColumn()
// FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns. // FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns.
void ImGui::TableBeginCell(ImGuiTable* table, int column_n) void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
{ {
ImGuiContext& g = *GImGui;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
ImGuiWindow* window = table->InnerWindow; ImGuiWindow* window = table->InnerWindow;
table->CurrentColumn = column_n; table->CurrentColumn = column_n;
@ -2002,7 +2005,6 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
window->SkipItems = column->IsSkipItems; window->SkipItems = column->IsSkipItems;
if (column->IsSkipItems) if (column->IsSkipItems)
{ {
ImGuiContext& g = *GImGui;
g.LastItemData.ID = 0; g.LastItemData.ID = 0;
g.LastItemData.StatusFlags = 0; g.LastItemData.StatusFlags = 0;
} }
@ -2021,7 +2023,6 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
} }
// Logging // Logging
ImGuiContext& g = *GImGui;
if (g.LogEnabled && !column->IsSkipItems) if (g.LogEnabled && !column->IsSkipItems)
{ {
LogRenderedText(&window->DC.CursorPos, "|"); LogRenderedText(&window->DC.CursorPos, "|");
@ -2141,7 +2142,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
// - All stretch: easy. // - All stretch: easy.
// - One or more fixed + one stretch: easy. // - One or more fixed + one stretch: easy.
// - One or more fixed + more than one stretch: tricky. // - One or more fixed + more than one stretch: tricky.
// Qt when manual resize is enabled only support a single _trailing_ stretch column. // Qt when manual resize is enabled only supports a single _trailing_ stretch column, we support more cases here.
// When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1. // When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1.
// FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user. // FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user.
@ -2224,7 +2225,7 @@ void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
{ {
IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1); IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1);
// Measure existing quantity // Measure existing quantities
float visible_weight = 0.0f; float visible_weight = 0.0f;
float visible_width = 0.0f; float visible_width = 0.0f;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@ -2381,11 +2382,11 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
struct MergeGroup struct MergeGroup
{ {
ImRect ClipRect; ImRect ClipRect;
int ChannelsCount; int ChannelsCount = 0;
ImBitArrayPtr ChannelsMask; ImBitArrayPtr ChannelsMask = NULL;
}; };
int merge_group_mask = 0x00; int merge_group_mask = 0x00;
MergeGroup merge_groups[4] = {}; MergeGroup merge_groups[4];
// Use a reusable temp buffer for the merge masks as they are dynamically sized. // Use a reusable temp buffer for the merge masks as they are dynamically sized.
const int max_draw_channels = (4 + table->ColumnsCount * 2); const int max_draw_channels = (4 + table->ColumnsCount * 2);
@ -2499,11 +2500,9 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x); merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x);
if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0) if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0)
merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y); merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y);
#if 0 //GetForegroundDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f); // [DEBUG]
GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f); //GetForegroundDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200));
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200)); //GetForegroundDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
#endif
remaining_count -= merge_group->ChannelsCount; remaining_count -= merge_group->ChannelsCount;
for (int n = 0; n < (size_for_masks_bitarrays_one >> 2); n++) for (int n = 0; n < (size_for_masks_bitarrays_one >> 2); n++)
remaining_mask[n] &= ~merge_group->ChannelsMask[n]; remaining_mask[n] &= ~merge_group->ChannelsMask[n];
@ -2667,7 +2666,6 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
TableUpdateLayout(table); TableUpdateLayout(table);
TableSortSpecsBuild(table); TableSortSpecsBuild(table);
return &table->SortSpecs; return &table->SortSpecs;
} }
@ -2786,7 +2784,7 @@ void ImGui::TableSortSpecsSanitize(ImGuiTable* table)
} }
} }
// Fallback default sort order (if no column had the ImGuiTableColumnFlags_DefaultSort flag) // Fallback default sort order (if no column with the ImGuiTableColumnFlags_DefaultSort flag)
if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
@ -3007,7 +3005,7 @@ void ImGui::TableHeader(const char* label)
} }
// Sort order arrow // Sort order arrow
const float ellipsis_max = cell_r.Max.x - w_arrow - w_sort_text; const float ellipsis_max = ImMax(cell_r.Max.x - w_arrow - w_sort_text, label_pos.x);
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
{ {
if (column->SortOrder != -1) if (column->SortOrder != -1)
@ -3477,12 +3475,12 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
if (!save_column) if (!save_column)
continue; continue;
buf->appendf("Column %-2d", column_n); buf->appendf("Column %-2d", column_n);
if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID); if (column->UserID != 0) { buf->appendf(" UserID=%08X", column->UserID); }
if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight); if (save_size && column->IsStretch) { buf->appendf(" Weight=%.4f", column->WidthOrWeight); }
if (save_size && !column->IsStretch) buf->appendf(" Width=%d", (int)column->WidthOrWeight); if (save_size && !column->IsStretch) { buf->appendf(" Width=%d", (int)column->WidthOrWeight); }
if (save_visible) buf->appendf(" Visible=%d", column->IsEnabled); if (save_visible) { buf->appendf(" Visible=%d", column->IsEnabled); }
if (save_order) buf->appendf(" Order=%d", column->DisplayOrder); if (save_order) { buf->appendf(" Order=%d", column->DisplayOrder); }
if (save_sort && column->SortOrder != -1) buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); if (save_sort && column->SortOrder != -1) { buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); }
buf->append("\n"); buf->append("\n");
} }
buf->append("\n"); buf->append("\n");
@ -3530,7 +3528,7 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
IM_ASSERT(table->MemoryCompacted == false); IM_ASSERT(table->MemoryCompacted == false);
table->SortSpecs.Specs = NULL; table->SortSpecs.Specs = NULL;
table->SortSpecsMulti.clear(); table->SortSpecsMulti.clear();
table->IsSortSpecsDirty = true; // FIXME: shouldn't have to leak into user performing a sort table->IsSortSpecsDirty = true; // FIXME: In theory shouldn't have to leak into user performing a sort on resume.
table->ColumnsNames.clear(); table->ColumnsNames.clear();
table->MemoryCompacted = true; table->MemoryCompacted = true;
for (int n = 0; n < table->ColumnsCount; n++) for (int n = 0; n < table->ColumnsCount; n++)
@ -3583,13 +3581,9 @@ static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_poli
void ImGui::DebugNodeTable(ImGuiTable* table) void ImGui::DebugNodeTable(ImGuiTable* table)
{ {
char buf[512]; const bool is_active = (table->LastFrameActive >= GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
char* p = buf;
const char* buf_end = buf + IM_ARRAYSIZE(buf);
const bool is_active = (table->LastFrameActive >= ImGui::GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
ImFormatString(p, buf_end - p, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
bool open = TreeNode(table, "%s", buf); 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 (!is_active) { PopStyleColor(); }
if (IsItemHovered()) if (IsItemHovered())
GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255)); GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
@ -3598,7 +3592,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
if (!open) if (!open)
return; return;
if (table->InstanceCurrent > 0) if (table->InstanceCurrent > 0)
ImGui::Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1); Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1);
bool clear_settings = SmallButton("Clear settings"); bool clear_settings = SmallButton("Clear settings");
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
@ -3614,6 +3608,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
{ {
ImGuiTableColumn* column = &table->Columns[n]; ImGuiTableColumn* column = &table->Columns[n];
const char* name = TableGetColumnName(table, n); const char* name = TableGetColumnName(table, n);
char buf[512];
ImFormatString(buf, IM_ARRAYSIZE(buf), ImFormatString(buf, IM_ARRAYSIZE(buf),
"Column %d order %d '%s': offset %+.2f to %+.2f%s\n" "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" "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n"
@ -3902,6 +3897,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFl
columns->Count = columns_count; columns->Count = columns_count;
columns->Flags = flags; columns->Flags = flags;
window->DC.CurrentColumns = columns; window->DC.CurrentColumns = columns;
window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX();
columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorPosY = window->DC.CursorPos.y;
columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
@ -4092,6 +4088,7 @@ void ImGui::EndColumns()
window->DC.CurrentColumns = NULL; window->DC.CurrentColumns = NULL;
window->DC.ColumnsOffset.x = 0.0f; window->DC.ColumnsOffset.x = 0.0f;
window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
NavUpdateCurrentWindowIsScrollPushableX();
} }
void ImGui::Columns(int columns_count, const char* id, bool border) void ImGui::Columns(int columns_count, const char* id, bool border)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.4 // dear imgui, v1.89.6
// (widgets code) // (widgets code)
/* /*
@ -622,7 +622,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
pressed = true; pressed = true;
SetActiveID(id, window); SetActiveID(id, window);
g.ActiveIdSource = ImGuiInputSource_Nav; g.ActiveIdSource = g.NavInputSource;
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus))
SetFocusID(id, window); SetFocusID(id, window);
} }
@ -638,7 +638,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
const int mouse_button = g.ActiveIdMouseButton; const int mouse_button = g.ActiveIdMouseButton;
if (IsMouseDown(mouse_button, test_owner_id)) if (mouse_button == -1)
{
// Fallback for the rare situation were g.ActiveId was set programmatically or from another widget (e.g. #6304).
ClearActiveID();
}
else if (IsMouseDown(mouse_button, test_owner_id))
{ {
held = true; held = true;
} }
@ -660,7 +665,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
if (!(flags & ImGuiButtonFlags_NoNavFocus)) if (!(flags & ImGuiButtonFlags_NoNavFocus))
g.NavDisableHighlight = true; g.NavDisableHighlight = true;
} }
else if (g.ActiveIdSource == ImGuiInputSource_Nav) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
// When activated using Nav, we hold on the ActiveID until activation button is released // When activated using Nav, we hold on the ActiveID until activation button is released
if (g.NavActivateDownId != id) if (g.NavActivateDownId != id)
@ -827,7 +832,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
ImVec2 center = bb.GetCenter(); ImVec2 center = bb.GetCenter();
if (hovered) if (hovered)
window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12); window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col);
float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
ImU32 cross_col = GetColorU32(ImGuiCol_Text); ImU32 cross_col = GetColorU32(ImGuiCol_Text);
@ -852,7 +857,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text); ImU32 text_col = GetColorU32(ImGuiCol_Text);
if (hovered || held) if (hovered || held)
window->DrawList->AddCircleFilled(bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12); window->DrawList->AddCircleFilled(bb.GetCenter()/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col);
RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
// Switch to moving the window after mouse is moved beyond the initial drag threshold // Switch to moving the window after mouse is moved beyond the initial drag threshold
@ -1233,17 +1238,18 @@ bool ImGui::RadioButton(const char* label, bool active)
MarkItemEdited(id); MarkItemEdited(id);
RenderNavHighlight(total_bb, id); RenderNavHighlight(total_bb, id);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
if (active) if (active)
{ {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark));
} }
if (style.FrameBorderSize > 0.0f) if (style.FrameBorderSize > 0.0f)
{ {
window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize); window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), num_segment, style.FrameBorderSize);
window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize); window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), num_segment, style.FrameBorderSize);
} }
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
@ -1386,8 +1392,9 @@ void ImGui::AlignTextToFramePadding()
} }
// Horizontal/vertical separating line // Horizontal/vertical separating line
// FIXME: Surprisingly, this seemingly simple widget is adjacent to MANY different legacy/tricky layout issues. // FIXME: Surprisingly, this seemingly trivial widget is a victim of many different legacy/tricky layout issues.
void ImGui::SeparatorEx(ImGuiSeparatorFlags flags) // Note how thickness == 1.0f is handled specifically as not moving CursorPos by 'thickness', but other values are.
void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
@ -1395,8 +1402,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
IM_ASSERT(thickness > 0.0f);
const float thickness = 1.0f; // Cannot use g.Style.SeparatorTextSize yet for various reasons.
if (flags & ImGuiSeparatorFlags_Vertical) if (flags & ImGuiSeparatorFlags_Vertical)
{ {
// Vertical separator, for menu bars (use current line height). // Vertical separator, for menu bars (use current line height).
@ -1430,6 +1437,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
x2 = table->Columns[table->CurrentColumn].MaxX; x2 = table->Columns[table->CurrentColumn].MaxX;
} }
// Before Tables API happened, we relied on Separator() to span all columns of a Columns() set.
// We currently don't need to provide the same feature for tables because tables naturally have border features.
ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL; ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
if (columns) if (columns)
PushColumnsBackground(); PushColumnsBackground();
@ -1439,8 +1448,8 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change. const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change.
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness)); const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness));
ItemSize(ImVec2(0.0f, thickness_for_layout)); ItemSize(ImVec2(0.0f, thickness_for_layout));
const bool item_visible = ItemAdd(bb, 0);
if (item_visible) if (ItemAdd(bb, 0))
{ {
// Draw // Draw
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator)); window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator));
@ -1463,10 +1472,11 @@ void ImGui::Separator()
if (window->SkipItems) if (window->SkipItems)
return; return;
// Those flags should eventually be overridable by the user // Those flags should eventually be configurable by the user
// FIXME: We cannot g.Style.SeparatorTextBorderSize for thickness as it relates to SeparatorText() which is a decorated separator, not defaulting to 1.0f.
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot. flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot.
SeparatorEx(flags); SeparatorEx(flags, 1.0f);
} }
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w) void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
@ -1526,8 +1536,8 @@ void ImGui::SeparatorText(const char* label)
return; return;
// The SeparatorText() vs SeparatorTextEx() distinction is designed to be considerate that we may want: // The SeparatorText() vs SeparatorTextEx() distinction is designed to be considerate that we may want:
// - allow headers to be draggable items (would require a stable ID + a noticeable highlight) // - allow separator-text to be draggable items (would require a stable ID + a noticeable highlight)
// - this high-level entry point to allow formatting? (may require ID separate from formatted string) // - this high-level entry point to allow formatting? (which in turns may require ID separate from formatted string)
// - because of this we probably can't turn 'const char* label' into 'const char* fmt, ...' // - because of this we probably can't turn 'const char* label' into 'const char* fmt, ...'
// Otherwise, we can decide that users wanting to drag this would layout a dedicated drag-item, // Otherwise, we can decide that users wanting to drag this would layout a dedicated drag-item,
// and then we can turn this into a format function. // and then we can turn this into a format function.
@ -2084,7 +2094,8 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
memcpy(&data_backup, p_data, type_info->Size); memcpy(&data_backup, p_data, type_info->Size);
// Sanitize format // Sanitize format
// For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf // - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
// - In theory could treat empty format as using default, but this would only cover rare/bizarre case of using InputScalar() + integer + format string without %.
char format_sanitized[32]; char format_sanitized[32];
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
format = type_info->ScanFmt; format = type_info->ScanFmt;
@ -2245,7 +2256,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
if (g.IO.KeyShift) if (g.IO.KeyShift)
adjust_delta *= 10.0f; adjust_delta *= 10.0f;
} }
else if (g.ActiveIdSource == ImGuiInputSource_Nav) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow); const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow);
@ -2352,7 +2363,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
// Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation. // Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation.
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
ClearActiveID(); ClearActiveID();
else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
ClearActiveID(); ClearActiveID();
} }
if (g.ActiveId != id) if (g.ActiveId != id)
@ -2821,7 +2832,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
set_new_value = true; set_new_value = true;
} }
} }
else if (g.ActiveIdSource == ImGuiInputSource_Nav) else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
{ {
if (g.ActiveIdIsJustActivated) if (g.ActiveIdIsJustActivated)
{ {
@ -3267,7 +3278,7 @@ const char* ImParseFormatFindEnd(const char* fmt)
} }
// Extract the format out of a format string with leading or trailing decorations // Extract the format out of a format string with leading or trailing decorations
// fmt = "blah blah" -> return fmt // fmt = "blah blah" -> return ""
// fmt = "%.3f" -> return fmt // fmt = "%.3f" -> return fmt
// fmt = "hello %.3f" -> return fmt + 6 // fmt = "hello %.3f" -> return fmt + 6
// fmt = "%.3f hello" -> return buf written with "%.3f" // fmt = "%.3f hello" -> return buf written with "%.3f"
@ -3275,7 +3286,7 @@ const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_
{ {
const char* fmt_start = ImParseFormatFindStart(fmt); const char* fmt_start = ImParseFormatFindStart(fmt);
if (fmt_start[0] != '%') if (fmt_start[0] != '%')
return fmt; return "";
const char* fmt_end = ImParseFormatFindEnd(fmt_start); const char* fmt_end = ImParseFormatFindEnd(fmt_start);
if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data. if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
return fmt_start; return fmt_start;
@ -3300,7 +3311,7 @@ void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t
*fmt_out = 0; // Zero-terminate *fmt_out = 0; // Zero-terminate
} }
// - For scanning we need to remove all width and precision fields "%3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d" // - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d"
const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size) const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size)
{ {
const char* fmt_end = ImParseFormatFindEnd(fmt_in); const char* fmt_end = ImParseFormatFindEnd(fmt_in);
@ -3311,7 +3322,7 @@ const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out,
while (fmt_in < fmt_end) while (fmt_in < fmt_end)
{ {
char c = *fmt_in++; char c = *fmt_in++;
if (!has_type && ((c >= '0' && c <= '9') || c == '.')) if (!has_type && ((c >= '0' && c <= '9') || c == '.' || c == '+' || c == '#'))
continue; continue;
has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits
if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
@ -3393,9 +3404,14 @@ static inline ImGuiInputTextFlags InputScalar_DefaultCharsFilter(ImGuiDataType d
// However this may not be ideal for all uses, as some user code may break on out of bound values. // However this may not be ideal for all uses, as some user code may break on out of bound values.
bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
{ {
// FIXME: May need to clarify display behavior if format doesn't contain %.
// "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405
const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
char fmt_buf[32]; char fmt_buf[32];
char data_buf[32]; char data_buf[32];
format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
if (format[0] == 0)
format = type_info->PrintFmt;
DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
ImStrTrimBlanks(data_buf); ImStrTrimBlanks(data_buf);
@ -3406,7 +3422,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
{ {
// Backup old value // Backup old value
size_t data_type_size = DataTypeGetInfo(data_type)->Size; size_t data_type_size = type_info->Size;
ImGuiDataTypeTempStorage data_backup; ImGuiDataTypeTempStorage data_backup;
memcpy(&data_backup, p_data, data_type_size); memcpy(&data_backup, p_data, data_type_size);
@ -3450,7 +3466,12 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
bool value_changed = false; bool value_changed = false;
if (p_step != NULL) if (p_step == NULL)
{
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
}
else
{ {
const float button_size = GetFrameHeight(); const float button_size = GetFrameHeight();
@ -3493,11 +3514,6 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
PopID(); PopID();
EndGroup(); EndGroup();
} }
else
{
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
}
if (value_changed) if (value_changed)
MarkItemEdited(g.LastItemData.ID); MarkItemEdited(g.LastItemData.ID);
@ -3699,10 +3715,34 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
r->num_chars = (int)(text_remaining - (text + line_start_idx)); r->num_chars = (int)(text_remaining - (text + line_start_idx));
} }
static bool is_separator(unsigned int c)
{
return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!';
}
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
{
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators. // When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; } if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; } return 0;
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; }
bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]);
bool prev_separ = is_separator(obj->TextW[idx - 1]);
bool curr_white = ImCharIsBlankW(obj->TextW[idx]);
bool curr_separ = is_separator(obj->TextW[idx]);
return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
}
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
{
if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
return 0;
bool prev_white = ImCharIsBlankW(obj->TextW[idx]);
bool prev_separ = is_separator(obj->TextW[idx]);
bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]);
bool curr_separ = is_separator(obj->TextW[idx - 1]);
return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
}
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
@ -3999,6 +4039,21 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i); p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i);
} }
// As InputText() retain textual data and we currently provide a path for user to not retain it (via local variables)
// we need some form of hook to reapply data back to user buffer on deactivation frame. (#4714)
// It would be more desirable that we discourage users from taking advantage of the "user not retaining data" trick,
// but that more likely be attractive when we do have _NoLiveEdit flag available.
void ImGui::InputTextDeactivateHook(ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiInputTextState* state = &g.InputTextState;
if (id == 0 || state->ID != id)
return;
g.InputTextDeactivatedState.ID = state->ID;
g.InputTextDeactivatedState.TextA.resize(state->CurLenA + 1);
memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data ? state->TextA.Data : "", state->CurLenA + 1);
}
// Edit a string of text // Edit a string of text
// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!". // - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
@ -4104,7 +4159,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state.
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing); const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing);
const bool init_state = (init_make_active || user_scroll_active); const bool init_state = (init_make_active || user_scroll_active);
if ((init_state && g.ActiveId != id) || init_changed_specs) if ((init_state && g.ActiveId != id) || init_changed_specs)
@ -4113,6 +4168,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state = &g.InputTextState; state = &g.InputTextState;
state->CursorAnimReset(); state->CursorAnimReset();
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
InputTextDeactivateHook(state->ID);
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar) // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
// From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode) // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
const int buf_len = (int)strlen(buf); const int buf_len = (int)strlen(buf);
@ -4248,7 +4306,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
// Down the line we should have a cleaner library-wide concept of Selected vs Active. // Down the line we should have a cleaner library-wide concept of Selected vs Active.
g.ActiveIdAllowOverlap = !io.MouseDown[0]; g.ActiveIdAllowOverlap = !io.MouseDown[0];
g.WantTextInputNextFrame = 1;
// Edit in progress // Edit in progress
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
@ -4525,6 +4582,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Push records into the undo stack so we can CTRL+Z the revert operation itself // Push records into the undo stack so we can CTRL+Z the revert operation itself
apply_new_text = state->InitialTextA.Data; apply_new_text = state->InitialTextA.Data;
apply_new_text_length = state->InitialTextA.Size - 1; apply_new_text_length = state->InitialTextA.Size - 1;
value_changed = true;
ImVector<ImWchar> w_text; ImVector<ImWchar> w_text;
if (apply_new_text_length > 0) if (apply_new_text_length > 0)
{ {
@ -4638,10 +4696,24 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
apply_new_text = state->TextA.Data; apply_new_text = state->TextA.Data;
apply_new_text_length = state->CurLenA; apply_new_text_length = state->CurLenA;
value_changed = true;
} }
} }
} }
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
if (g.InputTextDeactivatedState.ID == id)
{
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly)
{
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
value_changed |= (strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0);
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
}
g.InputTextDeactivatedState.ID = 0;
}
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id) // Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
if (apply_new_text != NULL) if (apply_new_text != NULL)
{ {
@ -4669,12 +4741,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size. // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size)); ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
value_changed = true;
} }
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
if (clear_active_id && g.ActiveId == id) // Otherwise request text input ahead for next frame.
if (g.ActiveId == id && clear_active_id)
ClearActiveID(); ClearActiveID();
else if (g.ActiveId == id)
g.WantTextInputNextFrame = 1;
// Render frame // Render frame
if (!is_multiline) if (!is_multiline)
@ -5582,7 +5656,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
float sin_hue_angle = ImSin(H * 2.0f * IM_PI); float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f); ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f);
float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32); int hue_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(hue_cursor_rad); // Lock segment count so the +1 one matches others.
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
@ -5592,13 +5666,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle); ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle); ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
ImVec2 uv_white = GetFontTexUvWhitePixel(); ImVec2 uv_white = GetFontTexUvWhitePixel();
draw_list->PrimReserve(6, 6); draw_list->PrimReserve(3, 3);
draw_list->PrimVtx(tra, uv_white, hue_color32); draw_list->PrimVtx(tra, uv_white, hue_color32);
draw_list->PrimVtx(trb, uv_white, hue_color32);
draw_list->PrimVtx(trc, uv_white, col_white);
draw_list->PrimVtx(tra, uv_white, 0);
draw_list->PrimVtx(trb, uv_white, col_black); draw_list->PrimVtx(trb, uv_white, col_black);
draw_list->PrimVtx(trc, uv_white, 0); draw_list->PrimVtx(trc, uv_white, col_white);
draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
} }
@ -5621,9 +5692,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f; float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12); int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others.
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12); draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments);
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12); draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments);
draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, sv_cursor_segments);
// Render alpha bar // Render alpha bar
if (alpha_bar) if (alpha_bar)
@ -6151,11 +6223,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open) if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open)
{ {
toggled = true; toggled = true;
NavClearPreferredPosForAxis(ImGuiAxis_X);
NavMoveRequestCancel(); NavMoveRequestCancel();
} }
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
{ {
toggled = true; toggled = true;
NavClearPreferredPosForAxis(ImGuiAxis_X);
NavMoveRequestCancel(); NavMoveRequestCancel();
} }
@ -6545,20 +6619,6 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
return true; return true;
} }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// OBSOLETED in 1.81 (from February 2021)
bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
{
// If height_in_items == -1, default height is maximum 7.
ImGuiContext& g = *GImGui;
float height_in_items_f = (height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f;
ImVec2 size;
size.x = 0.0f;
size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f;
return BeginListBox(label, size);
}
#endif
void ImGui::EndListBox() void ImGui::EndListBox()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -7022,7 +7082,7 @@ void ImGui::EndMainMenuBar()
// FIXME: With this strategy we won't be able to restore a NULL focus. // FIXME: With this strategy we won't be able to restore a NULL focus.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest) if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
FocusTopMostWindowUnderOne(g.NavWindow, NULL); FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild);
End(); End();
} }
@ -7036,7 +7096,7 @@ static bool IsRootOfOpenMenuSet()
// Initially we used 'upper_popup->OpenParentId == window->IDStack.back()' to differentiate multiple menu sets from each others // Initially we used 'upper_popup->OpenParentId == window->IDStack.back()' to differentiate multiple menu sets from each others
// (e.g. inside menu bar vs loose menu items) based on parent ID. // (e.g. inside menu bar vs loose menu items) based on parent ID.
// This would however prevent the use of e.g. PuhsID() user code submitting menus. // This would however prevent the use of e.g. PushID() user code submitting menus.
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag, // Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects. // making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup // Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
@ -7046,7 +7106,9 @@ static bool IsRootOfOpenMenuSet()
// open on hover, but that should be a lesser problem, because if such menus are close in proximity in window content then it won't feel weird and if they are far apart // open on hover, but that should be a lesser problem, because if such menus are close in proximity in window content then it won't feel weird and if they are far apart
// it likely won't be a problem anyone runs into. // it likely won't be a problem anyone runs into.
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size]; const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
return (window->DC.NavLayerCurrent == upper_popup->ParentNavLayer && upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu)); if (window->DC.NavLayerCurrent != upper_popup->ParentNavLayer)
return false;
return upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu) && ImGui::IsWindowChildOf(upper_popup->Window, window, true);
} }
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
@ -7563,6 +7625,12 @@ void ImGui::EndTabBar()
g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back()); g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
} }
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
static float TabBarCalcScrollableWidth(ImGuiTabBar* tab_bar, ImGuiTabBarSection* sections)
{
return tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
}
// This is called only once a frame before by the first call to ItemTab() // This is called only once a frame before by the first call to ItemTab()
// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions. // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
@ -7765,9 +7833,23 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
tab_bar->VisibleTabId = tab_bar->SelectedTabId; tab_bar->VisibleTabId = tab_bar->SelectedTabId;
tab_bar->VisibleTabWasSubmitted = false; tab_bar->VisibleTabWasSubmitted = false;
// Update scrolling // Apply request requests
if (scroll_to_tab_id != 0) if (scroll_to_tab_id != 0)
TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections); TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
else if ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) && IsMouseHoveringRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, true) && IsWindowContentHoverable(g.CurrentWindow))
{
const float wheel = g.IO.MouseWheelRequestAxisSwap ? g.IO.MouseWheel : g.IO.MouseWheelH;
const ImGuiKey wheel_key = g.IO.MouseWheelRequestAxisSwap ? ImGuiKey_MouseWheelY : ImGuiKey_MouseWheelX;
if (TestKeyOwner(wheel_key, tab_bar->ID) && wheel != 0.0f)
{
const float scroll_step = wheel * TabBarCalcScrollableWidth(tab_bar, sections) / 3.0f;
tab_bar->ScrollingTargetDistToVisibility = 0.0f;
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget - scroll_step);
}
SetKeyOwner(wheel_key, tab_bar->ID);
}
// Update scrolling
tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim); tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget); tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget) if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
@ -7904,8 +7986,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
int order = TabBarGetTabOrder(tab_bar, tab); int order = TabBarGetTabOrder(tab_bar, tab);
// Scrolling happens only in the central section (leading/trailing sections are not scrolling) // Scrolling happens only in the central section (leading/trailing sections are not scrolling)
// FIXME: This is all confusing. float scrollable_width = TabBarCalcScrollableWidth(tab_bar, sections);
float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
// We make all tabs positions all relative Sections[0].Width to make code simpler // We make all tabs positions all relative Sections[0].Width to make code simpler
float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f); float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f);

File diff suppressed because it is too large Load Diff

View File

@ -145,7 +145,7 @@ enum ImPlotFlags_ {
// Options for plot axes (see SetupAxis). // Options for plot axes (see SetupAxis).
enum ImPlotAxisFlags_ { enum ImPlotAxisFlags_ {
ImPlotAxisFlags_None = 0, // default ImPlotAxisFlags_None = 0, // default
ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is NULL) ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is nullptr)
ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed
ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed
ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed
@ -596,9 +596,9 @@ namespace ImPlot {
// Creates a new ImPlot context. Call this after ImGui::CreateContext. // Creates a new ImPlot context. Call this after ImGui::CreateContext.
IMPLOT_API ImPlotContext* CreateContext(); IMPLOT_API ImPlotContext* CreateContext();
// Destroys an ImPlot context. Call this before ImGui::DestroyContext. NULL = destroy current context. // Destroys an ImPlot context. Call this before ImGui::DestroyContext. nullptr = destroy current context.
IMPLOT_API void DestroyContext(ImPlotContext* ctx = NULL); IMPLOT_API void DestroyContext(ImPlotContext* ctx = nullptr);
// Returns the current ImPlot context. NULL if no context has ben set. // Returns the current ImPlot context. nullptr if no context has ben set.
IMPLOT_API ImPlotContext* GetCurrentContext(); IMPLOT_API ImPlotContext* GetCurrentContext();
// Sets the current ImPlot context. // Sets the current ImPlot context.
IMPLOT_API void SetCurrentContext(ImPlotContext* ctx); IMPLOT_API void SetCurrentContext(ImPlotContext* ctx);
@ -690,8 +690,8 @@ IMPLOT_API bool BeginSubplots(const char* title_id,
int cols, int cols,
const ImVec2& size, const ImVec2& size,
ImPlotSubplotFlags flags = 0, ImPlotSubplotFlags flags = 0,
float* row_ratios = NULL, float* row_ratios = nullptr,
float* col_ratios = NULL); float* col_ratios = nullptr);
// Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end // Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end
// of an if statement conditioned on BeginSublots(). See example above. // of an if statement conditioned on BeginSublots(). See example above.
@ -726,24 +726,24 @@ IMPLOT_API void EndSubplots();
// call it yourself, then the first subsequent plotting or utility function will // call it yourself, then the first subsequent plotting or utility function will
// call it for you. // call it for you.
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = NULL for no label. // Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label.
IMPLOT_API void SetupAxis(ImAxis axis, const char* label=NULL, ImPlotAxisFlags flags=0); IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0);
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. // Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot. // Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot.
IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max); IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);
// Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f). // Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f).
IMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt); IMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt);
// Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data. // Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data.
IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=NULL); IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=nullptr);
// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true. // Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true.
IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=NULL, bool keep_default=false); IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);
// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true. // Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.
IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=NULL, bool keep_default=false); IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);
// Sets an axis' scale using built-in options. // Sets an axis' scale using built-in options.
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale); IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale);
// Sets an axis' scale using user supplied forward and inverse transfroms. // Sets an axis' scale using user supplied forward and inverse transfroms.
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=NULL); IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=nullptr);
// Sets an axis' limits constraints. // Sets an axis' limits constraints.
IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max); IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max);
// Sets an axis' zoom constraints. // Sets an axis' zoom constraints.
@ -788,7 +788,7 @@ IMPLOT_API void SetupFinish();
// Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. // Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
IMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); IMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an upcoming axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot! // Links an upcoming axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot!
IMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max); IMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max);
// Set an upcoming axis to auto fit to its data. // Set an upcoming axis to auto fit to its data.
IMPLOT_API void SetNextAxisToFit(ImAxis axis); IMPLOT_API void SetNextAxisToFit(ImAxis axis);
@ -890,10 +890,10 @@ IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int co
// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes). // Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).
IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to NULL for no labels. // Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0); IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0);
// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to NULL for no labels. // Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels.
IMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0); IMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0);
// Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range. // Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range.
@ -1077,13 +1077,13 @@ IMPLOT_API void EndDragDropSource();
IMPLOT_API ImPlotStyle& GetStyle(); IMPLOT_API ImPlotStyle& GetStyle();
// Style plot colors for current ImGui style (default). // Style plot colors for current ImGui style (default).
IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = nullptr);
// Style plot colors for ImGui "Classic". // Style plot colors for ImGui "Classic".
IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = nullptr);
// Style plot colors for ImGui "Dark". // Style plot colors for ImGui "Dark".
IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = nullptr);
// Style plot colors for ImGui "Light". // Style plot colors for ImGui "Light".
IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = NULL); IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = nullptr);
// Use PushStyleX to temporarily modify your ImPlotStyle. The modification // Use PushStyleX to temporarily modify your ImPlotStyle. The modification
// will last until the matching call to PopStyleX. You MUST call a pop for // will last until the matching call to PopStyleX. You MUST call a pop for
@ -1150,7 +1150,7 @@ IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int
// Returns the number of available colormaps (i.e. the built-in + user-added count). // Returns the number of available colormaps (i.e. the built-in + user-added count).
IMPLOT_API int GetColormapCount(); IMPLOT_API int GetColormapCount();
// Returns a null terminated string name for a colormap given an index. Returns NULL if index is invalid. // Returns a null terminated string name for a colormap given an index. Returns nullptr if index is invalid.
IMPLOT_API const char* GetColormapName(ImPlotColormap cmap); IMPLOT_API const char* GetColormapName(ImPlotColormap cmap);
// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid. // Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid.
IMPLOT_API ImPlotColormap GetColormapIndex(const char* name); IMPLOT_API ImPlotColormap GetColormapIndex(const char* name);
@ -1179,18 +1179,18 @@ IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed. // Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed.
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1]. // Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = NULL, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = nullptr, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
// Shows a button with a colormap gradient brackground. // Shows a button with a colormap gradient brackground.
IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO); IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);
// When items in a plot sample their color from a colormap, the color is cached and does not change // When items in a plot sample their color from a colormap, the color is cached and does not change
// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted, // unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted,
// item colors will NOT update. If you need item colors to resample the new colormap, then use this // item colors will NOT update. If you need item colors to resample the new colormap, then use this
// function to bust the cached colors. If #plot_title_id is NULL, then every item in EVERY existing plot // function to bust the cached colors. If #plot_title_id is nullptr, then every item in EVERY existing plot
// will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the // will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the
// latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever // latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever
// need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo). // need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo).
IMPLOT_API void BustColorCache(const char* plot_title_id = NULL); IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Input Mapping // [SECTION] Input Mapping
@ -1200,9 +1200,9 @@ IMPLOT_API void BustColorCache(const char* plot_title_id = NULL);
IMPLOT_API ImPlotInputMap& GetInputMap(); IMPLOT_API ImPlotInputMap& GetInputMap();
// Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. // Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = NULL); IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = nullptr);
// Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll. // Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = NULL); IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = nullptr);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Miscellaneous // [SECTION] Miscellaneous
@ -1227,18 +1227,18 @@ IMPLOT_API bool ShowColormapSelector(const char* label);
// Shows ImPlot input map selector dropdown menu. // Shows ImPlot input map selector dropdown menu.
IMPLOT_API bool ShowInputMapSelector(const char* label); IMPLOT_API bool ShowInputMapSelector(const char* label);
// Shows ImPlot style editor block (not a window). // Shows ImPlot style editor block (not a window).
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL); IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = nullptr);
// Add basic help/info block for end users (not a window). // Add basic help/info block for end users (not a window).
IMPLOT_API void ShowUserGuide(); IMPLOT_API void ShowUserGuide();
// Shows ImPlot metrics/debug information window. // Shows ImPlot metrics/debug information window.
IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL); IMPLOT_API void ShowMetricsWindow(bool* p_popen = nullptr);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Demo // [SECTION] Demo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Shows the ImPlot demo window (add implot_demo.cpp to your sources!) // Shows the ImPlot demo window (add implot_demo.cpp to your sources!)
IMPLOT_API void ShowDemoWindow(bool* p_open = NULL); IMPLOT_API void ShowDemoWindow(bool* p_open = nullptr);
} // namespace ImPlot } // namespace ImPlot
@ -1276,16 +1276,16 @@ namespace ImPlot {
// OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0 // OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0
IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id, IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id,
const char* x_label, // = NULL, const char* x_label, // = nullptr,
const char* y_label, // = NULL, const char* y_label, // = nullptr,
const ImVec2& size = ImVec2(-1,0), const ImVec2& size = ImVec2(-1,0),
ImPlotFlags flags = ImPlotFlags_None, ImPlotFlags flags = ImPlotFlags_None,
ImPlotAxisFlags x_flags = 0, ImPlotAxisFlags x_flags = 0,
ImPlotAxisFlags y_flags = 0, ImPlotAxisFlags y_flags = 0,
ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault, ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault,
ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault, ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault,
const char* y2_label = NULL, const char* y2_label = nullptr,
const char* y3_label = NULL) ); const char* y3_label = nullptr) );
} // namespace ImPlot } // namespace ImPlot

View File

@ -232,11 +232,11 @@ void ModSelector(const char* label, int* k) {
void InputMapping(const char* label, ImGuiMouseButton* b, int* k) { void InputMapping(const char* label, ImGuiMouseButton* b, int* k) {
ImGui::LabelText("##","%s",label); ImGui::LabelText("##","%s",label);
if (b != NULL) { if (b != nullptr) {
ImGui::SameLine(100); ImGui::SameLine(100);
ButtonSelector(label,b); ButtonSelector(label,b);
} }
if (k != NULL) { if (k != nullptr) {
ImGui::SameLine(300); ImGui::SameLine(300);
ModSelector(label,k); ModSelector(label,k);
} }
@ -245,14 +245,14 @@ void InputMapping(const char* label, ImGuiMouseButton* b, int* k) {
void ShowInputMapping() { void ShowInputMapping() {
ImPlotInputMap& map = ImPlot::GetInputMap(); ImPlotInputMap& map = ImPlot::GetInputMap();
InputMapping("Pan",&map.Pan,&map.PanMod); InputMapping("Pan",&map.Pan,&map.PanMod);
InputMapping("Fit",&map.Fit,NULL); InputMapping("Fit",&map.Fit,nullptr);
InputMapping("Select",&map.Select,&map.SelectMod); InputMapping("Select",&map.Select,&map.SelectMod);
InputMapping("SelectHorzMod",NULL,&map.SelectHorzMod); InputMapping("SelectHorzMod",nullptr,&map.SelectHorzMod);
InputMapping("SelectVertMod",NULL,&map.SelectVertMod); InputMapping("SelectVertMod",nullptr,&map.SelectVertMod);
InputMapping("SelectCancel",&map.SelectCancel,NULL); InputMapping("SelectCancel",&map.SelectCancel,nullptr);
InputMapping("Menu",&map.Menu,NULL); InputMapping("Menu",&map.Menu,nullptr);
InputMapping("OverrideMod",NULL,&map.OverrideMod); InputMapping("OverrideMod",nullptr,&map.OverrideMod);
InputMapping("ZoomMod",NULL,&map.ZoomMod); InputMapping("ZoomMod",nullptr,&map.ZoomMod);
ImGui::SliderFloat("ZoomRate",&map.ZoomRate,-1,1); ImGui::SliderFloat("ZoomRate",&map.ZoomRate,-1,1);
} }
@ -268,7 +268,7 @@ void Demo_Config() {
ImGui::Checkbox("Use 24 Hour Clock", &ImPlot::GetStyle().Use24HourClock); ImGui::Checkbox("Use 24 Hour Clock", &ImPlot::GetStyle().Use24HourClock);
ImGui::Separator(); ImGui::Separator();
if (ImPlot::BeginPlot("Preview")) { if (ImPlot::BeginPlot("Preview")) {
static double now = (double)time(0); static double now = (double)time(nullptr);
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time); ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxisLimits(ImAxis_X1, now, now + 24*3600); ImPlot::SetupAxisLimits(ImAxis_X1, now, now + 24*3600);
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
@ -530,7 +530,7 @@ void Demo_BarStacks() {
ImPlot::PushColormap(Liars); ImPlot::PushColormap(Liars);
if (ImPlot::BeginPlot("PolitiFact: Who Lies More?",ImVec2(-1,400),ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("PolitiFact: Who Lies More?",ImVec2(-1,400),ImPlotFlags_NoMouseText)) {
ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Outside|ImPlotLegendFlags_Horizontal); ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Outside|ImPlotLegendFlags_Horizontal);
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Invert); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Invert);
ImPlot::SetupAxisTicks(ImAxis_Y1,0,19,20,politicians,false); ImPlot::SetupAxisTicks(ImAxis_Y1,0,19,20,politicians,false);
if (diverging) if (diverging)
ImPlot::PlotBarGroups(labels_div,data_div,9,20,0.75,0,ImPlotBarGroupsFlags_Stacked|ImPlotBarGroupsFlags_Horizontal); ImPlot::PlotBarGroups(labels_div,data_div,9,20,0.75,0,ImPlotBarGroupsFlags_Stacked|ImPlotBarGroupsFlags_Horizontal);
@ -595,7 +595,7 @@ void Demo_StemPlots() {
void Demo_InfiniteLines() { void Demo_InfiniteLines() {
static double vals[] = {0.25, 0.5, 0.75}; static double vals[] = {0.25, 0.5, 0.75};
if (ImPlot::BeginPlot("##Infinite")) { if (ImPlot::BeginPlot("##Infinite")) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoInitialFit,ImPlotAxisFlags_NoInitialFit); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoInitialFit,ImPlotAxisFlags_NoInitialFit);
ImPlot::PlotInfLines("Vertical",vals,3); ImPlot::PlotInfLines("Vertical",vals,3);
ImPlot::PlotInfLines("Horizontal",vals,3,ImPlotInfLinesFlags_Horizontal); ImPlot::PlotInfLines("Horizontal",vals,3,ImPlotInfLinesFlags_Horizontal);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -616,7 +616,7 @@ void Demo_PieCharts() {
} }
if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, 1, 0, 1); ImPlot::SetupAxesLimits(0, 1, 0, 1);
ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, "%.2f", 90, flags); ImPlot::PlotPieChart(labels1, data1, 4, 0.5, 0.5, 0.4, "%.2f", 90, flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -629,7 +629,7 @@ void Demo_PieCharts() {
ImPlot::PushColormap(ImPlotColormap_Pastel); ImPlot::PushColormap(ImPlotColormap_Pastel);
if (ImPlot::BeginPlot("##Pie2", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Pie2", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, 1, 0, 1); ImPlot::SetupAxesLimits(0, 1, 0, 1);
ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, "%.0f", 180, flags); ImPlot::PlotPieChart(labels2, data2, 5, 0.5, 0.5, 0.4, "%.0f", 180, flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -676,7 +676,7 @@ void Demo_Heatmaps() {
ImPlot::PushColormap(map); ImPlot::PushColormap(map);
if (ImPlot::BeginPlot("##Heatmap1",ImVec2(225,225),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Heatmap1",ImVec2(225,225),ImPlotFlags_NoLegend|ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(NULL, NULL, axes_flags, axes_flags); ImPlot::SetupAxes(nullptr, nullptr, axes_flags, axes_flags);
ImPlot::SetupAxisTicks(ImAxis_X1,0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels); ImPlot::SetupAxisTicks(ImAxis_X1,0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels);
ImPlot::SetupAxisTicks(ImAxis_Y1,1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels); ImPlot::SetupAxisTicks(ImAxis_Y1,1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels);
ImPlot::PlotHeatmap("heat",values1[0],7,7,scale_min,scale_max,"%g",ImPlotPoint(0,0),ImPlotPoint(1,1),hm_flags); ImPlot::PlotHeatmap("heat",values1[0],7,7,scale_min,scale_max,"%g",ImPlotPoint(0,0),ImPlotPoint(1,1),hm_flags);
@ -694,10 +694,10 @@ void Demo_Heatmaps() {
values2[i] = RandomRange(0.0,1.0); values2[i] = RandomRange(0.0,1.0);
if (ImPlot::BeginPlot("##Heatmap2",ImVec2(225,225))) { if (ImPlot::BeginPlot("##Heatmap2",ImVec2(225,225))) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(-1,1,-1,1); ImPlot::SetupAxesLimits(-1,1,-1,1);
ImPlot::PlotHeatmap("heat1",values2,size,size,0,1,NULL); ImPlot::PlotHeatmap("heat1",values2,size,size,0,1,nullptr);
ImPlot::PlotHeatmap("heat2",values2,size,size,0,1,NULL, ImPlotPoint(-1,-1), ImPlotPoint(0,0)); ImPlot::PlotHeatmap("heat2",values2,size,size,0,1,nullptr, ImPlotPoint(-1,-1), ImPlotPoint(0,0));
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImPlot::PopColormap(); ImPlot::PopColormap();
@ -756,7 +756,7 @@ void Demo_Histogram() {
} }
if (ImPlot::BeginPlot("##Histograms")) { if (ImPlot::BeginPlot("##Histograms")) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_AutoFit,ImPlotAxisFlags_AutoFit);
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f); ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f);
ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, 1.0, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), hist_flags); ImPlot::PlotHistogram("Empirical", dist.Data, 10000, bins, 1.0, range ? ImPlotRange(rmin,rmax) : ImPlotRange(), hist_flags);
if ((hist_flags & ImPlotHistogramFlags_Density) && !(hist_flags & ImPlotHistogramFlags_NoOutliers)) { if ((hist_flags & ImPlotHistogramFlags_Density) && !(hist_flags & ImPlotHistogramFlags_NoOutliers)) {
@ -788,7 +788,7 @@ void Demo_Histogram2D() {
ImPlotAxisFlags flags = ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Foreground; ImPlotAxisFlags flags = ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_Foreground;
ImPlot::PushColormap("Hot"); ImPlot::PushColormap("Hot");
if (ImPlot::BeginPlot("##Hist2D",ImVec2(ImGui::GetContentRegionAvail().x-100-ImGui::GetStyle().ItemSpacing.x,0))) { if (ImPlot::BeginPlot("##Hist2D",ImVec2(ImGui::GetContentRegionAvail().x-100-ImGui::GetStyle().ItemSpacing.x,0))) {
ImPlot::SetupAxes(NULL, NULL, flags, flags); ImPlot::SetupAxes(nullptr, nullptr, flags, flags);
ImPlot::SetupAxesLimits(-6,6,-6,6); ImPlot::SetupAxesLimits(-6,6,-6,6);
max_count = ImPlot::PlotHistogram2D("Hist2D",dist1.Data,dist2.Data,count,xybins[0],xybins[1],ImPlotRect(-6,6,-6,6), hist_flags); max_count = ImPlot::PlotHistogram2D("Hist2D",dist1.Data,dist2.Data,count,xybins[0],xybins[1],ImPlotRect(-6,6,-6,6), hist_flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
@ -897,7 +897,7 @@ void Demo_RealtimePlots() {
static ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels; static ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels;
if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1,150))) { if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1,150))) {
ImPlot::SetupAxes(NULL, NULL, flags, flags); ImPlot::SetupAxes(nullptr, nullptr, flags, flags);
ImPlot::SetupAxisLimits(ImAxis_X1,t - history, t, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_X1,t - history, t, ImGuiCond_Always);
ImPlot::SetupAxisLimits(ImAxis_Y1,0,1); ImPlot::SetupAxisLimits(ImAxis_Y1,0,1);
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f); ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL,0.5f);
@ -906,7 +906,7 @@ void Demo_RealtimePlots() {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImPlot::BeginPlot("##Rolling", ImVec2(-1,150))) { if (ImPlot::BeginPlot("##Rolling", ImVec2(-1,150))) {
ImPlot::SetupAxes(NULL, NULL, flags, flags); ImPlot::SetupAxes(nullptr, nullptr, flags, flags);
ImPlot::SetupAxisLimits(ImAxis_X1,0,history, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_X1,0,history, ImGuiCond_Always);
ImPlot::SetupAxisLimits(ImAxis_Y1,0,1); ImPlot::SetupAxisLimits(ImAxis_Y1,0,1);
ImPlot::PlotLine("Mouse X", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 0, 2 * sizeof(float)); ImPlot::PlotLine("Mouse X", &rdata1.Data[0].x, &rdata1.Data[0].y, rdata1.Data.size(), 0, 0, 2 * sizeof(float));
@ -925,7 +925,7 @@ void Demo_MarkersAndText() {
if (ImPlot::BeginPlot("##MarkerStyles", ImVec2(-1,0), ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##MarkerStyles", ImVec2(-1,0), ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(NULL, NULL, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, 10, 0, 12); ImPlot::SetupAxesLimits(0, 10, 0, 12);
ImS8 xs[2] = {1,4}; ImS8 xs[2] = {1,4};
@ -1040,8 +1040,8 @@ void Demo_TimeScale() {
ImGui::SameLine(); ImGui::SameLine();
ImGui::Checkbox("24 Hour Clock",&ImPlot::GetStyle().Use24HourClock); ImGui::Checkbox("24 Hour Clock",&ImPlot::GetStyle().Use24HourClock);
static HugeTimeData* data = NULL; static HugeTimeData* data = nullptr;
if (data == NULL) { if (data == nullptr) {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Generate Huge Data (~500MB!)")) { if (ImGui::Button("Generate Huge Data (~500MB!)")) {
static HugeTimeData sdata(t_min); static HugeTimeData sdata(t_min);
@ -1052,7 +1052,7 @@ void Demo_TimeScale() {
if (ImPlot::BeginPlot("##Time", ImVec2(-1,0))) { if (ImPlot::BeginPlot("##Time", ImVec2(-1,0))) {
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time); ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxesLimits(t_min,t_max,0,1); ImPlot::SetupAxesLimits(t_min,t_max,0,1);
if (data != NULL) { if (data != nullptr) {
// downsample our data // downsample our data
int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1; int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1;
int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min); int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min);
@ -1064,7 +1064,7 @@ void Demo_TimeScale() {
ImPlot::PlotLine("Time Series", &data->Ts[start], &data->Ys[start], size, 0, 0, sizeof(double)*downsample); ImPlot::PlotLine("Time Series", &data->Ts[start], &data->Ys[start], size, 0, 0, sizeof(double)*downsample);
} }
// plot time now // plot time now
double t_now = (double)time(0); double t_now = (double)time(nullptr);
double y_now = HugeTimeData::GetY(t_now); double y_now = HugeTimeData::GetY(t_now);
ImPlot::PlotScatter("Now",&t_now,&y_now,1); ImPlot::PlotScatter("Now",&t_now,&y_now,1);
ImPlot::Annotation(t_now,y_now,ImPlot::GetLastItemColor(),ImVec2(10,10),false,"Now"); ImPlot::Annotation(t_now,y_now,ImPlot::GetLastItemColor(),ImVec2(10,10),false,"Now");
@ -1169,14 +1169,14 @@ void Demo_LinkedAxes() {
if (BeginAlignedPlots("AlignedGroup")) { if (BeginAlignedPlots("AlignedGroup")) {
if (ImPlot::BeginPlot("Plot A")) { if (ImPlot::BeginPlot("Plot A")) {
ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : NULL, linkx ? &lims.X.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : nullptr, linkx ? &lims.X.Max : nullptr);
ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : NULL, linky ? &lims.Y.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : nullptr, linky ? &lims.Y.Max : nullptr);
ImPlot::PlotLine("Line",data,2); ImPlot::PlotLine("Line",data,2);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImPlot::BeginPlot("Plot B")) { if (ImPlot::BeginPlot("Plot B")) {
ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : NULL, linkx ? &lims.X.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_X1, linkx ? &lims.X.Min : nullptr, linkx ? &lims.X.Max : nullptr);
ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : NULL, linky ? &lims.Y.Max : NULL); ImPlot::SetupAxisLinks(ImAxis_Y1, linky ? &lims.Y.Min : nullptr, linky ? &lims.Y.Max : nullptr);
ImPlot::PlotLine("Line",data,2); ImPlot::PlotLine("Line",data,2);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -1215,8 +1215,8 @@ void Demo_EqualAxes() {
float xs2[] = {-1,0,1,0,-1}; float xs2[] = {-1,0,1,0,-1};
float ys2[] = {0,1,0,-1,0}; float ys2[] = {0,1,0,-1,0};
if (ImPlot::BeginPlot("##EqualAxes",ImVec2(-1,0),ImPlotFlags_Equal)) { if (ImPlot::BeginPlot("##EqualAxes",ImVec2(-1,0),ImPlotFlags_Equal)) {
ImPlot::SetupAxis(ImAxis_X2, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_X2, nullptr, ImPlotAxisFlags_AuxDefault);
ImPlot::SetupAxis(ImAxis_Y2, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_Y2, nullptr, ImPlotAxisFlags_AuxDefault);
ImPlot::PlotLine("Circle",xs1,ys1,360); ImPlot::PlotLine("Circle",xs1,ys1,360);
ImPlot::SetAxes(ImAxis_X2, ImAxis_Y2); ImPlot::SetAxes(ImAxis_X2, ImAxis_Y2);
ImPlot::PlotLine("Diamond",xs2,ys2,5); ImPlot::PlotLine("Diamond",xs2,ys2,5);
@ -1274,12 +1274,12 @@ void Demo_SubplotsSizing() {
ImGui::SliderInt("Cols",&cols,1,5); ImGui::SliderInt("Cols",&cols,1,5);
static float rratios[] = {5,1,1,1,1,1}; static float rratios[] = {5,1,1,1,1,1};
static float cratios[] = {5,1,1,1,1,1}; static float cratios[] = {5,1,1,1,1,1};
ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,0); ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,nullptr);
ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,0); ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,nullptr);
if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) { if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) {
for (int i = 0; i < rows*cols; ++i) { for (int i = 0; i < rows*cols; ++i) {
if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) { if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
float fi = 0.01f * (i+1); float fi = 0.01f * (i+1);
ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet)); ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet));
ImPlot::PlotLineG("data",SinewaveGetter,&fi,1000); ImPlot::PlotLineG("data",SinewaveGetter,&fi,1000);
@ -1314,7 +1314,7 @@ void Demo_SubplotItemSharing() {
ImPlot::PlotLineG(label,SinewaveGetter,&fj,1000); ImPlot::PlotLineG(label,SinewaveGetter,&fj,1000);
if (ImPlot::BeginDragDropSourceItem(label)) { if (ImPlot::BeginDragDropSourceItem(label)) {
curj = j; curj = j;
ImGui::SetDragDropPayload("MY_DND",NULL,0); ImGui::SetDragDropPayload("MY_DND",nullptr,0);
ImPlot::ItemIcon(GetLastItemColor()); ImGui::SameLine(); ImPlot::ItemIcon(GetLastItemColor()); ImGui::SameLine();
ImGui::TextUnformatted(label); ImGui::TextUnformatted(label);
ImPlot::EndDragDropSource(); ImPlot::EndDragDropSource();
@ -1404,7 +1404,7 @@ void Demo_DragPoints() {
ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs); ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);
ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks; ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks;
if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(0,0,ax_flags,ax_flags); ImPlot::SetupAxes(nullptr,nullptr,ax_flags,ax_flags);
ImPlot::SetupAxesLimits(0,1,0,1); ImPlot::SetupAxesLimits(0,1,0,1);
static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)}; static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)};
@ -1492,7 +1492,7 @@ void Demo_DragRects() {
ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs); ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);
if (ImPlot::BeginPlot("##Main",ImVec2(-1,150))) { if (ImPlot::BeginPlot("##Main",ImVec2(-1,150))) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoTickLabels,ImPlotAxisFlags_NoTickLabels); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoTickLabels,ImPlotAxisFlags_NoTickLabels);
ImPlot::SetupAxesLimits(0,0.01,-1,1); ImPlot::SetupAxesLimits(0,0.01,-1,1);
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
@ -1501,7 +1501,7 @@ void Demo_DragRects() {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(NULL,NULL,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always); ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always);
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
@ -1678,15 +1678,15 @@ void Demo_DragAndDrop() {
const int k_dnd = 20; const int k_dnd = 20;
static MyDndItem dnd[k_dnd]; static MyDndItem dnd[k_dnd];
static MyDndItem* dndx = NULL; // for plot 2 static MyDndItem* dndx = nullptr; // for plot 2
static MyDndItem* dndy = NULL; // for plot 2 static MyDndItem* dndy = nullptr; // for plot 2
// child window to serve as initial source for our DND items // child window to serve as initial source for our DND items
ImGui::BeginChild("DND_LEFT",ImVec2(100,400)); ImGui::BeginChild("DND_LEFT",ImVec2(100,400));
if (ImGui::Button("Reset Data")) { if (ImGui::Button("Reset Data")) {
for (int k = 0; k < k_dnd; ++k) for (int k = 0; k < k_dnd; ++k)
dnd[k].Reset(); dnd[k].Reset();
dndx = dndy = NULL; dndx = dndy = nullptr;
} }
for (int k = 0; k < k_dnd; ++k) { for (int k = 0; k < k_dnd; ++k) {
if (dnd[k].Plt > 0) if (dnd[k].Plt > 0)
@ -1713,7 +1713,7 @@ void Demo_DragAndDrop() {
// plot 1 (time series) // plot 1 (time series)
ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight; ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoHighlight;
if (ImPlot::BeginPlot("##DND1", ImVec2(-1,195))) { if (ImPlot::BeginPlot("##DND1", ImVec2(-1,195))) {
ImPlot::SetupAxis(ImAxis_X1, NULL, flags|ImPlotAxisFlags_Lock); ImPlot::SetupAxis(ImAxis_X1, nullptr, flags|ImPlotAxisFlags_Lock);
ImPlot::SetupAxis(ImAxis_Y1, "[drop here]", flags); ImPlot::SetupAxis(ImAxis_Y1, "[drop here]", flags);
ImPlot::SetupAxis(ImAxis_Y2, "[drop here]", flags|ImPlotAxisFlags_Opposite); ImPlot::SetupAxis(ImAxis_Y2, "[drop here]", flags|ImPlotAxisFlags_Opposite);
ImPlot::SetupAxis(ImAxis_Y3, "[drop here]", flags|ImPlotAxisFlags_Opposite); ImPlot::SetupAxis(ImAxis_Y3, "[drop here]", flags|ImPlotAxisFlags_Opposite);
@ -1759,12 +1759,12 @@ void Demo_DragAndDrop() {
} }
// plot 2 (Lissajous) // plot 2 (Lissajous)
if (ImPlot::BeginPlot("##DND2", ImVec2(-1,195))) { if (ImPlot::BeginPlot("##DND2", ImVec2(-1,195))) {
ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndx != NULL ? dndx->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]); ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndx != nullptr ? dndx->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]);
ImPlot::SetupAxis(ImAxis_X1, dndx == NULL ? "[drop here]" : dndx->Label, flags); ImPlot::SetupAxis(ImAxis_X1, dndx == nullptr ? "[drop here]" : dndx->Label, flags);
ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndy != NULL ? dndy->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]); ImPlot::PushStyleColor(ImPlotCol_AxisBg, dndy != nullptr ? dndy->Color : ImPlot::GetStyle().Colors[ImPlotCol_AxisBg]);
ImPlot::SetupAxis(ImAxis_Y1, dndy == NULL ? "[drop here]" : dndy->Label, flags); ImPlot::SetupAxis(ImAxis_Y1, dndy == nullptr ? "[drop here]" : dndy->Label, flags);
ImPlot::PopStyleColor(2); ImPlot::PopStyleColor(2);
if (dndx != NULL && dndy != NULL) { if (dndx != nullptr && dndy != nullptr) {
ImVec4 mixed((dndx->Color.x + dndy->Color.x)/2,(dndx->Color.y + dndy->Color.y)/2,(dndx->Color.z + dndy->Color.z)/2,(dndx->Color.w + dndy->Color.w)/2); ImVec4 mixed((dndx->Color.x + dndy->Color.x)/2,(dndx->Color.y + dndy->Color.y)/2,(dndx->Color.z + dndy->Color.z)/2,(dndx->Color.w + dndy->Color.w)/2);
ImPlot::SetNextLineStyle(mixed); ImPlot::SetNextLineStyle(mixed);
ImPlot::PlotLine("##dndxy", &dndx->Data[0].y, &dndy->Data[0].y, dndx->Data.size(), 0, 0, 2 * sizeof(float)); ImPlot::PlotLine("##dndxy", &dndx->Data[0].y, &dndy->Data[0].y, dndx->Data.size(), 0, 0, 2 * sizeof(float));
@ -1777,7 +1777,7 @@ void Demo_DragAndDrop() {
ImPlot::EndDragDropTarget(); ImPlot::EndDragDropTarget();
} }
// allow the x-axis to be a DND source // allow the x-axis to be a DND source
if (dndx != NULL && ImPlot::BeginDragDropSourceAxis(ImAxis_X1)) { if (dndx != nullptr && ImPlot::BeginDragDropSourceAxis(ImAxis_X1)) {
ImGui::SetDragDropPayload("MY_DND", &dndx->Idx, sizeof(int)); ImGui::SetDragDropPayload("MY_DND", &dndx->Idx, sizeof(int));
ImPlot::ItemIcon(dndx->Color); ImGui::SameLine(); ImPlot::ItemIcon(dndx->Color); ImGui::SameLine();
ImGui::TextUnformatted(dndx->Label); ImGui::TextUnformatted(dndx->Label);
@ -1791,7 +1791,7 @@ void Demo_DragAndDrop() {
ImPlot::EndDragDropTarget(); ImPlot::EndDragDropTarget();
} }
// allow the y-axis to be a DND source // allow the y-axis to be a DND source
if (dndy != NULL && ImPlot::BeginDragDropSourceAxis(ImAxis_Y1)) { if (dndy != nullptr && ImPlot::BeginDragDropSourceAxis(ImAxis_Y1)) {
ImGui::SetDragDropPayload("MY_DND", &dndy->Idx, sizeof(int)); ImGui::SetDragDropPayload("MY_DND", &dndy->Idx, sizeof(int));
ImPlot::ItemIcon(dndy->Color); ImGui::SameLine(); ImPlot::ItemIcon(dndy->Color); ImGui::SameLine();
ImGui::TextUnformatted(dndy->Label); ImGui::TextUnformatted(dndy->Label);
@ -1907,7 +1907,7 @@ void Demo_CustomDataAndGetters() {
ImPlot::PlotLine("Vector2f", &vec2_data[0].x, &vec2_data[0].y, 2, 0, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */); ImPlot::PlotLine("Vector2f", &vec2_data[0].x, &vec2_data[0].y, 2, 0, 0, sizeof(MyImPlot::Vector2f) /* or sizeof(float) * 2 */);
// custom getter example 1: // custom getter example 1:
ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, NULL, 1000); ImPlot::PlotLineG("Spiral", MyImPlot::Spiral, nullptr, 1000);
// custom getter example 2: // custom getter example 2:
static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75); static MyImPlot::WaveData data1(0.001, 0.2, 2, 0.75);
@ -1962,8 +1962,8 @@ void Demo_TickLabels() {
static const char* ylabels_aux[] = {"A","B","C","D","E","F"}; static const char* ylabels_aux[] = {"A","B","C","D","E","F"};
if (ImPlot::BeginPlot("##Ticks")) { if (ImPlot::BeginPlot("##Ticks")) {
ImPlot::SetupAxesLimits(2.5,5,0,1000); ImPlot::SetupAxesLimits(2.5,5,0,1000);
ImPlot::SetupAxis(ImAxis_Y2, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_Y2, nullptr, ImPlotAxisFlags_AuxDefault);
ImPlot::SetupAxis(ImAxis_Y3, NULL, ImPlotAxisFlags_AuxDefault); ImPlot::SetupAxis(ImAxis_Y3, nullptr, ImPlotAxisFlags_AuxDefault);
if (custom_fmt) { if (custom_fmt) {
ImPlot::SetupAxisFormat(ImAxis_X1, "%g ms"); ImPlot::SetupAxisFormat(ImAxis_X1, "%g ms");
ImPlot::SetupAxisFormat(ImAxis_Y1, MetricFormatter, (void*)"Hz"); ImPlot::SetupAxisFormat(ImAxis_Y1, MetricFormatter, (void*)"Hz");
@ -1971,10 +1971,10 @@ void Demo_TickLabels() {
ImPlot::SetupAxisFormat(ImAxis_Y3, MetricFormatter, (void*)"m"); ImPlot::SetupAxisFormat(ImAxis_Y3, MetricFormatter, (void*)"m");
} }
if (custom_ticks) { if (custom_ticks) {
ImPlot::SetupAxisTicks(ImAxis_X1, &pi,1,custom_labels ? pi_str : NULL, true); ImPlot::SetupAxisTicks(ImAxis_X1, &pi,1,custom_labels ? pi_str : nullptr, true);
ImPlot::SetupAxisTicks(ImAxis_Y1, yticks, 4, custom_labels ? ylabels : NULL, false); ImPlot::SetupAxisTicks(ImAxis_Y1, yticks, 4, custom_labels ? ylabels : nullptr, false);
ImPlot::SetupAxisTicks(ImAxis_Y2, yticks_aux, 3, custom_labels ? ylabels_aux : NULL, false); ImPlot::SetupAxisTicks(ImAxis_Y2, yticks_aux, 3, custom_labels ? ylabels_aux : nullptr, false);
ImPlot::SetupAxisTicks(ImAxis_Y3, 0, 1, 6, custom_labels ? ylabels_aux : NULL, false); ImPlot::SetupAxisTicks(ImAxis_Y3, 0, 1, 6, custom_labels ? ylabels_aux : nullptr, false);
} }
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
@ -2116,7 +2116,7 @@ void Demo_CustomPlottersAndTooltips() {
ImPlot::GetStyle().UseLocalTime = false; ImPlot::GetStyle().UseLocalTime = false;
if (ImPlot::BeginPlot("Candlestick Chart",ImVec2(-1,0))) { if (ImPlot::BeginPlot("Candlestick Chart",ImVec2(-1,0))) {
ImPlot::SetupAxes(NULL,NULL,0,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_RangeFit); ImPlot::SetupAxes(nullptr,nullptr,0,ImPlotAxisFlags_AutoFit|ImPlotAxisFlags_RangeFit);
ImPlot::SetupAxesLimits(1546300800, 1571961600, 1250, 1600); ImPlot::SetupAxesLimits(1546300800, 1571961600, 1250, 1600);
ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time); ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 1546300800, 1571961600); ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, 1546300800, 1571961600);
@ -2170,12 +2170,12 @@ void ShowDemoWindow(bool* p_open) {
ImGui::Begin("ImPlot Demo", p_open, ImGuiWindowFlags_MenuBar); ImGui::Begin("ImPlot Demo", p_open, ImGuiWindowFlags_MenuBar);
if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("Tools")) { if (ImGui::BeginMenu("Tools")) {
ImGui::MenuItem("Metrics", NULL, &show_implot_metrics); ImGui::MenuItem("Metrics", nullptr, &show_implot_metrics);
ImGui::MenuItem("Style Editor", NULL, &show_implot_style_editor); ImGui::MenuItem("Style Editor", nullptr, &show_implot_style_editor);
ImGui::Separator(); ImGui::Separator();
ImGui::MenuItem("ImGui Metrics", NULL, &show_imgui_metrics); ImGui::MenuItem("ImGui Metrics", nullptr, &show_imgui_metrics);
ImGui::MenuItem("ImGui Style Editor", NULL, &show_imgui_style_editor); ImGui::MenuItem("ImGui Style Editor", nullptr, &show_imgui_style_editor);
ImGui::MenuItem("ImGui Demo", NULL, &show_imgui_demo); ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::EndMenuBar(); ImGui::EndMenuBar();
@ -2300,7 +2300,7 @@ ImPlotPoint Spiral(int idx, void*) {
void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) { void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) {
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0)); ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0));
if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) { if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) {
ImPlot::SetupAxes(0,0,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always); ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always);
ImPlot::SetNextLineStyle(col); ImPlot::SetNextLineStyle(col);
ImPlot::SetNextFillStyle(col, 0.25); ImPlot::SetNextFillStyle(col, 0.25);

View File

@ -397,7 +397,7 @@ struct ImPlotColormapData {
} }
inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; } inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : NULL; } inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : nullptr; }
inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); } inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; } inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
@ -564,7 +564,7 @@ struct ImPlotTicker {
ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) { ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) {
ImPlotTick tick(value, major, level, show_label); ImPlotTick tick(value, major, level, show_label);
if (show_label && label != NULL) { if (show_label && label != nullptr) {
tick.TextOffset = TextBuffer.size(); tick.TextOffset = TextBuffer.size();
TextBuffer.append(label, label + strlen(label) + 1); TextBuffer.append(label, label + strlen(label) + 1);
tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset); tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
@ -574,7 +574,7 @@ struct ImPlotTicker {
ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) { ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) {
ImPlotTick tick(value, major, level, show_label); ImPlotTick tick(value, major, level, show_label);
if (show_label && formatter != NULL) { if (show_label && formatter != nullptr) {
char buff[IMPLOT_LABEL_MAX_SIZE]; char buff[IMPLOT_LABEL_MAX_SIZE];
tick.TextOffset = TextBuffer.size(); tick.TextOffset = TextBuffer.size();
formatter(tick.PlotPos, buff, sizeof(buff), data); formatter(tick.PlotPos, buff, sizeof(buff), data);
@ -673,23 +673,23 @@ struct ImPlotAxis
Range.Min = 0; Range.Min = 0;
Range.Max = 1; Range.Max = 1;
Scale = ImPlotScale_Linear; Scale = ImPlotScale_Linear;
TransformForward = TransformInverse = NULL; TransformForward = TransformInverse = nullptr;
TransformData = NULL; TransformData = nullptr;
FitExtents.Min = HUGE_VAL; FitExtents.Min = HUGE_VAL;
FitExtents.Max = -HUGE_VAL; FitExtents.Max = -HUGE_VAL;
OrthoAxis = NULL; OrthoAxis = nullptr;
ConstraintRange = ImPlotRange(-INFINITY,INFINITY); ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY); ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
LinkedMin = LinkedMax = NULL; LinkedMin = LinkedMax = nullptr;
PickerLevel = 0; PickerLevel = 0;
Datum1 = Datum2 = 0; Datum1 = Datum2 = 0;
PixelMin = PixelMax = 0; PixelMin = PixelMax = 0;
LabelOffset = -1; LabelOffset = -1;
ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0; ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
ColorHiLi = IM_COL32_BLACK_TRANS; ColorHiLi = IM_COL32_BLACK_TRANS;
Formatter = NULL; Formatter = nullptr;
FormatterData = NULL; FormatterData = nullptr;
Locator = NULL; Locator = nullptr;
Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false; Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;
ShowDefaultTicks = true; ShowDefaultTicks = true;
} }
@ -697,18 +697,18 @@ struct ImPlotAxis
inline void Reset() { inline void Reset() {
Enabled = false; Enabled = false;
Scale = ImPlotScale_Linear; Scale = ImPlotScale_Linear;
TransformForward = TransformInverse = NULL; TransformForward = TransformInverse = nullptr;
TransformData = NULL; TransformData = nullptr;
LabelOffset = -1; LabelOffset = -1;
HasFormatSpec = false; HasFormatSpec = false;
Formatter = NULL; Formatter = nullptr;
FormatterData = NULL; FormatterData = nullptr;
Locator = NULL; Locator = nullptr;
ShowDefaultTicks = true; ShowDefaultTicks = true;
FitThisFrame = false; FitThisFrame = false;
FitExtents.Min = HUGE_VAL; FitExtents.Min = HUGE_VAL;
FitExtents.Max = -HUGE_VAL; FitExtents.Max = -HUGE_VAL;
OrthoAxis = NULL; OrthoAxis = nullptr;
ConstraintRange = ImPlotRange(-INFINITY,INFINITY); ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY); ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
Ticker.Reset(); Ticker.Reset();
@ -806,7 +806,7 @@ struct ImPlotAxis
inline void UpdateTransformCache() { inline void UpdateTransformCache() {
ScaleToPixel = (PixelMax - PixelMin) / Range.Size(); ScaleToPixel = (PixelMax - PixelMin) / Range.Size();
if (TransformForward != NULL) { if (TransformForward != nullptr) {
ScaleMin = TransformForward(Range.Min, TransformData); ScaleMin = TransformForward(Range.Min, TransformData);
ScaleMax = TransformForward(Range.Max, TransformData); ScaleMax = TransformForward(Range.Max, TransformData);
} }
@ -817,7 +817,7 @@ struct ImPlotAxis
} }
inline float PlotToPixels(double plt) const { inline float PlotToPixels(double plt) const {
if (TransformForward != NULL) { if (TransformForward != nullptr) {
double s = TransformForward(plt, TransformData); double s = TransformForward(plt, TransformData);
double t = (s - ScaleMin) / (ScaleMax - ScaleMin); double t = (s - ScaleMin) / (ScaleMax - ScaleMin);
plt = Range.Min + Range.Size() * t; plt = Range.Min + Range.Size() * t;
@ -828,7 +828,7 @@ struct ImPlotAxis
inline double PixelsToPlot(float pix) const { inline double PixelsToPlot(float pix) const {
double plt = (pix - PixelMin) / ScaleToPixel + Range.Min; double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;
if (TransformInverse != NULL) { if (TransformInverse != nullptr) {
double t = (plt - Range.Min) / Range.Size(); double t = (plt - Range.Min) / Range.Size();
double s = t * (ScaleMax - ScaleMin) + ScaleMin; double s = t * (ScaleMax - ScaleMin) + ScaleMin;
plt = TransformInverse(s, TransformData); plt = TransformInverse(s, TransformData);
@ -1067,7 +1067,7 @@ struct ImPlotPlot
inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); } inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
inline void SetTitle(const char* title) { inline void SetTitle(const char* title) {
if (title && ImGui::FindRenderedTextEnd(title, NULL) != title) { if (title && ImGui::FindRenderedTextEnd(title, nullptr) != title) {
TitleOffset = TextBuffer.size(); TitleOffset = TextBuffer.size();
TextBuffer.append(title, title + strlen(title) + 1); TextBuffer.append(title, title + strlen(title) + 1);
} }
@ -1098,7 +1098,7 @@ struct ImPlotPlot
} }
inline void SetAxisLabel(ImPlotAxis& axis, const char* label) { inline void SetAxisLabel(ImPlotAxis& axis, const char* label) {
if (label && ImGui::FindRenderedTextEnd(label, NULL) != label) { if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label) {
axis.LabelOffset = TextBuffer.size(); axis.LabelOffset = TextBuffer.size();
TextBuffer.append(label, label + strlen(label) + 1); TextBuffer.append(label, label + strlen(label) + 1);
} }
@ -1162,7 +1162,7 @@ struct ImPlotNextPlotData
for (int i = 0; i < ImAxis_COUNT; ++i) { for (int i = 0; i < ImAxis_COUNT; ++i) {
HasRange[i] = false; HasRange[i] = false;
Fit[i] = false; Fit[i] = false;
LinkedMin[i] = LinkedMax[i] = NULL; LinkedMin[i] = LinkedMax[i] = nullptr;
} }
} }
@ -1288,9 +1288,10 @@ IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
// Lock Setup and call SetupFinish if necessary. // Lock Setup and call SetupFinish if necessary.
static inline void SetupLock() { static inline void SetupLock() {
if (!GImPlot->CurrentPlot->SetupLocked) ImPlotContext& gp = *GImPlot;
if (!gp.CurrentPlot->SetupLocked)
SetupFinish(); SetupFinish();
GImPlot->CurrentPlot->SetupLocked = true; gp.CurrentPlot->SetupLocked = true;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1326,7 +1327,7 @@ bool BeginItemEx(const char* label_id, const _Fitter& fitter, ImPlotItemFlags fl
IMPLOT_API void EndItem(); IMPLOT_API void EndItem();
// Register or get an existing item from the current plot. // Register or get an existing item from the current plot.
IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = NULL); IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr);
// Get a plot item from the current plot. // Get a plot item from the current plot.
IMPLOT_API ImPlotItem* GetItem(const char* label_id); IMPLOT_API ImPlotItem* GetItem(const char* label_id);
// Gets the current item. // Gets the current item.
@ -1438,7 +1439,7 @@ static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItem
// Returns true if a color is set to be automatically determined // Returns true if a color is set to be automatically determined
static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; } static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
// Returns true if a style color is set to be automaticaly determined // Returns true if a style color is set to be automatically determined
static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); } static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
// Returns the automatically deduced style color // Returns the automatically deduced style color
IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx); IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
@ -1448,9 +1449,9 @@ static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx)
static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); } static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
// Draws vertical text. The position is the bottom left of the text rect. // Draws vertical text. The position is the bottom left of the text rect.
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr);
// Draws multiline horizontal text centered. // Draws multiline horizontal text centered.
IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = NULL); IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr);
// Calculates the size of vertical text // Calculates the size of vertical text
static inline ImVec2 CalcTextSizeVertical(const char *text) { static inline ImVec2 CalcTextSizeVertical(const char *text) {
ImVec2 sz = ImGui::CalcTextSize(text); ImVec2 sz = ImGui::CalcTextSize(text);
@ -1589,7 +1590,7 @@ IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlo
// #level = 0 for day, 1 for month, 2 for year. Modified by user interaction. // #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
// #t will be set when a day is clicked and the function will return true. // #t will be set when a day is clicked and the function will return true.
// #t1 and #t2 are optional dates to highlight. // #t1 and #t2 are optional dates to highlight.
IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = NULL, const ImPlotTime* t2 = NULL); IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr);
// Shows a time picker widget block (hour/min/sec). // Shows a time picker widget block (hour/min/sec).
// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true. // #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t); IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);

View File

@ -285,15 +285,15 @@ ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool*
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
ImPlotItemGroup& Items = *gp.CurrentItems; ImPlotItemGroup& Items = *gp.CurrentItems;
ImGuiID id = Items.GetItemID(label_id); ImGuiID id = Items.GetItemID(label_id);
if (just_created != NULL) if (just_created != nullptr)
*just_created = Items.GetItem(id) == NULL; *just_created = Items.GetItem(id) == nullptr;
ImPlotItem* item = Items.GetOrAddItem(id); ImPlotItem* item = Items.GetOrAddItem(id);
if (item->SeenThisFrame) if (item->SeenThisFrame)
return item; return item;
item->SeenThisFrame = true; item->SeenThisFrame = true;
int idx = Items.GetItemIndex(item); int idx = Items.GetItemIndex(item);
item->ID = id; item->ID = id;
if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) { if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, nullptr) != label_id) {
Items.Legend.Indices.push_back(idx); Items.Legend.Indices.push_back(idx);
item->NameOffset = Items.Legend.Labels.size(); item->NameOffset = Items.Legend.Labels.size();
Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1); Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1);
@ -311,7 +311,7 @@ ImPlotItem* GetItem(const char* label_id) {
bool IsItemHidden(const char* label_id) { bool IsItemHidden(const char* label_id) {
ImPlotItem* item = GetItem(label_id); ImPlotItem* item = GetItem(label_id);
return item != NULL && !item->Show; return item != nullptr && !item->Show;
} }
ImPlotItem* GetCurrentItem() { ImPlotItem* GetCurrentItem() {
@ -368,17 +368,17 @@ void BustItemCache() {
void BustColorCache(const char* plot_title_id) { void BustColorCache(const char* plot_title_id) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
if (plot_title_id == NULL) { if (plot_title_id == nullptr) {
BustItemCache(); BustItemCache();
} }
else { else {
ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id); ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id);
ImPlotPlot* plot = gp.Plots.GetByKey(id); ImPlotPlot* plot = gp.Plots.GetByKey(id);
if (plot != NULL) if (plot != nullptr)
plot->Items.Reset(); plot->Items.Reset();
else { else {
ImPlotSubplot* subplot = gp.Subplots.GetByKey(id); ImPlotSubplot* subplot = gp.Subplots.GetByKey(id);
if (subplot != NULL) if (subplot != nullptr)
subplot->Items.Reset(); subplot->Items.Reset();
} }
} }
@ -394,7 +394,7 @@ static const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f;
// Begins a new item. Returns false if the item should not be plotted. // Begins a new item. Returns false if the item should not be plotted.
bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) { bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotX() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotX() needs to be called between BeginPlot() and EndPlot()!");
SetupLock(); SetupLock();
bool just_created; bool just_created;
ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created); ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created);
@ -422,7 +422,7 @@ bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_fr
// reset next item data // reset next item data
gp.NextItemData.Reset(); gp.NextItemData.Reset();
gp.PreviousItem = item; gp.PreviousItem = item;
gp.CurrentItem = NULL; gp.CurrentItem = nullptr;
return false; return false;
} }
else { else {
@ -481,7 +481,7 @@ void EndItem() {
gp.NextItemData.Reset(); gp.NextItemData.Reset();
// set current item // set current item
gp.PreviousItem = gp.CurrentItem; gp.PreviousItem = gp.CurrentItem;
gp.CurrentItem = NULL; gp.CurrentItem = nullptr;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -785,7 +785,7 @@ struct Transformer1 {
{ } { }
template <typename T> IMPLOT_INLINE float operator()(T p) const { template <typename T> IMPLOT_INLINE float operator()(T p) const {
if (TransformFwd != NULL) { if (TransformFwd != nullptr) {
double s = TransformFwd(p, TransformData); double s = TransformFwd(p, TransformData);
double t = (s - ScaMin) / (ScaMax - ScaMin); double t = (s - ScaMin) / (ScaMax - ScaMin);
p = PltMin + (PltMax - PltMin) * t; p = PltMin + (PltMax - PltMin) * t;
@ -1900,8 +1900,9 @@ void PlotBarGroups(const char* const label_ids[], const T* values, int item_coun
const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked); const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked);
if (stack) { if (stack) {
SetupLock(); SetupLock();
GImPlot->TempDouble1.resize(4*group_count); ImPlotContext& gp = *GImPlot;
double* temp = GImPlot->TempDouble1.Data; gp.TempDouble1.resize(4*group_count);
double* temp = gp.TempDouble1.Data;
double* neg = &temp[0]; double* neg = &temp[0];
double* pos = &temp[group_count]; double* pos = &temp[group_count];
double* curr_min = &temp[group_count*2]; double* curr_min = &temp[group_count*2];
@ -2172,7 +2173,7 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent
template <typename T> template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) { void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & draw_list = *GetPlotDrawList(); ImDrawList & draw_list = *GetPlotDrawList();
double sum = 0; double sum = 0;
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
@ -2200,7 +2201,7 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou
} }
a0 = a1; a0 = a1;
} }
if (fmt != NULL) { if (fmt != nullptr) {
a0 = angle0 * 2 * IM_PI / 360.0; a0 = angle0 * 2 * IM_PI / 360.0;
a1 = angle0 * 2 * IM_PI / 360.0; a1 = angle0 * 2 * IM_PI / 360.0;
char buffer[32]; char buffer[32];
@ -2254,7 +2255,8 @@ struct GetterHeatmapRowMaj {
rect.Pos = p; rect.Pos = p;
rect.HalfSize = HalfSize; rect.HalfSize = HalfSize;
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f); const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t); ImPlotContext& gp = *GImPlot;
rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);
return rect; return rect;
} }
const T* const Values; const T* const Values;
@ -2288,7 +2290,8 @@ struct GetterHeatmapColMaj {
rect.Pos = p; rect.Pos = p;
rect.HalfSize = HalfSize; rect.HalfSize = HalfSize;
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f); const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t); ImPlotContext& gp = *GImPlot;
rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);
return rect; return rect;
} }
const T* const Values; const T* const Values;
@ -2325,7 +2328,7 @@ void RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, d
RenderPrimitives1<RendererRectC>(getter); RenderPrimitives1<RendererRectC>(getter);
} }
// labels // labels
if (fmt != NULL) { if (fmt != nullptr) {
const double w = (bounds_max.x - bounds_min.x) / cols; const double w = (bounds_max.x - bounds_min.x) / cols;
const double h = (bounds_max.y - bounds_min.y) / rows; const double h = (bounds_max.y - bounds_min.y) / rows;
const ImPlotPoint half_size(w*0.5,h*0.5); const ImPlotPoint half_size(w*0.5,h*0.5);
@ -2409,8 +2412,9 @@ double PlotHistogram(const char* label_id, const T* values, int count, int bins,
else else
width = range.Size() / bins; width = range.Size() / bins;
ImVector<double>& bin_centers = GImPlot->TempDouble1; ImPlotContext& gp = *GImPlot;
ImVector<double>& bin_counts = GImPlot->TempDouble2; ImVector<double>& bin_centers = gp.TempDouble1;
ImVector<double>& bin_counts = gp.TempDouble2;
bin_centers.resize(bins); bin_centers.resize(bins);
bin_counts.resize(bins); bin_counts.resize(bins);
int below = 0; int below = 0;
@ -2507,7 +2511,8 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
const int bins = x_bins * y_bins; const int bins = x_bins * y_bins;
ImVector<double>& bin_counts = GImPlot->TempDouble1; ImPlotContext& gp = *GImPlot;
ImVector<double>& bin_counts = gp.TempDouble1;
bin_counts.resize(bins); bin_counts.resize(bins);
for (int b = 0; b < bins; ++b) for (int b = 0; b < bins; ++b)
@ -2535,7 +2540,7 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
if (BeginItemEx(label_id, FitterRect(range))) { if (BeginItemEx(label_id, FitterRect(range))) {
ImDrawList& draw_list = *GetPlotDrawList(); ImDrawList& draw_list = *GetPlotDrawList();
RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false, col_maj); RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj);
EndItem(); EndItem();
} }
return max_count; return max_count;
@ -2648,7 +2653,7 @@ void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) { void PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
SetupLock(); SetupLock();
ImDrawList & draw_list = *GetPlotDrawList(); ImDrawList & draw_list = *GetPlotDrawList();
PushPlotClipRect(); PushPlotClipRect();

View File

@ -0,0 +1,35 @@
const zgui = @import("gui.zig");
pub fn init(window: *anyopaque, glsl_version: []const u8) void {
if (!ImGui_ImplGlfw_InitForOpenGL(window, true)) unreachable;
if (!ImGui_ImplOpenGL3_Init(glsl_version.ptr)) unreachable;
}
pub fn deinit() void {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
}
pub fn newFrame(width: f32, height: f32) void {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
zgui.io.setDisplaySize(width, height);
zgui.io.setDisplayFramebufferScale(1.0, 1.0);
zgui.newFrame();
}
pub fn draw() void {
zgui.render();
ImGui_ImplOpenGL3_RenderDrawData(zgui.getDrawData());
}
extern fn ImGui_ImplGlfw_InitForOpenGL(window: *anyopaque, install_callbacks: bool) bool;
extern fn ImGui_ImplGlfw_Shutdown() void;
extern fn ImGui_ImplGlfw_NewFrame() void;
extern fn ImGui_ImplOpenGL3_Init(glsl_version: [*]const u8) bool;
extern fn ImGui_ImplOpenGL3_Shutdown() void;
extern fn ImGui_ImplOpenGL3_NewFrame() void;
extern fn ImGui_ImplOpenGL3_RenderDrawData(draw_data: *anyopaque) void; // ImDrawData

View File

@ -0,0 +1,42 @@
const zgui = @import("gui.zig");
const SDL_GL_Context = *anyopaque;
pub fn init(window: *anyopaque, context: SDL_GL_Context, glsl_version: []const u8) void {
if (!ImGui_ImplSDL2_InitForOpenGL(window, context)) unreachable;
if (!ImGui_ImplOpenGL3_Init(glsl_version.ptr)) unreachable;
}
pub fn deinit() void {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
}
pub fn newFrame(width: f32, height: f32) void {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
zgui.io.setDisplaySize(width, height);
zgui.io.setDisplayFramebufferScale(1.0, 1.0);
zgui.newFrame();
}
pub fn draw() void {
zgui.render();
ImGui_ImplOpenGL3_RenderDrawData(zgui.getDrawData());
}
pub fn processEvent(event: *anyopaque) bool {
return ImGui_ImplSDL2_ProcessEvent(event);
}
extern fn ImGui_ImplSDL2_InitForOpenGL(window: *anyopaque, sdl_gl_context: SDL_GL_Context) bool;
extern fn ImGui_ImplSDL2_Shutdown() void;
extern fn ImGui_ImplSDL2_NewFrame() void;
extern fn ImGui_ImplSDL2_ProcessEvent(event: *anyopaque) bool;
extern fn ImGui_ImplOpenGL3_Init(glsl_version: [*]const u8) bool;
extern fn ImGui_ImplOpenGL3_Shutdown() void;
extern fn ImGui_ImplOpenGL3_NewFrame() void;
extern fn ImGui_ImplOpenGL3_RenderDrawData(draw_data: *anyopaque) void;

View File

@ -1,4 +1,20 @@
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
//
// Zig bindings for 'dear imgui' library. Easy to use, hand-crafted API with default arguments,
// named parameters and Zig style text formatting.
//
//--------------------------------------------------------------------------------------------------
pub const version = @import("std").SemanticVersion{ .major = 1, .minor = 89, .patch = 6 };
pub const plot = @import("plot.zig");
pub const backend = switch (@import("zgui_options").backend) {
.glfw_wgpu => @import("backend_glfw_wgpu.zig"),
.glfw_opengl3 => @import("backend_glfw_opengl3.zig"),
.sdl2_opengl3 => @import("backend_sdl2_opengl3.zig"),
.win32_dx12 => .{}, // TODO:
.no_backend => .{},
};
//--------------------------------------------------------------------------------------------------
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -175,7 +191,13 @@ pub const io = struct {
config: ?FontConfig, config: ?FontConfig,
ranges: ?[*]const Wchar, ranges: ?[*]const Wchar,
) Font { ) Font {
return zguiIoAddFontFromMemoryWithConfig(fontdata.ptr, @intCast(i32, fontdata.len), size_pixels, if (config) |c| &c else null, ranges); return zguiIoAddFontFromMemoryWithConfig(
fontdata.ptr,
@intCast(i32, fontdata.len),
size_pixels,
if (config) |c| &c else null,
ranges,
);
} }
extern fn zguiIoAddFontFromMemoryWithConfig( extern fn zguiIoAddFontFromMemoryWithConfig(
font_data: *const anyopaque, font_data: *const anyopaque,
@ -3025,6 +3047,16 @@ extern fn zguiColorConvertRGBtoHSV(r: f32, g: f32, b: f32, out_h: *f32, out_s: *
extern fn zguiColorConvertHSVtoRGB(h: f32, s: f32, v: f32, out_r: *f32, out_g: *f32, out_b: *f32) void; extern fn zguiColorConvertHSVtoRGB(h: f32, s: f32, v: f32, out_r: *f32, out_g: *f32, out_b: *f32) void;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// //
// Inputs Utilities: Keyboard
//
//--------------------------------------------------------------------------------------------------
pub fn isKeyDown(key: Key) bool {
return zguiIsKeyDown(key);
}
extern fn zguiIsKeyDown(key: Key) bool;
//--------------------------------------------------------------------------------------------------
//
// Helpers // Helpers
// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -3053,7 +3085,14 @@ pub fn typeToDataTypeEnum(comptime T: type) DataType {
u64 => .U64, u64 => .U64,
f32 => .F32, f32 => .F32,
f64 => .F64, f64 => .F64,
else => @compileError("Only fundamental scalar types allowed"), usize => switch (@sizeOf(usize)) {
1 => .U8,
2 => .U16,
4 => .U32,
8 => .U64,
else => @compileError("Unsupported usize length"),
},
else => @compileError("Only fundamental scalar types allowed: " ++ @typeName(T)),
}; };
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -1,15 +0,0 @@
//--------------------------------------------------------------------------------------------------
//
// Zig bindings for 'dear imgui' library. Easy to use, hand-crafted API with default arguments,
// named parameters and Zig style text formatting.
//
//--------------------------------------------------------------------------------------------------
pub const version = @import("std").SemanticVersion{ .major = 0, .minor = 9, .patch = 6 };
pub usingnamespace @import("gui.zig");
pub const plot = @import("plot.zig");
pub const backend = switch (@import("zgui_options").backend) {
.glfw_wgpu => @import("backend_glfw_wgpu.zig"),
.win32_dx12 => .{}, // TODO:
.no_backend => .{},
};

View File

@ -497,6 +497,50 @@ extern fn zguiPlot_PlotScatter(
offset: i32, offset: i32,
stride: i32, stride: i32,
) void; ) void;
pub const ShadedFlags = packed struct(u32) {
_padding: u32 = 0,
};
fn PlotShadedGen(comptime T: type) type {
return struct {
xv: []const T,
yv: []const T,
yref: f64 = 0.0,
flags: ShadedFlags = .{},
offset: i32 = 0,
stride: i32 = @sizeOf(T),
};
}
pub fn plotShaded(label_id: [:0]const u8, comptime T: type, args: PlotShadedGen(T)) void {
assert(args.xv.len == args.yv.len);
zguiPlot_PlotShaded(
label_id,
gui.typeToDataTypeEnum(T),
args.xv.ptr,
args.yv.ptr,
@intCast(i32, args.xv.len),
args.yref,
args.flags,
args.offset,
args.stride,
);
}
extern fn zguiPlot_PlotShaded(
label_id: [*:0]const u8,
data_type: gui.DataType,
xv: *const anyopaque,
yv: *const anyopaque,
count: i32,
yref: f64,
flags: ShadedFlags,
offset: i32,
stride: i32,
) void;
//----------------------------------------------------------------------------------------------
/// `pub fn showDemoWindow(popen: ?*bool) void`
pub const showDemoWindow = zguiPlot_ShowDemoWindow;
extern fn zguiPlot_ShowDemoWindow(popen: ?*bool) void;
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
/// `pub fn endPlot() void` /// `pub fn endPlot() void`
pub const endPlot = zguiPlot_EndPlot; pub const endPlot = zguiPlot_EndPlot;

View File

@ -1579,6 +1579,14 @@ ZGUI_API void zguiColorConvertHSVtoRGB(float h, float s, float v, float* out_r,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// //
// Inputs Utilities: Keyboard
//
//--------------------------------------------------------------------------------------------------
ZGUI_API bool zguiIsKeyDown(ImGuiKey key) {
return ImGui::IsKeyDown(key);
}
//--------------------------------------------------------------------------------------------------
//
// DrawList // DrawList
// //
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -2308,6 +2316,41 @@ ZGUI_API void zguiPlot_PlotScatterValues(
assert(false); assert(false);
} }
ZGUI_API void zguiPlot_PlotShaded(
const char* label_id,
ImGuiDataType data_type,
const void* xv,
const void* yv,
int count,
double yref,
ImPlotShadedFlags flags,
int offset,
int stride
) {
if (data_type == ImGuiDataType_S8)
ImPlot::PlotShaded(label_id, (const ImS8*)xv, (const ImS8*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_U8)
ImPlot::PlotShaded(label_id, (const ImU8*)xv, (const ImU8*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_S16)
ImPlot::PlotShaded(label_id, (const ImS16*)xv, (const ImS16*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_U16)
ImPlot::PlotShaded(label_id, (const ImU16*)xv, (const ImU16*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_S32)
ImPlot::PlotShaded(label_id, (const ImS32*)xv, (const ImS32*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_U32)
ImPlot::PlotShaded(label_id, (const ImU32*)xv, (const ImU32*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_Float)
ImPlot::PlotShaded(label_id, (const float*)xv, (const float*)yv, count, yref, flags, offset, stride);
else if (data_type == ImGuiDataType_Double)
ImPlot::PlotShaded(label_id, (const double*)xv, (const double*)yv, count, yref, flags, offset, stride);
else
assert(false);
}
ZGUI_API void zguiPlot_ShowDemoWindow(bool* p_open) {
ImPlot::ShowDemoWindow(p_open);
}
ZGUI_API void zguiPlot_EndPlot(void) { ZGUI_API void zguiPlot_EndPlot(void) {
ImPlot::EndPlot(); ImPlot::EndPlot();
} }