diff --git a/CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs b/CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs
index de6e946..b24fcf4 100644
--- a/CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs
+++ b/CustomizePlus/Api/Compatibility/CustomizePlusLegacyIpc.cs
@@ -25,7 +25,7 @@ using Penumbra.GameData.Interop;
namespace CustomizePlus.Api.Compatibility;
-[Obsolete("Will be removed in the next release")]
+[Obsolete("Will be removed in the near future, do not use this IPC")]
public class CustomizePlusLegacyIpc : IDisposable
{
private readonly IObjectTable _objectTable;
@@ -73,7 +73,7 @@ public class CustomizePlusLegacyIpc : IDisposable
InitializeProviders();
- _profileChangedEvent.Subscribe(OnProfileChange, ProfileChanged.Priority.CustomizePlusIpc);
+ _profileChangedEvent.Subscribe(OnProfileChange, ProfileChanged.Priority.CustomizePlusLegacyIpc);
_armatureChangedEvent.Subscribe(OnArmatureChanged, ArmatureChanged.Priority.CustomizePlusIpc);
}
@@ -109,10 +109,10 @@ public class CustomizePlusLegacyIpc : IDisposable
return;
if (type == ArmatureChanged.Type.Created ||
- type == ArmatureChanged.Type.Rebound)
+ type == ArmatureChanged.Type.Updated)
{
if(armature.Profile == null)
- _logger.Warning("Armature created/rebound and profile is null");
+ _logger.Warning("[LEGACY IPC DO NOT USE] Armature created/rebound and profile is null");
OnProfileUpdate(armature.Profile);
return;
@@ -127,7 +127,7 @@ public class CustomizePlusLegacyIpc : IDisposable
private void InitializeProviders()
{
- _logger.Debug("Initializing legacy Customize+ IPC providers.");
+ _logger.Debug("[LEGACY IPC DO NOT USE] Initializing legacy Customize+ IPC providers.");
try
{
ProviderGetApiVersion = _pluginInterface.GetIpcProvider<(int, int)>(ProviderApiVersionLabel);
@@ -135,7 +135,7 @@ public class CustomizePlusLegacyIpc : IDisposable
}
catch (Exception ex)
{
- _logger.Error($"Error registering legacy Customize+ IPC provider for {ProviderApiVersionLabel}: {ex}");
+ _logger.Error($"[LEGACY IPC DO NOT USE] Error registering legacy Customize+ IPC provider for {ProviderApiVersionLabel}: {ex}");
}
try
@@ -146,7 +146,7 @@ public class CustomizePlusLegacyIpc : IDisposable
}
catch (Exception ex)
{
- _logger.Error($"Error registering legacy Customize+ IPC provider for {GetProfileFromCharacterLabel}: {ex}");
+ _logger.Error($"[LEGACY IPC DO NOT USE] Error registering legacy Customize+ IPC provider for {GetProfileFromCharacterLabel}: {ex}");
}
try
@@ -157,7 +157,7 @@ public class CustomizePlusLegacyIpc : IDisposable
}
catch (Exception ex)
{
- _logger.Error($"Error registering legacy Customize+ IPC provider for {SetProfileToCharacterLabel}: {ex}");
+ _logger.Error($"[LEGACY IPC DO NOT USE] Error registering legacy Customize+ IPC provider for {SetProfileToCharacterLabel}: {ex}");
}
try
@@ -168,7 +168,7 @@ public class CustomizePlusLegacyIpc : IDisposable
}
catch (Exception ex)
{
- _logger.Error($"Error registering legacy Customize+ IPC provider for {RevertCharacterLabel}: {ex}");
+ _logger.Error($"[LEGACY IPC DO NOT USE] Error registering legacy Customize+ IPC provider for {RevertCharacterLabel}: {ex}");
}
try
@@ -177,7 +177,7 @@ public class CustomizePlusLegacyIpc : IDisposable
}
catch (Exception ex)
{
- _logger.Error($"Error registering legacy Customize+ IPC provider for {OnProfileUpdateLabel}: {ex}");
+ _logger.Error($"[LEGACY IPC DO NOT USE] Error registering legacy Customize+ IPC provider for {OnProfileUpdateLabel}: {ex}");
}
}
@@ -192,7 +192,7 @@ public class CustomizePlusLegacyIpc : IDisposable
private void OnProfileUpdate(Profile? profile)
{
- _logger.Debug($"Sending local player update message: {(profile != null ? profile.ToString() : "no profile")}");
+ _logger.Debug($"[LEGACY IPC DO NOT USE] Sending local player update message: {(profile != null ? profile.ToString() : "no profile")}");
var convertedProfile = profile != null ? GetVersion3Profile(profile) : null;
@@ -246,7 +246,7 @@ public class CustomizePlusLegacyIpc : IDisposable
}
catch (Exception ex)
{
- _logger.Warning($"Unable to set body profile. Character: {character?.Name}, exception: {ex}, debug data: {GetBase64String(profileJson)}");
+ _logger.Warning($"[LEGACY IPC DO NOT USE] Unable to set body profile. Character: {character?.Name}, exception: {ex}, debug data: {GetBase64String(profileJson)}");
}
}
diff --git a/CustomizePlus/Api/CustomizePlusIpc.Profile.cs b/CustomizePlus/Api/CustomizePlusIpc.Profile.cs
index 3f0690f..236adaa 100644
--- a/CustomizePlus/Api/CustomizePlusIpc.Profile.cs
+++ b/CustomizePlus/Api/CustomizePlusIpc.Profile.cs
@@ -270,27 +270,6 @@ public partial class CustomizePlusIpc
}
//warn: limitation - ignores default profiles but why you would use default profile on your own character
- private void OnProfileChange(ProfileChanged.Type type, Profile? profile, object? arg3)
- {
- if (type != ProfileChanged.Type.AddedTemplate &&
- type != ProfileChanged.Type.RemovedTemplate &&
- type != ProfileChanged.Type.MovedTemplate &&
- type != ProfileChanged.Type.ChangedTemplate &&
- type != ProfileChanged.Type.Toggled)
- return;
-
- if (profile == null ||
- !profile.Enabled || //profile = null event will be sent from OnArmatureChanged
- profile.CharacterName.Text != _gameObjectService.GetCurrentPlayerName())
- return;
-
- Character? localPlayerCharacter = (Character?)_gameObjectService.GetDalamudGameObjectFromActor(_gameObjectService.GetLocalPlayerActor());
- if (localPlayerCharacter == null)
- return;
-
- OnProfileUpdateInternal(localPlayerCharacter, profile);
- }
-
private void OnArmatureChanged(ArmatureChanged.Type type, Armature armature, object? arg3)
{
string currentPlayerName = _gameObjectService.GetCurrentPlayerName();
@@ -302,13 +281,34 @@ public partial class CustomizePlusIpc
if (localPlayerCharacter == null)
return;
- if (type == ArmatureChanged.Type.Created || //todo: might create second call after OnProfileChange?
- type == ArmatureChanged.Type.Rebound)
+ if (type == ArmatureChanged.Type.Created ||
+ type == ArmatureChanged.Type.Updated)
{
if (armature.Profile == null)
- _logger.Warning("Armature created/rebound and profile is null");
+ _logger.Fatal("INTEGRITY ERROR: Armature created/rebound and profile is null");
- OnProfileUpdateInternal(localPlayerCharacter, armature.Profile);
+ (Profile? activeProfile, Profile? oldProfile) = (null, null);
+ if (type == ArmatureChanged.Type.Created)
+ (activeProfile, oldProfile) = ((Profile?)arg3, null);
+ else
+ (activeProfile, oldProfile) = ((Profile?, Profile?))arg3;
+
+ if (activeProfile != null)
+ {
+ if (activeProfile == _profileManager.DefaultProfile)
+ return; //default profiles are not allowed to be sent
+
+ if (activeProfile.ProfileType == ProfileType.Editor)
+ {
+ if (activeProfile == oldProfile) //ignore any changes while player is in editor
+ return;
+
+ OnProfileUpdateInternal(localPlayerCharacter, null); //send empty profile when player enters editor
+ return;
+ }
+ }
+
+ OnProfileUpdateInternal(localPlayerCharacter, activeProfile);
return;
}
diff --git a/CustomizePlus/Api/CustomizePlusIpc.cs b/CustomizePlus/Api/CustomizePlusIpc.cs
index 3994ba8..81451f8 100644
--- a/CustomizePlus/Api/CustomizePlusIpc.cs
+++ b/CustomizePlus/Api/CustomizePlusIpc.cs
@@ -18,7 +18,6 @@ public partial class CustomizePlusIpc : IDisposable
private readonly ProfileManager _profileManager;
private readonly GameObjectService _gameObjectService;
- private readonly ProfileChanged _profileChangedEvent;
private readonly ArmatureChanged _armatureChangedEvent;
///
@@ -32,8 +31,7 @@ public partial class CustomizePlusIpc : IDisposable
HookingService hookingService,
ProfileManager profileManager,
GameObjectService gameObjectService,
- ArmatureChanged armatureChangedEvent,
- ProfileChanged profileChangedEvent)
+ ArmatureChanged armatureChangedEvent)
{
_pluginInterface = pluginInterface;
_logger = logger;
@@ -41,19 +39,15 @@ public partial class CustomizePlusIpc : IDisposable
_profileManager = profileManager;
_gameObjectService = gameObjectService;
-
- _profileChangedEvent = profileChangedEvent;
_armatureChangedEvent = armatureChangedEvent;
EzIPC.Init(this, "CustomizePlus");
- _profileChangedEvent.Subscribe(OnProfileChange, ProfileChanged.Priority.CustomizePlusIpc);
_armatureChangedEvent.Subscribe(OnArmatureChanged, ArmatureChanged.Priority.CustomizePlusIpc);
}
public void Dispose()
{
- _profileChangedEvent.Unsubscribe(OnProfileChange);
_armatureChangedEvent.Unsubscribe(OnArmatureChanged);
}
}
diff --git a/CustomizePlus/Armatures/Data/Armature.cs b/CustomizePlus/Armatures/Data/Armature.cs
index 479defe..6d5e87e 100644
--- a/CustomizePlus/Armatures/Data/Armature.cs
+++ b/CustomizePlus/Armatures/Data/Armature.cs
@@ -200,7 +200,7 @@ public unsafe class Armature
_partialSkeletons = newPartials.Select(x => x.ToArray()).ToArray();
- RebuildBoneTemplateBinding();
+ RebuildBoneTemplateBinding(); //todo: intentionally not calling ArmatureChanged.Type.Updated because this is pending rewrite
Plugin.Logger.Debug($"Rebuilt {this}");
}
@@ -237,7 +237,7 @@ public unsafe class Armature
_partialSkeletons = oldPartials.Select(x => x.ToArray()).ToArray();
- RebuildBoneTemplateBinding();
+ RebuildBoneTemplateBinding(); //todo: intentionally not calling ArmatureChanged.Type.Updated because this is pending rewrite
Plugin.Logger.Debug($"Augmented {this} with new bones");
}
diff --git a/CustomizePlus/Armatures/Events/ArmatureChanged.cs b/CustomizePlus/Armatures/Events/ArmatureChanged.cs
index ae91d2c..c66fc1d 100644
--- a/CustomizePlus/Armatures/Events/ArmatureChanged.cs
+++ b/CustomizePlus/Armatures/Events/ArmatureChanged.cs
@@ -13,7 +13,10 @@ public sealed class ArmatureChanged() : EventWrapper
+ /// Called when armature was rebound to other profile or bone template bindings were rebuilt
+ ///
+ Updated
}
public enum Priority
diff --git a/CustomizePlus/Armatures/Services/ArmatureManager.cs b/CustomizePlus/Armatures/Services/ArmatureManager.cs
index 443cdec..ad305ca 100644
--- a/CustomizePlus/Armatures/Services/ArmatureManager.cs
+++ b/CustomizePlus/Armatures/Services/ArmatureManager.cs
@@ -163,28 +163,28 @@ public unsafe sealed class ArmatureManager : IDisposable
if (armature.IsPendingProfileRebind)
{
- _logger.Debug($"Armature {armature} is pending profile rebind, rebinding...");
+ _logger.Debug($"Armature {armature} is pending profile/bone rebind, rebinding...");
armature.IsPendingProfileRebind = false;
var activeProfile = GetProfileForActor(actorIdentifier);
- if (activeProfile == armature.Profile)
- continue;
-
- if (activeProfile == null)
+ Profile? oldProfile = armature.Profile;
+ if (activeProfile != armature.Profile)
{
- _logger.Debug($"Removing armature {armature} because it doesn't have any active profiles");
- RemoveArmature(armature, ArmatureChanged.DeletionReason.NoActiveProfiles);
- continue;
+ if (activeProfile == null)
+ {
+ _logger.Debug($"Removing armature {armature} because it doesn't have any active profiles");
+ RemoveArmature(armature, ArmatureChanged.DeletionReason.NoActiveProfiles);
+ continue;
+ }
+
+ armature.Profile.Armatures.Remove(armature);
+ armature.Profile = activeProfile;
+ activeProfile.Armatures.Add(armature);
}
- Profile oldProfile = armature.Profile;
-
- armature.Profile.Armatures.Remove(armature);
- armature.Profile = activeProfile;
- activeProfile.Armatures.Add(armature);
armature.RebuildBoneTemplateBinding();
- _event.Invoke(ArmatureChanged.Type.Rebound, armature, activeProfile);
+ _event.Invoke(ArmatureChanged.Type.Updated, armature, (activeProfile, oldProfile));
}
//Needed because skeleton sometimes appears to be not ready when armature is created
@@ -379,7 +379,7 @@ public unsafe sealed class ArmatureManager : IDisposable
if (!profile.Enabled || profile.Armatures.Count == 0)
continue;
- profile.Armatures.ForEach(x => x.RebuildBoneTemplateBinding());
+ profile.Armatures.ForEach(x => x.IsPendingProfileRebind = true);
}
});
@@ -548,7 +548,7 @@ public unsafe sealed class ArmatureManager : IDisposable
_logger.Debug($"ArmatureManager.OnProfileChange Added/Deleted/Moved/Changed template: {type}, data payload: {arg3?.ToString()}, profile: {profile.Name}->{profile.Enabled}->{profile.Armatures.Count} armatures");
- profile!.Armatures.ForEach(x => x.RebuildBoneTemplateBinding());
+ profile!.Armatures.ForEach(x => x.IsPendingProfileRebind = true);
}
private IEnumerable GetArmaturesForCharacterName(string characterName)
diff --git a/CustomizePlus/Profiles/Events/ProfileChanged.cs b/CustomizePlus/Profiles/Events/ProfileChanged.cs
index 0655b2c..f8c1b81 100644
--- a/CustomizePlus/Profiles/Events/ProfileChanged.cs
+++ b/CustomizePlus/Profiles/Events/ProfileChanged.cs
@@ -41,6 +41,6 @@ public sealed class ProfileChanged() : EventWrapper
/// Turn on editing of a specific template. If character name not set will default to local player.
///
- internal bool EnableEditor(Template template, string? characterName = null) //todo: editor is borked
+ internal bool EnableEditor(Template template, string? characterName = null)
{
if (IsEditorActive || IsEditorPaused)
return false;
diff --git a/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs b/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs
index f540652..cf406df 100644
--- a/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs
+++ b/CustomizePlus/UI/Windows/MainWindow/Tabs/Profiles/ProfilePanel.cs
@@ -11,6 +11,7 @@ using CustomizePlus.Game.Services;
using CustomizePlus.Configuration.Data;
using CustomizePlus.Profiles.Data;
using CustomizePlus.UI.Windows.Controls;
+using CustomizePlus.Templates;
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
@@ -20,6 +21,7 @@ public class ProfilePanel
private readonly ProfileManager _manager;
private readonly PluginConfiguration _configuration;
private readonly TemplateCombo _templateCombo;
+ private readonly TemplateEditorManager _templateEditorManager;
private string? _newName;
private string? _newCharacterName;
@@ -36,12 +38,14 @@ public class ProfilePanel
ProfileFileSystemSelector selector,
ProfileManager manager,
PluginConfiguration configuration,
- TemplateCombo templateCombo)
+ TemplateCombo templateCombo,
+ TemplateEditorManager templateEditorManager)
{
_selector = selector;
_manager = manager;
_configuration = configuration;
_templateCombo = templateCombo;
+ _templateEditorManager = templateEditorManager;
}
public void Draw()
@@ -139,8 +143,11 @@ public class ProfilePanel
using (var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing))
{
var enabled = _selector.Selected?.Enabled ?? false;
- if (ImGui.Checkbox("##Enabled", ref enabled))
- _manager.SetEnabled(_selector.Selected!, enabled);
+ using (ImRaii.Disabled(_templateEditorManager.IsEditorActive || _templateEditorManager.IsEditorPaused))
+ {
+ 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.");