mirror of
https://github.com/ocornut/imgui.git
synced 2025-01-19 01:34:08 +01:00
Merge branch 'master' into docking
This commit is contained in:
commit
ae8688974b
2
.github/workflows/static-analysis.yml
vendored
2
.github/workflows/static-analysis.yml
vendored
@ -42,5 +42,5 @@ jobs:
|
||||
fi
|
||||
cd examples/example_null
|
||||
pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
|
||||
pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
|
||||
pvs-studio-analyzer analyze --disableLicenseExpirationCheck -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
|
||||
plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977)
|
||||
// 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240)
|
||||
// 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes.
|
||||
// 2024-01-22: Fixed pipeline layout leak. (#7245)
|
||||
@ -37,6 +38,18 @@
|
||||
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-28: Initial version.
|
||||
|
||||
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
|
||||
#endif
|
||||
#else
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_wgpu.h"
|
||||
@ -247,7 +260,11 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
|
||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||
|
||||
WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
|
||||
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
|
||||
#else
|
||||
wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
|
||||
#endif
|
||||
wgsl_desc.code = wgsl_source;
|
||||
|
||||
WGPUShaderModuleDescriptor desc = {};
|
||||
@ -662,7 +679,11 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
// Create depth-stencil State
|
||||
WGPUDepthStencilState depth_stencil_state = {};
|
||||
depth_stencil_state.format = bd->depthStencilFormat;
|
||||
#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
|
||||
#else
|
||||
depth_stencil_state.depthWriteEnabled = false;
|
||||
#endif
|
||||
depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
|
||||
depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
|
||||
depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
|
||||
@ -732,7 +753,15 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
io.BackendRendererName = "imgui_impl_webgpu_emscripten";
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
io.BackendRendererName = "imgui_impl_webgpu_dawn";
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
io.BackendRendererName = "imgui_impl_webgpu_wgpu";
|
||||
#else
|
||||
io.BackendRendererName = "imgui_impl_webgpu";
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
bd->initInfo = *init_info;
|
||||
|
@ -2,6 +2,13 @@
|
||||
// This needs to be used along with a Platform Binding (e.g. GLFW)
|
||||
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
|
||||
|
||||
// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten),
|
||||
// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided.
|
||||
// Add #define to your imconfig.h file, or as a compilation flag in your build system.
|
||||
// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
|
||||
//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
@ -65,16 +65,27 @@ Other changes:
|
||||
- Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
|
||||
- MultiSelect+Tables: fixed an issue where box-select would skip items while drag-scrolling
|
||||
in a table with outer borders. (#7970, #7821).
|
||||
- Inputs: SetNextItemShortcut() with ImGuiInputFlags_Tooltip doesn't show tooltip when item is active.
|
||||
- InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been
|
||||
removed. Simplifications allowed to implement new optimizations for handling very large text buffers
|
||||
(e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
|
||||
This is the first step toward more refactorig. (#7925) [@alektron, @ocornut]
|
||||
This is the first step toward more refactoring. (#7925) [@alektron, @ocornut]
|
||||
- InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
|
||||
- Tables: fixed auto-width columns when using synced-instances of same table. The previous fix
|
||||
done in v1.90.5 was incomplete. (#7218)
|
||||
- Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend]
|
||||
- Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428)
|
||||
- Windows: fixed an issue where double-click to collapse could be triggered even while another
|
||||
item is active, if the item didn't use the left mouse button. (#7841)
|
||||
- Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow
|
||||
hacking in custom cursors if desirable.
|
||||
- Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
|
||||
- TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
|
||||
- Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
|
||||
- Backends: GLFW+Emscripten: use OSX behaviors automatically when using contrib glfw port. (#7965, #7915)
|
||||
[@ypujante]
|
||||
- Backends: WebGPU: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
defines to handle ever-changing native implementations. (#7977, #7969, #6602, #6188, #7523) [@acgaudette]
|
||||
|
||||
Docking+Viewports Branch:
|
||||
|
||||
|
@ -79,6 +79,11 @@ add_executable(example_glfw_wgpu
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
)
|
||||
IF(NOT EMSCRIPTEN)
|
||||
target_compile_definitions(example_glfw_wgpu PUBLIC
|
||||
"IMGUI_IMPL_WEBGPU_BACKEND_DAWN"
|
||||
)
|
||||
endif()
|
||||
target_include_directories(example_glfw_wgpu PUBLIC
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_DIR}/backends
|
||||
|
17
imgui.cpp
17
imgui.cpp
@ -3770,7 +3770,8 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
|
||||
void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
|
||||
if (mouse_cursor <= ImGuiMouseCursor_None || mouse_cursor >= ImGuiMouseCursor_COUNT) // We intentionally accept out of bound values.
|
||||
mouse_cursor = ImGuiMouseCursor_Arrow;
|
||||
ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas;
|
||||
for (ImGuiViewportP* viewport : g.Viewports)
|
||||
{
|
||||
@ -4438,7 +4439,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
|
||||
|
||||
// Display shortcut (only works with mouse)
|
||||
// (ImGuiItemStatusFlags_HasShortcut in LastItemData denotes we want a tooltip)
|
||||
if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut))
|
||||
if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut) && g.ActiveId != id)
|
||||
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal))
|
||||
SetTooltip("%s", GetKeyChordName(g.LastItemData.Shortcut));
|
||||
}
|
||||
@ -6497,7 +6498,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
||||
ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
|
||||
//GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
|
||||
if (hovered || held)
|
||||
g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
|
||||
SetMouseCursor((resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE);
|
||||
|
||||
if (held && g.IO.MouseDoubleClicked[0])
|
||||
{
|
||||
@ -6543,7 +6544,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
||||
if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
|
||||
hovered = false;
|
||||
if (hovered || held)
|
||||
g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
|
||||
SetMouseCursor((axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS);
|
||||
if (held && g.IO.MouseDoubleClicked[0])
|
||||
{
|
||||
// Double-clicking bottom or right border auto-fit on this axis
|
||||
@ -7374,9 +7375,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
// At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
|
||||
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive)
|
||||
{
|
||||
// We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar.
|
||||
// We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed),
|
||||
// so verify that we don't have items over the title bar.
|
||||
ImRect title_bar_rect = window->TitleBarRect();
|
||||
if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
|
||||
if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && g.ActiveId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
|
||||
if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
|
||||
window->WantCollapseToggle = true;
|
||||
if (window->WantCollapseToggle)
|
||||
@ -9915,6 +9917,9 @@ ImGuiMouseCursor ImGui::GetMouseCursor()
|
||||
return g.MouseCursor;
|
||||
}
|
||||
|
||||
// We intentionally accept values of ImGuiMouseCursor that are outside our bounds, in case users needs to hack-in a custom cursor value.
|
||||
// Custom cursors may be handled by custom backends. If you are using a standard backend and want to hack in a custom cursor, you may
|
||||
// handle it before the backend _NewFrame() call and temporarily set ImGuiConfigFlags_NoMouseCursorChange during the backend _NewFrame() call.
|
||||
void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
2
imgui.h
2
imgui.h
@ -29,7 +29,7 @@
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.91.2 WIP"
|
||||
#define IMGUI_VERSION_NUM 19114
|
||||
#define IMGUI_VERSION_NUM 19115
|
||||
#define IMGUI_HAS_TABLE
|
||||
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
|
||||
#define IMGUI_HAS_DOCK // Docking WIP branch
|
||||
|
@ -7565,7 +7565,8 @@ static void ShowDemoWindowInputs()
|
||||
IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
|
||||
|
||||
ImGuiMouseCursor current = ImGui::GetMouseCursor();
|
||||
ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
|
||||
const char* cursor_name = (current >= ImGuiMouseCursor_Arrow) && (current < ImGuiMouseCursor_COUNT) ? mouse_cursors_names[current] : "N/A";
|
||||
ImGui::Text("Current mouse cursor = %d: %s", current, cursor_name);
|
||||
ImGui::BeginDisabled(true);
|
||||
ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
|
||||
ImGui::EndDisabled();
|
||||
|
@ -2505,13 +2505,14 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
|
||||
{
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
|
||||
IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);
|
||||
IM_ASSERT(font_cfg->SizePixels > 0.0f);
|
||||
IM_ASSERT(font_cfg->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?");
|
||||
IM_ASSERT(font_cfg->OversampleH > 0 && font_cfg->OversampleV > 0 && "Is ImFontConfig struct correctly initialized?");
|
||||
|
||||
// Create new font
|
||||
if (!font_cfg->MergeMode)
|
||||
Fonts.push_back(IM_NEW(ImFont));
|
||||
else
|
||||
IM_ASSERT(!Fonts.empty() && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
|
||||
IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
|
||||
|
||||
ConfigData.push_back(*font_cfg);
|
||||
ImFontConfig& new_font_cfg = ConfigData.back();
|
||||
|
@ -328,7 +328,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
// - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[].
|
||||
const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
|
||||
const ImVec2 avail_size = GetContentRegionAvail();
|
||||
const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
|
||||
const ImVec2 actual_outer_size = ImTrunc(CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f));
|
||||
const ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size);
|
||||
const bool outer_window_is_measuring_size = (outer_window->AutoFitFramesX > 0) || (outer_window->AutoFitFramesY > 0); // Doesn't apply to AlwaysAutoResize windows!
|
||||
if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size)
|
||||
@ -866,7 +866,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
|
||||
// Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
|
||||
// Combine width from regular rows + width from headers unless requested not to.
|
||||
if (!column->IsPreserveWidthAuto)
|
||||
if (!column->IsPreserveWidthAuto && table->InstanceCurrent == 0)
|
||||
column->WidthAuto = TableGetColumnWidthAuto(table, column);
|
||||
|
||||
// Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto)
|
||||
@ -1261,7 +1261,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
else
|
||||
inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false);
|
||||
inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); // FIXME: use table->InnerClipRect?
|
||||
}
|
||||
|
||||
// Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
|
||||
@ -2011,7 +2011,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
{
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main;
|
||||
const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
|
||||
const float y0 = ImMax(table->RowPosY2 + 1, table->InnerClipRect.Min.y);
|
||||
table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y;
|
||||
|
||||
if (unfreeze_rows_actual)
|
||||
@ -2020,8 +2020,8 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
table->IsUnfrozenRows = true;
|
||||
|
||||
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
|
||||
table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
|
||||
table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
|
||||
table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, table->InnerClipRect.Max.y);
|
||||
table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = table->InnerClipRect.Max.y;
|
||||
table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
|
||||
IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
|
||||
|
||||
@ -4409,7 +4409,7 @@ void ImGui::EndColumns()
|
||||
{
|
||||
ButtonBehavior(column_hit_rect, column_id, &hovered, &held);
|
||||
if (hovered || held)
|
||||
g.MouseCursor = ImGuiMouseCursor_ResizeEW;
|
||||
SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||
if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize))
|
||||
dragging_column = n;
|
||||
}
|
||||
|
@ -3828,16 +3828,22 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, si
|
||||
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
|
||||
}
|
||||
|
||||
// This is only used in the path where the multiline widget is inactivate.
|
||||
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
|
||||
{
|
||||
int line_count = 0;
|
||||
const char* s = text_begin;
|
||||
while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding
|
||||
if (c == '\n')
|
||||
line_count++;
|
||||
s--;
|
||||
if (s[0] != '\n' && s[0] != '\r')
|
||||
while (true)
|
||||
{
|
||||
const char* s_eol = strchr(s, '\n');
|
||||
line_count++;
|
||||
if (s_eol == NULL)
|
||||
{
|
||||
s = s + strlen(s);
|
||||
break;
|
||||
}
|
||||
s = s_eol + 1;
|
||||
}
|
||||
*out_text_end = s;
|
||||
return line_count;
|
||||
}
|
||||
@ -4444,7 +4450,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
|
||||
if (hovered)
|
||||
g.MouseCursor = ImGuiMouseCursor_TextInput;
|
||||
SetMouseCursor(ImGuiMouseCursor_TextInput);
|
||||
|
||||
// We are only allowed to access the state if we are already the active widget.
|
||||
ImGuiInputTextState* state = GetInputTextState(id);
|
||||
@ -4977,7 +4983,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor;
|
||||
const int utf8_selection_start = callback_data.SelectionStart = state->Stb->select_start;
|
||||
const int utf8_selection_end = state->Stb->select_end;
|
||||
const int utf8_selection_end = callback_data.SelectionEnd = state->Stb->select_end;
|
||||
|
||||
// Call user code
|
||||
callback(&callback_data);
|
||||
@ -5101,49 +5107,39 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
|
||||
// FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
|
||||
const char* text_begin = state->TextA.Data;
|
||||
const char* text_end = text_begin + state->CurLenA;
|
||||
ImVec2 cursor_offset, select_start_offset;
|
||||
|
||||
{
|
||||
// Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions.
|
||||
const char* searches_input_ptr[2] = { NULL, NULL };
|
||||
int searches_result_line_no[2] = { -1000, -1000 };
|
||||
int searches_remaining = 0;
|
||||
if (render_cursor)
|
||||
{
|
||||
searches_input_ptr[0] = text_begin + state->Stb->cursor;
|
||||
searches_result_line_no[0] = -1;
|
||||
searches_remaining++;
|
||||
}
|
||||
if (render_selection)
|
||||
{
|
||||
searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
|
||||
searches_result_line_no[1] = -1;
|
||||
searches_remaining++;
|
||||
}
|
||||
// Find lines numbers straddling cursor and selection min position
|
||||
int cursor_line_no = render_cursor ? -1 : -1000;
|
||||
int selmin_line_no = render_selection ? -1 : -1000;
|
||||
const char* cursor_ptr = render_cursor ? text_begin + state->Stb->cursor : NULL;
|
||||
const char* selmin_ptr = render_selection ? text_begin + ImMin(state->Stb->select_start, state->Stb->select_end) : NULL;
|
||||
|
||||
// Iterate all lines to find our line numbers
|
||||
// In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
|
||||
searches_remaining += is_multiline ? 1 : 0;
|
||||
int line_count = 0;
|
||||
for (const char* s = text_begin; (s = strchr(s, '\n')) != NULL; s++) // FIXME-OPT: memchr() would be faster?
|
||||
// Count lines and find line number for cursor and selection ends
|
||||
int line_count = 1;
|
||||
if (is_multiline)
|
||||
{
|
||||
line_count++;
|
||||
if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
|
||||
if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
|
||||
for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++)
|
||||
{
|
||||
if (cursor_line_no == -1 && s >= cursor_ptr) { cursor_line_no = line_count; }
|
||||
if (selmin_line_no == -1 && s >= selmin_ptr) { selmin_line_no = line_count; }
|
||||
line_count++;
|
||||
}
|
||||
}
|
||||
line_count++;
|
||||
if (searches_result_line_no[0] == -1)
|
||||
searches_result_line_no[0] = line_count;
|
||||
if (searches_result_line_no[1] == -1)
|
||||
searches_result_line_no[1] = line_count;
|
||||
if (cursor_line_no == -1)
|
||||
cursor_line_no = line_count;
|
||||
if (selmin_line_no == -1)
|
||||
selmin_line_no = line_count;
|
||||
|
||||
// Calculate 2d position by finding the beginning of the line and measuring distance
|
||||
cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
|
||||
cursor_offset.y = searches_result_line_no[0] * g.FontSize;
|
||||
if (searches_result_line_no[1] >= 0)
|
||||
cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(cursor_ptr, text_begin), cursor_ptr).x;
|
||||
cursor_offset.y = cursor_line_no * g.FontSize;
|
||||
if (selmin_line_no >= 0)
|
||||
{
|
||||
select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
|
||||
select_start_offset.y = searches_result_line_no[1] * g.FontSize;
|
||||
select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(selmin_ptr, text_begin), selmin_ptr).x;
|
||||
select_start_offset.y = selmin_line_no * g.FontSize;
|
||||
}
|
||||
|
||||
// Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)
|
||||
|
Loading…
x
Reference in New Issue
Block a user