Fix errors due to Luna update, fix warnings.

This commit is contained in:
Ottermandias 2026-02-07 23:26:20 +01:00
parent afa804394f
commit 3a23bceb6d
42 changed files with 266 additions and 219 deletions

2
Luna

@ -1 +1 @@
Subproject commit a03f00b93d5efd04fab90e780c821d83127b2b52
Subproject commit 1f00860cbb38fecacde99e55461dbc251cb40f24

View file

@ -128,7 +128,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable
if (Im.SmallButton("Delete"u8))
_lastDeleteEc = new DeleteMod(_pi).Invoke(_modDirectory, _modName);
Im.Line.Same();
Im.Text(_lastDeleteEc.ToString());
Im.Text($"{_lastDeleteEc}");
}
using (IpcTester.DrawIntro(GetChangedItems.LabelU8, "Get Changed Items"u8))

View file

@ -36,7 +36,7 @@ public static partial class ChangedItemModeExtensions
=> new(value.Tooltip());
public override IEnumerable<ChangedItemMode> GetBaseItems()
=> Enum.GetValues<ChangedItemMode>();
=> ChangedItemMode.Values;
}
public static bool DrawCombo(ReadOnlySpan<byte> label, ChangedItemMode value, float width, Action<ChangedItemMode> setter)

View file

@ -1,4 +1,5 @@
using Dalamud.Interface.ImGuiNotification;
using ImSharp;
using Luna;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -16,7 +17,7 @@ public class ActiveCollectionData : IService
public ModCollection Default { get; internal set; } = ModCollection.Empty;
public ModCollection Interface { get; internal set; } = ModCollection.Empty;
public readonly ModCollection?[] SpecialCollections = new ModCollection?[Enum.GetValues<Api.Enums.ApiCollectionType>().Length - 3];
public readonly ModCollection?[] SpecialCollections = new ModCollection?[Api.Enums.ApiCollectionType.Values.Count - 3];
}
public class ActiveCollections : ISavable, IDisposable, IService
@ -528,7 +529,7 @@ public class ActiveCollections : ISavable, IDisposable, IService
return string.Empty;
var racial = false;
foreach (var race in Enum.GetValues<SubRace>().Skip(1))
foreach (var race in SubRace.Values.Skip(1))
{
var m = ByType(CollectionTypeExtensions.FromParts(race, Gender.Male, false));
if (m != null && m != yourself)

View file

@ -111,7 +111,7 @@ public static class CollectionTypeExtensions
public static bool CanBeRemoved(this CollectionType collectionType)
=> collectionType.IsSpecial() || collectionType is CollectionType.Individual;
public static readonly (CollectionType, StringU8, StringU8)[] Special = Enum.GetValues<CollectionType>()
public static readonly (CollectionType, StringU8, StringU8)[] Special = CollectionType.Values
.Where(IsSpecial)
.Select(s => (s, new StringU8(s.ToName()), new StringU8(s.ToDescription())))
.ToArray();
@ -331,7 +331,7 @@ public static class CollectionTypeExtensions
return true;
}
foreach (var t in Enum.GetValues<CollectionType>())
foreach (var t in CollectionType.Values)
{
if (t is CollectionType.Inactive or CollectionType.Temporary)
continue;

View file

@ -1,5 +1,6 @@
using Dalamud.Configuration;
using Dalamud.Interface.ImGuiNotification;
using ImSharp;
using Luna;
using Luna.Generators;
using Newtonsoft.Json;
@ -143,7 +144,7 @@ public partial class Configuration : IPluginConfiguration, ISavable, IService
public bool HdrRenderTargets { get; set; } = true;
public Dictionary<ColorId, uint> Colors { get; set; }
= Enum.GetValues<ColorId>().ToDictionary(c => c, c => c.Data().DefaultColor);
= ColorId.Values.ToDictionary(c => c, c => c.Data().DefaultColor);
/// <summary>
/// Load the current configuration.

View file

@ -1,4 +1,5 @@
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using ImSharp;
using Penumbra.Api.Enums;
using Penumbra.String;
using Penumbra.String.Functions;
@ -90,8 +91,8 @@ public enum ResourceCategoryFlag : ushort
public static class ResourceExtensions
{
public static readonly ResourceTypeFlag AllResourceTypes = Enum.GetValues<ResourceTypeFlag>().Aggregate((v, f) => v | f);
public static readonly ResourceCategoryFlag AllResourceCategories = Enum.GetValues<ResourceCategoryFlag>().Aggregate((v, f) => v | f);
public static readonly ResourceTypeFlag AllResourceTypes = ResourceTypeFlag.Values.Aggregate((v, f) => v | f);
public static readonly ResourceCategoryFlag AllResourceCategories = ResourceCategoryFlag.Values.Aggregate((v, f) => v | f);
public static ResourceTypeFlag ToFlag(this ResourceType type)
=> type switch

View file

@ -226,7 +226,7 @@ public partial class CombinedTexture
private sealed class CombineOperationCombo() : SimpleFilterCombo<CombineOp>(SimpleFilterType.None)
{
private static readonly CombineOp[] UserValues = Enum.GetValues<CombineOp>().Where(c => (int)c >= 0).ToArray();
private static readonly CombineOp[] UserValues = CombineOp.Values.Where(c => (int)c >= 0).ToArray();
public override StringU8 DisplayString(in CombineOp value)
=> new(value.ToLabelU8());
@ -243,7 +243,7 @@ public partial class CombinedTexture
private sealed class ResizeOperationCombo() : SimpleFilterCombo<ResizeOp>(SimpleFilterType.None)
{
private static readonly ResizeOp[] UserValues = Enum.GetValues<ResizeOp>().Where(c => (int)c >= 0).ToArray();
private static readonly ResizeOp[] UserValues = ResizeOp.Values.Where(c => (int)c >= 0).ToArray();
public override StringU8 DisplayString(in ResizeOp value)
=> new(value.ToLabelU8());
@ -282,11 +282,11 @@ public partial class CombinedTexture
using (Im.Disabled(_combineOp != CombineOp.CopyChannels))
{
Im.Text("Copy"u8);
foreach (var channel in Enum.GetValues<Channels>())
foreach (var channel in Channels.Values)
{
Im.Line.Same();
var copy = (_copyChannels & channel) != 0;
if (Im.Checkbox(channel.ToString(), ref copy))
var copy = (_copyChannels & channel) is not 0;
if (Im.Checkbox($"{channel}", ref copy))
{
_copyChannels = copy ? _copyChannels | channel : _copyChannels & ~channel;
ret = true;

View file

@ -1,38 +1,43 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Luna;
using Penumbra.GameData;
using Penumbra.GameData.Interop;
using Penumbra.Interop.PathResolving;
namespace Penumbra.Interop.Hooks.Meta;
public unsafe class AtchCallerHook1 : FastHook<AtchCallerHook1.Delegate>, IDisposable
{
public delegate void Delegate(DrawObjectData* data, uint slot, nint unk, Model playerModel);
private readonly CollectionResolver _collectionResolver;
private readonly MetaState _metaState;
public AtchCallerHook1(HookManager hooks, MetaState metaState, CollectionResolver collectionResolver)
{
_metaState = metaState;
_collectionResolver = collectionResolver;
Task = hooks.CreateHook<Delegate>("AtchCaller1", Sigs.AtchCaller1, Detour,
metaState.Config.EnableMods && !HookOverrides.Instance.Meta.AtchCaller1);
if (!HookOverrides.Instance.Meta.AtchCaller1)
_metaState.Config.ModsEnabled += Set;
}
private void Detour(DrawObjectData* data, uint slot, nint unk, Model playerModel)
{
var collection = playerModel.Valid ? _collectionResolver.IdentifyCollection(playerModel.AsDrawObject, true) : _collectionResolver.DefaultCollection;
_metaState.AtchCollection.Push(collection);
Task.Result.Original(data, slot, unk, playerModel);
_metaState.AtchCollection.Pop();
Penumbra.Log.Excessive(
$"[AtchCaller1] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, identified to {collection.ModCollection.Identity.AnonymizedName}.");
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
}
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Luna;
using Penumbra.GameData;
using Penumbra.GameData.Interop;
using Penumbra.Interop.PathResolving;
namespace Penumbra.Interop.Hooks.Meta;
public unsafe class AtchCallerHook1 : FastHook<AtchCallerHook1.Delegate>, IDisposable
{
public delegate void Delegate(DrawObjectData* data, uint slot, nint unk, Model playerModel);
private readonly CollectionResolver _collectionResolver;
private readonly MetaState _metaState;
public AtchCallerHook1(HookManager hooks, MetaState metaState, CollectionResolver collectionResolver)
{
_metaState = metaState;
_collectionResolver = collectionResolver;
Task = hooks.CreateHook<Delegate>("AtchCaller1", Sigs.AtchCaller1, Detour,
metaState.Config.EnableMods && !HookOverrides.Instance.Meta.AtchCaller1);
if (!HookOverrides.Instance.Meta.AtchCaller1)
_metaState.Config.ModsEnabled += Set;
}
private void Detour(DrawObjectData* data, uint slot, nint unk, Model playerModel)
{
var collection = playerModel.Valid
? _collectionResolver.IdentifyCollection(playerModel.AsDrawObject, true)
: _collectionResolver.DefaultCollection;
_metaState.AtchCollection.Push(collection);
Task.Result.Original(data, slot, unk, playerModel);
_metaState.AtchCollection.Pop();
Penumbra.Log.Excessive(
$"[AtchCaller1] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, identified to {collection.ModCollection.Identity.AnonymizedName}.");
}
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -33,6 +33,9 @@ public unsafe class AtchCallerHook2 : FastHook<AtchCallerHook2.Delegate>, IDispo
$"[AtchCaller2] Invoked on 0x{(ulong)data:X} with {slot}, {unk:X}, 0x{playerModel.Address:X}, {unk2}, identified to {collection.ModCollection.Identity.AnonymizedName}.");
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -32,6 +32,9 @@ public unsafe class EqdpAccessoryHook : FastHook<EqdpAccessoryHook.Delegate>, ID
$"[GetEqdpAccessoryEntry] Invoked on 0x{(ulong)utility:X} with {setId}, {(GenderRace)raceCode}, returned {(ushort)*entry:B10}.");
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -31,6 +31,9 @@ public unsafe class EqdpEquipHook : FastHook<EqdpEquipHook.Delegate>, IDisposabl
$"[GetEqdpEquipEntry] Invoked on 0x{(ulong)utility:X} with {setId}, {(GenderRace)raceCode}, returned {(ushort)*entry:B10}.");
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -36,6 +36,9 @@ public unsafe class EqpHook : FastHook<EqpHook.Delegate>, IDisposable
Penumbra.Log.Excessive($"[GetEqpFlags] Invoked on 0x{(nint)utility:X} with 0x{(ulong)armor:X}, returned 0x{(ulong)*flags:X16}.");
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -58,6 +58,9 @@ public unsafe class EstHook : FastHook<EstHook.Delegate>, IDisposable
return new EstIdentifier(i, 0, gr);
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -36,6 +36,9 @@ public unsafe class GmpHook : FastHook<GmpHook.Delegate>, IDisposable
return ret;
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -68,6 +68,9 @@ public unsafe class RspBustHook : FastHook<RspBustHook.Delegate>, IDisposable
return ret;
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -78,6 +78,9 @@ public class RspHeightHook : FastHook<RspHeightHook.Delegate>, IDisposable
return scale;
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -72,6 +72,9 @@ public class RspTailHook : FastHook<RspTailHook.Delegate>, IDisposable
return scale;
}
public void Dispose()
=> _metaState.Config.ModsEnabled -= Set;
public override void Dispose()
{
_metaState.Config.ModsEnabled -= Set;
base.Dispose();
}
}

View file

@ -1,98 +1,102 @@
using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
using FFXIVClientStructs.Interop;
using FFXIVClientStructs.STD;
using Penumbra.Api.Enums;
using Penumbra.GameData;
namespace Penumbra.Interop.Hooks.ResourceLoading;
public unsafe class ResourceManagerService : Luna.IRequiredService
{
public ResourceManagerService(IGameInteropProvider interop)
=> interop.InitializeFromAttributes(this);
/// <summary> The SE Resource Manager as pointer. </summary>
public ResourceManager* ResourceManager
=> *ResourceManagerAddress;
/// <summary> Find a resource in the resource manager by its category, extension and crc-hash. </summary>
public ResourceHandle* FindResource(ResourceCategory cat, ResourceType ext, uint crc32)
{
ref var manager = ref *ResourceManager;
var catIdx = (uint)cat >> 0x18;
cat = (ResourceCategory)(ushort)cat;
ref var category = ref manager.ResourceGraph->Containers[(int)cat];
var extMap = FindInMap(category.CategoryMaps[(int)catIdx].Value, (uint)ext);
if (extMap == null)
return null;
var ret = FindInMap(extMap->Value, crc32);
return ret == null ? null : ret->Value;
}
public delegate void ExtMapAction(ResourceCategory category, StdMap<uint, Pointer<StdMap<uint, Pointer<ResourceHandle>>>>* graph, int idx);
public delegate void ResourceMapAction(uint ext, StdMap<uint, Pointer<ResourceHandle>>* graph);
public delegate void ResourceAction(uint crc32, ResourceHandle* graph);
/// <summary> Iterate through the entire graph calling an action on every ExtMap. </summary>
public void IterateGraphs(ExtMapAction action)
{
ref var manager = ref *ResourceManager;
foreach (var resourceType in Enum.GetValues<ResourceCategory>().SkipLast(1))
{
ref var graph = ref manager.ResourceGraph->Containers[(int)resourceType];
for (var i = 0; i < 20; ++i)
{
var map = graph.CategoryMaps[i];
if (map.Value != null)
action(resourceType, map, i);
}
}
}
/// <summary> Iterate through a specific ExtMap calling an action on every resource map. </summary>
public void IterateExtMap(StdMap<uint, Pointer<StdMap<uint, Pointer<ResourceHandle>>>>* map, ResourceMapAction action)
=> IterateMap(map, (ext, m) => action(ext, m.Value));
/// <summary> Iterate through a specific resource map calling an action on every resource. </summary>
public void IterateResourceMap(StdMap<uint, Pointer<ResourceHandle>>* map, ResourceAction action)
=> IterateMap(map, (crc, r) => action(crc, r.Value));
/// <summary> Iterate through the entire graph calling an action on every resource. </summary>
public void IterateResources(ResourceAction action)
{
IterateGraphs((_, extMap, _)
=> IterateExtMap(extMap, (_, resourceMap)
=> IterateResourceMap(resourceMap, action)));
}
/// <summary> A static pointer to the SE Resource Manager. </summary>
[Signature(Sigs.ResourceManager, ScanType = ScanType.StaticAddress)]
internal readonly ResourceManager** ResourceManagerAddress = null;
// Find a key in a StdMap.
private static TValue* FindInMap<TKey, TValue>(StdMap<TKey, TValue>* map, in TKey key)
where TKey : unmanaged, IComparable<TKey>
where TValue : unmanaged
{
if (map == null)
return null;
return map->TryGetValuePointer(key, out var val) ? val : null;
}
// Iterate in tree-order through a map, applying action to each KeyValuePair.
private static void IterateMap<TKey, TValue>(StdMap<TKey, TValue>* map, Action<TKey, TValue> action)
where TKey : unmanaged
where TValue : unmanaged
{
if (map == null)
return;
foreach (var (key, value) in *map)
action(key, value);
}
}
using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
using FFXIVClientStructs.STD;
using Penumbra.Api.Enums;
using Penumbra.GameData;
using ImSharp;
namespace Penumbra.Interop.Hooks.ResourceLoading;
public unsafe class ResourceManagerService : Luna.IRequiredService
{
public ResourceManagerService(IGameInteropProvider interop)
=> interop.InitializeFromAttributes(this);
/// <summary> The SE Resource Manager as pointer. </summary>
public ResourceManager* ResourceManager
=> *ResourceManagerAddress;
/// <summary> Find a resource in the resource manager by its category, extension and crc-hash. </summary>
public ResourceHandle* FindResource(ResourceCategory cat, ResourceType ext, uint crc32)
{
ref var manager = ref *ResourceManager;
var catIdx = (uint)cat >> 0x18;
cat = (ResourceCategory)(ushort)cat;
ref var category = ref manager.ResourceGraph->Containers[(int)cat];
var extMap = FindInMap(category.CategoryMaps[(int)catIdx].Value, (uint)ext);
if (extMap == null)
return null;
var ret = FindInMap(extMap->Value, crc32);
return ret == null ? null : ret->Value;
}
public delegate void ExtMapAction(ResourceCategory category,
StdMap<uint, FFXIVClientStructs.Interop.Pointer<StdMap<uint, FFXIVClientStructs.Interop.Pointer<ResourceHandle>>>>* graph, int idx);
public delegate void ResourceMapAction(uint ext, StdMap<uint, FFXIVClientStructs.Interop.Pointer<ResourceHandle>>* graph);
public delegate void ResourceAction(uint crc32, ResourceHandle* graph);
/// <summary> Iterate through the entire graph calling an action on every ExtMap. </summary>
public void IterateGraphs(ExtMapAction action)
{
ref var manager = ref *ResourceManager;
foreach (var resourceType in ResourceCategory.Values.SkipLast(1))
{
ref var graph = ref manager.ResourceGraph->Containers[(int)resourceType];
for (var i = 0; i < 20; ++i)
{
var map = graph.CategoryMaps[i];
if (map.Value != null)
action(resourceType, map, i);
}
}
}
/// <summary> Iterate through a specific ExtMap calling an action on every resource map. </summary>
public void IterateExtMap(
StdMap<uint, FFXIVClientStructs.Interop.Pointer<StdMap<uint, FFXIVClientStructs.Interop.Pointer<ResourceHandle>>>>* map,
ResourceMapAction action)
=> IterateMap(map, (ext, m) => action(ext, m.Value));
/// <summary> Iterate through a specific resource map calling an action on every resource. </summary>
public void IterateResourceMap(StdMap<uint, FFXIVClientStructs.Interop.Pointer<ResourceHandle>>* map, ResourceAction action)
=> IterateMap(map, (crc, r) => action(crc, r.Value));
/// <summary> Iterate through the entire graph calling an action on every resource. </summary>
public void IterateResources(ResourceAction action)
{
IterateGraphs((_, extMap, _)
=> IterateExtMap(extMap, (_, resourceMap)
=> IterateResourceMap(resourceMap, action)));
}
/// <summary> A static pointer to the SE Resource Manager. </summary>
[Signature(Sigs.ResourceManager, ScanType = ScanType.StaticAddress)]
internal readonly ResourceManager** ResourceManagerAddress = null;
// Find a key in a StdMap.
private static TValue* FindInMap<TKey, TValue>(StdMap<TKey, TValue>* map, in TKey key)
where TKey : unmanaged, IComparable<TKey>
where TValue : unmanaged
{
if (map == null)
return null;
return map->TryGetValuePointer(key, out var val) ? val : null;
}
// Iterate in tree-order through a map, applying action to each KeyValuePair.
private static void IterateMap<TKey, TValue>(StdMap<TKey, TValue>* map, Action<TKey, TValue> action)
where TKey : unmanaged
where TValue : unmanaged
{
if (map == null)
return;
foreach (var (key, value) in *map)
action(key, value);
}
}

View file

@ -1,11 +1,11 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using ImSharp;
using Penumbra.GameData.Interop;
using Penumbra.GameData.Structs;
using Penumbra.Interop.PathResolving;
using Penumbra.String;
using static Penumbra.Interop.Structs.StructExtensions;
using Model = Penumbra.GameData.Interop.Model;
namespace Penumbra.Interop.MaterialPreview;
@ -54,7 +54,7 @@ public readonly record struct MaterialInfo(ObjectIndex ObjectIndex, DrawObjectTy
? m
: CiByteString.Empty;
var result = new List<MaterialInfo>(Enum.GetValues<DrawObjectType>().Length);
var result = new List<MaterialInfo>(DrawObjectType.Values.Count);
foreach (var objectPtr in gameObjects)
{
var gameObject = (Character*)objectPtr;
@ -63,7 +63,7 @@ public readonly record struct MaterialInfo(ObjectIndex ObjectIndex, DrawObjectTy
var index = (ObjectIndex)gameObject->GameObject.ObjectIndex;
foreach (var type in Enum.GetValues<DrawObjectType>())
foreach (var type in DrawObjectType.Values)
{
var drawObject = GetDrawObject(type, objectPtr);
if (!drawObject.Valid)

View file

@ -1,5 +1,6 @@
using Dalamud.Plugin.Services;
using Dalamud.Utility.Signatures;
using ImSharp;
using Penumbra.Communication;
using Penumbra.GameData;
using Penumbra.Interop.Structs;
@ -41,8 +42,7 @@ public unsafe class CharacterUtility : IDisposable, Luna.IRequiredService
/// The relevant indices depend on which meta manipulations we allow for.
/// The defines are set in the project configuration.
/// </summary>
public static readonly MetaIndex[]
RelevantIndices = Enum.GetValues<MetaIndex>();
public static readonly MetaIndex[] RelevantIndices = MetaIndex.Values.ToArray();
public static readonly InternalIndex[] ReverseIndices
= Enumerable.Range(0, CharacterUtilityData.TotalNumResources)

View file

@ -1,3 +1,4 @@
using ImSharp;
using Penumbra.GameData.Enums;
namespace Penumbra.Interop.Structs;
@ -18,7 +19,7 @@ public unsafe struct CharacterUtilityData
public const int IndexSphereDArrayTex = 96;
public static readonly MetaIndex[] EqdpIndices = Enum.GetNames<MetaIndex>()
.Zip(Enum.GetValues<MetaIndex>())
.Zip(MetaIndex.Values)
.Where(n => n.First.StartsWith("Eqdp"))
.Select(n => n.Second).ToArray();

View file

@ -1,4 +1,5 @@
using System.Collections.Frozen;
using ImSharp;
using Luna;
using Penumbra.Collections.Cache;
using Penumbra.Meta;
@ -34,7 +35,7 @@ public class ModMetaEditor(
}
public readonly FrozenDictionary<MetaManipulationType, OtherOptionData> OtherData =
Enum.GetValues<MetaManipulationType>().ToFrozenDictionary(t => t, _ => new OtherOptionData());
MetaManipulationType.Values.ToFrozenDictionary(t => t, _ => new OtherOptionData());
public bool Changes { get; set; }
@ -46,7 +47,7 @@ public class ModMetaEditor(
public void Load(Mod mod, IModDataContainer currentOption)
{
foreach (var type in Enum.GetValues<MetaManipulationType>())
foreach (var type in MetaManipulationType.Values)
OtherData[type].Clear();
foreach (var option in mod.AllDataContainers)

View file

@ -1,3 +1,4 @@
using ImSharp;
using Penumbra.Api.Enums;
using Penumbra.GameData.Data;
using Penumbra.GameData.Enums;
@ -45,13 +46,13 @@ public static class EquipmentSwap
var mtrlVariantTo = imcEntry.MaterialId;
var skipFemale = false;
var skipMale = false;
foreach (var gr in Enum.GetValues<GenderRace>())
foreach (var gr in GenderRace.Values)
{
switch (gr.Split().Item1)
{
case Gender.Male when skipMale: continue;
case Gender.Female when skipFemale: continue;
case Gender.MaleNpc when skipMale: continue;
case Gender.Male when skipMale:
case Gender.Female when skipFemale:
case Gender.MaleNpc when skipMale:
case Gender.FemaleNpc when skipFemale: continue;
}
@ -137,13 +138,13 @@ public static class EquipmentSwap
var skipFemale = false;
var skipMale = false;
foreach (var gr in Enum.GetValues<GenderRace>())
foreach (var gr in GenderRace.Values)
{
switch (gr.Split().Item1)
{
case Gender.Male when skipMale: continue;
case Gender.Female when skipFemale: continue;
case Gender.MaleNpc when skipMale: continue;
case Gender.Male when skipMale:
case Gender.Female when skipFemale:
case Gender.MaleNpc when skipMale:
case Gender.FemaleNpc when skipFemale: continue;
}

View file

@ -1,3 +1,4 @@
using ImSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Penumbra.GameData.Structs;
@ -31,7 +32,7 @@ public readonly struct ModMeta(Mod mod) : ISavable
{
var features = mod.RequiredFeatures;
var array = new JArray();
foreach (var flag in Enum.GetValues<FeatureFlags>())
foreach (var flag in FeatureFlags.Values)
{
if ((features & flag) is not FeatureFlags.None)
array.Add(flag.ToString());

View file

@ -1,3 +1,4 @@
using ImSharp;
using Luna;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -37,7 +38,7 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu
private static void AddColors(Configuration config, bool forceSave)
{
var save = false;
foreach (var color in Enum.GetValues<ColorId>())
foreach (var color in ColorId.Values)
save |= config.Colors.TryAdd(color, color.Data().DefaultColor);
if (save || forceSave)

View file

@ -241,6 +241,6 @@ public class StainService : IService
public sealed class StainCombo(DictStain stainData) : FilterComboColors
{
protected override IEnumerable<Item> GetItems()
=> stainData.Value.Select(t => new Item(new StringPair(t.Value.Name), t.Value.Dye, t.Key, t.Value.Gloss)).Prepend(None);
=> stainData.Value.Select(t => new Item(new StringPair(StringU8.CreateUnchecked(t.Value.Name)), t.Value.Dye, t.Key, t.Value.Gloss)).Prepend(None);
}
}

View file

@ -498,7 +498,7 @@ public class ItemSwapTab : IDisposable, ITab
using (var combo = Im.Combo.Begin("##fromType"u8, _slotFrom.ToNameU8()))
{
if (combo)
foreach (var slot in Enum.GetValues<BetweenSlotTypes>())
foreach (var slot in BetweenSlotTypes.Values)
{
if (!Im.Selectable(slot.ToNameU8(), slot == _slotFrom) || slot == _slotFrom)
continue;
@ -778,5 +778,5 @@ public class ItemSwapTab : IDisposable, ITab
};
private static readonly IReadOnlyList<BetweenSlotTypes> AvailableToTypes =
Enum.GetValues<BetweenSlotTypes>().Where(s => s is not BetweenSlotTypes.Hat).ToArray();
BetweenSlotTypes.Values.Where(s => s is not BetweenSlotTypes.Hat).ToArray();
}

View file

@ -178,7 +178,7 @@ public partial class MtrlTab
return false;
var ret = false;
foreach (var mode in Enum.GetValues<TextureAddressMode>())
foreach (var mode in TextureAddressMode.Values)
{
if (Im.Selectable(mode.ToNameU8(), mode == value))
{

View file

@ -90,7 +90,7 @@ public sealed class GlobalEqpMetaDrawer(ModMetaEditor editor, MetaFileManager me
return false;
var ret = false;
foreach (var type in Enum.GetValues<GlobalEqpType>())
foreach (var type in GlobalEqpType.Values)
{
if (Im.Selectable(type.ToNameU8(), type == identifier.Type))
{

View file

@ -230,7 +230,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable
DrawMaterialReassignmentTab();
}
private static readonly FrozenDictionary<GenderRace, StringU8> RaceCodeNames = Enum.GetValues<GenderRace>().ToFrozenDictionary(v => v, v =>
private static readonly FrozenDictionary<GenderRace, StringU8> RaceCodeNames = GenderRace.Values.ToFrozenDictionary(v => v, v =>
{
if (v is GenderRace.Unknown)
return new StringU8("All Races and Genders");

View file

@ -258,6 +258,6 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : IU
Im.Separator();
Im.Dummy(Vector2.One);
using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder);
Im.TextWrapped(modMerger.Error.ToString());
Im.TextWrapped($"{modMerger.Error}");
}
}

View file

@ -181,10 +181,11 @@ public class ResourceTreeViewer(
using (Im.Id.Push("TreeCategoryFilter"u8))
{
foreach (var category in Enum.GetValues<TreeCategory>())
foreach (var category in TreeCategory.Values)
{
using var c = ImGuiColor.CheckMark.Push(CategoryColor(category).Value());
Im.Checkbox($"##{category}", ref _categoryFilter, category);
using var id = Im.Id.Push((int)category);
using var c = ImGuiColor.CheckMark.Push(CategoryColor(category).Value());
Im.Checkbox(StringU8.Empty, ref _categoryFilter, category);
Im.Tooltip.OnHover(CategoryFilterDescription(category));
Im.Line.Same(0.0f, checkSpacing);
}

View file

@ -117,7 +117,7 @@ public class TutorialService(EphemeralConfig config) : Luna.IUiService
"You can now toggle mods as favorites using this button. You can filter for favorited mods in the mod selector. Favorites are stored locally, not within the mod, but independently of collections."u8)
.Register("Tags"u8,
"Mods can now have two types of tags:\n\n- Local Tags are those that you can set for yourself. They are stored locally and are not saved in any way in the mod directory itself.\n- Mod Tags are stored in the mod metadata, are set by the mod creator and are exported together with the mod, they can only be edited in the Edit Mod tab.\n\nIf a mod has a tag in its Mod Tags, this overwrites any identical Local Tags.\n\nYou can filter for tags in the mod selector via 't:text'."u8)
.EnsureSize(Enum.GetValues<BasicTutorialSteps>().Length);
.EnsureSize(BasicTutorialSteps.Values.Count);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OpenTutorial(BasicTutorialSteps step)

View file

@ -84,7 +84,7 @@ public sealed class CollectionPanel(
Button(CollectionType.NonPlayerChild);
Button(CollectionType.NonPlayerElderly);
foreach (var race in Enum.GetValues<SubRace>().Skip(1))
foreach (var race in SubRace.Values.Skip(1))
{
Button(CollectionTypeExtensions.FromParts(race, Gender.Male, false));
Button(CollectionTypeExtensions.FromParts(race, Gender.Female, false));
@ -691,9 +691,9 @@ public sealed class CollectionPanel(
/// <summary> Create names and border colors for special assignments. </summary>
private static IReadOnlyDictionary<CollectionType, (StringU8 Name, Vector4 Border)> CreateButtons()
{
var ret = Enum.GetValues<CollectionType>().ToDictionary(t => t, t => (new StringU8(t.ToName()), Vector4.Zero));
var ret = CollectionType.Values.ToDictionary(t => t, t => (new StringU8(t.ToName()), Vector4.Zero));
foreach (var race in Enum.GetValues<SubRace>().Skip(1))
foreach (var race in SubRace.Values.Skip(1))
{
Rgba32 color = race switch
{
@ -749,7 +749,7 @@ public sealed class CollectionPanel(
Add(CollectionType.MaleNonPlayerCharacter, true, true);
Add(CollectionType.FemaleNonPlayerCharacter, true, true);
var pre = true;
foreach (var race in Enum.GetValues<SubRace>().Skip(1))
foreach (var race in SubRace.Values.Skip(1))
{
Add(CollectionTypeExtensions.FromParts(race, Gender.Male, false), pre, !pre);
Add(CollectionTypeExtensions.FromParts(race, Gender.Female, false), pre, !pre);

View file

@ -9,7 +9,13 @@ using Penumbra.UI.Classes;
namespace Penumbra.UI.CollectionTab;
public sealed class CollectionSelector(ActiveCollections active, TutorialService tutorial, IncognitoService incognito) : IPanel
public sealed class CollectionSelector(
CollectionFilter filter,
CollectionStorage collections,
CommunicatorService communicator,
ActiveCollections active,
TutorialService tutorial,
IncognitoService incognito) : IPanel
{
public ReadOnlySpan<byte> Id
=> "##cs"u8;
@ -38,7 +44,7 @@ public sealed class CollectionSelector(ActiveCollections active, TutorialService
public void Draw()
{
Im.Cursor.Y += Im.Style.FramePadding.Y;
var cache = CacheManager.Instance.GetOrCreateCache<Cache>(Im.Id.Current);
var cache = CacheManager.Instance.GetOrCreateCache(Im.Id.Current, () => new Cache(filter, collections, communicator));
using var color = ImGuiColor.Header.Push(ColorId.SelectedCollection.Value());
foreach (var item in cache)
{

View file

@ -20,7 +20,7 @@ public sealed class RaceCodeTab : IKnowledgeTab
return;
DrawHeaders(table);
foreach (var gr in Enum.GetValues<GenderRace>())
foreach (var gr in GenderRace.Values)
{
var (gender, race) = gr.Split();
if (gender is not Gender.Male and not Gender.Female || race is ModelRace.Unknown)

View file

@ -24,7 +24,7 @@ public readonly struct ImcModGroupEditDrawer(ModGroupEditDrawer editor, ImcModGr
- Im.Font.CalculateSize("All Variants"u8).X
- Im.Font.CalculateSize("Only Attributes"u8).X
- 2 * Im.Style.FrameHeight;
ImEx.TextFramed(identifier.ToString(), new Vector2(width, 0), Rgba32.Transparent);
ImEx.TextFramed($"{identifier}", new Vector2(width, 0), Rgba32.Transparent);
Im.Line.SameInner();
var allVariants = group.AllVariants;

View file

@ -176,7 +176,7 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
=> item.TypeName;
protected override IReadOnlyList<(RecordType Value, StringU8 Name)> EnumData
=> Enum.GetValues<RecordType>().Select(t => (t, new StringU8(t.ToNameU8()))).ToArray();
=> RecordType.Values.Select(t => (t, new StringU8(t.ToNameU8()))).ToArray();
protected override RecordType GetValue(in CachedRecord item, int globalIndex)
=> item.Record.RecordType;
@ -304,7 +304,7 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
=> item.ResourceCategory;
protected override IReadOnlyList<(ResourceCategoryFlag Value, StringU8 Name)> EnumData { get; } =
Enum.GetValues<ResourceCategoryFlag>().Select(r => (r, new StringU8($"{r}"))).ToArray();
ResourceCategoryFlag.Values.Select(r => (r, new StringU8($"{r}"))).ToArray();
protected override ResourceCategoryFlag GetValue(in CachedRecord item, int globalIndex)
=> item.Record.Category;
@ -323,7 +323,7 @@ internal sealed class ResourceWatcherTable : TableBase<CachedRecord, TableCache<
}
protected override IReadOnlyList<(ResourceTypeFlag Value, StringU8 Name)> EnumData { get; } =
Enum.GetValues<ResourceTypeFlag>().Select(r => (r, new StringU8(r.ToString().ToLowerInvariant()))).ToArray();
ResourceTypeFlag.Values.Select(r => (r, new StringU8(r.ToString().ToLowerInvariant()))).ToArray();
protected override StringU8 DisplayString(in CachedRecord item, int globalIndex)
=> item.ResourceType;

View file

@ -403,7 +403,7 @@ public sealed class DebugTab : Window, ITab<TabType>
using var table = Im.Table.Begin("##Tasks"u8, 2, TableFlags.RowBackground);
if (table)
foreach (var task in _textureManager.Tasks)
table.DrawDataPair(task.Key.ToString()!, $"{task.Value.Item1.Status}");
table.DrawDataPair($"{task.Key}", $"{task.Value.Item1.Status}");
}
}

View file

@ -73,7 +73,7 @@ public class ShapeInspector(ObjectManager objects, CollectionResolver resolver)
table.SetupColumn("State"u8, TableColumnFlags.WidthStretch);
table.HeaderRow();
foreach (var condition in Enum.GetValues<ShapeConnectorCondition>())
foreach (var condition in ShapeConnectorCondition.Values)
{
foreach (var (shape, set) in data.ModCollection.MetaCache!.Shp.State(condition).OrderBy(shp => shp.Key))
{

View file

@ -48,7 +48,6 @@ public sealed class SettingsTab : ITab<TabType>
private readonly CrashHandlerService _crashService;
private readonly MigrationSectionDrawer _migrationDrawer;
private readonly CollectionAutoSelector _autoSelector;
private readonly CleanupService _cleanupService;
private readonly AttributeHook _attributeHook;
private readonly PcpService _pcpService;
private readonly IntegrationSettingsRegistry _integrationSettings;
@ -63,9 +62,8 @@ public sealed class SettingsTab : ITab<TabType>
FileWatcher fileWatcher, HttpApi httpApi,
DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig,
IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService,
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService,
AttributeHook attributeHook, PcpService pcpService, IntegrationSettingsRegistry integrationSettings,
ModFileSystemDrawer modFileSystemDrawer)
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, AttributeHook attributeHook, PcpService pcpService,
IntegrationSettingsRegistry integrationSettings, ModFileSystemDrawer modFileSystemDrawer)
{
_pluginInterface = pluginInterface;
_config = config;
@ -89,7 +87,6 @@ public sealed class SettingsTab : ITab<TabType>
_crashService = crashService;
_migrationDrawer = migrationDrawer;
_autoSelector = autoSelector;
_cleanupService = cleanupService;
_attributeHook = attributeHook;
_pcpService = pcpService;
_integrationSettings = integrationSettings;
@ -423,7 +420,7 @@ public sealed class SettingsTab : ITab<TabType>
_config.RememberCollectionFilters, v => _config.RememberCollectionFilters = v);
Checkbox("Remember Changed Items Filters Across Sessions"u8,
"Whether filters in the Changed Items tab should remember their input and start with their respective lists filtered identically to the last session."u8,
_config.RememberChangedItemFilters, v => _config.RememberChangedItemFilters= v);
_config.RememberChangedItemFilters, v => _config.RememberChangedItemFilters = v);
Checkbox("Remember Effective Changes Filters Across Sessions"u8,
"Whether filters in the Effective Changes tab should remember their input and start with their respective lists filtered identically to the last session."u8,
_config.RememberEffectiveChangesFilters, v => _config.RememberEffectiveChangesFilters = v);
@ -433,7 +430,6 @@ public sealed class SettingsTab : ITab<TabType>
Checkbox("Remember Resource Manager Filters Across Sessions"u8,
"Whether filters in the Resource Manager tab should remember their input and start with their respective lists filtered identically to the last session."u8,
_config.RememberResourceManagerFilters, v => _config.RememberResourceManagerFilters = v);
}
/// <summary> Draw all settings that do not fit into other categories. </summary>
@ -828,7 +824,7 @@ public sealed class SettingsTab : ITab<TabType>
if (!Im.Tree.Header("Colors"u8))
return;
foreach (var color in Enum.GetValues<ColorId>())
foreach (var color in ColorId.Values)
{
var (defaultColor, name, description) = color.Data();
var currentColor = _config.Colors.GetValueOrDefault(color, defaultColor);