using Dalamud.Interface.Internal; using Dalamud.Plugin.Services; using OtterGui.Classes; using OtterGui.Services; using Penumbra.GameData.Enums; using Race = Penumbra.GameData.Enums.Race; namespace Glamourer.GameData; /// Generate everything about customization per tribe and gender. public class CustomizeManager : IAsyncDataContainer { /// All races except for Unknown public static readonly IReadOnlyList Races = ((Race[])Enum.GetValues(typeof(Race))).Skip(1).ToArray(); /// All tribes except for Unknown public static readonly IReadOnlyList Clans = ((SubRace[])Enum.GetValues(typeof(SubRace))).Skip(1).ToArray(); /// Two genders. public static readonly IReadOnlyList Genders = [ Gender.Male, Gender.Female, ]; /// Every tribe and gender has a separate set of available customizations. public CustomizeSet GetSet(SubRace race, Gender gender) { if (!Finished) Awaiter.Wait(); return _customizationSets[ToIndex(race, gender)]; } /// Get specific icons. public IDalamudTextureWrap GetIcon(uint id) => _icons.LoadIcon(id)!; /// Iterate over all supported genders and clans. public static IEnumerable<(SubRace Clan, Gender Gender)> AllSets() { foreach (var clan in Clans) { yield return (clan, Gender.Male); yield return (clan, Gender.Female); } } public CustomizeManager(ITextureProvider textures, IDataManager gameData, IPluginLog log, NpcCustomizeSet npcCustomizeSet) { _icons = new IconStorage(textures, gameData); var stopwatch = new Stopwatch(); var tmpTask = Task.Run(() => { stopwatch.Start(); return new CustomizeSetFactory(gameData, log, _icons, npcCustomizeSet); }); var setTasks = AllSets().Select(p => tmpTask.ContinueWith(t => _customizationSets[ToIndex(p.Clan, p.Gender)] = t.Result.CreateSet(p.Clan, p.Gender))); Awaiter = Task.WhenAll(setTasks).ContinueWith(_ => { // This is far too hard to estimate sensibly. TotalCount = 0; Memory = 0; Time = stopwatch.ElapsedMilliseconds; }); } /// public Task Awaiter { get; } /// public bool Finished => Awaiter.IsCompletedSuccessfully; private readonly IconStorage _icons; private static readonly int ListSize = Clans.Count * Genders.Count; private readonly CustomizeSet[] _customizationSets = new CustomizeSet[ListSize]; /// Get the index for the given pair of tribe and gender. private static int ToIndex(SubRace race, Gender gender) { var idx = ((int)race - 1) * Genders.Count + (gender == Gender.Female ? 1 : 0); if (idx < 0 || idx >= ListSize) throw new Exception($"Invalid customization requested for {race} {gender}."); return idx; } public long Time { get; private set; } public long Memory { get; private set; } public string Name => nameof(CustomizeManager); public int TotalCount { get; private set; } }