From adc8fb707f609819ba396ab18d456449c21ff976 Mon Sep 17 00:00:00 2001 From: Edenane Date: Mon, 4 May 2026 18:20:42 +0100 Subject: [PATCH 1/3] Update ImRaii usage to new ref struct pattern --- Benchmark/Craftimizer.Benchmark.csproj | 4 +- Craftimizer/Craftimizer.csproj | 7 +- Craftimizer/ImRaii2.cs | 108 +++++++++++++++++-------- Craftimizer/Utils/DynamicBars.cs | 2 +- Craftimizer/Utils/SynthesisValues.cs | 2 +- Craftimizer/Windows/Settings.cs | 9 ++- Craftimizer/packages.lock.json | 30 +++---- Simulator/Craftimizer.Simulator.csproj | 2 +- Solver/Craftimizer.Solver.csproj | 4 +- Test/Craftimizer.Test.csproj | 6 +- 10 files changed, 109 insertions(+), 65 deletions(-) diff --git a/Benchmark/Craftimizer.Benchmark.csproj b/Benchmark/Craftimizer.Benchmark.csproj index ad3069b..b4ecc16 100644 --- a/Benchmark/Craftimizer.Benchmark.csproj +++ b/Benchmark/Craftimizer.Benchmark.csproj @@ -20,11 +20,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Craftimizer/Craftimizer.csproj b/Craftimizer/Craftimizer.csproj index a4d9aa0..d6497de 100644 --- a/Craftimizer/Craftimizer.csproj +++ b/Craftimizer/Craftimizer.csproj @@ -33,7 +33,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -41,4 +41,9 @@ + + + + + diff --git a/Craftimizer/ImRaii2.cs b/Craftimizer/ImRaii2.cs index 83d253e..6d45dde 100644 --- a/Craftimizer/ImRaii2.cs +++ b/Craftimizer/ImRaii2.cs @@ -8,78 +8,116 @@ namespace Craftimizer.Plugin; public static class ImRaii2 { - private struct EndUnconditionally(Action endAction, bool success) : ImRaii.IEndObject, IDisposable - { - private Action EndAction { get; } = endAction; - - public bool Success { get; } = success; + // Custom ref structs for each UI element. + // This eliminates the need for allocating 'Action' delegates and boxing. - public bool Disposed { get; private set; } = false; + public ref struct GroupPanelDisposable + { + private bool Disposed; public void Dispose() { - if (!Disposed) - { - EndAction(); - Disposed = true; - } + if (Disposed) return; + ImGuiUtils.EndGroupPanel(); + Disposed = true; } + + public static implicit operator bool(GroupPanelDisposable _) => true; } - private struct EndConditionally(Action endAction, bool success) : ImRaii.IEndObject, IDisposable + public static GroupPanelDisposable GroupPanel(string name, float width, out float internalWidth) { - public bool Success { get; } = success; + internalWidth = ImGuiUtils.BeginGroupPanel(name, width); + return new GroupPanelDisposable(); + } - public bool Disposed { get; private set; } = false; + public ref struct PlotDisposable + { + public bool Success { get; } + private bool Disposed; - private Action EndAction { get; } = endAction; + public PlotDisposable(bool success) + { + Success = success; + Disposed = false; + } public void Dispose() { - if (!Disposed) + if (Disposed) return; + if (Success) { - if (Success) - { - EndAction(); - } - - Disposed = true; + ImPlot.EndPlot(); } + Disposed = true; } + + // Allows you to do: using var plot = ImRaii2.Plot(...); if (plot) { ... } + public static implicit operator bool(PlotDisposable d) => d.Success; } - public static ImRaii.IEndObject GroupPanel(string name, float width, out float internalWidth) + public static PlotDisposable Plot(string title_id, Vector2 size, ImPlotFlags flags) { - internalWidth = ImGuiUtils.BeginGroupPanel(name, width); - return new EndUnconditionally(ImGuiUtils.EndGroupPanel, true); + return new PlotDisposable(ImPlot.BeginPlot(title_id, size, flags)); } - public static ImRaii.IEndObject Plot(string title_id, Vector2 size, ImPlotFlags flags) + public ref struct ImPlotStyleDisposable { - return new EndConditionally(new Action(ImPlot.EndPlot), ImPlot.BeginPlot(title_id, size, flags)); + private bool Disposed; + + public void Dispose() + { + if (Disposed) return; + ImPlot.PopStyleVar(); + Disposed = true; + } } - public static ImRaii.IEndObject PushStyle(ImPlotStyleVar idx, Vector2 val) + public static ImPlotStyleDisposable PushStyle(ImPlotStyleVar idx, Vector2 val) { ImPlot.PushStyleVar(idx, val); - return new EndUnconditionally(ImPlot.PopStyleVar, true); + return new ImPlotStyleDisposable(); } - public static ImRaii.IEndObject PushStyle(ImPlotStyleVar idx, float val) + public static ImPlotStyleDisposable PushStyle(ImPlotStyleVar idx, float val) { ImPlot.PushStyleVar(idx, val); - return new EndUnconditionally(ImPlot.PopStyleVar, true); + return new ImPlotStyleDisposable(); + } + + public ref struct ImPlotColorDisposable + { + private bool Disposed; + + public void Dispose() + { + if (Disposed) return; + ImPlot.PopStyleColor(); + Disposed = true; + } } - public static ImRaii.IEndObject PushColor(ImPlotCol idx, Vector4 col) + public static ImPlotColorDisposable PushColor(ImPlotCol idx, Vector4 col) { ImPlot.PushStyleColor(idx, col); - return new EndUnconditionally(ImPlot.PopStyleColor, true); + return new ImPlotColorDisposable(); + } + + public ref struct TextWrapPosDisposable + { + private bool Disposed; + + public void Dispose() + { + if (Disposed) return; + ImGui.PopTextWrapPos(); + Disposed = true; + } } - public static ImRaii.IEndObject TextWrapPos(float wrap_local_pos_x) + public static TextWrapPosDisposable TextWrapPos(float wrap_local_pos_x) { ImGui.PushTextWrapPos(wrap_local_pos_x); - return new EndUnconditionally(ImGui.PopTextWrapPos, true); + return new TextWrapPosDisposable(); } } diff --git a/Craftimizer/Utils/DynamicBars.cs b/Craftimizer/Utils/DynamicBars.cs index 08e1c62..a0c2181 100644 --- a/Craftimizer/Utils/DynamicBars.cs +++ b/Craftimizer/Utils/DynamicBars.cs @@ -45,7 +45,7 @@ public static float GetTextSize(IEnumerable bars) => defaultSize); }); - private static ImRaii.Color? PushCollectableColor(this in BarData bar, float collectability, bool colorUnmetThreshold = true) + private static ImRaii.ColorDisposable? PushCollectableColor(this in BarData bar, float collectability, bool colorUnmetThreshold = true) { if (bar.Collectability is not { } collectabilities) return null; diff --git a/Craftimizer/Utils/SynthesisValues.cs b/Craftimizer/Utils/SynthesisValues.cs index 494d177..102d7d7 100644 --- a/Craftimizer/Utils/SynthesisValues.cs +++ b/Craftimizer/Utils/SynthesisValues.cs @@ -4,7 +4,7 @@ using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; using System; -using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; +using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.AtkValueType; namespace Craftimizer.Utils; diff --git a/Craftimizer/Windows/Settings.cs b/Craftimizer/Windows/Settings.cs index f9d4cb1..821f4ae 100644 --- a/Craftimizer/Windows/Settings.cs +++ b/Craftimizer/Windows/Settings.cs @@ -50,14 +50,14 @@ public void SelectTab(string label) SelectedTab = label; } - private ImRaii.IEndObject TabItem(string label) + private ImRaii.TabItemDisposable TabItem(string label) { var isSelected = string.Equals(SelectedTab, label, StringComparison.Ordinal); if (isSelected) { SelectedTab = null; - var open = true; - return ImRaii.TabItem(label, ref open, ImGuiTabItemFlags.SetSelected); + // Use the overload that takes flags directly without the 'ref bool' + return ImRaii.TabItem(label, ImGuiTabItemFlags.SetSelected); } return ImRaii.TabItem(label); } @@ -122,9 +122,10 @@ private static void DrawOption(string label, string tooltip, string value, Actio private static void DrawOption(string label, string tooltip, Func getName, Func getTooltip, T value, Action setter, ref bool isDirty, params T[] excludedValues) where T : struct, Enum { ImGui.SetNextItemWidth(OptionWidth); + // ImRaii.Combo returns a ComboDisposable ref struct using (var combo = ImRaii.Combo(label, getName(value))) { - if (combo) + if (combo) // Uses the implicit bool operator { foreach (var type in Enum.GetValues()) { diff --git a/Craftimizer/packages.lock.json b/Craftimizer/packages.lock.json index 9b0ed54..b37cc34 100644 --- a/Craftimizer/packages.lock.json +++ b/Craftimizer/packages.lock.json @@ -4,15 +4,15 @@ "net10.0-windows7.0": { "DalamudPackager": { "type": "Direct", - "requested": "[14.0.1, )", - "resolved": "14.0.1", - "contentHash": "y0WWyUE6dhpGdolK3iKgwys05/nZaVf4ZPtIjpLhJBZvHxkkiE23zYRo7K7uqAgoK/QvK5cqF6l3VG5AbgC6KA==" + "requested": "[15.0.0, )", + "resolved": "15.0.0", + "contentHash": "411vwC8/X8Z/sQ2TI6v3SvOn66xFPeOjFn3Zn+h0d3Ox2t1kFm66AhDvmx/qcMwVrR+Hidxj0dadpQ2dgyXMBQ==" }, "DotNet.ReproducibleBuilds": { "type": "Direct", - "requested": "[1.2.39, )", - "resolved": "1.2.39", - "contentHash": "fcFN01tDTIQqDuTwr1jUQK/geofiwjG5DycJQOnC72i1SsLAk1ELe+apBOuZ11UMQG8YKFZG1FgvjZPbqHyatg==" + "requested": "[2.0.2, )", + "resolved": "2.0.2", + "contentHash": "VaHoEN6YHp0jXucxm67vfuRy8zo9ufiKSuaZ4ZudRi8xmWcEFMKxfCsg2nvYNvdISFTURDu+IHqADGh53+Bamw==" }, "MathNet.Numerics": { "type": "Direct", @@ -22,16 +22,16 @@ }, "Meziantou.Analyzer": { "type": "Direct", - "requested": "[2.0.264, )", - "resolved": "2.0.264", - "contentHash": "zRG13RDG446rZNdd/YjKRd4utpbjleRDUqNQSrX0etMnH8Rz9NBlXUpS5aR2ExoOokhNfkdOW8HpLzjLj5x0hQ==" + "requested": "[3.0.61, )", + "resolved": "3.0.61", + "contentHash": "Ed/5bKmY38QbQJgL9wmWnweX4mq3WaNYNq8kp4Hk/WPIFuLuK/P/dEB/ZnenQius+NNDXxTIiCXFPmQdLrHWMg==" }, "DotNext": { "type": "Transitive", - "resolved": "5.26.1", - "contentHash": "rcy6Yrpb64B7qYm/+D+4sfBUzwX/IOGeJBYReDL8/TAIp8aZrZPtXx8nwkYjWCuakYn2tBppwefIM6pd/cOnMw==", + "resolved": "6.1.0", + "contentHash": "oUvq/a1Fydh1dC2QtGp+opiG9XjzJNRctigtC60+PlKiqdVr3TOgkBIYy/U/Q3PfzmLudpsI2i1OdVSho9wbSQ==", "dependencies": { - "System.IO.Hashing": "8.0.0" + "System.IO.Hashing": "10.0.3" } }, "Raphael.Net": { @@ -41,8 +41,8 @@ }, "System.IO.Hashing": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ne1843evDugl0md7Fjzy6QjJrzsjh46ZKbhf8GwBXb5f/gw97J4bxMs0NQKifDuThh/f0bZ0e62NPl1jzTuRqA==" + "resolved": "10.0.3", + "contentHash": "La6ICwsdTKhVX+LKN+pvFjQRR3LhLwq3uKdi2knjLzRyPYBSydF4cjXidYxIiTcDD6XVYdsBWQEI8ZxiZ/OdIg==" }, "craftimizer.simulator": { "type": "Project" @@ -51,7 +51,7 @@ "type": "Project", "dependencies": { "Craftimizer.Simulator": "[1.0.0, )", - "DotNext": "[5.26.1, )", + "DotNext": "[6.1.0, )", "Raphael.Net": "[4.1.0, )" } } diff --git a/Simulator/Craftimizer.Simulator.csproj b/Simulator/Craftimizer.Simulator.csproj index da5b984..fa70b9e 100644 --- a/Simulator/Craftimizer.Simulator.csproj +++ b/Simulator/Craftimizer.Simulator.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Solver/Craftimizer.Solver.csproj b/Solver/Craftimizer.Solver.csproj index 5e409ea..cae096d 100644 --- a/Solver/Craftimizer.Solver.csproj +++ b/Solver/Craftimizer.Solver.csproj @@ -10,8 +10,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Test/Craftimizer.Test.csproj b/Test/Craftimizer.Test.csproj index b3b1c83..0f77edc 100644 --- a/Test/Craftimizer.Test.csproj +++ b/Test/Craftimizer.Test.csproj @@ -11,13 +11,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + From 106f5017f60f1798c73f89fdc52f93b3c8c76d57 Mon Sep 17 00:00:00 2001 From: Edenane Date: Mon, 4 May 2026 18:28:50 +0100 Subject: [PATCH 2/3] Update Craftimizer.csproj Update for 7.5, updated version --- Craftimizer/Craftimizer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Craftimizer/Craftimizer.csproj b/Craftimizer/Craftimizer.csproj index d6497de..94b72f2 100644 --- a/Craftimizer/Craftimizer.csproj +++ b/Craftimizer/Craftimizer.csproj @@ -2,7 +2,7 @@ Asriel Camora - 2.9.1.1 + 2.10.0.0 https://github.com/WorkingRobot/Craftimizer.git Debug;Release From a788c9745695d3437677416ceaca2d568b964abf Mon Sep 17 00:00:00 2001 From: Edenane Date: Tue, 5 May 2026 07:49:18 +0100 Subject: [PATCH 3/3] Update Craftimizer.csproj Updated Dalamud sdk to 15.0.0 Removed unneeded package references --- Craftimizer/Craftimizer.csproj | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Craftimizer/Craftimizer.csproj b/Craftimizer/Craftimizer.csproj index 94b72f2..bd2a328 100644 --- a/Craftimizer/Craftimizer.csproj +++ b/Craftimizer/Craftimizer.csproj @@ -1,5 +1,5 @@ - + Asriel Camora 2.10.0.0 @@ -41,9 +41,4 @@ - - - - -