Skip to content

Commit e4e10e0

Browse files
committed
Send IPC OnProfileUpdate when currently used template was changed in editor, fix Profile.GetActiveProfileIdOnCharacter IPC ignoring DefaultLocalPlayerProfile
1 parent 4ee6220 commit e4e10e0

File tree

6 files changed

+82
-14
lines changed

6 files changed

+82
-14
lines changed

CustomizePlus/Api/CustomizePlusIpc.Profile.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
using Dalamud.Game.ClientState.Objects.Types;
1616
using Penumbra.GameData.Structs;
1717
using Penumbra.GameData.Enums;
18+
using CustomizePlus.Templates.Data;
19+
using CustomizePlus.Templates.Events;
20+
using Penumbra.GameData.Actors;
1821

1922
namespace CustomizePlus.Api;
2023

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

147-
var profile = _profileManager.GetProfileByActor(actor.Value, true);
150+
var profile = _profileManager.GetActiveProfileByActor(actor.Value);
148151

149152
if (profile == null)
150153
return ((int)ErrorCode.ProfileNotFound, null);
@@ -268,6 +271,35 @@ private int DeleteTemporaryProfileByUniqueId(Guid uniqueId)
268271
}
269272
}
270273

274+
//Send profile update if any of the templates were changed in currently active profile
275+
private void OnTemplateChanged(TemplateChanged.Type type, Template? template, object? arg3)
276+
{
277+
if (type != TemplateChanged.Type.EditorDisabled)
278+
return;
279+
280+
(ActorIdentifier actorIdentifier, bool hasChanges) = ((ActorIdentifier, bool))arg3;
281+
282+
if (!hasChanges || actorIdentifier.Type != IdentifierType.Player)
283+
return;
284+
285+
var actor = _gameObjectService.GetLocalPlayerActor();
286+
if (!actor.Valid || !actorIdentifier.PlayerName.EqualsCi(actor.Utf8Name))
287+
return;
288+
289+
var profile = _profileManager.GetActiveProfileByActor(actor);
290+
if (profile == null) //safety check
291+
return;
292+
293+
if (!profile.Templates.Contains(template!))
294+
return;
295+
296+
ICharacter? localPlayerCharacter = (ICharacter?)_gameObjectService.GetDalamudGameObjectFromActor(actor);
297+
if (localPlayerCharacter == null)
298+
return;
299+
300+
OnProfileUpdateInternal(localPlayerCharacter, profile);
301+
}
302+
271303
//warn: intended limitation - ignores default profiles because why you would use default profile on your own character
272304
private void OnArmatureChanged(ArmatureChanged.Type type, Armature armature, object? arg3)
273305
{

CustomizePlus/Api/CustomizePlusIpc.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using CustomizePlus.GameData.Services;
55
using CustomizePlus.Profiles;
66
using CustomizePlus.Profiles.Events;
7+
using CustomizePlus.Templates.Data;
8+
using CustomizePlus.Templates.Events;
79
using Dalamud.Plugin;
810
using ECommonsLite.EzIpcManager;
911
using OtterGui.Log;
@@ -29,6 +31,7 @@ public partial class CustomizePlusIpc : IDisposable
2931
private readonly CutsceneService _cutsceneService;
3032

3133
private readonly ArmatureChanged _armatureChangedEvent;
34+
private readonly TemplateChanged _templateChangedEvent;
3235

3336
/// <summary>
3437
/// Shows if IPC failed to initialize or any other unrecoverable fatal error occured.
@@ -43,7 +46,8 @@ public CustomizePlusIpc(
4346
GameObjectService gameObjectService,
4447
ProfileFileSystem profileFileSystem,
4548
CutsceneService cutsceneService,
46-
ArmatureChanged armatureChangedEvent)
49+
ArmatureChanged armatureChangedEvent,
50+
TemplateChanged templateChangedEvent)
4751
{
4852
_pluginInterface = pluginInterface;
4953
_logger = logger;
@@ -54,14 +58,17 @@ public CustomizePlusIpc(
5458
_cutsceneService = cutsceneService;
5559

5660
_armatureChangedEvent = armatureChangedEvent;
61+
_templateChangedEvent = templateChangedEvent;
5762

5863
EzIPC.Init(this, "CustomizePlus");
5964

6065
_armatureChangedEvent.Subscribe(OnArmatureChanged, ArmatureChanged.Priority.CustomizePlusIpc);
66+
_templateChangedEvent.Subscribe(OnTemplateChanged, TemplateChanged.Priority.CustomizePlusIpc);
6167
}
6268

6369
public void Dispose()
6470
{
6571
_armatureChangedEvent.Unsubscribe(OnArmatureChanged);
72+
_templateChangedEvent.Unsubscribe(OnTemplateChanged);
6673
}
6774
}

CustomizePlus/Armatures/Services/ArmatureManager.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,15 @@ type is not TemplateChanged.Type.EditorEnabled &&
428428
if (type == TemplateChanged.Type.EditorEnabled ||
429429
type == TemplateChanged.Type.EditorDisabled)
430430
{
431-
foreach (var armature in GetArmaturesForCharacter((ActorIdentifier)arg3!))
431+
ActorIdentifier actor;
432+
bool hasChanges;
433+
434+
if(type == TemplateChanged.Type.EditorEnabled)
435+
actor = (ActorIdentifier)arg3;
436+
else
437+
(actor, hasChanges) = ((ActorIdentifier, bool))arg3;
438+
439+
foreach (var armature in GetArmaturesForCharacter(actor))
432440
{
433441
armature.IsPendingProfileRebind = true;
434442
_logger.Debug($"ArmatureManager.OnTemplateChange template editor enabled/disabled: {type}, pending profile set for {armature}");

CustomizePlus/Profiles/ProfileManager.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ public void RemoveTemporaryProfile(Actor actor)
432432
/// <summary>
433433
/// Return profile by actor identifier, does not return temporary profiles.
434434
/// </summary>
435-
public Profile? GetProfileByActor(Actor actor, bool enabledOnly = false)
435+
/// todo: use GetEnabledProfilesByActor
436+
public Profile? GetActiveProfileByActor(Actor actor)
436437
{
437438
var actorIdentifier = actor.GetIdentifier(_actorManager);
438439

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

445-
var query = Profiles.Where(p => p.Characters.Any(x => x.MatchesIgnoringOwnership(actorIdentifier)) && !p.IsTemporary);
446-
if (enabledOnly)
447-
query = query.Where(x => x.Enabled);
446+
var query = Profiles.Where(p => p.Characters.Any(x => x.MatchesIgnoringOwnership(actorIdentifier)) && !p.IsTemporary && p.Enabled);
448447

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

451-
if (profile == null)
450+
if(profile == null)
451+
{
452+
if (DefaultLocalPlayerProfile?.Enabled == true)
453+
return DefaultLocalPlayerProfile;
454+
452455
return null;
456+
}
453457

454458
return profile;
455459
}

CustomizePlus/Templates/TemplateEditorManager.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using CustomizePlus.Templates.Data;
1010
using CustomizePlus.Templates.Events;
1111
using Dalamud.Plugin.Services;
12+
using FFXIVClientStructs.FFXIV.Client.Game.Character;
1213
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
1314
using OtterGui.Classes;
1415
using OtterGui.Log;
@@ -160,28 +161,46 @@ internal bool DisableEditor()
160161

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

164+
//todo: can be optimized by storing actual reference to original template somewhere
165+
var template = _templateManager.GetTemplate(CurrentlyEditedTemplateId);
166+
var hasChanges = HasChanges;
167+
163168
CurrentlyEditedTemplateId = Guid.Empty;
164169
CurrentlyEditedTemplate = null;
165170
EditorProfile.Enabled = false;
166171
EditorProfile.Templates.Clear();
167172
IsEditorActive = false;
168173
HasChanges = false;
169174

170-
_event.Invoke(TemplateChanged.Type.EditorDisabled, null, Character);
175+
_event.Invoke(TemplateChanged.Type.EditorDisabled, template, (Character, hasChanges));
171176

172177
return true;
173178
}
174179

175-
public void SaveChanges(bool asCopy = false)
180+
public void SaveChangesAndDisableEditor(bool asCopy = false)
176181
{
182+
if (!IsEditorActive || IsEditorPaused)
183+
return;
184+
185+
if(!HasChanges)
186+
{
187+
DisableEditor();
188+
return;
189+
}
190+
177191
var targetTemplate = _templateManager.GetTemplate(CurrentlyEditedTemplateId);
178192
if (targetTemplate == null)
179193
throw new Exception($"Fatal editor error: Template with ID {CurrentlyEditedTemplateId} not found in template manager");
180194

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

184201
_templateManager.ApplyBoneChangesAndSave(targetTemplate, CurrentlyEditedTemplate!);
202+
203+
DisableEditor();
185204
}
186205

187206
public bool ChangeEditorCharacter(ActorIdentifier character)

CustomizePlus/UI/Windows/MainWindow/Tabs/Templates/BoneEditorPanel.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,17 +341,15 @@ private void DrawEditorConfirmationPopup()
341341
ImGui.SetCursorPos(new Vector2(xPos, yPos));
342342
if (ImGui.Button("Save", buttonWidth))
343343
{
344-
_editorManager.SaveChanges();
345-
_editorManager.DisableEditor();
344+
_editorManager.SaveChangesAndDisableEditor();
346345

347346
ImGui.CloseCurrentPopup();
348347
}
349348

350349
ImGui.SameLine();
351350
if (ImGui.Button("Save as a copy", buttonWidth))
352351
{
353-
_editorManager.SaveChanges(true);
354-
_editorManager.DisableEditor();
352+
_editorManager.SaveChangesAndDisableEditor(true);
355353

356354
ImGui.CloseCurrentPopup();
357355
}

0 commit comments

Comments
 (0)