cherry-pick ImGui code

from LTVA1/furnace

localization work
This commit is contained in:
tildearrow 2024-05-27 17:31:20 -05:00
parent 972346d22d
commit 5f16edd0df
6 changed files with 587 additions and 71 deletions

View file

@ -1046,7 +1046,7 @@ static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA = 0.50f; // For u
static void SetCurrentWindow(ImGuiWindow* window);
static void FindHoveredWindow();
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags);
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags, const char* displayedName = NULL);
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
@ -1219,6 +1219,8 @@ ImGuiStyle::ImGuiStyle()
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
DoFrameShadingForMultilineText = false;
// Behaviors
HoverStationaryDelay = 0.15f; // Delay for IsItemHovered(ImGuiHoveredFlags_Stationary). Time required to consider mouse stationary.
HoverDelayShort = 0.15f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayShort). Usually used along with HoverStationaryDelay.
@ -3341,6 +3343,17 @@ const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
return text_display_end;
}
const char* FindRenderedTextEndNoHashHide(const char* text, const char* text_end)
{
const char* text_display_end = text;
if (!text_end)
text_end = (const char*)-1;
while (text_display_end < text_end && *text_display_end != '\0')
text_display_end++;
return text_display_end;
}
// Internal ImGui functions to render text
// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
@ -3363,7 +3376,14 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool
if (text != text_display_end)
{
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
if (hide_text_after_hash)
{
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
}
else
{
window->DrawList->AddTextNoHashHide(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
}
if (g.LogEnabled)
LogRenderedText(&pos, text, text_display_end);
}
@ -3385,6 +3405,22 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
}
}
void ImGui::RenderTextWrappedNoHashHide(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (!text_end)
text_end = text + strlen(text); // FIXME-OPT
if (text != text_end)
{
window->DrawList->AddTextNoHashHide(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
if (g.LogEnabled)
LogRenderedText(&pos, text, text_end);
}
}
// Default clip_rect uses (pos_min,pos_max)
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
// FIXME-OPT: Since we have or calculate text_size we could coarse clip whole block immediately, especally for text above draw_list->DrawList.
@ -3433,6 +3469,21 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons
LogRenderedText(&pos_min, text, text_display_end);
}
void ImGui::RenderTextClippedNoHashHide(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
{
// Do not hide anything after a '##' string
const char* text_display_end = text_end;
const int text_len = (int)(text_display_end - text);
if (text_len == 0)
return;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
if (g.LogEnabled)
LogRenderedText(&pos_min, text, text_display_end);
}
// Another overly complex function until we reorganize everything into a nice all-in-one helper.
// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
@ -3843,12 +3894,23 @@ void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
//-----------------------------------------------------------------------------
// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NULL)
ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name, const char* displayedName) : DrawListInst(NULL)
{
memset(this, 0, sizeof(*this));
Ctx = ctx;
Name = ImStrdup(name);
NameBufLen = (int)strlen(name) + 1;
if(displayedName != NULL)
{
DisplayedName = ImStrdup(displayedName);
}
else
{
DisplayedName = NULL;
}
ID = ImHashStr(name);
IDStack.push_back(ID);
ViewportAllowPlatformMonitorExtend = -1;
@ -3879,6 +3941,7 @@ ImGuiWindow::~ImGuiWindow()
{
IM_ASSERT(DrawList == &DrawListInst);
IM_DELETE(Name);
IM_DELETE(DisplayedName);
ColumnsStorage.clear_destruct();
}
@ -5731,6 +5794,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
if (!border)
g.Style.ChildBorderSize = 0.0f;
bool ret = Begin(temp_window_name, NULL, flags);
g.Style.ChildBorderSize = backup_border_size;
ImGuiWindow* child_window = g.CurrentWindow;
@ -5930,12 +5994,12 @@ static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* s
}
}
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags, const char* displayedName)
{
// Create window the first time
//IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags);
ImGuiContext& g = *GImGui;
ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name, displayedName);
window->Flags = flags;
g.WindowsById.SetVoidPtr(window->ID, window);
@ -6651,7 +6715,7 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file.
// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned.
// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed.
bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const char* displayedName)
{
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
@ -6663,7 +6727,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
ImGuiWindow* window = FindWindowByName(name);
const bool window_just_created = (window == NULL);
if (window_just_created)
window = CreateNewWindow(name, flags);
window = CreateNewWindow(name, flags, displayedName);
// Automatically disable manual moving/resizing when NoInputs is set
if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
@ -6869,6 +6933,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->NameBufLen = (int)buf_len;
}
if(window->DisplayedName)
{
if(strcmp(displayedName, window->DisplayedName) != 0)
{
// WAHAHAHAHA
// you wrote free() instead of IM_DELETE() and broke portability HAHAHA
IM_DELETE(window->DisplayedName);
window->DisplayedName = ImStrdup(displayedName);
}
}
if(window->DisplayedName == NULL && displayedName != NULL)
{
window->DisplayedName = ImStrdup(displayedName);
}
// UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
// Update contents size from last frame for auto-fitting (or use explicit size)
@ -7420,7 +7500,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Title bar
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open);
RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), displayedName == NULL ? name : displayedName, p_open);
// Clear hit test shape every frame
window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
@ -14183,8 +14263,14 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count)
{
ImGuiContext& g = *GImGui;
for (int n = 0; n < count; n++)
g.LocalizationTable[entries[n].Key] = entries[n].Text;
if (GImGui != NULL)
{
for (int n = 0; n < count; n++)
{
g.LocalizationTable[entries[n].Key] = entries[n].Text;
}
}
}
@ -16891,7 +16977,7 @@ bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
return false;
if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
return false;
Begin(node->HostWindow->Name);
Begin(node->HostWindow->Name); //this is to be edited
PushOverrideID(node->ID);
bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags, node);
IM_UNUSED(ret);
@ -17094,7 +17180,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
// Note that TabItemEx() calls TabBarCalcTabID() so our tab item ID will ignore the current ID stack (rightly so)
bool tab_open = true;
TabItemEx(tab_bar, window->Name, window->HasCloseButton ? &tab_open : NULL, tab_item_flags, window);
TabItemEx(tab_bar, window->DisplayedName == NULL ? window->Name : window->DisplayedName, window->HasCloseButton ? &tab_open : NULL, tab_item_flags, window);
if (!tab_open)
node->WantCloseTabId = window->TabId;
if (tab_bar->VisibleTabId == window->TabId)
@ -17551,7 +17637,7 @@ static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDock
if (!tab_bar_rect.Contains(tab_bb))
overlay_draw_lists[overlay_n]->PushClipRect(tab_bar_rect.Min, tab_bar_rect.Max);
TabItemBackground(overlay_draw_lists[overlay_n], tab_bb, tab_flags, overlay_col_tabs);
TabItemLabelAndCloseButton(overlay_draw_lists[overlay_n], tab_bb, tab_flags, g.Style.FramePadding, payload_window->Name, 0, 0, false, NULL, NULL);
TabItemLabelAndCloseButton(overlay_draw_lists[overlay_n], tab_bb, tab_flags, g.Style.FramePadding, payload_window->DisplayedName == NULL ? payload_window->Name : payload_window->DisplayedName, 0, 0, false, NULL, NULL);
if (!tab_bar_rect.Contains(tab_bb))
overlay_draw_lists[overlay_n]->PopClipRect();
}