diff --git a/Luna b/Luna index e9ff6061..00d83664 160000 --- a/Luna +++ b/Luna @@ -1 +1 @@ -Subproject commit e9ff6061690b7dfc9ff4fe7cabfa296452866588 +Subproject commit 00d83664cf2366077253316e51ea38e47b4fd75c diff --git a/Penumbra.CrashHandler/Buffers/AnimationInvocationBuffer.cs b/Penumbra.CrashHandler/Buffers/AnimationInvocationBuffer.cs index 71570f60..4ae6ea98 100644 --- a/Penumbra.CrashHandler/Buffers/AnimationInvocationBuffer.cs +++ b/Penumbra.CrashHandler/Buffers/AnimationInvocationBuffer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text.Json.Nodes; @@ -9,6 +9,7 @@ public enum AnimationInvocationType : int { PapLoad, ActionLoad, + GetClipResources, ScheduleClipUpdate, LoadTimelineResources, LoadCharacterVfx, @@ -111,6 +112,7 @@ private static string ToName(AnimationInvocationType type) { AnimationInvocationType.PapLoad => "PAP Load", AnimationInvocationType.ActionLoad => "Action Load", + AnimationInvocationType.GetClipResources => "Get Clip Resources", AnimationInvocationType.ScheduleClipUpdate => "Schedule Clip Update", AnimationInvocationType.LoadTimelineResources => "Load Timeline Resources", AnimationInvocationType.LoadCharacterVfx => "Load Character VFX", diff --git a/Penumbra.GameData b/Penumbra.GameData index 678ac6d2..7b737239 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 678ac6d20576074b0b48338bfd8c282246e9a05d +Subproject commit 7b7372399d1094f6aa4f1fc18237bc2228eae41a diff --git a/Penumbra/Api/ModAdapter.cs b/Penumbra/Api/ModAdapter.cs index 3a15df56..3f42f60e 100644 --- a/Penumbra/Api/ModAdapter.cs +++ b/Penumbra/Api/ModAdapter.cs @@ -55,11 +55,5 @@ private Mod Mod } public void Dispose() - { - _mod.SetTarget(null!); - GC.SuppressFinalize(this); - } - - ~ModAdapter() - => Dispose(); + => _mod.SetTarget(null!); } diff --git a/Penumbra/CommandHandler.cs b/Penumbra/CommandHandler.cs index 8fb4c64c..050db60d 100644 --- a/Penumbra/CommandHandler.cs +++ b/Penumbra/CommandHandler.cs @@ -80,7 +80,6 @@ private void OnCommand(string command, string arguments) "toggle" => SetPenumbraState(arguments, null), "reload" => Reload(arguments), "redraw" => Redraw(arguments), - "lockui" => SetUiLockState(arguments), "size" => SetUiMinimumSize(arguments), "debug" => SetDebug(arguments), "collection" => SetCollection(arguments), @@ -112,9 +111,6 @@ private bool PrintHelp(string arguments) _chat.Print(new SeStringBuilder().AddCommand("reload", "Rediscover the mod directory and reload all mods.").BuiltString); _chat.Print(new SeStringBuilder() .AddCommand("redraw", "Redraw all game objects. Specify a placeholder or a name to redraw specific objects.").BuiltString); - _chat.Print(new SeStringBuilder() - .AddCommand("lockui", "Toggle the locked state of the main Penumbra window. Can be used with [on|off] to force specific state.") - .BuiltString); _chat.Print(new SeStringBuilder().AddCommand("size", "Reset the minimum config window size to its default values.").BuiltString); _chat.Print(new SeStringBuilder() .AddCommand("debug", "Toggle debug mode for Penumbra. Can be used with [on|off] to force specific state.").BuiltString); @@ -202,28 +198,6 @@ private bool SetPenumbraState(string _, bool? newValue) return _penumbra.SetEnabled(value); } - private bool SetUiLockState(string arguments) - { - var value = ParseTrueFalseToggle(arguments) ?? !_config.Ephemeral.FixMainWindow; - if (value == _config.Ephemeral.FixMainWindow) - return false; - - if (value) - { - Print("Penumbra UI locked in place."); - _mainWindow.Flags |= WindowFlags.NoMove | WindowFlags.NoResize; - } - else - { - Print("Penumbra UI unlocked."); - _mainWindow.Flags &= ~(WindowFlags.NoMove | WindowFlags.NoResize); - } - - _config.Ephemeral.FixMainWindow = value; - _config.Ephemeral.Save(); - return true; - } - private bool SetUiMinimumSize(string _) { if (_config.MinimumSize.X == Configuration.Constants.MinimumSizeX && _config.MinimumSize.Y == Configuration.Constants.MinimumSizeY) diff --git a/Penumbra/Config/EphemeralConfig.cs b/Penumbra/Config/EphemeralConfig.cs index a5361ead..54611dc7 100644 --- a/Penumbra/Config/EphemeralConfig.cs +++ b/Penumbra/Config/EphemeralConfig.cs @@ -3,7 +3,6 @@ using Luna.Generators; using Newtonsoft.Json; using Penumbra.Files; -using Penumbra.Services; using Penumbra.UI; using Penumbra.UI.ManagementTab; using Penumbra.UI.ModsTab; @@ -31,7 +30,6 @@ public sealed partial class EphemeralConfig : ISavable, IService [ConfigProperty] private ModPanelTab _selectedModPanelTab = ModPanelTab.Settings; - public bool FixMainWindow { get; set; } = false; public HashSet AdvancedEditingOpenForModPaths { get; set; } = []; public bool ForceRedrawOnFileChange { get; set; } = false; public bool IncognitoMode { get; set; } = false; diff --git a/Penumbra/Import/TexToolsImport.cs b/Penumbra/Import/TexToolsImport.cs index 7981b447..8061a522 100644 --- a/Penumbra/Import/TexToolsImport.cs +++ b/Penumbra/Import/TexToolsImport.cs @@ -26,8 +26,8 @@ public partial class TexToolsImporter : IDisposable private readonly CancellationTokenSource _cancellation = new(); private readonly CancellationToken _token; - public ImporterState State { get; private set; } - public readonly List<(FileInfo File, DirectoryInfo? Mod, Exception? Error)> ExtractedMods; + public ImporterState State { get; private set; } + public readonly List ExtractedMods; private readonly Configuration _config; private readonly DuplicateManager _duplicates; @@ -37,8 +37,9 @@ public partial class TexToolsImporter : IDisposable private readonly MigrationManager _migrationManager; public TexToolsImporter(int count, IEnumerable modPackFiles, Action handler, - Configuration config, DuplicateManager duplicates, ModNormalizer modNormalizer, ModManager modManager, FileCompactor compactor, - MigrationManager migrationManager, TexToolsImporter? previous) + TaskCompletionSource taskCompletionSource, Configuration config, DuplicateManager duplicates, + ModNormalizer modNormalizer, ModManager modManager, FileCompactor compactor, MigrationManager migrationManager, + TexToolsImporter? previous) { if (previous is not null) { @@ -58,7 +59,7 @@ public TexToolsImporter(int count, IEnumerable modPackFiles, Action(count + _previousModPackCount); + ExtractedMods = new List(count + _previousModPackCount); _token = _cancellation.Token; if (previous is not null) ExtractedMods.AddRange(previous.ExtractedMods); @@ -68,7 +69,9 @@ public TexToolsImporter(int count, IEnumerable modPackFiles, Action { taskCompletionSource.SetResult(ExtractedMods.Skip(_previousModPackCount).ToArray()); }, + TaskScheduler.Default); } private void CloseStreams() @@ -100,14 +103,14 @@ private void ImportFiles() _currentModDirectory = null; if (_token.IsCancellationRequested) { - ExtractedMods.Add((file, null, new TaskCanceledException("Task canceled by user."))); + ExtractedMods.Add(new ModImportResult(file, null, new TaskCanceledException("Task canceled by user."))); continue; } try { var directory = VerifyVersionAndImport(file); - ExtractedMods.Add((file, directory, null)); + ExtractedMods.Add(new ModImportResult(file, directory, null)); if (_config.AutoDeduplicateOnImport) { State = ImporterState.DeduplicatingFiles; @@ -116,7 +119,7 @@ private void ImportFiles() } catch (Exception e) { - ExtractedMods.Add((file, _currentModDirectory, e)); + ExtractedMods.Add(new ModImportResult(file, _currentModDirectory, e)); _currentNumOptions = 0; _currentOptionIdx = 0; _currentFileIdx = 0; diff --git a/Penumbra/Interop/Hooks/Animation/GetClipResources.cs b/Penumbra/Interop/Hooks/Animation/GetClipResources.cs new file mode 100644 index 00000000..c565744f --- /dev/null +++ b/Penumbra/Interop/Hooks/Animation/GetClipResources.cs @@ -0,0 +1,59 @@ +using FFXIVClientStructs.FFXIV.Client.System.Scheduler.Clip; +using Luna; +using Penumbra.Collections; +using Penumbra.CrashHandler.Buffers; +using Penumbra.GameData; +using Penumbra.GameData.Interop; +using Penumbra.Interop.PathResolving; +using Penumbra.Services; + +namespace Penumbra.Interop.Hooks.Animation; + +public sealed unsafe class GetClipResources : FastHook +{ + private readonly delegate* unmanaged _clipGameObject; + private readonly GameState _state; + private readonly CollectionResolver _collectionResolver; + private readonly CrashHandlerService _crashHandler; + + public GetClipResources(HookManager hooks, GameState state, CollectionResolver collectionResolver, ObjectManager objects, + CrashHandlerService crashHandler) + { + _state = state; + _collectionResolver = collectionResolver; + _crashHandler = crashHandler; + _clipGameObject = (delegate* unmanaged < BaseClip*, Actor >)hooks.SigScanner.ScanText(Sigs.BaseClipGetGameObject); + if (_clipGameObject is null) + throw new Exception($"Could not scan address {Sigs.BaseClipGetGameObject}."); + + Task = hooks.CreateHook("Get Clip Resources", Sigs.BaseClipGetClipResources, Detour, + !HookOverrides.Instance.Animation.GetClipResources); + } + + public delegate nint Delegate(BaseClip* clip); + + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + private nint Detour(BaseClip* clip) + { + if (clip is null) + return Task.Result!.Original(clip); + + var gameObject = _clipGameObject(clip); + var data = gameObject.Valid ? _collectionResolver.IdentifyCollection(gameObject.AsObject, true) : ResolveData.Invalid; + if (!data.Valid) + { + var ret2 = Task.Result!.Original(clip); + Penumbra.Log.Excessive($"[Get Clip Resources] Invoked on {(nint)clip:X} -> {ret2:X}."); + return ret2; + } + + var last = _state.SetSoundData(data); + _crashHandler.LogAnimation(data.AssociatedGameObject, data.ModCollection, AnimationInvocationType.GetClipResources); + var ret = Task.Result!.Original(clip); + _state.RestoreAnimationData(last); + Penumbra.Log.Excessive( + $"[Get Clip Resources] Invoked on {(nint)clip:X} for {data.AssociatedGameObject:X} ({data.ModCollection}) -> {ret:X}."); + return ret; + } +} diff --git a/Penumbra/Interop/Hooks/Animation/ScheduleClipUpdate.cs b/Penumbra/Interop/Hooks/Animation/ScheduleClipUpdate.cs index a1a3ab46..ff48a65f 100644 --- a/Penumbra/Interop/Hooks/Animation/ScheduleClipUpdate.cs +++ b/Penumbra/Interop/Hooks/Animation/ScheduleClipUpdate.cs @@ -23,7 +23,8 @@ public ScheduleClipUpdate(HookManager hooks, GameState state, CollectionResolver _collectionResolver = collectionResolver; _objects = objects; _crashHandler = crashHandler; - Task = hooks.CreateHook("Schedule Clip Update", Sigs.ScheduleClipUpdate, Detour, !HookOverrides.Instance.Animation.ScheduleClipUpdate); + Task = hooks.CreateHook("Schedule Clip Update", Sigs.ScheduleClipUpdate, Detour, + !HookOverrides.Instance.Animation.ScheduleClipUpdate); } public delegate void Delegate(ClipScheduler* x); diff --git a/Penumbra/Interop/Hooks/HookSettings.cs b/Penumbra/Interop/Hooks/HookSettings.cs index 49ee0309..2f5fc090 100644 --- a/Penumbra/Interop/Hooks/HookSettings.cs +++ b/Penumbra/Interop/Hooks/HookSettings.cs @@ -40,6 +40,7 @@ public struct AnimationHooks public bool LoadTimelineResources; public bool PlayFootstep; public bool ScheduleClipUpdate; + public bool GetClipResources; public bool SomeActionLoad; public bool SomeMountAnimation; public bool SomePapLoad; diff --git a/Penumbra/Meta/Files/CmpFile.cs b/Penumbra/Meta/Files/CmpFile.cs index 5c085fcc..fb50b670 100644 --- a/Penumbra/Meta/Files/CmpFile.cs +++ b/Penumbra/Meta/Files/CmpFile.cs @@ -16,13 +16,13 @@ public sealed unsafe class CmpFile : MetaBaseFile public static readonly CharacterUtility.InternalIndex InternalIndex = CharacterUtility.ReverseIndices[(int)MetaIndex.HumanCmp]; - public new GameData.Files.CmpData* Data - => (GameData.Files.CmpData*)base.Data; + public new CmpData* Data + => (CmpData*)base.Data; public RspEntry this[SubRace subRace, RspAttribute attribute] { - get => new(Data->GetScale(subRace).Get(attribute)); - set => Data->GetScale(subRace).Get(attribute) = value.Value; + get => new(Data->GetScaleWrite(subRace).Get(attribute)); + set => Data->GetScaleWrite(subRace).Get(attribute) = value.Value; } public override void Reset() @@ -43,15 +43,15 @@ public CmpFile(MetaFileManager manager) public static RspEntry GetDefault(MetaFileManager manager, SubRace subRace, RspAttribute attribute) { - var data = (GameData.Files.CmpData*)manager.CharacterUtility.DefaultResource(InternalIndex).Address; - return new RspEntry(data->GetScale(subRace).Get(attribute)); + var data = (CmpData*)manager.CharacterUtility.DefaultResource(InternalIndex).Address; + return new RspEntry(data->GetScaleWrite(subRace).Get(attribute)); } public static RspEntry* GetDefaults(MetaFileManager manager, SubRace subRace, RspAttribute attribute) { { - var data = (GameData.Files.CmpData*)manager.CharacterUtility.DefaultResource(InternalIndex).Address; - return (RspEntry*)Unsafe.AsPointer(ref data->GetScale(subRace).Get(attribute)); + var data = (CmpData*)manager.CharacterUtility.DefaultResource(InternalIndex).Address; + return (RspEntry*)Unsafe.AsPointer(ref data->GetScaleWrite(subRace).Get(attribute)); } } } diff --git a/Penumbra/Mods/Manager/ModImportManager.cs b/Penumbra/Mods/Manager/ModImportManager.cs index 43711788..13ad1730 100644 --- a/Penumbra/Mods/Manager/ModImportManager.cs +++ b/Penumbra/Mods/Manager/ModImportManager.cs @@ -13,29 +13,32 @@ public class ModImportManager( DuplicateManager duplicates, ModNormalizer modNormalizer, MigrationManager migrationManager, - FileCompactor compactor) : IDisposable, Luna.IService + FileCompactor compactor) : IDisposable, IService { - private readonly ConcurrentQueue _modsToUnpack = new(); + private readonly Dictionary _uniqueModsToUnpack = new(StringComparer.OrdinalIgnoreCase); + internal readonly Queue ModsToUnpack = new(); /// Mods need to be added thread-safely outside of iteration. private readonly ConcurrentQueue _modsToAdd = new(); private TexToolsImporter? _import; - - internal IEnumerable ModBatches - => _modsToUnpack; - internal IEnumerable AddableMods => _modsToAdd; - public void TryUnpacking() { - if (Importing && _import!.State is not ImporterState.Done || !_modsToUnpack.TryDequeue(out var newMods)) + if (Importing && _import!.State is not ImporterState.Done) return; - var files = newMods.Where(s => + UnpackRequest newMods; + lock (ModsToUnpack) + { + if (!ModsToUnpack.TryDequeue(out newMods)) + return; + } + + var files = newMods.Paths.Where(s => { if (File.Exists(s)) return true; @@ -47,10 +50,13 @@ public void TryUnpacking() Penumbra.Log.Debug($"Unpacking mods: {string.Join("\n\t", files.Select(f => f.FullName))}."); if (files.Length == 0) + { + newMods.TaskCompletionSource.SetResult([]); return; + } - _import = new TexToolsImporter(files.Length, files, AddNewMod, config, duplicates, modNormalizer, modManager, compactor, - migrationManager, _import); + _import = new TexToolsImporter(files.Length, files, AddNewMod, newMods.TaskCompletionSource, config, duplicates, modNormalizer, + modManager, compactor, migrationManager, _import); } public bool Importing @@ -62,13 +68,40 @@ public bool IsImporting([NotNullWhen(true)] out TexToolsImporter? importer) return _import != null; } - public void AddUnpack(IEnumerable paths) - => AddUnpack(paths.ToArray()); - - public void AddUnpack(params string[] paths) + public Task AddUnpack(params List paths) { - Penumbra.Log.Debug($"Adding mods to install: {string.Join("\n\t", paths)}"); - _modsToUnpack.Enqueue(paths); + lock (ModsToUnpack) + { + var now = DateTime.UtcNow; + var nowOffset = now.AddSeconds(-2); + for (var i = 0; i < paths.Count; ++i) + { + var path = paths[i]; + if (_uniqueModsToUnpack.TryGetValue(path, out var lastInstallTime)) + { + _uniqueModsToUnpack[path] = now; + if (lastInstallTime >= nowOffset) + { + paths.RemoveAt(i--); + Penumbra.Log.Debug($"Skipped installing mod {path} since it was last installed {(lastInstallTime - now).TotalSeconds} seconds ago."); + } + } + else + { + _uniqueModsToUnpack.Add(path, now); + } + } + + if (paths.Count > 0) + { + Penumbra.Log.Debug($"Adding mods to install: {string.Join("\n\t", paths)}"); + var tcs = new TaskCompletionSource(); + ModsToUnpack.Enqueue(new UnpackRequest(paths, tcs)); + return tcs.Task; + } + } + + return Task.FromResult(Array.Empty()); } public void ClearImport() @@ -93,7 +126,11 @@ public void Dispose() { ClearImport(); _modsToAdd.Clear(); - _modsToUnpack.Clear(); + lock (ModsToUnpack) + { + ModsToUnpack.Clear(); + _uniqueModsToUnpack.Clear(); + } } /// @@ -123,4 +160,6 @@ private void AddNewMod(FileInfo file, DirectoryInfo? dir, Exception? error) _modsToAdd.Enqueue(dir); } } + + internal readonly record struct UnpackRequest(List Paths, TaskCompletionSource TaskCompletionSource); } diff --git a/Penumbra/Mods/Manager/ModImportResult.cs b/Penumbra/Mods/Manager/ModImportResult.cs new file mode 100644 index 00000000..5350544c --- /dev/null +++ b/Penumbra/Mods/Manager/ModImportResult.cs @@ -0,0 +1,3 @@ +namespace Penumbra.Mods.Manager; + +public readonly record struct ModImportResult(FileInfo File, DirectoryInfo? Mod, Exception? Error); diff --git a/Penumbra/Services/ConfigMigrationService.cs b/Penumbra/Services/ConfigMigrationService.cs index 47638774..5006fb87 100644 --- a/Penumbra/Services/ConfigMigrationService.cs +++ b/Penumbra/Services/ConfigMigrationService.cs @@ -182,7 +182,6 @@ private void Version7To8() _config.Ephemeral.SelectedTab = _data["SelectedTab"]?.ToObject() ?? _config.Ephemeral.SelectedTab; _config.Filters.ChangedItemTypeFilter = _data["ChangedItemFilter"]?.ToObject() ?? _config.Filters.ChangedItemTypeFilter; - _config.Ephemeral.FixMainWindow = _data["FixMainWindow"]?.ToObject() ?? _config.Ephemeral.FixMainWindow; _config.Ephemeral.Save(); } diff --git a/Penumbra/Services/FileWatcher.cs b/Penumbra/Services/FileWatcher.cs index 756ff645..638996e0 100644 --- a/Penumbra/Services/FileWatcher.cs +++ b/Penumbra/Services/FileWatcher.cs @@ -306,12 +306,16 @@ private static async Task WaitForStableAsync(string path, CancellationToke return false; } - private void TriggerImport(string path) + private Task TriggerImport(string path) { if (_config.EnableAutomaticModImport) - _modImportManager.AddUnpack(path); + return _modImportManager.AddUnpack(path); else - _messageService.AddMessage(new InstallNotification(_modImportManager, path), false); + { + var tcs = new TaskCompletionSource(); + _messageService.AddMessage(new InstallNotification(_modImportManager, path, tcs), false); + return tcs.Task; + } } /// diff --git a/Penumbra/Services/InstallNotification.cs b/Penumbra/Services/InstallNotification.cs index 71c6884f..44c665ca 100644 --- a/Penumbra/Services/InstallNotification.cs +++ b/Penumbra/Services/InstallNotification.cs @@ -6,8 +6,11 @@ namespace Penumbra.Services; -public class InstallNotification(ModImportManager modImportManager, string filePath) : Luna.IMessage +public class InstallNotification(ModImportManager modImportManager, string filePath, TaskCompletionSource tcs) + : Luna.INotificationAwareMessage { + private bool _reportCancellationOnDismissal = true; + public NotificationType NotificationType => NotificationType.Info; @@ -37,7 +40,9 @@ public void OnNotificationActions(INotificationDrawArgs args) var buttonSize = new Vector2((region.X - Im.Style.ItemSpacing.X) / 2, 0); if (Im.Button("Install"u8, buttonSize)) { - modImportManager.AddUnpack(filePath); + _reportCancellationOnDismissal = false; + modImportManager.AddUnpack(filePath) + .ContinueWith(tcs.SetFromTask); args.Notification.DismissNow(); } @@ -45,4 +50,13 @@ public void OnNotificationActions(INotificationDrawArgs args) if (Im.Button("Ignore"u8, buttonSize)) args.Notification.DismissNow(); } + + public void OnNotificationCreated(IActiveNotification notification) + { + notification.Dismiss += _ => + { + if (_reportCancellationOnDismissal) + tcs.SetResult([]); + }; + } } diff --git a/Penumbra/UI/GlobalModImporter.cs b/Penumbra/UI/GlobalModImporter.cs index 2e63cd23..4c99ecb1 100644 --- a/Penumbra/UI/GlobalModImporter.cs +++ b/Penumbra/UI/GlobalModImporter.cs @@ -46,7 +46,7 @@ public void Dispose() } private void ImportFiles(IReadOnlyList files, IReadOnlyList _) - => _importManager.AddUnpack(files.Where(f => ValidModExtensions.Contains(Path.GetExtension(f)))); + => _importManager.AddUnpack(files.Where(f => ValidModExtensions.Contains(Path.GetExtension(f))).ToList()); private static bool ValidExtension(IDragDropManager manager) => manager.Extensions.Any(ValidModExtensions.Contains); diff --git a/Penumbra/UI/ImportPopup.cs b/Penumbra/UI/ImportPopup.cs index afb910e2..711a424b 100644 --- a/Penumbra/UI/ImportPopup.cs +++ b/Penumbra/UI/ImportPopup.cs @@ -11,12 +11,11 @@ using MessageService = Penumbra.Services.MessageService; using MouseButton = ImSharp.MouseButton; using Notification = Luna.Notification; -using Window = Luna.Window; namespace Penumbra.UI; /// Draw the progress information for import. -public sealed class ImportPopup : Window, INotificationAwareMessage +public sealed class ImportPopup : OverlayWindow, INotificationAwareMessage { public const string WindowLabel = "Penumbra Import Status"; diff --git a/Penumbra/UI/MainWindow/MainWindow.cs b/Penumbra/UI/MainWindow/MainWindow.cs index f950439a..02d9a5d7 100644 --- a/Penumbra/UI/MainWindow/MainWindow.cs +++ b/Penumbra/UI/MainWindow/MainWindow.cs @@ -55,10 +55,6 @@ public override bool DrawConditions() public override void PreDraw() { - if (_config.Ephemeral.FixMainWindow) - Flags |= WindowFlags.NoResize | WindowFlags.NoMove; - else - Flags &= ~(WindowFlags.NoResize | WindowFlags.NoMove); SizeConstraints = new WindowSizeConstraints { MinimumSize = _config.MinimumSize, diff --git a/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs b/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs index 6cc92ed0..26dbd289 100644 --- a/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs @@ -205,7 +205,6 @@ private void DrawCollapseHandling(IReadOnlyList options, float minWi draw(); } - var width = Math.Max(Im.Item.Size.X, minWidth); var endPos = Im.Cursor.Position; Im.Cursor.Position = pos; diff --git a/Penumbra/UI/Tabs/Debug/CmpDrawer.cs b/Penumbra/UI/Tabs/Debug/CmpDrawer.cs index 154497eb..6f7524fe 100644 --- a/Penumbra/UI/Tabs/Debug/CmpDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/CmpDrawer.cs @@ -42,7 +42,7 @@ private void DrawScales() foreach (var (name, race) in SubRace.NamesAndValuesU8.Skip(1)) { table.DrawColumn(name); - ref var values = ref _ptr->GetScale(race); + ref var values = ref _ptr->GetScaleWrite(race); foreach (var attribute in RspAttribute.Values.SkipLast(1)) table.DrawColumn($"{values.Get(attribute):F4}"); } @@ -96,19 +96,23 @@ private void DrawColors() ImEx.TextCentered($"{name.ToShortNameU8()}"); } - ref var eyesUi = ref _ptr->Interface.Eyes; - ref var highlightsUi = ref _ptr->Interface.HairHighlights; - ref var featuresUi = ref _ptr->Interface.Features; - var lipsUi = new CmpData.ColorsPair(ref _ptr->Interface.LipsDark, ref _ptr->Interface.LipsLight); - var facePaintUi = new CmpData.ColorsPair(ref _ptr->Interface.FacePaintDark, ref _ptr->Interface.FacePaintLight); - - ref var eyes = ref _ptr->Parameters.Eyes; - ref var highlights = ref _ptr->Parameters.HairHighlights; - ref var features = ref _ptr->Parameters.Features; - var lips = new CmpData.ColorsPair(ref _ptr->Parameters.LipsDark, ref _ptr->Parameters.LipsLight); - var facePaint = new CmpData.ColorsPair(ref _ptr->Parameters.FacePaintDark, ref _ptr->Parameters.FacePaintLight); - - using var clip = new Im.ListClipper(256, Im.Style.FrameHeightWithSpacing); + ref var eyesUi = ref _ptr->Interface.Eyes; + ref var highlightsUi = ref _ptr->Interface.HairHighlights; + ref var featuresUi = ref _ptr->Interface.Features; + ref var lipsUiDark = ref _ptr->Interface.LipsDark; + ref var lipsUiLight = ref _ptr->Interface.LipsLight; + ref var facePaintUiDark = ref _ptr->Interface.FacePaintDark; + ref var facePaintUiLight = ref _ptr->Interface.FacePaintLight; + + ref var eyes = ref _ptr->Parameters.Eyes; + ref var highlights = ref _ptr->Parameters.HairHighlights; + ref var features = ref _ptr->Parameters.Features; + ref var lipsDark = ref _ptr->Parameters.LipsDark; + ref var lipsLight = ref _ptr->Parameters.LipsLight; + ref var facePaintDark = ref _ptr->Parameters.FacePaintDark; + ref var facePaintLight = ref _ptr->Parameters.FacePaintLight; + + using var clip = new Im.ListClipper(256, Im.Style.FrameHeightWithSpacing); foreach (var index in clip) { using var id = Im.Id.Push(index); @@ -130,14 +134,14 @@ private void DrawColors() Im.Color.Button("Features Color"u8, features[index]); table.NextColumn(); - Im.Color.Button("Lips UI Color"u8, lipsUi[index]); + Im.Color.Button("Lips UI Color"u8, index < 128 ? lipsUiDark[index] : lipsUiLight[index - 128]); Im.Line.SameInner(); - Im.Color.Button("Lips Color"u8, lips[index]); + Im.Color.Button("Lips Color"u8, index < 128 ? lipsDark[index] : lipsLight[index - 128]); table.NextColumn(); - Im.Color.Button("Face Paint UI Color"u8, facePaintUi[index]); + Im.Color.Button("Face Paint UI Color"u8, index < 128 ? facePaintUiDark[index] : facePaintUiLight[index - 128]); Im.Line.SameInner(); - Im.Color.Button("Face Paint Color"u8, facePaint[index]); + Im.Color.Button("Face Paint Color"u8, index < 128 ? facePaintDark[index] : facePaintLight[index - 128]); foreach (var race in SubRace.Values.Skip(1)) { @@ -147,7 +151,7 @@ private void DrawColors() Im.Line.SameInner(); Im.Color.Button($"Skin UI Color ({name} Male)", _ptr->GetSkin(race, Gender.Male, true)[index]); Im.Line.SameInner(); - Im.Color.Button($"Skin Color ({name} Male)", _ptr->GetSkin(race, Gender.Male, false)[index]); + Im.Color.Button($"Skin Color ({name} Male)", _ptr->GetSkin(race, Gender.Male, false)[index]); Im.Line.Same(); ImEx.TextFramed("♀"u8, default, Rgba32.Transparent); Im.Line.SameInner(); diff --git a/Penumbra/UI/Tabs/Debug/DebugTab.cs b/Penumbra/UI/Tabs/Debug/DebugTab.cs index 6fed1094..9706e683 100644 --- a/Penumbra/UI/Tabs/Debug/DebugTab.cs +++ b/Penumbra/UI/Tabs/Debug/DebugTab.cs @@ -380,10 +380,13 @@ private void DrawDebugTabGeneral() table.DrawDataPair("Import Popup Was Drawn"u8, _importPopup.PopupWasDrawn); table.DrawColumn("Import Batches"u8); table.NextColumn(); - foreach (var (index, batch) in _modImporter.ModBatches.Index()) + lock (_modImporter.ModsToUnpack) { - foreach (var mod in batch) - table.DrawDataPair($"{index}", mod); + foreach (var (index, batch) in _modImporter.ModsToUnpack.Index()) + { + foreach (var mod in batch.Paths) + table.DrawDataPair($"{index}", mod); + } } table.DrawColumn("Addable Mods"u8); diff --git a/Penumbra/UI/Tabs/SettingsTab.cs b/Penumbra/UI/Tabs/SettingsTab.cs index 2f68b5cb..499a87cf 100644 --- a/Penumbra/UI/Tabs/SettingsTab.cs +++ b/Penumbra/UI/Tabs/SettingsTab.cs @@ -107,8 +107,7 @@ public void DrawContent() return; DrawEnabledBox(); - EphemeralCheckbox("Lock Main Window"u8, "Prevent the main window from being resized or moved."u8, _config.Ephemeral.FixMainWindow, - v => _config.Ephemeral.FixMainWindow = v); + Im.Line.New(); Im.Line.New(); DrawRootFolder();