This commit is contained in:
Ottermandias 2023-06-21 18:09:50 +02:00
parent 5e6f797af4
commit 803fd1b247
16 changed files with 521 additions and 132 deletions

View file

@ -0,0 +1,67 @@
using System;
using Glamourer.State;
using Penumbra.Api.Enums;
namespace Glamourer.Interop.Penumbra;
public class PenumbraAutoRedraw : IDisposable
{
private readonly Configuration _config;
private readonly PenumbraService _penumbra;
private readonly StateManager _state;
private readonly ObjectManager _objects;
private bool _enabled;
public PenumbraAutoRedraw(PenumbraService penumbra, Configuration config, StateManager state, ObjectManager objects)
{
_penumbra = penumbra;
_config = config;
_state = state;
_objects = objects;
if (_config.AutoRedrawEquipOnChanges)
Enable();
}
public void SetState(bool value)
{
if (value == _config.AutoRedrawEquipOnChanges)
return;
_config.AutoRedrawEquipOnChanges = value;
_config.Save();
if (value)
Enable();
else
Disable();
}
public void Enable()
{
if (_enabled)
return;
_penumbra.ModSettingChanged += OnModSettingChange;
_enabled = true;
}
public void Disable()
{
if (!_enabled)
return;
_penumbra.ModSettingChanged -= OnModSettingChange;
_enabled = false;
}
public void Dispose()
{
Disable();
}
private void OnModSettingChange(ModSettingChange type, string name, string mod, bool inherited)
{
var playerName = _penumbra.GetCurrentPlayerCollection();
if (playerName == name)
_state.ReapplyState(_objects.Player);
}
}

View file

@ -13,14 +13,16 @@ public unsafe class PenumbraService : IDisposable
public const int RequiredPenumbraBreakingVersion = 4;
public const int RequiredPenumbraFeatureVersion = 15;
private readonly DalamudPluginInterface _pluginInterface;
private readonly EventSubscriber<ChangedItemType, uint> _tooltipSubscriber;
private readonly EventSubscriber<MouseButton, ChangedItemType, uint> _clickSubscriber;
private readonly EventSubscriber<nint, string, nint, nint, nint> _creatingCharacterBase;
private readonly EventSubscriber<nint, string, nint> _createdCharacterBase;
private ActionSubscriber<int, RedrawType> _redrawSubscriber;
private FuncSubscriber<nint, (nint, string)> _drawObjectInfo;
private FuncSubscriber<int, int> _cutsceneParent;
private readonly DalamudPluginInterface _pluginInterface;
private readonly EventSubscriber<ChangedItemType, uint> _tooltipSubscriber;
private readonly EventSubscriber<MouseButton, ChangedItemType, uint> _clickSubscriber;
private readonly EventSubscriber<nint, string, nint, nint, nint> _creatingCharacterBase;
private readonly EventSubscriber<nint, string, nint> _createdCharacterBase;
private readonly EventSubscriber<ModSettingChange, string, string, bool> _modSettingChanged;
private ActionSubscriber<int, RedrawType> _redrawSubscriber;
private FuncSubscriber<nint, (nint, string)> _drawObjectInfo;
private FuncSubscriber<int, int> _cutsceneParent;
private FuncSubscriber<int, (bool, bool, string)> _objectCollection;
private readonly EventSubscriber _initializedEvent;
private readonly EventSubscriber _disposedEvent;
@ -35,6 +37,7 @@ public unsafe class PenumbraService : IDisposable
_clickSubscriber = Ipc.ChangedItemClick.Subscriber(pi);
_createdCharacterBase = Ipc.CreatedCharacterBase.Subscriber(pi);
_creatingCharacterBase = Ipc.CreatingCharacterBase.Subscriber(pi);
_modSettingChanged = Ipc.ModSettingChanged.Subscriber(pi);
Reattach();
}
@ -63,6 +66,22 @@ public unsafe class PenumbraService : IDisposable
remove => _createdCharacterBase.Event -= value;
}
public event Action<ModSettingChange, string, string, bool> ModSettingChanged
{
add => _modSettingChanged.Event += value;
remove => _modSettingChanged.Event -= value;
}
/// <summary> Obtain the name of the collection currently assigned to the player. </summary>
public string GetCurrentPlayerCollection()
{
if (!Available)
return string.Empty;
var (valid, _, name) = _objectCollection.Invoke(0);
return valid ? name : string.Empty;
}
/// <summary> Obtain the game object corresponding to a draw object. </summary>
public Actor GameObjectFromDrawObject(Model drawObject)
=> Available ? _drawObjectInfo.Invoke(drawObject.Address).Item1 : Actor.Null;
@ -103,9 +122,11 @@ public unsafe class PenumbraService : IDisposable
_clickSubscriber.Enable();
_creatingCharacterBase.Enable();
_createdCharacterBase.Enable();
_modSettingChanged.Enable();
_drawObjectInfo = Ipc.GetDrawObjectInfo.Subscriber(_pluginInterface);
_cutsceneParent = Ipc.GetCutsceneParentIndex.Subscriber(_pluginInterface);
_redrawSubscriber = Ipc.RedrawObjectByIndex.Subscriber(_pluginInterface);
_objectCollection = Ipc.GetCollectionForObject.Subscriber(_pluginInterface);
Available = true;
Glamourer.Log.Debug("Glamourer attached to Penumbra.");
}
@ -122,6 +143,7 @@ public unsafe class PenumbraService : IDisposable
_clickSubscriber.Disable();
_creatingCharacterBase.Disable();
_createdCharacterBase.Disable();
_modSettingChanged.Disable();
if (Available)
{
Available = false;
@ -138,5 +160,6 @@ public unsafe class PenumbraService : IDisposable
_createdCharacterBase.Dispose();
_initializedEvent.Dispose();
_disposedEvent.Dispose();
_modSettingChanged.Dispose();
}
}

View file

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using OtterGui.Log;
namespace Glamourer.Interop.Structs;
@ -8,7 +10,7 @@ namespace Glamourer.Interop.Structs;
public readonly struct ActorData
{
public readonly List<Actor> Objects;
public readonly string Label;
public readonly string Label;
public bool Valid
=> Objects.Count > 0;
@ -16,7 +18,7 @@ public readonly struct ActorData
public ActorData(Actor actor, string label)
{
Objects = new List<Actor> { actor };
Label = label;
Label = label;
}
public static readonly ActorData Invalid = new(false);
@ -24,6 +26,14 @@ public readonly struct ActorData
private ActorData(bool _)
{
Objects = new List<Actor>(0);
Label = string.Empty;
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);
}
}

View file

@ -5,6 +5,7 @@ using Glamourer.Events;
using Glamourer.Interop.Structs;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Glamourer.Interop;
@ -31,24 +32,18 @@ public unsafe class UpdateSlotService : IDisposable
{
if (!drawObject.IsCharacterBase)
return;
FlagSlotForUpdateInterop(drawObject, slot, data);
}
public void UpdateArmor(Model drawObject, EquipSlot slot, CharacterArmor data)
{
if (!drawObject.IsCharacterBase)
return;
public void UpdateArmor(Model drawObject, EquipSlot slot, CharacterArmor armor, StainId stain)
=> UpdateSlot(drawObject, slot, armor.With(stain));
FlagSlotForUpdateInterop(drawObject, slot, data.With(drawObject.GetArmor(slot).Stain));
}
public void UpdateArmor(Model drawObject, EquipSlot slot, CharacterArmor armor)
=> UpdateArmor(drawObject, slot, armor, drawObject.GetArmor(slot).Stain);
public void UpdateStain(Model drawObject, EquipSlot slot, StainId stain)
{
if (!drawObject.IsHuman)
return;
FlagSlotForUpdateInterop(drawObject, slot, drawObject.GetArmor(slot).With(stain));
}
=> UpdateArmor(drawObject, slot, drawObject.GetArmor(slot), stain);
private ulong FlagSlotForUpdateDetour(nint drawObject, uint slotIdx, CharacterArmor* data)
{