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 Penumbra.GameData.Actors;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.String;
using ObjectManager = Glamourer.Interop.ObjectManager;
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)]
internal IEnumerable<ActorState> FindExistingStates(string actorName)
@ -27,7 +27,7 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state)
{
var actor = objects[objectIndex];
var actor = objects.Objects[objectIndex];
var identifier = actor.GetIdentifier(actors);
if (!identifier.IsValid)
{
@ -42,7 +42,7 @@ public class ApiHelpers(ObjectManager objects, StateManager stateManager, ActorM
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal ActorState? FindState(int objectIndex)
{
var actor = objects[objectIndex];
var actor = objects.Objects[objectIndex];
var identifier = actor.GetIdentifier(actors);
if (identifier.IsValid && stateManager.GetOrCreate(identifier, actor, out var 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))
return [];
objects.Update();
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)
.SelectWhere(kvp =>
{

View file

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

View file

@ -11,7 +11,6 @@ using Penumbra.GameData.DataContainers;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Automation;
@ -24,7 +23,7 @@ public sealed class AutoDesignApplier : IDisposable
private readonly EquippedGearset _equippedGearset;
private readonly ActorManager _actors;
private readonly AutomationChanged _event;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private readonly WeaponLoading _weapons;
private readonly HumanModelList _humans;
private readonly DesignMerger _designMerger;
@ -33,7 +32,7 @@ public sealed class AutoDesignApplier : IDisposable
private readonly JobChangeState _jobChangeState;
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)
{
_config = config;
@ -154,7 +153,6 @@ public sealed class AutoDesignApplier : IDisposable
if (newSet is not { Enabled: true })
return;
_objects.Update();
foreach (var id in newSet.Identifiers)
{
if (_objects.TryGetValue(id, out var data))

View file

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

View file

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

View file

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

View file

@ -6,12 +6,10 @@ using Glamourer.Gui;
using Glamourer.Interop;
using Glamourer.Services;
using Glamourer.State;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Log;
using OtterGui.Services;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Files;
using Penumbra.GameData.Interop;
namespace Glamourer;
@ -82,7 +80,7 @@ public class Glamourer : IDalamudPlugin
var designManager = _services.GetService<DesignManager>();
var autoManager = _services.GetService<AutoDesignManager>();
var stateManager = _services.GetService<StateManager>();
var objectManager = _services.GetService<ObjectManager>();
var objectManager = _services.GetService<ActorObjectManager>();
var currentPlayer = objectManager.PlayerData.Identifier;
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 Glamourer.Automation;
using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra;
using Glamourer.Interop.Structs;
using Glamourer.State;
using ImGuiNET;
using OtterGui.Classes;
using OtterGui.Text;
using Penumbra.GameData.Actors;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui;
@ -41,7 +40,7 @@ public sealed class DesignQuickBar : Window, IDisposable
private readonly QuickDesignCombo _designCombo;
private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private readonly PenumbraService _penumbra;
private readonly IKeyState _keyState;
private readonly ImRaii.Style _windowPadding = new();
@ -51,7 +50,7 @@ public sealed class DesignQuickBar : Window, IDisposable
private readonly StringBuilder _tooltipBuilder = new(512);
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)
{
_config = config;
@ -222,7 +221,8 @@ public sealed class DesignQuickBar : Window, IDisposable
}
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);
ImGui.SameLine();
@ -258,7 +258,8 @@ public sealed class DesignQuickBar : Window, IDisposable
}
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);
ImGui.SameLine();
@ -300,7 +301,8 @@ public sealed class DesignQuickBar : Window, IDisposable
}
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);
ImGui.SameLine();
@ -424,7 +426,9 @@ public sealed class DesignQuickBar : Window, IDisposable
if (_playerIdentifier.IsValid && _playerData.Valid)
{
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('.');
}
@ -434,7 +438,9 @@ public sealed class DesignQuickBar : Window, IDisposable
if (available != 0)
_tooltipBuilder.Append('\n');
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('.');
}

View file

@ -1,6 +1,5 @@
using Glamourer.Designs;
using Glamourer.Events;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using Glamourer.State;
@ -9,6 +8,7 @@ using OtterGui.Raii;
using Penumbra.Api.Enums;
using Penumbra.GameData.Data;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
namespace Glamourer.Gui;
@ -18,7 +18,7 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
private readonly PenumbraService _penumbra;
private readonly StateManager _stateManager;
private readonly ItemManager _items;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private readonly CustomizeService _customize;
private readonly GPoseService _gpose;
@ -33,7 +33,7 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
public DateTime LastTooltip { 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)
{
_penumbra = penumbra;

View file

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

View file

@ -1,7 +1,4 @@
using System.Security.AccessControl;
using Dalamud.Interface;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Dalamud.Interface;
using ImGuiNET;
using OtterGui;
using OtterGui.Classes;
@ -9,11 +6,12 @@ using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Actors;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
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;
@ -89,11 +87,10 @@ public class ActorSelector(ObjectManager objects, ActorManager actors, Ephemeral
if (!child)
return;
objects.Update();
_world = new WorldId(objects.Player.Valid ? objects.Player.HomeWorld : (ushort)0);
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
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);
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
}

View file

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

View file

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

View file

@ -1,18 +1,17 @@
using Dalamud.Interface;
using Glamourer.GameData;
using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Interop.Structs;
using Glamourer.State;
using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab;
public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectManager) : IGameDataDrawer
public class ActiveStatePanel(StateManager _stateManager, ActorObjectManager _objectManager) : IGameDataDrawer
{
public string Label
=> $"Active Actors ({_stateManager.Count})###Active Actors";
@ -22,8 +21,7 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM
public void Draw()
{
_objectManager.Update();
foreach (var (identifier, actors) in _objectManager.Identifiers)
foreach (var (identifier, actors) in _objectManager)
{
if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Trash.ToIconString()}##{actors.Label}", new Vector2(ImGui.GetFrameHeight()),
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)
{
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)
{
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]);

View file

@ -1,13 +1,13 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using Glamourer.Interop;
using ImGuiNET;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class AdvancedCustomizationDrawer(ObjectManager objects) : IGameDataDrawer
public unsafe class AdvancedCustomizationDrawer(ActorObjectManager objects) : IGameDataDrawer
{
public string Label
=> "Advanced Customizations";

View file

@ -3,14 +3,15 @@ using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game;
using Glamourer.Designs;
using Glamourer.Interop;
using Glamourer.Services;
using Glamourer.State;
using ImGuiNET;
using OtterGui;
using OtterGui.Text;
using Penumbra.GameData;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
namespace Glamourer.Gui.Tabs.DebugTab;
@ -20,7 +21,7 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
private readonly DesignManager _design;
private readonly ItemManager _items;
private readonly StateManager _state;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
public string Label
=> "Glamour Plates";
@ -28,7 +29,8 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
public bool Disabled
=> 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;
_design = design;
@ -42,24 +44,24 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
var manager = MirageManager.Instance();
using (ImRaii.Group())
{
ImGui.TextUnformatted("Address:");
ImGui.TextUnformatted("Number of Glamour Plates:");
ImGui.TextUnformatted("Glamour Plates Requested:");
ImGui.TextUnformatted("Glamour Plates Loaded:");
ImGui.TextUnformatted("Is Applying Glamour Plates:");
ImUtf8.Text("Address:"u8);
ImUtf8.Text("Number of Glamour Plates:"u8);
ImUtf8.Text("Glamour Plates Requested:"u8);
ImUtf8.Text("Glamour Plates Loaded:"u8);
ImUtf8.Text("Is Applying Glamour Plates:"u8);
}
ImGui.SameLine();
using (ImRaii.Group())
{
ImGuiUtil.CopyOnClickSelectable($"0x{(ulong)manager:X}");
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlates.Length.ToString());
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesRequested.ToString());
ImUtf8.CopyOnClickSelectable($"0x{(ulong)manager:X}");
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlates.Length.ToString());
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesRequested.ToString());
ImGui.SameLine();
if (ImGui.SmallButton("Request Update"))
if (ImUtf8.SmallButton("Request Update"u8))
RequestGlamour();
ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString());
ImGui.TextUnformatted(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString());
ImUtf8.Text(manager == null ? "-" : manager->GlamourPlatesLoaded.ToString());
ImUtf8.Text(manager == null ? "-" : manager->IsApplyingGlamourPlate.ToString());
}
if (manager == null)
@ -71,12 +73,12 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
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)
continue;
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);
_state.ApplyDesign(state!, design, ApplySettings.Manual with { IsFinal = true });
@ -85,14 +87,14 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer
using (ImRaii.Group())
{
foreach (var slot in EquipSlotExtensions.FullSlots)
ImGui.TextUnformatted(slot.ToName());
ImUtf8.Text(slot.ToName());
}
ImGui.SameLine();
using (ImRaii.Group())
{
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.Interop;
using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Gui.Tabs.DebugTab;
public unsafe class ModelEvaluationPanel(
ObjectManager _objectManager,
ActorObjectManager _objectManager,
VisorService _visorService,
UpdateSlotService _updateSlotService,
ChangeCustomizeService _changeCustomizeService,
@ -34,7 +33,7 @@ public unsafe class ModelEvaluationPanel(
public void Draw()
{
ImGui.InputInt("Game Object Index", ref _gameObjectIndex, 0, 0);
var actor = _objectManager[_gameObjectIndex];
var actor = _objectManager.Objects[_gameObjectIndex];
var model = actor.Model;
using var table = ImRaii.Table("##evaluationTable", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
ImGui.TableNextColumn();

View file

@ -3,18 +3,18 @@ using Dalamud.Interface.Utility;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Glamourer.Designs;
using Glamourer.GameData;
using Glamourer.Interop;
using Glamourer.State;
using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Gui.Debug;
using Penumbra.GameData.Interop;
using ImGuiClip = OtterGui.ImGuiClip;
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
{
public string Label
@ -28,9 +28,9 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
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);
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,
new Vector2(-1, 400 * ImGuiHelpers.GlobalScale));
@ -40,19 +40,19 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
if (resetScroll)
ImGui.SetScrollY(0);
ImGui.TableSetupColumn("Button", ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300);
ImGui.TableSetupColumn("Kind", ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Id", ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Model", ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Visor", ImGuiTableColumnFlags.WidthFixed);
ImGui.TableSetupColumn("Compare", ImGuiTableColumnFlags.WidthStretch);
ImUtf8.TableSetupColumn("Button"u8, ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Name"u8, ImGuiTableColumnFlags.WidthFixed, ImGuiHelpers.GlobalScale * 300);
ImUtf8.TableSetupColumn("Kind"u8, ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Id"u8, ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Model"u8, ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Visor"u8, ImGuiTableColumnFlags.WidthFixed);
ImUtf8.TableSetupColumn("Compare"u8, ImGuiTableColumnFlags.WidthStretch);
ImGui.TableNextColumn();
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetFrameHeightWithSpacing());
ImGui.TableNextRow();
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);
ImGui.TableNextColumn();
ImGuiClip.DrawEndDummy(remainder, ImGui.GetFrameHeightWithSpacing());
@ -61,43 +61,31 @@ public class NpcAppearancePanel(NpcCombo _npcCombo, StateManager _state, ObjectM
void DrawData(NpcData data)
{
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();
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))
_state.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual);
_state.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual);
_state.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual);
foreach (var (slot, item, stain) in designConverter.FromDrawData(data.Equip.ToArray(), data.Mainhand, data.Offhand, true))
stateManager.ChangeEquip(state!, slot, item, stain, ApplySettings.Manual);
stateManager.ChangeMetaState(state!, MetaIndex.VisorState, data.VisorToggled, ApplySettings.Manual);
stateManager.ChangeEntireCustomize(state!, data.Customize, CustomizeFlagExtensions.All, ApplySettings.Manual);
}
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Name);
ImUtf8.DrawFrameColumn(data.Name);
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
ImUtf8.DrawFrameColumn(data.Kind is ObjectKind.BattleNpc ? "B" : "E");
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.Id.Id.ToString());
ImUtf8.DrawFrameColumn(data.Id.Id.ToString());
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.ModelId.ToString());
ImUtf8.DrawFrameColumn(data.ModelId.ToString());
using (_ = ImRaii.PushFont(UiBuilder.IconFont))
{
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
ImUtf8.DrawFrameColumn(data.VisorToggled ? FontAwesomeIcon.Check.ToIconString() : FontAwesomeIcon.Times.ToIconString());
}
using var mono = ImRaii.PushFont(UiBuilder.MonoFont);
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
ImUtf8.DrawFrameColumn(_customizeOrGear ? data.Customize.ToString() : data.WriteGear());
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -6,14 +6,14 @@ using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;
using Penumbra.GameData.Actors;
using ObjectManager = Glamourer.Interop.ObjectManager;
using Penumbra.GameData.Interop;
namespace Glamourer.Gui.Tabs.SettingsTab;
public class CollectionOverrideDrawer(
CollectionOverrideService collectionOverrides,
Configuration config,
ObjectManager objects,
ActorObjectManager objects,
ActorManager actors,
PenumbraService penumbra,
CollectionCombo combo) : IService
@ -61,7 +61,8 @@ public class CollectionOverrideDrawer(
DrawActorIdentifier(idx, actor);
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;
collectionOverrides.ChangeOverride(idx, guid, newName);

View file

@ -5,6 +5,7 @@ using Glamourer.Designs;
using Glamourer.Services;
using Glamourer.State;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
namespace Glamourer.Interop;
@ -16,13 +17,13 @@ public class ContextMenuService : IDisposable
private readonly ItemManager _items;
private readonly IContextMenu _contextMenu;
private readonly StateManager _state;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private EquipItem _lastItem;
private readonly StainId[] _lastStains = new StainId[StainId.NumStains];
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)
{
_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;
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
{
private readonly HashSet<Guid> _collectionTracker = [];
@ -17,7 +17,6 @@ public class ModSettingApplier(PenumbraService penumbra, PenumbraAutoRedrawSkip
if (!config.AlwaysApplyAssociatedMods || (design.AssociatedMods.Count == 0 && !design.ResetTemporarySettings))
return;
objects.Update();
if (!objects.TryGetValue(state.Identifier, out var data))
{
Glamourer.Log.Verbose(

View file

@ -2,11 +2,11 @@
using Glamourer.Api.Enums;
using Glamourer.Designs.History;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State;
using OtterGui.Classes;
using OtterGui.Services;
using Penumbra.Api.Enums;
using Penumbra.GameData.Interop;
namespace Glamourer.Interop.Penumbra;
@ -16,13 +16,14 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
private readonly Configuration _config;
private readonly PenumbraService _penumbra;
private readonly StateManager _state;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private readonly IFramework _framework;
private readonly StateChanged _stateChanged;
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)
{
_penumbra = penumbra;
@ -78,7 +79,6 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
{
_framework.RunOnFrameworkThread(() =>
{
_objects.Update();
foreach (var (id, state) in _state)
{
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.Interop;
using Penumbra.GameData.Structs;
using ObjectManager = Glamourer.Interop.ObjectManager;
namespace Glamourer.Services;
@ -30,7 +29,7 @@ public class CommandService : IDisposable, IApiService
private readonly MainWindow _mainWindow;
private readonly IChatGui _chat;
private readonly ActorManager _actors;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private readonly StateManager _stateManager;
private readonly AutoDesignApplier _autoDesignApplier;
private readonly AutoDesignManager _autoDesignManager;
@ -43,7 +42,7 @@ public class CommandService : IDisposable, IApiService
private readonly DesignResolver _resolver;
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,
DesignFileSystem designFileSystem, AutoDesignManager autoDesignManager, Configuration config, ModSettingApplier modApplier,
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(" | ")
.AddPurple("<true or false>").AddText(" | ").AddBlue("<true or false>").BuiltString);
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")
.AddText(" determines whether ").AddPurple("manually").AddText(" applied settings are cleared, the ").AddBlue("second")
.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))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
if (!_objects.TryGetValue(identifier, out var data))
@ -425,7 +425,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(argument, out var identifiers, false, true))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
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))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
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))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
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))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
if (!_objects.TryGetValue(identifier, out var actors))
@ -794,7 +790,6 @@ public class CommandService : IDisposable, IApiService
if (!IdentifierHandling(argument, out var identifiers, false, true))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
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))
return false;
_objects.Update();
foreach (var identifier in identifiers)
{
if (!_stateManager.TryGetValue(identifier, out var state)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,16 +1,15 @@
using Dalamud.Game;
using Dalamud.Hooking;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using Glamourer.GameData;
using Glamourer.Events;
using Glamourer.Interop;
using Glamourer.Services;
using Lumina.Excel.Sheets;
using Penumbra.GameData;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Interop;
namespace Glamourer.Unlocks;
@ -19,7 +18,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
private readonly SaveService _saveService;
private readonly IClientState _clientState;
private readonly ObjectUnlocked _event;
private readonly ObjectManager _objects;
private readonly ActorObjectManager _objects;
private readonly Dictionary<uint, long> _unlocked = new();
public readonly IReadOnlyDictionary<CustomizeData, (uint Data, string Name)> Unlockable;
@ -28,7 +27,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
=> _unlocked;
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);
_saveService = saveService;
@ -177,7 +176,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable
IDataManager gameData)
{
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())
{
var list = customizations.Manager.GetSet(clan, gender);

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

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