Simulator changes
- Progress bar tooltips in crafting log - Disable modifying actions when generating - Better bottom button layout - Saving/save new, etc
This commit is contained in:
@@ -19,6 +19,8 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
private bool IsExpert { get; }
|
private bool IsExpert { get; }
|
||||||
private SimulationInput Input { get; }
|
private SimulationInput Input { get; }
|
||||||
private ClassJob ClassJob { get; }
|
private ClassJob ClassJob { get; }
|
||||||
|
private Macro? Macro { get; set; }
|
||||||
|
private string MacroName { get; set; }
|
||||||
// State is the state of the simulation *after* its corresponding action is executed.
|
// State is the state of the simulation *after* its corresponding action is executed.
|
||||||
private List<(ActionType Action, string Tooltip, ActionResponse Response, SimulationState State)> Actions { get; }
|
private List<(ActionType Action, string Tooltip, ActionResponse Response, SimulationState State)> Actions { get; }
|
||||||
private Simulator.Simulator Simulator { get; set; }
|
private Simulator.Simulator Simulator { get; set; }
|
||||||
@@ -27,7 +29,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
|
|
||||||
// Simulator is set by ResetSimulator()
|
// Simulator is set by ResetSimulator()
|
||||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
public SimulatorWindow(Item item, bool isExpert, SimulationInput input, ClassJob classJob, List<ActionType> actions) : base("Simulator", WindowFlags)
|
public SimulatorWindow(Item item, bool isExpert, SimulationInput input, ClassJob classJob, Macro? macro) : base("Simulator", WindowFlags)
|
||||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
{
|
{
|
||||||
Service.WindowSystem.AddWindow(this);
|
Service.WindowSystem.AddWindow(this);
|
||||||
@@ -36,6 +38,8 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
IsExpert = isExpert;
|
IsExpert = isExpert;
|
||||||
Input = input;
|
Input = input;
|
||||||
ClassJob = classJob;
|
ClassJob = classJob;
|
||||||
|
Macro = macro;
|
||||||
|
MacroName = Macro?.Name ?? $"Macro {Configuration.Macros.Count + 1}";
|
||||||
Actions = new();
|
Actions = new();
|
||||||
ResetSimulator();
|
ResetSimulator();
|
||||||
|
|
||||||
@@ -47,8 +51,9 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
SizeCondition = ImGuiCond.Appearing;
|
SizeCondition = ImGuiCond.Appearing;
|
||||||
Size = SizeConstraints?.MinimumSize ?? new(10);
|
Size = SizeConstraints?.MinimumSize ?? new(10);
|
||||||
|
|
||||||
foreach (var action in actions)
|
if (Macro != null)
|
||||||
AppendAction(action);
|
foreach (var action in Macro.Actions)
|
||||||
|
AppendAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetSimulator()
|
private void ResetSimulator()
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
private static readonly Vector2 DurabilityBarSize = new(100, 20);
|
private static readonly Vector2 DurabilityBarSize = new(100, 20);
|
||||||
private static readonly Vector2 ConditionBarSize = new(20, 20);
|
private static readonly Vector2 ConditionBarSize = new(20, 20);
|
||||||
private static readonly Vector2 ProgressBarSizeOld = new(200, 20);
|
private static readonly Vector2 ProgressBarSizeOld = new(200, 20);
|
||||||
private 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);
|
private 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);
|
private static readonly Vector4 QualityColor = new(0.26f, 0.71f, 0.69f, 1f);
|
||||||
@@ -46,13 +46,12 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
while (SolverActionQueue.TryDequeue(out var poppedAction))
|
while (SolverActionQueue.TryDequeue(out var poppedAction))
|
||||||
AppendGeneratedAction(poppedAction);
|
AppendGeneratedAction(poppedAction);
|
||||||
|
|
||||||
ImGui.TextUnformatted($"{FrameTime.TotalMilliseconds:0.00}ms");
|
|
||||||
|
|
||||||
ImGui.BeginTable("simulatorWindow", 2, ImGuiTableFlags.BordersInnerV);
|
ImGui.BeginTable("simulatorWindow", 2, ImGuiTableFlags.BordersInnerV);
|
||||||
ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, ActionColumnSize);
|
ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, ActionColumnSize);
|
||||||
ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthStretch);
|
ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthStretch);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
DrawActions();
|
DrawActions();
|
||||||
|
ImGui.TextUnformatted($"{FrameTime.TotalMilliseconds:0.00}ms");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
DrawSimulation();
|
DrawSimulation();
|
||||||
ImGui.EndTable();
|
ImGui.EndTable();
|
||||||
@@ -73,6 +72,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
|
ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
|
||||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, Vector4.Zero);
|
ImGui.PushStyleColor(ImGuiCol.ButtonActive, Vector4.Zero);
|
||||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Vector4.Zero);
|
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Vector4.Zero);
|
||||||
|
ImGui.BeginDisabled(!CanModifyActions);
|
||||||
|
|
||||||
foreach (var (category, actions) in SortedActions)
|
foreach (var (category, actions) in SortedActions)
|
||||||
{
|
{
|
||||||
@@ -105,6 +105,8 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
ImGui.Dummy(actionSize);
|
ImGui.Dummy(actionSize);
|
||||||
ImGuiUtils.EndGroupPanel();
|
ImGuiUtils.EndGroupPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
ImGui.PopStyleColor(3);
|
ImGui.PopStyleColor(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +121,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
ImGuiHelpers.ScaledDummy(5);
|
ImGuiHelpers.ScaledDummy(5);
|
||||||
DrawSimulationActions(drawParams);
|
DrawSimulationActions(drawParams);
|
||||||
var bottom = ImGui.GetContentRegionAvail().Y - ImGui.GetStyle().FramePadding.Y * 2;
|
var bottom = ImGui.GetContentRegionAvail().Y - ImGui.GetStyle().FramePadding.Y * 2;
|
||||||
var textHeight = ImGui.CalcTextSize("A").Y;
|
var buttonHeight = ImGui.GetFrameHeightWithSpacing() * 2 + ImGui.GetFrameHeight();
|
||||||
var buttonHeight = ImGui.GetStyle().FramePadding.Y * 2 + textHeight;
|
|
||||||
ImGuiHelpers.ScaledDummy(bottom - buttonHeight);
|
ImGuiHelpers.ScaledDummy(bottom - buttonHeight);
|
||||||
DrawSimulationButtons(drawParams);
|
DrawSimulationButtons(drawParams);
|
||||||
}
|
}
|
||||||
@@ -245,27 +246,31 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
var (action, tooltip, response, state) = Actions[i];
|
var (action, tooltip, response, state) = Actions[i];
|
||||||
ImGui.PushID(i);
|
ImGui.PushID(i);
|
||||||
if (ImGui.ImageButton(action.GetIcon(ClassJob).ImGuiHandle, actionSize, Vector2.Zero, Vector2.One, 0, default, response != ActionResponse.UsedAction ? BadActionImageTint : Vector4.One))
|
if (ImGui.ImageButton(action.GetIcon(ClassJob).ImGuiHandle, actionSize, Vector2.Zero, Vector2.One, 0, default, response != ActionResponse.UsedAction ? BadActionImageTint : Vector4.One))
|
||||||
RemoveAction(i);
|
if (CanModifyActions)
|
||||||
if (ImGui.BeginDragDropSource())
|
RemoveAction(i);
|
||||||
|
if (CanModifyActions)
|
||||||
{
|
{
|
||||||
unsafe { ImGui.SetDragDropPayload("simulationAction", (nint)(&i), sizeof(int)); }
|
if (ImGui.BeginDragDropSource())
|
||||||
ImGui.ImageButton(Actions[i].Action.GetIcon(ClassJob).ImGuiHandle, actionSize);
|
|
||||||
ImGui.EndDragDropSource();
|
|
||||||
}
|
|
||||||
if (ImGui.BeginDragDropTarget())
|
|
||||||
{
|
|
||||||
var payload = ImGui.AcceptDragDropPayload("simulationAction");
|
|
||||||
bool isValidPayload;
|
|
||||||
unsafe { isValidPayload = payload.NativePtr != null; }
|
|
||||||
if (isValidPayload)
|
|
||||||
{
|
{
|
||||||
int draggedIdx;
|
unsafe { ImGui.SetDragDropPayload("simulationAction", (nint)(&i), sizeof(int)); }
|
||||||
unsafe { draggedIdx = *(int*)payload.Data; }
|
ImGui.ImageButton(Actions[i].Action.GetIcon(ClassJob).ImGuiHandle, actionSize);
|
||||||
var draggedAction = Actions[draggedIdx].Action;
|
ImGui.EndDragDropSource();
|
||||||
RemoveAction(draggedIdx);
|
}
|
||||||
InsertAction(i, draggedAction);
|
if (ImGui.BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
var payload = ImGui.AcceptDragDropPayload("simulationAction");
|
||||||
|
bool isValidPayload;
|
||||||
|
unsafe { isValidPayload = payload.NativePtr != null; }
|
||||||
|
if (isValidPayload)
|
||||||
|
{
|
||||||
|
int draggedIdx;
|
||||||
|
unsafe { draggedIdx = *(int*)payload.Data; }
|
||||||
|
var draggedAction = Actions[draggedIdx].Action;
|
||||||
|
RemoveAction(draggedIdx);
|
||||||
|
InsertAction(i, draggedAction);
|
||||||
|
}
|
||||||
|
ImGui.EndDragDropTarget();
|
||||||
}
|
}
|
||||||
ImGui.EndDragDropTarget();
|
|
||||||
}
|
}
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
{
|
{
|
||||||
@@ -282,11 +287,9 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
if (response != ActionResponse.UsedAction)
|
if (response != ActionResponse.UsedAction)
|
||||||
ImGui.TextColored(BadActionTextColor, responseText);
|
ImGui.TextColored(BadActionTextColor, responseText);
|
||||||
ImGui.Text($"{action.GetName(ClassJob)}\n{tooltip}");
|
ImGui.Text($"{action.GetName(ClassJob)}\n{tooltip}");
|
||||||
DrawProgressBarTooltip(state.Progress, Input.Recipe.MaxProgress, ProgressColor);
|
DrawAllProgressTooltips(state);
|
||||||
DrawProgressBarTooltip(state.Quality, Input.Recipe.MaxQuality, QualityColor);
|
if (CanModifyActions)
|
||||||
DrawProgressBarTooltip(state.Durability, Input.Recipe.MaxDurability, DurabilityColor);
|
ImGui.Text("Click to Remove\nDrag to Move");
|
||||||
DrawProgressBarTooltip(state.CP, Input.Stats.CP, CPColor);
|
|
||||||
ImGui.Text("Click to Remove\nDrag to Move");
|
|
||||||
ImGui.EndTooltip();
|
ImGui.EndTooltip();
|
||||||
}
|
}
|
||||||
ImGui.PopID();
|
ImGui.PopID();
|
||||||
@@ -300,11 +303,72 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
|
|
||||||
private void DrawSimulationButtons(SynthDrawParams drawParams)
|
private void DrawSimulationButtons(SynthDrawParams drawParams)
|
||||||
{
|
{
|
||||||
ImGui.Button("Save");
|
var totalWidth = drawParams.Total;
|
||||||
|
var halfWidth = (totalWidth - ImGui.GetStyle().ItemSpacing.X) / 2f;
|
||||||
|
var quarterWidth = (halfWidth - ImGui.GetStyle().ItemSpacing.X) / 2f;
|
||||||
|
var halfButtonSize = new Vector2(halfWidth, ImGui.CalcTextSize("A").Y + ImGui.GetStyle().FramePadding.Y * 2);
|
||||||
|
var quarterButtonSize = new Vector2(quarterWidth, ImGui.CalcTextSize("A").Y + ImGui.GetStyle().FramePadding.Y * 2);
|
||||||
|
|
||||||
|
var conditionRandomnessText = "Condition Randomness";
|
||||||
|
var conditionRandomness = Configuration.ConditionRandomness;
|
||||||
|
ImGui.BeginDisabled(!CanModifyActions);
|
||||||
|
if (ImGui.Checkbox(conditionRandomnessText, ref conditionRandomness))
|
||||||
|
{
|
||||||
|
Configuration.ConditionRandomness = conditionRandomness;
|
||||||
|
Configuration.Save();
|
||||||
|
ResetSimulator();
|
||||||
|
}
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
|
ImGui.SetTooltip("Allows the condition to fluctuate randomly like a real craft.\nTurns off when generating a macro.");
|
||||||
|
|
||||||
|
var labelSize = ImGui.CalcTextSize(conditionRandomnessText);
|
||||||
|
var checkboxWidth = ImGui.GetFrameHeight() + (labelSize.X > 0 ? ImGui.GetStyle().ItemInnerSpacing.X + labelSize.X : 0);
|
||||||
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
|
var cogWidth = ImGui.CalcTextSize(FontAwesomeIcon.Cog.ToIconString()).X;
|
||||||
|
ImGui.PopFont();
|
||||||
|
ImGui.SameLine(0, totalWidth - ImGui.GetStyle().ItemSpacing.X - checkboxWidth - cogWidth);
|
||||||
|
ImGuiComponents.IconButton("simSettingsButton", FontAwesomeIcon.Cog);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
var macroName = MacroName;
|
||||||
|
ImGui.SetNextItemWidth(halfWidth);
|
||||||
|
if (ImGui.InputTextWithHint("", "Macro Name", ref macroName, 64))
|
||||||
|
MacroName = macroName;
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button("Reset"))
|
|
||||||
|
ImGui.SetNextItemWidth(halfWidth);
|
||||||
|
DrawSimulationGenerateButton(halfButtonSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
ImGui.BeginDisabled(!CanModifyActions);
|
||||||
|
if (Macro != null)
|
||||||
|
{
|
||||||
|
if (ImGui.Button("Save", quarterButtonSize))
|
||||||
|
{
|
||||||
|
Macro.Name = MacroName;
|
||||||
|
Macro.Actions = Actions.Select(a => a.Action).ToList();
|
||||||
|
Configuration.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
}
|
||||||
|
if (ImGui.Button("Save New", Macro == null ? halfButtonSize : quarterButtonSize))
|
||||||
|
{
|
||||||
|
Macro = new() { Name = MacroName, Actions = Actions.Select(a => a.Action).ToList() };
|
||||||
|
Configuration.Macros.Add(Macro);
|
||||||
|
Configuration.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (ImGui.Button("Reset", halfButtonSize))
|
||||||
ClearAllActions();
|
ClearAllActions();
|
||||||
ImGui.SameLine();
|
ImGui.EndDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSimulationGenerateButton(Vector2 buttonSize)
|
||||||
|
{
|
||||||
var state = GenerateSolverState();
|
var state = GenerateSolverState();
|
||||||
string buttonText;
|
string buttonText;
|
||||||
string tooltipText;
|
string tooltipText;
|
||||||
@@ -342,7 +406,7 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui.BeginDisabled(!isEnabled);
|
ImGui.BeginDisabled(!isEnabled);
|
||||||
if (ImGui.Button(buttonText))
|
if (ImGui.Button(buttonText, buttonSize))
|
||||||
{
|
{
|
||||||
if (!SolverTask.IsCompleted)
|
if (!SolverTask.IsCompleted)
|
||||||
{
|
{
|
||||||
@@ -370,17 +434,5 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
ImGui.SetTooltip(tooltipText);
|
ImGui.SetTooltip(tooltipText);
|
||||||
ImGui.SameLine();
|
|
||||||
ImGuiComponents.IconButton(FontAwesomeIcon.Cog);
|
|
||||||
ImGui.SameLine();
|
|
||||||
var conditionRandomness = Configuration.ConditionRandomness;
|
|
||||||
if (ImGui.Checkbox("Condition Randomness", ref conditionRandomness))
|
|
||||||
{
|
|
||||||
Configuration.ConditionRandomness = conditionRandomness;
|
|
||||||
Configuration.Save();
|
|
||||||
ResetSimulator();
|
|
||||||
}
|
|
||||||
if (ImGui.IsItemHovered())
|
|
||||||
ImGui.SetTooltip("Allows the condition to fluctuate randomly like a real craft.\nTurns off when generating a macro.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Craftimizer.Simulator;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using System;
|
using System;
|
||||||
@@ -117,6 +118,22 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
ImGuiUtils.EndGroupPanel();
|
ImGuiUtils.EndGroupPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DrawAllProgressTooltips(SimulationState state)
|
||||||
|
{
|
||||||
|
DrawProgressBarTooltip(state.Progress, state.Input.Recipe.MaxProgress, ProgressColor);
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Progress: {state.Progress} / {state.Input.Recipe.MaxProgress}");
|
||||||
|
DrawProgressBarTooltip(state.Quality, state.Input.Recipe.MaxQuality, QualityColor);
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Quality: {state.Quality} / {state.Input.Recipe.MaxQuality}");
|
||||||
|
DrawProgressBarTooltip(state.Durability, state.Input.Recipe.MaxDurability, DurabilityColor);
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"Durability: {state.Durability} / {state.Input.Recipe.MaxDurability}");
|
||||||
|
DrawProgressBarTooltip(state.CP, state.Input.Stats.CP, CPColor);
|
||||||
|
if (ImGui.IsItemHovered())
|
||||||
|
ImGui.SetTooltip($"CP: {state.CP} / {state.Input.Stats.CP}");
|
||||||
|
}
|
||||||
|
|
||||||
private static void DrawProgressBarTooltip(int progress, int maxProgress, Vector4 color) =>
|
private static void DrawProgressBarTooltip(int progress, int maxProgress, Vector4 color) =>
|
||||||
DrawProgressBar(progress, maxProgress, TooltipProgressBarSize, color);
|
DrawProgressBar(progress, maxProgress, TooltipProgressBarSize, color);
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public sealed partial class SimulatorWindow : Window, IDisposable
|
|||||||
private int SolverInitialActionCount { get; set; }
|
private int SolverInitialActionCount { get; set; }
|
||||||
private bool SolverActionsChanged { get; set; } = true;
|
private bool SolverActionsChanged { get; set; } = true;
|
||||||
|
|
||||||
|
private bool CanModifyActions => SolverTask.IsCompleted;
|
||||||
|
|
||||||
private void OnActionsChanged()
|
private void OnActionsChanged()
|
||||||
{
|
{
|
||||||
SolverActionsChanged = true;
|
SolverActionsChanged = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user