Added ability to apply profile to several characters
This commit is contained in:
@@ -85,6 +85,23 @@ public static class ActorIdentifierExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string TypeToString(this ActorIdentifier identifier)
|
||||||
|
{
|
||||||
|
return identifier.Type switch
|
||||||
|
{
|
||||||
|
IdentifierType.Player => $" ({PenumbraExtensions.Manager?.Data.ToWorldName(identifier.HomeWorld) ?? "Unknown"})",
|
||||||
|
IdentifierType.Retainer => $"{identifier.Retainer switch
|
||||||
|
{
|
||||||
|
ActorIdentifier.RetainerType.Bell => " (Bell)",
|
||||||
|
ActorIdentifier.RetainerType.Mannequin => " (Mannequin)",
|
||||||
|
_ => " (Retainer)",
|
||||||
|
}}",
|
||||||
|
IdentifierType.Owned => " (Companion/Mount)",
|
||||||
|
IdentifierType.Npc => " (NPC)",
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For now used to determine if root scaling should be allowed or not
|
/// For now used to determine if root scaling should be allowed or not
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public partial class CustomizePlusIpc
|
|||||||
.Select(x =>
|
.Select(x =>
|
||||||
{
|
{
|
||||||
string path = _profileFileSystem.FindLeaf(x, out var leaf) ? leaf.FullName() : x.Name.Text;
|
string path = _profileFileSystem.FindLeaf(x, out var leaf) ? leaf.FullName() : x.Name.Text;
|
||||||
return (x.UniqueId, x.Name.Text, path, x.Character.ToNameWithoutOwnerName(), x.Enabled); //todo: proper update to v5
|
return (x.UniqueId, x.Name.Text, path, x.Characters[0].ToNameWithoutOwnerName(), x.Enabled); //todo: proper update to v5
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class IPCCharacterProfile
|
|||||||
{
|
{
|
||||||
var ipcProfile = new IPCCharacterProfile
|
var ipcProfile = new IPCCharacterProfile
|
||||||
{
|
{
|
||||||
CharacterName = profile.Character.ToNameWithoutOwnerName(),
|
CharacterName = profile.Characters.FirstOrDefault().ToNameWithoutOwnerName(),
|
||||||
Bones = new Dictionary<string, IPCBoneTransform>()
|
Bones = new Dictionary<string, IPCBoneTransform>()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -411,7 +411,8 @@ public unsafe sealed class ArmatureManager : IDisposable
|
|||||||
type is not ProfileChanged.Type.Deleted &&
|
type is not ProfileChanged.Type.Deleted &&
|
||||||
type is not ProfileChanged.Type.TemporaryProfileAdded &&
|
type is not ProfileChanged.Type.TemporaryProfileAdded &&
|
||||||
type is not ProfileChanged.Type.TemporaryProfileDeleted &&
|
type is not ProfileChanged.Type.TemporaryProfileDeleted &&
|
||||||
type is not ProfileChanged.Type.ChangedCharacter &&
|
type is not ProfileChanged.Type.AddedCharacter &&
|
||||||
|
type is not ProfileChanged.Type.RemovedCharacter &&
|
||||||
type is not ProfileChanged.Type.ChangedDefaultProfile &&
|
type is not ProfileChanged.Type.ChangedDefaultProfile &&
|
||||||
type is not ProfileChanged.Type.ChangedDefaultLocalPlayerProfile)
|
type is not ProfileChanged.Type.ChangedDefaultLocalPlayerProfile)
|
||||||
return;
|
return;
|
||||||
@@ -456,23 +457,23 @@ public unsafe sealed class ArmatureManager : IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.Character.IsValid)
|
foreach(var character in profile.Characters)
|
||||||
return;
|
{
|
||||||
|
if (!character.IsValid)
|
||||||
|
continue;
|
||||||
|
|
||||||
foreach (var armature in GetArmaturesForCharacter(profile.Character))
|
foreach (var armature in GetArmaturesForCharacter(character))
|
||||||
{
|
{
|
||||||
armature.IsPendingProfileRebind = true;
|
armature.IsPendingProfileRebind = true;
|
||||||
_logger.Debug($"ArmatureManager.OnProfileChange profile {profile} toggled, planning rebind for armature {armature}");
|
_logger.Debug($"ArmatureManager.OnProfileChange profile {profile} toggled, planning rebind for armature {armature}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ProfileChanged.Type.TemporaryProfileAdded)
|
if (type == ProfileChanged.Type.TemporaryProfileAdded)
|
||||||
{
|
{
|
||||||
if (!profile.Character.IsValid || !Armatures.ContainsKey(profile.Character)) //temporary profiles are never using AnyWorld identifiers so we should be fine here
|
|
||||||
return;
|
|
||||||
|
|
||||||
//todo: remove this later
|
//todo: remove this later
|
||||||
/*Armature? armature = null;
|
/*Armature? armature = null;
|
||||||
foreach(var kvPair in Armatures)
|
foreach(var kvPair in Armatures)
|
||||||
@@ -489,7 +490,12 @@ public unsafe sealed class ArmatureManager : IDisposable
|
|||||||
if (armature == null)
|
if (armature == null)
|
||||||
return;*/
|
return;*/
|
||||||
|
|
||||||
var armature = Armatures[profile.Character];
|
foreach(var character in profile.Characters)
|
||||||
|
{
|
||||||
|
if (!character.IsValid || !Armatures.ContainsKey(character))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var armature = Armatures[character];
|
||||||
|
|
||||||
if (armature.Profile == profile)
|
if (armature.Profile == profile)
|
||||||
return;
|
return;
|
||||||
@@ -497,13 +503,15 @@ public unsafe sealed class ArmatureManager : IDisposable
|
|||||||
armature.UpdateLastSeen();
|
armature.UpdateLastSeen();
|
||||||
|
|
||||||
armature.IsPendingProfileRebind = true;
|
armature.IsPendingProfileRebind = true;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Debug($"ArmatureManager.OnProfileChange TemporaryProfileAdded, calling rebind for existing armature: {type}, data payload: {arg3?.ToString()}, profile: {profile.Name.Text.Incognify()}->{profile.Enabled}");
|
_logger.Debug($"ArmatureManager.OnProfileChange TemporaryProfileAdded, calling rebind for existing armature: {type}, data payload: {arg3?.ToString()}, profile: {profile.Name.Text.Incognify()}->{profile.Enabled}");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == ProfileChanged.Type.ChangedCharacter ||
|
if (type == ProfileChanged.Type.AddedCharacter ||
|
||||||
|
type == ProfileChanged.Type.RemovedCharacter ||
|
||||||
type == ProfileChanged.Type.Deleted ||
|
type == ProfileChanged.Type.Deleted ||
|
||||||
type == ProfileChanged.Type.TemporaryProfileDeleted)
|
type == ProfileChanged.Type.TemporaryProfileDeleted)
|
||||||
{
|
{
|
||||||
@@ -518,7 +526,7 @@ public unsafe sealed class ArmatureManager : IDisposable
|
|||||||
armature.IsPendingProfileRebind = true;
|
armature.IsPendingProfileRebind = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug($"ArmatureManager.OnProfileChange CC/DEL/TPD/ATCACC, armature rebind scheduled: {type}, data payload: {arg3?.ToString()?.Incognify()}, profile: {profile.Name.Text.Incognify()}->{profile.Enabled}");
|
_logger.Debug($"ArmatureManager.OnProfileChange AC/RC/DEL/TPD/ATCACC, armature rebind scheduled: {type}, data payload: {arg3?.ToString()?.Incognify()}, profile: {profile.Name.Text.Incognify()}->{profile.Enabled}");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,10 +183,10 @@ public class CommandService : IDisposable
|
|||||||
if (!isTurningOffAllProfiles)
|
if (!isTurningOffAllProfiles)
|
||||||
{
|
{
|
||||||
profileName = subArgumentList[1].Trim();
|
profileName = subArgumentList[1].Trim();
|
||||||
targetProfile = _profileManager.Profiles.FirstOrDefault(x => x.Name == profileName && x.Character.ToNameWithoutOwnerName() == characterName);
|
targetProfile = _profileManager.Profiles.FirstOrDefault(x => x.Name == profileName && x.Characters.Any(x => x.ToNameWithoutOwnerName() == characterName));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
targetProfile = _profileManager.Profiles.FirstOrDefault(x => x.Character.ToNameWithoutOwnerName() == characterName && x.Enabled);
|
targetProfile = _profileManager.Profiles.FirstOrDefault(x => x.Characters.Any(x => x.ToNameWithoutOwnerName() == characterName) && x.Enabled);
|
||||||
|
|
||||||
if (targetProfile == null)
|
if (targetProfile == null)
|
||||||
{
|
{
|
||||||
@@ -225,7 +225,7 @@ public class CommandService : IDisposable
|
|||||||
.AddText(" was successfully ")
|
.AddText(" was successfully ")
|
||||||
.AddBlue(state != null ? ((bool)state ? "enabled" : "disabled") : "toggled")
|
.AddBlue(state != null ? ((bool)state ? "enabled" : "disabled") : "toggled")
|
||||||
.AddText(" for ")
|
.AddText(" for ")
|
||||||
.AddRed(targetProfile.Character.ToNameWithoutOwnerName()).BuiltString);
|
.AddRed(string.Join(',', targetProfile.Characters.Select(x => x.ToNameWithoutOwnerName()))).BuiltString);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class SupportLogBuilderService
|
|||||||
sb.Append($"> > **`{profile.ToString(),-32}`*\n");
|
sb.Append($"> > **`{profile.ToString(),-32}`*\n");
|
||||||
sb.Append($"> > **`Name: `** {profile.Name.Text.Incognify()}\n");
|
sb.Append($"> > **`Name: `** {profile.Name.Text.Incognify()}\n");
|
||||||
sb.Append($"> > **`Type: `** {profile.ProfileType} \n");
|
sb.Append($"> > **`Type: `** {profile.ProfileType} \n");
|
||||||
sb.Append($"> > **`Character name: `** {profile.Character.Incognito(null)}\n");
|
sb.Append($"> > **`Characters: `** {string.Join(',', profile.Characters.Select(x => x.Incognito(null)))}\n");
|
||||||
sb.Append($"> > **`Templates:`**\n");
|
sb.Append($"> > **`Templates:`**\n");
|
||||||
sb.Append($"> > > **`Count: `** {profile.Templates.Count}\n");
|
sb.Append($"> > > **`Count: `** {profile.Templates.Count}\n");
|
||||||
foreach (var template in profile.Templates)
|
foreach (var template in profile.Templates)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using CustomizePlus.Armatures.Data;
|
using CustomizePlus.Armatures.Data;
|
||||||
using CustomizePlus.Core.Data;
|
using CustomizePlus.Core.Data;
|
||||||
using CustomizePlus.Core.Extensions;
|
using CustomizePlus.Core.Extensions;
|
||||||
@@ -32,7 +33,8 @@ public sealed class Profile : ISavable
|
|||||||
/* [Obsolete("To be removed in the future versions")]
|
/* [Obsolete("To be removed in the future versions")]
|
||||||
public LowerString CharacterName { get; set; } = LowerString.Empty;*/
|
public LowerString CharacterName { get; set; } = LowerString.Empty;*/
|
||||||
|
|
||||||
public ActorIdentifier Character { get; set; } = ActorIdentifier.Invalid;
|
//public ActorIdentifier Character { get; set; } = ActorIdentifier.Invalid;
|
||||||
|
public List<ActorIdentifier> Characters { get; set; } = new();
|
||||||
|
|
||||||
public LowerString Name { get; set; } = LowerString.Empty;
|
public LowerString Name { get; set; } = LowerString.Empty;
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ public sealed class Profile : ISavable
|
|||||||
/// <param name="original"></param>
|
/// <param name="original"></param>
|
||||||
public Profile(Profile original) : this()
|
public Profile(Profile original) : this()
|
||||||
{
|
{
|
||||||
Character = original.Character;
|
Characters = original.Characters.ToList();
|
||||||
|
|
||||||
foreach (var template in original.Templates)
|
foreach (var template in original.Templates)
|
||||||
{
|
{
|
||||||
@@ -88,7 +90,7 @@ public sealed class Profile : ISavable
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"Profile '{Name.Text.Incognify()}' on {Character.Incognito(null)} [{UniqueId}]";
|
return $"Profile '{Name.Text.Incognify()}' on {string.Join(',', Characters.Select(x => x.Incognito(null)))} [{UniqueId}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Serialization
|
#region Serialization
|
||||||
@@ -101,7 +103,7 @@ public sealed class Profile : ISavable
|
|||||||
["UniqueId"] = UniqueId,
|
["UniqueId"] = UniqueId,
|
||||||
["CreationDate"] = CreationDate,
|
["CreationDate"] = CreationDate,
|
||||||
["ModifiedDate"] = ModifiedDate,
|
["ModifiedDate"] = ModifiedDate,
|
||||||
["Character"] = Character.ToJson(),
|
["Characters"] = SerializeCharacters(),
|
||||||
["Name"] = Name.Text,
|
["Name"] = Name.Text,
|
||||||
["Enabled"] = Enabled,
|
["Enabled"] = Enabled,
|
||||||
["IsWriteProtected"] = IsWriteProtected,
|
["IsWriteProtected"] = IsWriteProtected,
|
||||||
@@ -124,6 +126,16 @@ public sealed class Profile : ISavable
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JArray SerializeCharacters()
|
||||||
|
{
|
||||||
|
var ret = new JArray();
|
||||||
|
foreach (var character in Characters)
|
||||||
|
{
|
||||||
|
ret.Add(character.ToJson());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
//Loading is in ProfileManager
|
//Loading is in ProfileManager
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ public sealed class ProfileChanged() : EventWrapper<ProfileChanged.Type, Profile
|
|||||||
Deleted,
|
Deleted,
|
||||||
Renamed,
|
Renamed,
|
||||||
Toggled,
|
Toggled,
|
||||||
ChangedCharacter,
|
AddedCharacter,
|
||||||
|
RemovedCharacter,
|
||||||
|
//ChangedCharacter,
|
||||||
AddedTemplate,
|
AddedTemplate,
|
||||||
RemovedTemplate,
|
RemovedTemplate,
|
||||||
MovedTemplate,
|
MovedTemplate,
|
||||||
|
|||||||
@@ -101,30 +101,30 @@ public partial class ProfileManager : IDisposable
|
|||||||
var nameWordsCnt = characterName.Split(' ').Length;
|
var nameWordsCnt = characterName.Split(' ').Length;
|
||||||
|
|
||||||
if (_reverseNameDicts.TryGetID(ObjectKind.EventNpc, characterName, out var id))
|
if (_reverseNameDicts.TryGetID(ObjectKind.EventNpc, characterName, out var id))
|
||||||
profile.Character = _actorManager.CreateNpc(ObjectKind.EventNpc, new NpcId(id));
|
profile.Characters.Add(_actorManager.CreateNpc(ObjectKind.EventNpc, new NpcId(id)));
|
||||||
else if (_reverseNameDicts.TryGetID(ObjectKind.BattleNpc, characterName, out id))
|
else if (_reverseNameDicts.TryGetID(ObjectKind.BattleNpc, characterName, out id))
|
||||||
profile.Character = _actorManager.CreateNpc(ObjectKind.BattleNpc, new NpcId(id));
|
profile.Characters.Add(_actorManager.CreateNpc(ObjectKind.BattleNpc, new NpcId(id)));
|
||||||
else if (_reverseNameDicts.TryGetID(ObjectKind.MountType, characterName, out id))
|
else if (_reverseNameDicts.TryGetID(ObjectKind.MountType, characterName, out id))
|
||||||
{
|
{
|
||||||
var currentPlayer = _actorManager.GetCurrentPlayer();
|
var currentPlayer = _actorManager.GetCurrentPlayer();
|
||||||
profile.Character = _actorManager.CreateOwned(currentPlayer.PlayerName, currentPlayer.HomeWorld, ObjectKind.MountType, new NpcId(id));
|
profile.Characters.Add(_actorManager.CreateOwned(currentPlayer.PlayerName, currentPlayer.HomeWorld, ObjectKind.MountType, new NpcId(id)));
|
||||||
}
|
}
|
||||||
else if (_reverseNameDicts.TryGetID(ObjectKind.Companion, characterName, out id))
|
else if (_reverseNameDicts.TryGetID(ObjectKind.Companion, characterName, out id))
|
||||||
{
|
{
|
||||||
var currentPlayer = _actorManager.GetCurrentPlayer();
|
var currentPlayer = _actorManager.GetCurrentPlayer();
|
||||||
profile.Character = _actorManager.CreateOwned(currentPlayer.PlayerName, currentPlayer.HomeWorld, ObjectKind.Companion, new NpcId(id));
|
profile.Characters.Add(_actorManager.CreateOwned(currentPlayer.PlayerName, currentPlayer.HomeWorld, ObjectKind.Companion, new NpcId(id)));
|
||||||
}
|
}
|
||||||
else if (nameWordsCnt == 2)
|
else if (nameWordsCnt == 2)
|
||||||
profile.Character = _actorManager.CreatePlayer(ByteString.FromStringUnsafe(characterName, false), WorldId.AnyWorld);
|
profile.Characters.Add(_actorManager.CreatePlayer(ByteString.FromStringUnsafe(characterName, false), WorldId.AnyWorld));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to automatically migrate \"{profile.Name}\" to V5, unknown character name: {characterName}");
|
_logger.Warning($"Unable to automatically migrate \"{profile.Name}\" to V5, unknown character name: {characterName}");
|
||||||
_messageService.NotificationMessage($"Unable to detect character type for profile \"{profile.Name}\", please set character for this profile manually.", Dalamud.Interface.ImGuiNotification.NotificationType.Error);
|
_messageService.NotificationMessage($"Unable to detect character type for profile \"{profile.Name}\", please set character for this profile manually.", Dalamud.Interface.ImGuiNotification.NotificationType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile.Character.IsValid)
|
if (profile.Characters.Count > 0)
|
||||||
{
|
{
|
||||||
_logger.Debug($"Upgraded profile \"{profile.Name}\" to V5: {characterName} -> {profile.Character}. Save queued.");
|
_logger.Debug($"Upgraded profile \"{profile.Name}\" to V5: {characterName} -> {profile.Characters[0]}. Save queued.");
|
||||||
_saveService.QueueSave(profile);
|
_saveService.QueueSave(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,14 +135,32 @@ public partial class ProfileManager : IDisposable
|
|||||||
{
|
{
|
||||||
var profile = LoadProfileV4V5(obj);
|
var profile = LoadProfileV4V5(obj);
|
||||||
|
|
||||||
var character = _actorManager.FromJson(obj["Character"] as JObject);
|
if (obj["Characters"] is not JArray characterArray)
|
||||||
|
return profile;
|
||||||
|
|
||||||
profile.Character = character;
|
foreach(var characterObj in characterArray)
|
||||||
|
{
|
||||||
|
if (characterObj is not JObject characterObjCast)
|
||||||
|
{
|
||||||
|
//todo: warning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var character = _actorManager.FromJson(characterObjCast);
|
||||||
|
|
||||||
|
if(!character.IsValid)
|
||||||
|
{
|
||||||
|
//todo: warning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.Characters.Add(character);
|
||||||
|
}
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
//V4 and V5 are mostly not different, so common loading logic is here
|
//V4 and V5 are mostly the same, so common loading logic is here
|
||||||
private Profile LoadProfileV4V5(JObject obj)
|
private Profile LoadProfileV4V5(JObject obj)
|
||||||
{
|
{
|
||||||
var creationDate = obj["CreationDate"]?.ToObject<DateTimeOffset>() ?? throw new ArgumentNullException("CreationDate");
|
var creationDate = obj["CreationDate"]?.ToObject<DateTimeOffset>() ?? throw new ArgumentNullException("CreationDate");
|
||||||
|
|||||||
@@ -177,15 +177,14 @@ public partial class ProfileManager : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change character associated with profile
|
/// Add character to profile
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ChangeCharacter(Profile profile, ActorIdentifier actorIdentifier)
|
public void AddCharacter(Profile profile, ActorIdentifier actorIdentifier)
|
||||||
{
|
{
|
||||||
if (!actorIdentifier.IsValid || actorIdentifier.MatchesIgnoringOwnership(profile.Character))
|
if (!actorIdentifier.IsValid || profile.Characters.Any(x => actorIdentifier.MatchesIgnoringOwnership(x)) || profile.IsTemporary)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldCharacter = profile.Character;
|
profile.Characters.Add(actorIdentifier);
|
||||||
profile.Character = actorIdentifier;
|
|
||||||
|
|
||||||
//Called so all other active profiles for new character name get disabled
|
//Called so all other active profiles for new character name get disabled
|
||||||
//saving is performed there
|
//saving is performed there
|
||||||
@@ -193,8 +192,28 @@ public partial class ProfileManager : IDisposable
|
|||||||
|
|
||||||
SaveProfile(profile);
|
SaveProfile(profile);
|
||||||
|
|
||||||
_logger.Debug($"Changed character for profile {profile.UniqueId}.");
|
_logger.Debug($"Add character for profile {profile.UniqueId}.");
|
||||||
_event.Invoke(ProfileChanged.Type.ChangedCharacter, profile, oldCharacter);
|
_event.Invoke(ProfileChanged.Type.AddedCharacter, profile, actorIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete character from profile
|
||||||
|
/// </summary>
|
||||||
|
public void DeleteCharacter(Profile profile, ActorIdentifier actorIdentifier)
|
||||||
|
{
|
||||||
|
if (!actorIdentifier.IsValid || !profile.Characters.Any(x => actorIdentifier.MatchesIgnoringOwnership(x)) || profile.IsTemporary)
|
||||||
|
return;
|
||||||
|
|
||||||
|
profile.Characters.Remove(actorIdentifier);
|
||||||
|
|
||||||
|
//Called so all other active profiles for new character name get disabled
|
||||||
|
//saving is performed there
|
||||||
|
//SetEnabled(profile, profile.Enabled, true); //todo
|
||||||
|
|
||||||
|
SaveProfile(profile);
|
||||||
|
|
||||||
|
_logger.Debug($"Removed character from profile {profile.UniqueId}.");
|
||||||
|
_event.Invoke(ProfileChanged.Type.RemovedCharacter, profile, actorIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -235,13 +254,36 @@ public partial class ProfileManager : IDisposable
|
|||||||
{
|
{
|
||||||
_logger.Debug($"Setting {profile} as enabled...");
|
_logger.Debug($"Setting {profile} as enabled...");
|
||||||
|
|
||||||
foreach (var otherProfile in Profiles
|
foreach (var otherProfile in Profiles)
|
||||||
.Where(x => x.Character.MatchesIgnoringOwnership(profile.Character) && x != profile && x.Enabled && !x.IsTemporary))
|
{
|
||||||
|
if (otherProfile == profile || !otherProfile.Enabled || otherProfile.IsTemporary)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool shouldDisable = false;
|
||||||
|
|
||||||
|
//my god this is ugly
|
||||||
|
foreach(var otherCharacter in otherProfile.Characters)
|
||||||
|
{
|
||||||
|
foreach(var currentCharacter in profile.Characters)
|
||||||
|
{
|
||||||
|
if(otherCharacter.MatchesIgnoringOwnership(currentCharacter))
|
||||||
|
{
|
||||||
|
shouldDisable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldDisable)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(shouldDisable)
|
||||||
{
|
{
|
||||||
_logger.Debug($"\t-> {otherProfile} disabled");
|
_logger.Debug($"\t-> {otherProfile} disabled");
|
||||||
SetEnabled(otherProfile, false);
|
SetEnabled(otherProfile, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (oldValue != value)
|
if (oldValue != value)
|
||||||
{
|
{
|
||||||
@@ -366,12 +408,15 @@ public partial class ProfileManager : IDisposable
|
|||||||
|
|
||||||
profile.Enabled = true;
|
profile.Enabled = true;
|
||||||
profile.ProfileType = ProfileType.Temporary;
|
profile.ProfileType = ProfileType.Temporary;
|
||||||
profile.Character = identifier.CreatePermanent(); //warn: identifier must not be AnyWorld or stuff will break!
|
|
||||||
|
|
||||||
var existingProfile = Profiles.FirstOrDefault(x => x.Character.MatchesIgnoringOwnership(profile.Character) && x.IsTemporary);
|
var permanentIdentifier = identifier.CreatePermanent();
|
||||||
|
profile.Characters.Clear();
|
||||||
|
profile.Characters.Add(permanentIdentifier); //warn: identifier must not be AnyWorld or stuff will break!
|
||||||
|
|
||||||
|
var existingProfile = Profiles.FirstOrDefault(p => p.Characters.Count == 1 && p.Characters[0].MatchesIgnoringOwnership(permanentIdentifier) && p.IsTemporary);
|
||||||
if (existingProfile != null)
|
if (existingProfile != null)
|
||||||
{
|
{
|
||||||
_logger.Debug($"Temporary profile for {existingProfile.Character.Incognito(null)} already exists, removing...");
|
_logger.Debug($"Temporary profile for {permanentIdentifier.Incognito(null)} already exists, removing...");
|
||||||
Profiles.Remove(existingProfile);
|
Profiles.Remove(existingProfile);
|
||||||
_event.Invoke(ProfileChanged.Type.TemporaryProfileDeleted, existingProfile, null);
|
_event.Invoke(ProfileChanged.Type.TemporaryProfileDeleted, existingProfile, null);
|
||||||
}
|
}
|
||||||
@@ -381,16 +426,19 @@ public partial class ProfileManager : IDisposable
|
|||||||
//Make sure temporary profiles come first, so they are returned by all other methods first
|
//Make sure temporary profiles come first, so they are returned by all other methods first
|
||||||
Profiles.Sort((x, y) => y.IsTemporary.CompareTo(x.IsTemporary));
|
Profiles.Sort((x, y) => y.IsTemporary.CompareTo(x.IsTemporary));
|
||||||
|
|
||||||
_logger.Debug($"Added temporary profile for {profile.Character}");
|
_logger.Debug($"Added temporary profile for {permanentIdentifier}");
|
||||||
_event.Invoke(ProfileChanged.Type.TemporaryProfileAdded, profile, null);
|
_event.Invoke(ProfileChanged.Type.TemporaryProfileAdded, profile, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveTemporaryProfile(Profile profile)
|
public void RemoveTemporaryProfile(Profile profile)
|
||||||
{
|
{
|
||||||
|
if (!profile.IsTemporary)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!Profiles.Remove(profile))
|
if (!Profiles.Remove(profile))
|
||||||
throw new ProfileNotFoundException();
|
throw new ProfileNotFoundException();
|
||||||
|
|
||||||
_logger.Debug($"Removed temporary profile for {profile.Character.Incognito(null)}");
|
_logger.Debug($"Removed temporary profile for {profile.Characters[0].Incognito(null)}");
|
||||||
|
|
||||||
_event.Invoke(ProfileChanged.Type.TemporaryProfileDeleted, profile, null);
|
_event.Invoke(ProfileChanged.Type.TemporaryProfileDeleted, profile, null);
|
||||||
}
|
}
|
||||||
@@ -409,7 +457,7 @@ public partial class ProfileManager : IDisposable
|
|||||||
if (!actor.Identifier(_actorManager, out var identifier))
|
if (!actor.Identifier(_actorManager, out var identifier))
|
||||||
throw new ActorNotFoundException();
|
throw new ActorNotFoundException();
|
||||||
|
|
||||||
var profile = Profiles.FirstOrDefault(x => x.Character == identifier && x.IsTemporary);
|
var profile = Profiles.FirstOrDefault(x => x.Characters[0] == identifier && x.IsTemporary);
|
||||||
if (profile == null)
|
if (profile == null)
|
||||||
throw new ProfileNotFoundException();
|
throw new ProfileNotFoundException();
|
||||||
|
|
||||||
@@ -426,7 +474,7 @@ public partial class ProfileManager : IDisposable
|
|||||||
if (!actorIdentifier.IsValid)
|
if (!actorIdentifier.IsValid)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var query = Profiles.Where(x => x.Character.MatchesIgnoringOwnership(actorIdentifier) && !x.IsTemporary);
|
var query = Profiles.Where(p => p.Characters.Any(x => x.MatchesIgnoringOwnership(actorIdentifier)) && !p.IsTemporary);
|
||||||
if (enabledOnly)
|
if (enabledOnly)
|
||||||
query = query.Where(x => x.Enabled);
|
query = query.Where(x => x.Enabled);
|
||||||
|
|
||||||
@@ -475,7 +523,7 @@ public partial class ProfileManager : IDisposable
|
|||||||
if (actorIdentifier.Type == IdentifierType.Owned && !actorIdentifier.IsOwnedByLocalPlayer())
|
if (actorIdentifier.Type == IdentifierType.Owned && !actorIdentifier.IsOwnedByLocalPlayer())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return profile.Character.MatchesIgnoringOwnership(actorIdentifier);
|
return profile.Characters.Any(x => x.MatchesIgnoringOwnership(actorIdentifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_templateEditorManager.IsEditorActive && _templateEditorManager.EditorProfile.Enabled && IsProfileAppliesToCurrentActor(_templateEditorManager.EditorProfile))
|
if (_templateEditorManager.IsEditorActive && _templateEditorManager.EditorProfile.Enabled && IsProfileAppliesToCurrentActor(_templateEditorManager.EditorProfile))
|
||||||
@@ -585,7 +633,7 @@ public partial class ProfileManager : IDisposable
|
|||||||
if (!Profiles.Remove(profile))
|
if (!Profiles.Remove(profile))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_logger.Debug($"ProfileManager.OnArmatureChange: Removed unused temporary profile for {profile.Character.Incognito(null)}");
|
_logger.Debug($"ProfileManager.OnArmatureChange: Removed unused temporary profile for {profile.Characters[0].Incognito(null)}");
|
||||||
|
|
||||||
_event.Invoke(ProfileChanged.Type.TemporaryProfileDeleted, profile, null);
|
_event.Invoke(ProfileChanged.Type.TemporaryProfileDeleted, profile, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class TemplateEditorManager : IDisposable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the preview character for the editor
|
/// Name of the preview character for the editor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ActorIdentifier Character => EditorProfile.Character;
|
public ActorIdentifier Character => EditorProfile.Characters[0];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if preview character exists at the time of call
|
/// Checks if preview character exists at the time of call
|
||||||
@@ -107,8 +107,9 @@ public class TemplateEditorManager : IDisposable
|
|||||||
Enabled = false,
|
Enabled = false,
|
||||||
Name = "Template editor profile",
|
Name = "Template editor profile",
|
||||||
ProfileType = ProfileType.Editor,
|
ProfileType = ProfileType.Editor,
|
||||||
Character = configuration.EditorConfiguration.PreviewCharacter
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EditorProfile.Characters.Add(configuration.EditorConfiguration.PreviewCharacter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -194,9 +195,10 @@ public class TemplateEditorManager : IDisposable
|
|||||||
|
|
||||||
private bool ChangeEditorCharacterInternal(ActorIdentifier character)
|
private bool ChangeEditorCharacterInternal(ActorIdentifier character)
|
||||||
{
|
{
|
||||||
_logger.Debug($"Changing character name for editor profile from {EditorProfile.Character.Incognito(null)} to {character.Incognito(null)}");
|
_logger.Debug($"Changing character name for editor profile from {EditorProfile.Characters.FirstOrDefault().Incognito(null)} to {character.Incognito(null)}");
|
||||||
|
|
||||||
EditorProfile.Character = character;
|
EditorProfile.Characters.Clear();
|
||||||
|
EditorProfile.Characters.Add(character);
|
||||||
|
|
||||||
_configuration.EditorConfiguration.PreviewCharacter = character;
|
_configuration.EditorConfiguration.PreviewCharacter = character;
|
||||||
_configuration.Save();
|
_configuration.Save();
|
||||||
|
|||||||
@@ -134,12 +134,11 @@ public class StateMonitoringTab
|
|||||||
private void DrawSingleProfile(string prefix, Profile profile)
|
private void DrawSingleProfile(string prefix, Profile profile)
|
||||||
{
|
{
|
||||||
string name = profile.Name;
|
string name = profile.Name;
|
||||||
string characterName = profile.Character.Type == Penumbra.GameData.Enums.IdentifierType.Owned ?
|
string characterName = string.Join(',', profile.Characters.Select(x => x.ToNameWithoutOwnerName().Incognify()));
|
||||||
profile.Character.ToNameWithoutOwnerName() : profile.Character.ToString();
|
|
||||||
|
|
||||||
#if INCOGNIFY_STRINGS
|
#if INCOGNIFY_STRINGS
|
||||||
name = name.Incognify();
|
name = name.Incognify();
|
||||||
characterName = characterName.Incognify();
|
//characterName = characterName.Incognify();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var show = ImGui.CollapsingHeader($"[{(profile.Enabled ? "E" : "D")}] {name} on {characterName} [{profile.ProfileType}] [{profile.UniqueId}]###{prefix}-profile-{profile.UniqueId}");
|
var show = ImGui.CollapsingHeader($"[{(profile.Enabled ? "E" : "D")}] {name} on {characterName} [{profile.ProfileType}] [{profile.UniqueId}]###{prefix}-profile-{profile.UniqueId}");
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using CustomizePlus.Profiles.Data;
|
|||||||
using CustomizePlus.Game.Services;
|
using CustomizePlus.Game.Services;
|
||||||
using CustomizePlus.Profiles.Events;
|
using CustomizePlus.Profiles.Events;
|
||||||
using CustomizePlus.GameData.Extensions;
|
using CustomizePlus.GameData.Extensions;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
|
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
|
||||||
|
|
||||||
@@ -133,7 +134,8 @@ public class ProfileFileSystemSelector : FileSystemSelector<Profile, ProfileStat
|
|||||||
case ProfileChanged.Type.Deleted:
|
case ProfileChanged.Type.Deleted:
|
||||||
case ProfileChanged.Type.Renamed:
|
case ProfileChanged.Type.Renamed:
|
||||||
case ProfileChanged.Type.Toggled:
|
case ProfileChanged.Type.Toggled:
|
||||||
case ProfileChanged.Type.ChangedCharacter:
|
case ProfileChanged.Type.AddedCharacter:
|
||||||
|
case ProfileChanged.Type.RemovedCharacter:
|
||||||
case ProfileChanged.Type.ReloadedAll:
|
case ProfileChanged.Type.ReloadedAll:
|
||||||
SetFilterDirty();
|
SetFilterDirty();
|
||||||
break;
|
break;
|
||||||
@@ -239,10 +241,13 @@ public class ProfileFileSystemSelector : FileSystemSelector<Profile, ProfileStat
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var identifier = _gameObjectService.GetCurrentPlayerActorIdentifier();
|
||||||
if (leaf.Value.Enabled)
|
if (leaf.Value.Enabled)
|
||||||
state.Color = leaf.Value.Character.MatchesIgnoringOwnership(_gameObjectService.GetCurrentPlayerActorIdentifier()) ? ColorId.LocalCharacterEnabledProfile : ColorId.EnabledProfile;
|
state.Color = leaf.Value.Characters.Any(x => x.MatchesIgnoringOwnership(identifier)) ? ColorId.LocalCharacterEnabledProfile : ColorId.EnabledProfile;
|
||||||
else
|
else
|
||||||
state.Color = leaf.Value.Character.MatchesIgnoringOwnership(_gameObjectService.GetCurrentPlayerActorIdentifier()) ? ColorId.LocalCharacterDisabledProfile : ColorId.DisabledProfile;
|
state.Color = leaf.Value.Characters.Any(x => x.MatchesIgnoringOwnership(identifier)) ? ColorId.LocalCharacterDisabledProfile : ColorId.DisabledProfile;
|
||||||
|
|
||||||
|
//todo: missing actor color
|
||||||
|
|
||||||
return ApplyStringFilters(leaf, leaf.Value);
|
return ApplyStringFilters(leaf, leaf.Value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using Penumbra.GameData.Actors;
|
|||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
using static FFXIVClientStructs.FFXIV.Client.LayoutEngine.ILayoutInstance;
|
using static FFXIVClientStructs.FFXIV.Client.LayoutEngine.ILayoutInstance;
|
||||||
using CustomizePlus.GameData.Extensions;
|
using CustomizePlus.GameData.Extensions;
|
||||||
|
using CustomizePlus.Core.Extensions;
|
||||||
|
|
||||||
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
|
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Profiles;
|
||||||
|
|
||||||
@@ -151,6 +152,13 @@ public class ProfilePanel
|
|||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
|
var isShouldDraw = ImGui.CollapsingHeader("Character settings");
|
||||||
|
|
||||||
|
if (isShouldDraw)
|
||||||
|
DrawCharacterArea();
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
DrawTemplateArea();
|
DrawTemplateArea();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,25 +212,21 @@ public class ProfilePanel
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
ImGui.TextUnformatted(_selector.Selected!.Incognito);
|
ImGui.TextUnformatted(_selector.Selected!.Incognito);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.TableNextRow();
|
private void DrawCharacterArea()
|
||||||
|
{
|
||||||
ImGuiUtil.DrawFrameColumn("Character");
|
using (var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)))
|
||||||
ImGui.TableNextColumn();
|
{
|
||||||
width = new Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("Limit to my creatures").X - 68, 0);
|
var width = new Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("Limit to my creatures").X - 68, 0);
|
||||||
|
|
||||||
ImGui.SetNextItemWidth(width.X);
|
ImGui.SetNextItemWidth(width.X);
|
||||||
|
|
||||||
if (!_selector.IncognitoMode)
|
bool appliesToMultiple = _manager.DefaultProfile == _selector.Selected || _manager.DefaultLocalPlayerProfile == _selector.Selected;
|
||||||
|
using (ImRaii.Disabled(appliesToMultiple))
|
||||||
{
|
{
|
||||||
bool showMultipleMessage = false;
|
|
||||||
if (_manager.DefaultProfile != _selector.Selected && _manager.DefaultLocalPlayerProfile != _selector.Selected)
|
|
||||||
{
|
|
||||||
ImGui.Text(_selector.Selected!.Character.IsValid ? $"Applies to {(_selector.Selected?.Character.Type == Penumbra.GameData.Enums.IdentifierType.Owned ?
|
|
||||||
_selector.Selected?.Character.ToNameWithoutOwnerName() : _selector.Selected?.Character.ToString())}" : "No valid character selected for the profile");
|
|
||||||
|
|
||||||
ImGui.Separator();
|
|
||||||
|
|
||||||
_actorAssignmentUi.DrawWorldCombo(width.X / 2);
|
_actorAssignmentUi.DrawWorldCombo(width.X / 2);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
_actorAssignmentUi.DrawPlayerInput(width.X / 2);
|
_actorAssignmentUi.DrawPlayerInput(width.X / 2);
|
||||||
@@ -230,21 +234,21 @@ public class ProfilePanel
|
|||||||
var buttonWidth = new Vector2(165 * ImGuiHelpers.GlobalScale - ImGui.GetStyle().ItemSpacing.X / 2, 0);
|
var buttonWidth = new Vector2(165 * ImGuiHelpers.GlobalScale - ImGui.GetStyle().ItemSpacing.X / 2, 0);
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply to player character", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetPlayer))
|
if (ImGuiUtil.DrawDisabledButton("Apply to player character", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetPlayer))
|
||||||
_manager.ChangeCharacter(_selector.Selected!, _actorAssignmentUi.PlayerIdentifier);
|
_manager.AddCharacter(_selector.Selected!, _actorAssignmentUi.PlayerIdentifier);
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply to retainer", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetRetainer))
|
if (ImGuiUtil.DrawDisabledButton("Apply to retainer", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetRetainer))
|
||||||
_manager.ChangeCharacter(_selector.Selected!, _actorAssignmentUi.RetainerIdentifier);
|
_manager.AddCharacter(_selector.Selected!, _actorAssignmentUi.RetainerIdentifier);
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply to mannequin", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetMannequin))
|
if (ImGuiUtil.DrawDisabledButton("Apply to mannequin", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetMannequin))
|
||||||
_manager.ChangeCharacter(_selector.Selected!, _actorAssignmentUi.MannequinIdentifier);
|
_manager.AddCharacter(_selector.Selected!, _actorAssignmentUi.MannequinIdentifier);
|
||||||
|
|
||||||
var currentPlayer = _actorManager.GetCurrentPlayer();
|
var currentPlayer = _actorManager.GetCurrentPlayer();
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply to current character", buttonWidth, string.Empty, !currentPlayer.IsValid))
|
if (ImGuiUtil.DrawDisabledButton("Apply to current character", buttonWidth, string.Empty, !currentPlayer.IsValid))
|
||||||
_manager.ChangeCharacter(_selector.Selected!, currentPlayer);
|
_manager.AddCharacter(_selector.Selected!, currentPlayer);
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
@@ -253,14 +257,8 @@ public class ProfilePanel
|
|||||||
_actorAssignmentUi.DrawNpcInput(width.X / 2);
|
_actorAssignmentUi.DrawNpcInput(width.X / 2);
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply to selected NPC", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetNpc))
|
if (ImGuiUtil.DrawDisabledButton("Apply to selected NPC", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetNpc))
|
||||||
_manager.ChangeCharacter(_selector.Selected!, _actorAssignmentUi.NpcIdentifier);
|
_manager.AddCharacter(_selector.Selected!, _actorAssignmentUi.NpcIdentifier);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ImGui.TextUnformatted("Applies to multiple targets");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ImGui.TextUnformatted("Incognito active");
|
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
@@ -299,13 +297,64 @@ public class ProfilePanel
|
|||||||
ImGui.PopStyleColor();
|
ImGui.PopStyleColor();
|
||||||
ImGuiUtil.HoverTooltip("Can only be changed when both currently selected and profile where this checkbox is checked are disabled.");
|
ImGuiUtil.HoverTooltip("Can only be changed when both currently selected and profile where this checkbox is checked are disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.Separator();
|
||||||
|
|
||||||
|
using var dis = ImRaii.Disabled(appliesToMultiple);
|
||||||
|
using var table = ImRaii.Table("CharacterTable", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY, new Vector2(ImGui.GetContentRegionAvail().X, 150));
|
||||||
|
if (!table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui.TableSetupColumn("##charaDel", ImGuiTableColumnFlags.WidthFixed, ImGui.GetFrameHeight());
|
||||||
|
ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.WidthFixed, 320 * ImGuiHelpers.GlobalScale);
|
||||||
|
ImGui.TableHeadersRow();
|
||||||
|
|
||||||
|
if(appliesToMultiple)
|
||||||
|
{
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("Applies to multiple targets");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//warn: .ToList() might be performance critical at some point
|
||||||
|
//the copying via ToList is done because manipulations with .Templates list result in "Collection was modified" exception here
|
||||||
|
var charas = _selector.Selected!.Characters.WithIndex().ToList();
|
||||||
|
|
||||||
|
if (charas.Count == 0)
|
||||||
|
{
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted("No characters are associated with this profile");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (character, idx) in charas)
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId(idx);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
var keyValid = _configuration.UISettings.DeleteTemplateModifier.IsActive();
|
||||||
|
var tt = keyValid
|
||||||
|
? "Remove this character from the profile."
|
||||||
|
: $"Remove this character from the profile.\nHold {_configuration.UISettings.DeleteTemplateModifier} to remove.";
|
||||||
|
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), new Vector2(ImGui.GetFrameHeight()), tt, !keyValid, true))
|
||||||
|
_endAction = () => _manager.DeleteCharacter(_selector.Selected!, character);
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImGui.AlignTextToFramePadding();
|
||||||
|
ImGui.TextUnformatted(!_selector.IncognitoMode ? $"{character.ToNameWithoutOwnerName()}{character.TypeToString()}" : "Incognito");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_endAction?.Invoke();
|
||||||
|
_endAction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTemplateArea()
|
private void DrawTemplateArea()
|
||||||
{
|
{
|
||||||
using var table = ImRaii.Table("SetTable", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY);
|
using var table = ImRaii.Table("TemplateTable", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollX | ImGuiTableFlags.ScrollY);
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user