Update for new ActorObjectManager.

This commit is contained in:
Ottermandias 2025-04-05 18:48:39 +02:00
parent 8fe0ac8195
commit c0ad4aab51
38 changed files with 273 additions and 578 deletions

View file

@ -6,12 +6,12 @@ using OtterGui.Log;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.String; using Penumbra.String;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Api; namespace Glamourer.Api;
public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal IEnumerable<ActorState> FindExistingStates(string actorName) internal IEnumerable<ActorState> FindExistingStates(string actorName)
@ -27,7 +27,7 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state) internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state)
{ {
var actor = objects[objectIndex]; var actor = objects.Objects[objectIndex];
var identifier = actor.GetIdentifier(actors); var identifier = actor.GetIdentifier(actors);
if (!identifier.IsValid) if (!identifier.IsValid)
{ {
@ -42,7 +42,7 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal ActorState? FindState(int objectIndex) internal ActorState? FindState(int objectIndex)
{ {
var actor = objects[objectIndex]; var actor = objects.Objects[objectIndex];
var identifier = actor.GetIdentifier(actors); var identifier = actor.GetIdentifier(actors);
if (identifier.IsValid && stateManager.GetOrCreate(identifier, actor, out var state)) if (identifier.IsValid && stateManager.GetOrCreate(identifier, actor, out var state))
return state; return state;
@ -73,10 +73,8 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
if (objectName.Length == 0 || !ByteString.FromString(objectName, out var byteString)) if (objectName.Length == 0 || !ByteString.FromString(objectName, out var byteString))
return []; return [];
objects.Update();
return stateManager.Values.Where(state => state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString) return stateManager.Values.Where(state => state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString)
.Concat(objects.Identifiers .Concat(objects
.Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString) .Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString)
.SelectWhere(kvp => .SelectWhere(kvp =>
{ {

View file

@ -4,34 +4,32 @@ using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Designs.History; using Glamourer.Designs.History;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using ObjectManager = Glamourer.Interop.ObjectManager;
using StateChanged = Glamourer.Events.StateChanged; using StateChanged = Glamourer.Events.StateChanged;
namespace Glamourer.Api; namespace Glamourer.Api;
public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
{ {
private readonly ApiHelpers _helpers; private readonly ApiHelpers _helpers;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly Configuration _config; private readonly Configuration _config;
private readonly AutoDesignApplier _autoDesigns; private readonly AutoDesignApplier _autoDesigns;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly StateChanged _stateChanged; private readonly StateChanged _stateChanged;
private readonly StateFinalized _stateFinalized; private readonly StateFinalized _stateFinalized;
private readonly GPoseService _gPose; private readonly GPoseService _gPose;
public StateApi(ApiHelpers helpers, public StateApi(ApiHelpers helpers,
StateManager stateManager, StateManager stateManager,
DesignConverter converter, DesignConverter converter,
Configuration config, Configuration config,
AutoDesignApplier autoDesigns, AutoDesignApplier autoDesigns,
ObjectManager objects, ActorObjectManager objects,
StateChanged stateChanged, StateChanged stateChanged,
StateFinalized stateFinalized, StateFinalized stateFinalized,
GPoseService gPose) GPoseService gPose)
@ -219,7 +217,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
if (!state.CanUnlock(key)) if (!state.CanUnlock(key))
return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args); return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args);
RevertToAutomation(_objects[objectIndex], state, key, flags); RevertToAutomation(_objects.Objects[objectIndex], state, key, flags);
return ApiHelpers.Return(GlamourerApiEc.Success, args); return ApiHelpers.Return(GlamourerApiEc.Success, args);
} }
@ -272,15 +270,9 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
var source = (flags & ApplyFlag.Once) != 0 ? StateSource.IpcManual : StateSource.IpcFixed; var source = (flags & ApplyFlag.Once) != 0 ? StateSource.IpcManual : StateSource.IpcFixed;
switch (flags & (ApplyFlag.Equipment | ApplyFlag.Customization)) switch (flags & (ApplyFlag.Equipment | ApplyFlag.Customization))
{ {
case ApplyFlag.Equipment: case ApplyFlag.Equipment: _stateManager.ResetEquip(state, source, key); break;
_stateManager.ResetEquip(state, source, key); case ApplyFlag.Customization: _stateManager.ResetCustomize(state, source, key); break;
break; case ApplyFlag.Equipment | ApplyFlag.Customization: _stateManager.ResetState(state, source, key); break;
case ApplyFlag.Customization:
_stateManager.ResetCustomize(state, source, key);
break;
case ApplyFlag.Equipment | ApplyFlag.Customization:
_stateManager.ResetState(state, source, key);
break;
} }
ApiHelpers.Lock(state, key, flags); ApiHelpers.Lock(state, key, flags);
@ -288,7 +280,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
private GlamourerApiEc RevertToAutomation(ActorState state, uint key, ApplyFlag flags) private GlamourerApiEc RevertToAutomation(ActorState state, uint key, ApplyFlag flags)
{ {
_objects.Update();
if (!_objects.TryGetValue(state.Identifier, out var actors) || !actors.Valid) if (!_objects.TryGetValue(state.Identifier, out var actors) || !actors.Valid)
return GlamourerApiEc.ActorNotFound; return GlamourerApiEc.ActorNotFound;

View file

@ -11,29 +11,28 @@ using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Automation; namespace Glamourer.Automation;
public sealed class AutoDesignApplier : IDisposable public sealed class AutoDesignApplier : IDisposable
{ {
private readonly Configuration _config; private readonly Configuration _config;
private readonly AutoDesignManager _manager; private readonly AutoDesignManager _manager;
private readonly StateManager _state; private readonly StateManager _state;
private readonly JobService _jobs; private readonly JobService _jobs;
private readonly EquippedGearset _equippedGearset; private readonly EquippedGearset _equippedGearset;
private readonly ActorManager _actors; private readonly ActorManager _actors;
private readonly AutomationChanged _event; private readonly AutomationChanged _event;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly WeaponLoading _weapons; private readonly WeaponLoading _weapons;
private readonly HumanModelList _humans; private readonly HumanModelList _humans;
private readonly DesignMerger _designMerger; private readonly DesignMerger _designMerger;
private readonly IClientState _clientState; private readonly IClientState _clientState;
private readonly JobChangeState _jobChangeState; private readonly JobChangeState _jobChangeState;
public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors, public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, ActorManager actors,
AutomationChanged @event, ObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState, AutomationChanged @event, ActorObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState,
EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState) EquippedGearset equippedGearset, DesignMerger designMerger, JobChangeState jobChangeState)
{ {
_config = config; _config = config;
@ -154,7 +153,6 @@ public sealed class AutoDesignApplier : IDisposable
if (newSet is not { Enabled: true }) if (newSet is not { Enabled: true })
return; return;
_objects.Update();
foreach (var id in newSet.Identifiers) foreach (var id in newSet.Identifiers)
{ {
if (_objects.TryGetValue(id, out var data)) if (_objects.TryGetValue(id, out var data))

View file

@ -1,8 +1,8 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Interop;
namespace Glamourer.Designs.History; namespace Glamourer.Designs.History;

View file

@ -3,6 +3,7 @@ using Glamourer.Designs.History;
using Glamourer.Interop.Structs; using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Classes; using OtterGui.Classes;
using Penumbra.GameData.Interop;
namespace Glamourer.Events; namespace Glamourer.Events;

View file

@ -2,6 +2,7 @@ using Glamourer.Api;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Interop.Structs; using Glamourer.Interop.Structs;
using OtterGui.Classes; using OtterGui.Classes;
using Penumbra.GameData.Interop;
namespace Glamourer.Events; namespace Glamourer.Events;

View file

@ -6,12 +6,10 @@ using Glamourer.Gui;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Log; using OtterGui.Log;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Enums; using Penumbra.GameData.Interop;
using Penumbra.GameData.Files;
namespace Glamourer; namespace Glamourer;
@ -82,7 +80,7 @@ public class Glamourer : IDalamudPlugin
var designManager = _services.GetService<DesignManager>(); var designManager = _services.GetService<DesignManager>();
var autoManager = _services.GetService<AutoDesignManager>(); var autoManager = _services.GetService<AutoDesignManager>();
var stateManager = _services.GetService<StateManager>(); var stateManager = _services.GetService<StateManager>();
var objectManager = _services.GetService<ObjectManager>(); var objectManager = _services.GetService<ActorObjectManager>();
var currentPlayer = objectManager.PlayerData.Identifier; var currentPlayer = objectManager.PlayerData.Identifier;
var states = stateManager.Where(kvp => objectManager.ContainsKey(kvp.Key)).ToList(); var states = stateManager.Where(kvp => objectManager.ContainsKey(kvp.Key)).ToList();

View file

@ -6,14 +6,13 @@ using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using ImGuiNET; using ImGuiNET;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui; namespace Glamourer.Gui;
@ -37,21 +36,21 @@ public sealed class DesignQuickBar : Window, IDisposable
? ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoMove ? ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoMove
: ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing; : ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoFocusOnAppearing;
private readonly Configuration _config; private readonly Configuration _config;
private readonly QuickDesignCombo _designCombo; private readonly QuickDesignCombo _designCombo;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly IKeyState _keyState; private readonly IKeyState _keyState;
private readonly ImRaii.Style _windowPadding = new(); private readonly ImRaii.Style _windowPadding = new();
private readonly ImRaii.Color _windowColor = new(); private readonly ImRaii.Color _windowColor = new();
private DateTime _keyboardToggle = DateTime.UnixEpoch; private DateTime _keyboardToggle = DateTime.UnixEpoch;
private int _numButtons; private int _numButtons;
private readonly StringBuilder _tooltipBuilder = new(512); private readonly StringBuilder _tooltipBuilder = new(512);
public DesignQuickBar(Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState, public DesignQuickBar(Configuration config, QuickDesignCombo designCombo, StateManager stateManager, IKeyState keyState,
ObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra) ActorObjectManager objects, AutoDesignApplier autoDesignApplier, PenumbraService penumbra)
: base("Glamourer Quick Bar", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking) : base("Glamourer Quick Bar", ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking)
{ {
_config = config; _config = config;
@ -222,7 +221,8 @@ public sealed class DesignQuickBar : Window, IDisposable
} }
if (available == 0) if (available == 0)
_tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked."); _tooltipBuilder.Append(
"Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.UndoAlt, buttonSize, available); var (clicked, _, _, state) = ResolveTarget(FontAwesomeIcon.UndoAlt, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
@ -258,9 +258,10 @@ public sealed class DesignQuickBar : Window, IDisposable
} }
if (available == 0) if (available == 0)
_tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked."); _tooltipBuilder.Append(
"Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.SyncAlt, buttonSize, available); var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.SyncAlt, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
if (!clicked) if (!clicked)
return; return;
@ -300,7 +301,8 @@ public sealed class DesignQuickBar : Window, IDisposable
} }
if (available == 0) if (available == 0)
_tooltipBuilder.Append("Neither player character nor target are available, have state modified by Glamourer, or their state is locked."); _tooltipBuilder.Append(
"Neither player character nor target are available, have state modified by Glamourer, or their state is locked.");
var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.Repeat, buttonSize, available); var (clicked, id, data, state) = ResolveTarget(FontAwesomeIcon.Repeat, buttonSize, available);
ImGui.SameLine(); ImGui.SameLine();
@ -424,7 +426,9 @@ public sealed class DesignQuickBar : Window, IDisposable
if (_playerIdentifier.IsValid && _playerData.Valid) if (_playerIdentifier.IsValid && _playerData.Valid)
{ {
available |= 1; available |= 1;
_tooltipBuilder.Append("Left-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ") _tooltipBuilder
.Append(
"Left-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
.Append(_playerIdentifier) .Append(_playerIdentifier)
.Append('.'); .Append('.');
} }
@ -434,7 +438,9 @@ public sealed class DesignQuickBar : Window, IDisposable
if (available != 0) if (available != 0)
_tooltipBuilder.Append('\n'); _tooltipBuilder.Append('\n');
available |= 2; available |= 2;
_tooltipBuilder.Append("Right-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ") _tooltipBuilder
.Append(
"Right-Click: Reset all temporary settings applied by Glamourer (manually or through automation) to the collection affecting ")
.Append(_targetIdentifier) .Append(_targetIdentifier)
.Append('.'); .Append('.');
} }

View file

@ -1,6 +1,5 @@
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra; using Glamourer.Interop.Penumbra;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
@ -9,18 +8,19 @@ using OtterGui.Raii;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Data; using Penumbra.GameData.Data;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Gui; namespace Glamourer.Gui;
public sealed class PenumbraChangedItemTooltip : IDisposable public sealed class PenumbraChangedItemTooltip : IDisposable
{ {
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly CustomizeService _customize; private readonly CustomizeService _customize;
private readonly GPoseService _gpose; private readonly GPoseService _gpose;
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2]; private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2];
@ -33,7 +33,7 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
public DateTime LastTooltip { get; private set; } = DateTime.MinValue; public DateTime LastTooltip { get; private set; } = DateTime.MinValue;
public DateTime LastClick { get; private set; } = DateTime.MinValue; public DateTime LastClick { get; private set; } = DateTime.MinValue;
public PenumbraChangedItemTooltip(PenumbraService penumbra, StateManager stateManager, ItemManager items, ObjectManager objects, public PenumbraChangedItemTooltip(PenumbraService penumbra, StateManager stateManager, ItemManager items, ActorObjectManager objects,
CustomizeService customize, GPoseService gpose) CustomizeService customize, GPoseService gpose)
{ {
_penumbra = penumbra; _penumbra = penumbra;

View file

@ -10,7 +10,6 @@ using Glamourer.Gui.Customization;
using Glamourer.Gui.Equipment; using Glamourer.Gui.Equipment;
using Glamourer.Gui.Materials; using Glamourer.Gui.Materials;
using Glamourer.Interop; using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
@ -22,7 +21,6 @@ using Penumbra.GameData.Actors;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Gui.Tabs.ActorTab; namespace Glamourer.Gui.Tabs.ActorTab;
@ -35,7 +33,7 @@ public class ActorPanel
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly Configuration _config; private readonly Configuration _config;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly ImportService _importService; private readonly ImportService _importService;
private readonly ICondition _conditions; private readonly ICondition _conditions;
@ -53,7 +51,7 @@ public class ActorPanel
AutoDesignApplier autoDesignApplier, AutoDesignApplier autoDesignApplier,
Configuration config, Configuration config,
DesignConverter converter, DesignConverter converter,
ObjectManager objects, ActorObjectManager objects,
DesignManager designManager, DesignManager designManager,
ImportService importService, ImportService importService,
ICondition conditions, ICondition conditions,
@ -106,7 +104,7 @@ public class ActorPanel
{ {
using var group = ImRaii.Group(); using var group = ImRaii.Group();
(_identifier, _data) = _selector.Selection; (_identifier, _data) = _selector.Selection;
_lockedRedraw = _identifier.Type is IdentifierType.Special _lockedRedraw = _identifier.Type is IdentifierType.Special || _objects.IsInLobby
|| _conditions[ConditionFlag.OccupiedInCutSceneEvent]; || _conditions[ConditionFlag.OccupiedInCutSceneEvent];
(_actorName, _actor) = GetHeaderName(); (_actorName, _actor) = GetHeaderName();
DrawHeader(); DrawHeader();

View file

@ -1,7 +1,4 @@
using System.Security.AccessControl; using Dalamud.Interface;
using Dalamud.Interface;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
@ -9,11 +6,12 @@ using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Tabs.ActorTab; namespace Glamourer.Gui.Tabs.ActorTab;
public class ActorSelector(ObjectManager objects, ActorManager actors, EphemeralConfig config) public class ActorSelector(ActorObjectManager objects, ActorManager actors, EphemeralConfig config)
{ {
private ActorIdentifier _identifier = ActorIdentifier.Invalid; private ActorIdentifier _identifier = ActorIdentifier.Invalid;
@ -89,11 +87,10 @@ public class ActorSelector(ObjectManager objects, ActorManager actors, Ephemeral
if (!child) if (!child)
return; return;
objects.Update();
_world = new WorldId(objects.Player.Valid ? objects.Player.HomeWorld : (ushort)0); _world = new WorldId(objects.Player.Valid ? objects.Player.HomeWorld : (ushort)0);
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight()); var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
var remainder = ImGuiClip.FilteredClippedDraw(objects.Identifiers.Where(p => p.Value.Objects.Any(a => a.Model)), skips, CheckFilter, var remainder = ImGuiClip.FilteredClippedDraw(objects.Where(p => p.Value.Objects.Any(a => a.Model)), skips, CheckFilter,
DrawSelectable); DrawSelectable);
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight()); ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
} }

View file

@ -434,7 +434,7 @@ public class SetPanel(
if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0)) if (ImGui.SetDragDropPayload(dragDropLabel, nint.Zero, 0))
{ {
_dragIndex = index; _dragIndex = index;
_selector._dragDesignIndex = index; _selector.DragDesignIndex = index;
} }
} }
} }

View file

@ -2,12 +2,11 @@
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Glamourer.Automation; using Glamourer.Automation;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Actors; using Penumbra.GameData.Interop;
using Penumbra.String; using Penumbra.String;
using ImGuiClip = OtterGui.ImGuiClip; using ImGuiClip = OtterGui.ImGuiClip;
@ -18,8 +17,7 @@ public class SetSelector : IDisposable
private readonly Configuration _config; private readonly Configuration _config;
private readonly AutoDesignManager _manager; private readonly AutoDesignManager _manager;
private readonly AutomationChanged _event; private readonly AutomationChanged _event;
private readonly ActorManager _actors; private readonly ActorObjectManager _objects;
private readonly ObjectManager _objects;
private readonly List<(AutoDesignSet, int)> _list = []; private readonly List<(AutoDesignSet, int)> _list = [];
public AutoDesignSet? Selection { get; private set; } public AutoDesignSet? Selection { get; private set; }
@ -38,14 +36,13 @@ public class SetSelector : IDisposable
private int _dragIndex = -1; private int _dragIndex = -1;
private Action? _endAction; private Action? _endAction;
internal int _dragDesignIndex = -1; internal int DragDesignIndex = -1;
public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorManager actors, ObjectManager objects) public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorObjectManager objects)
{ {
_manager = manager; _manager = manager;
_event = @event; _event = @event;
_config = config; _config = config;
_actors = actors;
_objects = objects; _objects = objects;
_event.Subscribe(OnAutomationChange, AutomationChanged.Priority.SetSelector); _event.Subscribe(OnAutomationChange, AutomationChanged.Priority.SetSelector);
} }
@ -94,7 +91,7 @@ public class SetSelector : IDisposable
} }
private LowerString _filter = LowerString.Empty; private LowerString _filter = LowerString.Empty;
private uint _enabledFilter = 0; private uint _enabledFilter;
private float _width; private float _width;
private Vector2 _defaultItemSpacing; private Vector2 _defaultItemSpacing;
private Vector2 _selectableSize; private Vector2 _selectableSize;
@ -177,7 +174,6 @@ public class SetSelector : IDisposable
UpdateList(); UpdateList();
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
_selectableSize = new Vector2(0, 2 * ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y); _selectableSize = new Vector2(0, 2 * ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y);
_objects.Update();
ImGuiClip.ClippedDraw(_list, DrawSetSelectable, _selectableSize.Y + 2 * ImGui.GetStyle().ItemSpacing.Y); ImGuiClip.ClippedDraw(_list, DrawSetSelectable, _selectableSize.Y + 2 * ImGui.GetStyle().ItemSpacing.Y);
_endAction?.Invoke(); _endAction?.Invoke();
_endAction = null; _endAction = null;
@ -186,7 +182,7 @@ public class SetSelector : IDisposable
private void DrawSetSelectable((AutoDesignSet Set, int Index) pair) private void DrawSetSelectable((AutoDesignSet Set, int Index) pair)
{ {
using var id = ImRaii.PushId(pair.Index); using var id = ImRaii.PushId(pair.Index);
using (var color = ImRaii.PushColor(ImGuiCol.Text, pair.Set.Enabled ? ColorId.EnabledAutoSet.Value() : ColorId.DisabledAutoSet.Value())) using (ImRaii.PushColor(ImGuiCol.Text, pair.Set.Enabled ? ColorId.EnabledAutoSet.Value() : ColorId.DisabledAutoSet.Value()))
{ {
if (ImGui.Selectable(GetSetName(pair.Set, pair.Index), pair.Set == Selection, ImGuiSelectableFlags.None, _selectableSize)) if (ImGui.Selectable(GetSetName(pair.Set, pair.Index), pair.Set == Selection, ImGuiSelectableFlags.None, _selectableSize))
{ {
@ -285,9 +281,9 @@ public class SetSelector : IDisposable
private void NewSetButton(Vector2 size) private void NewSetButton(Vector2 size)
{ {
var id = _actors.GetCurrentPlayer(); var id = _objects.Actors.GetCurrentPlayer();
if (!id.IsValid) if (!id.IsValid)
id = _actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue); id = _objects.Actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue);
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), size, if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), size,
$"Create a new Automatic Design Set for {id}. The associated player can be changed later.", !id.IsValid, true)) $"Create a new Automatic Design Set for {id}. The associated player can be changed later.", !id.IsValid, true))
_manager.AddDesignSet("New Automation Set", id); _manager.AddDesignSet("New Automation Set", id);
@ -332,15 +328,15 @@ public class SetSelector : IDisposable
} }
else if (ImGuiUtil.IsDropping("DesignDragDrop")) else if (ImGuiUtil.IsDropping("DesignDragDrop"))
{ {
if (_dragDesignIndex >= 0) if (DragDesignIndex >= 0)
{ {
var idx = _dragDesignIndex; var idx = DragDesignIndex;
var setTo = set; var setTo = set;
var setFrom = Selection!; var setFrom = Selection!;
_endAction = () => _manager.MoveDesignToSet(setFrom, idx, setTo); _endAction = () => _manager.MoveDesignToSet(setFrom, idx, setTo);
} }
_dragDesignIndex = -1; DragDesignIndex = -1;
} }
} }
} }

View file

@ -1,18 +1,17 @@
using Dalamud.Interface; using Dalamud.Interface;
using Glamourer.GameData; using Glamourer.GameData;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer
{ {
public string Label public string Label
=> $"Active Actors ({_stateManager.Count})###Active Actors"; => $"Active Actors ({_stateManager.Count})###Active Actors";
@ -22,8 +21,7 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
public void Draw() public void Draw()
{ {
_objectManager.Update(); foreach (var (identifier, actors) in _objectManager)
foreach (var (identifier, actors) in _objectManager.Identifiers)
{ {
if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()), if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()),
string.Empty, !_stateManager.ContainsKey(identifier), true)) string.Empty, !_stateManager.ContainsKey(identifier), true))
@ -66,13 +64,15 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
static string ItemString(in DesignData data, EquipSlot slot) static string ItemString(in DesignData data, EquipSlot slot)
{ {
var item = data.Item(slot); var item = data.Item(slot);
return $"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})"; return
$"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
} }
static string BonusItemString(in DesignData data, BonusItemFlag slot) static string BonusItemString(in DesignData data, BonusItemFlag slot)
{ {
var item = data.BonusItem(slot); var item = data.BonusItem(slot);
return $"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})"; return
$"{item.Name} ({item.Id.ToDiscriminatingString()} {item.PrimaryId.Id}{(item.SecondaryId != 0 ? $"-{item.SecondaryId.Id}" : string.Empty)}-{item.Variant})";
} }
PrintRow("Model ID", state.BaseData.ModelId, state.ModelData.ModelId, state.Sources[MetaIndex.ModelId]); PrintRow("Model ID", state.BaseData.ModelId, state.ModelData.ModelId, state.Sources[MetaIndex.ModelId]);

View file

@ -1,13 +1,13 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using Glamourer.Interop;
using ImGuiNET; using ImGuiNET;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDataDrawer public unsafe class AdvancedCustomizationDrawer(ActorObjectManager objects) : IGameDataDrawer
{ {
public string Label public string Label
=> "Advanced Customizations"; => "Advanced Customizations";
@ -31,8 +31,8 @@ public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDa
return; return;
} }
DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0); DrawCBuffer("Customize"u8, model.AsHuman->CustomizeParameterCBuffer, 0);
DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1); DrawCBuffer("Decal"u8, model.AsHuman->DecalColorCBuffer, 1);
DrawCBuffer("Unk1"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA0), 2); DrawCBuffer("Unk1"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA0), 2);
DrawCBuffer("Unk2"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA8), 3); DrawCBuffer("Unk2"u8, *(ConstantBuffer**)((byte*)model.AsHuman + 0xBA8), 3);
} }

View file

@ -3,24 +3,25 @@ using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Text;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class GlamourPlatePanel : IGameDataDrawer public unsafe class GlamourPlatePanel : IGameDataDrawer
{ {
private readonly DesignManager _design; private readonly DesignManager _design;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
public string Label public string Label
=> "Glamour Plates"; => "Glamour Plates";
@ -28,7 +29,8 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
public bool Disabled public bool Disabled
=> false; => false;
public GlamourPlatePanel(IGameInteropProvider interop, ItemManager items, DesignManager design, StateManager state, ObjectManager objects) public GlamourPlatePanel(IGameInteropProvider interop, ItemManager items, DesignManager design, StateManager state,
ActorObjectManager objects)
{ {
_items = items; _items = items;
_design = design; _design = design;
@ -42,24 +44,24 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
var manager = MirageManager.Instance(); var manager = MirageManager.Instance();
using (ImRaii.Group()) using (ImRaii.Group())
{ {
ImGui.TextUnformatted("Address:"); ImUtf8.Text("Address:"u8);
ImGui.TextUnformatted("Number of Glamour Plates:"); ImUtf8.Text("Number of Glamour Plates:"u8);
ImGui.TextUnformatted("Glamour Plates Requested:"); ImUtf8.Text("Glamour Plates Requested:"u8);
ImGui.TextUnformatted("Glamour Plates Loaded:"); ImUtf8.Text("Glamour Plates Loaded:"u8);
ImGui.TextUnformatted("Is Applying Glamour Plates:"); ImUtf8.Text("Is Applying Glamour Plates:"u8);
} }
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.Group()) using (ImRaii.Group())
{ {
ImGuiUtil.CopyOnClickSelectable($"0x{(ulong)manager:X}"); ImUtf8.CopyOnClickSelectable($"0x{(ulong)manager:X}");
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlates.Length.ToString()); ImUtf8.Text(manager == null ? "-" : manager->GlamourPlates.Length.ToString());
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesRequested.ToString()); ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesRequested.ToString());
ImGui.SameLine(); ImGui.SameLine();
if (ImGui.SmallButton("Request Update")) if (ImUtf8.SmallButton("Request Update"u8))
RequestGlamour(); RequestGlamour();
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString()); ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString());
ImGui.TextUnformatted(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString()); ImUtf8.Text(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString());
} }
if (manager == null) if (manager == null)
@ -71,12 +73,12 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
for (var i = 0; i < manager->GlamourPlates.Length; ++i) for (var i = 0; i < manager->GlamourPlates.Length; ++i)
{ {
using var tree = ImRaii.TreeNode($"Plate #{i + 1:D2}"); using var tree = ImUtf8.TreeNode($"Plate #{i + 1:D2}");
if (!tree) if (!tree)
continue; continue;
ref var plate = ref manager->GlamourPlates[i]; ref var plate = ref manager->GlamourPlates[i];
if (ImGuiUtil.DrawDisabledButton("Apply to Player", Vector2.Zero, string.Empty, !enabled)) if (ImUtf8.ButtonEx("Apply to Player"u8, ""u8, Vector2.Zero, !enabled))
{ {
var design = CreateDesign(plate); var design = CreateDesign(plate);
_state.ApplyDesign(state!, design, ApplySettings.Manual with { IsFinal = true }); _state.ApplyDesign(state!, design, ApplySettings.Manual with { IsFinal = true });
@ -85,14 +87,14 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
using (ImRaii.Group()) using (ImRaii.Group())
{ {
foreach (var slot in EquipSlotExtensions.FullSlots) foreach (var slot in EquipSlotExtensions.FullSlots)
ImGui.TextUnformatted(slot.ToName()); ImUtf8.Text(slot.ToName());
} }
ImGui.SameLine(); ImGui.SameLine();
using (ImRaii.Group()) using (ImRaii.Group())
{ {
foreach (var (_, index) in EquipSlotExtensions.FullSlots.WithIndex()) foreach (var (_, index) in EquipSlotExtensions.FullSlots.WithIndex())
ImGui.TextUnformatted($"{plate.ItemIds[index]:D6}, {StainIds.FromGlamourPlate(plate, index)}"); ImUtf8.Text($"{plate.ItemIds[index]:D6}, {StainIds.FromGlamourPlate(plate, index)}");
} }
} }
} }

View file

@ -11,12 +11,11 @@ using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class ModelEvaluationPanel( public unsafe class ModelEvaluationPanel(
ObjectManager _objectManager, ActorObjectManager _objectManager,
VisorService _visorService, VisorService _visorService,
UpdateSlotService _updateSlotService, UpdateSlotService _updateSlotService,
ChangeCustomizeService _changeCustomizeService, ChangeCustomizeService _changeCustomizeService,
@ -34,7 +33,7 @@ public unsafe class ModelEvaluationPanel(
public void Draw() public void Draw()
{ {
ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0); ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0);
var actor = _objectManager[_gameObjectIndex]; var actor = _objectManager.Objects[_gameObjectIndex];
var model = actor.Model; var model = actor.Model;
using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
ImGui.TableNextColumn(); ImGui.TableNextColumn();

View file

@ -3,18 +3,18 @@ using Dalamud.Interface.Utility;
using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.GameData; using Glamourer.GameData;
using Glamourer.Interop;
using Glamourer.State; using Glamourer.State;
using ImGuiNET; using ImGuiNET;
using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
using ImGuiClip = OtterGui.ImGuiClip; using ImGuiClip = OtterGui.ImGuiClip;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectManager _objectManager, DesignConverter _designConverter) public class NpcAppearancePanel(NpcCombo npcCombo, StateManager stateManager, ActorObjectManager objectManager, DesignConverter designConverter)
: IGameDataDrawer : IGameDataDrawer
{ {
public string Label public string Label
@ -28,9 +28,9 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
public void Draw() public void Draw()
{ {
ImGui.Checkbox("Compare Customize (or Gear)", ref _customizeOrGear); ImUtf8.Checkbox("Compare Customize (or Gear)"u8, ref _customizeOrGear);
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
var resetScroll = ImGui.InputTextWithHint("##npcFilter", "Filter...", ref _npcFilter, 64); var resetScroll = ImUtf8.InputText("##npcFilter"u8, ref _npcFilter, "Filter..."u8);
using var table = ImRaii.Table("npcs", 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit, using var table = ImRaii.Table("npcs", 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit,
new Vector2(-1, 400 * ImGuiHelpers.GlobalScale)); new Vector2(-1, 400 * ImGuiHelpers.GlobalScale));
@ -40,19 +40,19 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
if (resetScroll) if (resetScroll)
ImGui.SetScrollY(0); ImGui.SetScrollY(0);
ImGui.TableSetupColumn("Button", ImGuiTableColumnFlags.WidthFixed); ImUtf8.TableSetupColumn("Button"u8, ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300); ImUtf8.TableSetupColumn("Name"u8, ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300);
ImGui.TableSetupColumn("Kind", ImGuiTableColumnFlags.WidthFixed); ImUtf8.TableSetupColumn("Kind"u8, ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed); ImUtf8.TableSetupColumn("Id"u8, ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Model", ImGuiTableColumnFlags.WidthFixed); ImUtf8.TableSetupColumn("Model"u8, ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Visor", ImGuiTableColumnFlags.WidthFixed); ImUtf8.TableSetupColumn("Visor"u8, ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Compare", ImGuiTableColumnFlags.WidthStretch); ImUtf8.TableSetupColumn("Compare"u8, ImGuiTableColumnFlags.WidthStretch);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetFrameHeightWithSpacing()); var skips = ImGuiClip.GetNecessarySkips(ImGui.GetFrameHeightWithSpacing());
ImGui.TableNextRow(); ImGui.TableNextRow();
var idx = 0; var idx = 0;
var remainder = ImGuiClip.FilteredClippedDraw(_npcCombo.Items, skips, var remainder = ImGuiClip.FilteredClippedDraw(npcCombo.Items, skips,
d => d.Name.Contains(_npcFilter, StringComparison.OrdinalIgnoreCase), DrawData); d => d.Name.Contains(_npcFilter, StringComparison.OrdinalIgnoreCase), DrawData);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGuiClip.DrawEndDummy(remainder, ImGui.GetFrameHeightWithSpacing()); ImGuiClip.DrawEndDummy(remainder, ImGui.GetFrameHeightWithSpacing());
@ -61,43 +61,31 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
void DrawData(NpcData data) void DrawData(NpcData data)
{ {
using var id = ImRaii.PushId(idx++); using var id = ImRaii.PushId(idx++);
var disabled = !_state.GetOrCreate(_objectManager.Player, out var state); var disabled = !stateManager.GetOrCreate(objectManager.Player, out var state);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (ImGuiUtil.DrawDisabledButton("Apply", Vector2.Zero, string.Empty, disabled)) if (ImUtf8.ButtonEx("Apply"u8, ""u8, Vector2.Zero, disabled))
{ {
foreach (var (slot, item, stain) in _designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true)) foreach (var (slot, item, stain) in designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true))
_state.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual); stateManager.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual);
_state.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual); stateManager.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual);
_state.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual); stateManager.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual);
} }
ImGui.TableNextColumn(); ImUtf8.DrawFrameColumn(data.Name);
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Name);
ImGui.TableNextColumn(); ImUtf8.DrawFrameColumn(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
ImGui.TableNextColumn(); ImUtf8.DrawFrameColumn(data.Id.Id.ToString());
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Id.Id.ToString());
ImGui.TableNextColumn(); ImUtf8.DrawFrameColumn(data.ModelId.ToString());
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.ModelId.ToString());
using (_ = ImRaii.PushFont(UiBuilder.IconFont)) using (_ = ImRaii.PushFont(UiBuilder.IconFont))
{ {
ImGui.TableNextColumn(); ImUtf8.DrawFrameColumn(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
} }
using var mono = ImRaii.PushFont(UiBuilder.MonoFont); using var mono = ImRaii.PushFont(UiBuilder.MonoFont);
ImGui.TableNextColumn(); ImUtf8.DrawFrameColumn(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
} }
} }
} }

View file

@ -1,13 +1,13 @@
using Glamourer.Interop; using ImGuiNET;
using ImGuiNET;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Text;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _actors) : IGameDataDrawer public class ObjectManagerPanel(ActorObjectManager _objectManager, ActorManager _actors) : IGameDataDrawer
{ {
public string Label public string Label
=> "Object Manager"; => "Object Manager";
@ -19,44 +19,45 @@ public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _acto
public void Draw() public void Draw()
{ {
_objectManager.Update(); _objectManager.Objects.DrawDebug();
using (var table = ImRaii.Table("##data", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
using (var table = ImUtf8.Table("##data"u8, 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
{ {
if (!table) if (!table)
return; return;
ImGuiUtil.DrawTableColumn("Last Update"); ImUtf8.DrawTableColumn("World"u8);
ImGuiUtil.DrawTableColumn(_objectManager.LastUpdate.ToString(CultureInfo.InvariantCulture)); ImUtf8.DrawTableColumn(_actors.Finished ? _actors.Data.ToWorldName(_objectManager.World) : "Service Missing");
ImUtf8.DrawTableColumn(_objectManager.World.ToString());
ImUtf8.DrawTableColumn("Player Character"u8);
ImUtf8.DrawTableColumn($"{_objectManager.Player.Utf8Name} ({_objectManager.Player.Index})");
ImGui.TableNextColumn();
ImUtf8.CopyOnClickSelectable(_objectManager.Player.ToString());
ImUtf8.DrawTableColumn("In GPose"u8);
ImUtf8.DrawTableColumn(_objectManager.IsInGPose.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGuiUtil.DrawTableColumn("World"); ImUtf8.DrawTableColumn("In Lobby"u8);
ImGuiUtil.DrawTableColumn(_actors.Finished ? _actors.Data.ToWorldName(_objectManager.World) : "Service Missing"); ImUtf8.DrawTableColumn(_objectManager.IsInLobby.ToString());
ImGuiUtil.DrawTableColumn(_objectManager.World.ToString());
ImGuiUtil.DrawTableColumn("Player Character");
ImGuiUtil.DrawTableColumn($"{_objectManager.Player.Utf8Name} ({_objectManager.Player.Index})");
ImGui.TableNextColumn();
ImGuiUtil.CopyOnClickSelectable(_objectManager.Player.ToString());
ImGuiUtil.DrawTableColumn("In GPose");
ImGuiUtil.DrawTableColumn(_objectManager.IsInGPose.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (_objectManager.IsInGPose) if (_objectManager.IsInGPose)
{ {
ImGuiUtil.DrawTableColumn("GPose Player"); ImUtf8.DrawTableColumn("GPose Player"u8);
ImGuiUtil.DrawTableColumn($"{_objectManager.GPosePlayer.Utf8Name} ({_objectManager.GPosePlayer.Index})"); ImUtf8.DrawTableColumn($"{_objectManager.GPosePlayer.Utf8Name} ({_objectManager.GPosePlayer.Index})");
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGuiUtil.CopyOnClickSelectable(_objectManager.GPosePlayer.ToString()); ImUtf8.CopyOnClickSelectable(_objectManager.GPosePlayer.ToString());
} }
ImGuiUtil.DrawTableColumn("Number of Players"); ImUtf8.DrawTableColumn("Number of Players"u8);
ImGuiUtil.DrawTableColumn(_objectManager.Count.ToString()); ImUtf8.DrawTableColumn(_objectManager.Count.ToString());
ImGui.TableNextColumn(); ImGui.TableNextColumn();
} }
var filterChanged = ImGui.InputTextWithHint("##Filter", "Filter...", ref _objectFilter, 64); var filterChanged = ImUtf8.InputText("##Filter"u8, ref _objectFilter, "Filter..."u8);
using var table2 = ImRaii.Table("##data2", 3, using var table2 = ImUtf8.Table("##data2"u8, 3,
ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.ScrollY, ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.ScrollY,
new Vector2(-1, 20 * ImGui.GetTextLineHeightWithSpacing())); new Vector2(-1, 20 * ImGui.GetTextLineHeightWithSpacing()));
if (!table2) if (!table2)
@ -69,13 +70,13 @@ public class ObjectManagerPanel(ObjectManager _objectManager, ActorManager _acto
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing()); var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
ImGui.TableNextRow(); ImGui.TableNextRow();
var remainder = ImGuiClip.FilteredClippedDraw(_objectManager.Identifiers, skips, var remainder = ImGuiClip.FilteredClippedDraw(_objectManager, skips,
p => p.Value.Label.Contains(_objectFilter, StringComparison.OrdinalIgnoreCase), p p => p.Value.Label.Contains(_objectFilter, StringComparison.OrdinalIgnoreCase), p
=> =>
{ {
ImGuiUtil.DrawTableColumn(p.Key.ToString()); ImUtf8.DrawTableColumn(p.Key.ToString());
ImGuiUtil.DrawTableColumn(p.Value.Label); ImUtf8.DrawTableColumn(p.Value.Label);
ImGuiUtil.DrawTableColumn(string.Join(", ", p.Value.Objects.OrderBy(a => a.Index).Select(a => a.Index.ToString()))); ImUtf8.DrawTableColumn(string.Join(", ", p.Value.Objects.OrderBy(a => a.Index).Select(a => a.Index.ToString())));
}); });
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeightWithSpacing()); ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeightWithSpacing());
} }

View file

@ -3,10 +3,11 @@ using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.GameData.Gui.Debug; using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab; namespace Glamourer.Gui.Tabs.DebugTab;
public class RetainedStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer public class RetainedStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer
{ {
public string Label public string Label
=> "Retained States (Inactive Actors)"; => "Retained States (Inactive Actors)";

View file

@ -18,6 +18,7 @@ using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using static Glamourer.Gui.Tabs.HeaderDrawer; using static Glamourer.Gui.Tabs.HeaderDrawer;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
@ -28,7 +29,7 @@ public class DesignPanel
private readonly DesignFileSystemSelector _selector; private readonly DesignFileSystemSelector _selector;
private readonly CustomizationDrawer _customizationDrawer; private readonly CustomizationDrawer _customizationDrawer;
private readonly DesignManager _manager; private readonly DesignManager _manager;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly StateManager _state; private readonly StateManager _state;
private readonly EquipmentDrawer _equipmentDrawer; private readonly EquipmentDrawer _equipmentDrawer;
private readonly ModAssociationsTab _modAssociations; private readonly ModAssociationsTab _modAssociations;
@ -48,7 +49,7 @@ public class DesignPanel
public DesignPanel(DesignFileSystemSelector selector, public DesignPanel(DesignFileSystemSelector selector,
CustomizationDrawer customizationDrawer, CustomizationDrawer customizationDrawer,
DesignManager manager, DesignManager manager,
ObjectManager objects, ActorObjectManager objects,
StateManager state, StateManager state,
EquipmentDrawer equipmentDrawer, EquipmentDrawer equipmentDrawer,
ModAssociationsTab modAssociations, ModAssociationsTab modAssociations,
@ -360,6 +361,7 @@ public class DesignPanel
equip = false; equip = false;
customize = true; customize = true;
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteDesignModifier} while clicking."); ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteDesignModifier} while clicking.");
@ -371,6 +373,7 @@ public class DesignPanel
_manager.ChangeApplyMulti(_selector.Selected!, true, true, true, false, true, true, false, true); _manager.ChangeApplyMulti(_selector.Selected!, true, true, true, false, true, true, false, true);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.Wetness, false); _manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.Wetness, false);
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteDesignModifier} while clicking."); ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteDesignModifier} while clicking.");
@ -386,7 +389,8 @@ public class DesignPanel
if (equip is null && customize is null) if (equip is null && customize is null)
return; return;
_manager.ChangeApplyMulti(_selector.Selected!, equip, customize, equip, customize.HasValue && !customize.Value ? false : null, null, equip, equip, equip); _manager.ChangeApplyMulti(_selector.Selected!, equip, customize, equip, customize.HasValue && !customize.Value ? false : null, null,
equip, equip, equip);
if (equip.HasValue) if (equip.HasValue)
{ {
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.HatState, equip.Value); _manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.HatState, equip.Value);

View file

@ -5,7 +5,6 @@ using Glamourer.Designs;
using Glamourer.Gui.Customization; using Glamourer.Gui.Customization;
using Glamourer.Gui.Equipment; using Glamourer.Gui.Equipment;
using Glamourer.Gui.Tabs.DesignTab; using Glamourer.Gui.Tabs.DesignTab;
using Glamourer.Interop;
using Glamourer.State; using Glamourer.State;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
@ -13,6 +12,7 @@ using OtterGui.Classes;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Text; using OtterGui.Text;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using static Glamourer.Gui.Tabs.HeaderDrawer; using static Glamourer.Gui.Tabs.HeaderDrawer;
namespace Glamourer.Gui.Tabs.NpcTab; namespace Glamourer.Gui.Tabs.NpcTab;
@ -30,7 +30,7 @@ public class NpcPanel
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly DesignColors _colors; private readonly DesignColors _colors;
private readonly Button[] _leftButtons; private readonly Button[] _leftButtons;
private readonly Button[] _rightButtons; private readonly Button[] _rightButtons;
@ -42,7 +42,7 @@ public class NpcPanel
DesignConverter converter, DesignConverter converter,
DesignManager designManager, DesignManager designManager,
StateManager state, StateManager state,
ObjectManager objects, ActorObjectManager objects,
DesignColors colors, DesignColors colors,
Configuration config) Configuration config)
{ {

View file

@ -6,14 +6,14 @@ using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using ObjectManager = Glamourer.Interop.ObjectManager; using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.SettingsTab; namespace Glamourer.Gui.Tabs.SettingsTab;
public class CollectionOverrideDrawer( public class CollectionOverrideDrawer(
CollectionOverrideService collectionOverrides, CollectionOverrideService collectionOverrides,
Configuration config, Configuration config,
ObjectManager objects, ActorObjectManager objects,
ActorManager actors, ActorManager actors,
PenumbraService penumbra, PenumbraService penumbra,
CollectionCombo combo) : IService CollectionCombo combo) : IService
@ -61,7 +61,8 @@ public class CollectionOverrideDrawer(
DrawActorIdentifier(idx, actor); DrawActorIdentifier(idx, actor);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (combo.Draw("##collection", name, $"Select the overriding collection. Current GUID:", ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight())) if (combo.Draw("##collection", name, $"Select the overriding collection. Current GUID:", ImGui.GetContentRegionAvail().X,
ImGui.GetTextLineHeight()))
{ {
var (guid, _, newName) = combo.CurrentSelection; var (guid, _, newName) = combo.CurrentSelection;
collectionOverrides.ChangeOverride(idx, guid, newName); collectionOverrides.ChangeOverride(idx, guid, newName);
@ -69,7 +70,7 @@ public class CollectionOverrideDrawer(
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
{ {
using var tt = ImRaii.Tooltip(); using var tt = ImRaii.Tooltip();
using var font = ImRaii.PushFont(UiBuilder.MonoFont); using var font = ImRaii.PushFont(UiBuilder.MonoFont);
ImGui.TextUnformatted($" {collection}"); ImGui.TextUnformatted($" {collection}");
} }
@ -102,7 +103,7 @@ public class CollectionOverrideDrawer(
return; return;
using var tt2 = ImRaii.Tooltip(); using var tt2 = ImRaii.Tooltip();
using var f = ImRaii.PushFont(UiBuilder.MonoFont); using var f = ImRaii.PushFont(UiBuilder.MonoFont);
ImGui.TextUnformatted(collection.ToString()); ImGui.TextUnformatted(collection.ToString());
} }
@ -146,7 +147,7 @@ public class CollectionOverrideDrawer(
} }
catch (ActorIdentifierFactory.IdentifierParseError e) catch (ActorIdentifierFactory.IdentifierParseError e)
{ {
_exception = e; _exception = e;
_identifiers = []; _identifiers = [];
} }

View file

@ -5,6 +5,7 @@ using Glamourer.Designs;
using Glamourer.Services; using Glamourer.Services;
using Glamourer.State; using Glamourer.State;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Interop; namespace Glamourer.Interop;
@ -13,16 +14,16 @@ public class ContextMenuService : IDisposable
{ {
public const int ChatLogContextItemId = 0x958; public const int ChatLogContextItemId = 0x958;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly IContextMenu _contextMenu; private readonly IContextMenu _contextMenu;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private EquipItem _lastItem; private EquipItem _lastItem;
private readonly StainId[] _lastStains = new StainId[StainId.NumStains]; private readonly StainId[] _lastStains = new StainId[StainId.NumStains];
private readonly MenuItem _inventoryItem; private readonly MenuItem _inventoryItem;
public ContextMenuService(ItemManager items, StateManager state, ObjectManager objects, Configuration config, public ContextMenuService(ItemManager items, StateManager state, ActorObjectManager objects, Configuration config,
IContextMenu context) IContextMenu context)
{ {
_contextMenu = context; _contextMenu = context;

View file

@ -1,209 +0,0 @@
using Dalamud.Game.ClientState.Objects;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Control;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using OtterGui.Log;
using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
namespace Glamourer.Interop;
public class ObjectManager(
IFramework framework,
IClientState clientState,
IObjectTable objects,
IDalamudPluginInterface pi,
Logger log,
ActorManager actors,
ITargetManager targets)
: global::Penumbra.GameData.Interop.ObjectManager(pi, log, framework, objects)
{
public DateTime LastUpdate
=> LastFrame;
private DateTime _identifierUpdate;
public bool IsInGPose
=> clientState.IsGPosing;
public ushort World { get; private set; }
private readonly Dictionary<ActorIdentifier, ActorData> _identifiers = new(200);
private readonly Dictionary<ActorIdentifier, ActorData> _allWorldIdentifiers = new(200);
private readonly Dictionary<ActorIdentifier, ActorData> _nonOwnedIdentifiers = new(200);
public IReadOnlyDictionary<ActorIdentifier, ActorData> Identifiers
=> _identifiers;
public override bool Update()
{
if (!base.Update() && _identifierUpdate >= LastUpdate)
return false;
_identifierUpdate = LastUpdate;
World = (ushort)(Player.Valid ? Player.HomeWorld : 0);
_identifiers.Clear();
_allWorldIdentifiers.Clear();
_nonOwnedIdentifiers.Clear();
foreach (var actor in BattleNpcs.Concat(CutsceneCharacters))
{
if (actor.Identifier(actors, out var identifier))
HandleIdentifier(identifier, actor);
}
void AddSpecial(ScreenActor idx, string label)
{
var actor = this[(int)idx];
if (actor.Identifier(actors, out var ident))
{
var data = new ActorData(actor, label);
_identifiers.Add(ident, data);
}
}
AddSpecial(ScreenActor.CharacterScreen, "Character Screen Actor");
AddSpecial(ScreenActor.ExamineScreen, "Examine Screen Actor");
AddSpecial(ScreenActor.FittingRoom, "Fitting Room Actor");
AddSpecial(ScreenActor.DyePreview, "Dye Preview Actor");
AddSpecial(ScreenActor.Portrait, "Portrait Actor");
AddSpecial(ScreenActor.Card6, "Card Actor 6");
AddSpecial(ScreenActor.Card7, "Card Actor 7");
AddSpecial(ScreenActor.Card8, "Card Actor 8");
foreach (var actor in EventNpcs)
{
if (actor.Identifier(actors, out var identifier))
HandleIdentifier(identifier, actor);
}
return true;
}
private void HandleIdentifier(ActorIdentifier identifier, Actor character)
{
if (!identifier.IsValid)
return;
if (!_identifiers.TryGetValue(identifier, out var data))
{
data = new ActorData(character, identifier.ToString());
_identifiers[identifier] = data;
}
else
{
data.Objects.Add(character);
}
if (identifier.Type is IdentifierType.Player or IdentifierType.Owned)
{
var allWorld = actors.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, ushort.MaxValue,
identifier.Kind,
identifier.DataId);
if (!_allWorldIdentifiers.TryGetValue(allWorld, out var allWorldData))
{
allWorldData = new ActorData(character, allWorld.ToString());
_allWorldIdentifiers[allWorld] = allWorldData;
}
else
{
allWorldData.Objects.Add(character);
}
}
if (identifier.Type is IdentifierType.Owned)
{
var nonOwned = actors.CreateNpc(identifier.Kind, identifier.DataId);
if (!_nonOwnedIdentifiers.TryGetValue(nonOwned, out var nonOwnedData))
{
nonOwnedData = new ActorData(character, nonOwned.ToString());
_nonOwnedIdentifiers[nonOwned] = nonOwnedData;
}
else
{
nonOwnedData.Objects.Add(character);
}
}
}
public Actor GPosePlayer
=> this[(int)ScreenActor.GPosePlayer];
public Actor Player
=> this[0];
public unsafe Actor Target
=> clientState.IsGPosing ? TargetSystem.Instance()->GPoseTarget : TargetSystem.Instance()->Target;
public Actor Focus
=> targets.FocusTarget?.Address ?? nint.Zero;
public Actor MouseOver
=> targets.MouseOverTarget?.Address ?? nint.Zero;
public (ActorIdentifier Identifier, ActorData Data) PlayerData
{
get
{
Update();
return Player.Identifier(actors, out var ident) && _identifiers.TryGetValue(ident, out var data)
? (ident, data)
: (ident, ActorData.Invalid);
}
}
public (ActorIdentifier Identifier, ActorData Data) TargetData
{
get
{
Update();
return Target.Identifier(actors, out var ident) && _identifiers.TryGetValue(ident, out var data)
? (ident, data)
: (ident, ActorData.Invalid);
}
}
/// <summary> Also handles All Worlds players and non-owned NPCs. </summary>
public bool ContainsKey(ActorIdentifier key)
=> Identifiers.ContainsKey(key) || _allWorldIdentifiers.ContainsKey(key) || _nonOwnedIdentifiers.ContainsKey(key);
public bool TryGetValue(ActorIdentifier key, out ActorData value)
=> Identifiers.TryGetValue(key, out value);
public bool TryGetValueAllWorld(ActorIdentifier key, out ActorData value)
=> _allWorldIdentifiers.TryGetValue(key, out value);
public bool TryGetValueNonOwned(ActorIdentifier key, out ActorData value)
=> _nonOwnedIdentifiers.TryGetValue(key, out value);
public ActorData this[ActorIdentifier key]
=> Identifiers[key];
public IEnumerable<ActorIdentifier> Keys
=> Identifiers.Keys;
public IEnumerable<ActorData> Values
=> Identifiers.Values;
public bool GetName(string lowerName, out Actor actor)
{
(actor, var ret) = lowerName switch
{
"" => (Actor.Null, true),
"<me>" => (Player, true),
"self" => (Player, true),
"<t>" => (Target, true),
"target" => (Target, true),
"<f>" => (Focus, true),
"focus" => (Focus, true),
"<mo>" => (MouseOver, true),
"mouseover" => (MouseOver, true),
_ => (Actor.Null, false),
};
return ret;
}
}

View file

@ -7,7 +7,7 @@ using Penumbra.GameData.Structs;
namespace Glamourer.Interop.Penumbra; namespace Glamourer.Interop.Penumbra;
public class ModSettingApplier(PenumbraService penumbra, PenumbraAutoRedrawSkip autoRedrawSkip, Configuration config, ObjectManager objects, CollectionOverrideService overrides) public class ModSettingApplier(PenumbraService penumbra, PenumbraAutoRedrawSkip autoRedrawSkip, Configuration config, ActorObjectManager objects, CollectionOverrideService overrides)
: IService : IService
{ {
private readonly HashSet<Guid> _collectionTracker = []; private readonly HashSet<Guid> _collectionTracker = [];
@ -17,7 +17,6 @@ public class ModSettingApplier(PenumbraService penumbra, PenumbraAutoRedrawSkip
if (!config.AlwaysApplyAssociatedMods || (design.AssociatedMods.Count == 0 && !design.ResetTemporarySettings)) if (!config.AlwaysApplyAssociatedMods || (design.AssociatedMods.Count == 0 && !design.ResetTemporarySettings))
return; return;
objects.Update();
if (!objects.TryGetValue(state.Identifier, out var data)) if (!objects.TryGetValue(state.Identifier, out var data))
{ {
Glamourer.Log.Verbose( Glamourer.Log.Verbose(

View file

@ -2,11 +2,11 @@
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using Glamourer.Designs.History; using Glamourer.Designs.History;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Interop;
namespace Glamourer.Interop.Penumbra; namespace Glamourer.Interop.Penumbra;
@ -16,13 +16,14 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
private readonly Configuration _config; private readonly Configuration _config;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
private readonly StateManager _state; private readonly StateManager _state;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly IFramework _framework; private readonly IFramework _framework;
private readonly StateChanged _stateChanged; private readonly StateChanged _stateChanged;
private readonly PenumbraAutoRedrawSkip _skip; private readonly PenumbraAutoRedrawSkip _skip;
public PenumbraAutoRedraw(PenumbraService penumbra, Configuration config, StateManager state, ObjectManager objects, IFramework framework, public PenumbraAutoRedraw(PenumbraService penumbra, Configuration config, StateManager state, ActorObjectManager objects,
IFramework framework,
StateChanged stateChanged, PenumbraAutoRedrawSkip skip) StateChanged stateChanged, PenumbraAutoRedrawSkip skip)
{ {
_penumbra = penumbra; _penumbra = penumbra;
@ -78,7 +79,6 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
{ {
_framework.RunOnFrameworkThread(() => _framework.RunOnFrameworkThread(() =>
{ {
_objects.Update();
foreach (var (id, state) in _state) foreach (var (id, state) in _state)
{ {
if (!_objects.TryGetValue(id, out var actors) || !actors.Valid) if (!_objects.TryGetValue(id, out var actors) || !actors.Valid)

View file

@ -1,47 +0,0 @@
using OtterGui.Log;
using Penumbra.GameData.Interop;
namespace Glamourer.Interop.Structs;
/// <summary>
/// A single actor with its label and the list of associated game objects.
/// </summary>
public readonly struct ActorData
{
public readonly List<Actor> Objects;
public readonly string Label;
public bool Valid
=> Objects.Count > 0;
public ActorData(Actor actor, string label)
{
Objects = [actor];
Label = label;
}
public static readonly ActorData Invalid = new(false);
private ActorData(bool _)
{
Objects = [];
Label = string.Empty;
}
public LazyString ToLazyString(string invalid)
{
var objects = Objects;
return Valid
? new LazyString(() => string.Join(", ", objects.Select(o => o.ToString())))
: new LazyString(() => invalid);
}
private ActorData(List<Actor> objects, string label)
{
Objects = objects;
Label = label;
}
public ActorData OnlyGPose()
=> new(Objects.Where(o => o.IsGPoseOrCutscene).ToList(), Label);
}

View file

@ -17,7 +17,6 @@ using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Services; namespace Glamourer.Services;
@ -26,24 +25,24 @@ public class CommandService : IDisposable, IApiService
private const string MainCommandString = "/glamourer"; private const string MainCommandString = "/glamourer";
private const string ApplyCommandString = "/glamour"; private const string ApplyCommandString = "/glamour";
private readonly ICommandManager _commands; private readonly ICommandManager _commands;
private readonly MainWindow _mainWindow; private readonly MainWindow _mainWindow;
private readonly IChatGui _chat; private readonly IChatGui _chat;
private readonly ActorManager _actors; private readonly ActorManager _actors;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier; private readonly AutoDesignApplier _autoDesignApplier;
private readonly AutoDesignManager _autoDesignManager; private readonly AutoDesignManager _autoDesignManager;
private readonly Configuration _config; private readonly Configuration _config;
private readonly ModSettingApplier _modApplier; private readonly ModSettingApplier _modApplier;
private readonly ItemManager _items; private readonly ItemManager _items;
private readonly CustomizeService _customizeService; private readonly CustomizeService _customizeService;
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly DesignConverter _converter; private readonly DesignConverter _converter;
private readonly DesignResolver _resolver; private readonly DesignResolver _resolver;
private readonly PenumbraService _penumbra; private readonly PenumbraService _penumbra;
public CommandService(ICommandManager commands, MainWindow mainWindow, IChatGui chat, ActorManager actors, ObjectManager objects, public CommandService(ICommandManager commands, MainWindow mainWindow, IChatGui chat, ActorManager actors, ActorObjectManager objects,
AutoDesignApplier autoDesignApplier, StateManager stateManager, DesignManager designManager, DesignConverter converter, AutoDesignApplier autoDesignApplier, StateManager stateManager, DesignManager designManager, DesignConverter converter,
DesignFileSystem designFileSystem, AutoDesignManager autoDesignManager, Configuration config, ModSettingApplier modApplier, DesignFileSystem designFileSystem, AutoDesignManager autoDesignManager, Configuration config, ModSettingApplier modApplier,
ItemManager items, RandomDesignGenerator randomDesign, CustomizeService customizeService, DesignFileSystemSelector designSelector, ItemManager items, RandomDesignGenerator randomDesign, CustomizeService customizeService, DesignFileSystemSelector designSelector,
@ -181,7 +180,9 @@ public class CommandService : IDisposable, IApiService
_chat.Print(new SeStringBuilder().AddText("Use with /glamour clearsettings ").AddGreen("[Character Identifier]").AddText(" | ") _chat.Print(new SeStringBuilder().AddText("Use with /glamour clearsettings ").AddGreen("[Character Identifier]").AddText(" | ")
.AddPurple("<true or false>").AddText(" | ").AddBlue("<true or false>").BuiltString); .AddPurple("<true or false>").AddText(" | ").AddBlue("<true or false>").BuiltString);
PlayerIdentifierHelp(false, true); PlayerIdentifierHelp(false, true);
_chat.Print(new SeStringBuilder().AddText(" 》 The character identifier specifies the collection to clear settings from. It also accepts '").AddGreen("all").AddText("' to clear all collections.").BuiltString); _chat.Print(new SeStringBuilder()
.AddText(" 》 The character identifier specifies the collection to clear settings from. It also accepts '").AddGreen("all")
.AddText("' to clear all collections.").BuiltString);
_chat.Print(new SeStringBuilder().AddText(" 》 The booleans are optional and default to 'true', the ").AddPurple("first") _chat.Print(new SeStringBuilder().AddText(" 》 The booleans are optional and default to 'true', the ").AddPurple("first")
.AddText(" determines whether ").AddPurple("manually").AddText(" applied settings are cleared, the ").AddBlue("second") .AddText(" determines whether ").AddPurple("manually").AddText(" applied settings are cleared, the ").AddBlue("second")
.AddText(" determines whether ").AddBlue("automatically").AddText(" applied settings are cleared.").BuiltString); .AddText(" determines whether ").AddBlue("automatically").AddText(" applied settings are cleared.").BuiltString);
@ -372,7 +373,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(argument, out var identifiers, false, true)) if (!IdentifierHandling(argument, out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_objects.TryGetValue(identifier, out var data)) if (!_objects.TryGetValue(identifier, out var data))
@ -425,7 +425,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(argument, out var identifiers, false, true)) if (!IdentifierHandling(argument, out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_objects.TryGetValue(identifier, out var data)) if (!_objects.TryGetValue(identifier, out var data))
@ -485,7 +484,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(split[1], out var identifiers, false, true)) if (!IdentifierHandling(split[1], out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_objects.TryGetValue(identifier, out var actors)) if (!_objects.TryGetValue(identifier, out var actors))
@ -568,7 +566,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(split[1], out var identifiers, false, true)) if (!IdentifierHandling(split[1], out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_objects.TryGetValue(identifier, out var actors)) if (!_objects.TryGetValue(identifier, out var actors))
@ -716,7 +713,6 @@ public class CommandService : IDisposable, IApiService
if (!_resolver.GetDesign(split[0], out var design, true) || !IdentifierHandling(split2[0], out var identifiers, false, true)) if (!_resolver.GetDesign(split[0], out var design, true) || !IdentifierHandling(split2[0], out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_objects.TryGetValue(identifier, out var actors)) if (!_objects.TryGetValue(identifier, out var actors))
@ -794,7 +790,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(argument, out var identifiers, false, true)) if (!IdentifierHandling(argument, out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_stateManager.TryGetValue(identifier, out var state) if (!_stateManager.TryGetValue(identifier, out var state)
@ -835,7 +830,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(split[1], out var identifiers, false, true)) if (!IdentifierHandling(split[1], out var identifiers, false, true))
return false; return false;
_objects.Update();
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
if (!_stateManager.TryGetValue(identifier, out var state) if (!_stateManager.TryGetValue(identifier, out var state)

View file

@ -1,13 +1,12 @@
using Glamourer.Designs; using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Glamourer.State; using Glamourer.State;
using OtterGui.Services; using OtterGui.Services;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Interop;
namespace Glamourer.Services; namespace Glamourer.Services;
public sealed class DesignApplier(StateManager stateManager, ObjectManager objects) : IService public sealed class DesignApplier(StateManager stateManager, ActorObjectManager objects) : IService
{ {
public void ApplyToPlayer(DesignBase design) public void ApplyToPlayer(DesignBase design)
{ {
@ -34,16 +33,10 @@ public sealed class DesignApplier(StateManager stateManager, ObjectManager objec
} }
public void Apply(ActorIdentifier actor, DesignBase design) public void Apply(ActorIdentifier actor, DesignBase design)
{ => Apply(actor, objects.TryGetValue(actor, out var d) ? d : ActorData.Invalid, design, ApplySettings.ManualWithLinks);
objects.Update();
Apply(actor, objects.TryGetValue(actor, out var d) ? d : ActorData.Invalid, design, ApplySettings.ManualWithLinks);
}
public void Apply(ActorIdentifier actor, DesignBase design, ApplySettings settings) public void Apply(ActorIdentifier actor, DesignBase design, ApplySettings settings)
{ => Apply(actor, objects.TryGetValue(actor, out var d) ? d : ActorData.Invalid, design, settings);
objects.Update();
Apply(actor, objects.TryGetValue(actor, out var d) ? d : ActorData.Invalid, design, settings);
}
public void Apply(ActorIdentifier actor, ActorData data, DesignBase design) public void Apply(ActorIdentifier actor, ActorData data, DesignBase design)
=> Apply(actor, data, design, ApplySettings.ManualWithLinks); => Apply(actor, data, design, ApplySettings.ManualWithLinks);

View file

@ -27,6 +27,7 @@ using OtterGui.Services;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.GameData.Data; using Penumbra.GameData.Data;
using Penumbra.GameData.DataContainers; using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.Services; namespace Glamourer.Services;
@ -102,6 +103,7 @@ public static class StaticServiceManager
.AddSingleton<PenumbraService>() .AddSingleton<PenumbraService>()
.AddSingleton(p => new CutsceneResolver(p.GetRequiredService<PenumbraService>().CutsceneParent)) .AddSingleton(p => new CutsceneResolver(p.GetRequiredService<PenumbraService>().CutsceneParent))
.AddSingleton<ObjectManager>() .AddSingleton<ObjectManager>()
.AddSingleton<ActorObjectManager>()
.AddSingleton<PenumbraAutoRedraw>() .AddSingleton<PenumbraAutoRedraw>()
.AddSingleton<JobService>() .AddSingleton<JobService>()
.AddSingleton<CustomizeUnlockManager>() .AddSingleton<CustomizeUnlockManager>()

View file

@ -11,7 +11,6 @@ using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
using CustomizeIndex = Penumbra.GameData.Enums.CustomizeIndex; using CustomizeIndex = Penumbra.GameData.Enums.CustomizeIndex;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.State; namespace Glamourer.State;
@ -35,7 +34,7 @@ public unsafe class FunModule : IDisposable
private readonly StateManager _stateManager; private readonly StateManager _stateManager;
private readonly DesignConverter _designConverter; private readonly DesignConverter _designConverter;
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly NpcCustomizeSet _npcs; private readonly NpcCustomizeSet _npcs;
private readonly StainId[] _stains; private readonly StainId[] _stains;
@ -69,7 +68,7 @@ public unsafe class FunModule : IDisposable
=> OnDayChange(DateTime.Now.Day, DateTime.Now.Month, DateTime.Now.Year); => OnDayChange(DateTime.Now.Day, DateTime.Now.Month, DateTime.Now.Year);
public FunModule(CodeService codes, CustomizeService customizations, ItemManager items, Configuration config, public FunModule(CodeService codes, CustomizeService customizations, ItemManager items, Configuration config,
GenericPopupWindow popupWindow, StateManager stateManager, ObjectManager objects, DesignConverter designConverter, GenericPopupWindow popupWindow, StateManager stateManager, ActorObjectManager objects, DesignConverter designConverter,
DesignManager designManager, NpcCustomizeSet npcs) DesignManager designManager, NpcCustomizeSet npcs)
{ {
_codes = codes; _codes = codes;
@ -125,9 +124,7 @@ public unsafe class FunModule : IDisposable
switch (_codes.Masked(CodeService.GearCodes)) switch (_codes.Masked(CodeService.GearCodes))
{ {
case CodeService.CodeFlag.Emperor: case CodeService.CodeFlag.Emperor: SetRandomItem(slot, ref armor); break;
SetRandomItem(slot, ref armor);
break;
case CodeService.CodeFlag.Elephants: case CodeService.CodeFlag.Elephants:
case CodeService.CodeFlag.Dolphins: case CodeService.CodeFlag.Dolphins:
case CodeService.CodeFlag.World when actor.Index != 0: case CodeService.CodeFlag.World when actor.Index != 0:
@ -137,9 +134,7 @@ public unsafe class FunModule : IDisposable
switch (_codes.Masked(CodeService.DyeCodes)) switch (_codes.Masked(CodeService.DyeCodes))
{ {
case CodeService.CodeFlag.Clown: case CodeService.CodeFlag.Clown: SetRandomDye(ref armor); break;
SetRandomDye(ref armor);
break;
} }
} }
@ -306,9 +301,7 @@ public unsafe class FunModule : IDisposable
SetDolphin(EquipSlot.Body, ref armor[1]); SetDolphin(EquipSlot.Body, ref armor[1]);
SetDolphin(EquipSlot.Head, ref armor[0]); SetDolphin(EquipSlot.Head, ref armor[0]);
break; break;
case CodeService.CodeFlag.World when actor.Index != 0: case CodeService.CodeFlag.World when actor.Index != 0: _worldSets.Apply(actor, _rng, armor); break;
_worldSets.Apply(actor, _rng, armor);
break;
} }
switch (_codes.Masked(CodeService.DyeCodes)) switch (_codes.Masked(CodeService.DyeCodes))
@ -368,17 +361,17 @@ public unsafe class FunModule : IDisposable
private static IReadOnlyList<CharacterArmor> DolphinBodies private static IReadOnlyList<CharacterArmor> DolphinBodies
=> =>
[ [
new CharacterArmor(6089, 1, new StainIds(4)), // Toad new(6089, 1, new StainIds(4)), // Toad
new CharacterArmor(6089, 1, new StainIds(4)), // Toad new(6089, 1, new StainIds(4)), // Toad
new CharacterArmor(6089, 1, new StainIds(4)), // Toad new(6089, 1, new StainIds(4)), // Toad
new CharacterArmor(6023, 1, new StainIds(4)), // Swine new(6023, 1, new StainIds(4)), // Swine
new CharacterArmor(6023, 1, new StainIds(4)), // Swine new(6023, 1, new StainIds(4)), // Swine
new CharacterArmor(6023, 1, new StainIds(4)), // Swine new(6023, 1, new StainIds(4)), // Swine
new CharacterArmor(6133, 1, new StainIds(4)), // Gaja new(6133, 1, new StainIds(4)), // Gaja
new CharacterArmor(6182, 1, new StainIds(3)), // Imp new(6182, 1, new StainIds(3)), // Imp
new CharacterArmor(6182, 1, new StainIds(3)), // Imp new(6182, 1, new StainIds(3)), // Imp
new CharacterArmor(6182, 1, new StainIds(4)), // Imp new(6182, 1, new StainIds(4)), // Imp
new CharacterArmor(6182, 1, new StainIds(4)), // Imp new(6182, 1, new StainIds(4)), // Imp
]; ];
private void SetDolphin(EquipSlot slot, ref CharacterArmor armor) private void SetDolphin(EquipSlot slot, ref CharacterArmor armor)

View file

@ -7,6 +7,7 @@ using Glamourer.Interop.Structs;
using Glamourer.Services; using Glamourer.Services;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.State; namespace Glamourer.State;
@ -23,7 +24,7 @@ public class StateApplier(
ItemManager _items, ItemManager _items,
PenumbraService _penumbra, PenumbraService _penumbra,
MetaService _metaService, MetaService _metaService,
ObjectManager _objects, ActorObjectManager _objects,
CrestService _crests, CrestService _crests,
DirectXService _directX) DirectXService _directX)
{ {
@ -411,8 +412,5 @@ public class StateApplier(
} }
private ActorData GetData(ActorState state) private ActorData GetData(ActorState state)
{ => _objects.TryGetValue(state.Identifier, out var data) ? data : ActorData.Invalid;
_objects.Update();
return _objects.TryGetValue(state.Identifier, out var data) ? data : ActorData.Invalid;
}
} }

View file

@ -9,6 +9,7 @@ using Glamourer.Interop.Penumbra;
using Glamourer.Interop.Structs; using Glamourer.Interop.Structs;
using Glamourer.Services; using Glamourer.Services;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs; using Penumbra.GameData.Structs;
namespace Glamourer.State; namespace Glamourer.State;

View file

@ -15,7 +15,6 @@ using Penumbra.GameData.DataContainers;
using Glamourer.Designs; using Glamourer.Designs;
using Penumbra.GameData.Interop; using Penumbra.GameData.Interop;
using Glamourer.Api.Enums; using Glamourer.Api.Enums;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.State; namespace Glamourer.State;
@ -28,7 +27,7 @@ public class StateListener : IDisposable
{ {
private readonly Configuration _config; private readonly Configuration _config;
private readonly ActorManager _actors; private readonly ActorManager _actors;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly StateManager _manager; private readonly StateManager _manager;
private readonly StateApplier _applier; private readonly StateApplier _applier;
private readonly ItemManager _items; private readonly ItemManager _items;
@ -61,7 +60,7 @@ public class StateListener : IDisposable
public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorManager actors, Configuration config, public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorManager actors, Configuration config,
EquipSlotUpdating equipSlotUpdating, GearsetDataLoaded gearsetDataLoaded, WeaponLoading weaponLoading, VisorStateChanged visorState, EquipSlotUpdating equipSlotUpdating, GearsetDataLoaded gearsetDataLoaded, WeaponLoading weaponLoading, VisorStateChanged visorState,
WeaponVisibilityChanged weaponVisibility, HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier, WeaponVisibilityChanged weaponVisibility, HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier,
FunModule funModule, HumanModelList humans, StateApplier applier, MovedEquipment movedEquipment, ObjectManager objects, FunModule funModule, HumanModelList humans, StateApplier applier, MovedEquipment movedEquipment, ActorObjectManager objects,
GPoseService gPose, ChangeCustomizeService changeCustomizeService, CustomizeService customizations, ICondition condition, GPoseService gPose, ChangeCustomizeService changeCustomizeService, CustomizeService customizations, ICondition condition,
CrestService crestService, BonusSlotUpdating bonusSlotUpdating, StateFinalized stateFinalized) CrestService crestService, BonusSlotUpdating bonusSlotUpdating, StateFinalized stateFinalized)
{ {
@ -205,9 +204,7 @@ public class StateListener : IDisposable
} }
break; break;
case UpdateState.NoChange: case UpdateState.NoChange: customize = state.ModelData.Customize; break;
customize = state.ModelData.Customize;
break;
} }
} }
@ -262,9 +259,7 @@ public class StateListener : IDisposable
item = state.ModelData.BonusItem(slot).Armor(); item = state.ModelData.BonusItem(slot).Armor();
break; break;
// Use current model data. // Use current model data.
case UpdateState.NoChange: case UpdateState.NoChange: item = state.ModelData.BonusItem(slot).Armor(); break;
item = state.ModelData.BonusItem(slot).Armor();
break;
case UpdateState.Transformed: break; case UpdateState.Transformed: break;
} }
} }
@ -279,7 +274,6 @@ public class StateListener : IDisposable
if (!actor.Identifier(_actors, out var identifier)) if (!actor.Identifier(_actors, out var identifier))
return; return;
_objects.Update();
if (_objects.TryGetValue(identifier, out var actors) && actors.Valid) if (_objects.TryGetValue(identifier, out var actors) && actors.Valid)
_stateFinalized.Invoke(StateFinalizationType.Gearset, actors); _stateFinalized.Invoke(StateFinalizationType.Gearset, actors);
} }
@ -287,7 +281,6 @@ public class StateListener : IDisposable
private void OnMovedEquipment((EquipSlot, uint, StainIds)[] items) private void OnMovedEquipment((EquipSlot, uint, StainIds)[] items)
{ {
_objects.Update();
var (identifier, objects) = _objects.PlayerData; var (identifier, objects) = _objects.PlayerData;
if (!identifier.IsValid || !_manager.TryGetValue(identifier, out var state)) if (!identifier.IsValid || !_manager.TryGetValue(identifier, out var state))
return; return;
@ -310,7 +303,7 @@ public class StateListener : IDisposable
var stainChanged = current.Stains == changed.Stains && !state.Sources[slot, true].IsFixed(); var stainChanged = current.Stains == changed.Stains && !state.Sources[slot, true].IsFixed();
switch ((itemChanged, stainChanged)) switch (itemChanged, stainChanged)
{ {
case (true, true): case (true, true):
_manager.ChangeEquip(state, slot, currentItem, current.Stains, ApplySettings.Game); _manager.ChangeEquip(state, slot, currentItem, current.Stains, ApplySettings.Game);
@ -376,9 +369,7 @@ public class StateListener : IDisposable
else else
apply = true; apply = true;
break; break;
case UpdateState.NoChange: case UpdateState.NoChange: apply = true; break;
apply = true;
break;
} }
var baseType = slot is EquipSlot.OffHand ? state.BaseData.MainhandType.Offhand() : state.BaseData.MainhandType; var baseType = slot is EquipSlot.OffHand ? state.BaseData.MainhandType.Offhand() : state.BaseData.MainhandType;

View file

@ -1,16 +1,15 @@
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Dalamud.Utility;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.Game.UI;
using Glamourer.GameData; using Glamourer.GameData;
using Glamourer.Events; using Glamourer.Events;
using Glamourer.Interop;
using Glamourer.Services; using Glamourer.Services;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
namespace Glamourer.Unlocks; namespace Glamourer.Unlocks;
@ -19,7 +18,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
private readonly SaveService _saveService; private readonly SaveService _saveService;
private readonly IClientState _clientState; private readonly IClientState _clientState;
private readonly ObjectUnlocked _event; private readonly ObjectUnlocked _event;
private readonly ObjectManager _objects; private readonly ActorObjectManager _objects;
private readonly Dictionary<uint, long> _unlocked = new(); private readonly Dictionary<uint, long> _unlocked = new();
public readonly IReadOnlyDictionary<CustomizeData, (uint Data, string Name)> Unlockable; public readonly IReadOnlyDictionary<CustomizeData, (uint Data, string Name)> Unlockable;
@ -28,7 +27,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
=> _unlocked; => _unlocked;
public CustomizeUnlockManager(SaveService saveService, CustomizeService customizations, IDataManager gameData, public CustomizeUnlockManager(SaveService saveService, CustomizeService customizations, IDataManager gameData,
IClientState clientState, ObjectUnlocked @event, IGameInteropProvider interop, ObjectManager objects) IClientState clientState, ObjectUnlocked @event, IGameInteropProvider interop, ActorObjectManager objects)
{ {
interop.InitializeFromAttributes(this); interop.InitializeFromAttributes(this);
_saveService = saveService; _saveService = saveService;
@ -177,7 +176,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
IDataManager gameData) IDataManager gameData)
{ {
var ret = new Dictionary<CustomizeData, (uint Data, string Name)>(); var ret = new Dictionary<CustomizeData, (uint Data, string Name)>();
var sheet = gameData.GetExcelSheet<CharaMakeCustomize>(ClientLanguage.English)!; var sheet = gameData.GetExcelSheet<CharaMakeCustomize>(ClientLanguage.English);
foreach (var (clan, gender) in CustomizeManager.AllSets()) foreach (var (clan, gender) in CustomizeManager.AllSets())
{ {
var list = customizations.Manager.GetSet(clan, gender); var list = customizations.Manager.GetSet(clan, gender);

@ -1 +1 @@
Subproject commit 3396ee176fa72ad2dfb2de3294f7125ebce4dae5 Subproject commit f53fd227a242435ce44a9fe9c5e847d0ca788869

@ -1 +1 @@
Subproject commit ab63da8047f3d99240159bb1b17dbcb61d77326a Subproject commit 801e98a2956d707a25fd19bdfa46dc674c95365d