diff --git a/Craftimizer/Configuration.cs b/Craftimizer/Configuration.cs index cd473f4..a892b46 100644 --- a/Craftimizer/Configuration.cs +++ b/Craftimizer/Configuration.cs @@ -112,6 +112,13 @@ public class Configuration : IPluginConfiguration } } + public void SwapMacros(int i, int j) + { + (macros[i], macros[j]) = (macros[j], macros[i]); + Save(); + OnMacroListChanged?.Invoke(); + } + public void Save() => Service.PluginInterface.SavePluginConfig(this); } diff --git a/Craftimizer/ImGuiExtras.cs b/Craftimizer/ImGuiExtras.cs index dbdd66d..dfc3e57 100644 --- a/Craftimizer/ImGuiExtras.cs +++ b/Craftimizer/ImGuiExtras.cs @@ -19,6 +19,9 @@ internal static unsafe class ImGuiExtras [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] private static extern bool igButtonBehavior(Vector4 bb, uint id, bool* outHovered, bool* outHeld, ImGuiButtonFlags flags); + [DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)] + private static extern bool igItemSize_Vec2(Vector2 size, float text_baseline_y = -1.0f); + // https://github.com/ImGuiNET/ImGui.NET/blob/069363672fed940ebdaa02f9b032c282b66467c7/src/ImGui.NET/Util.cs #region Util @@ -159,4 +162,22 @@ internal static unsafe class ImGuiExtras return igButtonBehavior(bb, id, hoveredPtr, heldPtr, flags); } } + + public static unsafe bool ItemSize(Vector2 size, float text_baseline_y = -1.0f) => + igItemSize_Vec2(size, text_baseline_y); + + public static unsafe bool SetDragDropPayload(string type, T data) where T : unmanaged => + ImGui.SetDragDropPayload(type, (nint)(&data), (uint)sizeof(T)); + + public static unsafe bool AcceptDragDropPayload(string type, out T data) where T : unmanaged + { + var payload = ImGui.AcceptDragDropPayload(type); + if (payload.NativePtr == null || payload.DataSize != sizeof(T)) + { + data = default; + return false; + } + data = *(T*)payload.Data; + return true; + } } diff --git a/Craftimizer/Windows/MacroList.cs b/Craftimizer/Windows/MacroList.cs index dbceea8..c8bc501 100644 --- a/Craftimizer/Windows/MacroList.cs +++ b/Craftimizer/Windows/MacroList.cs @@ -62,9 +62,34 @@ public sealed class MacroList : Window, IDisposable using var group = ImRaii.Child("macros", new(-1, -1)); if (sortedMacros.Count > 0) { + var width = ImGui.GetContentRegionAvail().X; var macros = new List(sortedMacros); - foreach (var macro in macros) - DrawMacro(macro); + for(var i = 0; i < macros.Count; ++i) + { + var pos = ImGui.GetCursorPos(); + DrawMacro(macros[i]); + ImGui.SetCursorPos(pos); + ImGui.InvisibleButton($"###macroButton{i}", ImGui.GetItemRectSize()); + if (isUnsorted) + { + using (var _source = ImRaii.DragDropSource()) + { + if (_source) + { + ImGuiExtras.SetDragDropPayload("macroListItem", i); + DrawMacro(macros[i], width); + } + } + using (var _target = ImRaii.DragDropTarget()) + { + if (_target) + { + if (ImGuiExtras.AcceptDragDropPayload("macroListItem", out int j)) + Service.Configuration.SwapMacros(i, j); + } + } + } + } } else { @@ -95,6 +120,7 @@ public sealed class MacroList : Window, IDisposable private string searchText = string.Empty; private List sortedMacros = null!; + private bool isUnsorted = true; private void DrawSearchBar() { ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); @@ -102,8 +128,10 @@ public sealed class MacroList : Window, IDisposable RefreshSearch(); } - private void DrawMacro(Macro macro) + private void DrawMacro(Macro macro, float width = -1) { + width = width < 0 ? ImGui.GetContentRegionAvail().X : width; + var windowHeight = 2 * ImGui.GetFrameHeightWithSpacing(); if (macro.Actions.Any(a => a.Category() == ActionCategory.Combo)) @@ -111,8 +139,8 @@ public sealed class MacroList : Window, IDisposable var stateNullable = GetMacroState(macro); - using var panel = ImRaii2.GroupPanel(macro.Name, -1, out var availWidth); - var stepsAvailWidthOffset = ImGui.GetContentRegionAvail().X - availWidth; + using var panel = ImRaii2.GroupPanel(macro.Name, width - ImGui.GetStyle().ItemSpacing.X * 2, out var availWidth); + var stepsAvailWidthOffset = width - availWidth; var spacing = ImGui.GetStyle().ItemSpacing.Y; var miniRowHeight = (windowHeight - spacing) / 2f; @@ -294,8 +322,10 @@ public sealed class MacroList : Window, IDisposable if (string.IsNullOrWhiteSpace(searchText)) { sortedMacros = new(Macros); + isUnsorted = true; return; } + isUnsorted = false; var matcher = new FuzzyMatcher(searchText.ToLowerInvariant(), MatchMode.FuzzyParts); var query = Macros.AsParallel().Select(i => (Item: i, Score: matcher.Matches(i.Name.ToLowerInvariant()))) .Where(t => t.Score > 0)