Compare commits

..

3 Commits

17 changed files with 1435 additions and 908 deletions

View File

@ -1,4 +1,4 @@
# zgui v0.9.5 - dear imgui bindings
# zgui v0.9.6 - dear imgui (1.89.4) 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).
@ -26,26 +26,24 @@ const zpool = @import("libs/zpool/build.zig");
pub fn build(b: *std.Build) void {
...
const zgui_pkg = zgui.package(b, .{
const optimize = b.standardOptimizeOption(.{});
const target = b.standardTargetOptions(.{});
const zgui_pkg = zgui.package(b, target, optimize, .{
.options = .{ .backend = .glfw_wgpu },
});
exe.addModule("zgui", zgui_pkg.module);
zgui.link(exe, zgui_pkg.options);
zgui_pkg.link(exe);
// Needed for glfw/wgpu rendering backend
const zglfw_pkg = zglfw.package(b, .{});
const zpool_pkg = zpool.package(b, .{});
const zgpu_pkg = zgpu.package(b, .{
.deps = .{ .zpool = zpool_pkg.module, .zglfw = zglfw_pkg.module },
const zglfw_pkg = zglfw.package(b, target, optimize, .{});
const zpool_pkg = zpool.package(b, target, optimize, .{});
const zgpu_pkg = zgpu.package(b, target, optimize, .{
.deps = .{ .zpool = zpool_pkg.zpool, .zglfw = zglfw_pkg.zglfw },
});
exe.addModule("zgpu", zgpu_pkg.module);
exe.addModule("zglfw", zglfw_pkg.module);
zglfw.link(exe);
zgpu.link(exe);
zglfw_pkg.link(exe);
zgpu_pkg.link(exe);
}
```
Now in your code you may import and use `zgui`:
@ -93,6 +91,26 @@ while (...) {
}
```
### Building a shared library
If your project spans multiple zig modules that both use ImGui, such as an exe paired with a dll, you may want to build the `zgui` dependencies (`zgui_pkg.zgui_c_cpp`) as a shared library. This can be enabled with the `shared` build option. Then, in `build.zig`, use `zgui_pkg.link` to link `zgui` to all the modules that use ImGui.
When built this way, the ImGui context will be located in the shared library. However, the `zgui` zig code (which is compiled separately into each module) requires its own memory buffer which has to be initialized separately with `initNoContext`.
In your executable:
```zig
const zgui = @import("zgui");
zgui.init(allocator);
defer zgui.deinit();
```
In your shared library:
```zig
const zgui = @import("zgui");
zgui.initNoContext(allocator);
defer zgui.deinitNoContxt();
```
### DrawList API
```zig

134
build.zig
View File

@ -10,85 +10,117 @@ pub const Backend = enum {
pub const Options = struct {
backend: Backend,
shared: bool = false,
};
pub const Package = struct {
module: *std.Build.Module,
options: Options,
options_module: *std.Build.Module,
zgui: *std.Build.Module,
zgui_options: *std.Build.Module,
zgui_c_cpp: *std.Build.CompileStep,
pub fn link(pkg: Package, exe: *std.Build.CompileStep) void {
exe.linkLibrary(pkg.zgui_c_cpp);
exe.addModule("zgui", pkg.zgui);
}
};
pub fn package(
b: *std.Build,
target: std.zig.CrossTarget,
optimize: std.builtin.Mode,
args: struct {
options: Options,
},
) Package {
const step = b.addOptions();
step.addOption(Backend, "backend", args.options.backend);
step.addOption(bool, "shared", args.options.shared);
const options_module = step.createModule();
const zgui_options = step.createModule();
const module = b.createModule(.{
const zgui = b.createModule(.{
.source_file = .{ .path = thisDir() ++ "/src/main.zig" },
.dependencies = &.{
.{ .name = "zgui_options", .module = options_module },
.{ .name = "zgui_options", .module = zgui_options },
},
});
const zgui_c_cpp = if (args.options.shared) blk: {
const lib = b.addSharedLibrary(.{
.name = "zgui",
.target = target,
.optimize = optimize,
});
lib.install();
if (target.isWindows()) {
lib.defineCMacro("IMGUI_API", "__declspec(dllexport)");
lib.defineCMacro("IMPLOT_API", "__declspec(dllexport)");
lib.defineCMacro("ZGUI_API", "__declspec(dllexport)");
}
break :blk lib;
} else b.addStaticLibrary(.{
.name = "zgui",
.target = target,
.optimize = optimize,
});
zgui_c_cpp.addIncludePath(thisDir() ++ "/libs");
zgui_c_cpp.addIncludePath(thisDir() ++ "/libs/imgui");
zgui_c_cpp.linkLibC();
zgui_c_cpp.linkLibCpp();
const cflags = &.{"-fno-sanitize=undefined"};
zgui_c_cpp.addCSourceFile(thisDir() ++ "/src/zgui.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/imgui.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_widgets.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_tables.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_draw.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_demo.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/implot_demo.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/implot.cpp", cflags);
zgui_c_cpp.addCSourceFile(thisDir() ++ "/libs/imgui/implot_items.cpp", cflags);
switch (args.options.backend) {
.glfw_wgpu => {
zgui_c_cpp.addIncludePath(thisDir() ++ "/../zglfw/libs/glfw/include");
zgui_c_cpp.addIncludePath(thisDir() ++ "/../zgpu/libs/dawn/include");
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);
},
.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 => {
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.linkSystemLibraryName("d3dcompiler_47");
zgui_c_cpp.linkSystemLibraryName("dwmapi");
},
.sdl2_opengl3 => {
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 => {},
}
return .{
.module = module,
.options = args.options,
.options_module = options_module,
.zgui = zgui,
.zgui_options = zgui_options,
.zgui_c_cpp = zgui_c_cpp,
};
}
pub fn build(_: *std.Build) void {}
pub fn link(exe: *std.Build.CompileStep, options: Options) void {
exe.addIncludePath(thisDir() ++ "/libs");
exe.addIncludePath(thisDir() ++ "/libs/imgui");
exe.linkSystemLibraryName("c");
exe.linkSystemLibraryName("c++");
const cflags = &.{"-fno-sanitize=undefined"};
exe.addCSourceFile(thisDir() ++ "/src/zgui.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/imgui.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_widgets.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_tables.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_draw.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/imgui_demo.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/implot_demo.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/implot.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/implot_items.cpp", cflags);
switch (options.backend) {
.glfw_wgpu => {
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_glfw.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_wgpu.cpp", cflags);
},
.glfw_opengl3 => {
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_glfw.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_opengl3.cpp", cflags);
},
.sdl2_opengl3 => {
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_sdl.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_opengl3.cpp", cflags);
},
.win32_dx12 => {
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_win32.cpp", cflags);
exe.addCSourceFile(thisDir() ++ "/libs/imgui/backends/imgui_impl_dx12.cpp", cflags);
exe.linkSystemLibraryName("d3dcompiler_47");
exe.linkSystemLibraryName("dwmapi");
},
.no_backend => {},
}
}
inline fn thisDir() []const u8 {
return comptime std.fs.path.dirname(@src().file) orelse ".";
}

View File

@ -67,6 +67,7 @@
#endif
// GLFW
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#ifdef _WIN32
#undef APIENTRY

View File

@ -90,6 +90,8 @@
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- ...Or use Dear ImGui's own very basic math operators.
//#define IMGUI_DEFINE_MATH_OPERATORS
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.2
// dear imgui, v1.89.4
// (headers)
// Help:
@ -11,7 +11,7 @@
// - FAQ http://dearimgui.org/faq
// - Homepage & latest https://github.com/ocornut/imgui
// - Releases & changelog https://github.com/ocornut/imgui/releases
// - Gallery https://github.com/ocornut/imgui/issues/5243 (please post your screenshots/video there!)
// - Gallery https://github.com/ocornut/imgui/issues/5886 (please post your screenshots/video there!)
// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
// - Issues & support https://github.com/ocornut/imgui/issues
@ -22,8 +22,8 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345')
#define IMGUI_VERSION "1.89.2"
#define IMGUI_VERSION_NUM 18920
#define IMGUI_VERSION "1.89.4"
#define IMGUI_VERSION_NUM 18940
#define IMGUI_HAS_TABLE
/*
@ -37,7 +37,7 @@ Index of this file:
// [SECTION] ImGuiStyle
// [SECTION] ImGuiIO
// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
@ -405,8 +405,8 @@ namespace ImGui
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame().
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame().
IMGUI_API void PopStyleVar(int count = 1);
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // == tab stop enable. Allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
IMGUI_API void PopAllowKeyboardFocus();
IMGUI_API void PushTabStop(bool tab_stop); // == tab stop enable. Allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
IMGUI_API void PopTabStop();
IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
IMGUI_API void PopButtonRepeat();
@ -493,6 +493,7 @@ namespace ImGui
IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2);
IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text()
IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1);
IMGUI_API void SeparatorText(const char* label); // currently: formatted text with an horizontal line
// Widgets: Main
// - Most widgets return true when the value has been changed or when pressed/selected
@ -664,8 +665,8 @@ namespace ImGui
// Tooltips
// - Tooltip are windows following the mouse. They do not take focus away.
IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items).
IMGUI_API void EndTooltip();
IMGUI_API bool BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items).
IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip() returns true!
IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip().
IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
@ -1014,10 +1015,8 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
ImGuiInputTextFlags_EscapeClearsAll = 1 << 20, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
// Obsolete names (will be removed soon)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
#endif
// Obsolete names
//ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
};
// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*()
@ -1352,6 +1351,7 @@ enum ImGuiSortDirection_
// All our named keys are >= 512. Keys value 0 to 511 are left unused as legacy native/opaque key values (< 1.87).
// Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey.
// Read details about the 1.87 and 1.89 transition : https://github.com/ocornut/imgui/issues/4921
// Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter().
enum ImGuiKey : int
{
// Keyboard
@ -1459,15 +1459,16 @@ enum ImGuiKey : int
// [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + the io.KeyMap[] array.
// We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE)
// If you need to iterate all keys (for e.g. an input mapper) you may use ImGuiKey_NamedKey_BEGIN..ImGuiKey_NamedKey_END.
ImGuiKey_NamedKey_BEGIN = 512,
ImGuiKey_NamedKey_END = ImGuiKey_COUNT,
ImGuiKey_NamedKey_COUNT = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN,
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
ImGuiKey_KeysData_SIZE = ImGuiKey_NamedKey_COUNT, // Size of KeysData[]: only hold named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_NamedKey_BEGIN, // First key stored in io.KeysData[0]. Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET).
ImGuiKey_KeysData_SIZE = ImGuiKey_NamedKey_COUNT, // Size of KeysData[]: only hold named keys
ImGuiKey_KeysData_OFFSET = ImGuiKey_NamedKey_BEGIN, // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index.
#else
ImGuiKey_KeysData_SIZE = ImGuiKey_COUNT, // Size of KeysData[]: hold legacy 0..512 keycodes + named keys
ImGuiKey_KeysData_OFFSET = 0, // First key stored in io.KeysData[0]. Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET).
ImGuiKey_KeysData_SIZE = ImGuiKey_COUNT, // Size of KeysData[]: hold legacy 0..512 keycodes + named keys
ImGuiKey_KeysData_OFFSET = 0, // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index.
#endif
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@ -1492,7 +1493,7 @@ enum ImGuiNavInput
enum ImGuiConfigFlags_
{
ImGuiConfigFlags_None = 0,
ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag.
ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + space/enter to activate.
ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. Backend also needs to set ImGuiBackendFlags_HasGamepad.
ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth.
ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set.
@ -1608,6 +1609,9 @@ enum ImGuiStyleVar_
ImGuiStyleVar_TabRounding, // float TabRounding
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
ImGuiStyleVar_SeparatorTextBorderSize,// float SeparatorTextBorderSize
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
ImGuiStyleVar_SeparatorTextPadding,// ImVec2 SeparatorTextPadding
ImGuiStyleVar_COUNT
};
@ -1664,8 +1668,8 @@ enum ImGuiColorEditFlags_
ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,
ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV,
// Obsolete names (will be removed)
// ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69]
// Obsolete names
//ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69]
};
// Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
@ -1680,10 +1684,8 @@ enum ImGuiSliderFlags_
ImGuiSliderFlags_NoInput = 1 << 7, // Disable CTRL+Click or Enter key allowing to input text directly into the widget
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiSliderFlags_ClampOnInput = ImGuiSliderFlags_AlwaysClamp, // [renamed in 1.79]
#endif
// Obsolete names
//ImGuiSliderFlags_ClampOnInput = ImGuiSliderFlags_AlwaysClamp, // [renamed in 1.79]
};
// Identify a mouse button.
@ -1862,6 +1864,9 @@ struct ImGuiStyle
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
float SeparatorTextBorderSize; // Thickkness of border in SeparatorText()
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly!
float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
@ -1932,6 +1937,14 @@ struct ImGuiIO
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
// Debug options
// - 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()
// 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.
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.
//------------------------------------------------------------------
// Platform Functions
// (the imgui_impl_xxxx backend files are setting those up for you)
@ -1968,7 +1981,7 @@ struct ImGuiIO
IMGUI_API void AddKeyAnalogEvent(ImGuiKey key, bool down, float v); // Queue a new key down/up event for analog values (e.g. ImGuiKey_Gamepad_ values). Dead-zones should be handled by the backend.
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 AddMouseWheelEvent(float wh_x, float wh_y); // Queue a mouse wheel update
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 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 AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate
@ -2013,13 +2026,15 @@ struct ImGuiIO
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
//------------------------------------------------------------------
ImGuiContext* Ctx; // Parent UI context (needs to be set explicitly by parent).
// Main Input State
// (this block used to be written by backend, since 1.87 it is best to NOT write to those directly, call the AddXXX functions above instead)
// (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere)
ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
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.
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends.
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.
bool KeyCtrl; // Keyboard modifier down: Control
bool KeyShift; // Keyboard modifier down: Shift
bool KeyAlt; // Keyboard modifier down: Alt
@ -2068,6 +2083,7 @@ struct ImGuiIO
// - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow.
struct ImGuiInputTextCallbackData
{
ImGuiContext* Ctx; // Parent UI context
ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
void* UserData; // What user passed to InputText() // Read-only
@ -2152,7 +2168,7 @@ struct ImGuiTableSortSpecs
};
//-----------------------------------------------------------------------------
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor)
//-----------------------------------------------------------------------------
// Helper: Unicode defines
@ -2292,6 +2308,7 @@ struct ImGuiStorage
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
struct ImGuiListClipper
{
ImGuiContext* Ctx; // Parent UI context
int DisplayStart; // First item to display, updated by each call to Step()
int DisplayEnd; // End of items to display (exclusive)
int ItemsCount; // [Internal] Number of items
@ -2315,6 +2332,32 @@ struct ImGuiListClipper
#endif
};
// Helpers: ImVec2/ImVec4 operators
// - 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)
// - 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
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
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*=(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; }
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; }
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
IM_MSVC_RUNTIME_CHECKS_RESTORE
#endif
// Helpers macros to generate 32-bit encoded colors
// User can declare their own format by #defining the 5 _SHIFT/_MASK macros in their imconfig file.
#ifndef IM_COL32_R_SHIFT
@ -2602,10 +2645,9 @@ struct ImDrawList
inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; }
inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
#endif
// Obsolete names
//inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
//inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
// [Internal helpers]
IMGUI_API void _ResetForNewFrame();
@ -2657,7 +2699,7 @@ struct ImFontConfig
bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input.
const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
const ImWchar* GlyphRanges; // NULL // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs
bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
@ -2859,8 +2901,10 @@ struct ImFont
const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData
short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found.
ImWchar EllipsisChar; // 2 // out // = '...' // Character used for ellipsis rendering.
ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found)
ImWchar EllipsisChar; // 2 // out // = '...'/'.'// Character used for ellipsis rendering.
short EllipsisCharCount; // 1 // out // 1 or 3
float EllipsisWidth; // 4 // out // Width
float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0
bool DirtyLookupTables; // 1 // out //
float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
@ -2963,6 +3007,9 @@ namespace ImGui
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{
// OBSOLETED in 1.89.4 (from March 2023)
static inline void PushAllowKeyboardFocus(bool tab_stop) { PushTabStop(tab_stop); }
static inline void PopAllowKeyboardFocus() { PopTabStop(); }
// OBSOLETED in 1.89 (from August 2022)
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding)
// OBSOLETED in 1.88 (from May 2022)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.2
// dear imgui, v1.89.4
// (demo code)
// Help:
@ -38,7 +38,7 @@
// - We try to declare static variables in the local scope, as close as possible to the code using them.
// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
// by imgui_internal.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
// by imgui.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
// and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
@ -211,9 +211,8 @@ static void ShowDemoWindowInputs();
static void HelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip())
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
@ -426,6 +425,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
if (ImGui::TreeNode("Configuration##2"))
{
ImGui::SeparatorText("General");
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
@ -448,6 +448,10 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::SeparatorText("Widgets");
ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive);
@ -457,11 +461,19 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
ImGui::Text("Also see Style->Rendering for rendering options.");
ImGui::SeparatorText("Debug");
ImGui::BeginDisabled();
ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); // .
ImGui::EndDisabled();
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::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::TreePop();
ImGui::Separator();
ImGui::Spacing();
}
IMGUI_DEMO_MARKER("Configuration/Backend Flags");
@ -479,7 +491,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &backend_flags, ImGuiBackendFlags_HasSetMousePos);
ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
ImGui::TreePop();
ImGui::Separator();
ImGui::Spacing();
}
IMGUI_DEMO_MARKER("Configuration/Style");
@ -488,7 +500,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
ImGui::ShowStyleEditor();
ImGui::TreePop();
ImGui::Separator();
ImGui::Spacing();
}
IMGUI_DEMO_MARKER("Configuration/Capture, Logging");
@ -556,6 +568,8 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Basic");
if (ImGui::TreeNode("Basic"))
{
ImGui::SeparatorText("General");
IMGUI_DEMO_MARKER("Widgets/Basic/Button");
static int clicked = 0;
if (ImGui::Button("Button"))
@ -610,19 +624,41 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine();
ImGui::Text("%d", counter);
ImGui::Separator();
{
// Tooltips
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
//ImGui::AlignTextToFramePadding();
ImGui::Text("Tooltips:");
ImGui::SameLine();
ImGui::SmallButton("Button");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::SmallButton("Fancy");
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
{
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SameLine();
ImGui::SmallButton("Delayed");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // With a delay
ImGui::SetTooltip("I am a tooltip with a delay.");
ImGui::SameLine();
HelpMarker(
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
}
ImGui::LabelText("label", "Value");
{
// Using the _simplified_ one-liner Combo() api here
// See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
ImGui::SameLine(); HelpMarker(
"Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
}
ImGui::SeparatorText("Inputs");
{
// To wire InputText() with std::string or any other custom string type,
@ -666,6 +702,8 @@ static void ShowDemoWindowWidgets()
ImGui::InputFloat3("input float3", vec4a);
}
ImGui::SeparatorText("Drags");
{
IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat");
static int i1 = 50, i2 = 42;
@ -682,6 +720,8 @@ static void ShowDemoWindowWidgets()
ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
}
ImGui::SeparatorText("Sliders");
{
IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat");
static int i1 = 0;
@ -708,6 +748,8 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
}
ImGui::SeparatorText("Selectors/Pickers");
{
IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4");
static float col1[3] = { 1.0f, 0.0f, 0.2f };
@ -722,6 +764,17 @@ static void ShowDemoWindowWidgets()
ImGui::ColorEdit4("color 2", col2);
}
{
// Using the _simplified_ one-liner Combo() api here
// See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
static int item_current = 0;
ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
ImGui::SameLine(); HelpMarker(
"Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
}
{
// Using the _simplified_ one-liner ListBox() api here
// See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
@ -733,40 +786,6 @@ static void ShowDemoWindowWidgets()
"Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
}
{
// Tooltips
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
ImGui::AlignTextToFramePadding();
ImGui::Text("Tooltips:");
ImGui::SameLine();
ImGui::Button("Button");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::Button("Fancy");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SameLine();
ImGui::Button("Delayed");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // Delay best used on items that highlight on hover, so this not a great example!
ImGui::SetTooltip("I am a tooltip with a delay.");
ImGui::SameLine();
HelpMarker(
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
}
ImGui::TreePop();
}
@ -1026,16 +1045,17 @@ static void ShowDemoWindowWidgets()
float my_tex_w = (float)io.Fonts->TexWidth;
float my_tex_h = (float)io.Fonts->TexHeight;
{
static bool use_text_color_for_tint = false;
ImGui::Checkbox("Use Text Color for Tint", &use_text_color_for_tint);
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
ImVec2 pos = ImGui::GetCursorScreenPos();
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
if (ImGui::IsItemHovered())
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
{
ImGui::BeginTooltip();
float region_sz = 32.0f;
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
@ -1689,7 +1709,7 @@ static void ShowDemoWindowWidgets()
}
// Use functions to generate output
// FIXME: This is rather awkward because current plot API only pass in indices.
// FIXME: This is actually VERY awkward because current plot API only pass in indices.
// We probably want an API passing floats and user provide sample rate/count.
struct Funcs
{
@ -1697,7 +1717,7 @@ static void ShowDemoWindowWidgets()
static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
};
static int func_type = 0, display_count = 70;
ImGui::Separator();
ImGui::SeparatorText("Functions");
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::Combo("func", &func_type, "Sin\0Saw\0");
ImGui::SameLine();
@ -1740,6 +1760,7 @@ static void ShowDemoWindowWidgets()
static bool drag_and_drop = true;
static bool options_menu = true;
static bool hdr = false;
ImGui::SeparatorText("Options");
ImGui::Checkbox("With Alpha Preview", &alpha_preview);
ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
@ -1748,6 +1769,7 @@ static void ShowDemoWindowWidgets()
ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit");
ImGui::SeparatorText("Inline color editor");
ImGui::Text("Color widget:");
ImGui::SameLine(); HelpMarker(
"Click on the color square to open a color picker.\n"
@ -1845,7 +1867,7 @@ static void ShowDemoWindowWidgets()
ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker");
ImGui::Text("Color picker:");
ImGui::SeparatorText("Color picker");
static bool alpha = true;
static bool alpha_bar = true;
static bool side_preview = true;
@ -2016,7 +2038,7 @@ static void ShowDemoWindowWidgets()
const float drag_speed = 0.2f;
static bool drag_clamp = false;
IMGUI_DEMO_MARKER("Widgets/Data Types/Drags");
ImGui::Text("Drags:");
ImGui::SeparatorText("Drags");
ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
ImGui::SameLine(); HelpMarker(
"As with every widget in dear imgui, we never modify values unless there is a user interaction.\n"
@ -2036,7 +2058,7 @@ static void ShowDemoWindowWidgets()
ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders");
ImGui::Text("Sliders");
ImGui::SeparatorText("Sliders");
ImGui::SliderScalar("slider s8 full", ImGuiDataType_S8, &s8_v, &s8_min, &s8_max, "%d");
ImGui::SliderScalar("slider u8 full", ImGuiDataType_U8, &u8_v, &u8_min, &u8_max, "%u");
ImGui::SliderScalar("slider s16 full", ImGuiDataType_S16, &s16_v, &s16_min, &s16_max, "%d");
@ -2061,7 +2083,7 @@ static void ShowDemoWindowWidgets()
ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic);
ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
ImGui::Text("Sliders (reverse)");
ImGui::SeparatorText("Sliders (reverse)");
ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d");
ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u");
ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d");
@ -2071,7 +2093,7 @@ static void ShowDemoWindowWidgets()
IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs");
static bool inputs_step = true;
ImGui::Text("Inputs");
ImGui::SeparatorText("Inputs");
ImGui::Checkbox("Show step buttons", &inputs_step);
ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d");
ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u");
@ -2095,22 +2117,23 @@ static void ShowDemoWindowWidgets()
static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
static int vec4i[4] = { 1, 5, 100, 255 };
ImGui::SeparatorText("2-wide");
ImGui::InputFloat2("input float2", vec4f);
ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
ImGui::InputInt2("input int2", vec4i);
ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
ImGui::SliderInt2("slider int2", vec4i, 0, 255);
ImGui::Spacing();
ImGui::SeparatorText("3-wide");
ImGui::InputFloat3("input float3", vec4f);
ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
ImGui::InputInt3("input int3", vec4i);
ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
ImGui::SliderInt3("slider int3", vec4i, 0, 255);
ImGui::Spacing();
ImGui::SeparatorText("4-wide");
ImGui::InputFloat4("input float4", vec4f);
ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
@ -2527,6 +2550,8 @@ static void ShowDemoWindowLayout()
IMGUI_DEMO_MARKER("Layout/Child windows");
if (ImGui::TreeNode("Child windows"))
{
ImGui::SeparatorText("Child windows");
HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
static bool disable_mouse_wheel = false;
static bool disable_menu = false;
@ -2579,7 +2604,7 @@ static void ShowDemoWindowLayout()
ImGui::PopStyleVar();
}
ImGui::Separator();
ImGui::SeparatorText("Misc/Advanced");
// Demonstrate a few extra things
// - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
@ -3343,8 +3368,7 @@ static void ShowDemoWindowPopups()
ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
if (ImGui::BeginPopup("my_select_popup"))
{
ImGui::Text("Aquarium");
ImGui::Separator();
ImGui::SeparatorText("Aquarium");
for (int i = 0; i < IM_ARRAYSIZE(names); i++)
if (ImGui::Selectable(names[i]))
selected_fish = i;
@ -3521,7 +3545,7 @@ static void ShowDemoWindowPopups()
if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!");
ImGui::Separator();
//static int unused_i = 0;
@ -3704,9 +3728,8 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
}
ImGui::SameLine();
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
{
@ -5718,13 +5741,15 @@ static void ShowDemoWindowInputs()
ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
// We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allows displaying the data for old/new backends.
// User code should never have to go through such hoops: old code may use native keycodes, new code may use ImGuiKey codes.
// User code should never have to go through such hoops! You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN;
#else
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
ImGuiKey start_key = (ImGuiKey)0;
#endif
ImGui::Text("Keys down:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; 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::SameLine(); ImGui::Text("(%.02f)", ImGui::GetKeyData(key)->DownDuration); }
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.
@ -5812,10 +5837,10 @@ static void ShowDemoWindowInputs()
ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
ImGui::PushAllowKeyboardFocus(false);
ImGui::PushTabStop(false);
ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
ImGui::PopAllowKeyboardFocus();
ImGui::PopTabStop();
ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
ImGui::TreePop();
}
@ -5837,12 +5862,12 @@ static void ShowDemoWindowInputs()
ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
if (ImGui::IsItemActive()) has_focus = 2;
ImGui::PushAllowKeyboardFocus(false);
ImGui::PushTabStop(false);
if (focus_3) ImGui::SetKeyboardFocusHere();
ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
if (ImGui::IsItemActive()) has_focus = 3;
ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
ImGui::PopAllowKeyboardFocus();
ImGui::PopTabStop();
if (has_focus)
ImGui::Text("Item with focus: %d", has_focus);
@ -5993,6 +6018,9 @@ void ImGui::ShowAboutWindow(bool* p_open)
#endif
#ifdef __clang_version__
ImGui::Text("define: __clang_version__=%s", __clang_version__);
#endif
#ifdef __EMSCRIPTEN__
ImGui::Text("define: __EMSCRIPTEN__");
#endif
ImGui::Separator();
ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
@ -6142,7 +6170,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
if (ImGui::BeginTabItem("Sizes"))
{
ImGui::Text("Main");
ImGui::SeparatorText("Main");
ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
@ -6152,22 +6180,24 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
ImGui::Text("Borders");
ImGui::SeparatorText("Borders");
ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::Text("Rounding");
ImGui::SeparatorText("Rounding");
ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
ImGui::Text("Alignment");
ImGui::SeparatorText("Widgets");
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
int window_menu_button_position = style.WindowMenuButtonPosition + 1;
if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
@ -6177,9 +6207,13 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
ImGui::Text("Safe Area Padding");
ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
ImGui::SliderFloat("SeparatorTextBorderSize", &style.SeparatorTextBorderSize, 0.0f, 10.0f, "%.0f");
ImGui::SliderFloat2("SeparatorTextAlign", (float*)&style.SeparatorTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%0.f");
ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
ImGui::SeparatorText("Misc");
ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
ImGui::EndTabItem();
}
@ -6289,10 +6323,11 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
// When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
if (ImGui::IsItemActive())
{
const bool show_samples = ImGui::IsItemActive();
if (show_samples)
ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
ImGui::BeginTooltip();
if (show_samples && ImGui::BeginTooltip())
{
ImGui::TextUnformatted("(R = radius, N = number of segments)");
ImGui::Spacing();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
@ -6489,6 +6524,7 @@ static void ShowExampleMenuFile()
IM_ASSERT(0);
}
if (ImGui::MenuItem("Checked", NULL, true)) {}
ImGui::Separator();
if (ImGui::MenuItem("Quit", "Alt+F4")) {}
}

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.2
// dear imgui, v1.89.4
// (drawing and font code)
/*
@ -26,13 +26,12 @@ Index of this file:
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_internal.h"
#ifdef IMGUI_ENABLE_FREETYPE
#include "misc/freetype/imgui_freetype.h"
@ -389,6 +388,8 @@ void ImDrawList::_ResetForNewFrame()
IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0);
IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4));
IM_STATIC_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID));
if (_Splitter._Count > 1)
_Splitter.Merge(this);
CmdBuffer.resize(0);
IdxBuffer.resize(0);
@ -706,7 +707,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
{
if (points_count < 2)
if (points_count < 2 || (col & IM_COL32_A_MASK) == 0)
return;
const bool closed = (flags & ImDrawFlags_Closed) != 0;
@ -964,7 +965,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
// - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing.
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
{
if (points_count < 3)
if (points_count < 3 || (col & IM_COL32_A_MASK) == 0)
return;
const ImVec2 uv = _Data->TexUvWhitePixel;
@ -2382,7 +2383,12 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
{
// Check for valid range. This may also help detect *some* dangling pointers, because a common
// user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent.
IM_ASSERT(src_range[0] <= src_range[1]);
src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]);
}
dst_tmp.SrcCount++;
dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest);
}
@ -2937,19 +2943,19 @@ const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
// 2999 ideograms code points for Japanese
// - 2136 Joyo (meaning "for regular use" or "for common use") Kanji code points
// - 863 Jinmeiyo (meaning "for personal name") Kanji code points
// - Sourced from the character information database of the Information-technology Promotion Agency, Japan
// - https://mojikiban.ipa.go.jp/mji/
// - Available under the terms of the Creative Commons Attribution-ShareAlike 2.1 Japan (CC BY-SA 2.1 JP).
// - https://creativecommons.org/licenses/by-sa/2.1/jp/deed.en
// - https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode
// - You can generate this code by the script at:
// - https://github.com/vaiorabbit/everyday_use_kanji
// - Sourced from official information provided by the government agencies of Japan:
// - List of Joyo Kanji by the Agency for Cultural Affairs
// - https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kijun/naikaku/kanji/
// - List of Jinmeiyo Kanji by the Ministry of Justice
// - http://www.moj.go.jp/MINJI/minji86.html
// - Available under the terms of the Creative Commons Attribution 4.0 International (CC BY 4.0).
// - https://creativecommons.org/licenses/by/4.0/legalcode
// - You can generate this code by the script at:
// - https://github.com/vaiorabbit/everyday_use_kanji
// - References:
// - List of Joyo Kanji
// - (Official list by the Agency for Cultural Affairs) https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kakuki/14/tosin02/index.html
// - (Wikipedia) https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji
// - List of Jinmeiyo Kanji
// - (Official list by the Ministry of Justice) http://www.moj.go.jp/MINJI/minji86.html
// - (Wikipedia) https://en.wikipedia.org/wiki/Jinmeiy%C5%8D_kanji
// - Missing 1 Joyo Kanji: U+20B9F (Kun'yomi: Shikaru, On'yomi: Shitsu,shichi), see https://github.com/ocornut/imgui/pull/3627 for details.
// You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
@ -3112,7 +3118,8 @@ ImFont::ImFont()
FallbackAdvanceX = 0.0f;
FallbackChar = (ImWchar)-1;
EllipsisChar = (ImWchar)-1;
DotChar = (ImWchar)-1;
EllipsisWidth = EllipsisCharStep = 0.0f;
EllipsisCharCount = 0;
FallbackGlyph = NULL;
ContainerAtlas = NULL;
ConfigData = NULL;
@ -3200,8 +3207,20 @@ void ImFont::BuildLookupTable()
const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
if (EllipsisChar == (ImWchar)-1)
EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));
if (DotChar == (ImWchar)-1)
DotChar = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
const ImWchar dot_char = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
if (EllipsisChar != (ImWchar)-1)
{
EllipsisCharCount = 1;
EllipsisWidth = EllipsisCharStep = FindGlyph(EllipsisChar)->X1;
}
else if (dot_char != (ImWchar)-1)
{
const ImFontGlyph* glyph = FindGlyph(dot_char);
EllipsisChar = dot_char;
EllipsisCharCount = 3;
EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f;
EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f;
}
// Setup fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
@ -3369,6 +3388,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
bool inside_word = true;
const char* s = text;
IM_ASSERT(text_end != NULL);
while (s < text_end)
{
unsigned int c = (unsigned int)*s;
@ -3377,8 +3397,6 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
next_s = s + 1;
else
next_s = s + ImTextCharFromUtf8(&c, s, text_end);
if (c == 0)
break;
if (c < 32)
{
@ -3484,15 +3502,9 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
const char* prev_s = s;
unsigned int c = (unsigned int)*s;
if (c < 0x80)
{
s += 1;
}
else
{
s += ImTextCharFromUtf8(&c, s, text_end);
if (c == 0) // Malformed UTF-8?
break;
}
if (c < 32)
{
@ -3567,18 +3579,17 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
while (y + line_height < clip_rect.y && s < text_end)
{
const char* line_end = (const char*)memchr(s, '\n', text_end - s);
const char* line_next = line_end ? line_end + 1 : text_end;
if (word_wrap_enabled)
{
// FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA().
// If the specs for CalcWordWrapPositionA() were reworked to optionally return on \n we could combine both.
// However it is still better than nothing performing the fast-forward!
s = CalcWordWrapPositionA(scale, s, line_next, wrap_width);
s = CalcWordWrapPositionA(scale, s, line_end ? line_end : text_end, wrap_width);
s = CalcWordWrapNextLineStartA(s, text_end);
}
else
{
s = line_next;
s = line_end ? line_end + 1 : text_end;
}
y += line_height;
}
@ -3605,10 +3616,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
const int idx_count_max = (int)(text_end - s) * 6;
const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;
draw_list->PrimReserve(idx_count_max, vtx_count_max);
ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
unsigned int vtx_index = draw_list->_VtxCurrentIdx;
const ImU32 col_untinted = col | ~IM_COL32_A_MASK;
const char* word_wrap_eol = NULL;
@ -3634,15 +3644,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
// Decode and advance source
unsigned int c = (unsigned int)*s;
if (c < 0x80)
{
s += 1;
}
else
{
s += ImTextCharFromUtf8(&c, s, text_end);
if (c == 0) // Malformed UTF-8?
break;
}
if (c < 32)
{
@ -3713,14 +3717,14 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
// We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:
{
idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2);
idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3);
vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1;
vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = glyph_col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1;
vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = glyph_col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2;
vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = glyph_col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2;
idx_write[0] = (ImDrawIdx)(vtx_index); idx_write[1] = (ImDrawIdx)(vtx_index + 1); idx_write[2] = (ImDrawIdx)(vtx_index + 2);
idx_write[3] = (ImDrawIdx)(vtx_index); idx_write[4] = (ImDrawIdx)(vtx_index + 2); idx_write[5] = (ImDrawIdx)(vtx_index + 3);
vtx_write += 4;
vtx_current_idx += 4;
vtx_index += 4;
idx_write += 6;
}
}
@ -3734,7 +3738,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
draw_list->_VtxWritePtr = vtx_write;
draw_list->_IdxWritePtr = idx_write;
draw_list->_VtxCurrentIdx = vtx_current_idx;
draw_list->_VtxCurrentIdx = vtx_index;
}
//-----------------------------------------------------------------------------

View File

@ -1,10 +1,12 @@
// dear imgui, v1.89.2
// dear imgui, v1.89.4
// (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
// Set:
// #define IMGUI_DEFINE_MATH_OPERATORS
// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
// To implement maths operators for ImVec2 (disabled by default to not conflict with using IM_VEC2_CLASS_EXTRA with your own math types+operators), use:
/*
#define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui_internal.h"
*/
/*
@ -93,6 +95,12 @@ Index of this file:
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#endif
// In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h
// As they are frequently requested, we do not want to encourage to many people using imgui_internal.h
#if defined(IMGUI_DEFINE_MATH_OPERATORS) && !defined(IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED)
#error Please '#define IMGUI_DEFINE_MATH_OPERATORS' _BEFORE_ including imgui.h!
#endif
// Legacy defines
#ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Renamed in 1.74
#error Use IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
@ -118,6 +126,7 @@ struct ImDrawListSharedData; // Data shared between all ImDrawList instan
struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataVarInfo; // Variable information (e.g. to avoid style variables from an enum)
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
@ -316,8 +325,8 @@ namespace ImStb
//-----------------------------------------------------------------------------
// Helpers: Hashing
IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImU32 seed = 0);
IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImU32 seed = 0);
IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImGuiID seed = 0);
IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImGuiID seed = 0);
// Helpers: Sorting
#ifndef ImQsort
@ -372,29 +381,6 @@ IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char
IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
// Helpers: ImVec2/ImVec4 operators
// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)
// 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
IM_MSVC_RUNTIME_CHECKS_OFF
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
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*=(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; }
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; }
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
IM_MSVC_RUNTIME_CHECKS_RESTORE
#endif
// Helpers: File System
#ifdef IMGUI_DISABLE_FILE_FUNCTIONS
#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
@ -548,9 +534,12 @@ struct IMGUI_API ImRect
bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
};
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Helper: ImBitArray
#define IM_BITARRAY_TESTBIT(_ARRAY, _N) ((_ARRAY[(_N) >> 5] & ((ImU32)1 << ((_N) & 31))) != 0) // Macro version of ImBitArrayTestBit(): ensure args have side-effect or are costly!
#define IM_BITARRAY_CLEARBIT(_ARRAY, _N) ((_ARRAY[(_N) >> 5] &= ~((ImU32)1 << ((_N) & 31)))) // Macro version of ImBitArrayClearBit(): ensure args have side-effect or are costly!
inline size_t ImBitArrayGetStorageSizeInBytes(int bitcount) { return (size_t)((bitcount + 31) >> 5) << 2; }
inline void ImBitArrayClearAllBits(ImU32* arr, int bitcount){ memset(arr, 0, ImBitArrayGetStorageSizeInBytes(bitcount)); }
inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; }
inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; }
inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; }
@ -567,6 +556,8 @@ inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on ran
}
}
typedef ImU32* ImBitArrayPtr; // Name for use in structs
// Helper: ImBitArray class (wrapper over ImBitArray functions)
// Store 1-bit per value.
template<int BITCOUNT, int OFFSET = 0>
@ -576,11 +567,11 @@ struct ImBitArray
ImBitArray() { ClearAllBits(); }
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); }
void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); }
void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); }
};
// Helper: ImBitVector
@ -590,10 +581,11 @@ struct IMGUI_API ImBitVector
ImVector<ImU32> Storage;
void Create(int sz) { Storage.resize((sz + 31) >> 5); memset(Storage.Data, 0, (size_t)Storage.Size * sizeof(Storage.Data[0])); }
void Clear() { Storage.clear(); }
bool TestBit(int n) const { IM_ASSERT(n < (Storage.Size << 5)); return ImBitArrayTestBit(Storage.Data, n); }
bool TestBit(int n) const { IM_ASSERT(n < (Storage.Size << 5)); return IM_BITARRAY_TESTBIT(Storage.Data, n); }
void SetBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArraySetBit(Storage.Data, n); }
void ClearBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArrayClearBit(Storage.Data, n); }
};
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Helper: ImSpan<>
// Pointing to a span of data we don't own.
@ -797,10 +789,10 @@ enum ImGuiItemFlags_
{
// Controlled by user
ImGuiItemFlags_None = 0,
ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing (FIXME: should merge with _NoNav)
ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav.
ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211
ImGuiItemFlags_NoNav = 1 << 3, // false // Disable keyboard/gamepad directional navigation (FIXME: should merge with _NoTabStop)
ImGuiItemFlags_NoNav = 1 << 3, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls)
ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items)
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window
ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
@ -827,11 +819,13 @@ enum ImGuiItemStatusFlags_
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon)
ImGuiItemStatusFlags_Visible = 1 << 9, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()).
// Additional status + semantic for ImGuiTestEngine
#ifdef IMGUI_ENABLE_TEST_ENGINE
ImGuiItemStatusFlags_Openable = 1 << 20, // Item is an openable (e.g. TreeNode)
ImGuiItemStatusFlags_Opened = 1 << 21, //
ImGuiItemStatusFlags_Opened = 1 << 21, // Opened status
ImGuiItemStatusFlags_Checkable = 1 << 22, // Item is a checkable (e.g. CheckBox, MenuItem)
ImGuiItemStatusFlags_Checked = 1 << 23, //
ImGuiItemStatusFlags_Checked = 1 << 23, // Checked status
ImGuiItemStatusFlags_Inputable = 1 << 24, // Item is a text-inputable (e.g. InputText, SliderXXX, DragXXX)
#endif
};
@ -960,6 +954,14 @@ enum ImGuiPopupPositionPolicy
ImGuiPopupPositionPolicy_Tooltip,
};
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeTempStorage
{
ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
@ -1050,7 +1052,7 @@ struct IMGUI_API ImGuiMenuColumns
// For a given item ID, access with ImGui::GetInputTextState()
struct IMGUI_API ImGuiInputTextState
{
ImGuiContext* Ctx; // parent dear imgui context
ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent).
ImGuiID ID; // widget id owning the text state
int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not.
ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
@ -1066,7 +1068,7 @@ struct IMGUI_API ImGuiInputTextState
bool Edited; // edited this frame
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
ImGuiInputTextState(ImGuiContext* ctx) { memset(this, 0, sizeof(*this)); Ctx = ctx;}
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
int GetUndoAvailCount() const { return Stb.undostate.undo_point; }
@ -1180,8 +1182,8 @@ struct IMGUI_API ImGuiStackSizes
short SizeOfDisabledStack;
ImGuiStackSizes() { memset(this, 0, sizeof(*this)); }
void SetToCurrentState();
void CompareWithCurrentState();
void SetToContextState(ImGuiContext* ctx);
void CompareWithContextState(ImGuiContext* ctx);
};
// Data saved for each window pushed into the stack
@ -1212,6 +1214,7 @@ struct ImGuiPtrOrIndex
// [SECTION] Inputs support
//-----------------------------------------------------------------------------
// Bit array for named keys
typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitArrayForNamedKeys;
// [Internal] Key ranges
@ -1412,8 +1415,8 @@ struct ImGuiListClipperData
enum ImGuiActivateFlags_
{
ImGuiActivateFlags_None = 0,
ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default if keyboard is available.
ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default if keyboard is not available.
ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key.
ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used.
ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
};
@ -1599,6 +1602,7 @@ struct ImGuiWindowSettings
ImVec2ih Size;
bool Collapsed;
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
bool WantDelete; // Set to invalidate/delete the settings entry
ImGuiWindowSettings() { memset(this, 0, sizeof(*this)); }
char* GetName() { return (char*)(this + 1); }
@ -1663,23 +1667,16 @@ enum ImGuiDebugLogFlags_
struct ImGuiMetricsConfig
{
bool ShowDebugLog;
bool ShowStackTool;
bool ShowWindowsRects;
bool ShowWindowsBeginOrder;
bool ShowTablesRects;
bool ShowDrawCmdMesh;
bool ShowDrawCmdBoundingBoxes;
int ShowWindowsRectsType;
int ShowTablesRectsType;
ImGuiMetricsConfig()
{
ShowDebugLog = ShowStackTool = ShowWindowsRects = ShowWindowsBeginOrder = ShowTablesRects = false;
ShowDrawCmdMesh = true;
ShowDrawCmdBoundingBoxes = true;
ShowWindowsRectsType = ShowTablesRectsType = -1;
}
bool ShowDebugLog = false;
bool ShowStackTool = false;
bool ShowWindowsRects = false;
bool ShowWindowsBeginOrder = false;
bool ShowTablesRects = false;
bool ShowDrawCmdMesh = true;
bool ShowDrawCmdBoundingBoxes = true;
bool ShowAtlasTintedWithTextColor = false;
int ShowWindowsRectsType = -1;
int ShowTablesRectsType = -1;
};
struct ImGuiStackLevelInfo
@ -1836,10 +1833,9 @@ struct ImGuiContext
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set)
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiID NavActivateInputId; // ~~ IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadInput) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiActivateFlags NavActivateFlags;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
@ -1943,9 +1939,11 @@ struct ImGuiContext
ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
float ColorEditLastHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips
float ColorEditLastSat; // Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips
ImU32 ColorEditLastColor; // RGB value with alpha set to 0.
ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others).
ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for
float ColorEditSavedHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips
float ColorEditSavedSat; // Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips
ImU32 ColorEditSavedColor; // RGB value with alpha set to 0.
ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.
ImGuiComboPreviewData ComboPreviewData;
float SliderGrabClickOffset;
@ -1996,7 +1994,9 @@ struct ImGuiContext
ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf;
ImGuiTextIndex DebugLogIndex;
ImU8 DebugLogClipperAutoDisableFrames;
ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above.
ImS8 DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around.
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
ImU8 DebugItemPickerMouseButton;
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID
@ -2014,8 +2014,10 @@ struct ImGuiContext
ImVector<char> TempBuffer; // Temporary text buffer
ImGuiContext(ImFontAtlas* shared_font_atlas)
: InputTextState(this)
{
IO.Ctx = this;
InputTextState.Ctx = this;
Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL;
@ -2074,7 +2076,7 @@ struct ImGuiContext
BeginMenuCount = 0;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiMod_None;
@ -2131,8 +2133,9 @@ struct ImGuiContext
TempInputId = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditLastHue = ColorEditLastSat = 0.0f;
ColorEditLastColor = 0;
ColorEditCurrentID = ColorEditSavedID = 0;
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
ColorEditSavedColor = 0;
SliderGrabClickOffset = 0.0f;
SliderCurrentAccum = 0.0f;
SliderCurrentAccumDirty = false;
@ -2165,7 +2168,9 @@ struct ImGuiContext
DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
DebugLocateId = 0;
DebugLogClipperAutoDisableFrames = 0;
DebugLocateFrames = 0;
DebugBeginReturnValueCullDepth = -1;
DebugItemPickerActive = false;
DebugItemPickerMouseButton = ImGuiMouseButton_Left;
DebugItemPickerBreakId = 0;
@ -2234,6 +2239,7 @@ struct IMGUI_API ImGuiWindowTempData
// Storage for one window
struct IMGUI_API ImGuiWindow
{
ImGuiContext* Ctx; // Parent UI context (needs to be set explicitly by parent).
char* Name; // Window name, owned by the window.
ImGuiID ID; // == ImHashStr(Name)
ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
@ -2344,10 +2350,10 @@ public:
// We don't use g.FontSize because the window may be != g.CurrentWindow.
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; }
float CalcFontSize() const { ImGuiContext& g = *Ctx; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; }
float MenuBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
};
@ -2384,7 +2390,7 @@ struct ImGuiTabItem
float RequestedWidth; // Width optionally requested by caller, -1.0f is unused
ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames
ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable
ImS16 IndexDuringLayout; // Index only used during TabBarLayout()
ImS16 IndexDuringLayout; // Index only used during TabBarLayout(). Tabs gets reordered so 'Tabs[n].IndexDuringLayout == n' but may mismatch during additions.
bool WantClose; // Marked as closed by SetTabItemClosed()
ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
@ -2426,12 +2432,6 @@ struct IMGUI_API ImGuiTabBar
ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer.
ImGuiTabBar();
int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); }
const char* GetTabName(const ImGuiTabItem* tab) const
{
IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < TabsNames.Buf.Size);
return TabsNames.Buf.Data + tab->NameOffset;
}
};
//-----------------------------------------------------------------------------
@ -2439,12 +2439,11 @@ struct IMGUI_API ImGuiTabBar
//-----------------------------------------------------------------------------
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableSetupDrawChannels()
#define IMGUI_TABLE_MAX_COLUMNS 512 // May be further lifted
// Our current column maximum is 64 but we may raise that in the future.
typedef ImS8 ImGuiTableColumnIdx;
typedef ImU8 ImGuiTableDrawChannelIdx;
typedef ImS16 ImGuiTableColumnIdx;
typedef ImU16 ImGuiTableDrawChannelIdx;
// [Internal] sizeof() ~ 104
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
@ -2515,14 +2514,15 @@ struct ImGuiTableCellData
ImGuiTableColumnIdx Column; // Column number
};
// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs, does that needs they could be moved to ImGuiTableTempData ?)
// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs. Does that means they could be moved to ImGuiTableTempData?)
struct ImGuiTableInstanceData
{
ImGuiID TableInstanceID;
float LastOuterHeight; // Outer height from last frame
float LastFirstRowHeight; // Height of first row from last frame (FIXME: this is used as "header height" and may be reworked)
float LastFrozenHeight; // Height of frozen section from last frame
ImGuiTableInstanceData() { LastOuterHeight = LastFirstRowHeight = LastFrozenHeight = 0.0f; }
ImGuiTableInstanceData() { TableInstanceID = 0; LastOuterHeight = LastFirstRowHeight = LastFrozenHeight = 0.0f; }
};
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData
@ -2535,10 +2535,9 @@ struct IMGUI_API ImGuiTable
ImSpan<ImGuiTableColumn> Columns; // Point within RawData[]
ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1)
ImSpan<ImGuiTableCellData> RowCellData; // Point within RawData[]. Store cells background requests for current row.
ImU64 EnabledMaskByDisplayOrder; // Column DisplayOrder -> IsEnabled map
ImU64 EnabledMaskByIndex; // Column Index -> IsEnabled map (== not hidden by user/api) in a format adequate for iterating column without touching cold data
ImU64 VisibleMaskByIndex; // Column Index -> IsVisibleX|IsVisibleY map (== not hidden by user/api && not hidden by scrolling/cliprect)
ImU64 RequestOutputMaskByIndex; // Column Index -> IsVisible || AutoFit (== expect user to submit items)
ImBitArrayPtr EnabledMaskByDisplayOrder; // Column DisplayOrder -> IsEnabled map
ImBitArrayPtr EnabledMaskByIndex; // Column Index -> IsEnabled map (== not hidden by user/api) in a format adequate for iterating column without touching cold data
ImBitArrayPtr VisibleMaskByIndex; // Column Index -> IsVisibleX|IsVisibleY map (== not hidden by user/api && not hidden by scrolling/cliprect)
ImGuiTableFlags SettingsLoadedFlags; // Which data were loaded from the .ini file (e.g. when order is not altered we won't save order)
int SettingsOffset; // Offset in g.SettingsTables
int LastFrameActive;
@ -2726,6 +2725,7 @@ namespace ImGui
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);
IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);
IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
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 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); }
@ -2769,13 +2769,16 @@ namespace ImGui
IMGUI_API void MarkIniSettingsDirty();
IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
IMGUI_API void ClearIniSettings();
IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name);
IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);
IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name);
IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler);
IMGUI_API void RemoveSettingsHandler(const char* type_name);
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
// Settings - Windows
IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name);
IMGUI_API ImGuiWindowSettings* FindWindowSettingsByID(ImGuiID id);
IMGUI_API ImGuiWindowSettings* FindWindowSettingsByWindow(ImGuiWindow* window);
IMGUI_API void ClearWindowSettings(const char* name);
// Localization
IMGUI_API void LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count);
inline const char* LocalizeGetMsg(ImGuiLocKey key) { ImGuiContext& g = *GImGui; const char* msg = g.LocalizationTable[key]; return msg ? msg : "*Missing Text*"; }
@ -2808,6 +2811,7 @@ namespace ImGui
IMGUI_API void MarkItemEdited(ImGuiID id); // Mark data associated to given item as "edited", used by IsItemDeactivatedAfterEdit() function.
IMGUI_API void PushOverrideID(ImGuiID id); // Push given value as-is at the top of the ID stack (whereas PushID combines old and new hashes)
IMGUI_API ImGuiID GetIDWithSeed(const char* str_id_begin, const char* str_id_end, ImGuiID seed);
IMGUI_API ImGuiID GetIDWithSeed(int n, ImGuiID seed);
// Basic Helpers for widget code
IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);
@ -2826,6 +2830,7 @@ namespace ImGui
// Parameter stacks (shared)
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
// Logging/Capture
IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
@ -2841,7 +2846,7 @@ namespace ImGui
IMGUI_API void ClosePopupsExceptModals();
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
IMGUI_API void BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
@ -3003,7 +3008,8 @@ namespace ImGui
IMGUI_API void TableDrawContextMenu(ImGuiTable* table);
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; }
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
@ -3015,7 +3021,7 @@ namespace ImGui
IMGUI_API void TableEndCell(ImGuiTable* table);
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0);
IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
@ -3034,12 +3040,18 @@ namespace ImGui
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
// Tab Bars
inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API ImGuiTabItem* TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order);
IMGUI_API ImGuiTabItem* TabBarGetCurrentTab(ImGuiTabBar* tab_bar);
inline int TabBarGetTabOrder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { return tab_bar->Tabs.index_from_ptr(tab); }
IMGUI_API const char* TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset);
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, ImVec2 mouse_pos);
IMGUI_API void TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset);
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos);
IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar);
IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window);
IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker);
@ -3074,8 +3086,9 @@ namespace ImGui
IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags 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 ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col);
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 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, ImU64* flags, ImU64 flags_value);
@ -3130,7 +3143,7 @@ namespace ImGui
IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags);
// Plot
IMGUI_API int PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size);
IMGUI_API int PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg);
// Shade functions (write over already created vertices)
IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
@ -3182,7 +3195,7 @@ namespace ImGui
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
// (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP)
// (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))' (WIP)
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()
inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd()
inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
@ -3222,14 +3235,15 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table
//-----------------------------------------------------------------------------
#ifdef IMGUI_ENABLE_TEST_ENGINE
extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, ImGuiID id, const ImRect& bb, const ImGuiLastItemData* item_data); // item_data may be NULL
extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags);
extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...);
extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiID id);
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
// In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data);
#define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _ID, _BB, _ITEM_DATA) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
#else
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.2
// dear imgui, v1.89.4
// (tables and columns code)
/*
@ -188,12 +188,12 @@ Index of this file:
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_internal.h"
// System includes
@ -315,7 +315,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
return false;
// Sanity checks
IM_ASSERT(columns_count > 0 && columns_count <= IMGUI_TABLE_MAX_COLUMNS && "Only 1..64 columns allowed!");
IM_ASSERT(columns_count > 0 && columns_count < IMGUI_TABLE_MAX_COLUMNS);
if (flags & ImGuiTableFlags_ScrollX)
IM_ASSERT(inner_width >= 0.0f);
@ -332,11 +332,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Acquire storage for the table
ImGuiTable* table = g.Tables.GetOrAddByKey(id);
const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
const ImGuiID instance_id = id + instance_no;
const ImGuiTableFlags table_last_flags = table->Flags;
if (instance_no > 0)
IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
// Acquire temporary buffers
const int table_idx = g.Tables.GetIndex(table);
@ -352,17 +348,32 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
flags = TableFixFlags(flags, outer_window);
// Initialize
const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
table->ID = id;
table->Flags = flags;
table->InstanceCurrent = (ImS16)instance_no;
table->LastFrameActive = g.FrameCount;
table->OuterWindow = table->InnerWindow = outer_window;
table->ColumnsCount = columns_count;
table->IsLayoutLocked = false;
table->InnerWidth = inner_width;
temp_data->UserOuterSize = outer_size;
if (instance_no > 0 && table->InstanceDataExtra.Size < instance_no)
table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
// Instance data (for instance 0, TableID == TableInstanceID)
ImGuiID instance_id;
table->InstanceCurrent = (ImS16)instance_no;
if (instance_no > 0)
{
IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
if (table->InstanceDataExtra.Size < instance_no)
table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instance" followed by (int)instance_no in ID stack.
}
else
{
instance_id = id;
}
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
table_instance->TableInstanceID = instance_id;
// When not using a child window, WorkRect.Max will grow as we append contents.
if (use_child_window)
@ -412,7 +423,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
}
// Push a standardized ID for both child-using and not-child-using tables
PushOverrideID(instance_id);
PushOverrideID(id);
if (instance_no > 0)
PushOverrideID(instance_id); // FIXME: Somehow this is not resolved by stack-tool, even tho GetIDWithSeed() submitted the symbol.
// Backup a copy of host window members we will modify
ImGuiWindow* inner_window = table->InnerWindow;
@ -581,16 +594,22 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
{
// Allocate single buffer for our arrays
ImSpanAllocator<3> span_allocator;
const int columns_bit_array_size = (int)ImBitArrayGetStorageSizeInBytes(columns_count);
ImSpanAllocator<6> span_allocator;
span_allocator.Reserve(0, columns_count * sizeof(ImGuiTableColumn));
span_allocator.Reserve(1, columns_count * sizeof(ImGuiTableColumnIdx));
span_allocator.Reserve(2, columns_count * sizeof(ImGuiTableCellData), 4);
for (int n = 3; n < 6; n++)
span_allocator.Reserve(n, columns_bit_array_size);
table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes());
memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes());
span_allocator.SetArenaBasePtr(table->RawData);
span_allocator.GetSpan(0, &table->Columns);
span_allocator.GetSpan(1, &table->DisplayOrderToIndex);
span_allocator.GetSpan(2, &table->RowCellData);
table->EnabledMaskByDisplayOrder = (ImU32*)span_allocator.GetSpanPtrBegin(3);
table->EnabledMaskByIndex = (ImU32*)span_allocator.GetSpanPtrBegin(4);
table->VisibleMaskByIndex = (ImU32*)span_allocator.GetSpanPtrBegin(5);
}
// Apply queued resizing/reordering/hiding requests
@ -729,8 +748,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
table->IsDefaultDisplayOrder = true;
table->ColumnsEnabledCount = 0;
table->EnabledMaskByIndex = 0x00;
table->EnabledMaskByDisplayOrder = 0x00;
ImBitArrayClearAllBits(table->EnabledMaskByIndex, table->ColumnsCount);
ImBitArrayClearAllBits(table->EnabledMaskByDisplayOrder, table->ColumnsCount);
table->LeftMostEnabledColumn = -1;
table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
@ -795,8 +814,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
else
table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n;
column->IndexWithinEnabledSet = table->ColumnsEnabledCount++;
table->EnabledMaskByIndex |= (ImU64)1 << column_n;
table->EnabledMaskByDisplayOrder |= (ImU64)1 << column->DisplayOrder;
ImBitArraySetBit(table->EnabledMaskByIndex, column_n);
ImBitArraySetBit(table->EnabledMaskByDisplayOrder, column->DisplayOrder);
prev_visible_column_idx = column_n;
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
@ -844,7 +863,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
@ -860,7 +879,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
if (column->AutoFitQueue != 0x00)
column->WidthRequest = width_auto;
else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)))
else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && column->IsRequestOutput)
column->WidthRequest = width_auto;
// FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
@ -908,7 +927,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
@ -935,7 +954,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths))
for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--)
{
if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
continue;
ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]];
if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch))
@ -966,8 +985,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
ImRect host_clip_rect = table->InnerClipRect;
//host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2;
table->VisibleMaskByIndex = 0x00;
table->RequestOutputMaskByIndex = 0x00;
ImBitArrayClearAllBits(table->VisibleMaskByIndex, table->ColumnsCount);
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
const int column_n = table->DisplayOrderToIndex[order_n];
@ -984,7 +1002,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Clear status flags
column->Flags &= ~ImGuiTableColumnFlags_StatusMask_;
if ((table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)) == 0)
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
{
// Hidden column: clear a few fields and we are done with it for the remainder of the function.
// We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper.
@ -1037,12 +1055,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y);
const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY;
if (is_visible)
table->VisibleMaskByIndex |= ((ImU64)1 << column_n);
ImBitArraySetBit(table->VisibleMaskByIndex, column_n);
// Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output.
column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0;
if (column->IsRequestOutput)
table->RequestOutputMaskByIndex |= ((ImU64)1 << column_n);
// Mark column as SkipItems (ignoring all items/layout)
column->IsSkipItems = !column->IsEnabled || table->HostSkipItems;
@ -1128,12 +1144,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
EndPopup();
}
// [Part 13] 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 change 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)
if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable))
TableSortSpecsBuild(table);
// [Part 14] Setup inner window decoration size (for scrolling / nav tracking to properly take account of frozen rows/columns)
// [Part 13] Setup inner window decoration size (for scrolling / nav tracking to properly take account of frozen rows/columns)
if (table->FreezeColumnsRequest > 0)
table->InnerWindow->DecoInnerSizeX1 = table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsRequest - 1]].MaxX - table->OuterRect.Min.x;
if (table->FreezeRowsRequest > 0)
@ -1169,7 +1185,7 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
continue;
const int column_n = table->DisplayOrderToIndex[order_n];
@ -1305,7 +1321,7 @@ void ImGui::EndTable()
float auto_fit_width_for_stretched = 0.0f;
float auto_fit_width_for_stretched_min = 0.0f;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
if (table->EnabledMaskByIndex & ((ImU64)1 << column_n))
if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n))
{
ImGuiTableColumn* column = &table->Columns[column_n];
float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column);
@ -1345,8 +1361,10 @@ void ImGui::EndTable()
}
// Pop from id stack
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table_instance->TableInstanceID, "Mismatching PushID/PopID!");
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
if (table->InstanceCurrent > 0)
PopID();
PopID();
// Restore window data that we modified
@ -1616,11 +1634,11 @@ ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n)
}
// Return the resizing ID for the right-side of the given column.
ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no)
ImGuiID ImGui::TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no)
{
IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
ImGuiID id = table->ID + 1 + (instance_no * table->ColumnsCount) + column_n;
return id;
ImGuiID instance_id = TableGetInstanceID(table, instance_no);
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.
@ -1651,7 +1669,7 @@ void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n
return;
if (column_n == -1)
column_n = table->CurrentColumn;
if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0)
if (!IM_BITARRAY_TESTBIT(table->VisibleMaskByIndex, column_n))
return;
if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n)
table->RowCellDataCurrent++;
@ -1926,7 +1944,7 @@ bool ImGui::TableSetColumnIndex(int column_n)
// Return whether the column is visible. User may choose to skip submitting items based on this return value,
// however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0;
return table->Columns[column_n].IsRequestOutput;
}
// [Public] Append into the next column, wrap and create a new row when already on last column
@ -1951,8 +1969,7 @@ bool ImGui::TableNextColumn()
// Return whether the column is visible. User may choose to skip submitting items based on this return value,
// however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
int column_n = table->CurrentColumn;
return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0;
return table->Columns[table->CurrentColumn].IsRequestOutput;
}
@ -1982,10 +1999,6 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
window->WorkRect.Max.x = column->WorkMaxX;
window->DC.ItemWidth = column->ItemWidth;
// To allow ImGuiListClipper to function we propagate our row height
if (!column->IsEnabled)
window->DC.CursorPos.y = ImMax(window->DC.CursorPos.y, table->RowPosY2);
window->SkipItems = column->IsSkipItems;
if (column->IsSkipItems)
{
@ -2032,7 +2045,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
else
p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
*p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
if (column->IsEnabled)
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
column->ItemWidth = window->DC.ItemWidth;
// Propagate text baseline for the entire row
@ -2292,7 +2306,7 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
const int freeze_row_multiplier = (table->FreezeRowsCount > 0) ? 2 : 1;
const int channels_for_row = (table->Flags & ImGuiTableFlags_NoClip) ? 1 : table->ColumnsEnabledCount;
const int channels_for_bg = 1 + 1 * freeze_row_multiplier;
const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || table->VisibleMaskByIndex != table->EnabledMaskByIndex) ? +1 : 0;
const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || (memcmp(table->VisibleMaskByIndex, table->EnabledMaskByIndex, ImBitArrayGetStorageSizeInBytes(table->ColumnsCount)) != 0)) ? +1 : 0;
const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy;
table->DrawSplitter->Split(table->InnerWindow->DrawList, channels_total);
table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1);
@ -2366,19 +2380,26 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
// Track which groups we are going to attempt to merge, and which channels goes into each group.
struct MergeGroup
{
ImRect ClipRect;
int ChannelsCount;
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask;
MergeGroup() { ChannelsCount = 0; }
ImRect ClipRect;
int ChannelsCount;
ImBitArrayPtr ChannelsMask;
};
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.
const int max_draw_channels = (4 + table->ColumnsCount * 2);
const int size_for_masks_bitarrays_one = (int)ImBitArrayGetStorageSizeInBytes(max_draw_channels);
g.TempBuffer.reserve(size_for_masks_bitarrays_one * 5);
memset(g.TempBuffer.Data, 0, size_for_masks_bitarrays_one * 5);
for (int n = 0; n < IM_ARRAYSIZE(merge_groups); n++)
merge_groups[n].ChannelsMask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * n));
ImBitArrayPtr remaining_mask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * 4));
// 1. Scan channels and take note of those which can be merged
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{
if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0)
if (!IM_BITARRAY_TESTBIT(table->VisibleMaskByIndex, column_n))
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
@ -2410,11 +2431,11 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
}
const int merge_group_n = (has_freeze_h && column_n < table->FreezeColumnsCount ? 0 : 1) + (has_freeze_v && merge_group_sub_n == 0 ? 0 : 2);
IM_ASSERT(channel_no < IMGUI_TABLE_MAX_DRAW_CHANNELS);
IM_ASSERT(channel_no < max_draw_channels);
MergeGroup* merge_group = &merge_groups[merge_group_n];
if (merge_group->ChannelsCount == 0)
merge_group->ClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
merge_group->ChannelsMask.SetBit(channel_no);
ImBitArraySetBit(merge_group->ChannelsMask, channel_no);
merge_group->ChannelsCount++;
merge_group->ClipRect.Add(src_channel->_CmdBuffer[0].ClipRect);
merge_group_mask |= (1 << merge_group_n);
@ -2450,9 +2471,8 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
const int LEADING_DRAW_CHANNELS = 2;
g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized
ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data;
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> remaining_mask; // We need 132-bit of storage
remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count);
remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen);
ImBitArraySetBitRange(remaining_mask, LEADING_DRAW_CHANNELS, splitter->_Count);
ImBitArrayClearBit(remaining_mask, table->Bg2DrawChannelUnfrozen);
IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN);
int remaining_count = splitter->_Count - (has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS);
//ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect;
@ -2485,14 +2505,14 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
#endif
remaining_count -= merge_group->ChannelsCount;
for (int n = 0; n < IM_ARRAYSIZE(remaining_mask.Storage); n++)
remaining_mask.Storage[n] &= ~merge_group->ChannelsMask.Storage[n];
for (int n = 0; n < (size_for_masks_bitarrays_one >> 2); n++)
remaining_mask[n] &= ~merge_group->ChannelsMask[n];
for (int n = 0; n < splitter->_Count && merge_channels_count != 0; n++)
{
// Copy + overwrite new clip rect
if (!merge_group->ChannelsMask.TestBit(n))
if (!IM_BITARRAY_TESTBIT(merge_group->ChannelsMask, n))
continue;
merge_group->ChannelsMask.ClearBit(n);
IM_BITARRAY_CLEARBIT(merge_group->ChannelsMask, n);
merge_channels_count--;
ImDrawChannel* channel = &splitter->_Channels[n];
@ -2510,7 +2530,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
// Append unmergeable channels that we didn't reorder at the end of the list
for (int n = 0; n < splitter->_Count && remaining_count != 0; n++)
{
if (!remaining_mask.TestBit(n))
if (!IM_BITARRAY_TESTBIT(remaining_mask, n))
continue;
ImDrawChannel* channel = &splitter->_Channels[n];
memcpy(dst_tmp++, channel, sizeof(ImDrawChannel));
@ -2542,7 +2562,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
{
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n))
continue;
const int column_n = table->DisplayOrderToIndex[order_n];
@ -2870,10 +2890,9 @@ void ImGui::TableHeadersRow()
continue;
// Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them)
// - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide
// - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier.
// In your own code you may omit the PushID/PopID all-together, provided you know they won't collide.
const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n);
PushID(table->InstanceCurrent * table->ColumnsCount + column_n);
PushID(column_n);
TableHeader(name);
PopID();
}

View File

@ -1,4 +1,4 @@
// dear imgui, v1.89.2
// dear imgui, v1.89.4
// (widgets code)
/*
@ -32,12 +32,12 @@ Index of this file:
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_internal.h"
// System includes
@ -274,7 +274,6 @@ void ImGui::TextV(const char* fmt, va_list args)
if (window->SkipItems)
return;
// FIXME-OPT: Handle the %s shortcut?
const char* text, *text_end;
ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
@ -291,10 +290,7 @@ void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
{
PushStyleColor(ImGuiCol_Text, col);
if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
else
TextV(fmt, args);
TextV(fmt, args);
PopStyleColor();
}
@ -310,10 +306,7 @@ void ImGui::TextDisabledV(const char* fmt, va_list args)
{
ImGuiContext& g = *GImGui;
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
else
TextV(fmt, args);
TextV(fmt, args);
PopStyleColor();
}
@ -328,13 +321,10 @@ void ImGui::TextWrapped(const char* fmt, ...)
void ImGui::TextWrappedV(const char* fmt, va_list args)
{
ImGuiContext& g = *GImGui;
bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
const bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
if (need_backup)
PushTextWrapPos(0.0f);
if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
else
TextV(fmt, args);
TextV(fmt, args);
if (need_backup)
PopTextWrapPos();
}
@ -508,8 +498,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
g.HoveredWindow = window;
#ifdef IMGUI_ENABLE_TEST_ENGINE
// Alternate registration spot, for when caller didn't use ItemAdd()
if (id != 0 && g.LastItemData.ID != id)
IMGUI_TEST_ENGINE_ITEM_ADD(bb, id);
IMGUI_TEST_ENGINE_ITEM_ADD(id, bb, NULL);
#endif
bool pressed = false;
@ -619,10 +610,11 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
bool nav_activated_by_inputs = (g.NavActivatePressedId == id);
if (!nav_activated_by_inputs && (flags & ImGuiButtonFlags_Repeat))
{
// Avoid pressing both keys from triggering double amount of repeat events
// Avoid pressing multiple keys from triggering excessive amount of repeat events
const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(key1->DownDuration, key2->DownDuration);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter);
const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration);
nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
}
if (nav_activated_by_code || nav_activated_by_inputs)
@ -1042,7 +1034,7 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2&
// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
bool ImGui::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)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -1056,7 +1048,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size
return false;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
@ -1394,6 +1386,7 @@ void ImGui::AlignTextToFramePadding()
}
// Horizontal/vertical separating line
// FIXME: Surprisingly, this seemingly simple widget is adjacent to MANY different legacy/tricky layout issues.
void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
{
ImGuiWindow* window = GetCurrentWindow();
@ -1403,20 +1396,19 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
ImGuiContext& g = *GImGui;
IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
float thickness_draw = 1.0f;
float thickness_layout = 0.0f;
const float thickness = 1.0f; // Cannot use g.Style.SeparatorTextSize yet for various reasons.
if (flags & ImGuiSeparatorFlags_Vertical)
{
// Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
// Vertical separator, for menu bars (use current line height).
float y1 = window->DC.CursorPos.y;
float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y;
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2));
ItemSize(ImVec2(thickness_layout, 0.0f));
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness, y2));
ItemSize(ImVec2(thickness, 0.0f));
if (!ItemAdd(bb, 0))
return;
// Draw
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator));
if (g.LogEnabled)
LogText(" |");
}
@ -1444,13 +1436,14 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell)
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
ItemSize(ImVec2(0.0f, thickness_layout));
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));
ItemSize(ImVec2(0.0f, thickness_for_layout));
const bool item_visible = ItemAdd(bb, 0);
if (item_visible)
{
// Draw
window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator));
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator));
if (g.LogEnabled)
LogRenderedText(&bb.Min, "--------------------------------\n");
@ -1476,6 +1469,71 @@ void ImGui::Separator()
SeparatorEx(flags);
}
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStyle& style = g.Style;
const ImVec2 label_size = CalcTextSize(label, label_end, false);
const ImVec2 pos = window->DC.CursorPos;
const ImVec2 padding = style.SeparatorTextPadding;
const float separator_thickness = style.SeparatorTextBorderSize;
const ImVec2 min_size(label_size.x + extra_w + padding.x * 2.0f, ImMax(label_size.y + padding.y * 2.0f, separator_thickness));
const ImRect bb(pos, ImVec2(window->WorkRect.Max.x, pos.y + min_size.y));
const float text_baseline_y = ImFloor((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.99999f); //ImMax(padding.y, ImFloor((style.SeparatorTextSize - label_size.y) * 0.5f));
ItemSize(min_size, text_baseline_y);
if (!ItemAdd(bb, id))
return;
const float sep1_x1 = pos.x;
const float sep2_x2 = bb.Max.x;
const float seps_y = ImFloor((bb.Min.y + bb.Max.y) * 0.5f + 0.99999f);
const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f);
const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN
// This allows using SameLine() to position something in the 'extra_w'
window->DC.CursorPosPrevLine.x = label_pos.x + label_size.x;
const ImU32 separator_col = GetColorU32(ImGuiCol_Separator);
if (label_size.x > 0.0f)
{
const float sep1_x2 = label_pos.x - style.ItemSpacing.x;
const float sep2_x1 = label_pos.x + label_size.x + extra_w + style.ItemSpacing.x;
if (sep1_x2 > sep1_x1 && separator_thickness > 0.0f)
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep1_x2, seps_y), separator_col, separator_thickness);
if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f)
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
if (g.LogEnabled)
LogSetNextTextDecoration("---", NULL);
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, bb.Max.x, label, label_end, &label_size);
}
else
{
if (g.LogEnabled)
LogText("---");
if (separator_thickness > 0.0f)
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
}
}
void ImGui::SeparatorText(const char* label)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
// 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)
// - this high-level entry point to allow formatting? (may require ID separate from formatted string)
// - 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,
// and then we can turn this into a format function.
SeparatorTextEx(0, label, FindRenderedTextEnd(label), 0.0f);
}
// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay, ImU32 bg_col)
{
@ -1705,7 +1763,12 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
ImVec2 constraint_min(0.0f, 0.0f), constraint_max(FLT_MAX, FLT_MAX);
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size
constraint_min.x = w;
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f)
constraint_max.y = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items);
SetNextWindowSizeConstraints(constraint_min, constraint_max);
}
// This is essentially a specialized version of BeginPopupEx()
@ -2349,18 +2412,18 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = hovered && IsMouseClicked(0, id);
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id));
const bool make_active = (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id);
const bool make_active = (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id);
if (make_active && (clicked || double_clicked))
SetKeyOwner(ImGuiKey_MouseLeft, id);
if (make_active && temp_input_allowed)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true;
// (Optional) simple click (without moving) turns Drag into an InputText
if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active)
if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
{
g.NavActivateId = g.NavActivateInputId = id;
g.NavActivateId = id;
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
temp_input_is_active = true;
}
@ -2401,7 +2464,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
return value_changed;
}
@ -2941,11 +3004,11 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
// Tabbing or CTRL-clicking on Slider turns it into an input box
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = hovered && IsMouseClicked(0, id);
const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id);
const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id);
if (make_active && clicked)
SetKeyOwner(ImGuiKey_MouseLeft, id);
if (make_active && temp_input_allowed)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true;
if (make_active && !temp_input_is_active)
@ -2989,7 +3052,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
return value_changed;
}
@ -3103,7 +3166,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
const bool hovered = ItemHoverable(frame_bb, id);
const bool clicked = hovered && IsMouseClicked(0, id);
if (clicked || g.NavActivateId == id || g.NavActivateInputId == id)
if (clicked || g.NavActivateId == id)
{
if (clicked)
SetKeyOwner(ImGuiKey_MouseLeft, id);
@ -3396,7 +3459,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags);
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
// Step buttons
const ImVec2 backup_frame_padding = style.FramePadding;
@ -3780,7 +3843,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
return;
// Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!)
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
ImGuiInputTextState* edit_state = &g.InputTextState;
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
IM_ASSERT(Buf == edit_state->TextA.Data);
@ -3884,8 +3947,9 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
// Custom callback filter
if (flags & ImGuiInputTextFlags_CallbackCharFilter)
{
ImGuiContext& g = *GImGui;
ImGuiInputTextCallbackData callback_data;
memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
callback_data.Ctx = &g;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
callback_data.EventChar = (ImWchar)c;
callback_data.Flags = flags;
@ -4030,7 +4094,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImGuiInputTextState* state = GetInputTextState(id);
const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
const bool user_clicked = hovered && io.MouseClicked[0];
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
@ -4096,6 +4160,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
}
const bool is_osx = io.ConfigMacOSXBehaviors;
if (g.ActiveId != id && init_make_active)
{
IM_ASSERT(state && state->ID == id);
@ -4118,8 +4183,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
SetKeyOwner(ImGuiKey_PageUp, id);
SetKeyOwner(ImGuiKey_PageDown, id);
}
if (is_osx)
SetKeyOwner(ImGuiMod_Alt, id);
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
SetKeyOwner(ImGuiKey_Tab, id);
SetShortcutRouting(ImGuiKey_Tab, id);
}
// We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
@ -4187,7 +4254,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
const bool is_osx = io.ConfigMacOSXBehaviors;
if (select_all)
{
state->SelectAll();
@ -4250,8 +4316,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We expect backends to emit a Tab key but some also emit a Tab character which we ignore (#2467, #1336)
// (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes)
const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressed(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly)
if ((flags & ImGuiInputTextFlags_AllowTabInput) && Shortcut(ImGuiKey_Tab, id) && !is_readonly)
{
unsigned int c = '\t'; // Insert TAB
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
@ -4260,6 +4325,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Process regular text input (before we check for Return because using some IME will effectively send a Return?)
// We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
if (io.InputQueueCharacters.Size > 0)
{
if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav)
@ -4288,7 +4354,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->Stb.row_count_per_page = row_count_per_page;
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
const bool is_osx = io.ConfigMacOSXBehaviors;
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
@ -4317,7 +4382,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut)
{
if (!state->HasSelection())
{
// OSX doesn't seem to have Super+Delete to delete until end-of-line, so we don't emulate that (as opposed to Super+Backspace)
if (is_wordmove_key_down)
state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
}
state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask);
}
else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly)
{
if (!state->HasSelection())
@ -4407,12 +4481,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const int clipboard_len = (int)strlen(clipboard);
ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar));
int clipboard_filtered_len = 0;
for (const char* s = clipboard; *s; )
for (const char* s = clipboard; *s != 0; )
{
unsigned int c;
s += ImTextCharFromUtf8(&c, s, NULL);
if (c == 0)
break;
if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard))
continue;
clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
@ -4490,7 +4562,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
ImGuiInputTextFlags event_flag = 0;
ImGuiKey event_key = ImGuiKey_None;
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressed(ImGuiKey_Tab))
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && Shortcut(ImGuiKey_Tab, id))
{
event_flag = ImGuiInputTextFlags_CallbackCompletion;
event_key = ImGuiKey_Tab;
@ -4517,7 +4589,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (event_flag)
{
ImGuiInputTextCallbackData callback_data;
memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
callback_data.Ctx = &g;
callback_data.EventFlag = event_flag;
callback_data.Flags = flags;
callback_data.UserData = callback_user_data;
@ -4580,6 +4652,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_resizable)
{
ImGuiInputTextCallbackData callback_data;
callback_data.Ctx = &g;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
callback_data.Flags = flags;
callback_data.Buf = buf;
@ -4846,7 +4919,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
MarkItemEdited(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
return validated;
else
@ -4861,7 +4934,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
ImStb::StbUndoState* undo_state = &stb_state->undostate;
Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
DebugLocateItemOnHover(state->ID);
Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, state->CurLenW, stb_state->cursor, stb_state->select_start, stb_state->select_end);
Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 15), true)) // Visualize undo state
@ -4909,28 +4982,32 @@ bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flag
return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);
}
static void ColorEditRestoreH(const float* col, float* H)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.ColorEditCurrentID != 0);
if (g.ColorEditSavedID != g.ColorEditCurrentID || g.ColorEditSavedColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
return;
*H = g.ColorEditSavedHue;
}
// ColorEdit supports RGB and HSV inputs. In case of RGB input resulting color may have undefined hue and/or saturation.
// Since widget displays both RGB and HSV values we must preserve hue and saturation to prevent these values resetting.
static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V)
{
// This check is optional. Suppose we have two color widgets side by side, both widgets display different colors, but both colors have hue and/or saturation undefined.
// With color check: hue/saturation is preserved in one widget. Editing color in one widget would reset hue/saturation in another one.
// Without color check: common hue/saturation would be displayed in all widgets that have hue/saturation undefined.
// g.ColorEditLastColor is stored as ImU32 RGB value: this essentially gives us color equality check with reduced precision.
// Tiny external color changes would not be detected and this check would still pass. This is OK, since we only restore hue/saturation _only_ if they are undefined,
// therefore this change flipping hue/saturation from undefined to a very tiny value would still be represented in color picker.
ImGuiContext& g = *GImGui;
if (g.ColorEditLastColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
IM_ASSERT(g.ColorEditCurrentID != 0);
if (g.ColorEditSavedID != g.ColorEditCurrentID || g.ColorEditSavedColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
return;
// When S == 0, H is undefined.
// When H == 1 it wraps around to 0.
if (*S == 0.0f || (*H == 0.0f && g.ColorEditLastHue == 1))
*H = g.ColorEditLastHue;
if (*S == 0.0f || (*H == 0.0f && g.ColorEditSavedHue == 1))
*H = g.ColorEditSavedHue;
// When V == 0, S is undefined.
if (*V == 0.0f)
*S = g.ColorEditLastSat;
*S = g.ColorEditSavedSat;
}
// Edit colors components (each component in 0.0f..1.0f range).
@ -4953,6 +5030,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
BeginGroup();
PushID(label);
const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0);
if (set_current_color_edit_id)
g.ColorEditCurrentID = window->IDStack.back();
// If we're not showing any slider there's no point in doing any HSV conversions
const ImGuiColorEditFlags flags_untouched = flags;
@ -4986,7 +5066,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV))
{
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
// Hue is lost when converting from grayscale rgb (saturation=0). Restore it.
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
ColorEditRestoreHS(col, &f[0], &f[1], &f[2]);
}
@ -5125,10 +5205,11 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
f[n] = i[n] / 255.0f;
if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB))
{
g.ColorEditLastHue = f[0];
g.ColorEditLastSat = f[1];
g.ColorEditSavedHue = f[0];
g.ColorEditSavedSat = f[1];
ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0));
g.ColorEditSavedID = g.ColorEditCurrentID;
g.ColorEditSavedColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0));
}
if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV))
ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
@ -5140,6 +5221,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
col[3] = f[3];
}
if (set_current_color_edit_id)
g.ColorEditCurrentID = 0;
PopID();
EndGroup();
@ -5213,6 +5296,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
g.NextItemData.ClearFlags();
PushID(label);
const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0);
if (set_current_color_edit_id)
g.ColorEditCurrentID = window->IDStack.back();
BeginGroup();
if (!(flags & ImGuiColorEditFlags_NoSidePreview))
@ -5261,7 +5347,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
float R = col[0], G = col[1], B = col[2];
if (flags & ImGuiColorEditFlags_InputRGB)
{
// Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
// Hue is lost when converting from grayscale rgb (saturation=0). Restore it.
ColorConvertRGBtoHSV(R, G, B, H, S, V);
ColorEditRestoreHS(col, &H, &S, &V);
}
@ -5316,10 +5402,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
{
S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
// Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square.
if (g.ColorEditLastColor == ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
H = g.ColorEditLastHue;
ColorEditRestoreH(col, &H); // Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square.
value_changed = value_changed_sv = true;
}
if (!(flags & ImGuiColorEditFlags_NoOptions))
@ -5394,9 +5477,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
if (flags & ImGuiColorEditFlags_InputRGB)
{
ColorConvertHSVtoRGB(H, S, V, col[0], col[1], col[2]);
g.ColorEditLastHue = H;
g.ColorEditLastSat = S;
g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0));
g.ColorEditSavedHue = H;
g.ColorEditSavedSat = S;
g.ColorEditSavedID = g.ColorEditCurrentID;
g.ColorEditSavedColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0));
}
else if (flags & ImGuiColorEditFlags_InputHSV)
{
@ -5560,6 +5644,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
if (value_changed && g.LastItemData.ID != 0) // In case of ID collision, the second EndGroup() won't catch g.ActiveId
MarkItemEdited(g.LastItemData.ID);
if (set_current_color_edit_id)
g.ColorEditCurrentID = 0;
PopID();
return value_changed;
@ -5673,7 +5759,8 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
{
ImGuiContext& g = *GImGui;
BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None);
if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None))
return;
const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
if (text_end > text)
{
@ -6548,7 +6635,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v
// - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
//-------------------------------------------------------------------------
int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size)
int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
@ -6559,10 +6646,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true);
if (frame_size.x == 0.0f)
frame_size.x = CalcItemWidth();
if (frame_size.y == 0.0f)
frame_size.y = label_size.y + (style.FramePadding.y * 2);
const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0f);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
@ -7027,7 +7111,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x;
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, 0.0f));
pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y));
RenderText(text_pos, label);
PopStyleVar();
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@ -7043,7 +7127,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
RenderText(text_pos, label);
if (icon_w > 0.0f)
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
@ -7235,7 +7319,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
{
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
@ -7287,11 +7371,17 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
// - TabBarCalcTabID() [Internal]
// - TabBarCalcMaxTabWidth() [Internal]
// - TabBarFindTabById() [Internal]
// - TabBarFindTabByOrder() [Internal]
// - TabBarGetCurrentTab() [Internal]
// - TabBarGetTabName() [Internal]
// - TabBarRemoveTab() [Internal]
// - TabBarCloseTab() [Internal]
// - TabBarScrollClamp() [Internal]
// - TabBarScrollToTab() [Internal]
// - TabBarQueueChangeTabOrder() [Internal]
// - TabBarQueueFocus() [Internal]
// - TabBarQueueReorder() [Internal]
// - TabBarProcessReorderFromMousePos() [Internal]
// - TabBarProcessReorder() [Internal]
// - TabBarScrollingButtons() [Internal]
// - TabBarTabListPopupButton() [Internal]
//-------------------------------------------------------------------------
@ -7416,6 +7506,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
tab_bar->FramePadding = g.Style.FramePadding;
tab_bar->TabsActiveCount = 0;
tab_bar->LastTabItemIdx = -1;
tab_bar->BeginCount = 1;
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
@ -7464,6 +7555,7 @@ void ImGui::EndTabBar()
if (tab_bar->BeginCount > 1)
window->DC.CursorPos = tab_bar->BackupCursorPos;
tab_bar->LastTabItemIdx = -1;
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
PopID();
@ -7573,7 +7665,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
const char* tab_name = tab_bar->GetTabName(tab);
const char* tab_name = TabBarGetTabName(tab_bar, tab);
const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument);
tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x;
@ -7652,6 +7744,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
{
ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n];
tab->Offset = tab_offset;
tab->NameOffset = -1;
tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f);
}
tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f);
@ -7659,6 +7752,9 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
section_tab_index += section->TabCount;
}
// Clear name buffers
tab_bar->TabsNames.Buf.resize(0);
// If we have lost the selected tab, select the next most recently active one
if (found_selected_tab_id == false)
tab_bar->SelectedTabId = 0;
@ -7690,10 +7786,6 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing;
tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing;
// Clear name buffers
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
tab_bar->TabsNames.Buf.resize(0);
// Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame)
ImGuiWindow* window = g.CurrentWindow;
window->DC.CursorPos = tab_bar->BarRect.Min;
@ -7734,7 +7826,30 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
return NULL;
}
// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
// Order = visible order, not submission order! (which is tab->BeginOrder)
ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order)
{
if (order < 0 || order >= tab_bar->Tabs.Size)
return NULL;
return &tab_bar->Tabs[order];
}
ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar)
{
if (tab_bar->LastTabItemIdx <= 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size)
return NULL;
return &tab_bar->Tabs[tab_bar->LastTabItemIdx];
}
const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
if (tab->NameOffset == -1)
return "N/A";
IM_ASSERT(tab->NameOffset < tab_bar->TabsNames.Buf.Size);
return tab_bar->TabsNames.Buf.Data + tab->NameOffset;
}
// The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
{
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
@ -7765,7 +7880,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
if (tab_bar->VisibleTabId != tab->ID)
tab_bar->NextSelectedTabId = tab->ID;
TabBarQueueFocus(tab_bar, tab);
}
}
@ -7786,7 +7901,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
ImGuiContext& g = *GImGui;
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
int order = tab_bar->GetTabOrder(tab);
int order = TabBarGetTabOrder(tab_bar, tab);
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
// FIXME: This is all confusing.
@ -7810,7 +7925,12 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
}
}
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
tab_bar->NextSelectedTabId = tab->ID;
}
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset)
{
IM_ASSERT(offset != 0);
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
@ -7818,7 +7938,7 @@ void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, in
tab_bar->ReorderRequestOffset = (ImS16)offset;
}
void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* src_tab, ImVec2 mouse_pos)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
@ -7861,7 +7981,7 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
return false;
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
int tab2_order = TabBarGetTabOrder(tab_bar, tab1) + tab_bar->ReorderRequestOffset;
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
return false;
@ -7921,7 +8041,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
if (select_dir != 0)
if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
{
int selected_order = tab_bar->GetTabOrder(tab_item);
int selected_order = TabBarGetTabOrder(tab_bar, tab_item);
int target_order = selected_order + select_dir;
// Skip tab item buttons until another tab item is found or end is reached
@ -7973,7 +8093,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
if (tab->Flags & ImGuiTabItemFlags_Button)
continue;
const char* tab_name = tab_bar->GetTabName(tab);
const char* tab_name = TabBarGetTabName(tab_bar, tab);
if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
tab_to_select = tab;
}
@ -8137,9 +8257,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
{
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
tab_bar->NextSelectedTabId = id; // New tabs gets activated
TabBarQueueFocus(tab_bar, tab); // New tabs gets activated
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
tab_bar->NextSelectedTabId = id;
TabBarQueueFocus(tab_bar, tab);
}
// Lock visibility
@ -8203,7 +8323,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
if (pressed && !is_tab_button)
tab_bar->NextSelectedTabId = id;
TabBarQueueFocus(tab_bar, tab);
// Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
if (g.ActiveId != id)
@ -8244,9 +8364,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
if (!is_tab_button)
tab_bar->NextSelectedTabId = id;
if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button)
TabBarQueueFocus(tab_bar, tab);
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;

View File

@ -122,6 +122,7 @@ You can read releases logs https://github.com/epezent/implot/releases for more d
*/
#define IMGUI_DEFINE_MATH_OPERATORS
#include "implot.h"
#include "implot_internal.h"

View File

@ -31,10 +31,6 @@
#pragma once
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <time.h>
#include "imgui_internal.h"

View File

@ -22,6 +22,7 @@
// ImPlot v0.14
#define IMGUI_DEFINE_MATH_OPERATORS
#include "implot.h"
#include "implot_internal.h"
@ -81,7 +82,7 @@ static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); }
// unsigned long long ImU64; // 64-bit unsigned integer
// (note: this list does *not* include `long`, `unsigned long` and `long double`)
//
// You can customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list.
// You can customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list.
// As an example, you could use the compile time define given by the line below in order to support only float and double.
// -DIMPLOT_CUSTOM_NUMERIC_TYPES="(float)(double)"
// In order to support all known C++ types, use:

View File

@ -50,6 +50,17 @@ pub fn deinit() void {
mem_allocator = null;
}
}
pub fn initNoContext(allocator: std.mem.Allocator) void {
if (temp_buffer == null) {
temp_buffer = std.ArrayList(u8).init(allocator);
temp_buffer.?.resize(3 * 1024 + 1) catch unreachable;
}
}
pub fn deinitNoContext() void {
if (temp_buffer) |buf| {
buf.deinit();
}
}
extern fn zguiCreateContext(shared_font_atlas: ?*const anyopaque) Context;
extern fn zguiDestroyContext(ctx: ?Context) void;
extern fn zguiGetCurrentContext() ?Context;
@ -92,16 +103,17 @@ extern fn zguiSetAllocatorFunctions(
free_func: ?*const fn (?*anyopaque, ?*anyopaque) callconv(.C) void,
) void;
//--------------------------------------------------------------------------------------------------
pub const ConfigFlags = enum(u32) {
none = 0,
nav_enable_keyboard = 1 << 0,
nav_enable_gamepad = 1 << 1,
nav_enable_set_mouse_pos = 1 << 2,
nav_no_capture_keyboard = 1 << 3,
no_mouse = 1 << 4,
no_mouse_cursor_change = 1 << 5,
is_srgb = 1 << 20,
is_touch_screen = 1 << 21,
pub const ConfigFlags = packed struct(u32) {
nav_enable_keyboard: bool = false,
nav_enable_gamepad: bool = false,
nav_enable_set_mouse_pos: bool = false,
nav_no_capture_keyboard: bool = false,
no_mouse: bool = false,
no_mouse_cursor_change: bool = false,
user_storage: u14 = 0,
is_srgb: bool = false,
is_touch_screen: bool = false,
_padding: u10 = 0,
};
pub const FontConfig = extern struct {
@ -787,6 +799,9 @@ pub const Style = extern struct {
color_button_position: Direction,
button_text_align: [2]f32,
selectable_text_align: [2]f32,
separator_text_border_size: f32,
separator_text_align: [2]f32,
separator_text_padding: [2]f32,
display_window_padding: [2]f32,
display_safe_area_padding: [2]f32,
mouse_cursor_scale: f32,
@ -892,9 +907,16 @@ const PopStyleColor = struct {
pub fn popStyleColor(args: PopStyleColor) void {
zguiPopStyleColor(args.count);
}
/// `fn pushTextWrapPos(wrap_pos_x: f32) void`
pub const pushTextWrapPos = zguiPushTextWrapPos;
/// `fn popTextWrapPos() void`
pub const popTextWrapPos = zguiPopTextWrapPos;
extern fn zguiPushStyleColor4f(idx: StyleCol, col: *const [4]f32) void;
extern fn zguiPushStyleColor1u(idx: StyleCol, col: u32) void;
extern fn zguiPopStyleColor(count: i32) void;
extern fn zguiPushTextWrapPos(wrap_pos_x: f32) void;
extern fn zguiPopTextWrapPos() void;
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
pub const StyleVar = enum(u32) {
alpha, // 1f
@ -922,6 +944,9 @@ pub const StyleVar = enum(u32) {
tab_rounding, // 1f
button_text_align, // 2f
selectable_text_align, // 2f
separator_text_border_size, // 1f
separator_text_align, // 2f
separator_text_padding, // 2f
};
const PushStyleVar1f = struct {
idx: StyleVar,
@ -972,6 +997,13 @@ extern fn zguiPushFont(font: Font) void;
/// `void popFont() void`
pub const popFont = zguiPopFont;
extern fn zguiPopFont() void;
pub fn getFontTexUvWhitePixel() [2]f32 {
var uv: [2]f32 = undefined;
zguiGetFontTexUvWhitePixel(&uv);
return uv;
}
extern fn zguiGetFontTexUvWhitePixel(uv: *[2]f32) void;
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
const BeginDisabled = struct {
@ -992,6 +1024,11 @@ extern fn zguiEndDisabled() void;
/// `pub fn separator() void`
pub const separator = zguiSeparator;
extern fn zguiSeparator() void;
pub fn separatorText(label: [:0]const u8) void {
zguiSeparatorText(label);
}
extern fn zguiSeparatorText(label: [*:0]const u8) void;
//--------------------------------------------------------------------------------------------------
const SameLine = struct {
offset_from_start_x: f32 = 0.0,
@ -2041,6 +2078,7 @@ pub const InputTextFlags = packed struct(u32) {
};
//--------------------------------------------------------------------------------------------------
pub const InputTextCallbackData = extern struct {
ctx: *Context,
event_flag: InputTextFlags,
flags: InputTextFlags,
user_data: ?*anyopaque,
@ -3047,6 +3085,15 @@ pub fn menuItem(label: [:0]const u8, args: MenuItem) bool {
return zguiMenuItem(label, if (args.shortcut) |s| s.ptr else null, args.selected, args.enabled);
}
const MenuItemPtr = struct {
shortcut: ?[:0]const u8 = null,
selected: *bool,
enabled: bool = true,
};
pub fn menuItemPtr(label: [:0]const u8, args: MenuItemPtr) bool {
return zguiMenuItemPtr(label, if (args.shortcut) |s| s.ptr else null, args.selected, args.enabled);
}
extern fn zguiBeginMenuBar() bool;
extern fn zguiEndMenuBar() void;
extern fn zguiBeginMainMenuBar() bool;
@ -3054,6 +3101,7 @@ extern fn zguiEndMainMenuBar() void;
extern fn zguiBeginMenu(label: [*:0]const u8, enabled: bool) bool;
extern fn zguiEndMenu() void;
extern fn zguiMenuItem(label: [*:0]const u8, shortcut: ?[*:0]const u8, selected: bool, enabled: bool) bool;
extern fn zguiMenuItemPtr(label: [*:0]const u8, shortcut: ?[*:0]const u8, selected: *bool, enabled: bool) bool;
//--------------------------------------------------------------------------------------------------
//
// Popups
@ -3063,11 +3111,13 @@ extern fn zguiMenuItem(label: [*:0]const u8, shortcut: ?[*:0]const u8, selected:
pub const beginTooltip = zguiBeginTooltip;
/// `pub fn endTooltip() void`
pub const endTooltip = zguiEndTooltip;
extern fn zguiBeginTooltip() void;
extern fn zguiBeginTooltip() bool;
extern fn zguiEndTooltip() void;
/// `pub fn beginPopupContextWindow() bool`
pub const beginPopupContextWindow = zguiBeginPopupContextWindow;
/// `pub fn beginPopupContextItem() bool`
pub const beginPopupContextItem = zguiBeginPopupContextItem;
pub const PopupFlags = packed struct(u32) {
mouse_button_left: bool = false,
mouse_button_right: bool = false,
@ -3092,6 +3142,7 @@ pub const endPopup = zguiEndPopup;
/// `pub fn closeCurrentPopup() void`
pub const closeCurrentPopup = zguiCloseCurrentPopup;
extern fn zguiBeginPopupContextWindow() bool;
extern fn zguiBeginPopupContextItem() bool;
extern fn zguiBeginPopupModal(name: [*:0]const u8, popen: ?*bool, flags: WindowFlags) bool;
extern fn zguiEndPopup() void;
extern fn zguiOpenPopup(str_id: [*:0]const u8, flags: PopupFlags) void;
@ -3323,6 +3374,8 @@ pub const DrawList = *opaque {
extern fn zguiDrawList_GetIndexBufferLength(draw_list: DrawList) i32;
pub const getIndexBufferData = zguiDrawList_GetIndexBufferData;
extern fn zguiDrawList_GetIndexBufferData(draw_list: DrawList) [*]const DrawIdx;
pub const getCurrentIndex = zguiDrawList_GetCurrentIndex;
extern fn zguiDrawList_GetCurrentIndex(draw_list: DrawList) u32;
pub const getCmdBufferLength = zguiDrawList_GetCmdBufferLength;
extern fn zguiDrawList_GetCmdBufferLength(draw_list: DrawList) i32;

View File

@ -4,7 +4,7 @@
// named parameters and Zig style text formatting.
//
//--------------------------------------------------------------------------------------------------
pub const version = @import("std").SemanticVersion{ .major = 0, .minor = 9, .patch = 5 };
pub const version = @import("std").SemanticVersion{ .major = 0, .minor = 9, .patch = 6 };
pub usingnamespace @import("gui.zig");
pub const plot = @import("plot.zig");

View File

@ -1,7 +1,11 @@
#include "./imgui/imgui.h"
#include "./imgui/implot.h"
#define ZGUI_API extern "C"
#ifndef ZGUI_API
#define ZGUI_API
#endif
extern "C" {
/*
#include <stdio.h>
@ -174,6 +178,10 @@ ZGUI_API void zguiSeparator(void) {
ImGui::Separator();
}
ZGUI_API void zguiSeparatorText(const char* label) {
ImGui::SeparatorText(label);
}
ZGUI_API void zguiSameLine(float offset_from_start_x, float spacing) {
ImGui::SameLine(offset_from_start_x, spacing);
}
@ -1052,6 +1060,12 @@ ZGUI_API float zguiGetFontSize(void) {
return ImGui::GetFontSize();
}
ZGUI_API void zguiGetFontTexUvWhitePixel(float uv[2]) {
const ImVec2 cs = ImGui::GetFontTexUvWhitePixel();
uv[0] = cs[0];
uv[1] = cs[1];
}
ZGUI_API void zguiPushFont(ImFont* font) {
ImGui::PushFont(font);
}
@ -1369,6 +1383,10 @@ ZGUI_API void zguiPushTextWrapPos(float wrap_pos_x) {
ImGui::PushTextWrapPos(wrap_pos_x);
}
ZGUI_API void zguiPopTextWrapPos(void) {
ImGui::PopTextWrapPos();
}
ZGUI_API bool zguiBeginTabBar(const char* string, ImGuiTabBarFlags flags) {
return ImGui::BeginTabBar(string, flags);
}
@ -1417,8 +1435,12 @@ ZGUI_API bool zguiMenuItem(const char* label, const char* shortcut, bool selecte
return ImGui::MenuItem(label, shortcut, selected, enabled);
}
ZGUI_API void zguiBeginTooltip(void) {
ImGui::BeginTooltip();
ZGUI_API bool zguiMenuItemPtr(const char* label, const char* shortcut, bool* selected, bool enabled) {
return ImGui::MenuItem(label, shortcut, selected, enabled);
}
ZGUI_API bool zguiBeginTooltip(void) {
return ImGui::BeginTooltip();
}
ZGUI_API void zguiEndTooltip(void) {
@ -1429,6 +1451,10 @@ ZGUI_API bool zguiBeginPopupContextWindow(void) {
return ImGui::BeginPopupContextWindow();
}
ZGUI_API bool zguiBeginPopupContextItem(void) {
return ImGui::BeginPopupContextItem();
}
ZGUI_API bool zguiBeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) {
return ImGui::BeginPopupModal(name, p_open, flags);
}
@ -1601,6 +1627,9 @@ ZGUI_API int zguiDrawList_GetIndexBufferLength(ImDrawList *draw_list) {
ZGUI_API ImDrawIdx *zguiDrawList_GetIndexBufferData(ImDrawList *draw_list) {
return draw_list->IdxBuffer.begin();
}
ZGUI_API unsigned int zguiDrawList_GetCurrentIndex(ImDrawList *draw_list) {
return draw_list->_VtxCurrentIdx;
}
ZGUI_API int zguiDrawList_GetCmdBufferLength(ImDrawList *draw_list) {
return draw_list->CmdBuffer.size();
@ -2283,3 +2312,4 @@ ZGUI_API void zguiPlot_EndPlot(void) {
ImPlot::EndPlot();
}
//--------------------------------------------------------------------------------------------------
} /* extern "C" */