From abb92e741e8e5a40af3115ffeb4e2963ec3164fb Mon Sep 17 00:00:00 2001 From: RisaDev <151885272+RisaDev@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:14:29 +0300 Subject: [PATCH] More IPC work Additional checks to make sure profile update event is not getting sent when editor and default profile is involved Selected default profile can no longer be changed if profile set as default is enabled Fixed "Limit to my creatures" not ignoring objects with IdentifierType != Owned IPC test tab no longer initializes IPC if debug mode is disabled Fixed incorrect warning priority in plugin state control Some slight text changes --- CustomizePlus/Api/CustomizePlusIpc.Profile.cs | 35 +++++++++---------- .../Armatures/Services/ArmatureManager.cs | 4 +-- CustomizePlus/Core/Data/Constants.cs | 8 +++++ .../UI/Windows/Controls/PluginStateBlock.cs | 23 ++++++------ .../MainWindow/Tabs/Debug/IPCTestTab.cs | 7 ++-- .../MainWindow/Tabs/Profiles/ProfilePanel.cs | 30 ++++++++++++---- .../UI/Windows/MainWindow/Tabs/SettingsTab.cs | 2 +- 7 files changed, 65 insertions(+), 44 deletions(-) diff --git a/CustomizePlus/Api/CustomizePlusIpc.Profile.cs b/CustomizePlus/Api/CustomizePlusIpc.Profile.cs index 0e3e6ee..ebaa260 100644 --- a/CustomizePlus/Api/CustomizePlusIpc.Profile.cs +++ b/CustomizePlus/Api/CustomizePlusIpc.Profile.cs @@ -152,12 +152,6 @@ public partial class CustomizePlusIpc if (!actor.Valid) return ((int)ErrorCode.InvalidCharacter, null); - /*if (character == _objectTable[0]) - { - _logger.Error($"Received request to set profile on local character, this is not allowed"); - return; - }*/ - try { IPCCharacterProfile? profile; @@ -204,12 +198,6 @@ public partial class CustomizePlusIpc if (!actor.Valid) return (int)ErrorCode.InvalidCharacter; - /*if (character == _objectTable[0]) - { - _logger.Error($"Received request to revert profile on local character, this is not allowed"); - return; - }*/ - try { _profileManager.RemoveTemporaryProfile(actor); @@ -269,7 +257,7 @@ public partial class CustomizePlusIpc } } - //warn: limitation - ignores default profiles but why you would use default profile on your own character + //warn: intended limitation - ignores default profiles because why you would use default profile on your own character private void OnArmatureChanged(ArmatureChanged.Type type, Armature armature, object? arg3) { string currentPlayerName = _gameObjectService.GetCurrentPlayerName(); @@ -295,25 +283,34 @@ public partial class CustomizePlusIpc if (activeProfile != null) { - if (activeProfile == _profileManager.DefaultProfile) - return; //default profiles are not allowed to be sent - - if (activeProfile.ProfileType == ProfileType.Editor) + if (activeProfile == _profileManager.DefaultProfile || activeProfile.ProfileType == ProfileType.Editor) { - if (activeProfile == oldProfile) //ignore any changes while player is in editor + //ignore any changes while player is in editor or if player changes between default profiles + //also do not send event if there were no active profile before + if (activeProfile == oldProfile || oldProfile == null) return; - OnProfileUpdateInternal(localPlayerCharacter, null); //send empty profile when player enters editor + OnProfileUpdateInternal(localPlayerCharacter, null); //send empty profile when player enters editor or turns on default profile return; } } + //do not send event if we are exiting editor or disabling default profile and don't have any active profile + if (oldProfile != null && + (oldProfile == _profileManager.DefaultProfile || oldProfile.ProfileType == ProfileType.Editor) && + activeProfile == null) + return; + OnProfileUpdateInternal(localPlayerCharacter, activeProfile); return; } if (type == ArmatureChanged.Type.Deleted) { + //Do not send event if default or editor profile was used + if (armature.Profile == _profileManager.DefaultProfile || armature.Profile.ProfileType == ProfileType.Editor) + return; + OnProfileUpdateInternal(localPlayerCharacter, null); return; } diff --git a/CustomizePlus/Armatures/Services/ArmatureManager.cs b/CustomizePlus/Armatures/Services/ArmatureManager.cs index ad305ca..fb79579 100644 --- a/CustomizePlus/Armatures/Services/ArmatureManager.cs +++ b/CustomizePlus/Armatures/Services/ArmatureManager.cs @@ -129,8 +129,8 @@ public unsafe sealed class ArmatureManager : IDisposable foreach (var profile in _profileManager.GetEnabledProfilesByActor(identifier)) { if (profile.LimitLookupToOwnedObjects && - identifier.Type == IdentifierType.Owned && - identifier.PlayerName != _objectManager.PlayerData.Identifier.PlayerName) + (identifier.Type != IdentifierType.Owned || + identifier.PlayerName != _objectManager.PlayerData.Identifier.PlayerName)) continue; return profile; diff --git a/CustomizePlus/Core/Data/Constants.cs b/CustomizePlus/Core/Data/Constants.cs index c382652..5d8051d 100644 --- a/CustomizePlus/Core/Data/Constants.cs +++ b/CustomizePlus/Core/Data/Constants.cs @@ -1,4 +1,5 @@ using FFXIVClientStructs.Havok; +using System.Numerics; namespace CustomizePlus.Core.Data; @@ -79,4 +80,11 @@ internal static class Constants /// Movement hook address, used for position offset and other changes which cannot be done in main hook /// public const string MovementHookAddress = "E8 ?? ?? ?? ?? EB 29 48 8B 5F 08"; + + internal static class Colors + { + public static Vector4 Normal = new Vector4(1, 1, 1, 1); + public static Vector4 Warning = new Vector4(1, 0.5f, 0, 1); + public static Vector4 Error = new Vector4(1, 0, 0, 1); + } } \ No newline at end of file diff --git a/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs b/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs index 0e5617b..fb31279 100644 --- a/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs +++ b/CustomizePlus/UI/Windows/Controls/PluginStateBlock.cs @@ -8,6 +8,7 @@ using CustomizePlus.Configuration.Data; using CustomizePlus.UI.Windows.MainWindow.Tabs.Templates; using CustomizePlus.Core.Helpers; using CustomizePlus.Api; +using CustomizePlus.Core.Data; namespace CustomizePlus.UI.Windows.Controls; @@ -20,10 +21,6 @@ public class PluginStateBlock private readonly HookingService _hookingService; private readonly CustomizePlusIpc _ipcService; - private static Vector4 normalColor = new Vector4(1, 1, 1, 1); - private static Vector4 warnColor = new Vector4(1, 0.5f, 0, 1); - private static Vector4 errorColor = new Vector4(1, 0, 0, 1); - public PluginStateBlock( BoneEditorPanel boneEditorPanel, PluginConfiguration configuration, @@ -55,11 +52,6 @@ public class PluginStateBlock severity = PluginStateSeverity.Error; message = $"Fantasia+ detected. The plugin is disabled until Fantasia+ is disabled and the game is restarted."; } - else if (_gameStateService.GameInPosingMode()) - { - severity = PluginStateSeverity.Warning; - message = $"GPose active. Compatibility with posing tools is limited."; - } else if (!_configuration.PluginEnabled) { severity = PluginStateSeverity.Warning; @@ -80,7 +72,12 @@ public class PluginStateBlock message = $"Editor is active.{(_boneEditorPanel.HasChanges ? " You have unsaved changes, finish template bone editing to open save/revert dialog." : "")}"; } } - else if (_ipcService.IPCFailed) //this is low priority error + else if (_gameStateService.GameInPosingMode()) + { + severity = PluginStateSeverity.Warning; + message = $"GPose active. Compatibility with posing tools is limited."; + } + else if (_ipcService.IPCFailed) //this is a low priority error { severity = PluginStateSeverity.Error; message = $"Detected failure in IPC. Integrations with other plugins will not function."; @@ -91,16 +88,16 @@ public class PluginStateBlock ImGui.SetCursorPos(new Vector2(ImGui.GetWindowContentRegionMax().X - ImGui.CalcTextSize(message).X - 30, yPos - ImGuiHelpers.GlobalScale)); var icon = FontAwesomeIcon.InfoCircle; - var color = normalColor; + var color = Constants.Colors.Normal; switch (severity) { case PluginStateSeverity.Warning: icon = FontAwesomeIcon.ExclamationTriangle; - color = warnColor; + color = Constants.Colors.Warning; break; case PluginStateSeverity.Error: icon = FontAwesomeIcon.ExclamationTriangle; - color = errorColor; + color = Constants.Colors.Error; break; } diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs index d76cefd..1106888 100644 --- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs +++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Debug/IPCTestTab.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using IPCProfileDataTuple = (System.Guid UniqueId, string Name, string VirtualPath, string CharacterName, bool IsEnabled); using OtterGui.Log; using CustomizePlus.Core.Extensions; +using CustomizePlus.Configuration.Data; namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Debug; @@ -85,7 +86,8 @@ public class IPCTestTab //: IDisposable ObjectManager objectManager, GameObjectService gameObjectService, ActorManager actorManager, - Logger logger) + Logger logger, + PluginConfiguration configuration) { _objectTable = objectTable; _profileManager = profileManager; @@ -95,7 +97,8 @@ public class IPCTestTab //: IDisposable _actorManager = actorManager; _logger = logger; - EzIPC.Init(this, "CustomizePlus"); + if(configuration.DebuggingModeEnabled) + EzIPC.Init(this, "CustomizePlus"); //do not init EzIPC if debugging disabled so no debug event hook is created if (_getApiVersionIpcFunc != null) _apiVersion = _getApiVersionIpcFunc(); diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs index cf406df..c31ede3 100644 --- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs +++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs @@ -12,6 +12,10 @@ 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; namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles; @@ -147,16 +151,28 @@ public class ProfilePanel { if (ImGui.Checkbox("##Enabled", ref enabled)) _manager.SetEnabled(_selector.Selected!, enabled); + ImGuiUtil.LabeledHelpMarker("Enabled", + "Whether the templates in this profile should be applied at all. Only one profile can be enabled for a character at the same time."); } - ImGuiUtil.LabeledHelpMarker("Enabled", - "Whether the templates in this profile should be applied at all. Only one profile can be enabled for a character at the same time."); ImGui.SameLine(); var isDefault = _manager.DefaultProfile == _selector.Selected; - if (ImGui.Checkbox("##DefaultProfile", ref isDefault)) - _manager.SetDefaultProfile(isDefault ? _selector.Selected! : null); - ImGuiUtil.LabeledHelpMarker("Default profile (Players and Retainers only)", - "Whether the templates in this profile are applied to all players and retainers without a specific profile. Only one profile can be default at the same time."); + var isDefaultEnabled = _manager.DefaultProfile?.Enabled ?? false; + using (ImRaii.Disabled(isDefaultEnabled)) + { + if (ImGui.Checkbox("##DefaultProfile", ref isDefault)) + _manager.SetDefaultProfile(isDefault ? _selector.Selected! : null); + ImGuiUtil.LabeledHelpMarker("Default profile (Players and Retainers only)", + "Whether the templates in this profile are applied to all players and retainers without a specific profile. Only one profile can be default at the same time."); + } + if(isDefaultEnabled) + { + ImGui.SameLine(); + ImGui.PushStyleColor(ImGuiCol.Text, Constants.Colors.Warning); + ImGuiUtil.PrintIcon(FontAwesomeIcon.ExclamationTriangle); + ImGui.PopStyleColor(); + ImGuiUtil.HoverTooltip("Can only be changed while the default profile is disabled."); + } } } @@ -224,7 +240,7 @@ public class ProfilePanel if (ImGui.Checkbox("##LimitLookupToOwnedObjects", ref enabled)) _manager.SetLimitLookupToOwned(_selector.Selected!, enabled); ImGuiUtil.LabeledHelpMarker("Limit to my creatures", - "When enabled limits the character search to only your own summons, mounts and minions.\nUseful when there is possibility there will be another character with that name owned by another player.\n* For battle chocobo use \"Chocobo\" as character name.\n** If you are changing root scale for mount and want to keep your scale make sure your own scale is set to anything other than default value."); + "When enabled limits the character search to only your own summons, mounts and minions.\nUseful when there is possibility there will be another character with that name owned by another player.\n* For battle chocobo use \"Chocobo\" as character name."); } } } diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/SettingsTab.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/SettingsTab.cs index 0627202..fe66006 100644 --- a/CustomizePlus/UI/Windows/MainWindow/Tabs/SettingsTab.cs +++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/SettingsTab.cs @@ -197,7 +197,7 @@ public class SettingsTab { var isChecked = _configuration.DebuggingModeEnabled; if (CtrlHelper.CheckboxWithTextAndHelp("##debugmode", "Debug mode", - "Enables debug mode", ref isChecked)) + "Enables debug mode. Requires plugin restart for all features to become properly initialized.", ref isChecked)) { _configuration.DebuggingModeEnabled = isChecked; _configuration.Save();