Better solver progress colors & add recipenote solver progress
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
using Dalamud.Interface.Colors;
|
||||||
|
using ImGuiNET;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Craftimizer.Utils;
|
namespace Craftimizer.Utils;
|
||||||
@@ -9,4 +11,24 @@ public static class Colors
|
|||||||
public static readonly Vector4 Durability = new(0.13f, 0.52f, 0.93f, 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 HQ = new(0.592f, 0.863f, 0.376f, 1f);
|
||||||
public static readonly Vector4 CP = new(0.63f, 0.37f, 0.75f, 1f);
|
public static readonly Vector4 CP = new(0.63f, 0.37f, 0.75f, 1f);
|
||||||
|
|
||||||
|
private static Vector4 SolverProgressBg => ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.TableBorderLight));
|
||||||
|
private static Vector4 SolverProgressFgBland => ImGuiColors.DalamudWhite2;
|
||||||
|
private static readonly Vector4[] SolverProgressFg = new Vector4[]
|
||||||
|
{
|
||||||
|
new(0.87f, 0.19f, 0.30f, 1f),
|
||||||
|
new(0.96f, 0.62f, 0.12f, 1f),
|
||||||
|
new(0.97f, 0.84f, 0.00f, 1f),
|
||||||
|
new(0.37f, 0.69f, 0.35f, 1f),
|
||||||
|
new(0.21f, 0.30f, 0.98f, 1f),
|
||||||
|
new(0.26f, 0.62f, 0.94f, 1f),
|
||||||
|
new(0.70f, 0.49f, 0.88f, 1f),
|
||||||
|
};
|
||||||
|
|
||||||
|
public static (Vector4 Background, Vector4 Foreground) GetSolverProgressColors(int? stageValue) =>
|
||||||
|
stageValue is not { } stage ?
|
||||||
|
(SolverProgressBg, SolverProgressFgBland) :
|
||||||
|
stage == 0 ?
|
||||||
|
(SolverProgressBg, SolverProgressFg[0]) :
|
||||||
|
(SolverProgressFg[(stage - 1) % SolverProgressFg.Length], SolverProgressFg[stage % SolverProgressFg.Length]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1257,8 +1257,11 @@ public sealed class MacroEditor : Window, IDisposable
|
|||||||
var percentWidth = ImGui.CalcTextSize("100%").X;
|
var percentWidth = ImGui.CalcTextSize("100%").X;
|
||||||
var progressWidth = availSpace - percentWidth - spacing;
|
var progressWidth = availSpace - percentWidth - spacing;
|
||||||
var fraction = Math.Clamp((float)solver.ProgressValue / solver.ProgressMax, 0, 1);
|
var fraction = Math.Clamp((float)solver.ProgressValue / solver.ProgressMax, 0, 1);
|
||||||
using (var color = ImRaii.PushColor(ImGuiCol.PlotHistogram, ImGuiColors.DalamudGrey3))
|
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
||||||
ImGui.ProgressBar(fraction, new(progressWidth, ImGui.GetFrameHeight()), string.Empty);
|
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.FrameBg, progressColors.Background))
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.PlotHistogram, progressColors.Foreground))
|
||||||
|
ImGui.ProgressBar(fraction, new(progressWidth, ImGui.GetFrameHeight()), string.Empty);
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
ImGuiUtils.Tooltip($"Solver Progress: {solver.ProgressValue} / {solver.ProgressMax}");
|
ImGuiUtils.Tooltip($"Solver Progress: {solver.ProgressValue} / {solver.ProgressMax}");
|
||||||
ImGui.SameLine(0, spacing);
|
ImGui.SameLine(0, spacing);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
|
|
||||||
private CancellationTokenSource? BestMacroTokenSource { get; set; }
|
private CancellationTokenSource? BestMacroTokenSource { get; set; }
|
||||||
private Exception? BestMacroException { get; set; }
|
private Exception? BestMacroException { get; set; }
|
||||||
|
private Solver.Solver? BestMacroSolver { get; set; }
|
||||||
public (Macro, SimulationState)? BestSavedMacro { get; private set; }
|
public (Macro, SimulationState)? BestSavedMacro { get; private set; }
|
||||||
public bool HasSavedMacro { get; private set; }
|
public bool HasSavedMacro { get; private set; }
|
||||||
public SolverSolution? BestSuggestedMacro { get; private set; }
|
public SolverSolution? BestSuggestedMacro { get; private set; }
|
||||||
@@ -264,19 +265,19 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
if (BestSavedMacro is { } savedMacro)
|
if (BestSavedMacro is { } savedMacro)
|
||||||
{
|
{
|
||||||
ImGuiUtils.TextCentered(savedMacro.Item1.Name, panelWidth);
|
ImGuiUtils.TextCentered(savedMacro.Item1.Name, panelWidth);
|
||||||
DrawMacro((savedMacro.Item1.Actions, savedMacro.Item2), a => { savedMacro.Item1.ActionEnumerable = a; Service.Configuration.Save(); }, stepsPanelWidthOffset, true);
|
DrawMacro((savedMacro.Item1.Actions, savedMacro.Item2), null, a => { savedMacro.Item1.ActionEnumerable = a; Service.Configuration.Save(); }, stepsPanelWidthOffset, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DrawMacro(null, null, stepsPanelWidthOffset, true);
|
DrawMacro(null, null, null, stepsPanelWidthOffset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var panel = ImRaii2.GroupPanel("Suggested Macro", panelWidth, out _))
|
using (var panel = ImRaii2.GroupPanel("Suggested Macro", panelWidth, out _))
|
||||||
{
|
{
|
||||||
var stepsPanelWidthOffset = ImGui.GetContentRegionAvail().X - panelWidth;
|
var stepsPanelWidthOffset = ImGui.GetContentRegionAvail().X - panelWidth;
|
||||||
if (BestSuggestedMacro is { } suggestedMacro)
|
if (BestSuggestedMacro is { } suggestedMacro)
|
||||||
DrawMacro((suggestedMacro.Actions, suggestedMacro.State), null, stepsPanelWidthOffset, false);
|
DrawMacro((suggestedMacro.Actions, suggestedMacro.State), null, null, stepsPanelWidthOffset, false);
|
||||||
else
|
else
|
||||||
DrawMacro(null, null, stepsPanelWidthOffset, false);
|
DrawMacro(null, BestMacroSolver, null, stepsPanelWidthOffset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiHelpers.ScaledDummy(5);
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
@@ -581,7 +582,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMacro((IReadOnlyList<ActionType> Actions, SimulationState State)? macroValue, Action<IEnumerable<ActionType>>? setter, float stepsAvailWidthOffset, bool isSavedMacro)
|
private void DrawMacro((IReadOnlyList<ActionType> Actions, SimulationState State)? macroValue, Solver.Solver? solver, Action<IEnumerable<ActionType>>? setter, float stepsAvailWidthOffset, bool isSavedMacro)
|
||||||
{
|
{
|
||||||
var windowHeight = 2 * ImGui.GetFrameHeightWithSpacing();
|
var windowHeight = 2 * ImGui.GetFrameHeightWithSpacing();
|
||||||
|
|
||||||
@@ -590,7 +591,33 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
if (isSavedMacro && !HasSavedMacro)
|
if (isSavedMacro && !HasSavedMacro)
|
||||||
ImGuiUtils.TextMiddleNewLine("You have no macros!", new(ImGui.GetContentRegionAvail().X - stepsAvailWidthOffset, windowHeight + 1));
|
ImGuiUtils.TextMiddleNewLine("You have no macros!", new(ImGui.GetContentRegionAvail().X - stepsAvailWidthOffset, windowHeight + 1));
|
||||||
else if (BestMacroException == null)
|
else if (BestMacroException == null)
|
||||||
ImGuiUtils.TextMiddleNewLine("Calculating...", new(ImGui.GetContentRegionAvail().X - stepsAvailWidthOffset, windowHeight + 1));
|
{
|
||||||
|
if (solver != null)
|
||||||
|
{
|
||||||
|
var calcTextSize = ImGui.CalcTextSize("Calculating...");
|
||||||
|
var spacing = ImGui.GetStyle().ItemSpacing.X;
|
||||||
|
var fraction = Math.Clamp((float)solver.ProgressValue / solver.ProgressMax, 0, 1);
|
||||||
|
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
||||||
|
|
||||||
|
ImGuiUtils.AlignCentered(windowHeight + spacing + calcTextSize.X, ImGui.GetContentRegionAvail().X - stepsAvailWidthOffset);
|
||||||
|
|
||||||
|
ImGuiUtils.ArcProgress(
|
||||||
|
fraction,
|
||||||
|
windowHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.ColorConvertFloat4ToU32(progressColors.Background),
|
||||||
|
ImGui.ColorConvertFloat4ToU32(progressColors.Foreground));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGuiUtils.Tooltip($"Solver Progress: {solver.ProgressValue} / {solver.ProgressMax}");
|
||||||
|
|
||||||
|
ImGui.SameLine(0, spacing);
|
||||||
|
|
||||||
|
ImGuiUtils.AlignMiddle(calcTextSize, new(calcTextSize.X, windowHeight));
|
||||||
|
ImGui.Text("Calculating...");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ImGuiUtils.TextMiddleNewLine("Calculating...", new(ImGui.GetContentRegionAvail().X - stepsAvailWidthOffset, windowHeight + 1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.AlignTextToFramePadding();
|
ImGui.AlignTextToFramePadding();
|
||||||
@@ -833,6 +860,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
{
|
{
|
||||||
BestMacroTokenSource?.Cancel();
|
BestMacroTokenSource?.Cancel();
|
||||||
BestMacroTokenSource = new();
|
BestMacroTokenSource = new();
|
||||||
|
BestMacroSolver = null;
|
||||||
BestMacroException = null;
|
BestMacroException = null;
|
||||||
BestSavedMacro = null;
|
BestSavedMacro = null;
|
||||||
HasSavedMacro = false;
|
HasSavedMacro = false;
|
||||||
@@ -900,6 +928,7 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
|
|
||||||
var solver = new Solver.Solver(config, state) { Token = token };
|
var solver = new Solver.Solver(config, state) { Token = token };
|
||||||
solver.OnLog += Log.Debug;
|
solver.OnLog += Log.Debug;
|
||||||
|
BestMacroSolver = solver;
|
||||||
solver.Start();
|
solver.Start();
|
||||||
var solution = solver.GetTask().GetAwaiter().GetResult();
|
var solution = solver.GetTask().GetAwaiter().GetResult();
|
||||||
|
|
||||||
|
|||||||
@@ -387,8 +387,11 @@ public sealed unsafe class SynthHelper : Window, IDisposable
|
|||||||
var percentWidth = ImGui.CalcTextSize("100%").X;
|
var percentWidth = ImGui.CalcTextSize("100%").X;
|
||||||
var progressWidth = availSpace - percentWidth - spacing;
|
var progressWidth = availSpace - percentWidth - spacing;
|
||||||
var fraction = Math.Clamp((float)solver.ProgressValue / solver.ProgressMax, 0, 1);
|
var fraction = Math.Clamp((float)solver.ProgressValue / solver.ProgressMax, 0, 1);
|
||||||
using (var color = ImRaii.PushColor(ImGuiCol.PlotHistogram, ImGuiColors.DalamudGrey3))
|
var progressColors = Colors.GetSolverProgressColors(solver.ProgressStage);
|
||||||
ImGui.ProgressBar(fraction, new(progressWidth, ImGui.GetFrameHeight()), string.Empty);
|
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.FrameBg, progressColors.Background))
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.PlotHistogram, progressColors.Foreground))
|
||||||
|
ImGui.ProgressBar(fraction, new(progressWidth, ImGui.GetFrameHeight()), string.Empty);
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
ImGuiUtils.Tooltip($"Solver Progress: {solver.ProgressValue} / {solver.ProgressMax}");
|
ImGuiUtils.Tooltip($"Solver Progress: {solver.ProgressValue} / {solver.ProgressMax}");
|
||||||
ImGui.SameLine(0, spacing);
|
ImGui.SameLine(0, spacing);
|
||||||
|
|||||||
+25
-8
@@ -22,11 +22,22 @@ public sealed class Solver : IDisposable
|
|||||||
|
|
||||||
private int progress;
|
private int progress;
|
||||||
private int maxProgress;
|
private int maxProgress;
|
||||||
|
private int progressStage;
|
||||||
|
|
||||||
// In iterative algorithms, the value can be reset back to 0.
|
// In iterative algorithms, the value can be reset back to 0 (and progress stage increases by 1)
|
||||||
// In other algorithms, the value increases monotonically.
|
// In other algorithms, the value increases monotonically.
|
||||||
public int ProgressValue => progress;
|
public int ProgressValue => progress;
|
||||||
|
// Maximum ProgressValue value.
|
||||||
public int ProgressMax => maxProgress;
|
public int ProgressMax => maxProgress;
|
||||||
|
// Always increases by 1 when ProgressValue is reset. Set to null if the algorithm is not iterative.
|
||||||
|
public int? ProgressStage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var stage = progressStage;
|
||||||
|
return stage == -1 ? null : stage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public delegate void LogDelegate(string text);
|
public delegate void LogDelegate(string text);
|
||||||
public delegate void NewActionDelegate(ActionType action);
|
public delegate void NewActionDelegate(ActionType action);
|
||||||
@@ -43,15 +54,17 @@ public sealed class Solver : IDisposable
|
|||||||
Config = config;
|
Config = config;
|
||||||
State = state;
|
State = state;
|
||||||
|
|
||||||
SearchFunc = Config.Algorithm switch
|
(SearchFunc, var hasProgressStage) = ((Func<Task<SolverSolution>>, bool))(Config.Algorithm switch
|
||||||
{
|
{
|
||||||
SolverAlgorithm.Oneshot => SearchOneshot,
|
SolverAlgorithm.Oneshot => (SearchOneshot, false),
|
||||||
SolverAlgorithm.OneshotForked => SearchOneshotForked,
|
SolverAlgorithm.OneshotForked => (SearchOneshotForked, false),
|
||||||
SolverAlgorithm.Stepwise => SearchStepwise,
|
SolverAlgorithm.Stepwise => (SearchStepwise, true),
|
||||||
SolverAlgorithm.StepwiseForked => SearchStepwiseForked,
|
SolverAlgorithm.StepwiseForked => (SearchStepwiseForked, true),
|
||||||
SolverAlgorithm.StepwiseFurcated => SearchStepwiseFurcated,
|
SolverAlgorithm.StepwiseFurcated => (SearchStepwiseFurcated, true),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(config), config, $"Invalid algorithm: {config.Algorithm}")
|
_ => throw new ArgumentOutOfRangeException(nameof(config), config, $"Invalid algorithm: {config.Algorithm}")
|
||||||
};
|
});
|
||||||
|
|
||||||
|
progressStage = hasProgressStage ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
@@ -116,7 +129,11 @@ public sealed class Solver : IDisposable
|
|||||||
|
|
||||||
private void ResetProgress()
|
private void ResetProgress()
|
||||||
{
|
{
|
||||||
|
if (!ProgressStage.HasValue)
|
||||||
|
throw new InvalidOperationException("Progress cannot be reset.");
|
||||||
|
|
||||||
Interlocked.Exchange(ref progress, 0);
|
Interlocked.Exchange(ref progress, 0);
|
||||||
|
Interlocked.Increment(ref progressStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SolverSolution> SearchStepwiseFurcated()
|
private async Task<SolverSolution> SearchStepwiseFurcated()
|
||||||
|
|||||||
Reference in New Issue
Block a user