From ef6c7014e42f93e38f4b192041cce4e0ab320da4 Mon Sep 17 00:00:00 2001 From: RisaDev <151885272+RisaDev@users.noreply.github.com> Date: Sun, 16 Jun 2024 02:58:17 +0300 Subject: [PATCH] Added button to jump to template editing from profile tab, made TemplateManager IDisposable --- .../Templates/Events/TemplateEditorEvent.cs | 33 ++++++++ CustomizePlus/Templates/TemplateManager.cs | 7 +- .../UI/Windows/MainWindow/MainWindow.cs | 51 ++++++++++++- .../MainWindow/Tabs/Profiles/ProfilePanel.cs | 32 ++++++-- .../Tabs/Templates/TemplatePanel.cs | 75 ++++++++++++++++--- 5 files changed, 178 insertions(+), 20 deletions(-) create mode 100644 CustomizePlus/Templates/Events/TemplateEditorEvent.cs diff --git a/CustomizePlus/Templates/Events/TemplateEditorEvent.cs b/CustomizePlus/Templates/Events/TemplateEditorEvent.cs new file mode 100644 index 0000000..a0afd2c --- /dev/null +++ b/CustomizePlus/Templates/Events/TemplateEditorEvent.cs @@ -0,0 +1,33 @@ +using CustomizePlus.Templates.Data; +using OtterGui.Classes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CustomizePlus.Templates.Events; + +/// +/// Triggered when something related to template editor happens +/// +public class TemplateEditorEvent() : EventWrapper(nameof(TemplateEditorEvent)) +{ + public enum Type + { + /// + /// Called when something requests editor to be enabled. + /// + EditorEnableRequested, + /// + /// Called when something requests editor to be enabled. Stage 2 - logic after tab has been switched. + /// + EditorEnableRequestedStage2 + } + + public enum Priority + { + MainWindow = -1, + TemplatePanel + } +} \ No newline at end of file diff --git a/CustomizePlus/Templates/TemplateManager.cs b/CustomizePlus/Templates/TemplateManager.cs index 1df8a31..a41dda6 100644 --- a/CustomizePlus/Templates/TemplateManager.cs +++ b/CustomizePlus/Templates/TemplateManager.cs @@ -13,7 +13,7 @@ using System.Linq; namespace CustomizePlus.Templates; -public class TemplateManager +public class TemplateManager : IDisposable { private readonly SaveService _saveService; private readonly Logger _logger; @@ -41,6 +41,11 @@ public class TemplateManager LoadTemplates(); } + public void Dispose() + { + _reloadEvent.Unsubscribe(OnReload); + } + public Template? GetTemplate(Guid templateId) => _templates.FirstOrDefault(d => d.UniqueId == templateId); public void LoadTemplates() diff --git a/CustomizePlus/UI/Windows/MainWindow/MainWindow.cs b/CustomizePlus/UI/Windows/MainWindow/MainWindow.cs index ab74f95..1d7f639 100644 --- a/CustomizePlus/UI/Windows/MainWindow/MainWindow.cs +++ b/CustomizePlus/UI/Windows/MainWindow/MainWindow.cs @@ -16,6 +16,9 @@ using CustomizePlus.Templates; using ECommons.ImGuiMethods; using static System.Windows.Forms.AxHost; using Dalamud.Interface.Colors; +using CustomizePlus.Templates.Events; +using CustomizePlus.Templates.Data; +using ECommons.Schedulers; namespace CustomizePlus.UI.Windows.MainWindow; @@ -34,6 +37,15 @@ public class MainWindow : Window, IDisposable private readonly PluginConfiguration _configuration; private readonly HookingService _hookingService; + private readonly TemplateEditorEvent _templateEditorEvent; + + /// + /// Used to force the main window to switch to specific tab + /// + private string? _switchToTab = null; + + private Action? _actionAfterTabSwitch = null; + public MainWindow( DalamudPluginInterface pluginInterface, SettingsTab settingsTab, @@ -45,7 +57,8 @@ public class MainWindow : Window, IDisposable PluginStateBlock pluginStateBlock, TemplateEditorManager templateEditorManager, PluginConfiguration configuration, - HookingService hookingService + HookingService hookingService, + TemplateEditorEvent templateEditorEvent ) : base($"Customize+ v{Plugin.Version}###CPlusMainWindow") { _settingsTab = settingsTab; @@ -61,6 +74,10 @@ public class MainWindow : Window, IDisposable _configuration = configuration; _hookingService = hookingService; + _templateEditorEvent = templateEditorEvent; + + _templateEditorEvent.Subscribe(OnTemplateEditorEvent, TemplateEditorEvent.Priority.MainWindow); + pluginInterface.UiBuilder.DisableGposeUiHide = true; SizeConstraints = new WindowSizeConstraints() { @@ -73,7 +90,7 @@ public class MainWindow : Window, IDisposable public void Dispose() { - //throw new NotImplementedException(); + _templateEditorEvent.Unsubscribe(OnTemplateEditorEvent); } public override void Draw() @@ -83,13 +100,21 @@ public class MainWindow : Window, IDisposable using (var disabled = ImRaii.Disabled(_hookingService.RenderHookFailed || _hookingService.MovementHookFailed)) { LockWindowClosureIfNeeded(); - ImGuiEx.EzTabBar("##tabs", [ + ImGuiEx.EzTabBar("##tabs", null, _switchToTab, [ ("Settings", _settingsTab.Draw, null, true), ("Templates", _templatesTab.Draw, null, true), ("Profiles", _profilesTab.Draw, null, true), (_configuration.DebuggingModeEnabled ? "IPC Test" : null, _ipcTestTab.Draw, ImGuiColors.DalamudGrey, true), (_configuration.DebuggingModeEnabled ? "State monitoring" : null, _stateMonitoringTab.Draw, ImGuiColors.DalamudGrey, true), ]); + + _switchToTab = null; + + if (_actionAfterTabSwitch != null) + { + _actionAfterTabSwitch(); + _actionAfterTabSwitch = null; + } } _pluginStateBlock.Draw(yPos); @@ -108,4 +133,24 @@ public class MainWindow : Window, IDisposable RespectCloseHotkey = true; } } + + private void OnTemplateEditorEvent(TemplateEditorEvent.Type type, Template? template) + { + if (type != TemplateEditorEvent.Type.EditorEnableRequested) + return; + + if (template == null) + return; + + if (!template.IsWriteProtected && !_templateEditorManager.IsEditorActive) + { + new TickScheduler(() => + { + _switchToTab = "Templates"; + + //To make sure the tab has switched, ugly but imgui is shit and I don't trust it. + _actionAfterTabSwitch = () => { _templateEditorEvent.Invoke(TemplateEditorEvent.Type.EditorEnableRequestedStage2, template); }; + }); + } + } } diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs index 71a5dfd..526a8a1 100644 --- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs +++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs @@ -7,15 +7,12 @@ using System; using System.Linq; using System.Numerics; using CustomizePlus.Profiles; -using CustomizePlus.Game.Services; using CustomizePlus.Configuration.Data; using CustomizePlus.Profiles.Data; using CustomizePlus.UI.Windows.Controls; using CustomizePlus.Templates; -using CustomizePlus.Core.Helpers; -using System.Windows.Forms; using CustomizePlus.Core.Data; -using static System.Windows.Forms.VisualStyles.VisualStyleElement; +using CustomizePlus.Templates.Events; namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles; @@ -26,6 +23,7 @@ public class ProfilePanel private readonly PluginConfiguration _configuration; private readonly TemplateCombo _templateCombo; private readonly TemplateEditorManager _templateEditorManager; + private readonly TemplateEditorEvent _templateEditorEvent; private string? _newName; private string? _newCharacterName; @@ -43,13 +41,15 @@ public class ProfilePanel ProfileManager manager, PluginConfiguration configuration, TemplateCombo templateCombo, - TemplateEditorManager templateEditorManager) + TemplateEditorManager templateEditorManager, + TemplateEditorEvent templateEditorEvent) { _selector = selector; _manager = manager; _configuration = configuration; _templateCombo = templateCombo; _templateEditorManager = templateEditorManager; + _templateEditorEvent = templateEditorEvent; } public void Draw() @@ -247,7 +247,7 @@ public class ProfilePanel private void DrawTemplateArea() { - using var table = ImRaii.Table("SetTable", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY); + using var table = ImRaii.Table("SetTable", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY); if (!table) return; @@ -256,6 +256,8 @@ public class ProfilePanel ImGui.TableSetupColumn("Template", ImGuiTableColumnFlags.WidthFixed, 220 * ImGuiHelpers.GlobalScale); + ImGui.TableSetupColumn("##editbtn", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale); + ImGui.TableHeadersRow(); //warn: .ToList() might be performance critical at some point @@ -277,6 +279,24 @@ public class ProfilePanel ImGui.TableNextColumn(); _templateCombo.Draw(_selector.Selected!, template, idx); DrawDragDrop(_selector.Selected!, idx); + ImGui.TableNextColumn(); + + var disabledCondition = _templateEditorManager.IsEditorActive || template.IsWriteProtected; + using (var disabled = ImRaii.Disabled(disabledCondition)) + { + if (ImGui.Button("Open in editor")) + _templateEditorEvent.Invoke(TemplateEditorEvent.Type.EditorEnableRequested, template); + ImGuiUtil.HoverTooltip("Open this template in the template editor"); + } + + if(disabledCondition) + { + ImGui.SameLine(); + ImGui.PushStyleColor(ImGuiCol.Text, Constants.Colors.Warning); + ImGuiUtil.PrintIcon(FontAwesomeIcon.ExclamationTriangle); + ImGui.PopStyleColor(); + ImGuiUtil.HoverTooltip("Can not be edited because this template is either write protected or template editor is already enabled."); + } } ImGui.TableNextColumn(); diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Templates/TemplatePanel.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Templates/TemplatePanel.cs index 12c4a6c..a6a7c89 100644 --- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Templates/TemplatePanel.cs +++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Templates/TemplatePanel.cs @@ -15,10 +15,12 @@ using CustomizePlus.Configuration.Data; using CustomizePlus.Core.Helpers; using CustomizePlus.Templates.Data; using OtterGui.Log; +using CustomizePlus.Templates.Events; +using ECommons.Schedulers; namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Templates; -public class TemplatePanel +public class TemplatePanel : IDisposable { private readonly TemplateFileSystemSelector _selector; private readonly TemplateManager _manager; @@ -28,9 +30,16 @@ public class TemplatePanel private readonly PopupSystem _popupSystem; private readonly Logger _logger; + private readonly TemplateEditorEvent _editorEvent; + private string? _newName; private Template? _changedTemplate; + /// + /// Set to true if we received OnEditorEvent EditorEnableRequested and waiting for selector value to be changed. + /// + private bool _isEditorEnablePending = false; + private string SelectionName => _selector.Selected == null ? "No Selection" : _selector.IncognitoMode ? _selector.Selected.Incognito : _selector.Selected.Name.Text; @@ -41,7 +50,8 @@ public class TemplatePanel PluginConfiguration configuration, MessageService messageService, PopupSystem popupSystem, - Logger logger) + Logger logger, + TemplateEditorEvent editorEvent) { _selector = selector; _manager = manager; @@ -51,6 +61,11 @@ public class TemplatePanel _popupSystem = popupSystem; _logger = logger; + _editorEvent = editorEvent; + + _editorEvent.Subscribe(OnEditorEvent, TemplateEditorEvent.Priority.TemplatePanel); + + _selector.SelectionChanged += SelectorSelectionChanged; } public void Draw() @@ -67,6 +82,11 @@ public class TemplatePanel } } + public void Dispose() + { + _editorEvent.Unsubscribe(OnEditorEvent); + } + private HeaderDrawer.Button LockButton() => _selector.Selected == null ? HeaderDrawer.Button.Invisible @@ -167,17 +187,23 @@ public class TemplatePanel private void DrawEditorToggle() { + (bool isEditorAllowed, bool isEditorActive) = CanToggleEditor(); + if (ImGuiUtil.DrawDisabledButton($"{(_boneEditor.IsEditorActive ? "Finish" : "Start")} bone editing", Vector2.Zero, - "Toggle the bone editor for this template", - (_selector.Selected?.IsWriteProtected ?? true) || !_configuration.PluginEnabled)) + "Toggle the bone editor for this template", !isEditorAllowed)) { - if (!_boneEditor.IsEditorActive) + if (!isEditorActive) _boneEditor.EnableEditor(_selector.Selected!); else _boneEditor.DisableEditor(); } } + private (bool isEditorAllowed, bool isEditorActive) CanToggleEditor() + { + return ((!_selector.Selected?.IsWriteProtected ?? false) || _configuration.PluginEnabled, _boneEditor.IsEditorActive); + } + private void DrawBasicSettings() { using (var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f))) @@ -214,11 +240,6 @@ public class TemplatePanel } } - /*private void SetFromClipboard() - { - - }*/ - private void ExportToClipboard() { try @@ -232,4 +253,38 @@ public class TemplatePanel _popupSystem.ShowPopup(PopupSystem.Messages.ActionError); } } + + + private void SelectorSelectionChanged(Template? oldSelection, Template? newSelection, in TemplateFileSystemSelector.TemplateState state) + { + if (!_isEditorEnablePending) + return; + + _isEditorEnablePending = false; + + _boneEditor.EnableEditor(_selector.Selected!); + } + + private void OnEditorEvent(TemplateEditorEvent.Type type, Template? template) + { + if (type != TemplateEditorEvent.Type.EditorEnableRequestedStage2) + return; + + if(template == null) + return; + + (bool isEditorAllowed, bool isEditorActive) = CanToggleEditor(); + + if (!isEditorAllowed || isEditorActive) + return; + + if(_selector.Selected != template) + { + _selector.SelectByValue(template); + + _isEditorEnablePending = true; + } + else + _boneEditor.EnableEditor(_selector.Selected!); + } }