From 5fc8209c85ad7e30d2b813370701ade5f6b453a4 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Tue, 9 Dec 2025 17:18:58 +0100 Subject: [PATCH] Current state. --- Luna | 2 +- Penumbra.Api | 2 +- Penumbra.GameData | 2 +- Penumbra.String | 2 +- Penumbra/Api/Api/RedrawApi.cs | 5 + Penumbra/Api/Api/UiApi.cs | 6 + .../Api/IpcTester/CollectionsIpcTester.cs | 20 +- Penumbra/Api/IpcTester/EditingIpcTester.cs | 4 +- Penumbra/Api/IpcTester/GameStateIpcTester.cs | 10 +- Penumbra/Api/IpcTester/MetaIpcTester.cs | 4 +- .../Api/IpcTester/ModSettingsIpcTester.cs | 20 +- Penumbra/Api/IpcTester/ModsIpcTester.cs | 22 +- .../Api/IpcTester/PluginStateIpcTester.cs | 16 +- Penumbra/Api/IpcTester/RedrawingIpcTester.cs | 6 +- Penumbra/Api/IpcTester/ResolveIpcTester.cs | 16 +- .../Api/IpcTester/ResourceTreeIpcTester.cs | 16 +- Penumbra/Api/IpcTester/TemporaryIpcTester.cs | 40 +- Penumbra/Api/IpcTester/UiIpcTester.cs | 10 +- Penumbra/Import/Models/ModelManager.cs | 2 +- Penumbra/Import/Textures/PathSelectCombo.cs | 2 +- .../ResolveContext.PathResolution.cs | 2 +- Penumbra/Meta/Manipulations/Est.cs | 6 +- Penumbra/Meta/Manipulations/GlobalEqpType.cs | 75 +- Penumbra/Meta/Manipulations/Rsp.cs | 4 +- Penumbra/Mods/ItemSwap/ItemSwap.cs | 4 +- Penumbra/UI/AdvancedWindow/FileEditor.cs | 90 +-- Penumbra/UI/AdvancedWindow/ItemSwapTab.cs | 353 ++++----- .../Materials/MtrlTab.CommonColorTable.cs | 145 ++-- .../Materials/MtrlTab.Constants.cs | 29 +- .../Materials/MtrlTab.LegacyColorTable.cs | 145 ++-- .../Materials/MtrlTab.LivePreview.cs | 21 +- .../Materials/MtrlTab.ShaderPackage.cs | 100 ++- .../Materials/MtrlTab.Textures.cs | 103 ++- .../UI/AdvancedWindow/Materials/MtrlTab.cs | 50 +- .../UI/AdvancedWindow/Meta/AtchMetaDrawer.cs | 108 ++- .../UI/AdvancedWindow/Meta/AtrMetaDrawer.cs | 84 +- .../UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs | 46 +- .../UI/AdvancedWindow/Meta/EqpMetaDrawer.cs | 32 +- .../UI/AdvancedWindow/Meta/EstMetaDrawer.cs | 46 +- .../Meta/GlobalEqpMetaDrawer.cs | 32 +- .../UI/AdvancedWindow/Meta/GmpMetaDrawer.cs | 27 +- .../UI/AdvancedWindow/Meta/ImcMetaDrawer.cs | 63 +- Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs | 25 +- .../UI/AdvancedWindow/Meta/RspMetaDrawer.cs | 32 +- .../UI/AdvancedWindow/Meta/ShpMetaDrawer.cs | 729 +++++++++--------- .../AdvancedWindow/ModEditWindow.Deformers.cs | 131 ++-- .../UI/AdvancedWindow/ModEditWindow.Files.cs | 167 ++-- .../AdvancedWindow/ModEditWindow.Materials.cs | 47 +- .../UI/AdvancedWindow/ModEditWindow.Meta.cs | 68 +- .../UI/AdvancedWindow/ModEditWindow.Models.cs | 340 ++++---- .../ModEditWindow.ShaderPackages.cs | 318 ++++---- .../AdvancedWindow/ModEditWindow.Textures.cs | 89 +-- Penumbra/UI/AdvancedWindow/ModEditWindow.cs | 233 +++--- Penumbra/UI/AdvancedWindow/ModMergeTab.cs | 4 +- .../UI/AdvancedWindow/OptionSelectCombo.cs | 44 -- Penumbra/UI/CollectionTab/InheritanceUi.cs | 3 +- Penumbra/UI/Combos/AtchPointCombo.cs | 11 + Penumbra/UI/{Classes => Combos}/Combos.cs | 4 +- Penumbra/UI/Combos/OptionSelectCombo.cs | 61 ++ Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs | 576 +++++++------- .../UI/ModsTab/ModPanelChangedItemsTab.cs | 53 +- Penumbra/UI/ModsTab/ModPanelEditTab.cs | 21 +- Penumbra/UI/ModsTab/ModPanelSettingsTab.cs | 8 +- .../ResourceWatcher/ResourceWatcherTable.cs | 4 +- Penumbra/UI/Tabs/Debug/AtchDrawer.cs | 10 +- Penumbra/UI/Tabs/Debug/DebugTab.cs | 395 +++++----- Penumbra/UI/Tabs/Debug/ShapeInspector.cs | 20 +- Penumbra/UI/Tabs/ModsTab.cs | 3 +- Penumbra/UI/Tabs/SettingsTab.cs | 2 +- 69 files changed, 2455 insertions(+), 2715 deletions(-) delete mode 100644 Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs create mode 100644 Penumbra/UI/Combos/AtchPointCombo.cs rename Penumbra/UI/{Classes => Combos}/Combos.cs (96%) create mode 100644 Penumbra/UI/Combos/OptionSelectCombo.cs diff --git a/Luna b/Luna index 950ebea5..23582561 160000 --- a/Luna +++ b/Luna @@ -1 +1 @@ -Subproject commit 950ebea591f4ab7dc0900cce22415c5221df3685 +Subproject commit 235825613cf1a2c95173d0a1ae43f2c6601a9df6 diff --git a/Penumbra.Api b/Penumbra.Api index 09cfde3d..d5207129 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 09cfde3dd43aa5afcfd147ccbe3ee61534556f12 +Subproject commit d52071290b48a1f2292023675b4b72365aef4cc0 diff --git a/Penumbra.GameData b/Penumbra.GameData index 885e5362..67f313d4 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 885e536267f814fc4e62e11a70a82cdde7b4778d +Subproject commit 67f313d42944e4d2c878b628cfc92b35d7d88436 diff --git a/Penumbra.String b/Penumbra.String index 4aac62e7..462afac5 160000 --- a/Penumbra.String +++ b/Penumbra.String @@ -1 +1 @@ -Subproject commit 4aac62e73b89a0c538a7a0a5c22822f15b13c0cc +Subproject commit 462afac558becebbe06b4e5be9b1b3c3f5a9b6d6 diff --git a/Penumbra/Api/Api/RedrawApi.cs b/Penumbra/Api/Api/RedrawApi.cs index 6cad99dd..be758093 100644 --- a/Penumbra/Api/Api/RedrawApi.cs +++ b/Penumbra/Api/Api/RedrawApi.cs @@ -28,6 +28,11 @@ public class RedrawApi(RedrawService redrawService, IFramework framework) : IPen framework.RunOnFrameworkThread(() => redrawService.RedrawAll(setting)); } + public void RedrawCollectionMembers(Guid collectionId, RedrawType setting) + { + throw new NotImplementedException(); + } + public event GameObjectRedrawnDelegate? GameObjectRedrawn { add => redrawService.GameObjectRedrawn += value; diff --git a/Penumbra/Api/Api/UiApi.cs b/Penumbra/Api/Api/UiApi.cs index 7926a8e9..6ff119b3 100644 --- a/Penumbra/Api/Api/UiApi.cs +++ b/Penumbra/Api/Api/UiApi.cs @@ -80,6 +80,12 @@ public class UiApi : IPenumbraApiUi, Luna.IApiService, IDisposable public void CloseMainWindow() => _mainWindow.IsOpen = false; + public PenumbraApiEc RegisterSettingsSection(Action draw) + => throw new NotImplementedException(); + + public PenumbraApiEc UnregisterSettingsSection(Action draw) + => throw new NotImplementedException(); + private void OnChangedItemClick(in ChangedItemClick.Arguments arguments) { if (ChangedItemClicked == null) diff --git a/Penumbra/Api/IpcTester/CollectionsIpcTester.cs b/Penumbra/Api/IpcTester/CollectionsIpcTester.cs index a75f3294..4dda1293 100644 --- a/Penumbra/Api/IpcTester/CollectionsIpcTester.cs +++ b/Penumbra/Api/IpcTester/CollectionsIpcTester.cs @@ -54,7 +54,7 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService Im.Text(!_oldCollection.HasValue ? "Created" : _oldCollection.ToString()!); table.NextRow(); - using (IpcTester.DrawIntro(GetCollectionsByIdentifier.Label, "Collection Identifier"u8)) + using (IpcTester.DrawIntro(GetCollectionsByIdentifier.LabelU8, "Collection Identifier"u8)) { var collectionList = new GetCollectionsByIdentifier(pi).Invoke(_collectionId.GetValueOrDefault().ToString()); if (collectionList.Count == 0) @@ -75,27 +75,27 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService } } - using (IpcTester.DrawIntro(GetCollection.Label, "Current Collection"u8)) + using (IpcTester.DrawIntro(GetCollection.LabelU8, "Current Collection"u8)) { DrawCollection(table, new GetCollection(pi).Invoke(ApiCollectionType.Current)); } - using (IpcTester.DrawIntro(GetCollection.Label, "Default Collection"u8)) + using (IpcTester.DrawIntro(GetCollection.LabelU8, "Default Collection"u8)) { DrawCollection(table, new GetCollection(pi).Invoke(ApiCollectionType.Default)); } - using (IpcTester.DrawIntro(GetCollection.Label, "Interface Collection"u8)) + using (IpcTester.DrawIntro(GetCollection.LabelU8, "Interface Collection"u8)) { DrawCollection(table, new GetCollection(pi).Invoke(ApiCollectionType.Interface)); } - using (IpcTester.DrawIntro(GetCollection.Label, "Special Collection"u8)) + using (IpcTester.DrawIntro(GetCollection.LabelU8, "Special Collection"u8)) { DrawCollection(table, new GetCollection(pi).Invoke(_type)); } - using (IpcTester.DrawIntro(GetCollections.Label, "Collections"u8)) + using (IpcTester.DrawIntro(GetCollections.LabelU8, "Collections"u8)) { DrawCollectionPopup(); table.NextColumn(); @@ -106,7 +106,7 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService } } - using (IpcTester.DrawIntro(GetCollectionForObject.Label, "Get Object Collection"u8)) + using (IpcTester.DrawIntro(GetCollectionForObject.LabelU8, "Get Object Collection"u8)) { var (valid, individual, effectiveCollection) = new GetCollectionForObject(pi).Invoke(_objectIdx); DrawCollection(table, effectiveCollection); @@ -114,7 +114,7 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService Im.Text($"({(valid ? "Valid" : "Invalid")} Object{(individual ? ", Individual Assignment)" : ")")}"); } - using (IpcTester.DrawIntro(SetCollection.Label, "Set Special Collection"u8)) + using (IpcTester.DrawIntro(SetCollection.LabelU8, "Set Special Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Set##SpecialCollection"u8)) @@ -125,7 +125,7 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService (_returnCode, _oldCollection) = new SetCollection(pi).Invoke(_type, null, _allowCreation, _allowDeletion); } - using (IpcTester.DrawIntro(SetCollectionForObject.Label, "Set Object Collection"u8)) + using (IpcTester.DrawIntro(SetCollectionForObject.LabelU8, "Set Object Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Set##ObjectCollection"u8)) @@ -136,7 +136,7 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService (_returnCode, _oldCollection) = new SetCollectionForObject(pi).Invoke(_objectIdx, null, _allowCreation, _allowDeletion); } - using (IpcTester.DrawIntro(GetChangedItemsForCollection.Label, "Changed Item List"u8)) + using (IpcTester.DrawIntro(GetChangedItemsForCollection.LabelU8, "Changed Item List"u8)) { DrawChangedItemPopup(); table.NextColumn(); diff --git a/Penumbra/Api/IpcTester/EditingIpcTester.cs b/Penumbra/Api/IpcTester/EditingIpcTester.cs index fff2e302..fd4fb206 100644 --- a/Penumbra/Api/IpcTester/EditingIpcTester.cs +++ b/Penumbra/Api/IpcTester/EditingIpcTester.cs @@ -35,7 +35,7 @@ public class EditingIpcTester(IDalamudPluginInterface pi) : Luna.IUiService if (!table) return; - using (IpcTester.DrawIntro(ConvertTextureFile.Label, "Convert Texture 1"u8)) + using (IpcTester.DrawIntro(ConvertTextureFile.LabelU8, "Convert Texture 1"u8)) { table.NextColumn(); if (ImEx.Button("Save 1"u8, Vector2.Zero, StringU8.Empty, _task1 is { IsCompleted: false })) @@ -46,7 +46,7 @@ public class EditingIpcTester(IDalamudPluginInterface pi) : Luna.IUiService Im.Tooltip.Set($"{_task1.Exception}"); } - using (IpcTester.DrawIntro(ConvertTextureFile.Label, "Convert Texture 2"u8)) + using (IpcTester.DrawIntro(ConvertTextureFile.LabelU8, "Convert Texture 2"u8)) { table.NextColumn(); if (ImEx.Button("Save 2"u8, Vector2.Zero, StringU8.Empty, _task2 is { IsCompleted: false })) diff --git a/Penumbra/Api/IpcTester/GameStateIpcTester.cs b/Penumbra/Api/IpcTester/GameStateIpcTester.cs index 2f0405eb..8e26c568 100644 --- a/Penumbra/Api/IpcTester/GameStateIpcTester.cs +++ b/Penumbra/Api/IpcTester/GameStateIpcTester.cs @@ -70,7 +70,7 @@ public class GameStateIpcTester : IUiService, IDisposable if (!table) return; - using (IpcTester.DrawIntro(GetDrawObjectInfo.Label, "Draw Object Info"u8)) + using (IpcTester.DrawIntro(GetDrawObjectInfo.LabelU8, "Draw Object Info"u8)) { table.NextColumn(); if (_currentDrawObject == nint.Zero) @@ -86,12 +86,12 @@ public class GameStateIpcTester : IUiService, IDisposable } } - using (IpcTester.DrawIntro(GetCutsceneParentIndex.Label, "Cutscene Parent"u8)) + using (IpcTester.DrawIntro(GetCutsceneParentIndex.LabelU8, "Cutscene Parent"u8)) { table.DrawColumn($"{new GetCutsceneParentIndex(_pi).Invoke(_currentCutsceneActor)}"); } - using (IpcTester.DrawIntro(SetCutsceneParentIndex.Label, "Cutscene Parent"u8)) + using (IpcTester.DrawIntro(SetCutsceneParentIndex.LabelU8, "Cutscene Parent"u8)) { table.NextColumn(); if (Im.SmallButton("Set Parent"u8)) @@ -99,7 +99,7 @@ public class GameStateIpcTester : IUiService, IDisposable .Invoke(_currentCutsceneActor, _currentCutsceneParent); } - using (IpcTester.DrawIntro(CreatingCharacterBase.Label, "Last Drawobject created"u8)) + using (IpcTester.DrawIntro(CreatingCharacterBase.LabelU8, "Last Drawobject created"u8)) { if (_lastCreatedGameObjectTime < DateTimeOffset.Now) table.DrawColumn(_lastCreatedDrawObject != nint.Zero @@ -107,7 +107,7 @@ public class GameStateIpcTester : IUiService, IDisposable : $"NULL for <{_lastCreatedGameObjectName}> at {_lastCreatedGameObjectTime}"); } - using (IpcTester.DrawIntro(IpcSubscribers.GameObjectResourcePathResolved.Label, "Last GamePath resolved"u8)) + using (IpcTester.DrawIntro(IpcSubscribers.GameObjectResourcePathResolved.LabelU8, "Last GamePath resolved"u8)) { if (_lastResolvedGamePathTime < DateTimeOffset.Now) table.DrawColumn( diff --git a/Penumbra/Api/IpcTester/MetaIpcTester.cs b/Penumbra/Api/IpcTester/MetaIpcTester.cs index 84402d94..0d4710f8 100644 --- a/Penumbra/Api/IpcTester/MetaIpcTester.cs +++ b/Penumbra/Api/IpcTester/MetaIpcTester.cs @@ -28,7 +28,7 @@ public class MetaIpcTester(IDalamudPluginInterface pi) : Luna.IUiService if (!table) return; - using (IpcTester.DrawIntro(GetPlayerMetaManipulations.Label, "Player Meta Manipulations"u8)) + using (IpcTester.DrawIntro(GetPlayerMetaManipulations.LabelU8, "Player Meta Manipulations"u8)) { table.NextColumn(); if (Im.SmallButton("Copy to Clipboard##Player"u8)) @@ -38,7 +38,7 @@ public class MetaIpcTester(IDalamudPluginInterface pi) : Luna.IUiService } } - using (IpcTester.DrawIntro(GetMetaManipulations.Label, "Game Object Manipulations"u8)) + using (IpcTester.DrawIntro(GetMetaManipulations.LabelU8, "Game Object Manipulations"u8)) { table.NextColumn(); if (Im.SmallButton("Copy to Clipboard##GameObject"u8)) diff --git a/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs b/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs index d2f7aba9..d3557d4a 100644 --- a/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs +++ b/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs @@ -63,14 +63,14 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable IpcTester.DrawIntro("Last Error"u8, $"{_lastSettingsError}").Dispose(); - using (IpcTester.DrawIntro(ModSettingChanged.Label, "Last Mod Setting Changed"u8)) + using (IpcTester.DrawIntro(ModSettingChanged.LabelU8, "Last Mod Setting Changed"u8)) { table.DrawColumn(_lastSettingChangeMod.Length > 0 ? $"{_lastSettingChangeType} of {_lastSettingChangeMod} in {_lastSettingChangeCollection}{(_lastSettingChangeInherited ? " (Inherited)" : string.Empty)} at {_lastSettingChange}" : "None"u8); } - using (IpcTester.DrawIntro(GetAvailableModSettings.Label, "Get Available Settings"u8)) + using (IpcTester.DrawIntro(GetAvailableModSettings.LabelU8, "Get Available Settings"u8)) { table.NextColumn(); if (Im.SmallButton("Get##Available"u8)) @@ -80,7 +80,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable } } - using (IpcTester.DrawIntro(GetCurrentModSettings.Label, "Get Current Settings"u8)) + using (IpcTester.DrawIntro(GetCurrentModSettings.LabelU8, "Get Current Settings"u8)) { table.NextColumn(); if (Im.SmallButton("Get##Current"u8)) @@ -103,7 +103,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable } } - using (IpcTester.DrawIntro(GetCurrentModSettingsWithTemp.Label, "Get Current Settings With Temp"u8)) + using (IpcTester.DrawIntro(GetCurrentModSettingsWithTemp.LabelU8, "Get Current Settings With Temp"u8)) { table.NextColumn(); if (Im.SmallButton("Get##CurrentTemp"u8)) @@ -127,7 +127,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable } } - using (IpcTester.DrawIntro(GetAllModSettings.Label, "Get All Mod Settings"u8)) + using (IpcTester.DrawIntro(GetAllModSettings.LabelU8, "Get All Mod Settings"u8)) { table.NextColumn(); if (Im.SmallButton("Get##All"u8)) @@ -144,7 +144,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable } } - using (IpcTester.DrawIntro(TryInheritMod.Label, "Inherit Mod"u8)) + using (IpcTester.DrawIntro(TryInheritMod.LabelU8, "Inherit Mod"u8)) { table.NextColumn(); Im.Checkbox("##inherit"u8, ref _settingsInherit); @@ -154,7 +154,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable .Invoke(collection, _settingsModDirectory, _settingsInherit, _settingsModName); } - using (IpcTester.DrawIntro(TrySetMod.Label, "Set Enabled"u8)) + using (IpcTester.DrawIntro(TrySetMod.LabelU8, "Set Enabled"u8)) { table.NextColumn(); Im.Checkbox("##enabled"u8, ref _settingsEnabled); @@ -164,7 +164,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable .Invoke(collection, _settingsModDirectory, _settingsEnabled, _settingsModName); } - using (IpcTester.DrawIntro(TrySetModPriority.Label, "Set Priority"u8)) + using (IpcTester.DrawIntro(TrySetModPriority.LabelU8, "Set Priority"u8)) { table.NextColumn(); Im.Item.SetNextWidthScaled(200); @@ -175,7 +175,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable .Invoke(collection, _settingsModDirectory, _settingsPriority, _settingsModName); } - using (IpcTester.DrawIntro(CopyModSettings.Label, "Copy Mod Settings"u8)) + using (IpcTester.DrawIntro(CopyModSettings.LabelU8, "Copy Mod Settings"u8)) { table.NextColumn(); if (Im.SmallButton("Copy Settings"u8)) @@ -185,7 +185,7 @@ public class ModSettingsIpcTester : Luna.IUiService, IDisposable } - using (IpcTester.DrawIntro(TrySetModSetting.Label, "Set Setting(s)"u8)) + using (IpcTester.DrawIntro(TrySetModSetting.LabelU8, "Set Setting(s)"u8)) { if (_availableSettings == null) return; diff --git a/Penumbra/Api/IpcTester/ModsIpcTester.cs b/Penumbra/Api/IpcTester/ModsIpcTester.cs index 9cc32d26..a402bda8 100644 --- a/Penumbra/Api/IpcTester/ModsIpcTester.cs +++ b/Penumbra/Api/IpcTester/ModsIpcTester.cs @@ -82,7 +82,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable if (!table) return; - using (IpcTester.DrawIntro(GetModList.Label, "Mods"u8)) + using (IpcTester.DrawIntro(GetModList.LabelU8, "Mods"u8)) { DrawModsPopup(); table.NextColumn(); @@ -93,7 +93,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable } } - using (IpcTester.DrawIntro(ReloadMod.Label, "Reload Mod"u8)) + using (IpcTester.DrawIntro(ReloadMod.LabelU8, "Reload Mod"u8)) { table.NextColumn(); if (Im.SmallButton("Reload"u8)) @@ -104,7 +104,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable } - using (IpcTester.DrawIntro(InstallMod.Label, "Install Mod"u8)) + using (IpcTester.DrawIntro(InstallMod.LabelU8, "Install Mod"u8)) { table.NextColumn(); if (Im.SmallButton("Install"u8)) @@ -113,7 +113,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable Im.Text($"{_lastInstallEc}"); } - using (IpcTester.DrawIntro(AddMod.Label, "Add Mod"u8)) + using (IpcTester.DrawIntro(AddMod.LabelU8, "Add Mod"u8)) { table.NextColumn(); if (Im.SmallButton("Add"u8)) @@ -122,7 +122,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable Im.Text($"{_lastAddEc}"); } - using (IpcTester.DrawIntro(DeleteMod.Label, "Delete Mod"u8)) + using (IpcTester.DrawIntro(DeleteMod.LabelU8, "Delete Mod"u8)) { table.NextColumn(); if (Im.SmallButton("Delete"u8)) @@ -131,7 +131,7 @@ public class ModsIpcTester : Luna.IUiService, IDisposable Im.Text(_lastDeleteEc.ToString()); } - using (IpcTester.DrawIntro(GetChangedItems.Label, "Get Changed Items"u8)) + using (IpcTester.DrawIntro(GetChangedItems.LabelU8, "Get Changed Items"u8)) { DrawChangedItemsPopup(); table.NextColumn(); @@ -142,13 +142,13 @@ public class ModsIpcTester : Luna.IUiService, IDisposable } } - using (IpcTester.DrawIntro(GetModPath.Label, "Current Path"u8)) + using (IpcTester.DrawIntro(GetModPath.LabelU8, "Current Path"u8)) { var (ec, path, def, nameDef) = new GetModPath(_pi).Invoke(_modDirectory, _modName); table.DrawColumn($"{path} ({(def ? "Custom" : "Default")} Path, {(nameDef ? "Custom" : "Default")} Name) [{ec}]"); } - using (IpcTester.DrawIntro(SetModPath.Label, "Set Path"u8)) + using (IpcTester.DrawIntro(SetModPath.LabelU8, "Set Path"u8)) { table.NextColumn(); if (Im.SmallButton("Set"u8)) @@ -158,19 +158,19 @@ public class ModsIpcTester : Luna.IUiService, IDisposable Im.Text($"{_lastSetPathEc}"); } - using (IpcTester.DrawIntro(ModDeleted.Label, "Last Mod Deleted"u8)) + using (IpcTester.DrawIntro(ModDeleted.LabelU8, "Last Mod Deleted"u8)) { if (_lastDeletedModTime > DateTimeOffset.UnixEpoch) table.DrawColumn($"{_lastDeletedMod} at {_lastDeletedModTime}"); } - using (IpcTester.DrawIntro(ModAdded.Label, "Last Mod Added"u8)) + using (IpcTester.DrawIntro(ModAdded.LabelU8, "Last Mod Added"u8)) { if (_lastAddedModTime > DateTimeOffset.UnixEpoch) table.DrawColumn($"{_lastAddedMod} at {_lastAddedModTime}"); } - using (IpcTester.DrawIntro(ModMoved.Label, "Last Mod Moved")) + using (IpcTester.DrawIntro(ModMoved.LabelU8, "Last Mod Moved"u8)) { if (_lastMovedModTime > DateTimeOffset.UnixEpoch) table.DrawColumn($"{_lastMovedModFrom} -> {_lastMovedModTo} at {_lastMovedModTime}"); diff --git a/Penumbra/Api/IpcTester/PluginStateIpcTester.cs b/Penumbra/Api/IpcTester/PluginStateIpcTester.cs index 0c111a77..bd252ea5 100644 --- a/Penumbra/Api/IpcTester/PluginStateIpcTester.cs +++ b/Penumbra/Api/IpcTester/PluginStateIpcTester.cs @@ -64,31 +64,31 @@ public class PluginStateIpcTester : IUiService, IDisposable DrawList(IpcSubscribers.Initialized.Label, "Last Initialized"u8, _initializedList); DrawList(IpcSubscribers.Disposed.Label, "Last Disposed"u8, _disposedList); - using (IpcTester.DrawIntro(ApiVersion.Label, "Current Version"u8)) + using (IpcTester.DrawIntro(ApiVersion.LabelU8, "Current Version"u8)) { var (breaking, features) = new ApiVersion(_pi).Invoke(); table.DrawColumn($"{breaking}.{features:D4}"); } - using (IpcTester.DrawIntro(GetEnabledState.Label, "Current State"u8)) + using (IpcTester.DrawIntro(GetEnabledState.LabelU8, "Current State"u8)) { table.DrawColumn($"{new GetEnabledState(_pi).Invoke()}"); } - using (IpcTester.DrawIntro(IpcSubscribers.EnabledChange.Label, "Last Change"u8)) + using (IpcTester.DrawIntro(IpcSubscribers.EnabledChange.LabelU8, "Last Change"u8)) { table.DrawColumn(_lastEnabledValue is { } v ? $"{_lastEnabledChange} (to {v})" : "Never"u8); } - using (IpcTester.DrawIntro(SupportedFeatures.Label, "Supported Features"u8)) + using (IpcTester.DrawIntro(SupportedFeatures.LabelU8, "Supported Features"u8)) { table.DrawColumn(StringU8.Join(", "u8, new SupportedFeatures(_pi).Invoke())); } - using (IpcTester.DrawIntro(CheckSupportedFeatures.Label, "Missing Features"u8)) + using (IpcTester.DrawIntro(CheckSupportedFeatures.LabelU8, "Missing Features"u8)) table.DrawColumn(StringU8.Join(", "u8, new CheckSupportedFeatures(_pi).Invoke(_requiredFeatures))); - using (IpcTester.DrawIntro(GetConfiguration.Label, "Configuration"u8)) + using (IpcTester.DrawIntro(GetConfiguration.LabelU8, "Configuration"u8)) { DrawConfigPopup(); table.NextColumn(); @@ -99,12 +99,12 @@ public class PluginStateIpcTester : IUiService, IDisposable } } - using (IpcTester.DrawIntro(GetModDirectory.Label, "Current Mod Directory"u8)) + using (IpcTester.DrawIntro(GetModDirectory.LabelU8, "Current Mod Directory"u8)) { table.DrawColumn(new GetModDirectory(_pi).Invoke()); } - using (IpcTester.DrawIntro(IpcSubscribers.ModDirectoryChanged.Label, "Last Mod Directory Change"u8)) + using (IpcTester.DrawIntro(IpcSubscribers.ModDirectoryChanged.LabelU8, "Last Mod Directory Change"u8)) { table.DrawColumn(_lastModDirectoryTime > DateTimeOffset.MinValue ? $"{_lastModDirectory} ({(_lastModDirectoryValid ? "Valid" : "Invalid")}) at {_lastModDirectoryTime}" diff --git a/Penumbra/Api/IpcTester/RedrawingIpcTester.cs b/Penumbra/Api/IpcTester/RedrawingIpcTester.cs index 6834d03d..32494574 100644 --- a/Penumbra/Api/IpcTester/RedrawingIpcTester.cs +++ b/Penumbra/Api/IpcTester/RedrawingIpcTester.cs @@ -38,7 +38,7 @@ public class RedrawingIpcTester : Luna.IUiService, IDisposable if (!table) return; - using (IpcTester.DrawIntro(RedrawObject.Label, "Redraw by Index"u8)) + using (IpcTester.DrawIntro(RedrawObject.LabelU8, "Redraw by Index"u8)) { var tmp = _redrawIndex; table.NextColumn(); @@ -50,14 +50,14 @@ public class RedrawingIpcTester : Luna.IUiService, IDisposable new RedrawObject(_pi).Invoke(_redrawIndex); } - using (IpcTester.DrawIntro(RedrawAll.Label, "Redraw All"u8)) + using (IpcTester.DrawIntro(RedrawAll.LabelU8, "Redraw All"u8)) { table.NextColumn(); if (Im.SmallButton("Redraw##All"u8)) new RedrawAll(_pi).Invoke(); } - using (IpcTester.DrawIntro(GameObjectRedrawn.Label, "Last Redrawn Object:"u8)) + using (IpcTester.DrawIntro(GameObjectRedrawn.LabelU8, "Last Redrawn Object:"u8)) { table.DrawColumn(_lastRedrawnString); } diff --git a/Penumbra/Api/IpcTester/ResolveIpcTester.cs b/Penumbra/Api/IpcTester/ResolveIpcTester.cs index 0f95dc38..6f93c5c7 100644 --- a/Penumbra/Api/IpcTester/ResolveIpcTester.cs +++ b/Penumbra/Api/IpcTester/ResolveIpcTester.cs @@ -24,31 +24,31 @@ public class ResolveIpcTester(IDalamudPluginInterface pi) : Luna.IUiService if (!table) return; - using (IpcTester.DrawIntro(ResolveDefaultPath.Label, "Default Collection Resolve"u8)) + using (IpcTester.DrawIntro(ResolveDefaultPath.LabelU8, "Default Collection Resolve"u8)) { if (_currentResolvePath.Length is not 0) table.DrawColumn(new ResolveDefaultPath(pi).Invoke(_currentResolvePath)); } - using (IpcTester.DrawIntro(ResolveInterfacePath.Label, "Interface Collection Resolve"u8)) + using (IpcTester.DrawIntro(ResolveInterfacePath.LabelU8, "Interface Collection Resolve"u8)) { if (_currentResolvePath.Length is not 0) table.DrawColumn(new ResolveInterfacePath(pi).Invoke(_currentResolvePath)); } - using (IpcTester.DrawIntro(ResolvePlayerPath.Label, "Player Collection Resolve"u8)) + using (IpcTester.DrawIntro(ResolvePlayerPath.LabelU8, "Player Collection Resolve"u8)) { if (_currentResolvePath.Length is not 0) table.DrawColumn(new ResolvePlayerPath(pi).Invoke(_currentResolvePath)); } - using (IpcTester.DrawIntro(ResolveGameObjectPath.Label, "Game Object Collection Resolve"u8)) + using (IpcTester.DrawIntro(ResolveGameObjectPath.LabelU8, "Game Object Collection Resolve"u8)) { if (_currentResolvePath.Length is not 0) table.DrawColumn(new ResolveGameObjectPath(pi).Invoke(_currentResolvePath, _currentReverseIdx)); } - using (IpcTester.DrawIntro(ReverseResolvePlayerPath.Label, "Reversed Game Paths (Player)"u8)) + using (IpcTester.DrawIntro(ReverseResolvePlayerPath.LabelU8, "Reversed Game Paths (Player)"u8)) { if (_currentReversePath.Length is not 0) { @@ -62,7 +62,7 @@ public class ResolveIpcTester(IDalamudPluginInterface pi) : Luna.IUiService } } - using (IpcTester.DrawIntro(ReverseResolveGameObjectPath.Label, "Reversed Game Paths (Game Object)"u8)) + using (IpcTester.DrawIntro(ReverseResolveGameObjectPath.LabelU8, "Reversed Game Paths (Game Object)"u8)) { if (_currentReversePath.Length is not 0) { @@ -79,7 +79,7 @@ public class ResolveIpcTester(IDalamudPluginInterface pi) : Luna.IUiService string[] forwardArray = _currentResolvePath.Length > 0 ? [_currentResolvePath] : []; string[] reverseArray = _currentReversePath.Length > 0 ? [_currentReversePath] : []; - using (IpcTester.DrawIntro(ResolvePlayerPaths.Label, "Resolved Paths (Player)"u8)) + using (IpcTester.DrawIntro(ResolvePlayerPaths.LabelU8, "Resolved Paths (Player)"u8)) { if (forwardArray.Length > 0 || reverseArray.Length > 0) { @@ -88,7 +88,7 @@ public class ResolveIpcTester(IDalamudPluginInterface pi) : Luna.IUiService } } - using (IpcTester.DrawIntro(ResolvePlayerPathsAsync.Label, "Resolved Paths Async (Player)"u8)) + using (IpcTester.DrawIntro(ResolvePlayerPathsAsync.LabelU8, "Resolved Paths Async (Player)"u8)) { table.NextColumn(); if (Im.SmallButton("Start"u8)) diff --git a/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs b/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs index 12c3fd94..d7b7dce8 100644 --- a/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs +++ b/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs @@ -41,7 +41,7 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj if (!table) return; - using (IpcTester.DrawIntro(GetGameObjectResourcePaths.Label, "Get GameObject resource paths"u8)) + using (IpcTester.DrawIntro(GetGameObjectResourcePaths.LabelU8, "Get GameObject resource paths"u8)) { DrawPopup("GetGameObjectResourcePaths"u8, ref _lastGameObjectResourcePaths, DrawResourcePaths, _lastCallDuration); @@ -63,7 +63,7 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj } } - using (IpcTester.DrawIntro(GetPlayerResourcePaths.Label, "Get local player resource paths"u8)) + using (IpcTester.DrawIntro(GetPlayerResourcePaths.LabelU8, "Get local player resource paths"u8)) { DrawPopup("GetPlayerResourcePaths"u8, ref _lastPlayerResourcePaths!, DrawResourcePaths, _lastCallDuration); table.NextColumn(); @@ -82,7 +82,7 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj } } - using (IpcTester.DrawIntro(GetGameObjectResourcesOfType.Label, "Get GameObject resources of type"u8)) + using (IpcTester.DrawIntro(GetGameObjectResourcesOfType.LabelU8, "Get GameObject resources of type"u8)) { DrawPopup("GetGameObjectResourcesOfType"u8, ref _lastGameObjectResourcesOfType, DrawResourcesOfType, _lastCallDuration); @@ -104,7 +104,7 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj } } - using (IpcTester.DrawIntro(GetPlayerResourcesOfType.Label, "Get local player resources of type"u8)) + using (IpcTester.DrawIntro(GetPlayerResourcesOfType.LabelU8, "Get local player resources of type"u8)) { DrawPopup("GetPlayerResourcesOfType"u8, ref _lastPlayerResourcesOfType, DrawResourcesOfType, _lastCallDuration); @@ -124,7 +124,7 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj } } - using (IpcTester.DrawIntro(GetGameObjectResourceTrees.Label, "Get GameObject resource trees"u8)) + using (IpcTester.DrawIntro(GetGameObjectResourceTrees.LabelU8, "Get GameObject resource trees"u8)) { DrawPopup("GetGameObjectResourceTrees"u8, ref _lastGameObjectResourceTrees, DrawResourceTrees, _lastCallDuration); @@ -146,7 +146,7 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj } } - using (IpcTester.DrawIntro(GetPlayerResourceTrees.Label, "Get local player resource trees"u8)) + using (IpcTester.DrawIntro(GetPlayerResourceTrees.LabelU8, "Get local player resource trees"u8)) { DrawPopup("GetPlayerResourceTrees"u8, ref _lastPlayerResourceTrees, DrawResourceTrees!, _lastCallDuration); table.NextColumn(); @@ -200,13 +200,13 @@ public class ResourceTreeIpcTester(IDalamudPluginInterface pi, ObjectManager obj { if (item == null) { - Im.Tree.Node($"{label}: null", TreeNodeFlags.Leaf).Dispose(); + Im.Tree.Leaf($"{label}: null"); continue; } if (firstSeen.TryGetValue(item, out var firstLabel)) { - Im.Tree.Node($"{label}: same as {firstLabel}", TreeNodeFlags.Leaf).Dispose(); + Im.Tree.Leaf($"{label}: same as {firstLabel}"); continue; } diff --git a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs index bbd317d0..ac494289 100644 --- a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs +++ b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs @@ -58,27 +58,26 @@ public class TemporaryIpcTester( if (!table) return; - using (IpcTester.DrawIntro("Last Error", $"{_lastTempError}")) + using (IpcTester.DrawIntro("Last Error"u8, $"{_lastTempError}")) { table.DrawColumn("Last Created Collection"u8); table.NextColumn(); LunaStyle.DrawGuid(LastCreatedCollectionId); } - using (IpcTester.DrawIntro(CreateTemporaryCollection.Label, "Create Temporary Collection"u8)) + using (IpcTester.DrawIntro(CreateTemporaryCollection.LabelU8, "Create Temporary Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Create##Collection"u8)) { - _lastTempError = new CreateTemporaryCollection(pi).Invoke(_identity, _tempCollectionName, out LastCreatedCollectionId); - if (_tempGuid is null) - _tempGuid = LastCreatedCollectionId; + _lastTempError = new CreateTemporaryCollection(pi).Invoke(_identity, _tempCollectionName, out LastCreatedCollectionId); + _tempGuid ??= LastCreatedCollectionId; } } var guid = _tempGuid.GetValueOrDefault(Guid.Empty); - using (IpcTester.DrawIntro(DeleteTemporaryCollection.Label, "Delete Temporary Collection"u8)) + using (IpcTester.DrawIntro(DeleteTemporaryCollection.LabelU8, "Delete Temporary Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Delete##Collection"u8)) @@ -88,14 +87,14 @@ public class TemporaryIpcTester( _lastTempError = new DeleteTemporaryCollection(pi).Invoke(LastCreatedCollectionId); } - using (IpcTester.DrawIntro(AssignTemporaryCollection.Label, "Assign Temporary Collection"u8)) + using (IpcTester.DrawIntro(AssignTemporaryCollection.LabelU8, "Assign Temporary Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Assign##NamedCollection"u8)) _lastTempError = new AssignTemporaryCollection(pi).Invoke(guid, _tempActorIndex, _forceOverwrite); } - using (IpcTester.DrawIntro(AddTemporaryMod.Label, "Add Temporary Mod to specific Collection"u8)) + using (IpcTester.DrawIntro(AddTemporaryMod.LabelU8, "Add Temporary Mod to specific Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Add##Mod"u8)) @@ -104,7 +103,7 @@ public class TemporaryIpcTester( _tempManipulation.Length > 0 ? _tempManipulation : string.Empty, int.MaxValue); } - using (IpcTester.DrawIntro(CreateTemporaryCollection.Label, "Copy Existing Collection"u8)) + using (IpcTester.DrawIntro(CreateTemporaryCollection.LabelU8, "Copy Existing Collection"u8)) { table.NextColumn(); if (ImEx.Button("Copy##Collection"u8, Vector2.Zero, @@ -118,7 +117,7 @@ public class TemporaryIpcTester( } } - using (IpcTester.DrawIntro(AddTemporaryModAll.Label, "Add Temporary Mod to all Collections"u8)) + using (IpcTester.DrawIntro(AddTemporaryModAll.LabelU8, "Add Temporary Mod to all Collections"u8)) { table.NextColumn(); if (Im.SmallButton("Add##All"u8)) @@ -127,21 +126,21 @@ public class TemporaryIpcTester( _tempManipulation.Length > 0 ? _tempManipulation : string.Empty, int.MaxValue); } - using (IpcTester.DrawIntro(RemoveTemporaryMod.Label, "Remove Temporary Mod from specific Collection"u8)) + using (IpcTester.DrawIntro(RemoveTemporaryMod.LabelU8, "Remove Temporary Mod from specific Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Remove##Mod"u8)) _lastTempError = new RemoveTemporaryMod(pi).Invoke(_tempModName, guid, int.MaxValue); } - using (IpcTester.DrawIntro(RemoveTemporaryModAll.Label, "Remove Temporary Mod from all Collections"u8)) + using (IpcTester.DrawIntro(RemoveTemporaryModAll.LabelU8, "Remove Temporary Mod from all Collections"u8)) { table.NextColumn(); if (Im.SmallButton("Remove##ModAll"u8)) _lastTempError = new RemoveTemporaryModAll(pi).Invoke(_tempModName, int.MaxValue); } - using (IpcTester.DrawIntro(SetTemporaryModSettings.Label, "Set Temporary Mod Settings (to default) in specific Collection"u8)) + using (IpcTester.DrawIntro(SetTemporaryModSettings.LabelU8, "Set Temporary Mod Settings (to default) in specific Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Set##SetTemporary"u8)) @@ -150,7 +149,8 @@ public class TemporaryIpcTester( "IPC Tester", 1337); } - using (IpcTester.DrawIntro(SetTemporaryModSettingsPlayer.Label, "Set Temporary Mod Settings (to default) in game object collection"u8)) + using (IpcTester.DrawIntro(SetTemporaryModSettingsPlayer.LabelU8, + "Set Temporary Mod Settings (to default) in game object collection"u8)) { table.NextColumn(); if (Im.SmallButton("Set##SetTemporaryPlayer"u8)) @@ -159,7 +159,7 @@ public class TemporaryIpcTester( "IPC Tester", 1337); } - using (IpcTester.DrawIntro(RemoveTemporaryModSettings.Label, "Remove Temporary Mod Settings from specific Collection"u8)) + using (IpcTester.DrawIntro(RemoveTemporaryModSettings.LabelU8, "Remove Temporary Mod Settings from specific Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Remove##RemoveTemporary"u8)) @@ -169,7 +169,7 @@ public class TemporaryIpcTester( _lastTempError = new RemoveTemporaryModSettings(pi).Invoke(guid, _modDirectory, 1338); } - using (IpcTester.DrawIntro(RemoveTemporaryModSettingsPlayer.Label, "Remove Temporary Mod Settings from game object Collection"u8)) + using (IpcTester.DrawIntro(RemoveTemporaryModSettingsPlayer.LabelU8, "Remove Temporary Mod Settings from game object Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Remove##RemoveTemporaryPlayer"u8)) @@ -179,7 +179,7 @@ public class TemporaryIpcTester( _lastTempError = new RemoveTemporaryModSettingsPlayer(pi).Invoke(_tempActorIndex, _modDirectory, 1338); } - using (IpcTester.DrawIntro(RemoveAllTemporaryModSettings.Label, "Remove All Temporary Mod Settings from specific Collection"u8)) + using (IpcTester.DrawIntro(RemoveAllTemporaryModSettings.LabelU8, "Remove All Temporary Mod Settings from specific Collection"u8)) { table.NextColumn(); if (Im.SmallButton("Remove##RemoveAllTemporary"u8)) @@ -189,7 +189,7 @@ public class TemporaryIpcTester( _lastTempError = new RemoveAllTemporaryModSettings(pi).Invoke(guid, 1338); } - using (IpcTester.DrawIntro(RemoveAllTemporaryModSettingsPlayer.Label, + using (IpcTester.DrawIntro(RemoveAllTemporaryModSettingsPlayer.LabelU8, "Remove All Temporary Mod Settings from game object Collection"u8)) { table.NextColumn(); @@ -200,7 +200,7 @@ public class TemporaryIpcTester( _lastTempError = new RemoveAllTemporaryModSettingsPlayer(pi).Invoke(_tempActorIndex, 1338); } - using (IpcTester.DrawIntro(QueryTemporaryModSettings.Label, "Query Temporary Mod Settings from specific Collection"u8)) + using (IpcTester.DrawIntro(QueryTemporaryModSettings.LabelU8, "Query Temporary Mod Settings from specific Collection"u8)) { table.NextColumn(); Im.SmallButton("Query##QueryTemporaryModSettings"u8); @@ -219,7 +219,7 @@ public class TemporaryIpcTester( } } - using (IpcTester.DrawIntro(QueryTemporaryModSettingsPlayer.Label, "Query Temporary Mod Settings from game object Collection"u8)) + using (IpcTester.DrawIntro(QueryTemporaryModSettingsPlayer.LabelU8, "Query Temporary Mod Settings from game object Collection"u8)) { table.NextColumn(); Im.SmallButton("Query##QueryTemporaryModSettingsPlayer"u8); diff --git a/Penumbra/Api/IpcTester/UiIpcTester.cs b/Penumbra/Api/IpcTester/UiIpcTester.cs index bfecc7dc..402dac77 100644 --- a/Penumbra/Api/IpcTester/UiIpcTester.cs +++ b/Penumbra/Api/IpcTester/UiIpcTester.cs @@ -66,12 +66,12 @@ public class UiIpcTester : Luna.IUiService, IDisposable if (!table) return; - using (IpcTester.DrawIntro(PostSettingsDraw.Label, "Last Drawn Mod"u8)) + using (IpcTester.DrawIntro(PostSettingsDraw.LabelU8, "Last Drawn Mod"u8)) { table.DrawColumn(_lastDrawnMod.Length > 0 ? $"{_lastDrawnMod} at {_lastDrawnModTime}" : "None"u8); } - using (IpcTester.DrawIntro(IpcSubscribers.ChangedItemTooltip.Label, "Add Tooltip"u8)) + using (IpcTester.DrawIntro(IpcSubscribers.ChangedItemTooltip.LabelU8, "Add Tooltip"u8)) { table.NextColumn(); if (Im.Checkbox("##tooltip"u8, ref _subscribedToTooltip)) @@ -86,7 +86,7 @@ public class UiIpcTester : Luna.IUiService, IDisposable ImEx.TextFrameAligned(_lastHovered); } - using (IpcTester.DrawIntro(IpcSubscribers.ChangedItemClicked.Label, "Subscribe Click"u8)) + using (IpcTester.DrawIntro(IpcSubscribers.ChangedItemClicked.LabelU8, "Subscribe Click"u8)) { table.NextColumn(); if (Im.Checkbox("##click"u8, ref _subscribedToClick)) @@ -101,7 +101,7 @@ public class UiIpcTester : Luna.IUiService, IDisposable ImEx.TextFrameAligned(_lastClicked); } - using (IpcTester.DrawIntro(OpenMainWindow.Label, "Open Mod Window"u8)) + using (IpcTester.DrawIntro(OpenMainWindow.LabelU8, "Open Mod Window"u8)) { table.NextColumn(); if (Im.SmallButton("Open##window"u8)) @@ -111,7 +111,7 @@ public class UiIpcTester : Luna.IUiService, IDisposable Im.Text($"{_ec}"); } - using (IpcTester.DrawIntro(CloseMainWindow.Label, "Close Mod Window"u8)) + using (IpcTester.DrawIntro(CloseMainWindow.LabelU8, "Close Mod Window"u8)) { table.NextColumn(); if (Im.SmallButton("Close##window"u8)) diff --git a/Penumbra/Import/Models/ModelManager.cs b/Penumbra/Import/Models/ModelManager.cs index 63b496f1..25c4ce9d 100644 --- a/Penumbra/Import/Models/ModelManager.cs +++ b/Penumbra/Import/Models/ModelManager.cs @@ -108,7 +108,7 @@ public sealed class ModelManager( if (targetId == EstEntry.Zero) return []; - return [GamePaths.Sklb.Customization(info.GenderRace, type.ToName(), targetId.AsId)]; + return [GamePaths.Sklb.Customization(info.GenderRace, type.ToSuffix(), targetId.AsId)]; } /// Try to resolve the absolute path to a .mtrl from the potentially-partial path provided by a model. diff --git a/Penumbra/Import/Textures/PathSelectCombo.cs b/Penumbra/Import/Textures/PathSelectCombo.cs index 25539c9a..b62d26a8 100644 --- a/Penumbra/Import/Textures/PathSelectCombo.cs +++ b/Penumbra/Import/Textures/PathSelectCombo.cs @@ -9,7 +9,7 @@ namespace Penumbra.Import.Textures; public abstract class PathSelectCombo(IDataManager dataManager) : FilterComboBase { - public bool Draw(Utf8StringHandler label, Utf8StringHandler tooltip, string current, + public bool Draw(Utf8StringHandler label, Utf8StringHandler tooltip, string current, int skipPrefix, out string newPath) { _skipPrefix = skipPrefix; diff --git a/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs b/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs index ce8db759..dfd27d77 100644 --- a/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs +++ b/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs @@ -273,7 +273,7 @@ internal partial record ResolveContext var metaCache = Global.Collection.MetaCache; var skeletonSet = metaCache?.GetEstEntry(type, raceCode, primary) ?? EstFile.GetDefault(Global.MetaFileManager, type, raceCode, primary); - return (raceCode, type.ToName(), skeletonSet.AsId); + return (raceCode, type.ToSuffix(), skeletonSet.AsId); } private unsafe Utf8GamePath ResolveSkeletonPathNative(uint partialSkeletonIndex) diff --git a/Penumbra/Meta/Manipulations/Est.cs b/Penumbra/Meta/Manipulations/Est.cs index b5192a9f..a92c710b 100644 --- a/Penumbra/Meta/Manipulations/Est.cs +++ b/Penumbra/Meta/Manipulations/Est.cs @@ -1,3 +1,4 @@ +using Luna.Generators; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Penumbra.GameData.Data; @@ -7,6 +8,7 @@ using Penumbra.Interop.Structs; namespace Penumbra.Meta.Manipulations; +[NamedEnum] public enum EstType : byte { Hair = MetaIndex.HairEst, @@ -120,9 +122,9 @@ public readonly record struct EstEntry(ushort Value) } } -public static class EstTypeExtension +public static partial class EstTypeExtension { - public static string ToName(this EstType type) + public static string ToSuffix(this EstType type) => type switch { EstType.Hair => "hair", diff --git a/Penumbra/Meta/Manipulations/GlobalEqpType.cs b/Penumbra/Meta/Manipulations/GlobalEqpType.cs index 29bfe825..a3ae779f 100644 --- a/Penumbra/Meta/Manipulations/GlobalEqpType.cs +++ b/Penumbra/Meta/Manipulations/GlobalEqpType.cs @@ -1,24 +1,58 @@ +using Luna.Generators; using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Penumbra.Meta.Manipulations; +[NamedEnum(Utf16: false)] +[TooltipEnum] [JsonConverter(typeof(StringEnumConverter))] public enum GlobalEqpType { + [Name("Always Show Earrings")] + [Tooltip("Prevents the game from hiding earrings through other models when a specific earring is worn.")] DoNotHideEarrings, + + [Name("Always Show Necklaces")] + [Tooltip("Prevents the game from hiding necklaces through other models when a specific necklace is worn.")] DoNotHideNecklace, + + [Name("Always Show Bracelets")] + [Tooltip("Prevents the game from hiding bracelets through other models when a specific bracelet is worn.")] DoNotHideBracelets, + + [Name("Always Show Rings (Right Finger)")] + [Tooltip( + "Prevents the game from hiding rings worn on the right finger through other models when a specific ring is worn on the right finger.")] DoNotHideRingR, + + [Name("Always Show Rings (Left Finger)")] + [Tooltip( + "Prevents the game from hiding rings worn on the left finger through other models when a specific ring is worn on the left finger.")] DoNotHideRingL, + + [Name("Always Show Hats for Hrothgar")] + [Tooltip("Prevents the game from hiding any hats for Hrothgar that are normally flagged to not display on them.")] DoNotHideHrothgarHats, + + [Name("Always Show Hats for Viera")] + [Tooltip("Prevents the game from hiding any hats for Viera that are normally flagged to not display on them.")] DoNotHideVieraHats, + + [Name("Always Hide Horns (Au Ra)")] + [Tooltip("Forces the game to hide Au Ra horns regardless of headwear.")] HideHorns, + + [Name("Always Hide Horns (Viera)")] + [Tooltip("Forces the game to hide Viera ears regardless of headwear.")] HideVieraEars, + + [Name("Always Hide Horns (Miqo'te)")] + [Tooltip("Forces the game to hide Miqo'te ears regardless of headwear.")] HideMiqoteEars, } -public static class GlobalEqpExtensions +public static partial class GlobalEqpExtensions { public static bool HasCondition(this GlobalEqpType type) => type switch @@ -35,43 +69,4 @@ public static class GlobalEqpExtensions GlobalEqpType.HideMiqoteEars => false, _ => false, }; - - - public static ReadOnlySpan ToName(this GlobalEqpType type) - => type switch - { - GlobalEqpType.DoNotHideEarrings => "Always Show Earrings"u8, - GlobalEqpType.DoNotHideNecklace => "Always Show Necklaces"u8, - GlobalEqpType.DoNotHideBracelets => "Always Show Bracelets"u8, - GlobalEqpType.DoNotHideRingR => "Always Show Rings (Right Finger)"u8, - GlobalEqpType.DoNotHideRingL => "Always Show Rings (Left Finger)"u8, - GlobalEqpType.DoNotHideHrothgarHats => "Always Show Hats for Hrothgar"u8, - GlobalEqpType.DoNotHideVieraHats => "Always Show Hats for Viera"u8, - GlobalEqpType.HideHorns => "Always Hide Horns (Au Ra)"u8, - GlobalEqpType.HideVieraEars => "Always Hide Ears (Viera)"u8, - GlobalEqpType.HideMiqoteEars => "Always Hide Ears (Miqo'te)"u8, - _ => "\0"u8, - }; - - public static ReadOnlySpan ToDescription(this GlobalEqpType type) - => type switch - { - GlobalEqpType.DoNotHideEarrings => "Prevents the game from hiding earrings through other models when a specific earring is worn."u8, - GlobalEqpType.DoNotHideNecklace => - "Prevents the game from hiding necklaces through other models when a specific necklace is worn."u8, - GlobalEqpType.DoNotHideBracelets => - "Prevents the game from hiding bracelets through other models when a specific bracelet is worn."u8, - GlobalEqpType.DoNotHideRingR => - "Prevents the game from hiding rings worn on the right finger through other models when a specific ring is worn on the right finger."u8, - GlobalEqpType.DoNotHideRingL => - "Prevents the game from hiding rings worn on the left finger through other models when a specific ring is worn on the left finger."u8, - GlobalEqpType.DoNotHideHrothgarHats => - "Prevents the game from hiding any hats for Hrothgar that are normally flagged to not display on them."u8, - GlobalEqpType.DoNotHideVieraHats => - "Prevents the game from hiding any hats for Viera that are normally flagged to not display on them."u8, - GlobalEqpType.HideHorns => "Forces the game to hide Au Ra horns regardless of headwear."u8, - GlobalEqpType.HideVieraEars => "Forces the game to hide Viera ears regardless of headwear."u8, - GlobalEqpType.HideMiqoteEars => "Forces the game to hide Miqo'te ears regardless of headwear."u8, - _ => "\0"u8, - }; } diff --git a/Penumbra/Meta/Manipulations/Rsp.cs b/Penumbra/Meta/Manipulations/Rsp.cs index 5f91a37c..d64fd16d 100644 --- a/Penumbra/Meta/Manipulations/Rsp.cs +++ b/Penumbra/Meta/Manipulations/Rsp.cs @@ -9,7 +9,7 @@ namespace Penumbra.Meta.Manipulations; public readonly record struct RspIdentifier(SubRace SubRace, RspAttribute Attribute) : IMetaIdentifier { public void AddChangedItems(ObjectIdentification identifier, IDictionary changedItems) - => changedItems.UpdateCountOrSet($"{SubRace.ToName()} {Attribute.ToFullString()}", () => new IdentifiedName()); + => changedItems.UpdateCountOrSet($"{SubRace.ToName()} {Attribute.ToName()}", () => new IdentifiedName()); public MetaIndex FileIndex() => MetaIndex.HumanCmp; @@ -42,7 +42,7 @@ public readonly record struct RspIdentifier(SubRace SubRace, RspAttribute Attrib => MetaManipulationType.Rsp; public override string ToString() - => $"RSP - {SubRace.ToName()} - {Attribute.ToFullString()}"; + => $"RSP - {SubRace.ToName()} - {Attribute.ToName()}"; } [JsonConverter(typeof(Converter))] diff --git a/Penumbra/Mods/ItemSwap/ItemSwap.cs b/Penumbra/Mods/ItemSwap/ItemSwap.cs index 0049fa12..1ee0a0d3 100644 --- a/Penumbra/Mods/ItemSwap/ItemSwap.cs +++ b/Penumbra/Mods/ItemSwap/ItemSwap.cs @@ -132,14 +132,14 @@ public static class ItemSwap public static FileSwap CreatePhyb(MetaFileManager manager, Func redirections, EstType type, GenderRace race, EstEntry estEntry) { - var phybPath = GamePaths.Phyb.Customization(race, type.ToName(), estEntry.AsId); + var phybPath = GamePaths.Phyb.Customization(race, type.ToSuffix(), estEntry.AsId); return FileSwap.CreateSwap(manager, ResourceType.Phyb, redirections, phybPath, phybPath); } public static FileSwap CreateSklb(MetaFileManager manager, Func redirections, EstType type, GenderRace race, EstEntry estEntry) { - var sklbPath = GamePaths.Sklb.Customization(race, type.ToName(), estEntry.AsId); + var sklbPath = GamePaths.Sklb.Customization(race, type.ToSuffix(), estEntry.AsId); return FileSwap.CreateSwap(manager, ResourceType.Sklb, redirections, sklbPath, sklbPath); } diff --git a/Penumbra/UI/AdvancedWindow/FileEditor.cs b/Penumbra/UI/AdvancedWindow/FileEditor.cs index 0ffc5b62..1c1f3387 100644 --- a/Penumbra/UI/AdvancedWindow/FileEditor.cs +++ b/Penumbra/UI/AdvancedWindow/FileEditor.cs @@ -1,14 +1,8 @@ -using Dalamud.Bindings.ImGui; -using Dalamud.Interface; -using Dalamud.Interface.Colors; using Dalamud.Interface.ImGuiNotification; using Dalamud.Plugin.Services; using ImSharp; using Luna; -using OtterGui; using OtterGui.Classes; -using OtterGui.Raii; -using OtterGui.Text; using OtterGui.Widgets; using Penumbra.Communication; using Penumbra.GameData.Data; @@ -39,7 +33,7 @@ public class FileEditor( { public void Draw() { - using var tab = ImRaii.TabItem(tabName); + using var tab = Im.TabBar.BeginItem(tabName); if (!tab) { _quickImport = null; @@ -55,7 +49,7 @@ public class FileEditor( RedrawOnSaveBox(); Im.Line.Same(); DefaultInput(); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawFilePanel(); } @@ -63,13 +57,13 @@ public class FileEditor( private void RedrawOnSaveBox() { var redraw = config.Ephemeral.ForceRedrawOnFileChange; - if (ImGui.Checkbox("Redraw on Save", ref redraw)) + if (Im.Checkbox("Redraw on Save"u8, ref redraw)) { config.Ephemeral.ForceRedrawOnFileChange = redraw; config.Ephemeral.Save(); } - ImGuiUtil.HoverTooltip("Force a redraw of your player character whenever you save a file here."); + Im.Tooltip.OnHover("Force a redraw of your player character whenever you save a file here."u8); } public void Dispose() @@ -92,7 +86,7 @@ public class FileEditor( private T? _defaultFile; private Exception? _defaultException; - private readonly Combo _combo = new(config, getFiles); + private readonly Combo _combo = new(getFiles); private ModEditWindow.QuickImportAction? _quickImport; @@ -100,9 +94,9 @@ public class FileEditor( { using var spacing = ImStyleDouble.ItemSpacing.PushX(Im.Style.GlobalScale * 3); Im.Item.SetNextWidth(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) + Im.Input.Text("##defaultInput"u8, ref _defaultPath, "Input game path to compare..."u8, maxLength: Utf8GamePath.MaxGamePathLength); + _inInput = Im.Item.Active; + if (Im.Item.DeactivatedAfterEdit && _defaultPath.Length > 0) { _isDefaultPathUtf8Valid = Utf8GamePath.FromString(_defaultPath, out _defaultPathUtf8); _quickImport = null; @@ -110,7 +104,7 @@ public class FileEditor( try { var file = gameData.GetFile(_defaultPath); - if (file != null) + if (file is not null) { _defaultException = null; (_defaultFile as IDisposable)?.Dispose(); @@ -131,8 +125,7 @@ public class FileEditor( } Im.Line.Same(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Save.ToIconString(), new Vector2(Im.Style.FrameHeight), "Export this file.", - _defaultFile == null, true)) + if (ImEx.Icon.Button(LunaStyle.SaveIcon, "Export this file."u8, _defaultFile is null)) fileDialog.OpenSavePicker($"Export {_defaultPath} to...", fileType, Path.GetFileNameWithoutExtension(_defaultPath), fileType, (success, name) => { @@ -152,8 +145,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(Im.Style.FrameHeight), - $"Add a copy of this file to {_quickImport.OptionName}.", !_quickImport.CanExecute, true)) + if (ImEx.Icon.Button(LunaStyle.ImportIcon, $"Add a copy of this file to {_quickImport.OptionName}.", !_quickImport.CanExecute)) { try { @@ -211,7 +203,7 @@ public class FileEditor( private void SaveButton() { var canSave = _changed && _currentFile is { Valid: true }; - if (ImGuiUtil.DrawDisabledButton("Save to File", Vector2.Zero, + if (ImEx.Button("Save to File"u8, Vector2.Zero, $"Save the selected {fileType} file with all changes applied. This is not revertible.", !canSave)) SaveFile(); } @@ -219,14 +211,14 @@ public class FileEditor( public void SaveFile() { compactor.WriteAllBytes(_currentPath!.File.FullName, _currentFile!.Write()); - if (owner.Mod != null) + if (owner.Mod is not null) communicator.ModFileChanged.Invoke(new ModFileChanged.Arguments(owner.Mod, _currentPath)); _changed = false; } private void ResetButton() { - if (ImGuiUtil.DrawDisabledButton("Reset Changes", Vector2.Zero, + if (ImEx.Button("Reset Changes"u8, Vector2.Zero, $"Reset all changes made to the {fileType} file.", !_changed)) { var tmp = _currentPath; @@ -237,31 +229,31 @@ public class FileEditor( private void DrawFilePanel() { - using var child = ImRaii.Child("##filePanel", -Vector2.One, true); + using var child = Im.Child.Begin("##filePanel"u8, Im.ContentRegion.Available, true); if (!child) return; - if (_currentPath != null) + if (_currentPath is not null) { - if (_currentFile == null) + if (_currentFile is null) { Im.Text($"Could not parse selected {fileType} file."); - if (_currentException != null) + if (_currentException is not null) { - using var tab = ImRaii.PushIndent(); - ImGuiUtil.TextWrapped(_currentException.ToString()); + using var tab = Im.Indent(); + Im.TextWrapped($"{_currentException}"); } } else { - using var id = ImRaii.PushId(0); + using var id = Im.Id.Push(0); _changed |= drawEdit(_currentFile, false); } } if (!_inInput && _defaultPath.Length > 0) { - if (_currentPath != null) + if (_currentPath is not null) { Im.Line.New(); Im.Line.New(); @@ -272,50 +264,46 @@ public class FileEditor( if (_defaultFile == null) { Im.Text($"Could not parse provided {fileType} game file:\n"); - if (_defaultException != null) + if (_defaultException is not null) { - using var tab = ImRaii.PushIndent(); - ImGuiUtil.TextWrapped(_defaultException.ToString()); + using var tab = Im.Indent(); + Im.TextWrapped($"{_defaultException}"); } } else { - using var id = ImRaii.PushId(1); + using var id = Im.Id.Push(1); drawEdit(_defaultFile, true); } } } - private class Combo : FilterComboCache + private class Combo(Func> generator) + : FilterComboCache(generator, MouseWheelType.None, Penumbra.Log) { - private readonly Configuration _config; - - public Combo(Configuration config, Func> generator) - : base(generator, MouseWheelType.None, Penumbra.Log) - => _config = config; - protected override bool DrawSelectable(int globalIdx, bool selected) { var file = Items[globalIdx]; bool ret; - using (var c = ImGuiColor.Text.Push(ColorId.HandledConflictMod.Value(), file.IsOnPlayer)) + using (ImGuiColor.Text.Push(ColorId.HandledConflictMod.Value(), file.IsOnPlayer)) { - ret = ImGui.Selectable(file.RelPath.ToString(), selected); + ret = Im.Selectable(file.RelPath.ToString(), selected); } if (Im.Item.Hovered()) { - using var tt = ImRaii.Tooltip(); + using var tt = Im.Tooltip.Begin(); Im.Text("All Game Paths"u8); Im.Separator(); using var t = Im.Table.Begin("##Tooltip"u8, 2, TableFlags.SizingFixedFit); - foreach (var (option, gamePath) in file.SubModUsage) + if (t) { - ImGui.TableNextColumn(); - ImUtf8.Text(gamePath.Path.Span); - ImGui.TableNextColumn(); - using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value()); - Im.Text(option.GetFullName()); + foreach (var (option, gamePath) in file.SubModUsage) + { + t.DrawColumn(gamePath.Path.Span); + using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value()); + t.DrawColumn(option.GetFullName()); + } } } @@ -323,7 +311,7 @@ public class FileEditor( { Im.Line.Same(); using var color = ImGuiColor.Text.Push(ColorId.ItemId.Value()); - ImGuiUtil.RightAlign(file.SubModUsage[0].Item2.Path.ToString()); + ImEx.TextRightAligned($"{file.SubModUsage[0].Item2.Path}"); } return ret; diff --git a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs index c5b3a311..d4565cb1 100644 --- a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs +++ b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs @@ -1,9 +1,8 @@ using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; +using Luna.Generators; using OtterGui; -using OtterGui.Raii; using OtterGui.Widgets; using Penumbra.Api.Enums; using Penumbra.Collections.Manager; @@ -29,6 +28,43 @@ using MouseWheelType = OtterGui.Widgets.MouseWheelType; namespace Penumbra.UI.AdvancedWindow; +[NamedEnum(Utf16: false)] +public enum SwapType +{ + Hat, + Top, + Gloves, + Pants, + Shoes, + Earrings, + Necklace, + Bracelet, + Ring, + [Name("Between Slots")] + BetweenSlots, + Hair, + Face, + Ears, + Tail, + Weapon, + Glasses, +} + + +[NamedEnum(Utf16: false)] +public enum BetweenSlotTypes +{ + Hat, + Earrings, + Necklace, + Bracelets, + [Name("Right Ring")] + RightRing, + [Name("Left Ring")] + LeftRing, + Glasses, +} + public class ItemSwapTab : IDisposable, ITab { private readonly Configuration _config; @@ -49,19 +85,19 @@ public class ItemSwapTab : IDisposable, ITab _swapData = new ItemSwapContainer(metaFileManager, identifier); var a = collectionManager.Active; - _selectors = new Dictionary + _selectors = new Dictionary { // @formatter:off - [SwapType.Hat] = (new ItemSelector(a, itemService, selector, FullEquipType.Head), new ItemSelector(a, itemService, null, FullEquipType.Head), "Take this Hat", "and put it on this one" ), - [SwapType.Top] = (new ItemSelector(a, itemService, selector, FullEquipType.Body), new ItemSelector(a, itemService, null, FullEquipType.Body), "Take this Top", "and put it on this one" ), - [SwapType.Gloves] = (new ItemSelector(a, itemService, selector, FullEquipType.Hands), new ItemSelector(a, itemService, null, FullEquipType.Hands), "Take these Gloves", "and put them on these" ), - [SwapType.Pants] = (new ItemSelector(a, itemService, selector, FullEquipType.Legs), new ItemSelector(a, itemService, null, FullEquipType.Legs), "Take these Pants", "and put them on these" ), - [SwapType.Shoes] = (new ItemSelector(a, itemService, selector, FullEquipType.Feet), new ItemSelector(a, itemService, null, FullEquipType.Feet), "Take these Shoes", "and put them on these" ), - [SwapType.Earrings] = (new ItemSelector(a, itemService, selector, FullEquipType.Ears), new ItemSelector(a, itemService, null, FullEquipType.Ears), "Take these Earrings", "and put them on these" ), - [SwapType.Necklace] = (new ItemSelector(a, itemService, selector, FullEquipType.Neck), new ItemSelector(a, itemService, null, FullEquipType.Neck), "Take this Necklace", "and put it on this one" ), - [SwapType.Bracelet] = (new ItemSelector(a, itemService, selector, FullEquipType.Wrists), new ItemSelector(a, itemService, null, FullEquipType.Wrists), "Take these Bracelets", "and put them on these" ), - [SwapType.Ring] = (new ItemSelector(a, itemService, selector, FullEquipType.Finger), new ItemSelector(a, itemService, null, FullEquipType.Finger), "Take this Ring", "and put it on this one" ), - [SwapType.Glasses] = (new ItemSelector(a, itemService, selector, FullEquipType.Glasses), new ItemSelector(a, itemService, null, FullEquipType.Glasses), "Take these Glasses", "and put them on these" ), + [SwapType.Hat] = (new ItemSelector(a, itemService, selector, FullEquipType.Head), new ItemSelector(a, itemService, null, FullEquipType.Head), new StringU8("Take this Hat"u8), new StringU8("and put it on this one"u8) ), + [SwapType.Top] = (new ItemSelector(a, itemService, selector, FullEquipType.Body), new ItemSelector(a, itemService, null, FullEquipType.Body), new StringU8("Take this Top"u8), new StringU8("and put it on this one"u8) ), + [SwapType.Gloves] = (new ItemSelector(a, itemService, selector, FullEquipType.Hands), new ItemSelector(a, itemService, null, FullEquipType.Hands), new StringU8("Take these Gloves"u8), new StringU8("and put them on these"u8) ), + [SwapType.Pants] = (new ItemSelector(a, itemService, selector, FullEquipType.Legs), new ItemSelector(a, itemService, null, FullEquipType.Legs), new StringU8("Take these Pants"u8), new StringU8("and put them on these"u8) ), + [SwapType.Shoes] = (new ItemSelector(a, itemService, selector, FullEquipType.Feet), new ItemSelector(a, itemService, null, FullEquipType.Feet), new StringU8("Take these Shoes"u8), new StringU8("and put them on these"u8) ), + [SwapType.Earrings] = (new ItemSelector(a, itemService, selector, FullEquipType.Ears), new ItemSelector(a, itemService, null, FullEquipType.Ears), new StringU8("Take these Earrings"u8), new StringU8("and put them on these"u8) ), + [SwapType.Necklace] = (new ItemSelector(a, itemService, selector, FullEquipType.Neck), new ItemSelector(a, itemService, null, FullEquipType.Neck), new StringU8("Take this Necklace"u8), new StringU8("and put it on this one"u8) ), + [SwapType.Bracelet] = (new ItemSelector(a, itemService, selector, FullEquipType.Wrists), new ItemSelector(a, itemService, null, FullEquipType.Wrists), new StringU8("Take these Bracelets"u8), new StringU8("and put them on these"u8) ), + [SwapType.Ring] = (new ItemSelector(a, itemService, selector, FullEquipType.Finger), new ItemSelector(a, itemService, null, FullEquipType.Finger), new StringU8("Take this Ring"u8), new StringU8("and put it on this one"u8) ), + [SwapType.Glasses] = (new ItemSelector(a, itemService, selector, FullEquipType.Glasses), new ItemSelector(a, itemService, null, FullEquipType.Glasses), new StringU8("Take these Glasses"u8), new StringU8("and put them on these"u8) ), // @formatter:on }; @@ -78,7 +114,7 @@ public class ItemSwapTab : IDisposable, ITab return; var oldDefaultName = $"{_mod?.Name ?? "Unknown"} (Swapped)"; - if (_newModName.Length == 0 || oldDefaultName == _newModName) + if (_newModName.Length is 0 || oldDefaultName == _newModName) _newModName = $"{mod.Name} (Swapped)"; _mod = mod; @@ -99,9 +135,9 @@ public class ItemSwapTab : IDisposable, ITab DrawSwapBar(); - using var table = ImRaii.ListBox("##swaps", -Vector2.One); - if (_loadException != null) - ImGuiUtil.TextWrapped($"Could not load Customization Swap:\n{_loadException}"); + using var table = Im.ListBox.Begin("##swaps"u8, Im.ContentRegion.Available); + if (_loadException is not null) + Im.TextWrapped($"Could not load Customization Swap:\n{_loadException}"); else if (_swapData.Loaded) foreach (var swap in _swapData.Swaps) DrawSwap(swap); @@ -117,25 +153,7 @@ public class ItemSwapTab : IDisposable, ITab _communicator.ModOptionChanged.Unsubscribe(OnModOptionChange); } - private enum SwapType - { - Hat, - Top, - Gloves, - Pants, - Shoes, - Earrings, - Necklace, - Bracelet, - Ring, - BetweenSlots, - Hair, - Face, - Ears, - Tail, - Weapon, - Glasses, - } + private class ItemSelector(ActiveCollections collections, ItemData data, ModFileSystemSelector? selector, FullEquipType type) : FilterComboCache<(EquipItem Item, bool InMod, SingleArray InCollection)>(() => @@ -173,8 +191,8 @@ public class ItemSwapTab : IDisposable, ITab => obj.Item.Name; } - private readonly Dictionary _selectors; - private readonly ItemSwapContainer _swapData; + private readonly Dictionary _selectors; + private readonly ItemSwapContainer _swapData; private Mod? _mod; private ModSettings? _modSettings; @@ -315,11 +333,9 @@ public class ItemSwapTab : IDisposable, ITab private string CreateAuthor() { - if (_mod!.Author.Length is 0) - return _config.DefaultModAuthor; - if (_mod!.Author == _config.DefaultModAuthor) - return _config.DefaultModAuthor; - if (_mod!.Author is "TexTools User" or DefaultTexToolsData.Author) + if (_mod!.Author.Length is 0 + || _mod!.Author == _config.DefaultModAuthor + || _mod!.Author is "TexTools User" or DefaultTexToolsData.Author) return _config.DefaultModAuthor; if (_config.DefaultModAuthor is DefaultTexToolsData.Author) return _mod!.Author; @@ -330,7 +346,7 @@ public class ItemSwapTab : IDisposable, ITab private void UpdateOption() { _selectedGroup = _mod?.Groups.FirstOrDefault(g => g.Name == _newGroupName); - _subModValid = _mod != null + _subModValid = _mod is not null && _newGroupName.Length > 0 && _newOptionName.Length > 0 && (_selectedGroup?.Options.All(o => o.Name != _newOptionName) ?? true); @@ -339,7 +355,7 @@ public class ItemSwapTab : IDisposable, ITab private void CreateMod() { var newDir = _modManager.Creator.CreateEmptyMod(_modManager.BasePath, _newModName, CreateDescription(), CreateAuthor()); - if (newDir == null) + if (newDir is null) return; _modManager.AddMod(newDir, false); @@ -351,7 +367,7 @@ public class ItemSwapTab : IDisposable, ITab private void CreateOption() { - if (_mod == null || !_subModValid) + if (_mod is null || !_subModValid) return; var groupCreated = false; @@ -366,9 +382,9 @@ public class ItemSwapTab : IDisposable, ITab if (optionFolderName?.Exists == true) throw new Exception($"The folder {optionFolderName.FullName} for the option already exists."); - if (optionFolderName != null) + if (optionFolderName is not null) { - if (_selectedGroup == null) + if (_selectedGroup is null) { if (_modManager.OptionEditor.AddModGroup(_mod, GroupType.Multi, _newGroupName) is not { } group) throw new Exception($"Failure creating option group."); @@ -383,7 +399,6 @@ public class ItemSwapTab : IDisposable, ITab createdOption = option; optionFolderName = Directory.CreateDirectory(optionFolderName.FullName); dirCreated = true; - // #TODO ModOption <> DataContainer if (!_swapData.WriteMod(_modManager, _mod, (IModDataContainer)option, _useFileSwaps ? ItemSwapContainer.WriteType.UseSwaps : ItemSwapContainer.WriteType.NoSwaps, optionFolderName)) throw new Exception("Failure writing files for mod swap."); @@ -417,56 +432,55 @@ public class ItemSwapTab : IDisposable, ITab private void DrawHeaderLine(float width) { - var newModAvailable = _loadException == null && _swapData.Loaded; + var newModAvailable = _loadException is null && _swapData.Loaded; Im.Item.SetNextWidth(width); - if (ImGui.InputTextWithHint("##newModName", "New Mod Name...", ref _newModName, 64)) + if (Im.Input.Text("##newModName"u8, ref _newModName, "New Mod Name..."u8)) { } Im.Line.Same(); var tt = !newModAvailable - ? "No swap is currently loaded." - : _newModName.Length == 0 - ? "Please enter a name for your mod." - : "Create a new mod of the given name containing only the swap."; - if (ImGuiUtil.DrawDisabledButton("Create New Mod", new Vector2(width / 2, 0), tt, !newModAvailable || _newModName.Length == 0)) + ? "No swap is currently loaded."u8 + : _newModName.Length is 0 + ? "Please enter a name for your mod."u8 + : "Create a new mod of the given name containing only the swap."u8; + if (ImEx.Button("Create New Mod"u8, new Vector2(width / 2, 0), tt, !newModAvailable || _newModName.Length is 0)) CreateMod(); Im.Line.Same(); - 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."); + Im.Cursor.X += 20 * Im.Style.GlobalScale; + Im.Checkbox("Use File Swaps"u8, ref _useFileSwaps); + Im.Tooltip.OnHover("Instead of writing every single non-default file to the newly created mod or option,\n"u8 + + "even those available from game files, use File Swaps to default game files where possible."u8); Im.Item.SetNextWidth((width - Im.Style.ItemSpacing.X) / 2); - if (ImGui.InputTextWithHint("##groupName", "Group Name...", ref _newGroupName, 32)) + if (Im.Input.Text("##groupName"u8, ref _newGroupName, "Group Name..."u8)) UpdateOption(); Im.Line.Same(); Im.Item.SetNextWidth((width - Im.Style.ItemSpacing.X) / 2); - if (ImGui.InputTextWithHint("##optionName", "New Option Name...", ref _newOptionName, 32)) + if (Im.Input.Text("##optionName"u8, ref _newOptionName, "New Option Name..."u8)) UpdateOption(); Im.Line.Same(); tt = !_subModValid - ? "An option with that name already exists in that group, or no name is specified." + ? "An option with that name already exists in that group, or no name is specified."u8 : !newModAvailable - ? "Create a new option inside this mod containing only the swap." - : "Create a new option (and possibly Multi-Group) inside the currently selected mod containing the swap."; - if (ImGuiUtil.DrawDisabledButton("Create New Option", new Vector2(width / 2, 0), tt, !newModAvailable || !_subModValid)) + ? "Create a new option inside this mod containing only the swap."u8 + : "Create a new option (and possibly Multi-Group) inside the currently selected mod containing the swap."u8; + if (ImEx.Button("Create New Option"u8, new Vector2(width / 2, 0), tt, !newModAvailable || !_subModValid)) CreateOption(); Im.Line.Same(); - 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" - + "instead of using only the selected mod with its current settings in the Selected collection or the default settings, ignoring the enabled state and inheritance."); + Im.Cursor.X += 20 * Im.Style.GlobalScale; + _dirty |= Im.Checkbox("Use Entire Collection"u8, ref _useCurrentCollection); + Im.Tooltip.OnHover("Use all applied mods from the Selected Collection with their current settings and respecting the enabled state of mods and inheritance,\n"u8 + + "instead of using only the selected mod with its current settings in the Selected collection or the default settings, ignoring the enabled state and inheritance."u8); } private void DrawSwapBar() { - using var bar = ImRaii.TabBar("##swapBar", ImGuiTabBarFlags.None); + using var bar = Im.TabBar.Begin("##swapBar"u8); DrawEquipmentSwap(SwapType.Hat); DrawEquipmentSwap(SwapType.Top); @@ -486,9 +500,9 @@ public class ItemSwapTab : IDisposable, ITab //DrawWeaponSwap(); } - private ImRaii.IEndObject DrawTab(SwapType newTab) + private Im.TabItemDisposable DrawTab(SwapType newTab) { - var tab = ImRaii.TabItem(newTab is SwapType.BetweenSlots ? "Between Slots" : newTab.ToString()); + var tab = Im.TabBar.BeginItem(newTab.ToNameU8()); if (tab) { _dirty |= _lastTab != newTab; @@ -510,18 +524,16 @@ public class ItemSwapTab : IDisposable, ITab table.SetupColumn("##text"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("and put them on these"u8).X); var (article1, article2, selector) = GetAccessorySelector(_slotFrom, true); - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text($"Take {article1}"); + table.DrawFrameColumn($"Take {article1}"); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(100 * Im.Style.GlobalScale); - using (var combo = ImRaii.Combo("##fromType", ToName(_slotFrom))) + table.NextColumn(); + Im.Item.SetNextWidthScaled(100); + using (var combo = Im.Combo.Begin("##fromType"u8, _slotFrom.ToNameU8())) { if (combo) foreach (var slot in Enum.GetValues()) { - if (!ImGui.Selectable(ToName(slot), slot == _slotFrom) || slot == _slotFrom) + if (!Im.Selectable(slot.ToNameU8(), slot == _slotFrom) || slot == _slotFrom) continue; _dirty = true; @@ -531,24 +543,22 @@ public class ItemSwapTab : IDisposable, ITab } } - ImGui.TableNextColumn(); + table.NextColumn(); _dirty |= selector.Draw("##itemSource", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * Im.Style.GlobalScale, Im.Style.TextHeightWithSpacing); (article1, _, selector) = GetAccessorySelector(_slotTo, false); - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text($"and put {article2} on {article1}"); + table.DrawFrameColumn($"and put {article2} on {article1}"); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(100 * Im.Style.GlobalScale); - using (var combo = ImRaii.Combo("##toType", ToName(_slotTo))) + table.NextColumn(); + Im.Item.SetNextWidthScaled(100); + using (var combo = Im.Combo.Begin("##toType"u8, _slotTo.ToNameU8())) { if (combo) foreach (var slot in AvailableToTypes.Where(t => t != _slotFrom)) { - if (!ImGui.Selectable(ToName(slot), slot == _slotTo) || slot == _slotTo) + if (!Im.Selectable(slot.ToNameU8(), slot == _slotTo) || slot == _slotTo) continue; _dirty = true; @@ -556,36 +566,37 @@ public class ItemSwapTab : IDisposable, ITab } } - ImGui.TableNextColumn(); - + table.NextColumn(); _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; Im.Line.Same(); - ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Count - 1} other Items.", Vector2.Zero, - new Rgba32(Colors.PressEnterWarningBg).Color); + ImEx.TextFramed($"which will also affect {_affectedItems.Count - 1} other Items.", Vector2.Zero, Colors.PressEnterWarningBg); if (Im.Item.Hovered()) - ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, selector.CurrentSelection.Item.Name)) - .Select(i => i.Name))); + { + using var tt = Im.Tooltip.Begin(); + foreach (var item in _affectedItems.Where(i => !ReferenceEquals(i.Name, selector.CurrentSelection.Item.Name))) + Im.Text(item.Name); + } } - private (string, string, ItemSelector) GetAccessorySelector(BetweenSlotTypes slot, bool source) + private RefTuple, ReadOnlySpan, ItemSelector> GetAccessorySelector(BetweenSlotTypes slot, bool source) { var (type, article1, article2) = slot switch { - BetweenSlotTypes.Hat => (SwapType.Hat, "this", "it"), - BetweenSlotTypes.Earrings => (SwapType.Earrings, "these", "them"), - BetweenSlotTypes.Necklace => (SwapType.Necklace, "this", "it"), - BetweenSlotTypes.Bracelets => (SwapType.Bracelet, "these", "them"), - BetweenSlotTypes.RightRing => (SwapType.Ring, "this", "it"), - BetweenSlotTypes.LeftRing => (SwapType.Ring, "this", "it"), - BetweenSlotTypes.Glasses => (SwapType.Glasses, "these", "them"), - _ => (SwapType.Ring, "this", "it"), + BetweenSlotTypes.Hat => RefTuple.Create(SwapType.Hat, "this"u8, "it"u8), + BetweenSlotTypes.Earrings => RefTuple.Create(SwapType.Earrings, "these"u8, "them"u8), + BetweenSlotTypes.Necklace => RefTuple.Create(SwapType.Necklace, "this"u8, "it"u8), + BetweenSlotTypes.Bracelets => RefTuple.Create(SwapType.Bracelet, "these"u8, "them"u8), + BetweenSlotTypes.RightRing => RefTuple.Create(SwapType.Ring, "this"u8, "it"u8), + BetweenSlotTypes.LeftRing => RefTuple.Create(SwapType.Ring, "this"u8, "it"u8), + BetweenSlotTypes.Glasses => RefTuple.Create(SwapType.Glasses, "these"u8, "them"u8), + _ => RefTuple.Create(SwapType.Ring, "this"u8, "it"u8), }; var (itemSelector, target, _, _) = _selectors[type]; - return (article1, article2, source ? itemSelector : target); + return RefTuple.Create(article1, article2, source ? itemSelector : target); } private void DrawEquipmentSwap(SwapType type) @@ -596,40 +607,41 @@ public class ItemSwapTab : IDisposable, ITab var (sourceSelector, targetSelector, text1, text2) = _selectors[type]; using var table = Im.Table.Begin("##settings"u8, 2, TableFlags.SizingFixedFit); - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text(text1); - ImGui.TableNextColumn(); - _dirty |= sourceSelector.Draw("##itemSource", sourceSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * Im.Style.GlobalScale, - Im.Style.TextHeightWithSpacing); + if (!table) + return; + table.DrawFrameColumn(text1); + table.NextColumn(); + _dirty |= sourceSelector.Draw("##itemSource", sourceSelector.CurrentSelection.Item.Name, string.Empty, + InputWidth * 2 * Im.Style.GlobalScale, Im.Style.TextHeightWithSpacing); - if (type == SwapType.Ring) + if (type is SwapType.Ring) { Im.Line.Same(); - _dirty |= ImGui.Checkbox("Swap Right Ring", ref _useRightRing); + _dirty |= Im.Checkbox("Swap Right Ring"u8, ref _useRightRing); } - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text(text2); - ImGui.TableNextColumn(); - _dirty |= targetSelector.Draw("##itemTarget", targetSelector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * Im.Style.GlobalScale, + table.DrawFrameColumn(text2); + table.NextColumn(); + _dirty |= targetSelector.Draw("##itemTarget", targetSelector.CurrentSelection.Item.Name, string.Empty, + InputWidth * 2 * Im.Style.GlobalScale, Im.Style.TextHeightWithSpacing); - if (type == SwapType.Ring) + if (type is SwapType.Ring) { Im.Line.Same(); - _dirty |= ImGui.Checkbox("Swap Left Ring", ref _useLeftRing); + _dirty |= Im.Checkbox("Swap Left Ring"u8, ref _useLeftRing); } if (_affectedItems is not { Count: > 1 }) return; Im.Line.Same(); - ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Count - 1} other Items.", Vector2.Zero, - new Rgba32(Colors.PressEnterWarningBg).Color); + ImEx.TextFramed($"which will also affect {_affectedItems.Count - 1} other Items.", Vector2.Zero, Colors.PressEnterWarningBg); if (Im.Item.Hovered()) - ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, targetSelector.CurrentSelection.Item.Name)) - .Select(i => i.Name))); + { + using var tt = Im.Tooltip.Begin(); + foreach (var item in _affectedItems.Where(i => !ReferenceEquals(i.Name, targetSelector.CurrentSelection.Item.Name))) + Im.Text(item.Name); + } } private void DrawHairSwap() @@ -639,9 +651,9 @@ public class ItemSwapTab : IDisposable, ITab return; using var table = Im.Table.Begin("##settings"u8, 2, TableFlags.SizingFixedFit); - DrawTargetIdInput("Take this Hairstyle"); - DrawSourceIdInput(); - DrawGenderInput(); + DrawTargetIdInput(table, "Take this Hairstyle"u8); + DrawSourceIdInput(table, "and put it on this one"u8); + DrawGenderInput(table, "for all"u8); } private void DrawTailSwap() @@ -651,9 +663,9 @@ public class ItemSwapTab : IDisposable, ITab return; using var table = Im.Table.Begin("##settings"u8, 2, TableFlags.SizingFixedFit); - DrawTargetIdInput("Take this Tail Type"); - DrawSourceIdInput(); - DrawGenderInput("for all", 2); + DrawTargetIdInput(table, "Take this Tail Type"u8); + DrawSourceIdInput(table, "and put it on this one"u8); + DrawGenderInput(table, "for all"u8, 2); } @@ -664,55 +676,48 @@ public class ItemSwapTab : IDisposable, ITab return; using var table = Im.Table.Begin("##settings"u8, 2, TableFlags.SizingFixedFit); - DrawTargetIdInput("Take this Ear Type"); - DrawSourceIdInput(); - DrawGenderInput("for all Viera", 0); + DrawTargetIdInput(table, "Take this Ear Type"u8); + DrawSourceIdInput(table, "and put it on this one"u8); + DrawGenderInput(table, "for all Viera"u8, 0); } private const float InputWidth = 120; - private void DrawTargetIdInput(string text = "Take this ID") + private void DrawTargetIdInput(in Im.TableDisposable table, ReadOnlySpan text) { - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text(text); - - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(InputWidth * Im.Style.GlobalScale); - if (ImGui.InputInt("##targetId", ref _targetId)) + table.DrawFrameColumn(text); + table.NextColumn(); + Im.Item.SetNextWidthScaled(InputWidth); + if (Im.Input.Scalar("##targetId"u8, ref _targetId)) _targetId = Math.Clamp(_targetId, 0, byte.MaxValue); - _dirty |= ImGui.IsItemDeactivatedAfterEdit(); + _dirty |= Im.Item.DeactivatedAfterEdit; } - private void DrawSourceIdInput(string text = "and put it on this one") + private void DrawSourceIdInput(in Im.TableDisposable table, ReadOnlySpan text) { - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text(text); + table.DrawFrameColumn(text); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(InputWidth * Im.Style.GlobalScale); - if (ImGui.InputInt("##sourceId", ref _sourceId)) + table.NextColumn(); + Im.Item.SetNextWidthScaled(InputWidth); + if (Im.Input.Scalar("##sourceId"u8, ref _sourceId)) _sourceId = Math.Clamp(_sourceId, 0, byte.MaxValue); - _dirty |= ImGui.IsItemDeactivatedAfterEdit(); + _dirty |= Im.Item.DeactivatedAfterEdit; } - private void DrawGenderInput(string text = "for all", int drawRace = 1) + private void DrawGenderInput(in Im.TableDisposable table, ReadOnlySpan text, int drawRace = 1) { - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text(text); + table.DrawFrameColumn(text); - ImGui.TableNextColumn(); - _dirty |= Combos.Gender("##Gender", _currentGender, out _currentGender); - if (drawRace == 1) + table.NextColumn(); + _dirty |= Combos.Combos.Gender("##Gender", _currentGender, out _currentGender); + if (drawRace is 1) { Im.Line.Same(); - _dirty |= Combos.Race("##Race", _currentRace, out _currentRace, InputWidth); + _dirty |= Combos.Combos.Race("##Race", _currentRace, out _currentRace, InputWidth); } - else if (drawRace == 2) + else if (drawRace is 2) { Im.Line.Same(); if (_currentRace is not ModelRace.Miqote and not ModelRace.AuRa and not ModelRace.Hrothgar) @@ -750,8 +755,8 @@ public class ItemSwapTab : IDisposable, ITab private static void DrawSwap(Swap swap) { - var flags = swap.ChildSwaps.Count is 0 ? ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf : ImGuiTreeNodeFlags.DefaultOpen; - using var tree = ImRaii.TreeNode(SwapToString(swap), flags); + var flags = swap.ChildSwaps.Count is 0 ? TreeNodeFlags.Bullet | TreeNodeFlags.Leaf : TreeNodeFlags.DefaultOpen; + using var tree = Im.Tree.Node(SwapToString(swap), flags); if (!tree) return; @@ -781,7 +786,7 @@ public class ItemSwapTab : IDisposable, ITab private void OnInheritanceChange(in CollectionInheritanceChanged.Arguments arguments) { - if (arguments.Collection != _collectionManager.Active.Current || _mod == null) + if (arguments.Collection != _collectionManager.Active.Current || _mod is null) return; UpdateMod(_mod, arguments.Collection.GetInheritedSettings(_mod.Index).Settings); @@ -800,17 +805,6 @@ public class ItemSwapTab : IDisposable, ITab _dirty = true; } - private enum BetweenSlotTypes - { - Hat, - Earrings, - Necklace, - Bracelets, - RightRing, - LeftRing, - Glasses, - } - private static EquipSlot ToEquipSlot(BetweenSlotTypes type) => type switch { @@ -824,19 +818,6 @@ public class ItemSwapTab : IDisposable, ITab _ => EquipSlot.Unknown, }; - private static string ToName(BetweenSlotTypes type) - => type switch - { - BetweenSlotTypes.Hat => "Hat", - BetweenSlotTypes.Earrings => "Earrings", - BetweenSlotTypes.Necklace => "Necklace", - BetweenSlotTypes.Bracelets => "Bracelets", - BetweenSlotTypes.RightRing => "Right Ring", - BetweenSlotTypes.LeftRing => "Left Ring", - BetweenSlotTypes.Glasses => "Glasses", - _ => "Unknown", - }; - private static readonly IReadOnlyList AvailableToTypes = Enum.GetValues().Where(s => s is not BetweenSlotTypes.Hat).ToArray(); } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs index 600ce44f..80f8b7f7 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs @@ -1,12 +1,9 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using ImSharp; -using Penumbra.GameData.Files.MaterialStructs; +using Luna; using Penumbra.GameData.Files; -using OtterGui.Text; +using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Structs; -using OtterGui.Raii; -using OtterGui.Text.Widget; namespace Penumbra.UI.AdvancedWindow.Materials; @@ -16,8 +13,6 @@ public partial class MtrlTab private static readonly float HalfMaxValue = (float)Half.MaxValue; private static readonly float HalfEpsilon = (float)Half.Epsilon; - private static readonly FontAwesomeCheckbox ApplyStainCheckbox = new(FontAwesomeIcon.FillDrip); - private static (Vector2 Scale, float Rotation, float Shear)? _pinnedTileTransform; private bool DrawColorTableSection(bool disabled) @@ -35,15 +30,15 @@ public partial class MtrlTab if (!disabled) { Im.Line.Same(); - ImUtf8.IconDummy(); + Im.FrameDummy(); Im.Line.Same(); ret |= ColorTableDyeableCheckbox(); } - if (Mtrl.DyeTable != null) + if (Mtrl.DyeTable is not null) { Im.Line.Same(); - ImUtf8.IconDummy(); + Im.FrameDummy(); Im.Line.Same(); ret |= DrawPreviewDye(disabled); } @@ -65,7 +60,7 @@ public partial class MtrlTab if (Mtrl.Table == null) return; - if (!ImUtf8.Button("Export All Rows to Clipboard"u8, ImEx.ScaledVector(200, 0))) + if (!Im.Button("Export All Rows to Clipboard"u8, ImEx.ScaledVector(200, 0))) return; try @@ -78,7 +73,7 @@ public partial class MtrlTab data2.TryCopyTo(array.AsSpan(data1.Length)); var text = Convert.ToBase64String(array); - ImGui.SetClipboardText(text); + Im.Clipboard.Set(text); } catch { @@ -93,7 +88,7 @@ public partial class MtrlTab var tt = dyeId1 is 0 && dyeId2 is 0 ? "Select a preview dye first."u8 : "Apply all preview values corresponding to the dye template and chosen dye where dyeing is enabled."u8; - if (ImUtf8.ButtonEx("Apply Preview Dye"u8, tt, disabled: disabled || dyeId1 == 0 && dyeId2 == 0)) + if (ImEx.Button("Apply Preview Dye"u8, default, tt, disabled || dyeId1 is 0 && dyeId2 is 0)) { var ret = false; if (Mtrl.DyeTable != null) @@ -108,11 +103,11 @@ public partial class MtrlTab } Im.Line.Same(); - var label = dyeId1 == 0 ? "Preview Dye 1###previewDye1" : $"{name1} (Preview 1)###previewDye1"; + var label = dyeId1 is 0 ? "Preview Dye 1###previewDye1" : $"{name1} (Preview 1)###previewDye1"; if (_stainService.StainCombo1.Draw(label, dyeColor1, string.Empty, true, gloss1)) UpdateColorTablePreview(); Im.Line.Same(); - label = dyeId2 == 0 ? "Preview Dye 2###previewDye2" : $"{name2} (Preview 2)###previewDye2"; + label = dyeId2 is 0 ? "Preview Dye 2###previewDye2" : $"{name2} (Preview 2)###previewDye2"; if (_stainService.StainCombo2.Draw(label, dyeColor2, string.Empty, true, gloss2)) UpdateColorTablePreview(); return false; @@ -120,15 +115,15 @@ public partial class MtrlTab private bool ColorTablePasteAllClipboardButton(bool disabled) { - if (Mtrl.Table == null) + if (Mtrl.Table is null) return false; - if (!ImUtf8.ButtonEx("Import All Rows from Clipboard"u8, ImEx.ScaledVector(200, 0), disabled)) + if (!ImEx.Button("Import All Rows from Clipboard"u8, ImEx.ScaledVector(200, 0), disabled)) return false; try { - var text = ImGui.GetClipboardText(); + var text = Im.Clipboard.GetUtf16(); var data = Convert.FromBase64String(text); var table = Mtrl.Table.AsBytes(); var dyeTable = Mtrl.DyeTable != null ? Mtrl.DyeTable.AsBytes() : []; @@ -154,21 +149,20 @@ public partial class MtrlTab if (Mtrl.Table == null) return; - if (!ImUtf8.IconButton(FontAwesomeIcon.Clipboard, "Export this row to your clipboard."u8, - Im.Style.FrameHeight * Vector2.One)) + if (!ImEx.Icon.Button(LunaStyle.ToClipboardIcon, "Export this row to your clipboard."u8)) return; try { var data1 = Mtrl.Table.RowAsBytes(rowIdx); - var data2 = Mtrl.DyeTable != null ? Mtrl.DyeTable.RowAsBytes(rowIdx) : []; + var data2 = Mtrl.DyeTable is not null ? Mtrl.DyeTable.RowAsBytes(rowIdx) : []; var array = new byte[data1.Length + data2.Length]; data1.TryCopyTo(array); data2.TryCopyTo(array.AsSpan(data1.Length)); var text = Convert.ToBase64String(array); - ImGui.SetClipboardText(text); + Im.Clipboard.Set(text); } catch { @@ -178,8 +172,8 @@ public partial class MtrlTab private bool ColorTableDyeableCheckbox() { - var dyeable = Mtrl.DyeTable != null; - var ret = ImUtf8.Checkbox("Dyeable"u8, ref dyeable); + var dyeable = Mtrl.DyeTable is not null; + var ret = Im.Checkbox("Dyeable"u8, ref dyeable); if (ret) { @@ -199,18 +193,17 @@ public partial class MtrlTab private bool ColorTablePasteFromClipboardButton(int rowIdx, bool disabled) { - if (Mtrl.Table == null) + if (Mtrl.Table is null) return false; - if (ImUtf8.IconButton(FontAwesomeIcon.Paste, - "Import an exported row from your clipboard onto this row.\n\nRight-Click for more options."u8, - Im.Style.FrameHeight * Vector2.One, disabled)) + if (ImEx.Icon.Button(LunaStyle.FromClipboardIcon, + "Import an exported row from your clipboard onto this row.\n\nRight-Click for more options."u8, disabled)) try { - var text = ImGui.GetClipboardText(); + var text = Im.Clipboard.GetUtf16(); var data = Convert.FromBase64String(text); var row = Mtrl.Table.RowAsBytes(rowIdx); - var dyeRow = Mtrl.DyeTable != null ? Mtrl.DyeTable.RowAsBytes(rowIdx) : []; + var dyeRow = Mtrl.DyeTable is not null ? Mtrl.DyeTable.RowAsBytes(rowIdx) : []; if (data.Length != row.Length && data.Length != row.Length + dyeRow.Length) return false; @@ -232,23 +225,23 @@ public partial class MtrlTab private unsafe bool ColorTablePasteFromClipboardContext(int rowIdx, bool disabled) { if (!disabled && Im.Item.RightClicked()) - ImUtf8.OpenPopup("context"u8); + Im.Popup.Open("context"u8); - using var context = ImUtf8.Popup("context"u8); + using var context = Im.Popup.Begin("context"u8); if (!context) return false; - using var _ = ImRaii.Disabled(disabled); + using var _ = Im.Disabled(disabled); IColorTable.ValueTypes copy = 0; IColorDyeTable.ValueTypes dyeCopy = 0; - if (ImUtf8.Selectable("Import Colors Only"u8)) + if (Im.Selectable("Import Colors Only"u8)) { copy = IColorTable.ValueTypes.Colors; dyeCopy = IColorDyeTable.ValueTypes.Colors; } - if (ImUtf8.Selectable("Import Other Values Only"u8)) + if (Im.Selectable("Import Other Values Only"u8)) { copy = ~IColorTable.ValueTypes.Colors; dyeCopy = ~IColorDyeTable.ValueTypes.Colors; @@ -259,7 +252,7 @@ public partial class MtrlTab try { - var text = ImGui.GetClipboardText(); + var text = Im.Clipboard.GetUtf16(); var data = Convert.FromBase64String(text); var row = Mtrl.Table!.RowAsHalves(rowIdx); var halves = new Span(Unsafe.AsPointer(ref data[0]), row.Length); @@ -280,9 +273,9 @@ public partial class MtrlTab private void ColorTablePairHighlightButton(int pairIdx, bool disabled) { - ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, + ImEx.Icon.Button(LunaStyle.OnHoverIcon, "Highlight this pair of rows on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8, - Im.Style.FrameHeight * Vector2.One, disabled || _colorTablePreviewers.Count == 0); + disabled || _colorTablePreviewers.Count is 0); if (Im.Item.Hovered()) HighlightColorTablePair(pairIdx); @@ -292,9 +285,9 @@ public partial class MtrlTab private void ColorTableRowHighlightButton(int rowIdx, bool disabled) { - ImUtf8.IconButton(FontAwesomeIcon.Crosshairs, + ImEx.Icon.Button(LunaStyle.OnHoverIcon, "Highlight this row on your character, if possible.\n\nHighlight colors can be configured in Penumbra's settings."u8, - Im.Style.FrameHeight * Vector2.One, disabled || _colorTablePreviewers.Count == 0); + disabled || _colorTablePreviewers.Count is 0); if (Im.Item.Hovered()) HighlightColorTableRow(rowIdx); @@ -335,24 +328,24 @@ public partial class MtrlTab var ret = false; var inputSqrt = PseudoSqrtRgb((Vector3)current); var tmp = inputSqrt; - if (ImUtf8.ColorEdit(label, ref tmp, - ImGuiColorEditFlags.NoInputs - | ImGuiColorEditFlags.DisplayRgb - | ImGuiColorEditFlags.InputRgb - | ImGuiColorEditFlags.NoTooltip - | ImGuiColorEditFlags.Hdr) + if (Im.Color.Editor(label, ref tmp, + ColorEditorFlags.NoInputs + | ColorEditorFlags.DisplayRgb + | ColorEditorFlags.InputRgb + | ColorEditorFlags.NoTooltip + | ColorEditorFlags.Hdr) && tmp != inputSqrt) { setter((HalfColor)PseudoSquareRgb(tmp)); ret = true; } - if (letter.Length > 0 && ImGui.IsItemVisible()) + if (letter.Length > 0 && Im.Item.Visible) { - var textSize = ImUtf8.CalcTextSize(letter); - var center = ImGui.GetItemRectMin() + (ImGui.GetItemRectSize() - textSize) / 2; + var textSize = Im.Font.CalculateSize(letter); + var center = Im.Item.UpperLeftCorner + (Im.Item.Size - textSize) / 2; var textColor = inputSqrt.LengthSquared() < 0.25f ? 0x80FFFFFFu : 0x80000000u; - ImGui.GetWindowDrawList().AddText(letter, center, textColor); + Im.Window.DrawList.Text(center, textColor, letter); } Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); @@ -370,19 +363,19 @@ public partial class MtrlTab else { var tmp = Vector4.Zero; - ImUtf8.ColorEdit(label, ref tmp, - ImGuiColorEditFlags.NoInputs - | ImGuiColorEditFlags.DisplayRgb - | ImGuiColorEditFlags.InputRgb - | ImGuiColorEditFlags.NoTooltip - | ImGuiColorEditFlags.Hdr - | ImGuiColorEditFlags.AlphaPreview); + Im.Color.Editor(label, ref tmp, + ColorEditorFlags.NoInputs + | ColorEditorFlags.DisplayRgb + | ColorEditorFlags.InputRgb + | ColorEditorFlags.NoTooltip + | ColorEditorFlags.Hdr + | ColorEditorFlags.AlphaPreview); - if (letter.Length > 0 && ImGui.IsItemVisible()) + if (letter.Length > 0 && Im.Item.Visible) { - var textSize = ImUtf8.CalcTextSize(letter); - var center = ImGui.GetItemRectMin() + (ImGui.GetItemRectSize() - textSize) / 2; - ImGui.GetWindowDrawList().AddText(letter, center, 0x80000000u); + var textSize = Im.Font.CalculateSize(letter); + var center = Im.Item.UpperLeftCorner + (Im.Item.Size - textSize) / 2; + Im.Window.DrawList.Text(center, 0x80000000u, letter); } Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); @@ -392,7 +385,7 @@ public partial class MtrlTab private static bool CtApplyStainCheckbox(ReadOnlySpan label, ReadOnlySpan description, bool current, Action setter) { var tmp = current; - var result = ApplyStainCheckbox.Draw(label, ref tmp); + var result = ImEx.IconCheckbox(label, FontAwesomeIcon.FillDrip.Icon(), ref tmp); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); if (!result || tmp == current) return false; @@ -405,7 +398,7 @@ public partial class MtrlTab float max, float speed, Action setter) { var tmp = (float)value; - var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed); + var result = Im.Drag(label, ref tmp, format, min, max, speed); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); if (!result) return false; @@ -422,7 +415,7 @@ public partial class MtrlTab float min, float max, float speed) { var tmp = (float)value; - var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed); + var result = Im.Drag(label, ref tmp, format, min, max, speed); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); if (!result) return false; @@ -437,7 +430,7 @@ public partial class MtrlTab private static void CtDragHalf(ReadOnlySpan label, ReadOnlySpan description, Half? value, ReadOnlySpan format) { - using var _ = ImRaii.Disabled(); + using var _ = Im.Disabled(); var valueOrDefault = value ?? Half.Zero; var floatValue = (float)valueOrDefault; CtDragHalf(label, description, valueOrDefault, value.HasValue ? format : "-"u8, floatValue, floatValue, 0.0f, Nop); @@ -447,7 +440,7 @@ public partial class MtrlTab T max, float speed, Action setter) where T : unmanaged, INumber { var tmp = value; - var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed); + var result = Im.Drag(label, ref tmp, format, min, max, speed); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); if (!result || tmp == value) return false; @@ -460,7 +453,7 @@ public partial class MtrlTab T max, float speed) where T : unmanaged, INumber { var tmp = value; - var result = ImUtf8.DragScalar(label, ref tmp, format, min, max, speed); + var result = Im.Drag(label, ref tmp, format, min, max, speed); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, description); if (!result || tmp == value) return false; @@ -472,7 +465,7 @@ public partial class MtrlTab private static void CtDragScalar(ReadOnlySpan label, ReadOnlySpan description, T? value, ReadOnlySpan format) where T : unmanaged, INumber { - using var _ = ImRaii.Disabled(); + using var _ = Im.Disabled(); var valueOrDefault = value ?? T.Zero; CtDragScalar(label, description, valueOrDefault, value.HasValue ? format : "-"u8, valueOrDefault, valueOrDefault, 0.0f, Nop); } @@ -526,24 +519,24 @@ public partial class MtrlTab shear *= 180.0f / MathF.PI; Im.Item.SetNextWidth(floatSize); var scaleXChanged = CtDragScalar("##TileScaleU"u8, "Tile Scale U"u8, ref scale.X, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f); - var activated = ImGui.IsItemActivated(); - var deactivated = ImGui.IsItemDeactivated(); + var activated = Im.Item.Activated; + var deactivated = Im.Item.Deactivated; Im.Line.SameInner(); Im.Item.SetNextWidth(floatSize); var scaleYChanged = CtDragScalar("##TileScaleV"u8, "Tile Scale V"u8, ref scale.Y, "%.2f"u8, HalfMinValue, HalfMaxValue, 0.1f); - activated |= ImGui.IsItemActivated(); - deactivated |= ImGui.IsItemDeactivated(); + activated |= Im.Item.Activated; + deactivated |= Im.Item.Deactivated; if (!twoRowLayout) Im.Line.SameInner(); Im.Item.SetNextWidth(floatSize); var rotationChanged = CtDragScalar("##TileRotation"u8, "Tile Rotation"u8, ref rotation, "%.0f°"u8, -180.0f, 180.0f, 1.0f); - activated |= ImGui.IsItemActivated(); - deactivated |= ImGui.IsItemDeactivated(); + activated |= Im.Item.Activated; + deactivated |= Im.Item.Deactivated; Im.Line.SameInner(); Im.Item.SetNextWidth(floatSize); var shearChanged = CtDragScalar("##TileShear"u8, "Tile Shear"u8, ref shear, "%.0f°"u8, -90.0f, 90.0f, 1.0f); - activated |= ImGui.IsItemActivated(); - deactivated |= ImGui.IsItemDeactivated(); + activated |= Im.Item.Activated; + deactivated |= Im.Item.Deactivated; if (deactivated) _pinnedTileTransform = null; else if (activated) diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs index c49068f6..b6297a45 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs @@ -1,10 +1,5 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; using OtterGui.Text.Widget.Editors; using Penumbra.GameData.Files.ShaderStructs; using static Penumbra.GameData.Files.ShpkFile; @@ -150,19 +145,18 @@ public partial class MtrlTab private bool DrawConstantsSection(bool disabled) { - if (Constants.Count == 0) + if (Constants.Count is 0) return false; - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); - if (!ImGui.CollapsingHeader("Material Constants")) + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); + using var tree = Im.Tree.HeaderId("Material Constants"u8); + if (!tree) return false; - using var _ = ImRaii.PushId("MaterialConstants"); - var ret = false; foreach (var (header, group) in Constants) { - using var t = ImRaii.TreeNode(header, ImGuiTreeNodeFlags.DefaultOpen); + using var t = Im.Tree.Node(header, TreeNodeFlags.DefaultOpen); if (!t) continue; @@ -172,8 +166,8 @@ public partial class MtrlTab var buffer = Mtrl.GetConstantValue(constant); if (buffer.Length > 0) { - using var id = ImRaii.PushId($"##{constant.Id:X8}:{slice.Start}"); - Im.Item.SetNextWidth(MaterialConstantSize * Im.Style.GlobalScale); + using var id = Im.Id.Push($"##{constant.Id:X8}:{slice.Start}"); + Im.Item.SetNextWidthScaled(MaterialConstantSize); if (editor.Draw(buffer[slice], disabled)) { ret = true; @@ -187,8 +181,7 @@ public partial class MtrlTab ? defaultValue.Length > 0 && !defaultValue.SequenceEqual(buffer[slice]) : buffer[slice].ContainsAnyExcept((byte)0); Im.Line.SameInner(); - 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)) + if (ImEx.Icon.Button(LunaStyle.RefreshIcon, "Reset this constant to its default value.\n\nHold Ctrl to unlock."u8, !Im.Io.KeyControl || !canReset)) { ret = true; if (defaultValue.Length > 0) @@ -199,10 +192,10 @@ public partial class MtrlTab SetMaterialParameter(constant.Id, slice.Start, buffer[slice]); } - Im.Line.Same(); - using var font = ImRaii.PushFont(UiBuilder.MonoFont, monoFont); + Im.Line.SameInner(); + using var font = Im.Font.Mono.Push(monoFont); if (description.Length > 0) - ImGuiUtil.LabeledHelpMarker(label, description); + LunaStyle.DrawHelpMarker(label, description); else Im.Text(label); } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs index db758fb9..94a66085 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs @@ -1,9 +1,6 @@ -using Dalamud.Interface; -using Dalamud.Interface.Utility.Raii; using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui; -using OtterGui.Text; +using Luna; using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Files.StainMapStructs; using Penumbra.Services; @@ -25,7 +22,7 @@ public partial class MtrlTab if (!imTable) return false; - DrawLegacyColorTableHeader(dyeTable is not null); + DrawLegacyColorTableHeader(imTable, dyeTable is not null); var ret = false; for (var i = 0; i < LegacyColorTable.NumRows; ++i) @@ -36,7 +33,7 @@ public partial class MtrlTab ret = true; } - ImGui.TableNextRow(); + imTable.NextRow(); } return ret; @@ -49,7 +46,7 @@ public partial class MtrlTab if (!imTable) return false; - DrawLegacyColorTableHeader(dyeTable is not null); + DrawLegacyColorTableHeader(imTable, dyeTable is not null); var ret = false; for (var i = 0; i < ColorTable.NumRows; ++i) @@ -60,62 +57,62 @@ public partial class MtrlTab ret = true; } - ImGui.TableNextRow(); + imTable.NextRow(); } return ret; } - private static void DrawLegacyColorTableHeader(bool hasDyeTable) + private static void DrawLegacyColorTableHeader(in Im.TableDisposable table, bool hasDyeTable) { - ImGui.TableNextColumn(); - ImUtf8.TableHeader(""u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Row"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Diffuse"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Specular"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Emissive"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Gloss"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Tile"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Repeat / Skew"u8); + table.NextColumn(); + table.Header(""u8); + table.NextColumn(); + table.Header("Row"u8); + table.NextColumn(); + table.Header("Diffuse"u8); + table.NextColumn(); + table.Header("Specular"u8); + table.NextColumn(); + table.Header("Emissive"u8); + table.NextColumn(); + table.Header("Gloss"u8); + table.NextColumn(); + table.Header("Tile"u8); + table.NextColumn(); + table.Header("Repeat / Skew"u8); if (hasDyeTable) { - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Dye"u8); - ImGui.TableNextColumn(); - ImUtf8.TableHeader("Dye Preview"u8); + table.NextColumn(); + table.Header("Dye"u8); + table.NextColumn(); + table.Header("Dye Preview"u8); } } private bool DrawLegacyColorTableRow(LegacyColorTable table, LegacyColorDyeTable? dyeTable, int rowIdx, bool disabled) { - using var id = ImRaii.PushId(rowIdx); + using var id = Im.Id.Push(rowIdx); ref var row = ref table[rowIdx]; - var dye = dyeTable != null ? dyeTable[rowIdx] : default; + var dye = dyeTable?[rowIdx] ?? default; var floatSize = LegacyColorTableFloatSize * Im.Style.GlobalScale; var pctSize = LegacyColorTablePercentageSize * Im.Style.GlobalScale; var intSize = LegacyColorTableIntegerSize * Im.Style.GlobalScale; - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ColorTableCopyClipboardButton(rowIdx); Im.Line.SameInner(); var ret = ColorTablePasteFromClipboardButton(rowIdx, disabled); Im.Line.SameInner(); ColorTableRowHighlightButton(rowIdx, disabled); - ImGui.TableNextColumn(); - using (ImRaii.PushFont(UiBuilder.MonoFont)) + Im.Table.NextColumn(); + using (Im.Font.PushMono()) { - ImUtf8.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}"); + Im.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}"); } - ImGui.TableNextColumn(); - using var dis = ImRaii.Disabled(disabled); + Im.Table.NextColumn(); + using var dis = Im.Disabled(disabled); ret |= CtColorPicker("##Diffuse"u8, "Diffuse Color"u8, row.DiffuseColor, c => table[rowIdx].DiffuseColor = c); if (dyeTable != null) @@ -125,10 +122,10 @@ public partial class MtrlTab b => dyeTable[rowIdx].DiffuseColor = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= CtColorPicker("##Specular"u8, "Specular Color"u8, row.SpecularColor, c => table[rowIdx].SpecularColor = c); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeSpecular"u8, "Apply Specular Color on Dye"u8, dye.SpecularColor, @@ -147,7 +144,7 @@ public partial class MtrlTab b => dyeTable[rowIdx].SpecularMask = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= CtColorPicker("##Emissive"u8, "Emissive Color"u8, row.EmissiveColor, c => table[rowIdx].EmissiveColor = c); if (dyeTable != null) @@ -157,32 +154,32 @@ public partial class MtrlTab b => dyeTable[rowIdx].EmissiveColor = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); Im.Item.SetNextWidth(floatSize); - var glossStrengthMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon; + var glossStrengthMin = Im.Io.KeyControl ? 0.0f : HalfEpsilon; ret |= CtDragHalf("##Shininess"u8, "Gloss Strength"u8, row.Shininess, "%.1f"u8, glossStrengthMin, HalfMaxValue, Math.Max(0.1f, (float)row.Shininess * 0.025f), v => table[rowIdx].Shininess = v); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeShininess"u8, "Apply Gloss Strength on Dye"u8, dye.Shininess, b => dyeTable[rowIdx].Shininess = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); Im.Item.SetNextWidth(intSize); ret |= CtTileIndexPicker("##TileIndex"u8, "Tile Index"u8, row.TileIndex, true, value => table[rowIdx].TileIndex = value); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= CtTileTransformMatrix(row.TileTransform, floatSize, false, m => table[rowIdx].TileTransform = m); if (dyeTable != null) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (_stainService.LegacyTemplateCombo.Draw("##dyeTemplate", dye.Template.ToString(), string.Empty, intSize + Im.Style.ScrollbarSize / 2, Im.Style.TextHeightWithSpacing, ImGuiComboFlags.NoArrowButton)) { @@ -192,7 +189,7 @@ public partial class MtrlTab Im.Tooltip.OnHover("Dye Template"u8, HoveredFlags.AllowWhenDisabled); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= DrawLegacyDyePreview(rowIdx, disabled, dye, floatSize); } @@ -201,41 +198,41 @@ public partial class MtrlTab private bool DrawLegacyColorTableRow(ColorTable table, ColorDyeTable? dyeTable, int rowIdx, bool disabled) { - using var id = ImRaii.PushId(rowIdx); + using var id = Im.Id.Push(rowIdx); ref var row = ref table[rowIdx]; var dye = dyeTable?[rowIdx] ?? default; 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(); + Im.Table.NextColumn(); ColorTableCopyClipboardButton(rowIdx); Im.Line.SameInner(); var ret = ColorTablePasteFromClipboardButton(rowIdx, disabled); Im.Line.SameInner(); ColorTableRowHighlightButton(rowIdx, disabled); - ImGui.TableNextColumn(); - using (ImRaii.PushFont(UiBuilder.MonoFont)) + Im.Table.NextColumn(); + using (Im.Font.PushMono()) { - ImUtf8.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}"); + Im.Text($"{(rowIdx >> 1) + 1,2:D}{"AB"[rowIdx & 1]}"); } - ImGui.TableNextColumn(); - using var dis = ImRaii.Disabled(disabled); + Im.Table.NextColumn(); + using var dis = Im.Disabled(disabled); ret |= CtColorPicker("##Diffuse"u8, "Diffuse Color"u8, row.DiffuseColor, c => table[rowIdx].DiffuseColor = c); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeDiffuse"u8, "Apply Diffuse Color on Dye"u8, dye.DiffuseColor, b => dyeTable[rowIdx].DiffuseColor = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= CtColorPicker("##Specular"u8, "Specular Color"u8, row.SpecularColor, c => table[rowIdx].SpecularColor = c); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeSpecular"u8, "Apply Specular Color on Dye"u8, dye.SpecularColor, @@ -246,38 +243,38 @@ public partial class MtrlTab Im.Item.SetNextWidth(pctSize); ret |= CtDragScalar("##SpecularMask"u8, "Specular Strength"u8, (float)row.Scalar7 * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f, v => table[rowIdx].Scalar7 = (Half)(v * 0.01f)); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeSpecularMask"u8, "Apply Specular Strength on Dye"u8, dye.Metalness, b => dyeTable[rowIdx].Metalness = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= CtColorPicker("##Emissive"u8, "Emissive Color"u8, row.EmissiveColor, c => table[rowIdx].EmissiveColor = c); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeEmissive"u8, "Apply Emissive Color on Dye"u8, dye.EmissiveColor, b => dyeTable[rowIdx].EmissiveColor = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); Im.Item.SetNextWidth(floatSize); - var glossStrengthMin = ImGui.GetIO().KeyCtrl ? 0.0f : HalfEpsilon; + var glossStrengthMin = Im.Io.KeyControl ? 0.0f : HalfEpsilon; ret |= CtDragHalf("##Shininess"u8, "Gloss Strength"u8, row.Scalar3, "%.1f"u8, glossStrengthMin, HalfMaxValue, Math.Max(0.1f, (float)row.Scalar3 * 0.025f), v => table[rowIdx].Scalar3 = v); - if (dyeTable != null) + if (dyeTable is not null) { Im.Line.SameInner(); ret |= CtApplyStainCheckbox("##dyeShininess"u8, "Apply Gloss Strength on Dye"u8, dye.Scalar3, b => dyeTable[rowIdx].Scalar3 = b); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); Im.Item.SetNextWidth(intSize); ret |= CtTileIndexPicker("##TileIndex"u8, "Tile Index"u8, row.TileIndex, true, value => table[rowIdx].TileIndex = value); @@ -286,13 +283,13 @@ public partial class MtrlTab ret |= CtDragScalar("##TileAlpha"u8, "Tile Opacity"u8, (float)row.TileAlpha * 100.0f, "%.0f%%"u8, 0f, HalfMaxValue * 100.0f, 1.0f, v => table[rowIdx].TileAlpha = (Half)(v * 0.01f)); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= CtTileTransformMatrix(row.TileTransform, floatSize, false, m => table[rowIdx].TileTransform = m); - if (dyeTable != null) + if (dyeTable is not null) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); Im.Item.SetNextWidth(byteSize); ret |= CtDragScalar("##DyeChannel"u8, "Dye Channel"u8, dye.Channel + 1, "%hhd"u8, 1, StainService.ChannelCount, 0.25f, value => dyeTable[rowIdx].Channel = (byte)(Math.Clamp(value, 1, StainService.ChannelCount) - 1)); @@ -307,7 +304,7 @@ public partial class MtrlTab Im.Tooltip.OnHover("Dye Template"u8, HoveredFlags.AllowWhenDisabled); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); ret |= DrawLegacyDyePreview(rowIdx, disabled, dye, floatSize); } @@ -322,8 +319,7 @@ public partial class MtrlTab using var style = ImStyleDouble.ItemSpacing.Push(Im.Style.ItemSpacing / 2); - var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(Im.Style.FrameHeight), - "Apply the selected dye to this row.", disabled, true); + var ret = ImEx.Icon.Button(LunaStyle.DyeIcon, "Apply the selected dye to this row."u8, disabled); ret = ret && Mtrl.ApplyDyeToRow(_stainService.LegacyStmFile, [stain], rowIdx); @@ -341,8 +337,7 @@ public partial class MtrlTab using var style = ImStyleDouble.ItemSpacing.Push(Im.Style.ItemSpacing / 2); - var ret = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.PaintBrush.ToIconString(), new Vector2(Im.Style.FrameHeight), - "Apply the selected dye to this row.", disabled, true); + var ret = ImEx.Icon.Button(LunaStyle.DyeIcon, "Apply the selected dye to this row."u8, disabled); ret = ret && Mtrl.ApplyDyeToRow(_stainService.LegacyStmFile, [ @@ -364,13 +359,13 @@ public partial class MtrlTab Im.Line.SameInner(); CtColorPicker("##emissivePreview"u8, default, values.EmissiveColor, "E"u8); Im.Line.SameInner(); - using var dis = ImRaii.Disabled(); + using var dis = Im.Disabled(); Im.Item.SetNextWidth(floatSize); var shininess = (float)values.Shininess; - ImGui.DragFloat("##shininessPreview", ref shininess, 0, shininess, shininess, "%.1f G"); + Im.Drag("##shininessPreview"u8, ref shininess, "%.1f G"u8, shininess, shininess, 0f); Im.Line.SameInner(); Im.Item.SetNextWidth(floatSize); var specularMask = (float)values.SpecularMask * 100.0f; - ImGui.DragFloat("##specularMaskPreview", ref specularMask, 0, specularMask, specularMask, "%.0f%% S"); + Im.Drag("##specularMaskPreview"u8, ref specularMask, "%.0f%% S"u8, specularMask, specularMask, 0f); } } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs index 1c0fdf54..84156806 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs @@ -1,7 +1,4 @@ -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Structs; using Penumbra.Interop.Hooks.Objects; @@ -27,7 +24,7 @@ public partial class MtrlTab if (Im.Button("Reload live preview"u8)) BindToMaterialInstances(); - if (_materialPreviewers.Count != 0 || _colorTablePreviewers.Count != 0) + if (_materialPreviewers.Count is not 0 || _colorTablePreviewers.Count is not 0) return; Im.Line.Same(); @@ -62,7 +59,7 @@ public partial class MtrlTab UpdateMaterialPreview(); - if (Mtrl.Table == null) + if (Mtrl.Table is null) return; foreach (var materialInfo in instances) @@ -207,10 +204,10 @@ public partial class MtrlTab private void UpdateColorTableRowPreview(int rowIdx) { - if (_colorTablePreviewers.Count == 0) + if (_colorTablePreviewers.Count is 0) return; - if (Mtrl.Table == null) + if (Mtrl.Table is null) return; var row = Mtrl.Table switch @@ -219,7 +216,7 @@ public partial class MtrlTab ColorTable table => table[rowIdx], _ => throw new InvalidOperationException($"Unsupported color table type {Mtrl.Table.GetType()}"), }; - if (Mtrl.DyeTable != null) + if (Mtrl.DyeTable is not null) { var dyeRow = Mtrl.DyeTable switch { @@ -251,15 +248,15 @@ public partial class MtrlTab private void UpdateColorTablePreview() { - if (_colorTablePreviewers.Count == 0) + if (_colorTablePreviewers.Count is 0) return; - if (Mtrl.Table == null) + if (Mtrl.Table is null) return; var rows = new ColorTable(Mtrl.Table); - var dyeRows = Mtrl.DyeTable != null ? ColorDyeTable.CastOrConvert(Mtrl.DyeTable) : null; - if (dyeRows != null) + var dyeRows = Mtrl.DyeTable is not null ? ColorDyeTable.CastOrConvert(Mtrl.DyeTable) : null; + if (dyeRows is not null) { ReadOnlySpan stainIds = [ diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs index 4e29e739..4985ccf5 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs @@ -1,12 +1,7 @@ -using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; using Newtonsoft.Json.Linq; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.GameData; using Penumbra.GameData.Data; using Penumbra.GameData.Files; @@ -326,7 +321,7 @@ public partial class MtrlTab private bool DrawShaderSection(bool disabled) { var ret = false; - if (ImGui.CollapsingHeader(_shaderHeader)) + if (Im.Tree.Header(_shaderHeader)) { ret |= DrawPackageNameInput(disabled); ret |= DrawShaderFlagsInput(disabled); @@ -335,17 +330,17 @@ public partial class MtrlTab DrawMaterialShaders(); } - if (!_shpkLoading && (_associatedShpk == null || _associatedShpkDevkit == null)) + if (!_shpkLoading && (_associatedShpk is null || _associatedShpkDevkit is null)) { - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.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, - ImGuiUtil.HalfBlendText(0x80u)); // Half red + if (_associatedShpk is null) + Im.Text("Unable to find a suitable shader (.shpk) file for cross-references. Some functionality will be missing."u8, + ImGuiColor.Text.Get().HalfBlend(0x80)); // Half red else - ImUtf8.Text( + Im.Text( "No dev-kit file found for this material's shaders. Please install one for optimal editing experience, such as actual constant names instead of hexadecimal identifiers."u8, - ImGuiUtil.HalfBlendText(0x8080u)); // Half yellow + ImGuiColor.Text.Get().HalfBlend(0x8080u)); // Half yellow } return ret; @@ -360,12 +355,12 @@ public partial class MtrlTab } var ret = false; - Im.Item.SetNextWidth(Im.Style.GlobalScale * 250.0f); - using var c = ImRaii.Combo("Shader Package", Mtrl.ShaderPackage.Name); + Im.Item.SetNextWidthScaled(250.0f); + using var c = Im.Combo.Begin("Shader Package"u8, Mtrl.ShaderPackage.Name); if (c) foreach (var value in GetShpkNames()) { - if (!ImGui.Selectable(value, value == Mtrl.ShaderPackage.Name)) + if (!Im.Selectable(value, value == Mtrl.ShaderPackage.Name)) continue; Mtrl.ShaderPackage.Name = value; @@ -382,9 +377,9 @@ public partial class MtrlTab private bool DrawShaderFlagsInput(bool disabled) { var shpkFlags = (int)Mtrl.ShaderPackage.Flags; - Im.Item.SetNextWidth(Im.Style.GlobalScale * 250.0f); - if (!ImGui.InputInt("Shader Flags", ref shpkFlags, 0, 0, - flags: ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None))) + Im.Item.SetNextWidthScaled(250.0f); + if (!Im.Input.Scalar("Shader Flags"u8, ref shpkFlags, 0, 0, + InputTextFlags.CharsHexadecimal | (disabled ? InputTextFlags.ReadOnly : InputTextFlags.None))) return false; Mtrl.ShaderPackage.Flags = (uint)shpkFlags; @@ -398,24 +393,19 @@ public partial class MtrlTab /// private void DrawCustomAssociations() { - const string tooltip = "Click to copy file path to clipboard."; - var text = _associatedShpk == null - ? "Associated .shpk file: None" - : $"Associated .shpk file: {_loadedShpkPathName}"; - var devkitText = _associatedShpkDevkit == null - ? "Associated dev-kit file: None" - : $"Associated dev-kit file: {_loadedShpkDevkitPathName}"; - var baseDevkitText = _associatedBaseDevkit == null - ? "Base dev-kit file: None" - : $"Base dev-kit file: {_loadedBaseDevkitPathName}"; + var tooltip = "Click to copy file path to clipboard."u8; - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); + ImEx.CopyOnClickSelectable(_associatedShpk is null ? "Associated .shpk file: None" : $"Associated .shpk file: {_loadedShpkPathName}", + _loadedShpkPathName, tooltip); + ImEx.CopyOnClickSelectable( + _associatedShpkDevkit is null ? "Associated dev-kit file: None" : $"Associated dev-kit file: {_loadedShpkDevkitPathName}", + _loadedShpkDevkitPathName, tooltip); + ImEx.CopyOnClickSelectable( + _associatedBaseDevkit is null ? "Base dev-kit file: None" : $"Base dev-kit file: {_loadedBaseDevkitPathName}", + _loadedBaseDevkitPathName, tooltip); - ImUtf8.CopyOnClickSelectable(text, _loadedShpkPathName, tooltip); - ImUtf8.CopyOnClickSelectable(devkitText, _loadedShpkDevkitPathName, tooltip); - ImUtf8.CopyOnClickSelectable(baseDevkitText, _loadedBaseDevkitPathName, tooltip); - - if (ImUtf8.Button("Associate Custom .shpk File"u8)) + if (Im.Button("Associate Custom .shpk File"u8)) _fileDialog.OpenFilePicker("Associate Custom .shpk File...", ".shpk", (success, name) => { if (success) @@ -424,19 +414,17 @@ public partial class MtrlTab var moddedPath = FindAssociatedShpk(out var defaultPath, out var gamePath); Im.Line.Same(); - if (ImUtf8.ButtonEx("Associate Default .shpk File"u8, moddedPath.ToPath(), Vector2.Zero, - moddedPath.Equals(_loadedShpkPath))) + if (ImEx.Button("Associate Default .shpk File"u8, Vector2.Zero, moddedPath.ToPath(), moddedPath.Equals(_loadedShpkPath))) LoadShpk(moddedPath); if (!gamePath.Path.Equals(moddedPath.InternalName)) { Im.Line.Same(); - if (ImUtf8.ButtonEx("Associate Unmodded .shpk File", defaultPath, Vector2.Zero, - gamePath.Path.Equals(_loadedShpkPath.InternalName))) + if (ImEx.Button("Associate Unmodded .shpk File"u8, Vector2.Zero, defaultPath, gamePath.Path.Equals(_loadedShpkPath.InternalName))) LoadShpk(new FullPath(gamePath)); } - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); } private bool DrawMaterialShaderKeys(bool disabled) @@ -447,22 +435,22 @@ public partial class MtrlTab var ret = false; foreach (var (label, index, description, monoFont, values) in _shaderKeys) { - using var font = ImRaii.PushFont(UiBuilder.MonoFont, monoFont); + using var font = Im.Font.Mono.Push(monoFont); ref var key = ref Mtrl.ShaderPackage.ShaderKeys[index]; - using var id = ImUtf8.PushId((int)key.Key); + using var id = Im.Id.Push((int)key.Key); var shpkKey = _associatedShpk?.GetMaterialKeyById(key.Key); var currentValue = key.Value; var (currentLabel, _, currentDescription) = values.FirstOrNull(v => v.Value == currentValue) ?? ($"0x{currentValue:X8}", currentValue, string.Empty); if (!disabled && shpkKey.HasValue) { - Im.Item.SetNextWidth(Im.Style.GlobalScale * 250.0f); - using (var c = ImUtf8.Combo(""u8, currentLabel)) + Im.Item.SetNextWidthScaled(250.0f); + using (var c = Im.Combo.Begin(StringU8.Empty, currentLabel)) { if (c) foreach (var (valueLabel, value, valueDescription) in values) { - if (ImGui.Selectable(valueLabel, value == currentValue)) + if (Im.Selectable(valueLabel, value == currentValue)) { key.Value = value; ret = true; @@ -471,24 +459,24 @@ public partial class MtrlTab } if (valueDescription.Length > 0) - ImGuiUtil.SelectableHelpMarker(valueDescription); + LunaStyle.DrawRightAlignedHelpMarker(valueDescription); } } - Im.Line.Same(); + Im.Line.SameInner(); if (description.Length > 0) - ImGuiUtil.LabeledHelpMarker(label, description); + LunaStyle.DrawHelpMarkerLabel(label, description); else - ImUtf8.Text(label); + Im.Text(label); } else if (description.Length > 0 || currentDescription.Length > 0) { - ImUtf8.LabeledHelpMarker($"{label}: {currentLabel}", + LunaStyle.DrawHelpMarkerLabel($"{label}: {currentLabel}", description + (description.Length > 0 && currentDescription.Length > 0 ? "\n\n" : string.Empty) + currentDescription); } else { - ImUtf8.Text($"{label}: {currentLabel}"); + Im.Text($"{label}: {currentLabel}"); } } @@ -497,19 +485,19 @@ public partial class MtrlTab private void DrawMaterialShaders() { - if (_associatedShpk == null) + if (_associatedShpk is null) return; - using (var node = ImUtf8.TreeNode("Candidate Shaders"u8)) + using (var node = Im.Tree.Node("Candidate Shaders"u8)) { if (node) - ImUtf8.Text(_shadersString.Span); + Im.Text(_shadersString.Span); } if (_shaderComment.Length > 0) { - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); - ImUtf8.Text(_shaderComment); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Text(_shaderComment); } } } diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs index c45f4f32..117e5624 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs @@ -1,9 +1,6 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; +using Luna; using Penumbra.GameData.Files.MaterialStructs; using Penumbra.String.Classes; using static Penumbra.GameData.Files.MaterialStructs.SamplerFlags; @@ -79,25 +76,20 @@ public partial class MtrlTab TextureLabelWidth = 50f * Im.Style.GlobalScale; - float helpWidth; - using (var _ = ImRaii.PushFont(UiBuilder.IconFont)) - { - helpWidth = Im.Style.ItemSpacing.X + ImGui.CalcTextSize(FontAwesomeIcon.InfoCircle.ToIconString()).X; - } + var helpWidth = Im.Style.ItemSpacing.X + ImEx.Icon.CalculateSize(FontAwesomeIcon.InfoCircle.Icon()).X; foreach (var (label, _, _, description, monoFont) in Textures) { if (!monoFont) - TextureLabelWidth = Math.Max(TextureLabelWidth, ImGui.CalcTextSize(label).X + (description.Length > 0 ? helpWidth : 0.0f)); + TextureLabelWidth = Math.Max(TextureLabelWidth, Im.Font.CalculateSize(label).X + (description.Length > 0 ? helpWidth : 0.0f)); } - using (var _ = ImRaii.PushFont(UiBuilder.MonoFont)) + using (Im.Font.PushMono()) { foreach (var (label, _, _, description, monoFont) in Textures) { if (monoFont) - TextureLabelWidth = Math.Max(TextureLabelWidth, - ImGui.CalcTextSize(label).X + (description.Length > 0 ? helpWidth : 0.0f)); + TextureLabelWidth = Math.Max(TextureLabelWidth, Im.Font.CalculateSize(label).X + (description.Length > 0 ? helpWidth : 0.0f)); } } @@ -122,8 +114,8 @@ public partial class MtrlTab if (Textures.Count == 0) return false; - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); - if (!ImGui.CollapsingHeader("Textures and Samplers", ImGuiTreeNodeFlags.DefaultOpen)) + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); + if (!Im.Tree.Header("Textures and Samplers"u8, TreeNodeFlags.DefaultOpen)) return false; var frameHeight = Im.Style.FrameHeight; @@ -135,13 +127,11 @@ public partial class MtrlTab table.SetupColumn("Name"u8, TableColumnFlags.WidthFixed, TextureLabelWidth * Im.Style.GlobalScale); foreach (var (label, textureI, samplerI, description, monoFont) in Textures) { - using var _ = ImRaii.PushId(samplerI); + using var _ = Im.Id.Push(samplerI); var tmp = Mtrl.Textures[textureI].Path; var unfolded = UnfoldedTextures.Contains(samplerI); - ImGui.TableNextColumn(); - if (ImGuiUtil.DrawDisabledButton((unfolded ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight).ToIconString(), - new Vector2(frameHeight), - "Settings for this texture and the associated sampler", false, true)) + table.NextColumn(); + if (ImEx.Icon.Button(unfolded ? LunaStyle.ExpandDownIcon : LunaStyle.CollapseUpIcon, "Settings for this texture and the associated sampler"u8)) { unfolded = !unfolded; if (unfolded) @@ -150,10 +140,9 @@ public partial class MtrlTab UnfoldedTextures.Remove(samplerI); } - ImGui.TableNextColumn(); + table.NextColumn(); Im.Item.SetNextWidth(Im.ContentRegion.Available.X); - if (ImGui.InputText(string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength, - disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None) + if (Im.Input.Text(StringU8.Empty, ref tmp, default, disabled ? InputTextFlags.ReadOnly : InputTextFlags.None, Utf8GamePath.MaxGamePathLength) && tmp.Length > 0 && tmp != Mtrl.Textures[textureI].Path) { @@ -161,22 +150,21 @@ public partial class MtrlTab Mtrl.Textures[textureI].Path = tmp; } - ImGui.TableNextColumn(); - using (ImRaii.PushFont(UiBuilder.MonoFont, monoFont)) + table.NextColumn(); + using (Im.Font.Mono.Push(monoFont)) { - ImGui.AlignTextToFramePadding(); if (description.Length > 0) - ImGuiUtil.LabeledHelpMarker(label, description); + LunaStyle.DrawHelpMarkerLabel(label, description); else - Im.Text(label); + ImEx.TextFrameAligned(label); } if (unfolded) { - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); + table.NextColumn(); + table.NextColumn(); ret |= DrawMaterialSampler(disabled, textureI, samplerI); - ImGui.TableNextColumn(); + table.NextColumn(); } } @@ -185,20 +173,20 @@ public partial class MtrlTab private static bool ComboTextureAddressMode(ReadOnlySpan label, ref TextureAddressMode value) { - using var c = ImUtf8.Combo(label, value.ToString()); + using var c = Im.Combo.Begin(label, value.ToNameU8()); if (!c) return false; var ret = false; foreach (var mode in Enum.GetValues()) { - if (ImGui.Selectable(mode.ToString(), mode == value)) + if (Im.Selectable(mode.ToNameU8(), mode == value)) { value = mode; ret = true; } - ImUtf8.SelectableHelpMarker(TextureAddressModeTooltip(mode)); + LunaStyle.DrawRightAlignedHelpMarker(TextureAddressModeTooltip(mode)); } return ret; @@ -211,7 +199,7 @@ public partial class MtrlTab ref var sampler = ref Mtrl.ShaderPackage.Samplers[samplerIdx]; var dx11 = texture.DX11; - if (ImUtf8.Checkbox("Prepend -- to the file name on DirectX 11"u8, ref dx11)) + if (Im.Checkbox("Prepend -- to the file name on DirectX 11"u8, ref dx11)) { texture.DX11 = dx11; ret = true; @@ -221,7 +209,7 @@ public partial class MtrlTab { ref var samplerFlags = ref Wrap(ref sampler.Flags); - Im.Item.SetNextWidth(Im.Style.GlobalScale * 100.0f); + Im.Item.SetNextWidthScaled(100.0f); var addressMode = samplerFlags.UAddressMode; if (ComboTextureAddressMode("##UAddressMode"u8, ref addressMode)) { @@ -230,11 +218,11 @@ public partial class MtrlTab SetSamplerFlags(sampler.SamplerId, sampler.Flags); } - Im.Line.Same(); - ImUtf8.LabeledHelpMarker("U Address Mode"u8, - "Method to use for resolving a U texture coordinate that is outside the 0 to 1 range."); + Im.Line.SameInner(); + LunaStyle.DrawHelpMarkerLabel("U Address Mode"u8, + "Method to use for resolving a U texture coordinate that is outside the 0 to 1 range."u8); - Im.Item.SetNextWidth(Im.Style.GlobalScale * 100.0f); + Im.Item.SetNextWidthScaled(100.0f); addressMode = samplerFlags.VAddressMode; if (ComboTextureAddressMode("##VAddressMode"u8, ref addressMode)) { @@ -244,12 +232,12 @@ public partial class MtrlTab } Im.Line.Same(); - ImUtf8.LabeledHelpMarker("V Address Mode"u8, - "Method to use for resolving a V texture coordinate that is outside the 0 to 1 range."); + LunaStyle.DrawHelpMarkerLabel("V Address Mode"u8, + "Method to use for resolving a V texture coordinate that is outside the 0 to 1 range."u8); var lodBias = samplerFlags.LodBias; - Im.Item.SetNextWidth(Im.Style.GlobalScale * 100.0f); - if (ImUtf8.DragScalar("##LoDBias"u8, ref lodBias, -8.0f, 7.984375f, 0.1f)) + Im.Item.SetNextWidthScaled(100.0f); + if (Im.Drag("##LoDBias"u8, ref lodBias, -8.0f, 7.984375f, 0.1f)) { samplerFlags.LodBias = lodBias; ret = true; @@ -257,12 +245,12 @@ public partial class MtrlTab } Im.Line.Same(); - ImUtf8.LabeledHelpMarker("Level of Detail Bias"u8, - "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."); + LunaStyle.DrawHelpMarkerLabel("Level of Detail Bias"u8, + "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."u8); var minLod = samplerFlags.MinLod; - Im.Item.SetNextWidth(Im.Style.GlobalScale * 100.0f); - if (ImUtf8.DragScalar("##MinLoD"u8, ref minLod, 0, 15, 0.1f)) + Im.Item.SetNextWidthScaled(100.0f); + if (Im.Drag("##MinLoD"u8, ref minLod, 0, 15, 0.1f)) { samplerFlags.MinLod = minLod; ret = true; @@ -270,26 +258,25 @@ public partial class MtrlTab } Im.Line.Same(); - ImUtf8.LabeledHelpMarker("Minimum Level of Detail"u8, - "Most detailed mipmap level to use.\n\n0 is the full-sized texture, 1 is the half-sized texture, 2 is the quarter-sized texture, and so on.\n15 will forcibly reduce the texture to its smallest mipmap."); + LunaStyle.DrawHelpMarkerLabel("Minimum Level of Detail"u8, + "Most detailed mipmap level to use.\n\n0 is the full-sized texture, 1 is the half-sized texture, 2 is the quarter-sized texture, and so on.\n15 will forcibly reduce the texture to its smallest mipmap."u8); } else { - ImUtf8.Text("This texture does not have a dedicated sampler."u8); + Im.Text("This texture does not have a dedicated sampler."u8); } - using var t = ImUtf8.TreeNode("Advanced Settings"u8); + using var t = Im.Tree.Node("Advanced Settings"u8); if (!t) return ret; - Im.Item.SetNextWidth(Im.Style.GlobalScale * 100.0f); - if (ImUtf8.InputScalar("Texture Flags"u8, ref texture.Flags, "%04X"u8, - flags: disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None)) + Im.Item.SetNextWidthScaled(100.0f); + if (Im.Input.Scalar("Texture Flags"u8, ref texture.Flags, "%04X"u8, + flags: disabled ? InputTextFlags.ReadOnly : InputTextFlags.None)) ret = true; - Im.Item.SetNextWidth(Im.Style.GlobalScale * 100.0f); - if (ImUtf8.InputScalar("Sampler Flags"u8, ref sampler.Flags, "%08X"u8, - flags: ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None))) + Im.Item.SetNextWidthScaled(100.0f); + if (Im.Input.Scalar("Sampler Flags"u8, ref sampler.Flags, "%08X"u8, flags: InputTextFlags.CharsHexadecimal | (disabled ? InputTextFlags.ReadOnly : InputTextFlags.None))) { ret = true; SetSamplerFlags(sampler.SamplerId, sampler.Flags); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs index 28440146..f7b284fd 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs @@ -1,11 +1,6 @@ -using Dalamud.Interface.Components; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; -using OtterGui.Widgets; +using Luna; using Penumbra.GameData.Files; using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Interop; @@ -75,9 +70,8 @@ public sealed partial class MtrlTab : IWritable, IDisposable if (disabled || Mtrl.IsDawntrail) return false; - if (!ImUtf8.ButtonEx("Update MTRL Version to Dawntrail"u8, - "Try using this if the material can not be loaded or should use legacy shaders.\n\nThis is not revertible."u8, - new Vector2(-0.1f, 0), false, 0, new Rgba32(Colors.PressEnterWarningBg).Color)) + if (!ImEx.Button("Update MTRL Version to Dawntrail"u8, Colors.PressEnterWarningBg, default, Im.ContentRegion.Available with { Y = 0 }, + "Try using this if the material can not be loaded or should use legacy shaders.\n\nThis is not revertible."u8)) return false; Mtrl.MigrateToDawntrail(); @@ -96,17 +90,17 @@ public sealed partial class MtrlTab : IWritable, IDisposable DrawMaterialLivePreviewRebind(disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); var ret = DrawBackFaceAndTransparency(disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); ret |= DrawShaderSection(disabled); ret |= DrawTextureSection(disabled); ret |= DrawColorTableSection(disabled); ret |= DrawConstantsSection(disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); DrawOtherMaterialDetails(disabled); return !disabled && ret; @@ -118,15 +112,15 @@ public sealed partial class MtrlTab : IWritable, IDisposable var ret = false; - using var dis = ImRaii.Disabled(disabled); + using var dis = Im.Disabled(disabled); var tmp = shaderFlags.EnableTransparency; // guardrail: the game crashes if transparency is enabled on characterstockings.shpk var disallowTransparency = Mtrl.ShaderPackage.Name == "characterstockings.shpk"; - using (ImRaii.Disabled(disallowTransparency)) + using (Im.Disabled(disallowTransparency)) { - if (ImUtf8.Checkbox("Enable Transparency"u8, ref tmp)) + if (Im.Checkbox("Enable Transparency"u8, ref tmp)) { shaderFlags.EnableTransparency = tmp; ret = true; @@ -135,13 +129,11 @@ public sealed partial class MtrlTab : IWritable, IDisposable } if (disallowTransparency) - { - ImGuiComponents.HelpMarker("Enabling transparency for shader package characterstockings.shpk will crash the game."); - } + LunaStyle.DrawHelpMarker("Enabling transparency for shader package characterstockings.shpk will crash the game."u8); Im.Line.Same(200 * Im.Style.GlobalScale + Im.Style.ItemSpacing.X + Im.Style.WindowPadding.X); tmp = shaderFlags.HideBackfaces; - if (ImUtf8.Checkbox("Hide Backfaces"u8, ref tmp)) + if (Im.Checkbox("Hide Backfaces"u8, ref tmp)) { shaderFlags.HideBackfaces = tmp; ret = true; @@ -152,8 +144,8 @@ public sealed partial class MtrlTab : IWritable, IDisposable { Im.Line.Same(400 * Im.Style.GlobalScale + 2 * Im.Style.ItemSpacing.X + Im.Style.WindowPadding.X); - ImUtf8.Text("Loading shader (.shpk) file. Some functionality will only be available after this is done."u8, - ImGuiUtil.HalfBlendText(0x808000u)); // Half cyan + Im.Text("Loading shader (.shpk) file. Some functionality will only be available after this is done."u8, + ImGuiColor.Text.Get().HalfBlend(0x808000)); } return ret; @@ -161,29 +153,29 @@ public sealed partial class MtrlTab : IWritable, IDisposable private void DrawOtherMaterialDetails(bool _) { - if (!ImUtf8.CollapsingHeader("Further Content"u8)) + if (!Im.Tree.Header("Further Content"u8)) return; - using (var sets = ImUtf8.TreeNode("UV Sets"u8, ImGuiTreeNodeFlags.DefaultOpen)) + using (var sets = Im.Tree.Node("UV Sets"u8, TreeNodeFlags.DefaultOpen)) { if (sets) foreach (var set in Mtrl.UvSets) - ImUtf8.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose(); + Im.Tree.Leaf($"#{set.Index:D2} - {set.Name}"); } - using (var sets = ImUtf8.TreeNode("Color Sets"u8, ImGuiTreeNodeFlags.DefaultOpen)) + using (var sets = Im.Tree.Node("Color Sets"u8, TreeNodeFlags.DefaultOpen)) { if (sets) foreach (var set in Mtrl.ColorSets) - ImUtf8.TreeNode($"#{set.Index:D2} - {set.Name}", ImGuiTreeNodeFlags.Leaf).Dispose(); + Im.Tree.Leaf($"#{set.Index:D2} - {set.Name}"); } if (Mtrl.AdditionalData.Length <= 0) return; - using var t = ImUtf8.TreeNode($"Additional Data (Size: {Mtrl.AdditionalData.Length})###AdditionalData"); + using var t = Im.Tree.Node($"Additional Data (Size: {Mtrl.AdditionalData.Length})###AdditionalData"); if (t) - Widget.DrawHexViewer(Mtrl.AdditionalData); + ImEx.HexViewer(Mtrl.AdditionalData); } private void UnpinResources(bool all) @@ -209,7 +201,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable UpdateConstants(); } - public unsafe void Dispose() + public void Dispose() { UnbindFromMaterialInstances(); if (Writable) diff --git a/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs index 3a806511..8ae926df 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs @@ -1,11 +1,8 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Raii; -using OtterGui.Text; -using OtterGui.Widgets; using Penumbra.Collections.Cache; using Penumbra.GameData.Data; using Penumbra.GameData.Enums; @@ -14,8 +11,7 @@ using Penumbra.GameData.Files.AtchStructs; using Penumbra.Meta; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; -using MouseWheelType = OtterGui.Widgets.MouseWheelType; +using Penumbra.UI.Combos; using Notification = Luna.Notification; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -29,12 +25,11 @@ public sealed class AtchMetaDrawer : MetaDrawer => 10; public override float ColumnHeight - => 2 * ImUtf8.FrameHeightSpacing; + => 2 * Im.Style.FrameHeightWithSpacing; private AtchFile? _currentBaseAtchFile; private AtchPoint? _currentBaseAtchPoint; private readonly AtchPointCombo _combo; - private string _fileImport = string.Empty; public AtchMetaDrawer(ModMetaEditor editor, MetaFileManager metaFiles) : base(editor, metaFiles) @@ -42,13 +37,6 @@ public sealed class AtchMetaDrawer : MetaDrawer _combo = new AtchPointCombo(() => _currentBaseAtchFile?.Points.Select(p => p.Type).ToList() ?? []); } - private sealed class AtchPointCombo(Func> generator) - : FilterComboCache(generator, MouseWheelType.Control, Penumbra.Log) - { - protected override string ToString(AtchType obj) - => obj.ToName(); - } - private sealed class RaceCodeException(string filePath) : Exception($"Could not identify race code from path {filePath}."); public void ImportFile(string filePath) @@ -70,7 +58,7 @@ public sealed class AtchMetaDrawer : MetaDrawer { var identifier = new AtchIdentifier(point.Type, gr, (ushort)index); var defaultValue = AtchCache.GetDefault(MetaFiles, identifier); - if (defaultValue == null) + if (defaultValue is null) continue; if (defaultValue.Value.Equals(entry)) @@ -83,27 +71,25 @@ public sealed class AtchMetaDrawer : MetaDrawer catch (RaceCodeException ex) { Penumbra.Messager.AddMessage(new Notification(ex, "The imported .atch file does not contain a race code (cXXXX) in its name.", - "Could not import .atch file:", - NotificationType.Warning)); + "Could not import .atch file:", NotificationType.Warning)); } catch (Exception ex) { - Penumbra.Messager.AddMessage(new Notification(ex, "Unable to import .atch file.", "Could not import .atch file:", - NotificationType.Warning)); + Penumbra.Messager.AddMessage(new Notification(ex, "Unable to import .atch file.", "Could not import .atch file:", NotificationType.Warning)); } } protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current ATCH manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Atch))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, disabled: !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) @@ -146,20 +132,20 @@ public sealed class AtchMetaDrawer : MetaDrawer private bool DrawIdentifierInput(ref AtchIdentifier identifier) { var changes = false; - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawRace(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawGender(ref identifier, false); if (changes) UpdateFile(); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (DrawPointInput(ref identifier, _combo)) { _currentBaseAtchPoint = _currentBaseAtchFile?.GetPoint(identifier.Type); changes = true; } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawEntryIndexInput(ref identifier, _currentBaseAtchPoint!); return changes; @@ -169,7 +155,7 @@ public sealed class AtchMetaDrawer : MetaDrawer { _currentBaseAtchFile = MetaFiles.AtchManager.AtchFileBase[Identifier.GenderRace]; _currentBaseAtchPoint = _currentBaseAtchFile.GetPoint(Identifier.Type); - if (_currentBaseAtchPoint == null) + if (_currentBaseAtchPoint is null) { _currentBaseAtchPoint = _currentBaseAtchFile.Points.First(); Identifier = Identifier with { Type = _currentBaseAtchPoint.Type }; @@ -181,32 +167,32 @@ public sealed class AtchMetaDrawer : MetaDrawer private static void DrawIdentifier(AtchIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Race.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Race.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Model Race"u8); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); DrawGender(ref identifier, true); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Type.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Type.ToName(), default, FrameColor); Im.Tooltip.OnHover("Attachment Point Type"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.EntryIndex.ToString(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.EntryIndex}", default, FrameColor); Im.Tooltip.OnHover("State Entry Index"u8); } private static bool DrawEntry(in AtchEntry defaultEntry, ref AtchEntry entry, bool disabled) { var changes = false; - using var dis = ImRaii.Disabled(disabled); + using var dis = Im.Disabled(disabled); if (defaultEntry.Bone.Length == 0) return false; - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(200 * Im.Style.GlobalScale); - if (ImUtf8.InputText("##BoneName"u8, entry.FullSpan, out TerminatedByteString newBone)) + Im.Table.NextColumn(); + Im.Item.SetNextWidthScaled(200); + if (Im.Input.Text("##BoneName"u8, entry.FullSpan, out StringU8 newBone)) { entry.SetBoneName(newBone); changes = true; @@ -214,32 +200,32 @@ public sealed class AtchMetaDrawer : MetaDrawer Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Bone Name"u8); - Im.Item.SetNextWidth(200 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchScale"u8, ref entry.Scale); + Im.Item.SetNextWidthScaled(200); + changes |= Im.Input.Scalar("##AtchScale"u8, ref entry.Scale); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Scale"u8); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(120 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchOffsetX"u8, ref entry.OffsetX); + Im.Table.NextColumn(); + Im.Item.SetNextWidthScaled(120); + changes |= Im.Input.Scalar("##AtchOffsetX"u8, ref entry.OffsetX); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Offset X-Coordinate"u8); - Im.Item.SetNextWidth(120 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchRotationX"u8, ref entry.RotationX); + Im.Item.SetNextWidthScaled(120); + changes |= Im.Input.Scalar("##AtchRotationX"u8, ref entry.RotationX); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Rotation X-Axis"u8); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(120 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchOffsetY"u8, ref entry.OffsetY); + Im.Table.NextColumn(); + Im.Item.SetNextWidthScaled(120); + changes |= Im.Input.Scalar("##AtchOffsetY"u8, ref entry.OffsetY); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Offset Y-Coordinate"u8); - Im.Item.SetNextWidth(120 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchRotationY"u8, ref entry.RotationY); + Im.Item.SetNextWidthScaled(120); + changes |= Im.Input.Scalar("##AtchRotationY"u8, ref entry.RotationY); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Rotation Y-Axis"u8); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(120 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchOffsetZ"u8, ref entry.OffsetZ); + Im.Table.NextColumn(); + Im.Item.SetNextWidthScaled(120); + changes |= Im.Input.Scalar("##AtchOffsetZ"u8, ref entry.OffsetZ); Im.Tooltip.OnHover("Offset Z-Coordinate"u8); - Im.Item.SetNextWidth(120 * Im.Style.GlobalScale); - changes |= ImUtf8.InputScalar("##AtchRotationZ"u8, ref entry.RotationZ); + Im.Item.SetNextWidthScaled(120); + changes |= Im.Input.Scalar("##AtchRotationZ"u8, ref entry.RotationZ); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, "Rotation Z-Axis"u8); return changes; @@ -247,7 +233,7 @@ public sealed class AtchMetaDrawer : MetaDrawer private static bool DrawRace(ref AtchIdentifier identifier, float unscaledWidth = 100) { - var ret = Combos.Race("##atchRace", identifier.Race, out var race, unscaledWidth); + var ret = Combos.Combos.Race("##atchRace", identifier.Race, out var race, unscaledWidth); Im.Tooltip.OnHover("Model Race"u8); if (ret) identifier = identifier with { GenderRace = Names.CombinedRace(identifier.Gender, race) }; @@ -259,7 +245,7 @@ public sealed class AtchMetaDrawer : MetaDrawer { var isMale = identifier.Gender is Gender.Male; - if (!ImUtf8.IconButton(isMale ? FontAwesomeIcon.Mars : FontAwesomeIcon.Venus, "Gender"u8, buttonColor: disabled ? 0x000F0000u : 0) + if (!ImEx.Icon.Button(isMale ? FontAwesomeIcon.Mars.Icon() : FontAwesomeIcon.Venus.Icon(), "Gender"u8, buttonColor: disabled ? 0x000F0000u : 0) || disabled) return false; @@ -281,8 +267,8 @@ public sealed class AtchMetaDrawer : MetaDrawer { var index = identifier.EntryIndex; Im.Item.SetNextWidth(40 * Im.Style.GlobalScale); - var ret = ImUtf8.DragScalar("##AtchEntry"u8, ref index, 0, (ushort)(currentAtchPoint.Entries.Length - 1), 0.05f, - ImGuiSliderFlags.AlwaysClamp); + var ret = Im.Drag("##AtchEntry"u8, ref index, 0, (ushort)(currentAtchPoint.Entries.Length - 1), 0.05f, + SliderFlags.AlwaysClamp); Im.Tooltip.OnHover("State Entry Index"u8); if (!ret) return false; @@ -291,4 +277,4 @@ public sealed class AtchMetaDrawer : MetaDrawer identifier = identifier with { EntryIndex = index }; return true; } -} +} diff --git a/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs index eb037418..6ca717b6 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs @@ -1,9 +1,6 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.Collections.Cache; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; @@ -28,7 +25,7 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile => 7; public override float ColumnHeight - => ImUtf8.FrameHeightSpacing; + => Im.Style.FrameHeightWithSpacing; protected override void Initialize() { @@ -38,18 +35,18 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current ATR manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Atr))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier) && _identifierValid; var tt = canAdd ? "Stage this edit."u8 : _identifierValid ? "This entry does not contain a valid attribute."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, AtrEntry.False); DrawIdentifierInput(ref Identifier); @@ -77,55 +74,55 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private bool DrawIdentifierInput(ref AtrIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var changes = DrawHumanSlot(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawGenderRaceConditionInput(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawPrimaryId(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawAttributeKeyInput(ref identifier, ref _buffer, ref _identifierValid); return changes; } private static void DrawIdentifier(AtrIdentifier identifier) { - ImGui.TableNextColumn(); - - ImUtf8.TextFramed(ShpMetaDrawer.SlotName(identifier.Slot), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(ShpMetaDrawer.SlotName(identifier.Slot), default, FrameColor); Im.Tooltip.OnHover("Model Slot"u8); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.GenderRaceCondition is not GenderRace.Unknown) { - ImUtf8.TextFramed($"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})", FrameColor); + ImEx.TextFramed($"{identifier.GenderRaceCondition.ToNameU8()} ({identifier.GenderRaceCondition.ToRaceCode()})", default, + FrameColor); Im.Tooltip.OnHover("Gender & Race Code for this attribute to be set."); } else { - ImUtf8.TextFramed("Any Gender & Race"u8, FrameColor); + ImEx.TextFramed("Any Gender & Race"u8, default, FrameColor); } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.Id.HasValue) - ImUtf8.TextFramed($"{identifier.Id.Value.Id}", FrameColor); + ImEx.TextFramed($"{identifier.Id.Value.Id}", default, FrameColor); else - ImUtf8.TextFramed("All IDs"u8, FrameColor); + ImEx.TextFramed("All IDs"u8, default, FrameColor); Im.Tooltip.OnHover("Primary ID"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Attribute.AsSpan, FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Attribute.AsSpan, default, FrameColor); } private static bool DrawEntry(ref AtrEntry entry, bool disabled) { - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); var value = entry.Value; - var changes = ImUtf8.Checkbox("##atrEntry"u8, ref value); + var changes = Im.Checkbox("##atrEntry"u8, ref value); if (changes) entry = new AtrEntry(value); Im.Tooltip.OnHover("Whether to enable or disable this attribute for the selected items."); @@ -137,9 +134,9 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile var allSlots = identifier.Slot is HumanSlot.Unknown; var all = !identifier.Id.HasValue; var ret = false; - using (ImRaii.Disabled(allSlots)) + using (Im.Disabled(allSlots)) { - if (ImUtf8.Checkbox("##atrAll"u8, ref all)) + if (Im.Checkbox("##atrAll"u8, ref all)) { identifier = identifier with { Id = all ? null : 0 }; ret = true; @@ -150,12 +147,12 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile ? "When using all slots, you also need to use all IDs."u8 : "Enable this attribute for all model IDs."u8); - Im.Line.Same(0, Im.Style.ItemInnerSpacing.X); + Im.Line.SameInner(); if (all) { using var style = ImStyleDouble.ButtonTextAlign.Push(new Vector2(0.05f, 0.5f)); - ImUtf8.TextFramed("All IDs"u8, ImGuiColor.FrameBackground.Get(all || allSlots ? Im.Style.DisabledAlpha : 1f).Color, - new Vector2(unscaledWidth, 0), ImGuiColor.TextDisabled.Get().Color); + ImEx.TextFramed("All IDs"u8, new Vector2(unscaledWidth, 0), + ImGuiColor.FrameBackground.Get(all || allSlots ? Im.Style.DisabledAlpha : 1f).Color, ImGuiColor.TextDisabled.Get().Color); } else { @@ -175,13 +172,13 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public bool DrawHumanSlot(ref AtrIdentifier identifier, float unscaledWidth = 150) { var ret = false; - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - using (var combo = ImUtf8.Combo("##atrSlot"u8, ShpMetaDrawer.SlotName(identifier.Slot))) + Im.Item.SetNextWidthScaled(unscaledWidth); + using (var combo = Im.Combo.Begin("##atrSlot"u8, ShpMetaDrawer.SlotName(identifier.Slot))) { if (combo) foreach (var slot in ShpMetaDrawer.AvailableSlots) { - if (!ImUtf8.Selectable(ShpMetaDrawer.SlotName(slot), slot == identifier.Slot) || slot == identifier.Slot) + if (!Im.Selectable(ShpMetaDrawer.SlotName(slot), slot == identifier.Slot) || slot == identifier.Slot) continue; ret = true; @@ -215,16 +212,16 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static bool DrawGenderRaceConditionInput(ref AtrIdentifier identifier, float unscaledWidth = 250) { var ret = false; - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); + Im.Item.SetNextWidthScaled(unscaledWidth); - using (var combo = ImUtf8.Combo("##shpGenderRace"u8, + using (var combo = Im.Combo.Begin("##shpGenderRace"u8, identifier.GenderRaceCondition is GenderRace.Unknown - ? "Any Gender & Race" - : $"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})")) + ? "Any Gender & Race"u8 + : $"{identifier.GenderRaceCondition.ToNameU8()} ({identifier.GenderRaceCondition.ToRaceCode()})")) { if (combo) { - if (ImUtf8.Selectable("Any Gender & Race"u8, identifier.GenderRaceCondition is GenderRace.Unknown) + if (Im.Selectable("Any Gender & Race"u8, identifier.GenderRaceCondition is GenderRace.Unknown) && identifier.GenderRaceCondition is not GenderRace.Unknown) { identifier = identifier with { GenderRaceCondition = GenderRace.Unknown }; @@ -233,7 +230,7 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile foreach (var gr in ShapeAttributeHashSet.GenderRaceValues.Skip(1)) { - if (ImUtf8.Selectable($"{gr.ToName()} ({gr.ToRaceCode()})", identifier.GenderRaceCondition == gr) + if (Im.Selectable($"{gr.ToNameU8()} ({gr.ToRaceCode()})", identifier.GenderRaceCondition == gr) && identifier.GenderRaceCondition != gr) { identifier = identifier with { GenderRaceCondition = gr }; @@ -243,8 +240,7 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile } } - Im.Tooltip.OnHover( - "Only activate this attribute for this gender & race code."u8); + Im.Tooltip.OnHover("Only activate this attribute for this gender & race code."u8); return ret; } @@ -257,8 +253,8 @@ public sealed class AtrMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile var span = new Span(ptr, ShapeAttributeString.MaxLength + 1); using (ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, !valid)) { - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - if (ImUtf8.InputText("##atrAttribute"u8, span, out int newLength, "Attribute..."u8)) + Im.Item.SetNextWidthScaled(unscaledWidth); + if (Im.Input.Text("##atrAttribute"u8, span, out ulong newLength, "Attribute..."u8)) { buffer.ForceLength((byte)newLength); valid = buffer.ValidateCustomAttributeString(); diff --git a/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs index 0a774235..bf2ea4d4 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs @@ -1,16 +1,12 @@ -using Dalamud.Interface; -using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; using Penumbra.Meta; using Penumbra.Meta.Files; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -34,15 +30,15 @@ public sealed class EqdpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFil protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current EQDP manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Eqdp))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var validRaceCode = CharacterUtilityData.EqdpIdx(Identifier.GenderRace, false) >= 0; var canAdd = validRaceCode && !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : validRaceCode ? "This entry is already edited."u8 : "This combination of race and gender can not be used."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) @@ -72,44 +68,44 @@ public sealed class EqdpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFil private static bool DrawIdentifierInput(ref EqdpIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var changes = DrawPrimaryId(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawRace(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawGender(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawEquipSlot(ref identifier); return changes; } private static void DrawIdentifier(EqdpIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed($"{identifier.SetId.Id}", FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.SetId.Id}", default, FrameColor); Im.Tooltip.OnHover("Model Set ID"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Race.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Race.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Model Race"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Gender.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Gender.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Gender"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Slot.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Slot.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Equip Slot"u8); } private static bool DrawEntry(EqdpEntryInternal defaultEntry, ref EqdpEntryInternal entry, bool disabled) { var changes = false; - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); if (Checkmark("Material##eqdp"u8, "\0"u8, entry.Material, defaultEntry.Material, out var newMaterial)) { entry = entry with { Material = newMaterial }; @@ -139,7 +135,7 @@ public sealed class EqdpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFil public static bool DrawRace(ref EqdpIdentifier identifier, float unscaledWidth = 100) { - var ret = Combos.Race("##eqdpRace", identifier.Race, out var race, unscaledWidth); + var ret = Combos.Combos.Race("##eqdpRace", identifier.Race, out var race, unscaledWidth); Im.Tooltip.OnHover("Model Race"u8); if (ret) identifier = identifier with { GenderRace = Names.CombinedRace(identifier.Gender, race) }; @@ -148,7 +144,7 @@ public sealed class EqdpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFil public static bool DrawGender(ref EqdpIdentifier identifier, float unscaledWidth = 120) { - var ret = Combos.Gender("##eqdpGender", identifier.Gender, out var gender, unscaledWidth); + var ret = Combos.Combos.Gender("##eqdpGender", identifier.Gender, out var gender, unscaledWidth); Im.Tooltip.OnHover("Gender"u8); if (ret) identifier = identifier with { GenderRace = Names.CombinedRace(gender, identifier.Race) }; @@ -157,7 +153,7 @@ public sealed class EqdpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFil public static bool DrawEquipSlot(ref EqdpIdentifier identifier, float unscaledWidth = 100) { - var ret = Combos.EqdpEquipSlot("##eqdpSlot", identifier.Slot, out var slot, unscaledWidth); + var ret = Combos.Combos.EqdpEquipSlot("##eqdpSlot", identifier.Slot, out var slot, unscaledWidth); Im.Tooltip.OnHover("Equip Slot"u8); if (ret) identifier = identifier with { Slot = slot }; diff --git a/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs index 5a000e5a..56b21778 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs @@ -1,16 +1,12 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Meta; using Penumbra.Meta.Files; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -34,13 +30,13 @@ public sealed class EqpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current EQP manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Eqp))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) @@ -70,30 +66,30 @@ public sealed class EqpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static bool DrawIdentifierInput(ref EqpIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var changes = DrawPrimaryId(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawEquipSlot(ref identifier); return changes; } private static void DrawIdentifier(EqpIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed($"{identifier.SetId.Id}", FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.SetId.Id}", default, FrameColor); Im.Tooltip.OnHover("Model Set ID"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Slot.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Slot.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Equip Slot"u8); } private static bool DrawEntry(EquipSlot slot, EqpEntryInternal defaultEntry, ref EqpEntryInternal entry, bool disabled) { var changes = false; - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); var offset = Eqp.OffsetAndMask(slot).Item1; DrawBox(ref entry, 0); for (var i = 1; i < Eqp.EqpAttributes[slot].Count; ++i) @@ -106,7 +102,7 @@ public sealed class EqpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile void DrawBox(ref EqpEntryInternal entry, int i) { - using var id = ImUtf8.PushId(i); + using var id = Im.Id.Push(i); var flag = 1u << i; var eqpFlag = (EqpEntry)((ulong)flag << offset); var defaultValue = (flag & defaultEntry.Value) != 0; @@ -132,7 +128,7 @@ public sealed class EqpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawEquipSlot(ref EqpIdentifier identifier, float unscaledWidth = 100) { - var ret = Combos.EqpEquipSlot("##eqpSlot", identifier.Slot, out var slot, unscaledWidth); + var ret = Combos.Combos.EqpEquipSlot("##eqpSlot", identifier.Slot, out var slot, unscaledWidth); Im.Tooltip.OnHover("Equip Slot"u8); if (ret) identifier = identifier with { Slot = slot }; diff --git a/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs index 9358dd44..946c1987 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs @@ -1,15 +1,11 @@ -using Dalamud.Interface; -using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.Meta; using Penumbra.Meta.Files; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -33,14 +29,14 @@ public sealed class EstMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current EST manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Est))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) @@ -71,16 +67,16 @@ public sealed class EstMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static bool DrawIdentifierInput(ref EstIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var changes = DrawPrimaryId(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawRace(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawGender(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawSlot(ref identifier); return changes; @@ -88,27 +84,27 @@ public sealed class EstMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static void DrawIdentifier(EstIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed($"{identifier.SetId.Id}", FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.SetId.Id}", default, FrameColor); Im.Tooltip.OnHover("Model Set ID"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Race.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Race.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Model Race"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Gender.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Gender.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Gender"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Slot.ToString(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Slot.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Extra Skeleton Type"u8); } private static bool DrawEntry(EstEntry defaultEntry, ref EstEntry entry, bool disabled) { - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); var ret = DragInput("##estValue"u8, [], 100f * Im.Style.GlobalScale, entry.Value, defaultEntry.Value, out var newValue, (ushort)0, ushort.MaxValue, 0.05f, !disabled); if (ret) @@ -129,7 +125,7 @@ public sealed class EstMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawRace(ref EstIdentifier identifier, float unscaledWidth = 100) { - var ret = Combos.Race("##estRace", identifier.Race, out var race, unscaledWidth); + var ret = Combos.Combos.Race("##estRace", identifier.Race, out var race, unscaledWidth); Im.Tooltip.OnHover("Model Race"u8); if (ret) identifier = identifier with { GenderRace = Names.CombinedRace(identifier.Gender, race) }; @@ -138,7 +134,7 @@ public sealed class EstMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawGender(ref EstIdentifier identifier, float unscaledWidth = 120) { - var ret = Combos.Gender("##estGender", identifier.Gender, out var gender, unscaledWidth); + var ret = Combos.Combos.Gender("##estGender", identifier.Gender, out var gender, unscaledWidth); Im.Tooltip.OnHover("Gender"u8); if (ret) identifier = identifier with { GenderRace = Names.CombinedRace(gender, identifier.Race) }; @@ -147,7 +143,7 @@ public sealed class EstMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawSlot(ref EstIdentifier identifier, float unscaledWidth = 200) { - var ret = Combos.EstSlot("##estSlot", identifier.Slot, out var slot, unscaledWidth); + var ret = Combos.Combos.EstSlot("##estSlot", identifier.Slot, out var slot, unscaledWidth); Im.Tooltip.OnHover("Extra Skeleton Type"u8); if (ret) identifier = identifier with { Slot = slot }; diff --git a/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs index 0f463d2b..184cf663 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs @@ -1,8 +1,6 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Text; using Penumbra.GameData.Structs; using Penumbra.Meta; using Penumbra.Meta.Manipulations; @@ -30,14 +28,14 @@ public sealed class GlobalEqpMetaDrawer(ModMetaEditor editor, MetaFileManager me protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current global EQP manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.GlobalEqp))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier); DrawIdentifierInput(ref Identifier); @@ -60,41 +58,41 @@ public sealed class GlobalEqpMetaDrawer(ModMetaEditor editor, MetaFileManager me private static void DrawIdentifierInput(ref GlobalEqpManipulation identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); DrawType(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.Type.HasCondition()) DrawCondition(ref identifier); else - ImUtf8.ScaledDummy(100); + Im.ScaledDummy(100); } private static void DrawIdentifier(GlobalEqpManipulation identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Type.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Type.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Global EQP Type"u8); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.Type.HasCondition()) { - ImUtf8.TextFramed($"{identifier.Condition.Id}", FrameColor); + ImEx.TextFramed($"{identifier.Condition.Id}", default, FrameColor); Im.Tooltip.OnHover("Conditional Model ID"u8); } } public static bool DrawType(ref GlobalEqpManipulation identifier, float unscaledWidth = 250) { - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - using var combo = ImUtf8.Combo("##geqpType"u8, identifier.Type.ToName()); + Im.Item.SetNextWidthScaled(unscaledWidth); + using var combo = Im.Combo.Begin("##geqpType"u8, identifier.Type.ToNameU8()); if (!combo) return false; var ret = false; foreach (var type in Enum.GetValues()) { - if (ImUtf8.Selectable(type.ToName(), type == identifier.Type)) + if (Im.Selectable(type.ToNameU8(), type == identifier.Type)) { identifier = new GlobalEqpManipulation { @@ -104,7 +102,7 @@ public sealed class GlobalEqpMetaDrawer(ModMetaEditor editor, MetaFileManager me ret = true; } - Im.Tooltip.OnHover(type.ToDescription()); + Im.Tooltip.OnHover(type.Tooltip()); } return ret; diff --git a/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs index a60f7b7a..b1166f52 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs @@ -1,8 +1,5 @@ -using Dalamud.Interface; -using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui.Text; +using Luna; using Penumbra.GameData.Structs; using Penumbra.Meta.Files; using Penumbra.Meta; @@ -32,14 +29,14 @@ public sealed class GmpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current Gmp manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Gmp))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) @@ -68,21 +65,21 @@ public sealed class GmpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static bool DrawIdentifierInput(ref GmpIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); return DrawPrimaryId(ref identifier); } private static void DrawIdentifier(GmpIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed($"{identifier.SetId.Id}", FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.SetId.Id}", default, FrameColor); Im.Tooltip.OnHover("Model Set ID"u8); } private static bool DrawEntry(GmpEntry defaultEntry, ref GmpEntry entry, bool disabled) { - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); var changes = false; if (Checkmark("##gmpEnabled"u8, "Gimmick Enabled", entry.Enabled, defaultEntry.Enabled, out var enabled)) { @@ -90,7 +87,7 @@ public sealed class GmpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile changes = true; } - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (Checkmark("##gmpAnimated"u8, "Gimmick Animated", entry.Animated, defaultEntry.Animated, out var animated)) { entry = entry with { Animated = animated }; @@ -98,7 +95,7 @@ public sealed class GmpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile } var rotationWidth = 75 * Im.Style.GlobalScale; - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (DragInput("##gmpRotationA"u8, "Rotation A in Degrees"u8, rotationWidth, entry.RotationA, defaultEntry.RotationA, out var rotationA, (ushort)0, (ushort)360, 0.05f, !disabled)) { @@ -123,7 +120,7 @@ public sealed class GmpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile } var unkWidth = 50 * Im.Style.GlobalScale; - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (DragInput("##gmpUnkA"u8, "Animation Type A?"u8, unkWidth, entry.UnknownA, defaultEntry.UnknownA, out var unknownA, (byte)0, (byte)15, 0.01f, !disabled)) { diff --git a/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs index f280b84f..7aea46ba 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs @@ -1,15 +1,11 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Meta; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -35,19 +31,19 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current IMC manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Imc))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = _fileExists && !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : !_fileExists ? "This IMC file does not exist."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) UpdateEntry(); - using var disabled = ImRaii.Disabled(); + using var disabled = Im.Disabled(); DrawEntry(Entry, ref Entry, false); } @@ -63,83 +59,82 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static bool DrawIdentifierInput(ref ImcIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var change = DrawObjectType(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); change |= DrawPrimaryId(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.ObjectType is ObjectType.Equipment or ObjectType.Accessory) change |= DrawSlot(ref identifier); else change |= DrawSecondaryId(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); change |= DrawVariant(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.ObjectType is ObjectType.DemiHuman) change |= DrawSlot(ref identifier, 70f); else - ImUtf8.ScaledDummy(70f); + Im.ScaledDummy(70f); return change; } private static void DrawIdentifier(ImcIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.ObjectType.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.ObjectType.ToName(), default, FrameColor); Im.Tooltip.OnHover("Object Type"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed($"{identifier.PrimaryId.Id}", FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.PrimaryId.Id}", default, FrameColor); Im.Tooltip.OnHover("Primary ID"); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.ObjectType is ObjectType.Equipment or ObjectType.Accessory) { - ImUtf8.TextFramed(identifier.EquipSlot.ToName(), FrameColor); + ImEx.TextFramed(identifier.EquipSlot.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Equip Slot"u8); } else { - ImUtf8.TextFramed($"{identifier.SecondaryId.Id}", FrameColor); + ImEx.TextFramed($"{identifier.SecondaryId.Id}", default, FrameColor); Im.Tooltip.OnHover("Secondary ID"u8); } - ImGui.TableNextColumn(); - ImUtf8.TextFramed($"{identifier.Variant.Id}", FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed($"{identifier.Variant.Id}", default, FrameColor); Im.Tooltip.OnHover("Variant"u8); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); if (identifier.ObjectType is ObjectType.DemiHuman) { - ImUtf8.TextFramed(identifier.EquipSlot.ToName(), FrameColor); + ImEx.TextFramed(identifier.EquipSlot.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Equip Slot"u8); } } private static bool DrawEntry(ImcEntry defaultEntry, ref ImcEntry entry, bool addDefault) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var change = DrawMaterialId(defaultEntry, ref entry, addDefault); Im.Line.SameInner(); change |= DrawMaterialAnimationId(defaultEntry, ref entry, addDefault); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); change |= DrawDecalId(defaultEntry, ref entry, addDefault); Im.Line.SameInner(); change |= DrawVfxId(defaultEntry, ref entry, addDefault); Im.Line.SameInner(); change |= DrawSoundId(defaultEntry, ref entry, addDefault); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); change |= DrawAttributes(defaultEntry, ref entry); return change; } - protected override IEnumerable<(ImcIdentifier, ImcEntry)> Enumerate() => Editor.Imc .OrderBy(kvp => kvp.Key.ObjectType) @@ -155,7 +150,7 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawObjectType(ref ImcIdentifier identifier, float width = 110) { - var ret = Combos.ImcType("##imcType", identifier.ObjectType, out var type, width); + var ret = Combos.Combos.ImcType("##imcType", identifier.ObjectType, out var type, width); Im.Tooltip.OnHover("Object Type"u8); if (ret) @@ -216,9 +211,9 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile { case ObjectType.Equipment: case ObjectType.DemiHuman: - ret = Combos.EqpEquipSlot("##slot", identifier.EquipSlot, out slot, unscaledWidth); + ret = Combos.Combos.EqpEquipSlot("##slot", identifier.EquipSlot, out slot, unscaledWidth); break; - case ObjectType.Accessory: ret = Combos.AccessorySlot("##slot", identifier.EquipSlot, out slot, unscaledWidth); break; + case ObjectType.Accessory: ret = Combos.Combos.AccessorySlot("##slot", identifier.EquipSlot, out slot, unscaledWidth); break; default: return false; } @@ -284,7 +279,7 @@ public sealed class ImcMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile var changes = false; for (var i = 0; i < ImcEntry.NumAttributes; ++i) { - using var id = ImRaii.PushId(i); + using var id = Im.Id.Push(i); var flag = 1 << i; var value = (entry.AttributeMask & flag) != 0; var def = (defaultEntry.AttributeMask & flag) != 0; diff --git a/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs index e03908aa..e47ff86b 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs @@ -1,11 +1,8 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; using OtterGui; -using OtterGui.Raii; using OtterGui.Text; -using Penumbra.Api.Api; using Penumbra.Meta; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; @@ -41,11 +38,11 @@ public abstract class MetaDrawer(ModMetaEditor editor, Meta _initialized = true; } - using var id = ImUtf8.PushId((int)Identifier.Type); + using var id = Im.Id.Push((int)Identifier.Type); DrawNew(); var height = ColumnHeight; - var skips = ImGuiClip.GetNecessarySkipsAtPos(height, ImGui.GetCursorPosY(), Count); + var skips = ImGuiClip.GetNecessarySkipsAtPos(height, Im.Cursor.Y, Count); if (skips < Count) { var remainder = ImGuiClip.ClippedTableDraw(Enumerate(), skips, DrawLine, Count); @@ -99,7 +96,7 @@ public abstract class MetaDrawer(ModMetaEditor editor, Meta var c = defaultValue > currentValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(); using var color = ImGuiColor.FrameBackground.Push(c, defaultValue != currentValue); Im.Item.SetNextWidth(width); - if (ImUtf8.DragScalar(label, ref newValue, minValue, maxValue, speed)) + if (Im.Drag(label, ref newValue, minValue, maxValue, speed)) newValue = newValue <= minValue ? minValue : newValue >= maxValue ? maxValue : newValue; if (addDefault) @@ -120,7 +117,7 @@ public abstract class MetaDrawer(ModMetaEditor editor, Meta var c = defaultValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(); using var color = ImGuiColor.FrameBackground.Push(c, defaultValue != currentValue); newValue = currentValue; - ImUtf8.Checkbox(label, ref newValue); + Im.Checkbox(label, ref newValue); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, tooltip); return newValue != currentValue; } @@ -135,29 +132,29 @@ public abstract class MetaDrawer(ModMetaEditor editor, Meta var c = defaultValue != currentValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(); using var color = ImGuiColor.FrameBackground.Push(c, defaultValue != currentValue); newValue = currentValue; - ImUtf8.Checkbox(label, ref newValue); + Im.Checkbox(label, ref newValue); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, tooltip); return newValue != currentValue; } protected void DrawMetaButtons(TIdentifier identifier, TEntry entry) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy this manipulation to clipboard."u8, new Lazy(() => new JArray { MetaDictionary.Serialize(identifier, entry)! })); - ImGui.TableNextColumn(); - if (ImUtf8.IconButton(FontAwesomeIcon.Trash, "Delete this meta manipulation."u8)) + Im.Table.NextColumn(); + if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this meta manipulation."u8)) Editor.Changes |= Editor.Remove(identifier); } protected void CopyToClipboardButton(ReadOnlySpan tooltip, Lazy manipulations) { - if (!ImUtf8.IconButton(FontAwesomeIcon.Clipboard, tooltip)) + if (!ImEx.Icon.Button(LunaStyle.ToClipboardIcon, tooltip)) return; var text = Functions.ToCompressedBase64(manipulations.Value, 0); if (text.Length > 0) - ImGui.SetClipboardText(text); + Im.Clipboard.Set(text); } } diff --git a/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs index cbefecda..306a643c 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs @@ -1,15 +1,11 @@ -using Dalamud.Interface; -using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using Newtonsoft.Json.Linq; -using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.Meta; using Penumbra.Meta.Files; using Penumbra.Meta.Manipulations; using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; namespace Penumbra.UI.AdvancedWindow.Meta; @@ -33,14 +29,14 @@ public sealed class RspMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile protected override void DrawNew() { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); CopyToClipboardButton("Copy all current RSP manipulations to clipboard."u8, new Lazy(() => MetaDictionary.SerializeTo([], Editor.Rsp))); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var canAdd = !Editor.Contains(Identifier); var tt = canAdd ? "Stage this edit."u8 : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) Editor.Changes |= Editor.TryAdd(Identifier, Entry); if (DrawIdentifierInput(ref Identifier)) @@ -70,29 +66,29 @@ public sealed class RspMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile private static bool DrawIdentifierInput(ref RspIdentifier identifier) { - ImGui.TableNextColumn(); + Im.Table.NextColumn(); var changes = DrawSubRace(ref identifier); - ImGui.TableNextColumn(); + Im.Table.NextColumn(); changes |= DrawAttribute(ref identifier); return changes; } private static void DrawIdentifier(RspIdentifier identifier) { - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.SubRace.ToName(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.SubRace.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Model Set ID"u8); - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Attribute.ToFullString(), FrameColor); + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Attribute.ToNameU8(), default, FrameColor); Im.Tooltip.OnHover("Equip Slot"u8); } private static bool DrawEntry(RspEntry defaultEntry, ref RspEntry entry, bool disabled) { - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); var ret = DragInput("##rspValue"u8, [], Im.Style.GlobalScale * 150, entry.Value, defaultEntry.Value, out var newValue, RspEntry.MinValue, RspEntry.MaxValue, 0.001f, !disabled); if (ret) @@ -102,7 +98,7 @@ public sealed class RspMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawSubRace(ref RspIdentifier identifier, float unscaledWidth = 150) { - var ret = Combos.SubRace("##rspSubRace", identifier.SubRace, out var subRace, unscaledWidth); + var ret = Combos.Combos.SubRace("##rspSubRace", identifier.SubRace, out var subRace, unscaledWidth); Im.Tooltip.OnHover("Racial Clan"u8); if (ret) identifier = identifier with { SubRace = subRace }; @@ -111,7 +107,7 @@ public sealed class RspMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile public static bool DrawAttribute(ref RspIdentifier identifier, float unscaledWidth = 200) { - var ret = Combos.RspAttribute("##rspAttribute", identifier.Attribute, out var attribute, unscaledWidth); + var ret = Combos.Combos.RspAttribute("##rspAttribute", identifier.Attribute, out var attribute, unscaledWidth); Im.Tooltip.OnHover("Scaling Attribute"u8); if (ret) identifier = identifier with { Attribute = attribute }; diff --git a/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs index b1a1fd97..a72051f7 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs @@ -1,366 +1,363 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; -using ImSharp; -using Newtonsoft.Json.Linq; -using OtterGui.Raii; -using OtterGui.Text; -using Penumbra.Collections.Cache; -using Penumbra.GameData.Enums; -using Penumbra.GameData.Structs; -using Penumbra.Meta; -using Penumbra.Meta.Files; -using Penumbra.Meta.Manipulations; -using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; - -namespace Penumbra.UI.AdvancedWindow.Meta; - -public sealed class ShpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFiles) - : MetaDrawer(editor, metaFiles) -{ - public override ReadOnlySpan Label - => "Shape Keys (SHP)###SHP"u8; - - private ShapeAttributeString _buffer = ShapeAttributeString.TryRead("shpx_"u8, out var s) ? s : ShapeAttributeString.Empty; - private bool _identifierValid; - - public override int NumColumns - => 8; - - public override float ColumnHeight - => ImUtf8.FrameHeightSpacing; - - protected override void Initialize() - { - Identifier = new ShpIdentifier(HumanSlot.Unknown, null, ShapeAttributeString.Empty, ShapeConnectorCondition.None, GenderRace.Unknown); - } - - protected override void DrawNew() - { - ImGui.TableNextColumn(); - CopyToClipboardButton("Copy all current SHP manipulations to clipboard."u8, - new Lazy(() => MetaDictionary.SerializeTo([], Editor.Shp))); - - ImGui.TableNextColumn(); - var canAdd = !Editor.Contains(Identifier) && _identifierValid; - var tt = canAdd - ? "Stage this edit."u8 - : _identifierValid - ? "This entry does not contain a valid shape key."u8 - : "This entry is already edited."u8; - if (ImUtf8.IconButton(FontAwesomeIcon.Plus, tt, disabled: !canAdd)) - Editor.Changes |= Editor.TryAdd(Identifier, ShpEntry.True); - - DrawIdentifierInput(ref Identifier); - DrawEntry(ref Entry, true); - } - - protected override void DrawEntry(ShpIdentifier identifier, ShpEntry entry) - { - DrawMetaButtons(identifier, entry); - DrawIdentifier(identifier); - - if (DrawEntry(ref entry, false)) - Editor.Changes |= Editor.Update(identifier, entry); - } - - protected override IEnumerable<(ShpIdentifier, ShpEntry)> Enumerate() - => Editor.Shp - .OrderBy(kvp => kvp.Key.Shape) - .ThenBy(kvp => kvp.Key.Slot) - .ThenBy(kvp => kvp.Key.Id) - .ThenBy(kvp => kvp.Key.ConnectorCondition) - .Select(kvp => (kvp.Key, kvp.Value)); - - protected override int Count - => Editor.Shp.Count; - - private bool DrawIdentifierInput(ref ShpIdentifier identifier) - { - ImGui.TableNextColumn(); - var changes = DrawHumanSlot(ref identifier); - - ImGui.TableNextColumn(); - changes |= DrawGenderRaceConditionInput(ref identifier); - - ImGui.TableNextColumn(); - changes |= DrawPrimaryId(ref identifier); - - ImGui.TableNextColumn(); - changes |= DrawShapeKeyInput(ref identifier, ref _buffer, ref _identifierValid); - - ImGui.TableNextColumn(); - changes |= DrawConnectorConditionInput(ref identifier); - return changes; - } - - private static void DrawIdentifier(ShpIdentifier identifier) - { - ImGui.TableNextColumn(); - - ImUtf8.TextFramed(SlotName(identifier.Slot), FrameColor); - Im.Tooltip.OnHover("Model Slot"u8); - - ImGui.TableNextColumn(); - if (identifier.GenderRaceCondition is not GenderRace.Unknown) - { - ImUtf8.TextFramed($"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})", FrameColor); - Im.Tooltip.OnHover("Gender & Race Code for this shape key to be set."); - } - else - { - ImUtf8.TextFramed("Any Gender & Race"u8, FrameColor); - } - - ImGui.TableNextColumn(); - if (identifier.Id.HasValue) - ImUtf8.TextFramed($"{identifier.Id.Value.Id}", FrameColor); - else - ImUtf8.TextFramed("All IDs"u8, FrameColor); - Im.Tooltip.OnHover("Primary ID"u8); - - ImGui.TableNextColumn(); - ImUtf8.TextFramed(identifier.Shape.AsSpan, FrameColor); - - ImGui.TableNextColumn(); - if (identifier.ConnectorCondition is not ShapeConnectorCondition.None) - { - ImUtf8.TextFramed($"{identifier.ConnectorCondition}", FrameColor); - Im.Tooltip.OnHover("Connector condition for this shape to be activated."); - } - } - - private static bool DrawEntry(ref ShpEntry entry, bool disabled) - { - using var dis = ImRaii.Disabled(disabled); - ImGui.TableNextColumn(); - var value = entry.Value; - var changes = ImUtf8.Checkbox("##shpEntry"u8, ref value); - if (changes) - entry = new ShpEntry(value); - Im.Tooltip.OnHover("Whether to enable or disable this shape key for the selected items."); - return changes; - } - - public static bool DrawPrimaryId(ref ShpIdentifier identifier, float unscaledWidth = 100) - { - var allSlots = identifier.Slot is HumanSlot.Unknown; - var all = !identifier.Id.HasValue; - var ret = false; - using (ImRaii.Disabled(allSlots)) - { - if (ImUtf8.Checkbox("##shpAll"u8, ref all)) - { - identifier = identifier with { Id = all ? null : 0 }; - ret = true; - } - } - - Im.Tooltip.OnHover(allSlots ? "When using all slots, you also need to use all IDs."u8 : "Enable this shape key for all model IDs."u8); - - Im.Line.Same(0, Im.Style.ItemInnerSpacing.X); - if (all) - { - using var style = ImStyleDouble.ButtonTextAlign.Push(new Vector2(0.05f, 0.5f)); - ImUtf8.TextFramed("All IDs"u8, ImGuiColor.FrameBackground.Get(all || allSlots ? Im.Style.DisabledAlpha : 1f).Color, - new Vector2(unscaledWidth, 0), ImGuiColor.TextDisabled.Get().Color); - } - else - { - var max = identifier.Slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1; - if (IdInput("##shpPrimaryId"u8, unscaledWidth, identifier.Id.GetValueOrDefault(0).Id, out var setId, 0, max, false)) - { - identifier = identifier with { Id = setId }; - ret = true; - } - } - - Im.Tooltip.OnHover("Primary ID - You can usually find this as the 'e####' part of an item path or similar for customizations."u8); - - return ret; - } - - public bool DrawHumanSlot(ref ShpIdentifier identifier, float unscaledWidth = 170) - { - var ret = false; - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - using (var combo = ImUtf8.Combo("##shpSlot"u8, SlotName(identifier.Slot))) - { - if (combo) - foreach (var slot in AvailableSlots) - { - if (!ImUtf8.Selectable(SlotName(slot), slot == identifier.Slot) || slot == identifier.Slot) - continue; - - ret = true; - if (slot is HumanSlot.Unknown) - { - identifier = identifier with - { - Id = null, - Slot = slot, - }; - } - else - { - identifier = identifier with - { - Id = identifier.Id.HasValue - ? (PrimaryId)Math.Clamp(identifier.Id.Value.Id, 0, - slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1) - : null, - Slot = slot, - ConnectorCondition = Identifier.ConnectorCondition switch - { - ShapeConnectorCondition.Wrists when slot is HumanSlot.Body or HumanSlot.Hands => ShapeConnectorCondition.Wrists, - ShapeConnectorCondition.Waist when slot is HumanSlot.Body or HumanSlot.Legs => ShapeConnectorCondition.Waist, - ShapeConnectorCondition.Ankles when slot is HumanSlot.Legs or HumanSlot.Feet => ShapeConnectorCondition.Ankles, - _ => ShapeConnectorCondition.None, - }, - }; - ret = true; - } - } - } - - Im.Tooltip.OnHover("Model Slot"u8); - return ret; - } - - public static unsafe bool DrawShapeKeyInput(ref ShpIdentifier identifier, ref ShapeAttributeString buffer, ref bool valid, - float unscaledWidth = 200) - { - var ret = false; - var ptr = Unsafe.AsPointer(ref buffer); - var span = new Span(ptr, ShapeAttributeString.MaxLength + 1); - using (ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, !valid)) - { - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - if (ImUtf8.InputText("##shpShape"u8, span, out int newLength, "Shape Key..."u8)) - { - buffer.ForceLength((byte)newLength); - valid = buffer.ValidateCustomShapeString(); - if (valid) - identifier = identifier with { Shape = buffer }; - ret = true; - } - } - - Im.Tooltip.OnHover("Supported shape keys need to have the format `shpx_*` and a maximum length of 30 characters."u8); - return ret; - } - - private static bool DrawConnectorConditionInput(ref ShpIdentifier identifier, float unscaledWidth = 80) - { - var ret = false; - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - var (showWrists, showWaist, showAnkles, disable) = identifier.Slot switch - { - HumanSlot.Unknown => (true, true, true, false), - HumanSlot.Body => (true, true, false, false), - HumanSlot.Legs => (false, true, true, false), - HumanSlot.Hands => (true, false, false, false), - HumanSlot.Feet => (false, false, true, false), - _ => (false, false, false, true), - }; - using var disabled = ImRaii.Disabled(disable); - using (var combo = ImUtf8.Combo("##shpCondition"u8, $"{identifier.ConnectorCondition}")) - { - if (combo) - { - if (ImUtf8.Selectable("None"u8, identifier.ConnectorCondition is ShapeConnectorCondition.None)) - identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.None }; - - if (showWrists && ImUtf8.Selectable("Wrists"u8, identifier.ConnectorCondition is ShapeConnectorCondition.Wrists)) - identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.Wrists }; - - if (showWaist && ImUtf8.Selectable("Waist"u8, identifier.ConnectorCondition is ShapeConnectorCondition.Waist)) - identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.Waist }; - - if (showAnkles && ImUtf8.Selectable("Ankles"u8, identifier.ConnectorCondition is ShapeConnectorCondition.Ankles)) - identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.Ankles }; - } - } - - Im.Tooltip.OnHover( - "Only activate this shape key if any custom connector shape keys (shpx_[wr|wa|an]_*) are also enabled through matching attributes."u8); - return ret; - } - - private static bool DrawGenderRaceConditionInput(ref ShpIdentifier identifier, float unscaledWidth = 250) - { - var ret = false; - Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); - - using (var combo = ImUtf8.Combo("##shpGenderRace"u8, identifier.GenderRaceCondition is GenderRace.Unknown - ? "Any Gender & Race" - : $"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})")) - { - if (combo) - { - if (ImUtf8.Selectable("Any Gender & Race"u8, identifier.GenderRaceCondition is GenderRace.Unknown) - && identifier.GenderRaceCondition is not GenderRace.Unknown) - { - identifier = identifier with { GenderRaceCondition = GenderRace.Unknown }; - ret = true; - } - - foreach (var gr in ShapeAttributeHashSet.GenderRaceValues.Skip(1)) - { - if (ImUtf8.Selectable($"{gr.ToName()} ({gr.ToRaceCode()})", identifier.GenderRaceCondition == gr) - && identifier.GenderRaceCondition != gr) - { - identifier = identifier with { GenderRaceCondition = gr }; - ret = true; - } - } - } - } - - Im.Tooltip.OnHover( - "Only activate this shape key for this gender & race code."u8); - - return ret; - } - - public static ReadOnlySpan AvailableSlots - => - [ - HumanSlot.Unknown, - HumanSlot.Head, - HumanSlot.Body, - HumanSlot.Hands, - HumanSlot.Legs, - HumanSlot.Feet, - HumanSlot.Ears, - HumanSlot.Neck, - HumanSlot.Wrists, - HumanSlot.RFinger, - HumanSlot.LFinger, - HumanSlot.Glasses, - HumanSlot.Hair, - HumanSlot.Face, - HumanSlot.Ear, - ]; - - public static ReadOnlySpan SlotName(HumanSlot slot) - => slot switch - { - HumanSlot.Unknown => "All Slots"u8, - HumanSlot.Head => "Equipment: Head"u8, - HumanSlot.Body => "Equipment: Body"u8, - HumanSlot.Hands => "Equipment: Hands"u8, - HumanSlot.Legs => "Equipment: Legs"u8, - HumanSlot.Feet => "Equipment: Feet"u8, - HumanSlot.Ears => "Equipment: Ears"u8, - HumanSlot.Neck => "Equipment: Neck"u8, - HumanSlot.Wrists => "Equipment: Wrists"u8, - HumanSlot.RFinger => "Equipment: Right Finger"u8, - HumanSlot.LFinger => "Equipment: Left Finger"u8, - HumanSlot.Glasses => "Equipment: Glasses"u8, - HumanSlot.Hair => "Customization: Hair"u8, - HumanSlot.Face => "Customization: Face"u8, - HumanSlot.Ear => "Customization: Ears"u8, - _ => "Unknown"u8, - }; -} +using ImSharp; +using Luna; +using Newtonsoft.Json.Linq; +using Penumbra.Collections.Cache; +using Penumbra.GameData.Enums; +using Penumbra.GameData.Structs; +using Penumbra.Meta; +using Penumbra.Meta.Files; +using Penumbra.Meta.Manipulations; +using Penumbra.Mods.Editor; +using Penumbra.UI.Classes; + +namespace Penumbra.UI.AdvancedWindow.Meta; + +public sealed class ShpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFiles) + : MetaDrawer(editor, metaFiles) +{ + public override ReadOnlySpan Label + => "Shape Keys (SHP)###SHP"u8; + + private ShapeAttributeString _buffer = ShapeAttributeString.TryRead("shpx_"u8, out var s) ? s : ShapeAttributeString.Empty; + private bool _identifierValid; + + public override int NumColumns + => 8; + + public override float ColumnHeight + => Im.Style.FrameHeightWithSpacing; + + protected override void Initialize() + => Identifier = new ShpIdentifier(HumanSlot.Unknown, null, ShapeAttributeString.Empty, ShapeConnectorCondition.None, + GenderRace.Unknown); + + protected override void DrawNew() + { + Im.Table.NextColumn(); + CopyToClipboardButton("Copy all current SHP manipulations to clipboard."u8, + new Lazy(() => MetaDictionary.SerializeTo([], Editor.Shp))); + + Im.Table.NextColumn(); + var canAdd = !Editor.Contains(Identifier) && _identifierValid; + var tt = canAdd + ? "Stage this edit."u8 + : _identifierValid + ? "This entry does not contain a valid shape key."u8 + : "This entry is already edited."u8; + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, !canAdd)) + Editor.Changes |= Editor.TryAdd(Identifier, ShpEntry.True); + + DrawIdentifierInput(ref Identifier); + DrawEntry(ref Entry, true); + } + + protected override void DrawEntry(ShpIdentifier identifier, ShpEntry entry) + { + DrawMetaButtons(identifier, entry); + DrawIdentifier(identifier); + + if (DrawEntry(ref entry, false)) + Editor.Changes |= Editor.Update(identifier, entry); + } + + protected override IEnumerable<(ShpIdentifier, ShpEntry)> Enumerate() + => Editor.Shp + .OrderBy(kvp => kvp.Key.Shape) + .ThenBy(kvp => kvp.Key.Slot) + .ThenBy(kvp => kvp.Key.Id) + .ThenBy(kvp => kvp.Key.ConnectorCondition) + .Select(kvp => (kvp.Key, kvp.Value)); + + protected override int Count + => Editor.Shp.Count; + + private bool DrawIdentifierInput(ref ShpIdentifier identifier) + { + Im.Table.NextColumn(); + var changes = DrawHumanSlot(ref identifier); + + Im.Table.NextColumn(); + changes |= DrawGenderRaceConditionInput(ref identifier); + + Im.Table.NextColumn(); + changes |= DrawPrimaryId(ref identifier); + + Im.Table.NextColumn(); + changes |= DrawShapeKeyInput(ref identifier, ref _buffer, ref _identifierValid); + + Im.Table.NextColumn(); + changes |= DrawConnectorConditionInput(ref identifier); + return changes; + } + + private static void DrawIdentifier(ShpIdentifier identifier) + { + Im.Table.NextColumn(); + + ImEx.TextFramed(SlotName(identifier.Slot), default, FrameColor); + Im.Tooltip.OnHover("Model Slot"u8); + + Im.Table.NextColumn(); + if (identifier.GenderRaceCondition is not GenderRace.Unknown) + { + ImEx.TextFramed($"{identifier.GenderRaceCondition.ToNameU8()} ({identifier.GenderRaceCondition.ToRaceCode()})", default, + FrameColor); + Im.Tooltip.OnHover("Gender & Race Code for this shape key to be set."); + } + else + { + ImEx.TextFramed("Any Gender & Race"u8, default, FrameColor); + } + + Im.Table.NextColumn(); + if (identifier.Id.HasValue) + ImEx.TextFramed($"{identifier.Id.Value.Id}", default, FrameColor); + else + ImEx.TextFramed("All IDs"u8, default, FrameColor); + Im.Tooltip.OnHover("Primary ID"u8); + + Im.Table.NextColumn(); + ImEx.TextFramed(identifier.Shape.AsSpan, default, FrameColor); + + Im.Table.NextColumn(); + if (identifier.ConnectorCondition is not ShapeConnectorCondition.None) + { + ImEx.TextFramed($"{identifier.ConnectorCondition}", default, FrameColor); + Im.Tooltip.OnHover("Connector condition for this shape to be activated."u8); + } + } + + private static bool DrawEntry(ref ShpEntry entry, bool disabled) + { + using var dis = Im.Disabled(disabled); + Im.Table.NextColumn(); + var value = entry.Value; + var changes = Im.Checkbox("##shpEntry"u8, ref value); + if (changes) + entry = new ShpEntry(value); + Im.Tooltip.OnHover("Whether to enable or disable this shape key for the selected items."u8); + return changes; + } + + public static bool DrawPrimaryId(ref ShpIdentifier identifier, float unscaledWidth = 100) + { + var allSlots = identifier.Slot is HumanSlot.Unknown; + var all = !identifier.Id.HasValue; + var ret = false; + using (Im.Disabled(allSlots)) + { + if (Im.Checkbox("##shpAll"u8, ref all)) + { + identifier = identifier with { Id = all ? null : 0 }; + ret = true; + } + } + + Im.Tooltip.OnHover(allSlots ? "When using all slots, you also need to use all IDs."u8 : "Enable this shape key for all model IDs."u8); + + Im.Line.SameInner(); + if (all) + { + using var style = ImStyleDouble.ButtonTextAlign.Push(new Vector2(0.05f, 0.5f)); + ImEx.TextFramed("All IDs"u8, new Vector2(unscaledWidth, 0), + ImGuiColor.FrameBackground.Get(all || allSlots ? Im.Style.DisabledAlpha : 1f).Color, + ImGuiColor.TextDisabled.Get().Color); + } + else + { + var max = identifier.Slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1; + if (IdInput("##shpPrimaryId"u8, unscaledWidth, identifier.Id.GetValueOrDefault(0).Id, out var setId, 0, max, false)) + { + identifier = identifier with { Id = setId }; + ret = true; + } + } + + Im.Tooltip.OnHover("Primary ID - You can usually find this as the 'e####' part of an item path or similar for customizations."u8); + + return ret; + } + + public bool DrawHumanSlot(ref ShpIdentifier identifier, float unscaledWidth = 170) + { + var ret = false; + Im.Item.SetNextWidthScaled(unscaledWidth); + using (var combo = Im.Combo.Begin("##shpSlot"u8, SlotName(identifier.Slot))) + { + if (combo) + foreach (var slot in AvailableSlots) + { + if (!Im.Selectable(SlotName(slot), slot == identifier.Slot) || slot == identifier.Slot) + continue; + + ret = true; + if (slot is HumanSlot.Unknown) + { + identifier = identifier with + { + Id = null, + Slot = slot, + }; + } + else + { + identifier = identifier with + { + Id = identifier.Id.HasValue + ? (PrimaryId)Math.Clamp(identifier.Id.Value.Id, 0, + slot.ToSpecificEnum() is BodySlot ? byte.MaxValue : ExpandedEqpGmpBase.Count - 1) + : null, + Slot = slot, + ConnectorCondition = Identifier.ConnectorCondition switch + { + ShapeConnectorCondition.Wrists when slot is HumanSlot.Body or HumanSlot.Hands => ShapeConnectorCondition.Wrists, + ShapeConnectorCondition.Waist when slot is HumanSlot.Body or HumanSlot.Legs => ShapeConnectorCondition.Waist, + ShapeConnectorCondition.Ankles when slot is HumanSlot.Legs or HumanSlot.Feet => ShapeConnectorCondition.Ankles, + _ => ShapeConnectorCondition.None, + }, + }; + ret = true; + } + } + } + + Im.Tooltip.OnHover("Model Slot"u8); + return ret; + } + + public static unsafe bool DrawShapeKeyInput(ref ShpIdentifier identifier, ref ShapeAttributeString buffer, ref bool valid, + float unscaledWidth = 200) + { + var ret = false; + var ptr = Unsafe.AsPointer(ref buffer); + var span = new Span(ptr, ShapeAttributeString.MaxLength + 1); + using (ImStyleBorder.Frame.Push(Colors.RegexWarningBorder, Im.Style.GlobalScale, !valid)) + { + Im.Item.SetNextWidthScaled(unscaledWidth); + if (Im.Input.Text("##shpShape"u8, span, out ulong newLength, "Shape Key..."u8)) + { + buffer.ForceLength((byte)newLength); + valid = buffer.ValidateCustomShapeString(); + if (valid) + identifier = identifier with { Shape = buffer }; + ret = true; + } + } + + Im.Tooltip.OnHover("Supported shape keys need to have the format `shpx_*` and a maximum length of 30 characters."u8); + return ret; + } + + private static bool DrawConnectorConditionInput(ref ShpIdentifier identifier, float unscaledWidth = 80) + { + var ret = false; + Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); + var (showWrists, showWaist, showAnkles, disable) = identifier.Slot switch + { + HumanSlot.Unknown => (true, true, true, false), + HumanSlot.Body => (true, true, false, false), + HumanSlot.Legs => (false, true, true, false), + HumanSlot.Hands => (true, false, false, false), + HumanSlot.Feet => (false, false, true, false), + _ => (false, false, false, true), + }; + using var disabled = Im.Disabled(disable); + using (var combo = Im.Combo.Begin("##shpCondition"u8, $"{identifier.ConnectorCondition}")) + { + if (combo) + { + if (Im.Selectable("None"u8, identifier.ConnectorCondition is ShapeConnectorCondition.None)) + identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.None }; + + if (showWrists && Im.Selectable("Wrists"u8, identifier.ConnectorCondition is ShapeConnectorCondition.Wrists)) + identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.Wrists }; + + if (showWaist && Im.Selectable("Waist"u8, identifier.ConnectorCondition is ShapeConnectorCondition.Waist)) + identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.Waist }; + + if (showAnkles && Im.Selectable("Ankles"u8, identifier.ConnectorCondition is ShapeConnectorCondition.Ankles)) + identifier = identifier with { ConnectorCondition = ShapeConnectorCondition.Ankles }; + } + } + + Im.Tooltip.OnHover( + "Only activate this shape key if any custom connector shape keys (shpx_[wr|wa|an]_*) are also enabled through matching attributes."u8); + return ret; + } + + private static bool DrawGenderRaceConditionInput(ref ShpIdentifier identifier, float unscaledWidth = 250) + { + var ret = false; + Im.Item.SetNextWidth(unscaledWidth * Im.Style.GlobalScale); + + using (var combo = Im.Combo.Begin("##shpGenderRace"u8, identifier.GenderRaceCondition is GenderRace.Unknown + ? "Any Gender & Race" + : $"{identifier.GenderRaceCondition.ToName()} ({identifier.GenderRaceCondition.ToRaceCode()})")) + { + if (combo) + { + if (Im.Selectable("Any Gender & Race"u8, identifier.GenderRaceCondition is GenderRace.Unknown) + && identifier.GenderRaceCondition is not GenderRace.Unknown) + { + identifier = identifier with { GenderRaceCondition = GenderRace.Unknown }; + ret = true; + } + + foreach (var gr in ShapeAttributeHashSet.GenderRaceValues.Skip(1)) + { + if (Im.Selectable($"{gr.ToNameU8()} ({gr.ToRaceCode()})", identifier.GenderRaceCondition == gr) + && identifier.GenderRaceCondition != gr) + { + identifier = identifier with { GenderRaceCondition = gr }; + ret = true; + } + } + } + } + + Im.Tooltip.OnHover("Only activate this shape key for this gender & race code."u8); + + return ret; + } + + public static ReadOnlySpan AvailableSlots + => + [ + HumanSlot.Unknown, + HumanSlot.Head, + HumanSlot.Body, + HumanSlot.Hands, + HumanSlot.Legs, + HumanSlot.Feet, + HumanSlot.Ears, + HumanSlot.Neck, + HumanSlot.Wrists, + HumanSlot.RFinger, + HumanSlot.LFinger, + HumanSlot.Glasses, + HumanSlot.Hair, + HumanSlot.Face, + HumanSlot.Ear, + ]; + + public static ReadOnlySpan SlotName(HumanSlot slot) + => slot switch + { + HumanSlot.Unknown => "All Slots"u8, + HumanSlot.Head => "Equipment: Head"u8, + HumanSlot.Body => "Equipment: Body"u8, + HumanSlot.Hands => "Equipment: Hands"u8, + HumanSlot.Legs => "Equipment: Legs"u8, + HumanSlot.Feet => "Equipment: Feet"u8, + HumanSlot.Ears => "Equipment: Ears"u8, + HumanSlot.Neck => "Equipment: Neck"u8, + HumanSlot.Wrists => "Equipment: Wrists"u8, + HumanSlot.RFinger => "Equipment: Right Finger"u8, + HumanSlot.LFinger => "Equipment: Left Finger"u8, + HumanSlot.Glasses => "Equipment: Glasses"u8, + HumanSlot.Hair => "Customization: Hair"u8, + HumanSlot.Face => "Customization: Face"u8, + HumanSlot.Ear => "Customization: Ears"u8, + _ => "Unknown"u8, + }; +} diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs index 740f1d7f..93e67d16 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs @@ -1,10 +1,5 @@ -using Dalamud.Interface; -using Dalamud.Interface.ImGuiNotification; -using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; using ImSharp; using OtterGui; -using OtterGui.Text; using Penumbra.GameData.Data; using Penumbra.GameData.Enums; using Penumbra.GameData.Files; @@ -29,17 +24,17 @@ public partial class ModEditWindow private void DrawGenderRaceSelector(PbdTab tab) { - using var group = ImUtf8.Group(); - var width = ImUtf8.CalcTextSize("Hellsguard - Female (Child)____0000"u8).X + 2 * Im.Style.WindowPadding.X; + using var group = Im.Group(); + var width = Im.Font.CalculateSize("Hellsguard - Female (Child)____0000"u8).X + 2 * Im.Style.WindowPadding.X; using (ImStyleSingle.FrameRounding.Push(0) .Push(ImStyleDouble.ItemSpacing, Vector2.Zero)) { Im.Item.SetNextWidth(width); - ImUtf8.InputText("##grFilter"u8, ref _pbdData.RaceCodeFilter, "Filter..."u8); + Im.Input.Text("##grFilter"u8, ref _pbdData.RaceCodeFilter, "Filter..."u8); } - using var child = ImUtf8.Child("GenderRace"u8, - new Vector2(width, ImGui.GetContentRegionMax().Y - Im.Style.FrameHeight - Im.Style.WindowPadding.Y), true); + using var child = Im.Child.Begin("GenderRace"u8, + new Vector2(width, Im.ContentRegion.Maximum.Y - Im.Style.FrameHeight - Im.Style.WindowPadding.Y), true); if (!child) return; @@ -52,9 +47,9 @@ public partial class ModEditWindow if (!name.Contains(_pbdData.RaceCodeFilter) && !raceCode.Contains(_pbdData.RaceCodeFilter)) continue; - using var id = ImUtf8.PushId(index); + using var id = Im.Id.Push(index); using var color = ImGuiColor.Text.Push(Im.Style[ImGuiColor.TextDisabled], deformer.RacialDeformer.IsEmpty); - if (ImUtf8.Selectable(name, deformer.GenderRace == _pbdData.SelectedRaceCode)) + if (Im.Selectable(name, deformer.GenderRace == _pbdData.SelectedRaceCode)) { _pbdData.SelectedRaceCode = deformer.GenderRace; _pbdData.SelectedDeformer = deformer.RacialDeformer; @@ -62,32 +57,32 @@ public partial class ModEditWindow Im.Line.Same(); color.Push(ImGuiColor.Text, metaColor); - ImUtf8.TextRightAligned(raceCode); + ImEx.TextRightAligned(raceCode); } } private void DrawBoneSelector() { - using var group = ImUtf8.Group(); + using var group = Im.Group(); var width = 200 * Im.Style.GlobalScale; using (ImStyleSingle.FrameRounding.Push(0) .Push(ImStyleDouble.ItemSpacing, Vector2.Zero)) { Im.Item.SetNextWidth(width); - ImUtf8.InputText("##boneFilter"u8, ref _pbdData.BoneFilter, "Filter..."u8); + Im.Input.Text("##boneFilter"u8, ref _pbdData.BoneFilter, "Filter..."u8); } - using var child = ImUtf8.Child("Bone"u8, - new Vector2(width, ImGui.GetContentRegionMax().Y - Im.Style.FrameHeight - Im.Style.WindowPadding.Y), true); + using var child = Im.Child.Begin("Bone"u8, + new Vector2(width, Im.ContentRegion.Maximum.Y - Im.Style.FrameHeight - Im.Style.WindowPadding.Y), true); if (!child) return; - if (_pbdData.SelectedDeformer == null) + if (_pbdData.SelectedDeformer is null) return; if (_pbdData.SelectedDeformer.IsEmpty) { - ImUtf8.Text(""u8); + Im.Text(""u8); } else { @@ -97,7 +92,7 @@ public partial class ModEditWindow b => b.Contains(_pbdData.BoneFilter), bone => { - if (ImUtf8.Selectable(bone, bone == _pbdData.SelectedBone)) + if (Im.Selectable(bone, bone == _pbdData.SelectedBone)) _pbdData.SelectedBone = bone; }); ImGuiClip.DrawEndDummy(remainder, height); @@ -106,32 +101,32 @@ public partial class ModEditWindow private bool DrawBoneData(PbdTab tab, bool disabled) { - using var child = ImUtf8.Child("Data"u8, - Im.ContentRegion.Available with { Y = ImGui.GetContentRegionMax().Y - Im.Style.WindowPadding.Y }, true); + using var child = Im.Child.Begin("Data"u8, + Im.ContentRegion.Available with { Y = Im.ContentRegion.Maximum.Y - Im.Style.WindowPadding.Y }, true); if (!child) return false; - if (_pbdData.SelectedBone == null) + if (_pbdData.SelectedBone is null) return false; if (!_pbdData.SelectedDeformer!.DeformMatrices.TryGetValue(_pbdData.SelectedBone, out var matrix)) return false; - var width = UiBuilder.MonoFont.GetCharAdvance('0') * 12 + Im.Style.FramePadding.X * 2; + var width = Im.Font.Mono.GetCharacterAdvance('0') * 12 + Im.Style.FramePadding.X * 2; var dummyHeight = Im.Style.TextHeight / 2; var ret = DrawAddNewBone(tab, disabled, matrix, width); - ImUtf8.Dummy(0, dummyHeight); + Im.Dummy(0, dummyHeight); Im.Separator(); - ImUtf8.Dummy(0, dummyHeight); + Im.Dummy(0, dummyHeight); ret |= DrawDeformerMatrix(disabled, matrix, width); - ImUtf8.Dummy(0, dummyHeight); + Im.Dummy(0, dummyHeight); ret |= DrawCopyPasteButtons(disabled, matrix, width); - ImUtf8.Dummy(0, dummyHeight); + Im.Dummy(0, dummyHeight); Im.Separator(); - ImUtf8.Dummy(0, dummyHeight); + Im.Dummy(0, dummyHeight); ret |= DrawDecomposedData(disabled, matrix, width); return ret; @@ -140,23 +135,23 @@ public partial class ModEditWindow private bool DrawAddNewBone(PbdTab tab, bool disabled, in TransformMatrix matrix, float width) { var ret = false; - ImUtf8.TextFrameAligned("Copy the values of the bone "u8); - Im.Line.Same(0, 0); + ImEx.TextFrameAligned("Copy the values of the bone "u8); + Im.Line.NoSpacing(); using (ImGuiColor.Text.Push(ColorId.NewMod.Value())) { - ImUtf8.TextFrameAligned(_pbdData.SelectedBone); + ImEx.TextFrameAligned(_pbdData.SelectedBone!); } - Im.Line.Same(0, 0); - ImUtf8.TextFrameAligned(" to a new bone of name"u8); + Im.Line.NoSpacing(); + ImEx.TextFrameAligned(" to a new bone of name"u8); var fullWidth = width * 4 + Im.Style.ItemSpacing.X * 3; Im.Item.SetNextWidth(fullWidth); - ImUtf8.InputText("##newBone"u8, ref _pbdData.NewBoneName, "New Bone Name..."u8); - ImUtf8.TextFrameAligned("for all races that have a corresponding bone."u8); - Im.Line.Same(0, fullWidth - width - ImGui.GetItemRectSize().X); - if (ImUtf8.ButtonEx("Apply"u8, ""u8, new Vector2(width, 0), - disabled || _pbdData.NewBoneName.Length == 0 || _pbdData.SelectedBone == null)) + Im.Input.Text("##newBone"u8, ref _pbdData.NewBoneName, "New Bone Name..."u8); + ImEx.TextFrameAligned("for all races that have a corresponding bone."u8); + Im.Line.Same(0, fullWidth - width - Im.Item.Size.X); + if (ImEx.Button("Apply"u8, new Vector2(width, 0), StringU8.Empty, + disabled || _pbdData.NewBoneName.Length is 0 || _pbdData.SelectedBone is null)) { foreach (var deformer in tab.File.Deformers) { @@ -167,8 +162,7 @@ public partial class ModEditWindow && deformer.RacialDeformer.DeformMatrices.TryGetValue(_pbdData.NewBoneName, out var newBoneMatrix) && !newBoneMatrix.Equals(existingMatrix)) Penumbra.Messager.AddMessage(new Luna.Notification( - $"Could not add deformer matrix to {deformer.GenderRace.ToName()}, Bone {_pbdData.NewBoneName} because it already has a deformer that differs from the intended one.", - NotificationType.Warning)); + $"Could not add deformer matrix to {deformer.GenderRace.ToName()}, Bone {_pbdData.NewBoneName} because it already has a deformer that differs from the intended one.")); else ret = true; } @@ -176,31 +170,30 @@ public partial class ModEditWindow _pbdData.NewBoneName = string.Empty; } - if (ImUtf8.ButtonEx("Copy Values to Single New Bone Entry"u8, ""u8, new Vector2(fullWidth, 0), - disabled || _pbdData.NewBoneName.Length == 0 || _pbdData.SelectedDeformer!.DeformMatrices.ContainsKey(_pbdData.NewBoneName))) + if (ImEx.Button("Copy Values to Single New Bone Entry"u8, new Vector2(fullWidth, 0), StringU8.Empty, + disabled || _pbdData.NewBoneName.Length is 0 || _pbdData.SelectedDeformer!.DeformMatrices.ContainsKey(_pbdData.NewBoneName))) { _pbdData.SelectedDeformer!.DeformMatrices[_pbdData.NewBoneName] = matrix; ret = true; _pbdData.NewBoneName = string.Empty; } - return ret; } private bool DrawDeformerMatrix(bool disabled, in TransformMatrix matrix, float width) { - using var font = ImRaii.PushFont(UiBuilder.MonoFont); - using var _ = ImRaii.Disabled(disabled); + using var font = Im.Font.PushMono(); + using var _ = Im.Disabled(disabled); var ret = false; for (var i = 0; i < 3; ++i) { for (var j = 0; j < 4; ++j) { - using var id = ImUtf8.PushId(i * 4 + j); + using var id = Im.Id.Push(i * 4 + j); Im.Item.SetNextWidth(width); var tmp = matrix[i, j]; - if (ImUtf8.InputScalar(""u8, ref tmp, "% 12.8f"u8)) + if (Im.Input.Scalar(StringU8.Empty, ref tmp, "% 12.8f"u8)) { ret = true; _pbdData.SelectedDeformer!.DeformMatrices[_pbdData.SelectedBone!] = matrix.ChangeValue(i, j, tmp); @@ -218,13 +211,13 @@ public partial class ModEditWindow private bool DrawCopyPasteButtons(bool disabled, in TransformMatrix matrix, float width) { var size = new Vector2(width, 0); - if (ImUtf8.Button("Copy Values"u8, size)) + if (Im.Button("Copy Values"u8, size)) _pbdData.CopiedMatrix = matrix; Im.Line.Same(); var ret = false; - if (ImUtf8.ButtonEx("Paste Values"u8, ""u8, size, disabled || !_pbdData.CopiedMatrix.HasValue)) + if (ImEx.Button("Paste Values"u8, size, StringU8.Empty, disabled || !_pbdData.CopiedMatrix.HasValue)) { _pbdData.SelectedDeformer!.DeformMatrices[_pbdData.SelectedBone!] = _pbdData.CopiedMatrix!.Value; ret = true; @@ -234,7 +227,7 @@ public partial class ModEditWindow Im.Line.Same(); if (modifier) { - if (ImUtf8.ButtonEx("Delete"u8, "Delete this bone entry."u8, size, disabled)) + if (ImEx.Button("Delete"u8, size, "Delete this bone entry."u8, disabled)) { ret |= _pbdData.SelectedDeformer!.DeformMatrices.Remove(_pbdData.SelectedBone!); _pbdData.SelectedBone = null; @@ -242,7 +235,7 @@ public partial class ModEditWindow } else { - ImUtf8.ButtonEx("Delete"u8, $"Delete this bone entry. Hold {_config.DeleteModModifier} to delete.", size, true); + ImEx.Button("Delete"u8, size, $"Delete this bone entry. Hold {_config.DeleteModModifier} to delete.", true); } return ret; @@ -256,56 +249,56 @@ public partial class ModEditWindow if (!matrix.TryDecompose(out var scale, out var rotation, out var translation)) return false; - using (ImUtf8.Group()) + using (Im.Group()) { - using var font = ImRaii.PushFont(UiBuilder.MonoFont); - using var _ = ImRaii.Disabled(disabled); + using var font = Im.Font.PushMono(); + using var _ = Im.Disabled(disabled); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##ScaleX"u8, ref scale.X, "% 12.8f"u8); + ret |= Im.Input.Scalar("##ScaleX"u8, ref scale.X, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##ScaleY"u8, ref scale.Y, "% 12.8f"u8); + ret |= Im.Input.Scalar("##ScaleY"u8, ref scale.Y, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##ScaleZ"u8, ref scale.Z, "% 12.8f"u8); + ret |= Im.Input.Scalar("##ScaleZ"u8, ref scale.Z, "% 12.8f"u8); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##TranslationX"u8, ref translation.X, "% 12.8f"u8); + ret |= Im.Input.Scalar("##TranslationX"u8, ref translation.X, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##TranslationY"u8, ref translation.Y, "% 12.8f"u8); + ret |= Im.Input.Scalar("##TranslationY"u8, ref translation.Y, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##TranslationZ"u8, ref translation.Z, "% 12.8f"u8); + ret |= Im.Input.Scalar("##TranslationZ"u8, ref translation.Z, "% 12.8f"u8); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##RotationR"u8, ref rotation.W, "% 12.8f"u8); + ret |= Im.Input.Scalar("##RotationR"u8, ref rotation.W, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##RotationI"u8, ref rotation.X, "% 12.8f"u8); + ret |= Im.Input.Scalar("##RotationI"u8, ref rotation.X, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##RotationJ"u8, ref rotation.Y, "% 12.8f"u8); + ret |= Im.Input.Scalar("##RotationJ"u8, ref rotation.Y, "% 12.8f"u8); Im.Line.Same(); Im.Item.SetNextWidth(width); - ret |= ImUtf8.InputScalar("##RotationK"u8, ref rotation.Z, "% 12.8f"u8); + ret |= Im.Input.Scalar("##RotationK"u8, ref rotation.Z, "% 12.8f"u8); } Im.Line.Same(); - using (ImUtf8.Group()) + using (Im.Group()) { - ImUtf8.TextFrameAligned("Scale"u8); - ImUtf8.TextFrameAligned("Translation"u8); - ImUtf8.TextFrameAligned("Rotation (Quaternion, rijk)"u8); + ImEx.TextFrameAligned("Scale"u8); + ImEx.TextFrameAligned("Translation"u8); + ImEx.TextFrameAligned("Rotation (Quaternion, rijk)"u8); } if (ret) diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs index 407e4c3c..f5f2b022 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs @@ -1,9 +1,7 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; +using Luna; using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.Mods.Editor; using Penumbra.Mods.SubMods; using Penumbra.String.Classes; @@ -35,7 +33,7 @@ public partial class ModEditWindow private void DrawFileTab() { - using var tab = ImRaii.TabItem("File Redirections"); + using var tab = Im.TabBar.BeginItem("File Redirections"u8); if (!tab) return; @@ -47,7 +45,7 @@ public partial class ModEditWindow else DrawFileManagementNormal(); - using var child = ImRaii.Child("##files", -Vector2.One, true); + using var child = Im.Child.Begin("##files"u8, Im.ContentRegion.Available, true); if (!child) return; @@ -62,7 +60,7 @@ public partial class ModEditWindow var height = Im.Style.TextHeightWithSpacing + 2 * Im.Style.CellPadding.Y; var skips = ImGuiClip.GetNecessarySkips(height); - using var table = Im.Table.Begin("##table"u8, 3, TableFlags.RowBackground | TableFlags.BordersInnerVertical, -Vector2.One); + using var table = Im.Table.Begin("##table"u8, 3, TableFlags.RowBackground | TableFlags.BordersInnerVertical, Im.ContentRegion.Available); if (!table) return; @@ -86,22 +84,21 @@ public partial class ModEditWindow void DrawLine((string, string, string, uint) data) { - using var id = ImRaii.PushId(idx++); - ImGui.TableNextColumn(); - if (data.Item4 != 0) - ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, data.Item4); + using var id = Im.Id.Push(idx++); + if (data.Item4 is not 0) + Im.Table.SetBackgroundColor(TableBackgroundTarget.Cell, data.Item4); - ImGuiUtil.CopyOnClickSelectable(data.Item1); - ImGui.TableNextColumn(); - if (data.Item4 != 0) - ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, data.Item4); + ImEx.CopyOnClickSelectable(data.Item1); + Im.Table.NextColumn(); + if (data.Item4 is not 0) + Im.Table.SetBackgroundColor(TableBackgroundTarget.Cell, data.Item4); - ImGuiUtil.CopyOnClickSelectable(data.Item2); - ImGui.TableNextColumn(); - if (data.Item4 != 0) - ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, data.Item4); + ImEx.CopyOnClickSelectable(data.Item2); + Im.Table.NextColumn(); + if (data.Item4 is not 0) + Im.Table.SetBackgroundColor(TableBackgroundTarget.Cell, data.Item4); - ImGuiUtil.CopyOnClickSelectable(data.Item3); + ImEx.CopyOnClickSelectable(data.Item3); } bool Filter((string, string, string, uint) data) @@ -115,22 +112,21 @@ public partial class ModEditWindow private void DrawFilesNormalMode() { - using var list = Im.Table.Begin("##table"u8, 1); - - if (!list) + using var table = Im.Table.Begin("##table"u8, 1); + if (!table) return; foreach (var (i, registry) in _editor.Files.Available.Index().Where(CheckFilter)) { - using var id = ImRaii.PushId(i); - ImGui.TableNextColumn(); + using var id = Im.Id.Push(i); + table.NextColumn(); DrawSelectable(registry, i); if (!_showGamePaths) continue; - using var indent = ImRaii.PushIndent(50f); + using var indent = Im.Indent(50f); for (var j = 0; j < registry.SubModUsage.Count; ++j) { var (subMod, gamePath) = registry.SubModUsage[j]; @@ -154,11 +150,11 @@ public partial class ModEditWindow _ => (null, 0), }; - if (text != null && Im.Item.Hovered()) + if (text is not null && Im.Item.Hovered()) { - using var tt = ImUtf8.Tooltip(); - using var c = ImRaii.DefaultColors(); - ImUtf8.Text(string.Join('\n', text)); + using var tt = Im.Tooltip.Begin(); + using var c = ImGuiColor.Text.PushDefault(); + Im.Text(StringU8.Join((byte) '\n', text)); } @@ -193,12 +189,12 @@ public partial class ModEditWindow } if (Im.Item.RightClicked()) - ImUtf8.OpenPopup("context"u8); + Im.Popup.Open("context"u8); var rightText = DrawFileTooltip(registry, color); Im.Line.Same(); - ImGuiUtil.RightAlign(rightText); + ImEx.TextRightAligned(rightText); } DrawContextMenu(registry, i); @@ -206,16 +202,16 @@ public partial class ModEditWindow private void DrawContextMenu(FileRegistry registry, int i) { - using var context = ImUtf8.Popup("context"u8); + using var context = Im.Popup.Begin("context"u8); if (!context) return; - if (ImUtf8.Selectable("Copy Full File Path")) - ImUtf8.SetClipboardText(registry.File.FullName); + if (Im.Selectable("Copy Full File Path"u8)) + Im.Clipboard.Set(registry.File.FullName); - using (ImRaii.Disabled(registry.CurrentUsage == 0)) + using (Im.Disabled(registry.CurrentUsage is 0)) { - if (ImUtf8.Selectable("Copy Game Paths"u8)) + if (Im.Selectable("Copy Game Paths"u8)) { _cutPaths.Clear(); for (var j = 0; j < registry.SubModUsage.Count; ++j) @@ -228,9 +224,9 @@ public partial class ModEditWindow } } - using (ImRaii.Disabled(registry.CurrentUsage == 0)) + using (Im.Disabled(registry.CurrentUsage is 0)) { - if (ImUtf8.Selectable("Cut Game Paths"u8)) + if (Im.Selectable("Cut Game Paths"u8)) { _cutPaths.Clear(); for (var j = 0; j < registry.SubModUsage.Count; ++j) @@ -244,9 +240,9 @@ public partial class ModEditWindow } } - using (ImRaii.Disabled(_cutPaths.Count == 0)) + using (Im.Disabled(_cutPaths.Count is 0)) { - if (ImUtf8.Selectable("Paste Game Paths"u8)) + if (Im.Selectable("Paste Game Paths"u8)) foreach (var path in _cutPaths) _editor.FileEditor.SetGamePath(_editor.Option!, i, -1, path); } @@ -254,21 +250,21 @@ public partial class ModEditWindow private void PrintGamePath(int i, int j, FileRegistry registry, IModDataContainer _, Utf8GamePath gamePath) { - using var id = ImRaii.PushId(j); - ImGui.TableNextColumn(); + using var id = Im.Id.Push(j); + Im.Table.NextColumn(); var tmp = _fileIdx == i && _pathIdx == j ? _gamePathEdit : gamePath.ToString(); - var pos = ImGui.GetCursorPosX() - Im.Style.FrameHeight; + var pos = Im.Cursor.X - Im.Style.FrameHeight; Im.Item.SetNextWidth(-1); - if (ImGui.InputText(string.Empty, ref tmp, Utf8GamePath.MaxGamePathLength)) + if (Im.Input.Text(StringU8.Empty, ref tmp, maxLength:Utf8GamePath.MaxGamePathLength)) { _fileIdx = i; _pathIdx = j; _gamePathEdit = tmp; } - ImGuiUtil.HoverTooltip("Clear completely to remove the path from this mod."); + Im.Tooltip.OnHover("Clear completely to remove the path from this mod."u8); - if (ImGui.IsItemDeactivatedAfterEdit()) + if (Im.Item.DeactivatedAfterEdit) { if (Utf8GamePath.FromString(_gamePathEdit, out var path)) _editor.FileEditor.SetGamePath(_editor.Option!, _fileIdx, _pathIdx, path); @@ -282,19 +278,14 @@ public partial class ModEditWindow || !path.IsEmpty && !path.Equals(gamePath) && !_editor.FileEditor.CanAddGamePath(path))) { Im.Line.Same(); - ImGui.SetCursorPosX(pos); - using var font = ImRaii.PushFont(UiBuilder.IconFont); - ImGuiUtil.TextColored(0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString()); + Im.Cursor.X = pos; + ImEx.Icon.Draw(FontAwesomeIcon.TimesCircle.Icon(), Rgba32.Red); } else if (tmp.Length > 0 && Path.GetExtension(tmp) != registry.File.Extension) { Im.Line.Same(); - ImGui.SetCursorPosX(pos); - using (ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); - } - + Im.Cursor.X = pos; + ImEx.Icon.Draw(FontAwesomeIcon.ExclamationCircle.Icon(), new Rgba32(0xFF00B0B0)); Im.Tooltip.OnHover("The game path and the file do not have the same extension."u8); } } @@ -302,16 +293,16 @@ 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() - Im.Style.FrameHeight; + var pos = Im.Cursor.X - Im.Style.FrameHeight; Im.Item.SetNextWidth(-1); - if (ImGui.InputTextWithHint("##new", "Add New Path...", ref tmp, Utf8GamePath.MaxGamePathLength)) + if (Im.Input.Text("##new"u8, ref tmp, "Add New Path..."u8, maxLength: Utf8GamePath.MaxGamePathLength)) { _fileIdx = i; _pathIdx = -1; _gamePathEdit = tmp; } - if (ImGui.IsItemDeactivatedAfterEdit()) + if (Im.Item.DeactivatedAfterEdit) { if (Utf8GamePath.FromString(_gamePathEdit, out var path) && !path.IsEmpty) _editor.FileEditor.SetGamePath(_editor.Option!, _fileIdx, _pathIdx, path); @@ -325,19 +316,14 @@ public partial class ModEditWindow || !path.IsEmpty && !_editor.FileEditor.CanAddGamePath(path))) { Im.Line.Same(); - ImGui.SetCursorPosX(pos); - using var font = ImRaii.PushFont(UiBuilder.IconFont); - ImGuiUtil.TextColored(0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString()); + Im.Cursor.X = pos; + ImEx.Icon.Draw(FontAwesomeIcon.TimesCircle.Icon(), Rgba32.Red); } else if (tmp.Length > 0 && Path.GetExtension(tmp) != registry.File.Extension) { Im.Line.Same(); - ImGui.SetCursorPosX(pos); - using (ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); - } - + Im.Cursor.X = pos; + ImEx.Icon.Draw(FontAwesomeIcon.ExclamationCircle.Icon(), new Rgba32(0xFF00B0B0)); Im.Tooltip.OnHover("The game path and the file do not have the same extension."u8); } } @@ -347,41 +333,40 @@ public partial class ModEditWindow Im.Line.New(); using var spacing = ImStyleDouble.ItemSpacing.Push(new Vector2(3 * Im.Style.GlobalScale, 0)); - Im.Item.SetNextWidth(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.Item.SetNextWidthScaled(30); + Im.Drag("##skippedFolders"u8, ref _folderSkip, 0, 10, 0.01f); + Im.Tooltip.OnHover("Skip the first N folders when automatically constructing the game path from the file path."u8); Im.Line.Same(); spacing.Pop(); - if (ImGui.Button("Add Paths")) + if (Im.Button("Add Paths"u8)) _editor.FileEditor.AddPathsToSelected(_editor.Option!, _editor.Files.Available.Where(_selectedFiles.Contains), _folderSkip); - ImGuiUtil.HoverTooltip( - "Add the file path converted to a game path to all selected files for the current option, optionally skipping the first N folders."); + Im.Tooltip.OnHover("Add the file path converted to a game path to all selected files for the current option, optionally skipping the first N folders."u8); Im.Line.Same(); - if (ImGui.Button("Remove Paths")) + if (Im.Button("Remove Paths"u8)) _editor.FileEditor.RemovePathsFromSelected(_editor.Option!, _editor.Files.Available.Where(_selectedFiles.Contains)); - ImGuiUtil.HoverTooltip("Remove all game paths associated with the selected files in the current option."); + Im.Tooltip.OnHover("Remove all game paths associated with the selected files in the current option."u8); Im.Line.Same(); var active = _config.DeleteModModifier.IsActive(); var tt = "Delete all selected files entirely from your filesystem, but not their file associations in the mod.\n!!!This can not be reverted!!!"; - if (_selectedFiles.Count == 0) + if (_selectedFiles.Count is 0) tt += "\n\nNo files selected."; else if (!active) tt += $"\n\nHold {_config.DeleteModModifier} to delete."; - if (ImGuiUtil.DrawDisabledButton("Delete Selected Files", Vector2.Zero, tt, _selectedFiles.Count == 0 || !active)) + if (ImEx.Button("Delete Selected Files"u8, Vector2.Zero, tt, _selectedFiles.Count is 0 || !active)) _editor.FileEditor.DeleteFiles(_editor.Mod!, _editor.Option!, _editor.Files.Available.Where(_selectedFiles.Contains)); Im.Line.Same(); var changes = _editor.FileEditor.Changes; - tt = changes ? "Apply the current file setup to the currently selected option." : "No changes made."; - if (ImGuiUtil.DrawDisabledButton("Apply Changes", Vector2.Zero, tt, !changes)) + var tt2 = changes ? "Apply the current file setup to the currently selected option."u8 : "No changes made."u8; + if (ImEx.Button("Apply Changes"u8, Vector2.Zero, tt2, !changes)) { var failedFiles = _editor.FileEditor.Apply(_editor.Mod!, _editor.Option!); if (failedFiles > 0) @@ -390,42 +375,42 @@ public partial class ModEditWindow Im.Line.Same(); - var label = changes ? "Revert Changes" : "Reload Files"; - var length = new Vector2(ImGui.CalcTextSize("Revert Changes").X, 0); - if (ImGui.Button(label, length)) + var label = changes ? "Revert Changes"u8 : "Reload Files"u8; + var length = new Vector2(Im.Font.CalculateSize("Revert Changes"u8).X, 0); + if (Im.Button(label, length)) _editor.FileEditor.Revert(_editor.Mod!, _editor.Option!); - ImGuiUtil.HoverTooltip("Revert all revertible changes since the last file or option reload or data refresh."); + Im.Tooltip.OnHover("Revert all revertible changes since the last file or option reload or data refresh."u8); Im.Line.Same(); - ImGui.Checkbox("Overview Mode", ref _overviewMode); + Im.Checkbox("Overview Mode"u8, ref _overviewMode); } private void DrawFileManagementNormal() { - Im.Item.SetNextWidth(250 * Im.Style.GlobalScale); + Im.Item.SetNextWidthScaled(250); Im.Input.Text("##filter"u8, ref _fileFilter, "Filter paths..."u8); Im.Line.Same(); - ImGui.Checkbox("Show Game Paths", ref _showGamePaths); + Im.Checkbox("Show Game Paths"u8, ref _showGamePaths); Im.Line.Same(); - if (ImGui.Button("Unselect All")) + if (Im.Button("Unselect All"u8)) _selectedFiles.Clear(); Im.Line.Same(); - if (ImGui.Button("Select Visible")) + if (Im.Button("Select Visible"u8)) _selectedFiles.UnionWith(_editor.Files.Available.Where(CheckFilter)); Im.Line.Same(); - if (ImGui.Button("Select Unused")) + if (Im.Button("Select Unused"u8)) _selectedFiles.UnionWith(_editor.Files.Available.Where(f => f.SubModUsage.Count == 0)); Im.Line.Same(); - if (ImGui.Button("Select Used Here")) + if (Im.Button("Select Used Here"u8)) _selectedFiles.UnionWith(_editor.Files.Available.Where(f => f.CurrentUsage > 0)); Im.Line.Same(); - ImGuiUtil.RightAlign($"{_selectedFiles.Count} / {_editor.Files.Available.Count} Files Selected"); + ImEx.TextRightAligned($"{_selectedFiles.Count} / {_editor.Files.Available.Count} Files Selected"); } private void DrawFileManagementOverview() diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs index 7b25d946..ad5bd07e 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs @@ -1,8 +1,5 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui.Raii; -using OtterGui.Text; +using Luna; using Penumbra.UI.AdvancedWindow.Materials; namespace Penumbra.UI.AdvancedWindow; @@ -21,10 +18,10 @@ public partial class ModEditWindow private void DrawMaterialReassignmentTab() { - if (_editor.Files.Mdl.Count == 0) + if (_editor.Files.Mdl.Count is 0) return; - using var tab = ImUtf8.TabItem("Material Reassignment"u8); + using var tab = Im.TabBar.BeginItem("Material Reassignment"u8); if (!tab) return; @@ -32,43 +29,43 @@ public partial class ModEditWindow MaterialSuffix.Draw(_editor, ImEx.ScaledVector(175, 0)); Im.Line.New(); - using var child = ImUtf8.Child("##mdlFiles"u8, -Vector2.One, true); + using var child = Im.Child.Begin("##mdlFiles"u8, Im.ContentRegion.Available, true); if (!child) return; - using var table = Im.Table.Begin("##files"u8, 4, TableFlags.RowBackground | TableFlags.SizingFixedFit, -Vector2.One); + using var table = Im.Table.Begin("##files"u8, 4, TableFlags.RowBackground | TableFlags.SizingFixedFit, Im.ContentRegion.Available); if (!table) return; foreach (var (idx, info) in _editor.MdlMaterialEditor.ModelFiles.Index()) { - using var id = ImRaii.PushId(idx); - ImGui.TableNextColumn(); - if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Save the changed mdl file.\nUse at own risk!"u8, disabled: !info.Changed)) + using var id = Im.Id.Push(idx); + table.NextColumn(); + if (ImEx.Icon.Button(LunaStyle.SaveIcon, "Save the changed mdl file.\nUse at own risk!"u8, !info.Changed)) info.Save(_editor.Compactor); - ImGui.TableNextColumn(); - if (ImUtf8.IconButton(FontAwesomeIcon.Recycle, "Restore current changes to default."u8, disabled: !info.Changed)) + table.NextColumn(); + if (ImEx.Icon.Button(LunaStyle.RefreshIcon, "Restore current changes to default."u8, !info.Changed)) info.Restore(); - ImGui.TableNextColumn(); - ImUtf8.Text(info.Path.InternalName.Span[(Mod!.ModPath.FullName.Length + 1)..]); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(400 * Im.Style.GlobalScale); + table.NextColumn(); + Im.Text(info.Path.InternalName.Span[(Mod!.ModPath.FullName.Length + 1)..]); + table.NextColumn(); + Im.Item.SetNextWidthScaled(400); var tmp = info.CurrentMaterials[0]; - if (ImUtf8.InputText("##0"u8, ref tmp)) + if (Im.Input.Text("##0"u8, ref tmp)) info.SetMaterial(tmp, 0); for (var i = 1; i < info.Count; ++i) { - using var id2 = ImUtf8.PushId(i); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(400 * Im.Style.GlobalScale); + using var id2 = Im.Id.Push(i); + table.NextColumn(); + table.NextColumn(); + table.NextColumn(); + table.NextColumn(); + Im.Item.SetNextWidthScaled(400); tmp = info.CurrentMaterials[i]; - if (ImUtf8.InputText(""u8, ref tmp)) + if (Im.Input.Text(""u8, ref tmp)) info.SetMaterial(tmp, i); } } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs index 0ce8a79d..e37fa953 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs @@ -1,9 +1,5 @@ -using Dalamud.Interface; -using Dalamud.Bindings.ImGui; using ImSharp; -using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; +using Luna; using Penumbra.Api.Api; using Penumbra.GameData.Data; using Penumbra.GameData.Enums; @@ -19,7 +15,7 @@ public partial class ModEditWindow private void DrawMetaTab() { - using var tab = ImUtf8.TabItem("Meta Manipulations"u8); + using var tab = Im.TabBar.BeginItem("Meta Manipulations"u8); if (!tab) return; @@ -28,12 +24,12 @@ 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; Im.Line.New(); - if (ImUtf8.ButtonEx("Apply Changes"u8, tt, Vector2.Zero, setsEqual)) + if (ImEx.Button("Apply Changes"u8, Vector2.Zero, tt, setsEqual)) _editor.MetaEditor.Apply(_editor.Option!); Im.Line.Same(); tt = setsEqual ? "No changes staged."u8 : "Revert all currently staged changes."u8; - if (ImUtf8.ButtonEx("Revert Changes"u8, tt, Vector2.Zero, setsEqual)) + if (ImEx.Button("Revert Changes"u8, Vector2.Zero, tt, setsEqual)) _editor.MetaEditor.Load(_editor.Mod!, _editor.Option!); Im.Line.Same(); @@ -41,17 +37,17 @@ public partial class ModEditWindow Im.Line.Same(); SetFromClipboardButton(); Im.Line.Same(); - CopyToClipboardButton("Copy all current manipulations to clipboard.", _iconSize, _editor.MetaEditor); + CopyToClipboardButton("Copy all current manipulations to clipboard."u8, _iconSize, _editor.MetaEditor); Im.Line.Same(); - if (ImUtf8.Button("Write as TexTools Files"u8)) + if (Im.Button("Write as TexTools Files"u8)) _metaFileManager.WriteAllTexToolsMeta(Mod!); Im.Line.Same(); - if (ImUtf8.ButtonEx("Remove All Default-Values"u8, "Delete any entries from all lists that set the value to its default value."u8)) + if (ImEx.Button("Remove All Default-Values"u8, "Delete any entries from all lists that set the value to its default value."u8)) _editor.MetaEditor.DeleteDefaultValues(); Im.Line.Same(); DrawAtchDragDrop(); - using var child = ImRaii.Child("##meta", -Vector2.One, true); + using var child = Im.Child.Begin("##meta"u8, Im.ContentRegion.Available, true); if (!child) return; @@ -75,23 +71,23 @@ public partial class ModEditWindow if (gr is GenderRace.Unknown) return false; - ImUtf8.Text($"Dragging .atch for {gr.ToName()}..."); + Im.Text($"Dragging .atch for {gr.ToName()}..."); return true; }); var hasAtch = _editor.Files.Atch.Count > 0; - if (ImUtf8.ButtonEx("Import .atch"u8, + if (ImEx.Button("Import .atch"u8, Vector2.Zero, _dragDropManager.IsDragging ? ""u8 : hasAtch ? "Drag a .atch file containing its race code in the path here to import its values.\n\nClick to select an .atch file from the mod."u8 - : "Drag a .atch file containing its race code in the path here to import its values."u8, default, + : "Drag a .atch file containing its race code in the path here to import its values."u8, !_dragDropManager.IsDragging && !hasAtch) && hasAtch) - ImUtf8.OpenPopup("##atchPopup"u8); + Im.Popup.Open("##atchPopup"u8); if (_dragDropManager.CreateImGuiTarget("atchDrag", out var files, out _) && files.FirstOrDefault() is { } file) _metaDrawers.Atch.ImportFile(file); - using var popup = ImUtf8.Popup("##atchPopup"u8); + using var popup = Im.Popup.Begin("##atchPopup"u8); if (!popup) return; @@ -103,7 +99,7 @@ public partial class ModEditWindow foreach (var atchFile in _editor.Files.Atch) { - if (ImUtf8.Selectable(atchFile.RelPath.Path.Span) && atchFile.File.Exists) + if (Im.Selectable(atchFile.RelPath.Path.Span) && atchFile.File.Exists) _metaDrawers.Atch.ImportFile(atchFile.File.FullName); } } @@ -114,9 +110,9 @@ public partial class ModEditWindow if (drawer == null) return; - var oldPos = ImGui.GetCursorPosY(); - var header = ImUtf8.CollapsingHeader($"{_editor.MetaEditor.GetCount(type)} {drawer.Label}"); - DrawOtherOptionData(type, oldPos, ImGui.GetCursorPos()); + var oldPos = Im.Cursor.Y; + var header = Im.Tree.Header($"{_editor.MetaEditor.GetCount(type)} {drawer.Label}"); + DrawOtherOptionData(type, oldPos, Im.Cursor.Position); if (!header) return; @@ -126,7 +122,7 @@ public partial class ModEditWindow private static void DrawTable(IMetaDrawer drawer) { const TableFlags flags = TableFlags.RowBackground | TableFlags.SizingFixedFit | TableFlags.BordersInnerVertical; - using var table = Im.Table.Begin(drawer.Label, drawer.NumColumns, flags); + using var table = Im.Table.Begin(drawer.Label, drawer.NumColumns, flags); if (!table) return; @@ -140,35 +136,35 @@ public partial class ModEditWindow if (otherOptionData.TotalCount <= 0) return; - var text = $"{otherOptionData.TotalCount} Edits in other Options"; - var size = ImGui.CalcTextSize(text).X; - ImGui.SetCursorPos(new Vector2(Im.ContentRegion.Available.X - size, oldPos + Im.Style.FramePadding.Y)); + Utf8StringHandler text = $"{otherOptionData.TotalCount} Edits in other Options"; + var size = Im.Font.CalculateSize(ref text).X; + Im.Cursor.Position = new Vector2(Im.ContentRegion.Available.X - size, oldPos + Im.Style.FramePadding.Y); Im.Text(text, ColorId.RedundantAssignment.Value().FullAlpha()); if (Im.Item.Hovered()) { - using var tt = ImUtf8.Tooltip(); + using var tt = Im.Tooltip.Begin(); foreach (var name in otherOptionData) - ImUtf8.Text(name); + Im.Text(name); } - ImGui.SetCursorPos(newPos); + Im.Cursor.Position = newPos; } - private static void CopyToClipboardButton(string tooltip, Vector2 iconSize, MetaDictionary manipulations) + private static void CopyToClipboardButton(ReadOnlySpan tooltip, Vector2 iconSize, MetaDictionary manipulations) { - if (!ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clipboard.ToIconString(), iconSize, tooltip, false, true)) + if (!ImEx.Icon.Button(LunaStyle.ToClipboardIcon, tooltip, iconSize)) return; - var text = Functions.ToCompressedBase64(manipulations, 0); + var text = CompressionFunctions.ToCompressedBase64(manipulations, 0); if (text.Length > 0) - ImGui.SetClipboardText(text); + Im.Clipboard.Set(text); } private void AddFromClipboardButton() { - if (ImUtf8.Button("Add from Clipboard"u8)) + if (Im.Button("Add from Clipboard"u8)) { - var clipboard = ImGuiUtil.GetClipboardText(); + var clipboard = Im.Clipboard.GetUtf16(); if (MetaApi.ConvertManips(clipboard, out var manips, out _)) { @@ -183,9 +179,9 @@ public partial class ModEditWindow private void SetFromClipboardButton() { - if (ImUtf8.Button("Set from Clipboard"u8)) + if (Im.Button("Set from Clipboard"u8)) { - var clipboard = ImGuiUtil.GetClipboardText(); + var clipboard = Im.Clipboard.GetUtf16(); if (MetaApi.ConvertManips(clipboard, out var manips, out _)) { _editor.MetaEditor.SetTo(manips); diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs index 8d99af7f..330c4d6b 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs @@ -1,12 +1,8 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using ImSharp; using Lumina.Data.Parsing; using Luna; -using OtterGui; -using OtterGui.Custom; using OtterGui.Raii; -using OtterGui.Text; using OtterGui.Widgets; using Penumbra.GameData; using Penumbra.GameData.Files; @@ -75,7 +71,7 @@ public partial class ModEditWindow ret |= DrawModelMaterialDetails(tab, disabled); - if (ImGui.CollapsingHeader($"Meshes ({data.LastFile.Meshes.Length})###meshes")) + if (Im.Tree.Header($"Meshes ({data.LastFile.Meshes.Length})###meshes")) for (var i = 0; i < data.LastFile.LodCount; ++i) ret |= DrawModelLodDetails(tab, i, disabled); @@ -89,9 +85,8 @@ public partial class ModEditWindow if (disabled || tab.Mdl.Version is not MdlFile.V5) return; - if (!ImUtf8.ButtonEx("Update MDL Version from V5 to V6"u8, - "Try using this if the bone weights of a pre-Dawntrail model seem wrong.\n\nThis is not revertible."u8, - new Vector2(-0.1f, 0), false, 0, new Rgba32(Colors.PressEnterWarningBg).Color)) + if (!ImEx.Button("Update MDL Version from V5 to V6"u8, Colors.PressEnterWarningBg, default, Im.ContentRegion.Available with { Y = 0 }, + "Try using this if the bone weights of a pre-Dawntrail model seem wrong.\n\nThis is not revertible."u8)) return; tab.Mdl.ConvertV5ToV6(); @@ -100,7 +95,7 @@ public partial class ModEditWindow private void DrawImportExport(MdlTab tab, bool disabled) { - if (!ImGui.CollapsingHeader("Import / Export")) + if (!Im.Tree.Header("Import / Export"u8)) return; var childSize = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); @@ -115,7 +110,7 @@ public partial class ModEditWindow private void DrawImport(MdlTab tab, Vector2 size, bool _1) { - using var id = ImRaii.PushId("import"); + using var id = Im.Id.Push("import"u8); _dragDropManager.CreateImGuiSource("ModelDragDrop", m => m.Extensions.Any(e => ValidModelExtensions.Contains(e.ToLowerInvariant())), m => @@ -129,11 +124,10 @@ public partial class ModEditWindow using (ImRaii.FramedGroup("Import", size, headerPreIcon: FontAwesomeIcon.FileImport)) { - ImGui.Checkbox("Keep current materials", ref tab.ImportKeepMaterials); - ImGui.Checkbox("Keep current attributes", ref tab.ImportKeepAttributes); + Im.Checkbox("Keep current materials"u8, ref tab.ImportKeepMaterials); + Im.Checkbox("Keep current attributes"u8, ref tab.ImportKeepAttributes); - if (ImGuiUtil.DrawDisabledButton("Import from glTF", Vector2.Zero, "Imports a glTF file, overriding the content of this mdl.", - tab.PendingIo)) + if (ImEx.Button("Import from glTF"u8, Vector2.Zero, "Imports a glTF file, overriding the content of this mdl."u8, tab.PendingIo)) _fileDialog.OpenFilePicker("Load model from glTF.", "glTF{.gltf,.glb}", (success, paths) => { if (success && paths.Count > 0) @@ -150,10 +144,10 @@ public partial class ModEditWindow private void DrawExport(MdlTab tab, Vector2 size, bool _) { - using var id = ImRaii.PushId("export"); + using var id = Im.Id.Push("export"u8); using var frame = ImRaii.FramedGroup("Export", size, headerPreIcon: FontAwesomeIcon.FileExport); - if (tab.GamePaths == null) + if (tab.GamePaths is null) { Im.Text(tab.IoExceptions.Count is 0 ? "Resolving model game paths."u8 : "Failed to resolve model game paths."u8); @@ -162,18 +156,17 @@ public partial class ModEditWindow DrawGamePathCombo(tab); - ImGui.Checkbox("##exportGeneratedMissingBones", ref tab.ExportConfig.GenerateMissingBones); - Im.Line.Same(); - ImGuiUtil.LabeledHelpMarker("Generate missing bones", - "WARNING: Enabling this option can result in unusable exported meshes.\n" - + "It is primarily intended to allow exporting models weighted to bones that do not exist.\n" - + "Before enabling, ensure dependencies are enabled in the current collection, and EST metadata is correctly configured."); + Im.Checkbox("##exportGeneratedMissingBones"u8, ref tab.ExportConfig.GenerateMissingBones); + LunaStyle.DrawAlignedHelpMarkerLabel("Generate Missing Bones"u8, + "WARNING: Enabling this option can result in unusable exported meshes.\n"u8 + + "It is primarily intended to allow exporting models weighted to bones that do not exist.\n"u8 + + "Before enabling, ensure dependencies are enabled in the current collection, and EST metadata is correctly configured."u8); var gamePath = tab.GamePathIndex >= 0 && tab.GamePathIndex < tab.GamePaths.Count ? tab.GamePaths[tab.GamePathIndex] : _customGamePath; - if (ImGuiUtil.DrawDisabledButton("Export to glTF", Vector2.Zero, "Exports this mdl file to glTF, for use in 3D authoring applications.", + if (ImEx.Button("Export to glTF"u8, Vector2.Zero, "Exports this mdl file to glTF, for use in 3D authoring applications."u8, tab.PendingIo || gamePath.IsEmpty)) _fileDialog.OpenSavePicker("Save model as glTF.", ".glb", Path.GetFileNameWithoutExtension(gamePath.Filename().ToString()), ".glb", (valid, path) => @@ -193,58 +186,58 @@ public partial class ModEditWindow private static void DrawIoExceptions(MdlTab tab) { - if (tab.IoExceptions.Count == 0) + if (tab.IoExceptions.Count is 0) return; - var size = new Vector2(Im.ContentRegion.Available.X, 0); + var size = Im.ContentRegion.Available with { Y = 0 }; using var frame = ImRaii.FramedGroup("Exceptions", size, headerPreIcon: FontAwesomeIcon.TimesCircle, borderColor: new Rgba32(Colors.RegexWarningBorder).Color); var spaceAvail = Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X - 100; foreach (var (index, exception) in tab.IoExceptions.Index()) { - using var id = ImRaii.PushId(index); - var message = $"{exception.GetType().Name}: {exception.Message}"; - var textSize = ImGui.CalcTextSize(message).X; + using var id = Im.Id.Push(index); + var message = new StringU8($"{exception.GetType().Name}: {exception.Message}"); + var textSize = Im.Font.CalculateSize(message).X; if (textSize > spaceAvail) - message = message[..(int)Math.Floor(message.Length * (spaceAvail / textSize))] + "..."; + message = new StringU8($"{message.Span[..(int)Math.Floor(message.Length * (spaceAvail / textSize))]}..."); - using var exceptionNode = ImRaii.TreeNode(message); + using var exceptionNode = Im.Tree.Node(message); if (exceptionNode) { - using var indent = ImRaii.PushIndent(); - ImGuiUtil.TextWrapped(exception.ToString()); + using var indent = Im.Indent(); + Im.TextWrapped($"{exception}"); } } } private static void DrawIoWarnings(MdlTab tab) { - if (tab.IoWarnings.Count == 0) + if (tab.IoWarnings.Count is 0) return; - var size = new Vector2(Im.ContentRegion.Available.X, 0); + var size = Im.ContentRegion.Available with { Y = 0 }; using var frame = ImRaii.FramedGroup("Warnings", size, headerPreIcon: FontAwesomeIcon.ExclamationCircle, borderColor: 0xFF40FFFF); var spaceAvail = Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X - 100; foreach (var (index, warning) in tab.IoWarnings.Index()) { - using var id = ImRaii.PushId(index); - var textSize = ImGui.CalcTextSize(warning).X; + using var id = Im.Id.Push(index); + var textSize = Im.Font.CalculateSize(warning).X; if (textSize <= spaceAvail) { - ImRaii.TreeNode(warning, ImGuiTreeNodeFlags.Leaf).Dispose(); + Im.Tree.Leaf(warning); continue; } - var firstLine = warning[..(int)Math.Floor(warning.Length * (spaceAvail / textSize))] + "..."; + var firstLine = new StringU8($"{warning.AsSpan(0, (int)Math.Floor(warning.Length * (spaceAvail / textSize)))}..."); - using var warningNode = ImRaii.TreeNode(firstLine); + using var warningNode = Im.Tree.Node(firstLine); if (warningNode) { - using var indent = ImRaii.PushIndent(); - ImGuiUtil.TextWrapped(warning); + using var indent = Im.Indent(); + Im.TextWrapped(warning); } } } @@ -258,7 +251,7 @@ public partial class ModEditWindow } Im.Text("No associated game path detected. Valid game paths are currently necessary for exporting."u8); - if (!ImGui.InputTextWithHint("##customInput", "Enter custom game path...", ref _customPath, 256)) + if (!Im.Input.Text("##customInput"u8, ref _customPath, "Enter custom game path..."u8)) return; if (!Utf8GamePath.FromString(_customPath, out _customGamePath)) @@ -268,10 +261,9 @@ public partial class ModEditWindow /// I disliked the combo with only one selection so turn it into a button in that case. private static void DrawComboButton(MdlTab tab) { - const string label = "Game Path"; - var preview = tab.GamePaths![tab.GamePathIndex].ToString(); - var labelWidth = ImGui.CalcTextSize(label).X + Im.Style.ItemInnerSpacing.X; - var buttonWidth = Im.ContentRegion.Available.X - labelWidth - Im.Style.ItemSpacing.X; + var preview = tab.GamePaths![tab.GamePathIndex].Path.Span; + var labelWidth = Im.Font.CalculateSize("Game Path"u8).X + Im.Style.ItemInnerSpacing.X; + var buttonWidth = Im.ContentRegion.Available.X - labelWidth - Im.Style.ItemSpacing.X; if (tab.GamePaths!.Count == 1) { using var style = ImStyleDouble.ButtonTextAlign.Push(new Vector2(0, 0.5f)); @@ -279,18 +271,18 @@ public partial class ModEditWindow .Push(ImGuiColor.ButtonHovered, Im.Style[ImGuiColor.FrameBackgroundHovered]) .Push(ImGuiColor.ButtonActive, Im.Style[ImGuiColor.FrameBackgroundActive]); using var group = Im.Group(); - ImGui.Button(preview, new Vector2(buttonWidth, 0)); + Im.Button(preview, new Vector2(buttonWidth, 0)); Im.Line.Same(0, Im.Style.ItemInnerSpacing.X); Im.Text("Game Path"u8); } else { Im.Item.SetNextWidth(buttonWidth); - using var combo = ImRaii.Combo("Game Path", preview); + using var combo = Im.Combo.Begin("Game Path"u8, preview); if (combo.Success) foreach (var (index, path) in tab.GamePaths.Index()) { - if (!ImGui.Selectable(path.ToString(), index == tab.GamePathIndex)) + if (!Im.Selectable(path.Path.Span, index == tab.GamePathIndex)) continue; tab.GamePathIndex = index; @@ -298,42 +290,39 @@ public partial class ModEditWindow } if (Im.Item.RightClicked()) - ImGui.SetClipboardText(preview); + Im.Clipboard.Set(preview); Im.Tooltip.OnHover("Right-Click to copy to clipboard."u8, HoveredFlags.AllowWhenDisabled); } private void DrawDocumentationLink(string address) { - var text = "Documentation →"u8; - - var framePadding = Im.Style.FramePadding; - var width = ImGui.CalcTextSize(text).X + framePadding.X * 2; - + var text = "Documentation →"u8; + var width = Im.Font.CalculateButtonSize(text).X; // Draw the link button. We set the background colour to transparent to mimic the look of a link. using var color = ImGuiColor.Button.Push(Vector4.Zero); SupportButton.Link(Penumbra.Messager, text, address, width, ""u8); // Draw an underline for the text. - var lineStart = ImGui.GetItemRectMax(); - lineStart -= framePadding; - var lineEnd = lineStart with { X = ImGui.GetItemRectMin().X + framePadding.X }; - ImGui.GetWindowDrawList().AddLine(lineStart, lineEnd, 0xFFFFFFFF); + var lineStart = Im.Item.LowerRightCorner; + lineStart -= Im.Style.FramePadding; + var lineEnd = lineStart with { X = Im.Item.UpperLeftCorner.X + Im.Style.FramePadding.X }; + Im.Window.DrawList.Shape.Line(lineStart, lineEnd, 0xFFFFFFFF); } private bool DrawModelMaterialDetails(MdlTab tab, bool disabled) { var invalidMaterialCount = tab.Mdl.Materials.Count(material => !tab.ValidateMaterial(material)); - var oldPos = ImGui.GetCursorPosY(); - var header = ImGui.CollapsingHeader("Materials"); - var newPos = ImGui.GetCursorPos(); + var oldPos = Im.Cursor.Y; + var header = Im.Tree.Header("Materials"u8); + var newPos = Im.Cursor.Position; if (invalidMaterialCount > 0) { - var text = $"{invalidMaterialCount} invalid material{(invalidMaterialCount > 1 ? "s" : "")}"; - var size = ImGui.CalcTextSize(text).X; - ImGui.SetCursorPos(new Vector2(Im.ContentRegion.Available.X - size, oldPos + Im.Style.FramePadding.Y)); - ImGuiUtil.TextColored(0xFF0000FF, text); - ImGui.SetCursorPos(newPos); + var text = new StringU8($"{invalidMaterialCount} invalid material{(invalidMaterialCount > 1 ? "s" : "")}"); + var size = Im.Font.CalculateSize(text).X; + Im.Cursor.Position = new Vector2(Im.ContentRegion.Available.X - size, oldPos + Im.Style.FramePadding.Y); + Im.Text(text, Rgba32.Red); + Im.Cursor.Position = newPos; } if (!header) @@ -354,46 +343,46 @@ public partial class ModEditWindow table.SetupColumn("help"u8, TableColumnFlags.WidthFixed, UiHelpers.IconButtonSize.X); } - var inputFlags = disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None; + var inputFlags = disabled ? InputTextFlags.ReadOnly : InputTextFlags.None; for (var materialIndex = 0; materialIndex < materials.Length; materialIndex++) - ret |= DrawMaterialRow(tab, disabled, materials, materialIndex, inputFlags); + ret |= DrawMaterialRow(table, tab, disabled, materials, materialIndex, inputFlags); if (materials.Length >= MdlMaterialMaximum || disabled) return ret; - ImGui.TableNextColumn(); + table.NextColumn(); - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(-1); - ImGui.InputTextWithHint("##newMaterial", "Add new material...", ref _modelNewMaterial, Utf8GamePath.MaxGamePathLength, inputFlags); + table.NextColumn(); + Im.Item.SetNextWidth(Im.ContentRegion.Available.X); + Im.Input.Text("##newMaterial"u8, ref _modelNewMaterial, "Add new material..."u8, maxLength: Utf8GamePath.MaxGamePathLength, + flags: inputFlags); var validName = tab.ValidateMaterial(_modelNewMaterial); - ImGui.TableNextColumn(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), UiHelpers.IconButtonSize, string.Empty, !validName, true)) + table.NextColumn(); + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, StringU8.Empty, !validName)) { - ret |= true; - tab.Mdl.Materials = materials.AddItem(_modelNewMaterial); - _modelNewMaterial = string.Empty; + ret = true; + tab.Mdl.Materials = materials.AddItem(_modelNewMaterial); + _modelNewMaterial = string.Empty; } - ImGui.TableNextColumn(); + table.NextColumn(); if (!validName && _modelNewMaterial.Length > 0) DrawInvalidMaterialMarker(); return ret; } - private bool DrawMaterialRow(MdlTab tab, bool disabled, string[] materials, int materialIndex, ImGuiInputTextFlags inputFlags) + private bool DrawMaterialRow(in Im.TableDisposable table, MdlTab tab, bool disabled, string[] materials, int materialIndex, + InputTextFlags inputFlags) { - using var id = ImRaii.PushId(materialIndex); + using var id = Im.Id.Push(materialIndex); var ret = false; - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text($"Material #{materialIndex + 1}"); + table.DrawFrameColumn($"Material #{materialIndex + 1}"); var temp = materials[materialIndex]; - ImGui.TableNextColumn(); - Im.Item.SetNextWidth(-1); - if (ImGui.InputText($"##material{materialIndex}", ref temp, Utf8GamePath.MaxGamePathLength, inputFlags) + table.NextColumn(); + Im.Item.SetNextWidth(Im.ContentRegion.Available.X); + if (Im.Input.Text($"##material{materialIndex}", ref temp, maxLength: Utf8GamePath.MaxGamePathLength, flags: inputFlags) && temp.Length > 0 && temp != materials[materialIndex] ) @@ -405,23 +394,23 @@ public partial class ModEditWindow if (disabled) return ret; - ImGui.TableNextColumn(); + table.NextColumn(); // Need to have at least one material. if (materials.Length > 1) { - var tt = "Delete this material.\nAny meshes targeting this material will be updated to use material #1."; var modifierActive = _config.DeleteModModifier.IsActive(); - if (!modifierActive) - tt += $"\nHold {_config.DeleteModModifier} to delete."; - - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), UiHelpers.IconButtonSize, tt, !modifierActive, true)) + if (ImEx.Icon.Button(LunaStyle.DeleteIcon, + "Delete this material.\nAny meshes targeting this material will be updated to use material #1."u8, !modifierActive)) { tab.RemoveMaterial(materialIndex); - ret |= true; + ret = true; } + + if (!modifierActive) + Im.Tooltip.OnHover($"\nHold {_config.DeleteModModifier} to delete."); } - ImGui.TableNextColumn(); + table.NextColumn(); // Add markers to invalid materials. if (!tab.ValidateMaterial(temp)) DrawInvalidMaterialMarker(); @@ -431,20 +420,16 @@ public partial class ModEditWindow private static void DrawInvalidMaterialMarker() { - using (ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString()); - } - - ImGuiUtil.HoverTooltip( - "Materials must be either relative (e.g. \"/filename.mtrl\")\n" - + "or absolute (e.g. \"bg/full/path/to/filename.mtrl\"),\n" - + "and must end in \".mtrl\"."); + ImEx.Icon.Draw(FontAwesomeIcon.TimesCircle.Icon(), Rgba32.Red); + Im.Tooltip.OnHover( + "Materials must be either relative (e.g. \"/filename.mtrl\")\n"u8 + + "or absolute (e.g. \"bg/full/path/to/filename.mtrl\"),\n"u8 + + "and must end in \".mtrl\"."u8); } private bool DrawModelLodDetails(MdlTab tab, int lodIndex, bool disabled) { - using var lodNode = ImRaii.TreeNode($"Level of Detail #{lodIndex + 1}", ImGuiTreeNodeFlags.DefaultOpen); + using var lodNode = Im.Tree.Node($"Level of Detail #{lodIndex + 1}", TreeNodeFlags.DefaultOpen); if (!lodNode) return false; @@ -459,11 +444,11 @@ public partial class ModEditWindow private bool DrawModelMeshDetails(MdlTab tab, int meshIndex, bool disabled) { - using var meshNode = ImRaii.TreeNode($"Mesh #{meshIndex + 1}", ImGuiTreeNodeFlags.DefaultOpen); + using var meshNode = Im.Tree.Node($"Mesh #{meshIndex + 1}", TreeNodeFlags.DefaultOpen); if (!meshNode) return false; - using var id = ImRaii.PushId(meshIndex); + using var id = Im.Id.Push(meshIndex); using var table = Im.Table.Begin(StringU8.Empty, 2, TableFlags.SizingFixedFit); if (!table) return false; @@ -475,35 +460,31 @@ public partial class ModEditWindow var mesh = file.Meshes[meshIndex]; // Vertex elements - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text("Vertex Elements"u8); + table.DrawFrameColumn("Vertex Elements"u8); - ImGui.TableNextColumn(); + table.NextColumn(); DrawVertexElementDetails(file.VertexDeclarations[meshIndex].VertexElements); // Mesh material - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text("Material"u8); + table.DrawFrameColumn("Material"u8); - ImGui.TableNextColumn(); + table.NextColumn(); var ret = DrawMaterialCombo(tab, meshIndex, disabled); // Sub meshes for (var subMeshOffset = 0; subMeshOffset < mesh.SubMeshCount; subMeshOffset++) - ret |= DrawSubMeshAttributes(tab, meshIndex, subMeshOffset, disabled); + ret |= DrawSubMeshAttributes(table, tab, meshIndex, subMeshOffset, disabled); return ret; } private static void DrawVertexElementDetails(MdlStructs.VertexElement[] vertexElements) { - using var node = ImRaii.TreeNode($"Click to expand"); + using var node = Im.Tree.Node("Click to expand"u8); if (!node) return; - var flags = TableFlags.SizingFixedFit + const TableFlags flags = TableFlags.SizingFixedFit | TableFlags.RowBackground | TableFlags.Borders | TableFlags.NoHostExtendX; @@ -515,28 +496,23 @@ public partial class ModEditWindow table.SetupColumn("Type"u8); table.SetupColumn("Stream"u8); table.SetupColumn("Offset"u8); - - ImGui.TableHeadersRow(); + table.HeaderRow(); foreach (var element in vertexElements) { - ImGui.TableNextColumn(); - Im.Text($"{(MdlFile.VertexUsage)element.Usage}"); - ImGui.TableNextColumn(); - Im.Text($"{(MdlFile.VertexType)element.Type}"); - ImGui.TableNextColumn(); - Im.Text($"{element.Stream}"); - ImGui.TableNextColumn(); - Im.Text($"{element.Offset}"); + table.DrawColumn($"{(MdlFile.VertexUsage)element.Usage}"); + table.DrawColumn($"{(MdlFile.VertexType)element.Type}"); + table.DrawColumn($"{element.Stream}"); + table.DrawColumn($"{element.Offset}"); } } private static bool DrawMaterialCombo(MdlTab tab, int meshIndex, bool disabled) { var mesh = tab.Mdl.Meshes[meshIndex]; - using var _ = ImRaii.Disabled(disabled); - Im.Item.SetNextWidth(-1); - using var materialCombo = ImRaii.Combo("##material", tab.Mdl.Materials[mesh.MaterialIndex]); + using var _ = Im.Disabled(disabled); + Im.Item.SetNextWidth(Im.ContentRegion.Available.X); + using var materialCombo = Im.Combo.Begin("##material"u8, tab.Mdl.Materials[mesh.MaterialIndex]); if (!materialCombo) return false; @@ -544,7 +520,7 @@ public partial class ModEditWindow var ret = false; foreach (var (materialIndex, material) in tab.Mdl.Materials.Index()) { - if (!ImGui.Selectable(material, mesh.MaterialIndex == materialIndex)) + if (!Im.Selectable(material, mesh.MaterialIndex == materialIndex)) continue; tab.Mdl.Meshes[meshIndex].MaterialIndex = (ushort)materialIndex; @@ -554,23 +530,21 @@ public partial class ModEditWindow return ret; } - private bool DrawSubMeshAttributes(MdlTab tab, int meshIndex, int subMeshOffset, bool disabled) + private bool DrawSubMeshAttributes(in Im.TableDisposable table, MdlTab tab, int meshIndex, int subMeshOffset, bool disabled) { - using var _ = ImRaii.PushId(subMeshOffset); + using var _ = Im.Id.Push(subMeshOffset); var mesh = tab.Mdl.Meshes[meshIndex]; var subMeshIndex = mesh.SubMeshIndex + subMeshOffset; - ImGui.TableNextColumn(); - ImGui.AlignTextToFramePadding(); - Im.Text($"Attributes #{subMeshOffset + 1}"); + table.DrawFrameColumn($"Attributes #{subMeshOffset + 1}"); - ImGui.TableNextColumn(); + table.NextColumn(); var data = disabled ? _preview : _main; var widget = data.SubMeshAttributeTags[subMeshIndex]; var attributes = tab.GetSubMeshAttributes(subMeshIndex); - if (attributes == null) + if (attributes is null) { attributes = ["invalid attribute data"]; disabled = true; @@ -590,7 +564,7 @@ public partial class ModEditWindow private bool DrawOtherModelDetails(LoadedData data) { - using var header = ImRaii.CollapsingHeader("Further Content"); + using var header = Im.Tree.HeaderId("Further Content"u8); if (!header) return false; @@ -599,68 +573,46 @@ public partial class ModEditWindow { if (table) { - ImGuiUtil.DrawTableColumn("Version"); - ImGuiUtil.DrawTableColumn($"0x{data.LastFile.Version:X}"); - ImGuiUtil.DrawTableColumn("Radius"); - ImGuiUtil.DrawTableColumn(data.LastFile.Radius.ToString(CultureInfo.InvariantCulture)); - ImGuiUtil.DrawTableColumn("Model Clip Out Distance"); - ImGuiUtil.DrawTableColumn(data.LastFile.ModelClipOutDistance.ToString(CultureInfo.InvariantCulture)); - ImGuiUtil.DrawTableColumn("Shadow Clip Out Distance"); - ImGuiUtil.DrawTableColumn(data.LastFile.ShadowClipOutDistance.ToString(CultureInfo.InvariantCulture)); - ImGuiUtil.DrawTableColumn("LOD Count"); - ImGuiUtil.DrawTableColumn(data.LastFile.LodCount.ToString()); - ImGuiUtil.DrawTableColumn("Enable Index Buffer Streaming"); - ImGuiUtil.DrawTableColumn(data.LastFile.EnableIndexBufferStreaming.ToString()); - ImGuiUtil.DrawTableColumn("Enable Edge Geometry"); - ImGuiUtil.DrawTableColumn(data.LastFile.EnableEdgeGeometry.ToString()); - ImGuiUtil.DrawTableColumn("Flags 1"); - ImGuiUtil.DrawTableColumn(data.LastFile.Flags1.ToString()); - ImGuiUtil.DrawTableColumn("Flags 2"); - ImGuiUtil.DrawTableColumn(data.LastFile.Flags2.ToString()); - ImGuiUtil.DrawTableColumn("Vertex Declarations"); - ImGuiUtil.DrawTableColumn(data.LastFile.VertexDeclarations.Length.ToString()); - ImGuiUtil.DrawTableColumn("Bone Bounding Boxes"); - ImGuiUtil.DrawTableColumn(data.LastFile.BoneBoundingBoxes.Length.ToString()); - ImGuiUtil.DrawTableColumn("Bone Tables"); - ImGuiUtil.DrawTableColumn(data.LastFile.BoneTables.Length.ToString()); - ImGuiUtil.DrawTableColumn("Element IDs"); - ImGuiUtil.DrawTableColumn(data.LastFile.ElementIds.Length.ToString()); - ImGuiUtil.DrawTableColumn("Extra LoDs"); - ImGuiUtil.DrawTableColumn(data.LastFile.ExtraLods.Length.ToString()); - ImGuiUtil.DrawTableColumn("Meshes"); - ImGuiUtil.DrawTableColumn(data.LastFile.Meshes.Length.ToString()); - ImGuiUtil.DrawTableColumn("Shape Meshes"); - ImGuiUtil.DrawTableColumn(data.LastFile.ShapeMeshes.Length.ToString()); - ImGuiUtil.DrawTableColumn("LoDs"); - ImGuiUtil.DrawTableColumn(data.LastFile.Lods.Length.ToString()); - ImGuiUtil.DrawTableColumn("Vertex Declarations"); - ImGuiUtil.DrawTableColumn(data.LastFile.VertexDeclarations.Length.ToString()); - ImGuiUtil.DrawTableColumn("Stack Size"); - ImGuiUtil.DrawTableColumn(data.LastFile.StackSize.ToString()); + table.DrawDataPair("Version"u8, $"0x{data.LastFile.Version:X}"); + table.DrawDataPair("Radius"u8, data.LastFile.Radius.ToString(CultureInfo.InvariantCulture)); + table.DrawDataPair("Model Clip Out Distance"u8, data.LastFile.ModelClipOutDistance.ToString(CultureInfo.InvariantCulture)); + table.DrawDataPair("Shadow Clip Out Distance"u8, data.LastFile.ShadowClipOutDistance.ToString(CultureInfo.InvariantCulture)); + table.DrawDataPair("LOD Count"u8, data.LastFile.LodCount); + table.DrawDataPair("Enable Index Buffer Streaming"u8, data.LastFile.EnableIndexBufferStreaming); + table.DrawDataPair("Enable Edge Geometry"u8, data.LastFile.EnableEdgeGeometry); + table.DrawDataPair("Flags 1"u8, data.LastFile.Flags1); + table.DrawDataPair("Flags 2"u8, data.LastFile.Flags2); + table.DrawDataPair("Vertex Declarations"u8, data.LastFile.VertexDeclarations.Length); + table.DrawDataPair("Bone Bounding Boxes"u8, data.LastFile.BoneBoundingBoxes.Length); + table.DrawDataPair("Bone Tables"u8, data.LastFile.BoneTables.Length); + table.DrawDataPair("Element IDs"u8, data.LastFile.ElementIds.Length); + table.DrawDataPair("Extra LoDs"u8, data.LastFile.ExtraLods.Length); + table.DrawDataPair("Meshes"u8, data.LastFile.Meshes.Length); + table.DrawDataPair("Shape Meshes"u8, data.LastFile.ShapeMeshes.Length); + table.DrawDataPair("LoDs"u8, data.LastFile.Lods.Length); + table.DrawDataPair("Vertex Declarations"u8, data.LastFile.VertexDeclarations.Length); + table.DrawDataPair("Stack Size"u8, data.LastFile.StackSize); foreach (var (lod, triCount) in data.LodTriCount.Index()) - { - ImGuiUtil.DrawTableColumn($"LOD #{lod + 1} Triangle Count"); - ImGuiUtil.DrawTableColumn(triCount.ToString()); - } + table.DrawDataPair($"LOD #{lod + 1} Triangle Count", triCount); } } - using (var materials = ImRaii.TreeNode("Materials", ImGuiTreeNodeFlags.DefaultOpen)) + using (var materials = Im.Tree.Node("Materials"u8, TreeNodeFlags.DefaultOpen)) { if (materials) foreach (var material in data.LastFile.Materials) - ImRaii.TreeNode(material, ImGuiTreeNodeFlags.Leaf).Dispose(); + Im.Tree.Leaf(material); } - using (var attributes = ImRaii.TreeNode("Attributes", ImGuiTreeNodeFlags.DefaultOpen)) + using (var attributes = Im.Tree.Node("Attributes"u8, TreeNodeFlags.DefaultOpen)) { if (attributes) for (var i = 0; i < data.LastFile.Attributes.Length; ++i) { - using var id = ImUtf8.PushId(i); + using var id = Im.Id.Push(i); ref var attribute = ref data.LastFile.Attributes[i]; var name = attribute; - if (ImUtf8.InputText("##attribute"u8, ref name, "Attribute Name..."u8) && name.Length > 0 && name != attribute) + if (Im.Input.Text("##attribute"u8, ref name, "Attribute Name..."u8) && name.Length > 0 && name != attribute) { attribute = name; ret = true; @@ -668,15 +620,15 @@ public partial class ModEditWindow } } - using (var bones = ImRaii.TreeNode("Bones", ImGuiTreeNodeFlags.DefaultOpen)) + using (var bones = Im.Tree.Node("Bones"u8, TreeNodeFlags.DefaultOpen)) { if (bones) for (var i = 0; i < data.LastFile.Bones.Length; ++i) { - using var id = ImUtf8.PushId(i); + using var id = Im.Id.Push(i); ref var bone = ref data.LastFile.Bones[i]; var name = bone; - if (ImUtf8.InputText("##bone"u8, ref name, "Bone Name..."u8) && name.Length > 0 && name != bone) + if (Im.Input.Text("##bone"u8, ref name, "Bone Name..."u8) && name.Length > 0 && name != bone) { bone = name; ret = true; @@ -684,15 +636,15 @@ public partial class ModEditWindow } } - using (var shapes = ImRaii.TreeNode("Shapes", ImGuiTreeNodeFlags.DefaultOpen)) + using (var shapes = Im.Tree.Node("Shapes"u8, TreeNodeFlags.DefaultOpen)) { if (shapes) for (var i = 0; i < data.LastFile.Shapes.Length; ++i) { - using var id = ImUtf8.PushId(i); + using var id = Im.Id.Push(i); ref var shape = ref data.LastFile.Shapes[i]; var name = shape.ShapeName; - if (ImUtf8.InputText("##shape"u8, ref name, "Shape Name..."u8) && name.Length > 0 && name != shape.ShapeName) + if (Im.Input.Text("##shape"u8, ref name, "Shape Name..."u8) && name.Length > 0 && name != shape.ShapeName) { shape.ShapeName = name; ret = true; @@ -702,7 +654,7 @@ public partial class ModEditWindow if (data.LastFile.RemainingData.Length > 0) { - using var t = ImRaii.TreeNode($"Additional Data (Size: {data.LastFile.RemainingData.Length})###AdditionalData"); + using var t = Im.Tree.Node($"Additional Data (Size: {data.LastFile.RemainingData.Length})###AdditionalData"); if (t) Widget.DrawHexViewer(data.LastFile.RemainingData); } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs index a301fd1b..5fc1bf42 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs @@ -1,51 +1,45 @@ -using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; -using OtterGui.Raii; -using OtterGui; using Penumbra.GameData; using Penumbra.GameData.Files; using Penumbra.GameData.Interop; -using Penumbra.String; using static Penumbra.GameData.Files.ShpkFile; -using OtterGui.Widgets; -using OtterGui.Text; using Penumbra.GameData.Structs; namespace Penumbra.UI.AdvancedWindow; public partial class ModEditWindow { - private static readonly CiByteString DisassemblyLabel = CiByteString.FromSpanUnsafe("##disassembly"u8, true, true, true); + private static readonly StringU8 DisassemblyLabel = new("##disassembly"u8); private readonly FileEditor _shaderPackageTab; private static bool DrawShaderPackagePanel(ShpkTab file, bool disabled) { + var dummyHeight = new Vector2(Im.Style.TextHeight / 2); DrawShaderPackageSummary(file); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); DrawShaderPackageFilterSection(file); var ret = false; - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); ret |= DrawShaderPackageShaderArray(file, "Vertex Shader", file.Shpk.VertexShaders, disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); ret |= DrawShaderPackageShaderArray(file, "Pixel Shader", file.Shpk.PixelShaders, disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); ret |= DrawShaderPackageMaterialParamLayout(file, disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); ret |= DrawShaderPackageResources(file, disabled); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); DrawShaderPackageSelection(file); - ImGui.Dummy(new Vector2(Im.Style.TextHeight / 2)); + Im.Dummy(dummyHeight); DrawOtherShaderPackageDetails(file); ret |= file.Shpk.IsChanged(); @@ -56,17 +50,17 @@ public partial class ModEditWindow private static void DrawShaderPackageSummary(ShpkTab tab) { if (tab.Shpk.IsLegacy) - ImUtf8.Text("This legacy shader package will not work in the current version of the game. Do not attempt to load it.", - ImGuiUtil.HalfBlendText(0x80u)); // Half red - ImUtf8.Text(tab.Header); + Im.Text("This legacy shader package will not work in the current version of the game. Do not attempt to load it."u8, + ImGuiColor.Text.Get().HalfBlend(new Rgba32(0x80))); + Im.Text(tab.Header); if (!tab.Shpk.Disassembled) - ImUtf8.Text("Your system doesn't support disassembling shaders. Some functionality will be missing.", - ImGuiUtil.HalfBlendText(0x80u)); // Half red + Im.Text("Your system doesn't support disassembling shaders. Some functionality will be missing."u8, + ImGuiColor.Text.Get().HalfBlend(new Rgba32(0x80))); // Half red } private static void DrawShaderExportButton(ShpkTab tab, string objectName, Shader shader, int idx) { - if (!ImUtf8.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)")) + if (!Im.Button($"Export Shader Program Blob ({shader.Blob.Length} bytes)")) return; var defaultName = objectName[0] switch @@ -102,7 +96,7 @@ public partial class ModEditWindow private static void DrawShaderImportButton(ShpkTab tab, string objectName, Shader[] shaders, int idx) { - if (!ImUtf8.Button("Replace Shader Program Blob"u8)) + if (!Im.Button("Replace Shader Program Blob"u8)) return; tab.FileDialog.OpenFilePicker($"Replace {objectName} #{idx} Program Blob...", "Shader Program Blobs{.o,.cso,.dxbc,.dxil}", @@ -141,58 +135,52 @@ public partial class ModEditWindow private static unsafe void DrawRawDisassembly(Shader shader) { - using var tree = ImUtf8.TreeNode("Raw Program Disassembly"u8); + using var tree = Im.Tree.Node("Raw Program Disassembly"u8); if (!tree) return; - using var font = ImRaii.PushFont(UiBuilder.MonoFont); - 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); + using var font = Im.Font.PushMono(); + var size = Im.ContentRegion.Available with { Y = Im.Style.TextHeight * 20 }; + Im.Input.MultiLine(DisassemblyLabel, + new Span(shader.Disassembly!.RawDisassembly.Path, shader.Disassembly.RawDisassembly.Length + 1), out ulong _, size, + InputTextFlags.ReadOnly); } private static void DrawShaderUsage(ShpkTab tab, Shader shader) { - using (var node = ImUtf8.TreeNode("Used with Shader Keys"u8)) + using (var node = Im.Tree.Node("Used with Shader Keys"u8)) { if (node) { foreach (var (keyIdx, key) in shader.SystemValues!.Index()) { - ImUtf8.TreeNode( - $"Used with System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"Used with System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}"); } foreach (var (keyIdx, key) in shader.SceneValues!.Index()) { - ImUtf8.TreeNode( - $"Used with Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"Used with Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}"); } foreach (var (keyIdx, key) in shader.MaterialValues!.Index()) { - ImUtf8.TreeNode( - $"Used with Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"Used with Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} \u2208 {{ {tab.NameSetToString(key)} }}"); } foreach (var (keyIdx, key) in shader.SubViewValues!.Index()) - { - ImUtf8.TreeNode($"Used with Sub-View Key #{keyIdx} \u2208 {{ {tab.NameSetToString(key)} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); - } + Im.Tree.Leaf($"Used with Sub-View Key #{keyIdx} \u2208 {{ {tab.NameSetToString(key)} }}"); } } - ImUtf8.TreeNode($"Used in Passes: {tab.NameSetToString(shader.Passes)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf($"Used in Passes: {tab.NameSetToString(shader.Passes)}"); } private static void DrawShaderPackageFilterSection(ShpkTab tab) { - if (!ImUtf8.CollapsingHeader(tab.FilterPopCount == tab.FilterMaximumPopCount ? "Filters###Filters"u8 : "Filters (ACTIVE)###Filters"u8)) + if (!Im.Tree.Header(tab.FilterPopCount == tab.FilterMaximumPopCount ? "Filters###Filters"u8 : "Filters (ACTIVE)###Filters"u8)) return; foreach (var (keyIdx, key) in tab.Shpk.SystemKeys.Index()) @@ -207,25 +195,26 @@ public partial class ModEditWindow foreach (var (keyIdx, _) in tab.Shpk.SubViewKeys.Index()) DrawShaderPackageFilterSet(tab, $"Sub-View Key #{keyIdx}", ref tab.FilterSubViewValues[keyIdx]); - DrawShaderPackageFilterSet(tab, "Passes", ref tab.FilterPasses); + DrawShaderPackageFilterSet(tab, "Passes"u8, ref tab.FilterPasses); } - private static void DrawShaderPackageFilterSet(ShpkTab tab, string label, ref SharedSet values) + private static void DrawShaderPackageFilterSet(ShpkTab tab, Utf8StringHandler label, + ref SharedSet values) { - if (values.PossibleValues == null) + if (values.PossibleValues is null) { - ImUtf8.TreeNode(label, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf(label); return; } - using var node = ImUtf8.TreeNode(label); + using var node = Im.Tree.Node(label); if (!node) return; foreach (var value in values.PossibleValues) { var contains = values.Contains(value); - if (!ImUtf8.Checkbox($"{tab.TryResolveName(value)}", ref contains)) + if (!Im.Checkbox($"{tab.TryResolveName(value)}", ref contains)) continue; if (contains) @@ -249,7 +238,7 @@ public partial class ModEditWindow private static bool DrawShaderPackageShaderArray(ShpkTab tab, string objectName, Shader[] shaders, bool disabled) { - if (shaders.Length == 0 || !ImUtf8.CollapsingHeader($"{objectName}s")) + if (shaders.Length is 0 || !Im.Tree.Header($"{objectName}s")) return false; var ret = false; @@ -259,7 +248,7 @@ public partial class ModEditWindow if (!tab.IsFilterMatch(shader)) continue; - using var t = ImUtf8.TreeNode($"{objectName} #{idx}"); + using var t = Im.Tree.Node($"{objectName} #{idx}"); if (!t) continue; @@ -270,22 +259,22 @@ public partial class ModEditWindow DrawShaderImportButton(tab, objectName, shaders, idx); } - ret |= DrawShaderPackageResourceArray("Constant Buffers", "slot", true, shader.Constants, false, true); - ret |= DrawShaderPackageResourceArray("Samplers", "slot", false, shader.Samplers, false, true); + ret |= DrawShaderPackageResourceArray("Constant Buffers"u8, "slot", true, shader.Constants, false, true); + ret |= DrawShaderPackageResourceArray("Samplers"u8, "slot", false, shader.Samplers, false, true); if (!tab.Shpk.IsLegacy) - ret |= DrawShaderPackageResourceArray("Textures", "slot", false, shader.Textures, false, true); - ret |= DrawShaderPackageResourceArray("Unordered Access Views", "slot", true, shader.Uavs, false, true); + ret |= DrawShaderPackageResourceArray("Textures"u8, "slot", false, shader.Textures, false, true); + ret |= DrawShaderPackageResourceArray("Unordered Access Views"u8, "slot", true, shader.Uavs, false, true); - if (shader.DeclaredInputs != 0) - ImUtf8.TreeNode($"Declared Inputs: {shader.DeclaredInputs}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); - if (shader.UsedInputs != 0) - ImUtf8.TreeNode($"Used Inputs: {shader.UsedInputs}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + if (shader.DeclaredInputs is not 0) + Im.Tree.Leaf($"Declared Inputs: {shader.DeclaredInputs}"); + if (shader.UsedInputs is not 0) + Im.Tree.Leaf($"Used Inputs: {shader.UsedInputs}"); if (shader.AdditionalHeader.Length > 8) { - using var t2 = ImUtf8.TreeNode($"Additional Header (Size: {shader.AdditionalHeader.Length})###AdditionalHeader"); + using var t2 = Im.Tree.Node($"Additional Header (Size: {shader.AdditionalHeader.Length})###AdditionalHeader"); if (t2) - Widget.DrawHexViewer(shader.AdditionalHeader); + ImEx.HexViewer(shader.AdditionalHeader); } if (tab.Shpk.Disassembled) @@ -303,43 +292,42 @@ public partial class ModEditWindow if (!disabled) { Im.Item.SetNextWidth(Im.Style.GlobalScale * 150.0f); - if (ImGuiUtil.InputUInt16($"{char.ToUpper(slotLabel[0])}{slotLabel[1..].ToLower()}", ref resource.Slot, ImGuiInputTextFlags.None)) + if (Im.Input.Scalar($"{char.ToUpper(slotLabel[0])}{slotLabel[1..].ToLower()}", ref resource.Slot)) ret = true; } - if (resource.Used == null) + if (resource.Used is null) return ret; var usedString = UsedComponentString(withSize, false, resource); if (usedString.Length > 0) { - ImUtf8.TreeNode(hasFilter ? $"Globally Used: {usedString}" : $"Used: {usedString}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf(hasFilter ? $"Globally Used: {usedString}" : $"Used: {usedString}"); if (hasFilter) { var filteredUsedString = UsedComponentString(withSize, true, resource); if (filteredUsedString.Length > 0) - ImUtf8.TreeNode($"Used within Filters: {filteredUsedString}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet) - .Dispose(); + Im.Tree.Leaf($"Used within Filters: {filteredUsedString}"); else - ImUtf8.TreeNode("Unused within Filters"u8, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf("Unused within Filters"u8); } } else { - ImUtf8.TreeNode(hasFilter ? "Globally Unused"u8 : "Unused"u8, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf(hasFilter ? "Globally Unused"u8 : "Unused"u8); } return ret; } - private static bool DrawShaderPackageResourceArray(string arrayName, string slotLabel, bool withSize, Resource[] resources, bool hasFilter, + private static bool DrawShaderPackageResourceArray(ReadOnlySpan arrayName, string slotLabel, bool withSize, Resource[] resources, + bool hasFilter, bool disabled) { - if (resources.Length == 0) + if (resources.Length is 0) return false; - using var t = ImRaii.TreeNode(arrayName); + using var t = Im.Tree.Node(arrayName); if (!t) return false; @@ -349,8 +337,8 @@ public partial class ModEditWindow ref var buf = ref resources[idx]; var name = $"#{idx}: {buf.Name} (ID: 0x{buf.Id:X8}), {slotLabel}: {buf.Slot}" + (withSize ? $", size: {buf.Size} registers###{idx}: {buf.Name} (ID: 0x{buf.Id:X8})" : string.Empty); - using var font = ImRaii.PushFont(UiBuilder.MonoFont); - using var t2 = ImUtf8.TreeNode(name, !disabled || buf.Used != null ? 0 : ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet); + using var font = Im.Font.PushMono(); + using var t2 = Im.Tree.Node(name, !disabled || buf.Used is not null ? 0 : TreeNodeFlags.Leaf | TreeNodeFlags.Bullet); font.Pop(); if (t2) ret |= DrawShaderPackageResource(slotLabel, withSize, ref buf, hasFilter, disabled); @@ -359,27 +347,26 @@ public partial class ModEditWindow return ret; } - private static bool DrawMaterialParamLayoutHeader(string label) + private static bool DrawMaterialParamLayoutHeader(Utf8StringHandler label) { - using var font = ImRaii.PushFont(UiBuilder.MonoFont); - var pos = ImGui.GetCursorScreenPos() - + new Vector2(ImGui.CalcTextSize(label).X + 3 * Im.Style.ItemInnerSpacing.X + Im.Style.FrameHeight, + using var font = Im.Font.PushMono(); + var pos = Im.Cursor.ScreenPosition + + new Vector2(Im.Font.CalculateSize(ref label).X + 3 * Im.Style.ItemInnerSpacing.X + Im.Style.FrameHeight, Im.Style.FramePadding.Y); - var ret = ImUtf8.CollapsingHeader(label); - ImGui.GetWindowDrawList() - .AddText(UiBuilder.DefaultFont, UiBuilder.DefaultFont.FontSize, pos, ImGuiColor.Text.Get().Color, "Layout"); + var ret = Im.Tree.Header(label); + Im.Window.DrawList.Text(Im.Font.Default, Im.Font.Default.Size, pos, ImGuiColor.Text.Get().Color, "Layout"u8); return ret; } private static bool DrawMaterialParamLayoutBufferSize(ShpkFile file, Resource? materialParams) { - var isSizeWellDefined = (file.MaterialParamsSize & 0xF) == 0 + var isSizeWellDefined = (file.MaterialParamsSize & 0xF) is 0 && (!materialParams.HasValue || file.MaterialParamsSize == materialParams.Value.Size << 4); if (isSizeWellDefined) return true; - ImUtf8.Text(materialParams.HasValue + Im.Text(materialParams.HasValue ? $"Buffer size mismatch: {file.MaterialParamsSize} bytes ≠ {materialParams.Value.Size} registers ({materialParams.Value.Size << 4} bytes)" : $"Buffer size mismatch: {file.MaterialParamsSize} bytes, not a multiple of 16"); return false; @@ -387,9 +374,9 @@ public partial class ModEditWindow private static bool DrawShaderPackageMaterialMatrix(ShpkTab tab, bool disabled) { - ImUtf8.Text(tab.Shpk.Disassembled - ? "Parameter positions (continuations are grayed out, globally unused values are red, unused values within filters are yellow):" - : "Parameter positions (continuations are grayed out):"); + Im.Text(tab.Shpk.Disassembled + ? "Parameter positions (continuations are grayed out, globally unused values are red, unused values within filters are yellow):"u8 + : "Parameter positions (continuations are grayed out):"u8); using var table = Im.Table.Begin("##MaterialParamLayout"u8, 5, TableFlags.SizingFixedFit | TableFlags.RowBackground); @@ -401,34 +388,34 @@ public partial class ModEditWindow table.SetupColumn("y"u8, TableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); table.SetupColumn("z"u8, TableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); table.SetupColumn("w"u8, TableColumnFlags.WidthFixed, 250 * Im.Style.GlobalScale); - ImGui.TableHeadersRow(); + table.HeaderRow(); - var textColorStart = ImGuiColor.Text.Get().Color; + var textColorStart = ImGuiColor.Text.Get(); var ret = false; for (var i = 0; i < tab.Matrix.GetLength(0); ++i) { - ImGui.TableNextColumn(); - ImGui.TableHeader($" [{i}]"); + table.NextColumn(); + table.Header($" [{i}]"); for (var j = 0; j < 4; ++j) { var (name, tooltip, idx, colorType) = tab.Matrix[i, j]; var color = textColorStart; if (!colorType.HasFlag(ShpkTab.ColorType.Used)) - color = ImGuiUtil.HalfBlend(color, 0x80u); // Half red + color = color.HalfBlend(new Rgba32(0x80)); // Half red else if (!colorType.HasFlag(ShpkTab.ColorType.FilteredUsed)) - color = ImGuiUtil.HalfBlend(color, 0x8080u); // Half yellow + color = color.HalfBlend(0x8080u); // Half yellow if (colorType.HasFlag(ShpkTab.ColorType.Continuation)) - color = ImGuiUtil.HalfTransparent(color); // Half opacity - using var _ = ImRaii.PushId(i * 4 + j); + color = color.HalfTransparent(); // Half opacity + using var _ = Im.Id.Push(i * 4 + j); var deletable = !disabled && idx >= 0; - using (ImRaii.PushFont(UiBuilder.MonoFont, tooltip.Length > 0)) + using (Im.Font.Mono.Push(tooltip.Length > 0)) { using (ImGuiColor.Text.Push(color)) { - ImGui.TableNextColumn(); - ImUtf8.Selectable(name); - if (deletable && Im.Item.RightClicked() && ImGui.GetIO().KeyCtrl) + table.NextColumn(); + Im.Selectable(name); + if (deletable && Im.Item.RightClicked() && Im.Io.KeyControl) { tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.RemoveItems(idx); ret = true; @@ -449,7 +436,7 @@ public partial class ModEditWindow private static void DrawShaderPackageMaterialDevkitExport(ShpkTab tab) { - if (!ImUtf8.Button("Export globally unused parameters as material dev-kit file"u8)) + if (!Im.Button("Export globally unused parameters as material dev-kit file"u8)) return; tab.FileDialog.OpenSavePicker("Export material dev-kit file", ".json", $"{Path.GetFileNameWithoutExtension(tab.FilePath)}.json", @@ -480,13 +467,13 @@ public partial class ModEditWindow private static void DrawShaderPackageMisalignedParameters(ShpkTab tab) { - using var t = ImUtf8.TreeNode("Misaligned / Overflowing Parameters"u8); + using var t = Im.Tree.Node("Misaligned / Overflowing Parameters"u8); if (!t) return; - using var _ = ImRaii.PushFont(UiBuilder.MonoFont); + using var _ = Im.Font.PushMono(); foreach (var name in tab.MalformedParameters) - ImUtf8.TreeNode(name, ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf(name); } private static void DrawShaderPackageStartCombo(ShpkTab tab) @@ -495,17 +482,17 @@ public partial class ModEditWindow using (Im.Font.PushMono()) { Im.Item.SetNextWidth(Im.Style.GlobalScale * 400); - using var c = ImUtf8.Combo("##Start", tab.Orphans[tab.NewMaterialParamStart].Name); + using var c = Im.Combo.Begin("##Start"u8, tab.Orphans[tab.NewMaterialParamStart].Name); if (c) - foreach (var(idx, start) in tab.Orphans.Index()) + foreach (var (idx, start) in tab.Orphans.Index()) { - if (ImGui.Selectable(start.Name, idx == tab.NewMaterialParamStart)) + if (Im.Selectable(start.Name, idx == tab.NewMaterialParamStart)) tab.UpdateOrphanStart(idx); } } Im.Line.Same(); - ImUtf8.Text("Start"u8); + Im.Text("Start"u8); } private static void DrawShaderPackageEndCombo(ShpkTab tab) @@ -514,7 +501,7 @@ public partial class ModEditWindow using (Im.Font.PushMono()) { Im.Item.SetNextWidth(Im.Style.GlobalScale * 400); - using var c = ImUtf8.Combo("##End", tab.Orphans[tab.NewMaterialParamEnd].Name); + using var c = Im.Combo.Begin("##End"u8, tab.Orphans[tab.NewMaterialParamEnd].Name); if (c) { var current = tab.Orphans[tab.NewMaterialParamStart].Index; @@ -524,19 +511,19 @@ public partial class ModEditWindow if (current++ != next.Index) break; - if (ImGui.Selectable(next.Name, i == tab.NewMaterialParamEnd)) + if (Im.Selectable(next.Name, i == tab.NewMaterialParamEnd)) tab.NewMaterialParamEnd = i; } } } Im.Line.Same(); - ImUtf8.Text("End"u8); + Im.Text("End"u8); } private static bool DrawShaderPackageNewParameter(ShpkTab tab) { - if (tab.Orphans.Count == 0) + if (tab.Orphans.Count is 0) return false; DrawShaderPackageStartCombo(tab); @@ -544,14 +531,15 @@ public partial class ModEditWindow Im.Item.SetNextWidth(Im.Style.GlobalScale * 400); var newName = tab.NewMaterialParamName.Value!; - if (ImUtf8.InputText("Name", ref newName)) + if (Im.Input.Text("Name"u8, ref newName)) tab.NewMaterialParamName = newName; var tooltip = tab.UsedIds.Contains(tab.NewMaterialParamName.Crc32) ? "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 * Im.Style.GlobalScale, Im.Style.FrameHeight), tooltip.Length > 0)) + if (!ImEx.Button($"Add {tab.NewMaterialParamName} (0x{tab.NewMaterialParamName.Crc32:X8})", + new Vector2(400 * Im.Style.GlobalScale, Im.Style.FrameHeight), + tooltip, tooltip.Length > 0)) return false; tab.Shpk.MaterialParams = tab.Shpk.MaterialParams.AddItem(new MaterialParam @@ -592,38 +580,36 @@ public partial class ModEditWindow { var ret = false; - if (!ImUtf8.CollapsingHeader("Shader Resources"u8)) + if (!Im.Tree.Header("Shader Resources"u8)) return false; var hasFilters = tab.FilterPopCount != tab.FilterMaximumPopCount; - ret |= DrawShaderPackageResourceArray("Constant Buffers", "type", true, tab.Shpk.Constants, hasFilters, disabled); - ret |= DrawShaderPackageResourceArray("Samplers", "type", false, tab.Shpk.Samplers, hasFilters, disabled); + ret |= DrawShaderPackageResourceArray("Constant Buffers"u8, "type", true, tab.Shpk.Constants, hasFilters, disabled); + ret |= DrawShaderPackageResourceArray("Samplers"u8, "type", false, tab.Shpk.Samplers, hasFilters, disabled); if (!tab.Shpk.IsLegacy) - ret |= DrawShaderPackageResourceArray("Textures", "type", false, tab.Shpk.Textures, hasFilters, disabled); - ret |= DrawShaderPackageResourceArray("Unordered Access Views", "type", false, tab.Shpk.Uavs, hasFilters, disabled); + ret |= DrawShaderPackageResourceArray("Textures"u8, "type", false, tab.Shpk.Textures, hasFilters, disabled); + ret |= DrawShaderPackageResourceArray("Unordered Access Views"u8, "type", false, tab.Shpk.Uavs, hasFilters, disabled); return ret; } - private static void DrawKeyArray(ShpkTab tab, string arrayName, bool withId, IReadOnlyCollection keys) + private static void DrawKeyArray(ShpkTab tab, ReadOnlySpan arrayName, bool withId, IReadOnlyCollection keys) { - if (keys.Count == 0) + if (keys.Count is 0) return; - using var t = ImUtf8.TreeNode(arrayName); + using var t = Im.Tree.Node(arrayName); if (!t) return; - using var font = ImRaii.PushFont(UiBuilder.MonoFont); + using var font = Im.Font.PushMono(); foreach (var (idx, key) in keys.Index()) { - using var t2 = ImUtf8.TreeNode(withId ? $"#{idx}: {tab.TryResolveName(key.Id)} (0x{key.Id:X8})" : $"#{idx}"); + using var t2 = Im.Tree.Node(withId ? $"#{idx}: {tab.TryResolveName(key.Id)} (0x{key.Id:X8})" : $"#{idx}"); if (t2) { - ImUtf8.TreeNode($"Default Value: {tab.TryResolveName(key.DefaultValue)} (0x{key.DefaultValue:X8})", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); - ImUtf8.TreeNode($"Known Values: {tab.NameSetToString(key.Values, true)}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet) - .Dispose(); + Im.Tree.Leaf($"Default Value: {tab.TryResolveName(key.DefaultValue)} (0x{key.DefaultValue:X8})"); + Im.Tree.Leaf($"Known Values: {tab.NameSetToString(key.Values, true)}"); } } } @@ -633,96 +619,86 @@ public partial class ModEditWindow if (tab.Shpk.Nodes.Length <= 0) return; - using var t = ImUtf8.TreeNode($"Nodes ({tab.Shpk.Nodes.Length})###Nodes"); + using var t = Im.Tree.Node($"Nodes ({tab.Shpk.Nodes.Length})###Nodes"); if (!t) return; - using var font = ImRaii.PushFont(UiBuilder.MonoFont); + using var font = Im.Font.PushMono(); foreach (var (idx, node) in tab.Shpk.Nodes.Index()) { if (!tab.IsFilterMatch(node)) continue; - using var t2 = ImUtf8.TreeNode($"#{idx:D4}: Selector: 0x{node.Selector:X8}"); + using var t2 = Im.Tree.Node($"#{idx:D4}: Selector: 0x{node.Selector:X8}"); if (!t2) continue; foreach (var (keyIdx, key) in node.SystemKeys.Index()) { - ImUtf8.TreeNode( - $"System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SystemValues![keyIdx])} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"System Key {tab.TryResolveName(tab.Shpk.SystemKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SystemValues![keyIdx])} }}"); } foreach (var (keyIdx, key) in node.SceneKeys.Index()) { - ImUtf8.TreeNode( - $"Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SceneValues![keyIdx])} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"Scene Key {tab.TryResolveName(tab.Shpk.SceneKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SceneValues![keyIdx])} }}"); } foreach (var (keyIdx, key) in node.MaterialKeys.Index()) { - ImUtf8.TreeNode( - $"Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.MaterialValues![keyIdx])} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"Material Key {tab.TryResolveName(tab.Shpk.MaterialKeys[keyIdx].Id)} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.MaterialValues![keyIdx])} }}"); } foreach (var (keyIdx, key) in node.SubViewKeys.Index()) { - ImUtf8.TreeNode( - $"Sub-View Key #{keyIdx} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SubViewValues![keyIdx])} }}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf( + $"Sub-View Key #{keyIdx} = {tab.TryResolveName(key)} / \u2208 {{ {tab.NameSetToString(node.SubViewValues![keyIdx])} }}"); } - ImUtf8.TreeNode($"Pass Indices: {string.Join(' ', node.PassIndices.Select(c => $"{c:X2}"))}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf($"Pass Indices: {string.Join(' ', node.PassIndices.Select(c => $"{c:X2}"))}"); foreach (var (passIdx, pass) in node.Passes.Index()) { - ImUtf8.TreeNode( - $"Pass #{passIdx}: ID: {tab.TryResolveName(pass.Id)}, Vertex Shader #{pass.VertexShader}, Pixel Shader #{pass.PixelShader}", - ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet) - .Dispose(); + Im.Tree.Leaf( + $"Pass #{passIdx}: ID: {tab.TryResolveName(pass.Id)}, Vertex Shader #{pass.VertexShader}, Pixel Shader #{pass.PixelShader}"); } } } private static void DrawShaderPackageSelection(ShpkTab tab) { - if (!ImUtf8.CollapsingHeader("Shader Selection"u8)) + if (!Im.Tree.Header("Shader Selection"u8)) return; - DrawKeyArray(tab, "System Keys", true, tab.Shpk.SystemKeys); - DrawKeyArray(tab, "Scene Keys", true, tab.Shpk.SceneKeys); - DrawKeyArray(tab, "Material Keys", true, tab.Shpk.MaterialKeys); - DrawKeyArray(tab, "Sub-View Keys", false, tab.Shpk.SubViewKeys); + DrawKeyArray(tab, "System Keys"u8, true, tab.Shpk.SystemKeys); + DrawKeyArray(tab, "Scene Keys"u8, true, tab.Shpk.SceneKeys); + DrawKeyArray(tab, "Material Keys"u8, true, tab.Shpk.MaterialKeys); + DrawKeyArray(tab, "Sub-View Keys"u8, false, tab.Shpk.SubViewKeys); DrawShaderPackageNodes(tab); - using var t = ImUtf8.TreeNode($"Node Selectors ({tab.Shpk.NodeSelectors.Count})###NodeSelectors"); + using var t = Im.Tree.Node($"Node Selectors ({tab.Shpk.NodeSelectors.Count})###NodeSelectors"); if (t) { - using var font = ImRaii.PushFont(UiBuilder.MonoFont); + using var font = Im.Font.PushMono(); foreach (var selector in tab.Shpk.NodeSelectors) - { - ImUtf8.TreeNode($"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet) - .Dispose(); - } + Im.Tree.Leaf($"#{selector.Value:D4}: Selector: 0x{selector.Key:X8}"); } } private static void DrawOtherShaderPackageDetails(ShpkTab tab) { - if (!ImUtf8.CollapsingHeader("Further Content"u8)) + if (!Im.Tree.Header("Further Content"u8)) return; - ImUtf8.TreeNode($"Version: 0x{tab.Shpk.Version:X8}", ImGuiTreeNodeFlags.Leaf | ImGuiTreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf($"Version: 0x{tab.Shpk.Version:X8}"); if (tab.Shpk.AdditionalData.Length > 0) { - using var t = ImUtf8.TreeNode($"Additional Data (Size: {tab.Shpk.AdditionalData.Length})###AdditionalData"); + using var t = Im.Tree.Node($"Additional Data (Size: {tab.Shpk.AdditionalData.Length})###AdditionalData"); if (t) - Widget.DrawHexViewer(tab.Shpk.AdditionalData); + ImEx.HexViewer(tab.Shpk.AdditionalData); } } @@ -737,10 +713,8 @@ public partial class ModEditWindow { switch (components) { - case 0: break; - case DisassembledShader.VectorComponents.All: - sb.Append($"[{i}], "); - break; + case 0: break; + case DisassembledShader.VectorComponents.All: sb.Append($"[{i}], "); break; default: sb.Append($"[{i}]."); foreach (var c in components.ToString().Where(char.IsUpper)) @@ -753,10 +727,8 @@ public partial class ModEditWindow switch (usedDynamically ?? 0) { - case 0: break; - case DisassembledShader.VectorComponents.All: - sb.Append("[*], "); - break; + case 0: break; + case DisassembledShader.VectorComponents.All: sb.Append("[*], "); break; default: sb.Append("[*]."); foreach (var c in usedDynamically!.Value.ToString().Where(char.IsUpper)) @@ -782,6 +754,6 @@ public partial class ModEditWindow sb.Append("Alpha, "); } - return sb.Length == 0 ? string.Empty : sb.ToString(0, sb.Length - 2); + return sb.Length is 0 ? string.Empty : sb.ToString(0, sb.Length - 2); } } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs index 69a7613e..f43ff702 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs @@ -1,8 +1,5 @@ -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; -using OtterGui; -using OtterGui.Raii; using OtterTex; using Penumbra.Communication; using Penumbra.Import.Textures; @@ -41,18 +38,18 @@ public partial class ModEditWindow "Save the current texture compressed via BC7 compression.\nThis offers a 4:1 compression ratio and has almost indistinguishable quality, but may take a while.\n\nGeneric format that can be used for most textures."), }; - private void DrawInputChild(string label, Texture tex, Vector2 size, Vector2 imageSize) + private void DrawInputChild(ReadOnlySpan label, Texture tex, Vector2 size, Vector2 imageSize) { - using (var child = ImRaii.Child(label, size, true)) + using (var child = Im.Child.Begin(label, size, true)) { if (!child) return; - using var id = ImRaii.PushId(label); + using var id = Im.Id.Push(label); ImEx.TextFramed(label, Im.ContentRegion.Available with { Y = 0 }, ImGuiColor.FrameBackground.Get()); Im.Line.New(); - using (ImRaii.Disabled(!_center.SaveTask.IsCompleted)) + using (Im.Disabled(!_center.SaveTask.IsCompleted)) { TextureDrawer.PathInputBox(_textures, tex, ref tex.TmpPath, "##input"u8, "Import Image..."u8, "Can import game paths as well as your own files."u8, Mod!.ModPath.FullName, _fileDialog, _config.DefaultModImportPath); @@ -69,7 +66,7 @@ public partial class ModEditWindow } Im.Line.New(); - using var child2 = ImRaii.Child("image"); + using var child2 = Im.Child.Begin("image"u8); if (child2) TextureDrawer.Draw(tex, imageSize); } @@ -82,44 +79,43 @@ public partial class ModEditWindow { var (text, desc) = SaveAsStrings[_currentSaveAs]; Im.Item.SetNextWidth(-Im.Style.FrameHeight - Im.Style.ItemSpacing.X); - using var combo = ImRaii.Combo("##format", text); - ImGuiUtil.HoverTooltip(desc); + using var combo = Im.Combo.Begin("##format"u8, text); + Im.Tooltip.OnHover(desc); if (!combo) return; foreach (var (idx, (newText, newDesc)) in SaveAsStrings.Index()) { - if (ImGui.Selectable(newText, idx == _currentSaveAs)) + if (Im.Selectable(newText, idx == _currentSaveAs)) _currentSaveAs = idx; - ImGuiUtil.SelectableHelpMarker(newDesc); + LunaStyle.DrawRightAlignedHelpMarker(newDesc); } } private void RedrawOnSaveBox() { var redraw = _config.Ephemeral.ForceRedrawOnFileChange; - if (ImGui.Checkbox("Redraw on Save", ref redraw)) + if (Im.Checkbox("Redraw on Save"u8, ref redraw)) { _config.Ephemeral.ForceRedrawOnFileChange = redraw; _config.Ephemeral.Save(); } - ImGuiUtil.HoverTooltip("Force a redraw of your player character whenever you save a file here."); + Im.Tooltip.OnHover("Force a redraw of your player character whenever you save a file here."u8); } private void MipMapInput() { - ImGui.Checkbox("##mipMaps", ref _addMipMaps); - ImGuiUtil.HoverTooltip( - "Add the appropriate number of MipMaps to the file."); + Im.Checkbox("##mipMaps"u8, ref _addMipMaps); + Im.Tooltip.OnHover("Add the appropriate number of MipMaps to the file."u8); } private bool _forceTextureStartPath = true; private void DrawOutputChild(Vector2 size, Vector2 imageSize) { - using var child = ImRaii.Child("Output", size, true); + using var child = Im.Child.Begin("Output"u8, size, true); if (!child) return; @@ -133,14 +129,13 @@ public partial class ModEditWindow var canSaveInPlace = Path.IsPathRooted(_left.Path) && _left.Type is TextureType.Tex or TextureType.Dds or TextureType.Png; var isActive = _config.DeleteModModifier.IsActive(); - var tt = isActive - ? "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((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var buttonSize3 = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X * 2) / 3, 0); - if (ImGuiUtil.DrawDisabledButton("Save in place", buttonSize2, - tt, !isActive || !canSaveInPlace || _center.IsLeftCopy && _currentSaveAs == (int)CombinedTexture.TextureSaveType.AsIs)) + if (ImEx.Button("Save in place"u8, buttonSize2, + isActive + ? "This saves the texture in place. This is not revertible."u8 + : $"This saves the texture in place. This is not revertible. Hold {_config.DeleteModModifier} to save.", + !isActive || !canSaveInPlace || _center.IsLeftCopy && _currentSaveAs is (int)CombinedTexture.TextureSaveType.AsIs)) { _center.SaveAs(_left.Type, _textures, _left.Path, (CombinedTexture.TextureSaveType)_currentSaveAs, _addMipMaps); AddChangeTask(_left.Path); @@ -148,23 +143,23 @@ public partial class ModEditWindow } Im.Line.Same(); - if (ImGui.Button("Save as TEX", buttonSize2)) + if (Im.Button("Save as TEX"u8, buttonSize2)) OpenSaveAsDialog(".tex"); - if (ImGui.Button("Export as TGA", buttonSize3)) + if (Im.Button("Export as TGA"u8, buttonSize3)) OpenSaveAsDialog(".tga"); Im.Line.Same(); - if (ImGui.Button("Export as PNG", buttonSize3)) + if (Im.Button("Export as PNG"u8, buttonSize3)) OpenSaveAsDialog(".png"); Im.Line.Same(); - if (ImGui.Button("Export as DDS", buttonSize3)) + if (Im.Button("Export as DDS"u8, buttonSize3)) OpenSaveAsDialog(".dds"); Im.Line.New(); var canConvertInPlace = canSaveInPlace && _left.Type is TextureType.Tex && _center.IsLeftCopy; - if (ImGuiUtil.DrawDisabledButton("Convert to BC7", buttonSize3, - "This converts the texture to BC7 format in place. This is not revertible.", + if (ImEx.Button("Convert to BC7"u8, buttonSize3, + "This converts the texture to BC7 format in place. This is not revertible."u8, !canConvertInPlace || _left.Format is DXGIFormat.BC7Typeless or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB)) { _center.SaveAsTex(_textures, _left.Path, CombinedTexture.TextureSaveType.BC7, _left.MipMaps > 1); @@ -173,8 +168,8 @@ public partial class ModEditWindow } Im.Line.Same(); - if (ImGuiUtil.DrawDisabledButton("Convert to BC3", buttonSize3, - "This converts the texture to BC3 format in place. This is not revertible.", + if (ImEx.Button("Convert to BC3"u8, buttonSize3, + "This converts the texture to BC3 format in place. This is not revertible."u8, !canConvertInPlace || _left.Format is DXGIFormat.BC3Typeless or DXGIFormat.BC3UNorm or DXGIFormat.BC3UNormSRGB)) { _center.SaveAsTex(_textures, _left.Path, CombinedTexture.TextureSaveType.BC3, _left.MipMaps > 1); @@ -183,8 +178,8 @@ public partial class ModEditWindow } Im.Line.Same(); - if (ImGuiUtil.DrawDisabledButton("Convert to RGBA", buttonSize3, - "This converts the texture to RGBA format in place. This is not revertible.", + if (ImEx.Button("Convert to RGBA"u8, buttonSize3, + "This converts the texture to RGBA format in place. This is not revertible."u8, !canConvertInPlace || _left.Format is DXGIFormat.B8G8R8A8UNorm or DXGIFormat.B8G8R8A8Typeless or DXGIFormat.B8G8R8A8UNormSRGB)) { @@ -199,22 +194,22 @@ public partial class ModEditWindow case TaskStatus.WaitingForActivation: case TaskStatus.WaitingToRun: case TaskStatus.Running: - ImGuiUtil.DrawTextButton("Computing...", -Vector2.UnitX, new Rgba32(Colors.PressEnterWarningBg).Color); + ImEx.TextFramed("Computing..."u8, Im.ContentRegion.Available with { Y = 0 }, Colors.PressEnterWarningBg); break; case TaskStatus.Canceled: case TaskStatus.Faulted: { Im.Text("Could not save file:"u8); using var color = ImGuiColor.Text.Push(new Vector4(1, 0, 0, 1)); - ImGuiUtil.TextWrapped(_center.SaveTask.Exception?.ToString() ?? "Unknown Error"); + Im.TextWrapped(_center.SaveTask.Exception?.ToString() ?? "Unknown Error"); break; } - default: ImGui.Dummy(new Vector2(1, Im.Style.FrameHeight)); break; + default: Im.Dummy(new Vector2(1, Im.Style.FrameHeight)); break; } Im.Line.New(); - using var child2 = ImRaii.Child("image"); + using var child2 = Im.Child.Begin("image"u8); if (child2) _center.Draw(_textures, imageSize); } @@ -292,7 +287,7 @@ public partial class ModEditWindow private void DrawTextureTab() { - using var tab = ImRaii.TabItem("Textures"); + using var tab = Im.TabBar.BeginItem("Textures"u8); if (!tab) return; @@ -309,13 +304,13 @@ public partial class ModEditWindow }); var childWidth = GetChildWidth(); var imageSize = new Vector2(childWidth.X - Im.Style.FramePadding.X * 2); - DrawInputChild("Input Texture", _left, childWidth, imageSize); + DrawInputChild("Input Texture"u8, _left, childWidth, imageSize); Im.Line.Same(); DrawOutputChild(childWidth, imageSize); if (!_overlayCollapsed) { Im.Line.Same(); - DrawInputChild("Overlay Texture", _right, childWidth, imageSize); + DrawInputChild("Overlay Texture"u8, _right, childWidth, imageSize); } Im.Line.Same(); @@ -330,12 +325,12 @@ public partial class ModEditWindow private void DrawOverlayCollapseButton() { 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(Im.Style.TextHeight, Im.ContentRegion.Available.Y))) + ? RefTuple.Create(">"u8, "Show a third panel in which you can import an additional texture as an overlay for the primary texture."u8) + : RefTuple.Create("<"u8, "Hide the overlay texture panel and clear the currently loaded overlay texture, if any."u8); + if (Im.Button(label, Im.ContentRegion.Available with { X = Im.Style.TextHeight })) _overlayCollapsed = !_overlayCollapsed; - ImGuiUtil.HoverTooltip(tooltip); + Im.Tooltip.OnHover(tooltip); } private static bool GetFirstTexture(IEnumerable files, [NotNullWhen(true)] out string? file) @@ -345,10 +340,10 @@ public partial class ModEditWindow } private static readonly string[] ValidTextureExtensions = - { + [ ".png", ".dds", ".tex", ".tga", - }; + ]; } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index 05246aba..5087cfab 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -1,13 +1,10 @@ -using Dalamud.Interface; +using System.Collections.Frozen; using Dalamud.Interface.Components; using Dalamud.Interface.DragDrop; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; using ImSharp; using Luna; using OtterGui; -using OtterGui.Raii; -using OtterGui.Text; using Penumbra.Api.Enums; using Penumbra.Collections.Manager; using Penumbra.Communication; @@ -27,6 +24,7 @@ using Penumbra.String.Classes; using Penumbra.UI.AdvancedWindow.Materials; using Penumbra.UI.AdvancedWindow.Meta; using Penumbra.UI.Classes; +using Penumbra.UI.Combos; using MdlMaterialEditor = Penumbra.Mods.Editor.MdlMaterialEditor; namespace Penumbra.UI.AdvancedWindow; @@ -154,7 +152,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable sb.Append($" | {subMods} Options"); if (size > 0) - sb.Append($" | {_editor.Files.Available.Count} Files ({Functions.HumanReadableSize(size)})"); + sb.Append($" | {_editor.Files.Available.Count} Files ({FormattingFunctions.HumanReadableSize(size)})"); if (unused > 0) sb.Append($" | {unused} Unused Files"); @@ -203,12 +201,12 @@ public partial class ModEditWindow : IndexedWindow, IDisposable var thickness = (int)(20 * Im.Style.GlobalScale); var offsetX = Im.ContentRegion.Available.X / 2 - radius; var offsetY = Im.ContentRegion.Available.Y / 2 - radius; - ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(offsetX, offsetY)); + Im.Cursor.Position += new Vector2(offsetX, offsetY); ImEx.Spinner("##spinner"u8, radius, thickness, ImGuiColor.Text.Get()); return; } - using var tabBar = ImUtf8.TabBar("##tabs"u8); + using var tabBar = Im.TabBar.Begin("##tabs"u8); if (!tabBar) return; @@ -223,7 +221,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable _materialTab.Draw(); DrawTextureTab(); _shaderPackageTab.Draw(); - using (var tab = ImUtf8.TabItem("Item Swap"u8)) + using (var tab = tabBar.Item("Item Swap"u8)) { if (tab) _itemSwapTab.DrawContent(); @@ -235,6 +233,15 @@ public partial class ModEditWindow : IndexedWindow, IDisposable DrawMaterialReassignmentTab(); } + private static readonly FrozenDictionary RaceCodeNames = Enum.GetValues().ToFrozenDictionary(v => v, v => + { + if (v is GenderRace.Unknown) + return new StringU8("All Races and Genders"); + + var (gender, race) = v.Split(); + return new StringU8($"({v.ToRaceCode()}) {race.ToNameU8()} {gender.ToNameU8()} "); + }); + /// A row of three buttonSizes and a help marker that can be used for material suffix changing. private static class MaterialSuffix { @@ -242,25 +249,16 @@ public partial class ModEditWindow : IndexedWindow, IDisposable private static string _materialSuffixTo = string.Empty; private static GenderRace _raceCode = GenderRace.Unknown; - private static string RaceCodeName(GenderRace raceCode) - { - if (raceCode == GenderRace.Unknown) - return "All Races and Genders"; - - var (gender, race) = raceCode.Split(); - return $"({raceCode.ToRaceCode()}) {race.ToName()} {gender.ToName()} "; - } - private static void DrawRaceCodeCombo(Vector2 buttonSize) { Im.Item.SetNextWidth(buttonSize.X); - using var combo = ImRaii.Combo("##RaceCode", RaceCodeName(_raceCode)); + using var combo = Im.Combo.Begin("##RaceCode"u8, RaceCodeNames[_raceCode]); if (!combo) return; - foreach (var raceCode in Enum.GetValues()) + foreach (var (raceCode, name) in RaceCodeNames) { - if (ImGui.Selectable(RaceCodeName(raceCode), _raceCode == raceCode)) + if (Im.Selectable(name, _raceCode == raceCode)) _raceCode = raceCode; } } @@ -270,175 +268,172 @@ public partial class ModEditWindow : IndexedWindow, IDisposable DrawRaceCodeCombo(buttonSize); Im.Line.Same(); Im.Item.SetNextWidth(buttonSize.X); - ImGui.InputTextWithHint("##suffixFrom", "From...", ref _materialSuffixFrom, 32); + Im.Input.Text("##suffixFrom"u8, ref _materialSuffixFrom, "From..."u8); Im.Line.Same(); Im.Item.SetNextWidth(buttonSize.X); - ImGui.InputTextWithHint("##suffixTo", "To...", ref _materialSuffixTo, 32); + Im.Input.Text("##suffixTo"u8, ref _materialSuffixTo, "To..."u8); Im.Line.Same(); var disabled = !MdlMaterialEditor.ValidString(_materialSuffixTo); - var tt = _materialSuffixTo.Length == 0 + Utf8StringHandler tt = _materialSuffixTo.Length is 0 ? "Please enter a target suffix." : _materialSuffixFrom == _materialSuffixTo ? "The source and target are identical." : disabled ? "The suffix is invalid." - : _materialSuffixFrom.Length == 0 - ? _raceCode == GenderRace.Unknown + : _materialSuffixFrom.Length is 0 + ? _raceCode is GenderRace.Unknown ? "Convert all skin material suffices to the target." : "Convert all skin material suffices for the given race code to the target." - : _raceCode == GenderRace.Unknown + : _raceCode is GenderRace.Unknown ? $"Convert all skin material suffices that are currently '{_materialSuffixFrom}' to '{_materialSuffixTo}'." : $"Convert all skin material suffices for the given race code that are currently '{_materialSuffixFrom}' to '{_materialSuffixTo}'."; - if (ImGuiUtil.DrawDisabledButton("Change Material Suffix", buttonSize, tt, disabled)) + if (ImEx.Button("Change Material Suffix"u8, buttonSize, tt, disabled)) editor.MdlMaterialEditor.ReplaceAllMaterials(_materialSuffixTo, _materialSuffixFrom, _raceCode); var anyChanges = editor.MdlMaterialEditor.ModelFiles.Any(m => m.Changed); - if (ImGuiUtil.DrawDisabledButton("Save All Changes", buttonSize, - anyChanges ? "Irreversibly rewrites all currently applied changes to model files." : "No changes made yet.", !anyChanges)) + if (ImEx.Button("Save All Changes"u8, buttonSize, + anyChanges ? "Irreversibly rewrites all currently applied changes to model files."u8 : "No changes made yet."u8, + !anyChanges)) editor.MdlMaterialEditor.SaveAllModels(editor.Compactor); Im.Line.Same(); - if (ImGuiUtil.DrawDisabledButton("Revert All Changes", buttonSize, - anyChanges ? "Revert all currently made and unsaved changes." : "No changes made yet.", !anyChanges)) + if (ImEx.Button("Revert All Changes"u8, buttonSize, + anyChanges ? "Revert all currently made and unsaved changes."u8 : "No changes made yet."u8, !anyChanges)) editor.MdlMaterialEditor.RestoreAllModels(); - Im.Line.Same(); - ImGuiComponents.HelpMarker( - "Model files refer to the skin material they should use. This skin material is always the same, but modders have started using different suffices to differentiate between body types.\n" - + "This option allows you to switch the suffix of all model files to another. This changes the files, so you do this on your own risk.\n" - + "If you do not know what the currently used suffix of this mod is, you can leave 'From' blank and it will replace all suffices with 'To', instead of only the matching ones."); + Im.Line.SameInner(); + LunaStyle.DrawAlignedHelpMarker( + "Model files refer to the skin material they should use. This skin material is always the same, but modders have started using different suffices to differentiate between body types.\n"u8 + + "This option allows you to switch the suffix of all model files to another. This changes the files, so you do this on your own risk.\n"u8 + + "If you do not know what the currently used suffix of this mod is, you can leave 'From' blank and it will replace all suffices with 'To', instead of only the matching ones."u8); } } private void DrawMissingFilesTab() { - if (_editor.Files.Missing.Count == 0) + if (_editor.Files.Missing.Count is 0) return; - using var tab = ImRaii.TabItem("Missing Files"); + using var tab = Im.TabBar.BeginItem("Missing Files"u8); if (!tab) return; Im.Line.New(); - if (ImGui.Button("Remove Missing Files from Mod")) + if (Im.Button("Remove Missing Files from Mod"u8)) _editor.FileEditor.RemoveMissingPaths(Mod!, _editor.Option!); - using var child = ImRaii.Child("##unusedFiles", -Vector2.One, true); + using var child = Im.Child.Begin("##unusedFiles"u8, Im.ContentRegion.Available, true); if (!child) return; - using var table = Im.Table.Begin("##missingFiles"u8, 1, TableFlags.RowBackground, -Vector2.One); + using var table = Im.Table.Begin("##missingFiles"u8, 1, TableFlags.RowBackground, Im.ContentRegion.Available); if (!table) return; foreach (var path in _editor.Files.Missing) - { - ImGui.TableNextColumn(); - Im.Text(path.FullName); - } + table.DrawColumn(path.FullName); } private void DrawDuplicatesTab() { - using var tab = ImRaii.TabItem("Duplicates"); + using var tab = Im.TabBar.BeginItem("Duplicates"u8); if (!tab) return; if (_editor.Duplicates.Worker.IsCompleted) { - if (ImGuiUtil.DrawDisabledButton("Scan for Duplicates", Vector2.Zero, - "Search for identical files in this mod. This may take a while.", false)) + if (ImEx.Button("Scan for Duplicates"u8, Vector2.Zero, + "Search for identical files in this mod. This may take a while."u8)) _editor.Duplicates.StartDuplicateCheck(_editor.Files.Available); } else { - if (ImGuiUtil.DrawDisabledButton("Cancel Scanning for Duplicates", Vector2.Zero, "Cancel the current scanning operation...", false)) + if (ImEx.Button("Cancel Scanning for Duplicates"u8, Vector2.Zero, "Cancel the current scanning operation..."u8)) _editor.Duplicates.Clear(); } - const string desc = - "Tries to create a unique copy of a file for every game path manipulated and put them in [Groupname]/[Optionname]/[GamePath] order.\n" - + "This will also delete all unused files and directories if it succeeds.\n" - + "Care was taken that a failure should not destroy the mod but revert to its original state, but you use this at your own risk anyway."; - var modifier = _config.DeleteModModifier.IsActive(); - var tt = _allowReduplicate ? desc : - modifier ? desc : desc + $"\n\nNo duplicates detected! Hold {_config.DeleteModModifier} to force normalization anyway."; - if (_editor.ModNormalizer.Running) { - ImGui.ProgressBar((float)_editor.ModNormalizer.Step / _editor.ModNormalizer.TotalSteps, + Im.ProgressBar((float)_editor.ModNormalizer.Step / _editor.ModNormalizer.TotalSteps, 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)) + else if (ImEx.Button("Re-Duplicate and Normalize Mod"u8, Vector2.Zero, + "Tries to create a unique copy of a file for every game path manipulated and put them in [Groupname]/[Optionname]/[GamePath] order.\n"u8 + + "This will also delete all unused files and directories if it succeeds.\n"u8 + + "Care was taken that a failure should not destroy the mod but revert to its original state, but you use this at your own risk anyway."u8, + !_allowReduplicate && !modifier)) { _editor.ModNormalizer.Normalize(Mod!); _editor.ModNormalizer.Worker.ContinueWith(_ => _editor.LoadMod(Mod!, _editor.GroupIdx, _editor.DataIdx), TaskScheduler.Default); } + if (_allowReduplicate && !modifier) + Im.Tooltip.OnHover($"\n\nNo duplicates detected! Hold {_config.DeleteModModifier} to force normalization anyway."); + if (!_editor.Duplicates.Worker.IsCompleted) return; - if (_editor.Duplicates.Duplicates.Count == 0) + if (_editor.Duplicates.Duplicates.Count is 0) { Im.Line.New(); Im.Text("No duplicates found."u8); return; } - if (ImGui.Button("Delete and Redirect Duplicates")) + if (Im.Button("Delete and Redirect Duplicates"u8)) _editor.Duplicates.DeleteDuplicates(_editor.Files, _editor.Mod!, _editor.Option!, true); if (_editor.Duplicates.SavedSpace > 0) { Im.Line.Same(); - Im.Text($"Frees up {Functions.HumanReadableSize(_editor.Duplicates.SavedSpace)} from your hard drive."); + Im.Text($"Frees up {FormattingFunctions.HumanReadableSize(_editor.Duplicates.SavedSpace)} from your hard drive."); } - using var child = ImRaii.Child("##duptable", -Vector2.One, true); + using var child = Im.Child.Begin("##duptable"u8, Im.ContentRegion.Available, true); if (!child) return; - using var table = Im.Table.Begin("##duplicates"u8, 3, TableFlags.RowBackground | TableFlags.SizingFixedFit, -Vector2.One); + using var table = Im.Table.Begin("##duplicates"u8, 3, TableFlags.RowBackground | TableFlags.SizingFixedFit, Im.ContentRegion.Available); if (!table) return; - var width = ImGui.CalcTextSize("NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN ").X; + var width = Im.Font.CalculateSize("NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN "u8).X; table.SetupColumn("file"u8, TableColumnFlags.WidthStretch); - table.SetupColumn("size"u8, TableColumnFlags.WidthFixed, ImGui.CalcTextSize("NNN.NNN "u8).X); + table.SetupColumn("size"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("NNN.NNN "u8).X); table.SetupColumn("hash"u8, TableColumnFlags.WidthFixed, - ImGui.GetWindowWidth() > 2 * width ? width : Im.Font.CalculateSize("NNNNNNNN... "u8).X); + Im.Window.Width > 2 * width ? width : Im.Font.CalculateSize("NNNNNNNN... "u8).X); foreach (var (set, size, hash) in _editor.Duplicates.Duplicates.Where(s => s.Paths.Length > 1)) { - ImGui.TableNextColumn(); - using var tree = ImRaii.TreeNode(set[0].FullName[(Mod!.ModPath.FullName.Length + 1)..], - ImGuiTreeNodeFlags.NoTreePushOnOpen); - ImGui.TableNextColumn(); - ImGuiUtil.RightAlign(Functions.HumanReadableSize(size)); - ImGui.TableNextColumn(); - using (var _ = ImRaii.PushFont(UiBuilder.MonoFont)) + table.NextColumn(); + using var tree = Im.Tree.Node(set[0].FullName[(Mod!.ModPath.FullName.Length + 1)..], + TreeNodeFlags.NoTreePushOnOpen); + table.NextColumn(); + ImEx.TextRightAligned(FormattingFunctions.HumanReadableSize(size)); + table.NextColumn(); + using (var _ = Im.Font.PushMono()) { - if (ImGui.GetWindowWidth() > 2 * width) - ImGuiUtil.RightAlign(string.Concat(hash.Select(b => b.ToString("X2")))); + if (Im.Window.Width > 2 * width) + ImEx.TextRightAligned(FormattingFunctions.BytewiseHex(hash)); else - ImGuiUtil.RightAlign(string.Concat(hash.Take(4).Select(b => b.ToString("X2"))) + "..."); + ImEx.TextRightAligned($"{FormattingFunctions.BytewiseHex(hash.AsSpan(4))}..."); } if (!tree) continue; - using var indent = ImRaii.PushIndent(); + using var indent = Im.Indent(); foreach (var duplicate in set.Skip(1)) { - ImGui.TableNextColumn(); - ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, Colors.RedTableBgTint); - using var node = ImRaii.TreeNode(duplicate.FullName[(Mod!.ModPath.FullName.Length + 1)..], ImGuiTreeNodeFlags.Leaf); - ImGui.TableNextColumn(); - ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, Colors.RedTableBgTint); - ImGui.TableNextColumn(); - ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, Colors.RedTableBgTint); + table.NextColumn(); + table.SetBackgroundColor(TableBackgroundTarget.Cell, Colors.RedTableBgTint); + Im.Tree.Leaf(duplicate.FullName.AsSpan(Mod!.ModPath.FullName.Length + 1), TreeNodeFlags.Leaf); + table.NextColumn(); + table.SetBackgroundColor(TableBackgroundTarget.Cell, Colors.RedTableBgTint); + table.NextColumn(); + table.SetBackgroundColor(TableBackgroundTarget.Cell, Colors.RedTableBgTint); } } } @@ -448,7 +443,7 @@ public partial class ModEditWindow : IndexedWindow, IDisposable using var style = ImStyleDouble.ItemSpacing.Push(Vector2.Zero).Push(ImStyleSingle.FrameRounding, 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, + if (ImEx.Button("Default Option"u8, width, "Switch to the default option for the mod.\nThis resets unsaved changes."u8, _editor.Option is DefaultSubMod)) { _editor.LoadOption(-1, 0).Wait(); @@ -456,17 +451,16 @@ public partial class ModEditWindow : IndexedWindow, IDisposable } Im.Line.Same(); - if (ImUtf8.ButtonEx("Refresh Data"u8, "Refresh data for the current option.\nThis resets unsaved changes."u8, width)) + if (ImEx.Button("Refresh Data"u8, width, "Refresh data for the current option.\nThis resets unsaved changes."u8)) { _editor.LoadMod(_editor.Mod!, _editor.GroupIdx, _editor.DataIdx).Wait(); ret = true; } Im.Line.Same(); - if (_optionSelect.Draw(width.X)) + if (_optionSelect.Draw("##option"u8, _editor.Option?.GetFullName() ?? string.Empty, default, width.X, out var option)) { - var (groupIdx, dataIdx) = _optionSelect.CurrentSelection.Index; - _editor.LoadOption(groupIdx, dataIdx).Wait(); + _editor.LoadOption(option.GroupIndex, option.DataIndex).Wait(); ret = true; } @@ -478,36 +472,36 @@ public partial class ModEditWindow : IndexedWindow, IDisposable private void DrawSwapTab() { - using var tab = ImRaii.TabItem("File Swaps"); + using var tab = Im.TabBar.BeginItem("File Swaps"u8); if (!tab) return; DrawOptionSelectHeader(); var setsEqual = !_editor.SwapEditor.Changes; - var tt = setsEqual ? "No changes staged." : "Apply the currently staged changes to the option."; + var tt = setsEqual ? "No changes staged."u8 : "Apply the currently staged changes to the option."u8; Im.Line.New(); - if (ImGuiUtil.DrawDisabledButton("Apply Changes", Vector2.Zero, tt, setsEqual)) + if (ImEx.Button("Apply Changes"u8, Vector2.Zero, tt, setsEqual)) _editor.SwapEditor.Apply(_editor.Option!); Im.Line.Same(); - tt = setsEqual ? "No changes staged." : "Revert all currently staged changes."; - if (ImGuiUtil.DrawDisabledButton("Revert Changes", Vector2.Zero, tt, setsEqual)) + tt = setsEqual ? "No changes staged."u8 : "Revert all currently staged changes."u8; + if (ImEx.Button("Revert Changes"u8, Vector2.Zero, tt, setsEqual)) _editor.SwapEditor.Revert(_editor.Option!); var otherSwaps = _editor.Mod!.TotalSwapCount - _editor.Option!.FileSwaps.Count; if (otherSwaps > 0) { Im.Line.Same(); - ImGuiUtil.DrawTextButton($"There are {otherSwaps} file swaps configured in other options.", Vector2.Zero, + ImEx.TextFramed($"There are {otherSwaps} file swaps configured in other options.", Vector2.Zero, ColorId.RedundantAssignment.Value().Color); } - using var child = ImRaii.Child("##swaps", -Vector2.One, true); + using var child = Im.Child.Begin("##swaps"u8, Im.ContentRegion.Available, true); if (!child) return; - using var table = Im.Table.Begin("##table"u8, 3, TableFlags.RowBackground, -Vector2.One); + using var table = Im.Table.Begin("##table"u8, 3, TableFlags.RowBackground, Im.ContentRegion.Available); if (!table) return; @@ -520,46 +514,45 @@ public partial class ModEditWindow : IndexedWindow, IDisposable foreach (var (gamePath, file) in _editor.SwapEditor.Swaps.ToList()) { - using var id = ImRaii.PushId(idx++); - ImGui.TableNextColumn(); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), iconSize, "Delete this swap.", false, true)) + using var id = Im.Id.Push(idx++); + table.NextColumn(); + if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this swap."u8)) _editor.SwapEditor.Remove(gamePath); - ImGui.TableNextColumn(); + table.NextColumn(); var tmp = file.FullName; Im.Item.SetNextWidth(-1); - if (ImGui.InputText("##value", ref tmp, Utf8GamePath.MaxGamePathLength) && tmp.Length > 0) + if (Im.Input.Text("##value"u8, ref tmp, maxLength: Utf8GamePath.MaxGamePathLength) && tmp.Length > 0) _editor.SwapEditor.Change(gamePath, new FullPath(tmp)); - ImGui.TableNextColumn(); + table.NextColumn(); tmp = gamePath.Path.ToString(); Im.Item.SetNextWidth(-1); - if (ImGui.InputText("##key", ref tmp, Utf8GamePath.MaxGamePathLength) + if (Im.Input.Text("##key"u8, ref tmp, maxLength: Utf8GamePath.MaxGamePathLength) && Utf8GamePath.FromString(tmp, out var path) && !_editor.SwapEditor.Swaps.ContainsKey(path)) _editor.SwapEditor.Change(gamePath, path); } - ImGui.TableNextColumn(); + table.NextColumn(); var addable = Utf8GamePath.FromString(_newSwapKey, out var newPath) && newPath.Length > 0 && _newSwapValue.Length > 0 && _newSwapValue != _newSwapKey && !_editor.SwapEditor.Swaps.ContainsKey(newPath); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), iconSize, "Add a new file swap to this option.", !addable, - true)) + if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, "Add a new file swap to this option."u8, !addable)) { _editor.SwapEditor.Add(newPath, new FullPath(_newSwapValue)); _newSwapKey = string.Empty; _newSwapValue = string.Empty; } - ImGui.TableNextColumn(); + table.NextColumn(); Im.Item.SetNextWidth(-1); - ImGui.InputTextWithHint("##swapKey", "Load this file...", ref _newSwapValue, Utf8GamePath.MaxGamePathLength); - ImGui.TableNextColumn(); + Im.Input.Text("##swapKey"u8, ref _newSwapValue, "Load this file..."u8, maxLength: Utf8GamePath.MaxGamePathLength); + table.NextColumn(); Im.Item.SetNextWidth(-1); - ImGui.InputTextWithHint("##swapValue", "... instead of this file.", ref _newSwapKey, Utf8GamePath.MaxGamePathLength); + Im.Input.Text("##swapValue"u8, ref _newSwapKey, "... instead of this file."u8, maxLength: Utf8GamePath.MaxGamePathLength); } /// @@ -573,10 +566,10 @@ public partial class ModEditWindow : IndexedWindow, IDisposable internal FullPath FindBestMatch(Utf8GamePath path) { var currentFile = _activeCollections.Current.ResolvePath(path); - if (currentFile != null) + if (currentFile is not null) return currentFile.Value; - if (Mod != null) + if (Mod is not null) { foreach (var option in Mod.Groups.OrderByDescending(g => g.Priority)) { @@ -594,22 +587,16 @@ public partial class ModEditWindow : IndexedWindow, IDisposable internal HashSet FindPathsStartingWith(CiByteString prefix) { var ret = new HashSet(); - foreach (var path in _activeCollections.Current.ResolvedFiles.Keys) { if (path.Path.StartsWith(prefix)) ret.Add(path); } - if (Mod != null) + if (Mod is not null) foreach (var option in Mod.AllDataContainers) - { - foreach (var path in option.Files.Keys) - { - if (path.Path.StartsWith(prefix)) - ret.Add(path); - } - } + foreach (var path in option.Files.Keys.Where(path => path.Path.StartsWith(prefix))) + ret.Add(path); return ret; } diff --git a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs index c9608247..d3f832d0 100644 --- a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs @@ -48,7 +48,7 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : IU using (Im.Group()) { Im.Text("Merge "u8); - Im.Line.Same(0, 0); + Im.Line.NoSpacing(); if (size - textSize < minComboSize) { Im.Text("selected mod"u8, ColorId.FolderLine.Value()); @@ -59,7 +59,7 @@ public class ModMergeTab(ModMerger modMerger, ModComboWithoutCurrent combo) : IU Im.Text(modMerger.MergeFromMod!.Name, ColorId.FolderLine.Value()); } - Im.Line.Same(0, 0); + Im.Line.NoSpacing(); Im.Text(" into"u8); } diff --git a/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs b/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs deleted file mode 100644 index 51c998ce..00000000 --- a/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Dalamud.Bindings.ImGui; -using ImSharp; -using OtterGui.Text; -using OtterGui.Widgets; -using Penumbra.Mods.Editor; -using Penumbra.UI.Classes; -using MouseWheelType = OtterGui.Widgets.MouseWheelType; - -namespace Penumbra.UI.AdvancedWindow; - -public sealed class OptionSelectCombo(ModEditor editor, ModEditWindow window) - : FilterComboCache<(string FullName, (int Group, int Data) Index)>( - () => window.Mod!.AllDataContainers.Select(c => (c.GetFullName(), c.GetDataIndices())).ToList(), MouseWheelType.Control, Penumbra.Log) -{ - private readonly Im.ColorStyleDisposable _border = new(); - - protected override void DrawCombo(string label, string preview, string tooltip, int currentSelected, float previewWidth, float itemHeight, - ImGuiComboFlags flags) - { - _border.Push(ImStyleBorder.Frame, ColorId.FolderLine.Value()); - base.DrawCombo(label, preview, tooltip, currentSelected, previewWidth, itemHeight, flags); - _border.Dispose(); - } - - protected override void DrawFilter(int currentSelected, float width) - { - _border.Dispose(); - base.DrawFilter(currentSelected, width); - } - - public bool Draw(float width) - { - var flags = window.Mod!.AllDataContainers.Count() switch - { - 0 => ImGuiComboFlags.NoArrowButton, - > 8 => ImGuiComboFlags.HeightLargest, - _ => ImGuiComboFlags.None, - }; - return Draw("##optionSelector", editor.Option!.GetFullName(), string.Empty, width, Im.Style.TextHeight, flags); - } - - protected override bool DrawSelectable(int globalIdx, bool selected) - => ImUtf8.Selectable(Items[globalIdx].FullName, selected); -} diff --git a/Penumbra/UI/CollectionTab/InheritanceUi.cs b/Penumbra/UI/CollectionTab/InheritanceUi.cs index 9a5f2e95..88bdc690 100644 --- a/Penumbra/UI/CollectionTab/InheritanceUi.cs +++ b/Penumbra/UI/CollectionTab/InheritanceUi.cs @@ -115,8 +115,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService _seenInheritedCollections.Contains(inheritance)); _seenInheritedCollections.Add(inheritance); - Im.Tree.Node($"{Name(inheritance)}###{inheritance.Identity.Id}", - TreeNodeFlags.NoTreePushOnOpen | TreeNodeFlags.Leaf | TreeNodeFlags.Bullet).Dispose(); + Im.Tree.Leaf($"{Name(inheritance)}###{inheritance.Identity.Id}", TreeNodeFlags.NoTreePushOnOpen); var (minRect, maxRect) = (Im.Item.UpperLeftCorner, Im.Item.LowerRightCorner); DrawInheritanceTreeClicks(inheritance, false); diff --git a/Penumbra/UI/Combos/AtchPointCombo.cs b/Penumbra/UI/Combos/AtchPointCombo.cs new file mode 100644 index 00000000..5c06eff7 --- /dev/null +++ b/Penumbra/UI/Combos/AtchPointCombo.cs @@ -0,0 +1,11 @@ +using OtterGui.Widgets; +using Penumbra.GameData.Files.AtchStructs; + +namespace Penumbra.UI.Combos; + +internal sealed class AtchPointCombo(Func> generator) + : FilterComboCache(generator, MouseWheelType.Control, Penumbra.Log) +{ + protected override string ToString(AtchType obj) + => obj.ToName(); +} diff --git a/Penumbra/UI/Classes/Combos.cs b/Penumbra/UI/Combos/Combos.cs similarity index 96% rename from Penumbra/UI/Classes/Combos.cs rename to Penumbra/UI/Combos/Combos.cs index f1cb292e..8e505315 100644 --- a/Penumbra/UI/Classes/Combos.cs +++ b/Penumbra/UI/Combos/Combos.cs @@ -3,7 +3,7 @@ using OtterGui; using Penumbra.GameData.Enums; using Penumbra.Meta.Manipulations; -namespace Penumbra.UI.Classes; +namespace Penumbra.UI.Combos; public static class Combos { @@ -31,7 +31,7 @@ public static class Combos public static bool RspAttribute(string label, RspAttribute current, out RspAttribute attribute, float unscaledWidth = 200) => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out attribute, - RspAttributeExtensions.ToFullString, 0, 1); + RspAttributeExtensions.ToName, 0, 1); public static bool EstSlot(string label, EstType current, out EstType attribute, float unscaledWidth = 200) => ImGuiUtil.GenericEnumCombo(label, unscaledWidth * Im.Style.GlobalScale, current, out attribute); diff --git a/Penumbra/UI/Combos/OptionSelectCombo.cs b/Penumbra/UI/Combos/OptionSelectCombo.cs new file mode 100644 index 00000000..7a30d68f --- /dev/null +++ b/Penumbra/UI/Combos/OptionSelectCombo.cs @@ -0,0 +1,61 @@ +using ImSharp; +using Penumbra.Mods.Editor; +using Penumbra.Mods.SubMods; +using Penumbra.UI.AdvancedWindow; +using Penumbra.UI.Classes; + +namespace Penumbra.UI.Combos; + +public sealed class OptionSelectCombo : FilterComboBase +{ + private sealed class OptionFilter : Utf8FilterBase