From 1e873729d48cbd1ae491fe634d27380bb96a644d Mon Sep 17 00:00:00 2001 From: Asriel Camora Date: Fri, 23 Feb 2024 07:16:02 -0800 Subject: [PATCH] Implement collectability bars --- Craftimizer/LuminaSheets.cs | 22 ++++++------- Craftimizer/Utils/Colors.cs | 8 +++++ Craftimizer/Utils/DynamicBars.cs | 51 ++++++++++++++++++++++++++---- Craftimizer/Utils/RecipeData.cs | 2 +- Craftimizer/Windows/MacroEditor.cs | 8 ++--- Craftimizer/Windows/SynthHelper.cs | 6 ++-- 6 files changed, 71 insertions(+), 26 deletions(-) diff --git a/Craftimizer/LuminaSheets.cs b/Craftimizer/LuminaSheets.cs index 8ccfbfe..e67b141 100644 --- a/Craftimizer/LuminaSheets.cs +++ b/Craftimizer/LuminaSheets.cs @@ -75,17 +75,17 @@ public class SharlayanCraftWorksSupply : ExcelRow for (var i = 0; i < 4; i++) { Items[i] = new ItemData(); - Items[i].Level = parser.ReadColumn(0 + (i * 11 + 0)); - Items[i].Item = new LazyRow(gameData, parser.ReadColumn(0 + (i * 11 + 1)), language); - Items[i].CollectabilityMid = parser.ReadColumn(0 + (i * 11 + 2)); - Items[i].CollectabilityHigh = parser.ReadColumn(0 + (i * 11 + 3)); - Items[i].XPReward = parser.ReadColumn(0 + (i * 11 + 4)); - Items[i].HighXPMultiplier = parser.ReadColumn(0 + (i * 11 + 5)); - Items[i].GilReward = parser.ReadColumn(0 + (i * 11 + 6)); - Items[i].HighGilMultiplier = parser.ReadColumn(0 + (i * 11 + 7)); - Items[i].Unknown8 = parser.ReadColumn(0 + (i * 11 + 8)); - Items[i].ScripReward = parser.ReadColumn(0 + (i * 11 + 9)); - Items[i].HighScripMultiplier = parser.ReadColumn(0 + (i * 11 + 10)); + Items[i].Level = parser.ReadColumn(0 * 4 + i); + Items[i].Item = new LazyRow(gameData, parser.ReadColumn(1 * 4 + i), language); + Items[i].CollectabilityMid = parser.ReadColumn(2 * 4 + i); + Items[i].CollectabilityHigh = parser.ReadColumn(3 * 4 + i); + Items[i].XPReward = parser.ReadColumn(4 * 4 + i); + Items[i].HighXPMultiplier = parser.ReadColumn(5 * 4 + i); + Items[i].GilReward = parser.ReadColumn(6 * 4 + i); + Items[i].HighGilMultiplier = parser.ReadColumn(7 * 4 + i); + Items[i].Unknown8 = parser.ReadColumn(8 * 4 + i); + Items[i].ScripReward = parser.ReadColumn(9 * 4 + i); + Items[i].HighScripMultiplier = parser.ReadColumn(10 * 4 + i); } } } diff --git a/Craftimizer/Utils/Colors.cs b/Craftimizer/Utils/Colors.cs index c74bdaf..7a62786 100644 --- a/Craftimizer/Utils/Colors.cs +++ b/Craftimizer/Utils/Colors.cs @@ -10,6 +10,7 @@ public static class Colors public static readonly Vector4 Quality = new(0.26f, 0.71f, 0.69f, 1f); public static readonly Vector4 Durability = new(0.13f, 0.52f, 0.93f, 1f); public static readonly Vector4 HQ = new(0.592f, 0.863f, 0.376f, 1f); + public static readonly Vector4 Collectability = new(0.99f, 0.56f, 0.57f, 1f); public static readonly Vector4 CP = new(0.63f, 0.37f, 0.75f, 1f); private static Vector4 SolverProgressBg => ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.TableBorderLight)); @@ -25,6 +26,13 @@ public static class Colors new(0.70f, 0.49f, 0.88f, 1f), }; + public static readonly Vector4[] CollectabilityThreshold = new Vector4[] + { + new(0.47f, 0.78f, 0.93f, 1f), // Blue + new(0.99f, 0.79f, 0f, 1f), // Yellow + new(0.75f, 1f, 0.75f, 1f), // Green + }; + public static (Vector4 Background, Vector4 Foreground) GetSolverProgressColors(int? stageValue) => stageValue is not { } stage ? (SolverProgressBg, SolverProgressFgBland) : diff --git a/Craftimizer/Utils/DynamicBars.cs b/Craftimizer/Utils/DynamicBars.cs index 9e4dbcd..225c0ff 100644 --- a/Craftimizer/Utils/DynamicBars.cs +++ b/Craftimizer/Utils/DynamicBars.cs @@ -5,19 +5,20 @@ using System.Collections.Generic; using System; using System.Numerics; using System.Linq; +using Dalamud.Utility.Numerics; namespace Craftimizer.Utils; internal static class DynamicBars { - public readonly record struct BarData(string Name, Vector4 Color, SimulatedMacro.Reliablity.Param? Reliability, float Value, float Max, string? Caption = null, Action? CustomDrawer = null) + public readonly record struct BarData(string Name, Vector4 Color, SimulatedMacro.Reliablity.Param? Reliability, float Value, float Max, IReadOnlyList? Collectability = null, string? Caption = null, string? DefaultCaptionSizeText = null, Action? CustomDrawer = null) { - public BarData(string name, Action customDrawer) : this(name, default, null, 0, 0, null, customDrawer) + public BarData(string name, Action customDrawer) : this(name, default, null, 0, 0, null, null, null, customDrawer) { } - public BarData(string name, Vector4 color, float value, float max) : this(name, color, null, value, max, null, null) + public BarData(string name, Vector4 color, float value, float max) : this(name, color, null, value, max, null, null, null) { } @@ -30,12 +31,17 @@ internal static class DynamicBars { if (b.CustomDrawer is { }) return 0; + var defaultSize = 0f; + if (b.DefaultCaptionSizeText is { } defaultCaptionSizeText) + defaultSize = ImGui.CalcTextSize(defaultCaptionSizeText).X; if (b.Caption is { } caption) - return ImGui.CalcTextSize(caption).X; + return Math.Max(ImGui.CalcTextSize(caption).X, defaultSize); // max (sp/2) "/" (sp/2) max - return Math.Max(ImGui.CalcTextSize($"{b.Value:0}").X, ImGui.CalcTextSize($"{b.Max:0}").X) * 2 + return Math.Max( + Math.Max(ImGui.CalcTextSize($"{b.Value:0}").X, ImGui.CalcTextSize($"{b.Max:0}").X) * 2 + ImGui.GetStyle().ItemSpacing.X - + ImGui.CalcTextSize("/").X; + + ImGui.CalcTextSize("/").X, + defaultSize); }); public static void Draw(IEnumerable bars, float? textSize = null) @@ -54,8 +60,40 @@ internal static class DynamicBars else { var pos = ImGui.GetCursorPos(); + var screenPos = ImGui.GetCursorScreenPos(); using (var color = ImRaii.PushColor(ImGuiCol.PlotHistogram, bar.Color)) ImGui.ProgressBar(Math.Clamp(bar.Value / bar.Max, 0, 1), new(barSize, ImGui.GetFrameHeight()), string.Empty); + var passedCollectabilityColor = 0; + if (bar.Collectability is { } collectability) + { + var i = 0; + var rounding = ImGui.GetStyle().FrameRounding; + var height = ImGui.GetFrameHeight(); + foreach (var (c, color) in collectability.Zip(Colors.CollectabilityThreshold)) + { + ++i; + if (c is not { } threshold) + continue; + var offset = barSize * threshold / bar.Max; + var isLast = i == collectability.Count; + var offsetNext = isLast ? barSize : barSize * collectability[i]!.Value / bar.Max; + var passedThreshold = bar.Value >= threshold; + if (passedThreshold) + passedCollectabilityColor = i; + ImGui.GetWindowDrawList().AddRectFilled( + screenPos + new Vector2(offset, 0), + screenPos + new Vector2(offsetNext, height), + ImGui.GetColorU32(color.WithW(passedThreshold ? 0.6f : 0.2f)), + isLast ? rounding : 0 + ); + ImGui.GetWindowDrawList().AddLine( + screenPos + new Vector2(offset, 0), + screenPos + new Vector2(offset, height), + ImGui.GetColorU32(color), + Math.Max(passedThreshold ? 3 : 1.5f, rounding / 2f) + ); + } + } if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenOverlapped)) { if (bar.Reliability is { } reliability) @@ -75,6 +113,7 @@ internal static class DynamicBars } ImGui.SameLine(0, spacing); ImGui.AlignTextToFramePadding(); + using var _color = ImRaii.PushColor(ImGuiCol.Text, passedCollectabilityColor != 0 ? Colors.CollectabilityThreshold[passedCollectabilityColor - 1] : default, passedCollectabilityColor != 0); if (bar.Caption is { } caption) ImGuiUtils.TextRight(caption, textSize.Value); else diff --git a/Craftimizer/Utils/RecipeData.cs b/Craftimizer/Utils/RecipeData.cs index e97cbca..7caba52 100644 --- a/Craftimizer/Utils/RecipeData.cs +++ b/Craftimizer/Utils/RecipeData.cs @@ -83,7 +83,7 @@ public sealed record RecipeData case 4: var data4 = LuminaSheets.SharlayanCraftWorksSupplySheet.GetRow(Recipe.Unknown46); if (data4 == null) - goto default; + break; foreach (var item in data4.Items) { if (item.Item.Row == Recipe.ItemResult.Row) diff --git a/Craftimizer/Windows/MacroEditor.cs b/Craftimizer/Windows/MacroEditor.cs index 2a95be5..499fed6 100644 --- a/Craftimizer/Windows/MacroEditor.cs +++ b/Craftimizer/Windows/MacroEditor.cs @@ -189,8 +189,6 @@ public sealed class MacroEditor : Window, IDisposable if (modifiedInput) RecalculateState(); - ImGui.Separator(); - using (var table = ImRaii.Table("macroInfo", 2, ImGuiTableFlags.BordersInnerV | ImGuiTableFlags.SizingStretchSame)) { if (table) @@ -1052,14 +1050,14 @@ public sealed class MacroEditor : Window, IDisposable new("Condition", DrawCondition) }; if (RecipeData.Recipe.ItemResult.Value!.IsCollectable) - datas.Add(new("Collectability", Colors.HQ, Reliability.ParamScore, State.Collectability, State.MaxCollectability, $"{State.Collectability}")); + datas.Add(new("Collectability", Colors.Collectability, Reliability.ParamScore, State.Collectability, State.MaxCollectability, RecipeData.CollectableThresholds, $"{State.Collectability}", $"{State.MaxCollectability:0}")); else if (RecipeData.Recipe.RequiredQuality > 0) { var qualityPercent = (float)State.Quality / RecipeData.Recipe.RequiredQuality * 100; - datas.Add(new("Quality %", Colors.HQ, Reliability.ParamScore, qualityPercent, 100, $"{qualityPercent:0}%")); + datas.Add(new("Quality %", Colors.HQ, Reliability.ParamScore, qualityPercent, 100, null, $"{qualityPercent:0}%")); } else if (RecipeData.RecipeInfo.MaxQuality > 0) - datas.Add(new("HQ %", Colors.HQ, Reliability.ParamScore, State.HQPercent, 100, $"{State.HQPercent}%")); + datas.Add(new("HQ %", Colors.HQ, Reliability.ParamScore, State.HQPercent, 100, null, $"{State.HQPercent}%")); DynamicBars.Draw(datas); ImGui.TableNextColumn(); diff --git a/Craftimizer/Windows/SynthHelper.cs b/Craftimizer/Windows/SynthHelper.cs index 5e52044..3c20a18 100644 --- a/Craftimizer/Windows/SynthHelper.cs +++ b/Craftimizer/Windows/SynthHelper.cs @@ -349,14 +349,14 @@ public sealed unsafe class SynthHelper : Window, IDisposable new("Durability", Colors.Durability, state.Durability, RecipeData.RecipeInfo.MaxDurability), }; if (RecipeData.Recipe.ItemResult.Value!.IsCollectable) - halfBars.Add(new("Collectability", Colors.HQ, reliability.ParamScore, state.Collectability, state.MaxCollectability, $"{state.Collectability}", null)); + halfBars.Add(new("Collectability", Colors.Collectability, reliability.ParamScore, state.Collectability, state.MaxCollectability, RecipeData.CollectableThresholds, $"{state.Collectability}", $"{state.MaxCollectability:0}")); else if (RecipeData.Recipe.RequiredQuality > 0) { var qualityPercent = (float)state.Quality / RecipeData.Recipe.RequiredQuality * 100; - halfBars.Add(new("Quality %", Colors.HQ, reliability.ParamScore, qualityPercent, 100, $"{qualityPercent:0}%", null)); + halfBars.Add(new("Quality %", Colors.HQ, reliability.ParamScore, qualityPercent, 100, null, $"{qualityPercent:0}%", null)); } else if (RecipeData.RecipeInfo.MaxQuality > 0) - halfBars.Add(new("HQ %", Colors.HQ, reliability.ParamScore, state.HQPercent, 100, $"{state.HQPercent}%", null)); + halfBars.Add(new("HQ %", Colors.HQ, reliability.ParamScore, state.HQPercent, 100, null, $"{state.HQPercent}%", null)); if (halfBars.Count > 1) {