Finish crafting log helper window
This commit is contained in:
@@ -26,6 +26,7 @@ public class Configuration : IPluginConfiguration
|
|||||||
public SolverConfig SimulatorSolverConfig { get; set; } = SolverConfig.SimulatorDefault;
|
public SolverConfig SimulatorSolverConfig { get; set; } = SolverConfig.SimulatorDefault;
|
||||||
public SolverConfig SynthHelperSolverConfig { get; set; } = SolverConfig.SynthHelperDefault;
|
public SolverConfig SynthHelperSolverConfig { get; set; } = SolverConfig.SynthHelperDefault;
|
||||||
public bool EnableSynthHelper { get; set; } = true;
|
public bool EnableSynthHelper { get; set; } = true;
|
||||||
|
public bool ShowOptimalMacroStat { get; set; } = true;
|
||||||
public int SynthHelperStepCount { get; set; } = 5;
|
public int SynthHelperStepCount { get; set; } = 5;
|
||||||
|
|
||||||
public Simulator.Simulator CreateSimulator(SimulationState state) =>
|
public Simulator.Simulator CreateSimulator(SimulationState state) =>
|
||||||
|
|||||||
+117
-11
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Craftimizer.Plugin;
|
namespace Craftimizer.Plugin;
|
||||||
|
|
||||||
internal static class ImGuiUtils
|
internal static class ImGuiUtils
|
||||||
@@ -124,6 +125,96 @@ internal static class ImGuiUtils
|
|||||||
ImGui.EndGroup();
|
ImGui.EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Vector2 UnitCircle(float theta)
|
||||||
|
{
|
||||||
|
var (s, c) = MathF.SinCos(theta);
|
||||||
|
// SinCos positive y is downwards, but we want it upwards for ImGui
|
||||||
|
return new Vector2(c, -s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float Lerp(float a, float b, float t) =>
|
||||||
|
MathF.FusedMultiplyAdd(b - a, t, a);
|
||||||
|
|
||||||
|
private static void ArcSegment(Vector2 o, Vector2 prev, Vector2 cur, Vector2? next, float radius, float ratio, uint color)
|
||||||
|
{
|
||||||
|
var d = ImGui.GetWindowDrawList();
|
||||||
|
|
||||||
|
d.PathLineTo(o + cur * radius);
|
||||||
|
d.PathLineTo(o + prev * radius);
|
||||||
|
d.PathLineTo(o + prev * radius * ratio);
|
||||||
|
d.PathLineTo(o + cur * radius * ratio);
|
||||||
|
if (next is { } nextValue)
|
||||||
|
d.PathLineTo(o + nextValue * radius);
|
||||||
|
d.PathFillConvex(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Arc(float startAngle, float endAngle, float radius, float ratio, uint backgroundColor, uint filledColor, bool addDummy = true)
|
||||||
|
{
|
||||||
|
// Fix normals when drawing (for antialiasing)
|
||||||
|
if (startAngle > endAngle)
|
||||||
|
(startAngle, endAngle) = (endAngle, startAngle);
|
||||||
|
|
||||||
|
var offset = ImGui.GetCursorScreenPos() + new Vector2(radius);
|
||||||
|
|
||||||
|
var segments = ImGui.GetWindowDrawList()._CalcCircleAutoSegmentCount(radius * 2);
|
||||||
|
var incrementAngle = MathF.Tau / segments;
|
||||||
|
var isFullCircle = (endAngle - startAngle) % MathF.Tau == 0;
|
||||||
|
|
||||||
|
var prevA = startAngle;
|
||||||
|
var prev = UnitCircle(prevA);
|
||||||
|
for (var i = 1; i <= segments; ++i)
|
||||||
|
{
|
||||||
|
var a = startAngle + incrementAngle * i;
|
||||||
|
var cur = UnitCircle(a);
|
||||||
|
|
||||||
|
var nextA = a + incrementAngle;
|
||||||
|
var next = UnitCircle(nextA);
|
||||||
|
|
||||||
|
// full segment is background
|
||||||
|
if (prevA >= endAngle)
|
||||||
|
{
|
||||||
|
// don't overlap with the first segment
|
||||||
|
if (i == segments && !isFullCircle)
|
||||||
|
ArcSegment(offset, prev, cur, null, radius, ratio, backgroundColor);
|
||||||
|
else
|
||||||
|
ArcSegment(offset, prev, cur, next, radius, ratio, backgroundColor);
|
||||||
|
}
|
||||||
|
// segment is partially filled
|
||||||
|
else if (a > endAngle && !isFullCircle)
|
||||||
|
{
|
||||||
|
// we split the drawing in two
|
||||||
|
var end = UnitCircle(endAngle);
|
||||||
|
ArcSegment(offset, prev, end, null, radius, ratio, filledColor);
|
||||||
|
ArcSegment(offset, end, cur, next, radius, ratio, backgroundColor);
|
||||||
|
// set the previous segment to endAngle
|
||||||
|
a = endAngle;
|
||||||
|
cur = end;
|
||||||
|
}
|
||||||
|
// full segment is filled
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the next segment will be partially filled, the next segment will be the endAngle
|
||||||
|
if (nextA > endAngle && !isFullCircle)
|
||||||
|
{
|
||||||
|
var end = UnitCircle(endAngle);
|
||||||
|
ArcSegment(offset, prev, cur, end, radius, ratio, filledColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ArcSegment(offset, prev, cur, next, radius, ratio, filledColor);
|
||||||
|
}
|
||||||
|
prevA = a;
|
||||||
|
prev = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addDummy)
|
||||||
|
ImGui.Dummy(new Vector2(radius * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ArcProgress(float value, float radiusInner, float radiusOuter, uint backgroundColor, uint filledColor)
|
||||||
|
{
|
||||||
|
Arc(MathF.PI / 2, MathF.PI / 2 - MathF.Tau * Math.Clamp(value, 0, 1), radiusInner, radiusOuter, backgroundColor, filledColor);
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IconButtonSized(FontAwesomeIcon icon, Vector2 size)
|
public static bool IconButtonSized(FontAwesomeIcon icon, Vector2 size)
|
||||||
{
|
{
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
@@ -155,16 +246,18 @@ internal static class ImGuiUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AlignCentered(float width)
|
public static void AlignCentered(float width, float availWidth = default)
|
||||||
{
|
{
|
||||||
var availWidth = ImGui.GetContentRegionAvail().X;
|
if (availWidth == default)
|
||||||
|
availWidth = ImGui.GetContentRegionAvail().X;
|
||||||
if (availWidth > width)
|
if (availWidth > width)
|
||||||
ImGui.SetCursorPosX(ImGui.GetCursorPos().X + (availWidth - width) / 2);
|
ImGui.SetCursorPosX(ImGui.GetCursorPos().X + (availWidth - width) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AlignMiddle(Vector2 size)
|
public static void AlignMiddle(Vector2 size, Vector2 availSize = default)
|
||||||
{
|
{
|
||||||
var availSize = ImGui.GetContentRegionAvail();
|
if (availSize == default)
|
||||||
|
availSize = ImGui.GetContentRegionAvail();
|
||||||
if (availSize.X > size.X)
|
if (availSize.X > size.X)
|
||||||
ImGui.SetCursorPosX(ImGui.GetCursorPos().X + (availSize.X - size.X) / 2);
|
ImGui.SetCursorPosX(ImGui.GetCursorPos().X + (availSize.X - size.X) / 2);
|
||||||
if (availSize.Y > size.Y)
|
if (availSize.Y > size.Y)
|
||||||
@@ -172,21 +265,34 @@ internal static class ImGuiUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/a/67855985
|
// https://stackoverflow.com/a/67855985
|
||||||
public static void TextCentered(string text)
|
public static void TextCentered(string text, float availWidth = default)
|
||||||
{
|
{
|
||||||
AlignCentered(ImGui.CalcTextSize(text).X);
|
AlignCentered(ImGui.CalcTextSize(text).X, availWidth);
|
||||||
ImGui.TextUnformatted(text);
|
ImGui.TextUnformatted(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TextMiddle(string text)
|
public static void TextMiddle(string text, Vector2 availSize = default)
|
||||||
{
|
{
|
||||||
AlignMiddle(ImGui.CalcTextSize(text));
|
AlignMiddle(ImGui.CalcTextSize(text), availSize);
|
||||||
ImGui.TextUnformatted(text);
|
ImGui.TextUnformatted(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ButtonCentered(string text)
|
public static void TextMiddleNewLine(string text, Vector2 availSize)
|
||||||
{
|
{
|
||||||
AlignCentered(ImGui.CalcTextSize(text).X + ImGui.GetStyle().FramePadding.Y * 2);
|
if (availSize == default)
|
||||||
return ImGui.Button(text);
|
availSize = ImGui.GetContentRegionAvail();
|
||||||
|
var c = ImGui.GetCursorPos();
|
||||||
|
AlignMiddle(ImGui.CalcTextSize(text), availSize);
|
||||||
|
ImGui.TextUnformatted(text);
|
||||||
|
ImGui.SetCursorPos(c + new Vector2(0, availSize.Y + ImGui.GetStyle().ItemSpacing.Y - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ButtonCentered(string text, Vector2 buttonSize = default)
|
||||||
|
{
|
||||||
|
var buttonWidth = buttonSize.X;
|
||||||
|
if (buttonSize == default)
|
||||||
|
buttonWidth = ImGui.CalcTextSize(text).X + ImGui.GetStyle().FramePadding.X * 2;
|
||||||
|
AlignCentered(buttonWidth);
|
||||||
|
return ImGui.Button(text, buttonSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public record RecipeData
|
|||||||
RLvl = (int)Table.RowId,
|
RLvl = (int)Table.RowId,
|
||||||
ConditionsFlag = Table.ConditionsFlag,
|
ConditionsFlag = Table.ConditionsFlag,
|
||||||
MaxDurability = Table.Durability * Recipe.DurabilityFactor / 100,
|
MaxDurability = Table.Durability * Recipe.DurabilityFactor / 100,
|
||||||
MaxQuality = (int)Table.Quality * Recipe.QualityFactor / 100,
|
MaxQuality = (Recipe.CanHq || Recipe.IsExpert) ? (int)Table.Quality * Recipe.QualityFactor / 100 : 0,
|
||||||
MaxProgress = Table.Difficulty * Recipe.DifficultyFactor / 100,
|
MaxProgress = Table.Difficulty * Recipe.DifficultyFactor / 100,
|
||||||
QualityModifier = Table.QualityModifier,
|
QualityModifier = Table.QualityModifier,
|
||||||
QualityDivider = Table.QualityDivider,
|
QualityDivider = Table.QualityDivider,
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ using Dalamud.Interface.Colors;
|
|||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.GameFonts;
|
using Dalamud.Interface.GameFonts;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Style;
|
|
||||||
using Dalamud.Interface.Utility;
|
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
@@ -21,7 +19,6 @@ using FFXIVClientStructs.FFXIV.Client.UI;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using ImGuiScene;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -193,12 +190,37 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ImGuiUtils.TextCentered("Best Saved Macro");
|
{
|
||||||
DrawMacro("savedMacro", BestSavedMacro == null ? null : (BestSavedMacro.Value.Item1.Actions, BestSavedMacro.Value.Item2));
|
using var table = ImRaii.Table("macros", 1, ImGuiTableFlags.SizingStretchSame);
|
||||||
ImGuiUtils.ButtonCentered("View Saved Macros");
|
if (table)
|
||||||
ImGuiUtils.TextCentered("Suggested Macro");
|
{
|
||||||
DrawMacro("suggestedMacro", BestSuggestedMacro == null ? null : (BestSuggestedMacro.Value.Actions, BestSuggestedMacro.Value.State));
|
ImGui.TableNextColumn();
|
||||||
ImGuiUtils.ButtonCentered("Open Simulator");
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGuiUtils.TextCentered("Best Saved Macro");
|
||||||
|
if (BestSavedMacro is { } savedMacro)
|
||||||
|
{
|
||||||
|
ImGuiUtils.TextCentered(savedMacro.Item1.Name);
|
||||||
|
DrawMacro("savedMacro", (savedMacro.Item1.Actions, savedMacro.Item2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.Text("");
|
||||||
|
DrawMacro("savedMacro", null);
|
||||||
|
}
|
||||||
|
ImGui.Button("View Saved Macros", new(-1, 0));
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGuiUtils.TextCentered("Suggested Macro");
|
||||||
|
if (BestSuggestedMacro is { } suggestedMacro)
|
||||||
|
DrawMacro("suggestedMacro", (suggestedMacro.Actions, suggestedMacro.State));
|
||||||
|
else
|
||||||
|
DrawMacro("suggestedMacro", null);
|
||||||
|
ImGui.Button("Open Simulator", new(-1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawCharacterStats()
|
private void DrawCharacterStats()
|
||||||
@@ -494,16 +516,16 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMacro(string macroName, (List<ActionType> Actions, SimulationState State)? macro)
|
private void DrawMacro(string imGuiId, (List<ActionType> Actions, SimulationState State)? macroValue)
|
||||||
{
|
{
|
||||||
var availWidth = ImGui.GetContentRegionAvail().X;
|
//using var window = ImRaii.Child(imGuiId, new(-1, (name != null ? ImGui.GetTextLineHeightWithSpacing() : 0) + 2 * ImGui.GetFrameHeightWithSpacing()), false, ImGuiWindowFlags.AlwaysAutoResize);
|
||||||
|
|
||||||
using var window = ImRaii.Child(macroName, new(availWidth, 2 * ImGui.GetFrameHeight()), false);
|
var windowHeight = 2 * ImGui.GetFrameHeightWithSpacing();
|
||||||
|
|
||||||
if (macro == null)
|
if (macroValue == null)
|
||||||
{
|
{
|
||||||
if (BestMacroException == null)
|
if (BestMacroException == null)
|
||||||
ImGuiUtils.TextMiddle("Calculating...");
|
ImGuiUtils.TextMiddleNewLine("Calculating...", new(ImGui.GetContentRegionAvail().X, windowHeight + 1 + ImGui.GetStyle().ItemSpacing.Y));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.AlignTextToFramePadding();
|
ImGui.AlignTextToFramePadding();
|
||||||
@@ -515,8 +537,123 @@ public sealed unsafe class RecipeNote : Window, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGuiUtils.TextCentered($"{macro.Value.Actions.Count} Actions");
|
var macro = macroValue!.Value;
|
||||||
ImGuiUtils.TextCentered($"{macro.Value.State.Quality} Quality");
|
|
||||||
|
using var table = ImRaii.Table("table", 3, ImGuiTableFlags.BordersInnerV | ImGuiTableFlags.SizingStretchSame);
|
||||||
|
if (table)
|
||||||
|
{
|
||||||
|
ImGui.TableSetupColumn("desc", ImGuiTableColumnFlags.WidthFixed, 0);
|
||||||
|
ImGui.TableSetupColumn("actions", ImGuiTableColumnFlags.WidthFixed, 0);
|
||||||
|
ImGui.TableSetupColumn("steps", ImGuiTableColumnFlags.WidthStretch);
|
||||||
|
|
||||||
|
ImGui.TableNextRow(ImGuiTableRowFlags.None, windowHeight);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
|
||||||
|
var spacing = ImGui.GetStyle().ItemSpacing.Y;
|
||||||
|
var miniRowHeight = (windowHeight - spacing) / 2f;
|
||||||
|
|
||||||
|
//ImGui.Text($"{macro.Actions.Count}");
|
||||||
|
{
|
||||||
|
if (Service.Configuration.ShowOptimalMacroStat)
|
||||||
|
{
|
||||||
|
var progressHeight = windowHeight;
|
||||||
|
if (macro.State.Progress >= macro.State.Input.Recipe.MaxProgress && macro.State.Input.Recipe.MaxQuality > 0)
|
||||||
|
{
|
||||||
|
ImGuiUtils.ArcProgress(
|
||||||
|
(float)macro.State.Quality / macro.State.Input.Recipe.MaxQuality,
|
||||||
|
progressHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.GetColorU32(ImGuiCol.TableBorderLight),
|
||||||
|
ImGui.GetColorU32(Plugin.Windows.Simulator.QualityColor));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Quality: {macro.State.Quality} / {macro.State.Input.Recipe.MaxQuality}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGuiUtils.ArcProgress(
|
||||||
|
(float)macro.State.Progress / macro.State.Input.Recipe.MaxProgress,
|
||||||
|
progressHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.GetColorU32(ImGuiCol.TableBorderLight),
|
||||||
|
ImGui.GetColorU32(Plugin.Windows.Simulator.ProgressColor));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Progress: {macro.State.Progress} / {macro.State.Input.Recipe.MaxProgress}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGuiUtils.ArcProgress(
|
||||||
|
(float)macro.State.Progress / macro.State.Input.Recipe.MaxProgress,
|
||||||
|
miniRowHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.GetColorU32(ImGuiCol.TableBorderLight),
|
||||||
|
ImGui.GetColorU32(Plugin.Windows.Simulator.ProgressColor));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Progress: {macro.State.Progress} / {macro.State.Input.Recipe.MaxProgress}");
|
||||||
|
|
||||||
|
ImGui.SameLine(0, spacing);
|
||||||
|
ImGuiUtils.ArcProgress(
|
||||||
|
(float)macro.State.Quality / macro.State.Input.Recipe.MaxQuality,
|
||||||
|
miniRowHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.GetColorU32(ImGuiCol.TableBorderLight),
|
||||||
|
ImGui.GetColorU32(Plugin.Windows.Simulator.QualityColor));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Quality: {macro.State.Quality} / {macro.State.Input.Recipe.MaxQuality}");
|
||||||
|
|
||||||
|
ImGuiUtils.ArcProgress((float)macro.State.Durability / macro.State.Input.Recipe.MaxDurability,
|
||||||
|
miniRowHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.GetColorU32(ImGuiCol.TableBorderLight),
|
||||||
|
ImGui.GetColorU32(Plugin.Windows.Simulator.DurabilityColor));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Remaining Durability: {macro.State.Durability} / {macro.State.Input.Recipe.MaxDurability}");
|
||||||
|
|
||||||
|
ImGui.SameLine(0, spacing);
|
||||||
|
ImGuiUtils.ArcProgress(
|
||||||
|
(float)macro.State.CP / macro.State.Input.Stats.CP,
|
||||||
|
miniRowHeight / 2f,
|
||||||
|
.5f,
|
||||||
|
ImGui.GetColorU32(ImGuiCol.TableBorderLight),
|
||||||
|
ImGui.GetColorU32(Plugin.Windows.Simulator.CPColor));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Remaining CP: {macro.State.CP} / {macro.State.Input.Stats.CP}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
{
|
||||||
|
ImGuiUtils.TextMiddleNewLine($"{macro.Actions.Count}", new(miniRowHeight));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"{macro.Actions.Count} Step{(macro.Actions.Count != 1 ? "s" : "")}");
|
||||||
|
using (var iconFont = ImRaii.PushFont(UiBuilder.IconFont))
|
||||||
|
if (ImGuiUtils.ButtonCentered(FontAwesomeIcon.Copy.ToIconString(), new(miniRowHeight)))
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip("Copy to Clipboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
{
|
||||||
|
var itemsPerRow = (int)MathF.Ceiling((ImGui.GetContentRegionAvail().X + spacing) / (miniRowHeight + spacing));
|
||||||
|
var itemCount = Math.Min(macro.Actions.Count, itemsPerRow * 2);
|
||||||
|
for (var i = 0; i < itemsPerRow * 2; i++)
|
||||||
|
{
|
||||||
|
if (i % itemsPerRow != 0)
|
||||||
|
ImGui.SameLine(0, spacing);
|
||||||
|
if (i < itemCount)
|
||||||
|
{
|
||||||
|
ImGui.Image(macro.Actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(miniRowHeight));
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip(macro.Actions[i].GetName(RecipeData!.ClassJob));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ImGui.Dummy(new(miniRowHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawRequiredStatsTable(int current, int required)
|
private static void DrawRequiredStatsTable(int current, int required)
|
||||||
|
|||||||
@@ -154,6 +154,16 @@ public class Settings : Window
|
|||||||
ref isDirty
|
ref isDirty
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DrawOption(
|
||||||
|
"Show Only One Macro Stat",
|
||||||
|
"Only one stat will be shown for a macro. If a craft will be finished, quality\n" +
|
||||||
|
"is shown. Otherwise, progress is shown. Durability and remaining CP will be\n" +
|
||||||
|
"hidden.",
|
||||||
|
Config.ShowOptimalMacroStat,
|
||||||
|
v => Config.ShowOptimalMacroStat = v,
|
||||||
|
ref isDirty
|
||||||
|
);
|
||||||
|
|
||||||
if (isDirty)
|
if (isDirty)
|
||||||
Config.Save();
|
Config.Save();
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ public sealed partial class Simulator : Window, IDisposable
|
|||||||
private static readonly Vector2 ProgressBarSizeOld = new(200, 20);
|
private static readonly Vector2 ProgressBarSizeOld = new(200, 20);
|
||||||
public static readonly Vector2 TooltipProgressBarSize = new(100, 5);
|
public static readonly Vector2 TooltipProgressBarSize = new(100, 5);
|
||||||
|
|
||||||
private static readonly Vector4 ProgressColor = new(0.44f, 0.65f, 0.18f, 1f);
|
public static readonly Vector4 ProgressColor = new(0.44f, 0.65f, 0.18f, 1f);
|
||||||
private static readonly Vector4 QualityColor = new(0.26f, 0.71f, 0.69f, 1f);
|
public static readonly Vector4 QualityColor = new(0.26f, 0.71f, 0.69f, 1f);
|
||||||
private static readonly Vector4 DurabilityColor = new(0.13f, 0.52f, 0.93f, 1f);
|
public static readonly Vector4 DurabilityColor = new(0.13f, 0.52f, 0.93f, 1f);
|
||||||
private static readonly Vector4 HQColor = new(0.592f, 0.863f, 0.376f, 1f);
|
public static readonly Vector4 HQColor = new(0.592f, 0.863f, 0.376f, 1f);
|
||||||
private static readonly Vector4 CPColor = new(0.63f, 0.37f, 0.75f, 1f);
|
public static readonly Vector4 CPColor = new(0.63f, 0.37f, 0.75f, 1f);
|
||||||
|
|
||||||
private static readonly Vector4 BadActionImageTint = new(1f, .5f, .5f, 1f);
|
private static readonly Vector4 BadActionImageTint = new(1f, .5f, .5f, 1f);
|
||||||
private static readonly Vector4 BadActionImageColor = new(1f, .3f, .3f, 1f);
|
private static readonly Vector4 BadActionImageColor = new(1f, .3f, .3f, 1f);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public struct SimulationNode
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
static float Apply(float bonus, float value, float target) =>
|
static float Apply(float bonus, float value, float target) =>
|
||||||
bonus * Math.Min(1f, value / target);
|
bonus * (target > 0 ? Math.Min(1f, value / target) : 1);
|
||||||
|
|
||||||
var progressScore = Apply(
|
var progressScore = Apply(
|
||||||
config.ScoreProgress,
|
config.ScoreProgress,
|
||||||
|
|||||||
Reference in New Issue
Block a user