using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Text; using Dalamud.Bindings.ImGui; using Dalamud.Game.Text; using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.ManagedFontAtlas; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; namespace Questionable.Windows; internal static class UiThemeUtils { public readonly record struct GridCheckbox(string Label, bool Value, string? Tooltip = null); public const float SpacingInner = 8f; public const float SpacingSection = 16f; public const float CardPadding = 12f; public const float ControlWidth = 260f; private static readonly uint AltRowColor = ImGui.ColorConvertFloat4ToU32(new Vector4(0.15f, 0.12f, 0.2f, 0.3f)); public static readonly Vector4 CardBackgroundColor = new Vector4(1f, 1f, 1f, 0.035f); public static readonly Vector4 AccentColor = new Vector4(0.75f, 0.55f, 0.95f, 1f); public static readonly Vector4 AccentDimColor; public static readonly Vector4 CardBorderColor; public static readonly Vector4 CardBorderHighColor; private const float CardRounding = 6f; public static readonly Vector4 PrimaryTextColor; public static readonly Vector4 DimTextColor; public static readonly Vector4 MutedTextColor; public static readonly Vector4 PlayButtonColor; public static readonly Vector4 PlayButtonHover; public static readonly Vector4 PlayButtonActive; public static readonly Vector4 PlayButtonText; public static readonly Vector4 SubtleHoverColor; public static readonly Vector4 SubtleActiveColor; public static readonly Vector4 SubtlePressColor; public static readonly Vector4 StatusComplete; public static readonly Vector4 StatusActive; public static readonly Vector4 StatusAvailable; public static readonly Vector4 StatusAvailableComplete; public static readonly Vector4 StatusLocked; public static readonly Vector4 StatusUnobtainable; public static readonly Vector4 StatusBlacklisted; private static readonly string Ellipsis; private static float _cardContentRightInset; public const ImGuiTableFlags ThemedTableFlags = ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerH; public static void WrappedText(string text) { ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X); ImGui.TextUnformatted(text); ImGui.PopTextWrapPos(); } public static void WrappedTextColored(Vector4 color, string text) { using (ImRaii.PushColor(ImGuiCol.Text, color)) { WrappedText(text); } } public static string TruncateToWidth(string text, float maxWidth) { if (string.IsNullOrEmpty(text) || maxWidth <= 0f || ImGui.CalcTextSize(text).X <= maxWidth) { return text; } if (ImGui.CalcTextSize(Ellipsis).X > maxWidth) { return Ellipsis; } int num = 0; int num2 = text.Length; while (num < num2) { int num3 = (num + num2 + 1) / 2; if (ImGui.CalcTextSize(string.Concat(text.AsSpan(0, num3), Ellipsis.AsSpan())).X <= maxWidth) { num = num3; } else { num2 = num3 - 1; } } if (num > 0) { return string.Concat(text.AsSpan(0, num), Ellipsis.AsSpan()); } return Ellipsis; } public static void RowLabel(string text, float reservedRightWidth) { float maxWidth = ImGui.GetContentRegionAvail().X - reservedRightWidth; ImGui.TextUnformatted(TruncateToWidth(text, maxWidth)); } public static void RowLabel(string text, float reservedRightWidth, Vector4 color) { using (ImRaii.PushColor(ImGuiCol.Text, color)) { RowLabel(text, reservedRightWidth); } } public static (Vector2 ContentStartPos, float AvailableWidth, ImDrawListPtr DrawList) BeginCard() { Vector2 cursorPos = ImGui.GetCursorPos(); float x = ImGui.GetContentRegionAvail().X; ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); windowDrawList.ChannelsSplit(2); windowDrawList.ChannelsSetCurrent(1); ImGui.Indent(12f); ImGui.SetCursorPosY(cursorPos.Y + 12f); ImGui.PushItemWidth(-13f); _cardContentRightInset = 12f; return (ContentStartPos: cursorPos, AvailableWidth: x, DrawList: windowDrawList); } public static void EndCard(Vector2 contentStartPos, float availableWidth, ImDrawListPtr drawList) { ImGui.PopItemWidth(); ImGui.Unindent(12f); _cardContentRightInset = 0f; Vector2 cursorPos = ImGui.GetCursorPos(); drawList.ChannelsSetCurrent(0); ImGui.SetCursorPos(contentStartPos); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImGui.SetCursorPos(cursorPos + new Vector2(0f, 12f)); Vector2 cursorScreenPos2 = ImGui.GetCursorScreenPos(); drawList.AddRectFilled(cursorScreenPos, new Vector2(cursorScreenPos.X + availableWidth, cursorScreenPos2.Y), ImGui.ColorConvertFloat4ToU32(CardBackgroundColor), 6f); drawList.AddRect(cursorScreenPos, new Vector2(cursorScreenPos.X + availableWidth, cursorScreenPos2.Y), ImGui.ColorConvertFloat4ToU32(CardBorderColor), 6f, ImDrawFlags.None, 1f); drawList.ChannelsMerge(); ImGui.SetCursorPos(new Vector2(contentStartPos.X, cursorPos.Y + 12f)); } public static ImRaii.TableDisposable BeginThemedTable(string id, int columns, ImGuiTableFlags extra = ImGuiTableFlags.None) { return ImRaii.Table(id, columns, ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerH | extra); } public static void SectionHeader(string title) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float textLineHeight = ImGui.GetTextLineHeight(); windowDrawList.AddRectFilled(cursorScreenPos, new Vector2(cursorScreenPos.X + 3f, cursorScreenPos.Y + textLineHeight), ImGui.ColorConvertFloat4ToU32(AccentColor)); ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 3f + 6f); ImGui.TextColored(in PrimaryTextColor, title); } public static void SectionSpacing() { ImGui.SetCursorPosY(ImGui.GetCursorPosY() + 16f); } public static void SubSectionHeader(string label) { ImGui.Spacing(); ImGui.TextColored(in DimTextColor, label); } public static void StatusBadge(string text, Vector4 color, FontAwesomeIcon icon) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float fontSize = ImGui.GetFontSize(); string text2 = icon.ToIconString(); Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text2); } Vector2 vector2 = ImGui.CalcTextSize(text); float num = 6f; float num2 = 2f; float num3 = 4f; float x = num + vector.X + num3 + vector2.X + num; float num4 = num2 + MathF.Max(vector.Y, vector2.Y) + num2; Vector2 pMin = cursorScreenPos; Vector2 pMax = cursorScreenPos + new Vector2(x, num4); Vector4 input = new Vector4(color.X, color.Y, color.Z, 0.15f); float rounding = num4 * 0.5f; windowDrawList.AddRectFilled(pMin, pMax, ImGui.ColorConvertFloat4ToU32(input), rounding); Vector2 pos = cursorScreenPos + new Vector2(num, num2); windowDrawList.AddText(UiBuilder.IconFont, fontSize, pos, ImGui.ColorConvertFloat4ToU32(color), text2); Vector2 pos2 = cursorScreenPos + new Vector2(num + vector.X + num3, num2); windowDrawList.AddText(pos2, ImGui.ColorConvertFloat4ToU32(color), text); ImGui.Dummy(new Vector2(x, num4)); } public static void StatusBanner(string text, Vector4 color, FontAwesomeIcon icon) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float fontSize = ImGui.GetFontSize(); string text2 = icon.ToIconString(); float x = ImGui.GetContentRegionAvail().X; Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text2); } Vector2 vector2 = ImGui.CalcTextSize(text); float y = 12f + MathF.Max(vector.Y, vector2.Y) + 12f; float num = 6f; Vector2 pMin = cursorScreenPos; Vector2 pMax = cursorScreenPos + new Vector2(x, y); Vector4 input = new Vector4(color.X, color.Y, color.Z, 0.1f); Vector4 input2 = new Vector4(color.X, color.Y, color.Z, 0.25f); windowDrawList.AddRectFilled(pMin, pMax, ImGui.ColorConvertFloat4ToU32(input), 6f); windowDrawList.AddRect(pMin, pMax, ImGui.ColorConvertFloat4ToU32(input2), 6f, ImDrawFlags.None, 1f); Vector2 pos = cursorScreenPos + new Vector2(12f, 12f); windowDrawList.AddText(UiBuilder.IconFont, fontSize, pos, ImGui.ColorConvertFloat4ToU32(color), text2); Vector2 pos2 = cursorScreenPos + new Vector2(12f + vector.X + num, 12f); windowDrawList.AddText(pos2, ImGui.ColorConvertFloat4ToU32(color), text); ImGui.Dummy(new Vector2(x, y)); } public static void EmptyState(FontAwesomeIcon icon, string title, string? hint = null) { float x = ImGui.GetContentRegionAvail().X; ImGui.Dummy(new Vector2(0f, 12f)); ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); string text = icon.ToIconString(); float fontSize = ImGui.GetFontSize() * 1.4f; Vector2 size; using (ImRaii.PushFont(UiBuilder.IconFont)) { size = ImGui.CalcTextSize(text) * 1.4f; } Vector2 pos = ImGui.GetCursorScreenPos() + new Vector2((x - size.X) / 2f, 0f); windowDrawList.AddText(UiBuilder.IconFont, fontSize, pos, ImGui.ColorConvertFloat4ToU32(MutedTextColor), text); ImGui.Dummy(size); ImGui.Spacing(); ImGui.SetCursorPosX((x - ImGui.CalcTextSize(title).X) / 2f); ImGui.TextColored(in DimTextColor, title); if (hint != null) { ImGui.Spacing(); ImGui.SetCursorPosX((x - ImGui.CalcTextSize(hint).X) / 2f); ImGui.TextColored(in MutedTextColor, hint); } ImGui.Dummy(new Vector2(0f, 12f)); } public static void DrawTrackerCount(string formattedText, bool isComplete, bool isEmpty) { ImGui.PushFont(UiBuilder.MonoFont); if (isEmpty) { ImGui.TextColored(in StatusUnobtainable, formattedText); } else if (isComplete) { ImGui.TextColored(in StatusComplete, formattedText); } else { ImGui.TextUnformatted(formattedText); } ImGui.PopFont(); } public static void DrawTrackerGroupCaret(IFontHandle iconFontFixedWidth, bool expanded) { ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, ImGui.ColorConvertFloat4ToU32(CardBackgroundColor)); using (iconFontFixedWidth.Push()) { ImGui.TextColored(in AccentColor, (expanded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight).ToIconString()); } } public static void DrawAltRowBackground(int rowIndex) { if (rowIndex % 2 == 0) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); windowDrawList.AddRectFilled(pMax: new Vector2(cursorScreenPos.X + ImGui.GetContentRegionAvail().X, cursorScreenPos.Y + ImGui.GetTextLineHeightWithSpacing()), pMin: cursorScreenPos, col: AltRowColor); } } public static void DrawRowBackground(Vector2 topLeft, Vector2 bottomRight) { ImGui.GetWindowDrawList().AddRectFilled(topLeft, bottomRight, ImGui.ColorConvertFloat4ToU32(CardBackgroundColor), 3f); } public static bool ThemedAccordion(string id, string label, string? rightText, ref bool open, bool enabled = true) { using (ImRaii.PushId(id)) { float x = ImGui.GetContentRegionAvail().X - _cardContentRightInset; float frameHeight = ImGui.GetFrameHeight(); using (ImRaii.ColorDisposable colorDisposable = ImRaii.PushColor(ImGuiCol.Header, Vector4.Zero)) { colorDisposable.Push(ImGuiCol.HeaderHovered, Vector4.Zero); colorDisposable.Push(ImGuiCol.HeaderActive, Vector4.Zero); if (ImGui.Selectable("##hdr", selected: false, ImGuiSelectableFlags.None, new Vector2(x, frameHeight)) && enabled) { open = !open; } } bool num = enabled && ImGui.IsItemHovered(); Vector2 itemRectMin = ImGui.GetItemRectMin(); Vector2 itemRectMax = ImGui.GetItemRectMax(); float x2 = ImGui.GetStyle().ItemSpacing.X; float num2 = MathF.Truncate(x2 * 0.5f); itemRectMin.X += num2; itemRectMax.X -= x2 - num2; ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); windowDrawList.AddRectFilled(itemRectMin, itemRectMax, ImGui.ColorConvertFloat4ToU32(CardBackgroundColor), 4f); windowDrawList.AddRect(itemRectMin, itemRectMax, ImGui.ColorConvertFloat4ToU32(CardBorderColor), 4f, ImDrawFlags.None, 1f); if (num) { windowDrawList.AddRectFilled(itemRectMin, itemRectMax, ImGui.ColorConvertFloat4ToU32(SubtleHoverColor), 4f); } float fontSize = ImGui.GetFontSize(); float num3 = itemRectMin.X + 12f; if (enabled) { string text = (open ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight).ToIconString(); Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text); } windowDrawList.AddText(UiBuilder.IconFont, fontSize, new Vector2(num3, itemRectMin.Y + (frameHeight - vector.Y) / 2f), ImGui.ColorConvertFloat4ToU32(AccentColor), text); } Vector2 vector2 = ImGui.CalcTextSize(label); windowDrawList.AddText(new Vector2(num3 + 18f, itemRectMin.Y + (frameHeight - vector2.Y) / 2f), ImGui.ColorConvertFloat4ToU32(enabled ? PrimaryTextColor : DimTextColor), label); if (!string.IsNullOrEmpty(rightText)) { Vector2 vector3; using (ImRaii.PushFont(UiBuilder.MonoFont)) { vector3 = ImGui.CalcTextSize(rightText); } float x3 = itemRectMax.X - 12f - vector3.X; windowDrawList.AddText(UiBuilder.MonoFont, fontSize, new Vector2(x3, itemRectMin.Y + (frameHeight - vector3.Y) / 2f), ImGui.ColorConvertFloat4ToU32(DimTextColor), rightText); } return open; } } public static bool WrappedCheckbox(string label, ref bool value, string? infoTooltip = null) { ImU8String label2 = new ImU8String(2, 1); label2.AppendLiteral("##"); label2.AppendFormatted(label); bool result = ImGui.Checkbox(label2, ref value); ImGui.SameLine(); if (infoTooltip != null) { float x; using (ImRaii.PushFont(UiBuilder.IconFont)) { x = ImGui.CalcTextSize(FontAwesomeIcon.InfoCircle.ToIconString()).X; } ImGui.PushTextWrapPos(ImGui.GetCursorPosX() + ImGui.GetContentRegionAvail().X - x - ImGui.GetStyle().ItemSpacing.X); ImGui.Text(label); ImGui.PopTextWrapPos(); ImGui.SameLine(); using (ImRaii.PushFont(UiBuilder.IconFont)) { ImGui.TextColored(in DimTextColor, FontAwesomeIcon.InfoCircle.ToIconString()); } if (ImGui.IsItemHovered()) { using (ImRaii.Tooltip()) { ImGui.PushTextWrapPos(400f); ImGui.Text(infoTooltip); ImGui.PopTextWrapPos(); } } } else { ImGui.PushTextWrapPos(0f); ImGui.Text(label); ImGui.PopTextWrapPos(); } return result; } public static int CheckboxGrid(string id, ReadOnlySpan items, int columns = 2) { using (ImRaii.PushId(id)) { float x = ImGui.GetContentRegionAvail().X; float x2 = ImGui.GetStyle().ItemSpacing.X; float num = 0f; ReadOnlySpan readOnlySpan = items; for (int i = 0; i < readOnlySpan.Length; i++) { GridCheckbox gridCheckbox = readOnlySpan[i]; float num2 = ImGui.GetFrameHeight() + x2 + ImGui.CalcTextSize(gridCheckbox.Label).X; if (gridCheckbox.Tooltip != null) { num2 += x2 + ImGui.GetFontSize(); } num = MathF.Max(num, num2); } while (columns > 1 && num > x / (float)columns) { columns--; } float num3 = x / (float)columns; int result = -1; for (int j = 0; j < items.Length; j++) { if (j % columns != 0) { ImGui.SameLine(num3 * (float)(j % columns)); } bool v = items[j].Value; ImU8String label = new ImU8String(4, 1); label.AppendLiteral("##cg"); label.AppendFormatted(j); if (ImGui.Checkbox(label, ref v)) { result = j; } ImGui.SameLine(); ImGui.TextUnformatted(items[j].Label); if (items[j].Tooltip != null) { ImGui.SameLine(); InfoIcon(items[j].Tooltip); } } return result; } } public static bool SearchInput(string id, ref string text, float width = -1E-45f, string hint = "Search...") { ImGui.SetNextItemWidth(width); return ImGui.InputTextWithHint(id, hint, ref text, 256); } public static void InfoIcon(string tooltip) { using (ImRaii.PushFont(UiBuilder.IconFont)) { ImGui.TextColored(in DimTextColor, FontAwesomeIcon.InfoCircle.ToIconString()); } if (ImGui.IsItemHovered()) { using (ImRaii.Tooltip()) { ImGui.PushTextWrapPos(400f); ImGui.Text(tooltip); ImGui.PopTextWrapPos(); } } } public static bool AccentSliderInt(string label, ref int value, int min, int max, float width = 250f) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float frameHeight = ImGui.GetFrameHeight(); float num = ((max > min) ? ((float)(value - min) / (float)(max - min)) : 0f); windowDrawList.AddRectFilled(cursorScreenPos, new Vector2(cursorScreenPos.X + width * num, cursorScreenPos.Y + frameHeight), ImGui.ColorConvertFloat4ToU32(AccentDimColor), 4f); using (ImRaii.PushColor(ImGuiCol.FrameBg, new Vector4(0.15f, 0.12f, 0.2f, 0.5f))) { ImGui.SetNextItemWidth(width); return ImGui.SliderInt(label, ref value, min, max); } } public static bool AccentSliderFloat(string label, ref float value, float min, float max, string format = "%.1f", float width = 250f) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float frameHeight = ImGui.GetFrameHeight(); float num = ((max > min) ? ((value - min) / (max - min)) : 0f); windowDrawList.AddRectFilled(cursorScreenPos, new Vector2(cursorScreenPos.X + width * num, cursorScreenPos.Y + frameHeight), ImGui.ColorConvertFloat4ToU32(AccentDimColor), 4f); using (ImRaii.PushColor(ImGuiCol.FrameBg, new Vector4(0.15f, 0.12f, 0.2f, 0.5f))) { ImGui.SetNextItemWidth(width); return ImGui.SliderFloat(label, ref value, min, max, format); } } public static bool ThemedCombo(string label, ref int currentItem, string[] items, int itemCount) { using ImRaii.ColorDisposable colorDisposable = ImRaii.PushColor(ImGuiCol.FrameBg, new Vector4(0.15f, 0.12f, 0.2f, 0.65f)); colorDisposable.Push(ImGuiCol.FrameBgHovered, new Vector4(0.2f, 0.16f, 0.28f, 0.75f)); colorDisposable.Push(ImGuiCol.FrameBgActive, new Vector4(0.22f, 0.18f, 0.3f, 0.85f)); string text = ((currentItem >= 0 && currentItem < itemCount) ? items[currentItem] : string.Empty); ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float num = ImGui.CalcItemWidth(); float frameHeight = ImGui.GetFrameHeight(); bool result = false; if (ImGui.BeginCombo(label, text, ImGuiComboFlags.NoArrowButton)) { Vector4 accentColor = AccentColor; accentColor.W = 0.35f; using ImRaii.ColorDisposable colorDisposable2 = ImRaii.PushColor(ImGuiCol.Header, accentColor); accentColor = AccentColor; accentColor.W = 0.45f; colorDisposable2.Push(ImGuiCol.HeaderHovered, accentColor); accentColor = AccentColor; accentColor.W = 0.6f; colorDisposable2.Push(ImGuiCol.HeaderActive, accentColor); colorDisposable2.Push(ImGuiCol.Text, new Vector4(0.95f, 0.95f, 1f, 1f)); for (int i = 0; i < itemCount; i++) { bool flag = i == currentItem; if (ImGui.Selectable(items[i], flag)) { currentItem = i; result = true; } if (flag) { ImGui.SetItemDefaultFocus(); } } ImGui.EndCombo(); } float x = ImGui.GetStyle().FramePadding.X; float num2 = 5f; float num3 = cursorScreenPos.X + num - x - num2; float num4 = cursorScreenPos.Y + frameHeight * 0.5f; windowDrawList.AddTriangleFilled(new Vector2(num3 - num2 * 0.5f, num4 - num2 * 0.4f), new Vector2(num3 + num2 * 0.5f, num4 - num2 * 0.4f), new Vector2(num3, num4 + num2 * 0.5f), ImGui.ColorConvertFloat4ToU32(DimTextColor)); return result; } public static bool SearchableCombo(string label, ref int currentItem, string[] items, ref string searchText, float width = 250f, string? previewOverride = null) { using ImRaii.ColorDisposable colorDisposable = ImRaii.PushColor(ImGuiCol.FrameBg, new Vector4(0.15f, 0.12f, 0.2f, 0.65f)); colorDisposable.Push(ImGuiCol.FrameBgHovered, new Vector4(0.2f, 0.16f, 0.28f, 0.75f)); colorDisposable.Push(ImGuiCol.FrameBgActive, new Vector4(0.22f, 0.18f, 0.3f, 0.85f)); string text = previewOverride ?? ((currentItem >= 0 && currentItem < items.Length) ? items[currentItem] : string.Empty); ImGui.SetNextItemWidth(width); ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float num = ImGui.CalcItemWidth(); float frameHeight = ImGui.GetFrameHeight(); bool result = false; if (ImGui.BeginCombo(label, text, ImGuiComboFlags.NoArrowButton)) { Vector4 accentColor = AccentColor; accentColor.W = 0.35f; using ImRaii.ColorDisposable colorDisposable2 = ImRaii.PushColor(ImGuiCol.Header, accentColor); accentColor = AccentColor; accentColor.W = 0.45f; colorDisposable2.Push(ImGuiCol.HeaderHovered, accentColor); accentColor = AccentColor; accentColor.W = 0.6f; colorDisposable2.Push(ImGuiCol.HeaderActive, accentColor); colorDisposable2.Push(ImGuiCol.Text, new Vector4(0.95f, 0.95f, 1f, 1f)); if (ImGui.IsWindowAppearing()) { searchText = string.Empty; ImGui.SetKeyboardFocusHere(); } ImGui.SetNextItemWidth(-1E-45f); ImGui.InputTextWithHint("##search", "Search...", ref searchText, 256); ImGui.Separator(); int num2 = items.Length; if (!string.IsNullOrEmpty(searchText)) { num2 = 0; for (int i = 0; i < items.Length; i++) { if (items[i].Contains(searchText, StringComparison.OrdinalIgnoreCase)) { num2++; } } } float textLineHeightWithSpacing = ImGui.GetTextLineHeightWithSpacing(); int max = Math.Max(1, (int)(250f * ImGuiHelpers.GlobalScale / textLineHeightWithSpacing)); float y = (float)Math.Clamp(Math.Max(num2, 1), 1, max) * textLineHeightWithSpacing + 4f; using (ImRaii.Child("##items", new Vector2(0f, y))) { if (num2 == 0) { ImGui.TextColored(in MutedTextColor, "No matches"); } else { for (int j = 0; j < items.Length; j++) { if (string.IsNullOrEmpty(searchText) || items[j].Contains(searchText, StringComparison.OrdinalIgnoreCase)) { bool flag = j == currentItem; if (ImGui.Selectable(items[j], flag)) { currentItem = j; result = true; ImGui.CloseCurrentPopup(); } if (flag) { ImGui.SetItemDefaultFocus(); } } } } } ImGui.EndCombo(); } float x = ImGui.GetStyle().FramePadding.X; float num3 = 5f; float num4 = cursorScreenPos.X + num - x - num3; float num5 = cursorScreenPos.Y + frameHeight * 0.5f; windowDrawList.AddTriangleFilled(new Vector2(num4 - num3 * 0.5f, num5 - num3 * 0.4f), new Vector2(num4 + num3 * 0.5f, num5 - num3 * 0.4f), new Vector2(num4, num5 + num3 * 0.5f), ImGui.ColorConvertFloat4ToU32(DimTextColor)); return result; } public static ImRaii.ColorDisposable PushProgressBarColors() { ImRaii.ColorDisposable colorDisposable = ImRaii.PushColor(ImGuiCol.PlotHistogram, AccentColor); colorDisposable.Push(ImGuiCol.FrameBg, new Vector4(1f, 1f, 1f, 0.12f)); return colorDisposable; } public static void DrawTabUnderline() { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 itemRectMin = ImGui.GetItemRectMin(); Vector2 itemRectMax = ImGui.GetItemRectMax(); windowDrawList.AddRectFilled(new Vector2(itemRectMin.X, itemRectMax.Y - 3f), new Vector2(itemRectMax.X, itemRectMax.Y), ImGui.ColorConvertFloat4ToU32(AccentColor)); } public static int DrawTabBar(string label0, string label1, int selected) { InlineArray2 buffer = default(InlineArray2); global::_003CPrivateImplementationDetails_003E.InlineArrayElementRef, string>(ref buffer, 0) = label0; global::_003CPrivateImplementationDetails_003E.InlineArrayElementRef, string>(ref buffer, 1) = label1; return DrawTabBar(global::_003CPrivateImplementationDetails_003E.InlineArrayAsReadOnlySpan, string>(in buffer, 2), selected, equalWidth: true); } public static int DrawTabBar(ReadOnlySpan labels, int selected, bool equalWidth = false) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); float x = ImGui.GetContentRegionAvail().X; float x2 = ImGui.GetStyle().ItemSpacing.X; float x3 = ImGui.GetCursorScreenPos().X; int result = selected; float x4 = 0f; float x5 = 0f; float num = 0f; float num2 = 0f; float num3 = (equalWidth ? ((x - x2 * (float)(labels.Length - 1)) / (float)labels.Length) : 0f); Span span = stackalloc float[labels.Length]; int num4 = 0; using (ImRaii.PushId("QstTabBar")) { using (ImRaii.PushColor(ImGuiCol.Button, Vector4.Zero)) { using (ImRaii.PushColor(ImGuiCol.ButtonHovered, SubtleHoverColor)) { using (ImRaii.PushColor(ImGuiCol.ButtonActive, SubtleActiveColor)) { float num5 = 0f; for (int i = 0; i < labels.Length; i++) { float num6 = (equalWidth ? num3 : (ImGui.CalcTextSize(labels[i]).X + ImGui.GetStyle().FramePadding.X * 2f)); if (i > 0) { if (num5 + x2 + num6 <= x) { ImGui.SameLine(); num5 += x2; } else { span[num4++] = num2; num5 = 0f; } } using (ImRaii.PushColor(ImGuiCol.Text, (i == selected) ? AccentColor : DimTextColor)) { if (ImGui.Button(labels[i], new Vector2(num6, 0f))) { result = i; } } if (i == selected) { x4 = ImGui.GetItemRectMin().X; x5 = ImGui.GetItemRectMax().X; num = ImGui.GetItemRectMax().Y; } num2 = ImGui.GetItemRectMax().Y; num5 += num6; } } } } } span[num4++] = num2; for (int j = 0; j < num4; j++) { windowDrawList.AddRectFilled(new Vector2(x3, span[j]), new Vector2(x3 + x, span[j] + 2f), ImGui.ColorConvertFloat4ToU32(AccentDimColor)); } windowDrawList.AddRectFilled(new Vector2(x4, num), new Vector2(x5, num + 2f), ImGui.ColorConvertFloat4ToU32(AccentColor)); ImGui.Spacing(); return result; } public static bool IconButton(FontAwesomeIcon icon, float size) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImU8String label = new ImU8String(2, 1); label.AppendLiteral("##"); label.AppendFormatted(icon); bool result = ImGui.Button(label, new Vector2(size, size)); string text = icon.ToIconString(); Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text); } uint colorU = ImGui.GetColorU32(ImGuiCol.Text); float x = cursorScreenPos.X + (size - vector.X) / 2f; float y = cursorScreenPos.Y + (size - vector.Y) / 2f; windowDrawList.AddText(UiBuilder.IconFont, ImGui.GetFontSize(), new Vector2(x, y), colorU, text); return result; } public static bool IconTextButton(FontAwesomeIcon icon, string text) { string text2 = icon.ToIconString(); Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text2); } Vector2 vector2 = ImGui.CalcTextSize(text); float num = 6f; float width = vector.X + num + vector2.X + 2f * ImGui.GetStyle().FramePadding.X; return IconTextButton(icon, text, width); } public static bool IconTextButton(FontAwesomeIcon icon, string text, float width) { ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); float frameHeight = ImGui.GetFrameHeight(); ImU8String label = new ImU8String(2, 1); label.AppendLiteral("##"); label.AppendFormatted(text); bool result = ImGui.Button(label, new Vector2(width, frameHeight)); string text2 = icon.ToIconString(); Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(text2); } Vector2 vector2 = ImGui.CalcTextSize(text); float num = 6f; float num2 = vector.X + num + vector2.X; float num3 = cursorScreenPos.X + (width - num2) / 2f; float y = cursorScreenPos.Y + ImGui.GetStyle().FramePadding.Y; uint colorU = ImGui.GetColorU32(ImGuiCol.Text); windowDrawList.AddText(UiBuilder.IconFont, ImGui.GetFontSize(), new Vector2(num3, y), colorU, text2); windowDrawList.AddText(new Vector2(num3 + vector.X + num, y), colorU, text); return result; } public static bool PillButton(string label, bool selected) { float value = ImGui.GetFrameHeight() * 0.5f; Vector2 framePadding = ImGui.GetStyle().FramePadding; using (ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, value)) { using (ImRaii.PushStyle(ImGuiStyleVar.FramePadding, new Vector2(framePadding.X * 2f, framePadding.Y))) { using (ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, selected ? 1f : 0f)) { using ImRaii.ColorDisposable colorDisposable = new ImRaii.ColorDisposable(); if (selected) { colorDisposable.Push(ImGuiCol.Button, new Vector4(0.55f, 0.35f, 0.8f, 0.3f)); colorDisposable.Push(ImGuiCol.ButtonHovered, new Vector4(0.55f, 0.35f, 0.8f, 0.4f)); colorDisposable.Push(ImGuiCol.ButtonActive, new Vector4(0.55f, 0.35f, 0.8f, 0.5f)); colorDisposable.Push(ImGuiCol.Border, CardBorderColor); colorDisposable.Push(ImGuiCol.Text, AccentColor); } else { colorDisposable.Push(ImGuiCol.Button, Vector4.Zero); colorDisposable.Push(ImGuiCol.ButtonHovered, SubtleHoverColor); colorDisposable.Push(ImGuiCol.ButtonActive, SubtlePressColor); colorDisposable.Push(ImGuiCol.Text, MutedTextColor); } return ImGui.Button(label); } } } } public static bool DestructiveButton(FontAwesomeIcon icon, string label) { bool result; using (ImRaii.ColorDisposable colorDisposable = ImRaii.PushColor(ImGuiCol.Button, new Vector4(0.55f, 0.2f, 0.2f, 0.45f))) { colorDisposable.Push(ImGuiCol.ButtonHovered, new Vector4(0.7f, 0.25f, 0.25f, 0.65f)); using (ImRaii.Disabled(!ImGui.IsKeyDown(ImGuiKey.ModCtrl))) { result = IconTextButton(icon, label); } } if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) { ImGui.SetTooltip("Hold CTRL to enable."); } return result; } public static string CleanSeString(string text) { if (string.IsNullOrEmpty(text)) { return text; } StringBuilder stringBuilder = new StringBuilder(text.Length); foreach (char c in text) { if ((c < '\ue000' || c > '\uf8ff') && (c >= ' ' || c == '\n' || c == '\r' || c == '\t')) { stringBuilder.Append(c); } } return stringBuilder.ToString().Trim(); } static UiThemeUtils() { Vector4 accentColor = AccentColor; accentColor.W = 0.12f; AccentDimColor = accentColor; accentColor = AccentColor; accentColor.W = 0.16f; CardBorderColor = accentColor; accentColor = AccentColor; accentColor.W = 0.35f; CardBorderHighColor = accentColor; PrimaryTextColor = new Vector4(0.95f, 0.95f, 1f, 1f); DimTextColor = new Vector4(0.565f, 0.533f, 0.659f, 1f); MutedTextColor = new Vector4(0.361f, 0.33f, 0.471f, 1f); PlayButtonColor = new Vector4(0.75f, 0.55f, 0.95f, 1f); PlayButtonHover = new Vector4(0.8f, 0.65f, 0.97f, 1f); PlayButtonActive = new Vector4(0.85f, 0.7f, 1f, 1f); PlayButtonText = new Vector4(0.08f, 0.06f, 0.12f, 1f); SubtleHoverColor = new Vector4(1f, 1f, 1f, 0.04f); SubtleActiveColor = new Vector4(1f, 1f, 1f, 0.06f); SubtlePressColor = new Vector4(1f, 1f, 1f, 0.08f); StatusComplete = ImGuiColors.ParsedGreen; StatusActive = ImGuiColors.DalamudYellow; StatusAvailable = ImGuiColors.DalamudYellow; StatusAvailableComplete = ImGuiColors.ParsedBlue; StatusLocked = ImGuiColors.DalamudRed; StatusUnobtainable = ImGuiColors.DalamudGrey; StatusBlacklisted = ImGuiColors.DalamudGrey3; Ellipsis = ((SeIconChar)57434).ToIconString(); } }