Skip to content

Commit

Permalink
Send IPC OnProfileUpdate when currently used template was changed in …
Browse files Browse the repository at this point in the history
…editor, fix Profile.GetActiveProfileIdOnCharacter IPC ignoring DefaultLocalPlayerProfile
  • Loading branch information
RisaDev committed Nov 23, 2024
1 parent 4ee6220 commit e4e10e0
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 14 deletions.
34 changes: 33 additions & 1 deletion CustomizePlus/Api/CustomizePlusIpc.Profile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
using Dalamud.Game.ClientState.Objects.Types;
using Penumbra.GameData.Structs;
using Penumbra.GameData.Enums;
using CustomizePlus.Templates.Data;
using CustomizePlus.Templates.Events;
using Penumbra.GameData.Actors;

namespace CustomizePlus.Api;

Expand Down Expand Up @@ -144,7 +147,7 @@ private ErrorCode SetProfileStateInternal(Guid uniqueId, bool state)
if (actor == null || !actor.Value.Valid || !actor.Value.IsCharacter)
return ((int)ErrorCode.InvalidCharacter, null);

var profile = _profileManager.GetProfileByActor(actor.Value, true);
var profile = _profileManager.GetActiveProfileByActor(actor.Value);

if (profile == null)
return ((int)ErrorCode.ProfileNotFound, null);
Expand Down Expand Up @@ -268,6 +271,35 @@ private int DeleteTemporaryProfileByUniqueId(Guid uniqueId)
}
}

//Send profile update if any of the templates were changed in currently active profile
private void OnTemplateChanged(TemplateChanged.Type type, Template? template, object? arg3)
{
if (type != TemplateChanged.Type.EditorDisabled)
return;

(ActorIdentifier actorIdentifier, bool hasChanges) = ((ActorIdentifier, bool))arg3;

if (!hasChanges || actorIdentifier.Type != IdentifierType.Player)
return;

var actor = _gameObjectService.GetLocalPlayerActor();
if (!actor.Valid || !actorIdentifier.PlayerName.EqualsCi(actor.Utf8Name))
return;

var profile = _profileManager.GetActiveProfileByActor(actor);
if (profile == null) //safety check
return;

if (!profile.Templates.Contains(template!))
return;

ICharacter? localPlayerCharacter = (ICharacter?)_gameObjectService.GetDalamudGameObjectFromActor(actor);
if (localPlayerCharacter == null)
return;

OnProfileUpdateInternal(localPlayerCharacter, profile);
}

//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)
{
Expand Down
9 changes: 8 additions & 1 deletion CustomizePlus/Api/CustomizePlusIpc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using CustomizePlus.GameData.Services;
using CustomizePlus.Profiles;
using CustomizePlus.Profiles.Events;
using CustomizePlus.Templates.Data;
using CustomizePlus.Templates.Events;
using Dalamud.Plugin;
using ECommonsLite.EzIpcManager;
using OtterGui.Log;
Expand All @@ -29,6 +31,7 @@ public partial class CustomizePlusIpc : IDisposable
private readonly CutsceneService _cutsceneService;

private readonly ArmatureChanged _armatureChangedEvent;
private readonly TemplateChanged _templateChangedEvent;

/// <summary>
/// Shows if IPC failed to initialize or any other unrecoverable fatal error occured.
Expand All @@ -43,7 +46,8 @@ public CustomizePlusIpc(
GameObjectService gameObjectService,
ProfileFileSystem profileFileSystem,
CutsceneService cutsceneService,
ArmatureChanged armatureChangedEvent)
ArmatureChanged armatureChangedEvent,
TemplateChanged templateChangedEvent)
{
_pluginInterface = pluginInterface;
_logger = logger;
Expand All @@ -54,14 +58,17 @@ public CustomizePlusIpc(
_cutsceneService = cutsceneService;

_armatureChangedEvent = armatureChangedEvent;
_templateChangedEvent = templateChangedEvent;

EzIPC.Init(this, "CustomizePlus");

_armatureChangedEvent.Subscribe(OnArmatureChanged, ArmatureChanged.Priority.CustomizePlusIpc);
_templateChangedEvent.Subscribe(OnTemplateChanged, TemplateChanged.Priority.CustomizePlusIpc);
}

public void Dispose()
{
_armatureChangedEvent.Unsubscribe(OnArmatureChanged);
_templateChangedEvent.Unsubscribe(OnTemplateChanged);
}
}
10 changes: 9 additions & 1 deletion CustomizePlus/Armatures/Services/ArmatureManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,15 @@ type is not TemplateChanged.Type.EditorEnabled &&
if (type == TemplateChanged.Type.EditorEnabled ||
type == TemplateChanged.Type.EditorDisabled)
{
foreach (var armature in GetArmaturesForCharacter((ActorIdentifier)arg3!))
ActorIdentifier actor;
bool hasChanges;

if(type == TemplateChanged.Type.EditorEnabled)
actor = (ActorIdentifier)arg3;
else
(actor, hasChanges) = ((ActorIdentifier, bool))arg3;

foreach (var armature in GetArmaturesForCharacter(actor))
{
armature.IsPendingProfileRebind = true;
_logger.Debug($"ArmatureManager.OnTemplateChange template editor enabled/disabled: {type}, pending profile set for {armature}");
Expand Down
14 changes: 9 additions & 5 deletions CustomizePlus/Profiles/ProfileManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,8 @@ public void RemoveTemporaryProfile(Actor actor)
/// <summary>
/// Return profile by actor identifier, does not return temporary profiles.
/// </summary>
public Profile? GetProfileByActor(Actor actor, bool enabledOnly = false)
/// todo: use GetEnabledProfilesByActor
public Profile? GetActiveProfileByActor(Actor actor)
{
var actorIdentifier = actor.GetIdentifier(_actorManager);

Expand All @@ -442,14 +443,17 @@ public void RemoveTemporaryProfile(Actor actor)
if (actorIdentifier.Type == IdentifierType.Owned && !actorIdentifier.IsOwnedByLocalPlayer())
return null;

var query = Profiles.Where(p => p.Characters.Any(x => x.MatchesIgnoringOwnership(actorIdentifier)) && !p.IsTemporary);
if (enabledOnly)
query = query.Where(x => x.Enabled);
var query = Profiles.Where(p => p.Characters.Any(x => x.MatchesIgnoringOwnership(actorIdentifier)) && !p.IsTemporary && p.Enabled);

var profile = query.OrderByDescending(x => x.Priority).FirstOrDefault();

if (profile == null)
if(profile == null)
{
if (DefaultLocalPlayerProfile?.Enabled == true)
return DefaultLocalPlayerProfile;

return null;
}

return profile;
}
Expand Down
23 changes: 21 additions & 2 deletions CustomizePlus/Templates/TemplateEditorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using CustomizePlus.Templates.Data;
using CustomizePlus.Templates.Events;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Classes;
using OtterGui.Log;
Expand Down Expand Up @@ -160,28 +161,46 @@ internal bool DisableEditor()

_logger.Debug($"Disabling editor profile");

//todo: can be optimized by storing actual reference to original template somewhere
var template = _templateManager.GetTemplate(CurrentlyEditedTemplateId);
var hasChanges = HasChanges;

CurrentlyEditedTemplateId = Guid.Empty;
CurrentlyEditedTemplate = null;
EditorProfile.Enabled = false;
EditorProfile.Templates.Clear();
IsEditorActive = false;
HasChanges = false;

_event.Invoke(TemplateChanged.Type.EditorDisabled, null, Character);
_event.Invoke(TemplateChanged.Type.EditorDisabled, template, (Character, hasChanges));

return true;
}

public void SaveChanges(bool asCopy = false)
public void SaveChangesAndDisableEditor(bool asCopy = false)
{
if (!IsEditorActive || IsEditorPaused)
return;

if(!HasChanges)
{
DisableEditor();
return;
}

var targetTemplate = _templateManager.GetTemplate(CurrentlyEditedTemplateId);
if (targetTemplate == null)
throw new Exception($"Fatal editor error: Template with ID {CurrentlyEditedTemplateId} not found in template manager");

if (asCopy)
{
targetTemplate = _templateManager.Clone(targetTemplate, $"{targetTemplate.Name} - Copy {Guid.NewGuid().ToString().Substring(0, 4)}", false);
HasChanges = false; //do this so EditorDisabled event sends proper info about the state of *currently edited* template
}

_templateManager.ApplyBoneChangesAndSave(targetTemplate, CurrentlyEditedTemplate!);

DisableEditor();
}

public bool ChangeEditorCharacter(ActorIdentifier character)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,17 +341,15 @@ private void DrawEditorConfirmationPopup()
ImGui.SetCursorPos(new Vector2(xPos, yPos));
if (ImGui.Button("Save", buttonWidth))
{
_editorManager.SaveChanges();
_editorManager.DisableEditor();
_editorManager.SaveChangesAndDisableEditor();

ImGui.CloseCurrentPopup();
}

ImGui.SameLine();
if (ImGui.Button("Save as a copy", buttonWidth))
{
_editorManager.SaveChanges(true);
_editorManager.DisableEditor();
_editorManager.SaveChangesAndDisableEditor(true);

ImGui.CloseCurrentPopup();
}
Expand Down

0 comments on commit e4e10e0

Please sign in to comment.