Fix UIColor layout (#1998)

* Fix UIColor layout

* Handle <color(0)> correctly
This commit is contained in:
srkizer 2024-08-07 05:31:24 +09:00 committed by GitHub
parent 88bb224894
commit 018524fb8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 105 additions and 66 deletions

View file

@ -148,10 +148,12 @@ internal sealed class SeStringColorStackSet
if (expr.TryGetUInt(out var bgra)) if (expr.TryGetUInt(out var bgra))
{ {
// NOTE: if it reads a `0`, then it seems to be doing something else. // <color(0)> adds the color on the top of the stack. This makes usages like <color(gnum99)> effectively
// See case 0x12 from `Component::GUI::AtkFontAnalyzerBase.vf4`. // become a no-op if no value is provided.
// Fix when someone figures what's this about. if (bgra == 0)
rgbaStack.Add(ColorHelpers.SwapRedBlue(bgra) | 0xFF000000u); rgbaStack.Add(rgbaStack[^1]);
else
rgbaStack.Add(ColorHelpers.SwapRedBlue(bgra) | 0xFF000000u);
return rgbaStack[^1]; return rgbaStack[^1];
} }

View file

@ -1,9 +1,13 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Interface.ImGuiNotification;
using Dalamud.Interface.ImGuiNotification.Internal;
using Dalamud.Interface.ImGuiSeStringRenderer.Internal; using Dalamud.Interface.ImGuiSeStringRenderer.Internal;
using Dalamud.Interface.Utility;
using Dalamud.Storage.Assets; using Dalamud.Storage.Assets;
using ImGuiNET; using ImGuiNET;
@ -41,21 +45,35 @@ internal class UiColorWidget : IDataWindowWidget
this.colors ??= Service<DataManager>.Get().GetExcelSheet<UIColor>()?.ToArray(); this.colors ??= Service<DataManager>.Get().GetExcelSheet<UIColor>()?.ToArray();
if (this.colors is null) return; if (this.colors is null) return;
ImGui.TextUnformatted("Color notation is #RRGGBB."); Service<SeStringRenderer>.Get().CompileAndDrawWrapped(
"· Color notation is #" +
"<edgecolor(0xFFEEEE)><color(0xFF0000)>RR<color(stackcolor)><edgecolor(stackcolor)>" +
"<edgecolor(0xEEFFEE)><color(0x00FF00)>GG<color(stackcolor)><edgecolor(stackcolor)>" +
"<edgecolor(0xEEEEFF)><color(0x0000FF)>BB<color(stackcolor)><edgecolor(stackcolor)>.<br>" +
"· Click on a color to copy the color code.<br>" +
"· Hover on a color to preview the text with edge, when the next color has been used together.");
if (!ImGui.BeginTable("UIColor", 5)) if (!ImGui.BeginTable("UIColor", 5))
return; return;
ImGui.TableSetupScrollFreeze(0, 1); ImGui.TableSetupScrollFreeze(0, 1);
var basew = ImGui.CalcTextSize("9").X; var rowidw = ImGui.CalcTextSize("9999999").X;
ImGui.TableSetupColumn("Row ID", ImGuiTableColumnFlags.WidthFixed, basew * 7); var colorw = ImGui.CalcTextSize("#999999").X;
ImGui.TableSetupColumn("Dark", ImGuiTableColumnFlags.WidthFixed, basew * 17); colorw = Math.Max(colorw, ImGui.CalcTextSize("#AAAAAA").X);
ImGui.TableSetupColumn("Light", ImGuiTableColumnFlags.WidthFixed, basew * 17); colorw = Math.Max(colorw, ImGui.CalcTextSize("#BBBBBB").X);
ImGui.TableSetupColumn("Classic FF", ImGuiTableColumnFlags.WidthFixed, basew * 17); colorw = Math.Max(colorw, ImGui.CalcTextSize("#CCCCCC").X);
ImGui.TableSetupColumn("Clear Blue", ImGuiTableColumnFlags.WidthFixed, basew * 17); colorw = Math.Max(colorw, ImGui.CalcTextSize("#DDDDDD").X);
colorw = Math.Max(colorw, ImGui.CalcTextSize("#EEEEEE").X);
colorw = Math.Max(colorw, ImGui.CalcTextSize("#FFFFFF").X);
colorw += ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X;
ImGui.TableSetupColumn("Row ID", ImGuiTableColumnFlags.WidthFixed, rowidw);
ImGui.TableSetupColumn("Dark", ImGuiTableColumnFlags.WidthFixed, colorw);
ImGui.TableSetupColumn("Light", ImGuiTableColumnFlags.WidthFixed, colorw);
ImGui.TableSetupColumn("Classic FF", ImGuiTableColumnFlags.WidthFixed, colorw);
ImGui.TableSetupColumn("Clear Blue", ImGuiTableColumnFlags.WidthFixed, colorw);
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper()); var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
clipper.Begin(this.colors.Length); clipper.Begin(this.colors.Length, ImGui.GetFrameHeightWithSpacing());
while (clipper.Step()) while (clipper.Step())
{ {
for (var i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) for (var i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
@ -70,32 +88,32 @@ internal class UiColorWidget : IDataWindowWidget
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.PushID($"row{id}_col1"); ImGui.PushID($"row{id}_col1");
DrawColorColumn(this.colors[i].UIForeground); if (this.DrawColorColumn(this.colors[i].UIForeground) &&
if (id is >= 500 and < 580) i + 1 < this.colors.Length && this.colors[i + 1].RowId == id + 1)
DrawEdgePreview(id, this.colors[i].UIForeground, this.colors[i + 1].UIForeground); DrawEdgePreview(id, this.colors[i].UIForeground, this.colors[i + 1].UIForeground);
ImGui.PopID(); ImGui.PopID();
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.PushID($"row{id}_col2"); ImGui.PushID($"row{id}_col2");
DrawColorColumn(this.colors[i].UIGlow); if (this.DrawColorColumn(this.colors[i].UIGlow) &&
if (id is >= 500 and < 580) i + 1 < this.colors.Length && this.colors[i + 1].RowId == id + 1)
DrawEdgePreview(id, this.colors[i].UIGlow, this.colors[i + 1].UIGlow); DrawEdgePreview(id, this.colors[i].UIGlow, this.colors[i + 1].UIGlow);
ImGui.PopID(); ImGui.PopID();
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.PushID($"row{id}_col3"); ImGui.PushID($"row{id}_col3");
DrawColorColumn(this.colors[i].Unknown2); if (this.DrawColorColumn(this.colors[i].Unknown2) &&
if (id is >= 500 and < 580) i + 1 < this.colors.Length && this.colors[i + 1].RowId == id + 1)
DrawEdgePreview(id, this.colors[i].Unknown2, this.colors[i + 1].Unknown2); DrawEdgePreview(id, this.colors[i].Unknown2, this.colors[i + 1].Unknown2);
ImGui.PopID(); ImGui.PopID();
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
ImGui.PushID($"row{id}_col4"); ImGui.PushID($"row{id}_col4");
DrawColorColumn(this.colors[i].Unknown3); if (this.DrawColorColumn(this.colors[i].Unknown3) &&
if (id is >= 500 and < 580) i + 1 < this.colors.Length && this.colors[i + 1].RowId == id + 1)
DrawEdgePreview(id, this.colors[i].Unknown3, this.colors[i + 1].Unknown3); DrawEdgePreview(id, this.colors[i].Unknown3, this.colors[i + 1].Unknown3);
ImGui.PopID(); ImGui.PopID();
} }
@ -105,58 +123,77 @@ internal class UiColorWidget : IDataWindowWidget
ImGui.EndTable(); ImGui.EndTable();
} }
private static void DrawColorColumn(uint sheetColor)
{
sheetColor = BinaryPrimitives.ReverseEndianness(sheetColor);
ImGui.Image(
Service<DalamudAssetManager>.Get().White4X4.ImGuiHandle,
new(ImGui.GetFrameHeight()),
Vector2.Zero,
Vector2.One,
ImGui.ColorConvertU32ToFloat4(sheetColor | 0xFF000000u));
ImGui.SameLine();
ImGui.TextUnformatted($"#{sheetColor & 0xFF:X02}{(sheetColor >> 8) & 0xFF:X02}{(sheetColor >> 16) & 0xFF:X02}");
}
private static void DrawEdgePreview(uint id, uint sheetColor, uint sheetColor2) private static void DrawEdgePreview(uint id, uint sheetColor, uint sheetColor2)
{ {
ImGui.SameLine(); ImGui.BeginTooltip();
if (Service<SeStringRenderer>.Get().Draw( Span<byte> buf = stackalloc byte[256];
new("+E"u8), var ptr = 0;
new() ptr += Encoding.UTF8.GetBytes("<colortype(", buf[ptr..]);
{ id.TryFormat(buf[ptr..], out var bytesWritten);
Edge = true, ptr += bytesWritten;
Color = BinaryPrimitives.ReverseEndianness(sheetColor) | 0xFF000000u, ptr += Encoding.UTF8.GetBytes(")><edgecolortype(", buf[ptr..]);
EdgeColor = BinaryPrimitives.ReverseEndianness(sheetColor2) | 0xFF000000u, (id + 1).TryFormat(buf[ptr..], out bytesWritten);
}, ptr += bytesWritten;
"+E"u8).Clicked) ptr += Encoding.UTF8.GetBytes(")>", buf[ptr..]);
ImGui.SetClipboardText($"<colortype({id})><edgecolortype({id + 1})>+E<edgecolortype(0)><colortype(0)>"); Service<SeStringRenderer>.Get().Draw(
if (ImGui.IsItemHovered()) buf[..ptr],
ImGui.SetTooltip($"<colortype({id})><edgecolortype({id + 1})>+E<edgecolortype(0)><colortype(0)>"); new()
{
Edge = true,
Color = BinaryPrimitives.ReverseEndianness(sheetColor) | 0xFF000000u,
EdgeColor = BinaryPrimitives.ReverseEndianness(sheetColor2) | 0xFF000000u,
WrapWidth = float.PositiveInfinity,
});
ImGui.SameLine(); ptr = 0;
ImGui.AlignTextToFramePadding(); ptr += Encoding.UTF8.GetBytes("<colortype(", buf[ptr..]);
if (Service<SeStringRenderer>.Get().Draw( (id + 1).TryFormat(buf[ptr..], out bytesWritten);
new("+F"u8), ptr += bytesWritten;
new() ptr += Encoding.UTF8.GetBytes(")><edgecolortype(", buf[ptr..]);
{ id.TryFormat(buf[ptr..], out bytesWritten);
Edge = true, ptr += bytesWritten;
Color = BinaryPrimitives.ReverseEndianness(sheetColor2) | 0xFF000000u, ptr += Encoding.UTF8.GetBytes(")>", buf[ptr..]);
EdgeColor = BinaryPrimitives.ReverseEndianness(sheetColor) | 0xFF000000u, Service<SeStringRenderer>.Get().Draw(
}, buf[..ptr],
"+F"u8).Clicked) new()
ImGui.SetClipboardText($"<colortype({id + 1})><edgecolortype({id})>+E<edgecolortype(0)><colortype(0)>"); {
if (ImGui.IsItemHovered()) Edge = true,
ImGui.SetTooltip($"<colortype({id + 1})><edgecolortype({id})>+E<edgecolortype(0)><colortype(0)>"); Color = BinaryPrimitives.ReverseEndianness(sheetColor2) | 0xFF000000u,
EdgeColor = BinaryPrimitives.ReverseEndianness(sheetColor) | 0xFF000000u,
WrapWidth = float.PositiveInfinity,
});
ImGui.EndTooltip();
} }
private Vector4 ConvertToVector4(uint color) private bool DrawColorColumn(uint sheetColor)
{ {
var r = (byte)(color >> 24); sheetColor = BinaryPrimitives.ReverseEndianness(sheetColor);
var g = (byte)(color >> 16); var rgbtext = $"#{sheetColor & 0xFF:X02}{(sheetColor >> 8) & 0xFF:X02}{(sheetColor >> 16) & 0xFF:X02}";
var b = (byte)(color >> 8); var size = new Vector2(ImGui.GetFrameHeight());
var a = (byte)color; size.X += ImGui.CalcTextSize(rgbtext).X + ImGui.GetStyle().FramePadding.X;
return new Vector4(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); var off = ImGui.GetCursorScreenPos();
ImGui.GetWindowDrawList().AddRectFilled(
off,
off + new Vector2(size.Y),
sheetColor | 0xFF000000u);
ImGui.GetWindowDrawList().AddText(
off + ImGui.GetStyle().FramePadding + new Vector2(size.Y, 0),
ImGui.GetColorU32(ImGuiCol.Text),
rgbtext);
if (ImGui.InvisibleButton("##copy", size))
{
ImGui.SetClipboardText(rgbtext);
Service<NotificationManager>.Get().AddNotification(
new()
{
Content = $"Copied \"{rgbtext}\".",
Title = this.DisplayName,
Type = NotificationType.Success,
});
}
return ImGui.IsItemHovered();
} }
} }