mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-25 06:01:48 +01:00
Actually push what I said in the message before.
This commit is contained in:
parent
8012c92704
commit
f1d377c9dc
109 changed files with 1201 additions and 1208 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 18
|
# Visual Studio Version 18
|
||||||
VisualStudioVersion = 18.3.11415.281 d18.3
|
VisualStudioVersion = 18.3.11415.281
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{383AEE76-D423-431C-893A-7AB3DEA13630}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{383AEE76-D423-431C-893A-7AB3DEA13630}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
|
@ -20,8 +20,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.GameData", "Penumb
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.String", "Penumbra.String\Penumbra.String.csproj", "{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.String", "Penumbra.String\Penumbra.String.csproj", "{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OtterGui", "OtterGui\OtterGui.csproj", "{EF233CE2-F243-449E-BE05-72B9D110E419}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Glamourer.Api", "Glamourer.Api\Glamourer.Api.csproj", "{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Glamourer.Api", "Glamourer.Api\Glamourer.Api.csproj", "{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luna", "Luna\Luna\Luna.csproj", "{DEA936D7-1386-55A1-7451-E0C240F56E9D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Luna", "Luna\Luna\Luna.csproj", "{DEA936D7-1386-55A1-7451-E0C240F56E9D}"
|
||||||
|
|
@ -68,14 +66,6 @@ Global
|
||||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.Build.0 = Release|x64
|
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|Any CPU.Build.0 = Release|x64
|
||||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|x64.ActiveCfg = Release|x64
|
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|x64.ActiveCfg = Release|x64
|
||||||
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|x64.Build.0 = Release|x64
|
{AAFE22E7-0F9B-462A-AAA3-6EE3B268F3F8}.Release|x64.Build.0 = Release|x64
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.ActiveCfg = Debug|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|Any CPU.Build.0 = Debug|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.ActiveCfg = Release|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|Any CPU.Build.0 = Release|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{EF233CE2-F243-449E-BE05-72B9D110E419}.Release|x64.Build.0 = Release|x64
|
|
||||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.ActiveCfg = Debug|x64
|
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.Build.0 = Debug|x64
|
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|Any CPU.Build.0 = Debug|x64
|
||||||
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|x64.ActiveCfg = Debug|x64
|
{9B46691B-FAB2-4CC3-9B89-C8B91A590F47}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterGui.Extensions;
|
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
@ -73,26 +72,26 @@ public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, A
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void Lock(ActorState state, uint key, ApplyFlag flags)
|
internal static void Lock(ActorState state, uint key, ApplyFlag flags)
|
||||||
{
|
{
|
||||||
if ((flags & ApplyFlag.Lock) != 0 && key != 0)
|
if ((flags & ApplyFlag.Lock) is not 0 && key is not 0)
|
||||||
state.Lock(key);
|
state.Lock(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal IEnumerable<ActorState> FindStates(string objectName)
|
internal IEnumerable<ActorState> FindStates(string objectName)
|
||||||
{
|
{
|
||||||
if (objectName.Length == 0 || !ByteString.FromString(objectName, out var byteString))
|
if (objectName.Length is 0 || !ByteString.FromString(objectName, out var byteString))
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
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(ArrayExtensions.SelectWhere(objects
|
.Concat(objects
|
||||||
.Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString), kvp =>
|
.Where(kvp => kvp.Key is { IsValid: true, Type: IdentifierType.Player } && kvp.Key.PlayerName == byteString).SelectWhere(kvp =>
|
||||||
{
|
{
|
||||||
if (stateManager.ContainsKey(kvp.Key))
|
if (stateManager.ContainsKey(kvp.Key))
|
||||||
return (false, null);
|
return (false, null);
|
||||||
|
|
||||||
var ret = stateManager.GetOrCreate(kvp.Key, kvp.Value.Objects[0], out var state);
|
var ret = stateManager.GetOrCreate(kvp.Key, kvp.Value.Objects[0], out var state);
|
||||||
return (ret, state);
|
return (ret, state);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,14 @@ public class DesignsApi(
|
||||||
: IGlamourerApiDesigns, IApiService
|
: IGlamourerApiDesigns, IApiService
|
||||||
{
|
{
|
||||||
public Dictionary<Guid, string> GetDesignList()
|
public Dictionary<Guid, string> GetDesignList()
|
||||||
=> designs.Designs.ToDictionary(d => d.Identifier, d => d.Name.Text);
|
=> designs.Designs.ToDictionary(d => d.Identifier, d => d.Name);
|
||||||
|
|
||||||
public Dictionary<Guid, (string DisplayName, string FullPath, uint DisplayColor, bool ShownInQdb)> GetDesignListExtended()
|
public Dictionary<Guid, (string DisplayName, string FullPath, uint DisplayColor, bool ShownInQdb)> GetDesignListExtended()
|
||||||
=> designs.Designs.ToDictionary(d => d.Identifier, d => (d.DisplayName, d.Path.CurrentPath, color.GetColor(d).Color, d.QuickDesign));
|
=> designs.Designs.ToDictionary(d => d.Identifier, d => (d.DisplayName, d.Path.CurrentPath, color.GetColor(d).Color, d.QuickDesign));
|
||||||
|
|
||||||
public (string DisplayName, string FullPath, uint DisplayColor, bool ShowInQdb) GetExtendedDesignData(Guid designId)
|
public (string DisplayName, string FullPath, uint DisplayColor, bool ShowInQdb) GetExtendedDesignData(Guid designId)
|
||||||
=> designs.Designs.ByIdentifier(designId) is { } d
|
=> designs.Designs.ByIdentifier(designId) is { } d
|
||||||
? (d.Name.Text, d.Path.CurrentPath, color.GetColor(d).Color, d.QuickDesign)
|
? (d.Name, d.Path.CurrentPath, color.GetColor(d).Color, d.QuickDesign)
|
||||||
: (string.Empty, string.Empty, 0, false);
|
: (string.Empty, string.Empty, 0, false);
|
||||||
|
|
||||||
public GlamourerApiEc ApplyDesign(Guid designId, int objectIndex, uint key, ApplyFlag flags)
|
public GlamourerApiEc ApplyDesign(Guid designId, int objectIndex, uint key, ApplyFlag flags)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
using Glamourer.Api.Enums;
|
using Glamourer.Api.Enums;
|
||||||
using Glamourer.Automation;
|
using Glamourer.Automation;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
@ -143,10 +142,10 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
|
|
||||||
public GlamourerApiEc ReapplyStateName(string playerName, uint key, ApplyFlag flags)
|
public GlamourerApiEc ReapplyStateName(string playerName, uint key, ApplyFlag flags)
|
||||||
{
|
{
|
||||||
var args = ApiHelpers.Args("Name", playerName, "Key", key, "Flags", flags);
|
var args = ApiHelpers.Args("Name", playerName, "Key", key, "Flags", flags);
|
||||||
var states = _helpers.FindExistingStates(playerName);
|
var states = _helpers.FindExistingStates(playerName);
|
||||||
|
|
||||||
var any = false;
|
var any = false;
|
||||||
var anyReapplied = false;
|
var anyReapplied = false;
|
||||||
foreach (var state in states)
|
foreach (var state in states)
|
||||||
{
|
{
|
||||||
|
|
@ -154,7 +153,7 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
if (!state.CanUnlock(key))
|
if (!state.CanUnlock(key))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
anyReapplied = true;
|
anyReapplied = true;
|
||||||
anyReapplied |= Reapply(state, key, flags) is GlamourerApiEc.Success;
|
anyReapplied |= Reapply(state, key, flags) is GlamourerApiEc.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,13 +226,14 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
public GlamourerApiEc CanUnlock(int objectIndex, uint key, out bool isLocked, out bool canUnlock)
|
public GlamourerApiEc CanUnlock(int objectIndex, uint key, out bool isLocked, out bool canUnlock)
|
||||||
{
|
{
|
||||||
var args = ApiHelpers.Args("Index", objectIndex, "Key", key);
|
var args = ApiHelpers.Args("Index", objectIndex, "Key", key);
|
||||||
isLocked = false;
|
isLocked = false;
|
||||||
canUnlock = true;
|
canUnlock = true;
|
||||||
if (_helpers.FindExistingState(objectIndex, out var state) is not GlamourerApiEc.Success)
|
if (_helpers.FindExistingState(objectIndex, out var state) is not GlamourerApiEc.Success)
|
||||||
return ApiHelpers.Return(GlamourerApiEc.ActorNotFound, args);
|
return ApiHelpers.Return(GlamourerApiEc.ActorNotFound, args);
|
||||||
if (state is null)
|
if (state is null)
|
||||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||||
isLocked = state.IsLocked;
|
|
||||||
|
isLocked = state.IsLocked;
|
||||||
canUnlock = state.CanUnlock(key);
|
canUnlock = state.CanUnlock(key);
|
||||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||||
}
|
}
|
||||||
|
|
@ -423,29 +423,31 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAutoRedrawChange(bool autoReload)
|
private void OnAutoRedrawChange(in bool autoReload)
|
||||||
=> AutoReloadGearChanged?.Invoke(autoReload);
|
=> AutoReloadGearChanged?.Invoke(autoReload);
|
||||||
|
|
||||||
private void OnStateChanged(StateChangeType type, StateSource _2, ActorState _3, ActorData actors, ITransaction? _5)
|
private void OnStateChanged(in StateChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
Glamourer.Log.Excessive($"[OnStateChanged] State Changed with Type {type} [Affecting {actors.ToLazyString("nothing")}.]");
|
Glamourer.Log.Excessive(
|
||||||
if (StateChanged != null)
|
$"[OnStateChanged] State Changed with Type {arguments.Type} [Affecting {arguments.Actors.ToLazyString("nothing")}.]");
|
||||||
foreach (var actor in actors.Objects)
|
if (StateChanged is not null)
|
||||||
|
foreach (var actor in arguments.Actors.Objects)
|
||||||
StateChanged.Invoke(actor.Address);
|
StateChanged.Invoke(actor.Address);
|
||||||
|
|
||||||
if (StateChangedWithType != null)
|
if (StateChangedWithType is not null)
|
||||||
foreach (var actor in actors.Objects)
|
foreach (var actor in arguments.Actors.Objects)
|
||||||
StateChangedWithType.Invoke(actor.Address, type);
|
StateChangedWithType.Invoke(actor.Address, arguments.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateFinalized(StateFinalizationType type, ActorData actors)
|
private void OnStateFinalized(in StateFinalized.Arguments arguments)
|
||||||
{
|
{
|
||||||
Glamourer.Log.Verbose($"[OnStateUpdated] State Updated with Type {type}. [Affecting {actors.ToLazyString("nothing")}.]");
|
Glamourer.Log.Verbose(
|
||||||
if (StateFinalized != null)
|
$"[OnStateUpdated] State Updated with Type {arguments.Type}. [Affecting {arguments.Actors.ToLazyString("nothing")}.]");
|
||||||
foreach (var actor in actors.Objects)
|
if (StateFinalized is not null)
|
||||||
StateFinalized.Invoke(actor.Address, type);
|
foreach (var actor in arguments.Actors.Objects)
|
||||||
|
StateFinalized.Invoke(actor.Address, arguments.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGPoseChange(bool gPose)
|
private void OnGPoseChange(in bool gPose)
|
||||||
=> GPoseChanged?.Invoke(gPose);
|
=> GPoseChanged?.Invoke(gPose);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using Glamourer.Events;
|
||||||
using Glamourer.Interop;
|
using Glamourer.Interop;
|
||||||
using Glamourer.Interop.Material;
|
using Glamourer.Interop.Material;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
@ -15,7 +16,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Automation;
|
namespace Glamourer.Automation;
|
||||||
|
|
||||||
public sealed class AutoDesignApplier : IDisposable
|
public sealed class AutoDesignApplier : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
private readonly AutoDesignManager _manager;
|
private readonly AutoDesignManager _manager;
|
||||||
|
|
@ -72,38 +73,38 @@ public sealed class AutoDesignApplier : IDisposable
|
||||||
_jobs.JobChanged -= OnJobChange;
|
_jobs.JobChanged -= OnJobChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnWeaponLoading(Actor actor, EquipSlot slot, ref CharacterWeapon weapon)
|
private void OnWeaponLoading(in WeaponLoading.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (!_jobChangeState.HasState || !_config.EnableAutoDesigns)
|
if (!_jobChangeState.HasState || !_config.EnableAutoDesigns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var id = actor.GetIdentifier(_actors);
|
var id = arguments.Actor.GetIdentifier(_actors);
|
||||||
if (id == _jobChangeState.Identifier)
|
if (id == _jobChangeState.Identifier)
|
||||||
{
|
{
|
||||||
var state = _jobChangeState.State!;
|
var state = _jobChangeState.State!;
|
||||||
var current = state.BaseData.Item(slot);
|
var current = state.BaseData.Item(arguments.Slot);
|
||||||
switch (slot)
|
switch (arguments.Slot)
|
||||||
{
|
{
|
||||||
case EquipSlot.MainHand:
|
case EquipSlot.MainHand:
|
||||||
{
|
{
|
||||||
if (_jobChangeState.TryGetValue(current.Type, actor.Job, false, out var data))
|
if (_jobChangeState.TryGetValue(current.Type, arguments.Actor.Job, false, out var data))
|
||||||
{
|
{
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
$"Changing Mainhand from {state.ModelData.Weapon(EquipSlot.MainHand)} | {state.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
$"Changing Mainhand from {state.ModelData.Weapon(EquipSlot.MainHand)} | {state.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{arguments.Actor.Address:X}.");
|
||||||
_state.ChangeItem(state, EquipSlot.MainHand, data.Item1, new ApplySettings(Source: data.Item2));
|
_state.ChangeItem(state, EquipSlot.MainHand, data.Item1, new ApplySettings(Source: data.Item2));
|
||||||
weapon = state.ModelData.Weapon(EquipSlot.MainHand);
|
arguments.Weapon = state.ModelData.Weapon(EquipSlot.MainHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EquipSlot.OffHand when current.Type == state.BaseData.MainhandType.Offhand():
|
case EquipSlot.OffHand when current.Type == state.BaseData.MainhandType.Offhand():
|
||||||
{
|
{
|
||||||
if (_jobChangeState.TryGetValue(current.Type, actor.Job, false, out var data))
|
if (_jobChangeState.TryGetValue(current.Type, arguments.Actor.Job, false, out var data))
|
||||||
{
|
{
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
$"Changing Offhand from {state.ModelData.Weapon(EquipSlot.OffHand)} | {state.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
$"Changing Offhand from {state.ModelData.Weapon(EquipSlot.OffHand)} | {state.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{arguments.Actor.Address:X}.");
|
||||||
_state.ChangeItem(state, EquipSlot.OffHand, data.Item1, new ApplySettings(Source: data.Item2));
|
_state.ChangeItem(state, EquipSlot.OffHand, data.Item1, new ApplySettings(Source: data.Item2));
|
||||||
weapon = state.ModelData.Weapon(EquipSlot.OffHand);
|
arguments.Weapon = state.ModelData.Weapon(EquipSlot.OffHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
_jobChangeState.Reset();
|
_jobChangeState.Reset();
|
||||||
|
|
@ -117,22 +118,22 @@ public sealed class AutoDesignApplier : IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAutomationChange(AutomationChanged.Type type, AutoDesignSet? set, object? bonusData)
|
private void OnAutomationChange(in AutomationChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (!_config.EnableAutoDesigns || set == null)
|
if (!_config.EnableAutoDesigns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (type)
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case AutomationChanged.Type.ToggleSet when !set.Enabled:
|
// The automation set was disabled or deleted, no other for those identifiers can be enabled, remove existing Fixed Locks.
|
||||||
case AutomationChanged.Type.DeletedDesign when set.Enabled:
|
case AutomationChanged.Type.ToggleSet when arguments.Set.Enabled:
|
||||||
// The automation set was disabled or deleted, no other for those identifiers can be enabled, remove existing Fixed Locks.
|
case AutomationChanged.Type.DeletedDesign when arguments.Set.Enabled:
|
||||||
RemoveOld(set.Identifiers);
|
RemoveOld(arguments.Set.Identifiers);
|
||||||
break;
|
break;
|
||||||
case AutomationChanged.Type.ChangeIdentifier when set.Enabled:
|
case AutomationChanged.Type.ChangeIdentifier
|
||||||
|
when arguments.As<AutomationChanged.ChangeIdentifierArguments>().Set is { Enabled: true } set:
|
||||||
// Remove fixed state from the old identifiers assigned and the old enabled set, if any.
|
// Remove fixed state from the old identifiers assigned and the old enabled set, if any.
|
||||||
var (oldIds, _, _) = ((ActorIdentifier[], ActorIdentifier, AutoDesignSet?))bonusData!;
|
RemoveOld(arguments.As<AutomationChanged.ChangeIdentifierArguments>().OldIdentifiers);
|
||||||
RemoveOld(oldIds);
|
|
||||||
ApplyNew(set); // Does not need to disable oldSet because same identifiers.
|
ApplyNew(set); // Does not need to disable oldSet because same identifiers.
|
||||||
break;
|
break;
|
||||||
case AutomationChanged.Type.ToggleSet: // Does not need to disable old states because same identifiers.
|
case AutomationChanged.Type.ToggleSet: // Does not need to disable old states because same identifiers.
|
||||||
|
|
@ -143,7 +144,7 @@ public sealed class AutoDesignApplier : IDisposable
|
||||||
case AutomationChanged.Type.ChangedConditions:
|
case AutomationChanged.Type.ChangedConditions:
|
||||||
case AutomationChanged.Type.ChangedType:
|
case AutomationChanged.Type.ChangedType:
|
||||||
case AutomationChanged.Type.ChangedData:
|
case AutomationChanged.Type.ChangedData:
|
||||||
ApplyNew(set);
|
ApplyNew(arguments.Set);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,7 +304,7 @@ public sealed class AutoDesignApplier : IDisposable
|
||||||
mergedDesign.ResetTemporarySettings = true;
|
mergedDesign.ResetTemporarySettings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_state.ApplyDesign(state, mergedDesign, new ApplySettings(0, StateSource.Fixed, respectManual, fromJobChange, false, false, false));
|
_state.ApplyDesign(state, mergedDesign, new ApplySettings(0, StateSource.Fixed, respectManual, fromJobChange));
|
||||||
forcedRedraw = mergedDesign.ForcedRedraw;
|
forcedRedraw = mergedDesign.ForcedRedraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,7 +346,7 @@ public sealed class AutoDesignApplier : IDisposable
|
||||||
|
|
||||||
internal static int NewGearsetId = -1;
|
internal static int NewGearsetId = -1;
|
||||||
|
|
||||||
private void OnEquippedGearset(string name, int id, int prior, byte _, byte job)
|
private void OnEquippedGearset(in EquippedGearset.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (!_config.EnableAutoDesigns)
|
if (!_config.EnableAutoDesigns)
|
||||||
return;
|
return;
|
||||||
|
|
@ -357,9 +358,9 @@ public sealed class AutoDesignApplier : IDisposable
|
||||||
if (!GetPlayerSet(player, out var set) || !_state.TryGetValue(player, out var state))
|
if (!GetPlayerSet(player, out var set) || !_state.TryGetValue(player, out var state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var respectManual = prior == id;
|
var respectManual = arguments.PriorId == arguments.Id;
|
||||||
NewGearsetId = id;
|
NewGearsetId = arguments.Id;
|
||||||
Reduce(data.Objects[0], state, set, respectManual, job != state.LastJob, prior == id, out var forcedRedraw);
|
Reduce(data.Objects[0], state, set, respectManual, arguments.JobId != state.LastJob, arguments.PriorId == arguments.Id, out var forcedRedraw);
|
||||||
NewGearsetId = -1;
|
NewGearsetId = -1;
|
||||||
foreach (var actor in data.Objects)
|
foreach (var actor in data.Objects)
|
||||||
_state.ReapplyState(actor, forcedRedraw, StateSource.Fixed);
|
_state.ReapplyState(actor, forcedRedraw, StateSource.Fixed);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
using Dalamud.Game.ClientState.Objects.Enums;
|
using Dalamud.Game.ClientState.Objects.Enums;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Designs.Special;
|
using Glamourer.Designs.Special;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.Interop;
|
using Glamourer.Interop;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Extensions;
|
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
@ -16,7 +14,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Automation;
|
namespace Glamourer.Automation;
|
||||||
|
|
||||||
public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDisposable
|
public sealed class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDisposable, IService
|
||||||
{
|
{
|
||||||
public const int CurrentVersion = 1;
|
public const int CurrentVersion = 1;
|
||||||
|
|
||||||
|
|
@ -77,7 +75,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
_data.Add(newSet);
|
_data.Add(newSet);
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Created new design set for {newSet.Identifiers[0].Incognito(null)}.");
|
Glamourer.Log.Debug($"Created new design set for {newSet.Identifiers[0].Incognito(null)}.");
|
||||||
_event.Invoke(AutomationChanged.Type.AddedSet, newSet, (_data.Count - 1, name));
|
_event.Invoke(new AutomationChanged.AddedSetArguments(newSet, _data.Count - 1, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DuplicateDesignSet(AutoDesignSet set)
|
public void DuplicateDesignSet(AutoDesignSet set)
|
||||||
|
|
@ -102,7 +100,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Duplicated new design set for {newSet.Identifiers[0].Incognito(null)} with {newSet.Designs.Count} auto designs from existing set.");
|
$"Duplicated new design set for {newSet.Identifiers[0].Incognito(null)} with {newSet.Designs.Count} auto designs from existing set.");
|
||||||
_event.Invoke(AutomationChanged.Type.AddedSet, newSet, (_data.Count - 1, name));
|
_event.Invoke(new AutomationChanged.AddedSetArguments(newSet, _data.Count - 1, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteDesignSet(int whichSet)
|
public void DeleteDesignSet(int whichSet)
|
||||||
|
|
@ -121,12 +119,12 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
_data.RemoveAt(whichSet);
|
_data.RemoveAt(whichSet);
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Deleted design set {whichSet + 1}.");
|
Glamourer.Log.Debug($"Deleted design set {whichSet + 1}.");
|
||||||
_event.Invoke(AutomationChanged.Type.DeletedSet, set, whichSet);
|
_event.Invoke(new AutomationChanged.DeletedSetArguments(set, whichSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Rename(int whichSet, string newName)
|
public void Rename(int whichSet, string newName)
|
||||||
{
|
{
|
||||||
if (whichSet >= _data.Count || whichSet < 0 || newName.Length == 0)
|
if (whichSet >= _data.Count || whichSet < 0 || newName.Length is 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var set = _data[whichSet];
|
var set = _data[whichSet];
|
||||||
|
|
@ -137,7 +135,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
set.Name = newName;
|
set.Name = newName;
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Renamed design set {whichSet + 1} from {old} to {newName}.");
|
Glamourer.Log.Debug($"Renamed design set {whichSet + 1} from {old} to {newName}.");
|
||||||
_event.Invoke(AutomationChanged.Type.RenamedSet, set, (old, newName));
|
_event.Invoke(new AutomationChanged.RenamedSetArguments(set, old, newName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -148,7 +146,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Moved design set {whichSet + 1} to position {toWhichSet + 1}.");
|
Glamourer.Log.Debug($"Moved design set {whichSet + 1} to position {toWhichSet + 1}.");
|
||||||
_event.Invoke(AutomationChanged.Type.MovedSet, _data[toWhichSet], (whichSet, toWhichSet));
|
_event.Invoke(new AutomationChanged.MovedSetArguments(_data[toWhichSet], whichSet, toWhichSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeIdentifier(int whichSet, ActorIdentifier to)
|
public void ChangeIdentifier(int whichSet, ActorIdentifier to)
|
||||||
|
|
@ -180,7 +178,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed Identifier of design set {whichSet + 1} from {old[0].Incognito(null)} to {to.Incognito(null)}.");
|
Glamourer.Log.Debug($"Changed Identifier of design set {whichSet + 1} from {old[0].Incognito(null)} to {to.Incognito(null)}.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangeIdentifier, set, (old, to, oldEnabled));
|
_event.Invoke(new AutomationChanged.ChangeIdentifierArguments(set, old, to, oldEnabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetState(int whichSet, bool value)
|
public void SetState(int whichSet, bool value)
|
||||||
|
|
@ -214,7 +212,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed enabled state of design set {whichSet + 1} to {value}.");
|
Glamourer.Log.Debug($"Changed enabled state of design set {whichSet + 1} to {value}.");
|
||||||
_event.Invoke(AutomationChanged.Type.ToggleSet, set, oldEnabled);
|
_event.Invoke(new AutomationChanged.ToggleSetArguments(set, oldEnabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeBaseState(int whichSet, AutoDesignSet.Base newBase)
|
public void ChangeBaseState(int whichSet, AutoDesignSet.Base newBase)
|
||||||
|
|
@ -230,7 +228,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
set.BaseState = newBase;
|
set.BaseState = newBase;
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed base state of set {whichSet + 1} from {old} to {newBase}.");
|
Glamourer.Log.Debug($"Changed base state of set {whichSet + 1} from {old} to {newBase}.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedBase, set, (old, newBase));
|
_event.Invoke(new AutomationChanged.ChangedBaseArguments(set, old, newBase));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeResetSettings(int whichSet, bool newValue)
|
public void ChangeResetSettings(int whichSet, bool newValue)
|
||||||
|
|
@ -246,12 +244,12 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
set.ResetTemporarySettings = newValue;
|
set.ResetTemporarySettings = newValue;
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed resetting of temporary settings of set {whichSet + 1} from {old} to {newValue}.");
|
Glamourer.Log.Debug($"Changed resetting of temporary settings of set {whichSet + 1} from {old} to {newValue}.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedTemporarySettingsReset, set, newValue);
|
_event.Invoke(new AutomationChanged.ChangedTemporarySettingsResetArguments(set, newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDesign(AutoDesignSet set, IDesignStandIn design)
|
public void AddDesign(AutoDesignSet set, IDesignStandIn design)
|
||||||
{
|
{
|
||||||
var newDesign = new AutoDesign()
|
var newDesign = new AutoDesign
|
||||||
{
|
{
|
||||||
Design = design,
|
Design = design,
|
||||||
Type = ApplicationType.All,
|
Type = ApplicationType.All,
|
||||||
|
|
@ -261,7 +259,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Added new associated design {design.ResolveName(true)} as design {set.Designs.Count} to design set.");
|
$"Added new associated design {design.ResolveName(true)} as design {set.Designs.Count} to design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.AddedDesign, set, set.Designs.Count - 1);
|
_event.Invoke(new AutomationChanged.AddedDesignArguments(set, set.Designs.Count - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks> Only used to move between sets. </remarks>
|
/// <remarks> Only used to move between sets. </remarks>
|
||||||
|
|
@ -275,8 +273,8 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
from.Designs.RemoveAt(idx);
|
from.Designs.RemoveAt(idx);
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Moved design {idx} from design set {from.Name} to design set {to.Name}.");
|
Glamourer.Log.Debug($"Moved design {idx} from design set {from.Name} to design set {to.Name}.");
|
||||||
_event.Invoke(AutomationChanged.Type.AddedDesign, to, to.Designs.Count - 1);
|
_event.Invoke(new AutomationChanged.AddedDesignArguments(to, to.Designs.Count - 1));
|
||||||
_event.Invoke(AutomationChanged.Type.DeletedDesign, from, idx);
|
_event.Invoke(new AutomationChanged.DeletedDesignArguments(from, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteDesign(AutoDesignSet set, int which)
|
public void DeleteDesign(AutoDesignSet set, int which)
|
||||||
|
|
@ -287,7 +285,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
set.Designs.RemoveAt(which);
|
set.Designs.RemoveAt(which);
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Removed associated design {which + 1} from design set.");
|
Glamourer.Log.Debug($"Removed associated design {which + 1} from design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.DeletedDesign, set, which);
|
_event.Invoke(new AutomationChanged.DeletedDesignArguments(set, which));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveDesign(AutoDesignSet set, int from, int to)
|
public void MoveDesign(AutoDesignSet set, int from, int to)
|
||||||
|
|
@ -297,7 +295,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Moved design {from + 1} to {to + 1} in design set.");
|
Glamourer.Log.Debug($"Moved design {from + 1} to {to + 1} in design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.MovedDesign, set, (from, to));
|
_event.Invoke(new AutomationChanged.MovedDesignArguments(set, from, to));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeDesign(AutoDesignSet set, int which, IDesignStandIn newDesign)
|
public void ChangeDesign(AutoDesignSet set, int which, IDesignStandIn newDesign)
|
||||||
|
|
@ -314,7 +312,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Changed linked design from {old.ResolveName(true)} to {newDesign.ResolveName(true)} for associated design {which + 1} in design set.");
|
$"Changed linked design from {old.ResolveName(true)} to {newDesign.ResolveName(true)} for associated design {which + 1} in design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedDesign, set, (which, old, newDesign));
|
_event.Invoke(new AutomationChanged.ChangedDesignArguments(set, which, old, newDesign));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeJobCondition(AutoDesignSet set, int which, JobGroup jobs)
|
public void ChangeJobCondition(AutoDesignSet set, int which, JobGroup jobs)
|
||||||
|
|
@ -331,7 +329,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
design.Jobs = jobs;
|
design.Jobs = jobs;
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed job condition from {old.Id} to {jobs.Id} for associated design {which + 1} in design set.");
|
Glamourer.Log.Debug($"Changed job condition from {old.Id} to {jobs.Id} for associated design {which + 1} in design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedConditions, set, (which, old, jobs));
|
_event.Invoke(new AutomationChanged.ChangedConditionsArguments(set, which, old, jobs));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeGearsetCondition(AutoDesignSet set, int which, short index)
|
public void ChangeGearsetCondition(AutoDesignSet set, int which, short index)
|
||||||
|
|
@ -347,7 +345,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
design.GearsetIndex = index;
|
design.GearsetIndex = index;
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed gearset condition from {old} to {index} for associated design {which + 1} in design set.");
|
Glamourer.Log.Debug($"Changed gearset condition from {old} to {index} for associated design {which + 1} in design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedConditions, set, (which, old, index));
|
_event.Invoke(new AutomationChanged.ChangedConditionsArguments(set, which, default, default));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeApplicationType(AutoDesignSet set, int which, ApplicationType applicationType)
|
public void ChangeApplicationType(AutoDesignSet set, int which, ApplicationType applicationType)
|
||||||
|
|
@ -364,7 +362,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
design.Type = applicationType;
|
design.Type = applicationType;
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed application type from {old} to {applicationType} for associated design {which + 1} in design set.");
|
Glamourer.Log.Debug($"Changed application type from {old} to {applicationType} for associated design {which + 1} in design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedType, set, (which, old, applicationType));
|
_event.Invoke(new AutomationChanged.ChangedTypeArguments(set, which, old, applicationType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeData(AutoDesignSet set, int which, object data)
|
public void ChangeData(AutoDesignSet set, int which, object data)
|
||||||
|
|
@ -378,7 +376,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
Glamourer.Log.Debug($"Changed additional design data for associated design {which + 1} in design set.");
|
Glamourer.Log.Debug($"Changed additional design data for associated design {which + 1} in design set.");
|
||||||
_event.Invoke(AutomationChanged.Type.ChangedData, set, (which, data));
|
_event.Invoke(new AutomationChanged.ChangedDataArguments(set, which, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToFilePath(FilenameService fileNames)
|
public string ToFilePath(FilenameService fileNames)
|
||||||
|
|
@ -397,7 +395,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
foreach (var set in _data)
|
foreach (var set in _data)
|
||||||
array.Add(set.Serialize());
|
array.Add(set.Serialize());
|
||||||
|
|
||||||
return new JObject()
|
return new JObject
|
||||||
{
|
{
|
||||||
["Version"] = CurrentVersion,
|
["Version"] = CurrentVersion,
|
||||||
["Data"] = array,
|
["Data"] = array,
|
||||||
|
|
@ -424,9 +422,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
Glamourer.Messager.NotificationMessage("Failure to load automated designs: No valid version available.",
|
Glamourer.Messager.NotificationMessage("Failure to load automated designs: No valid version available.",
|
||||||
NotificationType.Error);
|
NotificationType.Error);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1: LoadV1(obj["Data"]); break;
|
||||||
LoadV1(obj["Data"]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -638,17 +634,17 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChange(DesignChanged.Type type, Design design, ITransaction? _)
|
private void OnDesignChange(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (type is not DesignChanged.Type.Deleted)
|
if (arguments.Type is not DesignChanged.Type.Deleted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var (set, idx) in this.WithIndex())
|
foreach (var (idx, set) in this.Index())
|
||||||
{
|
{
|
||||||
var deleted = 0;
|
var deleted = 0;
|
||||||
for (var i = 0; i < set.Designs.Count; ++i)
|
for (var i = 0; i < set.Designs.Count; ++i)
|
||||||
{
|
{
|
||||||
if (set.Designs[i].Design != design)
|
if (set.Designs[i].Design != arguments.Design)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
DeleteDesign(set, i--);
|
DeleteDesign(set, i--);
|
||||||
|
|
@ -657,7 +653,7 @@ public class AutoDesignManager : ISavable, IReadOnlyList<AutoDesignSet>, IDispos
|
||||||
|
|
||||||
if (deleted > 0)
|
if (deleted > 0)
|
||||||
Glamourer.Log.Information(
|
Glamourer.Log.Information(
|
||||||
$"Removed {deleted} automated designs from automated design set {idx} due to deletion of {design.Incognito}.");
|
$"Removed {deleted} automated designs from automated design set {idx} due to deletion of {arguments.Design.Incognito}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using Penumbra.String;
|
||||||
|
|
||||||
namespace Glamourer.Automation;
|
namespace Glamourer.Automation;
|
||||||
|
|
||||||
public class FixedDesignMigrator(JobService jobs)
|
public sealed class FixedDesignMigrator(JobService jobs) : IRequiredService
|
||||||
{
|
{
|
||||||
private List<(string Name, List<(string, JobGroup, bool)> Data)>? _migratedData;
|
private List<(string Name, List<(string, JobGroup, bool)> Data)>? _migratedData;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||||
|
|
||||||
namespace Glamourer.Config;
|
namespace Glamourer.Config;
|
||||||
|
|
||||||
public sealed partial class Configuration : IPluginConfiguration, ISavable
|
public sealed partial class Configuration : IPluginConfiguration, ISavable, IService
|
||||||
{
|
{
|
||||||
public const int CurrentVersion = 9;
|
public const int CurrentVersion = 9;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||||
|
|
||||||
namespace Glamourer.Config;
|
namespace Glamourer.Config;
|
||||||
|
|
||||||
public partial class EphemeralConfig : ISavable
|
public partial class EphemeralConfig : ISavable, IService
|
||||||
{
|
{
|
||||||
public int Version { get; set; } = Configuration.CurrentVersion;
|
public int Version { get; set; } = Configuration.CurrentVersion;
|
||||||
|
|
||||||
|
|
@ -16,18 +16,13 @@ public partial class EphemeralConfig : ISavable
|
||||||
private bool _incognitoMode;
|
private bool _incognitoMode;
|
||||||
|
|
||||||
public bool UnlockDetailMode { get; set; } = true;
|
public bool UnlockDetailMode { get; set; } = true;
|
||||||
public bool ShowDesignQuickBar { get; set; } = false;
|
public bool ShowDesignQuickBar { get; set; }
|
||||||
public bool LockDesignQuickBar { get; set; } = false;
|
public bool LockDesignQuickBar { get; set; }
|
||||||
public bool LockMainWindow { get; set; } = false;
|
public bool LockMainWindow { get; set; }
|
||||||
public MainTabType SelectedMainTab { get; set; } = MainTabType.Settings;
|
public MainTabType SelectedMainTab { get; set; } = MainTabType.Settings;
|
||||||
public Guid SelectedDesign { get; set; } = Guid.Empty;
|
|
||||||
public Guid SelectedQuickDesign { get; set; } = Guid.Empty;
|
public Guid SelectedQuickDesign { get; set; } = Guid.Empty;
|
||||||
public int LastSeenVersion { get; set; } = GlamourerChangelog.LastChangelogVersion;
|
public int LastSeenVersion { get; set; } = GlamourerChangelog.LastChangelogVersion;
|
||||||
|
|
||||||
public float CurrentDesignSelectorWidth { get; set; } = 200f;
|
|
||||||
public float DesignSelectorMinimumScale { get; set; } = 0.1f;
|
|
||||||
public float DesignSelectorMaximumScale { get; set; } = 0.5f;
|
|
||||||
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private readonly SaveService _saveService;
|
private readonly SaveService _saveService;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ using Glamourer.Services;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Luna;
|
using Luna;
|
||||||
using Notification = Luna.Notification;
|
using Notification = Luna.Notification;
|
||||||
|
|
@ -47,7 +46,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
public IFileSystemData<Design>? Node { get; set; }
|
public IFileSystemData<Design>? Node { get; set; }
|
||||||
public DateTimeOffset CreationDate { get; internal init; }
|
public DateTimeOffset CreationDate { get; internal init; }
|
||||||
public DateTimeOffset LastEdit { get; internal set; }
|
public DateTimeOffset LastEdit { get; internal set; }
|
||||||
public LowerString Name { get; internal set; } = LowerString.Empty;
|
public string Name { get; internal set; } = string.Empty;
|
||||||
public string Description { get; internal set; } = string.Empty;
|
public string Description { get; internal set; } = string.Empty;
|
||||||
public string[] Tags { get; internal set; } = [];
|
public string[] Tags { get; internal set; } = [];
|
||||||
public int Index { get; internal set; }
|
public int Index { get; internal set; }
|
||||||
|
|
@ -71,7 +70,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
#region IDesignStandIn
|
#region IDesignStandIn
|
||||||
|
|
||||||
public string ResolveName(bool incognito)
|
public string ResolveName(bool incognito)
|
||||||
=> incognito ? Incognito : Name.Text;
|
=> incognito ? Incognito : Name;
|
||||||
|
|
||||||
public string SerializeName()
|
public string SerializeName()
|
||||||
=> Identifier.ToString();
|
=> Identifier.ToString();
|
||||||
|
|
@ -109,7 +108,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
["Identifier"] = Identifier,
|
["Identifier"] = Identifier,
|
||||||
["CreationDate"] = CreationDate,
|
["CreationDate"] = CreationDate,
|
||||||
["LastEdit"] = LastEdit,
|
["LastEdit"] = LastEdit,
|
||||||
["Name"] = Name.Text,
|
["Name"] = Name,
|
||||||
["Description"] = Description,
|
["Description"] = Description,
|
||||||
["ForcedRedraw"] = ForcedRedraw,
|
["ForcedRedraw"] = ForcedRedraw,
|
||||||
["ResetAdvancedDyes"] = ResetAdvancedDyes,
|
["ResetAdvancedDyes"] = ResetAdvancedDyes,
|
||||||
|
|
@ -200,7 +199,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
var hasNegativeGloss = false;
|
var hasNegativeGloss = false;
|
||||||
var hasNonPositiveGloss = false;
|
var hasNonPositiveGloss = false;
|
||||||
var specularLarger = 0;
|
var specularLarger = 0;
|
||||||
foreach (var (key, value) in materialData.GetValues(MaterialValueIndex.Min(), MaterialValueIndex.Max()))
|
foreach (var (_, value) in materialData.GetValues(MaterialValueIndex.Min(), MaterialValueIndex.Max()))
|
||||||
{
|
{
|
||||||
hasNegativeGloss |= value.Value.GlossStrength < 0;
|
hasNegativeGloss |= value.Value.GlossStrength < 0;
|
||||||
hasNonPositiveGloss |= value.Value.GlossStrength <= 0;
|
hasNonPositiveGloss |= value.Value.GlossStrength <= 0;
|
||||||
|
|
@ -239,7 +238,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
Glamourer.Messager.AddMessage(new Notification(
|
Glamourer.Messager.AddMessage(new Notification(
|
||||||
$"Swapped Gloss and Specular Strength in {materialDesignData.Values.Count} Rows in design {design.Incognito} {reason}",
|
$"Swapped Gloss and Specular Strength in {materialDesignData.Values.Count} Rows in design {design.Incognito} {reason}",
|
||||||
NotificationType.Info));
|
NotificationType.Info));
|
||||||
saveService.Save(Luna.SaveType.ImmediateSync, design);
|
saveService.Save(SaveType.ImmediateSync, design);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,7 +250,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
{
|
{
|
||||||
CreationDate = creationDate,
|
CreationDate = creationDate,
|
||||||
Identifier = json["Identifier"]?.ToObject<Guid>() ?? throw new ArgumentNullException("Identifier"),
|
Identifier = json["Identifier"]?.ToObject<Guid>() ?? throw new ArgumentNullException("Identifier"),
|
||||||
Name = new LowerString(json["Name"]?.ToObject<string>() ?? throw new ArgumentNullException("Name")),
|
Name = json["Name"]?.ToObject<string>() ?? throw new ArgumentNullException("Name"),
|
||||||
Description = json["Description"]?.ToObject<string>() ?? string.Empty,
|
Description = json["Description"]?.ToObject<string>() ?? string.Empty,
|
||||||
Tags = ParseTags(json),
|
Tags = ParseTags(json),
|
||||||
LastEdit = json["LastEdit"]?.ToObject<DateTimeOffset>() ?? creationDate,
|
LastEdit = json["LastEdit"]?.ToObject<DateTimeOffset>() ?? creationDate,
|
||||||
|
|
@ -359,5 +358,5 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn, IFileSystemVa
|
||||||
=> Identifier.ToString();
|
=> Identifier.ToString();
|
||||||
|
|
||||||
public string DisplayName
|
public string DisplayName
|
||||||
=> Name.Text;
|
=> Name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
using Glamourer.Api.Enums;
|
using Glamourer.Api.Enums;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using OtterGui;
|
|
||||||
using OtterGui.Extensions;
|
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
@ -107,7 +105,7 @@ public class DesignBase64Migration
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Customize = *(CustomizeArray*)(ptr + 4);
|
data.Customize = *(CustomizeArray*)(ptr + 4);
|
||||||
foreach (var (slot, idx) in EquipSlotExtensions.EqdpSlots.WithIndex())
|
foreach (var (idx, slot) in EquipSlotExtensions.EqdpSlots.Index())
|
||||||
{
|
{
|
||||||
var mdl = eq[idx];
|
var mdl = eq[idx];
|
||||||
var item = items.Identify(slot, mdl.Set, mdl.Variant);
|
var item = items.Identify(slot, mdl.Set, mdl.Variant);
|
||||||
|
|
@ -121,7 +119,7 @@ public class DesignBase64Migration
|
||||||
data.SetStain(slot, mdl.Stain);
|
data.SetStain(slot, mdl.Stain);
|
||||||
}
|
}
|
||||||
|
|
||||||
var main = cur[0].Skeleton.Id == 0
|
var main = cur[0].Skeleton.Id is 0
|
||||||
? items.DefaultSword
|
? items.DefaultSword
|
||||||
: items.Identify(EquipSlot.MainHand, cur[0].Skeleton, cur[0].Weapon, cur[0].Variant);
|
: items.Identify(EquipSlot.MainHand, cur[0].Skeleton, cur[0].Weapon, cur[0].Variant);
|
||||||
if (!main.Valid)
|
if (!main.Valid)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Glamourer.Config;
|
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
|
@ -9,114 +8,7 @@ using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace Glamourer.Designs;
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
public class DesignColorUi(DesignColors colors, Configuration config)
|
public sealed class DesignColors : ISavable, IReadOnlyDictionary<string, Rgba32>, IService
|
||||||
{
|
|
||||||
private string _newName = string.Empty;
|
|
||||||
|
|
||||||
public void Draw()
|
|
||||||
{
|
|
||||||
using var table = Im.Table.Begin("designColors"u8, 3, TableFlags.RowBackground);
|
|
||||||
if (!table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var changeString = string.Empty;
|
|
||||||
Rgba32? changeValue = null;
|
|
||||||
|
|
||||||
table.SetupColumn("##Delete"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight);
|
|
||||||
table.SetupColumn("##Select"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight);
|
|
||||||
table.SetupColumn("Color Name"u8, TableColumnFlags.WidthStretch);
|
|
||||||
|
|
||||||
table.HeaderRow();
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
if (ImEx.Icon.Button(LunaStyle.RefreshIcon, "Revert the color used for missing design colors to its default."u8,
|
|
||||||
colors.MissingColor == DesignColors.MissingColorDefault))
|
|
||||||
{
|
|
||||||
changeString = DesignColors.MissingColorName;
|
|
||||||
changeValue = DesignColors.MissingColorDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
if (DrawColorButton(DesignColors.MissingColorNameU8, colors.MissingColor, out var newColor))
|
|
||||||
{
|
|
||||||
changeString = DesignColors.MissingColorName;
|
|
||||||
changeValue = newColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
Im.Cursor.X += Im.Style.FramePadding.X;
|
|
||||||
Im.Text(DesignColors.MissingColorNameU8);
|
|
||||||
Im.Tooltip.OnHover("This color is used when the color specified in a design is not available."u8);
|
|
||||||
|
|
||||||
var disabled = !config.DeleteDesignModifier.IsActive();
|
|
||||||
foreach (var (idx, (name, color)) in colors.Index())
|
|
||||||
{
|
|
||||||
using var id = Im.Id.Push(idx);
|
|
||||||
table.NextColumn();
|
|
||||||
|
|
||||||
if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this color. This does not remove it from designs using it."u8, disabled))
|
|
||||||
{
|
|
||||||
changeString = name;
|
|
||||||
changeValue = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disabled)
|
|
||||||
Im.Tooltip.OnHover($"\nHold {config.DeleteDesignModifier} to delete.");
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
if (DrawColorButton(name, color, out newColor))
|
|
||||||
{
|
|
||||||
changeString = name;
|
|
||||||
changeValue = newColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
Im.Cursor.X += Im.Style.FramePadding.X;
|
|
||||||
Im.Text(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
(var tt, disabled) = _newName.Length == 0
|
|
||||||
? ("Specify a name for a new color first.", true)
|
|
||||||
: _newName is DesignColors.MissingColorName or DesignColors.AutomaticName
|
|
||||||
? ($"You can not use the name {DesignColors.MissingColorName} or {DesignColors.AutomaticName}, choose a different one.", true)
|
|
||||||
: colors.ContainsKey(_newName)
|
|
||||||
? ($"The color {_newName} already exists, please choose a different name.", true)
|
|
||||||
: ($"Add a new color {_newName} to your list.", false);
|
|
||||||
if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, disabled))
|
|
||||||
{
|
|
||||||
changeString = _newName;
|
|
||||||
changeValue = 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.NextColumn();
|
|
||||||
table.NextColumn();
|
|
||||||
Im.Item.SetNextWidth(Im.ContentRegion.Available.X);
|
|
||||||
if (Im.Input.Text("##newDesignColor"u8, ref _newName, "New Color Name..."u8, InputTextFlags.EnterReturnsTrue))
|
|
||||||
{
|
|
||||||
changeString = _newName;
|
|
||||||
changeValue = 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeString.Length > 0)
|
|
||||||
{
|
|
||||||
if (!changeValue.HasValue)
|
|
||||||
colors.DeleteColor(changeString);
|
|
||||||
else
|
|
||||||
colors.SetColor(changeString, changeValue.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool DrawColorButton(Utf8StringHandler<LabelStringHandlerBuffer> tooltip, Rgba32 color, out Rgba32 newColor)
|
|
||||||
{
|
|
||||||
var ret = Im.Color.Editor(tooltip, ref color, ColorEditorFlags.AlphaPreviewHalf | ColorEditorFlags.NoInputs);
|
|
||||||
Im.Tooltip.OnHover(ref tooltip);
|
|
||||||
newColor = color;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DesignColors : ISavable, IReadOnlyDictionary<string, Rgba32>
|
|
||||||
{
|
{
|
||||||
public const string AutomaticName = "Automatic";
|
public const string AutomaticName = "Automatic";
|
||||||
public static readonly StringU8 AutomaticNameU8 = new("Automatic"u8);
|
public static readonly StringU8 AutomaticNameU8 = new("Automatic"u8);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using Glamourer.Interop.Material;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Glamourer.Utility;
|
using Glamourer.Utility;
|
||||||
|
using Luna;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
|
|
@ -12,13 +13,13 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Designs;
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
public class DesignConverter(
|
public sealed class DesignConverter(
|
||||||
SaveService saveService,
|
SaveService saveService,
|
||||||
ItemManager _items,
|
ItemManager items,
|
||||||
DesignManager _designs,
|
DesignManager designs,
|
||||||
CustomizeService _customize,
|
CustomizeService customizeService,
|
||||||
HumanModelList _humans,
|
HumanModelList humans,
|
||||||
DesignLinkLoader _linkLoader)
|
DesignLinkLoader linkLoader) : IService
|
||||||
{
|
{
|
||||||
public const byte Version = 6;
|
public const byte Version = 6;
|
||||||
|
|
||||||
|
|
@ -54,9 +55,9 @@ public class DesignConverter(
|
||||||
|
|
||||||
public DesignBase Convert(in DesignData data, in StateMaterialManager materials, in ApplicationRules rules)
|
public DesignBase Convert(in DesignData data, in StateMaterialManager materials, in ApplicationRules rules)
|
||||||
{
|
{
|
||||||
var design = _designs.CreateTemporary();
|
var design = designs.CreateTemporary();
|
||||||
rules.Apply(design);
|
rules.Apply(design);
|
||||||
design.SetDesignData(_customize, data);
|
design.SetDesignData(customizeService, data);
|
||||||
if (rules.Materials)
|
if (rules.Materials)
|
||||||
ComputeMaterials(design.GetMaterialDataRef(), materials, rules.Equip);
|
ComputeMaterials(design.GetMaterialDataRef(), materials, rules.Equip);
|
||||||
return design;
|
return design;
|
||||||
|
|
@ -70,8 +71,8 @@ public class DesignConverter(
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var ret = jObject["Identifier"] != null
|
var ret = jObject["Identifier"] != null
|
||||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObject)
|
? Design.LoadDesign(saveService, customizeService, items, linkLoader, jObject)
|
||||||
: DesignBase.LoadDesignBase(_customize, _items, jObject);
|
: DesignBase.LoadDesignBase(customizeService, items, jObject);
|
||||||
|
|
||||||
if (!customize)
|
if (!customize)
|
||||||
ret.Application.RemoveCustomize();
|
ret.Application.RemoveCustomize();
|
||||||
|
|
@ -101,14 +102,14 @@ public class DesignConverter(
|
||||||
case (byte)'{':
|
case (byte)'{':
|
||||||
var jObj1 = JObject.Parse(Encoding.UTF8.GetString(bytes));
|
var jObj1 = JObject.Parse(Encoding.UTF8.GetString(bytes));
|
||||||
ret = jObj1["Identifier"] != null
|
ret = jObj1["Identifier"] != null
|
||||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj1)
|
? Design.LoadDesign(saveService, customizeService, items, linkLoader, jObj1)
|
||||||
: DesignBase.LoadDesignBase(_customize, _items, jObj1);
|
: DesignBase.LoadDesignBase(customizeService, items, jObj1);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 4:
|
case 4:
|
||||||
ret = _designs.CreateTemporary();
|
ret = designs.CreateTemporary();
|
||||||
ret.MigrateBase64(_customize, _items, _humans, base64);
|
ret.MigrateBase64(customizeService, items, humans, base64);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
|
|
@ -116,8 +117,8 @@ public class DesignConverter(
|
||||||
var jObj2 = JObject.Parse(decompressed);
|
var jObj2 = JObject.Parse(decompressed);
|
||||||
Debug.Assert(version == 3);
|
Debug.Assert(version == 3);
|
||||||
ret = jObj2["Identifier"] != null
|
ret = jObj2["Identifier"] != null
|
||||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj2)
|
? Design.LoadDesign(saveService, customizeService, items, linkLoader, jObj2)
|
||||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
: DesignBase.LoadDesignBase(customizeService, items, jObj2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
|
|
@ -127,8 +128,8 @@ public class DesignConverter(
|
||||||
var jObj2 = JObject.Parse(decompressed);
|
var jObj2 = JObject.Parse(decompressed);
|
||||||
Debug.Assert(version == 5);
|
Debug.Assert(version == 5);
|
||||||
ret = jObj2["Identifier"] != null
|
ret = jObj2["Identifier"] != null
|
||||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj2)
|
? Design.LoadDesign(saveService, customizeService, items, linkLoader, jObj2)
|
||||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
: DesignBase.LoadDesignBase(customizeService, items, jObj2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6:
|
case 6:
|
||||||
|
|
@ -137,8 +138,8 @@ public class DesignConverter(
|
||||||
var jObj2 = JObject.Parse(decompressed);
|
var jObj2 = JObject.Parse(decompressed);
|
||||||
Debug.Assert(version == 6);
|
Debug.Assert(version == 6);
|
||||||
ret = jObj2["Identifier"] != null
|
ret = jObj2["Identifier"] != null
|
||||||
? Design.LoadDesign(saveService, _customize, _items, _linkLoader, jObj2)
|
? Design.LoadDesign(saveService, customizeService, items, linkLoader, jObj2)
|
||||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
: DesignBase.LoadDesignBase(customizeService, items, jObj2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +178,7 @@ public class DesignConverter(
|
||||||
{
|
{
|
||||||
var index = (int)slot.ToIndex();
|
var index = (int)slot.ToIndex();
|
||||||
var armor = armors[index];
|
var armor = armors[index];
|
||||||
var item = _items.Identify(slot, armor.Set, armor.Variant);
|
var item = items.Identify(slot, armor.Set, armor.Variant);
|
||||||
if (!item.Valid)
|
if (!item.Valid)
|
||||||
{
|
{
|
||||||
if (!skipWarnings)
|
if (!skipWarnings)
|
||||||
|
|
@ -188,20 +189,20 @@ public class DesignConverter(
|
||||||
yield return (slot, item, armor.Stains);
|
yield return (slot, item, armor.Stains);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mh = _items.Identify(EquipSlot.MainHand, mainhand.Skeleton, mainhand.Weapon, mainhand.Variant);
|
var mh = items.Identify(EquipSlot.MainHand, mainhand.Skeleton, mainhand.Weapon, mainhand.Variant);
|
||||||
if (!skipWarnings && !mh.Valid)
|
if (!skipWarnings && !mh.Valid)
|
||||||
{
|
{
|
||||||
Glamourer.Log.Warning($"Appearance data {mainhand} for mainhand weapon invalid, item could not be identified.");
|
Glamourer.Log.Warning($"Appearance data {mainhand} for mainhand weapon invalid, item could not be identified.");
|
||||||
mh = _items.DefaultSword;
|
mh = items.DefaultSword;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return (EquipSlot.MainHand, mh, mainhand.Stains);
|
yield return (EquipSlot.MainHand, mh, mainhand.Stains);
|
||||||
|
|
||||||
var oh = _items.Identify(EquipSlot.OffHand, offhand.Skeleton, offhand.Weapon, offhand.Variant, mh.Type);
|
var oh = items.Identify(EquipSlot.OffHand, offhand.Skeleton, offhand.Weapon, offhand.Variant, mh.Type);
|
||||||
if (!skipWarnings && !oh.Valid)
|
if (!skipWarnings && !oh.Valid)
|
||||||
{
|
{
|
||||||
Glamourer.Log.Warning($"Appearance data {offhand} for offhand weapon invalid, item could not be identified.");
|
Glamourer.Log.Warning($"Appearance data {offhand} for offhand weapon invalid, item could not be identified.");
|
||||||
oh = _items.GetDefaultOffhand(mh);
|
oh = items.GetDefaultOffhand(mh);
|
||||||
if (!oh.Valid)
|
if (!oh.Valid)
|
||||||
oh = ItemManager.NothingItem(FullEquipType.Shield);
|
oh = ItemManager.NothingItem(FullEquipType.Shield);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
Glamourer.Log.Debug($"Changed customize {idx.ToName()} in design {design.Identifier} from {oldValue.Value} to {value.Value}.");
|
Glamourer.Log.Debug($"Changed customize {idx.ToName()} in design {design.Identifier} from {oldValue.Value} to {value.Value}.");
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Customize, design, new CustomizeTransaction(idx, oldValue, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Customize, design, new CustomizeTransaction(idx, oldValue, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -91,7 +91,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
Glamourer.Log.Debug($"Changed entire customize with resulting flags {applied} and {changed}.");
|
Glamourer.Log.Debug($"Changed entire customize with resulting flags {applied} and {changed}.");
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.EntireCustomize, design, new EntireCustomizeTransaction(changed, oldCustomize, newCustomize));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.EntireCustomize, design, new EntireCustomizeTransaction(changed, oldCustomize, newCustomize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -106,7 +106,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
Glamourer.Log.Debug($"Set customize parameter {flag} in design {design.Identifier} from {old} to {@new}.");
|
Glamourer.Log.Debug($"Set customize parameter {flag} in design {design.Identifier} from {old} to {@new}.");
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Parameter, design, new ParameterTransaction(flag, old, @new));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Parameter, design, new ParameterTransaction(flag, old, @new)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -130,9 +130,9 @@ public class DesignEditor(
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Set {EquipSlot.MainHand.ToName()} weapon in design {design.Identifier} from {currentMain.Name} ({currentMain.ItemId}) to {item.Name} ({item.ItemId}).");
|
$"Set {EquipSlot.MainHand.ToName()} weapon in design {design.Identifier} from {currentMain.Name} ({currentMain.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Weapon, design,
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Weapon, design,
|
||||||
new WeaponTransaction(currentMain, currentOff, currentGauntlets, item, newOff ?? currentOff,
|
new WeaponTransaction(currentMain, currentOff, currentGauntlets, item, newOff ?? currentOff,
|
||||||
newGauntlets ?? currentGauntlets));
|
newGauntlets ?? currentGauntlets)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case EquipSlot.OffHand:
|
case EquipSlot.OffHand:
|
||||||
|
|
@ -150,8 +150,8 @@ public class DesignEditor(
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Set {EquipSlot.OffHand.ToName()} weapon in design {design.Identifier} from {currentOff.Name} ({currentOff.ItemId}) to {item.Name} ({item.ItemId}).");
|
$"Set {EquipSlot.OffHand.ToName()} weapon in design {design.Identifier} from {currentOff.Name} ({currentOff.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Weapon, design,
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Weapon, design,
|
||||||
new WeaponTransaction(currentMain, currentOff, currentGauntlets, currentMain, item, currentGauntlets));
|
new WeaponTransaction(currentMain, currentOff, currentGauntlets, currentMain, item, currentGauntlets)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -167,7 +167,7 @@ public class DesignEditor(
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Set {slot.ToName()} equipment piece in design {design.Identifier} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}).");
|
$"Set {slot.ToName()} equipment piece in design {design.Identifier} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}).");
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Equip, design, new EquipTransaction(slot, old, item));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Equip, design, new EquipTransaction(slot, old, item)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +187,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set {slot} bonus item to {item}.");
|
Glamourer.Log.Debug($"Set {slot} bonus item to {item}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.BonusItem, design, new BonusItemTransaction(slot, oldItem, item));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.BonusItem, design, new BonusItemTransaction(slot, oldItem, item)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -204,7 +204,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set stain of {slot} equipment piece to {stains}.");
|
Glamourer.Log.Debug($"Set stain of {slot} equipment piece to {stains}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Stains, design, new StainTransaction(slot, oldStain, stains));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Stains, design, new StainTransaction(slot, oldStain, stains)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -227,7 +227,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set crest visibility of {slot} equipment piece to {crest}.");
|
Glamourer.Log.Debug($"Set crest visibility of {slot} equipment piece to {crest}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Crest, design, new CrestTransaction(slot, oldCrest, crest));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Crest, design, new CrestTransaction(slot, oldCrest, crest)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -240,7 +240,7 @@ public class DesignEditor(
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set value of {metaIndex} to {value}.");
|
Glamourer.Log.Debug($"Set value of {metaIndex} to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Other, design, new MetaTransaction(metaIndex, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Other, design, new MetaTransaction(metaIndex, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeMaterialRevert(Design design, MaterialValueIndex index, bool revert)
|
public void ChangeMaterialRevert(Design design, MaterialValueIndex index, bool revert)
|
||||||
|
|
@ -253,7 +253,7 @@ public class DesignEditor(
|
||||||
Glamourer.Log.Debug($"Changed advanced dye value for {index} to {(revert ? "Revert." : "no longer Revert.")}");
|
Glamourer.Log.Debug($"Changed advanced dye value for {index} to {(revert ? "Revert." : "no longer Revert.")}");
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.MaterialRevert, design, new MaterialRevertTransaction(index, !revert, revert));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.MaterialRevert, design, new MaterialRevertTransaction(index, !revert, revert)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeMaterialValue(Design design, MaterialValueIndex index, ColorRow? row)
|
public void ChangeMaterialValue(Design design, MaterialValueIndex index, ColorRow? row)
|
||||||
|
|
@ -288,7 +288,7 @@ public class DesignEditor(
|
||||||
|
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.DelaySave(design);
|
SaveService.DelaySave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Material, design, new MaterialTransaction(index, oldValue.Value, row));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Material, design, new MaterialTransaction(index, oldValue.Value, row)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeApplyMaterialValue(Design design, MaterialValueIndex index, bool value)
|
public void ChangeApplyMaterialValue(Design design, MaterialValueIndex index, bool value)
|
||||||
|
|
@ -301,7 +301,7 @@ public class DesignEditor(
|
||||||
Glamourer.Log.Debug($"Changed application of advanced dye for {index} to {value}.");
|
Glamourer.Log.Debug($"Changed application of advanced dye for {index} to {value}.");
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyMaterial, design, new ApplicationTransaction(index, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyMaterial, design, new ApplicationTransaction(index, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
@ -10,41 +9,50 @@ public sealed class DesignFileSystem : BaseFileSystem, IDisposable, IRequiredSer
|
||||||
{
|
{
|
||||||
private readonly DesignFileSystemSaver _saver;
|
private readonly DesignFileSystemSaver _saver;
|
||||||
private readonly DesignChanged _designChanged;
|
private readonly DesignChanged _designChanged;
|
||||||
|
private readonly TabSelected _tabSelected;
|
||||||
|
|
||||||
public DesignFileSystem(Logger log, SaveService saveService, DesignStorage designs, DesignChanged designChanged)
|
public DesignFileSystem(Logger log, SaveService saveService, DesignStorage designs, DesignChanged designChanged, TabSelected tabSelected)
|
||||||
: base("DesignFileSystem", log, true)
|
: base("DesignFileSystem", log, true)
|
||||||
{
|
{
|
||||||
_designChanged = designChanged;
|
_designChanged = designChanged;
|
||||||
|
_tabSelected = tabSelected;
|
||||||
_saver = new DesignFileSystemSaver(log, this, saveService, designs);
|
_saver = new DesignFileSystemSaver(log, this, saveService, designs);
|
||||||
|
|
||||||
_saver.Load();
|
_saver.Load();
|
||||||
_designChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignFileSystem);
|
_designChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignFileSystem);
|
||||||
|
_tabSelected.Subscribe(OnTabSelected, TabSelected.Priority.DesignSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? _)
|
private void OnTabSelected(in TabSelected.Arguments arguments)
|
||||||
{
|
{
|
||||||
switch (type)
|
if (arguments.Design?.Node is { } node)
|
||||||
|
Selection.Select(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
|
{
|
||||||
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case DesignChanged.Type.ReloadedAll: _saver.Load(); break;
|
case DesignChanged.Type.ReloadedAll: _saver.Load(); break;
|
||||||
case DesignChanged.Type.Created:
|
case DesignChanged.Type.Created:
|
||||||
var parent = Root;
|
var parent = Root;
|
||||||
if (design.Path.Folder.Length > 0)
|
if (arguments.Design.Path.Folder.Length > 0)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parent = FindOrCreateAllFolders(design.Path.Folder);
|
parent = FindOrCreateAllFolders(arguments.Design.Path.Folder);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Glamourer.Messager.NotificationMessage(ex,
|
Glamourer.Messager.NotificationMessage(ex,
|
||||||
$"Could not move design to {design.Path} because the folder could not be created.",
|
$"Could not move design to {arguments.Design.Path} because the folder could not be created.",
|
||||||
NotificationType.Error);
|
NotificationType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
var (data, _) = CreateDuplicateDataNode(parent, design.Path.SortName ?? design.Name, design);
|
var (data, _) = CreateDuplicateDataNode(parent, arguments.Design.Path.SortName ?? arguments.Design.Name, arguments.Design);
|
||||||
Selection.Select(data);
|
Selection.Select(data);
|
||||||
break;
|
break;
|
||||||
case DesignChanged.Type.Deleted:
|
case DesignChanged.Type.Deleted:
|
||||||
if (design.Node is { } node)
|
if (arguments.Design.Node is { } node)
|
||||||
{
|
{
|
||||||
if (node.Selected)
|
if (node.Selected)
|
||||||
Selection.UnselectAll();
|
Selection.UnselectAll();
|
||||||
|
|
@ -52,8 +60,8 @@ public sealed class DesignFileSystem : BaseFileSystem, IDisposable, IRequiredSer
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DesignChanged.Type.Renamed when design.Path.SortName is null:
|
case DesignChanged.Type.Renamed when arguments.Design.Path.SortName is null:
|
||||||
RenameWithDuplicates(design.Node!, design.Path.GetIntendedName(design.Name.Text));
|
RenameWithDuplicates(arguments.Design.Node!, arguments.Design.Path.GetIntendedName(arguments.Design.Name));
|
||||||
break;
|
break;
|
||||||
// TODO: Maybe add path changes?
|
// TODO: Maybe add path changes?
|
||||||
}
|
}
|
||||||
|
|
@ -61,6 +69,7 @@ public sealed class DesignFileSystem : BaseFileSystem, IDisposable, IRequiredSer
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_tabSelected.Unsubscribe(OnTabSelected);
|
||||||
_designChanged.Unsubscribe(OnDesignChanged);
|
_designChanged.Unsubscribe(OnDesignChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using Glamourer.GameData;
|
||||||
using Glamourer.Interop.Material;
|
using Glamourer.Interop.Material;
|
||||||
using Glamourer.Interop.Penumbra;
|
using Glamourer.Interop.Penumbra;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using OtterGui.Extensions;
|
using Luna;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
|
|
@ -16,7 +16,7 @@ using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
namespace Glamourer.Designs;
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
public sealed class DesignManager : DesignEditor
|
public sealed class DesignManager : DesignEditor, IService
|
||||||
{
|
{
|
||||||
public readonly DesignStorage Designs;
|
public readonly DesignStorage Designs;
|
||||||
private readonly HumanModelList _humans;
|
private readonly HumanModelList _humans;
|
||||||
|
|
@ -89,7 +89,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
|
|
||||||
Glamourer.Log.Information(
|
Glamourer.Log.Information(
|
||||||
$"Loaded {Designs.Count} designs in {stopwatch.ElapsedMilliseconds} ms.{(skipped > 0 ? $" Skipped loading {skipped} designs due to errors." : string.Empty)}");
|
$"Loaded {Designs.Count} designs in {stopwatch.ElapsedMilliseconds} ms.{(skipped > 0 ? $" Skipped loading {skipped} designs due to errors." : string.Empty)}");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ReloadedAll, null!, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ReloadedAll, null!));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Create a new temporary design without adding it to the manager. </summary>
|
/// <summary> Create a new temporary design without adding it to the manager. </summary>
|
||||||
|
|
@ -116,7 +116,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
Designs.Add(design);
|
Designs.Add(design);
|
||||||
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
|
Glamourer.Log.Debug($"Added new design {design.Identifier}.");
|
||||||
SaveService.ImmediateSave(design);
|
SaveService.ImmediateSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, new CreationTransaction(actualName, path));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Created, design, new CreationTransaction(actualName, path)));
|
||||||
return design;
|
return design;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
Designs.Add(design);
|
Designs.Add(design);
|
||||||
Glamourer.Log.Debug($"Added new design {design.Identifier} by cloning Temporary Design.");
|
Glamourer.Log.Debug($"Added new design {design.Identifier} by cloning Temporary Design.");
|
||||||
SaveService.ImmediateSave(design);
|
SaveService.ImmediateSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, new CreationTransaction(actualName, path));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Created, design, new CreationTransaction(actualName, path)));
|
||||||
return design;
|
return design;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,7 +162,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Added new design {design.Identifier} by cloning {clone.Identifier.ToString()}.");
|
$"Added new design {design.Identifier} by cloning {clone.Identifier.ToString()}.");
|
||||||
SaveService.ImmediateSave(design);
|
SaveService.ImmediateSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, new CreationTransaction(actualName, path));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Created, design, new CreationTransaction(actualName, path)));
|
||||||
return design;
|
return design;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
--d.Index;
|
--d.Index;
|
||||||
Designs.RemoveAt(design.Index);
|
Designs.RemoveAt(design.Index);
|
||||||
SaveService.ImmediateDelete(design);
|
SaveService.ImmediateDelete(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Deleted, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Deleted, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -183,7 +183,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
/// <summary> Rename a design. </summary>
|
/// <summary> Rename a design. </summary>
|
||||||
public void Rename(Design design, string newName)
|
public void Rename(Design design, string newName)
|
||||||
{
|
{
|
||||||
var oldName = design.Name.Text;
|
var oldName = design.Name;
|
||||||
if (oldName == newName)
|
if (oldName == newName)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -191,7 +191,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Renamed design {design.Identifier}.");
|
Glamourer.Log.Debug($"Renamed design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Renamed, design, new RenameTransaction(oldName, newName));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Renamed, design, new RenameTransaction(oldName, newName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change the description of a design. </summary>
|
/// <summary> Change the description of a design. </summary>
|
||||||
|
|
@ -205,7 +205,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Changed description of design {design.Identifier}.");
|
Glamourer.Log.Debug($"Changed description of design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ChangedDescription, design, new DescriptionTransaction(oldDescription, description));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedDescription, design, new DescriptionTransaction(oldDescription, description)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change the associated color of a design. </summary>
|
/// <summary> Change the associated color of a design. </summary>
|
||||||
|
|
@ -219,7 +219,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Changed color of design {design.Identifier}.");
|
Glamourer.Log.Debug($"Changed color of design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ChangedColor, design, new DesignColorTransaction(oldColor, newColor));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedColor, design, new DesignColorTransaction(oldColor, newColor)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Add a new tag to a design. The tags remain sorted. </summary>
|
/// <summary> Add a new tag to a design. The tags remain sorted. </summary>
|
||||||
|
|
@ -233,7 +233,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
var idx = design.Tags.AsEnumerable().IndexOf(tag);
|
var idx = design.Tags.AsEnumerable().IndexOf(tag);
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Added tag {tag} at {idx} to design {design.Identifier}.");
|
Glamourer.Log.Debug($"Added tag {tag} at {idx} to design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.AddedTag, design, new TagAddedTransaction(tag, idx));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.AddedTag, design, new TagAddedTransaction(tag, idx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Remove a tag from a design by its index. </summary>
|
/// <summary> Remove a tag from a design by its index. </summary>
|
||||||
|
|
@ -247,7 +247,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Removed tag {oldTag} at {tagIdx} from design {design.Identifier}.");
|
Glamourer.Log.Debug($"Removed tag {oldTag} at {tagIdx} from design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.RemovedTag, design, new TagRemovedTransaction(oldTag, tagIdx));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.RemovedTag, design, new TagRemovedTransaction(oldTag, tagIdx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Rename a tag from a design by its index. The tags stay sorted.</summary>
|
/// <summary> Rename a tag from a design by its index. The tags stay sorted.</summary>
|
||||||
|
|
@ -262,8 +262,8 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Renamed tag {oldTag} at {tagIdx} to {newTag} in design {design.Identifier} and reordered tags.");
|
Glamourer.Log.Debug($"Renamed tag {oldTag} at {tagIdx} to {newTag} in design {design.Identifier} and reordered tags.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ChangedTag, design,
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedTag, design,
|
||||||
new TagChangedTransaction(oldTag, newTag, tagIdx, design.Tags.AsEnumerable().IndexOf(newTag)));
|
new TagChangedTransaction(oldTag, newTag, tagIdx, design.Tags.AsEnumerable().IndexOf(newTag))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Add an associated mod to a design. </summary>
|
/// <summary> Add an associated mod to a design. </summary>
|
||||||
|
|
@ -275,7 +275,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Added associated mod {mod.DirectoryName} to design {design.Identifier}.");
|
Glamourer.Log.Debug($"Added associated mod {mod.DirectoryName} to design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.AddedMod, design, new ModAddedTransaction(mod, settings));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.AddedMod, design, new ModAddedTransaction(mod, settings)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Remove an associated mod from a design. </summary>
|
/// <summary> Remove an associated mod from a design. </summary>
|
||||||
|
|
@ -287,7 +287,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Removed associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
Glamourer.Log.Debug($"Removed associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.RemovedMod, design, new ModRemovedTransaction(mod, settings));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.RemovedMod, design, new ModRemovedTransaction(mod, settings)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Add or update an associated mod to a design. </summary>
|
/// <summary> Add or update an associated mod to a design. </summary>
|
||||||
|
|
@ -300,12 +300,12 @@ public sealed class DesignManager : DesignEditor
|
||||||
if (hasOldSettings)
|
if (hasOldSettings)
|
||||||
{
|
{
|
||||||
Glamourer.Log.Debug($"Updated associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
Glamourer.Log.Debug($"Updated associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.UpdatedMod, design, new ModUpdatedTransaction(mod, oldSettings, settings));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.UpdatedMod, design, new ModUpdatedTransaction(mod, oldSettings, settings)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Glamourer.Log.Debug($"Added associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
Glamourer.Log.Debug($"Added associated mod {mod.DirectoryName} from design {design.Identifier}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.AddedMod, design, new ModAddedTransaction(mod, settings));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.AddedMod, design, new ModAddedTransaction(mod, settings)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,7 +317,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
|
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set design {design.Identifier} to {(value ? "no longer be " : string.Empty)} write-protected.");
|
Glamourer.Log.Debug($"Set design {design.Identifier} to {(value ? "no longer be " : string.Empty)} write-protected.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.WriteProtection, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.WriteProtection, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Set the quick design bar display status of a design. </summary>
|
/// <summary> Set the quick design bar display status of a design. </summary>
|
||||||
|
|
@ -330,7 +330,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug(
|
Glamourer.Log.Debug(
|
||||||
$"Set design {design.Identifier} to {(!value ? "no longer be " : string.Empty)} displayed in the quick design bar.");
|
$"Set design {design.Identifier} to {(!value ? "no longer be " : string.Empty)} displayed in the quick design bar.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.QuickDesignBar, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.QuickDesignBar, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -345,7 +345,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.ForcedRedraw = forcedRedraw;
|
design.ForcedRedraw = forcedRedraw;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set {design.Identifier} to {(forcedRedraw ? string.Empty : "not")} force redraws.");
|
Glamourer.Log.Debug($"Set {design.Identifier} to {(forcedRedraw ? string.Empty : "not")} force redraws.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ForceRedraw, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ForceRedraw, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeResetAdvancedDyes(Design design, bool resetAdvancedDyes)
|
public void ChangeResetAdvancedDyes(Design design, bool resetAdvancedDyes)
|
||||||
|
|
@ -356,7 +356,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.ResetAdvancedDyes = resetAdvancedDyes;
|
design.ResetAdvancedDyes = resetAdvancedDyes;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set {design.Identifier} to {(resetAdvancedDyes ? string.Empty : "not")} reset advanced dyes.");
|
Glamourer.Log.Debug($"Set {design.Identifier} to {(resetAdvancedDyes ? string.Empty : "not")} reset advanced dyes.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ResetAdvancedDyes, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ResetAdvancedDyes, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeResetTemporarySettings(Design design, bool resetTemporarySettings)
|
public void ChangeResetTemporarySettings(Design design, bool resetTemporarySettings)
|
||||||
|
|
@ -367,7 +367,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.ResetTemporarySettings = resetTemporarySettings;
|
design.ResetTemporarySettings = resetTemporarySettings;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set {design.Identifier} to {(resetTemporarySettings ? string.Empty : "not")} reset temporary settings.");
|
Glamourer.Log.Debug($"Set {design.Identifier} to {(resetTemporarySettings ? string.Empty : "not")} reset temporary settings.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ResetTemporarySettings, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ResetTemporarySettings, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change whether to apply a specific customize value. </summary>
|
/// <summary> Change whether to apply a specific customize value. </summary>
|
||||||
|
|
@ -379,7 +379,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of customization {idx.ToName()} to {value}.");
|
Glamourer.Log.Debug($"Set applying of customization {idx.ToName()} to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyCustomize, design, new ApplicationTransaction(idx, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyCustomize, design, new ApplicationTransaction(idx, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change whether to apply a specific equipment piece. </summary>
|
/// <summary> Change whether to apply a specific equipment piece. </summary>
|
||||||
|
|
@ -391,7 +391,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of {slot} equipment piece to {value}.");
|
Glamourer.Log.Debug($"Set applying of {slot} equipment piece to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyEquip, design, new ApplicationTransaction((slot, false), !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyEquip, design, new ApplicationTransaction((slot, false), !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change whether to apply a specific equipment piece. </summary>
|
/// <summary> Change whether to apply a specific equipment piece. </summary>
|
||||||
|
|
@ -403,7 +403,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of {slot} bonus item to {value}.");
|
Glamourer.Log.Debug($"Set applying of {slot} bonus item to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyBonusItem, design, new ApplicationTransaction(slot, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyBonusItem, design, new ApplicationTransaction(slot, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change whether to apply a specific stain. </summary>
|
/// <summary> Change whether to apply a specific stain. </summary>
|
||||||
|
|
@ -415,7 +415,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of stain of {slot} equipment piece to {value}.");
|
Glamourer.Log.Debug($"Set applying of stain of {slot} equipment piece to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyStain, design, new ApplicationTransaction((slot, true), !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyStain, design, new ApplicationTransaction((slot, true), !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change whether to apply a specific crest visibility. </summary>
|
/// <summary> Change whether to apply a specific crest visibility. </summary>
|
||||||
|
|
@ -427,7 +427,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of crest visibility of {slot} equipment piece to {value}.");
|
Glamourer.Log.Debug($"Set applying of crest visibility of {slot} equipment piece to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyCrest, design, new ApplicationTransaction(slot, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyCrest, design, new ApplicationTransaction(slot, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change the application value of one of the meta flags. </summary>
|
/// <summary> Change the application value of one of the meta flags. </summary>
|
||||||
|
|
@ -439,7 +439,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of {metaIndex} to {value}.");
|
Glamourer.Log.Debug($"Set applying of {metaIndex} to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Other, design, new ApplicationTransaction(metaIndex, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Other, design, new ApplicationTransaction(metaIndex, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change the application value of a customize parameter. </summary>
|
/// <summary> Change the application value of a customize parameter. </summary>
|
||||||
|
|
@ -451,7 +451,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
SaveService.QueueSave(design);
|
SaveService.QueueSave(design);
|
||||||
Glamourer.Log.Debug($"Set applying of parameter {flag} to {value}.");
|
Glamourer.Log.Debug($"Set applying of parameter {flag} to {value}.");
|
||||||
DesignChanged.Invoke(DesignChanged.Type.ApplyParameter, design, new ApplicationTransaction(flag, !value, value));
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ApplyParameter, design, new ApplicationTransaction(flag, !value, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change multiple application values at once. </summary>
|
/// <summary> Change multiple application values at once. </summary>
|
||||||
|
|
@ -512,7 +512,6 @@ public sealed class DesignManager : DesignEditor
|
||||||
{
|
{
|
||||||
var text = File.ReadAllText(SaveService.FileNames.MigrationDesignFile);
|
var text = File.ReadAllText(SaveService.FileNames.MigrationDesignFile);
|
||||||
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(text) ?? new Dictionary<string, string>();
|
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(text) ?? new Dictionary<string, string>();
|
||||||
var migratedFileSystemPaths = new Dictionary<string, string>(dict.Count);
|
|
||||||
foreach (var (name, base64) in dict)
|
foreach (var (name, base64) in dict)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -529,7 +528,6 @@ public sealed class DesignManager : DesignEditor
|
||||||
if (!oldDesigns.Any(d => d.Name == design.Name && d.CreationDate == design.CreationDate))
|
if (!oldDesigns.Any(d => d.Name == design.Name && d.CreationDate == design.CreationDate))
|
||||||
{
|
{
|
||||||
Add(design, $"Migrated old design to {design.Identifier}.");
|
Add(design, $"Migrated old design to {design.Identifier}.");
|
||||||
migratedFileSystemPaths.Add(design.Identifier.ToString(), name);
|
|
||||||
++successes;
|
++successes;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -632,7 +630,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
if (!message.IsNullOrEmpty())
|
if (!message.IsNullOrEmpty())
|
||||||
Glamourer.Log.Debug(message);
|
Glamourer.Log.Debug(message);
|
||||||
SaveService.ImmediateSave(design);
|
SaveService.ImmediateSave(design);
|
||||||
DesignChanged.Invoke(DesignChanged.Type.Created, design, null);
|
DesignChanged.Invoke(new DesignChanged.Arguments(DesignChanged.Type.Created, design));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Split a given string into its folder path and its name, if <paramref name="handlePath"/> is true. </summary>
|
/// <summary> Split a given string into its folder path and its name, if <paramref name="handlePath"/> is true. </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
using Glamourer.Api.Enums;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Luna;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
|
||||||
|
|
||||||
namespace Glamourer.Designs.History;
|
namespace Glamourer.Designs.History;
|
||||||
|
|
||||||
|
|
@ -171,21 +169,21 @@ public class EditorHistory : IDisposable, IService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnStateChanged(StateChangeType type, StateSource source, ActorState state, ActorData actors, ITransaction? data)
|
private void OnStateChanged(in StateChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (_undoMode || source is not StateSource.Manual)
|
if (_undoMode || arguments.Source is not StateSource.Manual)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (data is not null)
|
if (arguments.Transaction is not null)
|
||||||
AddStateTransaction(state, data);
|
AddStateTransaction(arguments.State, arguments.Transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? data)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (_undoMode)
|
if (_undoMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (data is not null)
|
if (arguments.Transaction is not null)
|
||||||
AddDesignTransaction(design, data);
|
AddDesignTransaction(arguments.Design, arguments.Transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ public interface ITransaction
|
||||||
public void Revert(IDesignEditor editor, object data);
|
public void Revert(IDesignEditor editor, object data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct CustomizeTransaction(CustomizeIndex Slot, CustomizeValue Old, CustomizeValue New)
|
public record CustomizeTransaction(CustomizeIndex Slot, CustomizeValue Old, CustomizeValue New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -20,7 +20,7 @@ public readonly record struct CustomizeTransaction(CustomizeIndex Slot, Customiz
|
||||||
=> editor.ChangeCustomize(data, Slot, Old, ApplySettings.Manual);
|
=> editor.ChangeCustomize(data, Slot, Old, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct EntireCustomizeTransaction(CustomizeFlag Apply, CustomizeArray Old, CustomizeArray New)
|
public record EntireCustomizeTransaction(CustomizeFlag Apply, CustomizeArray Old, CustomizeArray New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -30,7 +30,7 @@ public readonly record struct EntireCustomizeTransaction(CustomizeFlag Apply, Cu
|
||||||
=> editor.ChangeEntireCustomize(data, Old, Apply, ApplySettings.Manual);
|
=> editor.ChangeEntireCustomize(data, Old, Apply, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct EquipTransaction(EquipSlot Slot, EquipItem Old, EquipItem New)
|
public record EquipTransaction(EquipSlot Slot, EquipItem Old, EquipItem New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -40,7 +40,7 @@ public readonly record struct EquipTransaction(EquipSlot Slot, EquipItem Old, Eq
|
||||||
=> editor.ChangeItem(data, Slot, Old, ApplySettings.Manual);
|
=> editor.ChangeItem(data, Slot, Old, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct BonusItemTransaction(BonusItemFlag Slot, EquipItem Old, EquipItem New)
|
public record BonusItemTransaction(BonusItemFlag Slot, EquipItem Old, EquipItem New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -50,7 +50,7 @@ public readonly record struct BonusItemTransaction(BonusItemFlag Slot, EquipItem
|
||||||
=> editor.ChangeBonusItem(data, Slot, Old, ApplySettings.Manual);
|
=> editor.ChangeBonusItem(data, Slot, Old, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct WeaponTransaction(
|
public record WeaponTransaction(
|
||||||
EquipItem OldMain,
|
EquipItem OldMain,
|
||||||
EquipItem OldOff,
|
EquipItem OldOff,
|
||||||
EquipItem OldGauntlets,
|
EquipItem OldGauntlets,
|
||||||
|
|
@ -72,7 +72,7 @@ public readonly record struct WeaponTransaction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct StainTransaction(EquipSlot Slot, StainIds Old, StainIds New)
|
public record StainTransaction(EquipSlot Slot, StainIds Old, StainIds New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -82,7 +82,7 @@ public readonly record struct StainTransaction(EquipSlot Slot, StainIds Old, Sta
|
||||||
=> editor.ChangeStains(data, Slot, Old, ApplySettings.Manual);
|
=> editor.ChangeStains(data, Slot, Old, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct CrestTransaction(CrestFlag Slot, bool Old, bool New)
|
public record CrestTransaction(CrestFlag Slot, bool Old, bool New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -92,7 +92,7 @@ public readonly record struct CrestTransaction(CrestFlag Slot, bool Old, bool Ne
|
||||||
=> editor.ChangeCrest(data, Slot, Old, ApplySettings.Manual);
|
=> editor.ChangeCrest(data, Slot, Old, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct ParameterTransaction(CustomizeParameterFlag Slot, CustomizeParameterValue Old, CustomizeParameterValue New)
|
public record ParameterTransaction(CustomizeParameterFlag Slot, CustomizeParameterValue Old, CustomizeParameterValue New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
@ -102,7 +102,7 @@ public readonly record struct ParameterTransaction(CustomizeParameterFlag Slot,
|
||||||
=> editor.ChangeCustomizeParameter(data, Slot, Old, ApplySettings.Manual);
|
=> editor.ChangeCustomizeParameter(data, Slot, Old, ApplySettings.Manual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct MetaTransaction(MetaIndex Slot, bool Old, bool New)
|
public record MetaTransaction(MetaIndex Slot, bool Old, bool New)
|
||||||
: ITransaction
|
: ITransaction
|
||||||
{
|
{
|
||||||
public ITransaction? Merge(ITransaction older)
|
public ITransaction? Merge(ITransaction older)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using Glamourer.Automation;
|
using Glamourer.Automation;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
@ -32,7 +31,7 @@ public sealed class DesignLinkManager : IService, IDisposable
|
||||||
parent.LastEdit = DateTimeOffset.UtcNow;
|
parent.LastEdit = DateTimeOffset.UtcNow;
|
||||||
_saveService.QueueSave(parent);
|
_saveService.QueueSave(parent);
|
||||||
Glamourer.Log.Debug($"Moved link from {orderFrom} {idxFrom} to {idxTo} {orderTo}.");
|
Glamourer.Log.Debug($"Moved link from {orderFrom} {idxFrom} to {idxTo} {orderTo}.");
|
||||||
_event.Invoke(DesignChanged.Type.ChangedLink, parent, null);
|
_event.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedLink, parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDesignLink(Design parent, Design child, LinkOrder order)
|
public void AddDesignLink(Design parent, Design child, LinkOrder order)
|
||||||
|
|
@ -43,7 +42,7 @@ public sealed class DesignLinkManager : IService, IDisposable
|
||||||
parent.LastEdit = DateTimeOffset.UtcNow;
|
parent.LastEdit = DateTimeOffset.UtcNow;
|
||||||
_saveService.QueueSave(parent);
|
_saveService.QueueSave(parent);
|
||||||
Glamourer.Log.Debug($"Added new {order} link to {child.Identifier} for {parent.Identifier}.");
|
Glamourer.Log.Debug($"Added new {order} link to {child.Identifier} for {parent.Identifier}.");
|
||||||
_event.Invoke(DesignChanged.Type.ChangedLink, parent, null);
|
_event.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedLink, parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveDesignLink(Design parent, int idx, LinkOrder order)
|
public void RemoveDesignLink(Design parent, int idx, LinkOrder order)
|
||||||
|
|
@ -54,7 +53,7 @@ public sealed class DesignLinkManager : IService, IDisposable
|
||||||
parent.LastEdit = DateTimeOffset.UtcNow;
|
parent.LastEdit = DateTimeOffset.UtcNow;
|
||||||
_saveService.QueueSave(parent);
|
_saveService.QueueSave(parent);
|
||||||
Glamourer.Log.Debug($"Removed the {order} link at {idx} for {parent.Identifier}.");
|
Glamourer.Log.Debug($"Removed the {order} link at {idx} for {parent.Identifier}.");
|
||||||
_event.Invoke(DesignChanged.Type.ChangedLink, parent, null);
|
_event.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedLink, parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeApplicationType(Design parent, int idx, LinkOrder order, ApplicationType applicationType)
|
public void ChangeApplicationType(Design parent, int idx, LinkOrder order, ApplicationType applicationType)
|
||||||
|
|
@ -64,22 +63,23 @@ public sealed class DesignLinkManager : IService, IDisposable
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_saveService.QueueSave(parent);
|
_saveService.QueueSave(parent);
|
||||||
Glamourer.Log.Debug($"Changed link application type from {old} to {applicationType} for design link {order} {idx + 1} in design {parent.Identifier}.");
|
Glamourer.Log.Debug(
|
||||||
_event.Invoke(DesignChanged.Type.ChangedLink, parent, null);
|
$"Changed link application type from {old} to {applicationType} for design link {order} {idx + 1} in design {parent.Identifier}.");
|
||||||
|
_event.Invoke(new DesignChanged.Arguments(DesignChanged.Type.ChangedLink, parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design deletedDesign, ITransaction? _)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (type is not DesignChanged.Type.Deleted)
|
if (arguments.Type is not DesignChanged.Type.Deleted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var design in _storage)
|
foreach (var design in _storage)
|
||||||
{
|
{
|
||||||
if (!design.Links.Remove(deletedDesign))
|
if (!design.Links.Remove(arguments.Design))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
design.LastEdit = DateTimeOffset.UtcNow;
|
design.LastEdit = DateTimeOffset.UtcNow;
|
||||||
Glamourer.Log.Debug($"Removed {deletedDesign.Identifier} from {design.Identifier} links due to deletion.");
|
Glamourer.Log.Debug($"Removed {arguments.Design.Identifier} from {design.Identifier} links due to deletion.");
|
||||||
_saveService.QueueSave(design);
|
_saveService.QueueSave(design);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using Glamourer.Automation;
|
using Glamourer.Automation;
|
||||||
|
using Luna;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Filesystem;
|
|
||||||
|
|
||||||
namespace Glamourer.Designs.Links;
|
namespace Glamourer.Designs.Links;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Designs.Special;
|
namespace Glamourer.Designs.Special;
|
||||||
|
|
||||||
public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileSystem, Configuration config) : IService
|
public class RandomDesignGenerator(DesignStorage designs, Configuration config) : IService
|
||||||
{
|
{
|
||||||
private readonly Random _rng = new();
|
private readonly Random _rng = new();
|
||||||
private readonly WeakReference<Design> _lastDesign = new(null!, false);
|
private readonly WeakReference<Design> _lastDesign = new(null!, false);
|
||||||
|
|
@ -34,7 +34,7 @@ public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileS
|
||||||
=> Design(designs);
|
=> Design(designs);
|
||||||
|
|
||||||
public Design? Design(IDesignPredicate predicate)
|
public Design? Design(IDesignPredicate predicate)
|
||||||
=> Design(predicate.Get(designs, fileSystem).ToList());
|
=> Design(predicate.Get(designs).ToList());
|
||||||
|
|
||||||
public Design? Design(IReadOnlyList<IDesignPredicate> predicates)
|
public Design? Design(IReadOnlyList<IDesignPredicate> predicates)
|
||||||
{
|
{
|
||||||
|
|
@ -42,7 +42,7 @@ public class RandomDesignGenerator(DesignStorage designs, DesignFileSystem fileS
|
||||||
{
|
{
|
||||||
0 => Design(),
|
0 => Design(),
|
||||||
1 => Design(predicates[0]),
|
1 => Design(predicates[0]),
|
||||||
_ => Design(IDesignPredicate.Get(predicates, designs, fileSystem).ToList()),
|
_ => Design(IDesignPredicate.Get(predicates, designs).ToList()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,59 @@
|
||||||
using OtterGui.Classes;
|
namespace Glamourer.Designs.Special;
|
||||||
|
|
||||||
namespace Glamourer.Designs.Special;
|
|
||||||
|
|
||||||
public interface IDesignPredicate
|
public interface IDesignPredicate
|
||||||
{
|
{
|
||||||
public bool Invoke(Design design, string lowerName, string identifier, string lowerPath);
|
bool Invoke(Design design, string name, string identifier, string path);
|
||||||
|
|
||||||
public bool Invoke((Design Design, string LowerName, string Identifier, string LowerPath) args)
|
bool Invoke((Design Design, string Name, string Identifier, string Path) args)
|
||||||
=> Invoke(args.Design, args.LowerName, args.Identifier, args.LowerPath);
|
=> Invoke(args.Design, args.Name, args.Identifier, args.Path);
|
||||||
|
|
||||||
public IEnumerable<Design> Get(IEnumerable<Design> designs, DesignFileSystem fileSystem)
|
IEnumerable<Design> Get(IEnumerable<Design> designs)
|
||||||
=> designs.Select(Transform)
|
=> designs.Select(Transform)
|
||||||
.Where(Invoke)
|
.Where(Invoke)
|
||||||
.Select(t => t.Design);
|
.Select(t => t.Design);
|
||||||
|
|
||||||
public static IEnumerable<Design> Get(IReadOnlyList<IDesignPredicate> predicates, IEnumerable<Design> designs, DesignFileSystem fileSystem)
|
static IEnumerable<Design> Get(IReadOnlyList<IDesignPredicate> predicates, IEnumerable<Design> designs)
|
||||||
=> predicates.Count > 0
|
=> predicates.Count > 0
|
||||||
? designs.Select(Transform)
|
? designs.Select(Transform)
|
||||||
.Where(t => predicates.Any(p => p.Invoke(t)))
|
.Where(t => predicates.Any(p => p.Invoke(t)))
|
||||||
.Select(t => t.Design)
|
.Select(t => t.Design)
|
||||||
: designs;
|
: designs;
|
||||||
|
|
||||||
private static (Design Design, string LowerName, string Identifier, string LowerPath) Transform(Design d)
|
private static (Design Design, string Name, string Identifier, string Path) Transform(Design d)
|
||||||
=> (d, d.Name.Lower, d.Identifier.ToString(), d.Path.CurrentPath.ToLowerInvariant());
|
=> (d, d.Name, d.Identifier.ToString(), d.Path.CurrentPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RandomPredicate
|
public static class RandomPredicate
|
||||||
{
|
{
|
||||||
public readonly struct StartsWith(string value) : IDesignPredicate
|
public readonly struct StartsWith(string value) : IDesignPredicate
|
||||||
{
|
{
|
||||||
public LowerString Value { get; } = value;
|
public string Value { get; } = value;
|
||||||
|
|
||||||
public bool Invoke(Design design, string lowerName, string identifier, string lowerPath)
|
public bool Invoke(Design design, string name, string identifier, string path)
|
||||||
=> lowerPath.StartsWith(Value.Lower);
|
=> path.StartsWith(Value, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"/{Value.Text}";
|
=> $"/{Value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct Contains(string value) : IDesignPredicate
|
public readonly struct Contains(string value) : IDesignPredicate
|
||||||
{
|
{
|
||||||
public LowerString Value { get; } = value;
|
public string Value { get; } = value;
|
||||||
|
|
||||||
public bool Invoke(Design design, string lowerName, string identifier, string lowerPath)
|
public bool Invoke(Design design, string name, string identifier, string path)
|
||||||
{
|
{
|
||||||
if (lowerName.Contains(Value.Lower))
|
if (name.Contains(Value, StringComparison.OrdinalIgnoreCase))
|
||||||
return true;
|
return true;
|
||||||
if (identifier.Contains(Value.Lower))
|
if (identifier.Contains(Value, StringComparison.OrdinalIgnoreCase))
|
||||||
return true;
|
return true;
|
||||||
if (lowerPath.Contains(Value.Lower))
|
if (path.Contains(Value, StringComparison.OrdinalIgnoreCase))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> Value.Text;
|
=> Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct Exact(Exact.Type type, string value) : IDesignPredicate
|
public readonly struct Exact(Exact.Type type, string value) : IDesignPredicate
|
||||||
|
|
@ -69,25 +67,25 @@ public static class RandomPredicate
|
||||||
Color,
|
Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type Which { get; } = type;
|
public Type Which { get; } = type;
|
||||||
public LowerString Value { get; } = value;
|
public string Value { get; } = value;
|
||||||
|
|
||||||
public bool Invoke(Design design, string lowerName, string identifier, string lowerPath)
|
public bool Invoke(Design design, string name, string identifier, string path)
|
||||||
=> Which switch
|
=> Which switch
|
||||||
{
|
{
|
||||||
Type.Name => lowerName == Value.Lower,
|
Type.Name => string.Equals(name, Value, StringComparison.OrdinalIgnoreCase),
|
||||||
Type.Path => lowerPath == Value.Lower,
|
Type.Path => string.Equals(path, Value, StringComparison.OrdinalIgnoreCase),
|
||||||
Type.Identifier => identifier == Value.Lower,
|
Type.Identifier => string.Equals(identifier, Value, StringComparison.OrdinalIgnoreCase),
|
||||||
Type.Tag => IsContained(Value, design.Tags),
|
Type.Tag => IsContained(Value, design.Tags),
|
||||||
Type.Color => design.Color == Value,
|
Type.Color => string.Equals(design.Color, Value, StringComparison.OrdinalIgnoreCase),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static bool IsContained(LowerString value, IEnumerable<string> data)
|
private static bool IsContained(string value, IEnumerable<string> data)
|
||||||
=> data.Any(t => t == value);
|
=> data.Any(t => string.Equals(t, value, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"\"{Which switch { Type.Name => 'n', Type.Identifier => 'i', Type.Path => 'p', Type.Tag => 't', Type.Color => 'c', _ => '?' }}?{Value.Text}\"";
|
=> $"\"{Which switch { Type.Name => 'n', Type.Identifier => 'i', Type.Path => 'p', Type.Tag => 't', Type.Color => 'c', _ => '?' }}?{Value}\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDesignPredicate CreateSinglePredicate(string restriction)
|
public static IDesignPredicate CreateSinglePredicate(string restriction)
|
||||||
|
|
@ -125,7 +123,7 @@ public static class RandomPredicate
|
||||||
|
|
||||||
public static List<IDesignPredicate> GeneratePredicates(string restrictions)
|
public static List<IDesignPredicate> GeneratePredicates(string restrictions)
|
||||||
{
|
{
|
||||||
if (restrictions.Length == 0)
|
if (restrictions.Length is 0)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
List<IDesignPredicate> predicates = new(1);
|
List<IDesignPredicate> predicates = new(1);
|
||||||
|
|
@ -153,9 +151,9 @@ public static class RandomPredicate
|
||||||
|
|
||||||
public static string GeneratePredicateString(IReadOnlyCollection<IDesignPredicate> predicates)
|
public static string GeneratePredicateString(IReadOnlyCollection<IDesignPredicate> predicates)
|
||||||
{
|
{
|
||||||
if (predicates.Count == 0)
|
if (predicates.Count is 0)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
if (predicates.Count == 1)
|
if (predicates.Count is 1)
|
||||||
return predicates.First()!.ToString()!;
|
return predicates.First()!.ToString()!;
|
||||||
|
|
||||||
return $"{{{string.Join("; ", predicates)}}}";
|
return $"{{{string.Join("; ", predicates)}}}";
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered when the auto-reload gear setting is changed in glamourer configuration.
|
/// Triggered when the auto-reload gear setting is changed in glamourer configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class AutoRedrawChanged()
|
public sealed class AutoRedrawChanged(Logger log)
|
||||||
: EventWrapper<bool, AutoRedrawChanged.Priority>(nameof(AutoRedrawChanged))
|
: EventBase<bool, AutoRedrawChanged.Priority>(nameof(AutoRedrawChanged), log)
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Api.StateApi.OnGPoseChange"/>
|
/// <seealso cref="Api.StateApi.OnGPoseChange"/>
|
||||||
StateApi = int.MinValue,
|
StateApi = int.MinValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,64 +1,60 @@
|
||||||
using Glamourer.Automation;
|
using Glamourer.Automation;
|
||||||
using OtterGui.Classes;
|
using Glamourer.Designs;
|
||||||
|
using Luna;
|
||||||
|
using Penumbra.GameData.Actors;
|
||||||
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when an automated design is changed in any way. </summary>
|
||||||
/// Triggered when an automated design is changed in any way.
|
public sealed class AutomationChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<AutomationChanged.Arguments, AutomationChanged.Priority>(nameof(AutomationChanged), log)
|
||||||
/// <item>Parameter is the type of the change </item>
|
|
||||||
/// <item>Parameter is the added or changed design set or null on deletion. </item>
|
|
||||||
/// <item>Parameter is additional data depending on the type of change. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class AutomationChanged()
|
|
||||||
: EventWrapper<AutomationChanged.Type, AutoDesignSet?, object?, AutomationChanged.Priority>(nameof(AutomationChanged))
|
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
/// <summary> Add a new set. Names and identifiers do not have to be unique. It is not enabled by default. Additional data is the index it gets added at and the name [(int, string)]. </summary>
|
/// <summary> Add a new set. Names and identifiers do not have to be unique. It is not enabled by default. </summary>
|
||||||
AddedSet,
|
AddedSet,
|
||||||
|
|
||||||
/// <summary> Delete a given set. Additional data is the index it got removed from [int].</summary>
|
/// <summary> Delete a given set. </summary>
|
||||||
DeletedSet,
|
DeletedSet,
|
||||||
|
|
||||||
/// <summary> Rename a given set. Names do not have to be unique. Additional data is the old name and the new name [(string, string)]. </summary>
|
/// <summary> Rename a given set. Names do not have to be unique. </summary>
|
||||||
RenamedSet,
|
RenamedSet,
|
||||||
|
|
||||||
/// <summary> Move a given set to a different position. Additional data is the old index of the set and the new index of the set [(int, int)]. </summary>
|
/// <summary> Move a given set to a different position. </summary>
|
||||||
MovedSet,
|
MovedSet,
|
||||||
|
|
||||||
/// <summary> Change the identifier a given set is associated with to another one. Additional data is the old identifier and the new one, and a potentially disabled other design set. [(ActorIdentifier[], ActorIdentifier, AutoDesignSet?)]. </summary>
|
/// <summary> Change the identifier a given set is associated with to another one. </summary>
|
||||||
ChangeIdentifier,
|
ChangeIdentifier,
|
||||||
|
|
||||||
/// <summary> Toggle the enabled state of a given set. Additional data is the thus disabled other set, if any [AutoDesignSet?]. </summary>
|
/// <summary> Toggle the enabled state of a given set. </summary>
|
||||||
ToggleSet,
|
ToggleSet,
|
||||||
|
|
||||||
/// <summary> Change the used base state of a given set. Additional data is prior and new base. [(AutoDesignSet.Base, AutoDesignSet.Base)]. </summary>
|
/// <summary> Change the used base state of a given set. </summary>
|
||||||
ChangedBase,
|
ChangedBase,
|
||||||
|
|
||||||
/// <summary> Change the resetting of temporary settings for a given set. Additional data is the new value. </summary>
|
/// <summary> Change the resetting of temporary settings for a given set. </summary>
|
||||||
ChangedTemporarySettingsReset,
|
ChangedTemporarySettingsReset,
|
||||||
|
|
||||||
/// <summary> Add a new associated design to a given set. Additional data is the index it got added at [int]. </summary>
|
/// <summary> Add a new associated design to a given set. </summary>
|
||||||
AddedDesign,
|
AddedDesign,
|
||||||
|
|
||||||
/// <summary> Remove a given associated design from a given set. Additional data is the index it got removed from [int]. </summary>
|
/// <summary> Remove a given associated design from a given set. </summary>
|
||||||
DeletedDesign,
|
DeletedDesign,
|
||||||
|
|
||||||
/// <summary> Move a given associated design in the list of a given set. Additional data is the index that got moved and the index it got moved to [(int, int)]. </summary>
|
/// <summary> Move a given associated design in the list of a given set. </summary>
|
||||||
MovedDesign,
|
MovedDesign,
|
||||||
|
|
||||||
/// <summary> Change the linked design in an associated design for a given set. Additional data is the index of the changed associated design, the old linked design and the new linked design [(int, IDesignStandIn, IDesignStandIn)]. </summary>
|
/// <summary> Change the linked design in an associated design for a given set. </summary>
|
||||||
ChangedDesign,
|
ChangedDesign,
|
||||||
|
|
||||||
/// <summary> Change the job condition in an associated design for a given set. Additional data is the index of the changed associated design, the old job group and the new job group [(int, JobGroup, JobGroup)]. </summary>
|
/// <summary> Change the job condition in an associated design for a given set. </summary>
|
||||||
ChangedConditions,
|
ChangedConditions,
|
||||||
|
|
||||||
/// <summary> Change the application type in an associated design for a given set. Additional data is the index of the changed associated design, the old type and the new type. [(int, AutoDesign.Type, AutoDesign.Type)]. </summary>
|
/// <summary> Change the application type in an associated design for a given set. </summary>
|
||||||
ChangedType,
|
ChangedType,
|
||||||
|
|
||||||
/// <summary> Change the additional data for a specific design type. Additional data is the index of the changed associated design and the new data. [(int, object)] </summary>
|
/// <summary> Change the additional data for a specific design type. </summary>
|
||||||
ChangedData,
|
ChangedData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,4 +72,92 @@ public sealed class AutomationChanged()
|
||||||
/// <seealso cref="Gui.Tabs.AutomationTab.RandomRestrictionDrawer.OnAutomationChange"/>
|
/// <seealso cref="Gui.Tabs.AutomationTab.RandomRestrictionDrawer.OnAutomationChange"/>
|
||||||
RandomRestrictionDrawer = -1,
|
RandomRestrictionDrawer = -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <param name="Type"> The type of change. </param>
|
||||||
|
public record Arguments(Type Type, AutoDesignSet Set)
|
||||||
|
{
|
||||||
|
public T As<T>() where T : Arguments
|
||||||
|
=> (T)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="Set"> The added set. </param>
|
||||||
|
/// <param name="Index"> The index the set was added at. </param>
|
||||||
|
/// <param name="Name"> The name of the added set. </param>
|
||||||
|
public sealed record AddedSetArguments(AutoDesignSet Set, int Index, string Name) : Arguments(Type.AddedSet, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The deleted set. </param>
|
||||||
|
/// <param name="Index"> The index the set was deleted from. </param>
|
||||||
|
public sealed record DeletedSetArguments(AutoDesignSet Set, int Index) : Arguments(Type.DeletedSet, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The renamed set. </param>
|
||||||
|
/// <param name="OldName"> The old name of the set. </param>
|
||||||
|
/// <param name="NewName"> The new name of the set. </param>
|
||||||
|
public sealed record RenamedSetArguments(AutoDesignSet Set, string OldName, string NewName) : Arguments(Type.RenamedSet, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The moved set. </param>
|
||||||
|
/// <param name="OldIndex"> The index the set was moved from. </param>
|
||||||
|
/// <param name="NewIndex"> The index the set was moved to. </param>
|
||||||
|
public sealed record MovedSetArguments(AutoDesignSet Set, int OldIndex, int NewIndex) : Arguments(Type.MovedSet, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that got its associated identifiers changed. </param>
|
||||||
|
/// <param name="OldIdentifiers"> The prior identifiers that got removed. </param>
|
||||||
|
/// <param name="NewIdentifier"> The new identifiers associated with the set. </param>
|
||||||
|
/// <param name="DisabledSet"> A set that was associated with the new identifiers before and got disabled through this change, or null. </param>
|
||||||
|
public sealed record ChangeIdentifierArguments(
|
||||||
|
AutoDesignSet Set,
|
||||||
|
ActorIdentifier[] OldIdentifiers,
|
||||||
|
ActorIdentifier NewIdentifier,
|
||||||
|
AutoDesignSet? DisabledSet) : Arguments(Type.ChangeIdentifier, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that got toggled on or off. </param>
|
||||||
|
/// <param name="DisabledSet"> A set with the same association that got disabled due to this change, or null. </param>
|
||||||
|
public sealed record ToggleSetArguments(AutoDesignSet Set, AutoDesignSet? DisabledSet) : Arguments(Type.ToggleSet, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that changed its base state. </param>
|
||||||
|
/// <param name="OldBase"> The old base state of the set. </param>
|
||||||
|
/// <param name="NewBase"> The new base state of the set. </param>
|
||||||
|
public sealed record ChangedBaseArguments(AutoDesignSet Set, AutoDesignSet.Base OldBase, AutoDesignSet.Base NewBase) : Arguments(Type.ChangedBase, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that changed whether it resets all temporary settings. </param>
|
||||||
|
/// <param name="NewValue"> The new state of resetting temporary settings. </param>
|
||||||
|
public sealed record ChangedTemporarySettingsResetArguments(AutoDesignSet Set, bool NewValue) : Arguments(Type.ChangedTemporarySettingsReset, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that added a new design. </param>
|
||||||
|
/// <param name="Index"> The index the new design was added in the set. </param>
|
||||||
|
public sealed record AddedDesignArguments(AutoDesignSet Set, int Index) : Arguments(Type.AddedDesign, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that removed a design. </param>
|
||||||
|
/// <param name="Index"> The index the design was removed from. </param>
|
||||||
|
public sealed record DeletedDesignArguments(AutoDesignSet Set, int Index) : Arguments(Type.DeletedDesign, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that moved a design. </param>
|
||||||
|
/// <param name="OldIndex"> The index the design was moved from in the set. </param>
|
||||||
|
/// <param name="NewIndex"> The index the design was moved from to the set. </param>
|
||||||
|
public sealed record MovedDesignArguments(AutoDesignSet Set, int OldIndex, int NewIndex) : Arguments(Type.MovedDesign, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that changed a design. </param>
|
||||||
|
/// <param name="DesignIndex"> The index of the changed design. </param>
|
||||||
|
/// <param name="OldDesign"> The design previously assigned to the set. </param>
|
||||||
|
/// <param name="NewDesign"> The design the old one was changed to. </param>
|
||||||
|
public sealed record ChangedDesignArguments(AutoDesignSet Set, int DesignIndex, IDesignStandIn OldDesign, IDesignStandIn NewDesign)
|
||||||
|
: Arguments(Type.ChangedDesign, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that changed a job group condition. </param>
|
||||||
|
/// <param name="DesignIndex"> The index of the changed design. </param>
|
||||||
|
/// <param name="OldGroup"> The prior job condition for the design. </param>
|
||||||
|
/// <param name="NewGroup"> The new job condition for the design. </param>
|
||||||
|
public sealed record ChangedConditionsArguments(AutoDesignSet Set, int DesignIndex, JobGroup OldGroup, JobGroup NewGroup)
|
||||||
|
: Arguments(Type.ChangedConditions, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that changed its application type. </param>
|
||||||
|
/// <param name="DesignIndex"> The index of the changed design. </param>
|
||||||
|
/// <param name="OldType"> The old application flags. </param>
|
||||||
|
/// <param name="NewType"> The new application flags. </param>
|
||||||
|
public sealed record ChangedTypeArguments(AutoDesignSet Set, int DesignIndex, ApplicationType OldType, ApplicationType NewType)
|
||||||
|
: Arguments(Type.ChangedType, Set);
|
||||||
|
|
||||||
|
/// <param name="Set"> The set that got a design data changed. </param>
|
||||||
|
/// <param name="DesignIndex"> The index of the changed design. </param>
|
||||||
|
/// <param name="NewData"> The new additional data for the changed design. </param>
|
||||||
|
public sealed record ChangedDataArguments(AutoDesignSet Set, int DesignIndex, object NewData) : Arguments(Type.ChangedData, Set);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,32 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a model flags a bonus slot for an update. </summary>
|
||||||
/// Triggered when a model flags a bonus slot for an update.
|
public sealed class BonusSlotUpdating(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<BonusSlotUpdating.Arguments, BonusSlotUpdating.Priority>(nameof(BonusSlotUpdating), log)
|
||||||
/// <item>Parameter is the model with a flagged slot. </item>
|
|
||||||
/// <item>Parameter is the bonus slot changed. </item>
|
|
||||||
/// <item>Parameter is the model values to change the bonus piece to. </item>
|
|
||||||
/// <item>Parameter is the return value the function should return, if it is ulong.MaxValue, the original will be called and returned. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class BonusSlotUpdating()
|
|
||||||
: EventWrapperRef34<Model, BonusItemFlag, CharacterArmor, ulong, BonusSlotUpdating.Priority>(nameof(BonusSlotUpdating))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnBonusSlotUpdating"/>
|
/// <seealso cref="State.StateListener.OnBonusSlotUpdating"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref struct Arguments(Model model, BonusItemFlag flag, ref CharacterArmor armor, ref ulong returnValue)
|
||||||
|
{
|
||||||
|
/// <summary> The draw object with an updated bonus slot. </summary>
|
||||||
|
public readonly Model Model = model;
|
||||||
|
|
||||||
|
/// <summary> The updated slot. </summary>
|
||||||
|
public readonly BonusItemFlag Slot = flag;
|
||||||
|
|
||||||
|
/// <summary> The model data for the new bonus slot. This can be changed. </summary>
|
||||||
|
public ref CharacterArmor Armor = ref armor;
|
||||||
|
|
||||||
|
/// <summary> The return value of the event. If this is <see cref="ulong.MaxValue"/>, the original function will be called and its return value used, otherwise this value will be returned. </summary>
|
||||||
|
public ref ulong ReturnValue = ref returnValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,13 @@ using Glamourer.Designs;
|
||||||
using Glamourer.Designs.History;
|
using Glamourer.Designs.History;
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using Glamourer.Gui.Tabs.DesignTab;
|
using Glamourer.Gui.Tabs.DesignTab;
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a Design is edited in any way. </summary>
|
||||||
/// Triggered when a Design is edited in any way.
|
public sealed class DesignChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<DesignChanged.Arguments, DesignChanged.Priority>(nameof(DesignChanged), log)
|
||||||
/// <item>Parameter is the type of the change </item>
|
|
||||||
/// <item>Parameter is the changed Design. </item>
|
|
||||||
/// <item>Parameter is any additional data depending on the type of change. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DesignChanged()
|
|
||||||
: EventWrapper<DesignChanged.Type, Design, ITransaction?, DesignChanged.Priority>(nameof(DesignChanged))
|
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -151,4 +144,10 @@ public sealed class DesignChanged()
|
||||||
/// <seealso cref="EditorHistory.OnDesignChanged" />
|
/// <seealso cref="EditorHistory.OnDesignChanged" />
|
||||||
EditorHistory = -1000,
|
EditorHistory = -1000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Arguments for the DesignChanged event. </summary>
|
||||||
|
/// <param name="Type"> The type of changed. </param>
|
||||||
|
/// <param name="Design"> The changed design. </param>
|
||||||
|
/// <param name="Transaction"> A transaction with further data corresponding to the change. </param>
|
||||||
|
public readonly record struct Arguments(Type Type, Design Design, ITransaction? Transaction = null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,32 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a model flags an equipment slot for an update. </summary>
|
||||||
/// Triggered when a model flags an equipment slot for an update.
|
public sealed class EquipSlotUpdating(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<EquipSlotUpdating.Arguments, EquipSlotUpdating.Priority>(nameof(EquipSlotUpdating), log)
|
||||||
/// <item>Parameter is the model with a flagged slot. </item>
|
|
||||||
/// <item>Parameter is the equipment slot changed. </item>
|
|
||||||
/// <item>Parameter is the model values to change the equipment piece to. </item>
|
|
||||||
/// <item>Parameter is the return value the function should return, if it is ulong.MaxValue, the original will be called and returned. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class EquipSlotUpdating()
|
|
||||||
: EventWrapperRef34<Model, EquipSlot, CharacterArmor, ulong, EquipSlotUpdating.Priority>(nameof(EquipSlotUpdating))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnEquipSlotUpdating"/>
|
/// <seealso cref="State.StateListener.OnEquipSlotUpdating"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref struct Arguments(Model model, EquipSlot slot, ref CharacterArmor armor, ref ulong returnValue)
|
||||||
|
{
|
||||||
|
/// <summary> The draw object with an updated equipment slot. </summary>
|
||||||
|
public readonly Model Model = model;
|
||||||
|
|
||||||
|
/// <summary> The updated slot. </summary>
|
||||||
|
public readonly EquipSlot Slot = slot;
|
||||||
|
|
||||||
|
/// <summary> The model data for the new equipment slot. This can be changed. </summary>
|
||||||
|
public ref CharacterArmor Armor = ref armor;
|
||||||
|
|
||||||
|
/// <summary> The return value of the event. If this is <see cref="ulong.MaxValue"/>, the original function will be called and its return value used, otherwise this value will be returned. </summary>
|
||||||
|
public ref ulong ReturnValue = ref returnValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
|
using Penumbra.String;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when the player equips a gear set. </summary>
|
||||||
/// Triggered when the player equips a gear set.
|
public sealed class EquippedGearset(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<EquippedGearset.Arguments, EquippedGearset.Priority>(nameof(EquippedGearset), log)
|
||||||
/// <item>Parameter is the name of the gear set. </item>
|
|
||||||
/// <item>Parameter is the id of the gear set. </item>
|
|
||||||
/// <item>Parameter is the id of the prior gear set. </item>
|
|
||||||
/// <item>Parameter is the id of the associated glamour. </item>
|
|
||||||
/// <item>Parameter is the job id of the associated job. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class EquippedGearset()
|
|
||||||
: EventWrapper<string, int, int, byte, byte, EquippedGearset.Priority>(nameof(EquippedGearset))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Automation.AutoDesignApplier.OnEquippedGearset"/>
|
/// <seealso cref="Automation.AutoDesignApplier.OnEquippedGearset"/>
|
||||||
AutoDesignApplier = 0,
|
AutoDesignApplier = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Arguments for the EquippedGearset event. </summary>
|
||||||
|
/// <param name="Name"> The name of the equipped gear set. </param>
|
||||||
|
/// <param name="Id"> The ID of the equipped gear set.</param>
|
||||||
|
/// <param name="PriorId"> The ID of the gear set previously equipped.</param>
|
||||||
|
/// <param name="GlamourId"> The ID of the associated glamour plate. </param>
|
||||||
|
/// <param name="JobId"> The job ID of the associated job. </param>
|
||||||
|
public readonly record struct Arguments(ByteString Name, int Id, int PriorId, int GlamourId, byte JobId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
public sealed class GPoseService : EventWrapper<bool, GPoseService.Priority>
|
public sealed class GPoseService : EventBase<bool, GPoseService.Priority>
|
||||||
{
|
{
|
||||||
private readonly IFramework _framework;
|
private readonly IFramework _framework;
|
||||||
private readonly IClientState _state;
|
private readonly IClientState _state;
|
||||||
|
|
@ -19,8 +19,8 @@ public sealed class GPoseService : EventWrapper<bool, GPoseService.Priority>
|
||||||
|
|
||||||
public bool InGPose { get; private set; }
|
public bool InGPose { get; private set; }
|
||||||
|
|
||||||
public GPoseService(IFramework framework, IClientState state)
|
public GPoseService(IFramework framework, IClientState state, Logger log)
|
||||||
: base(nameof(GPoseService))
|
: base(nameof(GPoseService), log)
|
||||||
{
|
{
|
||||||
_framework = framework;
|
_framework = framework;
|
||||||
_state = state;
|
_state = state;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,23 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggers when the equipped gearset finished all LoadEquipment, LoadWeapon, and LoadCrest calls. (All Non-MetaData)
|
/// Triggers when the equipped gearset finished all LoadEquipment, LoadWeapon, and LoadCrest calls. (All Non-MetaData)
|
||||||
/// This defines an endpoint for when the gameState is updated.
|
/// This defines an endpoint for when the gameState is updated.
|
||||||
/// <list type="number">
|
|
||||||
/// <item>The model draw object associated with the finished load (Also fired by other players on render) </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GearsetDataLoaded()
|
public sealed class GearsetDataLoaded(Logger log)
|
||||||
: EventWrapper<Actor, Model, GearsetDataLoaded.Priority>(nameof(GearsetDataLoaded))
|
: EventBase<GearsetDataLoaded.Arguments, GearsetDataLoaded.Priority>(nameof(GearsetDataLoaded), log)
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnGearsetDataLoaded"/>
|
/// <seealso cref="State.StateListener.OnGearsetDataLoaded"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Arguments for the GearsetDataLoaded event. </summary>
|
||||||
|
/// <param name="Actor"> The actor that loaded a gear set. </param>
|
||||||
|
/// <param name="Model"> The draw object that finished the load. </param>
|
||||||
|
public readonly record struct Arguments(Actor Actor, Model Model);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,24 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when the visibility of head gear is changed. </summary>
|
||||||
/// Triggered when the visibility of head gear is changed.
|
public sealed class HeadGearVisibilityChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<HeadGearVisibilityChanged.Arguments, HeadGearVisibilityChanged.Priority>(nameof(HeadGearVisibilityChanged), log)
|
||||||
/// <item>Parameter is the actor with changed head gear visibility. </item>
|
|
||||||
/// <item>Parameter is the new state. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class HeadGearVisibilityChanged()
|
|
||||||
: EventWrapperRef2<Actor, bool, HeadGearVisibilityChanged.Priority>(nameof(HeadGearVisibilityChanged))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnHeadGearVisibilityChange"/>
|
/// <seealso cref="State.StateListener.OnHeadGearVisibilityChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref struct Arguments(Actor actor, ref bool visible)
|
||||||
|
{
|
||||||
|
/// <summary> The actor whose head gear visibility changed. </summary>
|
||||||
|
public readonly Actor Actor = actor;
|
||||||
|
|
||||||
|
/// <summary> The new visibility state. </summary>
|
||||||
|
public ref bool Visible = ref visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
@ -10,12 +10,14 @@ namespace Glamourer.Events;
|
||||||
/// <item>Parameter is an array of slots updated and corresponding item ids and stains. </item>
|
/// <item>Parameter is an array of slots updated and corresponding item ids and stains. </item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class MovedEquipment()
|
public sealed class MovedEquipment(Logger log)
|
||||||
: EventWrapper<(EquipSlot, uint, StainIds)[], MovedEquipment.Priority>(nameof(MovedEquipment))
|
: EventBase<MovedEquipment.Arguments, MovedEquipment.Priority>(nameof(MovedEquipment), log)
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnMovedEquipment"/>
|
/// <seealso cref="State.StateListener.OnMovedEquipment"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly record struct Arguments(params (EquipSlot, uint, StainIds)[] Items);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,10 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a new item or customization is unlocked. </summary>
|
||||||
/// Triggered when a new item or customization is unlocked.
|
public sealed class ObjectUnlocked(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<ObjectUnlocked.Arguments, ObjectUnlocked.Priority>(nameof(ObjectUnlocked), log), IRequiredService
|
||||||
/// <item>Parameter is the type of the unlocked object </item>
|
|
||||||
/// <item>Parameter is the id of the unlocked object. </item>
|
|
||||||
/// <item>Parameter is the timestamp of the unlock. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ObjectUnlocked()
|
|
||||||
: EventWrapper<ObjectUnlocked.Type, uint, DateTimeOffset, ObjectUnlocked.Priority>(nameof(ObjectUnlocked))
|
|
||||||
{
|
{
|
||||||
public enum Type
|
public enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -21,8 +14,15 @@ public sealed class ObjectUnlocked()
|
||||||
|
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Gui.Tabs.UnlocksTab.UnlockTable.OnObjectUnlock"/>
|
/// <seealso cref="Gui.Tabs.UnlocksTab.UnlockTable.Cache.OnItemUnlock"/>
|
||||||
/// <remarks> Currently used as a hack to make the unlock table dirty in it. If anything else starts using this, rework. </remarks>
|
/// <remarks> Currently used as a hack to make the unlock table dirty in it. If anything else starts using this, rework. </remarks>
|
||||||
UnlockTable = 0,
|
UnlockTable = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> Arguments for the ObjectUnlocked event. </summary>
|
||||||
|
/// <param name="Type"> The type of the unlocked object. </param>
|
||||||
|
/// <param name="Id"> The ID of the unlocked object. </param>
|
||||||
|
/// <param name="Timestamp"> The timestamp of the unlock event.</param>
|
||||||
|
public readonly record struct Arguments(Type Type, uint Id, DateTimeOffset Timestamp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered when Penumbra is reloaded.
|
/// Triggered when Penumbra is reloaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PenumbraReloaded()
|
public sealed class PenumbraReloaded(Logger log)
|
||||||
: EventWrapper<PenumbraReloaded.Priority>(nameof(PenumbraReloaded))
|
: EventBase<PenumbraReloaded.Priority>(nameof(PenumbraReloaded), log)
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Interop.ChangeCustomizeService.Restore"/>
|
/// <seealso cref="global::Glamourer.Interop.ChangeCustomizeService.Restore"/>
|
||||||
ChangeCustomizeService = 0,
|
ChangeCustomizeService = 0,
|
||||||
|
|
||||||
/// <seealso cref="Interop.VisorService.Restore"/>
|
/// <seealso cref="global::Glamourer.Interop.VisorService.Restore"/>
|
||||||
VisorService = 0,
|
VisorService = 0,
|
||||||
|
|
||||||
/// <seealso cref="Interop.VieraEarService.Restore"/>
|
/// <seealso cref="global::Glamourer.Interop.VieraEarService.Restore"/>
|
||||||
VieraEarService = 0,
|
VieraEarService = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,37 @@
|
||||||
using Glamourer.Api.Enums;
|
using Glamourer.Api.Enums;
|
||||||
using Glamourer.Designs.History;
|
using Glamourer.Designs.History;
|
||||||
using Glamourer.Interop.Structs;
|
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a state changes in any way. </summary>
|
||||||
/// Triggered when a Design is edited in any way.
|
public sealed class StateChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<StateChanged.Arguments, StateChanged.Priority>(nameof(StateChanged), log)
|
||||||
/// <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, ITransaction?, StateChanged.Priority>(nameof(StateChanged))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Api.StateApi.OnStateChanged" />
|
/// <seealso cref="Api.StateApi.OnStateChanged" />
|
||||||
GlamourerIpc = int.MinValue,
|
GlamourerIpc = int.MinValue,
|
||||||
|
|
||||||
/// <seealso cref="Interop.Penumbra.PenumbraAutoRedraw.OnStateChanged" />
|
/// <seealso cref="global::Glamourer.Interop.Penumbra.PenumbraAutoRedraw.OnStateChanged" />
|
||||||
PenumbraAutoRedraw = 0,
|
PenumbraAutoRedraw = 0,
|
||||||
|
|
||||||
/// <seealso cref="EditorHistory.OnStateChanged" />
|
/// <seealso cref="EditorHistory.OnStateChanged" />
|
||||||
EditorHistory = -1000,
|
EditorHistory = -1000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Arguments for the StateChanged event. </summary>
|
||||||
|
/// <param name="Type"> The type of change that occured. </param>
|
||||||
|
/// <param name="Source"> The source of the change. </param>
|
||||||
|
/// <param name="State"> The changed state. </param>
|
||||||
|
/// <param name="Actors"> Any currently affected actors. </param>
|
||||||
|
/// <param name="Transaction"> Additional data depending on the type of change. </param>
|
||||||
|
public readonly record struct Arguments(
|
||||||
|
StateChangeType Type,
|
||||||
|
StateSource Source,
|
||||||
|
ActorState State,
|
||||||
|
ActorData Actors,
|
||||||
|
ITransaction? Transaction = null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,22 @@
|
||||||
using Glamourer.Api;
|
using Glamourer.Api;
|
||||||
using Glamourer.Api.Enums;
|
using Glamourer.Api.Enums;
|
||||||
using Glamourer.Interop.Structs;
|
using Luna;
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a set of grouped changes finishes being applied to a Glamourer state. </summary>
|
||||||
/// Triggered when a set of grouped changes finishes being applied to a Glamourer state.
|
public sealed class StateFinalized(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<StateFinalized.Arguments, StateFinalized.Priority>(nameof(StateFinalized), log)
|
||||||
/// <item>Parameter is the operation that finished updating the saved state. </item>
|
|
||||||
/// <item>Parameter is the existing actors using this saved state. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class StateFinalized()
|
|
||||||
: EventWrapper<StateFinalizationType, ActorData, StateFinalized.Priority>(nameof(StateFinalized))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="StateApi.OnStateFinalized"/>
|
/// <seealso cref="StateApi.OnStateFinalized"/>
|
||||||
StateApi = int.MinValue,
|
StateApi = int.MinValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Arguments for the StateFinalized event. </summary>
|
||||||
|
/// <param name="Type"> The operation that finished updating the saved state. </param>
|
||||||
|
/// <param name="Actors"> The existing actors using this saved state at the moment. </param>
|
||||||
|
public readonly record struct Arguments(StateFinalizationType Type, ActorData Actors);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using Glamourer.Gui.Tabs.DesignTab;
|
using Luna;
|
||||||
using OtterGui.Classes;
|
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered to select a tab or design. </summary>
|
||||||
/// Triggered when an automated design is changed in any way.
|
public sealed class TabSelected(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<TabSelected.Arguments, TabSelected.Priority>(nameof(TabSelected), log)
|
||||||
/// <item>Parameter is the tab to select. </item>
|
|
||||||
/// <item>Parameter is the design to select if the tab is the designs tab. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class TabSelected()
|
|
||||||
: EventWrapper<MainTabType, Design?, TabSelected.Priority>(nameof(TabSelected))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="DesignFileSystemDrawer.OnTabSelected"/>
|
/// <seealso cref="DesignFileSystem.OnTabSelected"/>
|
||||||
DesignSelector = 0,
|
DesignSelector = 0,
|
||||||
|
|
||||||
/// <seealso cref="Gui.MainWindow.OnTabSelected"/>
|
/// <seealso cref="Gui.MainTabBar.OnEvent"/>
|
||||||
MainWindow = 1,
|
MainWindow = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Arguments for the TabSelected event. </summary>
|
||||||
|
/// <param name="Type"> The tab to be selected. </param>
|
||||||
|
/// <param name="Design"> The design to be selected in the Designs tab. </param>
|
||||||
|
public readonly record struct Arguments(MainTabType Type, Design? Design = null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when the state of viera ear visibility for any draw object is changed. </summary>
|
||||||
/// Triggered when the state of viera ear visibility for any draw object is changed.
|
public sealed class VieraEarStateChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<VieraEarStateChanged.Arguments, VieraEarStateChanged.Priority>(nameof(VieraEarStateChanged), log)
|
||||||
/// <item>Parameter is the model with a changed viera ear visibility state. </item>
|
|
||||||
/// <item>Parameter is the new state. </item>
|
|
||||||
/// <item>Parameter is whether to call the original function. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class VieraEarStateChanged()
|
|
||||||
: EventWrapperRef2<Actor, bool, VieraEarStateChanged.Priority>(nameof(VieraEarStateChanged))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnVieraEarChange"/>
|
/// <seealso cref="State.StateListener.OnVieraEarChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref struct Arguments(Actor actor, ref bool state)
|
||||||
|
{
|
||||||
|
/// <summary> The actor with a changed viera ear visibility state. </summary>
|
||||||
|
public readonly Actor Actor = actor;
|
||||||
|
|
||||||
|
/// <summary> The new ear visibility state. </summary>
|
||||||
|
public ref bool State = ref state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,27 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when the state of a visor for any draw object is changed. </summary>
|
||||||
/// Triggered when the state of a visor for any draw object is changed.
|
public sealed class VisorStateChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<VisorStateChanged.Arguments, VisorStateChanged.Priority>(nameof(VisorStateChanged), log)
|
||||||
/// <item>Parameter is the model with a changed visor state. </item>
|
|
||||||
/// <item>Parameter is the new state. </item>
|
|
||||||
/// <item>Parameter is whether to call the original function. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class VisorStateChanged()
|
|
||||||
: EventWrapperRef3<Model, bool, bool, VisorStateChanged.Priority>(nameof(VisorStateChanged))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnVisorChange"/>
|
/// <seealso cref="State.StateListener.OnVisorChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public ref struct Arguments(Model model, bool visorState, ref bool value)
|
||||||
|
{
|
||||||
|
/// <summary> The model with a changed visor state. </summary>
|
||||||
|
public readonly Model Model = model;
|
||||||
|
|
||||||
|
/// <summary> The game's visor state. </summary>
|
||||||
|
public readonly bool NewVisorState = visorState;
|
||||||
|
|
||||||
|
/// <summary> The actual new value </summary>
|
||||||
|
public ref bool Value = ref value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,13 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when a model flags an equipment slot for an update. </summary>
|
||||||
/// Triggered when a model flags an equipment slot for an update.
|
public sealed class WeaponLoading(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<WeaponLoading.Arguments, WeaponLoading.Priority>(nameof(WeaponLoading), log)
|
||||||
/// <item>Parameter is the actor that has its weapons changed. </item>
|
|
||||||
/// <item>Parameter is the equipment slot changed (Mainhand or Offhand). </item>
|
|
||||||
/// <item>Parameter is the model values to change the weapon to. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class WeaponLoading()
|
|
||||||
: EventWrapperRef3<Actor, EquipSlot, CharacterWeapon, WeaponLoading.Priority>(nameof(WeaponLoading))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
@ -24,4 +17,16 @@ public sealed class WeaponLoading()
|
||||||
/// <seealso cref="Automation.AutoDesignApplier.OnWeaponLoading"/>
|
/// <seealso cref="Automation.AutoDesignApplier.OnWeaponLoading"/>
|
||||||
AutoDesignApplier = -1,
|
AutoDesignApplier = -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref struct Arguments(Actor actor, EquipSlot slot, ref CharacterWeapon weapon)
|
||||||
|
{
|
||||||
|
/// <summary> The actor that has its weapons changed. </summary>
|
||||||
|
public readonly Actor Actor = actor;
|
||||||
|
|
||||||
|
/// <summary> The changed equipment slot (either Mainhand or Offhand). </summary>
|
||||||
|
public readonly EquipSlot Slot = slot;
|
||||||
|
|
||||||
|
/// <summary> The model data for the new weapon. </summary>
|
||||||
|
public ref CharacterWeapon Weapon = ref weapon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,24 @@
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Events;
|
namespace Glamourer.Events;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when the visibility of weapons is changed. </summary>
|
||||||
/// Triggered when the visibility of weapons is changed.
|
public sealed class WeaponVisibilityChanged(Logger log)
|
||||||
/// <list type="number">
|
: EventBase<WeaponVisibilityChanged.Arguments, WeaponVisibilityChanged.Priority>(nameof(WeaponVisibilityChanged), log)
|
||||||
/// <item>Parameter is the actor with changed weapon visibility. </item>
|
|
||||||
/// <item>Parameter is the new state. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed class WeaponVisibilityChanged() : EventWrapperRef2<Actor, bool, WeaponVisibilityChanged.Priority>(nameof(WeaponVisibilityChanged))
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="State.StateListener.OnWeaponVisibilityChange"/>
|
/// <seealso cref="State.StateListener.OnWeaponVisibilityChange"/>
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref struct Arguments(Actor actor, ref bool value)
|
||||||
|
{
|
||||||
|
/// <summary> The actor with changed weapon visibility. </summary>
|
||||||
|
public readonly Actor Actor = actor;
|
||||||
|
|
||||||
|
/// <summary> The new state. </summary>
|
||||||
|
public ref bool Value = ref value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using OtterGui.Extensions;
|
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Race = Penumbra.GameData.Enums.Race;
|
using Race = Penumbra.GameData.Enums.Race;
|
||||||
|
|
@ -139,10 +138,10 @@ public class CustomizeSet
|
||||||
_ => Invalid(out custom),
|
_ => Invalid(out custom),
|
||||||
};
|
};
|
||||||
|
|
||||||
int Get(IEnumerable<CustomizeData> list, CustomizeValue v, out CustomizeData? output)
|
static int Get(IEnumerable<CustomizeData> list, CustomizeValue v, out CustomizeData? output)
|
||||||
{
|
{
|
||||||
var (val, idx) = list.Cast<CustomizeData?>().WithIndex().FirstOrDefault(p => p.Value!.Value.Value == v);
|
var (idx, val) = list.Cast<CustomizeData?>().Index().FirstOrDefault(p => p.Item!.Value.Value == v);
|
||||||
if (val == null)
|
if (val is null)
|
||||||
{
|
{
|
||||||
output = null;
|
output = null;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ using Glamourer.State;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Logger = OtterGui.Log.Logger;
|
using Vortice.Direct3D11.Debug;
|
||||||
|
|
||||||
namespace Glamourer;
|
namespace Glamourer;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,12 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Glamourer.Api\Glamourer.Api.csproj" />
|
<ProjectReference Include="..\Glamourer.Api\Glamourer.Api.csproj" />
|
||||||
<ProjectReference Include="..\Luna\Luna\Luna.csproj" />
|
<ProjectReference Include="..\Luna\Luna\Luna.csproj" />
|
||||||
<ProjectReference Include="..\OtterGui\OtterGui.csproj" />
|
|
||||||
<ProjectReference Include="..\Penumbra.Api\Penumbra.Api.csproj" />
|
<ProjectReference Include="..\Penumbra.Api\Penumbra.Api.csproj" />
|
||||||
<ProjectReference Include="..\Penumbra.String\Penumbra.String.csproj" />
|
<ProjectReference Include="..\Penumbra.String\Penumbra.String.csproj" />
|
||||||
<ProjectReference Include="..\Penumbra.GameData\Penumbra.GameData.csproj" />
|
<ProjectReference Include="..\Penumbra.GameData\Penumbra.GameData.csproj" />
|
||||||
<PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" />
|
<PackageReference Include="Vortice.Direct3D11" Version="3.4.2-beta" />
|
||||||
|
|
||||||
<ProjectReference Include="..\Luna\Luna.Generators\Luna.Generators.csproj" OutputItemType="Analyzer"
|
<ProjectReference Include="..\Luna\Luna.Generators\Luna.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
ReferenceOutputAssembly="false" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -56,8 +54,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="GetGitHash" BeforeTargets="GetAssemblyVersion" Returns="InformationalVersion">
|
<Target Name="GetGitHash" BeforeTargets="GetAssemblyVersion" Returns="InformationalVersion">
|
||||||
<Exec Command="git rev-parse --short HEAD" ConsoleToMSBuild="true" StandardOutputImportance="low"
|
<Exec Command="git rev-parse --short HEAD" ConsoleToMSBuild="true" StandardOutputImportance="low" ContinueOnError="true">
|
||||||
ContinueOnError="true">
|
|
||||||
<Output TaskParameter="ExitCode" PropertyName="GitCommitHashSuccess" />
|
<Output TaskParameter="ExitCode" PropertyName="GitCommitHashSuccess" />
|
||||||
<Output TaskParameter="ConsoleOutput" PropertyName="GitCommitHash" Condition="$(GitCommitHashSuccess) == 0" />
|
<Output TaskParameter="ConsoleOutput" PropertyName="GitCommitHash" Condition="$(GitCommitHashSuccess) == 0" />
|
||||||
</Exec>
|
</Exec>
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Customization;
|
namespace Glamourer.Gui.Customization;
|
||||||
|
|
||||||
public partial class CustomizationDrawer(
|
public sealed partial class CustomizationDrawer(
|
||||||
ITextureProvider textures,
|
ITextureProvider textures,
|
||||||
CustomizeService service,
|
CustomizeService service,
|
||||||
Configuration config,
|
Configuration config,
|
||||||
FavoriteManager favorites,
|
FavoriteManager favorites,
|
||||||
HeightService heightService)
|
HeightService heightService)
|
||||||
: IDisposable
|
: IDisposable, IUiService
|
||||||
{
|
{
|
||||||
private readonly Vector4 _redTint = new(0.6f, 0.3f, 0.3f, 1f);
|
private readonly Vector4 _redTint = new(0.6f, 0.3f, 0.3f, 1f);
|
||||||
private readonly IDalamudTextureWrap? _legacyTattoo = GetLegacyTattooIcon(textures);
|
private readonly IDalamudTextureWrap? _legacyTattoo = GetLegacyTattooIcon(textures);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using Glamourer.Automation;
|
using Glamourer.Automation;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Designs.Special;
|
using Glamourer.Designs.Special;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
|
@ -54,7 +53,7 @@ public abstract class DesignComboBase(
|
||||||
if (CurrentDesign is Design design)
|
if (CurrentDesign is Design design)
|
||||||
{
|
{
|
||||||
if (Im.Item.RightClicked() && Im.Io.KeyControl)
|
if (Im.Item.RightClicked() && Im.Io.KeyControl)
|
||||||
TabSelected.Invoke(MainTabType.Designs, design);
|
TabSelected.Invoke(new TabSelected.Arguments(MainTabType.Designs, design));
|
||||||
Im.Tooltip.OnHover("Control + Right-Click to move to design."u8);
|
Im.Tooltip.OnHover("Control + Right-Click to move to design."u8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -81,7 +80,7 @@ public abstract class DesignComboBase(
|
||||||
Im.Text("Currently resolving to "u8);
|
Im.Text("Currently resolving to "u8);
|
||||||
using var color = ImGuiColor.Text.Push(DesignColors.GetColor(linkedDesign));
|
using var color = ImGuiColor.Text.Push(DesignColors.GetColor(linkedDesign));
|
||||||
Im.Line.NoSpacing();
|
Im.Line.NoSpacing();
|
||||||
Im.Text(linkedDesign.Name.Text);
|
Im.Text(linkedDesign.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -133,9 +132,9 @@ public abstract class DesignComboBase(
|
||||||
private void OnDesignColorChanged()
|
private void OnDesignColorChanged()
|
||||||
=> Dirty |= IManagedCache.DirtyFlags.Custom;
|
=> Dirty |= IManagedCache.DirtyFlags.Custom;
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design? _1, ITransaction? _2 = null)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (type switch
|
if (arguments.Type switch
|
||||||
{
|
{
|
||||||
DesignChanged.Type.Created => true,
|
DesignChanged.Type.Created => true,
|
||||||
DesignChanged.Type.Renamed => true,
|
DesignChanged.Type.Renamed => true,
|
||||||
|
|
@ -215,18 +214,18 @@ public sealed class QuickDesignCombo : DesignComboBase, IDisposable, IUiService
|
||||||
DesignChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignCombo);
|
DesignChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignCombo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design changedDesign, ITransaction? _)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case DesignChanged.Type.Created:
|
case DesignChanged.Type.Created:
|
||||||
// If the quick design bar has no selection, select the new design if it supports the bar.
|
// If the quick design bar has no selection, select the new design if it supports the bar.
|
||||||
if (QuickDesign is null && changedDesign.QuickDesign)
|
if (QuickDesign is null && arguments.Design.QuickDesign)
|
||||||
QuickDesign = changedDesign;
|
QuickDesign = arguments.Design;
|
||||||
break;
|
break;
|
||||||
case DesignChanged.Type.Deleted:
|
case DesignChanged.Type.Deleted:
|
||||||
// If the deleted design was selected, select the first design that supports the bar, if any.
|
// If the deleted design was selected, select the first design that supports the bar, if any.
|
||||||
if (QuickDesign == changedDesign)
|
if (QuickDesign == arguments.Design)
|
||||||
QuickDesign = Designs.Designs.FirstOrDefault(d => d.QuickDesign);
|
QuickDesign = Designs.Designs.FirstOrDefault(d => d.QuickDesign);
|
||||||
break;
|
break;
|
||||||
case DesignChanged.Type.ReloadedAll:
|
case DesignChanged.Type.ReloadedAll:
|
||||||
|
|
@ -235,10 +234,10 @@ public sealed class QuickDesignCombo : DesignComboBase, IDisposable, IUiService
|
||||||
break;
|
break;
|
||||||
case DesignChanged.Type.QuickDesignBar:
|
case DesignChanged.Type.QuickDesignBar:
|
||||||
// If the quick design support of a design was changed, select the new design if the bar has no selection and the design now supports it,
|
// If the quick design support of a design was changed, select the new design if the bar has no selection and the design now supports it,
|
||||||
if (QuickDesign is null && changedDesign.QuickDesign)
|
if (QuickDesign is null && arguments.Design.QuickDesign)
|
||||||
QuickDesign = changedDesign;
|
QuickDesign = arguments.Design;
|
||||||
// or select the first design that supports the bar, if any, if the support was removed from the currently selected design.
|
// or select the first design that supports the bar, if any, if the support was removed from the currently selected design.
|
||||||
else if (QuickDesign == changedDesign && !changedDesign.QuickDesign)
|
else if (QuickDesign == arguments.Design && !arguments.Design.QuickDesign)
|
||||||
QuickDesign = Designs.Designs.FirstOrDefault(d => d.QuickDesign);
|
QuickDesign = Designs.Designs.FirstOrDefault(d => d.QuickDesign);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -290,9 +289,10 @@ public sealed class LinkDesignCombo : DesignComboBase, IUiService, IDisposable
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
=> DesignChanged.Unsubscribe(OnDesignChanged);
|
=> DesignChanged.Unsubscribe(OnDesignChanged);
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? _)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (type is DesignChanged.Type.Deleted && design == NewSelection || type is DesignChanged.Type.ReloadedAll)
|
if (arguments.Type is DesignChanged.Type.Deleted && arguments.Design == NewSelection
|
||||||
|
|| arguments.Type is DesignChanged.Type.ReloadedAll)
|
||||||
NewSelection = null;
|
NewSelection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -311,8 +311,8 @@ public sealed class RandomDesignCombo(
|
||||||
return exact.Which switch
|
return exact.Which switch
|
||||||
{
|
{
|
||||||
RandomPredicate.Exact.Type.Name => Designs.Designs.FirstOrDefault(d => d.Name == exact.Value),
|
RandomPredicate.Exact.Type.Name => Designs.Designs.FirstOrDefault(d => d.Name == exact.Value),
|
||||||
RandomPredicate.Exact.Type.Path => Designs.Designs.FirstOrDefault(d => d.Node!.FullPath == exact.Value.Text),
|
RandomPredicate.Exact.Type.Path => Designs.Designs.FirstOrDefault(d => d.Node!.FullPath == exact.Value),
|
||||||
RandomPredicate.Exact.Type.Identifier => Designs.Designs.ByIdentifier(Guid.TryParse(exact.Value.Text, out var g) ? g : Guid.Empty),
|
RandomPredicate.Exact.Type.Identifier => Designs.Designs.ByIdentifier(Guid.TryParse(exact.Value, out var g) ? g : Guid.Empty),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -320,7 +320,7 @@ public sealed class RandomDesignCombo(
|
||||||
public bool Draw(RandomPredicate.Exact exact, [NotNullWhen(true)] out Design? newDesign, float width)
|
public bool Draw(RandomPredicate.Exact exact, [NotNullWhen(true)] out Design? newDesign, float width)
|
||||||
{
|
{
|
||||||
var design = GetDesign(exact);
|
var design = GetDesign(exact);
|
||||||
if (Draw(StringU8.Empty, design?.ResolveName(Config.IncognitoMode) ?? $"Not Found [{exact.Value.Text}]", StringU8.Empty, width,
|
if (Draw(StringU8.Empty, design?.ResolveName(Config.IncognitoMode) ?? $"Not Found [{exact.Value}]", StringU8.Empty, width,
|
||||||
out var newItem)
|
out var newItem)
|
||||||
&& newItem.Design is Design d)
|
&& newItem.Design is Design d)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Equipment;
|
namespace Glamourer.Gui.Equipment;
|
||||||
|
|
||||||
public class EquipmentDrawer
|
public sealed class EquipmentDrawer : IUiService
|
||||||
{
|
{
|
||||||
private const float DefaultWidth = 280;
|
private const float DefaultWidth = 280;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
namespace Glamourer.Gui;
|
||||||
|
|
||||||
public class GenericPopupWindow : Luna.Window
|
public sealed class GenericPopupWindow : Window
|
||||||
{
|
{
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
private readonly ICondition _condition;
|
private readonly ICondition _condition;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
namespace Glamourer.Gui;
|
||||||
|
|
||||||
public class GlamourerChangelog
|
public sealed class GlamourerChangelog : IUiService
|
||||||
{
|
{
|
||||||
public const int LastChangelogVersion = 0;
|
public const int LastChangelogVersion = 0;
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Interface.Windowing;
|
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using Glamourer.Gui.Tabs.UnlocksTab;
|
using Glamourer.Gui.Tabs.UnlocksTab;
|
||||||
|
using Luna;
|
||||||
|
using WindowSystem = Dalamud.Interface.Windowing.WindowSystem;
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
namespace Glamourer.Gui;
|
||||||
|
|
||||||
public class GlamourerWindowSystem : IDisposable
|
public sealed class GlamourerWindowSystem : IDisposable, IUiService
|
||||||
{
|
{
|
||||||
private readonly WindowSystem _windowSystem = new("Glamourer");
|
private readonly WindowSystem _windowSystem = new("Glamourer");
|
||||||
private readonly IUiBuilder _uiBuilder;
|
private readonly IUiBuilder _uiBuilder;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Glamourer.Designs;
|
using Glamourer.Config;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.Gui.Tabs;
|
using Glamourer.Gui.Tabs;
|
||||||
using Glamourer.Gui.Tabs.ActorTab;
|
using Glamourer.Gui.Tabs.ActorTab;
|
||||||
|
|
@ -14,11 +14,11 @@ namespace Glamourer.Gui;
|
||||||
|
|
||||||
public sealed class MainTabBar : TabBar<MainTabType>
|
public sealed class MainTabBar : TabBar<MainTabType>
|
||||||
{
|
{
|
||||||
private readonly Config.EphemeralConfig _config;
|
private readonly EphemeralConfig _config;
|
||||||
public readonly TabSelected Event;
|
public readonly TabSelected Event;
|
||||||
public readonly SettingsTab Settings;
|
public readonly SettingsTab Settings;
|
||||||
|
|
||||||
public MainTabBar(Logger log, Config.EphemeralConfig config, SettingsTab settings, ActorTab actors, DesignTab designs,
|
public MainTabBar(Logger log, EphemeralConfig config, SettingsTab settings, ActorTab actors, DesignTab designs,
|
||||||
AutomationTab automation, UnlocksTab unlocks, NpcTab npcs, MessagesTab messages, DebugTab debug, TabSelected @event)
|
AutomationTab automation, UnlocksTab unlocks, NpcTab npcs, MessagesTab messages, DebugTab debug, TabSelected @event)
|
||||||
: base("MainTabBar", log, settings, actors, designs, automation, unlocks, npcs, messages, debug)
|
: base("MainTabBar", log, settings, actors, designs, automation, unlocks, npcs, messages, debug)
|
||||||
{
|
{
|
||||||
|
|
@ -30,8 +30,8 @@ public sealed class MainTabBar : TabBar<MainTabType>
|
||||||
NextTab = _config.SelectedMainTab;
|
NextTab = _config.SelectedMainTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEvent(MainTabType tab, Design? _)
|
private void OnEvent(in TabSelected.Arguments arguments)
|
||||||
=> NextTab = tab;
|
=> NextTab = arguments.Type;
|
||||||
|
|
||||||
private void OnTabSelected(in MainTabType arguments)
|
private void OnTabSelected(in MainTabType arguments)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ public sealed class AutomationSelection : IUiService, IDisposable
|
||||||
|
|
||||||
public int DraggedDesignIndex = -1;
|
public int DraggedDesignIndex = -1;
|
||||||
|
|
||||||
public AutoDesignSet? Set { get; private set; }
|
public AutoDesignSet? Set { get; private set; }
|
||||||
public int Index { get; private set; } = -1;
|
public int Index { get; private set; } = -1;
|
||||||
public StringU8 Name { get; private set; } = NoSelection;
|
public StringU8 Name { get; private set; } = NoSelection;
|
||||||
public StringU8 Incognito { get; private set; } = NoSelection;
|
public StringU8 Incognito { get; private set; } = NoSelection;
|
||||||
|
|
@ -29,16 +29,16 @@ public sealed class AutomationSelection : IUiService, IDisposable
|
||||||
_automationChanged.Unsubscribe(OnAutomationChanged);
|
_automationChanged.Unsubscribe(OnAutomationChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAutomationChanged(AutomationChanged.Type type, AutoDesignSet? set, object? data)
|
private void OnAutomationChanged(in AutomationChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (set != Set)
|
if (arguments.Set != Set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (type)
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case AutomationChanged.Type.DeletedSet: Update(null); break;
|
case AutomationChanged.Type.DeletedSet: Update(null); break;
|
||||||
case AutomationChanged.Type.RenamedSet: Name = new StringU8(set!.Name); break;
|
case AutomationChanged.Type.RenamedSet: Name = new StringU8(arguments.Set!.Name); break;
|
||||||
case AutomationChanged.Type.MovedSet: Index = (((int, int))data!).Item2; break;
|
case AutomationChanged.Type.MovedSet: Index = arguments.As<AutomationChanged.MovedSetArguments>().NewIndex; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public class AutomationTab : TwoPanelLayout, ITab<MainTabType>
|
public sealed class AutomationTab : TwoPanelLayout, ITab<MainTabType>
|
||||||
{
|
{
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Dalamud.Game.ClientState.Objects.Enums;
|
using Dalamud.Game.ClientState.Objects.Enums;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Gui;
|
using Penumbra.GameData.Gui;
|
||||||
|
|
@ -7,13 +8,13 @@ using Penumbra.String;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public class IdentifierDrawer(
|
public sealed class IdentifierDrawer(
|
||||||
ActorManager actors,
|
ActorManager actors,
|
||||||
DictWorld dictWorld,
|
DictWorld dictWorld,
|
||||||
DictModelChara dictModelChara,
|
DictModelChara dictModelChara,
|
||||||
DictBNpcNames bNpcNames,
|
DictBNpcNames bNpcNames,
|
||||||
DictBNpc bNpc,
|
DictBNpc bNpc,
|
||||||
HumanModelList humans)
|
HumanModelList humans) : IUiService
|
||||||
{
|
{
|
||||||
private readonly WorldCombo _worldCombo = new(dictWorld);
|
private readonly WorldCombo _worldCombo = new(dictWorld);
|
||||||
private readonly HumanNpcCombo _humanNpcCombo = new(bNpcNames, dictModelChara, humans, bNpc);
|
private readonly HumanNpcCombo _humanNpcCombo = new(bNpcNames, dictModelChara, humans, bNpc);
|
||||||
|
|
|
||||||
|
|
@ -20,21 +20,19 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
private readonly RandomDesignCombo _randomDesignCombo;
|
private readonly RandomDesignCombo _randomDesignCombo;
|
||||||
private readonly AutomationSelection _selection;
|
private readonly AutomationSelection _selection;
|
||||||
private readonly DesignStorage _designs;
|
private readonly DesignStorage _designs;
|
||||||
private readonly DesignFileSystem _designFileSystem;
|
|
||||||
|
|
||||||
private string _newText = string.Empty;
|
private string _newText = string.Empty;
|
||||||
private string? _newDefinition;
|
private string? _newDefinition;
|
||||||
private Design? _newDesign;
|
private Design? _newDesign;
|
||||||
|
|
||||||
public RandomRestrictionDrawer(AutomationChanged automationChanged, Configuration config, AutoDesignManager autoDesignManager,
|
public RandomRestrictionDrawer(AutomationChanged automationChanged, Configuration config, AutoDesignManager autoDesignManager,
|
||||||
RandomDesignCombo randomDesignCombo, AutomationSelection selection, DesignFileSystem designFileSystem, DesignStorage designs)
|
RandomDesignCombo randomDesignCombo, AutomationSelection selection, DesignStorage designs)
|
||||||
{
|
{
|
||||||
_automationChanged = automationChanged;
|
_automationChanged = automationChanged;
|
||||||
_config = config;
|
_config = config;
|
||||||
_autoDesignManager = autoDesignManager;
|
_autoDesignManager = autoDesignManager;
|
||||||
_randomDesignCombo = randomDesignCombo;
|
_randomDesignCombo = randomDesignCombo;
|
||||||
_selection = selection;
|
_selection = selection;
|
||||||
_designFileSystem = designFileSystem;
|
|
||||||
_designs = designs;
|
_designs = designs;
|
||||||
_automationChanged.Subscribe(OnAutomationChange, AutomationChanged.Priority.RandomRestrictionDrawer);
|
_automationChanged.Subscribe(OnAutomationChange, AutomationChanged.Priority.RandomRestrictionDrawer);
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +167,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
{
|
{
|
||||||
ImEx.TextFrameAligned("that contain"u8);
|
ImEx.TextFrameAligned("that contain"u8);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
var data = contains.Value.Text;
|
var data = contains.Value;
|
||||||
Im.Item.SetNextWidthFull();
|
Im.Item.SetNextWidthFull();
|
||||||
if (Im.Input.Text("##match"u8, ref data, "Name, Path, or Identifier Contains..."u8))
|
if (Im.Input.Text("##match"u8, ref data, "Name, Path, or Identifier Contains..."u8))
|
||||||
{
|
{
|
||||||
|
|
@ -186,7 +184,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
{
|
{
|
||||||
ImEx.TextFrameAligned("whose path starts with"u8);
|
ImEx.TextFrameAligned("whose path starts with"u8);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
var data = startsWith.Value.Text;
|
var data = startsWith.Value;
|
||||||
Im.Item.SetNextWidthFull();
|
Im.Item.SetNextWidthFull();
|
||||||
if (Im.Input.Text("##startsWith"u8, ref data, "Path Starts With..."u8))
|
if (Im.Input.Text("##startsWith"u8, ref data, "Path Starts With..."u8))
|
||||||
{
|
{
|
||||||
|
|
@ -204,7 +202,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
ImEx.TextFrameAligned("that contain the tag"u8);
|
ImEx.TextFrameAligned("that contain the tag"u8);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
Im.Item.SetNextWidthFull();
|
Im.Item.SetNextWidthFull();
|
||||||
var data = exact.Value.Text;
|
var data = exact.Value;
|
||||||
if (Im.Input.Text("##color"u8, ref data, "Contained tag..."u8))
|
if (Im.Input.Text("##color"u8, ref data, "Contained tag..."u8))
|
||||||
{
|
{
|
||||||
if (data.Length is 0)
|
if (data.Length is 0)
|
||||||
|
|
@ -221,7 +219,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
ImEx.TextFrameAligned("that are set to the color"u8);
|
ImEx.TextFrameAligned("that are set to the color"u8);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
Im.Item.SetNextWidthFull();
|
Im.Item.SetNextWidthFull();
|
||||||
var data = exact.Value.Text;
|
var data = exact.Value;
|
||||||
if (Im.Input.Text("##color"u8, ref data, "Assigned Color is..."u8))
|
if (Im.Input.Text("##color"u8, ref data, "Assigned Color is..."u8))
|
||||||
{
|
{
|
||||||
if (data.Length is 0)
|
if (data.Length is 0)
|
||||||
|
|
@ -265,7 +263,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
if (!Im.Item.Hovered())
|
if (!Im.Item.Hovered())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var designs = predicate.Get(_designs, _designFileSystem);
|
var designs = predicate.Get(_designs);
|
||||||
LookupTooltip(designs);
|
LookupTooltip(designs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,7 +374,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
|
|
||||||
private void DrawTotalPreview(IReadOnlyList<IDesignPredicate> list)
|
private void DrawTotalPreview(IReadOnlyList<IDesignPredicate> list)
|
||||||
{
|
{
|
||||||
var designs = IDesignPredicate.Get(list, _designs, _designFileSystem).ToList();
|
var designs = IDesignPredicate.Get(list, _designs).ToList();
|
||||||
Im.Button(designs.Count > 0
|
Im.Button(designs.Count > 0
|
||||||
? $"All Restrictions Combined Match {designs.Count} Designs"
|
? $"All Restrictions Combined Match {designs.Count} Designs"
|
||||||
: "None of the Restrictions Matches Any Designs"u8, Im.ContentRegion.Available with { Y = 0 });
|
: "None of the Restrictions Matches Any Designs"u8, Im.ContentRegion.Available with { Y = 0 });
|
||||||
|
|
@ -414,26 +412,27 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
DrawManualInput(list);
|
DrawManualInput(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAutomationChange(AutomationChanged.Type type, AutoDesignSet? set, object? data)
|
private void OnAutomationChange(in AutomationChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (set != _set || _set is null)
|
if (arguments.Set != _set || _set is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (type)
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case AutomationChanged.Type.DeletedSet:
|
case AutomationChanged.Type.DeletedSet:
|
||||||
case AutomationChanged.Type.DeletedDesign when data is int index && _designIndex == index:
|
case AutomationChanged.Type.DeletedDesign when arguments.As<AutomationChanged.DeletedDesignArguments>().Index == _designIndex:
|
||||||
Close();
|
Close();
|
||||||
break;
|
break;
|
||||||
case AutomationChanged.Type.MovedDesign when data is (int from, int to):
|
case AutomationChanged.Type.MovedDesign:
|
||||||
if (_designIndex == from)
|
var data = arguments.As<AutomationChanged.MovedDesignArguments>();
|
||||||
_designIndex = to;
|
if (_designIndex == data.OldIndex)
|
||||||
else if (_designIndex < from && _designIndex > to)
|
_designIndex = data.NewIndex;
|
||||||
|
else if (_designIndex < data.OldIndex && _designIndex > data.NewIndex)
|
||||||
_designIndex++;
|
_designIndex++;
|
||||||
else if (_designIndex > to && _designIndex < from)
|
else if (_designIndex > data.NewIndex && _designIndex < data.OldIndex)
|
||||||
_designIndex--;
|
_designIndex--;
|
||||||
break;
|
break;
|
||||||
case AutomationChanged.Type.ChangedDesign when data is (int index, IDesignStandIn _, IDesignStandIn _) && index == _designIndex:
|
case AutomationChanged.Type.ChangedDesign when arguments.As<AutomationChanged.ChangedDesignArguments>().DesignIndex == _designIndex:
|
||||||
Close();
|
Close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public class SetPanel(
|
public sealed class SetPanel(
|
||||||
AutoDesignManager manager,
|
AutoDesignManager manager,
|
||||||
JobService jobs,
|
JobService jobs,
|
||||||
ItemUnlockManager itemUnlocks,
|
ItemUnlockManager itemUnlocks,
|
||||||
|
|
|
||||||
|
|
@ -125,9 +125,9 @@ public sealed class SetSelector(
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAutomationChanged(AutomationChanged.Type type, AutoDesignSet? set, object? data)
|
private void OnAutomationChanged(in AutomationChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case AutomationChanged.Type.DeletedSet:
|
case AutomationChanged.Type.DeletedSet:
|
||||||
case AutomationChanged.Type.AddedSet:
|
case AutomationChanged.Type.AddedSet:
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
using Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
using Glamourer.Gui.Tabs.DebugTab.IpcTester;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using OtterGui.Raii;
|
|
||||||
using Penumbra.GameData.Gui.Debug;
|
using Penumbra.GameData.Gui.Debug;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.DebugTab;
|
namespace Glamourer.Gui.Tabs.DebugTab;
|
||||||
|
|
||||||
public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
public class DebugTabHeader(ReadOnlySpan<byte> label, params IGameDataDrawer[] subTrees)
|
||||||
{
|
{
|
||||||
public string Label { get; } = label;
|
public StringU8 Label { get; } = new(label);
|
||||||
public IReadOnlyList<IGameDataDrawer> SubTrees { get; } = subTrees;
|
public IReadOnlyList<IGameDataDrawer> SubTrees { get; } = subTrees;
|
||||||
|
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
{
|
||||||
using var h = ImRaii.CollapsingHeader(Label);
|
using var h = Im.Tree.HeaderId(Label);
|
||||||
if (!h)
|
if (!h)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -32,7 +31,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
||||||
public static DebugTabHeader CreateInterop(IServiceProvider provider)
|
public static DebugTabHeader CreateInterop(IServiceProvider provider)
|
||||||
=> new
|
=> new
|
||||||
(
|
(
|
||||||
"Interop",
|
"Interop"u8,
|
||||||
provider.GetRequiredService<ModelEvaluationPanel>(),
|
provider.GetRequiredService<ModelEvaluationPanel>(),
|
||||||
provider.GetRequiredService<ObjectManagerPanel>(),
|
provider.GetRequiredService<ObjectManagerPanel>(),
|
||||||
provider.GetRequiredService<PenumbraPanel>(),
|
provider.GetRequiredService<PenumbraPanel>(),
|
||||||
|
|
@ -46,7 +45,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
||||||
public static DebugTabHeader CreateGameData(IServiceProvider provider)
|
public static DebugTabHeader CreateGameData(IServiceProvider provider)
|
||||||
=> new
|
=> new
|
||||||
(
|
(
|
||||||
"Game Data",
|
"Game Data"u8,
|
||||||
provider.GetRequiredService<DataServiceDiagnosticsDrawer>(),
|
provider.GetRequiredService<DataServiceDiagnosticsDrawer>(),
|
||||||
provider.GetRequiredService<IdentificationDrawer>(),
|
provider.GetRequiredService<IdentificationDrawer>(),
|
||||||
provider.GetRequiredService<RestrictedGearDrawer>(),
|
provider.GetRequiredService<RestrictedGearDrawer>(),
|
||||||
|
|
@ -62,7 +61,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
||||||
public static DebugTabHeader CreateDesigns(IServiceProvider provider)
|
public static DebugTabHeader CreateDesigns(IServiceProvider provider)
|
||||||
=> new
|
=> new
|
||||||
(
|
(
|
||||||
"Designs",
|
"Designs"u8,
|
||||||
provider.GetRequiredService<DesignManagerPanel>(),
|
provider.GetRequiredService<DesignManagerPanel>(),
|
||||||
provider.GetRequiredService<DesignConverterPanel>(),
|
provider.GetRequiredService<DesignConverterPanel>(),
|
||||||
provider.GetRequiredService<DesignTesterPanel>(),
|
provider.GetRequiredService<DesignTesterPanel>(),
|
||||||
|
|
@ -72,7 +71,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
||||||
public static DebugTabHeader CreateState(IServiceProvider provider)
|
public static DebugTabHeader CreateState(IServiceProvider provider)
|
||||||
=> new
|
=> new
|
||||||
(
|
(
|
||||||
"State",
|
"State"u8,
|
||||||
provider.GetRequiredService<ActiveStatePanel>(),
|
provider.GetRequiredService<ActiveStatePanel>(),
|
||||||
provider.GetRequiredService<RetainedStatePanel>(),
|
provider.GetRequiredService<RetainedStatePanel>(),
|
||||||
provider.GetRequiredService<FunPanel>()
|
provider.GetRequiredService<FunPanel>()
|
||||||
|
|
@ -81,7 +80,7 @@ public class DebugTabHeader(string label, params IGameDataDrawer[] subTrees)
|
||||||
public static DebugTabHeader CreateUnlocks(IServiceProvider provider)
|
public static DebugTabHeader CreateUnlocks(IServiceProvider provider)
|
||||||
=> new
|
=> new
|
||||||
(
|
(
|
||||||
"Unlocks",
|
"Unlocks"u8,
|
||||||
provider.GetRequiredService<CustomizationUnlockPanel>(),
|
provider.GetRequiredService<CustomizationUnlockPanel>(),
|
||||||
provider.GetRequiredService<ItemUnlockPanel>(),
|
provider.GetRequiredService<ItemUnlockPanel>(),
|
||||||
provider.GetRequiredService<UnlockableItemsPanel>(),
|
provider.GetRequiredService<UnlockableItemsPanel>(),
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ public sealed class DesignManagerPanel(DesignManager designManager, DesignFileSy
|
||||||
foreach (var (idx, design) in designManager.Designs.Index())
|
foreach (var (idx, design) in designManager.Designs.Index())
|
||||||
{
|
{
|
||||||
using var id = Im.Id.Push(idx);
|
using var id = Im.Id.Push(idx);
|
||||||
using var t = Im.Tree.Node(design.Name.Text);
|
using var t = Im.Tree.Node(design.Name);
|
||||||
if (!t)
|
if (!t)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ public sealed class DesignManagerPanel(DesignManager designManager, DesignFileSy
|
||||||
if (design is Design d)
|
if (design is Design d)
|
||||||
{
|
{
|
||||||
table.DrawColumn("Name"u8);
|
table.DrawColumn("Name"u8);
|
||||||
table.DrawColumn(d.Name.Text);
|
table.DrawColumn(d.Name);
|
||||||
table.DrawColumn($"({d.Index})");
|
table.DrawColumn($"({d.Index})");
|
||||||
table.DrawColumn("Description (Hover)"u8);
|
table.DrawColumn("Description (Hover)"u8);
|
||||||
Im.Tooltip.OnHover(d.Description);
|
Im.Tooltip.OnHover(d.Description);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using OtterGui.Raii;
|
using ImSharp;
|
||||||
using Penumbra.GameData.Gui.Debug;
|
using Penumbra.GameData.Gui.Debug;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ public sealed class RetainedStatePanel(StateManager stateManager, ActorObjectMan
|
||||||
{
|
{
|
||||||
foreach (var (identifier, state) in stateManager.Where(kvp => !objectManager.ContainsKey(kvp.Key)))
|
foreach (var (identifier, state) in stateManager.Where(kvp => !objectManager.ContainsKey(kvp.Key)))
|
||||||
{
|
{
|
||||||
using var t = ImRaii.TreeNode(identifier.ToString());
|
using var t = Im.Tree.Node($"{identifier}");
|
||||||
if (t)
|
if (t)
|
||||||
ActiveStatePanel.DrawState(stateManager, ActorData.Invalid, state);
|
ActiveStatePanel.DrawState(stateManager, ActorData.Invalid, state);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
|
using Glamourer.Gui.Tabs.SettingsTab;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||||
|
|
||||||
public class DesignDetailTab
|
public sealed class DesignDetailTab : IUiService
|
||||||
{
|
{
|
||||||
private readonly SaveService _saveService;
|
private readonly SaveService _saveService;
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
|
|
@ -57,7 +58,7 @@ public class DesignDetailTab
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
var width = Im.ContentRegion.Available with { Y = 0 };
|
var width = Im.ContentRegion.Available with { Y = 0 };
|
||||||
Im.Item.SetNextWidth(width.X);
|
Im.Item.SetNextWidth(width.X);
|
||||||
if (ImEx.InputOnDeactivation.Text("##Name"u8, Selected.Name.Text, out string newName))
|
if (ImEx.InputOnDeactivation.Text("##Name"u8, Selected.Name, out string newName))
|
||||||
_manager.Rename(Selected, newName);
|
_manager.Rename(Selected, newName);
|
||||||
|
|
||||||
var identifier = Selected.Identifier.ToString();
|
var identifier = Selected.Identifier.ToString();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Security.AccessControl;
|
using Glamourer.Config;
|
||||||
using Glamourer.Config;
|
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Designs.History;
|
using Glamourer.Designs.History;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
|
|
@ -31,29 +30,29 @@ public sealed class DesignHeader : SplitButtonHeader, IDisposable
|
||||||
LeftButtons.AddButton(new ApplyCharacterButton(fileSystem, manager, objects, stateManager, converter), 70);
|
LeftButtons.AddButton(new ApplyCharacterButton(fileSystem, manager, objects, stateManager, converter), 70);
|
||||||
LeftButtons.AddButton(new UndoButton(fileSystem, history), 60);
|
LeftButtons.AddButton(new UndoButton(fileSystem, history), 60);
|
||||||
|
|
||||||
RightButtons.AddButton(incognito, 50);
|
RightButtons.AddButton(incognito, 50);
|
||||||
RightButtons.AddButton(new LockedButton(fileSystem, manager), 100);
|
RightButtons.AddButton(new LockedButton(fileSystem, manager), 100);
|
||||||
_fileSystem.Selection.Changed += OnSelectionChanged;
|
_fileSystem.Selection.Changed += OnSelectionChanged;
|
||||||
OnSelectionChanged();
|
OnSelectionChanged();
|
||||||
designChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignHeader);
|
designChanged.Subscribe(OnDesignChanged, DesignChanged.Priority.DesignHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type arg1, Design arg2, ITransaction? arg3)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (arg1 is not DesignChanged.Type.Renamed)
|
if (arguments.Type is not DesignChanged.Type.Renamed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (arg2 != _fileSystem.Selection.Selection?.Value)
|
if (arguments.Design != _fileSystem.Selection.Selection?.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_header = new StringU8(arg2.Name.Text);
|
_header = new StringU8(arguments.Design.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSelectionChanged()
|
private void OnSelectionChanged()
|
||||||
{
|
{
|
||||||
if (_fileSystem.Selection.Selection?.GetValue<Design>() is { } selection)
|
if (_fileSystem.Selection.Selection?.GetValue<Design>() is { } selection)
|
||||||
{
|
{
|
||||||
_header = new StringU8(selection.Name.Text);
|
_header = new StringU8(selection.Name);
|
||||||
_incognito = new StringU8(selection.Incognito);
|
_incognito = new StringU8(selection.Incognito);
|
||||||
}
|
}
|
||||||
else if (_fileSystem.Selection.OrderedNodes.Count > 0)
|
else if (_fileSystem.Selection.OrderedNodes.Count > 0)
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ public class DesignLinkDrawer(
|
||||||
using (ImGuiColor.Text.Push(color))
|
using (ImGuiColor.Text.Push(color))
|
||||||
{
|
{
|
||||||
Im.Cursor.FrameAlign();
|
Im.Cursor.FrameAlign();
|
||||||
Im.Selectable(config.Ephemeral.IncognitoMode ? Selected.Incognito : Selected.Name.Text);
|
Im.Selectable(config.Ephemeral.IncognitoMode ? Selected.Incognito : Selected.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Im.Tooltip.OnHover("Current Design"u8);
|
Im.Tooltip.OnHover("Current Design"u8);
|
||||||
|
|
@ -137,7 +137,7 @@ public class DesignLinkDrawer(
|
||||||
using (ImGuiColor.Text.Push(colorManager.GetColor(design)))
|
using (ImGuiColor.Text.Push(colorManager.GetColor(design)))
|
||||||
{
|
{
|
||||||
Im.Cursor.FrameAlign();
|
Im.Cursor.FrameAlign();
|
||||||
Im.Selectable(config.Ephemeral.IncognitoMode ? design.Incognito : design.Name.Text);
|
Im.Selectable(config.Ephemeral.IncognitoMode ? design.Incognito : design.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawDragDrop(design, order, i);
|
DrawDragDrop(design, order, i);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||||
|
|
||||||
public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystem fileSystem, DesignManager manager, Configuration config)
|
public sealed class ModAssociationsTab(PenumbraService penumbra, DesignFileSystem fileSystem, DesignManager manager, Configuration config) : IUiService
|
||||||
{
|
{
|
||||||
private readonly ModCombo _modCombo = new(penumbra, fileSystem);
|
private readonly ModCombo _modCombo = new(penumbra, fileSystem);
|
||||||
private (Mod, ModSettings)[]? _copy;
|
private (Mod, ModSettings)[]? _copy;
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||||
|
|
||||||
public class MultiDesignPanel(
|
public sealed class MultiDesignPanel(
|
||||||
DesignFileSystem fileSystem,
|
DesignFileSystem fileSystem,
|
||||||
DesignManager editor,
|
DesignManager editor,
|
||||||
DesignColors colors,
|
DesignColors colors,
|
||||||
Configuration config)
|
Configuration config) : IUiService
|
||||||
{
|
{
|
||||||
private readonly DesignColorCombo _colorCombo = new(colors, true);
|
private readonly DesignColorCombo _colorCombo = new(colors, true);
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ public class MultiDesignPanel(
|
||||||
{
|
{
|
||||||
using var id = Im.Id.Push(index);
|
using var id = Im.Id.Push(index);
|
||||||
var (icon, text) = node is IFileSystemData<Design> l
|
var (icon, text) = node is IFileSystemData<Design> l
|
||||||
? (LunaStyle.RemoveFileIcon, l.Value.Name.Text)
|
? (LunaStyle.RemoveFileIcon, l.Value.Name)
|
||||||
: (LunaStyle.RemoveFolderIcon, string.Empty);
|
: (LunaStyle.RemoveFolderIcon, string.Empty);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
if (ImEx.Icon.Button(icon, "Remove from selection."u8, sizeType))
|
if (ImEx.Icon.Button(icon, "Remove from selection."u8, sizeType))
|
||||||
|
|
@ -152,7 +152,7 @@ public class MultiDesignPanel(
|
||||||
? _tag.Length is 0
|
? _tag.Length is 0
|
||||||
? "No tag specified."u8
|
? "No tag specified."u8
|
||||||
: $"All designs selected already contain the tag \"{_tag}\"."
|
: $"All designs selected already contain the tag \"{_tag}\"."
|
||||||
: $"Add the tag \"{_tag}\" to {_addDesigns.Count} designs as a local tag:\n\n\t{StringU8.Join("\n\t"u8, _addDesigns.Select(m => m.Name.Text))}",
|
: $"Add the tag \"{_tag}\" to {_addDesigns.Count} designs as a local tag:\n\n\t{StringU8.Join("\n\t"u8, _addDesigns.Select(m => m.Name))}",
|
||||||
_addDesigns.Count is 0))
|
_addDesigns.Count is 0))
|
||||||
foreach (var design in _addDesigns)
|
foreach (var design in _addDesigns)
|
||||||
editor.AddTag(design, _tag);
|
editor.AddTag(design, _tag);
|
||||||
|
|
@ -164,7 +164,7 @@ public class MultiDesignPanel(
|
||||||
? _tag.Length is 0
|
? _tag.Length is 0
|
||||||
? "No tag specified."u8
|
? "No tag specified."u8
|
||||||
: $"No selected design contains the tag \"{_tag}\" locally."
|
: $"No selected design contains the tag \"{_tag}\" locally."
|
||||||
: $"Remove the local tag \"{_tag}\" from {_removeDesigns.Count} designs:\n\n\t{string.Join("\n\t", _removeDesigns.Select(m => m.Item1.Name.Text))}",
|
: $"Remove the local tag \"{_tag}\" from {_removeDesigns.Count} designs:\n\n\t{string.Join("\n\t", _removeDesigns.Select(m => m.Item1.Name))}",
|
||||||
_removeDesigns.Count is 0))
|
_removeDesigns.Count is 0))
|
||||||
foreach (var (design, index) in _removeDesigns)
|
foreach (var (design, index) in _removeDesigns)
|
||||||
editor.RemoveTag(design, index);
|
editor.RemoveTag(design, index);
|
||||||
|
|
@ -306,7 +306,7 @@ public class MultiDesignPanel(
|
||||||
DesignColors.AutomaticName => "Use the other button to set to automatic."u8,
|
DesignColors.AutomaticName => "Use the other button to set to automatic."u8,
|
||||||
_ => $"All designs selected are already set to the color \"{_colorComboSelection}\".",
|
_ => $"All designs selected are already set to the color \"{_colorComboSelection}\".",
|
||||||
}
|
}
|
||||||
: $"Set the color of {_addDesigns.Count} designs to \"{_colorComboSelection}\"\n\n\t{StringU8.Join("\n\t"u8, _addDesigns.Select(m => m.Name.Text))}",
|
: $"Set the color of {_addDesigns.Count} designs to \"{_colorComboSelection}\"\n\n\t{StringU8.Join("\n\t"u8, _addDesigns.Select(m => m.Name))}",
|
||||||
_addDesigns.Count is 0))
|
_addDesigns.Count is 0))
|
||||||
foreach (var design in _addDesigns)
|
foreach (var design in _addDesigns)
|
||||||
editor.ChangeColor(design, _colorComboSelection!);
|
editor.ChangeColor(design, _colorComboSelection!);
|
||||||
|
|
@ -316,7 +316,7 @@ public class MultiDesignPanel(
|
||||||
? $"Unset {_removeDesigns.Count} Designs"
|
? $"Unset {_removeDesigns.Count} Designs"
|
||||||
: "Unset"u8, width, _removeDesigns.Count is 0
|
: "Unset"u8, width, _removeDesigns.Count is 0
|
||||||
? "No selected design is set to a non-automatic color."u8
|
? "No selected design is set to a non-automatic color."u8
|
||||||
: $"Set {_removeDesigns.Count} designs to use automatic color again:\n\n\t{StringU8.Join("\n\t"u8, _removeDesigns.Select(m => m.Item1.Name.Text))}",
|
: $"Set {_removeDesigns.Count} designs to use automatic color again:\n\n\t{StringU8.Join("\n\t"u8, _removeDesigns.Select(m => m.Item1.Name))}",
|
||||||
_removeDesigns.Count is 0))
|
_removeDesigns.Count is 0))
|
||||||
foreach (var (design, _) in _removeDesigns)
|
foreach (var (design, _) in _removeDesigns)
|
||||||
editor.ChangeColor(design, string.Empty);
|
editor.ChangeColor(design, string.Empty);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
@ -21,9 +20,9 @@ public sealed class DesignFileSystemCache : FileSystemCache<DesignFileSystemCach
|
||||||
node.Dirty = true;
|
node.Dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDesignChanged(DesignChanged.Type type, Design design, ITransaction? _2)
|
private void OnDesignChanged(in DesignChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (arguments.Type)
|
||||||
{
|
{
|
||||||
case DesignChanged.Type.Created:
|
case DesignChanged.Type.Created:
|
||||||
case DesignChanged.Type.Deleted:
|
case DesignChanged.Type.Deleted:
|
||||||
|
|
@ -45,7 +44,7 @@ public sealed class DesignFileSystemCache : FileSystemCache<DesignFileSystemCach
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (design.Node is { } node && AllNodes.TryGetValue(node, out var cache))
|
if (arguments.Design.Node is { } node && AllNodes.TryGetValue(node, out var cache))
|
||||||
cache.Dirty = true;
|
cache.Dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,14 +77,14 @@ public sealed class DesignFileSystemCache : FileSystemCache<DesignFileSystemCach
|
||||||
{
|
{
|
||||||
public readonly IFileSystemData<Design> Node = node;
|
public readonly IFileSystemData<Design> Node = node;
|
||||||
public Vector4 Color;
|
public Vector4 Color;
|
||||||
public StringU8 Name = new(node.Value.Name.Text);
|
public StringU8 Name = new(node.Value.Name);
|
||||||
public StringU8 Incognito = new(node.Value.Incognito);
|
public StringU8 Incognito = new(node.Value.Incognito);
|
||||||
|
|
||||||
public override void Update(FileSystemCache cache, IFileSystemNode node)
|
public override void Update(FileSystemCache cache, IFileSystemNode node)
|
||||||
{
|
{
|
||||||
var drawer = (DesignFileSystemDrawer)cache.Parent;
|
var drawer = (DesignFileSystemDrawer)cache.Parent;
|
||||||
Color = drawer.DesignColors.GetColor(Node.Value).ToVector();
|
Color = drawer.DesignColors.GetColor(Node.Value).ToVector();
|
||||||
Name = new StringU8(Node.Value.Name.Text);
|
Name = new StringU8(Node.Value.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DrawInternal(FileSystemCache<DesignData> cache, IFileSystemNode node)
|
protected override void DrawInternal(FileSystemCache<DesignData> cache, IFileSystemNode node)
|
||||||
|
|
|
||||||
|
|
@ -42,12 +42,12 @@ public sealed class DesignFilter : TokenizedFilter<DesignFilterTokenType, Design
|
||||||
=> token.Type switch
|
=> token.Type switch
|
||||||
{
|
{
|
||||||
DesignFilterTokenType.Default => cacheItem.Node.FullPath.Contains(token.Needle, StringComparison.OrdinalIgnoreCase)
|
DesignFilterTokenType.Default => cacheItem.Node.FullPath.Contains(token.Needle, StringComparison.OrdinalIgnoreCase)
|
||||||
|| cacheItem.Node.Value.Name.Text.Contains(token.Needle, StringComparison.OrdinalIgnoreCase),
|
|| cacheItem.Node.Value.Name.Contains(token.Needle, StringComparison.OrdinalIgnoreCase),
|
||||||
DesignFilterTokenType.Mod => CheckMods(token.Needle, cacheItem),
|
DesignFilterTokenType.Mod => CheckMods(token.Needle, cacheItem),
|
||||||
DesignFilterTokenType.Tag => CheckTags(token.Needle, cacheItem),
|
DesignFilterTokenType.Tag => CheckTags(token.Needle, cacheItem),
|
||||||
DesignFilterTokenType.Color => cacheItem.Node.Value.Color.Contains(token.Needle, StringComparison.OrdinalIgnoreCase),
|
DesignFilterTokenType.Color => cacheItem.Node.Value.Color.Contains(token.Needle, StringComparison.OrdinalIgnoreCase),
|
||||||
DesignFilterTokenType.Item => cacheItem.Node.Value.DesignData.ContainsName(token.Needle),
|
DesignFilterTokenType.Item => cacheItem.Node.Value.DesignData.ContainsName(token.Needle),
|
||||||
DesignFilterTokenType.Name => cacheItem.Node.Value.Name.Text.Contains(token.Needle, StringComparison.OrdinalIgnoreCase),
|
DesignFilterTokenType.Name => cacheItem.Node.Value.Name.Contains(token.Needle, StringComparison.OrdinalIgnoreCase),
|
||||||
DesignFilterTokenType.FullContext => CheckFullContext(token.Needle, cacheItem),
|
DesignFilterTokenType.FullContext => CheckFullContext(token.Needle, cacheItem),
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
|
|
@ -77,7 +77,7 @@ public sealed class DesignFilter : TokenizedFilter<DesignFilterTokenType, Design
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var design = cacheItem.Node.Value;
|
var design = cacheItem.Node.Value;
|
||||||
if (design.Name.Text.Contains(needle, StringComparison.OrdinalIgnoreCase))
|
if (design.Name.Contains(needle, StringComparison.OrdinalIgnoreCase))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (design.Description.Contains(needle, StringComparison.OrdinalIgnoreCase))
|
if (design.Description.Contains(needle, StringComparison.OrdinalIgnoreCase))
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ public sealed class RenameDesignInput(DesignFileSystemDrawer fileSystem) : BaseB
|
||||||
public override bool DrawMenuItem(in IFileSystemData data)
|
public override bool DrawMenuItem(in IFileSystemData data)
|
||||||
{
|
{
|
||||||
var design = (Design)data.Value;
|
var design = (Design)data.Value;
|
||||||
var currentName = design.Name.Text;
|
var currentName = design.Name;
|
||||||
using var style = Im.Style.PushDefault(ImStyleDouble.FramePadding);
|
using var style = Im.Style.PushDefault(ImStyleDouble.FramePadding);
|
||||||
MenuSeparator.DrawSeparator();
|
MenuSeparator.DrawSeparator();
|
||||||
Im.Text("Rename Design:"u8);
|
Im.Text("Rename Design:"u8);
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,13 @@ using Glamourer.Designs;
|
||||||
using Glamourer.GameData;
|
using Glamourer.GameData;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.NpcTab;
|
namespace Glamourer.Gui.Tabs.NpcTab;
|
||||||
|
|
||||||
public class LocalNpcAppearanceData : ISavable
|
public sealed class LocalNpcAppearanceData : ISavable, IUiService
|
||||||
{
|
{
|
||||||
private readonly DesignColors _colors;
|
private readonly DesignColors _colors;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ 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.Gui.Tabs.SettingsTab;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
|
||||||
113
Glamourer/Gui/Tabs/SettingsTab/DesignColorUi.cs
Normal file
113
Glamourer/Gui/Tabs/SettingsTab/DesignColorUi.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
using Glamourer.Config;
|
||||||
|
using Glamourer.Designs;
|
||||||
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui.Tabs.SettingsTab;
|
||||||
|
|
||||||
|
public sealed class DesignColorUi(DesignColors colors, Configuration config) : IUiService
|
||||||
|
{
|
||||||
|
private string _newName = string.Empty;
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
using var table = Im.Table.Begin("designColors"u8, 3, TableFlags.RowBackground);
|
||||||
|
if (!table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var changeString = string.Empty;
|
||||||
|
Rgba32? changeValue = null;
|
||||||
|
|
||||||
|
table.SetupColumn("##Delete"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight);
|
||||||
|
table.SetupColumn("##Select"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight);
|
||||||
|
table.SetupColumn("Color Name"u8, TableColumnFlags.WidthStretch);
|
||||||
|
|
||||||
|
table.HeaderRow();
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
if (ImEx.Icon.Button(LunaStyle.RefreshIcon, "Revert the color used for missing design colors to its default."u8,
|
||||||
|
colors.MissingColor == DesignColors.MissingColorDefault))
|
||||||
|
{
|
||||||
|
changeString = DesignColors.MissingColorName;
|
||||||
|
changeValue = DesignColors.MissingColorDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
if (DrawColorButton(DesignColors.MissingColorNameU8, colors.MissingColor, out var newColor))
|
||||||
|
{
|
||||||
|
changeString = DesignColors.MissingColorName;
|
||||||
|
changeValue = newColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
Im.Cursor.X += Im.Style.FramePadding.X;
|
||||||
|
Im.Text(DesignColors.MissingColorNameU8);
|
||||||
|
Im.Tooltip.OnHover("This color is used when the color specified in a design is not available."u8);
|
||||||
|
|
||||||
|
var disabled = !config.DeleteDesignModifier.IsActive();
|
||||||
|
foreach (var (idx, (name, color)) in colors.Index())
|
||||||
|
{
|
||||||
|
using var id = Im.Id.Push(idx);
|
||||||
|
table.NextColumn();
|
||||||
|
|
||||||
|
if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this color. This does not remove it from designs using it."u8, disabled))
|
||||||
|
{
|
||||||
|
changeString = name;
|
||||||
|
changeValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disabled)
|
||||||
|
Im.Tooltip.OnHover($"\nHold {config.DeleteDesignModifier} to delete.");
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
if (DrawColorButton(name, color, out newColor))
|
||||||
|
{
|
||||||
|
changeString = name;
|
||||||
|
changeValue = newColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
Im.Cursor.X += Im.Style.FramePadding.X;
|
||||||
|
Im.Text(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
(var tt, disabled) = _newName.Length == 0
|
||||||
|
? ("Specify a name for a new color first.", true)
|
||||||
|
: _newName is DesignColors.MissingColorName or DesignColors.AutomaticName
|
||||||
|
? ($"You can not use the name {DesignColors.MissingColorName} or {DesignColors.AutomaticName}, choose a different one.", true)
|
||||||
|
: colors.ContainsKey(_newName)
|
||||||
|
? ($"The color {_newName} already exists, please choose a different name.", true)
|
||||||
|
: ($"Add a new color {_newName} to your list.", false);
|
||||||
|
if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, disabled))
|
||||||
|
{
|
||||||
|
changeString = _newName;
|
||||||
|
changeValue = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.NextColumn();
|
||||||
|
table.NextColumn();
|
||||||
|
Im.Item.SetNextWidth(Im.ContentRegion.Available.X);
|
||||||
|
if (Im.Input.Text("##newDesignColor"u8, ref _newName, "New Color Name..."u8, InputTextFlags.EnterReturnsTrue))
|
||||||
|
{
|
||||||
|
changeString = _newName;
|
||||||
|
changeValue = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeString.Length > 0)
|
||||||
|
{
|
||||||
|
if (!changeValue.HasValue)
|
||||||
|
colors.DeleteColor(changeString);
|
||||||
|
else
|
||||||
|
colors.SetColor(changeString, changeValue.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool DrawColorButton(Utf8StringHandler<LabelStringHandlerBuffer> tooltip, Rgba32 color, out Rgba32 newColor)
|
||||||
|
{
|
||||||
|
var ret = Im.Color.Editor(tooltip, ref color, ColorEditorFlags.AlphaPreviewHalf | ColorEditorFlags.NoInputs);
|
||||||
|
Im.Tooltip.OnHover(ref tooltip);
|
||||||
|
newColor = color;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.UnlocksTab;
|
namespace Glamourer.Gui.Tabs.UnlocksTab;
|
||||||
|
|
||||||
public class UnlockOverview(
|
public sealed class UnlockOverview(
|
||||||
ItemManager items,
|
ItemManager items,
|
||||||
CustomizeService customizations,
|
CustomizeService customizations,
|
||||||
ItemUnlockManager itemUnlocks,
|
ItemUnlockManager itemUnlocks,
|
||||||
|
|
@ -21,7 +21,7 @@ public class UnlockOverview(
|
||||||
CodeService codes,
|
CodeService codes,
|
||||||
JobService jobs,
|
JobService jobs,
|
||||||
FavoriteManager favorites,
|
FavoriteManager favorites,
|
||||||
PenumbraService penumbra)
|
PenumbraService penumbra) : IUiService
|
||||||
{
|
{
|
||||||
private static readonly Vector4 UnavailableTint = new(0.3f, 0.3f, 0.3f, 1.0f);
|
private static readonly Vector4 UnavailableTint = new(0.3f, 0.3f, 0.3f, 1.0f);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.UnlocksTab;
|
namespace Glamourer.Gui.Tabs.UnlocksTab;
|
||||||
|
|
||||||
public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>
|
public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>, IUiService
|
||||||
{
|
{
|
||||||
private readonly JobService _jobs;
|
private readonly JobService _jobs;
|
||||||
private readonly ItemManager _items;
|
private readonly ItemManager _items;
|
||||||
|
|
@ -554,16 +554,17 @@ public sealed class UnlockTable : TableBase<UnlockCacheItem, UnlockTable.Cache>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnItemUnlock(ObjectUnlocked.Type type, uint id, DateTimeOffset timestamp)
|
private void OnItemUnlock(in ObjectUnlocked.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (type is not ObjectUnlocked.Type.Item)
|
if (arguments.Type is not ObjectUnlocked.Type.Item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FilterDirty = true;
|
FilterDirty = true;
|
||||||
SortDirty = true;
|
SortDirty = true;
|
||||||
|
var id = arguments.Id;
|
||||||
var idx = UnfilteredItems.IndexOf(i => i.Item.ItemId == id);
|
var idx = UnfilteredItems.IndexOf(i => i.Item.ItemId == id);
|
||||||
if (idx >= 0)
|
if (idx >= 0)
|
||||||
UpdateSingleItem(idx, UnfilteredItems[idx] with { UnlockTimestamp = timestamp }, false);
|
UpdateSingleItem(idx, UnfilteredItems[idx] with { UnlockTimestamp = arguments.Timestamp }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
@ -13,13 +13,19 @@ namespace Glamourer.Interop;
|
||||||
/// Changes in Race, body type or Gender are probably ignored.
|
/// Changes in Race, body type or Gender are probably ignored.
|
||||||
/// This operates on draw objects, not game objects.
|
/// This operates on draw objects, not game objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class ChangeCustomizeService : EventWrapperRef2<Model, CustomizeArray, ChangeCustomizeService.Priority>
|
public sealed unsafe class ChangeCustomizeService : EventBase<ChangeCustomizeService.Arguments, ChangeCustomizeService.Priority>
|
||||||
{
|
{
|
||||||
private readonly PenumbraReloaded _penumbraReloaded;
|
private readonly PenumbraReloaded _penumbraReloaded;
|
||||||
private readonly IGameInteropProvider _interop;
|
private readonly IGameInteropProvider _interop;
|
||||||
private readonly delegate* unmanaged<Human*, byte*, bool, bool> _original;
|
private readonly delegate* unmanaged<Human*, byte*, bool, bool> _original;
|
||||||
private readonly Post _postEvent = new();
|
private readonly Post _postEvent;
|
||||||
|
|
||||||
|
public ref struct Arguments(Model model, ref CustomizeArray customize)
|
||||||
|
{
|
||||||
|
public readonly Model Model = model;
|
||||||
|
public ref CustomizeArray Customize = ref customize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary> Check whether we in a manual customize update, in which case we need to not toggle certain flags. </summary>
|
/// <summary> Check whether we in a manual customize update, in which case we need to not toggle certain flags. </summary>
|
||||||
public static readonly InMethodChecker InUpdate = new();
|
public static readonly InMethodChecker InUpdate = new();
|
||||||
|
|
@ -30,8 +36,8 @@ public unsafe class ChangeCustomizeService : EventWrapperRef2<Model, CustomizeAr
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangeCustomizeService(PenumbraReloaded penumbraReloaded, IGameInteropProvider interop)
|
public ChangeCustomizeService(PenumbraReloaded penumbraReloaded, IGameInteropProvider interop, Logger log)
|
||||||
: base("ChangeCustomize")
|
: base("ChangeCustomize", log)
|
||||||
{
|
{
|
||||||
_penumbraReloaded = penumbraReloaded;
|
_penumbraReloaded = penumbraReloaded;
|
||||||
_interop = interop;
|
_interop = interop;
|
||||||
|
|
@ -39,6 +45,7 @@ public unsafe class ChangeCustomizeService : EventWrapperRef2<Model, CustomizeAr
|
||||||
_original = Human.MemberFunctionPointers.UpdateDrawData;
|
_original = Human.MemberFunctionPointers.UpdateDrawData;
|
||||||
interop.InitializeFromAttributes(this);
|
interop.InitializeFromAttributes(this);
|
||||||
_penumbraReloaded.Subscribe(Restore, PenumbraReloaded.Priority.ChangeCustomizeService);
|
_penumbraReloaded.Subscribe(Restore, PenumbraReloaded.Priority.ChangeCustomizeService);
|
||||||
|
_postEvent = new Post(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool _)
|
protected override void Dispose(bool _)
|
||||||
|
|
@ -81,20 +88,20 @@ public unsafe class ChangeCustomizeService : EventWrapperRef2<Model, CustomizeAr
|
||||||
private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment)
|
private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment)
|
||||||
{
|
{
|
||||||
if (!InUpdate.InMethod)
|
if (!InUpdate.InMethod)
|
||||||
Invoke(human, ref *(CustomizeArray*)data);
|
Invoke(new Arguments(human, ref *(CustomizeArray*)data));
|
||||||
|
|
||||||
var ret = _changeCustomizeHook.Original(human, data, skipEquipment);
|
var ret = _changeCustomizeHook.Original(human, data, skipEquipment);
|
||||||
_postEvent.Invoke(human);
|
_postEvent.Invoke(human);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Subscribe(Action<Model> action, Post.Priority priority)
|
public void Subscribe(InAction<Model> action, Post.Priority priority)
|
||||||
=> _postEvent.Subscribe(action, priority);
|
=> _postEvent.Subscribe(action, priority);
|
||||||
|
|
||||||
public void Unsubscribe(Action<Model> action)
|
public void Unsubscribe(InAction<Model> action)
|
||||||
=> _postEvent.Unsubscribe(action);
|
=> _postEvent.Unsubscribe(action);
|
||||||
|
|
||||||
public sealed class Post() : EventWrapper<Model, Post.Priority>(nameof(ChangeCustomizeService) + '.' + nameof(Post))
|
public sealed class Post(Logger log) : EventBase<Model, Post.Priority>(nameof(ChangeCustomizeService) + '.' + nameof(Post), log)
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,14 @@ using Glamourer.Config;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public class ContextMenuService : IDisposable
|
public sealed class ContextMenuService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
public const int ChatLogContextItemId = 0x958;
|
public const int ChatLogContextItemId = 0x958;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,24 +2,16 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Event;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using OtterGui.Classes;
|
using Luna;
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary> Triggered when the crest visibility is updated on a model. </summary>
|
||||||
/// Triggered when the crest visibility is updated on a model.
|
public sealed unsafe class CrestService : EventBase<CrestService.Arguments, CrestService.Priority>
|
||||||
/// <list type="number">
|
|
||||||
/// <item>Parameter is the model with an update. </item>
|
|
||||||
/// <item>Parameter is the equipment slot changed. </item>
|
|
||||||
/// <item>Parameter is whether the crest will be shown. </item>
|
|
||||||
/// </list>
|
|
||||||
/// </summary>
|
|
||||||
public sealed unsafe class CrestService : EventWrapperRef3<Actor, CrestFlag, bool, CrestService.Priority>
|
|
||||||
{
|
{
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
@ -27,8 +19,20 @@ public sealed unsafe class CrestService : EventWrapperRef3<Actor, CrestFlag, boo
|
||||||
StateListener = 0,
|
StateListener = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public CrestService(IGameInteropProvider interop)
|
public ref struct Arguments(Actor actor, CrestFlag slot, ref bool value)
|
||||||
: base(nameof(CrestService))
|
{
|
||||||
|
/// <summary> The game object with a crest update. </summary>
|
||||||
|
public readonly Actor Actor = actor;
|
||||||
|
|
||||||
|
/// <summary> The equipment slot changed. </summary>
|
||||||
|
public readonly CrestFlag Slot = slot;
|
||||||
|
|
||||||
|
/// <summary> The new value. </summary>
|
||||||
|
public ref bool Value = ref value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrestService(IGameInteropProvider interop, Logger log)
|
||||||
|
: base(nameof(CrestService), log)
|
||||||
{
|
{
|
||||||
interop.InitializeFromAttributes(this);
|
interop.InitializeFromAttributes(this);
|
||||||
_humanSetFreeCompanyCrestVisibleOnSlot =
|
_humanSetFreeCompanyCrestVisibleOnSlot =
|
||||||
|
|
@ -76,7 +80,7 @@ public sealed unsafe class CrestService : EventWrapperRef3<Actor, CrestFlag, boo
|
||||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||||
{
|
{
|
||||||
var newValue = ((CrestFlag)crestFlags).HasFlag(slot);
|
var newValue = ((CrestFlag)crestFlags).HasFlag(slot);
|
||||||
Invoke(actor, slot, ref newValue);
|
Invoke(new Arguments(actor, slot, ref newValue));
|
||||||
crestFlags = (byte)(newValue ? crestFlags | (byte)slot : crestFlags & (byte)~slot);
|
crestFlags = (byte)(newValue ? crestFlags | (byte)slot : crestFlags & (byte)~slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +102,7 @@ public sealed unsafe class CrestService : EventWrapperRef3<Actor, CrestFlag, boo
|
||||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||||
{
|
{
|
||||||
var newValue = ((CrestFlag)flags).HasFlag(slot);
|
var newValue = ((CrestFlag)flags).HasFlag(slot);
|
||||||
Invoke(actor, slot, ref newValue);
|
Invoke(new Arguments(actor, slot, ref newValue));
|
||||||
flags = (byte)(newValue ? flags | (byte)slot : flags & (byte)~slot);
|
flags = (byte)(newValue ? flags | (byte)slot : flags & (byte)~slot);
|
||||||
}
|
}
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public class ImportService(CustomizeService customizations, IDragDropManager dragDropManager, ItemManager items)
|
public sealed class ImportService(CustomizeService customizations, IDragDropManager dragDropManager, ItemManager items) : IService
|
||||||
{
|
{
|
||||||
public void CreateDatSource()
|
public void CreateDatSource()
|
||||||
=> dragDropManager.CreateImGuiSource("DatDragger", m => m.Files.Count == 1 && m.Extensions.Contains(".dat"), m =>
|
=> dragDropManager.CreateImGuiSource("DatDragger", m => m.Files.Count == 1 && m.Extensions.Contains(".dat"), m =>
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,12 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService
|
||||||
public InventoryService(MovedEquipment movedItemsEvent, IGameInteropProvider interop, EquippedGearset gearsetEvent)
|
public InventoryService(MovedEquipment movedItemsEvent, IGameInteropProvider interop, EquippedGearset gearsetEvent)
|
||||||
{
|
{
|
||||||
_movedItemsEvent = movedItemsEvent;
|
_movedItemsEvent = movedItemsEvent;
|
||||||
_gearsetEvent = gearsetEvent;
|
_gearsetEvent = gearsetEvent;
|
||||||
|
|
||||||
_moveItemHook = interop.HookFromAddress<MoveItemDelegate>((nint)InventoryManager.MemberFunctionPointers.MoveItemSlot, MoveItemDetour);
|
_moveItemHook = interop.HookFromAddress<MoveItemDelegate>((nint)InventoryManager.MemberFunctionPointers.MoveItemSlot, MoveItemDetour);
|
||||||
_equipGearsetHook = interop.HookFromAddress<EquipGearsetInternalDelegate>((nint)RaptureGearsetModule.MemberFunctionPointers.EquipGearsetInternal, EquipGearSetDetour);
|
_equipGearsetHook =
|
||||||
|
interop.HookFromAddress<EquipGearsetInternalDelegate>((nint)RaptureGearsetModule.MemberFunctionPointers.EquipGearsetInternal,
|
||||||
|
EquipGearSetDetour);
|
||||||
|
|
||||||
_moveItemHook.Enable();
|
_moveItemHook.Enable();
|
||||||
_equipGearsetHook.Enable();
|
_equipGearsetHook.Enable();
|
||||||
|
|
@ -36,14 +38,14 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService
|
||||||
|
|
||||||
private delegate nint EquipGearsetInternalDelegate(RaptureGearsetModule* module, uint gearsetId, byte glamourPlateId);
|
private delegate nint EquipGearsetInternalDelegate(RaptureGearsetModule* module, uint gearsetId, byte glamourPlateId);
|
||||||
|
|
||||||
private readonly Hook<EquipGearsetInternalDelegate> _equipGearsetHook = null!;
|
private readonly Hook<EquipGearsetInternalDelegate> _equipGearsetHook;
|
||||||
|
|
||||||
private nint EquipGearSetDetour(RaptureGearsetModule* module, uint gearsetId, byte glamourPlateId)
|
private nint EquipGearSetDetour(RaptureGearsetModule* module, uint gearsetId, byte glamourPlateId)
|
||||||
{
|
{
|
||||||
var prior = module->CurrentGearsetIndex;
|
var prior = module->CurrentGearsetIndex;
|
||||||
var ret = _equipGearsetHook.Original(module, gearsetId, glamourPlateId);
|
var ret = _equipGearsetHook.Original(module, gearsetId, glamourPlateId);
|
||||||
var set = module->GetGearset((int)gearsetId);
|
var set = module->GetGearset((int)gearsetId);
|
||||||
_gearsetEvent.Invoke(new ByteString(set->Name).ToString(), (int)gearsetId, prior, glamourPlateId, set->ClassJob);
|
_gearsetEvent.Invoke(new EquippedGearset.Arguments(new ByteString(set->Name), (int)gearsetId, prior, glamourPlateId, set->ClassJob));
|
||||||
Glamourer.Log.Verbose($"[InventoryService] Applied gear set {gearsetId} with glamour plate {glamourPlateId} (Returned {ret})");
|
Glamourer.Log.Verbose($"[InventoryService] Applied gear set {gearsetId} with glamour plate {glamourPlateId} (Returned {ret})");
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -111,7 +113,7 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService
|
||||||
Add(EquipSlot.LFinger, ref entry->Items[12]);
|
Add(EquipSlot.LFinger, ref entry->Items[12]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_movedItemsEvent.Invoke(_itemList.ToArray());
|
_movedItemsEvent.Invoke(new MovedEquipment.Arguments(_itemList.ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -130,25 +132,15 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
var ret = _moveItemHook.Original(manager, sourceContainer, sourceSlot, targetContainer, targetSlot, unk);
|
var ret = _moveItemHook.Original(manager, sourceContainer, sourceSlot, targetContainer, targetSlot, unk);
|
||||||
Glamourer.Log.Excessive($"[InventoryService] Moved {sourceContainer} {sourceSlot} {targetContainer} {targetSlot} (Returned {ret})");
|
Glamourer.Log.Excessive($"[InventoryService] Moved {sourceContainer} {sourceSlot} {targetContainer} {targetSlot} (Returned {ret})");
|
||||||
if (ret == 0)
|
if (ret is 0)
|
||||||
{
|
{
|
||||||
if (InvokeSource(sourceContainer, sourceSlot, out var source))
|
if (InvokeSource(sourceContainer, sourceSlot, out var source))
|
||||||
if (InvokeTarget(manager, targetContainer, targetSlot, out var target))
|
if (InvokeTarget(manager, targetContainer, targetSlot, out var target))
|
||||||
_movedItemsEvent.Invoke(new[]
|
_movedItemsEvent.Invoke(new MovedEquipment.Arguments(source, target));
|
||||||
{
|
|
||||||
source,
|
|
||||||
target,
|
|
||||||
});
|
|
||||||
else
|
else
|
||||||
_movedItemsEvent.Invoke(new[]
|
_movedItemsEvent.Invoke(new MovedEquipment.Arguments(source));
|
||||||
{
|
|
||||||
source,
|
|
||||||
});
|
|
||||||
else if (InvokeTarget(manager, targetContainer, targetSlot, out var target))
|
else if (InvokeTarget(manager, targetContainer, targetSlot, out var target))
|
||||||
_movedItemsEvent.Invoke(new[]
|
_movedItemsEvent.Invoke(new MovedEquipment.Arguments(target));
|
||||||
{
|
|
||||||
target,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Dalamud.Hooking;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
@ -9,7 +10,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public class JobService : IDisposable
|
public sealed class JobService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly nint _characterDataOffset;
|
private readonly nint _characterDataOffset;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,11 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
=> _event.Unsubscribe(OnPrepareColorSet);
|
=> _event.Unsubscribe(OnPrepareColorSet);
|
||||||
|
|
||||||
private void OnPrepareColorSet(CharacterBase* characterBase, MaterialResourceHandle* material, ref StainIds stain, ref nint ret)
|
private void OnPrepareColorSet(in PrepareColorSet.Arguments arguments)
|
||||||
{
|
{
|
||||||
var actor = _penumbra.GameObjectFromDrawObject(characterBase);
|
var actor = _penumbra.GameObjectFromDrawObject(arguments.Model);
|
||||||
var validType = FindType(characterBase, actor, out var type);
|
var validType = FindType(arguments.Model.AsCharacterBase, actor, out var type);
|
||||||
var (slotId, materialId) = FindMaterial(characterBase, material);
|
var (slotId, materialId) = FindMaterial(arguments.Model.AsCharacterBase, arguments.Handle);
|
||||||
|
|
||||||
if (!validType
|
if (!validType
|
||||||
|| type is not MaterialValueIndex.DrawObjectType.Human && slotId > 0
|
|| type is not MaterialValueIndex.DrawObjectType.Human && slotId > 0
|
||||||
|
|
@ -55,19 +55,19 @@ public sealed unsafe class MaterialManager : IRequiredService, IDisposable
|
||||||
if (values.Length == 0)
|
if (values.Length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!PrepareColorSet.TryGetColorTable(material, stain, out var baseColorSet))
|
if (!PrepareColorSet.TryGetColorTable(arguments.Handle, arguments.Ids, out var baseColorSet))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var drawData = type switch
|
var drawData = type switch
|
||||||
{
|
{
|
||||||
MaterialValueIndex.DrawObjectType.Human => GetTempSlot((Human*)characterBase, (HumanSlot)slotId),
|
MaterialValueIndex.DrawObjectType.Human => GetTempSlot(arguments.Model.AsHuman, (HumanSlot)slotId),
|
||||||
_ => GetTempSlot((Weapon*)characterBase),
|
_ => GetTempSlot(arguments.Model.AsWeapon),
|
||||||
};
|
};
|
||||||
var mode = PrepareColorSet.GetMode(material);
|
var mode = PrepareColorSet.GetMode(arguments.Handle);
|
||||||
UpdateMaterialValues(state, values, drawData, ref baseColorSet, mode);
|
UpdateMaterialValues(state, values, drawData, ref baseColorSet, mode);
|
||||||
|
|
||||||
if (MaterialService.GenerateNewColorTable(baseColorSet, out var texture))
|
if (MaterialService.GenerateNewColorTable(baseColorSet, out var texture))
|
||||||
ret = (nint)texture;
|
arguments.ReturnValue = (nint)texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Update and apply the glamourer state of an actor according to the application sources when updated by the game. </summary>
|
/// <summary> Update and apply the glamourer state of an actor according to the application sources when updated by the game. </summary>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Files.MaterialStructs;
|
using Penumbra.GameData.Files.MaterialStructs;
|
||||||
|
|
@ -13,7 +12,7 @@ using Penumbra.GameData.Structs;
|
||||||
namespace Glamourer.Interop.Material;
|
namespace Glamourer.Interop.Material;
|
||||||
|
|
||||||
public sealed unsafe class PrepareColorSet
|
public sealed unsafe class PrepareColorSet
|
||||||
: EventWrapperPtr12Ref34<CharacterBase, MaterialResourceHandle, StainIds, nint, PrepareColorSet.Priority>, IHookService
|
: EventBase<PrepareColorSet.Arguments, PrepareColorSet.Priority>, IHookService
|
||||||
{
|
{
|
||||||
private readonly UpdateColorSets _updateColorSets;
|
private readonly UpdateColorSets _updateColorSets;
|
||||||
|
|
||||||
|
|
@ -23,11 +22,19 @@ public sealed unsafe class PrepareColorSet
|
||||||
MaterialManager = 0,
|
MaterialManager = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrepareColorSet(HookManager hooks, UpdateColorSets updateColorSets)
|
public ref struct Arguments(Model model, MaterialResourceHandle* handle, ref StainIds ids, ref nint returnValue)
|
||||||
: base("Prepare Color Set ")
|
{
|
||||||
|
public readonly Model Model = model;
|
||||||
|
public readonly MaterialResourceHandle* Handle = handle;
|
||||||
|
public ref StainIds Ids = ref ids;
|
||||||
|
public ref nint ReturnValue = ref returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrepareColorSet(HookManager hooks, UpdateColorSets updateColorSets, Logger log)
|
||||||
|
: base("Prepare Color Set", log)
|
||||||
{
|
{
|
||||||
_updateColorSets = updateColorSets;
|
_updateColorSets = updateColorSets;
|
||||||
_task = hooks.CreateHook<Delegate>(Name, Sigs.PrepareColorSet, Detour, true);
|
_task = hooks.CreateHook<Delegate>(Name, Sigs.PrepareColorSet, Detour, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Task<Hook<Delegate>> _task;
|
private readonly Task<Hook<Delegate>> _task;
|
||||||
|
|
@ -64,7 +71,7 @@ public sealed unsafe class PrepareColorSet
|
||||||
|
|
||||||
var ret = nint.Zero;
|
var ret = nint.Zero;
|
||||||
var stainIds = new StainIds(stainId1, stainId2);
|
var stainIds = new StainIds(stainId1, stainId2);
|
||||||
Invoke(characterBase.AsCharacterBase, material, ref stainIds, ref ret);
|
Invoke(new Arguments(characterBase.AsCharacterBase, material, ref stainIds, ref ret));
|
||||||
if (ret != nint.Zero)
|
if (ret != nint.Zero)
|
||||||
return (Texture*)ret;
|
return (Texture*)ret;
|
||||||
|
|
||||||
|
|
@ -74,7 +81,7 @@ public sealed unsafe class PrepareColorSet
|
||||||
public static bool TryGetColorTable(MaterialResourceHandle* material, StainIds stainIds,
|
public static bool TryGetColorTable(MaterialResourceHandle* material, StainIds stainIds,
|
||||||
out ColorTable.Table table)
|
out ColorTable.Table table)
|
||||||
{
|
{
|
||||||
if (material->DataSet == null || material->DataSetSize < sizeof(ColorTable.Table) || !material->HasColorTable)
|
if (material->DataSet is null || material->DataSetSize < sizeof(ColorTable.Table) || !material->HasColorTable)
|
||||||
{
|
{
|
||||||
table = default;
|
table = default;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -83,10 +90,10 @@ public sealed unsafe class PrepareColorSet
|
||||||
var newTable = *(ColorTable.Table*)material->DataSet;
|
var newTable = *(ColorTable.Table*)material->DataSet;
|
||||||
if (GetDyeTable(material, out var dyeTable))
|
if (GetDyeTable(material, out var dyeTable))
|
||||||
{
|
{
|
||||||
if (stainIds.Stain1.Id != 0)
|
if (stainIds.Stain1.Id is not 0)
|
||||||
material->ReadStainingTemplate(dyeTable, stainIds.Stain1.Id, (Half*)&newTable, 0);
|
material->ReadStainingTemplate(dyeTable, stainIds.Stain1.Id, (Half*)&newTable, 0);
|
||||||
|
|
||||||
if (stainIds.Stain2.Id != 0)
|
if (stainIds.Stain2.Id is not 0)
|
||||||
material->ReadStainingTemplate(dyeTable, stainIds.Stain2.Id, (Half*)&newTable, 1);
|
material->ReadStainingTemplate(dyeTable, stainIds.Stain2.Id, (Half*)&newTable, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public unsafe class MetaService : IDisposable
|
public sealed unsafe class MetaService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly HeadGearVisibilityChanged _headGearEvent;
|
private readonly HeadGearVisibilityChanged _headGearEvent;
|
||||||
private readonly WeaponVisibilityChanged _weaponEvent;
|
private readonly WeaponVisibilityChanged _weaponEvent;
|
||||||
|
|
@ -75,8 +76,8 @@ public unsafe class MetaService : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor actor = drawData->OwnerObject;
|
Actor actor = drawData->OwnerObject;
|
||||||
var v = value == 0;
|
var v = value is 0;
|
||||||
_headGearEvent.Invoke(actor, ref v);
|
_headGearEvent.Invoke(new HeadGearVisibilityChanged.Arguments(actor, ref v));
|
||||||
value = (byte)(v ? 0 : 1);
|
value = (byte)(v ? 0 : 1);
|
||||||
Glamourer.Log.Verbose($"[MetaService] Hide Hat triggered with 0x{(nint)drawData:X} {id} {value} for {actor.Utf8Name}.");
|
Glamourer.Log.Verbose($"[MetaService] Hide Hat triggered with 0x{(nint)drawData:X} {id} {value} for {actor.Utf8Name}.");
|
||||||
_hideHatGearHook.Original(drawData, id, value);
|
_hideHatGearHook.Original(drawData, id, value);
|
||||||
|
|
@ -85,8 +86,8 @@ public unsafe class MetaService : IDisposable
|
||||||
private void HideWeaponsDetour(DrawDataContainer* drawData, byte value)
|
private void HideWeaponsDetour(DrawDataContainer* drawData, byte value)
|
||||||
{
|
{
|
||||||
Actor actor = drawData->OwnerObject;
|
Actor actor = drawData->OwnerObject;
|
||||||
var v = value == 0;
|
var v = value is 0;
|
||||||
_weaponEvent.Invoke(actor, ref v);
|
_weaponEvent.Invoke(new WeaponVisibilityChanged.Arguments(actor, ref v));
|
||||||
Glamourer.Log.Verbose($"[MetaService] Hide Weapon triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
Glamourer.Log.Verbose($"[MetaService] Hide Weapon triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
||||||
_hideWeaponsHook.Original(drawData, (byte)(v ? 0 : 1));
|
_hideWeaponsHook.Original(drawData, (byte)(v ? 0 : 1));
|
||||||
}
|
}
|
||||||
|
|
@ -94,8 +95,8 @@ public unsafe class MetaService : IDisposable
|
||||||
private void ToggleVisorDetour(DrawDataContainer* drawData, byte value)
|
private void ToggleVisorDetour(DrawDataContainer* drawData, byte value)
|
||||||
{
|
{
|
||||||
Actor actor = drawData->OwnerObject;
|
Actor actor = drawData->OwnerObject;
|
||||||
var v = value != 0;
|
var v = value is not 0;
|
||||||
_visorEvent.Invoke(actor.Model, true, ref v);
|
_visorEvent.Invoke(new VisorStateChanged.Arguments(actor.Model, true, ref v));
|
||||||
Glamourer.Log.Verbose($"[MetaService] Toggle Visor triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
Glamourer.Log.Verbose($"[MetaService] Toggle Visor triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
||||||
_toggleVisorHook.Original(drawData, (byte)(v ? 1 : 0));
|
_toggleVisorHook.Original(drawData, (byte)(v ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Glamourer.Api.Enums;
|
using Glamourer.Api.Enums;
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using Glamourer.Designs.History;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Luna;
|
using Luna;
|
||||||
|
|
@ -10,7 +9,7 @@ using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Interop.Penumbra;
|
namespace Glamourer.Interop.Penumbra;
|
||||||
|
|
||||||
public class PenumbraAutoRedraw : IDisposable, IRequiredService
|
public sealed class PenumbraAutoRedraw : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private const int WaitFrames = 5;
|
private const int WaitFrames = 5;
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
|
|
@ -46,13 +45,13 @@ public class PenumbraAutoRedraw : IDisposable, IRequiredService
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ConcurrentQueue<(ActorState, Action, int)> _actions = [];
|
private readonly ConcurrentQueue<(ActorState, Action, int)> _actions = [];
|
||||||
private readonly OtterGui.Classes.ConcurrentSet<ActorState> _skips = [];
|
private readonly ConcurrentSet<ActorState> _skips = [];
|
||||||
private DateTime _frame;
|
private DateTime _frame;
|
||||||
|
|
||||||
private void OnStateChanged(StateChangeType type, StateSource source, ActorState state, ActorData _1, ITransaction? _2)
|
private void OnStateChanged(in StateChanged.Arguments arguments)
|
||||||
{
|
{
|
||||||
if (type is StateChangeType.Design && source.IsIpc())
|
if (arguments.Type is StateChangeType.Design && arguments.Source.IsIpc())
|
||||||
_skips.TryAdd(state);
|
_skips.TryAdd(arguments.State);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFramework(IFramework _)
|
private void OnFramework(IFramework _)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public readonly record struct ModSettings(Dictionary<string, List<string>> Setti
|
||||||
=> new();
|
=> new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PenumbraService : IDisposable
|
public sealed class PenumbraService : IDisposable, IService
|
||||||
{
|
{
|
||||||
public const int RequiredPenumbraBreakingVersion = 5;
|
public const int RequiredPenumbraBreakingVersion = 5;
|
||||||
public const int RequiredPenumbraFeatureVersion = 13;
|
public const int RequiredPenumbraFeatureVersion = 13;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Character = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
|
using Character = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
|
||||||
|
|
@ -13,7 +14,7 @@ using CustomizeIndex = Dalamud.Game.ClientState.Objects.Enums.CustomizeIndex;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public unsafe class ScalingService : IDisposable
|
public sealed unsafe class ScalingService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly ActorManager _actors;
|
private readonly ActorManager _actors;
|
||||||
private readonly StateManager _state;
|
private readonly StateManager _state;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Network;
|
using FFXIVClientStructs.FFXIV.Client.Game.Network;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
@ -12,7 +13,7 @@ using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public unsafe class UpdateSlotService : IDisposable
|
public sealed unsafe class UpdateSlotService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
public readonly EquipSlotUpdating EquipSlotUpdatingEvent;
|
public readonly EquipSlotUpdating EquipSlotUpdatingEvent;
|
||||||
public readonly BonusSlotUpdating BonusSlotUpdatingEvent;
|
public readonly BonusSlotUpdating BonusSlotUpdatingEvent;
|
||||||
|
|
@ -97,18 +98,18 @@ public unsafe class UpdateSlotService : IDisposable
|
||||||
{
|
{
|
||||||
var slot = slotIdx.ToEquipSlot();
|
var slot = slotIdx.ToEquipSlot();
|
||||||
var returnValue = ulong.MaxValue;
|
var returnValue = ulong.MaxValue;
|
||||||
EquipSlotUpdatingEvent.Invoke(drawObject, slot, ref *data, ref returnValue);
|
EquipSlotUpdatingEvent.Invoke(new EquipSlotUpdating.Arguments(drawObject, slot, ref *data, ref returnValue));
|
||||||
Glamourer.Log.Excessive($"[FlagSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X}).");
|
Glamourer.Log.Excessive($"[FlagSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X}).");
|
||||||
return returnValue == ulong.MaxValue ? _flagSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue;
|
return returnValue is ulong.MaxValue ? _flagSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong FlagBonusSlotForUpdateDetour(nint drawObject, uint slotIdx, CharacterArmor* data)
|
private ulong FlagBonusSlotForUpdateDetour(nint drawObject, uint slotIdx, CharacterArmor* data)
|
||||||
{
|
{
|
||||||
var slot = slotIdx.ToBonusSlot();
|
var slot = slotIdx.ToBonusSlot();
|
||||||
var returnValue = ulong.MaxValue;
|
var returnValue = ulong.MaxValue;
|
||||||
BonusSlotUpdatingEvent.Invoke(drawObject, slot, ref *data, ref returnValue);
|
BonusSlotUpdatingEvent.Invoke(new BonusSlotUpdating.Arguments(drawObject, slot, ref *data, ref returnValue));
|
||||||
Glamourer.Log.Excessive($"[FlagBonusSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X}).");
|
Glamourer.Log.Excessive($"[FlagBonusSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X}).");
|
||||||
return returnValue == ulong.MaxValue ? _flagBonusSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue;
|
return returnValue is ulong.MaxValue ? _flagBonusSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong FlagSlotForUpdateInterop(Model drawObject, EquipSlot slot, CharacterArmor armor)
|
private ulong FlagSlotForUpdateInterop(Model drawObject, EquipSlot slot, CharacterArmor armor)
|
||||||
|
|
@ -120,7 +121,7 @@ public unsafe class UpdateSlotService : IDisposable
|
||||||
{
|
{
|
||||||
var ret = _loadGearsetDataHook.Original(drawDataContainer, gearsetData);
|
var ret = _loadGearsetDataHook.Original(drawDataContainer, gearsetData);
|
||||||
var drawObject = drawDataContainer->OwnerObject->DrawObject;
|
var drawObject = drawDataContainer->OwnerObject->DrawObject;
|
||||||
GearsetDataLoadedEvent.Invoke(drawDataContainer->OwnerObject, drawObject);
|
GearsetDataLoadedEvent.Invoke(new GearsetDataLoaded.Arguments(drawDataContainer->OwnerObject, drawObject));
|
||||||
Glamourer.Log.Excessive($"[LoadAllEquipmentDetour] GearsetItemData: {FormatGearsetItemDataStruct(*gearsetData)}");
|
Glamourer.Log.Excessive($"[LoadAllEquipmentDetour] GearsetItemData: {FormatGearsetItemDataStruct(*gearsetData)}");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public unsafe class VieraEarService : IDisposable
|
public unsafe sealed class VieraEarService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly PenumbraReloaded _penumbra;
|
private readonly PenumbraReloaded _penumbra;
|
||||||
private readonly IGameInteropProvider _interop;
|
private readonly IGameInteropProvider _interop;
|
||||||
|
|
@ -57,10 +58,10 @@ public unsafe class VieraEarService : IDisposable
|
||||||
private void SetupVieraEarDetour(DrawDataContainer* drawData, byte value)
|
private void SetupVieraEarDetour(DrawDataContainer* drawData, byte value)
|
||||||
{
|
{
|
||||||
Actor actor = drawData->OwnerObject;
|
Actor actor = drawData->OwnerObject;
|
||||||
var originalOn = value != 0;
|
var originalOn = value is not 0;
|
||||||
var on = originalOn;
|
var on = originalOn;
|
||||||
// Invoke an event that can change the requested value
|
// Invoke an event that can change the requested value
|
||||||
Event.Invoke(actor, ref on);
|
Event.Invoke(new VieraEarStateChanged.Arguments(actor, ref on));
|
||||||
|
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
$"[SetVieraEarState] Invoked from game on 0x{actor.Address:X} switching to {on} (original {originalOn} from {value}).");
|
$"[SetVieraEarState] Invoked from game on 0x{actor.Address:X} switching to {on} (original {originalOn} from {value}).");
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public class VisorService : IDisposable
|
public sealed class VisorService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly PenumbraReloaded _penumbra;
|
private readonly PenumbraReloaded _penumbra;
|
||||||
private readonly IGameInteropProvider _interop;
|
private readonly IGameInteropProvider _interop;
|
||||||
|
|
@ -58,11 +59,11 @@ public class VisorService : IDisposable
|
||||||
|
|
||||||
private void SetupVisorDetour(nint human, ushort modelId, byte value)
|
private void SetupVisorDetour(nint human, ushort modelId, byte value)
|
||||||
{
|
{
|
||||||
var originalOn = value != 0;
|
var originalOn = value is not 0;
|
||||||
var on = originalOn;
|
var on = originalOn;
|
||||||
// Invoke an event that can change the requested value
|
// Invoke an event that can change the requested value
|
||||||
// and also control whether the function should be called at all.
|
// and also control whether the function should be called at all.
|
||||||
Event.Invoke(human, false, ref on);
|
Event.Invoke(new VisorStateChanged.Arguments(human, false, ref on));
|
||||||
|
|
||||||
Glamourer.Log.Verbose(
|
Glamourer.Log.Verbose(
|
||||||
$"[SetVisorState] Invoked from game on 0x{human:X} switching to {on} (original {originalOn} from {value} with {modelId}).");
|
$"[SetVisorState] Invoked from game on 0x{human:X} switching to {on} (original {originalOn} from {value} with {modelId}).");
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,14 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Interop;
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
public unsafe class WeaponService : IDisposable
|
public sealed unsafe class WeaponService : IDisposable, IRequiredService
|
||||||
{
|
{
|
||||||
private readonly WeaponLoading _event;
|
private readonly WeaponLoading _event;
|
||||||
private readonly ThreadLocal<bool> _inUpdate = new(() => false);
|
private readonly ThreadLocal<bool> _inUpdate = new(() => false);
|
||||||
|
|
@ -59,17 +60,17 @@ public unsafe class WeaponService : IDisposable
|
||||||
var tmpWeapon = weapon;
|
var tmpWeapon = weapon;
|
||||||
// First call the regular function.
|
// First call the regular function.
|
||||||
if (equipSlot is not EquipSlot.Unknown)
|
if (equipSlot is not EquipSlot.Unknown)
|
||||||
_event.Invoke(actor, equipSlot, ref tmpWeapon);
|
_event.Invoke(new WeaponLoading.Arguments(actor, equipSlot, ref tmpWeapon));
|
||||||
// Sage hack for weapons appearing in animations?
|
// Sage hack for weapons appearing in animations?
|
||||||
// Check for weapon value 0 for certain cases (e.g. carbuncles transforming to humans) because that breaks some stuff (weapon hiding?) otherwise.
|
// Check for weapon value 0 for certain cases (e.g. carbuncles transforming to humans) because that breaks some stuff (weapon hiding?) otherwise.
|
||||||
else if (weaponValue == actor.GetMainhand().Value && weaponValue != 0)
|
else if (weaponValue == actor.GetMainhand().Value && weaponValue is not 0)
|
||||||
_event.Invoke(actor, EquipSlot.MainHand, ref tmpWeapon);
|
_event.Invoke(new WeaponLoading.Arguments(actor, EquipSlot.MainHand, ref tmpWeapon));
|
||||||
|
|
||||||
_loadWeaponHook.Original(drawData, slot, weapon.Value, redrawOnEquality, unk2, skipGameObject, unk4, unk5);
|
_loadWeaponHook.Original(drawData, slot, weapon.Value, redrawOnEquality, unk2, skipGameObject, unk4, unk5);
|
||||||
|
|
||||||
if (tmpWeapon.Value != weapon.Value)
|
if (tmpWeapon.Value != weapon.Value)
|
||||||
{
|
{
|
||||||
if (tmpWeapon.Skeleton.Id == 0)
|
if (tmpWeapon.Skeleton.Id is 0)
|
||||||
tmpWeapon.Stains = StainIds.None;
|
tmpWeapon.Stains = StainIds.None;
|
||||||
_loadWeaponHook.Original(drawData, slot, tmpWeapon.Value, 1, unk2, 1, unk4, unk5);
|
_loadWeaponHook.Original(drawData, slot, tmpWeapon.Value, 1, unk2, 1, unk4, unk5);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
public class BackupService(Logger log, FilenameService provider) : BaseBackupService<FilenameService>(log, provider)
|
public sealed class BackupService(Logger log, FilenameService provider) : BaseBackupService<FilenameService>(log, provider)
|
||||||
{
|
{
|
||||||
/// <summary> Collect all relevant files for glamourer configuration. </summary>
|
/// <summary> Collect all relevant files for glamourer configuration. </summary>
|
||||||
private static IReadOnlyList<FileInfo> GlamourerFiles(FilenameService fileNames)
|
private static IReadOnlyList<FileInfo> GlamourerFiles(FilenameService fileNames)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
public class CodeService
|
public sealed class CodeService : IService
|
||||||
{
|
{
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
private readonly SHA256 _hasher = SHA256.Create();
|
private readonly SHA256 _hasher = SHA256.Create();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
|
||||||
using Glamourer.Interop.Penumbra;
|
using Glamourer.Interop.Penumbra;
|
||||||
using Luna;
|
using Luna;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Extensions;
|
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Extensions = OtterGui.Filesystem.Extensions;
|
|
||||||
using Notification = Luna.Notification;
|
using Notification = Luna.Notification;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
@ -31,7 +28,7 @@ public sealed class CollectionOverrideService : IService, ISavable
|
||||||
if (!identifier.IsValid)
|
if (!identifier.IsValid)
|
||||||
identifier = _actors.FromObject(actor.AsObject, out _, true, true, true);
|
identifier = _actors.FromObject(actor.AsObject, out _, true, true, true);
|
||||||
|
|
||||||
return ArrayExtensions.FindFirst(_overrides, p => p.Actor.Matches(identifier), out var ret)
|
return _overrides.FindFirst(p => p.Actor.Matches(identifier), out var ret)
|
||||||
? (ret.CollectionId, ret.DisplayName, true)
|
? (ret.CollectionId, ret.DisplayName, true)
|
||||||
: (_penumbra.GetActorCollection(actor, out var name), name, false);
|
: (_penumbra.GetActorCollection(actor, out var name), name, false);
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +75,7 @@ public sealed class CollectionOverrideService : IService, ISavable
|
||||||
if (idx < 0 || idx >= _overrides.Count)
|
if (idx < 0 || idx >= _overrides.Count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (newCollectionId == Guid.Empty || newDisplayName.Length == 0)
|
if (newCollectionId == Guid.Empty || newDisplayName.Length is 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var current = _overrides[idx];
|
var current = _overrides[idx];
|
||||||
|
|
@ -106,7 +103,7 @@ public sealed class CollectionOverrideService : IService, ISavable
|
||||||
|
|
||||||
public void MoveOverride(int idxFrom, int idxTo)
|
public void MoveOverride(int idxFrom, int idxTo)
|
||||||
{
|
{
|
||||||
if (!Extensions.Move(_overrides, idxFrom, idxTo))
|
if (!_overrides.Move(idxFrom, idxTo))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Glamourer.Log.Debug($"Moved collection override {idxFrom + 1} to {idxTo + 1}.");
|
Glamourer.Log.Debug($"Moved collection override {idxFrom + 1} to {idxTo + 1}.");
|
||||||
|
|
@ -192,7 +189,7 @@ public sealed class CollectionOverrideService : IService, ISavable
|
||||||
|
|
||||||
public void Save(StreamWriter writer)
|
public void Save(StreamWriter writer)
|
||||||
{
|
{
|
||||||
var jObj = new JObject()
|
var jObj = new JObject
|
||||||
{
|
{
|
||||||
["Version"] = Version,
|
["Version"] = Version,
|
||||||
["Overrides"] = SerializeOverrides(),
|
["Overrides"] = SerializeOverrides(),
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,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 SeStringBuilderExtensions = OtterGui.Classes.SeStringBuilderExtensions;
|
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using Glamourer.Gui;
|
using Glamourer.Gui;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
public class ConfigMigrationService(SaveService saveService, FixedDesignMigrator fixedDesignMigrator, BackupService backupService)
|
public sealed class ConfigMigrationService(SaveService saveService, FixedDesignMigrator fixedDesignMigrator, BackupService backupService) : IRequiredService
|
||||||
{
|
{
|
||||||
private Configuration _config = null!;
|
private Configuration _config = null!;
|
||||||
private JObject _data = null!;
|
private JObject _data = null!;
|
||||||
|
|
|
||||||
|
|
@ -142,11 +142,10 @@ public class DesignResolver(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var lower = argument.ToLowerInvariant();
|
|
||||||
// Search for design by name and partial identifier.
|
// Search for design by name and partial identifier.
|
||||||
design = manager.Designs.FirstOrDefault(MatchNameAndIdentifier(lower));
|
design = manager.Designs.FirstOrDefault(MatchNameAndIdentifier(argument));
|
||||||
// Search for design by path, if nothing was found.
|
// Search for design by path, if nothing was found.
|
||||||
if (design is null && designFileSystem.Find(lower, out var child) && child is IFileSystemData<Design> leaf)
|
if (design is null && designFileSystem.Find(argument, out var child) && child is IFileSystemData<Design> leaf)
|
||||||
design = leaf.Value;
|
design = leaf.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,13 +158,13 @@ public class DesignResolver(
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static Func<Design, bool> MatchNameAndIdentifier(string lower)
|
private static Func<Design, bool> MatchNameAndIdentifier(string text)
|
||||||
{
|
{
|
||||||
// Check for names and identifiers, prefer names
|
// Check for names and identifiers, prefer names
|
||||||
if (lower.Length > 3)
|
if (text.Length > 3)
|
||||||
return d => d.Name.Lower == lower || d.Identifier.ToString().StartsWith(lower);
|
return d => string.Equals(d.Name, text, StringComparison.OrdinalIgnoreCase) || d.Identifier.ToString().StartsWith(text, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// Check only for names.
|
// Check only for names.
|
||||||
return d => d.Name.Lower == lower;
|
return d => string.Equals(d.Name, text, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
public class FilenameService(IDalamudPluginInterface pi) : BaseFilePathProvider(pi)
|
public sealed class FilenameService(IDalamudPluginInterface pi) : BaseFilePathProvider(pi)
|
||||||
{
|
{
|
||||||
public readonly string MigrationDesignFileSystem = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json");
|
public readonly string MigrationDesignFileSystem = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json");
|
||||||
public readonly string MigrationDesignFile = Path.Combine(pi.ConfigDirectory.FullName, "Designs.json");
|
public readonly string MigrationDesignFile = Path.Combine(pi.ConfigDirectory.FullName, "Designs.json");
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Dalamud.Plugin.Services;
|
||||||
using Glamourer.Config;
|
using Glamourer.Config;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
using Luna;
|
||||||
using Penumbra.GameData.Data;
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.DataContainers;
|
using Penumbra.GameData.DataContainers;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
@ -10,7 +11,7 @@ using Race = Penumbra.GameData.Enums.Race;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
public class ItemManager
|
public sealed class ItemManager : IService
|
||||||
{
|
{
|
||||||
public const string Nothing = EquipItem.Nothing;
|
public const string Nothing = EquipItem.Nothing;
|
||||||
public const string SmallClothesNpc = "Smallclothes (NPC)";
|
public const string SmallClothesNpc = "Smallclothes (NPC)";
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,4 @@ namespace Glamourer.Services;
|
||||||
public interface ISavable : ISavable<FilenameService>;
|
public interface ISavable : ISavable<FilenameService>;
|
||||||
|
|
||||||
public sealed class SaveService(Logger log, FrameworkManager framework, FilenameService fileNames)
|
public sealed class SaveService(Logger log, FrameworkManager framework, FilenameService fileNames)
|
||||||
: BaseSaveService<FilenameService>(log, framework, fileNames);
|
: BaseSaveService<FilenameService>(log, framework, fileNames), IService;
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,12 @@
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Glamourer.Api;
|
using Glamourer.Api;
|
||||||
using Glamourer.Api.Api;
|
using Glamourer.Api.Api;
|
||||||
using Glamourer.Automation;
|
|
||||||
using Glamourer.Config;
|
|
||||||
using Glamourer.Designs;
|
|
||||||
using Glamourer.Events;
|
|
||||||
using Glamourer.Gui;
|
|
||||||
using Glamourer.Gui.Customization;
|
|
||||||
using Glamourer.Gui.Equipment;
|
|
||||||
using Glamourer.Gui.Tabs;
|
|
||||||
using Glamourer.Gui.Tabs.ActorTab;
|
|
||||||
using Glamourer.Gui.Tabs.AutomationTab;
|
|
||||||
using Glamourer.Gui.Tabs.DebugTab;
|
|
||||||
using Glamourer.Gui.Tabs.DesignTab;
|
|
||||||
using Glamourer.Gui.Tabs.NpcTab;
|
|
||||||
using Glamourer.Gui.Tabs.SettingsTab;
|
|
||||||
using Glamourer.Gui.Tabs.UnlocksTab;
|
|
||||||
using Glamourer.Interop;
|
|
||||||
using Glamourer.Interop.Penumbra;
|
using Glamourer.Interop.Penumbra;
|
||||||
using Glamourer.State;
|
|
||||||
using Glamourer.Unlocks;
|
|
||||||
using Luna;
|
using Luna;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using OtterGui.Classes;
|
|
||||||
using OtterGui.Raii;
|
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Data;
|
|
||||||
using Penumbra.GameData.DataContainers;
|
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using FrameworkManager = OtterGui.Classes.FrameworkManager;
|
|
||||||
using Logger = OtterGui.Log.Logger;
|
|
||||||
using MessageService = Luna.MessageService;
|
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
|
|
@ -39,146 +14,19 @@ public static class StaticServiceManager
|
||||||
{
|
{
|
||||||
public static ServiceManager CreateProvider(IDalamudPluginInterface pi, Logger log, Glamourer glamourer)
|
public static ServiceManager CreateProvider(IDalamudPluginInterface pi, Logger log, Glamourer glamourer)
|
||||||
{
|
{
|
||||||
EventWrapperBase.ChangeLogger(log);
|
var services = new ServiceManager(log)
|
||||||
var services = new ServiceManager(new Luna.Logger("Glamourer"))
|
|
||||||
.AddExistingService(log)
|
.AddExistingService(log)
|
||||||
.AddMeta()
|
.AddSingleton<MessageService>()
|
||||||
.AddInterop()
|
.AddSingleton<ActorObjectManager>()
|
||||||
.AddEvents()
|
.AddSingleton(p => new CutsceneResolver(p.GetRequiredService<PenumbraService>().CutsceneParent))
|
||||||
.AddData()
|
|
||||||
.AddDesigns()
|
|
||||||
.AddState()
|
|
||||||
.AddUi()
|
|
||||||
.AddExistingService(glamourer);
|
.AddExistingService(glamourer);
|
||||||
DalamudServices.AddServices(services, pi);
|
|
||||||
services.AddIServices(typeof(EquipItem).Assembly);
|
services.AddIServices(typeof(EquipItem).Assembly);
|
||||||
services.AddIServices(typeof(Glamourer).Assembly);
|
services.AddIServices(typeof(Glamourer).Assembly);
|
||||||
services.AddIServices(typeof(ImRaii).Assembly);
|
|
||||||
services.AddIServices(typeof(ServiceManager).Assembly);
|
services.AddIServices(typeof(ServiceManager).Assembly);
|
||||||
services.AddIServices<OtterGui.Services.IService>(typeof(Glamourer).Assembly);
|
|
||||||
|
|
||||||
services.AddSingleton<DictJob>();
|
|
||||||
services.AddSingleton<DictJobGroup>();
|
|
||||||
services.AddSingleton<NameDicts>();
|
|
||||||
services.AddSingleton<DictWorld>();
|
|
||||||
services.AddSingleton<IGlamourerApi>(p => p.GetRequiredService<GlamourerApi>());
|
services.AddSingleton<IGlamourerApi>(p => p.GetRequiredService<GlamourerApi>());
|
||||||
|
DalamudServices.AddServices(services, pi);
|
||||||
|
|
||||||
services.BuildProvider();
|
services.BuildProvider();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ServiceManager AddMeta(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<MessageService>()
|
|
||||||
.AddSingleton<FilenameService>()
|
|
||||||
.AddSingleton<BackupService>()
|
|
||||||
.AddSingleton<FrameworkManager>()
|
|
||||||
.AddSingleton<SaveService>()
|
|
||||||
.AddSingleton<CodeService>()
|
|
||||||
.AddSingleton<ConfigMigrationService>()
|
|
||||||
.AddSingleton<Configuration>()
|
|
||||||
.AddSingleton<EphemeralConfig>()
|
|
||||||
.AddSingleton<TextureService>()
|
|
||||||
.AddSingleton<FavoriteManager>();
|
|
||||||
|
|
||||||
private static ServiceManager AddEvents(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<VisorStateChanged>()
|
|
||||||
.AddSingleton<VieraEarStateChanged>()
|
|
||||||
.AddSingleton<EquipSlotUpdating>()
|
|
||||||
.AddSingleton<DesignChanged>()
|
|
||||||
.AddSingleton<AutomationChanged>()
|
|
||||||
.AddSingleton<StateChanged>()
|
|
||||||
.AddSingleton<WeaponLoading>()
|
|
||||||
.AddSingleton<HeadGearVisibilityChanged>()
|
|
||||||
.AddSingleton<WeaponVisibilityChanged>()
|
|
||||||
.AddSingleton<ObjectUnlocked>()
|
|
||||||
.AddSingleton<TabSelected>()
|
|
||||||
.AddSingleton<MovedEquipment>()
|
|
||||||
.AddSingleton<EquippedGearset>()
|
|
||||||
.AddSingleton<GPoseService>()
|
|
||||||
.AddSingleton<PenumbraReloaded>();
|
|
||||||
|
|
||||||
private static ServiceManager AddData(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<ObjectIdentification>()
|
|
||||||
.AddSingleton<ItemData>()
|
|
||||||
.AddSingleton<ActorManager>()
|
|
||||||
.AddSingleton<CustomizeService>()
|
|
||||||
.AddSingleton<ItemManager>()
|
|
||||||
.AddSingleton<GamePathParser>()
|
|
||||||
.AddSingleton<HumanModelList>();
|
|
||||||
|
|
||||||
private static ServiceManager AddInterop(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<VisorService>()
|
|
||||||
.AddSingleton<VieraEarService>()
|
|
||||||
.AddSingleton<ChangeCustomizeService>()
|
|
||||||
.AddSingleton<MetaService>()
|
|
||||||
.AddSingleton<UpdateSlotService>()
|
|
||||||
.AddSingleton<WeaponService>()
|
|
||||||
.AddSingleton<PenumbraService>()
|
|
||||||
.AddSingleton(p => new CutsceneResolver(p.GetRequiredService<PenumbraService>().CutsceneParent))
|
|
||||||
.AddSingleton<ObjectManager>()
|
|
||||||
.AddSingleton<ActorObjectManager>()
|
|
||||||
.AddSingleton<PenumbraAutoRedraw>()
|
|
||||||
.AddSingleton<JobService>()
|
|
||||||
.AddSingleton<CustomizeUnlockManager>()
|
|
||||||
.AddSingleton<ItemUnlockManager>()
|
|
||||||
.AddSingleton<ImportService>()
|
|
||||||
.AddSingleton<CrestService>()
|
|
||||||
.AddSingleton<InventoryService>()
|
|
||||||
.AddSingleton<ContextMenuService>()
|
|
||||||
.AddSingleton<ScalingService>()
|
|
||||||
.AddSingleton<DynamisIpc>();
|
|
||||||
|
|
||||||
private static ServiceManager AddDesigns(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<DesignManager>()
|
|
||||||
.AddSingleton<DesignFileSystem>()
|
|
||||||
.AddSingleton<AutoDesignManager>()
|
|
||||||
.AddSingleton<AutoDesignApplier>()
|
|
||||||
.AddSingleton<FixedDesignMigrator>()
|
|
||||||
.AddSingleton<DesignConverter>()
|
|
||||||
.AddSingleton<DesignColors>();
|
|
||||||
|
|
||||||
private static ServiceManager AddState(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<StateManager>()
|
|
||||||
.AddSingleton<StateApplier>()
|
|
||||||
.AddSingleton<InternalStateEditor>()
|
|
||||||
.AddSingleton<StateListener>()
|
|
||||||
.AddSingleton<FunModule>();
|
|
||||||
|
|
||||||
private static ServiceManager AddUi(this ServiceManager services)
|
|
||||||
=> services.AddSingleton<DebugTab>()
|
|
||||||
.AddSingleton<MessagesTab>()
|
|
||||||
.AddSingleton<SettingsTab>()
|
|
||||||
.AddSingleton<ActorTab>()
|
|
||||||
.AddSingleton<ActorSelector>()
|
|
||||||
.AddSingleton<ActorPanel>()
|
|
||||||
.AddSingleton<NpcPanel>()
|
|
||||||
.AddSingleton<NpcSelector>()
|
|
||||||
.AddSingleton<LocalNpcAppearanceData>()
|
|
||||||
.AddSingleton<NpcTab>()
|
|
||||||
.AddSingleton<MainWindow>()
|
|
||||||
.AddSingleton<GenericPopupWindow>()
|
|
||||||
.AddSingleton<GlamourerWindowSystem>()
|
|
||||||
.AddSingleton<CustomizationDrawer>()
|
|
||||||
.AddSingleton<EquipmentDrawer>()
|
|
||||||
.AddSingleton<DesignFileSystemDrawer>()
|
|
||||||
.AddSingleton<MultiDesignPanel>()
|
|
||||||
.AddSingleton<DesignPanel>()
|
|
||||||
.AddSingleton<DesignTab>()
|
|
||||||
.AddSingleton<QuickDesignCombo>()
|
|
||||||
.AddSingleton<LinkDesignCombo>()
|
|
||||||
.AddSingleton<RandomDesignCombo>()
|
|
||||||
.AddSingleton<SpecialDesignCombo>()
|
|
||||||
.AddSingleton<ModAssociationsTab>()
|
|
||||||
.AddSingleton<DesignDetailTab>()
|
|
||||||
.AddSingleton<UnlockTable>()
|
|
||||||
.AddSingleton<UnlockOverview>()
|
|
||||||
.AddSingleton<UnlocksTab>()
|
|
||||||
.AddSingleton<PenumbraChangedItemTooltip>()
|
|
||||||
.AddSingleton<AutomationTab>()
|
|
||||||
.AddSingleton<SetSelector>()
|
|
||||||
.AddSingleton<SetPanel>()
|
|
||||||
.AddSingleton<IdentifierDrawer>()
|
|
||||||
.AddSingleton<GlamourerChangelog>()
|
|
||||||
.AddSingleton<DesignQuickBar>()
|
|
||||||
.AddSingleton<DesignColorUi>()
|
|
||||||
.AddSingleton<TextureCache>();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,56 @@
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.Textures;
|
||||||
using Dalamud.Interface.Textures.TextureWraps;
|
using Dalamud.Interface.Textures.TextureWraps;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterGui.Classes;
|
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Services;
|
namespace Glamourer.Services;
|
||||||
|
|
||||||
public sealed class TextureService(IUiBuilder uiBuilder, IDataManager dataManager, ITextureProvider textureProvider)
|
public sealed class TextureService(IUiBuilder uiBuilder, ITextureProvider textureProvider)
|
||||||
: TextureCache(dataManager, textureProvider), IDisposable
|
: IDisposable, IUiService
|
||||||
{
|
{
|
||||||
private readonly IDalamudTextureWrap?[] _slotIcons = CreateSlotIcons(uiBuilder);
|
private readonly IDalamudTextureWrap?[] _slotIcons = CreateSlotIcons(uiBuilder);
|
||||||
|
|
||||||
|
public IDalamudTextureWrap? LoadIcon(uint iconId)
|
||||||
|
{
|
||||||
|
var icon = textureProvider.GetFromGameIcon(new GameIconLookup(iconId));
|
||||||
|
if (!icon.TryGetWrap(out var wrap, out _))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryLoadIcon(uint iconId, [NotNullWhen(true)] out IDalamudTextureWrap? wrap)
|
||||||
|
{
|
||||||
|
wrap = LoadIcon(iconId);
|
||||||
|
return wrap is not null;
|
||||||
|
}
|
||||||
|
|
||||||
public (ImTextureId, Vector2, bool) GetIcon(EquipItem item, EquipSlot slot)
|
public (ImTextureId, Vector2, bool) GetIcon(EquipItem item, EquipSlot slot)
|
||||||
{
|
{
|
||||||
if (item.IconId.Id != 0 && TryLoadIcon(item.IconId.Id, out var ret))
|
if (item.IconId.Id is not 0 && TryLoadIcon(item.IconId.Id, out var ret))
|
||||||
return (ret.Id, new Vector2(ret.Width, ret.Height), false);
|
return (ret.Id, new Vector2(ret.Width, ret.Height), false);
|
||||||
|
|
||||||
var idx = slot.ToIndex();
|
var idx = slot.ToIndex();
|
||||||
return idx < 12 && _slotIcons[idx] != null
|
return idx < 12 && _slotIcons[idx] is not null
|
||||||
? (_slotIcons[idx]!.Id, new Vector2(_slotIcons[idx]!.Width, _slotIcons[idx]!.Height), true)
|
? (_slotIcons[idx]!.Id, new Vector2(_slotIcons[idx]!.Width, _slotIcons[idx]!.Height), true)
|
||||||
: (default, Vector2.Zero, true);
|
: (default, Vector2.Zero, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (ImTextureId, Vector2, bool) GetIcon(EquipItem item, BonusItemFlag slot)
|
public (ImTextureId, Vector2, bool) GetIcon(EquipItem item, BonusItemFlag slot)
|
||||||
{
|
{
|
||||||
if (item.IconId.Id != 0 && TryLoadIcon(item.IconId.Id, out var ret))
|
if (item.IconId.Id is not 0 && TryLoadIcon(item.IconId.Id, out var ret))
|
||||||
return (ret.Id, new Vector2(ret.Width, ret.Height), false);
|
return (ret.Id, new Vector2(ret.Width, ret.Height), false);
|
||||||
|
|
||||||
var idx = slot.ToIndex();
|
var idx = slot.ToIndex();
|
||||||
if (idx == uint.MaxValue)
|
if (idx is uint.MaxValue)
|
||||||
return (default, Vector2.Zero, true);
|
return (default, Vector2.Zero, true);
|
||||||
|
|
||||||
idx += 12;
|
idx += 12;
|
||||||
return idx < 13 && _slotIcons[idx] != null
|
return idx < 13 && _slotIcons[idx] is not null
|
||||||
? (_slotIcons[idx]!.Id, new Vector2(_slotIcons[idx]!.Width, _slotIcons[idx]!.Height), true)
|
? (_slotIcons[idx]!.Id, new Vector2(_slotIcons[idx]!.Width, _slotIcons[idx]!.Height), true)
|
||||||
: (default, Vector2.Zero, true);
|
: (default, Vector2.Zero, true);
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +87,7 @@ public sealed class TextureService(IUiBuilder uiBuilder, IDataManager dataManage
|
||||||
SetIcon(EquipSlot.RFinger, 28);
|
SetIcon(EquipSlot.RFinger, 28);
|
||||||
SetIcon(EquipSlot.MainHand, 17);
|
SetIcon(EquipSlot.MainHand, 17);
|
||||||
SetIcon(EquipSlot.OffHand, 18);
|
SetIcon(EquipSlot.OffHand, 18);
|
||||||
Set(BonusItemFlag.Glasses.ToName(), (int) BonusItemFlag.Glasses.ToIndex() + 12, 55);
|
Set(BonusItemFlag.Glasses.ToName(), (int)BonusItemFlag.Glasses.ToIndex() + 12, 55);
|
||||||
ret[EquipSlot.LFinger.ToIndex()] = ret[EquipSlot.RFinger.ToIndex()];
|
ret[EquipSlot.LFinger.ToIndex()] = ret[EquipSlot.RFinger.ToIndex()];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue