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();