diff --git a/Luna b/Luna index 2870892f..e69b638e 160000 --- a/Luna +++ b/Luna @@ -1 +1 @@ -Subproject commit 2870892f30f7b92bd74110c7da366779eae85ce7 +Subproject commit e69b638efaf89468517fe3741a300c8d3a7c6860 diff --git a/Penumbra.GameData b/Penumbra.GameData index 3a5a03ff..0901f2b7 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 3a5a03ff24e24151f80584cd4a8d45b36d94db36 +Subproject commit 0901f2b7075c280c5216198921a3c09209b667d8 diff --git a/Penumbra/Collections/Manager/ActiveCollectionMigration.cs b/Penumbra/Collections/Manager/ActiveCollectionMigration.cs index 6b8df9e0..5bda2c43 100644 --- a/Penumbra/Collections/Manager/ActiveCollectionMigration.cs +++ b/Penumbra/Collections/Manager/ActiveCollectionMigration.cs @@ -14,7 +14,7 @@ public static class ActiveCollectionMigration if (!ActiveCollections.Load(fileNames, out var jObject)) return; - foreach (var (type, _, _) in CollectionTypeExtensions.Special.Where(t => t.Item2.StartsWith("Male "))) + foreach (var (type, _, _) in CollectionTypeExtensions.Special.Where(t => t.Item2.StartsWith("Male "u8))) { var oldName = type.ToString()[4..]; var value = jObject[oldName]; diff --git a/Penumbra/Collections/Manager/CollectionType.cs b/Penumbra/Collections/Manager/CollectionType.cs index c25413b8..02f26028 100644 --- a/Penumbra/Collections/Manager/CollectionType.cs +++ b/Penumbra/Collections/Manager/CollectionType.cs @@ -1,3 +1,4 @@ +using ImSharp; using Penumbra.GameData.Enums; namespace Penumbra.Collections.Manager; @@ -110,9 +111,9 @@ public static class CollectionTypeExtensions public static bool CanBeRemoved(this CollectionType collectionType) => collectionType.IsSpecial() || collectionType is CollectionType.Individual; - public static readonly (CollectionType, string, string)[] Special = Enum.GetValues() + public static readonly (CollectionType, StringU8, StringU8)[] Special = Enum.GetValues() .Where(IsSpecial) - .Select(s => (s, s.ToName(), s.ToDescription())) + .Select(s => (s, new StringU8(s.ToName()), new StringU8(s.ToDescription()))) .ToArray(); public static CollectionType FromParts(Gender gender, bool npc) @@ -427,16 +428,16 @@ public static class CollectionTypeExtensions _ => string.Empty, }; - public static string ToDescription(this CollectionType collectionType) + public static ReadOnlySpan ToDescription(this CollectionType collectionType) => collectionType switch { - CollectionType.Default => "World, Music, Furniture, baseline for characters and monsters not specialized.", - CollectionType.Interface => "User Interface, Icons, Maps, Styles.", - CollectionType.Yourself => "Your characters, regardless of name, race or gender. Applies in the login screen.", - CollectionType.MalePlayerCharacter => "Baseline for male player characters.", - CollectionType.FemalePlayerCharacter => "Baseline for female player characters.", - CollectionType.MaleNonPlayerCharacter => "Baseline for humanoid male non-player characters.", - CollectionType.FemaleNonPlayerCharacter => "Baseline for humanoid female non-player characters.", - _ => string.Empty, + CollectionType.Default => "World, Music, Furniture, baseline for characters and monsters not specialized."u8, + CollectionType.Interface => "User Interface, Icons, Maps, Styles."u8, + CollectionType.Yourself => "Your characters, regardless of name, race or gender. Applies in the login screen."u8, + CollectionType.MalePlayerCharacter => "Baseline for male player characters."u8, + CollectionType.FemalePlayerCharacter => "Baseline for female player characters."u8, + CollectionType.MaleNonPlayerCharacter => "Baseline for humanoid male non-player characters."u8, + CollectionType.FemaleNonPlayerCharacter => "Baseline for humanoid female non-player characters."u8, + _ => StringU8.Empty, }; } diff --git a/Penumbra/CommandHandler.cs b/Penumbra/CommandHandler.cs index 8a3e502c..11e70b1c 100644 --- a/Penumbra/CommandHandler.cs +++ b/Penumbra/CommandHandler.cs @@ -1,7 +1,7 @@ using Dalamud.Game.Command; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImSharp; using Luna; using Penumbra.Api.Api; using Penumbra.Api.Enums; @@ -211,12 +211,12 @@ public class CommandHandler : IDisposable, IApiService if (value) { Print("Penumbra UI locked in place."); - _configWindow.Flags |= ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize; + _configWindow.Flags |= WindowFlags.NoMove | WindowFlags.NoResize; } else { Print("Penumbra UI unlocked."); - _configWindow.Flags &= ~(ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize); + _configWindow.Flags &= ~(WindowFlags.NoMove | WindowFlags.NoResize); } _config.Ephemeral.FixMainWindow = value; diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index e3ca27a7..e4e09cf8 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -169,7 +169,7 @@ public class Configuration : IPluginConfiguration, ISavable, IService /// Contains some default values or boundaries for config values. public static class Constants { - public const int CurrentVersion = 9; + public const int CurrentVersion = 10; public const float MaxAbsoluteSize = 600; public const int DefaultAbsoluteSize = 250; public const float MinAbsoluteSize = 50; diff --git a/Penumbra/Import/Textures/TextureDrawer.cs b/Penumbra/Import/Textures/TextureDrawer.cs index ba217209..eaca8927 100644 --- a/Penumbra/Import/Textures/TextureDrawer.cs +++ b/Penumbra/Import/Textures/TextureDrawer.cs @@ -42,7 +42,7 @@ public static class TextureDrawer string startPath, FileDialogService fileDialog, string defaultModImportPath) { tmpPath ??= current.Path; - using var spacing = ImStyleDouble.ItemSpacing.PushX(UiHelpers.ScaleX3); + using var spacing = ImStyleDouble.ItemSpacing.PushX(Im.Style.GlobalScale * 3); Im.Item.SetNextWidth(-2 * Im.Style.FrameHeight - 7 * Im.Style.GlobalScale); if (ImEx.InputOnDeactivation.Text(label, tmpPath, out tmpPath, hint)) current.Load(textures, tmpPath); diff --git a/Penumbra/Interop/Services/TextureArraySlicer.cs b/Penumbra/Interop/Services/TextureArraySlicer.cs index ac20b923..5e2526da 100644 --- a/Penumbra/Interop/Services/TextureArraySlicer.cs +++ b/Penumbra/Interop/Services/TextureArraySlicer.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; +using ImSharp; using SharpDX.Direct3D; using SharpDX.Direct3D11; @@ -16,7 +16,7 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable private readonly HashSet<(nint XivTexture, byte SliceIndex)> _expiredKeys = []; /// Caching this across frames will cause a crash to desktop. - public ImTextureID GetImGuiHandle(Texture* texture, byte sliceIndex) + public ImTextureId GetImGuiHandle(Texture* texture, byte sliceIndex) { if (texture == null) throw new ArgumentNullException(nameof(texture)); @@ -25,7 +25,7 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable if (_activeSlices.TryGetValue(((nint)texture, sliceIndex), out var state)) { state.Refresh(); - return new ImTextureID((nint)state.ShaderResourceView); + return new ImTextureId((nint)state.ShaderResourceView); } var srv = (ShaderResourceView)(nint)texture->D3D11ShaderResourceView; var description = srv.Description; @@ -60,7 +60,7 @@ public sealed unsafe class TextureArraySlicer : Luna.IUiService, IDisposable } state = new SliceState(new ShaderResourceView(srv.Device, srv.Resource, description)); _activeSlices.Add(((nint)texture, sliceIndex), state); - return new ImTextureID((nint)state.ShaderResourceView); + return new ImTextureId((nint)state.ShaderResourceView); } public void Tick() diff --git a/Penumbra/Mods/Manager/ModDataEditor.cs b/Penumbra/Mods/Manager/ModDataEditor.cs index 1bbdb67f..a151af6d 100644 --- a/Penumbra/Mods/Manager/ModDataEditor.cs +++ b/Penumbra/Mods/Manager/ModDataEditor.cs @@ -7,25 +7,27 @@ using Penumbra.Services; namespace Penumbra.Mods.Manager; [Flags] -public enum ModDataChangeType : ushort +public enum ModDataChangeType : uint { - None = 0x0000, - Name = 0x0001, - Author = 0x0002, - Description = 0x0004, - Version = 0x0008, - Website = 0x0010, - Deletion = 0x0020, - Migration = 0x0040, - ModTags = 0x0080, - ImportDate = 0x0100, - Favorite = 0x0200, - LocalTags = 0x0400, - Note = 0x0800, - Image = 0x1000, - DefaultChangedItems = 0x2000, - PreferredChangedItems = 0x4000, - RequiredFeatures = 0x8000, + None = 0x000000, + Name = 0x000001, + Author = 0x000002, + Description = 0x000004, + Version = 0x000008, + Website = 0x000010, + Deletion = 0x000020, + Migration = 0x000040, + ModTags = 0x000080, + ImportDate = 0x000100, + Favorite = 0x000200, + LocalTags = 0x000400, + Note = 0x000800, + Image = 0x001000, + DefaultChangedItems = 0x002000, + PreferredChangedItems = 0x004000, + RequiredFeatures = 0x008000, + FileSystemFolder = 0x010000, + FileSystemSortOrder = 0x020000, } public class ModDataEditor(SaveService saveService, CommunicatorService communicatorService, ItemData itemData) : Luna.IService diff --git a/Penumbra/Mods/Manager/ModFileSystem.cs b/Penumbra/Mods/Manager/ModFileSystem.cs index 7cbd611d..c1f8b96b 100644 --- a/Penumbra/Mods/Manager/ModFileSystem.cs +++ b/Penumbra/Mods/Manager/ModFileSystem.cs @@ -7,102 +7,73 @@ using FileSystemChangeType = OtterGui.Filesystem.FileSystemChangeType; namespace Penumbra.Mods.Manager; -//public sealed class ModFileSystem2 : BaseFileSystem -//{ -// private readonly Configuration _config; -// private readonly SaveService _saveService; -// public ModFileSystem2(FileSystemChanged @event, DataNodePathChange dataChangeEvent, Configuration config, SaveService saveService, IComparer>? comparer = null) -// : base(@event, dataChangeEvent, comparer) -// { -// _config = config; -// _saveService = saveService; -// } -// -// public void Dispose() -// { -// _communicator.ModPathChanged.Unsubscribe(OnModPathChange); -// _communicator.ModDiscoveryFinished.Unsubscribe(Reload); -// _communicator.ModDataChanged.Unsubscribe(OnModDataChange); -// } -// -// // Save the filesystem on every filesystem change except full reloading. -// private void OnChange(FileSystemChangeType type, IPath _1, IPath? _2, IPath? _3) -// { -// if (type != FileSystemChangeType.Reload) -// _saveService.DelaySave(this); -// } -// -// // Update sort order when defaulted mod names change. -// private void OnModDataChange(in ModDataChanged.Arguments arguments) -// { -// if (!arguments.Type.HasFlag(ModDataChangeType.Name) || arguments.OldName == null || !TryGetValue(arguments.Mod, out var leaf)) -// return; -// -// var old = Extensions.FixName(arguments.OldName); -// if (old == leaf.Name || Extensions.IsDuplicateName(leaf.Name, out var baseName, out _) && baseName == old) -// RenameWithDuplicates(leaf, arguments.Mod.Name); -// } -// -// // Update the filesystem if a mod has been added or removed. -// // Save it, if the mod directory has been moved, since this will change the save format. -// private void OnModPathChange(in ModPathChanged.Arguments arguments) -// { -// switch (arguments.Type) -// { -// case ModPathChangeType.Added: -// var parent = Root; -// if (_config.DefaultImportFolder.Length != 0) -// try -// { -// parent = FindOrCreateAllFolders(_config.DefaultImportFolder); -// } -// catch (Exception e) -// { -// Penumbra.Messager.NotificationMessage(e, -// $"Could not move newly imported mod {arguments.Mod.Name} to default import folder {_config.DefaultImportFolder}.", -// NotificationType.Warning); -// } -// -// CreateDuplicateLeaf(parent, arguments.Mod.Name, arguments.Mod); -// break; -// case ModPathChangeType.Deleted: -// if (arguments.Mod.Node is not null) -// Delete(arguments.Mod.Node); -// break; -// case ModPathChangeType.Moved: -// _saveService.DelaySave(this); -// break; -// case ModPathChangeType.Reloaded: -// // Nothing -// break; -// } -// } -// -// public struct ImportDate : ISortMode -// { -// public ReadOnlySpan Name -// => "Import Date (Older First)"u8; -// -// public ReadOnlySpan Description -// => "In each folder, sort all subfolders lexicographically, then sort all leaves using their import date."u8; -// -// public IEnumerable GetChildren(IFileSystemFolder f) -// => f.GetSubFolders().Cast().Concat(f.GetLeaves().OfType>().OrderBy(l => l.Value.ImportDate)); -// } -// -// public struct InverseImportDate : ISortMode -// { -// public ReadOnlySpan Name -// => "Import Date (Newer First)"u8; -// -// public ReadOnlySpan Description -// => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse import date."u8; -// -// public IEnumerable GetChildren(IFileSystemFolder f) -// => f.GetSubFolders().Cast().Concat(f.GetLeaves().OfType>().OrderByDescending(l => l.Value.ImportDate)); -// } -// -//} +public sealed class ModFileSystem2 : BaseFileSystem, IDisposable, IRequiredService +{ + private readonly Configuration _config; + private readonly CommunicatorService _communicator; + private readonly ModFileSystemSaver _saver; + + public ModFileSystem2(Configuration config, CommunicatorService communicator, SaveService saveService, Logger log, ModStorage modStorage) + : base("ModFileSystem", log) + { + _config = config; + _communicator = communicator; + _saver = new ModFileSystemSaver(log, this, saveService, modStorage); + _communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModFileSystem); + _communicator.ModDiscoveryFinished.Subscribe(_saver.Load, ModDiscoveryFinished.Priority.ModFileSystem); + _communicator.ModDataChanged.Subscribe(OnModDataChange, ModDataChanged.Priority.ModFileSystem); + _saver.Load(); + } + + public void Dispose() + { + _communicator.ModPathChanged.Unsubscribe(OnModPathChange); + _communicator.ModDiscoveryFinished.Unsubscribe(_saver.Load); + _communicator.ModDataChanged.Unsubscribe(OnModDataChange); + } + + // Update sort order when defaulted mod names change. + private void OnModDataChange(in ModDataChanged.Arguments arguments) + { + if (arguments.Type.HasFlag(ModDataChangeType.FileSystemFolder)) + RenameAndMoveWithDuplicates(arguments.Mod.Node!, arguments.Mod.Path.GetIntendedPath(arguments.Mod.Name)); + else if (arguments.Type.HasFlag(ModDataChangeType.Name) && arguments.Mod.Path.SortName is null + || arguments.Type.HasFlag(ModDataChangeType.FileSystemSortOrder)) + RenameWithDuplicates(arguments.Mod.Node!, arguments.Mod.Path.GetIntendedName(arguments.Mod.Name)); + } + + // Update the filesystem if a mod has been added or removed. + // Save it, if the mod directory has been moved, since this will change the save format. + private void OnModPathChange(in ModPathChanged.Arguments arguments) + { + switch (arguments.Type) + { + case ModPathChangeType.Added: + var parent = Root; + if (_config.DefaultImportFolder.Length is not 0) + try + { + parent = FindOrCreateAllFolders(_config.DefaultImportFolder); + } + catch (Exception e) + { + Penumbra.Messager.NotificationMessage(e, + $"Could not move newly imported mod {arguments.Mod.Name} to default import folder {_config.DefaultImportFolder}.", + NotificationType.Warning); + } + + CreateDuplicateDataNode(parent, arguments.Mod.Name, arguments.Mod); + break; + case ModPathChangeType.Deleted: + if (arguments.Mod.Node is not null) + Delete(arguments.Mod.Node); + break; + case ModPathChangeType.Reloaded: + // Nothing + break; + } + } +} public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, IService { @@ -160,7 +131,7 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer // Used on construction and on mod rediscoveries. private void Reload() { - var jObj = BackupService.GetJObjectForFile(_saveService.FileNames, _saveService.FileNames.FilesystemFile); + var jObj = BackupService.GetJObjectForFile(_saveService.FileNames, _saveService.FileNames.OldFilesystemFile); if (Load(jObj, _modManager, ModToIdentifier, ModToName)) _saveService.ImmediateSave(this); @@ -212,9 +183,7 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer Delete(leaf); break; - case ModPathChangeType.Moved: - _saveService.DelaySave(this); - break; + case ModPathChangeType.Moved: _saveService.DelaySave(this); break; case ModPathChangeType.Reloaded: // Nothing break; @@ -232,7 +201,7 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer public static bool ModHasDefaultPath(Mod mod, string fullPath) { var regex = new Regex($@"^{Regex.Escape(ModToName(mod))}( \(\d+\))?$"); - return regex.IsMatch(fullPath); + return regex.IsMatch(fullPath); } private static (string, bool) SaveMod(Mod mod, string fullPath) @@ -242,7 +211,7 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer : (ModToIdentifier(mod), true); public string ToFilePath(FilenameService fileNames) - => fileNames.FilesystemFile; + => fileNames.OldFilesystemFile; public void Save(StreamWriter writer) => SaveToFile(writer, SaveMod, true); diff --git a/Penumbra/Mods/Manager/ModFileSystemSaver.cs b/Penumbra/Mods/Manager/ModFileSystemSaver.cs new file mode 100644 index 00000000..a88d73b9 --- /dev/null +++ b/Penumbra/Mods/Manager/ModFileSystemSaver.cs @@ -0,0 +1,54 @@ +using Luna; +using Penumbra.Services; + +namespace Penumbra.Mods.Manager; + +public sealed class ModFileSystemSaver(Logger log, BaseFileSystem fileSystem, SaveService saveService, ModStorage mods) + : FileSystemSaver(log, fileSystem, saveService) +{ + protected override string LockedFile(FilenameService provider) + => provider.FileSystemLockedNodes; + + protected override string ExpandedFile(FilenameService provider) + => provider.FileSystemExpandedFolders; + + protected override string EmptyFoldersFile(FilenameService provider) + => provider.FileSystemEmptyFolders; + + protected override string MigrationFile(FilenameService provider) + => provider.OldFilesystemFile; + + protected override bool GetValueFromIdentifier(ReadOnlySpan identifier, [NotNullWhen(true)] out IFileSystemValue? value) + { + if (mods.TryGetMod(identifier, out var mod)) + { + value = mod; + return true; + } + + value = null; + return false; + } + + protected override void CreateDataNodes() + { + foreach (var mod in mods) + { + try + { + var folder = mod.Path.Folder.Length is 0 ? FileSystem.Root : FileSystem.FindOrCreateAllFolders(mod.Path.Folder); + FileSystem.CreateDuplicateDataNode(folder, mod.Path.SortName ?? mod.Name, mod); + } + catch (Exception e) + { + Log.Error($"Could not create folder structure for mod {mod.Name} at path {mod.Path.Folder}: {e}"); + } + } + } + + protected override void SaveDataValue(IFileSystemValue value) + { + if (value is Mod mod) + SaveService.QueueSave(new ModLocalData(mod)); + } +} diff --git a/Penumbra/Mods/Manager/ModStorage.cs b/Penumbra/Mods/Manager/ModStorage.cs index 7989f206..4458f3f5 100644 --- a/Penumbra/Mods/Manager/ModStorage.cs +++ b/Penumbra/Mods/Manager/ModStorage.cs @@ -20,20 +20,27 @@ public class ModStorage : IReadOnlyList IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - /// - /// Try to obtain a mod by its directory name (unique identifier). - /// - public bool TryGetMod(string identifier, [NotNullWhen(true)] out Mod? mod) + /// Try to obtain a mod by its directory name (unique identifier). + public bool TryGetMod(ReadOnlySpan identifier, [NotNullWhen(true)] out Mod? mod) { - mod = this.FirstOrDefault(m => string.Equals(m.Identifier, identifier, StringComparison.OrdinalIgnoreCase)); - return mod is not null; + foreach (var m in Mods) + { + if (!identifier.Equals(m.Identifier, StringComparison.OrdinalIgnoreCase)) + continue; + + mod = m; + return true; + } + + mod = null; + return false; } /// /// Try to obtain a mod by its directory name (unique identifier, preferred), /// or the first mod of the given name if no directory fits. /// - public bool TryGetMod(string identifier, string modName, [NotNullWhen(true)] out Mod? mod) + public bool TryGetMod(ReadOnlySpan identifier, ReadOnlySpan modName, [NotNullWhen(true)] out Mod? mod) { if (modName.Length is 0) return TryGetMod(identifier, out mod); @@ -41,13 +48,13 @@ public class ModStorage : IReadOnlyList mod = null; foreach (var m in Mods) { - if (string.Equals(m.Identifier, identifier, StringComparison.OrdinalIgnoreCase)) + if (identifier.Equals(m.Identifier, StringComparison.OrdinalIgnoreCase)) { mod = m; return true; } - if (m.Name == modName) + if (m.Name.SequenceEqual(modName)) mod ??= m; } diff --git a/Penumbra/Mods/Manager/SortModes.cs b/Penumbra/Mods/Manager/SortModes.cs new file mode 100644 index 00000000..247c14a4 --- /dev/null +++ b/Penumbra/Mods/Manager/SortModes.cs @@ -0,0 +1,28 @@ +using Luna; + +namespace Penumbra.Mods.Manager; + +public readonly struct ImportDate : ISortMode +{ + public ReadOnlySpan Name + => "Import Date (Older First)"u8; + + public ReadOnlySpan Description + => "In each folder, sort all subfolders lexicographically, then sort all leaves using their import date."u8; + + public IEnumerable GetChildren(IFileSystemFolder f) + => f.GetSubFolders().Cast().Concat(f.GetLeaves().OfType>().OrderBy(l => l.Value.ImportDate)); +} + +public readonly struct InverseImportDate : ISortMode +{ + public ReadOnlySpan Name + => "Import Date (Newer First)"u8; + + public ReadOnlySpan Description + => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse import date."u8; + + public IEnumerable GetChildren(IFileSystemFolder f) + => f.GetSubFolders().Cast() + .Concat(f.GetLeaves().OfType>().OrderByDescending(l => l.Value.ImportDate)); +} diff --git a/Penumbra/Mods/Mod.cs b/Penumbra/Mods/Mod.cs index 7bdcba0d..af194949 100644 --- a/Penumbra/Mods/Mod.cs +++ b/Penumbra/Mods/Mod.cs @@ -69,7 +69,7 @@ public sealed class Mod : IMod, IFileSystemValue // Local Data - public string FullPath { get; set; } = string.Empty; + public DataPath Path { get; } = new(); public long ImportDate { get; internal set; } = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds(); public IReadOnlyList LocalTags { get; internal set; } = []; public string Note { get; internal set; } = string.Empty; @@ -137,9 +137,12 @@ public sealed class Mod : IMod, IFileSystemValue public string LowerChangedItemsString { get; internal set; } = string.Empty; public string AllTagsLower { get; internal set; } = string.Empty; - public int TotalFileCount { get; internal set; } - public int TotalSwapCount { get; internal set; } - public int TotalManipulations { get; internal set; } - public ushort LastChangedItemsUpdate { get; internal set; } - public bool HasOptions { get; internal set; } + public int TotalFileCount { get; internal set; } + public int TotalSwapCount { get; internal set; } + public int TotalManipulations { get; internal set; } + public ushort LastChangedItemsUpdate { get; internal set; } + public bool HasOptions { get; internal set; } + + string IFileSystemValue.DisplayName + => Name; } diff --git a/Penumbra/Mods/ModLocalData.cs b/Penumbra/Mods/ModLocalData.cs index b4cc9405..5991d313 100644 --- a/Penumbra/Mods/ModLocalData.cs +++ b/Penumbra/Mods/ModLocalData.cs @@ -26,11 +26,10 @@ public readonly struct ModLocalData(Mod mod) : ISavable { nameof(Mod.PreferredChangedItems), JToken.FromObject(mod.PreferredChangedItems) }, }; - if (mod.FullPath.Length > 0) - { - var baseName = mod.FullPath.GetBaseName(mod.Name, out var folder); - jObject[nameof(Mod.FullPath)] = folder.Length > 0 ? $"{folder}/{baseName}" : baseName.ToString(); - } + if (mod.Path.Folder.Length > 0) + jObject["FileSystemFolder"] = mod.Path.Folder; + if (mod.Path.SortName is not null) + jObject["SortOrderName"] = mod.Path.SortName; using var jWriter = new JsonTextWriter(writer); jWriter.Formatting = Formatting.Indented; @@ -41,10 +40,12 @@ public readonly struct ModLocalData(Mod mod) : ISavable { var dataFile = editor.SaveService.FileNames.LocalDataFile(mod); - var importDate = 0L; - var localTags = Enumerable.Empty(); - var favorite = false; - var note = string.Empty; + var importDate = 0L; + var localTags = Enumerable.Empty(); + var favorite = false; + var note = string.Empty; + var fileSystemFolder = string.Empty; + string? sortOrderName = null; HashSet preferredChangedItems = []; @@ -62,7 +63,9 @@ public readonly struct ModLocalData(Mod mod) : ISavable preferredChangedItems = (json[nameof(Mod.PreferredChangedItems)] as JArray)?.Values().Select(i => (CustomItemId)i).ToHashSet() ?? mod.DefaultPreferredItems; - save = false; + fileSystemFolder = json["FileSystemFolder"]?.Value() ?? string.Empty; + sortOrderName = json["SortOrderName"]?.Value()?.FixName(); + save = false; } catch (Exception e) { @@ -101,6 +104,18 @@ public readonly struct ModLocalData(Mod mod) : ISavable changes |= ModDataChangeType.PreferredChangedItems; } + if (!mod.Path.Folder.Equals(fileSystemFolder, StringComparison.OrdinalIgnoreCase)) + { + mod.Path.Folder = fileSystemFolder; + changes |= ModDataChangeType.FileSystemFolder; + } + + if (mod.Path.SortName != sortOrderName) + { + mod.Path.SortName = sortOrderName; + changes |= ModDataChangeType.FileSystemSortOrder; + } + if (save) editor.SaveService.QueueSave(new ModLocalData(mod)); diff --git a/Penumbra/Services/ConfigMigrationService.cs b/Penumbra/Services/ConfigMigrationService.cs index e0a15b49..8369e1d6 100644 --- a/Penumbra/Services/ConfigMigrationService.cs +++ b/Penumbra/Services/ConfigMigrationService.cs @@ -73,9 +73,22 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu Version6To7(); Version7To8(); Version8To9(); + Version9To10(); AddColors(config, true); } + private void Version9To10() + { + if (_config.Version != 9) + return; + + backupService.CreateMigrationBackup("pre_filesystem_update", saveService.FileNames.OldFilesystemFile); + _config.Version = 10; + _config.Ephemeral.Version = 10; + _config.Save(); + _config.Ephemeral.Save(); + } + // Migrate to ephemeral config. private void Version8To9() { @@ -254,7 +267,7 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu private void ResettleSortOrder() { ModSortOrder = _data[nameof(ModSortOrder)]?.ToObject>() ?? ModSortOrder; - var file = saveService.FileNames.FilesystemFile; + var file = saveService.FileNames.OldFilesystemFile; using var stream = File.Open(file, File.Exists(file) ? FileMode.Truncate : FileMode.CreateNew); using var writer = new StreamWriter(stream); using var j = new JsonTextWriter(writer); diff --git a/Penumbra/Services/FilenameService.cs b/Penumbra/Services/FilenameService.cs index 3021bb97..65362ee1 100644 --- a/Penumbra/Services/FilenameService.cs +++ b/Penumbra/Services/FilenameService.cs @@ -1,95 +1,101 @@ -using Dalamud.Plugin; -using Luna; -using Penumbra.Collections; -using Penumbra.Mods; - -namespace Penumbra.Services; - -public sealed class FilenameService(IDalamudPluginInterface pi) : BaseFilePathProvider(pi) -{ - public readonly string CollectionDirectory = Path.Combine(pi.ConfigDirectory.FullName, "collections"); - public readonly string LocalDataDirectory = Path.Combine(pi.ConfigDirectory.FullName, "mod_data"); - public readonly string EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json"); - public readonly string FilesystemFile = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json"); - public readonly string ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json"); - public readonly string PredefinedTagFile = Path.Combine(pi.ConfigDirectory.FullName, "predefined_tags.json"); - - public readonly string CrashHandlerExe = - Path.Combine(pi.AssemblyLocation.DirectoryName!, "Penumbra.CrashHandler.exe"); - - public readonly string LogFileName = - Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(pi.ConfigDirectory.FullName)!)!, "Penumbra.log"); - - /// Obtain the path of a collection file given its name. - public string CollectionFile(ModCollection collection) - => CollectionFile(collection.Identity.Identifier); - - /// Obtain the path of a collection file given its name. - public string CollectionFile(string collectionName) - => Path.Combine(CollectionDirectory, $"{collectionName}.json"); - - /// Obtain the path of the local data file given a mod directory. Returns an empty string if the mod is temporary. - public string LocalDataFile(Mod mod) - => LocalDataFile(mod.ModPath.FullName); - - /// Obtain the path of the local data file given a mod directory. - public string LocalDataFile(string modDirectory) - => Path.Combine(LocalDataDirectory, $"{Path.GetFileName(modDirectory)}.json"); - - /// Enumerate all collection files. - public IEnumerable CollectionFiles - { - get - { - var directory = new DirectoryInfo(CollectionDirectory); - return directory.Exists ? directory.EnumerateFiles("*.json") : []; - } - } - - /// Enumerate all local data files. - public IEnumerable LocalDataFiles - { - get - { - var directory = new DirectoryInfo(LocalDataDirectory); - return directory.Exists ? directory.EnumerateFiles("*.json") : []; - } - } - - /// Obtain the path of the meta file for a given mod. Returns an empty string if the mod is temporary. - public string ModMetaPath(Mod mod) - => ModMetaPath(mod.ModPath.FullName); - - /// Obtain the path of the meta file given a mod directory. - public string ModMetaPath(string modDirectory) - => Path.Combine(modDirectory, "meta.json"); - - /// Obtain the path of the file describing a given option group by its index and the mod. If the index is less than 0, return the path for the default mod file. - public string OptionGroupFile(Mod mod, int index, bool onlyAscii) - => OptionGroupFile(mod.ModPath.FullName, index, index >= 0 ? mod.Groups[index].Name : string.Empty, onlyAscii); - - /// Obtain the path of the file describing a given option group by its index, name and basepath. If the index is less than 0, return the path for the default mod file. - public string OptionGroupFile(string basePath, int index, string name, bool onlyAscii) - { - var fileName = index >= 0 - ? $"group_{index + 1:D3}_{name.ToLowerInvariant().ReplaceBadXivSymbols(onlyAscii)}.json" - : "default_mod.json"; - return Path.Combine(basePath, fileName); - } - - /// Enumerate all group files for a given mod. - public IEnumerable GetOptionGroupFiles(Mod mod) - => mod.ModPath.EnumerateFiles("group_*.json"); - - /// Collect all relevant files for penumbra configuration. - public override List GetBackupFiles() - { - var list = CollectionFiles.ToList(); - list.AddRange(LocalDataFiles); - list.Add(new FileInfo(ConfigurationFile)); - list.Add(new FileInfo(FilesystemFile)); - list.Add(new FileInfo(ActiveCollectionsFile)); - list.Add(new FileInfo(PredefinedTagFile)); - return list; - } -} +using Dalamud.Plugin; +using Luna; +using Penumbra.Collections; +using Penumbra.Mods; + +namespace Penumbra.Services; + +public sealed class FilenameService(IDalamudPluginInterface pi) : BaseFilePathProvider(pi) +{ + public readonly string CollectionDirectory = Path.Combine(pi.ConfigDirectory.FullName, "collections"); + public readonly string LocalDataDirectory = Path.Combine(pi.ConfigDirectory.FullName, "mod_data"); + public readonly string EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json"); + public readonly string OldFilesystemFile = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json"); + public readonly string ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json"); + public readonly string PredefinedTagFile = Path.Combine(pi.ConfigDirectory.FullName, "predefined_tags.json"); + public readonly string FileSystemFolder = Path.Combine(pi.ConfigDirectory.FullName, "mod_filesystem"); + public readonly string FileSystemEmptyFolders = Path.Combine(pi.ConfigDirectory.FullName, "mod_filesystem", "empty_folders.json"); + public readonly string FileSystemExpandedFolders = Path.Combine(pi.ConfigDirectory.FullName, "mod_filesystem", "expanded_folders.json"); + public readonly string FileSystemLockedNodes = Path.Combine(pi.ConfigDirectory.FullName, "mod_filesystem", "locked_nodes.json"); + + public readonly string CrashHandlerExe = + Path.Combine(pi.AssemblyLocation.DirectoryName!, "Penumbra.CrashHandler.exe"); + + public readonly string LogFileName = + Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(pi.ConfigDirectory.FullName)!)!, "Penumbra.log"); + + /// Obtain the path of a collection file given its name. + public string CollectionFile(ModCollection collection) + => CollectionFile(collection.Identity.Identifier); + + /// Obtain the path of a collection file given its name. + public string CollectionFile(string collectionName) + => Path.Combine(CollectionDirectory, $"{collectionName}.json"); + + /// Obtain the path of the local data file given a mod directory. Returns an empty string if the mod is temporary. + public string LocalDataFile(Mod mod) + => LocalDataFile(mod.ModPath.FullName); + + /// Obtain the path of the local data file given a mod directory. + public string LocalDataFile(string modDirectory) + => Path.Combine(LocalDataDirectory, $"{Path.GetFileName(modDirectory)}.json"); + + /// Enumerate all collection files. + public IEnumerable CollectionFiles + { + get + { + var directory = new DirectoryInfo(CollectionDirectory); + return directory.Exists ? directory.EnumerateFiles("*.json") : []; + } + } + + /// Enumerate all local data files. + public IEnumerable LocalDataFiles + { + get + { + var directory = new DirectoryInfo(LocalDataDirectory); + return directory.Exists ? directory.EnumerateFiles("*.json") : []; + } + } + + /// Obtain the path of the meta file for a given mod. Returns an empty string if the mod is temporary. + public string ModMetaPath(Mod mod) + => ModMetaPath(mod.ModPath.FullName); + + /// Obtain the path of the meta file given a mod directory. + public string ModMetaPath(string modDirectory) + => Path.Combine(modDirectory, "meta.json"); + + /// Obtain the path of the file describing a given option group by its index and the mod. If the index is less than 0, return the path for the default mod file. + public string OptionGroupFile(Mod mod, int index, bool onlyAscii) + => OptionGroupFile(mod.ModPath.FullName, index, index >= 0 ? mod.Groups[index].Name : string.Empty, onlyAscii); + + /// Obtain the path of the file describing a given option group by its index, name and basepath. If the index is less than 0, return the path for the default mod file. + public string OptionGroupFile(string basePath, int index, string name, bool onlyAscii) + { + var fileName = index >= 0 + ? $"group_{index + 1:D3}_{name.ToLowerInvariant().ReplaceBadXivSymbols(onlyAscii)}.json" + : "default_mod.json"; + return Path.Combine(basePath, fileName); + } + + /// Enumerate all group files for a given mod. + public IEnumerable GetOptionGroupFiles(Mod mod) + => mod.ModPath.EnumerateFiles("group_*.json"); + + /// Collect all relevant files for penumbra configuration. + public override List GetBackupFiles() + { + var list = CollectionFiles.ToList(); + list.AddRange(LocalDataFiles); + list.Add(new FileInfo(ConfigurationFile)); + list.Add(new FileInfo(ActiveCollectionsFile)); + list.Add(new FileInfo(PredefinedTagFile)); + list.Add(new FileInfo(FileSystemLockedNodes)); + list.Add(new FileInfo(FileSystemEmptyFolders)); + // Do not back up expanded folders, as they are not critical and change often. + return list; + } +} diff --git a/Penumbra/Services/InstallNotification.cs b/Penumbra/Services/InstallNotification.cs index 7b0da414..71c6884f 100644 --- a/Penumbra/Services/InstallNotification.cs +++ b/Penumbra/Services/InstallNotification.cs @@ -1,4 +1,3 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification.EventArgs; @@ -42,7 +41,7 @@ public class InstallNotification(ModImportManager modImportManager, string fileP args.Notification.DismissNow(); } - ImGui.SameLine(); + Im.Line.Same(); if (Im.Button("Ignore"u8, buttonSize)) args.Notification.DismissNow(); } diff --git a/Penumbra/UI/AdvancedWindow/FileEditor.cs b/Penumbra/UI/AdvancedWindow/FileEditor.cs index cc9ee136..ac8eb4f0 100644 --- a/Penumbra/UI/AdvancedWindow/FileEditor.cs +++ b/Penumbra/UI/AdvancedWindow/FileEditor.cs @@ -46,7 +46,7 @@ public class FileEditor( return; } - ImGui.NewLine(); + Im.Line.New(); DrawFileSelectCombo(); SaveButton(); Im.Line.Same(); @@ -55,7 +55,7 @@ public class FileEditor( RedrawOnSaveBox(); Im.Line.Same(); DefaultInput(); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawFilePanel(); } @@ -98,8 +98,8 @@ public class FileEditor( private void DefaultInput() { - using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing with { X = UiHelpers.ScaleX3 }); - ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - 2 * (UiHelpers.ScaleX3 + ImGui.GetFrameHeight())); + using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing with { X = Im.Style.GlobalScale * 3 }); + ImGui.SetNextItemWidth(Im.ContentRegion.Available.X - 2 * (Im.Style.GlobalScale * 3 + Im.Style.FrameHeight)); ImGui.InputTextWithHint("##defaultInput", "Input game path to compare...", ref _defaultPath, Utf8GamePath.MaxGamePathLength); _inInput = ImGui.IsItemActive(); if (ImGui.IsItemDeactivatedAfterEdit() && _defaultPath.Length > 0) @@ -131,7 +131,7 @@ public class FileEditor( } Im.Line.Same(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Save.ToIconString(), new Vector2(ImGui.GetFrameHeight()), "Export this file.", + if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Save.ToIconString(), new Vector2(Im.Style.FrameHeight), "Export this file.", _defaultFile == null, true)) fileDialog.OpenSavePicker($"Export {_defaultPath} to...", fileType, Path.GetFileNameWithoutExtension(_defaultPath), fileType, (success, name) => @@ -152,7 +152,7 @@ public class FileEditor( _quickImport ??= ModEditWindow.QuickImportAction.Prepare(owner, _isDefaultPathUtf8Valid ? _defaultPathUtf8 : Utf8GamePath.Empty, _defaultFile); Im.Line.Same(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.FileImport.ToIconString(), new Vector2(ImGui.GetFrameHeight()), + if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.FileImport.ToIconString(), new Vector2(Im.Style.FrameHeight), $"Add a copy of this file to {_quickImport.OptionName}.", !_quickImport.CanExecute, true)) { try @@ -180,7 +180,7 @@ public class FileEditor( private void DrawFileSelectCombo() { if (_combo.Draw("##fileSelect", _currentPath?.RelPath.ToString() ?? $"Select {fileType} File...", string.Empty, - ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight()) + Im.ContentRegion.Available.X, Im.Style.TextHeight) && _combo.CurrentSelection != null) UpdateCurrentFile(_combo.CurrentSelection); } @@ -263,8 +263,8 @@ public class FileEditor( { if (_currentPath != null) { - ImGui.NewLine(); - ImGui.NewLine(); + Im.Line.New(); + Im.Line.New(); ImGui.TextUnformatted($"Preview of {_defaultPath}:"); ImGui.Separator(); } diff --git a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs index b6208fa5..cee0e177 100644 --- a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs +++ b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs @@ -93,9 +93,9 @@ public class ItemSwapTab : IDisposable, ITab public void DrawContent() { - ImGui.NewLine(); - DrawHeaderLine(300 * UiHelpers.Scale); - ImGui.NewLine(); + Im.Line.New(); + DrawHeaderLine(300 * Im.Style.GlobalScale); + Im.Line.New(); DrawSwapBar(); @@ -433,7 +433,7 @@ public class ItemSwapTab : IDisposable, ITab CreateMod(); Im.Line.Same(); - ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 20 * UiHelpers.Scale); + ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 20 * Im.Style.GlobalScale); ImGui.Checkbox("Use File Swaps", ref _useFileSwaps); ImGuiUtil.HoverTooltip("Instead of writing every single non-default file to the newly created mod or option,\n" + "even those available from game files, use File Swaps to default game files where possible."); @@ -457,7 +457,7 @@ public class ItemSwapTab : IDisposable, ITab CreateOption(); Im.Line.Same(); - ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 20 * UiHelpers.Scale); + ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 20 * Im.Style.GlobalScale); _dirty |= ImGui.Checkbox("Use Entire Collection", ref _useCurrentCollection); ImGuiUtil.HoverTooltip( "Use all applied mods from the Selected Collection with their current settings and respecting the enabled state of mods and inheritance,\n" @@ -515,7 +515,7 @@ public class ItemSwapTab : IDisposable, ITab ImGui.TextUnformatted($"Take {article1}"); ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(100 * UiHelpers.Scale); + ImGui.SetNextItemWidth(100 * Im.Style.GlobalScale); using (var combo = ImRaii.Combo("##fromType", ToName(_slotFrom))) { if (combo) @@ -533,8 +533,8 @@ public class ItemSwapTab : IDisposable, ITab ImGui.TableNextColumn(); _dirty |= selector.Draw("##itemSource", selector.CurrentSelection.Item.Name, string.Empty, - InputWidth * 2 * UiHelpers.Scale, - ImGui.GetTextLineHeightWithSpacing()); + InputWidth * 2 * Im.Style.GlobalScale, + Im.Style.TextHeightWithSpacing); (article1, _, selector) = GetAccessorySelector(_slotTo, false); ImGui.TableNextColumn(); @@ -542,7 +542,7 @@ public class ItemSwapTab : IDisposable, ITab ImGui.TextUnformatted($"and put {article2} on {article1}"); ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(100 * UiHelpers.Scale); + ImGui.SetNextItemWidth(100 * Im.Style.GlobalScale); using (var combo = ImRaii.Combo("##toType", ToName(_slotTo))) { if (combo) @@ -558,8 +558,8 @@ public class ItemSwapTab : IDisposable, ITab ImGui.TableNextColumn(); - _dirty |= selector.Draw("##itemTarget", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale, - ImGui.GetTextLineHeightWithSpacing()); + _dirty |= selector.Draw("##itemTarget", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * Im.Style.GlobalScale, + Im.Style.TextHeightWithSpacing); if (_affectedItems is not { Count: > 1 }) return; @@ -600,8 +600,8 @@ public class ItemSwapTab : IDisposable, ITab ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted(text1); ImGui.TableNextColumn(); - _dirty |= sourceSelector.Draw("##itemSource", sourceSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale, - ImGui.GetTextLineHeightWithSpacing()); + _dirty |= sourceSelector.Draw("##itemSource", sourceSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * Im.Style.GlobalScale, + Im.Style.TextHeightWithSpacing); if (type == SwapType.Ring) { @@ -613,8 +613,8 @@ public class ItemSwapTab : IDisposable, ITab ImGui.AlignTextToFramePadding(); ImGui.TextUnformatted(text2); ImGui.TableNextColumn(); - _dirty |= targetSelector.Draw("##itemTarget", targetSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale, - ImGui.GetTextLineHeightWithSpacing()); + _dirty |= targetSelector.Draw("##itemTarget", targetSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * Im.Style.GlobalScale, + Im.Style.TextHeightWithSpacing); if (type == SwapType.Ring) { Im.Line.Same(); @@ -678,7 +678,7 @@ public class ItemSwapTab : IDisposable, ITab ImGui.TextUnformatted(text); ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(InputWidth * UiHelpers.Scale); + ImGui.SetNextItemWidth(InputWidth * Im.Style.GlobalScale); if (ImGui.InputInt("##targetId", ref _targetId)) _targetId = Math.Clamp(_targetId, 0, byte.MaxValue); @@ -692,7 +692,7 @@ public class ItemSwapTab : IDisposable, ITab ImGui.TextUnformatted(text); ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(InputWidth * UiHelpers.Scale); + ImGui.SetNextItemWidth(InputWidth * Im.Style.GlobalScale); if (ImGui.InputInt("##sourceId", ref _sourceId)) _sourceId = Math.Clamp(_sourceId, 0, byte.MaxValue); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs b/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs index cbf3a185..4ad78398 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; -using FFXIVClientStructs.Interop; using Dalamud.Bindings.ImGui; +using ImSharp; using OtterGui; using OtterGui.Raii; using OtterGui.Text; @@ -31,18 +31,19 @@ public sealed unsafe class MaterialTemplatePickers : Luna.IUiService public bool DrawTileIndexPicker(ReadOnlySpan label, ReadOnlySpan description, ref ushort value, bool compact) => _characterUtility.Address != null - && DrawTextureArrayIndexPicker(label, description, ref value, compact, [ + && DrawTextureArrayIndexPicker(label, description, ref value, compact, [ _characterUtility.Address->TileOrbArrayTexResource, _characterUtility.Address->TileNormArrayTexResource, ]); public bool DrawSphereMapIndexPicker(ReadOnlySpan label, ReadOnlySpan description, ref ushort value, bool compact) => _characterUtility.Address != null - && DrawTextureArrayIndexPicker(label, description, ref value, compact, [ + && DrawTextureArrayIndexPicker(label, description, ref value, compact, [ _characterUtility.Address->SphereDArrayTexResource, ]); - public bool DrawTextureArrayIndexPicker(ReadOnlySpan label, ReadOnlySpan description, ref ushort value, bool compact, ReadOnlySpan> textureRHs) + public bool DrawTextureArrayIndexPicker(ReadOnlySpan label, ReadOnlySpan description, ref ushort value, bool compact, + ReadOnlySpan> textureRHs) { TextureResourceHandle* firstNonNullTextureRH = null; foreach (var texture in textureRHs) @@ -53,10 +54,13 @@ public sealed unsafe class MaterialTemplatePickers : Luna.IUiService break; } } + var firstNonNullTexture = firstNonNullTextureRH != null ? firstNonNullTextureRH->CsHandle.Texture : null; - var textureSize = firstNonNullTexture != null ? new Vector2(firstNonNullTexture->ActualWidth, firstNonNullTexture->ActualHeight).Contain(new Vector2(MaximumTextureSize)) : Vector2.Zero; - var count = firstNonNullTexture != null ? firstNonNullTexture->ArraySize : 0; + var textureSize = firstNonNullTexture != null + ? new Vector2(firstNonNullTexture->ActualWidth, firstNonNullTexture->ActualHeight).Contain(new Vector2(MaximumTextureSize)) + : Vector2.Zero; + var count = firstNonNullTexture != null ? firstNonNullTexture->ArraySize : 0; var ret = false; @@ -64,25 +68,32 @@ public sealed unsafe class MaterialTemplatePickers : Luna.IUiService var itemSpacing = ImGui.GetStyle().ItemSpacing; using (var font = ImRaii.PushFont(UiBuilder.MonoFont)) { - var spaceSize = ImUtf8.CalcTextSize(" "u8).X; - var spaces = (int)((ImGui.CalcItemWidth() - framePadding.X * 2.0f - (compact ? 0.0f : (textureSize.X + itemSpacing.X) * textureRHs.Length)) / spaceSize); - using var padding = ImRaii.PushStyle(ImGuiStyleVar.FramePadding, framePadding + new Vector2(0.0f, Math.Max(textureSize.Y - ImGui.GetFrameHeight() + itemSpacing.Y, 0.0f) * 0.5f), !compact); - using var combo = ImUtf8.Combo(label, (value == ushort.MaxValue ? "-" : value.ToString()).PadLeft(spaces), ImGuiComboFlags.NoArrowButton | ImGuiComboFlags.HeightLarge); + var spaceSize = ImUtf8.CalcTextSize(" "u8).X; + var spaces = (int)((ImGui.CalcItemWidth() + - framePadding.X * 2.0f + - (compact ? 0.0f : (textureSize.X + itemSpacing.X) * textureRHs.Length)) + / spaceSize); + using var padding = ImRaii.PushStyle(ImGuiStyleVar.FramePadding, + framePadding + new Vector2(0.0f, Math.Max(textureSize.Y - Im.Style.FrameHeight + itemSpacing.Y, 0.0f) * 0.5f), !compact); + using var combo = ImUtf8.Combo(label, (value == ushort.MaxValue ? "-" : value.ToString()).PadLeft(spaces), + ImGuiComboFlags.NoArrowButton | ImGuiComboFlags.HeightLarge); if (combo.Success && firstNonNullTextureRH != null) { - var lineHeight = Math.Max(ImGui.GetTextLineHeightWithSpacing(), framePadding.Y * 2.0f + textureSize.Y); - var itemWidth = Math.Max(ImGui.GetContentRegionAvail().X, ImUtf8.CalcTextSize("MMM"u8).X + (itemSpacing.X + textureSize.X) * textureRHs.Length + framePadding.X * 2.0f); + var lineHeight = Math.Max(Im.Style.TextHeightWithSpacing, framePadding.Y * 2.0f + textureSize.Y); + var itemWidth = Math.Max(Im.ContentRegion.Available.X, + ImUtf8.CalcTextSize("MMM"u8).X + (itemSpacing.X + textureSize.X) * textureRHs.Length + framePadding.X * 2.0f); using var center = ImRaii.PushStyle(ImGuiStyleVar.SelectableTextAlign, new Vector2(0, 0.5f)); using var clipper = ImUtf8.ListClipper(count, lineHeight); while (clipper.Step()) { for (var i = clipper.DisplayStart; i < clipper.DisplayEnd && i < count; i++) { - if (ImUtf8.Selectable($"{i,3}", i == value, size: new(itemWidth, lineHeight))) + if (ImUtf8.Selectable($"{i,3}", i == value, size: new Vector2(itemWidth, lineHeight))) { ret = value != i; value = (ushort)i; } + var rectMin = ImGui.GetItemRectMin(); var rectMax = ImGui.GetItemRectMax(); var textureRegionStart = new Vector2( @@ -94,14 +105,18 @@ public sealed unsafe class MaterialTemplatePickers : Luna.IUiService } } } + if (!compact && value != ushort.MaxValue) { - var cbRectMin = ImGui.GetItemRectMin(); - var cbRectMax = ImGui.GetItemRectMax(); - var cbTextureRegionStart = new Vector2(cbRectMax.X - framePadding.X - textureSize.X * textureRHs.Length - itemSpacing.X * (textureRHs.Length - 1), cbRectMin.Y + framePadding.Y); - var cbMaxSize = new Vector2(textureSize.X, cbRectMax.Y - framePadding.Y - cbTextureRegionStart.Y); + var cbRectMin = ImGui.GetItemRectMin(); + var cbRectMax = ImGui.GetItemRectMax(); + var cbTextureRegionStart = + new Vector2(cbRectMax.X - framePadding.X - textureSize.X * textureRHs.Length - itemSpacing.X * (textureRHs.Length - 1), + cbRectMin.Y + framePadding.Y); + var cbMaxSize = new Vector2(textureSize.X, cbRectMax.Y - framePadding.Y - cbTextureRegionStart.Y); DrawTextureSlices(cbTextureRegionStart, cbMaxSize, itemSpacing.X, textureRHs, (byte)value); } + if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled) && (description.Length > 0 || compact && value != ushort.MaxValue)) { using var disabled = ImRaii.Enabled(); @@ -120,24 +135,28 @@ public sealed unsafe class MaterialTemplatePickers : Luna.IUiService return ret; } - public void DrawTextureSlices(Vector2 regionStart, Vector2 itemSize, float itemSpacing, ReadOnlySpan> textureRHs, byte sliceIndex) + public void DrawTextureSlices(Vector2 regionStart, Vector2 itemSize, float itemSpacing, + ReadOnlySpan> textureRHs, byte sliceIndex) { for (var j = 0; j < textureRHs.Length; ++j) { if (textureRHs[j].Value == null) continue; + var texture = textureRHs[j].Value->CsHandle.Texture; if (texture == null) continue; + var handle = _textureArraySlicer.GetImGuiHandle(texture, sliceIndex); if (handle.IsNull) continue; - var position = regionStart with { X = regionStart.X + (itemSize.X + itemSpacing) * j }; - var size = new Vector2(texture->ActualWidth, texture->ActualHeight).Contain(itemSize); - position += (itemSize - size) * 0.5f; - ImGui.GetWindowDrawList().AddImage(handle, position, position + size, Vector2.Zero, - new Vector2(texture->ActualWidth / (float)texture->AllocatedWidth, texture->ActualHeight / (float)texture->AllocatedHeight)); + var position = regionStart with { X = regionStart.X + (itemSize.X + itemSpacing) * j }; + var size = new Vector2(texture->ActualWidth, texture->ActualHeight).Contain(itemSize); + position += (itemSize - size) * 0.5f; + var uvSize = Rectangle.FromSize(texture->ActualWidth / (float)texture->AllocatedWidth, + texture->ActualHeight / (float)texture->AllocatedHeight); + Im.Window.DrawList.Image(handle, Rectangle.FromSize(position, size), uvSize); } } @@ -148,7 +167,7 @@ public sealed unsafe class MaterialTemplatePickers : Luna.IUiService public bool Draw(Span values, bool disabled) { var helper = Editors.PrepareMultiComponent(values.Length); - var ret = false; + var ret = false; for (var valueIdx = 0; valueIdx < values.Length; ++valueIdx) { diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs index c00e6fc4..c0449c29 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs @@ -28,8 +28,8 @@ public partial class MtrlTab var itemSpacing = style.ItemSpacing.X; var itemInnerSpacing = style.ItemInnerSpacing.X; var framePadding = style.FramePadding; - var buttonWidth = (ImGui.GetContentRegionAvail().X - itemSpacing * 7.0f) * 0.125f; - var frameHeight = ImGui.GetFrameHeight(); + var buttonWidth = (Im.ContentRegion.Available.X - itemSpacing * 7.0f) * 0.125f; + var frameHeight = Im.Style.FrameHeight; var highlighterSize = ImUtf8.CalcIconSize(FontAwesomeIcon.Crosshairs) + framePadding * 2.0f; using var font = ImRaii.PushFont(UiBuilder.MonoFont); @@ -47,7 +47,7 @@ public partial class MtrlTab using (ImGuiColor.Button.Push(Im.Style[ImGuiColor.ButtonActive], pairIndex == _colorTableSelectedPair)) { if (ImUtf8.Button($"#{pairIndex + 1}".PadLeft(3 + spacePadding), - new Vector2(buttonWidth, ImGui.GetFrameHeightWithSpacing() + frameHeight))) + new Vector2(buttonWidth, Im.Style.FrameHeightWithSpacing + frameHeight))) _colorTableSelectedPair = pairIndex; } @@ -254,10 +254,10 @@ public partial class MtrlTab private static bool DrawColors(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx) { - var dyeOffset = ImGui.GetContentRegionAvail().X + var dyeOffset = Im.ContentRegion.Available.X + ImGui.GetStyle().ItemSpacing.X - ImGui.GetStyle().ItemInnerSpacing.X - - ImGui.GetFrameHeight() * 2.0f; + - Im.Style.FrameHeight * 2.0f; var ret = false; ref var row = ref table[rowIdx]; @@ -301,11 +301,11 @@ public partial class MtrlTab private static bool DrawBlending(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx) { - var scalarSize = ColorTableScalarSize * UiHelpers.Scale; - var dyeOffset = ImGui.GetContentRegionAvail().X + var scalarSize = ColorTableScalarSize * Im.Style.GlobalScale; + var dyeOffset = Im.ContentRegion.Available.X + ImGui.GetStyle().ItemSpacing.X - ImGui.GetStyle().ItemInnerSpacing.X - - ImGui.GetFrameHeight() + - Im.Style.FrameHeight - scalarSize; var isRowB = (rowIdx & 1) != 0; @@ -334,9 +334,9 @@ public partial class MtrlTab private bool DrawTemplate(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx) { - var scalarSize = ColorTableScalarSize * UiHelpers.Scale; + var scalarSize = ColorTableScalarSize * Im.Style.GlobalScale; var itemSpacing = ImGui.GetStyle().ItemSpacing.X; - var dyeOffset = ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - scalarSize - 64.0f; + var dyeOffset = Im.ContentRegion.Available.X - ImGui.GetStyle().ItemInnerSpacing.X - Im.Style.FrameHeight - scalarSize - 64.0f; var subColWidth = CalculateSubColumnWidth(2); var ret = false; @@ -347,7 +347,7 @@ public partial class MtrlTab ret |= CtDragScalar("Shader ID"u8, default, row.ShaderId, "%d"u8, (ushort)0, (ushort)255, 0.25f, v => table[rowIdx].ShaderId = v); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ImGui.SetNextItemWidth(scalarSize + itemSpacing + 64.0f); ret |= CtSphereMapIndexPicker("###SphereMapIndex"u8, default, row.SphereMapIndex, false, @@ -360,7 +360,7 @@ public partial class MtrlTab var textRectMax = ImGui.GetItemRectMax(); ImGui.SameLine(dyeOffset); var cursor = ImGui.GetCursorScreenPos(); - ImGui.SetCursorScreenPos(cursor with { Y = float.Lerp(textRectMin.Y, textRectMax.Y, 0.5f) - ImGui.GetFrameHeight() * 0.5f }); + ImGui.SetCursorScreenPos(cursor with { Y = float.Lerp(textRectMin.Y, textRectMax.Y, 0.5f) - Im.Style.FrameHeight * 0.5f }); ret |= CtApplyStainCheckbox("##dyeSphereMapIndex"u8, "Apply Sphere Map on Dye"u8, dye.SphereMapIndex, b => dyeTable[rowIdx].SphereMapIndex = b); ImUtf8.SameLineInner(); @@ -387,10 +387,10 @@ public partial class MtrlTab CtDragScalar("##dyeSphereMapMask"u8, "Dye Preview for Sphere Map Intensity"u8, (float?)dyePack?.SphereMapMask * 100.0f, "%.0f%%"u8); } - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); var leftLineHeight = 64.0f + ImGui.GetStyle().FramePadding.Y * 2.0f; - var rightLineHeight = 3.0f * ImGui.GetFrameHeight() + 2.0f * ImGui.GetStyle().ItemSpacing.Y; + var rightLineHeight = 3.0f * Im.Style.FrameHeight + 2.0f * ImGui.GetStyle().ItemSpacing.Y; var lineHeight = Math.Max(leftLineHeight, rightLineHeight); var cursorPos = ImGui.GetCursorScreenPos(); ImGui.SetCursorScreenPos(cursorPos + new Vector2(0.0f, (lineHeight - leftLineHeight) * 0.5f)); @@ -403,7 +403,7 @@ public partial class MtrlTab ImGui.SameLine(subColWidth); ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() with { Y = cursorPos.Y + (lineHeight - rightLineHeight) * 0.5f }); using (ImUtf8.Child("###TileProperties"u8, - new Vector2(ImGui.GetContentRegionAvail().X, float.Lerp(rightLineHeight, lineHeight, 0.5f)))) + new Vector2(Im.ContentRegion.Available.X, float.Lerp(rightLineHeight, lineHeight, 0.5f)))) { ImGui.Dummy(new Vector2(scalarSize, 0.0f)); ImUtf8.SameLineInner(); @@ -415,7 +415,7 @@ public partial class MtrlTab m => table[rowIdx].TileTransform = m); ImUtf8.SameLineInner(); ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() - - new Vector2(0.0f, (ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y) * 0.5f)); + - new Vector2(0.0f, (Im.Style.FrameHeight + ImGui.GetStyle().ItemSpacing.Y) * 0.5f)); ImUtf8.Text("Tile Transform"u8); } @@ -424,12 +424,12 @@ public partial class MtrlTab private static bool DrawPbr(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx) { - var scalarSize = ColorTableScalarSize * UiHelpers.Scale; + var scalarSize = ColorTableScalarSize * Im.Style.GlobalScale; var subColWidth = CalculateSubColumnWidth(2) + ImGui.GetStyle().ItemSpacing.X; var dyeOffset = subColWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - - ImGui.GetFrameHeight() + - Im.Style.FrameHeight - scalarSize; var ret = false; @@ -470,12 +470,12 @@ public partial class MtrlTab private static bool DrawSheen(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx) { - var scalarSize = ColorTableScalarSize * UiHelpers.Scale; + var scalarSize = ColorTableScalarSize * Im.Style.GlobalScale; var subColWidth = CalculateSubColumnWidth(2) + ImGui.GetStyle().ItemSpacing.X; var dyeOffset = subColWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - - ImGui.GetFrameHeight() + - Im.Style.FrameHeight - scalarSize; var ret = false; @@ -530,12 +530,12 @@ public partial class MtrlTab private static bool DrawFurther(ColorTable table, ColorDyeTable? dyeTable, DyePack? dyePack, int rowIdx) { - var scalarSize = ColorTableScalarSize * UiHelpers.Scale; + var scalarSize = ColorTableScalarSize * Im.Style.GlobalScale; var subColWidth = CalculateSubColumnWidth(2) + ImGui.GetStyle().ItemSpacing.X; var dyeOffset = subColWidth - ImGui.GetStyle().ItemSpacing.X * 2.0f - ImGui.GetStyle().ItemInnerSpacing.X - - ImGui.GetFrameHeight() + - Im.Style.FrameHeight - scalarSize; var ret = false; @@ -555,7 +555,7 @@ public partial class MtrlTab CtDragHalf("##dyePreviewScalar11"u8, "Dye Preview for Field #11"u8, dyePack?.Scalar3, "%.2f"u8); } - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ImGui.SetNextItemWidth(scalarSize); ret |= CtDragHalf("Field #3"u8, default, row.Scalar3, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f, @@ -593,7 +593,7 @@ public partial class MtrlTab private bool DrawDye(ColorDyeTable dyeTable, DyePack? dyePack, int rowIdx) { - var scalarSize = ColorTableScalarSize * UiHelpers.Scale; + var scalarSize = ColorTableScalarSize * Im.Style.GlobalScale; var applyButtonWidth = ImUtf8.CalcTextSize("Apply Preview Dye"u8).X + ImGui.GetStyle().FramePadding.X * 2.0f; var subColWidth = CalculateSubColumnWidth(2, applyButtonWidth); @@ -607,7 +607,7 @@ public partial class MtrlTab ImGui.SetNextItemWidth(scalarSize); _stainService.GudTemplateCombo.CurrentDyeChannel = dye.Channel; if (_stainService.GudTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, - scalarSize + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton)) + scalarSize + ImGui.GetStyle().ScrollbarSize / 2, Im.Style.TextHeightWithSpacing, ImGuiComboFlags.NoArrowButton)) { dye.Template = _stainService.GudTemplateCombo.CurrentSelection.UShort; ret = true; @@ -615,7 +615,7 @@ public partial class MtrlTab ImUtf8.SameLineInner(); ImUtf8.Text("Dye Template"u8); - ImGui.SameLine(ImGui.GetContentRegionAvail().X - applyButtonWidth + ImGui.GetStyle().ItemSpacing.X); + ImGui.SameLine(Im.ContentRegion.Available.X - applyButtonWidth + ImGui.GetStyle().ItemSpacing.X); using var dis = ImRaii.Disabled(!dyePack.HasValue); if (ImUtf8.Button("Apply Preview Dye"u8)) ret |= Mtrl.ApplyDyeToRow(_stainService.GudStmFile, [ @@ -632,13 +632,13 @@ public partial class MtrlTab private static void AlignedTextInRest(string text, float alignment) { var width = ImGui.CalcTextSize(text).X; - ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() + new Vector2((ImGui.GetContentRegionAvail().X - width) * alignment, 0.0f)); + ImGui.SetCursorScreenPos(ImGui.GetCursorScreenPos() + new Vector2((Im.ContentRegion.Available.X - width) * alignment, 0.0f)); ImGui.TextUnformatted(text); } private static float CalculateSubColumnWidth(int numSubColumns, float reservedSpace = 0.0f) { var itemSpacing = ImGui.GetStyle().ItemSpacing.X; - return (ImGui.GetContentRegionAvail().X - reservedSpace - itemSpacing * (numSubColumns - 1)) / numSubColumns + itemSpacing; + return (Im.ContentRegion.Available.X - reservedSpace - itemSpacing * (numSubColumns - 1)) / numSubColumns + itemSpacing; } } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs index fc0b3611..31ee13f2 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs @@ -26,7 +26,7 @@ public partial class MtrlTab if (!_shpkLoading && !TextureIds.Contains(ShpkFile.TableSamplerId) || Mtrl.Table == null) return false; - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); if (!ImUtf8.CollapsingHeader("Color Table"u8, ImGuiTreeNodeFlags.DefaultOpen)) return false; @@ -66,7 +66,7 @@ public partial class MtrlTab if (Mtrl.Table == null) return; - if (!ImUtf8.Button("Export All Rows to Clipboard"u8, ImGuiHelpers.ScaledVector2(200, 0))) + if (!ImUtf8.Button("Export All Rows to Clipboard"u8, ImEx.ScaledVector(200, 0))) return; try @@ -124,7 +124,7 @@ public partial class MtrlTab if (Mtrl.Table == null) return false; - if (!ImUtf8.ButtonEx("Import All Rows from Clipboard"u8, ImGuiHelpers.ScaledVector2(200, 0), disabled)) + if (!ImUtf8.ButtonEx("Import All Rows from Clipboard"u8, ImEx.ScaledVector(200, 0), disabled)) return false; try @@ -156,7 +156,7 @@ public partial class MtrlTab return; if (!ImUtf8.IconButton(FontAwesomeIcon.Clipboard, "Export this row to your clipboard."u8, - ImGui.GetFrameHeight() * Vector2.One)) + Im.Style.FrameHeight * Vector2.One)) return; try @@ -205,7 +205,7 @@ public partial class MtrlTab if (ImUtf8.IconButton(FontAwesomeIcon.Paste, "Import an exported row from your clipboard onto this row.\n\nRight-Click for more options."u8, - ImGui.GetFrameHeight() * Vector2.One, disabled)) + Im.Style.FrameHeight * Vector2.One, disabled)) try { var text = ImGui.GetClipboardText(); @@ -232,7 +232,7 @@ public partial class MtrlTab private unsafe bool ColorTablePasteFromClipboardContext(int rowIdx, bool disabled) { - if (!disabled && ImGui.IsItemClicked(ImGuiMouseButton.Right)) + if (!disabled && Im.Item.RightClicked()) ImUtf8.OpenPopup("context"u8); using var context = ImUtf8.Popup("context"u8); @@ -283,7 +283,7 @@ public partial class MtrlTab { ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, "Highlight this pair of rows on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8, - ImGui.GetFrameHeight() * Vector2.One, disabled || _colorTablePreviewers.Count == 0); + Im.Style.FrameHeight * Vector2.One, disabled || _colorTablePreviewers.Count == 0); if (ImGui.IsItemHovered()) HighlightColorTablePair(pairIdx); @@ -295,7 +295,7 @@ public partial class MtrlTab { ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, "Highlight this row on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8, - ImGui.GetFrameHeight() * Vector2.One, disabled || _colorTablePreviewers.Count == 0); + Im.Style.FrameHeight * Vector2.One, disabled || _colorTablePreviewers.Count == 0); if (ImGui.IsItemHovered()) HighlightColorTableRow(rowIdx); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs index 8b2e46bf..4736f8b6 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs @@ -153,7 +153,7 @@ public partial class MtrlTab if (Constants.Count == 0) return false; - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); if (!ImGui.CollapsingHeader("Material Constants")) return false; @@ -173,7 +173,7 @@ public partial class MtrlTab if (buffer.Length > 0) { using var id = ImRaii.PushId($"##{constant.Id:X8}:{slice.Start}"); - ImGui.SetNextItemWidth(MaterialConstantSize * UiHelpers.Scale); + ImGui.SetNextItemWidth(MaterialConstantSize * Im.Style.GlobalScale); if (editor.Draw(buffer[slice], disabled)) { ret = true; @@ -187,7 +187,7 @@ public partial class MtrlTab ? defaultValue.Length > 0 && !defaultValue.SequenceEqual(buffer[slice]) : buffer[slice].ContainsAnyExcept((byte)0); ImUtf8.SameLineInner(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Backspace.ToIconString(), ImGui.GetFrameHeight() * Vector2.One, + if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Backspace.ToIconString(), Im.Style.FrameHeight * Vector2.One, "Reset this constant to its default value.\n\nHold Ctrl to unlock.", !ImGui.GetIO().KeyCtrl || !canReset, true)) { ret = true; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs index c4ef8dd5..030d7c9c 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs @@ -97,9 +97,9 @@ public partial class MtrlTab using var id = ImRaii.PushId(rowIdx); ref var row = ref table[rowIdx]; var dye = dyeTable != null ? dyeTable[rowIdx] : default; - var floatSize = LegacyColorTableFloatSize * UiHelpers.Scale; - var pctSize = LegacyColorTablePercentageSize * UiHelpers.Scale; - var intSize = LegacyColorTableIntegerSize * UiHelpers.Scale; + var floatSize = LegacyColorTableFloatSize * Im.Style.GlobalScale; + var pctSize = LegacyColorTablePercentageSize * Im.Style.GlobalScale; + var intSize = LegacyColorTableIntegerSize * Im.Style.GlobalScale; ImGui.TableNextColumn(); ColorTableCopyClipboardButton(rowIdx); ImUtf8.SameLineInner(); @@ -183,7 +183,7 @@ public partial class MtrlTab { ImGui.TableNextColumn(); if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize - + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton)) + + ImGui.GetStyle().ScrollbarSize / 2, Im.Style.TextHeightWithSpacing, ImGuiComboFlags.NoArrowButton)) { dyeTable[rowIdx].Template = _stainService.LegacyTemplateCombo.CurrentSelection.UShort; ret = true; @@ -203,10 +203,10 @@ public partial class MtrlTab using var id = ImRaii.PushId(rowIdx); ref var row = ref table[rowIdx]; var dye = dyeTable?[rowIdx] ?? default; - var floatSize = LegacyColorTableFloatSize * UiHelpers.Scale; - var pctSize = LegacyColorTablePercentageSize * UiHelpers.Scale; - var intSize = LegacyColorTableIntegerSize * UiHelpers.Scale; - var byteSize = LegacyColorTableByteSize * UiHelpers.Scale; + var floatSize = LegacyColorTableFloatSize * Im.Style.GlobalScale; + var pctSize = LegacyColorTablePercentageSize * Im.Style.GlobalScale; + var intSize = LegacyColorTableIntegerSize * Im.Style.GlobalScale; + var byteSize = LegacyColorTableByteSize * Im.Style.GlobalScale; ImGui.TableNextColumn(); ColorTableCopyClipboardButton(rowIdx); ImUtf8.SameLineInner(); @@ -298,7 +298,7 @@ public partial class MtrlTab ImUtf8.SameLineInner(); _stainService.LegacyTemplateCombo.CurrentDyeChannel = dye.Channel; if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize - + ImGui.GetStyle().ScrollbarSize / 2, ImGui.GetTextLineHeightWithSpacing(), ImGuiComboFlags.NoArrowButton)) + + ImGui.GetStyle().ScrollbarSize / 2, Im.Style.TextHeightWithSpacing, ImGuiComboFlags.NoArrowButton)) { dyeTable[rowIdx].Template = _stainService.LegacyTemplateCombo.CurrentSelection.UShort; ret = true; @@ -321,7 +321,7 @@ public partial class MtrlTab using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2); - var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(ImGui.GetFrameHeight()), + var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(Im.Style.FrameHeight), "Apply the selected dye to this row.", disabled, true); ret = ret && Mtrl.ApplyDyeToRow(_stainService.LegacyStmFile, [stain], rowIdx); @@ -340,7 +340,7 @@ public partial class MtrlTab using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2); - var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(ImGui.GetFrameHeight()), + var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(Im.Style.FrameHeight), "Apply the selected dye to this row.", disabled, true); ret = ret diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs index 9a15375e..5a3815cc 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs @@ -337,7 +337,7 @@ public partial class MtrlTab if (!_shpkLoading && (_associatedShpk == null || _associatedShpkDevkit == null)) { - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); if (_associatedShpk == null) ImUtf8.Text("Unable to find a suitable shader (.shpk) file for cross-references. Some functionality will be missing."u8, @@ -360,7 +360,7 @@ public partial class MtrlTab } var ret = false; - ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 250.0f); using var c = ImRaii.Combo("Shader Package", Mtrl.ShaderPackage.Name); if (c) foreach (var value in GetShpkNames()) @@ -382,7 +382,7 @@ public partial class MtrlTab private bool DrawShaderFlagsInput(bool disabled) { var shpkFlags = (int)Mtrl.ShaderPackage.Flags; - ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 250.0f); if (!ImGui.InputInt("Shader Flags", ref shpkFlags, 0, 0, flags: ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None))) return false; @@ -409,7 +409,7 @@ public partial class MtrlTab ? "Base dev-kit file: None" : $"Base dev-kit file: {_loadedBaseDevkitPathName}"; - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ImUtf8.CopyOnClickSelectable(text, _loadedShpkPathName, tooltip); ImUtf8.CopyOnClickSelectable(devkitText, _loadedShpkDevkitPathName, tooltip); @@ -436,7 +436,7 @@ public partial class MtrlTab LoadShpk(new FullPath(gamePath)); } - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); } private bool DrawMaterialShaderKeys(bool disabled) @@ -456,7 +456,7 @@ public partial class MtrlTab values.FirstOrNull(v => v.Value == currentValue) ?? ($"0x{currentValue:X8}", currentValue, string.Empty); if (!disabled && shpkKey.HasValue) { - ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 250.0f); using (var c = ImUtf8.Combo(""u8, currentLabel)) { if (c) @@ -508,7 +508,7 @@ public partial class MtrlTab if (_shaderComment.Length > 0) { - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ImUtf8.Text(_shaderComment); } } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs index e71ad943..1869b714 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs @@ -77,7 +77,7 @@ public partial class MtrlTab Textures.Sort((x, y) => string.CompareOrdinal(x.Label, y.Label)); - TextureLabelWidth = 50f * UiHelpers.Scale; + TextureLabelWidth = 50f * Im.Style.GlobalScale; float helpWidth; using (var _ = ImRaii.PushFont(UiBuilder.IconFont)) @@ -101,7 +101,7 @@ public partial class MtrlTab } } - TextureLabelWidth = TextureLabelWidth / UiHelpers.Scale + 4; + TextureLabelWidth = TextureLabelWidth / Im.Style.GlobalScale + 4; } private static ReadOnlySpan TextureAddressModeTooltip(TextureAddressMode addressMode) @@ -122,17 +122,17 @@ public partial class MtrlTab if (Textures.Count == 0) return false; - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); if (!ImGui.CollapsingHeader("Textures and Samplers", ImGuiTreeNodeFlags.DefaultOpen)) return false; - var frameHeight = ImGui.GetFrameHeight(); + var frameHeight = Im.Style.FrameHeight; var ret = false; using var table = ImRaii.Table("##Textures", 3); ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, frameHeight); ImGui.TableSetupColumn("Path", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, TextureLabelWidth * UiHelpers.Scale); + ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, TextureLabelWidth * Im.Style.GlobalScale); foreach (var (label, textureI, samplerI, description, monoFont) in Textures) { using var _ = ImRaii.PushId(samplerI); @@ -151,7 +151,7 @@ public partial class MtrlTab } ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); + ImGui.SetNextItemWidth(Im.ContentRegion.Available.X); if (ImGui.InputText(string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength, disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None) && tmp.Length > 0 @@ -221,7 +221,7 @@ public partial class MtrlTab { ref var samplerFlags = ref Wrap(ref sampler.Flags); - ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 100.0f); var addressMode = samplerFlags.UAddressMode; if (ComboTextureAddressMode("##UAddressMode"u8, ref addressMode)) { @@ -234,7 +234,7 @@ public partial class MtrlTab ImUtf8.LabeledHelpMarker("U Address Mode"u8, "Method to use for resolving a U texture coordinate that is outside the 0 to 1 range."); - ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 100.0f); addressMode = samplerFlags.VAddressMode; if (ComboTextureAddressMode("##VAddressMode"u8, ref addressMode)) { @@ -248,7 +248,7 @@ public partial class MtrlTab "Method to use for resolving a V texture coordinate that is outside the 0 to 1 range."); var lodBias = samplerFlags.LodBias; - ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 100.0f); if (ImUtf8.DragScalar("##LoDBias"u8, ref lodBias, -8.0f, 7.984375f, 0.1f)) { samplerFlags.LodBias = lodBias; @@ -261,7 +261,7 @@ public partial class MtrlTab "Offset from the calculated mipmap level.\n\nHigher means that the texture will start to lose detail nearer.\nLower means that the texture will keep its detail until farther."); var minLod = samplerFlags.MinLod; - ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 100.0f); if (ImUtf8.DragScalar("##MinLoD"u8, ref minLod, 0, 15, 0.1f)) { samplerFlags.MinLod = minLod; @@ -282,12 +282,12 @@ public partial class MtrlTab if (!t) return ret; - ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 100.0f); if (ImUtf8.InputScalar("Texture Flags"u8, ref texture.Flags, "%04X"u8, flags: disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None)) ret = true; - ImGui.SetNextItemWidth(UiHelpers.Scale * 100.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 100.0f); if (ImUtf8.InputScalar("Sampler Flags"u8, ref sampler.Flags, "%08X"u8, flags: ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None))) { diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs index 877246a3..bde529d2 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs @@ -1,6 +1,7 @@ using Dalamud.Interface.Components; using Dalamud.Plugin.Services; using Dalamud.Bindings.ImGui; +using ImSharp; using OtterGui; using OtterGui.Raii; using OtterGui.Text; @@ -95,17 +96,17 @@ public sealed partial class MtrlTab : IWritable, IDisposable DrawMaterialLivePreviewRebind(disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); var ret = DrawBackFaceAndTransparency(disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ret |= DrawShaderSection(disabled); ret |= DrawTextureSection(disabled); ret |= DrawColorTableSection(disabled); ret |= DrawConstantsSection(disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawOtherMaterialDetails(disabled); return !disabled && ret; @@ -138,7 +139,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable ImGuiComponents.HelpMarker("Enabling transparency for shader package characterstockings.shpk will crash the game."); } - ImGui.SameLine(200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X); + ImGui.SameLine(200 * Im.Style.GlobalScale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X); tmp = shaderFlags.HideBackfaces; if (ImUtf8.Checkbox("Hide Backfaces"u8, ref tmp)) { @@ -149,7 +150,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable if (_shpkLoading) { - ImGui.SameLine(400 * UiHelpers.Scale + 2 * ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X); + ImGui.SameLine(400 * Im.Style.GlobalScale + 2 * ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X); ImUtf8.Text("Loading shader (.shpk) file. Some functionality will only be available after this is done."u8, ImGuiUtil.HalfBlendText(0x808000u)); // Half cyan diff --git a/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs index b69a9b56..345315cc 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs @@ -1,6 +1,7 @@ using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; +using ImSharp; using Newtonsoft.Json.Linq; using OtterGui.Raii; using OtterGui.Text; @@ -14,6 +15,7 @@ using Penumbra.Meta; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; using Penumbra.UI.Classes; +using MouseWheelType = OtterGui.Widgets.MouseWheelType; using Notification = Luna.Notification; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -268,7 +270,7 @@ public sealed class AtchMetaDrawer : MetaDrawer private static bool DrawPointInput(ref AtchIdentifier identifier, AtchPointCombo combo) { if (!combo.Draw("##AtchPoint", identifier.Type.ToName(), "Attachment Point Type", 160 * ImUtf8.GlobalScale, - ImGui.GetTextLineHeightWithSpacing())) + Im.Style.TextHeightWithSpacing)) return false; identifier = identifier with { Type = combo.CurrentSelection }; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs index 1031fb66..d039b460 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs @@ -39,7 +39,7 @@ public partial class ModEditWindow } using var child = ImUtf8.Child("GenderRace"u8, - new Vector2(width, ImGui.GetContentRegionMax().Y - ImGui.GetFrameHeight() - ImGui.GetStyle().WindowPadding.Y), true); + new Vector2(width, ImGui.GetContentRegionMax().Y - Im.Style.FrameHeight - ImGui.GetStyle().WindowPadding.Y), true); if (!child) return; @@ -78,7 +78,7 @@ public partial class ModEditWindow } using var child = ImUtf8.Child("Bone"u8, - new Vector2(width, ImGui.GetContentRegionMax().Y - ImGui.GetFrameHeight() - ImGui.GetStyle().WindowPadding.Y), true); + new Vector2(width, ImGui.GetContentRegionMax().Y - Im.Style.FrameHeight - ImGui.GetStyle().WindowPadding.Y), true); if (!child) return; @@ -91,7 +91,7 @@ public partial class ModEditWindow } else { - var height = ImGui.GetTextLineHeightWithSpacing(); + var height = Im.Style.TextHeightWithSpacing; var skips = ImGuiClip.GetNecessarySkips(height); var remainder = ImGuiClip.FilteredClippedDraw(_pbdData.SelectedDeformer.DeformMatrices.Keys, skips, b => b.Contains(_pbdData.BoneFilter), bone @@ -107,7 +107,7 @@ public partial class ModEditWindow private bool DrawBoneData(PbdTab tab, bool disabled) { using var child = ImUtf8.Child("Data"u8, - ImGui.GetContentRegionAvail() with { Y = ImGui.GetContentRegionMax().Y - ImGui.GetStyle().WindowPadding.Y }, true); + Im.ContentRegion.Available with { Y = ImGui.GetContentRegionMax().Y - ImGui.GetStyle().WindowPadding.Y }, true); if (!child) return false; @@ -118,7 +118,7 @@ public partial class ModEditWindow return false; var width = UiBuilder.MonoFont.GetCharAdvance('0') * 12 + ImGui.GetStyle().FramePadding.X * 2; - var dummyHeight = ImGui.GetTextLineHeight() / 2; + var dummyHeight = Im.Style.TextHeight / 2; var ret = DrawAddNewBone(tab, disabled, matrix, width); ImUtf8.Dummy(0, dummyHeight); @@ -209,7 +209,7 @@ public partial class ModEditWindow Im.Line.Same(); } - ImGui.NewLine(); + Im.Line.New(); } return ret; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs index f8ba7f67..266d515b 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs @@ -59,7 +59,7 @@ public partial class ModEditWindow private void DrawFilesOverviewMode() { - var height = ImGui.GetTextLineHeightWithSpacing() + 2 * ImGui.GetStyle().CellPadding.Y; + var height = Im.Style.TextHeightWithSpacing + 2 * ImGui.GetStyle().CellPadding.Y; var skips = ImGuiClip.GetNecessarySkips(height); using var list = ImRaii.Table("##table", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV, -Vector2.One); @@ -67,7 +67,7 @@ public partial class ModEditWindow if (!list) return; - var width = ImGui.GetContentRegionAvail().X / 8; + var width = Im.ContentRegion.Available.X / 8; ImGui.TableSetupColumn("##file", ImGuiTableColumnFlags.WidthFixed, width * 3); ImGui.TableSetupColumn("##path", ImGuiTableColumnFlags.WidthFixed, width * 3 + ImGui.GetStyle().FrameBorderSize); @@ -192,7 +192,7 @@ public partial class ModEditWindow _selectedFiles.Add(registry); } - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + if (Im.Item.RightClicked()) ImUtf8.OpenPopup("context"u8); var rightText = DrawFileTooltip(registry, color); @@ -257,7 +257,7 @@ public partial class ModEditWindow using var id = ImRaii.PushId(j); ImGui.TableNextColumn(); var tmp = _fileIdx == i && _pathIdx == j ? _gamePathEdit : gamePath.ToString(); - var pos = ImGui.GetCursorPosX() - ImGui.GetFrameHeight(); + var pos = ImGui.GetCursorPosX() - Im.Style.FrameHeight; ImGui.SetNextItemWidth(-1); if (ImGui.InputText(string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength)) { @@ -302,7 +302,7 @@ public partial class ModEditWindow private void PrintNewGamePath(int i, FileRegistry registry, IModDataContainer _) { var tmp = _fileIdx == i && _pathIdx == -1 ? _gamePathEdit : string.Empty; - var pos = ImGui.GetCursorPosX() - ImGui.GetFrameHeight(); + var pos = ImGui.GetCursorPosX() - Im.Style.FrameHeight; ImGui.SetNextItemWidth(-1); if (ImGui.InputTextWithHint("##new", "Add New Path...", ref tmp, Utf8GamePath.MaxGamePathLength)) { @@ -344,10 +344,10 @@ public partial class ModEditWindow private void DrawButtonHeader() { - ImGui.NewLine(); + Im.Line.New(); - using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3 * UiHelpers.Scale, 0)); - ImGui.SetNextItemWidth(30 * UiHelpers.Scale); + using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3 * Im.Style.GlobalScale, 0)); + ImGui.SetNextItemWidth(30 * Im.Style.GlobalScale); ImGui.DragInt("##skippedFolders", ref _folderSkip, 0.01f, 0, 10); ImGuiUtil.HoverTooltip("Skip the first N folders when automatically constructing the game path from the file path."); Im.Line.Same(); @@ -403,7 +403,7 @@ public partial class ModEditWindow private void DrawFileManagementNormal() { - ImGui.SetNextItemWidth(250 * UiHelpers.Scale); + ImGui.SetNextItemWidth(250 * Im.Style.GlobalScale); Im.Input.Text("##filter"u8, ref _fileFilter, "Filter paths..."u8); Im.Line.Same(); ImGui.Checkbox("Show Game Paths", ref _showGamePaths); @@ -434,7 +434,7 @@ public partial class ModEditWindow .Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero) .Push(ImGuiStyleVar.FrameBorderSize, ImGui.GetStyle().ChildBorderSize); - var width = ImGui.GetContentRegionAvail().X / 8; + var width = Im.ContentRegion.Available.X / 8; ImGui.SetNextItemWidth(width * 3); Im.Input.Text("##fileFilter"u8, ref _fileOverviewFilter1, "Filter file..."u8); diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs index d76ce304..83200ccc 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; -using Dalamud.Interface.Utility; using Dalamud.Bindings.ImGui; +using ImSharp; using OtterGui.Raii; using OtterGui.Text; using Penumbra.UI.AdvancedWindow.Materials; @@ -28,10 +28,10 @@ public partial class ModEditWindow if (!tab) return; - ImGui.NewLine(); - MaterialSuffix.Draw(_editor, ImGuiHelpers.ScaledVector2(175, 0)); + Im.Line.New(); + MaterialSuffix.Draw(_editor, ImEx.ScaledVector(175, 0)); - ImGui.NewLine(); + Im.Line.New(); using var child = ImUtf8.Child("##mdlFiles"u8, -Vector2.One, true); if (!child) return; @@ -54,7 +54,7 @@ public partial class ModEditWindow ImGui.TableNextColumn(); ImUtf8.Text(info.Path.InternalName.Span[(Mod!.ModPath.FullName.Length + 1)..]); ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(400 * UiHelpers.Scale); + ImGui.SetNextItemWidth(400 * Im.Style.GlobalScale); var tmp = info.CurrentMaterials[0]; if (ImUtf8.InputText("##0"u8, ref tmp)) info.SetMaterial(tmp, 0); @@ -66,7 +66,7 @@ public partial class ModEditWindow ImGui.TableNextColumn(); ImGui.TableNextColumn(); ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(400 * UiHelpers.Scale); + ImGui.SetNextItemWidth(400 * Im.Style.GlobalScale); tmp = info.CurrentMaterials[i]; if (ImUtf8.InputText(""u8, ref tmp)) info.SetMaterial(tmp, i); diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs index 8fa2fe18..3b797413 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs @@ -27,7 +27,7 @@ public partial class ModEditWindow var setsEqual = !_editor.MetaEditor.Changes; var tt = setsEqual ? "No changes staged."u8 : "Apply the currently staged changes to the option."u8; - ImGui.NewLine(); + Im.Line.New(); if (ImUtf8.ButtonEx("Apply Changes"u8, tt, Vector2.Zero, setsEqual)) _editor.MetaEditor.Apply(_editor.Option!); @@ -131,7 +131,7 @@ public partial class ModEditWindow return; drawer.Draw(); - ImGui.NewLine(); + Im.Line.New(); } private void DrawOtherOptionData(MetaManipulationType type, float oldPos, Vector2 newPos) @@ -142,7 +142,7 @@ public partial class ModEditWindow var text = $"{otherOptionData.TotalCount} Edits in other Options"; var size = ImGui.CalcTextSize(text).X; - ImGui.SetCursorPos(new Vector2(ImGui.GetContentRegionAvail().X - size, oldPos + ImGui.GetStyle().FramePadding.Y)); + ImGui.SetCursorPos(new Vector2(Im.ContentRegion.Available.X - size, oldPos + ImGui.GetStyle().FramePadding.Y)); Im.Text(text, ColorId.RedundantAssignment.Value().FullAlpha()); if (ImGui.IsItemHovered()) { diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs index 0bd5d93a..fc3e0368 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs @@ -103,7 +103,7 @@ public partial class ModEditWindow if (!ImGui.CollapsingHeader("Import / Export")) return; - var childSize = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X) / 2, 0); + var childSize = new Vector2((Im.ContentRegion.Available.X - ImGui.GetStyle().ItemSpacing.X) / 2, 0); DrawImport(tab, childSize, disabled); Im.Line.Same(); @@ -196,11 +196,11 @@ public partial class ModEditWindow if (tab.IoExceptions.Count == 0) return; - var size = new Vector2(ImGui.GetContentRegionAvail().X, 0); + var size = new Vector2(Im.ContentRegion.Available.X, 0); using var frame = ImRaii.FramedGroup("Exceptions", size, headerPreIcon: FontAwesomeIcon.TimesCircle, borderColor: Colors.RegexWarningBorder); - var spaceAvail = ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X - 100; + var spaceAvail = Im.ContentRegion.Available.X - ImGui.GetStyle().ItemSpacing.X - 100; foreach (var (index, exception) in tab.IoExceptions.Index()) { using var id = ImRaii.PushId(index); @@ -223,10 +223,10 @@ public partial class ModEditWindow if (tab.IoWarnings.Count == 0) return; - var size = new Vector2(ImGui.GetContentRegionAvail().X, 0); + var size = new Vector2(Im.ContentRegion.Available.X, 0); using var frame = ImRaii.FramedGroup("Warnings", size, headerPreIcon: FontAwesomeIcon.ExclamationCircle, borderColor: 0xFF40FFFF); - var spaceAvail = ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X - 100; + var spaceAvail = Im.ContentRegion.Available.X - ImGui.GetStyle().ItemSpacing.X - 100; foreach (var (index, warning) in tab.IoWarnings.Index()) { using var id = ImRaii.PushId(index); @@ -271,7 +271,7 @@ public partial class ModEditWindow const string label = "Game Path"; var preview = tab.GamePaths![tab.GamePathIndex].ToString(); var labelWidth = ImGui.CalcTextSize(label).X + ImGui.GetStyle().ItemInnerSpacing.X; - var buttonWidth = ImGui.GetContentRegionAvail().X - labelWidth - ImGui.GetStyle().ItemSpacing.X; + var buttonWidth = Im.ContentRegion.Available.X - labelWidth - ImGui.GetStyle().ItemSpacing.X; if (tab.GamePaths!.Count == 1) { using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); @@ -297,7 +297,7 @@ public partial class ModEditWindow } } - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + if (Im.Item.RightClicked()) ImGui.SetClipboardText(preview); ImGuiUtil.HoverTooltip("Right-Click to copy to clipboard.", ImGuiHoveredFlags.AllowWhenDisabled); } @@ -331,7 +331,7 @@ public partial class ModEditWindow { var text = $"{invalidMaterialCount} invalid material{(invalidMaterialCount > 1 ? "s" : "")}"; var size = ImGui.CalcTextSize(text).X; - ImGui.SetCursorPos(new Vector2(ImGui.GetContentRegionAvail().X - size, oldPos + ImGui.GetStyle().FramePadding.Y)); + ImGui.SetCursorPos(new Vector2(Im.ContentRegion.Available.X - size, oldPos + ImGui.GetStyle().FramePadding.Y)); ImGuiUtil.TextColored(0xFF0000FF, text); ImGui.SetCursorPos(newPos); } @@ -346,7 +346,7 @@ public partial class ModEditWindow var ret = false; var materials = tab.Mdl.Materials; - ImGui.TableSetupColumn("index", ImGuiTableColumnFlags.WidthFixed, 80 * UiHelpers.Scale); + ImGui.TableSetupColumn("index", ImGuiTableColumnFlags.WidthFixed, 80 * Im.Style.GlobalScale); ImGui.TableSetupColumn("path", ImGuiTableColumnFlags.WidthStretch, 1); if (!disabled) { @@ -468,7 +468,7 @@ public partial class ModEditWindow if (!table) return false; - ImGui.TableSetupColumn("name", ImGuiTableColumnFlags.WidthFixed, 100 * UiHelpers.Scale); + ImGui.TableSetupColumn("name", ImGuiTableColumnFlags.WidthFixed, 100 * Im.Style.GlobalScale); ImGui.TableSetupColumn("field", ImGuiTableColumnFlags.WidthStretch, 1); var file = tab.Mdl; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs index 573a0cf2..a7668a2a 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs @@ -26,26 +26,26 @@ public partial class ModEditWindow { DrawShaderPackageSummary(file); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawShaderPackageFilterSection(file); var ret = false; - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ret |= DrawShaderPackageShaderArray(file, "Vertex Shader", file.Shpk.VertexShaders, disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ret |= DrawShaderPackageShaderArray(file, "Pixel Shader", file.Shpk.PixelShaders, disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ret |= DrawShaderPackageMaterialParamLayout(file, disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); ret |= DrawShaderPackageResources(file, disabled); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawShaderPackageSelection(file); - ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2)); + ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawOtherShaderPackageDetails(file); ret |= file.Shpk.IsChanged(); @@ -146,7 +146,7 @@ public partial class ModEditWindow return; using var font = ImRaii.PushFont(UiBuilder.MonoFont); - var size = new Vector2(ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight() * 20); + var size = new Vector2(Im.ContentRegion.Available.X, Im.Style.TextHeight * 20); ImGuiNative.InputTextMultiline(DisassemblyLabel.Path, shader.Disassembly!.RawDisassembly.Path, (uint)shader.Disassembly!.RawDisassembly.Length + 1, size, ImGuiInputTextFlags.ReadOnly, null, null); @@ -302,7 +302,7 @@ public partial class ModEditWindow var ret = false; if (!disabled) { - ImGui.SetNextItemWidth(UiHelpers.Scale * 150.0f); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 150.0f); if (ImGuiUtil.InputUInt16($"{char.ToUpper(slotLabel[0])}{slotLabel[1..].ToLower()}", ref resource.Slot, ImGuiInputTextFlags.None)) ret = true; } @@ -363,7 +363,7 @@ public partial class ModEditWindow { using var font = ImRaii.PushFont(UiBuilder.MonoFont); var pos = ImGui.GetCursorScreenPos() - + new Vector2(ImGui.CalcTextSize(label).X + 3 * ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight(), + + new Vector2(ImGui.CalcTextSize(label).X + 3 * ImGui.GetStyle().ItemInnerSpacing.X + Im.Style.FrameHeight, ImGui.GetStyle().FramePadding.Y); var ret = ImUtf8.CollapsingHeader(label); @@ -396,11 +396,11 @@ public partial class ModEditWindow if (!table) return false; - ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, 40 * UiHelpers.Scale); - ImGui.TableSetupColumn("x", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale); - ImGui.TableSetupColumn("y", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale); - ImGui.TableSetupColumn("z", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale); - ImGui.TableSetupColumn("w", ImGuiTableColumnFlags.WidthFixed, 250 * UiHelpers.Scale); + ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, 40 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("x", ImGuiTableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("y", ImGuiTableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("z", ImGuiTableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("w", ImGuiTableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); ImGui.TableHeadersRow(); var textColorStart = ImGuiColor.Text.Get().Color; @@ -428,7 +428,7 @@ public partial class ModEditWindow { ImGui.TableNextColumn(); ImUtf8.Selectable(name); - if (deletable && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl) + if (deletable && Im.Item.RightClicked() && ImGui.GetIO().KeyCtrl) { tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems(idx); ret = true; @@ -494,7 +494,7 @@ public partial class ModEditWindow using var s = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing); using (ImRaii.PushFont(UiBuilder.MonoFont)) { - ImGui.SetNextItemWidth(UiHelpers.Scale * 400); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 400); using var c = ImUtf8.Combo("##Start", tab.Orphans[tab.NewMaterialParamStart].Name); if (c) foreach (var(idx, start) in tab.Orphans.Index()) @@ -513,7 +513,7 @@ public partial class ModEditWindow using var s = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing); using (var _ = ImRaii.PushFont(UiBuilder.MonoFont)) { - ImGui.SetNextItemWidth(UiHelpers.Scale * 400); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 400); using var c = ImUtf8.Combo("##End", tab.Orphans[tab.NewMaterialParamEnd].Name); if (c) { @@ -542,7 +542,7 @@ public partial class ModEditWindow DrawShaderPackageStartCombo(tab); DrawShaderPackageEndCombo(tab); - ImGui.SetNextItemWidth(UiHelpers.Scale * 400); + ImGui.SetNextItemWidth(Im.Style.GlobalScale * 400); var newName = tab.NewMaterialParamName.Value!; if (ImUtf8.InputText("Name", ref newName)) tab.NewMaterialParamName = newName; @@ -551,7 +551,7 @@ public partial class ModEditWindow ? "The ID is already in use. Please choose a different name."u8 : ""u8; if (!ImUtf8.ButtonEx($"Add {tab.NewMaterialParamName} (0x{tab.NewMaterialParamName.Crc32:X8})", tooltip, - new Vector2(400 * UiHelpers.Scale, ImGui.GetFrameHeight()), tooltip.Length > 0)) + new Vector2(400 * Im.Style.GlobalScale, Im.Style.FrameHeight), tooltip.Length > 0)) return false; tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem(new MaterialParam diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs index e420dbb5..6366efdf 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs @@ -50,7 +50,7 @@ public partial class ModEditWindow using var id = ImRaii.PushId(label); ImEx.TextFramed(label, Im.ContentRegion.Available with { Y = 0 }, ImGuiColor.FrameBackground.Get()); - ImGui.NewLine(); + Im.Line.New(); using (ImRaii.Disabled(!_center.SaveTask.IsCompleted)) { @@ -68,7 +68,7 @@ public partial class ModEditWindow _center.DrawMatrixInputRight(size.X); } - ImGui.NewLine(); + Im.Line.New(); using var child2 = ImRaii.Child("image"); if (child2) TextureDrawer.Draw(tex, imageSize); @@ -81,7 +81,7 @@ public partial class ModEditWindow private void SaveAsCombo() { var (text, desc) = SaveAsStrings[_currentSaveAs]; - ImGui.SetNextItemWidth(-ImGui.GetFrameHeight() - ImGui.GetStyle().ItemSpacing.X); + ImGui.SetNextItemWidth(-Im.Style.FrameHeight - ImGui.GetStyle().ItemSpacing.X); using var combo = ImRaii.Combo("##format", text); ImGuiUtil.HoverTooltip(desc); if (!combo) @@ -137,8 +137,8 @@ public partial class ModEditWindow ? "This saves the texture in place. This is not revertible." : $"This saves the texture in place. This is not revertible. Hold {_config.DeleteModModifier} to save."; - var buttonSize2 = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X) / 2, 0); - var buttonSize3 = new Vector2((ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X * 2) / 3, 0); + var buttonSize2 = new Vector2((Im.ContentRegion.Available.X - ImGui.GetStyle().ItemSpacing.X) / 2, 0); + var buttonSize3 = new Vector2((Im.ContentRegion.Available.X - ImGui.GetStyle().ItemSpacing.X * 2) / 3, 0); if (ImGuiUtil.DrawDisabledButton("Save in place", buttonSize2, tt, !isActive || !canSaveInPlace || _center.IsLeftCopy && _currentSaveAs == (int)CombinedTexture.TextureSaveType.AsIs)) { @@ -159,7 +159,7 @@ public partial class ModEditWindow Im.Line.Same(); if (ImGui.Button("Export as DDS", buttonSize3)) OpenSaveAsDialog(".dds"); - ImGui.NewLine(); + Im.Line.New(); var canConvertInPlace = canSaveInPlace && _left.Type is TextureType.Tex && _center.IsLeftCopy; @@ -209,10 +209,10 @@ public partial class ModEditWindow ImGuiUtil.TextWrapped(_center.SaveTask.Exception?.ToString() ?? "Unknown Error"); break; } - default: ImGui.Dummy(new Vector2(1, ImGui.GetFrameHeight())); break; + default: ImGui.Dummy(new Vector2(1, Im.Style.FrameHeight)); break; } - ImGui.NewLine(); + Im.Line.New(); using var child2 = ImRaii.Child("image"); if (child2) @@ -280,7 +280,7 @@ public partial class ModEditWindow private Vector2 GetChildWidth() { - var windowWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - ImGui.GetTextLineHeight(); + var windowWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - Im.Style.TextHeight; if (_overlayCollapsed) { var width = windowWidth - ImGui.GetStyle().FramePadding.X * 3; @@ -332,7 +332,7 @@ public partial class ModEditWindow var (label, tooltip) = _overlayCollapsed ? (">", "Show a third panel in which you can import an additional texture as an overlay for the primary texture.") : ("<", "Hide the overlay texture panel and clear the currently loaded overlay texture, if any."); - if (ImGui.Button(label, new Vector2(ImGui.GetTextLineHeight(), ImGui.GetContentRegionAvail().Y))) + if (ImGui.Button(label, new Vector2(Im.Style.TextHeight, Im.ContentRegion.Available.Y))) _overlayCollapsed = !_overlayCollapsed; ImGuiUtil.HoverTooltip(tooltip); diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index 73ee867b..c3d60411 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -201,8 +201,8 @@ public partial class ModEditWindow : IndexedWindow, IDisposable { var radius = 100 * ImUtf8.GlobalScale; var thickness = (int)(20 * ImUtf8.GlobalScale); - var offsetX = ImGui.GetContentRegionAvail().X / 2 - radius; - var offsetY = ImGui.GetContentRegionAvail().Y / 2 - radius; + var offsetX = Im.ContentRegion.Available.X / 2 - radius; + var offsetY = Im.ContentRegion.Available.Y / 2 - radius; ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(offsetX, offsetY)); ImEx.Spinner("##spinner"u8, radius, thickness, ImGuiColor.Text.Get()); return; @@ -212,7 +212,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable if (!tabBar) return; - _iconSize = new Vector2(ImGui.GetFrameHeight()); + _iconSize = new Vector2(Im.Style.FrameHeight); DrawFileTab(); DrawMetaTab(); DrawSwapTab(); @@ -319,7 +319,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable if (!tab) return; - ImGui.NewLine(); + Im.Line.New(); if (ImGui.Button("Remove Missing Files from Mod")) _editor.FileEditor.RemoveMissingPaths(Mod!, _editor.Option!); @@ -369,7 +369,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable if (_editor.ModNormalizer.Running) { ImGui.ProgressBar((float)_editor.ModNormalizer.Step / _editor.ModNormalizer.TotalSteps, - new Vector2(300 * UiHelpers.Scale, ImGui.GetFrameHeight()), + new Vector2(300 * Im.Style.GlobalScale, Im.Style.FrameHeight), $"{_editor.ModNormalizer.Step} / {_editor.ModNormalizer.TotalSteps}"); } else if (ImGuiUtil.DrawDisabledButton("Re-Duplicate and Normalize Mod", Vector2.Zero, tt, !_allowReduplicate && !modifier)) @@ -383,7 +383,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable if (_editor.Duplicates.Duplicates.Count == 0) { - ImGui.NewLine(); + Im.Line.New(); ImGui.TextUnformatted("No duplicates found."); return; } @@ -446,7 +446,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable private bool DrawOptionSelectHeader() { using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero).Push(ImGuiStyleVar.FrameRounding, 0); - var width = new Vector2(ImGui.GetContentRegionAvail().X / 3, 0); + var width = new Vector2(Im.ContentRegion.Available.X / 3, 0); var ret = false; if (ImUtf8.ButtonEx("Default Option"u8, "Switch to the default option for the mod.\nThis resets unsaved changes."u8, width, _editor.Option is DefaultSubMod)) @@ -486,7 +486,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable var setsEqual = !_editor.SwapEditor.Changes; var tt = setsEqual ? "No changes staged." : "Apply the currently staged changes to the option."; - ImGui.NewLine(); + Im.Line.New(); if (ImGuiUtil.DrawDisabledButton("Apply Changes", Vector2.Zero, tt, setsEqual)) _editor.SwapEditor.Apply(_editor.Option!); @@ -512,8 +512,8 @@ public partial class ModEditWindow : IndexedWindow, IDisposable return; var idx = 0; - var iconSize = ImGui.GetFrameHeight() * Vector2.One; - var pathSize = ImGui.GetContentRegionAvail().X / 2 - iconSize.X; + var iconSize = Im.Style.FrameHeight * Vector2.One; + var pathSize = Im.ContentRegion.Available.X / 2 - iconSize.X; ImGui.TableSetupColumn("button", ImGuiTableColumnFlags.WidthFixed, iconSize.X); ImGui.TableSetupColumn("source", ImGuiTableColumnFlags.WidthFixed, pathSize); ImGui.TableSetupColumn("value", ImGuiTableColumnFlags.WidthFixed, pathSize); diff --git a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs index 44fc5d4c..bbae5fda 100644 --- a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs @@ -25,7 +25,7 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : Lu return; ImGui.Dummy(Vector2.One); - var size = 550 * ImGuiHelpers.GlobalScale; + var size = 550 * Im.Style.GlobalScale; DrawMergeInto(size); Im.Line.Same(); DrawMergeIntoDesc(); @@ -46,7 +46,7 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : Lu private void DrawMergeInto(float size) { using var bigGroup = ImRaii.Group(); - var minComboSize = 300 * ImGuiHelpers.GlobalScale; + var minComboSize = 300 * Im.Style.GlobalScale; var textSize = ImUtf8.CalcTextSize($"Merge {modMerger.MergeFromMod!.Name} into ").X; ImGui.AlignTextToFramePadding(); @@ -167,9 +167,9 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : Lu { var options = modMerger.MergeFromMod!.AllDataContainers.ToList(); var height = modMerger.Warnings.Count == 0 && modMerger.Error == null - ? ImGui.GetContentRegionAvail().Y - 3 * ImGui.GetFrameHeightWithSpacing() - : 8 * ImGui.GetFrameHeightWithSpacing(); - height = Math.Min(height, (options.Count + 1) * ImGui.GetFrameHeightWithSpacing()); + ? Im.ContentRegion.Available.Y - 3 * Im.Style.FrameHeightWithSpacing + : 8 * Im.Style.FrameHeightWithSpacing; + height = Math.Min(height, (options.Count + 1) * Im.Style.FrameHeightWithSpacing); var tableSize = new Vector2(size, height); using var table = ImRaii.Table("##options", 6, ImGuiTableFlags.RowBg @@ -181,12 +181,12 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : Lu if (!table) return; - ImGui.TableSetupColumn("##Selected", ImGuiTableColumnFlags.WidthFixed, ImGui.GetFrameHeight()); + ImGui.TableSetupColumn("##Selected", ImGuiTableColumnFlags.WidthFixed, Im.Style.FrameHeight); ImGui.TableSetupColumn("Option", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableSetupColumn("Option Group", ImGuiTableColumnFlags.WidthFixed, 120 * ImGuiHelpers.GlobalScale); - ImGui.TableSetupColumn("#Files", ImGuiTableColumnFlags.WidthFixed, 50 * ImGuiHelpers.GlobalScale); - ImGui.TableSetupColumn("#Swaps", ImGuiTableColumnFlags.WidthFixed, 50 * ImGuiHelpers.GlobalScale); - ImGui.TableSetupColumn("#Manips", ImGuiTableColumnFlags.WidthFixed, 50 * ImGuiHelpers.GlobalScale); + ImGui.TableSetupColumn("Option Group", ImGuiTableColumnFlags.WidthFixed, 120 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("#Files", ImGuiTableColumnFlags.WidthFixed, 50 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("#Swaps", ImGuiTableColumnFlags.WidthFixed, 50 * Im.Style.GlobalScale); + ImGui.TableSetupColumn("#Manips", ImGuiTableColumnFlags.WidthFixed, 50 * Im.Style.GlobalScale); ImGui.TableHeadersRow(); foreach (var (idx, option) in options.Index()) { @@ -224,11 +224,11 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : Lu } ImGui.TableNextColumn(); - ImGuiUtil.RightAlign(option.Files.Count.ToString(), 3 * ImGuiHelpers.GlobalScale); + ImGuiUtil.RightAlign(option.Files.Count.ToString(), 3 * Im.Style.GlobalScale); ImGui.TableNextColumn(); - ImGuiUtil.RightAlign(option.FileSwaps.Count.ToString(), 3 * ImGuiHelpers.GlobalScale); + ImGuiUtil.RightAlign(option.FileSwaps.Count.ToString(), 3 * Im.Style.GlobalScale); ImGui.TableNextColumn(); - ImGuiUtil.RightAlign(option.Manipulations.Count.ToString(), 3 * ImGuiHelpers.GlobalScale); + ImGuiUtil.RightAlign(option.Manipulations.Count.ToString(), 3 * Im.Style.GlobalScale); continue; void Handle(IModDataContainer option2, bool selected2) diff --git a/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs b/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs index adb38d75..8470e8ad 100644 --- a/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs +++ b/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs @@ -36,7 +36,7 @@ public sealed class OptionSelectCombo(ModEditor editor, ModEditWindow window) > 8 => ImGuiComboFlags.HeightLargest, _ => ImGuiComboFlags.None, }; - return Draw("##optionSelector", editor.Option!.GetFullName(), string.Empty, width, ImGui.GetTextLineHeight(), flags); + return Draw("##optionSelector", editor.Option!.GetFullName(), string.Empty, width, Im.Style.TextHeight, flags); } protected override bool DrawSelectable(int globalIdx, bool selected) diff --git a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs index 33ecddc1..8ed1b587 100644 --- a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs +++ b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs @@ -64,12 +64,12 @@ public class ResourceTreeViewer( if (!_task.IsCompleted) { - ImGui.NewLine(); + Im.Line.New(); ImGui.TextUnformatted("Calculating character list..."); } else if (_task.Exception != null) { - ImGui.NewLine(); + Im.Line.New(); using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder); ImGui.TextUnformatted($"Error during calculation of character list:\n\n{_task.Exception}"); } @@ -138,7 +138,7 @@ public class ResourceTreeViewer( _note = string.Empty; }, config.ExportDirectory, false); ImUtf8.SameLineInner(); - ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); + ImGui.SetNextItemWidth(Im.ContentRegion.Available.X); ImUtf8.InputText("##note"u8, ref _note, "Export note..."u8); @@ -151,7 +151,7 @@ public class ResourceTreeViewer( ImGui.TableSetupColumn("Game Path", ImGuiTableColumnFlags.WidthStretch, 0.3f); ImGui.TableSetupColumn("Actual Path", ImGuiTableColumnFlags.WidthStretch, 0.5f); ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, - actionCapacity * 3 * ImGuiHelpers.GlobalScale + (actionCapacity + 1) * ImGui.GetFrameHeight()); + actionCapacity * 3 * Im.Style.GlobalScale + (actionCapacity + 1) * Im.Style.FrameHeight); ImGui.TableHeadersRow(); DrawNodes(tree.Nodes, 0, unchecked(tree.DrawObjectAddress * 31), 0); @@ -179,47 +179,47 @@ public class ResourceTreeViewer( private void DrawControls() { - var yOffset = (ChangedItemDrawer.TypeFilterIconSize.Y - ImGui.GetFrameHeight()) / 2f; + var yOffset = (ChangedItemDrawer.TypeFilterIconSize.Y - Im.Style.FrameHeight) / 2f; ImGui.SetCursorPosY(ImGui.GetCursorPosY() + yOffset); if (ImGui.Button("Refresh Character List")) _task = RefreshCharacterList(); var checkSpacing = ImGui.GetStyle().ItemInnerSpacing.X; - var checkPadding = 10 * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.X; + var checkPadding = 10 * Im.Style.GlobalScale + ImGui.GetStyle().ItemSpacing.X; ImGui.SameLine(0, checkPadding); - using (ImRaii.PushId("TreeCategoryFilter")) - { - var categoryFilter = (uint)_categoryFilter; - foreach (var category in Enum.GetValues()) - { - using var c = ImGuiColor.CheckMark.Push(CategoryColor(category).Value()); - ImGui.CheckboxFlags($"##{category}", ref categoryFilter, (uint)category); - ImGuiUtil.HoverTooltip(CategoryFilterDescription(category)); - ImGui.SameLine(0.0f, checkSpacing); - } - - _categoryFilter = (TreeCategory)categoryFilter; + using (ImRaii.PushId("TreeCategoryFilter")) + { + var categoryFilter = (uint)_categoryFilter; + foreach (var category in Enum.GetValues()) + { + using var c = ImGuiColor.CheckMark.Push(CategoryColor(category).Value()); + ImGui.CheckboxFlags($"##{category}", ref categoryFilter, (uint)category); + ImGuiUtil.HoverTooltip(CategoryFilterDescription(category)); + ImGui.SameLine(0.0f, checkSpacing); + } + + _categoryFilter = (TreeCategory)categoryFilter; } ImGui.SameLine(0, checkPadding); var filterChanged = false; ImGui.SetCursorPosY(ImGui.GetCursorPosY() - yOffset); - using (ImRaii.Child("##typeFilter", new Vector2(ImGui.GetContentRegionAvail().X, ChangedItemDrawer.TypeFilterIconSize.Y))) + using (ImRaii.Child("##typeFilter", new Vector2(Im.ContentRegion.Available.X, ChangedItemDrawer.TypeFilterIconSize.Y))) { filterChanged |= changedItemDrawer.DrawTypeFilter(ref _typeFilter); } - var fieldWidth = (ImGui.GetContentRegionAvail().X - checkSpacing * 2.0f - ImGui.GetFrameHeightWithSpacing()) / 2.0f; + var fieldWidth = (Im.ContentRegion.Available.X - checkSpacing * 2.0f - Im.Style.FrameHeightWithSpacing) / 2.0f; ImGui.SetNextItemWidth(fieldWidth); filterChanged |= ImGui.InputTextWithHint("##TreeNameFilter", "Filter by Character/Entity Name...", ref _nameFilter, 128); ImGui.SameLine(0, checkSpacing); ImGui.SetNextItemWidth(fieldWidth); filterChanged |= ImGui.InputTextWithHint("##NodeFilter", "Filter by Item/Part Name or Path...", ref _nodeFilter, 128); ImGui.SameLine(0, checkSpacing); - incognito.DrawToggle(ImGui.GetFrameHeightWithSpacing()); + incognito.DrawToggle(Im.Style.FrameHeightWithSpacing); if (filterChanged) _filterCache.Clear(); @@ -247,7 +247,7 @@ public class ResourceTreeViewer( ChangedItemIconFlag parentFilterIconFlag) { var debugMode = config.DebugMode; - var frameHeight = ImGui.GetFrameHeight(); + var frameHeight = Im.Style.FrameHeight; foreach (var (index, resourceNode) in resourceNodes.Index()) { @@ -273,7 +273,7 @@ public class ResourceTreeViewer( { using var font = ImRaii.PushFont(UiBuilder.IconFont); var icon = (unfolded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight).ToIconString(); - var offset = (ImGui.GetFrameHeight() - ImGui.CalcTextSize(icon).X) / 2; + var offset = (Im.Style.FrameHeight - ImGui.CalcTextSize(icon).X) / 2; ImGui.SetCursorPosX(ImGui.GetCursorPosX() + offset); ImGui.TextUnformatted(icon); ImGui.SameLine(0f, offset + ImGui.GetStyle().ItemInnerSpacing.X); @@ -286,7 +286,7 @@ public class ResourceTreeViewer( unfolded = true; } - ImGui.Dummy(new Vector2(ImGui.GetFrameHeight())); + ImGui.Dummy(new Vector2(Im.Style.FrameHeight)); ImGui.SameLine(0f, ImGui.GetStyle().ItemInnerSpacing.X); } @@ -317,7 +317,7 @@ public class ResourceTreeViewer( 0 => "(none)", 1 => resourceNode.GamePath.ToString(), _ => "(multiple)", - }, false, hasGamePaths ? 0 : ImGuiSelectableFlags.Disabled, new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + }, false, hasGamePaths ? 0 : ImGuiSelectableFlags.Disabled, new Vector2(Im.ContentRegion.Available.X, frameHeight)); if (hasGamePaths) { var allPaths = string.Join('\n', resourceNode.PossibleGamePaths); @@ -338,7 +338,7 @@ public class ResourceTreeViewer( using (ImGuiColor.Text.Push((hasMod ? ColorId.NewMod : ColorId.DisabledMod).Value())) { ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + new Vector2(Im.ContentRegion.Available.X, frameHeight)); } Im.Line.Same(); @@ -355,17 +355,17 @@ public class ResourceTreeViewer( if (secondLastDirectorySeparator >= 0) path = $"…{path.AsSpan(secondLastDirectorySeparator)}"; ImGui.Selectable(path.AsSpan(), false, ImGuiSelectableFlags.AllowItemOverlap, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + new Vector2(Im.ContentRegion.Available.X, frameHeight)); } else { ImGui.Selectable(resourceNode.FullPath.ToPath(), false, ImGuiSelectableFlags.AllowItemOverlap, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + new Vector2(Im.ContentRegion.Available.X, frameHeight)); } if (ImGui.IsItemClicked()) ImGui.SetClipboardText(resourceNode.FullPath.ToPath()); - if (hasMod && ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl) + if (hasMod && Im.Item.RightClicked() && ImGui.GetIO().KeyCtrl) communicator.SelectTab.Invoke(new SelectTab.Arguments(TabType.Mods, mod)); ImGuiUtil.HoverTooltip( @@ -374,7 +374,7 @@ public class ResourceTreeViewer( else { ImUtf8.Selectable(GetPathStatusLabel(resourceNode.FullPathStatus), false, ImGuiSelectableFlags.Disabled, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + new Vector2(Im.ContentRegion.Available.X, frameHeight)); ImGuiUtil.HoverTooltip( $"{GetPathStatusDescription(resourceNode.FullPathStatus)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}"); } @@ -383,7 +383,7 @@ public class ResourceTreeViewer( ImGui.TableNextColumn(); using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, - ImGui.GetStyle().ItemSpacing with { X = 3 * ImGuiHelpers.GlobalScale }); + ImGui.GetStyle().ItemSpacing with { X = 3 * Im.Style.GlobalScale }); DrawActions(resourceNode, new Vector2(frameHeight)); if (unfolded) diff --git a/Penumbra/UI/ChangedItemDrawer.cs b/Penumbra/UI/ChangedItemDrawer.cs index 7a897f39..d6256158 100644 --- a/Penumbra/UI/ChangedItemDrawer.cs +++ b/Penumbra/UI/ChangedItemDrawer.cs @@ -117,8 +117,8 @@ public class ChangedItemDrawer : IDisposable, IUiService public void ChangedItemHandling(IIdentifiedObjectData data, bool leftClicked) { var ret = leftClicked ? MouseButton.Left : MouseButton.None; - ret = Im.Item.Clicked(ImSharp.MouseButton.Right) ? MouseButton.Right : ret; - ret = Im.Item.Clicked(ImSharp.MouseButton.Middle) ? MouseButton.Middle : ret; + ret = Im.Item.RightClicked() ? MouseButton.Right : ret; + ret = Im.Item.MiddleClicked() ? MouseButton.Middle : ret; if (ret != MouseButton.None) _communicator.ChangedItemClick.Invoke(new ChangedItemClick.Arguments(ret, data)); if (!Im.Item.Hovered()) @@ -199,7 +199,7 @@ public class ChangedItemDrawer : IDisposable, IUiService }); if (Im.Item.Clicked()) { - typeFilter = typeFilter == ChangedItemFlagExtensions.AllFlags ? 0 : ChangedItemFlagExtensions.AllFlags; + typeFilter = typeFilter is ChangedItemFlagExtensions.AllFlags ? 0 : ChangedItemFlagExtensions.AllFlags; ret = true; } diff --git a/Penumbra/UI/Classes/Combos.cs b/Penumbra/UI/Classes/Combos.cs index 234f7a3e..326534dc 100644 --- a/Penumbra/UI/Classes/Combos.cs +++ b/Penumbra/UI/Classes/Combos.cs @@ -1,4 +1,4 @@ -using Dalamud.Interface; +using ImSharp; using OtterGui; using Penumbra.GameData.Enums; using Penumbra.Meta.Manipulations; @@ -9,34 +9,34 @@ public static class Combos { // Different combos to use with enums. public static bool Race(string label, ModelRace current, out ModelRace race, float unscaledWidth = 100) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out race, RaceEnumExtensions.ToName, 1); + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out race, RaceEnumExtensions.ToName, 1); public static bool Gender(string label, Gender current, out Gender gender, float unscaledWidth = 120) => ImGuiUtil.GenericEnumCombo(label, unscaledWidth, current, out gender, RaceEnumExtensions.ToName, 1); public static bool EqdpEquipSlot(string label, EquipSlot current, out EquipSlot slot, float unscaledWidth = 100) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out slot, EquipSlotExtensions.EqdpSlots, + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out slot, EquipSlotExtensions.EqdpSlots, EquipSlotExtensions.ToName); public static bool EqpEquipSlot(string label, EquipSlot current, out EquipSlot slot, float unscaledWidth = 100) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out slot, EquipSlotExtensions.EquipmentSlots, + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out slot, EquipSlotExtensions.EquipmentSlots, EquipSlotExtensions.ToName); public static bool AccessorySlot(string label, EquipSlot current, out EquipSlot slot, float unscaledWidth = 100) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out slot, EquipSlotExtensions.AccessorySlots, + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out slot, EquipSlotExtensions.AccessorySlots, EquipSlotExtensions.ToName); public static bool SubRace(string label, SubRace current, out SubRace subRace, float unscaledWidth = 150) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out subRace, RaceEnumExtensions.ToName, 1); + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out subRace, RaceEnumExtensions.ToName, 1); public static bool RspAttribute(string label, RspAttribute current, out RspAttribute attribute, float unscaledWidth = 200) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out attribute, + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out attribute, RspAttributeExtensions.ToFullString, 0, 1); public static bool EstSlot(string label, EstType current, out EstType attribute, float unscaledWidth = 200) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out attribute); + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out attribute); public static bool ImcType(string label, ObjectType current, out ObjectType type, float unscaledWidth = 110) - => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * UiHelpers.Scale, current, out type, ObjectTypeExtensions.ValidImcTypes, + => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out type, ObjectTypeExtensions.ValidImcTypes, ObjectTypeExtensions.ToName); } diff --git a/Penumbra/UI/Classes/MigrationSectionDrawer.cs b/Penumbra/UI/Classes/MigrationSectionDrawer.cs index dd42e393..5a04dcfc 100644 --- a/Penumbra/UI/Classes/MigrationSectionDrawer.cs +++ b/Penumbra/UI/Classes/MigrationSectionDrawer.cs @@ -1,6 +1,4 @@ -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui.Text; using Penumbra.Services; namespace Penumbra.UI.Classes; @@ -12,18 +10,18 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura public void Draw() { - using var header = ImUtf8.CollapsingHeaderId("Migration"u8); + using var header = Im.Tree.HeaderId("Migration"u8); if (!header) return; _buttonSize = UiHelpers.InputTextWidth; DrawSettings(); - ImGui.Separator(); + Im.Separator(); DrawMdlMigration(); DrawMdlRestore(); DrawMdlCleanup(); // TODO enable when this works - ImGui.Separator(); + Im.Separator(); //DrawMtrlMigration(); DrawMtrlRestore(); DrawMtrlCleanup(); @@ -32,26 +30,26 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawSettings() { var value = config.MigrateImportedModelsToV6; - if (ImUtf8.Checkbox("Automatically Migrate V5 Models to V6 on Import"u8, ref value)) + if (Im.Checkbox("Automatically Migrate V5 Models to V6 on Import"u8, ref value)) { config.MigrateImportedModelsToV6 = value; config.Save(); } - ImUtf8.HoverTooltip("This increments the version marker and restructures the bone table to the new version."u8); + Im.Tooltip.OnHover("This increments the version marker and restructures the bone table to the new version."u8); // TODO enable when this works //value = config.MigrateImportedMaterialsToLegacy; - //if (ImUtf8.Checkbox("Automatically Migrate Materials to Dawntrail on Import"u8, ref value)) + //if (Im.Checkbox("Automatically Migrate Materials to Dawntrail on Import"u8, ref value)) //{ // config.MigrateImportedMaterialsToLegacy = value; // config.Save(); //} // - //ImUtf8.HoverTooltip( + //Im.Tooltip.OnHover( // "This currently only increases the color-table size and switches the shader from 'character.shpk' to 'characterlegacy.shpk', if the former is used."u8); - ImUtf8.Checkbox("Create Backups During Manual Migration", ref _createBackups); + Im.Checkbox("Create Backups During Manual Migration"u8, ref _createBackups); } private static ReadOnlySpan MigrationTooltip @@ -59,10 +57,10 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawMdlMigration() { - if (ImUtf8.ButtonEx("Migrate Model Files From V5 to V6"u8, "\0"u8, _buttonSize, migrationManager.IsRunning)) + if (ImEx.Button("Migrate Model Files From V5 to V6"u8, _buttonSize, StringU8.Empty, migrationManager.IsRunning)) migrationManager.MigrateMdlDirectory(config.ModDirectory, _createBackups); - ImUtf8.SameLineInner(); + Im.Line.SameInner(); DrawCancelButton(MigrationManager.TaskType.MdlMigration, "Cancel the migration. This does not revert already finished migrations."u8); DrawSpinner(migrationManager is { CurrentTask: MigrationManager.TaskType.MdlMigration, IsRunning: true }); DrawData(migrationManager.MdlMigration, "No model files found."u8, "migrated"u8); @@ -70,10 +68,10 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawMtrlMigration() { - if (ImUtf8.ButtonEx("Migrate Material Files to Dawntrail"u8, "\0"u8, _buttonSize, migrationManager.IsRunning)) + if (ImEx.Button("Migrate Material Files to Dawntrail"u8, _buttonSize, StringU8.Empty, migrationManager.IsRunning)) migrationManager.MigrateMtrlDirectory(config.ModDirectory, _createBackups); - ImUtf8.SameLineInner(); + Im.Line.SameInner(); DrawCancelButton(MigrationManager.TaskType.MtrlMigration, MigrationTooltip); DrawSpinner(migrationManager is { CurrentTask: MigrationManager.TaskType.MtrlMigration, IsRunning: true }); DrawData(migrationManager.MtrlMigration, "No material files found."u8, "migrated"u8); @@ -85,10 +83,10 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawMdlCleanup() { - if (ImUtf8.ButtonEx("Delete Existing Model Backup Files"u8, "\0"u8, _buttonSize, migrationManager.IsRunning)) + if (ImEx.Button("Delete Existing Model Backup Files"u8, _buttonSize, StringU8.Empty, migrationManager.IsRunning)) migrationManager.CleanMdlBackups(config.ModDirectory); - ImUtf8.SameLineInner(); + Im.Line.SameInner(); DrawCancelButton(MigrationManager.TaskType.MdlCleanup, CleanupTooltip); DrawSpinner(migrationManager is { CurrentTask: MigrationManager.TaskType.MdlCleanup, IsRunning: true }); DrawData(migrationManager.MdlCleanup, "No model backup files found."u8, "deleted"u8); @@ -96,10 +94,10 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawMtrlCleanup() { - if (ImUtf8.ButtonEx("Delete Existing Material Backup Files"u8, "\0"u8, _buttonSize, migrationManager.IsRunning)) + if (ImEx.Button("Delete Existing Material Backup Files"u8, _buttonSize, StringU8.Empty, migrationManager.IsRunning)) migrationManager.CleanMtrlBackups(config.ModDirectory); - ImUtf8.SameLineInner(); + Im.Line.SameInner(); DrawCancelButton(MigrationManager.TaskType.MtrlCleanup, CleanupTooltip); DrawSpinner(migrationManager is { CurrentTask: MigrationManager.TaskType.MtrlCleanup, IsRunning: true }); DrawData(migrationManager.MtrlCleanup, "No material backup files found."u8, "deleted"u8); @@ -110,10 +108,10 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawMdlRestore() { - if (ImUtf8.ButtonEx("Restore Model Backups"u8, "\0"u8, _buttonSize, migrationManager.IsRunning)) + if (ImEx.Button("Restore Model Backups"u8, _buttonSize, StringU8.Empty, migrationManager.IsRunning)) migrationManager.RestoreMdlBackups(config.ModDirectory); - ImUtf8.SameLineInner(); + Im.Line.SameInner(); DrawCancelButton(MigrationManager.TaskType.MdlRestoration, RestorationTooltip); DrawSpinner(migrationManager is { CurrentTask: MigrationManager.TaskType.MdlRestoration, IsRunning: true }); DrawData(migrationManager.MdlRestoration, "No model backup files found."u8, "restored"u8); @@ -121,10 +119,10 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura private void DrawMtrlRestore() { - if (ImUtf8.ButtonEx("Restore Material Backups"u8, "\0"u8, _buttonSize, migrationManager.IsRunning)) + if (ImEx.Button("Restore Material Backups"u8, _buttonSize, StringU8.Empty, migrationManager.IsRunning)) migrationManager.RestoreMtrlBackups(config.ModDirectory); - ImUtf8.SameLineInner(); + Im.Line.SameInner(); DrawCancelButton(MigrationManager.TaskType.MtrlRestoration, RestorationTooltip); DrawSpinner(migrationManager is { CurrentTask: MigrationManager.TaskType.MtrlRestoration, IsRunning: true }); DrawData(migrationManager.MtrlRestoration, "No material backup files found."u8, "restored"u8); @@ -136,13 +134,13 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura return; Im.Line.Same(); - ImEx.Spinner("Spinner"u8, ImGui.GetTextLineHeight() / 2, 2, ImGuiColor.Text.Get()); + ImEx.Spinner("Spinner"u8, Im.Style.TextHeight / 2, 2, ImGuiColor.Text.Get()); } private void DrawCancelButton(MigrationManager.TaskType task, ReadOnlySpan tooltip) { - using var _ = ImUtf8.PushId((int)task); - if (ImUtf8.ButtonEx("Cancel"u8, tooltip, disabled: !migrationManager.IsRunning || task != migrationManager.CurrentTask)) + using var _ = Im.Id.Push((int)task); + if (ImEx.Button("Cancel"u8, Vector2.Zero, tooltip, !migrationManager.IsRunning || task != migrationManager.CurrentTask)) migrationManager.Cancel(); } @@ -150,14 +148,14 @@ public class MigrationSectionDrawer(MigrationManager migrationManager, Configura { if (!data.HasData) { - ImUtf8.IconDummy(); + Im.FrameDummy(); return; } var total = data.Total; - if (total == 0) - ImUtf8.TextFrameAligned(empty); + if (total is 0) + ImEx.TextFrameAligned(empty); else - ImUtf8.TextFrameAligned($"{data.Changed} files {action}, {data.Failed} files failed, {total} files found."); + ImEx.TextFrameAligned($"{data.Changed} files {action}, {data.Failed} files failed, {total} files found."); } } diff --git a/Penumbra/UI/CollectionTab/CollectionPanel.cs b/Penumbra/UI/CollectionTab/CollectionPanel.cs index 9f8b8c44..c4de27b9 100644 --- a/Penumbra/UI/CollectionTab/CollectionPanel.cs +++ b/Penumbra/UI/CollectionTab/CollectionPanel.cs @@ -1,17 +1,11 @@ using Dalamud.Game.ClientState.Objects; -using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Interface.GameFonts; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ManagedFontAtlas; -using Dalamud.Interface.Utility; using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.GameData.Actors; @@ -40,10 +34,9 @@ public sealed class CollectionPanel( private readonly InheritanceUi _inheritanceUi = new(manager, incognito); private readonly IFontHandle _nameFont = pi.UiBuilder.FontAtlas.NewGameFontHandle(new GameFontStyle(GameFontFamilyAndSize.Jupiter23)); - private static readonly IReadOnlyDictionary Buttons = CreateButtons(); - private static readonly IReadOnlyList<(CollectionType, bool, bool, string, uint)> AdvancedTree = CreateTree(); - private readonly List<(CollectionType Type, ActorIdentifier Identifier)> _inUseCache = []; - private string? _newName; + private static readonly IReadOnlyDictionary Buttons = CreateButtons(); + private static readonly IReadOnlyList<(CollectionType, bool, bool, StringU8, Vector4)> AdvancedTree = CreateTree(); + private readonly List<(CollectionType Type, ActorIdentifier Identifier)> _inUseCache = []; private int _draggedIndividualAssignment = -1; @@ -61,7 +54,7 @@ public sealed class CollectionPanel( Im.TextWrapped( "There are functions you can assign these collections to, so different mod configurations apply for different things.\n"u8 + "You can assign an existing collection to such a function by clicking the function or dragging the collection over."u8); - ImGui.Separator(); + Im.Separator(); var buttonWidth = new Vector2(200 * Im.Style.GlobalScale, 2 * Im.Style.FrameHeightWithSpacing); using var style = Im.Style.Push(ImStyleDouble.ButtonTextAlign, Vector2.Zero) @@ -74,11 +67,12 @@ public sealed class CollectionPanel( DrawSimpleCollectionButton(CollectionType.MaleNonPlayerCharacter, buttonWidth); DrawSimpleCollectionButton(CollectionType.FemaleNonPlayerCharacter, buttonWidth); - ImGuiUtil.DrawColoredText(("Individual ", ColorId.NewMod.Value().Color), - ("Assignments take precedence before anything else and only apply to one specific character or monster.", 0)); - ImGui.Dummy(Vector2.UnitX); + ImEx.TextMultiColored("Individual"u8, ColorId.NewMod.Value()) + .Then("Assignments take precedence before anything else and only apply to one specific character or monster."u8) + .End(); + Im.Dummy(1); - var specialWidth = buttonWidth with { X = 275 * ImGuiHelpers.GlobalScale }; + var specialWidth = buttonWidth with { X = 275 * Im.Style.GlobalScale }; DrawCurrentCharacter(specialWidth); Im.Line.Same(); DrawCurrentTarget(specialWidth); @@ -107,31 +101,31 @@ public sealed class CollectionPanel( if (first) { - ImGui.Separator(); - ImGui.TextUnformatted("Currently Active Advanced Assignments"); + Im.Separator(); + Im.Text("Currently Active Advanced Assignments"u8); first = false; } DrawButton(name, type, buttonWidth, border, ActorIdentifier.Invalid, 's', collection); Im.Line.Same(); - if (ImGui.GetContentRegionAvail().X < buttonWidth.X + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X) - ImGui.NewLine(); + if (Im.ContentRegion.Available.X < buttonWidth.X + Im.Style.ItemSpacing.X + Im.Style.WindowPadding.X) + Im.Line.New(); } } /// Draw the panel containing new and existing individual assignments. public void DrawIndividualPanel() { - using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, Vector2.Zero) - .Push(ImGuiStyleVar.FrameBorderSize, 1 * ImGuiHelpers.GlobalScale); - var width = new Vector2(300 * ImGuiHelpers.GlobalScale, 2 * ImGui.GetTextLineHeightWithSpacing()); + using var style = ImStyleDouble.ButtonTextAlign.Push(Vector2.Zero) + .Push(ImStyleSingle.FrameBorderThickness, Im.Style.GlobalScale); + var width = new Vector2(300 * Im.Style.GlobalScale, 2 * Im.Style.TextHeightWithSpacing); - ImGui.Dummy(Vector2.One); + Im.Dummy(Vector2.One); DrawCurrentCharacter(width); Im.Line.Same(); DrawCurrentTarget(width); - ImGui.Separator(); - ImGui.Dummy(Vector2.One); + Im.Separator(); + Im.Dummy(Vector2.One); style.Pop(); _individualAssignmentUi.DrawWorldCombo(width.X / 2); Im.Line.Same(); @@ -143,58 +137,58 @@ public sealed class CollectionPanel( Im.Line.Same(); ImGuiComponents.HelpMarker( "Battle- and Event NPCs may apply to more than one ID if they share the same name. This is language dependent. If you change your clients language, verify that your collections are still correctly assigned."); - ImGui.Dummy(Vector2.One); - ImGui.Separator(); - style.Push(ImGuiStyleVar.FrameBorderSize, 1 * ImGuiHelpers.GlobalScale); + Im.Dummy(Vector2.One); + Im.Separator(); + style.Push(ImStyleSingle.FrameBorderThickness, Im.Style.GlobalScale); DrawNewPlayer(width); Im.Line.Same(); - ImGuiUtil.TextWrapped("Also check General Settings for UI characters and inheritance through ownership."); - ImGui.Separator(); + Im.TextWrapped("Also check General Settings for UI characters and inheritance through ownership."u8); + Im.Separator(); DrawNewRetainer(width); Im.Line.Same(); - ImGuiUtil.TextWrapped("Bell Retainers apply to Mannequins, but not to outdoor retainers, since those only carry their owners name."); - ImGui.Separator(); + Im.TextWrapped("Bell Retainers apply to Mannequins, but not to outdoor retainers, since those only carry their owners name."u8); + Im.Separator(); DrawNewNpc(width); Im.Line.Same(); - ImGuiUtil.TextWrapped("Some NPCs are available as Battle - and Event NPCs and need to be setup for both if desired."); - ImGui.Separator(); + Im.TextWrapped("Some NPCs are available as Battle - and Event NPCs and need to be setup for both if desired."u8); + Im.Separator(); DrawNewOwned(width); Im.Line.Same(); - ImGuiUtil.TextWrapped("Owned NPCs take precedence before unowned NPCs of the same type."); - ImGui.Separator(); + Im.TextWrapped("Owned NPCs take precedence before unowned NPCs of the same type."u8); + Im.Separator(); - DrawIndividualCollections(width with { X = 200 * ImGuiHelpers.GlobalScale }); + DrawIndividualCollections(width with { X = 200 * Im.Style.GlobalScale }); } /// Draw the panel containing all special group assignments. public void DrawGroupPanel() { - ImGui.Dummy(Vector2.One); - using var table = ImRaii.Table("##advanced", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); + Im.Dummy(Vector2.One); + using var table = Im.Table.Begin("##advanced"u8, 4, TableFlags.SizingFixedFit | TableFlags.RowBackground); if (!table) return; - using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, Vector2.Zero) - .Push(ImGuiStyleVar.FrameBorderSize, 1 * ImGuiHelpers.GlobalScale); + using var style = ImStyleDouble.ButtonTextAlign.Push(Vector2.Zero) + .Push(ImStyleSingle.FrameBorderThickness, Im.Style.GlobalScale); - var buttonWidth = new Vector2(150 * ImGuiHelpers.GlobalScale, 2 * ImGui.GetTextLineHeightWithSpacing()); - var dummy = new Vector2(1, 0); + var buttonWidth = new Vector2(150 * Im.Style.GlobalScale, 2 * Im.Style.TextHeightWithSpacing); + var dummy = new Vector2(1, 0); foreach (var (type, pre, post, name, border) in AdvancedTree) { - ImGui.TableNextColumn(); + table.NextColumn(); if (type is CollectionType.Inactive) continue; if (pre) - ImGui.Dummy(dummy); + Im.Dummy(dummy); DrawAssignmentButton(type, buttonWidth, name, border); if (post) - ImGui.Dummy(dummy); + Im.Dummy(dummy); } } @@ -206,108 +200,103 @@ public sealed class CollectionPanel( DrawStatistics(collection); DrawCollectionData(collection); _inheritanceUi.Draw(); - ImGui.Separator(); + Im.Separator(); DrawInactiveSettingsList(collection); DrawSettingsList(collection); } private void DrawCollectionData(ModCollection collection) { - ImGui.Dummy(Vector2.Zero); - ImGui.BeginGroup(); - ImGui.AlignTextToFramePadding(); - ImGui.TextUnformatted("Name"); - ImGui.AlignTextToFramePadding(); - ImGui.TextUnformatted("Identifier"); - ImGui.EndGroup(); + Im.Dummy(Vector2.Zero); + using (Im.Group()) + { + ImEx.TextFrameAligned("Name"u8); + ImEx.TextFrameAligned("Identifier"u8); + } + Im.Line.Same(); - ImGui.BeginGroup(); - var width = ImGui.GetContentRegionAvail().X; - using (ImRaii.Disabled(_collections.DefaultNamed == collection)) + using (Im.Group()) { - using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); - var name = _newName ?? collection.Identity.Name; - ImGui.SetNextItemWidth(width); - if (ImGui.InputText("##name", ref name, 128)) - _newName = name; - if (ImGui.IsItemDeactivatedAfterEdit() && _newName != null && _newName != collection.Identity.Name) + var width = Im.ContentRegion.Available.X; + using (Im.Disabled(_collections.DefaultNamed == collection)) { - collection.Identity.Name = _newName; - saveService.QueueSave(new ModCollectionSave(mods, collection)); - selector.RestoreCollections(); - _newName = null; + using var style = ImStyleDouble.ButtonTextAlign.Push(new Vector2(0, 0.5f)); + Im.Item.SetNextWidth(width); + if (ImEx.InputOnDeactivation.Text("##name"u8, collection.Identity.Name, out string newName) + && newName != collection.Identity.Name) + { + collection.Identity.Name = newName; + saveService.QueueSave(new ModCollectionSave(mods, collection)); + selector.RestoreCollections(); + } } - else if (ImGui.IsItemDeactivated()) - { - _newName = null; - } - } - if (_collections.DefaultNamed == collection) - ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "The Default collection can not be renamed."u8); - var identifier = collection.Identity.Identifier; - var fileName = saveService.FileNames.CollectionFile(collection); - using (ImRaii.PushFont(UiBuilder.MonoFont)) - { - if (ImGui.Button(collection.Identity.Identifier, new Vector2(width, 0))) - try - { - Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true }); - } - catch (Exception ex) - { - Penumbra.Messager.NotificationMessage(ex, $"Could not open file {fileName}.", $"Could not open file {fileName}", - NotificationType.Warning); - } + if (_collections.DefaultNamed == collection) + Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "The Default collection can not be renamed."u8); + + var identifier = collection.Identity.Identifier; + var fileName = saveService.FileNames.CollectionFile(collection); + using (Im.Font.PushMono()) + { + if (Im.Button(collection.Identity.Identifier, new Vector2(width, 0))) + try + { + Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true }); + } + catch (Exception ex) + { + Penumbra.Messager.NotificationMessage(ex, $"Could not open file {fileName}.", $"Could not open file {fileName}", + NotificationType.Warning); + } + } + + if (Im.Item.RightClicked()) + Im.Clipboard.Set(identifier); + + Im.Tooltip.OnHover( + $"Open the file\n\t{fileName}\ncontaining this design in the .json-editor of your choice.\n\nRight-Click to copy identifier to clipboard."); } - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) - ImGui.SetClipboardText(identifier); - - ImGuiUtil.HoverTooltip( - $"Open the file\n\t{fileName}\ncontaining this design in the .json-editor of your choice.\n\nRight-Click to copy identifier to clipboard."); - - ImGui.EndGroup(); - ImGui.Dummy(Vector2.Zero); - ImGui.Separator(); - ImGui.Dummy(Vector2.Zero); + Im.Dummy(Vector2.Zero); + Im.Separator(); + Im.Dummy(Vector2.Zero); } - private void DrawContext(bool open, ModCollection? collection, CollectionType type, ActorIdentifier identifier, string text, char suffix) + private void DrawContext(bool open, ModCollection? collection, CollectionType type, ActorIdentifier identifier, StringU8 text, char suffix) { var label = $"{type}{text}{suffix}"; if (open) - ImGui.OpenPopup(label); + Im.Popup.Open(label); - using var context = ImRaii.Popup(label); + using var context = Im.Popup.Begin(label); if (!context) return; - using (var color = ImGuiColor.Text.Push(Colors.DiscordColor)) + using (ImGuiColor.Text.Push(Colors.DiscordColor)) { - if (ImGui.MenuItem("Use no mods.")) + if (Im.Menu.Item("Use no mods."u8)) _active.SetCollection(ModCollection.Empty, type, _active.Individuals.GetGroup(identifier)); } - if (collection != null && type.CanBeRemoved()) + if (collection is not null && type.CanBeRemoved()) { using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder); - if (ImGui.MenuItem("Remove this assignment.")) + if (Im.Menu.Item("Remove this assignment."u8)) _active.SetCollection(null, type, _active.Individuals.GetGroup(identifier)); } foreach (var coll in _collections.OrderBy(c => c.Identity.Name)) { - if (coll != collection && ImGui.MenuItem($"Use {coll.Identity.Name}.")) + if (coll != collection && Im.Menu.Item($"Use {coll.Identity.Name}.")) _active.SetCollection(coll, type, _active.Individuals.GetGroup(identifier)); } } - private bool DrawButton(string text, CollectionType type, Vector2 width, Rgba32 borderColor, ActorIdentifier id, char suffix, + private void DrawButton(StringU8 text, CollectionType type, Vector2 width, Rgba32 borderColor, ActorIdentifier id, char suffix, ModCollection? collection = null) { - using var group = ImRaii.Group(); - var invalid = type == CollectionType.Individual && !id.IsValid; + using var group = Im.Group(); + var invalid = type is CollectionType.Individual && !id.IsValid; var redundancy = _active.RedundancyCheck(type, id); collection ??= _active.ByType(type, id); using var color = ImGuiColor.Button.Push( @@ -321,38 +310,36 @@ public sealed class CollectionPanel( ? ColorId.NoModsAssignment.Value() : ImGuiColor.Button.Get(), !invalid) .Push(ImGuiColor.Border, borderColor == 0 ? ImGuiColor.TextDisabled.Get().Color : borderColor); - using var disabled = ImRaii.Disabled(invalid); - var button = ImGui.Button(text, width) || ImGui.IsItemClicked(ImGuiMouseButton.Right); - var hovered = redundancy.Length > 0 && ImGui.IsItemHovered(); + using var disabled = Im.Disabled(invalid); + var button = Im.Button(text, width) || Im.Item.RightClicked(); + var hovered = redundancy.Length > 0 && Im.Item.Hovered(); DrawIndividualDragSource(text, id); DrawIndividualDragTarget(id); if (!invalid) { selector.DragTargetAssignment(type, id); var name = Name(collection); - var size = ImGui.CalcTextSize(name); - var textPos = ImGui.GetItemRectMax() - size - ImGui.GetStyle().FramePadding; - ImGui.GetWindowDrawList().AddText(textPos, ImGuiColor.Text.Get().Color, name); + var size = Im.Font.CalculateSize(name); + var textPos = Im.Item.LowerRightCorner - size - Im.Style.FramePadding; + Im.Window.DrawList.Text(textPos, ImGuiColor.Text.Get().Color, name); DrawContext(button, collection, type, id, text, suffix); } if (hovered) - ImGui.SetTooltip(redundancy); - - return button; + Im.Tooltip.Set(redundancy); } - private void DrawIndividualDragSource(string text, ActorIdentifier id) + private void DrawIndividualDragSource(ReadOnlySpan text, ActorIdentifier id) { if (!id.IsValid) return; - using var source = ImRaii.DragDropSource(); + using var source = Im.DragDrop.Source(); if (!source) return; - ImGui.SetDragDropPayload("DragIndividual", null, 0); - ImGui.TextUnformatted($"Re-ordering {text}..."); + Im.DragDrop.SetPayload("DragIndividual"u8); + Im.Text($"Re-ordering {text}..."); _draggedIndividualAssignment = _active.Individuals.Index(id); } @@ -361,8 +348,8 @@ public sealed class CollectionPanel( if (!id.IsValid) return; - using var target = ImRaii.DragDropTarget(); - if (!target || !ImGuiUtil.IsDropping("DragIndividual")) + using var target = Im.DragDrop.Target(); + if (!target || !target.IsDropping("DragIndividual")) return; var currentIdx = _active.Individuals.Index(id); @@ -373,55 +360,84 @@ public sealed class CollectionPanel( private void DrawSimpleCollectionButton(CollectionType type, Vector2 width) { - DrawButton(type.ToName(), type, width, 0, ActorIdentifier.Invalid, 's'); + DrawButton(new StringU8(type.ToName()), type, width, 0, ActorIdentifier.Invalid, 's'); Im.Line.Same(); - using (var group = ImRaii.Group()) + using (Im.Group()) { - ImGuiUtil.TextWrapped(type.ToDescription()); + Im.TextWrapped(type.ToDescription()); switch (type) { - case CollectionType.Default: ImGui.TextUnformatted("Overruled by any other Assignment."); break; + case CollectionType.Default: Im.Text("Overruled by any other Assignment."u8); break; case CollectionType.Yourself: - ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Individual ", ColorId.NewMod.Value().Color), ("Assignments.", 0)); + ImEx.TextMultiColored("Overruled by "u8) + .Then("Individual "u8, ColorId.NewMod.Value().Color) + .Then("Assignments."u8) + .End(); break; case CollectionType.MalePlayerCharacter: - ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Male Racial Player", Colors.DiscordColor), (", ", 0), - ("Your Character", ColorId.HandledConflictMod.Value().Color), (", or ", 0), - ("Individual ", ColorId.NewMod.Value().Color), ("Assignments.", 0)); + ImEx.TextMultiColored("Overruled by "u8) + .Then("Male Racial Player"u8, Colors.DiscordColor) + .Then(", "u8) + .Then("Your Character"u8, ColorId.HandledConflictMod.Value().Color) + .Then(", or "u8) + .Then("Individual "u8, ColorId.NewMod.Value().Color) + .Then("Assignments."u8) + .End(); break; case CollectionType.FemalePlayerCharacter: - ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Female Racial Player", Colors.ReniColorActive), (", ", 0), - ("Your Character", ColorId.HandledConflictMod.Value().Color), (", or ", 0), - ("Individual ", ColorId.NewMod.Value().Color), ("Assignments.", 0)); + ImEx.TextMultiColored("Overruled by "u8) + .Then("Female Racial Player"u8, Colors.ReniColorActive) + .Then(", "u8) + .Then("Your Character"u8, ColorId.HandledConflictMod.Value().Color) + .Then(", or "u8) + .Then("Individual "u8, ColorId.NewMod.Value().Color) + .Then("Assignments."u8) + .End(); break; case CollectionType.MaleNonPlayerCharacter: - ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Male Racial NPC", Colors.DiscordColor), (", ", 0), - ("Children", ColorId.FolderLine.Value().Color), (", ", 0), ("Elderly", Colors.MetaInfoText), (", or ", 0), - ("Individual ", ColorId.NewMod.Value().Color), ("Assignments.", 0)); + ImEx.TextMultiColored("Overruled by "u8) + .Then("Male Racial NPC"u8, Colors.DiscordColor) + .Then(", "u8) + .Then("Children"u8, ColorId.FolderLine.Value().Color) + .Then(", "u8) + .Then("Elderly"u8, Colors.MetaInfoText) + .Then(", or "u8) + .Then("Individual "u8, ColorId.NewMod.Value().Color) + .Then("Assignments.") + .End(); break; case CollectionType.FemaleNonPlayerCharacter: - ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Female Racial NPC", Colors.ReniColorActive), (", ", 0), - ("Children", ColorId.FolderLine.Value().Color), (", ", 0), ("Elderly", Colors.MetaInfoText), (", or ", 0), - ("Individual ", ColorId.NewMod.Value().Color), ("Assignments.", 0)); + ImEx.TextMultiColored("Overruled by "u8) + .Then("Female Racial NPC"u8, Colors.ReniColorActive) + .Then(", "u8) + .Then("Children"u8, ColorId.FolderLine.Value().Color) + .Then(", "u8) + .Then("Elderly"u8, Colors.MetaInfoText) + .Then(", or ") + .Then("Individual "u8, ColorId.NewMod.Value().Color) + .Then("Assignments."u8) + .End(); break; } } - ImGui.Separator(); + Im.Separator(); } - private void DrawAssignmentButton(CollectionType type, Vector2 width, string name, uint color) + private void DrawAssignmentButton(CollectionType type, Vector2 width, StringU8 name, Vector4 color) => DrawButton(name, type, width, color, ActorIdentifier.Invalid, 's', _active.ByType(type)); /// Respect incognito mode for names of identifiers. - private string Name(ActorIdentifier id, string? name) + private StringU8 Name(ActorIdentifier id, string? name) => incognito.IncognitoMode && id.Type is IdentifierType.Player or IdentifierType.Owned - ? id.Incognito(name) - : name ?? id.ToString(); + ? new StringU8(id.Incognito(name)) + : name is not null + ? new StringU8(name) + : new StringU8($"{id}"); /// Respect incognito mode for names of collections. private string Name(ModCollection? collection) - => collection == null ? "Unassigned" : + => collection is null ? "Unassigned" : collection == ModCollection.Empty ? "Use No Mods" : incognito.IncognitoMode ? collection.Identity.AnonymizedName : collection.Identity.Name; @@ -429,16 +445,16 @@ public sealed class CollectionPanel( { if (identifiers.Length > 0 && identifiers[0].IsValid) { - DrawButton($"{intro} ({Name(identifiers[0], null)})", CollectionType.Individual, width, 0, identifiers[0], suffix); + DrawButton(new StringU8($"{intro} ({Name(identifiers[0], null)})"), CollectionType.Individual, width, 0, identifiers[0], suffix); } else { if (tooltip.Length == 0 && identifiers.Length > 0) tooltip = $"The current target {identifiers[0].PlayerName} is not valid for an assignment."; - DrawButton($"{intro} (Unavailable)", CollectionType.Individual, width, 0, ActorIdentifier.Invalid, suffix); + DrawButton(new StringU8($"{intro} (Unavailable)"), CollectionType.Individual, width, 0, ActorIdentifier.Invalid, suffix); } - ImGuiUtil.HoverTooltip(tooltip); + Im.Tooltip.OnHover(tooltip); } private void DrawCurrentCharacter(Vector2 width) @@ -472,50 +488,49 @@ public sealed class CollectionPanel( DrawButton(Name(ids[0], name), CollectionType.Individual, width, 0, ids[0], 'i', coll); Im.Line.Same(); - if (ImGui.GetContentRegionAvail().X < width.X + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X + if (Im.ContentRegion.Available.X < width.X + Im.Style.ItemSpacing.X + Im.Style.WindowPadding.X && i < _active.Individuals.Count - 1) - ImGui.NewLine(); + Im.Line.New(); } if (_active.Individuals.Count > 0) - ImGui.NewLine(); + Im.Line.New(); } private void DrawCollectionName(ModCollection collection) { - ImGui.Dummy(Vector2.One); - using var color = ImGuiColor.Border.Push(Colors.MetaInfoText); - using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 2 * UiHelpers.Scale); + Im.Dummy(Vector2.One); + using var style = ImStyleBorder.Frame.Push(Colors.MetaInfoText, 2 * Im.Style.GlobalScale); using var f = _nameFont.Push(); var name = Name(collection); - var size = ImGui.CalcTextSize(name).X; - var pos = ImGui.GetContentRegionAvail().X - size + ImGui.GetStyle().FramePadding.X * 2; + var size = Im.Font.CalculateSize(name).X; + var pos = Im.ContentRegion.Available.X - size + Im.Style.FramePadding.X * 2; if (pos > 0) - ImGui.SetCursorPosX(pos / 2); - ImGuiUtil.DrawTextButton(name, Vector2.Zero, 0); - ImGui.Dummy(Vector2.One); + Im.Cursor.X = pos / 2; + ImEx.TextFramed(name, Vector2.Zero, 0); + Im.Dummy(Vector2.One); } private void DrawStatistics(ModCollection collection) { GatherInUse(collection); - ImGui.Separator(); + Im.Separator(); - var buttonHeight = 2 * ImGui.GetTextLineHeightWithSpacing(); + var buttonHeight = 2 * Im.Style.TextHeightWithSpacing; if (_inUseCache.Count == 0 && collection.Inheritance.DirectlyInheritedBy.Count == 0) { - ImGui.Dummy(Vector2.One); + Im.Dummy(Vector2.One); using var f = _nameFont.Push(); - ImGuiUtil.DrawTextButton("Collection is not used.", new Vector2(ImGui.GetContentRegionAvail().X, buttonHeight), + ImEx.TextFramed("Collection is not used."u8, Im.ContentRegion.Available with { Y = buttonHeight }, Colors.PressEnterWarningBg); - ImGui.Dummy(Vector2.One); - ImGui.Separator(); + Im.Dummy(Vector2.One); + Im.Separator(); } else { - var buttonWidth = new Vector2(175 * ImGuiHelpers.GlobalScale, buttonHeight); + var buttonWidth = new Vector2(175 * Im.Style.GlobalScale, buttonHeight); DrawInUseStatistics(collection, buttonWidth); - DrawInheritanceStatistics(collection, buttonWidth); + DrawInheritanceStatistics(collection); } } @@ -528,8 +543,8 @@ public sealed class CollectionPanel( .Where(t => _active.ByType(t) == collection)) _inUseCache.Add((special, ActorIdentifier.Invalid)); - foreach (var (_, id, coll) in _active.Individuals.Assignments.Where(t - => t.Collection == collection && t.Identifiers.FirstOrDefault().IsValid)) + foreach (var (_, id, _) in _active.Individuals.Assignments.Where(t + => t.Collection == collection && t.Identifiers.Count > 0 && t.Identifiers[0].IsValid)) _inUseCache.Add((CollectionType.Individual, id[0])); } @@ -538,155 +553,152 @@ public sealed class CollectionPanel( if (_inUseCache.Count <= 0) return; - using (var _ = ImRaii.PushStyle(ImGuiStyleVar.FramePadding, Vector2.Zero)) + using (ImStyleDouble.FramePadding.Push(Vector2.Zero)) { - ImGuiUtil.DrawTextButton("In Use By", ImGui.GetContentRegionAvail() with { Y = 0 }, 0); + ImEx.TextFramed("In Use By"u8, Im.ContentRegion.Available with { Y = 0 }, 0); } - using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, 1 * ImGuiHelpers.GlobalScale) - .Push(ImGuiStyleVar.ButtonTextAlign, Vector2.Zero); + using var style = ImStyleSingle.FrameBorderThickness.Push(Im.Style.GlobalScale) + .Push(ImStyleDouble.ButtonTextAlign, Vector2.Zero); foreach (var (idx, (type, id)) in _inUseCache.Index()) { - var name = type == CollectionType.Individual ? Name(id, null) : Buttons[type].Name; - var color = Buttons.TryGetValue(type, out var p) ? p.Border : 0; + var name = type is CollectionType.Individual ? Name(id, null) : Buttons[type].Name; + var color = Buttons.TryGetValue(type, out var p) ? p.Border : Vector4.Zero; DrawButton(name, type, buttonWidth, color, id, 's', collection); Im.Line.Same(); - if (ImGui.GetContentRegionAvail().X < buttonWidth.X + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X + if (Im.ContentRegion.Available.X < buttonWidth.X + Im.Style.ItemSpacing.X + Im.Style.WindowPadding.X && idx != _inUseCache.Count - 1) - ImGui.NewLine(); + Im.Line.New(); } - ImGui.NewLine(); - ImGui.Dummy(Vector2.One); - ImGui.Separator(); + Im.Line.New(); + Im.Dummy(Vector2.One); + Im.Separator(); } - private void DrawInheritanceStatistics(ModCollection collection, Vector2 buttonWidth) + private void DrawInheritanceStatistics(ModCollection collection) { if (collection.Inheritance.DirectlyInheritedBy.Count <= 0) return; - using (var _ = ImRaii.PushStyle(ImGuiStyleVar.FramePadding, Vector2.Zero)) + using (ImStyleDouble.FramePadding.Push(Vector2.Zero)) { - ImGuiUtil.DrawTextButton("Inherited by", ImGui.GetContentRegionAvail() with { Y = 0 }, 0); + ImEx.TextFramed("Inherited by"u8, Im.ContentRegion.Available with { Y = 0 }, 0); } using var f = _nameFont.Push(); - using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale); - using var color = ImGuiColor.Border.Push(Colors.MetaInfoText); - ImGuiUtil.DrawTextButton(Name(collection.Inheritance.DirectlyInheritedBy[0]), Vector2.Zero, 0); - var constOffset = (ImGui.GetStyle().FramePadding.X + ImGuiHelpers.GlobalScale) * 2 - + ImGui.GetStyle().ItemSpacing.X - + ImGui.GetStyle().WindowPadding.X; + using var style = ImStyleBorder.Frame.Push(Colors.MetaInfoText); + ImEx.TextFramed(Name(collection.Inheritance.DirectlyInheritedBy[0]), Vector2.Zero, 0); + var constOffset = (Im.Style.FramePadding.X + Im.Style.GlobalScale) * 2 + + Im.Style.ItemSpacing.X + + Im.Style.WindowPadding.X; foreach (var parent in collection.Inheritance.DirectlyInheritedBy.Skip(1)) { var name = Name(parent); - var size = ImGui.CalcTextSize(name).X; + var size = Im.Font.CalculateSize(name).X; Im.Line.Same(); - if (constOffset + size >= ImGui.GetContentRegionAvail().X) - ImGui.NewLine(); - ImGuiUtil.DrawTextButton(name, Vector2.Zero, 0); + if (constOffset + size >= Im.ContentRegion.Available.X) + Im.Line.New(); + ImEx.TextFramed(name, Vector2.Zero, 0); } - ImGui.Dummy(Vector2.One); - ImGui.Separator(); + Im.Dummy(Vector2.One); + Im.Separator(); } private void DrawSettingsList(ModCollection collection) { - ImGui.Dummy(Vector2.One); - var size = new Vector2(ImGui.GetContentRegionAvail().X, 10 * ImGui.GetFrameHeightWithSpacing()); - using var table = ImRaii.Table("##activeSettings", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, size); + Im.Dummy(Vector2.One); + var size = Im.ContentRegion.Available with { Y = 10 * Im.Style.FrameHeightWithSpacing }; + using var table = Im.Table.Begin("##activeSettings"u8, 4, TableFlags.ScrollY | TableFlags.RowBackground, size); if (!table) return; - ImGui.TableSetupScrollFreeze(0, 1); - ImGui.TableSetupColumn("Mod Name", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableSetupColumn("Inherited From", ImGuiTableColumnFlags.WidthFixed, 5f * ImGui.GetFrameHeight()); - ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, 1.75f * ImGui.GetFrameHeight()); - ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, 2.5f * ImGui.GetFrameHeight()); - ImGui.TableHeadersRow(); + table.SetupScrollFreeze(0, 1); + table.SetupColumn("Mod Name"u8, TableColumnFlags.WidthStretch); + table.SetupColumn("Inherited From"u8, TableColumnFlags.WidthFixed, 5f * Im.Style.FrameHeight); + table.SetupColumn("State"u8, TableColumnFlags.WidthFixed, 1.75f * Im.Style.FrameHeight); + table.SetupColumn("Priority"u8, TableColumnFlags.WidthFixed, 2.5f * Im.Style.FrameHeight); + table.HeaderRow(); + foreach (var (mod, (settings, parent)) in mods.Select(m => (m, collection.GetInheritedSettings(m.Index))) .Where(t => t.Item2.Settings != null) .OrderBy(t => t.m.Name)) { - ImGui.TableNextColumn(); - ImGuiUtil.CopyOnClickSelectable(mod.Name); - ImGui.TableNextColumn(); + table.NextColumn(); + ImEx.CopyOnClickSelectable(mod.Name); + table.NextColumn(); if (parent != collection) - ImGui.TextUnformatted(Name(parent)); - ImGui.TableNextColumn(); + Im.Text(Name(parent)); + table.NextColumn(); var enabled = settings!.Enabled; - using (var dis = ImRaii.Disabled()) + using (Im.Disabled()) { - ImGui.Checkbox("##check", ref enabled); + Im.Checkbox("##check"u8, ref enabled); } - ImGui.TableNextColumn(); - ImGuiUtil.RightAlign(settings.Priority.ToString(), ImGui.GetStyle().WindowPadding.X); + table.NextColumn(); + ImEx.TextRightAligned($"{settings.Priority}", Im.Style.WindowPadding.X); } } private void DrawInactiveSettingsList(ModCollection collection) { - if (collection.Settings.Unused.Count == 0) + if (collection.Settings.Unused.Count is 0) return; - ImGui.Dummy(Vector2.One); - var text = collection.Settings.Unused.Count > 1 - ? $"Clear all {collection.Settings.Unused.Count} unused settings from deleted mods." - : "Clear the currently unused setting from a deleted mods."; - if (ImGui.Button(text, new Vector2(ImGui.GetContentRegionAvail().X, 0))) + Im.Dummy(Vector2.One); + if (Im.Button(collection.Settings.Unused.Count > 1 + ? $"Clear all {collection.Settings.Unused.Count} unused settings from deleted mods." + : "Clear the currently unused setting from a deleted mods."u8, Im.ContentRegion.Available with { Y = 0 })) _collections.CleanUnavailableSettings(collection); - ImGui.Dummy(Vector2.One); + Im.Dummy(Vector2.One); - var size = new Vector2(ImGui.GetContentRegionAvail().X, - Math.Min(10, collection.Settings.Unused.Count + 1) * ImGui.GetFrameHeightWithSpacing()); - using var table = ImRaii.Table("##inactiveSettings", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, size); + var size = Im.ContentRegion.Available with { Y = Math.Min(10, collection.Settings.Unused.Count + 1) * Im.Style.FrameHeightWithSpacing }; + using var table = Im.Table.Begin("##inactiveSettings"u8, 4, TableFlags.ScrollY | TableFlags.RowBackground, size); if (!table) return; - ImGui.TableSetupScrollFreeze(0, 1); - ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, UiHelpers.IconButtonSize.X); - ImGui.TableSetupColumn("Unused Mod Identifier", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, 1.75f * ImGui.GetFrameHeight()); - ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, 2.5f * ImGui.GetFrameHeight()); - ImGui.TableHeadersRow(); + table.SetupScrollFreeze(0, 1); + table.SetupColumn(StringU8.Empty, TableColumnFlags.WidthFixed, UiHelpers.IconButtonSize.X); + table.SetupColumn("Unused Mod Identifier"u8, TableColumnFlags.WidthStretch); + table.SetupColumn("State"u8, TableColumnFlags.WidthFixed, 1.75f * Im.Style.FrameHeight); + table.SetupColumn("Priority"u8, TableColumnFlags.WidthFixed, 2.5f * Im.Style.FrameHeight); + table.HeaderRow(); string? delete = null; foreach (var (name, settings) in collection.Settings.Unused.OrderBy(n => n.Key)) { - using var id = ImRaii.PushId(name); - ImGui.TableNextColumn(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), UiHelpers.IconButtonSize, - "Delete this unused setting.", false, true)) + using var id = Im.Id.Push(name); + table.NextColumn(); + if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this unused setting."u8)) delete = name; - ImGui.TableNextColumn(); - ImGuiUtil.CopyOnClickSelectable(name); - ImGui.TableNextColumn(); + table.NextColumn(); + ImEx.CopyOnClickSelectable(name); + table.NextColumn(); var enabled = settings.Enabled; - using (var dis = ImRaii.Disabled()) + using (Im.Disabled()) { - ImGui.Checkbox("##check", ref enabled); + Im.Checkbox("##check"u8, ref enabled); } - ImGui.TableNextColumn(); - ImGuiUtil.RightAlign(settings.Priority.ToString(), ImGui.GetStyle().WindowPadding.X); + table.NextColumn(); + ImEx.TextRightAligned($"{settings.Priority}", Im.Style.WindowPadding.X); } _collections.CleanUnavailableSetting(collection, delete); - ImGui.Separator(); + Im.Separator(); } /// Create names and border colors for special assignments. - private static IReadOnlyDictionary CreateButtons() + private static IReadOnlyDictionary CreateButtons() { - var ret = Enum.GetValues().ToDictionary(t => t, t => (t.ToName(), 0u)); + var ret = Enum.GetValues().ToDictionary(t => t, t => (new StringU8(t.ToName()), Vector4.Zero)); foreach (var race in Enum.GetValues().Skip(1)) { - var color = race switch + Rgba32 color = race switch { SubRace.Midlander => 0xAA5C9FE4u, SubRace.Highlander => 0xAA5C9FE4u, @@ -707,29 +719,25 @@ public sealed class CollectionPanel( _ => 0u, }; - ret[CollectionTypeExtensions.FromParts(race, Gender.Male, false)] = ($"♂ {race.ToShortName()}", color); - ret[CollectionTypeExtensions.FromParts(race, Gender.Female, false)] = ($"♀ {race.ToShortName()}", color); - ret[CollectionTypeExtensions.FromParts(race, Gender.Male, true)] = ($"♂ {race.ToShortName()} (NPC)", color); - ret[CollectionTypeExtensions.FromParts(race, Gender.Female, true)] = ($"♀ {race.ToShortName()} (NPC)", color); + ret[CollectionTypeExtensions.FromParts(race, Gender.Male, false)] = (new StringU8($"♂ {race.ToShortName()}"), color.ToVector()); + ret[CollectionTypeExtensions.FromParts(race, Gender.Female, false)] = (new StringU8($"♀ {race.ToShortName()}"), color.ToVector()); + ret[CollectionTypeExtensions.FromParts(race, Gender.Male, true)] = + (new StringU8($"♂ {race.ToShortName()} (NPC)"), color.ToVector()); + ret[CollectionTypeExtensions.FromParts(race, Gender.Female, true)] = + (new StringU8($"♀ {race.ToShortName()} (NPC)"), color.ToVector()); } - ret[CollectionType.MalePlayerCharacter] = ("♂ Player", 0); - ret[CollectionType.FemalePlayerCharacter] = ("♀ Player", 0); - ret[CollectionType.MaleNonPlayerCharacter] = ("♂ NPC", 0); - ret[CollectionType.FemaleNonPlayerCharacter] = ("♀ NPC", 0); + ret[CollectionType.MalePlayerCharacter] = (new StringU8("♂ Player"), Vector4.Zero); + ret[CollectionType.FemalePlayerCharacter] = (new StringU8("♀ Player"), Vector4.Zero); + ret[CollectionType.MaleNonPlayerCharacter] = (new StringU8("♂ NPC"), Vector4.Zero); + ret[CollectionType.FemaleNonPlayerCharacter] = (new StringU8("♀ NPC"), Vector4.Zero); return ret; } /// Create the special assignment tree in order and with free spaces. - private static IReadOnlyList<(CollectionType, bool, bool, string, uint)> CreateTree() + private static List<(CollectionType, bool, bool, StringU8, Vector4)> CreateTree() { - var ret = new List<(CollectionType, bool, bool, string, uint)>(Buttons.Count); - - void Add(CollectionType type, bool pre, bool post) - { - var (name, border) = Buttons[type]; - ret.Add((type, pre, post, name, border)); - } + var ret = new List<(CollectionType, bool, bool, StringU8, Vector4)>(Buttons.Count); Add(CollectionType.Default, false, false); Add(CollectionType.Interface, false, false); @@ -754,5 +762,11 @@ public sealed class CollectionPanel( } return ret; + + void Add(CollectionType type, bool localPre, bool post) + { + var (name, border) = Buttons[type]; + ret.Add((type, localPre, post, name, border)); + } } } diff --git a/Penumbra/UI/CollectionTab/InheritanceUi.cs b/Penumbra/UI/CollectionTab/InheritanceUi.cs index 3fd1fe89..fbb3c15e 100644 --- a/Penumbra/UI/CollectionTab/InheritanceUi.cs +++ b/Penumbra/UI/CollectionTab/InheritanceUi.cs @@ -35,7 +35,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService DrawNewInheritanceSelection(); Im.Line.Same(); - if (ImGui.Button("More Information about Inheritance", new Vector2(ImGui.GetContentRegionAvail().X, 0))) + if (ImGui.Button("More Information about Inheritance", new Vector2(Im.ContentRegion.Available.X, 0))) ImGui.OpenPopup("InheritanceHelp"); DrawHelpPopup(); @@ -61,9 +61,9 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService } private static void DrawHelpPopup() - => ImGuiUtil.HelpPopup("InheritanceHelp", new Vector2(1000 * UiHelpers.Scale, 20 * ImGui.GetTextLineHeightWithSpacing()), () => + => ImGuiUtil.HelpPopup("InheritanceHelp", new Vector2(1000 * Im.Style.GlobalScale, 20 * Im.Style.TextHeightWithSpacing), () => { - ImGui.NewLine(); + Im.Line.New(); ImGui.TextUnformatted("Every mod in a collection can have three basic states: 'Enabled', 'Disabled' and 'Unconfigured'."); ImGui.BulletText("If the mod is 'Enabled' or 'Disabled', it does not matter if the collection inherits from other collections."); ImGui.BulletText( @@ -73,7 +73,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService ImGui.BulletText("If no such collection is found, the mod will be treated as disabled."); ImGui.BulletText( "Highlighted collections in the left box are never reached because they are already checked in a sub-inheritance before."); - ImGui.NewLine(); + Im.Line.New(); ImGui.TextUnformatted("Example"); ImGui.BulletText("Collection A has the Bibo+ body and a Hempen Camise mod enabled."); ImGui.BulletText( @@ -102,9 +102,9 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService var lineStart = ImGui.GetCursorScreenPos(); var offsetX = -ImGui.GetStyle().IndentSpacing + ImGui.GetTreeNodeToLabelSpacing() / 2; var drawList = ImGui.GetWindowDrawList(); - var lineSize = Math.Max(0, ImGui.GetStyle().IndentSpacing - 9 * UiHelpers.Scale); + var lineSize = Math.Max(0, ImGui.GetStyle().IndentSpacing - 9 * Im.Style.GlobalScale); lineStart.X += offsetX; - lineStart.Y -= 2 * UiHelpers.Scale; + lineStart.Y -= 2 * Im.Style.GlobalScale; var lineEnd = lineStart; // Skip the collection itself. @@ -127,12 +127,12 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService // Draw the notch and increase the line length. var midPoint = (minRect.Y + maxRect.Y) / 2f - 1f; drawList.AddLine(lineStart with { Y = midPoint }, new Vector2(lineStart.X + lineSize, midPoint), Colors.MetaInfoText, - UiHelpers.Scale); + Im.Style.GlobalScale); lineEnd.Y = midPoint; } // Finally, draw the folder line. - drawList.AddLine(lineStart, lineEnd, Colors.MetaInfoText, UiHelpers.Scale); + drawList.AddLine(lineStart, lineEnd, Colors.MetaInfoText, Im.Style.GlobalScale); } /// Draw a single primary inherited collection. @@ -158,7 +158,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService private void DrawCurrentCollectionInheritance() { using var list = ImRaii.ListBox("##inheritanceList", - new Vector2(UiHelpers.InputTextMinusButton, ImGui.GetTextLineHeightWithSpacing() * InheritedCollectionHeight)); + new Vector2(UiHelpers.InputTextMinusButton, Im.Style.TextHeightWithSpacing * InheritedCollectionHeight)); if (!list) return; @@ -171,7 +171,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService /// Draw a drag and drop button to delete. private void DrawInheritanceTrashButton() { - var size = UiHelpers.IconButtonSize with { Y = ImGui.GetTextLineHeightWithSpacing() * InheritedCollectionHeight }; + var size = UiHelpers.IconButtonSize with { Y = Im.Style.TextHeightWithSpacing * InheritedCollectionHeight }; var buttonColor = Im.Style[ImGuiColor.Button]; // Prevent hovering from highlighting the button. using var color = ImGuiColor.ButtonActive.Push(buttonColor) @@ -300,7 +300,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService /// private void DrawInheritanceTreeClicks(ModCollection collection, bool withDelete) { - if (ImGui.GetIO().KeyCtrl && ImGui.IsItemClicked(ImGuiMouseButton.Right)) + if (ImGui.GetIO().KeyCtrl && Im.Item.RightClicked()) { if (withDelete && ImGui.GetIO().KeyShift) _inheritanceAction = (_active.Current.Inheritance.DirectlyInheritsFrom.IndexOf(collection), -1); diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index f2d018c4..9f2c458a 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -1,20 +1,14 @@ using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.Api.Enums; using Penumbra.Services; using Penumbra.UI.Classes; using Penumbra.UI.Tabs; -using Penumbra.Util; -using Window = Dalamud.Interface.Windowing.Window; namespace Penumbra.UI; -public sealed class ConfigWindow : Window, Luna.IUiService +public sealed class ConfigWindow : Window { private readonly IDalamudPluginInterface _pluginInterface; private readonly Configuration _config; @@ -55,10 +49,10 @@ public sealed class ConfigWindow : Window, Luna.IUiService public override void PreDraw() { if (_config.Ephemeral.FixMainWindow) - Flags |= ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove; + Flags |= WindowFlags.NoResize | WindowFlags.NoMove; else - Flags &= ~(ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove); - SizeConstraints = new WindowSizeConstraints() + Flags &= ~(WindowFlags.NoResize | WindowFlags.NoMove); + SizeConstraints = new WindowSizeConstraints { MinimumSize = _config.MinimumSize, MaximumSize = new Vector2(4096, 2160), @@ -138,33 +132,33 @@ public sealed class ConfigWindow : Window, Luna.IUiService ? "Penumbra###PenumbraConfigWindow" : $"Penumbra v{checker.Version}###PenumbraConfigWindow"; - private void DrawProblemWindow(string text) + private void DrawProblemWindow(Utf8StringHandler text) { using var color = ImGuiColor.Text.Push(Colors.RegexWarningBorder); - ImGui.NewLine(); - ImGui.NewLine(); - ImUtf8.TextWrapped(text); + Im.Line.New(); + Im.Line.New(); + Im.TextWrapped(ref text); color.Pop(); - ImGui.NewLine(); - ImGui.NewLine(); + Im.Line.New(); + Im.Line.New(); SupportButton.Discord(Penumbra.Messager, 0); Im.Line.Same(); UiHelpers.DrawSupportButton(_penumbra!); - ImGui.NewLine(); - ImGui.NewLine(); + Im.Line.New(); + Im.Line.New(); } private void DrawImcExceptions() { - ImGui.TextUnformatted("Exceptions"); - ImGui.Separator(); - using var box = ImRaii.ListBox("##Exceptions", new Vector2(-1, -1)); + Im.Text("Exceptions"u8); + Im.Separator(); + using var box = Im.ListBox.Begin("##Exceptions"u8, new Vector2(-1, -1)); foreach (var exception in _validityChecker.ImcExceptions) { - ImGuiUtil.TextWrapped(exception.ToString()); - ImGui.Separator(); - ImGui.NewLine(); + Im.TextWrapped($"{exception}"); + Im.Separator(); + Im.Line.New(); } } } diff --git a/Penumbra/UI/FileDialogService.cs b/Penumbra/UI/FileDialogService.cs index abfe11d2..00fcc189 100644 --- a/Penumbra/UI/FileDialogService.cs +++ b/Penumbra/UI/FileDialogService.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Utility; -using Dalamud.Bindings.ImGui; +using ImSharp; using Luna; using Penumbra.Communication; using Penumbra.Services; @@ -120,7 +120,7 @@ public class FileDialogService : IDisposable, IUiService { var fileManager = new FileDialogManager { - AddedWindowFlags = ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoDocking, + AddedWindowFlags = (WindowFlags.NoCollapse | WindowFlags.NoDocking).ToDalamudWindowFlags(), }; if (WindowsFunctions.GetDownloadsFolder(out var downloadsFolder)) diff --git a/Penumbra/UI/ModsTab/DescriptionEditPopup.cs b/Penumbra/UI/ModsTab/DescriptionEditPopup.cs index b03dd72e..1ea273ac 100644 --- a/Penumbra/UI/ModsTab/DescriptionEditPopup.cs +++ b/Penumbra/UI/ModsTab/DescriptionEditPopup.cs @@ -55,7 +55,7 @@ public class DescriptionEditPopup(ModManager modManager) : Luna.IUiService ImUtf8.OpenPopup(PopupId); } - var inputSize = ImGuiHelpers.ScaledVector2(800); + var inputSize = ImEx.ScaledVector(800); using var popup = ImUtf8.Popup(PopupId); if (!popup) return; diff --git a/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs b/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs index ee2e11af..59b0e54e 100644 --- a/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs @@ -1,5 +1,6 @@ using Dalamud.Interface; using Dalamud.Bindings.ImGui; +using ImSharp; using OtterGui; using OtterGui.Raii; using OtterGui.Text; @@ -59,8 +60,8 @@ public readonly struct CombiningModGroupEditDrawer(ModGroupEditDrawer editor, Co new Vector2(400 * ImUtf8.GlobalScale, 0))) ImUtf8.OpenPopup("DataContainerNames"u8); - var sizeX = group.OptionData.Count * (ImGui.GetStyle().ItemInnerSpacing.X + ImGui.GetFrameHeight()) + 300 * ImUtf8.GlobalScale; - ImGui.SetNextWindowSize(new Vector2(sizeX, ImGui.GetFrameHeightWithSpacing() * Math.Min(16, group.Data.Count) + 200 * ImUtf8.GlobalScale)); + var sizeX = group.OptionData.Count * (ImGui.GetStyle().ItemInnerSpacing.X + Im.Style.FrameHeight) + 300 * ImUtf8.GlobalScale; + ImGui.SetNextWindowSize(new Vector2(sizeX, Im.Style.FrameHeightWithSpacing * Math.Min(16, group.Data.Count) + 200 * ImUtf8.GlobalScale)); using var popup = ImUtf8.Popup("DataContainerNames"u8); if (!popup) return; @@ -71,10 +72,10 @@ public readonly struct CombiningModGroupEditDrawer(ModGroupEditDrawer editor, Co ImUtf8.SameLineInner(); } - ImGui.NewLine(); + Im.Line.New(); ImGui.Separator(); - using var child = ImUtf8.Child("##Child"u8, ImGui.GetContentRegionAvail()); - ImGuiClip.ClippedDraw(group.Data, DrawRow, ImGui.GetFrameHeightWithSpacing()); + using var child = ImUtf8.Child("##Child"u8, Im.ContentRegion.Available); + ImGuiClip.ClippedDraw(group.Data, DrawRow, Im.Style.FrameHeightWithSpacing); } private void DrawRow(CombinedDataContainer container, int index) diff --git a/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs b/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs index a09e4fb9..1d231912 100644 --- a/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs @@ -60,7 +60,7 @@ public sealed class ModGroupDrawer : Luna.IUiService CurrentSelectionIdx = currentOption; CurrentSelection = _group.Options[CurrentSelectionIdx]; if (Draw(string.Empty, CurrentSelection.Name, string.Empty, ref CurrentSelectionIdx, UiHelpers.InputTextWidth.X * 3 / 4, - ImGui.GetTextLineHeightWithSpacing())) + Im.Style.TextHeightWithSpacing)) parent.SetModSetting(_group, _groupIdx, Setting.Single(CurrentSelectionIdx)); } } @@ -173,7 +173,7 @@ public sealed class ModGroupDrawer : Luna.IUiService Widget.EndFramedGroup(); var label = $"##multi{groupIdx}"; - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + if (Im.Item.RightClicked()) ImUtf8.OpenPopup($"##multi{groupIdx}"); DrawMultiPopup(group, groupIdx, label); @@ -254,7 +254,7 @@ public sealed class ModGroupDrawer : Luna.IUiService { var optionWidth = options.Max(o => ImUtf8.CalcTextSize(o.Name).X) + ImGui.GetStyle().ItemInnerSpacing.X - + ImGui.GetFrameHeight() + + Im.Style.FrameHeight + ImGui.GetStyle().FramePadding.X; var width = Math.Max(optionWidth, minWidth); if (ImUtf8.Button(buttonTextShow, new Vector2(width, 0))) diff --git a/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs b/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs index 9b43de70..34f944c9 100644 --- a/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs @@ -1,6 +1,7 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; using Dalamud.Bindings.ImGui; +using ImSharp; using Luna; using OtterGui; using OtterGui.Raii; @@ -23,7 +24,7 @@ public sealed class ModGroupEditDrawer( Configuration config, FilenameService filenames, DescriptionEditPopup descriptionPopup, - ImcChecker imcChecker) : Luna.IUiService + ImcChecker imcChecker) : IUiService { private static ReadOnlySpan AcrossGroupsLabel => "##DragOptionAcross"u8; @@ -99,7 +100,7 @@ public sealed class ModGroupEditDrawer( { var text = _currentGroupEdited == group ? _currentGroupName ?? group.Name : group.Name; ImGui.SetNextItemWidth(_groupNameWidth); - using var border = ImRaii.PushFrameBorder(UiHelpers.ScaleX2, Colors.RegexWarningBorder, !_isGroupNameValid); + using var border = ImRaii.PushFrameBorder(Im.Style.GlobalScale * 2, Colors.RegexWarningBorder, !_isGroupNameValid); if (ImUtf8.InputText("##GroupName"u8, ref text)) { _currentGroupEdited = group; @@ -140,7 +141,7 @@ public sealed class ModGroupEditDrawer( ? (_currentGroupPriority ?? group.Priority).Value : group.Priority.Value; ImGui.SetNextItemWidth(PriorityWidth); - if (ImGui.InputInt("##GroupPriority", ref priority, 0, 0)) + if (ImGui.InputInt("##GroupPriority", ref priority)) { _currentGroupEdited = group; _currentGroupPriority = new ModPriority(priority); diff --git a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs index f256e15f..862bcbb3 100644 --- a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs +++ b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs @@ -223,7 +223,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector + ImGuiUtil.HelpPopup("ExtendedHelp", new Vector2(1000 * Im.Style.GlobalScale, 38.5f * Im.Style.TextHeightWithSpacing), () => { - ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeight()); + ImGui.Dummy(Vector2.UnitY * Im.Style.TextHeight); ImUtf8.Text("Mod Management"u8); ImUtf8.BulletText("You can create empty mods or import mods with the buttons in this row."u8); using var indent = ImRaii.PushIndent(); @@ -452,7 +452,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector 0) ImUtf8.Text($"It is also implicitly used in {inherited} {(inherited == 1 ? "collection" : "collections")} through inheritance."); - ImGui.NewLine(); + Im.Line.New(); ImGui.Separator(); - ImGui.NewLine(); + Im.Line.New(); using var table = ImUtf8.Table("##modCollections"u8, 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); if (!table) return; - var size = ImUtf8.CalcTextSize(ToText(ModState.Unconfigured)).X + 20 * ImGuiHelpers.GlobalScale; - var collectionSize = 200 * ImGuiHelpers.GlobalScale; + var size = ImUtf8.CalcTextSize(ToText(ModState.Unconfigured)).X + 20 * Im.Style.GlobalScale; + var collectionSize = 200 * Im.Style.GlobalScale; ImGui.TableSetupColumn("Collection", ImGuiTableColumnFlags.WidthFixed, collectionSize); ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, size); ImGui.TableSetupColumn("Inherited From", ImGuiTableColumnFlags.WidthFixed, collectionSize); diff --git a/Penumbra/UI/ModsTab/ModPanelConflictsTab.cs b/Penumbra/UI/ModsTab/ModPanelConflictsTab.cs index 6ab54a01..d098fbd5 100644 --- a/Penumbra/UI/ModsTab/ModPanelConflictsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelConflictsTab.cs @@ -39,13 +39,13 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy public void DrawContent() { - using var table = ImRaii.Table("conflicts", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, ImGui.GetContentRegionAvail()); + using var table = ImRaii.Table("conflicts", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, Im.ContentRegion.Available); if (!table) return; - var buttonSize = new Vector2(ImGui.GetFrameHeight()); + var buttonSize = new Vector2(Im.Style.FrameHeight); var spacing = ImGui.GetStyle().ItemInnerSpacing with { Y = ImGui.GetStyle().ItemSpacing.Y }; - var priorityRowWidth = ImGui.CalcTextSize("Priority").X + 20 * ImGuiHelpers.GlobalScale + 2 * buttonSize.X; + var priorityRowWidth = ImGui.CalcTextSize("Priority").X + 20 * Im.Style.GlobalScale + 2 * buttonSize.X; var priorityWidth = priorityRowWidth - 2 * (buttonSize.X + spacing.X); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); ImGui.TableSetupColumn("Conflicting Mod", ImGuiTableColumnFlags.WidthStretch); @@ -106,7 +106,7 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy if (ImGui.Selectable(conflict.Mod2.Name) && conflict.Mod2 is Mod otherMod) selector.SelectByValue(otherMod); var hovered = ImGui.IsItemHovered(); - var rightClicked = ImGui.IsItemClicked(ImGuiMouseButton.Right); + var rightClicked = Im.Item.RightClicked(); if (conflict.Mod2 is Mod otherMod2) { if (hovered) diff --git a/Penumbra/UI/ModsTab/ModPanelDescriptionTab.cs b/Penumbra/UI/ModsTab/ModPanelDescriptionTab.cs index ac779335..2da5c450 100644 --- a/Penumbra/UI/ModsTab/ModPanelDescriptionTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelDescriptionTab.cs @@ -1,5 +1,5 @@ using Dalamud.Bindings.ImGui; -using Dalamud.Interface.Utility; +using ImSharp; using OtterGui.Raii; using OtterGui; using OtterGui.Widgets; @@ -26,11 +26,11 @@ public class ModPanelDescriptionTab( if (!child) return; - ImGui.Dummy(ImGuiHelpers.ScaledVector2(2)); + ImGui.Dummy(ImEx.ScaledVector(2)); - ImGui.Dummy(ImGuiHelpers.ScaledVector2(2)); + ImGui.Dummy(ImEx.ScaledVector(2)); var (predefinedTagsEnabled, predefinedTagButtonOffset) = predefinedTagsConfig.Enabled - ? (true, ImGui.GetFrameHeight() + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0)) + ? (true, Im.Style.FrameHeight + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0)) : (false, 0); var tagIdx = _localTags.Draw("Local Tags: ", "Custom tags you can set personally that will not be exported to the mod data but only set for you.\n" @@ -49,7 +49,7 @@ public class ModPanelDescriptionTab( selector.Selected!.ModTags, out _, false, ImGui.CalcTextSize("Local ").X - ImGui.CalcTextSize("Mod ").X); - ImGui.Dummy(ImGuiHelpers.ScaledVector2(2)); + ImGui.Dummy(ImEx.ScaledVector(2)); ImGui.Separator(); ImGuiUtil.TextWrapped(selector.Selected!.Description); diff --git a/Penumbra/UI/ModsTab/ModPanelEditTab.cs b/Penumbra/UI/ModsTab/ModPanelEditTab.cs index 07ff516f..1facc0b0 100644 --- a/Penumbra/UI/ModsTab/ModPanelEditTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelEditTab.cs @@ -70,7 +70,7 @@ public class ModPanelEditTab( UiHelpers.DefaultLineSpace(); var sharedTagsEnabled = predefinedTagManager.Enabled; - var sharedTagButtonOffset = sharedTagsEnabled ? ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X : 0; + var sharedTagButtonOffset = sharedTagsEnabled ? Im.Style.FrameHeight + ImGui.GetStyle().FramePadding.X : 0; var tagIdx = _modTags.Draw("Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags, out var editedTag, rightEndOffset: sharedTagButtonOffset); if (tagIdx >= 0) @@ -98,7 +98,7 @@ public class ModPanelEditTab( /// The general edit row for non-detailed mod edits. private void EditButtons() { - var buttonSize = new Vector2(150 * UiHelpers.Scale, 0); + var buttonSize = new Vector2(150 * Im.Style.GlobalScale, 0); var folderExists = Directory.Exists(_mod.ModPath.FullName); var tt = folderExists ? $"Open \"{_mod.ModPath.FullName}\" in the file explorer of your choice." @@ -129,7 +129,7 @@ public class ModPanelEditTab( if (ImUtf8.ButtonEx("Export Mod"u8, tt, buttonSize, ModBackup.CreatingBackup)) backup.CreateAsync(); - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + if (Im.Item.RightClicked()) ImUtf8.OpenPopup("context"u8); Im.Line.Same(); @@ -181,7 +181,7 @@ public class ModPanelEditTab( UiHelpers.InputTextWidth.X)) modManager.DataEditor.ChangeModWebsite(_mod, newWebsite); - using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(UiHelpers.ScaleX3)); + using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(Im.Style.GlobalScale * 3)); var reducedSize = new Vector2(UiHelpers.InputTextMinusButton3, 0); if (ImGui.Button("Edit Description", reducedSize)) diff --git a/Penumbra/UI/ModsTab/ModPanelHeader.cs b/Penumbra/UI/ModsTab/ModPanelHeader.cs index b1d4d9e5..c0d0b55e 100644 --- a/Penumbra/UI/ModsTab/ModPanelHeader.cs +++ b/Penumbra/UI/ModsTab/ModPanelHeader.cs @@ -36,10 +36,10 @@ public class ModPanelHeader : IDisposable public void Draw() { UpdateModData(); - var height = ImGui.GetContentRegionAvail().Y; + var height = Im.ContentRegion.Available.Y; var maxHeight = 3 * height / 4; using var child = _lastPreSettingsHeight > maxHeight && _communicator.PreSettingsTabBarDraw.HasSubscribers - ? ImRaii.Child("HeaderChild", new Vector2(ImGui.GetContentRegionAvail().X, maxHeight), false) + ? ImRaii.Child("HeaderChild", new Vector2(Im.ContentRegion.Available.X, maxHeight), false) : null; using (ImRaii.Group()) { @@ -75,7 +75,7 @@ public class ModPanelHeader : IDisposable { using var f = _nameFont.Push(); _modName = name; - _modNameWidth = ImGui.CalcTextSize(name).X + 2 * (ImGui.GetStyle().FramePadding.X + 2 * UiHelpers.Scale); + _modNameWidth = ImGui.CalcTextSize(name).X + 2 * (ImGui.GetStyle().FramePadding.X + 2 * Im.Style.GlobalScale); } // Author @@ -178,7 +178,7 @@ public class ModPanelHeader : IDisposable { if (_modWebsiteButton.Length == 0) { - ImGui.NewLine(); + Im.Line.New(); return; } diff --git a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs index 209b0996..666b9038 100644 --- a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs @@ -40,7 +40,7 @@ public class ModPanelSettingsTab( public void DrawContent() { - using var table = ImUtf8.Table("##settings"u8, 1, ImGuiTableFlags.ScrollY, ImGui.GetContentRegionAvail()); + using var table = ImUtf8.Table("##settings"u8, 1, ImGuiTableFlags.ScrollY, Im.ContentRegion.Available); if (!table) return; @@ -76,7 +76,7 @@ public class ModPanelSettingsTab( return; using var color = ImGuiColor.Button.Push(Rgba32.TintColor(Im.Style[ImGuiColor.Button], ColorId.TemporaryModSettingsTint.Value().ToVector())); - var width = new Vector2(ImGui.GetContentRegionAvail().X, 0); + var width = new Vector2(Im.ContentRegion.Available.X, 0); if (ImUtf8.ButtonEx($"These settings are temporarily set by {selection.TemporarySettings!.Source}{(_locked ? " and locked." : ".")}", width, _locked)) @@ -93,7 +93,7 @@ public class ModPanelSettingsTab( return; using var color = ImGuiColor.Button.Push(Colors.PressEnterWarningBg); - var width = new Vector2(ImGui.GetContentRegionAvail().X, 0); + var width = new Vector2(Im.ContentRegion.Available.X, 0); if (ImUtf8.ButtonEx($"These settings are inherited from {selection.Collection.Identity.Name}.", width, _locked)) { if (_temporary) @@ -142,7 +142,7 @@ public class ModPanelSettingsTab( using var group = ImUtf8.Group(); var settings = selection.Settings; var priority = _currentPriority ?? settings.Priority.Value; - ImGui.SetNextItemWidth(50 * UiHelpers.Scale); + ImGui.SetNextItemWidth(50 * Im.Style.GlobalScale); using var disabled = ImRaii.Disabled(_locked); if (ImUtf8.InputScalar("##Priority"u8, ref priority)) _currentPriority = priority; diff --git a/Penumbra/UI/ModsTab/MultiModPanel.cs b/Penumbra/UI/ModsTab/MultiModPanel.cs index cea228ba..f8d0605b 100644 --- a/Penumbra/UI/ModsTab/MultiModPanel.cs +++ b/Penumbra/UI/ModsTab/MultiModPanel.cs @@ -17,7 +17,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, if (selector.SelectedPaths.Count == 0) return; - ImGui.NewLine(); + Im.Line.New(); var treeNodePos = ImGui.GetCursorPos(); var numLeaves = DrawModList(); DrawCounts(treeNodePos, numLeaves); @@ -50,8 +50,8 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, if (!tree) return selector.SelectedPaths.Count(l => l is ModFileSystem.Leaf); - var sizeType = new Vector2(ImGui.GetFrameHeight()); - var availableSizePercent = (ImGui.GetContentRegionAvail().X - sizeType.X - 4 * ImGui.GetStyle().CellPadding.X) / 100; + var sizeType = new Vector2(Im.Style.FrameHeight); + var availableSizePercent = (Im.ContentRegion.Available.X - sizeType.X - 4 * ImGui.GetStyle().CellPadding.X) / 100; var sizeMods = availableSizePercent * 35; var sizeFolders = availableSizePercent * 65; @@ -94,14 +94,14 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, private void DrawMultiTagger() { - var width = ImGuiHelpers.ScaledVector2(150, 0); + var width = ImEx.ScaledVector(150, 0); ImUtf8.TextFrameAligned("Multi Tagger:"u8); Im.Line.Same(); var predefinedTagsEnabled = tagManager.Enabled; var inputWidth = predefinedTagsEnabled - ? ImGui.GetContentRegionAvail().X - 2 * width.X - 3 * ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - : ImGui.GetContentRegionAvail().X - 2 * (width.X + ImGui.GetStyle().ItemInnerSpacing.X); + ? Im.ContentRegion.Available.X - 2 * width.X - 3 * ImGui.GetStyle().ItemInnerSpacing.X - Im.Style.FrameHeight + : Im.ContentRegion.Available.X - 2 * (width.X + ImGui.GetStyle().ItemInnerSpacing.X); ImGui.SetNextItemWidth(inputWidth); ImUtf8.InputText("##tag"u8, ref _tag, "Local Tag Name..."u8); diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs index 68d00ae2..4106f75d 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs @@ -100,7 +100,7 @@ public sealed class ResourceWatcher : IDisposable, ITab, Luna.IUiService { UpdateRecords(); - ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetTextLineHeightWithSpacing() / 2); + ImGui.SetCursorPosY(ImGui.GetCursorPosY() + Im.Style.TextHeightWithSpacing / 2); var isEnabled = _ephemeral.EnableResourceWatcher; if (Im.Checkbox("Enable"u8, ref isEnabled)) { @@ -182,7 +182,7 @@ public sealed class ResourceWatcher : IDisposable, ITab, Luna.IUiService Im.Item.SetNextWidthScaled(80); Im.Input.Scalar("Max. Entries"u8, ref _newMaxEntries); var change = ImGui.IsItemDeactivatedAfterEdit(); - if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl) + if (Im.Item.RightClicked() && ImGui.GetIO().KeyCtrl) { change = true; _newMaxEntries = DefaultMaxEntries; diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs index 3cc974c2..81e0490f 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs @@ -42,7 +42,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class PathColumn : ColumnString { public override float Width - => 300 * UiHelpers.Scale; + => 300 * Im.Style.GlobalScale; public override string ToName(Record item) => item.Path.ToString(); @@ -51,7 +51,7 @@ internal sealed class ResourceWatcherTable : Table => lhs.Path.CompareTo(rhs.Path); public override void DrawColumn(Record item, int _) - => DrawByteString(item.Path, 280 * UiHelpers.Scale); + => DrawByteString(item.Path, 280 * Im.Style.GlobalScale); } private static unsafe void DrawByteString(CiByteString path, float length) @@ -104,7 +104,7 @@ internal sealed class ResourceWatcherTable : Table } public override float Width - => 80 * UiHelpers.Scale; + => 80 * Im.Style.GlobalScale; public override bool FilterFunc(Record item) => FilterValue.HasFlag(item.RecordType); @@ -139,7 +139,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class DateColumn : Column { public override float Width - => 80 * UiHelpers.Scale; + => 80 * Im.Style.GlobalScale; public override int Compare(Record lhs, Record rhs) => lhs.Time.CompareTo(rhs.Time); @@ -167,7 +167,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class CollectionColumn : ColumnString { public override float Width - => 80 * UiHelpers.Scale; + => 80 * Im.Style.GlobalScale; public override string ToName(Record item) => (item.Collection != null ? item.Collection.Identity.Name : null) ?? string.Empty; @@ -176,7 +176,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class ObjectColumn : ColumnString { public override float Width - => 200 * UiHelpers.Scale; + => 200 * Im.Style.GlobalScale; public override string ToName(Record item) => item.AssociatedGameObject; @@ -185,7 +185,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class OriginalPathColumn : ColumnString { public override float Width - => 200 * UiHelpers.Scale; + => 200 * Im.Style.GlobalScale; public override string ToName(Record item) => item.OriginalPath.ToString(); @@ -194,7 +194,7 @@ internal sealed class ResourceWatcherTable : Table => lhs.OriginalPath.CompareTo(rhs.OriginalPath); public override void DrawColumn(Record item, int _) - => DrawByteString(item.OriginalPath, 190 * UiHelpers.Scale); + => DrawByteString(item.OriginalPath, 190 * Im.Style.GlobalScale); } private sealed class ResourceCategoryColumn : ColumnFlags @@ -208,7 +208,7 @@ internal sealed class ResourceWatcherTable : Table } public override float Width - => 80 * UiHelpers.Scale; + => 80 * Im.Style.GlobalScale; public override bool FilterFunc(Record item) => FilterValue.HasFlag(item.Category); @@ -245,7 +245,7 @@ internal sealed class ResourceWatcherTable : Table } public override float Width - => 50 * UiHelpers.Scale; + => 50 * Im.Style.GlobalScale; public override bool FilterFunc(Record item) => FilterValue.HasFlag(item.ResourceType); @@ -272,7 +272,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class LoadStateColumn : ColumnFlags { public override float Width - => 50 * UiHelpers.Scale; + => 50 * Im.Style.GlobalScale; [Flags] public enum LoadStateFlag : byte @@ -354,7 +354,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class HandleColumn : ColumnString { public override float Width - => 120 * UiHelpers.Scale; + => 120 * Im.Style.GlobalScale; public override unsafe string ToName(Record item) => item.Handle == null ? string.Empty : $"0x{(ulong)item.Handle:X}"; @@ -419,7 +419,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class CustomLoadColumn : OptBoolColumn { public override float Width - => 60 * UiHelpers.Scale; + => 60 * Im.Style.GlobalScale; public override bool FilterFunc(Record item) => FilterFunc(item.CustomLoad); @@ -431,7 +431,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class SynchronousLoadColumn : OptBoolColumn { public override float Width - => 45 * UiHelpers.Scale; + => 45 * Im.Style.GlobalScale; public override bool FilterFunc(Record item) => FilterFunc(item.Synchronously); @@ -443,7 +443,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class RefCountColumn : Column { public override float Width - => 30 * UiHelpers.Scale; + => 30 * Im.Style.GlobalScale; public override void DrawColumn(Record item, int _) => ImGuiUtil.RightAlign(item.RefCount.ToString()); @@ -455,7 +455,7 @@ internal sealed class ResourceWatcherTable : Table private sealed class OsThreadColumn : ColumnString { public override float Width - => 60 * UiHelpers.Scale; + => 60 * Im.Style.GlobalScale; public override string ToName(Record item) => item.OsThreadId.ToString(); diff --git a/Penumbra/UI/Tabs/ChangedItemsTab.cs b/Penumbra/UI/Tabs/ChangedItemsTab.cs index 43aaf6c2..50eb6172 100644 --- a/Penumbra/UI/Tabs/ChangedItemsTab.cs +++ b/Penumbra/UI/Tabs/ChangedItemsTab.cs @@ -38,7 +38,7 @@ public class ChangedItemsTab( if (!child) return; - _buttonSize = new Vector2(ImGui.GetStyle().ItemSpacing.Y + ImGui.GetFrameHeight()); + _buttonSize = new Vector2(ImGui.GetStyle().ItemSpacing.Y + Im.Style.FrameHeight); using var style = ImRaii.PushStyle(ImGuiStyleVar.CellPadding, Vector2.Zero) .Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero) .Push(ImGuiStyleVar.FramePadding, Vector2.Zero) @@ -50,9 +50,9 @@ public class ChangedItemsTab( return; const ImGuiTableColumnFlags flags = ImGuiTableColumnFlags.NoResize | ImGuiTableColumnFlags.WidthFixed; - ImUtf8.TableSetupColumn("items"u8, flags, 450 * UiHelpers.Scale); - ImUtf8.TableSetupColumn("mods"u8, flags, varWidth - 140 * UiHelpers.Scale); - ImUtf8.TableSetupColumn("id"u8, flags, 140 * UiHelpers.Scale); + ImUtf8.TableSetupColumn("items"u8, flags, 450 * Im.Style.GlobalScale); + ImUtf8.TableSetupColumn("mods"u8, flags, varWidth - 140 * Im.Style.GlobalScale); + ImUtf8.TableSetupColumn("id"u8, flags, 140 * Im.Style.GlobalScale); var items = collectionManager.Active.Current.ChangedItems; var rest = ImGuiClip.FilteredClippedDraw(items, skips, FilterChangedItem, DrawChangedItemColumn); @@ -62,10 +62,10 @@ public class ChangedItemsTab( /// Draw a pair of filters and return the variable width of the flexible column. private float DrawFilters() { - var varWidth = ImGui.GetContentRegionAvail().X - - 450 * UiHelpers.Scale + var varWidth = Im.ContentRegion.Available.X + - 450 * Im.Style.GlobalScale - ImGui.GetStyle().ItemSpacing.X; - ImGui.SetNextItemWidth(450 * UiHelpers.Scale); + ImGui.SetNextItemWidth(450 * Im.Style.GlobalScale); Im.Input.Text("##changedItemsFilter"u8, ref _changedItemFilter, "Filter Item..."u8); Im.Line.Same(); ImGui.SetNextItemWidth(varWidth); diff --git a/Penumbra/UI/Tabs/CollectionsTab.cs b/Penumbra/UI/Tabs/CollectionsTab.cs index 0a2f8bc6..f40b7496 100644 --- a/Penumbra/UI/Tabs/CollectionsTab.cs +++ b/Penumbra/UI/Tabs/CollectionsTab.cs @@ -82,9 +82,9 @@ public sealed class CollectionsTab : IDisposable, ITab, Luna.IUiService private void DrawHeaderLine() { - var withSpacing = ImGui.GetFrameHeightWithSpacing(); + var withSpacing = Im.Style.FrameHeightWithSpacing; using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0).Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero); - var buttonSize = new Vector2((ImGui.GetContentRegionAvail().X - withSpacing) / 4f, ImGui.GetFrameHeight()); + var buttonSize = new Vector2((Im.ContentRegion.Available.X - withSpacing) / 4f, Im.Style.FrameHeight); using var _ = ImRaii.Group(); var tabSelectedColor = Im.Style[ImGuiColor.TabSelected]; @@ -122,7 +122,7 @@ public sealed class CollectionsTab : IDisposable, ITab, Luna.IUiService private void DrawPanel() { using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero); - using var child = ImRaii.Child("##CollectionSettings", new Vector2(ImGui.GetContentRegionAvail().X, 0), true); + using var child = ImRaii.Child("##CollectionSettings", new Vector2(Im.ContentRegion.Available.X, 0), true); if (!child) return; diff --git a/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs b/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs index b383a96c..4972ed88 100644 --- a/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs +++ b/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs @@ -59,7 +59,7 @@ public static class CrashDataExtensions ImGuiUtil.DrawTableColumn(character.CollectionId.ToString()); ImGuiUtil.DrawTableColumn(character.CharacterAddress); ImGuiUtil.DrawTableColumn(character.Timestamp.ToString()); - }, ImGui.GetTextLineHeightWithSpacing()); + }, Im.Style.TextHeightWithSpacing); } public static void DrawFiles(this CrashData data) @@ -83,7 +83,7 @@ public static class CrashDataExtensions ImGuiUtil.DrawTableColumn(file.CollectionId.ToString()); ImGuiUtil.DrawTableColumn(file.CharacterAddress); ImGuiUtil.DrawTableColumn(file.Timestamp.ToString()); - }, ImGui.GetTextLineHeightWithSpacing()); + }, Im.Style.TextHeightWithSpacing); } public static void DrawVfxInvocations(this CrashData data) @@ -106,6 +106,6 @@ public static class CrashDataExtensions ImGuiUtil.DrawTableColumn(vfx.CollectionId.ToString()); ImGuiUtil.DrawTableColumn(vfx.CharacterAddress); ImGuiUtil.DrawTableColumn(vfx.Timestamp.ToString()); - }, ImGui.GetTextLineHeightWithSpacing()); + }, Im.Style.TextHeightWithSpacing); } } diff --git a/Penumbra/UI/Tabs/Debug/DebugTab.cs b/Penumbra/UI/Tabs/Debug/DebugTab.cs index 2a22465a..48fac942 100644 --- a/Penumbra/UI/Tabs/Debug/DebugTab.cs +++ b/Penumbra/UI/Tabs/Debug/DebugTab.cs @@ -243,17 +243,17 @@ public class DebugTab : Window, ITab if (i < collection.Inheritance.DirectlyInheritsFrom.Count) ImUtf8.Text(collection.Inheritance.DirectlyInheritsFrom[i].Identity.Name); else - ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetTextLineHeight())); + ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, Im.Style.TextHeight)); ImGui.TableNextColumn(); if (i < collection.Inheritance.DirectlyInheritedBy.Count) ImUtf8.Text(collection.Inheritance.DirectlyInheritedBy[i].Identity.Name); else - ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetTextLineHeight())); + ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, Im.Style.TextHeight)); ImGui.TableNextColumn(); if (i < collection.Inheritance.FlatHierarchy.Count) ImUtf8.Text(collection.Inheritance.FlatHierarchy[i].Identity.Name); else - ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetTextLineHeight())); + ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, Im.Style.TextHeight)); } } } @@ -500,7 +500,7 @@ public class DebugTab : Window, ITab using (var start = Im.Tree.Node("Startup Performance"u8, TreeNodeFlags.DefaultOpen)) { if (start) - ImGui.NewLine(); + Im.Line.New(); } } @@ -820,7 +820,7 @@ public class DebugTab : Window, ITab return; using var list = ImUtf8.ListBox("##ChangedItemList"u8, - new Vector2(ImGui.GetContentRegionAvail().X, 8 * ImGui.GetTextLineHeightWithSpacing())); + new Vector2(Im.ContentRegion.Available.X, 8 * Im.Style.TextHeightWithSpacing)); if (!list) return; @@ -865,11 +865,11 @@ public class DebugTab : Window, ITab ImGui.InputText("File Name", ref _emoteSearchFile, 256); ImGui.InputText("Emote Name", ref _emoteSearchName, 256); using var table = Im.Table.Begin("##table"u8, 2, TableFlags.RowBackground | TableFlags.ScrollY | TableFlags.SizingFixedFit, - new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing())); + new Vector2(-1, 12 * Im.Style.TextHeightWithSpacing)); if (!table) return; - var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing()); + var skips = ImGuiClip.GetNecessarySkips(Im.Style.TextHeightWithSpacing); var dummy = ImGuiClip.FilteredClippedDraw(_emotes, skips, p => p.Key.Contains(_emoteSearchFile, StringComparison.OrdinalIgnoreCase) && (_emoteSearchName.Length == 0 @@ -881,7 +881,7 @@ public class DebugTab : Window, ITab ImGui.TableNextColumn(); ImGui.TextUnformatted(string.Join(", ", p.Value.Select(v => v.Name.ToDalamudString().TextValue))); }); - ImGuiClip.DrawEndDummy(dummy, ImGui.GetTextLineHeightWithSpacing()); + ImGuiClip.DrawEndDummy(dummy, Im.Style.TextHeightWithSpacing); } private string _tmbKeyFilter = string.Empty; @@ -896,11 +896,11 @@ public class DebugTab : Window, ITab if (ImGui.InputText("Key", ref _tmbKeyFilter, 256)) _tmbKeyFilterU8 = CiByteString.FromString(_tmbKeyFilter, out var r, MetaDataComputation.All) ? r : CiByteString.Empty; using var table = Im.Table.Begin("##table"u8, 2, TableFlags.RowBackground | TableFlags.ScrollY | TableFlags.SizingFixedFit, - new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing())); + new Vector2(-1, 12 * Im.Style.TextHeightWithSpacing)); if (!table) return; - var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing()); + var skips = ImGuiClip.GetNecessarySkips(Im.Style.TextHeightWithSpacing); var dummy = ImGuiClip.FilteredClippedDraw(_schedulerService.ActionTmbs.OrderBy(r => r.Value), skips, kvp => kvp.Key.Contains(_tmbKeyFilterU8), p => @@ -908,7 +908,7 @@ public class DebugTab : Window, ITab ImUtf8.DrawTableColumn($"{p.Value}"); ImUtf8.DrawTableColumn(p.Key.Span); }); - ImGuiClip.DrawEndDummy(dummy, ImGui.GetTextLineHeightWithSpacing()); + ImGuiClip.DrawEndDummy(dummy, Im.Style.TextHeightWithSpacing); } private void DrawStainTemplates() @@ -949,7 +949,7 @@ public class DebugTab : Window, ITab { var color = list[i]; ImGui.TableNextColumn(); - var frame = new Vector2(ImGui.GetTextLineHeight()); + var frame = new Vector2(Im.Style.TextHeight); ImGui.ColorButton("###color", new Vector4(MtrlTab.PseudoSqrtRgb((Vector3)color), 1), 0, frame); Im.Line.Same(); ImGui.TextUnformatted($"{color.Red:F6} | {color.Green:F6} | {color.Blue:F6}"); diff --git a/Penumbra/UI/Tabs/EffectiveTab.cs b/Penumbra/UI/Tabs/EffectiveTab.cs index c2ba7a87..68fe8144 100644 --- a/Penumbra/UI/Tabs/EffectiveTab.cs +++ b/Penumbra/UI/Tabs/EffectiveTab.cs @@ -1,5 +1,6 @@ using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using ImSharp; using OtterGui; using OtterGui.Raii; using OtterGui.Text; @@ -25,11 +26,11 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH SetupEffectiveSizes(); collectionHeader.Draw(true); DrawFilters(); - using var child = ImRaii.Child("##EffectiveChangesTab", ImGui.GetContentRegionAvail(), false); + using var child = ImRaii.Child("##EffectiveChangesTab", Im.ContentRegion.Available, false); if (!child) return; - var height = ImGui.GetTextLineHeightWithSpacing() + 2 * ImGui.GetStyle().CellPadding.Y; + var height = Im.Style.TextHeightWithSpacing + 2 * ImGui.GetStyle().CellPadding.Y; var skips = ImGuiClip.GetNecessarySkips(height); using var table = ImRaii.Table("##EffectiveChangesTable", 3, ImGuiTableFlags.RowBg); if (!table) @@ -60,11 +61,11 @@ public class EffectiveTab(CollectionManager collectionManager, CollectionSelectH { using var font = ImRaii.PushFont(UiBuilder.IconFont); _effectiveUnscaledArrowLength = - ImGui.CalcTextSize(FontAwesomeIcon.LongArrowAltLeft.ToIconString()).X / UiHelpers.Scale; + ImGui.CalcTextSize(FontAwesomeIcon.LongArrowAltLeft.ToIconString()).X / Im.Style.GlobalScale; } - _effectiveArrowLength = _effectiveUnscaledArrowLength * UiHelpers.Scale; - _effectiveLeftTextLength = 450 * UiHelpers.Scale; + _effectiveArrowLength = _effectiveUnscaledArrowLength * Im.Style.GlobalScale; + _effectiveLeftTextLength = 450 * Im.Style.GlobalScale; _effectiveRightTextLength = ImGui.GetWindowSize().X - _effectiveArrowLength - _effectiveLeftTextLength; } diff --git a/Penumbra/UI/Tabs/ModsTab.cs b/Penumbra/UI/Tabs/ModsTab.cs index 5ae39e3a..1d6bcb2e 100644 --- a/Penumbra/UI/Tabs/ModsTab.cs +++ b/Penumbra/UI/Tabs/ModsTab.cs @@ -60,7 +60,7 @@ public class ModsTab( collectionHeader.Draw(false); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero); - using (var child = ImRaii.Child("##ModsTabMod", new Vector2(ImGui.GetContentRegionAvail().X, config.HideRedrawBar ? 0 : -ImGui.GetFrameHeight()), + using (var child = ImRaii.Child("##ModsTabMod", new Vector2(Im.ContentRegion.Available.X, config.HideRedrawBar ? 0 : -Im.Style.FrameHeight), true, ImGuiWindowFlags.HorizontalScrollbar)) { style.Pop(); @@ -94,7 +94,7 @@ public class ModsTab( return; } - var frameHeight = new Vector2(0, ImGui.GetFrameHeight()); + var frameHeight = new Vector2(0, Im.Style.FrameHeight); var frameColor = ImGuiColor.FrameBackground.Get().Color; using (var _ = ImRaii.Group()) { @@ -115,7 +115,7 @@ public class ModsTab( using var id = ImRaii.PushId("Redraw"); using var disabled = ImRaii.Disabled(clientState.LocalPlayer == null); Im.Line.Same(); - var buttonWidth = frameHeight with { X = ImGui.GetContentRegionAvail().X / 5 }; + var buttonWidth = frameHeight with { X = Im.ContentRegion.Available.X / 5 }; var tt = !objects[0].Valid ? "\nCan only be used when you are logged in and your character is available." : string.Empty; @@ -139,7 +139,7 @@ public class ModsTab( tt = !IsIndoors() ? "\nCan currently only be used for indoor furniture." : string.Empty; - DrawButton(frameHeight with { X = ImGui.GetContentRegionAvail().X - 1 }, "Furniture", "furniture", tt); + DrawButton(frameHeight with { X = Im.ContentRegion.Available.X - 1 }, "Furniture", "furniture", tt); return; void DrawButton(Vector2 size, string label, string lower, string additionalTooltip) diff --git a/Penumbra/UI/Tabs/ResourceTab.cs b/Penumbra/UI/Tabs/ResourceTab.cs index 8bcd0fea..842040b3 100644 --- a/Penumbra/UI/Tabs/ResourceTab.cs +++ b/Penumbra/UI/Tabs/ResourceTab.cs @@ -37,7 +37,7 @@ public class ResourceTab(Configuration config, ResourceManagerService resourceMa resourceManager.IterateGraphs(DrawCategoryContainer); } - ImGui.NewLine(); + Im.Line.New(); unsafe { ImGui.TextUnformatted( @@ -131,8 +131,8 @@ public class ResourceTab(Configuration config, ResourceManagerService resourceMa /// Set the widths for a resource table. private void SetTableWidths() { - _hashColumnWidth = 100 * UiHelpers.Scale; - _pathColumnWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - 300 * UiHelpers.Scale; - _refsColumnWidth = 30 * UiHelpers.Scale; + _hashColumnWidth = 100 * Im.Style.GlobalScale; + _pathColumnWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - 300 * Im.Style.GlobalScale; + _refsColumnWidth = 30 * Im.Style.GlobalScale; } } diff --git a/Penumbra/UI/Tabs/SettingsTab.cs b/Penumbra/UI/Tabs/SettingsTab.cs index 6980117d..af11ac9a 100644 --- a/Penumbra/UI/Tabs/SettingsTab.cs +++ b/Penumbra/UI/Tabs/SettingsTab.cs @@ -185,7 +185,7 @@ public class SettingsTab : ITab, IUiService if (!child) return; - using var c2 = ImRaii.Child("a", new Vector2(300, 5 * ImGui.GetTextLineHeightWithSpacing()), true, + using var c2 = ImRaii.Child("a", new Vector2(300, 5 * Im.Style.TextHeightWithSpacing), true, ImGuiWindowFlags.AlwaysVerticalScrollbar); TreeLine.Draw(List, 0xFFFFFFFF); @@ -193,11 +193,11 @@ public class SettingsTab : ITab, IUiService //EphemeralCheckbox("Lock Main Window", "Prevent the main window from being resized or moved.", _config.Ephemeral.FixMainWindow, // v => _config.Ephemeral.FixMainWindow = v); // - //ImGui.NewLine(); + //Im.Line.New(); //DrawRootFolder(); //DrawDirectoryButtons(); - //ImGui.NewLine(); - //ImGui.NewLine(); + //Im.Line.New(); + //Im.Line.New(); // //DrawGeneralSettings(); //_migrationDrawer.Draw(); @@ -350,7 +350,7 @@ public class SettingsTab : ITab, IUiService } selected = ImGui.IsItemActive(); - using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(UiHelpers.ScaleX3, 0)); + using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(Im.Style.GlobalScale * 3, 0)); Im.Line.Same(); DrawDirectoryPickerButton(); style.Pop(); @@ -372,7 +372,7 @@ public class SettingsTab : ITab, IUiService _tutorial.OpenTutorial(BasicTutorialSteps.ModDirectory); Im.Line.Same(); var pos = ImGui.GetCursorPosX(); - ImGui.NewLine(); + Im.Line.New(); if (_config.ModDirectory != _newModDirectory && _newModDirectory.Length != 0 @@ -433,7 +433,7 @@ public class SettingsTab : ITab, IUiService UiHelpers.DefaultLineSpace(); DrawModEditorSettings(); - ImGui.NewLine(); + Im.Line.New(); } private int _singleGroupRadioMax = int.MaxValue; @@ -739,7 +739,7 @@ public class SettingsTab : ITab, IUiService private void DrawDefaultModImportPath() { var tmp = _config.DefaultModImportPath; - var spacing = new Vector2(UiHelpers.ScaleX3); + var spacing = new Vector2(Im.Style.GlobalScale * 3); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton3); @@ -780,7 +780,7 @@ public class SettingsTab : ITab, IUiService private void DrawDefaultModExportPath() { var tmp = _config.ExportDirectory; - var spacing = new Vector2(UiHelpers.ScaleX3); + var spacing = new Vector2(Im.Style.GlobalScale * 3); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton3); if (ImGui.InputText("##defaultModExport", ref tmp, 256)) @@ -817,7 +817,7 @@ public class SettingsTab : ITab, IUiService private void DrawFileWatcherPath() { var tmp = _tempWatchDirectory ?? _config.WatchDirectory; - var spacing = new Vector2(UiHelpers.ScaleX3); + var spacing = new Vector2(Im.Style.GlobalScale * 3); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton3); if (ImGui.InputText("##fileWatchPath", ref tmp, 256)) @@ -942,7 +942,7 @@ public class SettingsTab : ITab, IUiService _config.Save(); } - ImGui.NewLine(); + Im.Line.New(); } #region Advanced Settings @@ -980,7 +980,7 @@ public class SettingsTab : ITab, IUiService DrawReloadFontsButton(); ImGui.Separator(); DrawCleanupButtons(); - ImGui.NewLine(); + Im.Line.New(); } private void DrawCrashHandler() @@ -1027,8 +1027,8 @@ public class SettingsTab : ITab, IUiService if (_compactor.MassCompactRunning) { ImGui.ProgressBar((float)_compactor.CurrentIndex / _compactor.TotalFiles, - new Vector2(ImGui.GetContentRegionAvail().X - ImGui.GetStyle().ItemSpacing.X - UiHelpers.IconButtonSize.X, - ImGui.GetFrameHeight()), + new Vector2(Im.ContentRegion.Available.X - ImGui.GetStyle().ItemSpacing.X - UiHelpers.IconButtonSize.X, + Im.Style.FrameHeight), _compactor.CurrentFile?.FullName[(_modManager.BasePath.FullName.Length + 1)..] ?? "Gathering Files..."); Im.Line.Same(); if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Ban.ToIconString(), UiHelpers.IconButtonSize, "Cancel the mass action.", @@ -1082,7 +1082,7 @@ public class SettingsTab : ITab, IUiService if (warning.Length > 0) ImGuiUtil.DrawTextButton(warning, UiHelpers.InputTextWidth, Colors.PressEnterWarningBg); else - ImGui.NewLine(); + Im.Line.New(); if (!edited) return; @@ -1095,7 +1095,7 @@ public class SettingsTab : ITab, IUiService private void DrawHdrRenderTargets() { - ImGui.SetNextItemWidth(ImUtf8.CalcTextSize("M"u8).X * 5.0f + ImGui.GetFrameHeight()); + ImGui.SetNextItemWidth(ImUtf8.CalcTextSize("M"u8).X * 5.0f + Im.Style.FrameHeight); using (var combo = ImUtf8.Combo("##hdrRenderTarget"u8, _config.HdrRenderTargets ? "HDR"u8 : "SDR"u8)) { if (combo) @@ -1176,7 +1176,7 @@ public class SettingsTab : ITab, IUiService var enabled = _config.DeleteModModifier.IsActive(); if (_cleanupService.Progress is not 0.0 and not 1.0) { - ImUtf8.ProgressBar((float)_cleanupService.Progress, new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetFrameHeight()), + ImUtf8.ProgressBar((float)_cleanupService.Progress, new Vector2(200 * ImUtf8.GlobalScale, Im.Style.FrameHeight), $"{_cleanupService.Progress * 100}%"); Im.Line.Same(); if (ImUtf8.Button("Cancel##FileCleanup"u8)) @@ -1184,7 +1184,7 @@ public class SettingsTab : ITab, IUiService } else { - ImGui.NewLine(); + Im.Line.New(); } if (ImUtf8.ButtonEx("Clear Unused Local Mod Data Files"u8, @@ -1240,27 +1240,27 @@ public class SettingsTab : ITab, IUiService if (ImGui.GetScrollMaxY() > 0) xPos -= ImGui.GetStyle().ScrollbarSize + ImGui.GetStyle().FramePadding.X; - ImGui.SetCursorPos(new Vector2(xPos, ImGui.GetFrameHeightWithSpacing())); + ImGui.SetCursorPos(new Vector2(xPos, Im.Style.FrameHeightWithSpacing)); UiHelpers.DrawSupportButton(_penumbra); ImGui.SetCursorPos(new Vector2(xPos, 0)); SupportButton.Discord(Penumbra.Messager, width); - ImGui.SetCursorPos(new Vector2(xPos, 2 * ImGui.GetFrameHeightWithSpacing())); + ImGui.SetCursorPos(new Vector2(xPos, 2 * Im.Style.FrameHeightWithSpacing)); SupportButton.ReniGuide(Penumbra.Messager, width); - ImGui.SetCursorPos(new Vector2(xPos, 3 * ImGui.GetFrameHeightWithSpacing())); + ImGui.SetCursorPos(new Vector2(xPos, 3 * Im.Style.FrameHeightWithSpacing)); if (ImGui.Button("Restart Tutorial", new Vector2(width, 0))) { _config.Ephemeral.TutorialStep = 0; _config.Ephemeral.Save(); } - ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing())); + ImGui.SetCursorPos(new Vector2(xPos, 4 * Im.Style.FrameHeightWithSpacing)); if (ImGui.Button("Show Changelogs", new Vector2(width, 0))) _penumbra.ForceChangelogOpen(); - ImGui.SetCursorPos(new Vector2(xPos, 5 * ImGui.GetFrameHeightWithSpacing())); + ImGui.SetCursorPos(new Vector2(xPos, 5 * Im.Style.FrameHeightWithSpacing)); SupportButton.KoFiPatreon(Penumbra.Messager, new Vector2(width, 0)); }