using Dalamud.Interface; using ImGuiNET; using System; using System.Collections.Generic; using System.Linq; using System.Numerics; namespace CCMM { public class PluginUI { private readonly CCMMPlugin plugin; private INode dragged = null; private Guid runningChoice = Guid.Empty; private uint spawned = 0; private bool _settingsVisible = false; public bool SettingsVisible { get => this._settingsVisible; set => this._settingsVisible = value; } public PluginUI(CCMMPlugin plugin) { this.plugin = plugin ?? throw new ArgumentNullException(nameof(plugin), "CCMMPlugin cannot be null"); } public void OpenSettings(object sender, EventArgs e) { this.SettingsVisible = true; } public void Draw() { if (this.SettingsVisible) { this.DrawSettings(); } } private bool RemoveNode(List list, INode toRemove) { if (list.Remove(toRemove)) { return true; } foreach (INode node in list) { if (node.Children.Count > 0 && this.RemoveNode(node.Children, toRemove)) { return true; } } return false; } private void DrawSettings() { // unset the cancel choice if no longer running if (this.runningChoice != Guid.Empty && !this.plugin.MacroHandler.IsRunning(this.runningChoice)) { this.runningChoice = Guid.Empty; } if (ImGui.Begin(this.plugin.Name, ref this._settingsVisible)) { ImGui.Columns(2); if (IconButton(FontAwesomeIcon.Plus)) { this.plugin.Config.Nodes.Add(new Macro("Untitled macro", "")); this.plugin.Config.Save(); } Tooltip("Add macro"); ImGui.SameLine(); if (IconButton(FontAwesomeIcon.FolderPlus)) { this.plugin.Config.Nodes.Add(new Folder("Untitled folder")); this.plugin.Config.Save(); } Tooltip("Add folder"); List toRemove = new List(); foreach (INode node in this.plugin.Config.Nodes) { toRemove.AddRange(this.DrawNode(node)); } foreach (INode node in toRemove) { this.RemoveNode(this.plugin.Config.Nodes, node); } if (toRemove.Count != 0) { this.plugin.Config.Save(); } ImGui.NextColumn(); ImGui.Text("Running macros"); ImGui.PushItemWidth(-1f); if (ImGui.ListBoxHeader("##running-macros", this.plugin.MacroHandler.Running.Count, 5)) { foreach (KeyValuePair entry in this.plugin.MacroHandler.Running) { if (ImGui.Selectable($"{entry.Value.Name}##{entry.Key}", this.runningChoice == entry.Key)) { this.runningChoice = entry.Key; } } ImGui.ListBoxFooter(); } ImGui.PopItemWidth(); if (ImGui.Button("Cancel") && this.runningChoice != Guid.Empty) { this.plugin.MacroHandler.CancelMacro(this.runningChoice); } ImGui.SameLine(); bool paused = this.runningChoice != Guid.Empty && this.plugin.MacroHandler.IsPaused(this.runningChoice); if (ImGui.Button(paused ? "Resume" : "Pause") && this.runningChoice != Guid.Empty) { if (paused) { this.plugin.MacroHandler.ResumeMacro(this.runningChoice); } else { this.plugin.MacroHandler.PauseMacro(this.runningChoice); } } ImGui.Columns(1); ImGui.End(); } } private List DrawNode(INode node) { List toRemove = new List(); ImGui.PushID($"{node.Id}"); bool open = ImGui.TreeNode($"{node.Id}", $"{node.Name}"); if (ImGui.BeginPopupContextItem()) { string name = node.Name; if (ImGui.InputText($"##{node.Id}-rename", ref name, (uint)this.plugin.Config.MaxLength, ImGuiInputTextFlags.AutoSelectAll)) { node.Name = name; this.plugin.Config.Save(); } if (ImGui.Button("Delete")) { toRemove.Add(node); } ImGui.SameLine(); if (ImGui.Button("Copy UUID")) { ImGui.SetClipboardText($"{node.Id}"); } if (node is Macro macro) { ImGui.SameLine(); if (ImGui.Button("Run##context")) { this.RunMacro(macro); } } ImGui.EndPopup(); } if (ImGui.BeginDragDropSource()) { ImGui.Text(node.Name); this.dragged = node; ImGui.SetDragDropPayload("CCMM-GUID", IntPtr.Zero, 0); ImGui.EndDragDropSource(); } if (node is Folder dfolder && ImGui.BeginDragDropTarget()) { ImGuiPayloadPtr payloadPtr = ImGui.AcceptDragDropPayload("CCMM-GUID"); bool nullPtr; unsafe { nullPtr = payloadPtr.NativePtr == null; } if (!nullPtr && payloadPtr.IsDelivery() && this.dragged != null) { dfolder.Children.Add(this.dragged.Duplicate()); this.dragged.Id = Guid.NewGuid(); toRemove.Add(this.dragged); this.dragged = null; } ImGui.EndDragDropTarget(); } ImGui.PopID(); if (open) { if (node is Macro macro) { this.DrawMacro(macro); } else if (node is Folder folder) { this.DrawFolder(folder); foreach (INode child in node.Children) { toRemove.AddRange(this.DrawNode(child)); } } ImGui.TreePop(); } return toRemove; } private void DrawMacro(Macro macro) { string contents = macro.Contents; ImGui.PushItemWidth(-1f); if (ImGui.InputTextMultiline($"##{macro.Id}-editor", ref contents, (uint)this.plugin.Config.MaxLength, new Vector2(0, 250))) { macro.Contents = contents; this.plugin.Config.Save(); } ImGui.PopItemWidth(); if (ImGui.Button("Run")) { this.RunMacro(macro); } } private void DrawFolder(Folder folder) { } private void RunMacro(Macro macro) { this.plugin.MacroHandler.SpawnMacro(macro); } private static bool IconButton(FontAwesomeIcon icon) { ImGui.PushFont(UiBuilder.IconFont); bool ret = ImGui.Button(icon.ToIconString()); ImGui.PopFont(); return ret; } private static void Tooltip(string text) { if (ImGui.IsItemHovered()) { ImGui.BeginTooltip(); ImGui.TextUnformatted(text); ImGui.EndTooltip(); } } } }