Add StateChangedWithType.

This commit is contained in:
Ottermandias 2024-06-01 20:26:18 +02:00
parent 86fc472144
commit 0450c4e3f7
8 changed files with 56 additions and 92 deletions

@ -1 +1 @@
Subproject commit 30cdd0a2386045b84f3cfdde483a1ffe60441f05
Subproject commit a20d4ab1811a7f66918afab9b41ec723f75054f5

View file

@ -6,7 +6,7 @@ namespace Glamourer.Api;
public class GlamourerApi(DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService
{
public const int CurrentApiVersionMajor = 1;
public const int CurrentApiVersionMinor = 1;
public const int CurrentApiVersionMinor = 2;
public (int Major, int Minor) ApiVersion
=> (CurrentApiVersionMajor, CurrentApiVersionMinor);

View file

@ -247,8 +247,9 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
return ApiHelpers.Return(GlamourerApiEc.Success, args);
}
public event Action<IntPtr>? StateChanged;
public event Action<bool>? GPoseChanged;
public event Action<nint>? StateChanged;
public event Action<IntPtr, StateChangeType>? StateChangedWithType;
public event Action<bool>? GPoseChanged;
private void ApplyDesign(ActorState state, DesignBase design, uint key, ApplyFlag flags)
{
@ -329,12 +330,14 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
private void OnGPoseChange(bool gPose)
=> GPoseChanged?.Invoke(gPose);
private void OnStateChange(StateChanged.Type _1, StateSource _2, ActorState _3, ActorData actors, object? _5)
private void OnStateChange(StateChangeType type, StateSource _2, ActorState _3, ActorData actors, object? _5)
{
if (StateChanged == null)
return;
if (StateChanged != null)
foreach (var actor in actors.Objects)
StateChanged.Invoke(actor.Address);
foreach (var actor in actors.Objects)
StateChanged.Invoke(actor.Address);
if (StateChangedWithType != null)
foreach (var actor in actors.Objects)
StateChangedWithType.Invoke(actor.Address, type);
}
}

View file

@ -1,67 +1,25 @@
using Glamourer.Api.Enums;
using Glamourer.Interop.Structs;
using Glamourer.State;
using OtterGui.Classes;
namespace Glamourer.Events
namespace Glamourer.Events;
/// <summary>
/// Triggered when a Design is edited in any way.
/// <list type="number">
/// <item>Parameter is the type of the change </item>
/// <item>Parameter is the changed saved state. </item>
/// <item>Parameter is the existing actors using this saved state. </item>
/// <item>Parameter is any additional data depending on the type of change. </item>
/// </list>
/// </summary>
public sealed class StateChanged()
: EventWrapper<StateChangeType, StateSource, ActorState, ActorData, object?, StateChanged.Priority>(nameof(StateChanged))
{
/// <summary>
/// Triggered when a Design is edited in any way.
/// <list type="number">
/// <item>Parameter is the type of the change </item>
/// <item>Parameter is the changed saved state. </item>
/// <item>Parameter is the existing actors using this saved state. </item>
/// <item>Parameter is any additional data depending on the type of change. </item>
/// </list>
/// </summary>
public sealed class StateChanged()
: EventWrapper<StateChanged.Type, StateSource, ActorState, ActorData, object?, StateChanged.Priority>(nameof(StateChanged))
public enum Priority
{
public enum Type
{
/// <summary> A characters saved state had the model id changed. This means everything may have changed. Data is the old model id and the new model id. [(uint, uint)] </summary>
Model,
/// <summary> A characters saved state had multiple customization values changed. TData is the old customize array and the applied changes. [(Customize, CustomizeFlag)] </summary>
EntireCustomize,
/// <summary> A characters saved state had a customization value changed. Data is the old value, the new value and the type. [(CustomizeValue, CustomizeValue, CustomizeIndex)]. </summary>
Customize,
/// <summary> A characters saved state had an equipment piece changed. Data is the old value, the new value and the slot [(EquipItem, EquipItem, EquipSlot)]. </summary>
Equip,
/// <summary> A characters saved state had its weapons changed. Data is the old mainhand, the old offhand, the new mainhand and the new offhand [(EquipItem, EquipItem, EquipItem, EquipItem)]. </summary>
Weapon,
/// <summary> A characters saved state had a stain changed. Data is the old stain id, the new stain id and the slot [(StainId, StainId, EquipSlot)]. </summary>
Stain,
/// <summary> A characters saved state had a crest visibility changed. Data is the old crest visibility, the new crest visibility and the slot [(bool, bool, EquipSlot)]. </summary>
Crest,
/// <summary> A characters saved state had its customize parameter changed. Data is the old value, the new value and the type [(CustomizeParameterValue, CustomizeParameterValue, CustomizeParameterFlag)]. </summary>
Parameter,
/// <summary> A characters saved state had a material color table value changed. Data is the old value, the new value and the index [(Vector3, Vector3, MaterialValueIndex)] or just the index for resets. </summary>
MaterialValue,
/// <summary> A characters saved state had a design applied. This means everything may have changed. Data is the applied design. [DesignBase] </summary>
Design,
/// <summary> A characters saved state had its state reset to its game values. This means everything may have changed. Data is null. </summary>
Reset,
/// <summary> A characters saved state had a meta toggle changed. Data is the old stain id, the new stain id and the slot [(StainId, StainId, EquipSlot)]. </summary>
Other,
/// <summary> A characters state was reapplied. Data is null. </summary>
Reapply,
}
public enum Priority
{
GlamourerIpc = int.MinValue,
PenumbraAutoRedraw = 0,
}
GlamourerIpc = int.MinValue,
PenumbraAutoRedraw = 0,
}
}
}

View file

@ -30,7 +30,7 @@ public class StateIpcTester : IUiService, IDisposable
private string _base64State = string.Empty;
private string? _getStateString;
public readonly EventSubscriber<nint> StateChanged;
public readonly EventSubscriber<nint, StateChangeType> StateChanged;
private nint _lastStateChangeActor;
private ByteString _lastStateChangeName = ByteString.Empty;
private DateTime _lastStateChangeTime;
@ -44,7 +44,7 @@ public class StateIpcTester : IUiService, IDisposable
public StateIpcTester(DalamudPluginInterface pluginInterface)
{
_pluginInterface = pluginInterface;
StateChanged = Api.IpcSubscribers.StateChanged.Subscriber(_pluginInterface, OnStateChanged);
StateChanged = Api.IpcSubscribers.StateChangedWithType.Subscriber(_pluginInterface, OnStateChanged);
GPoseChanged = Api.IpcSubscribers.GPoseChanged.Subscriber(_pluginInterface, OnGPoseChange);
StateChanged.Disable();
GPoseChanged.Disable();
@ -195,7 +195,7 @@ public class StateIpcTester : IUiService, IDisposable
ImGui.TextUnformatted($"at {_lastStateChangeTime.ToLocalTime().TimeOfDay}");
}
private void OnStateChanged(nint actor)
private void OnStateChanged(nint actor, StateChangeType _)
{
_lastStateChangeActor = actor;
_lastStateChangeTime = DateTime.UtcNow;

View file

@ -1,4 +1,5 @@
using Dalamud.Plugin.Services;
using Glamourer.Api.Enums;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using Glamourer.State;
@ -43,9 +44,9 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
private readonly ConcurrentSet<ActorState> _skips = [];
private DateTime _frame;
private void OnStateChange(StateChanged.Type type, StateSource source, ActorState state, ActorData _1, object? _2)
private void OnStateChange(StateChangeType type, StateSource source, ActorState state, ActorData _1, object? _2)
{
if (type is StateChanged.Type.Design && source.IsIpc())
if (type is StateChangeType.Design && source.IsIpc())
_skips.TryAdd(state);
}

View file

@ -1,3 +1,4 @@
using Glamourer.Api.Enums;
using Glamourer.Designs;
using Glamourer.Designs.Links;
using Glamourer.Events;
@ -38,7 +39,7 @@ public class StateEditor(
var actors = Applier.ForceRedraw(state, source.RequiresChange());
Glamourer.Log.Verbose(
$"Set model id in state {state.Identifier.Incognito(null)} from {old} to {modelId}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Model, source, state, actors, (old, modelId));
StateChanged.Invoke(StateChangeType.Model, source, state, actors, (old, modelId));
}
/// <inheritdoc/>
@ -51,7 +52,7 @@ public class StateEditor(
var actors = Applier.ChangeCustomize(state, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set {idx.ToDefaultName()} customizations in state {state.Identifier.Incognito(null)} from {old.Value} to {value.Value}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Customize, settings.Source, state, actors, (old, value, idx));
StateChanged.Invoke(StateChangeType.Customize, settings.Source, state, actors, (old, value, idx));
}
/// <inheritdoc/>
@ -64,7 +65,7 @@ public class StateEditor(
var actors = Applier.ChangeCustomize(state, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set {applied} customizations in state {state.Identifier.Incognito(null)} from {old} to {customizeInput}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.EntireCustomize, settings.Source, state, actors, (old, applied));
StateChanged.Invoke(StateChangeType.EntireCustomize, settings.Source, state, actors, (old, applied));
}
/// <inheritdoc/>
@ -74,8 +75,8 @@ public class StateEditor(
if (!Editor.ChangeItem(state, slot, item, settings.Source, out var old, settings.Key))
return;
var type = slot.ToIndex() < 10 ? StateChanged.Type.Equip : StateChanged.Type.Weapon;
var actors = type is StateChanged.Type.Equip
var type = slot.ToIndex() < 10 ? StateChangeType.Equip : StateChangeType.Weapon;
var actors = type is StateChangeType.Equip
? Applier.ChangeArmor(state, slot, settings.Source.RequiresChange())
: Applier.ChangeWeapon(state, slot, settings.Source.RequiresChange(),
item.Type != (slot is EquipSlot.MainHand ? state.BaseData.MainhandType : state.BaseData.OffhandType));
@ -107,8 +108,8 @@ public class StateEditor(
out var old, out var oldStain, settings.Key))
return;
var type = slot.ToIndex() < 10 ? StateChanged.Type.Equip : StateChanged.Type.Weapon;
var actors = type is StateChanged.Type.Equip
var type = slot.ToIndex() < 10 ? StateChangeType.Equip : StateChangeType.Weapon;
var actors = type is StateChangeType.Equip
? Applier.ChangeArmor(state, slot, settings.Source.RequiresChange())
: Applier.ChangeWeapon(state, slot, settings.Source.RequiresChange(),
item!.Value.Type != (slot is EquipSlot.MainHand ? state.BaseData.MainhandType : state.BaseData.OffhandType));
@ -119,7 +120,7 @@ public class StateEditor(
Glamourer.Log.Verbose(
$"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item!.Value.Name} ({item.Value.ItemId}) and its stain from {oldStain.Id} to {stain!.Value.Id}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(type, settings.Source, state, actors, (old, item!.Value, slot));
StateChanged.Invoke(StateChanged.Type.Stain, settings.Source, state, actors, (oldStain, stain!.Value, slot));
StateChanged.Invoke(StateChangeType.Stain, settings.Source, state, actors, (oldStain, stain!.Value, slot));
}
/// <inheritdoc/>
@ -132,7 +133,7 @@ public class StateEditor(
var actors = Applier.ChangeStain(state, slot, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set {slot.ToName()} stain in state {state.Identifier.Incognito(null)} from {old.Id} to {stain.Id}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Stain, settings.Source, state, actors, (old, stain, slot));
StateChanged.Invoke(StateChangeType.Stain, settings.Source, state, actors, (old, stain, slot));
}
/// <inheritdoc/>
@ -145,7 +146,7 @@ public class StateEditor(
var actors = Applier.ChangeCrests(state, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set {slot.ToLabel()} crest in state {state.Identifier.Incognito(null)} from {old} to {crest}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Crest, settings.Source, state, actors, (old, crest, slot));
StateChanged.Invoke(StateChangeType.Crest, settings.Source, state, actors, (old, crest, slot));
}
/// <inheritdoc/>
@ -163,7 +164,7 @@ public class StateEditor(
var actors = Applier.ChangeParameters(state, flag, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set {flag} crest in state {state.Identifier.Incognito(null)} from {old} to {@new}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Parameter, settings.Source, state, actors, (old, @new, flag));
StateChanged.Invoke(StateChangeType.Parameter, settings.Source, state, actors, (old, @new, flag));
}
public void ChangeMaterialValue(object data, MaterialValueIndex index, in MaterialValueState newValue, ApplySettings settings)
@ -175,7 +176,7 @@ public class StateEditor(
var actors = Applier.ChangeMaterialValue(state, index, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set material value in state {state.Identifier.Incognito(null)} from {oldValue} to {newValue.Game}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.MaterialValue, settings.Source, state, actors, (oldValue, newValue.Game, index));
StateChanged.Invoke(StateChangeType.MaterialValue, settings.Source, state, actors, (oldValue, newValue.Game, index));
}
public void ResetMaterialValue(object data, MaterialValueIndex index, ApplySettings settings)
@ -187,7 +188,7 @@ public class StateEditor(
var actors = Applier.ChangeMaterialValue(state, index, true);
Glamourer.Log.Verbose(
$"Reset material value in state {state.Identifier.Incognito(null)} to game value. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.MaterialValue, settings.Source, state, actors, index);
StateChanged.Invoke(StateChangeType.MaterialValue, settings.Source, state, actors, index);
}
/// <inheritdoc/>
@ -200,7 +201,7 @@ public class StateEditor(
var actors = Applier.ChangeMetaState(state, index, settings.Source.RequiresChange());
Glamourer.Log.Verbose(
$"Set Head Gear Visibility in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Other, settings.Source, state, actors, (old, value, MetaIndex.HatState));
StateChanged.Invoke(StateChangeType.Other, settings.Source, state, actors, (old, value, MetaIndex.HatState));
}
/// <inheritdoc/>
@ -357,7 +358,7 @@ public class StateEditor(
Glamourer.Log.Verbose(
$"Applied design to {state.Identifier.Incognito(null)}. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Design, state.Sources[MetaIndex.Wetness], state, actors, mergedDesign.Design);
StateChanged.Invoke(StateChangeType.Design, state.Sources[MetaIndex.Wetness], state, actors, mergedDesign.Design);
return;

View file

@ -1,4 +1,5 @@
using Dalamud.Plugin.Services;
using Glamourer.Api.Enums;
using Glamourer.Designs;
using Glamourer.Designs.Links;
using Glamourer.Events;
@ -257,7 +258,7 @@ public sealed class StateManager(
Glamourer.Log.Verbose(
$"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Reset, source, state, actors, null);
StateChanged.Invoke(StateChangeType.Reset, source, state, actors, null);
}
public void ResetAdvancedState(ActorState state, StateSource source, uint key = 0)
@ -282,7 +283,7 @@ public sealed class StateManager(
Glamourer.Log.Verbose(
$"Reset advanced customization and dye state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
StateChanged.Invoke(StateChanged.Type.Reset, source, state, actors, null);
StateChanged.Invoke(StateChangeType.Reset, source, state, actors, null);
}
public void ResetCustomize(ActorState state, StateSource source, uint key = 0)
@ -414,7 +415,7 @@ public sealed class StateManager(
{
var data = Applier.ApplyAll(state,
forceRedraw || !actor.Model.IsHuman || CustomizeArray.Compare(actor.Model.GetCustomize(), state.ModelData.Customize).RequiresRedraw(), false);
StateChanged.Invoke(StateChanged.Type.Reapply, source, state, data, null);
StateChanged.Invoke(StateChangeType.Reapply, source, state, data, null);
}
public void DeleteState(ActorIdentifier identifier)