Use actor identifiers in template editor

This commit is contained in:
RisaDev
2024-10-16 23:19:05 +03:00
parent 3781000d75
commit d6975591fe
9 changed files with 161 additions and 82 deletions

View File

@@ -368,9 +368,9 @@ public unsafe sealed class ArmatureManager : IDisposable
if (type == TemplateChanged.Type.EditorCharacterChanged) if (type == TemplateChanged.Type.EditorCharacterChanged)
{ {
(var characterName, var profile) = ((string, Profile))arg3; (var character, var profile) = ((ActorIdentifier, Profile))arg3;
foreach (var armature in GetArmaturesForCharacterName(characterName)) foreach (var armature in GetArmaturesForCharacter(character))
{ {
armature.IsPendingProfileRebind = true; armature.IsPendingProfileRebind = true;
_logger.Debug($"ArmatureManager.OnTemplateChange Editor profile character name changed, armature rebind scheduled: {type}, {armature}"); _logger.Debug($"ArmatureManager.OnTemplateChange Editor profile character name changed, armature rebind scheduled: {type}, {armature}");
@@ -383,7 +383,7 @@ public unsafe sealed class ArmatureManager : IDisposable
foreach (var armature in profile.Armatures) foreach (var armature in profile.Armatures)
armature.IsPendingProfileRebind = true; armature.IsPendingProfileRebind = true;
_logger.Debug($"ArmatureManager.OnTemplateChange Editor profile character name changed, armature rebind scheduled: {type}, profile: {profile.Name.Text.Incognify()}->{profile.Enabled}, new name: {characterName.Incognify()}"); _logger.Debug($"ArmatureManager.OnTemplateChange Editor profile character name changed, armature rebind scheduled: {type}, profile: {profile.Name.Text.Incognify()}->{profile.Enabled}, new name: {character.Incognito(null)}");
return; return;
} }
@@ -391,7 +391,7 @@ public unsafe sealed class ArmatureManager : IDisposable
if (type == TemplateChanged.Type.EditorEnabled || if (type == TemplateChanged.Type.EditorEnabled ||
type == TemplateChanged.Type.EditorDisabled) type == TemplateChanged.Type.EditorDisabled)
{ {
foreach (var armature in GetArmaturesForCharacterName((string)arg3!)) foreach (var armature in GetArmaturesForCharacter((ActorIdentifier)arg3!))
{ {
armature.IsPendingProfileRebind = true; armature.IsPendingProfileRebind = true;
_logger.Debug($"ArmatureManager.OnTemplateChange template editor enabled/disabled: {type}, pending profile set for {armature}"); _logger.Debug($"ArmatureManager.OnTemplateChange template editor enabled/disabled: {type}, pending profile set for {armature}");
@@ -516,17 +516,6 @@ public unsafe sealed class ArmatureManager : IDisposable
profile!.Armatures.ForEach(x => x.IsPendingProfileRebind = true); profile!.Armatures.ForEach(x => x.IsPendingProfileRebind = true);
} }
private IEnumerable<Armature> GetArmaturesForCharacterName(string characterName)
{
foreach(var kvPair in Armatures)
{
(var actorIdentifier, _) = _gameObjectService.GetTrueActorForSpecialTypeActor(kvPair.Key);
if(actorIdentifier.ToNameWithoutOwnerName() == characterName)
yield return kvPair.Value;
}
}
private IEnumerable<Armature> GetArmaturesForCharacter(ActorIdentifier actorIdentifier) private IEnumerable<Armature> GetArmaturesForCharacter(ActorIdentifier actorIdentifier)
{ {
foreach (var kvPair in Armatures) foreach (var kvPair in Armatures)

View File

@@ -11,6 +11,8 @@ using CustomizePlus.Core.Data;
using CustomizePlus.Configuration.Services; using CustomizePlus.Configuration.Services;
using CustomizePlus.UI.Windows; using CustomizePlus.UI.Windows;
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Penumbra.GameData.Actors;
using CustomizePlus.Core.Helpers;
namespace CustomizePlus.Configuration.Data; namespace CustomizePlus.Configuration.Data;
@@ -66,9 +68,8 @@ public class PluginConfiguration : IPluginConfiguration, ISavable
public bool ShowLiveBones { get; set; } = true; public bool ShowLiveBones { get; set; } = true;
public bool BoneMirroringEnabled { get; set; } = false; public bool BoneMirroringEnabled { get; set; } = false;
public bool LimitLookupToOwnedObjects { get; set; } = false;
public string? PreviewCharacterName { get; set; } = null; public ActorIdentifier PreviewCharacter { get; set; } = ActorIdentifier.Invalid;
public int EditorValuesPrecision { get; set; } = 3; public int EditorValuesPrecision { get; set; } = 3;
@@ -134,6 +135,7 @@ public class PluginConfiguration : IPluginConfiguration, ISavable
JsonConvert.PopulateObject(text, this, new JsonSerializerSettings JsonConvert.PopulateObject(text, this, new JsonSerializerSettings
{ {
Error = HandleDeserializationError, Error = HandleDeserializationError,
Converters = new List<JsonConverter> { new ActorIdentifierJsonConverter() }
}); });
} }
catch (Exception ex) catch (Exception ex)
@@ -153,6 +155,7 @@ public class PluginConfiguration : IPluginConfiguration, ISavable
{ {
using var jWriter = new JsonTextWriter(writer) { Formatting = Formatting.Indented }; using var jWriter = new JsonTextWriter(writer) { Formatting = Formatting.Indented };
var serializer = new JsonSerializer { Formatting = Formatting.Indented }; var serializer = new JsonSerializer { Formatting = Formatting.Indented };
serializer.Converters.Add(new ActorIdentifierJsonConverter());
serializer.Serialize(jWriter, this); serializer.Serialize(jWriter, this);
} }

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Text.Json;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Penumbra.GameData.Actors;
using Newtonsoft.Json.Linq;
namespace CustomizePlus.Core.Helpers;
internal sealed class ActorIdentifierJsonConverter : JsonConverter<ActorIdentifier>
{
public override ActorIdentifier ReadJson(JsonReader reader, Type objectType, ActorIdentifier existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
if (Penumbra.GameData.Actors.ActorIdentifierExtensions.Manager == null)
throw new Exception("Penumbra.GameData.Actors.ActorIdentifierExtensions.Manager is not ready");
return Penumbra.GameData.Actors.ActorIdentifierExtensions.Manager.FromJson(obj);
}
public override void WriteJson(JsonWriter writer, ActorIdentifier value, Newtonsoft.Json.JsonSerializer serializer)
{
value.ToJson().WriteTo(writer);
}
}

View File

@@ -46,8 +46,7 @@ public class SupportLogBuilderService
sb.Append($"> **`Commit Hash: `** {ThisAssembly.Git.Commit}+{ThisAssembly.Git.Sha}\n"); sb.Append($"> **`Commit Hash: `** {ThisAssembly.Git.Commit}+{ThisAssembly.Git.Sha}\n");
sb.Append($"> **`Plugin enabled: `** {_configuration.PluginEnabled}\n"); sb.Append($"> **`Plugin enabled: `** {_configuration.PluginEnabled}\n");
sb.AppendLine("**Settings -> Editor Settings**"); sb.AppendLine("**Settings -> Editor Settings**");
sb.Append($"> **`Limit to my creatures (editor): `** {_configuration.EditorConfiguration.LimitLookupToOwnedObjects}\n"); sb.Append($"> **`Preview character (editor): `** {_configuration.EditorConfiguration.PreviewCharacter.Incognito(null)}\n");
sb.Append($"> **`Preview character (editor): `** {_configuration.EditorConfiguration.PreviewCharacterName?.Incognify() ?? "Not set"}\n");
sb.Append($"> **`Set preview character on login: `** {_configuration.EditorConfiguration.SetPreviewToCurrentCharacterOnLogin}\n"); sb.Append($"> **`Set preview character on login: `** {_configuration.EditorConfiguration.SetPreviewToCurrentCharacterOnLogin}\n");
sb.Append($"> **`Root editing: `** {_configuration.EditorConfiguration.RootPositionEditingEnabled}\n"); sb.Append($"> **`Root editing: `** {_configuration.EditorConfiguration.RootPositionEditingEnabled}\n");
sb.AppendLine("**Settings -> Profile application**"); sb.AppendLine("**Settings -> Profile application**");

View File

@@ -9,6 +9,7 @@ using ObjectManager = CustomizePlus.GameData.Services.ObjectManager;
using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.IGameObject; using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.IGameObject;
using CustomizePlus.Configuration.Data; using CustomizePlus.Configuration.Data;
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Penumbra.GameData.Files.ShaderStructs;
namespace CustomizePlus.Game.Services; namespace CustomizePlus.Game.Services;
@@ -59,8 +60,6 @@ public class GameObjectService
/// <summary> /// <summary>
/// Case sensitive /// Case sensitive
/// </summary> /// </summary>
/// <param name="name"></param>
/// <returns></returns>
public IEnumerable<(ActorIdentifier, Actor)> FindActorsByName(string name) public IEnumerable<(ActorIdentifier, Actor)> FindActorsByName(string name)
{ {
_objectManager.Update(); _objectManager.Update();
@@ -85,6 +84,36 @@ public class GameObjectService
} }
} }
/// <summary>
/// Searches using CompareIgnoringOwnership
/// </summary>
public IEnumerable<(ActorIdentifier, Actor)> FindActorsByIdentifier(ActorIdentifier identifier)
{
if (!identifier.IsValid)
yield break;
_objectManager.Update();
foreach (var kvPair in _objectManager.Identifiers)
{
var objectIdentifier = kvPair.Key;
(objectIdentifier, _) = GetTrueActorForSpecialTypeActor(objectIdentifier);
if (!objectIdentifier.IsValid)
continue;
if (identifier.CompareIgnoringOwnership(objectIdentifier))
{
if (kvPair.Value.Objects.Count > 1) //in gpose we can have more than a single object for one actor
foreach (var obj in kvPair.Value.Objects)
yield return (kvPair.Key.CreatePermanent(), obj);
else
yield return (kvPair.Key.CreatePermanent(), kvPair.Value.Objects[0]);
}
}
}
public Actor GetLocalPlayerActor() public Actor GetLocalPlayerActor()
{ {
_objectManager.Update(); _objectManager.Update();

View File

@@ -21,6 +21,7 @@ using CustomizePlus.Core.Extensions;
using CustomizePlus.Templates; using CustomizePlus.Templates;
using CustomizePlus.Profiles; using CustomizePlus.Profiles;
using CustomizePlus.Armatures.Services; using CustomizePlus.Armatures.Services;
using Penumbra.GameData.Actors;
namespace CustomizePlus; namespace CustomizePlus;
@@ -44,6 +45,8 @@ public sealed class Plugin : IDalamudPlugin
_services = ServiceManagerBuilder.CreateProvider(pluginInterface, Logger); _services = ServiceManagerBuilder.CreateProvider(pluginInterface, Logger);
_services.GetService<ActorManager>(); //needs to be initialized early for config to be read properly
//temporary //temporary
var v3ConfigFixer = _services.GetService<Version3ConfigFixer>(); var v3ConfigFixer = _services.GetService<Version3ConfigFixer>();
v3ConfigFixer.FixV3ConfigIfNeeded(); v3ConfigFixer.FixV3ConfigIfNeeded();

View File

@@ -11,6 +11,7 @@ using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Log; using OtterGui.Log;
using Penumbra.GameData.Actors;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -63,12 +64,22 @@ 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 string CharacterName => EditorProfile.CharacterName; public ActorIdentifier Character => EditorProfile.Character;
/// <summary> /// <summary>
/// Checks if preview character exists at the time of call /// Checks if preview character exists at the time of call
/// </summary> /// </summary>
public bool IsCharacterFound => _gameObjectService.FindActorsByName(CharacterName).Count() > 0; public bool IsCharacterFound
{
get
{
//todo: check with mounts/companions
var playerName = _gameObjectService.GetCurrentPlayerName();
return _gameObjectService.FindActorsByIdentifier(Character)
.Where(x => x.Item1.Type != Penumbra.GameData.Enums.IdentifierType.Owned || x.Item1.PlayerName.ToString() == playerName)
.Any();
}
}
public bool IsKeepOnlyEditorProfileActive { get; set; } //todo public bool IsKeepOnlyEditorProfileActive { get; set; } //todo
@@ -95,7 +106,7 @@ public class TemplateEditorManager : IDisposable
Enabled = false, Enabled = false,
Name = "Template editor profile", Name = "Template editor profile",
ProfileType = ProfileType.Editor, ProfileType = ProfileType.Editor,
CharacterName = configuration.EditorConfiguration.PreviewCharacterName ?? LowerString.Empty Character = configuration.EditorConfiguration.PreviewCharacter
}; };
} }
@@ -112,7 +123,7 @@ public class TemplateEditorManager : IDisposable
if (IsEditorActive || IsEditorPaused) if (IsEditorActive || IsEditorPaused)
return false; return false;
_logger.Debug($"Enabling editor profile for {template.Name} via character {CharacterName}"); _logger.Debug($"Enabling editor profile for {template.Name} via character {Character.Incognito(null)}");
CurrentlyEditedTemplateId = template.UniqueId; CurrentlyEditedTemplateId = template.UniqueId;
_currentlyEditedTemplateOriginal = template; _currentlyEditedTemplateOriginal = template;
@@ -124,8 +135,8 @@ public class TemplateEditorManager : IDisposable
Name = "Template editor temporary template" Name = "Template editor temporary template"
}; };
if (string.IsNullOrWhiteSpace(CharacterName)) //safeguard if (!Character.IsValid) //safeguard
ChangeEditorCharacterInternal(_gameObjectService.GetCurrentPlayerName()); //will set EditorProfile.CharacterName ChangeEditorCharacterInternal(_gameObjectService.GetCurrentPlayerActorIdentifier()); //will set EditorProfile.Character
EditorProfile.Templates.Clear(); //safeguard EditorProfile.Templates.Clear(); //safeguard
EditorProfile.Templates.Add(CurrentlyEditedTemplate); EditorProfile.Templates.Add(CurrentlyEditedTemplate);
@@ -133,7 +144,7 @@ public class TemplateEditorManager : IDisposable
HasChanges = false; HasChanges = false;
IsEditorActive = true; IsEditorActive = true;
_event.Invoke(TemplateChanged.Type.EditorEnabled, template, CharacterName); _event.Invoke(TemplateChanged.Type.EditorEnabled, template, Character);
return true; return true;
} }
@@ -155,7 +166,7 @@ public class TemplateEditorManager : IDisposable
IsEditorActive = false; IsEditorActive = false;
HasChanges = false; HasChanges = false;
_event.Invoke(TemplateChanged.Type.EditorDisabled, null, CharacterName); _event.Invoke(TemplateChanged.Type.EditorDisabled, null, Character);
return true; return true;
} }
@@ -172,24 +183,24 @@ public class TemplateEditorManager : IDisposable
_templateManager.ApplyBoneChangesAndSave(targetTemplate, CurrentlyEditedTemplate!); _templateManager.ApplyBoneChangesAndSave(targetTemplate, CurrentlyEditedTemplate!);
} }
public bool ChangeEditorCharacter(string characterName) public bool ChangeEditorCharacter(ActorIdentifier character)
{ {
if (!IsEditorActive || CharacterName == characterName || IsEditorPaused || string.IsNullOrWhiteSpace(characterName)) if (!IsEditorActive || Character == character || IsEditorPaused || !character.IsValid)
return false; return false;
return ChangeEditorCharacterInternal(characterName); return ChangeEditorCharacterInternal(character);
} }
private bool ChangeEditorCharacterInternal(string characterName) private bool ChangeEditorCharacterInternal(ActorIdentifier character)
{ {
_logger.Debug($"Changing character name for editor profile from {EditorProfile.CharacterName} to {characterName}"); _logger.Debug($"Changing character name for editor profile from {EditorProfile.Character.Incognito(null)} to {character.Incognito(null)}");
EditorProfile.CharacterName = characterName; EditorProfile.Character = character;
_configuration.EditorConfiguration.PreviewCharacterName = CharacterName; _configuration.EditorConfiguration.PreviewCharacter = character;
_configuration.Save(); _configuration.Save();
_event.Invoke(TemplateChanged.Type.EditorCharacterChanged, CurrentlyEditedTemplate, (characterName, EditorProfile)); _event.Invoke(TemplateChanged.Type.EditorCharacterChanged, CurrentlyEditedTemplate, (character, EditorProfile));
return true; return true;
} }
@@ -294,19 +305,19 @@ public class TemplateEditorManager : IDisposable
private void OnLogin() private void OnLogin()
{ {
if (_configuration.EditorConfiguration.SetPreviewToCurrentCharacterOnLogin || if (_configuration.EditorConfiguration.SetPreviewToCurrentCharacterOnLogin ||
string.IsNullOrWhiteSpace(_configuration.EditorConfiguration.PreviewCharacterName)) !_configuration.EditorConfiguration.PreviewCharacter.IsValid)
{ {
var localPlayerName = _gameObjectService.GetCurrentPlayerName(); var localPlayer = _gameObjectService.GetCurrentPlayerActorIdentifier();
if(string.IsNullOrWhiteSpace(localPlayerName)) if(!localPlayer.IsValid)
{ {
_logger.Warning("Can't retrieve local player name on login"); _logger.Warning("Can't retrieve local player on login");
return; return;
} }
if (_configuration.EditorConfiguration.PreviewCharacterName != localPlayerName) if (_configuration.EditorConfiguration.PreviewCharacter != localPlayer)
{ {
_logger.Debug("Resetting editor character because automatic condition triggered in OnLogin"); _logger.Debug("Resetting editor character because automatic condition triggered in OnLogin");
ChangeEditorCharacterInternal(localPlayerName); ChangeEditorCharacterInternal(localPlayer);
} }
} }
} }

View File

@@ -32,7 +32,6 @@ public class ProfilePanel
private readonly TemplateEditorEvent _templateEditorEvent; private readonly TemplateEditorEvent _templateEditorEvent;
private string? _newName; private string? _newName;
//private string? _newCharacterName;
private Profile? _changedProfile; private Profile? _changedProfile;
private Action? _endAction; private Action? _endAction;
@@ -219,7 +218,8 @@ public class ProfilePanel
bool showMultipleMessage = false; bool showMultipleMessage = false;
if (_manager.DefaultProfile != _selector.Selected && !_selector.Selected!.ApplyToCurrentlyActiveCharacter) if (_manager.DefaultProfile != _selector.Selected && !_selector.Selected!.ApplyToCurrentlyActiveCharacter)
{ {
ImGui.Text(_selector.Selected!.Character.IsValid ? $"Applies to {_selector.Selected?.Character.ToNameWithoutOwnerName()}" : "No valid character selected for the profile"); 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.Text($"Legacy: {_selector.Selected!.CharacterName.Text ?? "None"}"); ImGui.Text($"Legacy: {_selector.Selected!.CharacterName.Text ?? "None"}");
ImGui.Separator(); ImGui.Separator();

View File

@@ -15,6 +15,10 @@ using CustomizePlus.Core.Helpers;
using CustomizePlus.Templates; using CustomizePlus.Templates;
using CustomizePlus.Game.Services; using CustomizePlus.Game.Services;
using CustomizePlus.Templates.Data; using CustomizePlus.Templates.Data;
using CustomizePlus.UI.Windows.Controls;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using Penumbra.GameData.Actors;
using CustomizePlus.GameData.Extensions;
namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Templates; namespace CustomizePlus.UI.Windows.MainWindow.Tabs.Templates;
@@ -24,6 +28,7 @@ public class BoneEditorPanel
private readonly TemplateEditorManager _editorManager; private readonly TemplateEditorManager _editorManager;
private readonly PluginConfiguration _configuration; private readonly PluginConfiguration _configuration;
private readonly GameObjectService _gameObjectService; private readonly GameObjectService _gameObjectService;
private readonly ActorAssignmentUi _actorAssignmentUi;
private BoneAttribute _editingAttribute; private BoneAttribute _editingAttribute;
private int _precision; private int _precision;
@@ -31,8 +36,6 @@ public class BoneEditorPanel
private bool _isShowLiveBones; private bool _isShowLiveBones;
private bool _isMirrorModeEnabled; private bool _isMirrorModeEnabled;
private string? _newCharacterName;
private Dictionary<BoneData.BoneFamily, bool> _groupExpandedState = new(); private Dictionary<BoneData.BoneFamily, bool> _groupExpandedState = new();
private bool _openSavePopup; private bool _openSavePopup;
@@ -48,12 +51,14 @@ public class BoneEditorPanel
TemplateFileSystemSelector templateFileSystemSelector, TemplateFileSystemSelector templateFileSystemSelector,
TemplateEditorManager editorManager, TemplateEditorManager editorManager,
PluginConfiguration configuration, PluginConfiguration configuration,
GameObjectService gameObjectService) GameObjectService gameObjectService,
ActorAssignmentUi actorAssignmentUi)
{ {
_templateFileSystemSelector = templateFileSystemSelector; _templateFileSystemSelector = templateFileSystemSelector;
_editorManager = editorManager; _editorManager = editorManager;
_configuration = configuration; _configuration = configuration;
_gameObjectService = gameObjectService; _gameObjectService = gameObjectService;
_actorAssignmentUi = actorAssignmentUi;
_isShowLiveBones = configuration.EditorConfiguration.ShowLiveBones; _isShowLiveBones = configuration.EditorConfiguration.ShowLiveBones;
_isMirrorModeEnabled = configuration.EditorConfiguration.BoneMirroringEnabled; _isMirrorModeEnabled = configuration.EditorConfiguration.BoneMirroringEnabled;
@@ -96,47 +101,57 @@ public class BoneEditorPanel
using (var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f))) using (var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)))
{ {
//using (var table = ImRaii.Table("BasicSettings", 2))
//{
/* ImGui.TableSetupColumn("BasicCol1", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("Show editor preview on").X);
ImGui.TableSetupColumn("BasicCol2", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableNextRow();
ImGuiUtil.DrawFrameColumn("Show editor preview on");
ImGui.TableNextColumn();*/
var width = new Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("Limit to my creatures").X - 68, 0);
var name = _newCharacterName ?? _editorManager.CharacterName;
//ImGui.SetNextItemWidth(width.X);
var isShouldDraw = ImGui.CollapsingHeader("Preview settings"); var isShouldDraw = ImGui.CollapsingHeader("Preview settings");
if (isShouldDraw) if (isShouldDraw)
{ {
var width = new Vector2(ImGui.GetContentRegionAvail().X - ImGui.CalcTextSize("Limit to my creatures").X - 68, 0);
using (var disabled = ImRaii.Disabled(!IsEditorActive || IsEditorPaused)) using (var disabled = ImRaii.Disabled(!IsEditorActive || IsEditorPaused))
{ {
if (!_templateFileSystemSelector.IncognitoMode) if (!_templateFileSystemSelector.IncognitoMode)
{ {
if (ImGui.InputText("##PreviewCharacterName", ref name, 128)) ImGui.Text(_editorManager.Character.IsValid ? $"Applies to {(_editorManager.Character.Type == Penumbra.GameData.Enums.IdentifierType.Owned ?
{ _editorManager.Character.ToNameWithoutOwnerName() : _editorManager.Character.ToString())}" : "No valid character selected");
_newCharacterName = name; ImGui.Separator();
}
if (ImGui.IsItemDeactivatedAfterEdit()) _actorAssignmentUi.DrawWorldCombo(width.X / 2);
{ ImGui.SameLine();
if (string.IsNullOrWhiteSpace(_newCharacterName)) _actorAssignmentUi.DrawPlayerInput(width.X / 2);
_newCharacterName = _gameObjectService.GetCurrentPlayerName();
_editorManager.ChangeEditorCharacter(_newCharacterName); var buttonWidth = new Vector2(165 * ImGuiHelpers.GlobalScale - ImGui.GetStyle().ItemSpacing.X / 2, 0);
_newCharacterName = null; if (ImGuiUtil.DrawDisabledButton("Apply to player character", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetPlayer))
} _editorManager.ChangeEditorCharacter(_actorAssignmentUi.PlayerIdentifier);
ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton("Apply to retainer", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetRetainer))
_editorManager.ChangeEditorCharacter(_actorAssignmentUi.RetainerIdentifier);
ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton("Apply to mannequin", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetMannequin))
_editorManager.ChangeEditorCharacter(_actorAssignmentUi.MannequinIdentifier);
var currentPlayer = _gameObjectService.GetCurrentPlayerActorIdentifier();
if (ImGuiUtil.DrawDisabledButton("Apply to current character", buttonWidth, string.Empty, !currentPlayer.IsValid))
_editorManager.ChangeEditorCharacter(currentPlayer);
ImGui.Separator();
_actorAssignmentUi.DrawObjectKindCombo(width.X / 2);
ImGui.SameLine();
_actorAssignmentUi.DrawNpcInput(width.X / 2);
if (ImGuiUtil.DrawDisabledButton("Apply to selected NPC", buttonWidth, string.Empty, !_actorAssignmentUi.CanSetNpc))
_editorManager.ChangeEditorCharacter(_actorAssignmentUi.NpcIdentifier);
} }
else else
ImGui.TextUnformatted("Incognito active"); ImGui.TextUnformatted("Incognito active");
} }
} }
//}
ImGui.Separator(); ImGui.Separator();
using (var table = ImRaii.Table("BoneEditorMenu", 2)) using (var table = ImRaii.Table("BoneEditorMenu", 2))