diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 377919b2..c87c0244 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: run: dotnet restore - name: Download Dalamud run: | - Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -OutFile latest.zip + Invoke-WebRequest -Uri https://goatcorp.github.io/dalamud-distrib/latest.zip -OutFile latest.zip Expand-Archive -Force latest.zip "$env:AppData\XIVLauncher\addon\Hooks\dev" - name: Build run: | diff --git a/OtterGui b/OtterGui index a63f6735..78528f93 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit a63f6735cf4bed4f7502a022a10378607082b770 +Subproject commit 78528f93ac253db0061d9a8244cfa0cee5c2f873 diff --git a/Penumbra.Api b/Penumbra.Api index 3d6cee1a..ff7b3b40 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 3d6cee1a11922ccd426f36060fd026bc1a698adf +Subproject commit ff7b3b4014a97455f823380c78b8a7c5107f8e2f diff --git a/Penumbra.CrashHandler/Penumbra.CrashHandler.csproj b/Penumbra.CrashHandler/Penumbra.CrashHandler.csproj index 1b1f0a28..4cb53c8b 100644 --- a/Penumbra.CrashHandler/Penumbra.CrashHandler.csproj +++ b/Penumbra.CrashHandler/Penumbra.CrashHandler.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/Penumbra.GameData b/Penumbra.GameData index d889f9ef..10fdb025 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit d889f9ef918514a46049725052d378b441915b00 +Subproject commit 10fdb025436f7ea9f1f5e97635c19eee0578de7b diff --git a/Penumbra.String b/Penumbra.String index c8611a0c..0e5dcd1a 160000 --- a/Penumbra.String +++ b/Penumbra.String @@ -1 +1 @@ -Subproject commit c8611a0c546b6b2ec29214ab319fc2c38fe74793 +Subproject commit 0e5dcd1a5687ec5f8fa2ef2526b94b9a0ea1b5b5 diff --git a/Penumbra/Api/Api/IdentityChecker.cs b/Penumbra/Api/Api/IdentityChecker.cs deleted file mode 100644 index e090053e..00000000 --- a/Penumbra/Api/Api/IdentityChecker.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Penumbra.Api.Api; - -public static class IdentityChecker -{ - public static bool Check(string identity) - => true; -} diff --git a/Penumbra/Api/Api/ModsApi.cs b/Penumbra/Api/Api/ModsApi.cs index 1f4f1cf4..78c62953 100644 --- a/Penumbra/Api/Api/ModsApi.cs +++ b/Penumbra/Api/Api/ModsApi.cs @@ -1,4 +1,3 @@ -using Newtonsoft.Json.Linq; using OtterGui.Compression; using OtterGui.Services; using Penumbra.Api.Enums; @@ -34,8 +33,12 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable { switch (type) { - case ModPathChangeType.Deleted when oldDirectory != null: ModDeleted?.Invoke(oldDirectory.Name); break; - case ModPathChangeType.Added when newDirectory != null: ModAdded?.Invoke(newDirectory.Name); break; + case ModPathChangeType.Deleted when oldDirectory != null: + ModDeleted?.Invoke(oldDirectory.Name); + break; + case ModPathChangeType.Added when newDirectory != null: + ModAdded?.Invoke(newDirectory.Name); + break; case ModPathChangeType.Moved when newDirectory != null && oldDirectory != null: ModMoved?.Invoke(oldDirectory.Name, newDirectory.Name); break; @@ -43,9 +46,7 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable } public void Dispose() - { - _communicator.ModPathChanged.Unsubscribe(OnModPathChanged); - } + => _communicator.ModPathChanged.Unsubscribe(OnModPathChanged); public Dictionary GetModList() => _modManager.ToDictionary(m => m.ModPath.Name, m => m.Name.Text); @@ -108,18 +109,6 @@ public class ModsApi : IPenumbraApiMods, IApiService, IDisposable public event Action? ModAdded; public event Action? ModMoved; - public event Action? CreatingPcp - { - add => _communicator.PcpCreation.Subscribe(value!, PcpCreation.Priority.ModsApi); - remove => _communicator.PcpCreation.Unsubscribe(value!); - } - - public event Action? ParsingPcp - { - add => _communicator.PcpParsing.Subscribe(value!, PcpParsing.Priority.ModsApi); - remove => _communicator.PcpParsing.Unsubscribe(value!); - } - public (PenumbraApiEc, string, bool, bool) GetModPath(string modDirectory, string modName) { if (!_modManager.TryGetMod(modDirectory, modName, out var mod) diff --git a/Penumbra/Api/Api/PenumbraApi.cs b/Penumbra/Api/Api/PenumbraApi.cs index c4026c72..7ca41324 100644 --- a/Penumbra/Api/Api/PenumbraApi.cs +++ b/Penumbra/Api/Api/PenumbraApi.cs @@ -17,7 +17,7 @@ public class PenumbraApi( UiApi ui) : IDisposable, IApiService, IPenumbraApi { public const int BreakingVersion = 5; - public const int FeatureVersion = 13; + public const int FeatureVersion = 10; public void Dispose() { diff --git a/Penumbra/Api/Api/RedrawApi.cs b/Penumbra/Api/Api/RedrawApi.cs index 08f1f9df..ec4de892 100644 --- a/Penumbra/Api/Api/RedrawApi.cs +++ b/Penumbra/Api/Api/RedrawApi.cs @@ -2,14 +2,11 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; using OtterGui.Services; using Penumbra.Api.Enums; -using Penumbra.Collections; -using Penumbra.Collections.Manager; -using Penumbra.GameData.Interop; using Penumbra.Interop.Services; -namespace Penumbra.Api.Api; - -public class RedrawApi(RedrawService redrawService, IFramework framework, CollectionManager collections, ObjectManager objects, ApiHelpers helpers) : IPenumbraApiRedraw, IApiService +namespace Penumbra.Api.Api; + +public class RedrawApi(RedrawService redrawService, IFramework framework) : IPenumbraApiRedraw, IApiService { public void RedrawObject(int gameObjectIndex, RedrawType setting) { @@ -31,27 +28,9 @@ public class RedrawApi(RedrawService redrawService, IFramework framework, Collec framework.RunOnFrameworkThread(() => redrawService.RedrawAll(setting)); } - public void RedrawCollectionMembers(Guid collectionId, RedrawType setting) - { - - if (!collections.Storage.ById(collectionId, out var collection)) - collection = ModCollection.Empty; - framework.RunOnFrameworkThread(() => - { - foreach (var actor in objects.Objects) - { - helpers.AssociatedCollection(actor.ObjectIndex, out var modCollection); - if (collection == modCollection) - { - redrawService.RedrawObject(actor.ObjectIndex, setting); - } - } - }); - } - public event GameObjectRedrawnDelegate? GameObjectRedrawn { add => redrawService.GameObjectRedrawn += value; remove => redrawService.GameObjectRedrawn -= value; } -} +} diff --git a/Penumbra/Api/Api/TemporaryApi.cs b/Penumbra/Api/Api/TemporaryApi.cs index 7567acd3..a997ded8 100644 --- a/Penumbra/Api/Api/TemporaryApi.cs +++ b/Penumbra/Api/Api/TemporaryApi.cs @@ -20,16 +20,8 @@ public class TemporaryApi( ApiHelpers apiHelpers, ModManager modManager) : IPenumbraApiTemporary, IApiService { - public (PenumbraApiEc, Guid) CreateTemporaryCollection(string identity, string name) - { - if (!IdentityChecker.Check(identity)) - return (PenumbraApiEc.InvalidCredentials, Guid.Empty); - - var collection = tempCollections.CreateTemporaryCollection(name); - if (collection == Guid.Empty) - return (PenumbraApiEc.UnknownError, collection); - return (PenumbraApiEc.Success, collection); - } + public Guid CreateTemporaryCollection(string name) + => tempCollections.CreateTemporaryCollection(name); public PenumbraApiEc DeleteTemporaryCollection(Guid collectionId) => tempCollections.RemoveTemporaryCollection(collectionId) diff --git a/Penumbra/Api/HttpApi.cs b/Penumbra/Api/HttpApi.cs index 79348a88..b6e1d799 100644 --- a/Penumbra/Api/HttpApi.cs +++ b/Penumbra/Api/HttpApi.cs @@ -5,7 +5,6 @@ using EmbedIO.WebApi; using OtterGui.Services; using Penumbra.Api.Api; using Penumbra.Api.Enums; -using Penumbra.Mods.Settings; namespace Penumbra.Api; @@ -14,15 +13,12 @@ public class HttpApi : IDisposable, IApiService private partial class Controller : WebApiController { // @formatter:off - [Route( HttpVerbs.Get, "/moddirectory" )] public partial string GetModDirectory(); - [Route( HttpVerbs.Get, "/mods" )] public partial object? GetMods(); - [Route( HttpVerbs.Post, "/redraw" )] public partial Task Redraw(); - [Route( HttpVerbs.Post, "/redrawAll" )] public partial Task RedrawAll(); - [Route( HttpVerbs.Post, "/reloadmod" )] public partial Task ReloadMod(); - [Route( HttpVerbs.Post, "/installmod" )] public partial Task InstallMod(); - [Route( HttpVerbs.Post, "/openwindow" )] public partial void OpenWindow(); - [Route( HttpVerbs.Post, "/focusmod" )] public partial Task FocusMod(); - [Route( HttpVerbs.Post, "/setmodsettings")] public partial Task SetModSettings(); + [Route( HttpVerbs.Get, "/mods" )] public partial object? GetMods(); + [Route( HttpVerbs.Post, "/redraw" )] public partial Task Redraw(); + [Route( HttpVerbs.Post, "/redrawAll" )] public partial Task RedrawAll(); + [Route( HttpVerbs.Post, "/reloadmod" )] public partial Task ReloadMod(); + [Route( HttpVerbs.Post, "/installmod" )] public partial Task InstallMod(); + [Route( HttpVerbs.Post, "/openwindow" )] public partial void OpenWindow(); // @formatter:on } @@ -68,12 +64,6 @@ public class HttpApi : IDisposable, IApiService private partial class Controller(IPenumbraApi api, IFramework framework) { - public partial string GetModDirectory() - { - Penumbra.Log.Debug($"[HTTP] {nameof(GetModDirectory)} triggered."); - return api.PluginState.GetModDirectory(); - } - public partial object? GetMods() { Penumbra.Log.Debug($"[HTTP] {nameof(GetMods)} triggered."); @@ -126,38 +116,6 @@ public class HttpApi : IDisposable, IApiService api.Ui.OpenMainWindow(TabType.Mods, string.Empty, string.Empty); } - public async partial Task FocusMod() - { - var data = await HttpContext.GetRequestDataAsync().ConfigureAwait(false); - Penumbra.Log.Debug($"[HTTP] {nameof(FocusMod)} triggered."); - if (data.Path.Length != 0) - api.Ui.OpenMainWindow(TabType.Mods, data.Path, data.Name); - } - - public async partial Task SetModSettings() - { - var data = await HttpContext.GetRequestDataAsync().ConfigureAwait(false); - Penumbra.Log.Debug($"[HTTP] {nameof(SetModSettings)} triggered."); - await framework.RunOnFrameworkThread(() => - { - var collection = data.CollectionId ?? api.Collection.GetCollection(ApiCollectionType.Current)!.Value.Id; - if (data.Inherit.HasValue) - { - api.ModSettings.TryInheritMod(collection, data.ModPath, data.ModName, data.Inherit.Value); - if (data.Inherit.Value) - return; - } - - if (data.State.HasValue) - api.ModSettings.TrySetMod(collection, data.ModPath, data.ModName, data.State.Value); - if (data.Priority.HasValue) - api.ModSettings.TrySetModPriority(collection, data.ModPath, data.ModName, data.Priority.Value); - foreach (var (group, settings) in data.Settings ?? []) - api.ModSettings.TrySetModSettings(collection, data.ModPath, data.ModName, group, settings); - } - ).ConfigureAwait(false); - } - private record ModReloadData(string Path, string Name) { public ModReloadData() @@ -165,13 +123,6 @@ public class HttpApi : IDisposable, IApiService { } } - private record ModFocusData(string Path, string Name) - { - public ModFocusData() - : this(string.Empty, string.Empty) - { } - } - private record ModInstallData(string Path) { public ModInstallData() @@ -185,19 +136,5 @@ public class HttpApi : IDisposable, IApiService : this(string.Empty, RedrawType.Redraw, -1) { } } - - private record SetModSettingsData( - Guid? CollectionId, - string ModPath, - string ModName, - bool? Inherit, - bool? State, - int? Priority, - Dictionary>? Settings) - { - public SetModSettingsData() - : this(null, string.Empty, string.Empty, null, null, null, null) - {} - } } } diff --git a/Penumbra/Api/IpcProviders.cs b/Penumbra/Api/IpcProviders.cs index 5f04540f..7dcee375 100644 --- a/Penumbra/Api/IpcProviders.cs +++ b/Penumbra/Api/IpcProviders.cs @@ -54,8 +54,6 @@ public sealed class IpcProviders : IDisposable, IApiService IpcSubscribers.ModDeleted.Provider(pi, api.Mods), IpcSubscribers.ModAdded.Provider(pi, api.Mods), IpcSubscribers.ModMoved.Provider(pi, api.Mods), - IpcSubscribers.CreatingPcp.Provider(pi, api.Mods), - IpcSubscribers.ParsingPcp.Provider(pi, api.Mods), IpcSubscribers.GetModPath.Provider(pi, api.Mods), IpcSubscribers.SetModPath.Provider(pi, api.Mods), IpcSubscribers.GetChangedItems.Provider(pi, api.Mods), @@ -88,7 +86,6 @@ public sealed class IpcProviders : IDisposable, IApiService IpcSubscribers.RedrawObject.Provider(pi, api.Redraw), IpcSubscribers.RedrawAll.Provider(pi, api.Redraw), IpcSubscribers.GameObjectRedrawn.Provider(pi, api.Redraw), - IpcSubscribers.RedrawCollectionMembers.Provider(pi, api.Redraw), IpcSubscribers.ResolveDefaultPath.Provider(pi, api.Resolve), IpcSubscribers.ResolveInterfacePath.Provider(pi, api.Resolve), diff --git a/Penumbra/Api/IpcTester/CollectionsIpcTester.cs b/Penumbra/Api/IpcTester/CollectionsIpcTester.cs index f033b7c3..1d516eba 100644 --- a/Penumbra/Api/IpcTester/CollectionsIpcTester.cs +++ b/Penumbra/Api/IpcTester/CollectionsIpcTester.cs @@ -1,7 +1,7 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility; using Dalamud.Plugin; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; @@ -121,10 +121,6 @@ public class CollectionsIpcTester(IDalamudPluginInterface pi) : IUiService }).ToArray(); ImGui.OpenPopup("Changed Item List"); } - IpcTester.DrawIntro(RedrawCollectionMembers.Label, "Redraw Collection Members"); - if (ImGui.Button("Redraw##ObjectCollection")) - new RedrawCollectionMembers(pi).Invoke(collectionList[0].Id, RedrawType.Redraw); - } private void DrawChangedItemPopup() diff --git a/Penumbra/Api/IpcTester/EditingIpcTester.cs b/Penumbra/Api/IpcTester/EditingIpcTester.cs index d754cf90..a1001630 100644 --- a/Penumbra/Api/IpcTester/EditingIpcTester.cs +++ b/Penumbra/Api/IpcTester/EditingIpcTester.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Plugin; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/Api/IpcTester/GameStateIpcTester.cs b/Penumbra/Api/IpcTester/GameStateIpcTester.cs index 38a09714..04541a57 100644 --- a/Penumbra/Api/IpcTester/GameStateIpcTester.cs +++ b/Penumbra/Api/IpcTester/GameStateIpcTester.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Plugin; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using Penumbra.Api.Enums; diff --git a/Penumbra/Api/IpcTester/IpcTester.cs b/Penumbra/Api/IpcTester/IpcTester.cs index b03d7e03..201e7068 100644 --- a/Penumbra/Api/IpcTester/IpcTester.cs +++ b/Penumbra/Api/IpcTester/IpcTester.cs @@ -1,6 +1,6 @@ using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.System.Framework; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using Penumbra.Api.Api; diff --git a/Penumbra/Api/IpcTester/MetaIpcTester.cs b/Penumbra/Api/IpcTester/MetaIpcTester.cs index bee1981c..9cf20cd7 100644 --- a/Penumbra/Api/IpcTester/MetaIpcTester.cs +++ b/Penumbra/Api/IpcTester/MetaIpcTester.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Plugin; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs b/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs index 152efa45..c8eb8496 100644 --- a/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs +++ b/Penumbra/Api/IpcTester/ModSettingsIpcTester.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Plugin; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/Api/IpcTester/ModsIpcTester.cs b/Penumbra/Api/IpcTester/ModsIpcTester.cs index 9ea53366..a24861a3 100644 --- a/Penumbra/Api/IpcTester/ModsIpcTester.cs +++ b/Penumbra/Api/IpcTester/ModsIpcTester.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface.Utility; using Dalamud.Plugin; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/Api/IpcTester/PluginStateIpcTester.cs b/Penumbra/Api/IpcTester/PluginStateIpcTester.cs index 073305d0..a1bf4fc4 100644 --- a/Penumbra/Api/IpcTester/PluginStateIpcTester.cs +++ b/Penumbra/Api/IpcTester/PluginStateIpcTester.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Interface.Utility; using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/Api/IpcTester/RedrawingIpcTester.cs b/Penumbra/Api/IpcTester/RedrawingIpcTester.cs index 6b853ed2..b862dde5 100644 --- a/Penumbra/Api/IpcTester/RedrawingIpcTester.cs +++ b/Penumbra/Api/IpcTester/RedrawingIpcTester.cs @@ -1,6 +1,6 @@ using Dalamud.Plugin; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using Penumbra.Api.Enums; diff --git a/Penumbra/Api/IpcTester/ResolveIpcTester.cs b/Penumbra/Api/IpcTester/ResolveIpcTester.cs index 9fc5bfc7..a79b099d 100644 --- a/Penumbra/Api/IpcTester/ResolveIpcTester.cs +++ b/Penumbra/Api/IpcTester/ResolveIpcTester.cs @@ -1,5 +1,5 @@ using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using Penumbra.Api.IpcSubscribers; diff --git a/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs b/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs index e6c8d52e..48f3b4a8 100644 --- a/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs +++ b/Penumbra/Api/IpcTester/ResourceTreeIpcTester.cs @@ -1,8 +1,8 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Interface; using Dalamud.Interface.Utility; using Dalamud.Plugin; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs index d46c5728..c106a867 100644 --- a/Penumbra/Api/IpcTester/TemporaryIpcTester.cs +++ b/Penumbra/Api/IpcTester/TemporaryIpcTester.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; @@ -38,7 +38,6 @@ public class TemporaryIpcTester( private string _tempGamePath = "test/game/path.mtrl"; private string _tempFilePath = "test/success.mtrl"; private string _tempManipulation = string.Empty; - private string _identity = string.Empty; private PenumbraApiEc _lastTempError; private int _tempActorIndex; private bool _forceOverwrite; @@ -49,7 +48,6 @@ public class TemporaryIpcTester( if (!_) return; - ImGui.InputTextWithHint("##identity", "Identity...", ref _identity, 128); ImGui.InputTextWithHint("##tempCollection", "Collection Name...", ref _tempCollectionName, 128); ImGuiUtil.GuidInput("##guid", "Collection GUID...", string.Empty, ref _tempGuid, ref _tempCollectionGuidName); ImGui.InputInt("##tempActorIndex", ref _tempActorIndex, 0, 0); @@ -75,7 +73,7 @@ public class TemporaryIpcTester( IpcTester.DrawIntro(CreateTemporaryCollection.Label, "Create Temporary Collection"); if (ImGui.Button("Create##Collection")) { - _lastTempError = new CreateTemporaryCollection(pi).Invoke(_identity, _tempCollectionName, out LastCreatedCollectionId); + LastCreatedCollectionId = new CreateTemporaryCollection(pi).Invoke(_tempCollectionName); if (_tempGuid == null) { _tempGuid = LastCreatedCollectionId; @@ -284,7 +282,7 @@ public class TemporaryIpcTester( foreach (var mod in list) { ImGui.TableNextColumn(); - ImGui.TextUnformatted(mod.Name.Text); + ImGui.TextUnformatted(mod.Name); ImGui.TableNextColumn(); ImGui.TextUnformatted(mod.Priority.ToString()); ImGui.TableNextColumn(); diff --git a/Penumbra/Api/IpcTester/UiIpcTester.cs b/Penumbra/Api/IpcTester/UiIpcTester.cs index 852339c9..647a4dda 100644 --- a/Penumbra/Api/IpcTester/UiIpcTester.cs +++ b/Penumbra/Api/IpcTester/UiIpcTester.cs @@ -1,5 +1,5 @@ using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using Penumbra.Api.Enums; diff --git a/Penumbra/ChangedItemMode.cs b/Penumbra/ChangedItemMode.cs index ddb79ee0..dccffded 100644 --- a/Penumbra/ChangedItemMode.cs +++ b/Penumbra/ChangedItemMode.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Text; namespace Penumbra; diff --git a/Penumbra/Collections/CollectionAutoSelector.cs b/Penumbra/Collections/CollectionAutoSelector.cs index f6e6bf72..68dac914 100644 --- a/Penumbra/Collections/CollectionAutoSelector.cs +++ b/Penumbra/Collections/CollectionAutoSelector.cs @@ -59,15 +59,8 @@ public sealed class CollectionAutoSelector : IService, IDisposable return; var collection = _resolver.PlayerCollection(); - if (collection.Identity.Id == Guid.Empty) - { - Penumbra.Log.Debug($"Not setting current collection because character has no mods assigned."); - } - else - { - Penumbra.Log.Debug($"Setting current collection to {collection.Identity.Identifier} through automatic collection selection."); - _collections.SetCollection(collection, CollectionType.Current); - } + Penumbra.Log.Debug($"Setting current collection to {collection.Identity.Identifier} through automatic collection selection."); + _collections.SetCollection(collection, CollectionType.Current); } diff --git a/Penumbra/CommandHandler.cs b/Penumbra/CommandHandler.cs index b5d307ef..9f681da2 100644 --- a/Penumbra/CommandHandler.cs +++ b/Penumbra/CommandHandler.cs @@ -1,7 +1,7 @@ using Dalamud.Game.Command; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Classes; using OtterGui.Services; using Penumbra.Api.Api; diff --git a/Penumbra/Communication/ModPathChanged.cs b/Penumbra/Communication/ModPathChanged.cs index efe59482..1e4f8d36 100644 --- a/Penumbra/Communication/ModPathChanged.cs +++ b/Penumbra/Communication/ModPathChanged.cs @@ -3,7 +3,6 @@ using Penumbra.Api; using Penumbra.Api.Api; using Penumbra.Mods; using Penumbra.Mods.Manager; -using Penumbra.Services; namespace Penumbra.Communication; @@ -21,14 +20,11 @@ public sealed class ModPathChanged() { public enum Priority { - /// - PcpService = int.MinValue, - /// - ApiMods = int.MinValue + 1, + ApiMods = int.MinValue, /// - ApiModSettings = int.MinValue + 1, + ApiModSettings = int.MinValue, /// EphemeralConfig = -500, diff --git a/Penumbra/Communication/PcpCreation.cs b/Penumbra/Communication/PcpCreation.cs deleted file mode 100644 index ca0cfcf6..00000000 --- a/Penumbra/Communication/PcpCreation.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Newtonsoft.Json.Linq; -using OtterGui.Classes; - -namespace Penumbra.Communication; - -/// -/// Triggered when the character.json file for a .pcp file is written. -/// -/// Parameter is the JObject that gets written to file. -/// Parameter is the object index of the game object this is written for. -/// Parameter is the full path to the directory being set up for the PCP creation. -/// -/// -public sealed class PcpCreation() : EventWrapper(nameof(PcpCreation)) -{ - public enum Priority - { - /// - ModsApi = int.MinValue, - } -} diff --git a/Penumbra/Communication/PcpParsing.cs b/Penumbra/Communication/PcpParsing.cs deleted file mode 100644 index 95b78951..00000000 --- a/Penumbra/Communication/PcpParsing.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Newtonsoft.Json.Linq; -using OtterGui.Classes; - -namespace Penumbra.Communication; - -/// -/// Triggered when the character.json file for a .pcp file is parsed and applied. -/// -/// Parameter is parsed JObject that contains the data. -/// Parameter is the identifier of the created mod. -/// Parameter is the GUID of the created collection. -/// -/// -public sealed class PcpParsing() : EventWrapper(nameof(PcpParsing)) -{ - public enum Priority - { - /// - ModsApi = int.MinValue, - } -} diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index 2991230e..8c50dad7 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -18,15 +18,6 @@ using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; namespace Penumbra; -public record PcpSettings -{ - public bool CreateCollection { get; set; } = true; - public bool AssignCollection { get; set; } = true; - public bool AllowIpc { get; set; } = true; - public bool DisableHandling { get; set; } = false; - public string FolderName { get; set; } = "PCP"; -} - [Serializable] public class Configuration : IPluginConfiguration, ISavable, IService { @@ -53,7 +44,6 @@ public class Configuration : IPluginConfiguration, ISavable, IService public string ModDirectory { get; set; } = string.Empty; public string ExportDirectory { get; set; } = string.Empty; - public string WatchDirectory { get; set; } = string.Empty; public bool? UseCrashHandler { get; set; } = null; public bool OpenWindowAtStart { get; set; } = false; @@ -77,13 +67,10 @@ public class Configuration : IPluginConfiguration, ISavable, IService public bool HideRedrawBar { get; set; } = false; public bool HideMachinistOffhandFromChangedItems { get; set; } = true; public bool DefaultTemporaryMode { get; set; } = false; - public bool EnableDirectoryWatch { get; set; } = false; - public bool EnableAutomaticModImport { get; set; } = false; public bool EnableCustomShapes { get; set; } = true; - public PcpSettings PcpSettings = new(); - public RenameField ShowRename { get; set; } = RenameField.BothDataPrio; - public ChangedItemMode ChangedItemDisplay { get; set; } = ChangedItemMode.GroupedCollapsed; - public int OptionGroupCollapsibleMin { get; set; } = 5; + public RenameField ShowRename { get; set; } = RenameField.BothDataPrio; + public ChangedItemMode ChangedItemDisplay { get; set; } = ChangedItemMode.GroupedCollapsed; + public int OptionGroupCollapsibleMin { get; set; } = 5; public Vector2 MinimumSize = new(Constants.MinimumSizeX, Constants.MinimumSizeY); diff --git a/Penumbra/DebugConfiguration.cs b/Penumbra/DebugConfiguration.cs index 3f9e8207..76987df8 100644 --- a/Penumbra/DebugConfiguration.cs +++ b/Penumbra/DebugConfiguration.cs @@ -2,6 +2,5 @@ namespace Penumbra; public class DebugConfiguration { - public static bool WriteImcBytesToLog = false; - public static bool UseSkinMaterialProcessing = true; + public static bool WriteImcBytesToLog = false; } diff --git a/Penumbra/Import/Models/Export/MaterialExporter.cs b/Penumbra/Import/Models/Export/MaterialExporter.cs index 0d91534e..6be2ccbd 100644 --- a/Penumbra/Import/Models/Export/MaterialExporter.cs +++ b/Penumbra/Import/Models/Export/MaterialExporter.cs @@ -1,7 +1,6 @@ using Lumina.Data.Parsing; using Penumbra.GameData.Files; using Penumbra.GameData.Files.MaterialStructs; -using Penumbra.UI.AdvancedWindow.Materials; using SharpGLTF.Materials; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Advanced; @@ -141,13 +140,13 @@ public class MaterialExporter // Lerp between table row values to fetch final pixel values for each subtexture. var lerpedDiffuse = Vector3.Lerp((Vector3)prevRow.DiffuseColor, (Vector3)nextRow.DiffuseColor, rowBlend); - baseColorSpan[x].FromVector4(new Vector4(MtrlTab.PseudoSqrtRgb(lerpedDiffuse), 1)); + baseColorSpan[x].FromVector4(new Vector4(lerpedDiffuse, 1)); var lerpedSpecularColor = Vector3.Lerp((Vector3)prevRow.SpecularColor, (Vector3)nextRow.SpecularColor, rowBlend); - specularSpan[x].FromVector4(new Vector4(MtrlTab.PseudoSqrtRgb(lerpedSpecularColor), 1)); + specularSpan[x].FromVector4(new Vector4(lerpedSpecularColor, 1)); var lerpedEmissive = Vector3.Lerp((Vector3)prevRow.EmissiveColor, (Vector3)nextRow.EmissiveColor, rowBlend); - emissiveSpan[x].FromVector4(new Vector4(MtrlTab.PseudoSqrtRgb(lerpedEmissive), 1)); + emissiveSpan[x].FromVector4(new Vector4(lerpedEmissive, 1)); } } } diff --git a/Penumbra/Import/Models/Export/MeshExporter.cs b/Penumbra/Import/Models/Export/MeshExporter.cs index 6ea2b284..0070a808 100644 --- a/Penumbra/Import/Models/Export/MeshExporter.cs +++ b/Penumbra/Import/Models/Export/MeshExporter.cs @@ -360,11 +360,11 @@ public class MeshExporter // (Bi)tangents are universally stored as ByteFloat4, which uses 0..1 to represent the full -1..1 range. // TODO: While this assumption is safe, it would be sensible to actually check. var bitangent = ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Tangent1)) * 2 - Vector4.One; - + return new VertexPositionNormalTangent( ToVector3(GetFirstSafe(attributes, MdlFile.VertexUsage.Position)), ToVector3(GetFirstSafe(attributes, MdlFile.VertexUsage.Normal)), - bitangent.SanitizeTangent() + bitangent ); } @@ -390,30 +390,23 @@ public class MeshExporter } } - usages.TryGetValue(MdlFile.VertexUsage.Color, out var colours); - var nColors = colours?.Count ?? 0; - var materialUsages = ( uvCount, - nColors + usages.ContainsKey(MdlFile.VertexUsage.Color) ); return materialUsages switch { - (3, 2) => typeof(VertexTexture3Color2Ffxiv), - (3, 1) => typeof(VertexTexture3ColorFfxiv), - (3, 0) => typeof(VertexTexture3), - (2, 2) => typeof(VertexTexture2Color2Ffxiv), - (2, 1) => typeof(VertexTexture2ColorFfxiv), - (2, 0) => typeof(VertexTexture2), - (1, 2) => typeof(VertexTexture1Color2Ffxiv), - (1, 1) => typeof(VertexTexture1ColorFfxiv), - (1, 0) => typeof(VertexTexture1), - (0, 2) => typeof(VertexColor2Ffxiv), - (0, 1) => typeof(VertexColorFfxiv), - (0, 0) => typeof(VertexEmpty), + (3, true) => typeof(VertexTexture3ColorFfxiv), + (3, false) => typeof(VertexTexture3), + (2, true) => typeof(VertexTexture2ColorFfxiv), + (2, false) => typeof(VertexTexture2), + (1, true) => typeof(VertexTexture1ColorFfxiv), + (1, false) => typeof(VertexTexture1), + (0, true) => typeof(VertexColorFfxiv), + (0, false) => typeof(VertexEmpty), - _ => throw _notifier.Exception($"Unhandled UV/color count of {uvCount}/{nColors} encountered."), + _ => throw _notifier.Exception($"Unhandled UV count of {uvCount} encountered."), }; } @@ -426,12 +419,6 @@ public class MeshExporter if (_materialType == typeof(VertexColorFfxiv)) return new VertexColorFfxiv(ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))); - if (_materialType == typeof(VertexColor2Ffxiv)) - { - var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color); - return new VertexColor2Ffxiv(ToVector4(color0), ToVector4(color1)); - } - if (_materialType == typeof(VertexTexture1)) return new VertexTexture1(ToVector2(GetFirstSafe(attributes, MdlFile.VertexUsage.UV))); @@ -441,16 +428,6 @@ public class MeshExporter ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color)) ); - if (_materialType == typeof(VertexTexture1Color2Ffxiv)) - { - var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color); - return new VertexTexture1Color2Ffxiv( - ToVector2(GetFirstSafe(attributes, MdlFile.VertexUsage.UV)), - ToVector4(color0), - ToVector4(color1) - ); - } - // XIV packs two UVs into a single vec4 attribute. if (_materialType == typeof(VertexTexture2)) @@ -471,20 +448,6 @@ public class MeshExporter ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color)) ); } - - if (_materialType == typeof(VertexTexture2Color2Ffxiv)) - { - var uv = ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.UV)); - var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color); - - return new VertexTexture2Color2Ffxiv( - new Vector2(uv.X, uv.Y), - new Vector2(uv.Z, uv.W), - ToVector4(color0), - ToVector4(color1) - ); - } - if (_materialType == typeof(VertexTexture3)) { // Not 100% sure about this @@ -509,21 +472,6 @@ public class MeshExporter ); } - if (_materialType == typeof(VertexTexture3Color2Ffxiv)) - { - var uv0 = ToVector4(attributes[MdlFile.VertexUsage.UV][0]); - var uv1 = ToVector4(attributes[MdlFile.VertexUsage.UV][1]); - var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color); - - return new VertexTexture3Color2Ffxiv( - new Vector2(uv0.X, uv0.Y), - new Vector2(uv0.Z, uv0.W), - new Vector2(uv1.X, uv1.Y), - ToVector4(color0), - ToVector4(color1) - ); - } - throw _notifier.Exception($"Unknown material type {_skinningType}"); } @@ -589,17 +537,6 @@ public class MeshExporter return list[0]; } - - /// Check that the list has length 2 for any case where this is expected and return both entries. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private (T First, T Second) GetBothSafe(IReadOnlyDictionary> attributes, MdlFile.VertexUsage usage) - { - var list = attributes[usage]; - if (list.Count != 2) - throw _notifier.Exception($"{list.Count} usage indices encountered for {usage}, but expected 2."); - - return (list[0], list[1]); - } /// Convert a vertex attribute value to a Vector2. Supported inputs are Vector2, Vector3, and Vector4. private static Vector2 ToVector2(object data) diff --git a/Penumbra/Import/Models/Export/VertexFragment.cs b/Penumbra/Import/Models/Export/VertexFragment.cs index 463c59fc..56495f2f 100644 --- a/Penumbra/Import/Models/Export/VertexFragment.cs +++ b/Penumbra/Import/Models/Export/VertexFragment.cs @@ -84,103 +84,6 @@ public struct VertexColorFfxiv(Vector4 ffxivColor) : IVertexCustom } } -public struct VertexColor2Ffxiv(Vector4 ffxivColor0, Vector4 ffxivColor1) : IVertexCustom -{ - public IEnumerable> GetEncodingAttributes() - { - yield return new KeyValuePair("_FFXIV_COLOR_0", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - yield return new KeyValuePair("_FFXIV_COLOR_1", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - } - - public Vector4 FfxivColor0 = ffxivColor0; - public Vector4 FfxivColor1 = ffxivColor1; - - public int MaxColors - => 0; - - public int MaxTextCoords - => 0; - - private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"]; - - public IEnumerable CustomAttributes - => CustomNames; - - public void Add(in VertexMaterialDelta delta) - { } - - public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - => new(Vector4.Zero, Vector4.Zero, Vector2.Zero, Vector2.Zero); - - public Vector2 GetTexCoord(int index) - => throw new ArgumentOutOfRangeException(nameof(index)); - - public void SetTexCoord(int setIndex, Vector2 coord) - { } - - public bool TryGetCustomAttribute(string attributeName, out object? value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0": - value = FfxivColor0; - return true; - - case "_FFXIV_COLOR_1": - value = FfxivColor1; - return true; - - default: - value = null; - return false; - } - } - - public void SetCustomAttribute(string attributeName, object value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0" when value is Vector4 valueVector4: - FfxivColor0 = valueVector4; - break; - case "_FFXIV_COLOR_1" when value is Vector4 valueVector4: - FfxivColor1 = valueVector4; - break; - } - } - - public Vector4 GetColor(int index) - => throw new ArgumentOutOfRangeException(nameof(index)); - - public void SetColor(int setIndex, Vector4 color) - { } - - public void Validate() - { - var components = new[] - { - FfxivColor0.X, - FfxivColor0.Y, - FfxivColor0.Z, - FfxivColor0.W, - }; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor0)); - components = - [ - FfxivColor1.X, - FfxivColor1.Y, - FfxivColor1.Z, - FfxivColor1.W, - ]; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor1)); - } -} - - public struct VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor) : IVertexCustom { public IEnumerable> GetEncodingAttributes() @@ -269,118 +172,6 @@ public struct VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor) : } } -public struct VertexTexture1Color2Ffxiv(Vector2 texCoord0, Vector4 ffxivColor0, Vector4 ffxivColor1) : IVertexCustom -{ - public IEnumerable> GetEncodingAttributes() - { - yield return new KeyValuePair("TEXCOORD_0", - new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); - yield return new KeyValuePair("_FFXIV_COLOR_0", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - yield return new KeyValuePair("_FFXIV_COLOR_1", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - } - - public Vector2 TexCoord0 = texCoord0; - - public Vector4 FfxivColor0 = ffxivColor0; - public Vector4 FfxivColor1 = ffxivColor1; - - public int MaxColors - => 0; - - public int MaxTextCoords - => 1; - - private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"]; - - public IEnumerable CustomAttributes - => CustomNames; - - public void Add(in VertexMaterialDelta delta) - { - TexCoord0 += delta.TexCoord0Delta; - } - - public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - => new(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), Vector2.Zero); - - public Vector2 GetTexCoord(int index) - => index switch - { - 0 => TexCoord0, - _ => throw new ArgumentOutOfRangeException(nameof(index)), - }; - - public void SetTexCoord(int setIndex, Vector2 coord) - { - if (setIndex == 0) - TexCoord0 = coord; - if (setIndex >= 1) - throw new ArgumentOutOfRangeException(nameof(setIndex)); - } - - public bool TryGetCustomAttribute(string attributeName, out object? value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0": - value = FfxivColor0; - return true; - - case "_FFXIV_COLOR_1": - value = FfxivColor1; - return true; - - default: - value = null; - return false; - } - } - - public void SetCustomAttribute(string attributeName, object value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0" when value is Vector4 valueVector4: - FfxivColor0 = valueVector4; - break; - case "_FFXIV_COLOR_1" when value is Vector4 valueVector4: - FfxivColor1 = valueVector4; - break; - } - } - - public Vector4 GetColor(int index) - => throw new ArgumentOutOfRangeException(nameof(index)); - - public void SetColor(int setIndex, Vector4 color) - { } - - public void Validate() - { - var components = new[] - { - FfxivColor0.X, - FfxivColor0.Y, - FfxivColor0.Z, - FfxivColor0.W, - }; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor0)); - components = - [ - FfxivColor1.X, - FfxivColor1.Y, - FfxivColor1.Z, - FfxivColor1.W, - ]; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor1)); - } -} - - public struct VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor) : IVertexCustom { public IEnumerable> GetEncodingAttributes() @@ -475,124 +266,6 @@ public struct VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vec } } -public struct VertexTexture2Color2Ffxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor0, Vector4 ffxivColor1) : IVertexCustom -{ - public IEnumerable> GetEncodingAttributes() - { - yield return new KeyValuePair("TEXCOORD_0", - new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); - yield return new KeyValuePair("TEXCOORD_1", - new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); - yield return new KeyValuePair("_FFXIV_COLOR_0", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - yield return new KeyValuePair("_FFXIV_COLOR_1", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - } - - public Vector2 TexCoord0 = texCoord0; - public Vector2 TexCoord1 = texCoord1; - public Vector4 FfxivColor0 = ffxivColor0; - public Vector4 FfxivColor1 = ffxivColor1; - - public int MaxColors - => 0; - - public int MaxTextCoords - => 2; - - private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"]; - - public IEnumerable CustomAttributes - => CustomNames; - - public void Add(in VertexMaterialDelta delta) - { - TexCoord0 += delta.TexCoord0Delta; - TexCoord1 += delta.TexCoord1Delta; - } - - public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - => new(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), TexCoord1 - baseValue.GetTexCoord(1)); - - public Vector2 GetTexCoord(int index) - => index switch - { - 0 => TexCoord0, - 1 => TexCoord1, - _ => throw new ArgumentOutOfRangeException(nameof(index)), - }; - - public void SetTexCoord(int setIndex, Vector2 coord) - { - if (setIndex == 0) - TexCoord0 = coord; - if (setIndex == 1) - TexCoord1 = coord; - if (setIndex >= 2) - throw new ArgumentOutOfRangeException(nameof(setIndex)); - } - - public bool TryGetCustomAttribute(string attributeName, out object? value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0": - value = FfxivColor0; - return true; - - case "_FFXIV_COLOR_1": - value = FfxivColor1; - return true; - - default: - value = null; - return false; - } - } - - public void SetCustomAttribute(string attributeName, object value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0" when value is Vector4 valueVector4: - FfxivColor0 = valueVector4; - break; - case "_FFXIV_COLOR_1" when value is Vector4 valueVector4: - FfxivColor1 = valueVector4; - break; - } - } - - public Vector4 GetColor(int index) - => throw new ArgumentOutOfRangeException(nameof(index)); - - public void SetColor(int setIndex, Vector4 color) - { } - - public void Validate() - { - var components = new[] - { - FfxivColor0.X, - FfxivColor0.Y, - FfxivColor0.Z, - FfxivColor0.W, - }; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor0)); - components = - [ - FfxivColor1.X, - FfxivColor1.Y, - FfxivColor1.Z, - FfxivColor1.W, - ]; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor1)); - } - -} - public struct VertexTexture3ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector2 texCoord2, Vector4 ffxivColor) : IVertexCustom { @@ -694,126 +367,3 @@ public struct VertexTexture3ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vec throw new ArgumentOutOfRangeException(nameof(FfxivColor)); } } - -public struct VertexTexture3Color2Ffxiv(Vector2 texCoord0, Vector2 texCoord1, Vector2 texCoord2, Vector4 ffxivColor0, Vector4 ffxivColor1) - : IVertexCustom -{ - public IEnumerable> GetEncodingAttributes() - { - yield return new KeyValuePair("TEXCOORD_0", - new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); - yield return new KeyValuePair("TEXCOORD_1", - new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); - yield return new KeyValuePair("_FFXIV_COLOR_0", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - yield return new KeyValuePair("_FFXIV_COLOR_1", - new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); - } - - public Vector2 TexCoord0 = texCoord0; - public Vector2 TexCoord1 = texCoord1; - public Vector2 TexCoord2 = texCoord2; - public Vector4 FfxivColor0 = ffxivColor0; - public Vector4 FfxivColor1 = ffxivColor1; - - public int MaxColors - => 0; - - public int MaxTextCoords - => 3; - - private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"]; - - public IEnumerable CustomAttributes - => CustomNames; - - public void Add(in VertexMaterialDelta delta) - { - TexCoord0 += delta.TexCoord0Delta; - TexCoord1 += delta.TexCoord1Delta; - TexCoord2 += delta.TexCoord2Delta; - } - - public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - => new(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), TexCoord1 - baseValue.GetTexCoord(1)); - - public Vector2 GetTexCoord(int index) - => index switch - { - 0 => TexCoord0, - 1 => TexCoord1, - 2 => TexCoord2, - _ => throw new ArgumentOutOfRangeException(nameof(index)), - }; - - public void SetTexCoord(int setIndex, Vector2 coord) - { - if (setIndex == 0) - TexCoord0 = coord; - if (setIndex == 1) - TexCoord1 = coord; - if (setIndex == 2) - TexCoord2 = coord; - if (setIndex >= 3) - throw new ArgumentOutOfRangeException(nameof(setIndex)); - } - - public bool TryGetCustomAttribute(string attributeName, out object? value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0": - value = FfxivColor0; - return true; - - case "_FFXIV_COLOR_1": - value = FfxivColor1; - return true; - - default: - value = null; - return false; - } - } - - public void SetCustomAttribute(string attributeName, object value) - { - switch (attributeName) - { - case "_FFXIV_COLOR_0" when value is Vector4 valueVector4: - FfxivColor0 = valueVector4; - break; - case "_FFXIV_COLOR_1" when value is Vector4 valueVector4: - FfxivColor1 = valueVector4; - break; - } - } - - public Vector4 GetColor(int index) - => throw new ArgumentOutOfRangeException(nameof(index)); - - public void SetColor(int setIndex, Vector4 color) - { } - - public void Validate() - { - var components = new[] - { - FfxivColor0.X, - FfxivColor0.Y, - FfxivColor0.Z, - FfxivColor0.W, - }; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor0)); - components = - [ - FfxivColor1.X, - FfxivColor1.Y, - FfxivColor1.Z, - FfxivColor1.W, - ]; - if (components.Any(component => component is < 0 or > 1)) - throw new ArgumentOutOfRangeException(nameof(FfxivColor1)); - } -} diff --git a/Penumbra/Import/Models/Import/VertexAttribute.cs b/Penumbra/Import/Models/Import/VertexAttribute.cs index 155fa833..a1c3246b 100644 --- a/Penumbra/Import/Models/Import/VertexAttribute.cs +++ b/Penumbra/Import/Models/Import/VertexAttribute.cs @@ -319,7 +319,7 @@ public class VertexAttribute var normals = normalAccessor.AsVector3Array(); var tangents = accessors.TryGetValue("TANGENT", out var accessor) - ? accessor.AsVector4Array().ToArray() + ? accessor.AsVector4Array() : CalculateTangents(accessors, indices, normals, notifier); if (tangents == null) diff --git a/Penumbra/Import/Models/ModelExtensions.cs b/Penumbra/Import/Models/ModelExtensions.cs deleted file mode 100644 index 2edb3ca4..00000000 --- a/Penumbra/Import/Models/ModelExtensions.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace Penumbra.Import.Models; - -public static class ModelExtensions -{ - // https://github.com/vpenades/SharpGLTF/blob/2073cf3cd671f8ecca9667f9a8c7f04ed865d3ac/src/Shared/_Extensions.cs#L158 - private const float UnitLengthThresholdVec3 = 0.00674f; - private const float UnitLengthThresholdVec4 = 0.00769f; - - internal static bool _IsFinite(this float value) - { - return float.IsFinite(value); - } - - internal static bool _IsFinite(this Vector2 v) - { - return v.X._IsFinite() && v.Y._IsFinite(); - } - - internal static bool _IsFinite(this Vector3 v) - { - return v.X._IsFinite() && v.Y._IsFinite() && v.Z._IsFinite(); - } - - internal static bool _IsFinite(this in Vector4 v) - { - return v.X._IsFinite() && v.Y._IsFinite() && v.Z._IsFinite() && v.W._IsFinite(); - } - - internal static Boolean IsNormalized(this Vector3 normal) - { - if (!normal._IsFinite()) return false; - - return Math.Abs(normal.Length() - 1) <= UnitLengthThresholdVec3; - } - - internal static void ValidateNormal(this Vector3 normal, string msg) - { - if (!normal._IsFinite()) throw new NotFiniteNumberException($"{msg} is invalid."); - - if (!normal.IsNormalized()) throw new ArithmeticException($"{msg} is not unit length."); - } - - internal static void ValidateTangent(this Vector4 tangent, string msg) - { - if (tangent.W != 1 && tangent.W != -1) throw new ArithmeticException(msg); - - new Vector3(tangent.X, tangent.Y, tangent.Z).ValidateNormal(msg); - } - - internal static Vector3 SanitizeNormal(this Vector3 normal) - { - if (normal == Vector3.Zero) return Vector3.UnitX; - return normal.IsNormalized() ? normal : Vector3.Normalize(normal); - } - - internal static bool IsValidTangent(this Vector4 tangent) - { - if (tangent.W != 1 && tangent.W != -1) return false; - - return new Vector3(tangent.X, tangent.Y, tangent.Z).IsNormalized(); - } - - internal static Vector4 SanitizeTangent(this Vector4 tangent) - { - var n = new Vector3(tangent.X, tangent.Y, tangent.Z).SanitizeNormal(); - var s = float.IsNaN(tangent.W) ? 1 : tangent.W; - return new Vector4(n, s > 0 ? 1 : -1); - } -} diff --git a/Penumbra/Import/TexToolsImport.cs b/Penumbra/Import/TexToolsImport.cs index 8e4fea41..fed06573 100644 --- a/Penumbra/Import/TexToolsImport.cs +++ b/Penumbra/Import/TexToolsImport.cs @@ -119,7 +119,7 @@ public partial class TexToolsImporter : IDisposable // Puts out warnings if extension does not correspond to data. private DirectoryInfo VerifyVersionAndImport(FileInfo modPackFile) { - if (modPackFile.Extension.ToLowerInvariant() is ".pmp" or ".pcp" or ".zip" or ".7z" or ".rar") + if (modPackFile.Extension.ToLowerInvariant() is ".pmp" or ".zip" or ".7z" or ".rar") return HandleRegularArchive(modPackFile); using var zfs = modPackFile.OpenRead(); diff --git a/Penumbra/Import/TexToolsImporter.Gui.cs b/Penumbra/Import/TexToolsImporter.Gui.cs index 5cb99d72..f145f560 100644 --- a/Penumbra/Import/TexToolsImporter.Gui.cs +++ b/Penumbra/Import/TexToolsImporter.Gui.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using Penumbra.Import.Structs; diff --git a/Penumbra/Import/Textures/CombinedTexture.Manipulation.cs b/Penumbra/Import/Textures/CombinedTexture.Manipulation.cs index 7a7e5888..2d131d71 100644 --- a/Penumbra/Import/Textures/CombinedTexture.Manipulation.cs +++ b/Penumbra/Import/Textures/CombinedTexture.Manipulation.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui; using SixLabors.ImageSharp.PixelFormats; diff --git a/Penumbra/Import/Textures/TexFileParser.cs b/Penumbra/Import/Textures/TexFileParser.cs index 04bbf5d8..6a12a0dd 100644 --- a/Penumbra/Import/Textures/TexFileParser.cs +++ b/Penumbra/Import/Textures/TexFileParser.cs @@ -95,8 +95,7 @@ public static class TexFileParser if (width == minSize && height == minSize) { - ++i; - newSize = totalSize + requiredSize; + newSize = totalSize; if (header.MipCount != i) { Penumbra.Log.Debug($"-- Reduced number of Mip Maps from {header.MipCount} to {i} due to minimum size constraints."); diff --git a/Penumbra/Import/Textures/TextureDrawer.cs b/Penumbra/Import/Textures/TextureDrawer.cs index 14203dff..b0a65ac0 100644 --- a/Penumbra/Import/Textures/TextureDrawer.cs +++ b/Penumbra/Import/Textures/TextureDrawer.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using ImGuiNET; using Lumina.Data.Files; using OtterGui; using OtterGui.Raii; @@ -20,7 +20,7 @@ public static class TextureDrawer { size = texture.TextureWrap.Size.Contain(size); - ImGui.Image(texture.TextureWrap.Handle, size); + ImGui.Image(texture.TextureWrap.ImGuiHandle, size); DrawData(texture); } else if (texture.LoadError != null) diff --git a/Penumbra/Import/Textures/TextureManager.cs b/Penumbra/Import/Textures/TextureManager.cs index 073fef2f..0c85f5be 100644 --- a/Penumbra/Import/Textures/TextureManager.cs +++ b/Penumbra/Import/Textures/TextureManager.cs @@ -406,7 +406,7 @@ public sealed class TextureManager(IDataManager gameData, Logger logger, ITextur // See https://github.com/microsoft/DirectXTex/wiki/Compress#parameters for the format condition. if (format is DXGIFormat.BC6HUF16 or DXGIFormat.BC6HSF16 or DXGIFormat.BC7UNorm or DXGIFormat.BC7UNormSRGB) { - var device = new Device(uiBuilder.DeviceHandle); + var device = uiBuilder.Device; var dxgiDevice = device.QueryInterface(); using var deviceClone = new Device(dxgiDevice.Adapter, device.CreationFlags, device.FeatureLevel); diff --git a/Penumbra/Interop/CloudApi.cs b/Penumbra/Interop/CloudApi.cs deleted file mode 100644 index 603d4c9f..00000000 --- a/Penumbra/Interop/CloudApi.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Penumbra.Interop; - -public static unsafe partial class CloudApi -{ - private const int CfSyncRootInfoBasic = 0; - - /// Determines whether a file or directory is cloud-synced using OneDrive or other providers that use the Cloud API. - /// Can be expensive. Callers should cache the result when relevant. - public static bool IsCloudSynced(string path) - { - var buffer = stackalloc long[1]; - int hr; - uint length; - try - { - hr = CfGetSyncRootInfoByPath(path, CfSyncRootInfoBasic, buffer, sizeof(long), out length); - } - catch (DllNotFoundException) - { - Penumbra.Log.Debug($"{nameof(CfGetSyncRootInfoByPath)} threw DllNotFoundException"); - return false; - } - catch (EntryPointNotFoundException) - { - Penumbra.Log.Debug($"{nameof(CfGetSyncRootInfoByPath)} threw EntryPointNotFoundException"); - return false; - } - - Penumbra.Log.Debug($"{nameof(CfGetSyncRootInfoByPath)} returned HRESULT 0x{hr:X8}"); - if (hr < 0) - return false; - - if (length != sizeof(long)) - { - Penumbra.Log.Debug($"Expected {nameof(CfGetSyncRootInfoByPath)} to return {sizeof(long)} bytes, got {length} bytes"); - return false; - } - - Penumbra.Log.Debug($"{nameof(CfGetSyncRootInfoByPath)} returned {{ SyncRootFileId = 0x{*buffer:X16} }}"); - - return true; - } - - [LibraryImport("cldapi.dll", StringMarshalling = StringMarshalling.Utf16)] - private static partial int CfGetSyncRootInfoByPath(string filePath, int infoClass, void* infoBuffer, uint infoBufferLength, - out uint returnedLength); -} diff --git a/Penumbra/Interop/GameState.cs b/Penumbra/Interop/GameState.cs index b5171244..95cef468 100644 --- a/Penumbra/Interop/GameState.cs +++ b/Penumbra/Interop/GameState.cs @@ -59,6 +59,9 @@ public class GameState : IService private readonly ThreadLocal _characterSoundData = new(() => ResolveData.Invalid, true); + public ResolveData SoundData + => _animationLoadData.Value; + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public ResolveData SetSoundData(ResolveData data) { diff --git a/Penumbra/Interop/Hooks/Meta/ChangeCustomize.cs b/Penumbra/Interop/Hooks/Meta/ChangeCustomize.cs index 523ae610..368845b4 100644 --- a/Penumbra/Interop/Hooks/Meta/ChangeCustomize.cs +++ b/Penumbra/Interop/Hooks/Meta/ChangeCustomize.cs @@ -16,7 +16,7 @@ public sealed unsafe class ChangeCustomize : FastHook { _collectionResolver = collectionResolver; _metaState = metaState; - Task = hooks.CreateHook("Change Customize", Sigs.UpdateDrawData, Detour, !HookOverrides.Instance.Meta.ChangeCustomize); + Task = hooks.CreateHook("Change Customize", Sigs.ChangeCustomize, Detour, !HookOverrides.Instance.Meta.ChangeCustomize); } public delegate bool Delegate(Human* human, CustomizeArray* data, byte skipEquipment); diff --git a/Penumbra/Interop/Hooks/Objects/WeaponReload.cs b/Penumbra/Interop/Hooks/Objects/WeaponReload.cs index 4231b027..b09103f6 100644 --- a/Penumbra/Interop/Hooks/Objects/WeaponReload.cs +++ b/Penumbra/Interop/Hooks/Objects/WeaponReload.cs @@ -35,14 +35,14 @@ public sealed unsafe class WeaponReload : EventWrapperPtr _task.IsCompletedSuccessfully; - private delegate void Delegate(DrawDataContainer* drawData, uint slot, ulong weapon, byte d, byte e, byte f, byte g, byte h); + private delegate void Delegate(DrawDataContainer* drawData, uint slot, ulong weapon, byte d, byte e, byte f, byte g); - private void Detour(DrawDataContainer* drawData, uint slot, ulong weapon, byte d, byte e, byte f, byte g, byte h) + private void Detour(DrawDataContainer* drawData, uint slot, ulong weapon, byte d, byte e, byte f, byte g) { var gameObject = drawData->OwnerObject; - Penumbra.Log.Verbose($"[{Name}] Triggered with drawData: 0x{(nint)drawData:X}, {slot}, {weapon}, {d}, {e}, {f}, {g}, {h}."); + Penumbra.Log.Verbose($"[{Name}] Triggered with drawData: 0x{(nint)drawData:X}, {slot}, {weapon}, {d}, {e}, {f}, {g}."); Invoke(drawData, gameObject, (CharacterWeapon*)(&weapon)); - _task.Result.Original(drawData, slot, weapon, d, e, f, g, h); + _task.Result.Original(drawData, slot, weapon, d, e, f, g); _postEvent.Invoke(drawData, gameObject); } diff --git a/Penumbra/Interop/Hooks/PostProcessing/PreBoneDeformerReplacer.cs b/Penumbra/Interop/Hooks/PostProcessing/PreBoneDeformerReplacer.cs index 51af5813..30e643c7 100644 --- a/Penumbra/Interop/Hooks/PostProcessing/PreBoneDeformerReplacer.cs +++ b/Penumbra/Interop/Hooks/PostProcessing/PreBoneDeformerReplacer.cs @@ -63,7 +63,7 @@ public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredServi if (!_framework.IsInFrameworkUpdateThread) Penumbra.Log.Warning( $"{nameof(PreBoneDeformerReplacer)}.{nameof(SetupHssReplacements)}(0x{(nint)drawObject:X}, {slotIndex}) called out of framework thread"); - + var preBoneDeformer = GetPreBoneDeformerForCharacter(drawObject); try { diff --git a/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs b/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs index 1a40accc..e90b4575 100644 --- a/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs +++ b/Penumbra/Interop/Hooks/ResourceLoading/ResourceService.cs @@ -1,5 +1,4 @@ using Dalamud.Hooking; -using Dalamud.Interface.Windowing; using Dalamud.Plugin.Services; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Resource; @@ -86,8 +85,7 @@ public unsafe class ResourceService : IDisposable, IRequiredService ResourceType* pResourceType, int* pResourceHash, byte* pPath, GetResourceParameters* pGetResParams, nint unk7, uint unk8); private delegate ResourceHandle* GetResourceAsyncPrototype(ResourceManager* resourceManager, ResourceCategory* pCategoryId, - ResourceType* pResourceType, int* pResourceHash, byte* pPath, GetResourceParameters* pGetResParams, byte isUnknown, nint unk8, - uint unk9); + ResourceType* pResourceType, int* pResourceHash, byte* pPath, GetResourceParameters* pGetResParams, byte isUnknown, nint unk8, uint unk9); [Signature(Sigs.GetResourceSync, DetourName = nameof(GetResourceSyncDetour))] private readonly Hook _getResourceSyncHook = null!; @@ -120,26 +118,18 @@ public unsafe class ResourceService : IDisposable, IRequiredService unk9); } - if (gamePath.IsEmpty) - { - Penumbra.Log.Error($"[ResourceService] Empty resource path requested with category {*categoryId}, type {*resourceType}, hash {*resourceHash}."); - return null; - } - - var original = gamePath; + var original = gamePath; ResourceHandle* returnValue = null; ResourceRequested?.Invoke(ref *categoryId, ref *resourceType, ref *resourceHash, ref gamePath, original, pGetResParams, ref isSync, ref returnValue); if (returnValue != null) return returnValue; - return GetOriginalResource(isSync, *categoryId, *resourceType, *resourceHash, gamePath.Path, original, pGetResParams, isUnk, unk8, - unk9); + return GetOriginalResource(isSync, *categoryId, *resourceType, *resourceHash, gamePath.Path, original, pGetResParams, isUnk, unk8, unk9); } /// Call the original GetResource function. - public ResourceHandle* GetOriginalResource(bool sync, ResourceCategory categoryId, ResourceType type, int hash, CiByteString path, - Utf8GamePath original, + public ResourceHandle* GetOriginalResource(bool sync, ResourceCategory categoryId, ResourceType type, int hash, CiByteString path, Utf8GamePath original, GetResourceParameters* resourceParameters = null, byte unk = 0, nint unk8 = 0, uint unk9 = 0) { var previous = _currentGetResourcePath.Value; @@ -151,8 +141,7 @@ public unsafe class ResourceService : IDisposable, IRequiredService resourceParameters, unk8, unk9) : _getResourceAsyncHook.OriginalDisposeSafe(_resourceManager.ResourceManager, &categoryId, &type, &hash, path.Path, resourceParameters, unk, unk8, unk9); - } - finally + } finally { _currentGetResourcePath.Value = previous; } @@ -174,8 +163,7 @@ public unsafe class ResourceService : IDisposable, IRequiredService /// The original game path of the resource, if loaded synchronously. /// The previous state of the resource. /// The return value to use. - public delegate void ResourceStateUpdatedDelegate(ResourceHandle* handle, Utf8GamePath syncOriginal, - (byte UnkState, LoadState LoadState) previousState, ref uint returnValue); + public delegate void ResourceStateUpdatedDelegate(ResourceHandle* handle, Utf8GamePath syncOriginal, (byte UnkState, LoadState LoadState) previousState, ref uint returnValue); /// /// @@ -197,7 +185,7 @@ public unsafe class ResourceService : IDisposable, IRequiredService private uint UpdateResourceStateDetour(ResourceHandle* handle, byte offFileThread) { var previousState = (handle->UnkState, handle->LoadState); - var syncOriginal = _currentGetResourcePath.IsValueCreated ? _currentGetResourcePath.Value : Utf8GamePath.Empty; + var syncOriginal = _currentGetResourcePath.IsValueCreated ? _currentGetResourcePath.Value : Utf8GamePath.Empty; ResourceStateUpdating?.Invoke(handle, syncOriginal); var ret = _updateResourceStateHook.OriginalDisposeSafe(handle, offFileThread); ResourceStateUpdated?.Invoke(handle, syncOriginal, previousState, ref ret); diff --git a/Penumbra/Interop/Hooks/Resources/ResolvePathHooksBase.cs b/Penumbra/Interop/Hooks/Resources/ResolvePathHooksBase.cs index db39889e..8a45ec2c 100644 --- a/Penumbra/Interop/Hooks/Resources/ResolvePathHooksBase.cs +++ b/Penumbra/Interop/Hooks/Resources/ResolvePathHooksBase.cs @@ -6,7 +6,6 @@ using Penumbra.Collections; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Interop.PathResolving; -using Penumbra.Interop.Processing; using static FFXIVClientStructs.FFXIV.Client.Game.Character.ActionEffectHandler; namespace Penumbra.Interop.Hooks.Resources; @@ -36,7 +35,6 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable private readonly Hook _resolveMPapPathHook; private readonly Hook _resolveMdlPathHook; private readonly Hook _resolveMtrlPathHook; - private readonly Hook _resolveSkinMtrlPathHook; private readonly Hook _resolvePapPathHook; private readonly Hook _resolveKdbPathHook; private readonly Hook _resolvePhybPathHook; @@ -54,23 +52,22 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable { _parent = parent; // @formatter:off - _resolveSklbPathHook = Create($"{name}.{nameof(ResolveSklb)}", hooks, vTable[76], type, ResolveSklb, ResolveSklbHuman); - _resolveMdlPathHook = Create($"{name}.{nameof(ResolveMdl)}", hooks, vTable[77], type, ResolveMdl, ResolveMdlHuman); - _resolveSkpPathHook = Create($"{name}.{nameof(ResolveSkp)}", hooks, vTable[78], type, ResolveSkp, ResolveSkpHuman); - _resolvePhybPathHook = Create($"{name}.{nameof(ResolvePhyb)}", hooks, vTable[79], type, ResolvePhyb, ResolvePhybHuman); - _resolveKdbPathHook = Create($"{name}.{nameof(ResolveKdb)}", hooks, vTable[80], type, ResolveKdb, ResolveKdbHuman); - _vFunc81Hook = Create( $"{name}.{nameof(VFunc81)}", hooks, vTable[81], type, null, VFunc81); - _resolveBnmbPathHook = Create($"{name}.{nameof(ResolveBnmb)}", hooks, vTable[82], type, ResolveBnmb, ResolveBnmbHuman); - _vFunc83Hook = Create( $"{name}.{nameof(VFunc83)}", hooks, vTable[83], type, null, VFunc83); - _resolvePapPathHook = Create( $"{name}.{nameof(ResolvePap)}", hooks, vTable[84], type, ResolvePap, ResolvePapHuman); - _resolveTmbPathHook = Create( $"{name}.{nameof(ResolveTmb)}", hooks, vTable[85], ResolveTmb); - _resolveMPapPathHook = Create( $"{name}.{nameof(ResolveMPap)}", hooks, vTable[87], ResolveMPap); - _resolveImcPathHook = Create($"{name}.{nameof(ResolveImc)}", hooks, vTable[89], ResolveImc); - _resolveMtrlPathHook = Create( $"{name}.{nameof(ResolveMtrl)}", hooks, vTable[90], ResolveMtrl); - _resolveSkinMtrlPathHook = Create($"{name}.{nameof(ResolveSkinMtrl)}", hooks, vTable[91], ResolveSkinMtrl); - _resolveDecalPathHook = Create($"{name}.{nameof(ResolveDecal)}", hooks, vTable[92], ResolveDecal); - _resolveVfxPathHook = Create( $"{name}.{nameof(ResolveVfx)}", hooks, vTable[93], type, ResolveVfx, ResolveVfxHuman); - _resolveEidPathHook = Create( $"{name}.{nameof(ResolveEid)}", hooks, vTable[94], ResolveEid); + _resolveSklbPathHook = Create($"{name}.{nameof(ResolveSklb)}", hooks, vTable[76], type, ResolveSklb, ResolveSklbHuman); + _resolveMdlPathHook = Create($"{name}.{nameof(ResolveMdl)}", hooks, vTable[77], type, ResolveMdl, ResolveMdlHuman); + _resolveSkpPathHook = Create($"{name}.{nameof(ResolveSkp)}", hooks, vTable[78], type, ResolveSkp, ResolveSkpHuman); + _resolvePhybPathHook = Create($"{name}.{nameof(ResolvePhyb)}", hooks, vTable[79], type, ResolvePhyb, ResolvePhybHuman); + _resolveKdbPathHook = Create($"{name}.{nameof(ResolveKdb)}", hooks, vTable[80], type, ResolveKdb, ResolveKdbHuman); + _vFunc81Hook = Create( $"{name}.{nameof(VFunc81)}", hooks, vTable[81], type, null, VFunc81); + _resolveBnmbPathHook = Create($"{name}.{nameof(ResolveBnmb)}", hooks, vTable[82], type, ResolveBnmb, ResolveBnmbHuman); + _vFunc83Hook = Create( $"{name}.{nameof(VFunc83)}", hooks, vTable[83], type, null, VFunc83); + _resolvePapPathHook = Create( $"{name}.{nameof(ResolvePap)}", hooks, vTable[84], type, ResolvePap, ResolvePapHuman); + _resolveTmbPathHook = Create( $"{name}.{nameof(ResolveTmb)}", hooks, vTable[85], ResolveTmb); + _resolveMPapPathHook = Create( $"{name}.{nameof(ResolveMPap)}", hooks, vTable[87], ResolveMPap); + _resolveImcPathHook = Create($"{name}.{nameof(ResolveImc)}", hooks, vTable[89], ResolveImc); + _resolveMtrlPathHook = Create( $"{name}.{nameof(ResolveMtrl)}", hooks, vTable[90], ResolveMtrl); + _resolveDecalPathHook = Create($"{name}.{nameof(ResolveDecal)}", hooks, vTable[92], ResolveDecal); + _resolveVfxPathHook = Create( $"{name}.{nameof(ResolveVfx)}", hooks, vTable[93], type, ResolveVfx, ResolveVfxHuman); + _resolveEidPathHook = Create( $"{name}.{nameof(ResolveEid)}", hooks, vTable[94], ResolveEid); // @formatter:on @@ -86,7 +83,6 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable _resolveMPapPathHook.Enable(); _resolveMdlPathHook.Enable(); _resolveMtrlPathHook.Enable(); - _resolveSkinMtrlPathHook.Enable(); _resolvePapPathHook.Enable(); _resolveKdbPathHook.Enable(); _resolvePhybPathHook.Enable(); @@ -107,7 +103,6 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable _resolveMPapPathHook.Disable(); _resolveMdlPathHook.Disable(); _resolveMtrlPathHook.Disable(); - _resolveSkinMtrlPathHook.Disable(); _resolvePapPathHook.Disable(); _resolveKdbPathHook.Disable(); _resolvePhybPathHook.Disable(); @@ -128,7 +123,6 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable _resolveMPapPathHook.Dispose(); _resolveMdlPathHook.Dispose(); _resolveMtrlPathHook.Dispose(); - _resolveSkinMtrlPathHook.Dispose(); _resolvePapPathHook.Dispose(); _resolveKdbPathHook.Dispose(); _resolvePhybPathHook.Dispose(); @@ -159,15 +153,6 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable private nint ResolveMtrl(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, nint mtrlFileName) => ResolvePath(drawObject, _resolveMtrlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex, mtrlFileName)); - private nint ResolveSkinMtrl(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex) - { - var finalPathBuffer = _resolveSkinMtrlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex); - if (DebugConfiguration.UseSkinMaterialProcessing && finalPathBuffer != nint.Zero && finalPathBuffer == pathBuffer) - SkinMtrlPathEarlyProcessing.Process(new Span((void*)pathBuffer, (int)pathBufferSize), (CharacterBase*)drawObject, slotIndex); - - return ResolvePath(drawObject, finalPathBuffer); - } - private nint ResolvePap(nint drawObject, nint pathBuffer, nint pathBufferSize, uint unkAnimationIndex, nint animationName) => ResolvePath(drawObject, _resolvePapPathHook.Original(drawObject, pathBuffer, pathBufferSize, unkAnimationIndex, animationName)); diff --git a/Penumbra/Interop/MaterialPreview/MaterialInfo.cs b/Penumbra/Interop/MaterialPreview/MaterialInfo.cs index a9fb46ff..f2ea2d6c 100644 --- a/Penumbra/Interop/MaterialPreview/MaterialInfo.cs +++ b/Penumbra/Interop/MaterialPreview/MaterialInfo.cs @@ -85,7 +85,7 @@ public readonly record struct MaterialInfo(ObjectIndex ObjectIndex, DrawObjectTy if (mtrlHandle == null) continue; - PathDataHandler.Split(mtrlHandle->FileName.AsSpan(), out var path, out _); + PathDataHandler.Split(mtrlHandle->ResourceHandle.FileName.AsSpan(), out var path, out _); var fileName = CiByteString.FromSpanUnsafe(path, true); if (fileName == needle) result.Add(new MaterialInfo(index, type, i, j)); diff --git a/Penumbra/Interop/PathResolving/CollectionResolver.cs b/Penumbra/Interop/PathResolving/CollectionResolver.cs index 136393d4..10795e6d 100644 --- a/Penumbra/Interop/PathResolving/CollectionResolver.cs +++ b/Penumbra/Interop/PathResolving/CollectionResolver.cs @@ -137,7 +137,7 @@ public sealed unsafe class CollectionResolver( { var item = charaEntry.Value; var identifier = actors.CreatePlayer(new ByteString(item->Name), item->HomeWorldId); - Penumbra.Log.Excessive( + Penumbra.Log.Verbose( $"Identified {identifier.Incognito(null)} in cutscene for actor {idx + 200} at 0x{(ulong)gameObject:X} of race {(gameObject->IsCharacter() ? ((Character*)gameObject)->DrawData.CustomizeData.Race.ToString() : "Unknown")}."); if (identifier.IsValid && CollectionByIdentifier(identifier) is { } coll) { diff --git a/Penumbra/Interop/PathResolving/CutsceneService.cs b/Penumbra/Interop/PathResolving/CutsceneService.cs index 97e64f84..6be19c46 100644 --- a/Penumbra/Interop/PathResolving/CutsceneService.cs +++ b/Penumbra/Interop/PathResolving/CutsceneService.cs @@ -75,7 +75,6 @@ public sealed class CutsceneService : IRequiredService, IDisposable return false; _copiedCharacters[copyIdx - CutsceneStartIdx] = (short)parentIdx; - _objects.InvokeRequiredUpdates(); return true; } diff --git a/Penumbra/Interop/ProcessThreadApi.cs b/Penumbra/Interop/ProcessThreadApi.cs deleted file mode 100644 index 5ee213d9..00000000 --- a/Penumbra/Interop/ProcessThreadApi.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Penumbra.Interop; - -public static partial class ProcessThreadApi -{ - [LibraryImport("kernel32.dll")] - public static partial uint GetCurrentThreadId(); -} diff --git a/Penumbra/Interop/Processing/PbdFilePostProcessor.cs b/Penumbra/Interop/Processing/PbdFilePostProcessor.cs deleted file mode 100644 index 674500cd..00000000 --- a/Penumbra/Interop/Processing/PbdFilePostProcessor.cs +++ /dev/null @@ -1,119 +0,0 @@ -using Dalamud.Game; -using Dalamud.Plugin.Services; -using Penumbra.Api.Enums; -using Penumbra.GameData; -using Penumbra.GameData.Data; -using Penumbra.Interop.Structs; -using Penumbra.Meta.Files; -using Penumbra.String; - -namespace Penumbra.Interop.Processing; - -public sealed class PbdFilePostProcessor : IFilePostProcessor -{ - private readonly IFileAllocator _allocator; - private byte[] _epbdData; - private unsafe delegate* unmanaged _loadEpbdData; - - public ResourceType Type - => ResourceType.Pbd; - - public unsafe PbdFilePostProcessor(IDataManager dataManager, XivFileAllocator allocator, ISigScanner scanner) - { - _allocator = allocator; - _epbdData = SetEpbdData(dataManager); - _loadEpbdData = (delegate* unmanaged)scanner.ScanText(Sigs.LoadEpbdData); - } - - public unsafe void PostProcess(ResourceHandle* resource, CiByteString originalGamePath, ReadOnlySpan additionalData) - { - if (_epbdData.Length is 0) - return; - - if (resource->LoadState is not LoadState.Success) - { - Penumbra.Log.Warning($"[ResourceLoader] Requested PBD at {resource->FileName()} failed load ({resource->LoadState})."); - return; - } - - var (data, length) = resource->GetData(); - if (length is 0 || data == nint.Zero) - { - Penumbra.Log.Warning($"[ResourceLoader] Requested PBD at {resource->FileName()} succeeded load but has no data."); - return; - } - - var span = new ReadOnlySpan((void*)data, (int)resource->FileSize); - var reader = new PackReader(span); - if (reader.HasData) - { - Penumbra.Log.Excessive($"[ResourceLoader] Successfully loaded PBD at {resource->FileName()} with EPBD data."); - return; - } - - var newData = AppendData(span); - fixed (byte* ptr = newData) - { - // Set the appended data and the actual file size, then re-load the EPBD data via game function call. - if (resource->SetData((nint)ptr, newData.Length)) - { - resource->FileSize = (uint)newData.Length; - resource->CsHandle.FileSize2 = (uint)newData.Length; - resource->CsHandle.FileSize3 = (uint)newData.Length; - _loadEpbdData(resource); - // Free original data. - _allocator.Release((void*)data, length); - Penumbra.Log.Debug($"[ResourceLoader] Loaded {resource->FileName()} from file and appended default EPBD data."); - } - else - { - Penumbra.Log.Warning( - $"[ResourceLoader] Failed to append EPBD data to custom PBD at {resource->FileName()}."); - } - } - } - - /// Combine the given data with the default PBD data using the game's file allocator. - private unsafe ReadOnlySpan AppendData(ReadOnlySpan data) - { - // offset has to be set, otherwise not called. - var newLength = data.Length + _epbdData.Length; - var memory = _allocator.Allocate(newLength); - var span = new Span(memory, newLength); - data.CopyTo(span); - _epbdData.CopyTo(span[data.Length..]); - return span; - } - - /// Fetch the default EPBD data from the .pbd file of the game's installation. - private static byte[] SetEpbdData(IDataManager dataManager) - { - try - { - var file = dataManager.GetFile(GamePaths.Pbd.Path); - if (file is null || file.Data.Length is 0) - { - Penumbra.Log.Warning("Default PBD file has no data."); - return []; - } - - ReadOnlySpan span = file.Data; - var reader = new PackReader(span); - if (!reader.HasData) - { - Penumbra.Log.Warning("Default PBD file has no EPBD section."); - return []; - } - - var offset = span.Length - (int)reader.PackLength; - var ret = span[offset..]; - Penumbra.Log.Verbose($"Default PBD file has EPBD section of length {ret.Length} at offset {offset}."); - return ret.ToArray(); - } - catch (Exception ex) - { - Penumbra.Log.Error($"Unknown error getting default EPBD data:\n{ex}"); - return []; - } - } -} diff --git a/Penumbra/Interop/Processing/SkinMtrlPathEarlyProcessing.cs b/Penumbra/Interop/Processing/SkinMtrlPathEarlyProcessing.cs deleted file mode 100644 index bd066d83..00000000 --- a/Penumbra/Interop/Processing/SkinMtrlPathEarlyProcessing.cs +++ /dev/null @@ -1,63 +0,0 @@ -using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; -using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; - -namespace Penumbra.Interop.Processing; - -public static unsafe class SkinMtrlPathEarlyProcessing -{ - public static void Process(Span path, CharacterBase* character, uint slotIndex) - { - var end = path.IndexOf(MaterialExtension()); - if (end < 0) - return; - - var suffixPos = path[..end].LastIndexOf((byte)'_'); - if (suffixPos < 0) - return; - - var handle = GetModelResourceHandle(character, slotIndex); - if (handle == null) - return; - - var skinSuffix = GetSkinSuffix(handle); - if (skinSuffix.IsEmpty || skinSuffix.Length > path.Length - suffixPos - 7) - return; - - ++suffixPos; - skinSuffix.CopyTo(path[suffixPos..]); - suffixPos += skinSuffix.Length; - MaterialExtension().CopyTo(path[suffixPos..]); - return; - - static ReadOnlySpan MaterialExtension() - => ".mtrl\0"u8; - } - - private static ModelResourceHandle* GetModelResourceHandle(CharacterBase* character, uint slotIndex) - { - if (character is null) - return null; - - if (character->PerSlotStagingArea is not null) - { - var handle = character->PerSlotStagingArea[slotIndex].ModelResourceHandle; - if (handle != null) - return handle; - } - - var model = character->Models[slotIndex]; - return model is null ? null : model->ModelResourceHandle; - } - - private static ReadOnlySpan GetSkinSuffix(ModelResourceHandle* handle) - { - foreach (var (attribute, _) in handle->Attributes) - { - var attributeSpan = attribute.AsSpan(); - if (attributeSpan.Length > 12 && attributeSpan[..11].SequenceEqual("skin_suffix"u8) && attributeSpan[11] is (byte)'=' or (byte)'_') - return attributeSpan[12..]; - } - - return []; - } -} diff --git a/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs b/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs index c204f141..b6d04769 100644 --- a/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs +++ b/Penumbra/Interop/ResourceTree/ResolveContext.PathResolution.cs @@ -338,34 +338,6 @@ internal partial record ResolveContext return Utf8GamePath.FromByteString(path, out var gamePath) ? gamePath : Utf8GamePath.Empty; } - private Utf8GamePath ResolveKineDriverModulePath(uint partialSkeletonIndex) - { - // Correctness and Safety: - // Resolving a KineDriver module path through the game's code can use EST metadata for human skeletons. - // Additionally, it can dereference null pointers for human equipment skeletons. - return ModelType switch - { - ModelType.Human => ResolveHumanKineDriverModulePath(partialSkeletonIndex), - _ => ResolveKineDriverModulePathNative(partialSkeletonIndex), - }; - } - - private Utf8GamePath ResolveHumanKineDriverModulePath(uint partialSkeletonIndex) - { - var (raceCode, slot, set) = ResolveHumanSkeletonData(partialSkeletonIndex); - if (set.Id is 0) - return Utf8GamePath.Empty; - - var path = GamePaths.Kdb.Customization(raceCode, slot, set); - return Utf8GamePath.FromString(path, out var gamePath) ? gamePath : Utf8GamePath.Empty; - } - - private unsafe Utf8GamePath ResolveKineDriverModulePathNative(uint partialSkeletonIndex) - { - var path = CharacterBase->ResolveKdbPathAsByteString(partialSkeletonIndex); - return Utf8GamePath.FromByteString(path, out var gamePath) ? gamePath : Utf8GamePath.Empty; - } - private unsafe Utf8GamePath ResolveMaterialAnimationPath(ResourceHandle* imc) { var animation = ResolveImcData(imc).MaterialAnimationId; diff --git a/Penumbra/Interop/ResourceTree/ResolveContext.cs b/Penumbra/Interop/ResourceTree/ResolveContext.cs index 501bbc56..013d7db7 100644 --- a/Penumbra/Interop/ResourceTree/ResolveContext.cs +++ b/Penumbra/Interop/ResourceTree/ResolveContext.cs @@ -59,7 +59,7 @@ internal unsafe partial record ResolveContext( if (!Utf8GamePath.FromByteString(CiByteString.Join((byte)'/', ShpkPrefix, gamePath), out var path)) return null; - return GetOrCreateNode(ResourceType.Shpk, (nint)resourceHandle->ShaderPackage, (ResourceHandle*)resourceHandle, path); + return GetOrCreateNode(ResourceType.Shpk, (nint)resourceHandle->ShaderPackage, &resourceHandle->ResourceHandle, path); } [SkipLocalsInit] @@ -188,8 +188,7 @@ internal unsafe partial record ResolveContext( return GetOrCreateNode(ResourceType.Tex, (nint)tex->Texture, &tex->ResourceHandle, gamePath); } - public ResourceNode? CreateNodeFromModel(Model* mdl, ResourceHandle* imc, TextureResourceHandle* decalHandle, - MaterialResourceHandle* skinMtrlHandle, ResourceHandle* mpapHandle) + public ResourceNode? CreateNodeFromModel(Model* mdl, ResourceHandle* imc, TextureResourceHandle* decalHandle, ResourceHandle* mpapHandle) { if (mdl is null || mdl->ModelResourceHandle is null) return null; @@ -219,12 +218,6 @@ internal unsafe partial record ResolveContext( } } - if (skinMtrlHandle is not null - && Utf8GamePath.FromByteString(CharacterBase->ResolveSkinMtrlPathAsByteString(SlotIndex), out var skinMtrlPath) - && CreateNodeFromMaterial(skinMtrlHandle->Material, skinMtrlPath) is - { } skinMaaterialNode) - node.Children.Add(skinMaaterialNode); - if (CreateNodeFromDecal(decalHandle, imc) is { } decalNode) node.Children.Add(decalNode); @@ -245,7 +238,7 @@ internal unsafe partial record ResolveContext( if (Global.Nodes.TryGetValue((path, (nint)resource), out var cached)) return cached; - var node = CreateNode(ResourceType.Mtrl, (nint)mtrl, (ResourceHandle*)resource, path, false); + var node = CreateNode(ResourceType.Mtrl, (nint)mtrl, &resource->ResourceHandle, path, false); var shpkNode = CreateNodeFromShpk(resource->ShaderPackageResourceHandle, new CiByteString(resource->ShpkName.Value)); if (shpkNode is not null) { @@ -371,8 +364,7 @@ internal unsafe partial record ResolveContext( return node; } - public ResourceNode? CreateNodeFromPartialSkeleton(PartialSkeleton* sklb, ResourceHandle* phybHandle, ResourceHandle* kdbHandle, - uint partialSkeletonIndex) + public ResourceNode? CreateNodeFromPartialSkeleton(PartialSkeleton* sklb, ResourceHandle* phybHandle, uint partialSkeletonIndex) { if (sklb is null || sklb->SkeletonResourceHandle is null) return null; @@ -387,8 +379,6 @@ internal unsafe partial record ResolveContext( node.Children.Add(skpNode); if (CreateNodeFromPhyb(phybHandle, partialSkeletonIndex) is { } phybNode) node.Children.Add(phybNode); - if (CreateNodeFromKdb(kdbHandle, partialSkeletonIndex) is { } kdbNode) - node.Children.Add(kdbNode); Global.Nodes.Add((path, (nint)sklb->SkeletonResourceHandle), node); return node; @@ -430,24 +420,6 @@ internal unsafe partial record ResolveContext( return node; } - private ResourceNode? CreateNodeFromKdb(ResourceHandle* kdbHandle, uint partialSkeletonIndex) - { - if (kdbHandle is null) - return null; - - var path = ResolveKineDriverModulePath(partialSkeletonIndex); - - if (Global.Nodes.TryGetValue((path, (nint)kdbHandle), out var cached)) - return cached; - - var node = CreateNode(ResourceType.Kdb, 0, kdbHandle, path, false); - if (Global.WithUiData) - node.FallbackName = "KineDriver Module"; - Global.Nodes.Add((path, (nint)kdbHandle), node); - - return node; - } - internal ResourceNode.UiData GuessModelUiData(Utf8GamePath gamePath) { var path = gamePath.Path.Split((byte)'/'); diff --git a/Penumbra/Interop/ResourceTree/ResourceNode.cs b/Penumbra/Interop/ResourceTree/ResourceNode.cs index 08dee818..3699ae0b 100644 --- a/Penumbra/Interop/ResourceTree/ResourceNode.cs +++ b/Penumbra/Interop/ResourceTree/ResourceNode.cs @@ -45,9 +45,7 @@ public class ResourceNode : ICloneable /// Whether to treat the file as protected (require holding the Mod Deletion Modifier to make a quick import). public bool Protected - => ForceProtected - || Internal - || Type is ResourceType.Shpk or ResourceType.Sklb or ResourceType.Skp or ResourceType.Phyb or ResourceType.Kdb or ResourceType.Pbd; + => ForceProtected || Internal || Type is ResourceType.Shpk or ResourceType.Sklb or ResourceType.Pbd; internal ResourceNode(ResourceType type, nint objectAddress, nint resourceHandle, ulong length, ResolveContext? resolveContext) { diff --git a/Penumbra/Interop/ResourceTree/ResourceTree.cs b/Penumbra/Interop/ResourceTree/ResourceTree.cs index 1ebfe53d..7be8694a 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTree.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTree.cs @@ -70,16 +70,12 @@ public class ResourceTree( var genericContext = globalContext.CreateContext(model); - var mpapArrayPtr = model->MaterialAnimationPacks; + // TODO ClientStructs-ify (aers/FFXIVClientStructs#1312) + var mpapArrayPtr = *(ResourceHandle***)((nint)model + 0x948); var mpapArray = mpapArrayPtr is not null ? new ReadOnlySpan>(mpapArrayPtr, model->SlotCount) : []; - var skinMtrlArray = modelType switch - { - ModelType.Human => ((Human*) model)->SlotSkinMaterials, - _ => [], - }; var decalArray = modelType switch { - ModelType.Human => human->SlotDecals, + ModelType.Human => human->SlotDecalsSpan, ModelType.DemiHuman => ((Demihuman*)model)->SlotDecals, ModelType.Weapon => [((Weapon*)model)->Decal], ModelType.Monster => [((Monster*)model)->Decal], @@ -112,8 +108,7 @@ public class ResourceTree( var mdl = model->Models[i]; if (slotContext.CreateNodeFromModel(mdl, imc, i < decalArray.Length ? decalArray[(int)i].Value : null, - i < skinMtrlArray.Length ? skinMtrlArray[(int)i].Value : null, i < mpapArray.Length ? mpapArray[(int)i].Value : null) is - { } mdlNode) + i < mpapArray.Length ? mpapArray[(int)i].Value : null) is { } mdlNode) { if (globalContext.WithUiData) mdlNode.FallbackName = $"Model #{i}"; @@ -121,8 +116,9 @@ public class ResourceTree( } } - AddSkeleton(Nodes, genericContext, model); - AddMaterialAnimationSkeleton(Nodes, genericContext, model->MaterialAnimationSkeleton); + AddSkeleton(Nodes, genericContext, model->EID, model->Skeleton, model->BonePhysicsModule); + // TODO ClientStructs-ify (aers/FFXIVClientStructs#1312) + AddMaterialAnimationSkeleton(Nodes, genericContext, *(SkeletonResourceHandle**)((nint)model + 0x940)); AddWeapons(globalContext, model); @@ -153,7 +149,8 @@ public class ResourceTree( var genericContext = globalContext.CreateContext(subObject, 0xFFFFFFFFu, slot, equipment, weaponType); - var mpapArrayPtr = subObject->MaterialAnimationPacks; + // TODO ClientStructs-ify (aers/FFXIVClientStructs#1312) + var mpapArrayPtr = *(ResourceHandle***)((nint)subObject + 0x948); var mpapArray = mpapArrayPtr is not null ? new ReadOnlySpan>(mpapArrayPtr, subObject->SlotCount) : []; for (var i = 0; i < subObject->SlotCount; ++i) @@ -169,8 +166,7 @@ public class ResourceTree( } var mdl = subObject->Models[i]; - if (slotContext.CreateNodeFromModel(mdl, imc, weapon->Decal, null, i < mpapArray.Length ? mpapArray[i].Value : null) is - { } mdlNode) + if (slotContext.CreateNodeFromModel(mdl, imc, weapon->Decal, i < mpapArray.Length ? mpapArray[i].Value : null) is { } mdlNode) { if (globalContext.WithUiData) mdlNode.FallbackName = $"Weapon #{weaponIndex}, Model #{i}"; @@ -178,8 +174,10 @@ public class ResourceTree( } } - AddSkeleton(weaponNodes, genericContext, subObject, $"Weapon #{weaponIndex}, "); - AddMaterialAnimationSkeleton(weaponNodes, genericContext, subObject->MaterialAnimationSkeleton, + AddSkeleton(weaponNodes, genericContext, subObject->EID, subObject->Skeleton, subObject->BonePhysicsModule, + $"Weapon #{weaponIndex}, "); + // TODO ClientStructs-ify (aers/FFXIVClientStructs#1312) + AddMaterialAnimationSkeleton(weaponNodes, genericContext, *(SkeletonResourceHandle**)((nint)subObject + 0x940), $"Weapon #{weaponIndex}, "); ++weaponIndex; @@ -241,11 +239,8 @@ public class ResourceTree( } } - private unsafe void AddSkeleton(List nodes, ResolveContext context, CharacterBase* model, string prefix = "") - => AddSkeleton(nodes, context, model->EID, model->Skeleton, model->BonePhysicsModule, model->BoneKineDriverModule, prefix); - private unsafe void AddSkeleton(List nodes, ResolveContext context, void* eid, Skeleton* skeleton, BonePhysicsModule* physics, - BoneKineDriverModule* kineDriver, string prefix = "") + string prefix = "") { var eidNode = context.CreateNodeFromEid((ResourceHandle*)eid); if (eidNode != null) @@ -260,9 +255,9 @@ public class ResourceTree( for (var i = 0; i < skeleton->PartialSkeletonCount; ++i) { - var phybHandle = physics != null ? physics->BonePhysicsResourceHandles[i] : null; - var kdbHandle = kineDriver != null ? kineDriver->PartialSkeletonEntries[i].KineDriverResourceHandle : null; - if (context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i], phybHandle, kdbHandle, (uint)i) is { } sklbNode) + // TODO ClientStructs-ify (aers/FFXIVClientStructs#1312) + var phybHandle = physics != null ? ((ResourceHandle**)((nint)physics + 0x190))[i] : null; + if (context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i], phybHandle, (uint)i) is { } sklbNode) { if (context.Global.WithUiData) sklbNode.FallbackName = $"{prefix}Skeleton #{i}"; diff --git a/Penumbra/Interop/Services/RedrawService.cs b/Penumbra/Interop/Services/RedrawService.cs index 2d741277..08e9ddf5 100644 --- a/Penumbra/Interop/Services/RedrawService.cs +++ b/Penumbra/Interop/Services/RedrawService.cs @@ -421,9 +421,9 @@ public sealed unsafe partial class RedrawService : IDisposable return; - foreach (ref var f in currentTerritory->FurnitureManager.FurnitureMemory) + foreach (ref var f in currentTerritory->Furniture) { - var gameObject = f.Index >= 0 ? currentTerritory->FurnitureManager.ObjectManager.ObjectArray.Objects[f.Index].Value : null; + var gameObject = f.Index >= 0 ? currentTerritory->HousingObjectManager.Objects[f.Index].Value : null; if (gameObject == null) continue; diff --git a/Penumbra/Interop/Services/TextureArraySlicer.cs b/Penumbra/Interop/Services/TextureArraySlicer.cs index 11498878..c934ac2b 100644 --- a/Penumbra/Interop/Services/TextureArraySlicer.cs +++ b/Penumbra/Interop/Services/TextureArraySlicer.cs @@ -1,4 +1,3 @@ -using Dalamud.Bindings.ImGui; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using OtterGui.Services; using SharpDX.Direct3D; @@ -17,7 +16,7 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable private readonly HashSet<(nint XivTexture, byte SliceIndex)> _expiredKeys = []; /// Caching this across frames will cause a crash to desktop. - public ImTextureID GetImGuiHandle(Texture* texture, byte sliceIndex) + public nint GetImGuiHandle(Texture* texture, byte sliceIndex) { if (texture == null) throw new ArgumentNullException(nameof(texture)); @@ -26,7 +25,7 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable if (_activeSlices.TryGetValue(((nint)texture, sliceIndex), out var state)) { state.Refresh(); - return new ImTextureID((nint)state.ShaderResourceView); + return (nint)state.ShaderResourceView; } var srv = (ShaderResourceView)(nint)texture->D3D11ShaderResourceView; var description = srv.Description; @@ -61,7 +60,7 @@ public sealed unsafe class TextureArraySlicer : IUiService, IDisposable } state = new SliceState(new ShaderResourceView(srv.Device, srv.Resource, description)); _activeSlices.Add(((nint)texture, sliceIndex), state); - return new ImTextureID((nint)state.ShaderResourceView); + return (nint)state.ShaderResourceView; } public void Tick() diff --git a/Penumbra/Interop/Structs/StructExtensions.cs b/Penumbra/Interop/Structs/StructExtensions.cs index 7349f6cc..03b4cf36 100644 --- a/Penumbra/Interop/Structs/StructExtensions.cs +++ b/Penumbra/Interop/Structs/StructExtensions.cs @@ -10,34 +10,28 @@ internal static class StructExtensions public static CiByteString AsByteString(in this StdString str) => CiByteString.FromSpanUnsafe(str.AsSpan(), true); - public static CiByteString ResolveEidPathAsByteString(ref this CharacterBase character) - { - Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveEidPath(pathBuffer)); + public static CiByteString ResolveEidPathAsByteString(ref this CharacterBase character) + { + Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; + return ToOwnedByteString(character.ResolveEidPath(pathBuffer)); + } + + public static CiByteString ResolveImcPathAsByteString(ref this CharacterBase character, uint slotIndex) + { + Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; + return ToOwnedByteString(character.ResolveImcPath(pathBuffer, slotIndex)); } - public static CiByteString ResolveImcPathAsByteString(ref this CharacterBase character, uint slotIndex) - { - Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveImcPath(pathBuffer, slotIndex)); + public static CiByteString ResolveMdlPathAsByteString(ref this CharacterBase character, uint slotIndex) + { + Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; + return ToOwnedByteString(character.ResolveMdlPath(pathBuffer, slotIndex)); } - public static CiByteString ResolveMdlPathAsByteString(ref this CharacterBase character, uint slotIndex) - { - Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveMdlPath(pathBuffer, slotIndex)); - } - - public static unsafe CiByteString ResolveMtrlPathAsByteString(ref this CharacterBase character, uint slotIndex, byte* mtrlFileName) - { - var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveMtrlPath(pathBuffer, CharacterBase.PathBufferSize, slotIndex, mtrlFileName)); - } - - public static unsafe CiByteString ResolveSkinMtrlPathAsByteString(ref this CharacterBase character, uint slotIndex) - { - var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveSkinMtrlPath(pathBuffer, CharacterBase.PathBufferSize, slotIndex)); + public static unsafe CiByteString ResolveMtrlPathAsByteString(ref this CharacterBase character, uint slotIndex, byte* mtrlFileName) + { + var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; + return ToOwnedByteString(character.ResolveMtrlPath(pathBuffer, CharacterBase.PathBufferSize, slotIndex, mtrlFileName)); } public static CiByteString ResolveMaterialPapPathAsByteString(ref this CharacterBase character, uint slotIndex, uint unkSId) @@ -46,16 +40,16 @@ internal static class StructExtensions return ToOwnedByteString(character.ResolveMaterialPapPath(pathBuffer, slotIndex, unkSId)); } - public static CiByteString ResolveSklbPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex) - { - Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveSklbPath(pathBuffer, partialSkeletonIndex)); + public static CiByteString ResolveSklbPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex) + { + Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; + return ToOwnedByteString(character.ResolveSklbPath(pathBuffer, partialSkeletonIndex)); } - public static CiByteString ResolveSkpPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex) - { - Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveSkpPath(pathBuffer, partialSkeletonIndex)); + public static CiByteString ResolveSkpPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex) + { + Span pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; + return ToOwnedByteString(character.ResolveSkpPath(pathBuffer, partialSkeletonIndex)); } public static CiByteString ResolvePhybPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex) @@ -64,12 +58,6 @@ internal static class StructExtensions return ToOwnedByteString(character.ResolvePhybPath(pathBuffer, partialSkeletonIndex)); } - public static unsafe CiByteString ResolveKdbPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex) - { - var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize]; - return ToOwnedByteString(character.ResolveKdbPath(pathBuffer, CharacterBase.PathBufferSize, partialSkeletonIndex)); - } - private static unsafe CiByteString ToOwnedByteString(CStringPointer str) => str.HasValue ? new CiByteString(str.Value).Clone() : CiByteString.Empty; diff --git a/Penumbra/Meta/Manipulations/MetaDictionary.cs b/Penumbra/Meta/Manipulations/MetaDictionary.cs index 8b448ec6..ede062ae 100644 --- a/Penumbra/Meta/Manipulations/MetaDictionary.cs +++ b/Penumbra/Meta/Manipulations/MetaDictionary.cs @@ -1,10 +1,7 @@ -using System.Collections.Frozen; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Penumbra.Collections.Cache; -using Penumbra.GameData.Enums; using Penumbra.GameData.Files.AtchStructs; -using Penumbra.GameData.Interop; using Penumbra.GameData.Structs; using Penumbra.Util; using ImcEntry = Penumbra.GameData.Structs.ImcEntry; @@ -43,165 +40,6 @@ public class MetaDictionary foreach (var geqp in cache.GlobalEqp.Keys) Add(geqp); } - - public static unsafe Wrapper Filtered(MetaCache cache, Actor actor) - { - if (!actor.IsCharacter) - return new Wrapper(cache); - - var model = actor.Model; - if (!model.IsHuman) - return new Wrapper(cache); - - var headId = model.GetModelId(HumanSlot.Head); - var bodyId = model.GetModelId(HumanSlot.Body); - var equipIdSet = ((IEnumerable) - [ - headId, - bodyId, - model.GetModelId(HumanSlot.Hands), - model.GetModelId(HumanSlot.Legs), - model.GetModelId(HumanSlot.Feet), - ]).ToFrozenSet(); - var earsId = model.GetModelId(HumanSlot.Ears); - var neckId = model.GetModelId(HumanSlot.Neck); - var wristId = model.GetModelId(HumanSlot.Wrists); - var rFingerId = model.GetModelId(HumanSlot.RFinger); - var lFingerId = model.GetModelId(HumanSlot.LFinger); - - var wrapper = new Wrapper(); - // Check for all relevant primary IDs due to slot overlap. - foreach (var (eqp, value) in cache.Eqp) - { - if (eqp.Slot.IsEquipment()) - { - if (equipIdSet.Contains(eqp.SetId)) - wrapper.Eqp.Add(eqp, new EqpEntryInternal(value.Entry, eqp.Slot)); - } - else - { - switch (eqp.Slot) - { - case EquipSlot.Ears when eqp.SetId == earsId: - case EquipSlot.Neck when eqp.SetId == neckId: - case EquipSlot.Wrists when eqp.SetId == wristId: - case EquipSlot.RFinger when eqp.SetId == rFingerId: - case EquipSlot.LFinger when eqp.SetId == lFingerId: - wrapper.Eqp.Add(eqp, new EqpEntryInternal(value.Entry, eqp.Slot)); - break; - } - } - } - - // Check also for body IDs due to body occupying head. - foreach (var (gmp, value) in cache.Gmp) - { - if (gmp.SetId == headId || gmp.SetId == bodyId) - wrapper.Gmp.Add(gmp, value.Entry); - } - - // Check for all races due to inheritance and all slots due to overlap. - foreach (var (eqdp, value) in cache.Eqdp) - { - if (eqdp.Slot.IsEquipment()) - { - if (equipIdSet.Contains(eqdp.SetId)) - wrapper.Eqdp.Add(eqdp, new EqdpEntryInternal(value.Entry, eqdp.Slot)); - } - else - { - switch (eqdp.Slot) - { - case EquipSlot.Ears when eqdp.SetId == earsId: - case EquipSlot.Neck when eqdp.SetId == neckId: - case EquipSlot.Wrists when eqdp.SetId == wristId: - case EquipSlot.RFinger when eqdp.SetId == rFingerId: - case EquipSlot.LFinger when eqdp.SetId == lFingerId: - wrapper.Eqdp.Add(eqdp, new EqdpEntryInternal(value.Entry, eqdp.Slot)); - break; - } - } - } - - var genderRace = (GenderRace)model.AsHuman->RaceSexId; - var hairId = model.GetModelId(HumanSlot.Hair); - var faceId = model.GetModelId(HumanSlot.Face); - // We do not need to care for racial inheritance for ESTs. - foreach (var (est, value) in cache.Est) - { - switch (est.Slot) - { - case EstType.Hair when est.SetId == hairId && est.GenderRace == genderRace: - case EstType.Face when est.SetId == faceId && est.GenderRace == genderRace: - case EstType.Body when est.SetId == bodyId && est.GenderRace == genderRace: - case EstType.Head when (est.SetId == headId || est.SetId == bodyId) && est.GenderRace == genderRace: - wrapper.Est.Add(est, value.Entry); - break; - } - } - - foreach (var (geqp, _) in cache.GlobalEqp) - { - switch (geqp.Type) - { - case GlobalEqpType.DoNotHideEarrings when geqp.Condition != earsId: - case GlobalEqpType.DoNotHideNecklace when geqp.Condition != neckId: - case GlobalEqpType.DoNotHideBracelets when geqp.Condition != wristId: - case GlobalEqpType.DoNotHideRingR when geqp.Condition != rFingerId: - case GlobalEqpType.DoNotHideRingL when geqp.Condition != lFingerId: - continue; - default: wrapper.Add(geqp); break; - } - } - - var (_, _, main, off) = model.GetWeapons(actor); - foreach (var (imc, value) in cache.Imc) - { - switch (imc.ObjectType) - { - case ObjectType.Equipment when equipIdSet.Contains(imc.PrimaryId): wrapper.Imc.Add(imc, value.Entry); break; - - case ObjectType.Weapon: - if (imc.PrimaryId == main.Skeleton && imc.SecondaryId == main.Weapon) - wrapper.Imc.Add(imc, value.Entry); - else if (imc.PrimaryId == off.Skeleton && imc.SecondaryId == off.Weapon) - wrapper.Imc.Add(imc, value.Entry); - break; - case ObjectType.Accessory: - switch (imc.EquipSlot) - { - case EquipSlot.Ears when imc.PrimaryId == earsId: - case EquipSlot.Neck when imc.PrimaryId == neckId: - case EquipSlot.Wrists when imc.PrimaryId == wristId: - case EquipSlot.RFinger when imc.PrimaryId == rFingerId: - case EquipSlot.LFinger when imc.PrimaryId == lFingerId: - wrapper.Imc.Add(imc, value.Entry); - break; - } - - break; - } - } - - var subRace = (SubRace)model.AsHuman->Customize[4]; - foreach (var (rsp, value) in cache.Rsp) - { - if (rsp.SubRace == subRace) - wrapper.Rsp.Add(rsp, value.Entry); - } - - // Keep all atch, atr and shp. - wrapper.Atch.EnsureCapacity(cache.Atch.Count); - wrapper.Shp.EnsureCapacity(cache.Shp.Count); - wrapper.Atr.EnsureCapacity(cache.Atr.Count); - foreach (var (atch, value) in cache.Atch) - wrapper.Atch.Add(atch, value.Entry); - foreach (var (shp, value) in cache.Shp) - wrapper.Shp.Add(shp, value.Entry); - foreach (var (atr, value) in cache.Atr) - wrapper.Atr.Add(atr, value.Entry); - return wrapper; - } } private Wrapper? _data; @@ -288,7 +126,6 @@ public class MetaDictionary { _data = null; Count = 0; - return; } Count = GlobalEqp.Count + Shp.Count + Atr.Count; @@ -1096,24 +933,4 @@ public class MetaDictionary _data = new Wrapper(cache); Count = cache.Count; } - - public MetaDictionary(MetaCache? cache, Actor actor) - { - if (cache is null) - return; - - _data = Wrapper.Filtered(cache, actor); - Count = _data.Count - + _data.Eqp.Count - + _data.Eqdp.Count - + _data.Est.Count - + _data.Gmp.Count - + _data.Imc.Count - + _data.Rsp.Count - + _data.Atch.Count - + _data.Atr.Count - + _data.Shp.Count; - if (Count is 0) - _data = null; - } } diff --git a/Penumbra/Meta/ShapeAttributeManager.cs b/Penumbra/Meta/ShapeAttributeManager.cs index a7f71ac7..a742806f 100644 --- a/Penumbra/Meta/ShapeAttributeManager.cs +++ b/Penumbra/Meta/ShapeAttributeManager.cs @@ -58,72 +58,11 @@ public unsafe class ShapeAttributeManager : IRequiredService, IDisposable _ids[(int)_modelIndex] = model.GetModelId(_modelIndex); CheckShapes(collection.MetaCache!.Shp); CheckAttributes(collection.MetaCache!.Atr); - if (_modelIndex is <= HumanSlot.LFinger and >= HumanSlot.Ears) - AccessoryImcCheck(model); } UpdateDefaultMasks(model, collection.MetaCache!.Shp); } - private void AccessoryImcCheck(Model model) - { - var imcMask = (ushort)(0x03FF & *(ushort*)(model.Address + 0xAAC + 6 * (int)_modelIndex)); - - Span attr = - [ - (byte)'a', - (byte)'t', - (byte)'r', - (byte)'_', - AccessoryByte(_modelIndex), - (byte)'v', - (byte)'_', - (byte)'a', - 0, - ]; - for (var i = 1; i < 10; ++i) - { - var flag = (ushort)(1 << i); - if ((imcMask & flag) is not 0) - continue; - - attr[^2] = (byte)('a' + i); - - foreach (var (attribute, index) in _model->ModelResourceHandle->Attributes) - { - if (!EqualAttribute(attr, attribute.Value)) - continue; - - _model->EnabledAttributeIndexMask &= ~(1u << index); - break; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] - private static bool EqualAttribute(Span needle, byte* haystack) - { - foreach (var character in needle) - { - if (*haystack++ != character) - return false; - } - - return true; - } - - private static byte AccessoryByte(HumanSlot slot) - => slot switch - { - HumanSlot.Head => (byte)'m', - HumanSlot.Ears => (byte)'e', - HumanSlot.Neck => (byte)'n', - HumanSlot.Wrists => (byte)'w', - HumanSlot.RFinger => (byte)'r', - HumanSlot.LFinger => (byte)'r', - _ => 0, - }; - private void CheckAttributes(AtrCache attributeCache) { if (attributeCache.DisabledCount is 0) diff --git a/Penumbra/Mods/Editor/ModMerger.cs b/Penumbra/Mods/Editor/ModMerger.cs index eb270e13..bb84173a 100644 --- a/Penumbra/Mods/Editor/ModMerger.cs +++ b/Penumbra/Mods/Editor/ModMerger.cs @@ -372,6 +372,7 @@ public class ModMerger : IDisposable, IService } else { + // TODO DataContainer <> Option. var (group, _, _) = _editor.FindOrAddModGroup(result, originalGroup.Type, originalGroup.Name); var (option, _, _) = _editor.FindOrAddOption(group!, originalOption.GetName()); var folder = Path.Combine(dir.FullName, group!.Name, option!.Name); diff --git a/Penumbra/Mods/Editor/ModNormalizer.cs b/Penumbra/Mods/Editor/ModNormalizer.cs index df1528f6..527dbf7c 100644 --- a/Penumbra/Mods/Editor/ModNormalizer.cs +++ b/Penumbra/Mods/Editor/ModNormalizer.cs @@ -76,7 +76,7 @@ public class ModNormalizer(ModManager modManager, Configuration config, SaveServ else { var groupDir = ModCreator.NewOptionDirectory(mod.ModPath, container.Group.Name, config.ReplaceNonAsciiOnImport); - var optionDir = ModCreator.NewOptionDirectory(groupDir, container.GetDirectoryName(), config.ReplaceNonAsciiOnImport); + var optionDir = ModCreator.NewOptionDirectory(groupDir, container.GetName(), config.ReplaceNonAsciiOnImport); containers[container] = optionDir.FullName; } } @@ -286,7 +286,7 @@ public class ModNormalizer(ModManager modManager, Configuration config, SaveServ void HandleSubMod(DirectoryInfo groupDir, IModDataContainer option, Dictionary newDict) { - var name = option.GetDirectoryName(); + var name = option.GetName(); var optionDir = ModCreator.CreateModFolder(groupDir, name, config.ReplaceNonAsciiOnImport, true); newDict.Clear(); diff --git a/Penumbra/Mods/FeatureChecker.cs b/Penumbra/Mods/FeatureChecker.cs index 10874fc9..5800ef07 100644 --- a/Penumbra/Mods/FeatureChecker.cs +++ b/Penumbra/Mods/FeatureChecker.cs @@ -1,7 +1,7 @@ using System.Collections.Frozen; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Text; using Penumbra.Mods.Manager; using Penumbra.UI.Classes; diff --git a/Penumbra/Mods/Groups/ComplexModGroup.cs b/Penumbra/Mods/Groups/ComplexModGroup.cs deleted file mode 100644 index 435bc253..00000000 --- a/Penumbra/Mods/Groups/ComplexModGroup.cs +++ /dev/null @@ -1,180 +0,0 @@ -using Dalamud.Interface.ImGuiNotification; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OtterGui.Classes; -using OtterGui.Extensions; -using Penumbra.Api.Enums; -using Penumbra.GameData.Data; -using Penumbra.Meta.Manipulations; -using Penumbra.Mods.Settings; -using Penumbra.Mods.SubMods; -using Penumbra.String.Classes; -using Penumbra.UI.ModsTab.Groups; -using Penumbra.Util; - -namespace Penumbra.Mods.Groups; - -public sealed class ComplexModGroup(Mod mod) : IModGroup -{ - public Mod Mod { get; } = mod; - public string Name { get; set; } = "Option"; - public string Description { get; set; } = string.Empty; - public string Image { get; set; } = string.Empty; - - public GroupType Type - => GroupType.Complex; - - public GroupDrawBehaviour Behaviour - => GroupDrawBehaviour.Complex; - - public ModPriority Priority { get; set; } - public int Page { get; set; } - public Setting DefaultSettings { get; set; } - - public readonly List Options = []; - public readonly List Containers = []; - - - public FullPath? FindBestMatch(Utf8GamePath gamePath) - => throw new NotImplementedException(); - - public IModOption? AddOption(string name, string description = "") - => throw new NotImplementedException(); - - IReadOnlyList IModGroup.Options - => Options; - - IReadOnlyList IModGroup.DataContainers - => Containers; - - public bool IsOption - => Options.Count > 0; - - public int GetIndex() - => ModGroup.GetIndex(this); - - public IModGroupEditDrawer EditDrawer(ModGroupEditDrawer editDrawer) - => throw new NotImplementedException(); - - public void AddData(Setting setting, Dictionary redirections, MetaDictionary manipulations) - { - foreach (var container in Containers.Where(c => c.Association.IsEnabled(setting))) - SubMod.AddContainerTo(container, redirections, manipulations); - } - - public void AddChangedItems(ObjectIdentification identifier, IDictionary changedItems) - { - foreach (var container in Containers) - identifier.AddChangedItems(container, changedItems); - } - - public Setting FixSetting(Setting setting) - => new(setting.Value & ((1ul << Options.Count) - 1)); - - public void WriteJson(JsonTextWriter jWriter, JsonSerializer serializer, DirectoryInfo? basePath = null) - { - ModSaveGroup.WriteJsonBase(jWriter, this); - jWriter.WritePropertyName("Options"); - jWriter.WriteStartArray(); - foreach (var option in Options) - { - jWriter.WriteStartObject(); - SubMod.WriteModOption(jWriter, option); - if (!option.Conditions.IsZero) - { - jWriter.WritePropertyName("ConditionMask"); - jWriter.WriteValue(option.Conditions.Mask.Value); - jWriter.WritePropertyName("ConditionValue"); - jWriter.WriteValue(option.Conditions.Value.Value); - } - - if (option.Indentation > 0) - { - jWriter.WritePropertyName("Indentation"); - jWriter.WriteValue(option.Indentation); - } - - if (option.SubGroupLabel.Length > 0) - { - jWriter.WritePropertyName("SubGroup"); - jWriter.WriteValue(option.SubGroupLabel); - } - - jWriter.WriteEndObject(); - } - - jWriter.WriteEndArray(); - - jWriter.WritePropertyName("Containers"); - jWriter.WriteStartArray(); - foreach (var container in Containers) - { - jWriter.WriteStartObject(); - if (container.Name.Length > 0) - { - jWriter.WritePropertyName("Name"); - jWriter.WriteValue(container.Name); - } - - if (!container.Association.IsZero) - { - jWriter.WritePropertyName("AssociationMask"); - jWriter.WriteValue(container.Association.Mask.Value); - - jWriter.WritePropertyName("AssociationValue"); - jWriter.WriteValue(container.Association.Value.Value); - } - - SubMod.WriteModContainer(jWriter, serializer, container, basePath ?? Mod.ModPath); - jWriter.WriteEndObject(); - } - - jWriter.WriteEndArray(); - } - - public (int Redirections, int Swaps, int Manips) GetCounts() - => ModGroup.GetCountsBase(this); - - public static ComplexModGroup? Load(Mod mod, JObject json) - { - var ret = new ComplexModGroup(mod); - if (!ModSaveGroup.ReadJsonBase(json, ret)) - return null; - - var options = json["Options"]; - if (options != null) - foreach (var child in options.Children()) - { - if (ret.Options.Count == IModGroup.MaxComplexOptions) - { - Penumbra.Messager.NotificationMessage( - $"Complex Group {ret.Name} in {mod.Name} has more than {IModGroup.MaxComplexOptions} options, ignoring excessive options.", - NotificationType.Warning); - break; - } - - var subMod = new ComplexSubMod(ret, child); - ret.Options.Add(subMod); - } - - // Fix up conditions: No condition on itself. - foreach (var (option, index) in ret.Options.WithIndex()) - { - option.Conditions = option.Conditions.Limit(ret.Options.Count); - option.Conditions = new MaskedSetting(option.Conditions.Mask.SetBit(index, false), option.Conditions.Value); - } - - var containers = json["Containers"]; - if (containers != null) - foreach (var child in containers.Children()) - { - var container = new ComplexDataContainer(ret, child); - container.Association = container.Association.Limit(ret.Options.Count); - ret.Containers.Add(container); - } - - ret.DefaultSettings = ret.FixSetting(ret.DefaultSettings); - - return ret; - } -} diff --git a/Penumbra/Mods/Groups/IModGroup.cs b/Penumbra/Mods/Groups/IModGroup.cs index 98f62862..cc961b0f 100644 --- a/Penumbra/Mods/Groups/IModGroup.cs +++ b/Penumbra/Mods/Groups/IModGroup.cs @@ -18,13 +18,11 @@ public enum GroupDrawBehaviour { SingleSelection, MultiSelection, - Complex, } public interface IModGroup { public const int MaxMultiOptions = 32; - public const int MaxComplexOptions = MaxMultiOptions; public const int MaxCombiningOptions = 8; public Mod Mod { get; } diff --git a/Penumbra/Mods/ItemSwap/EquipmentSwap.cs b/Penumbra/Mods/ItemSwap/EquipmentSwap.cs index 216b5841..5c67df52 100644 --- a/Penumbra/Mods/ItemSwap/EquipmentSwap.cs +++ b/Penumbra/Mods/ItemSwap/EquipmentSwap.cs @@ -234,56 +234,9 @@ public static class EquipmentSwap mdl.ChildSwaps.Add(mtrl); } - FixAttributes(mdl, slotFrom, slotTo); - return mdl; } - private static void FixAttributes(FileSwap swap, EquipSlot slotFrom, EquipSlot slotTo) - { - if (slotFrom == slotTo) - return; - - var needle = slotTo switch - { - EquipSlot.Head => "atr_mv_", - EquipSlot.Ears => "atr_ev_", - EquipSlot.Neck => "atr_nv_", - EquipSlot.Wrists => "atr_wv_", - EquipSlot.RFinger or EquipSlot.LFinger => "atr_rv_", - _ => string.Empty, - }; - - var replacement = slotFrom switch - { - EquipSlot.Head => 'm', - EquipSlot.Ears => 'e', - EquipSlot.Neck => 'n', - EquipSlot.Wrists => 'w', - EquipSlot.RFinger or EquipSlot.LFinger => 'r', - _ => 'm', - }; - - var attributes = swap.AsMdl()!.Attributes; - for (var i = 0; i < attributes.Length; ++i) - { - if (FixAttribute(ref attributes[i], needle, replacement)) - swap.DataWasChanged = true; - } - } - - private static unsafe bool FixAttribute(ref string attribute, string from, char to) - { - if (!attribute.StartsWith(from) || attribute.Length != from.Length + 1 || attribute[^1] is < 'a' or > 'j') - return false; - - Span stack = stackalloc char[attribute.Length]; - attribute.CopyTo(stack); - stack[4] = to; - attribute = new string(stack); - return true; - } - private static void LookupItem(EquipItem i, out EquipSlot slot, out PrimaryId modelId, out Variant variant) { slot = i.Type.ToSlot(); @@ -446,7 +399,7 @@ public static class EquipmentSwap return null; var folderTo = GamePaths.Mtrl.GearFolder(slotTo, idTo, variantTo); - var pathTo = $"{folderTo}{fileName}"; + var pathTo = $"{folderTo}{fileName}"; var folderFrom = GamePaths.Mtrl.GearFolder(slotFrom, idFrom, variantTo); var newFileName = ItemSwap.ReplaceId(fileName, prefix, idTo, idFrom); diff --git a/Penumbra/Mods/Manager/ModDataEditor.cs b/Penumbra/Mods/Manager/ModDataEditor.cs index ffa73b76..fc4fdadc 100644 --- a/Penumbra/Mods/Manager/ModDataEditor.cs +++ b/Penumbra/Mods/Manager/ModDataEditor.cs @@ -36,7 +36,7 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic /// Create the file containing the meta information about a mod from scratch. public void CreateMeta(DirectoryInfo directory, string? name, string? author, string? description, string? version, - string? website, params string[] tags) + string? website) { var mod = new Mod(directory); mod.Name = name.IsNullOrEmpty() ? mod.Name : new LowerString(name); @@ -44,7 +44,6 @@ public class ModDataEditor(SaveService saveService, CommunicatorService communic mod.Description = description ?? mod.Description; mod.Version = version ?? mod.Version; mod.Website = website ?? mod.Website; - mod.ModTags = tags; saveService.ImmediateSaveSync(new ModMeta(mod)); } diff --git a/Penumbra/Mods/Manager/ModFileSystem.cs b/Penumbra/Mods/Manager/ModFileSystem.cs index 20a78995..a5c46972 100644 --- a/Penumbra/Mods/Manager/ModFileSystem.cs +++ b/Penumbra/Mods/Manager/ModFileSystem.cs @@ -37,11 +37,11 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer public struct ImportDate : ISortMode { - public ReadOnlySpan Name - => "Import Date (Older First)"u8; + public string Name + => "Import Date (Older First)"; - public ReadOnlySpan Description - => "In each folder, sort all subfolders lexicographically, then sort all leaves using their import date."u8; + public string Description + => "In each folder, sort all subfolders lexicographically, then sort all leaves using their import date."; public IEnumerable GetChildren(Folder f) => f.GetSubFolders().Cast().Concat(f.GetLeaves().OrderBy(l => l.Value.ImportDate)); @@ -49,11 +49,11 @@ public sealed class ModFileSystem : FileSystem, IDisposable, ISavable, ISer public struct InverseImportDate : ISortMode { - public ReadOnlySpan Name - => "Import Date (Newer First)"u8; + public string Name + => "Import Date (Newer First)"; - public ReadOnlySpan Description - => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse import date."u8; + public string Description + => "In each folder, sort all subfolders lexicographically, then sort all leaves using their inverse import date."; public IEnumerable GetChildren(Folder f) => f.GetSubFolders().Cast().Concat(f.GetLeaves().OrderByDescending(l => l.Value.ImportDate)); diff --git a/Penumbra/Mods/Manager/ModManager.cs b/Penumbra/Mods/Manager/ModManager.cs index 77385bbd..32dac049 100644 --- a/Penumbra/Mods/Manager/ModManager.cs +++ b/Penumbra/Mods/Manager/ModManager.cs @@ -1,6 +1,5 @@ using OtterGui.Services; using Penumbra.Communication; -using Penumbra.Interop; using Penumbra.Mods.Editor; using Penumbra.Mods.Manager.OptionEditor; using Penumbra.Services; @@ -304,9 +303,6 @@ public sealed class ModManager : ModStorage, IDisposable, IService if (!firstTime && _config.ModDirectory != BasePath.FullName) TriggerModDirectoryChange(BasePath.FullName, Valid); } - - if (CloudApi.IsCloudSynced(BasePath.FullName)) - Penumbra.Log.Warning($"Mod base directory {BasePath.FullName} is cloud-synced. This may cause issues."); } private void TriggerModDirectoryChange(string newPath, bool valid) diff --git a/Penumbra/Mods/ModCreator.cs b/Penumbra/Mods/ModCreator.cs index 3a7bd105..1bb2a073 100644 --- a/Penumbra/Mods/ModCreator.cs +++ b/Penumbra/Mods/ModCreator.cs @@ -32,12 +32,12 @@ public partial class ModCreator( public readonly Configuration Config = config; /// Creates directory and files necessary for a new mod without adding it to the manager. - public DirectoryInfo? CreateEmptyMod(DirectoryInfo basePath, string newName, string description = "", string? author = null, params string[] tags) + public DirectoryInfo? CreateEmptyMod(DirectoryInfo basePath, string newName, string description = "", string? author = null) { try { var newDir = CreateModFolder(basePath, newName, Config.ReplaceNonAsciiOnImport, true); - dataEditor.CreateMeta(newDir, newName, author ?? Config.DefaultModAuthor, description, "1.0", string.Empty, tags); + dataEditor.CreateMeta(newDir, newName, author ?? Config.DefaultModAuthor, description, "1.0", string.Empty); CreateDefaultFiles(newDir); return newDir; } diff --git a/Penumbra/Mods/SubMods/CombinedDataContainer.cs b/Penumbra/Mods/SubMods/CombinedDataContainer.cs index bfca2afd..b467c360 100644 --- a/Penumbra/Mods/SubMods/CombinedDataContainer.cs +++ b/Penumbra/Mods/SubMods/CombinedDataContainer.cs @@ -48,25 +48,6 @@ public class CombinedDataContainer(IModGroup group) : IModDataContainer return sb.ToString(0, sb.Length - 3); } - public unsafe string GetDirectoryName() - { - if (Name.Length > 0) - return Name; - - var index = GetDataIndex(); - if (index == 0) - return "None"; - - var text = stackalloc char[IModGroup.MaxCombiningOptions].Slice(0, Group.Options.Count); - for (var i = 0; i < Group.Options.Count; ++i) - { - text[Group.Options.Count - 1 - i] = (index & 1) is 0 ? '0' : '1'; - index >>= 1; - } - - return new string(text); - } - public string GetFullName() => $"{Group.Name}: {GetName()}"; diff --git a/Penumbra/Mods/SubMods/ComplexDataContainer.cs b/Penumbra/Mods/SubMods/ComplexDataContainer.cs deleted file mode 100644 index 0f0fdef8..00000000 --- a/Penumbra/Mods/SubMods/ComplexDataContainer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Newtonsoft.Json.Linq; -using OtterGui.Extensions; -using Penumbra.Meta.Manipulations; -using Penumbra.Mods.Editor; -using Penumbra.Mods.Groups; -using Penumbra.String.Classes; - -namespace Penumbra.Mods.SubMods; - -public sealed class ComplexDataContainer(ComplexModGroup group) : IModDataContainer -{ - public IMod Mod - => Group.Mod; - - public IModGroup Group { get; } = group; - - public Dictionary Files { get; set; } = []; - public Dictionary FileSwaps { get; set; } = []; - public MetaDictionary Manipulations { get; set; } = new(); - - public MaskedSetting Association = MaskedSetting.Zero; - - public string Name { get; set; } = string.Empty; - - public string GetName() - => Name.Length > 0 ? Name : $"Container {Group.DataContainers.IndexOf(this)}"; - - public string GetDirectoryName() - => Name.Length > 0 ? Name : $"{Group.DataContainers.IndexOf(this)}"; - - public string GetFullName() - => $"{Group.Name}: {GetName()}"; - - public (int GroupIndex, int DataIndex) GetDataIndices() - => (Group.GetIndex(), Group.DataContainers.IndexOf(this)); - - public ComplexDataContainer(ComplexModGroup group, JToken json) - : this(group) - { - SubMod.LoadDataContainer(json, this, group.Mod.ModPath); - var mask = json["AssociationMask"]?.ToObject() ?? 0; - var value = json["AssociationMask"]?.ToObject() ?? 0; - Association = new MaskedSetting(mask, value); - Name = json["Name"]?.ToObject() ?? string.Empty; - } -} diff --git a/Penumbra/Mods/SubMods/ComplexSubMod.cs b/Penumbra/Mods/SubMods/ComplexSubMod.cs deleted file mode 100644 index 7c189170..00000000 --- a/Penumbra/Mods/SubMods/ComplexSubMod.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Newtonsoft.Json.Linq; -using OtterGui.Extensions; -using Penumbra.Mods.Groups; - -namespace Penumbra.Mods.SubMods; - -public sealed class ComplexSubMod(ComplexModGroup group) : IModOption -{ - public Mod Mod - => group.Mod; - - public IModGroup Group { get; } = group; - public string Name { get; set; } = "Option"; - - public string FullName - => $"{Group.Name}: {Name}"; - - public MaskedSetting Conditions = MaskedSetting.Zero; - public int Indentation = 0; - public string SubGroupLabel = string.Empty; - - public string Description { get; set; } = string.Empty; - - public int GetIndex() - => Group.Options.IndexOf(this); - - public ComplexSubMod(ComplexModGroup group, JToken json) - : this(group) - { - SubMod.LoadOptionData(json, this); - var mask = json["ConditionMask"]?.ToObject() ?? 0; - var value = json["ConditionMask"]?.ToObject() ?? 0; - Conditions = new MaskedSetting(mask, value); - Indentation = json["Indentation"]?.ToObject() ?? 0; - SubGroupLabel = json["SubGroup"]?.ToObject() ?? string.Empty; - } -} diff --git a/Penumbra/Mods/SubMods/DefaultSubMod.cs b/Penumbra/Mods/SubMods/DefaultSubMod.cs index 3282f518..3840468f 100644 --- a/Penumbra/Mods/SubMods/DefaultSubMod.cs +++ b/Penumbra/Mods/SubMods/DefaultSubMod.cs @@ -27,9 +27,6 @@ public class DefaultSubMod(IMod mod) : IModDataContainer public string GetName() => FullName; - public string GetDirectoryName() - => GetName(); - public string GetFullName() => FullName; diff --git a/Penumbra/Mods/SubMods/IModDataContainer.cs b/Penumbra/Mods/SubMods/IModDataContainer.cs index 92ccf7e1..1a89ec17 100644 --- a/Penumbra/Mods/SubMods/IModDataContainer.cs +++ b/Penumbra/Mods/SubMods/IModDataContainer.cs @@ -15,7 +15,6 @@ public interface IModDataContainer public MetaDictionary Manipulations { get; set; } public string GetName(); - public string GetDirectoryName(); public string GetFullName(); public (int GroupIndex, int DataIndex) GetDataIndices(); } diff --git a/Penumbra/Mods/SubMods/MaskedSetting.cs b/Penumbra/Mods/SubMods/MaskedSetting.cs deleted file mode 100644 index 75bb46c2..00000000 --- a/Penumbra/Mods/SubMods/MaskedSetting.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Penumbra.Mods.Groups; -using Penumbra.Mods.Settings; - -namespace Penumbra.Mods.SubMods; - -public readonly struct MaskedSetting(Setting mask, Setting value) -{ - public const int MaxSettings = IModGroup.MaxMultiOptions; - public static readonly MaskedSetting Zero = new(Setting.Zero, Setting.Zero); - public static readonly MaskedSetting FullMask = new(Setting.AllBits(IModGroup.MaxComplexOptions), Setting.Zero); - - public readonly Setting Mask = mask; - public readonly Setting Value = new(value.Value & mask.Value); - - public MaskedSetting(ulong mask, ulong value) - : this(new Setting(mask), new Setting(value)) - { } - - public MaskedSetting Limit(int numOptions) - => new(Mask.Value & Setting.AllBits(numOptions).Value, Value.Value); - - public bool IsZero - => Mask.Value is 0; - - public bool IsEnabled(Setting input) - => (input.Value & Mask.Value) == Value.Value; -} diff --git a/Penumbra/Mods/SubMods/OptionSubMod.cs b/Penumbra/Mods/SubMods/OptionSubMod.cs index aa3fed8f..9044350d 100644 --- a/Penumbra/Mods/SubMods/OptionSubMod.cs +++ b/Penumbra/Mods/SubMods/OptionSubMod.cs @@ -41,9 +41,6 @@ public abstract class OptionSubMod(IModGroup group) : IModOption, IModDataContai public string GetName() => Name; - public string GetDirectoryName() - => GetName(); - public string GetFullName() => FullName; diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index d433a0fb..70636bbf 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -1,6 +1,5 @@ using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; -using Dalamud.Game; +using ImGuiNET; using OtterGui; using OtterGui.Log; using OtterGui.Services; @@ -22,7 +21,6 @@ using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManage using Dalamud.Plugin.Services; using Lumina.Excel.Sheets; using Penumbra.GameData.Data; -using Penumbra.Interop; using Penumbra.Interop.Hooks; using Penumbra.Interop.Hooks.PostProcessing; using Penumbra.Interop.Hooks.ResourceLoading; @@ -211,11 +209,10 @@ public class Penumbra : IDalamudPlugin public string GatherSupportInformation() { - var sb = new StringBuilder(10240); - var exists = _config.ModDirectory.Length > 0 && Directory.Exists(_config.ModDirectory); - var cloudSynced = exists && CloudApi.IsCloudSynced(_config.ModDirectory); - var hdrEnabler = _services.GetService(); - var drive = exists ? new DriveInfo(new DirectoryInfo(_config.ModDirectory).Root.FullName) : null; + var sb = new StringBuilder(10240); + var exists = _config.ModDirectory.Length > 0 && Directory.Exists(_config.ModDirectory); + var hdrEnabler = _services.GetService(); + var drive = exists ? new DriveInfo(new DirectoryInfo(_config.ModDirectory).Root.FullName) : null; sb.AppendLine("**Settings**"); sb.Append($"> **`Plugin Version: `** {_validityChecker.Version}\n"); sb.Append($"> **`Commit Hash: `** {_validityChecker.CommitHash}\n"); @@ -224,8 +221,7 @@ public class Penumbra : IDalamudPlugin sb.Append($"> **`Operating System: `** {(Dalamud.Utility.Util.IsWine() ? "Mac/Linux (Wine)" : "Windows")}\n"); if (Dalamud.Utility.Util.IsWine()) sb.Append($"> **`Locale Environment Variables:`** {CollectLocaleEnvironmentVariables()}\n"); - sb.Append( - $"> **`Root Directory: `** `{_config.ModDirectory}`, {(exists ? "Exists" : "Not Existing")}{(cloudSynced ? ", Cloud-Synced" : "")}\n"); + sb.Append($"> **`Root Directory: `** `{_config.ModDirectory}`, {(exists ? "Exists" : "Not Existing")}\n"); sb.Append( $"> **`Free Drive Space: `** {(drive != null ? Functions.HumanReadableSize(drive.AvailableFreeSpace) : "Unknown")}\n"); sb.Append($"> **`Game Data Files: `** {(_gameData.HasModifiedGameDataFiles ? "Modified" : "Pristine")}\n"); @@ -233,12 +229,10 @@ public class Penumbra : IDalamudPlugin sb.Append($"> **`Auto-UI-Reduplication: `** {_config.AutoReduplicateUiOnImport}\n"); sb.Append($"> **`Debug Mode: `** {_config.DebugMode}\n"); sb.Append($"> **`Penumbra Reloads: `** {hdrEnabler.PenumbraReloadCount}\n"); - sb.Append( - $"> **`HDR Enabled (from Start): `** {_config.HdrRenderTargets} ({hdrEnabler is { FirstLaunchHdrState: true, FirstLaunchHdrHookOverrideState: true }}){(hdrEnabler.HdrEnabledSuccess ? ", Detour Called" : ", **NEVER CALLED**")}\n"); + sb.Append($"> **`HDR Enabled (from Start): `** {_config.HdrRenderTargets} ({hdrEnabler is { FirstLaunchHdrState: true, FirstLaunchHdrHookOverrideState: true }}){(hdrEnabler.HdrEnabledSuccess ? ", Detour Called" : ", **NEVER CALLED**")}\n"); sb.Append($"> **`Custom Shapes Enabled: `** {_config.EnableCustomShapes}\n"); sb.Append($"> **`Hook Overrides: `** {HookOverrides.Instance.IsCustomLoaded}\n"); - sb.Append( - $"> **`Synchronous Load (Dalamud): `** {(_services.GetService().GetDalamudConfig(DalamudConfigService.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")} (first Start: {hdrEnabler.FirstLaunchWaitForPluginsState?.ToString() ?? "Unknown"})\n"); + sb.Append($"> **`Synchronous Load (Dalamud): `** {(_services.GetService().GetDalamudConfig(DalamudConfigService.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")} (first Start: {hdrEnabler.FirstLaunchWaitForPluginsState?.ToString() ?? "Unknown"})\n"); sb.Append( $"> **`Logging: `** Log: {_config.Ephemeral.EnableResourceLogging}, Watcher: {_config.Ephemeral.EnableResourceWatcher} ({_config.MaxResourceWatcherRecords})\n"); sb.Append($"> **`Use Ownership: `** {_config.UseOwnerNameForCharacterCollection}\n"); diff --git a/Penumbra/Penumbra.csproj b/Penumbra/Penumbra.csproj index fa45ffbf..f668f775 100644 --- a/Penumbra/Penumbra.csproj +++ b/Penumbra/Penumbra.csproj @@ -1,4 +1,4 @@ - + Penumbra absolute gangstas @@ -57,11 +57,11 @@ - - - - - + + + + + diff --git a/Penumbra/Penumbra.json b/Penumbra/Penumbra.json index 32032282..924d7bd3 100644 --- a/Penumbra/Penumbra.json +++ b/Penumbra/Penumbra.json @@ -1,5 +1,5 @@ { - "Author": "Ottermandias, Nylfae, Adam, Wintermute", + "Author": "Ottermandias, Adam, Wintermute", "Name": "Penumbra", "Punchline": "Runtime mod loader and manager.", "Description": "Runtime mod loader and manager.", @@ -8,7 +8,7 @@ "RepoUrl": "https://github.com/xivdev/Penumbra", "ApplicableVersion": "any", "Tags": [ "modding" ], - "DalamudApiLevel": 13, + "DalamudApiLevel": 12, "LoadPriority": 69420, "LoadRequiredState": 2, "LoadSync": true, diff --git a/Penumbra/Services/CommunicatorService.cs b/Penumbra/Services/CommunicatorService.cs index 35f15e9e..5d745419 100644 --- a/Penumbra/Services/CommunicatorService.cs +++ b/Penumbra/Services/CommunicatorService.cs @@ -81,12 +81,6 @@ public class CommunicatorService : IDisposable, IService /// public readonly ResolvedFileChanged ResolvedFileChanged = new(); - /// - public readonly PcpCreation PcpCreation = new(); - - /// - public readonly PcpParsing PcpParsing = new(); - public void Dispose() { CollectionChange.Dispose(); @@ -111,7 +105,5 @@ public class CommunicatorService : IDisposable, IService ChangedItemClick.Dispose(); SelectTab.Dispose(); ResolvedFileChanged.Dispose(); - PcpCreation.Dispose(); - PcpParsing.Dispose(); } } diff --git a/Penumbra/Services/FileWatcher.cs b/Penumbra/Services/FileWatcher.cs deleted file mode 100644 index 1d572f05..00000000 --- a/Penumbra/Services/FileWatcher.cs +++ /dev/null @@ -1,209 +0,0 @@ -using OtterGui.Services; -using Penumbra.Mods.Manager; - -namespace Penumbra.Services; - -public class FileWatcher : IDisposable, IService -{ - // TODO: use ConcurrentSet when it supports comparers in Luna. - private readonly ConcurrentDictionary _pending = new(StringComparer.OrdinalIgnoreCase); - private readonly ModImportManager _modImportManager; - private readonly MessageService _messageService; - private readonly Configuration _config; - - private bool _pausedConsumer; - private FileSystemWatcher? _fsw; - private CancellationTokenSource? _cts = new(); - private Task? _consumer; - - public FileWatcher(ModImportManager modImportManager, MessageService messageService, Configuration config) - { - _modImportManager = modImportManager; - _messageService = messageService; - _config = config; - - if (_config.EnableDirectoryWatch) - { - SetupFileWatcher(_config.WatchDirectory); - SetupConsumerTask(); - } - } - - public void Toggle(bool value) - { - if (_config.EnableDirectoryWatch == value) - return; - - _config.EnableDirectoryWatch = value; - _config.Save(); - if (value) - { - SetupFileWatcher(_config.WatchDirectory); - SetupConsumerTask(); - } - else - { - EndFileWatcher(); - EndConsumerTask(); - } - } - - internal void PauseConsumer(bool pause) - => _pausedConsumer = pause; - - private void EndFileWatcher() - { - if (_fsw is null) - return; - - _fsw.Dispose(); - _fsw = null; - } - - private void SetupFileWatcher(string directory) - { - EndFileWatcher(); - _fsw = new FileSystemWatcher - { - IncludeSubdirectories = false, - NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime, - InternalBufferSize = 32 * 1024, - }; - - // Only wake us for the exact patterns we care about - _fsw.Filters.Add("*.pmp"); - _fsw.Filters.Add("*.pcp"); - _fsw.Filters.Add("*.ttmp"); - _fsw.Filters.Add("*.ttmp2"); - - _fsw.Created += OnPath; - _fsw.Renamed += OnPath; - UpdateDirectory(directory); - } - - - private void EndConsumerTask() - { - if (_cts is not null) - { - _cts.Cancel(); - _cts = null; - } - _consumer = null; - } - - private void SetupConsumerTask() - { - EndConsumerTask(); - _cts = new CancellationTokenSource(); - _consumer = Task.Factory.StartNew( - () => ConsumerLoopAsync(_cts.Token), - _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); - } - - public void UpdateDirectory(string newPath) - { - if (_config.WatchDirectory != newPath) - { - _config.WatchDirectory = newPath; - _config.Save(); - } - - if (_fsw is null) - return; - - _fsw.EnableRaisingEvents = false; - if (!Directory.Exists(newPath) || newPath.Length is 0) - { - _fsw.Path = string.Empty; - } - else - { - _fsw.Path = newPath; - _fsw.EnableRaisingEvents = true; - } - } - - private void OnPath(object? sender, FileSystemEventArgs e) - => _pending.TryAdd(e.FullPath, 0); - - private async Task ConsumerLoopAsync(CancellationToken token) - { - while (true) - { - var (path, _) = _pending.FirstOrDefault(); - if (path is null || _pausedConsumer) - { - await Task.Delay(500, token).ConfigureAwait(false); - continue; - } - - try - { - await ProcessOneAsync(path, token).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - Penumbra.Log.Debug("[FileWatcher] Canceled via Token."); - } - catch (Exception ex) - { - Penumbra.Log.Warning($"[FileWatcher] Error during Processing: {ex}"); - } - finally - { - _pending.TryRemove(path, out _); - } - } - } - - private async Task ProcessOneAsync(string path, CancellationToken token) - { - // Downloads often finish via rename; file may be locked briefly. - // Wait until it exists and is readable; also require two stable size checks. - const int maxTries = 40; - long lastLen = -1; - - for (var i = 0; i < maxTries && !token.IsCancellationRequested; i++) - { - if (!File.Exists(path)) - { - await Task.Delay(100, token); - continue; - } - - try - { - var fi = new FileInfo(path); - var len = fi.Length; - if (len > 0 && len == lastLen) - { - if (_config.EnableAutomaticModImport) - _modImportManager.AddUnpack(path); - else - _messageService.AddMessage(new InstallNotification(_modImportManager, path), false); - return; - } - - lastLen = len; - } - catch (IOException) - { - Penumbra.Log.Debug($"[FileWatcher] File is still being written to."); - } - catch (UnauthorizedAccessException) - { - Penumbra.Log.Debug($"[FileWatcher] File is locked."); - } - - await Task.Delay(150, token); - } - } - - - public void Dispose() - { - EndConsumerTask(); - EndFileWatcher(); - } -} diff --git a/Penumbra/Services/InstallNotification.cs b/Penumbra/Services/InstallNotification.cs deleted file mode 100644 index e3956076..00000000 --- a/Penumbra/Services/InstallNotification.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Dalamud.Bindings.ImGui; -using Dalamud.Interface.ImGuiNotification; -using Dalamud.Interface.ImGuiNotification.EventArgs; -using OtterGui.Text; -using Penumbra.Mods.Manager; - -namespace Penumbra.Services; - -public class InstallNotification(ModImportManager modImportManager, string filePath) : OtterGui.Classes.MessageService.IMessage -{ - public string Message - => "A new mod has been found!"; - - public NotificationType NotificationType - => NotificationType.Info; - - public uint NotificationDuration - => uint.MaxValue; - - public string NotificationTitle { get; } = Path.GetFileNameWithoutExtension(filePath); - - public string LogMessage - => $"A new mod has been found: {Path.GetFileName(filePath)}"; - - public void OnNotificationActions(INotificationDrawArgs args) - { - var region = ImGui.GetContentRegionAvail(); - var buttonSize = new Vector2((region.X - ImGui.GetStyle().ItemSpacing.X) / 2, 0); - if (ImUtf8.ButtonEx("Install"u8, ""u8, buttonSize)) - { - modImportManager.AddUnpack(filePath); - args.Notification.DismissNow(); - } - - ImGui.SameLine(); - if (ImUtf8.ButtonEx("Ignore"u8, ""u8, buttonSize)) - args.Notification.DismissNow(); - } -} diff --git a/Penumbra/Services/PcpService.cs b/Penumbra/Services/PcpService.cs deleted file mode 100644 index 17646564..00000000 --- a/Penumbra/Services/PcpService.cs +++ /dev/null @@ -1,308 +0,0 @@ -using Dalamud.Game.ClientState.Objects.Types; -using FFXIVClientStructs.FFXIV.Client.Game.Object; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using OtterGui.Classes; -using OtterGui.Services; -using Penumbra.Collections; -using Penumbra.Collections.Manager; -using Penumbra.Communication; -using Penumbra.GameData.Actors; -using Penumbra.GameData.Interop; -using Penumbra.GameData.Structs; -using Penumbra.Interop.PathResolving; -using Penumbra.Interop.ResourceTree; -using Penumbra.Meta.Manipulations; -using Penumbra.Mods; -using Penumbra.Mods.Groups; -using Penumbra.Mods.Manager; -using Penumbra.Mods.SubMods; -using Penumbra.String.Classes; - -namespace Penumbra.Services; - -public class PcpService : IApiService, IDisposable -{ - public const string Extension = ".pcp"; - - private readonly Configuration _config; - private readonly SaveService _files; - private readonly ResourceTreeFactory _treeFactory; - private readonly ObjectManager _objectManager; - private readonly ActorManager _actors; - private readonly FrameworkManager _framework; - private readonly CollectionResolver _collectionResolver; - private readonly CollectionManager _collections; - private readonly ModCreator _modCreator; - private readonly ModExportManager _modExport; - private readonly CommunicatorService _communicator; - private readonly SHA1 _sha1 = SHA1.Create(); - private readonly ModFileSystem _fileSystem; - private readonly ModManager _mods; - - public PcpService(Configuration config, - SaveService files, - ResourceTreeFactory treeFactory, - ObjectManager objectManager, - ActorManager actors, - FrameworkManager framework, - CollectionManager collections, - CollectionResolver collectionResolver, - ModCreator modCreator, - ModExportManager modExport, - CommunicatorService communicator, - ModFileSystem fileSystem, - ModManager mods) - { - _config = config; - _files = files; - _treeFactory = treeFactory; - _objectManager = objectManager; - _actors = actors; - _framework = framework; - _collectionResolver = collectionResolver; - _collections = collections; - _modCreator = modCreator; - _modExport = modExport; - _communicator = communicator; - _fileSystem = fileSystem; - _mods = mods; - - _communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.PcpService); - } - - public void CleanPcpMods() - { - var mods = _mods.Where(m => m.ModTags.Contains("PCP")).ToList(); - Penumbra.Log.Information($"[PCPService] Deleting {mods.Count} mods containing the tag PCP."); - foreach (var mod in mods) - _mods.DeleteMod(mod); - } - - public void CleanPcpCollections() - { - var collections = _collections.Storage.Where(c => c.Identity.Name.StartsWith("PCP/")).ToList(); - Penumbra.Log.Information($"[PCPService] Deleting {collections.Count} collections starting with PCP/."); - foreach (var collection in collections) - _collections.Storage.RemoveCollection(collection); - } - - private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, DirectoryInfo? newDirectory) - { - if (type is not ModPathChangeType.Added || _config.PcpSettings.DisableHandling || newDirectory is null) - return; - - try - { - var file = Path.Combine(newDirectory.FullName, "character.json"); - if (!File.Exists(file)) - { - // First version had collection.json, changed. - var oldFile = Path.Combine(newDirectory.FullName, "collection.json"); - if (File.Exists(oldFile)) - { - Penumbra.Log.Information("[PCPService] Renaming old PCP file from collection.json to character.json."); - File.Move(oldFile, file, true); - } - else - return; - } - - Penumbra.Log.Information($"[PCPService] Found a PCP file for {mod.Name}, applying."); - var text = File.ReadAllText(file); - var jObj = JObject.Parse(text); - var collection = ModCollection.Empty; - // Create collection. - if (_config.PcpSettings.CreateCollection) - { - var identifier = _actors.FromJson(jObj["Actor"] as JObject); - if (identifier.IsValid && jObj["Collection"]?.ToObject() is { } collectionName) - { - var name = $"PCP/{collectionName}"; - if (_collections.Storage.AddCollection(name, null)) - { - collection = _collections.Storage[^1]; - _collections.Editor.SetModState(collection, mod, true); - - // Assign collection. - if (_config.PcpSettings.AssignCollection) - { - var identifierGroup = _collections.Active.Individuals.GetGroup(identifier); - _collections.Active.SetCollection(collection, CollectionType.Individual, identifierGroup); - } - } - } - } - - // Move to folder. - if (_fileSystem.TryGetValue(mod, out var leaf)) - { - try - { - var folder = _fileSystem.FindOrCreateAllFolders(_config.PcpSettings.FolderName); - _fileSystem.Move(leaf, folder); - } - catch - { - // ignored. - } - } - - // Invoke IPC. - if (_config.PcpSettings.AllowIpc) - _communicator.PcpParsing.Invoke(jObj, mod.Identifier, collection.Identity.Id); - } - catch (Exception ex) - { - Penumbra.Log.Error($"Error reading the character.json file from {mod.Identifier}:\n{ex}"); - } - } - - public void Dispose() - => _communicator.ModPathChanged.Unsubscribe(OnModPathChange); - - public async Task<(bool, string)> CreatePcp(ObjectIndex objectIndex, string note = "", CancellationToken cancel = default) - { - try - { - Penumbra.Log.Information($"[PCPService] Creating PCP file for game object {objectIndex.Index}."); - var (identifier, tree, meta) = await _framework.Framework.RunOnFrameworkThread(() => - { - var (actor, identifier) = CheckActor(objectIndex); - cancel.ThrowIfCancellationRequested(); - unsafe - { - var collection = _collectionResolver.IdentifyCollection((GameObject*)actor.Address, true); - if (!collection.Valid || !collection.ModCollection.HasCache) - throw new Exception($"Actor {identifier} has no mods applying, nothing to do."); - - cancel.ThrowIfCancellationRequested(); - if (_treeFactory.FromCharacter(actor, 0) is not { } tree) - throw new Exception($"Unable to fetch modded resources for {identifier}."); - - var meta = new MetaDictionary(collection.ModCollection.MetaCache, actor.Address); - return (identifier.CreatePermanent(), tree, meta); - } - }); - cancel.ThrowIfCancellationRequested(); - var time = DateTime.Now; - var modDirectory = CreateMod(identifier, note, time); - await CreateDefaultMod(modDirectory, meta, tree, cancel); - await CreateCollectionInfo(modDirectory, objectIndex, identifier, note, time, cancel); - var file = ZipUp(modDirectory); - return (true, file); - } - catch (Exception ex) - { - return (false, ex.Message); - } - } - - private static string ZipUp(DirectoryInfo directory) - { - var fileName = directory.FullName + Extension; - ZipFile.CreateFromDirectory(directory.FullName, fileName, CompressionLevel.Optimal, false); - directory.Delete(true); - return fileName; - } - - private async Task CreateCollectionInfo(DirectoryInfo directory, ObjectIndex index, ActorIdentifier actor, string note, DateTime time, - CancellationToken cancel = default) - { - var jObj = new JObject - { - ["Version"] = 1, - ["Actor"] = actor.ToJson(), - ["Mod"] = directory.Name, - ["Collection"] = note.Length > 0 ? $"{actor.ToName()}: {note}" : actor.ToName(), - ["Time"] = time, - ["Note"] = note, - }; - if (note.Length > 0) - cancel.ThrowIfCancellationRequested(); - if (_config.PcpSettings.AllowIpc) - await _framework.Framework.RunOnFrameworkThread(() => _communicator.PcpCreation.Invoke(jObj, index.Index, directory.FullName)); - var filePath = Path.Combine(directory.FullName, "character.json"); - await using var file = File.Open(filePath, File.Exists(filePath) ? FileMode.Truncate : FileMode.CreateNew); - await using var stream = new StreamWriter(file); - await using var json = new JsonTextWriter(stream); - json.Formatting = Formatting.Indented; - await jObj.WriteToAsync(json, cancel); - } - - private DirectoryInfo CreateMod(ActorIdentifier actor, string note, DateTime time) - { - var directory = _modExport.ExportDirectory; - directory.Create(); - var actorName = actor.ToName(); - var authorName = _actors.GetCurrentPlayer().ToName(); - var suffix = note.Length > 0 - ? note - : time.ToString("yyyy-MM-ddTHH\\:mm", CultureInfo.InvariantCulture); - var modName = $"{actorName} - {suffix}"; - var description = $"On-Screen Data for {actorName} as snapshotted on {time}."; - return _modCreator.CreateEmptyMod(directory, modName, description, authorName, "PCP") - ?? throw new Exception($"Unable to create mod {modName} in {directory.FullName}."); - } - - private async Task CreateDefaultMod(DirectoryInfo modDirectory, MetaDictionary meta, ResourceTree tree, - CancellationToken cancel = default) - { - var subDirectory = modDirectory.CreateSubdirectory("files"); - var subMod = new DefaultSubMod(null!) - { - Manipulations = meta, - }; - - foreach (var node in tree.FlatNodes) - { - cancel.ThrowIfCancellationRequested(); - var gamePath = node.GamePath; - var fullPath = node.FullPath; - if (fullPath.IsRooted) - { - var hash = await _sha1.ComputeHashAsync(File.OpenRead(fullPath.FullName), cancel).ConfigureAwait(false); - cancel.ThrowIfCancellationRequested(); - var name = Convert.ToHexString(hash) + fullPath.Extension; - var newFile = Path.Combine(subDirectory.FullName, name); - if (!File.Exists(newFile)) - File.Copy(fullPath.FullName, newFile); - subMod.Files.TryAdd(gamePath, new FullPath(newFile)); - } - else if (gamePath.Path != fullPath.InternalName) - { - subMod.FileSwaps.TryAdd(gamePath, fullPath); - } - } - - cancel.ThrowIfCancellationRequested(); - - var saveGroup = new ModSaveGroup(modDirectory, subMod, _config.ReplaceNonAsciiOnImport); - var filePath = _files.FileNames.OptionGroupFile(modDirectory.FullName, -1, string.Empty, _config.ReplaceNonAsciiOnImport); - cancel.ThrowIfCancellationRequested(); - await using var fileStream = File.Open(filePath, File.Exists(filePath) ? FileMode.Truncate : FileMode.CreateNew); - await using var writer = new StreamWriter(fileStream); - saveGroup.Save(writer); - } - - private (ICharacter Actor, ActorIdentifier Identifier) CheckActor(ObjectIndex objectIndex) - { - var actor = _objectManager[objectIndex]; - if (!actor.Valid) - throw new Exception($"No Actor at index {objectIndex} found."); - - if (!actor.Identifier(_actors, out var identifier)) - throw new Exception($"Could not create valid identifier for actor at index {objectIndex}."); - - if (!actor.IsCharacter) - throw new Exception($"Actor {identifier} at index {objectIndex} is not a valid character."); - - if (!actor.Model.Valid) - throw new Exception($"Actor {identifier} at index {objectIndex} has no model."); - - if (_objectManager.Objects.CreateObjectReference(actor.Address) is not ICharacter character) - throw new Exception($"Actor {identifier} at index {objectIndex} could not be converted to ICharacter"); - - return (character, identifier); - } -} diff --git a/Penumbra/Services/StainService.cs b/Penumbra/Services/StainService.cs index 17294aa8..b16d4dcd 100644 --- a/Penumbra/Services/StainService.cs +++ b/Penumbra/Services/StainService.cs @@ -1,7 +1,7 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Services; +using ImGuiNET; using OtterGui.Services; using OtterGui.Widgets; using Penumbra.GameData.DataContainers; diff --git a/Penumbra/UI/AdvancedWindow/FileEditor.cs b/Penumbra/UI/AdvancedWindow/FileEditor.cs index 424bc56f..c783e17f 100644 --- a/Penumbra/UI/AdvancedWindow/FileEditor.cs +++ b/Penumbra/UI/AdvancedWindow/FileEditor.cs @@ -1,14 +1,13 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Compression; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; -using Penumbra.GameData.Data; using Penumbra.GameData.Files; using Penumbra.Mods.Editor; using Penumbra.Services; @@ -81,7 +80,7 @@ public class FileEditor( private Exception? _currentException; private bool _changed; - private string _defaultPath = typeof(T) == typeof(ModEditWindow.PbdTab) ? GamePaths.Pbd.Path : string.Empty; + private string _defaultPath = string.Empty; private bool _inInput; private Utf8GamePath _defaultPathUtf8; private bool _isDefaultPathUtf8Valid; diff --git a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs index e9d76990..f5d2a8c7 100644 --- a/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs +++ b/Penumbra/UI/AdvancedWindow/ItemSwapTab.cs @@ -1,5 +1,5 @@ using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs b/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs index 24a5f9c2..5c636b1d 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MaterialTemplatePickers.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using FFXIVClientStructs.Interop; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; @@ -131,7 +131,7 @@ public sealed unsafe class MaterialTemplatePickers : IUiService if (texture == null) continue; var handle = _textureArraySlicer.GetImGuiHandle(texture, sliceIndex); - if (handle.IsNull) + if (handle == 0) continue; var position = regionStart with { X = regionStart.X + (itemSize.X + itemSpacing) * j }; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs index fad9adeb..0c987972 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ColorTable.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs index 9ea9c2e0..d70a4b50 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.CommonColorTable.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility; +using ImGuiNET; using Penumbra.GameData.Files.MaterialStructs; using Penumbra.GameData.Files; using OtterGui.Text; @@ -338,10 +338,10 @@ public partial class MtrlTab var tmp = inputSqrt; if (ImUtf8.ColorEdit(label, ref tmp, ImGuiColorEditFlags.NoInputs - | ImGuiColorEditFlags.DisplayRgb - | ImGuiColorEditFlags.InputRgb + | ImGuiColorEditFlags.DisplayRGB + | ImGuiColorEditFlags.InputRGB | ImGuiColorEditFlags.NoTooltip - | ImGuiColorEditFlags.Hdr) + | ImGuiColorEditFlags.HDR) && tmp != inputSqrt) { setter((HalfColor)PseudoSquareRgb(tmp)); @@ -373,10 +373,10 @@ public partial class MtrlTab var tmp = Vector4.Zero; ImUtf8.ColorEdit(label, ref tmp, ImGuiColorEditFlags.NoInputs - | ImGuiColorEditFlags.DisplayRgb - | ImGuiColorEditFlags.InputRgb + | ImGuiColorEditFlags.DisplayRGB + | ImGuiColorEditFlags.InputRGB | ImGuiColorEditFlags.NoTooltip - | ImGuiColorEditFlags.Hdr + | ImGuiColorEditFlags.HDR | ImGuiColorEditFlags.AlphaPreview); if (letter.Length > 0 && ImGui.IsItemVisible()) @@ -594,7 +594,7 @@ public partial class MtrlTab internal static float PseudoSqrtRgb(float x) => x < 0.0f ? -MathF.Sqrt(-x) : MathF.Sqrt(x); - public static Vector3 PseudoSqrtRgb(Vector3 vec) + internal static Vector3 PseudoSqrtRgb(Vector3 vec) => new(PseudoSqrtRgb(vec.X), PseudoSqrtRgb(vec.Y), PseudoSqrtRgb(vec.Z)); internal static Vector4 PseudoSqrtRgb(Vector4 vec) diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs index 4ad6968b..f413a6a2 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Constants.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Extensions; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs index e75cd633..0ffdd1cc 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LegacyColorTable.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Text; using Penumbra.GameData.Files.MaterialStructs; @@ -67,7 +67,7 @@ public partial class MtrlTab private static void DrawLegacyColorTableHeader(bool hasDyeTable) { ImGui.TableNextColumn(); - ImUtf8.TableHeader(""u8); + ImUtf8.TableHeader(default(ReadOnlySpan)); ImGui.TableNextColumn(); ImUtf8.TableHeader("Row"u8); ImGui.TableNextColumn(); diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs index dfa3a963..5025bafd 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.LivePreview.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Text; using Penumbra.GameData.Files.MaterialStructs; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs index 43040ca3..ee5341b2 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.ShaderPackage.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui; using OtterGui.Classes; @@ -384,7 +384,7 @@ public partial class MtrlTab var shpkFlags = (int)Mtrl.ShaderPackage.Flags; ImGui.SetNextItemWidth(UiHelpers.Scale * 250.0f); if (!ImGui.InputInt("Shader Flags", ref shpkFlags, 0, 0, - flags: ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None))) + ImGuiInputTextFlags.CharsHexadecimal | (disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None))) return false; Mtrl.ShaderPackage.Flags = (uint)shpkFlags; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs index 82ba7be4..ac88f77c 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.Textures.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs index 2c7c889e..97acf130 100644 --- a/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs +++ b/Penumbra/UI/AdvancedWindow/Materials/MtrlTab.cs @@ -1,6 +1,5 @@ -using Dalamud.Interface.Components; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Text; @@ -120,22 +119,11 @@ public sealed partial class MtrlTab : IWritable, IDisposable using var dis = ImRaii.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)) + if (ImUtf8.Checkbox("Enable Transparency"u8, ref tmp)) { - if (ImUtf8.Checkbox("Enable Transparency"u8, ref tmp)) - { - shaderFlags.EnableTransparency = tmp; - ret = true; - SetShaderPackageFlags(Mtrl.ShaderPackage.Flags); - } - } - - if (disallowTransparency) - { - ImGuiComponents.HelpMarker("Enabling transparency for shader package characterstockings.shpk will crash the game."); + shaderFlags.EnableTransparency = tmp; + ret = true; + SetShaderPackageFlags(Mtrl.ShaderPackage.Flags); } ImGui.SameLine(200 * UiHelpers.Scale + ImGui.GetStyle().ItemSpacing.X + ImGui.GetStyle().WindowPadding.X); @@ -216,7 +204,7 @@ public sealed partial class MtrlTab : IWritable, IDisposable } public bool Valid - => Mtrl.Valid; // FIXME This should be _shadersKnown && Mtrl.Valid but the algorithm for _shadersKnown is flawed as of 7.2. + => _shadersKnown && Mtrl.Valid; public byte[] Write() { diff --git a/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs index 4a74cda5..5b6d585a 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/AtchMetaDrawer.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs index 4b375c26..89fadfa8 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/AtrMetaDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs index 16af5217..348a0d4c 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/EqdpMetaDrawer.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs index 77c2915a..d6df95cb 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/EqpMetaDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs index 84e09be5..e5e28a3d 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/EstMetaDrawer.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs index b03f4aa5..929feadd 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/GlobalEqpMetaDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs index 4053560b..3691a4f7 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/GmpMetaDrawer.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.GameData.Structs; diff --git a/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs index bb87cd47..34488a87 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/ImcMetaDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs index f608a194..7e788462 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/MetaDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs index 88abe0cb..d60f877b 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/RspMetaDrawer.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs b/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs index 59692195..35c8ccec 100644 --- a/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs +++ b/Penumbra/UI/AdvancedWindow/Meta/ShpMetaDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Newtonsoft.Json.Linq; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs index 4f7ae8da..36154105 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Deformers.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.Utility.Raii; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs index 63c99b8a..3f63967e 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Files.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Extensions; @@ -287,17 +287,6 @@ public partial class ModEditWindow using var font = ImRaii.PushFont(UiBuilder.IconFont); ImGuiUtil.TextColored(0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString()); } - else if (tmp.Length > 0 && Path.GetExtension(tmp) != registry.File.Extension) - { - ImGui.SameLine(); - ImGui.SetCursorPosX(pos); - using (var font = ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); - } - - ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8); - } } private void PrintNewGamePath(int i, FileRegistry registry, IModDataContainer subMod) @@ -330,17 +319,6 @@ public partial class ModEditWindow using var font = ImRaii.PushFont(UiBuilder.IconFont); ImGuiUtil.TextColored(0xFF0000FF, FontAwesomeIcon.TimesCircle.ToIconString()); } - else if (tmp.Length > 0 && Path.GetExtension(tmp) != registry.File.Extension) - { - ImGui.SameLine(); - ImGui.SetCursorPosX(pos); - using (var font = ImRaii.PushFont(UiBuilder.IconFont)) - { - ImGuiUtil.TextColored(0xFF00B0B0, FontAwesomeIcon.ExclamationCircle.ToIconString()); - } - - ImUtf8.HoverTooltip("The game path and the file do not have the same extension."u8); - } } private void DrawButtonHeader() diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs index 3caff226..4c946fe7 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.Utility; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Extensions; using OtterGui.Raii; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs index 06cd0763..aa3d9172 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Text; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs index a7db7f25..cc592296 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using ImGuiNET; using Lumina.Data.Parsing; using OtterGui; using OtterGui.Custom; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.QuickImport.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.QuickImport.cs index f55ae576..00caaabc 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.QuickImport.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.QuickImport.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Lumina.Data; using OtterGui.Text; using Penumbra.Api.Enums; @@ -17,6 +17,7 @@ public partial class ModEditWindow private readonly FileDialogService _fileDialog; private readonly ResourceTreeFactory _resourceTreeFactory; private readonly ResourceTreeViewer _quickImportViewer; + private readonly Dictionary _quickImportWritables = new(); private readonly Dictionary<(Utf8GamePath, IWritable?), QuickImportAction> _quickImportActions = new(); private HashSet GetPlayerResourcesOfType(ResourceType type) @@ -55,11 +56,52 @@ public partial class ModEditWindow private void OnQuickImportRefresh() { + _quickImportWritables.Clear(); _quickImportActions.Clear(); } - private void DrawQuickImportActions(ResourceNode resourceNode, IWritable? writable, Vector2 buttonSize) + private void DrawQuickImportActions(ResourceNode resourceNode, Vector2 buttonSize) { + if (!_quickImportWritables!.TryGetValue(resourceNode.FullPath, out var writable)) + { + var path = resourceNode.FullPath.ToPath(); + if (resourceNode.FullPath.IsRooted) + { + writable = new RawFileWritable(path); + } + else + { + var file = _gameData.GetFile(path); + writable = file is null ? null : new RawGameFileWritable(file); + } + + _quickImportWritables.Add(resourceNode.FullPath, writable); + } + + if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Export this file."u8, buttonSize, + resourceNode.FullPath.FullName.Length is 0 || writable is null)) + { + var fullPathStr = resourceNode.FullPath.FullName; + var ext = resourceNode.PossibleGamePaths.Length == 1 + ? Path.GetExtension(resourceNode.GamePath.ToString()) + : Path.GetExtension(fullPathStr); + _fileDialog.OpenSavePicker($"Export {Path.GetFileName(fullPathStr)} to...", ext, Path.GetFileNameWithoutExtension(fullPathStr), ext, + (success, name) => + { + if (!success) + return; + + try + { + _editor.Compactor.WriteAllBytes(name, writable!.Write()); + } + catch (Exception e) + { + Penumbra.Log.Error($"Could not export {fullPathStr}:\n{e}"); + } + }, null, false); + } + ImGui.SameLine(); if (!_quickImportActions!.TryGetValue((resourceNode.GamePath, writable), out var quickImport)) { @@ -79,6 +121,24 @@ public partial class ModEditWindow } } + private record RawFileWritable(string Path) : IWritable + { + public bool Valid + => true; + + public byte[] Write() + => File.ReadAllBytes(Path); + } + + private record RawGameFileWritable(FileResource FileResource) : IWritable + { + public bool Valid + => true; + + public byte[] Write() + => FileResource.Data; + } + public class QuickImportAction { public const string FallbackOptionName = "the current option"; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs index baaf4a82..a6a75e0d 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.ShaderPackages.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui; using OtterGui.Classes; @@ -147,7 +147,7 @@ public partial class ModEditWindow using var font = ImRaii.PushFont(UiBuilder.MonoFont); var size = new Vector2(ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight() * 20); - ImGuiNative.InputTextMultiline(DisassemblyLabel.Path, shader.Disassembly!.RawDisassembly.Path, + ImGuiNative.igInputTextMultiline(DisassemblyLabel.Path, shader.Disassembly!.RawDisassembly.Path, (uint)shader.Disassembly!.RawDisassembly.Length + 1, size, ImGuiInputTextFlags.ReadOnly, null, null); } diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs index 34e1e0d4..ee4e1eda 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Textures.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index 5a0fb849..e148167b 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -4,7 +4,7 @@ using Dalamud.Interface.DragDrop; using Dalamud.Interface.Utility; using Dalamud.Interface.Windowing; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Log; @@ -667,7 +667,7 @@ public partial class ModEditWindow : Window, IDisposable, IUiService _center = new CombinedTexture(_left, _right); _textureSelectCombo = new TextureDrawer.PathSelectCombo(textures, editor, () => GetPlayerResourcesOfType(ResourceType.Tex)); _resourceTreeFactory = resourceTreeFactory; - _quickImportViewer = resourceTreeViewerFactory.Create(1, OnQuickImportRefresh, DrawQuickImportActions); + _quickImportViewer = resourceTreeViewerFactory.Create(2, OnQuickImportRefresh, DrawQuickImportActions); _communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModEditWindow); IsOpen = _config is { OpenWindowAtStart: true, Ephemeral.AdvancedEditingOpen: true }; if (IsOpen && selection.Mod != null) diff --git a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs index bf16fa37..3c110fab 100644 --- a/Penumbra/UI/AdvancedWindow/ModMergeTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModMergeTab.cs @@ -1,5 +1,5 @@ using Dalamud.Interface.Utility; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs b/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs index c9996a1e..1fa12b6d 100644 --- a/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs +++ b/Penumbra/UI/AdvancedWindow/OptionSelectCombo.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Text; using OtterGui.Widgets; diff --git a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs index ae450bec..4d33a3fc 100644 --- a/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs +++ b/Penumbra/UI/AdvancedWindow/ResourceTreeViewer.cs @@ -1,24 +1,15 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; -using Dalamud.Interface.Colors; -using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.Utility; -using Dalamud.Plugin.Services; -using Lumina.Data; -using OtterGui; -using OtterGui.Classes; -using OtterGui.Compression; -using OtterGui.Extensions; +using ImGuiNET; using OtterGui.Raii; +using OtterGui; using OtterGui.Text; using Penumbra.Api.Enums; -using Penumbra.GameData.Files; -using Penumbra.GameData.Structs; using Penumbra.Interop.ResourceTree; using Penumbra.Services; -using Penumbra.String; -using Penumbra.String.Classes; using Penumbra.UI.Classes; +using Penumbra.String; +using OtterGui.Extensions; namespace Penumbra.UI.AdvancedWindow; @@ -29,32 +20,25 @@ public class ResourceTreeViewer( IncognitoService incognito, int actionCapacity, Action onRefresh, - Action drawActions, - CommunicatorService communicator, - PcpService pcpService, - IDataManager gameData, - FileDialogService fileDialog, - FileCompactor compactor) + Action drawActions, + CommunicatorService communicator) { private const ResourceTreeFactory.Flags ResourceTreeFactoryFlags = - ResourceTreeFactory.Flags.WithUiData | ResourceTreeFactory.Flags.WithOwnership; + ResourceTreeFactory.Flags.RedactExternalPaths | ResourceTreeFactory.Flags.WithUiData | ResourceTreeFactory.Flags.WithOwnership; - private readonly HashSet _unfolded = []; + private readonly HashSet _unfolded = []; - private readonly Dictionary _filterCache = []; - private readonly Dictionary _writableCache = []; + private readonly Dictionary _filterCache = []; private TreeCategory _categoryFilter = AllCategories; private ChangedItemIconFlag _typeFilter = ChangedItemFlagExtensions.AllFlags; private string _nameFilter = string.Empty; private string _nodeFilter = string.Empty; - private string _note = string.Empty; private Task? _task; public void Draw() { - DrawModifiedGameFilesWarning(); DrawControls(); _task ??= RefreshCharacterList(); @@ -99,30 +83,9 @@ public class ResourceTreeViewer( using var id = ImRaii.PushId(index); - ImUtf8.TextFrameAligned($"Collection: {(incognito.IncognitoMode ? tree.AnonymizedCollectionName : tree.CollectionName)}"); - ImGui.SameLine(); - if (ImUtf8.ButtonEx("Export Character Pack"u8, - "Note that this recomputes the current data of the actor if it still exists, and does not use the cached data."u8)) - { - pcpService.CreatePcp((ObjectIndex)tree.GameObjectIndex, _note).ContinueWith(t => - { + ImGui.TextUnformatted($"Collection: {(incognito.IncognitoMode ? tree.AnonymizedCollectionName : tree.CollectionName)}"); - var (success, text) = t.Result; - - if (success) - Penumbra.Messager.NotificationMessage($"Created {text}.", NotificationType.Success, false); - else - Penumbra.Messager.NotificationMessage(text, NotificationType.Error, false); - }); - _note = string.Empty; - } - - ImUtf8.SameLineInner(); - ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); - ImUtf8.InputText("##note"u8, ref _note, "Export note..."u8); - - - using var table = ImRaii.Table("##ResourceTree", 4, + using var table = ImRaii.Table("##ResourceTree", actionCapacity > 0 ? 4 : 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); if (!table) continue; @@ -130,8 +93,9 @@ public class ResourceTreeViewer( ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthStretch, 0.2f); ImGui.TableSetupColumn("Game Path", ImGuiTableColumnFlags.WidthStretch, 0.3f); ImGui.TableSetupColumn("Actual Path", ImGuiTableColumnFlags.WidthStretch, 0.5f); - ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, - actionCapacity * 3 * ImGuiHelpers.GlobalScale + (actionCapacity + 1) * ImGui.GetFrameHeight()); + if (actionCapacity > 0) + ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, + (actionCapacity - 1) * 3 * ImGuiHelpers.GlobalScale + actionCapacity * ImGui.GetFrameHeight()); ImGui.TableHeadersRow(); DrawNodes(tree.Nodes, 0, unchecked(tree.DrawObjectAddress * 31), 0); @@ -139,24 +103,6 @@ public class ResourceTreeViewer( } } - private void DrawModifiedGameFilesWarning() - { - if (!gameData.HasModifiedGameDataFiles) - return; - - using var style = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudOrange); - - ImUtf8.TextWrapped( - "Dalamud is reporting your FFXIV installation has modified game files. Any mods installed through TexTools will produce this message."u8); - ImUtf8.TextWrapped("Penumbra and some other plugins assume your FFXIV installation is unmodified in order to work."u8); - ImUtf8.TextWrapped( - "Data displayed here may be inaccurate because of this, which, in turn, can break functionality relying on it, such as Character Pack exports/imports, or mod synchronization functions provided by other plugins."u8); - ImUtf8.TextWrapped( - "Exit the game, open XIVLauncher, click the arrow next to Log In and select \"repair game files\" to resolve this issue. Afterwards, do not install any mods with TexTools. Your plugin configurations will remain, as will mods enabled in Penumbra."u8); - - ImGui.Separator(); - } - private void DrawControls() { var yOffset = (ChangedItemDrawer.TypeFilterIconSize.Y - ImGui.GetFrameHeight()) / 2f; @@ -217,7 +163,6 @@ public class ResourceTreeViewer( finally { _filterCache.Clear(); - _writableCache.Clear(); _unfolded.Clear(); onRefresh(); } @@ -228,6 +173,7 @@ public class ResourceTreeViewer( { var debugMode = config.DebugMode; var frameHeight = ImGui.GetFrameHeight(); + var cellHeight = actionCapacity > 0 ? frameHeight : 0.0f; foreach (var (resourceNode, index) in resourceNodes.WithIndex()) { @@ -297,7 +243,7 @@ public class ResourceTreeViewer( 0 => "(none)", 1 => resourceNode.GamePath.ToString(), _ => "(multiple)", - }, false, hasGamePaths ? 0 : ImGuiSelectableFlags.Disabled, new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + }, false, hasGamePaths ? 0 : ImGuiSelectableFlags.Disabled, new Vector2(ImGui.GetContentRegionAvail().X, cellHeight)); if (hasGamePaths) { var allPaths = string.Join('\n', resourceNode.PossibleGamePaths); @@ -317,30 +263,16 @@ public class ResourceTreeViewer( using var group = ImUtf8.Group(); using (var color = ImRaii.PushColor(ImGuiCol.Text, (hasMod ? ColorId.NewMod : ColorId.DisabledMod).Value())) { - ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap, new Vector2(ImGui.GetContentRegionAvail().X, cellHeight)); } ImGui.SameLine(); ImGui.SetCursorPosX(textPos); ImUtf8.Text(resourceNode.ModRelativePath); } - else if (resourceNode.FullPath.IsRooted) - { - var path = resourceNode.FullPath.FullName; - var lastDirectorySeparator = path.LastIndexOf('\\'); - var secondLastDirectorySeparator = lastDirectorySeparator > 0 - ? path.LastIndexOf('\\', lastDirectorySeparator - 1) - : -1; - if (secondLastDirectorySeparator >= 0) - path = $"…{path.AsSpan(secondLastDirectorySeparator)}"; - ImGui.Selectable(path.AsSpan(), false, ImGuiSelectableFlags.AllowItemOverlap, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); - } else { - ImGui.Selectable(resourceNode.FullPath.ToPath(), false, ImGuiSelectableFlags.AllowItemOverlap, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + ImGui.Selectable(resourceNode.FullPath.ToPath(), false, ImGuiSelectableFlags.AllowItemOverlap, new Vector2(ImGui.GetContentRegionAvail().X, cellHeight)); } if (ImGui.IsItemClicked()) @@ -354,17 +286,20 @@ public class ResourceTreeViewer( else { ImUtf8.Selectable(GetPathStatusLabel(resourceNode.FullPathStatus), false, ImGuiSelectableFlags.Disabled, - new Vector2(ImGui.GetContentRegionAvail().X, frameHeight)); + new Vector2(ImGui.GetContentRegionAvail().X, cellHeight)); ImGuiUtil.HoverTooltip( $"{GetPathStatusDescription(resourceNode.FullPathStatus)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}"); } mutedColor.Dispose(); - ImGui.TableNextColumn(); - using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, - ImGui.GetStyle().ItemSpacing with { X = 3 * ImGuiHelpers.GlobalScale }); - DrawActions(resourceNode, new Vector2(frameHeight)); + if (actionCapacity > 0) + { + ImGui.TableNextColumn(); + using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, + ImGui.GetStyle().ItemSpacing with { X = 3 * ImGuiHelpers.GlobalScale }); + drawActions(resourceNode, new Vector2(frameHeight)); + } if (unfolded) DrawNodes(resourceNode.Children, level + 1, unchecked(nodePathHash * 31), filterIcon); @@ -417,51 +352,6 @@ public class ResourceTreeViewer( || node.FullPath.InternalName.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase) || Array.Exists(node.PossibleGamePaths, path => path.Path.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase)); } - - void DrawActions(ResourceNode resourceNode, Vector2 buttonSize) - { - if (!_writableCache!.TryGetValue(resourceNode.FullPath, out var writable)) - { - var path = resourceNode.FullPath.ToPath(); - if (resourceNode.FullPath.IsRooted) - { - writable = new RawFileWritable(path); - } - else - { - var file = gameData.GetFile(path); - writable = file is null ? null : new RawGameFileWritable(file); - } - - _writableCache.Add(resourceNode.FullPath, writable); - } - - if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Export this file."u8, buttonSize, - resourceNode.FullPath.FullName.Length is 0 || writable is null)) - { - var fullPathStr = resourceNode.FullPath.FullName; - var ext = resourceNode.PossibleGamePaths.Length == 1 - ? Path.GetExtension(resourceNode.GamePath.ToString()) - : Path.GetExtension(fullPathStr); - fileDialog.OpenSavePicker($"Export {Path.GetFileName(fullPathStr)} to...", ext, Path.GetFileNameWithoutExtension(fullPathStr), ext, - (success, name) => - { - if (!success) - return; - - try - { - compactor.WriteAllBytes(name, writable!.Write()); - } - catch (Exception e) - { - Penumbra.Log.Error($"Could not export {fullPathStr}:\n{e}"); - } - }, null, false); - } - - drawActions(resourceNode, writable, new Vector2(frameHeight)); - } } private static ReadOnlySpan GetPathStatusLabel(ResourceNode.PathStatus status) @@ -475,10 +365,9 @@ public class ResourceTreeViewer( private static string GetPathStatusDescription(ResourceNode.PathStatus status) => status switch { - ResourceNode.PathStatus.External => "The actual path to this file is unavailable, because it is managed by external tools.", - ResourceNode.PathStatus.NonExistent => - "The actual path to this file is unavailable, because it seems to have been moved or deleted since it was loaded.", - _ => "The actual path to this file is unavailable.", + ResourceNode.PathStatus.External => "The actual path to this file is unavailable, because it is managed by external tools.", + ResourceNode.PathStatus.NonExistent => "The actual path to this file is unavailable, because it seems to have been moved or deleted since it was loaded.", + _ => "The actual path to this file is unavailable.", }; [Flags] @@ -525,22 +414,4 @@ public class ResourceTreeViewer( Visible = 1, DescendentsOnly = 2, } - - private record RawFileWritable(string Path) : IWritable - { - public bool Valid - => true; - - public byte[] Write() - => File.ReadAllBytes(Path); - } - - private record RawGameFileWritable(FileResource FileResource) : IWritable - { - public bool Valid - => true; - - public byte[] Write() - => FileResource.Data; - } } diff --git a/Penumbra/UI/AdvancedWindow/ResourceTreeViewerFactory.cs b/Penumbra/UI/AdvancedWindow/ResourceTreeViewerFactory.cs index 6518ae67..10a4aea2 100644 --- a/Penumbra/UI/AdvancedWindow/ResourceTreeViewerFactory.cs +++ b/Penumbra/UI/AdvancedWindow/ResourceTreeViewerFactory.cs @@ -1,7 +1,4 @@ -using Dalamud.Plugin.Services; -using OtterGui.Compression; using OtterGui.Services; -using Penumbra.GameData.Files; using Penumbra.Interop.ResourceTree; using Penumbra.Services; @@ -12,13 +9,8 @@ public class ResourceTreeViewerFactory( ResourceTreeFactory treeFactory, ChangedItemDrawer changedItemDrawer, IncognitoService incognito, - CommunicatorService communicator, - PcpService pcpService, - IDataManager gameData, - FileDialogService fileDialog, - FileCompactor compactor) : IService + CommunicatorService communicator) : IService { - public ResourceTreeViewer Create(int actionCapacity, Action onRefresh, Action drawActions) - => new(config, treeFactory, changedItemDrawer, incognito, actionCapacity, onRefresh, drawActions, communicator, pcpService, gameData, - fileDialog, compactor); + public ResourceTreeViewer Create(int actionCapacity, Action onRefresh, Action drawActions) + => new(config, treeFactory, changedItemDrawer, incognito, actionCapacity, onRefresh, drawActions, communicator); } diff --git a/Penumbra/UI/ChangedItemDrawer.cs b/Penumbra/UI/ChangedItemDrawer.cs index db54a8e5..a9070360 100644 --- a/Penumbra/UI/ChangedItemDrawer.cs +++ b/Penumbra/UI/ChangedItemDrawer.cs @@ -3,7 +3,7 @@ using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Plugin.Services; using Dalamud.Utility; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Lumina.Data.Files; using OtterGui; using OtterGui.Classes; @@ -107,11 +107,11 @@ public class ChangedItemDrawer : IDisposable, IUiService return; } - ImGui.Image(icon.Handle, new Vector2(height)); + ImGui.Image(icon.ImGuiHandle, new Vector2(height)); if (ImGui.IsItemHovered()) { using var tt = ImRaii.Tooltip(); - ImGui.Image(icon.Handle, new Vector2(_smallestIconWidth)); + ImGui.Image(icon.ImGuiHandle, new Vector2(_smallestIconWidth)); ImGui.SameLine(); ImGuiUtil.DrawTextButton(iconFlagType.ToDescription(), new Vector2(0, _smallestIconWidth), 0); } @@ -193,7 +193,7 @@ public class ChangedItemDrawer : IDisposable, IUiService } ImGui.SetCursorPosX(ImGui.GetContentRegionMax().X - size.X); - ImGui.Image(_icons[ChangedItemFlagExtensions.AllFlags].Handle, size, Vector2.Zero, Vector2.One, + ImGui.Image(_icons[ChangedItemFlagExtensions.AllFlags].ImGuiHandle, size, Vector2.Zero, Vector2.One, typeFilter switch { 0 => new Vector4(0.6f, 0.3f, 0.3f, 1f), @@ -213,7 +213,7 @@ public class ChangedItemDrawer : IDisposable, IUiService var localRet = false; var icon = _icons[type]; var flag = typeFilter.HasFlag(type); - ImGui.Image(icon.Handle, size, Vector2.Zero, Vector2.One, flag ? Vector4.One : new Vector4(0.6f, 0.3f, 0.3f, 1f)); + ImGui.Image(icon.ImGuiHandle, size, Vector2.Zero, Vector2.One, flag ? Vector4.One : new Vector4(0.6f, 0.3f, 0.3f, 1f)); if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) { typeFilter = flag ? typeFilter & ~type : typeFilter | type; @@ -232,7 +232,7 @@ public class ChangedItemDrawer : IDisposable, IUiService if (ImGui.IsItemHovered()) { using var tt = ImRaii.Tooltip(); - ImGui.Image(icon.Handle, new Vector2(_smallestIconWidth)); + ImGui.Image(icon.ImGuiHandle, new Vector2(_smallestIconWidth)); ImGui.SameLine(); ImGuiUtil.DrawTextButton(type.ToDescription(), new Vector2(0, _smallestIconWidth), 0); } diff --git a/Penumbra/UI/Changelog.cs b/Penumbra/UI/Changelog.cs index 306dcc79..c1f7a1e6 100644 --- a/Penumbra/UI/Changelog.cs +++ b/Penumbra/UI/Changelog.cs @@ -62,55 +62,10 @@ public class PenumbraChangelog : IUiService Add1_3_6_0(Changelog); Add1_3_6_4(Changelog); Add1_4_0_0(Changelog); - Add1_5_0_0(Changelog); - Add1_5_1_0(Changelog); - } - + } + #region Changelogs - private static void Add1_5_1_0(Changelog log) - => log.NextVersion("Version 1.5.1.0") - .RegisterHighlight("Added the option to export a characters current data as a .pcp modpack in the On-Screen tab.") - .RegisterEntry("Other plugins can attach to this functionality and package and interpret their own data.", 1) - .RegisterEntry("When a .pcp modpack is installed, it can create and assign collections for the corresponding character it was created for.", 1) - .RegisterEntry("This basically provides an easier way to manually synchronize other players, but does not contain any automation.", 1) - .RegisterEntry("The settings provide some fine control about what happens when a PCP is installed, as well as buttons to cleanup any PCP-created data.", 1) - .RegisterEntry("Added a warning message when the game's integrity is corrupted to the On-Screen tab.") - .RegisterEntry("Added .kdb files to the On-Screen tab and associated functionality (thanks Ny!).") - .RegisterEntry("Updated the creation of temporary collections to require a passed identity.") - .RegisterEntry("Added the option to change the skin material suffix in models using the stockings shader by adding specific attributes (thanks Ny!).") - .RegisterEntry("Added predefined tag utility to the multi-mod selection.") - .RegisterEntry("Fixed an issue with the automatic collection selection on character login when no mods are assigned.") - .RegisterImportant( - "Fixed issue with new deformer data that makes modded deformers not containing this data work implicitly. Updates are still recommended (1.5.0.5).") - .RegisterEntry("Fixed various issues after patch (1.5.0.1 - 1.5.0.4)."); - - private static void Add1_5_0_0(Changelog log) - => log.NextVersion("Version 1.5.0.0") - .RegisterImportant("Updated for game version 7.30 and Dalamud API13, which uses a new GUI backend. Some things may not work as expected. Please let me know any issues you encounter.") - .RegisterEntry("Added support for exporting models using two vertex color schemes (thanks zeroeightysix!).") - .RegisterEntry("Possibly improved the color accuracy of the basecolor texture created when exporting models (thanks zeroeightysix!).") - .RegisterEntry("Disabled enabling transparency for materials that use the characterstockings shader due to crashes (thanks zeroeightysix!).") - .RegisterEntry("Fixed some issues with model i/o and invalid tangents (thanks PassiveModding!)") - .RegisterEntry("Changed the behavior for default directory names when using the mod normalizer with combining groups.") - .RegisterEntry("Added jumping to specific mods to the HTTP API.") - .RegisterEntry("Fixed an issue with character sound modding (1.4.0.6).") - .RegisterHighlight("Added support for IMC-toggle attributes to accessories beyond the first toggle (1.4.0.5).") - .RegisterEntry("Fixed up some slot-specific attributes and shapes in models when swapping items between slots (1.4.0.5).") - .RegisterEntry("Added handling for human skin materials to the OnScreen tab and similar functionality (thanks Ny!) (1.4.0.5).") - .RegisterEntry("The OS thread ID a resource was loaded from was added to the resource logger (1.4.0.5).") - .RegisterEntry("A button linking to my (Ottermandias') Ko-Fi and Patreon was added in the settings tab. Feel free, but not pressured, to use it! :D ") - .RegisterHighlight("Mod setting combos now support mouse-wheel scrolling with Control and have filters (1.4.0.4).") - .RegisterEntry("Using the middle mouse button to toggle designs now works correctly with temporary settings (1.4.0.4).") - .RegisterEntry("Updated some BNPC associations (1.4.0.3).") - .RegisterEntry("Fixed further issues with shapes and attributes (1.4.0.4).") - .RegisterEntry("Penumbra now handles textures with MipMap offsets broken by TexTools on import and removes unnecessary MipMaps (1.4.0.3).") - .RegisterEntry("Updated the Mod Merger for the new group types (1.4.0.3).") - .RegisterEntry("Added querying Penumbra for supported features via IPC (1.4.0.3).") - .RegisterEntry("Shape names can now be edited in Penumbras model editor (1.4.0.2).") - .RegisterEntry("Attributes and Shapes can be fully toggled (1.4.0.2).") - .RegisterEntry("Fixed several issues with attributes and shapes (1.4.0.1)."); - private static void Add1_4_0_0(Changelog log) => log.NextVersion("Version 1.4.0.0") .RegisterHighlight("Added two types of new Meta Changes, SHP and ATR (Thanks Karou!).") diff --git a/Penumbra/UI/Classes/CollectionSelectHeader.cs b/Penumbra/UI/Classes/CollectionSelectHeader.cs index 355a6106..aa492362 100644 --- a/Penumbra/UI/Classes/CollectionSelectHeader.cs +++ b/Penumbra/UI/Classes/CollectionSelectHeader.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/Classes/Colors.cs b/Penumbra/UI/Classes/Colors.cs index 90ef0591..9c15ceb8 100644 --- a/Penumbra/UI/Classes/Colors.cs +++ b/Penumbra/UI/Classes/Colors.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Custom; namespace Penumbra.UI.Classes; diff --git a/Penumbra/UI/Classes/MigrationSectionDrawer.cs b/Penumbra/UI/Classes/MigrationSectionDrawer.cs index 98a59a5b..a3dcd23a 100644 --- a/Penumbra/UI/Classes/MigrationSectionDrawer.cs +++ b/Penumbra/UI/Classes/MigrationSectionDrawer.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.Services; diff --git a/Penumbra/UI/CollectionTab/CollectionCombo.cs b/Penumbra/UI/CollectionTab/CollectionCombo.cs index bf97f178..98dc924f 100644 --- a/Penumbra/UI/CollectionTab/CollectionCombo.cs +++ b/Penumbra/UI/CollectionTab/CollectionCombo.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Extensions; using OtterGui.Raii; using OtterGui.Text; diff --git a/Penumbra/UI/CollectionTab/CollectionPanel.cs b/Penumbra/UI/CollectionTab/CollectionPanel.cs index e41ceade..dc0e71b5 100644 --- a/Penumbra/UI/CollectionTab/CollectionPanel.cs +++ b/Penumbra/UI/CollectionTab/CollectionPanel.cs @@ -6,12 +6,11 @@ using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ManagedFontAtlas; using Dalamud.Interface.Utility; using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Extensions; using OtterGui.Raii; -using OtterGui.Text; using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.GameData.Actors; @@ -223,31 +222,26 @@ public sealed class CollectionPanel( ImGui.EndGroup(); ImGui.SameLine(); ImGui.BeginGroup(); - var width = ImGui.GetContentRegionAvail().X; - using (ImRaii.Disabled(_collections.DefaultNamed == collection)) + using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); + var name = _newName ?? collection.Identity.Name; + var identifier = collection.Identity.Identifier; + var width = ImGui.GetContentRegionAvail().X; + var fileName = saveService.FileNames.CollectionFile(collection); + ImGui.SetNextItemWidth(width); + if (ImGui.InputText("##name", ref name, 128)) + _newName = name; + if (ImGui.IsItemDeactivatedAfterEdit() && _newName != null && _newName != collection.Identity.Name) { - using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); - var name = _newName ?? collection.Identity.Name; - ImGui.SetNextItemWidth(width); - if (ImGui.InputText("##name", ref name, 128)) - _newName = name; - if (ImGui.IsItemDeactivatedAfterEdit() && _newName != null && _newName != collection.Identity.Name) - { - collection.Identity.Name = _newName; - saveService.QueueSave(new ModCollectionSave(mods, collection)); - selector.RestoreCollections(); - _newName = null; - } - else if (ImGui.IsItemDeactivated()) - { - _newName = null; - } + collection.Identity.Name = _newName; + saveService.QueueSave(new ModCollectionSave(mods, collection)); + selector.RestoreCollections(); + _newName = null; + } + else if (ImGui.IsItemDeactivated()) + { + _newName = null; } - if (_collections.DefaultNamed == collection) - ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, "The Default collection can not be renamed."u8); - var identifier = collection.Identity.Identifier; - var fileName = saveService.FileNames.CollectionFile(collection); using (ImRaii.PushFont(UiBuilder.MonoFont)) { if (ImGui.Button(collection.Identity.Identifier, new Vector2(width, 0))) @@ -352,7 +346,7 @@ public sealed class CollectionPanel( if (!source) return; - ImGui.SetDragDropPayload("DragIndividual", null, 0); + ImGui.SetDragDropPayload("DragIndividual", nint.Zero, 0); ImGui.TextUnformatted($"Re-ordering {text}..."); _draggedIndividualAssignment = _active.Individuals.Index(id); } @@ -381,7 +375,9 @@ public sealed class CollectionPanel( ImGuiUtil.TextWrapped(type.ToDescription()); switch (type) { - case CollectionType.Default: ImGui.TextUnformatted("Overruled by any other Assignment."); break; + case CollectionType.Default: + ImGui.TextUnformatted("Overruled by any other Assignment."); + break; case CollectionType.Yourself: ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Individual ", ColorId.NewMod.Value()), ("Assignments.", 0)); break; diff --git a/Penumbra/UI/CollectionTab/CollectionSelector.cs b/Penumbra/UI/CollectionTab/CollectionSelector.cs index 79254090..57429531 100644 --- a/Penumbra/UI/CollectionTab/CollectionSelector.cs +++ b/Penumbra/UI/CollectionTab/CollectionSelector.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using Penumbra.Collections; @@ -85,7 +85,7 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl if (source) { _dragging = Items[idx]; - ImGui.SetDragDropPayload(PayloadString, null, 0); + ImGui.SetDragDropPayload(PayloadString, nint.Zero, 0); ImGui.TextUnformatted($"Assigning {Name(_dragging)} to..."); } @@ -116,8 +116,7 @@ public sealed class CollectionSelector : ItemSelector, IDisposabl public void RestoreCollections() { Items.Clear(); - Items.Add(_storage.DefaultNamed); - foreach (var c in _storage.OrderBy(c => c.Identity.Name).Where(c => c != _storage.DefaultNamed)) + foreach (var c in _storage.OrderBy(c => c.Identity.Name)) Items.Add(c); SetFilterDirty(); SetCurrent(_active.Current); diff --git a/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs b/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs index f472e346..fd8f9b25 100644 --- a/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs +++ b/Penumbra/UI/CollectionTab/IndividualAssignmentUi.cs @@ -1,5 +1,5 @@ using Dalamud.Game.ClientState.Objects.Enums; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Custom; using Penumbra.Collections; using Penumbra.Collections.Manager; diff --git a/Penumbra/UI/CollectionTab/InheritanceUi.cs b/Penumbra/UI/CollectionTab/InheritanceUi.cs index 2053f269..cdc1e83e 100644 --- a/Penumbra/UI/CollectionTab/InheritanceUi.cs +++ b/Penumbra/UI/CollectionTab/InheritanceUi.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; @@ -288,7 +288,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService if (!source) return; - ImGui.SetDragDropPayload(InheritanceDragDropLabel, null, 0); + ImGui.SetDragDropPayload(InheritanceDragDropLabel, nint.Zero, 0); _movedInheritance = collection; ImGui.TextUnformatted($"Moving {(_movedInheritance != null ? Name(_movedInheritance) : "Unknown")}..."); } diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index 55d0bc19..64d370b5 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -1,6 +1,6 @@ using Dalamud.Interface.Windowing; using Dalamud.Plugin; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Custom; using OtterGui.Raii; diff --git a/Penumbra/UI/FileDialogService.cs b/Penumbra/UI/FileDialogService.cs index 3bbc4ba8..6773bc88 100644 --- a/Penumbra/UI/FileDialogService.cs +++ b/Penumbra/UI/FileDialogService.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Utility; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Services; diff --git a/Penumbra/UI/ImportPopup.cs b/Penumbra/UI/ImportPopup.cs index 59ed0308..28767edc 100644 --- a/Penumbra/UI/ImportPopup.cs +++ b/Penumbra/UI/ImportPopup.cs @@ -1,7 +1,7 @@ using Dalamud.Game.ClientState.Keys; using Dalamud.Interface.Windowing; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using Penumbra.Import.Structs; diff --git a/Penumbra/UI/IncognitoService.cs b/Penumbra/UI/IncognitoService.cs index 678e072e..29358618 100644 --- a/Penumbra/UI/IncognitoService.cs +++ b/Penumbra/UI/IncognitoService.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using Penumbra.UI.Classes; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/Knowledge/KnowledgeWindow.cs b/Penumbra/UI/Knowledge/KnowledgeWindow.cs index 118ed479..f831975b 100644 --- a/Penumbra/UI/Knowledge/KnowledgeWindow.cs +++ b/Penumbra/UI/Knowledge/KnowledgeWindow.cs @@ -1,6 +1,6 @@ using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.String; diff --git a/Penumbra/UI/Knowledge/RaceCodeTab.cs b/Penumbra/UI/Knowledge/RaceCodeTab.cs index 44b544eb..36b048aa 100644 --- a/Penumbra/UI/Knowledge/RaceCodeTab.cs +++ b/Penumbra/UI/Knowledge/RaceCodeTab.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Text; using Penumbra.GameData.Enums; diff --git a/Penumbra/UI/ModsTab/DescriptionEditPopup.cs b/Penumbra/UI/ModsTab/DescriptionEditPopup.cs index 7d7a6967..c284afc3 100644 --- a/Penumbra/UI/ModsTab/DescriptionEditPopup.cs +++ b/Penumbra/UI/ModsTab/DescriptionEditPopup.cs @@ -1,5 +1,5 @@ using Dalamud.Interface.Utility; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.Mods; diff --git a/Penumbra/UI/ModsTab/Groups/AddGroupDrawer.cs b/Penumbra/UI/ModsTab/Groups/AddGroupDrawer.cs index 1430f17b..a3e7ce14 100644 --- a/Penumbra/UI/ModsTab/Groups/AddGroupDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/AddGroupDrawer.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.Api.Enums; diff --git a/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs b/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs index e9840e6c..5bd5dfdf 100644 --- a/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/CombiningModGroupEditDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/UI/ModsTab/Groups/ImcModGroupEditDrawer.cs b/Penumbra/UI/ModsTab/Groups/ImcModGroupEditDrawer.cs index fa5b0ef6..3d330093 100644 --- a/Penumbra/UI/ModsTab/Groups/ImcModGroupEditDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/ImcModGroupEditDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Extensions; using OtterGui.Raii; using OtterGui.Text; diff --git a/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs b/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs index 3d8409ad..566ec02c 100644 --- a/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/ModGroupDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface.Components; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Extensions; using OtterGui.Raii; diff --git a/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs b/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs index 9610f173..e9ab72ae 100644 --- a/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/ModGroupEditDrawer.cs @@ -1,6 +1,6 @@ using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Extensions; diff --git a/Penumbra/UI/ModsTab/Groups/SingleModGroupEditDrawer.cs b/Penumbra/UI/ModsTab/Groups/SingleModGroupEditDrawer.cs index 8fa6a377..492a8fb7 100644 --- a/Penumbra/UI/ModsTab/Groups/SingleModGroupEditDrawer.cs +++ b/Penumbra/UI/ModsTab/Groups/SingleModGroupEditDrawer.cs @@ -1,5 +1,5 @@ using Dalamud.Interface; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Extensions; using OtterGui.Raii; using OtterGui.Text; diff --git a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs index 3f3c82aa..8a383791 100644 --- a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs +++ b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs @@ -2,7 +2,7 @@ using Dalamud.Interface; using Dalamud.Interface.DragDrop; using Dalamud.Interface.ImGuiNotification; using Dalamud.Plugin.Services; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Filesystem; @@ -126,7 +126,6 @@ public sealed class ModFileSystemSelector : FileSystemSelector + "Mod Packs{.ttmp,.ttmp2,.pmp},TexTools Mod Packs{.ttmp,.ttmp2},Penumbra Mod Packs{.pmp},Archives{.zip,.7z,.rar}", (s, f) => { if (!s) return; @@ -446,7 +445,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector 0 ? (true, ImGui.GetFrameHeight() + ImGui.GetStyle().WindowPadding.X + (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0)) : (false, 0); var tagIdx = _localTags.Draw("Local Tags: ", diff --git a/Penumbra/UI/ModsTab/ModPanelEditTab.cs b/Penumbra/UI/ModsTab/ModPanelEditTab.cs index c3737b40..478ab892 100644 --- a/Penumbra/UI/ModsTab/ModPanelEditTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelEditTab.cs @@ -1,7 +1,7 @@ using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Widgets; @@ -69,7 +69,7 @@ public class ModPanelEditTab( FeatureChecker.DrawFeatureFlagInput(modManager.DataEditor, _mod, UiHelpers.InputTextWidth.X); UiHelpers.DefaultLineSpace(); - var sharedTagsEnabled = predefinedTagManager.Enabled; + var sharedTagsEnabled = predefinedTagManager.Count > 0; var sharedTagButtonOffset = sharedTagsEnabled ? ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X : 0; var tagIdx = _modTags.Draw("Mod Tags: ", "Edit tags by clicking them, or add new tags. Empty tags are removed.", _mod.ModTags, out var editedTag, rightEndOffset: sharedTagButtonOffset); @@ -325,7 +325,7 @@ public class ModPanelEditTab( var tmp = field == _currentField && option == _optionIndex ? _currentEdit ?? oldValue : oldValue; ImGui.SetNextItemWidth(width); - if (ImGui.InputText(label, ref tmp)) + if (ImGui.InputText(label, ref tmp, maxLength)) { _currentEdit = tmp; _optionIndex = option; diff --git a/Penumbra/UI/ModsTab/ModPanelHeader.cs b/Penumbra/UI/ModsTab/ModPanelHeader.cs index b42ac680..aafbffa6 100644 --- a/Penumbra/UI/ModsTab/ModPanelHeader.cs +++ b/Penumbra/UI/ModsTab/ModPanelHeader.cs @@ -1,7 +1,7 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface.GameFonts; using Dalamud.Interface.ManagedFontAtlas; using Dalamud.Plugin; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using Penumbra.Communication; diff --git a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs index 84f69bcb..7c6ebf74 100644 --- a/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelSettingsTab.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/ModsTab/ModPanelTabBar.cs b/Penumbra/UI/ModsTab/ModPanelTabBar.cs index 5981d979..639118f5 100644 --- a/Penumbra/UI/ModsTab/ModPanelTabBar.cs +++ b/Penumbra/UI/ModsTab/ModPanelTabBar.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/ModsTab/MultiModPanel.cs b/Penumbra/UI/ModsTab/MultiModPanel.cs index 947ede14..ff5f636d 100644 --- a/Penumbra/UI/ModsTab/MultiModPanel.cs +++ b/Penumbra/UI/ModsTab/MultiModPanel.cs @@ -1,8 +1,7 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility; +using ImGuiNET; using OtterGui.Extensions; -using OtterGui.Filesystem; using OtterGui.Raii; using OtterGui.Services; using OtterGui.Text; @@ -11,7 +10,7 @@ using Penumbra.Mods.Manager; namespace Penumbra.UI.ModsTab; -public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, PredefinedTagManager tagManager) : IUiService +public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor) : IUiService { public void Draw() { @@ -98,12 +97,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, var width = ImGuiHelpers.ScaledVector2(150, 0); ImUtf8.TextFrameAligned("Multi Tagger:"u8); ImGui.SameLine(); - - var predefinedTagsEnabled = tagManager.Enabled; - var inputWidth = predefinedTagsEnabled - ? ImGui.GetContentRegionAvail().X - 2 * width.X - 3 * ImGui.GetStyle().ItemInnerSpacing.X - ImGui.GetFrameHeight() - : ImGui.GetContentRegionAvail().X - 2 * (width.X + ImGui.GetStyle().ItemInnerSpacing.X); - ImGui.SetNextItemWidth(inputWidth); + ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - 2 * (width.X + ImGui.GetStyle().ItemSpacing.X)); ImUtf8.InputText("##tag"u8, ref _tag, "Local Tag Name..."u8); UpdateTagCache(); @@ -115,7 +109,7 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, ? "No tag specified." : $"All mods selected already contain the tag \"{_tag}\", either locally or as mod data." : $"Add the tag \"{_tag}\" to {_addMods.Count} mods as a local tag:\n\n\t{string.Join("\n\t", _addMods.Select(m => m.Name.Text))}"; - ImUtf8.SameLineInner(); + ImGui.SameLine(); if (ImUtf8.ButtonEx(label, tooltip, width, _addMods.Count == 0)) foreach (var mod in _addMods) editor.ChangeLocalTag(mod, mod.LocalTags.Count, _tag); @@ -128,18 +122,10 @@ public class MultiModPanel(ModFileSystemSelector selector, ModDataEditor editor, ? "No tag specified." : $"No selected mod contains the tag \"{_tag}\" locally." : $"Remove the local tag \"{_tag}\" from {_removeMods.Count} mods:\n\n\t{string.Join("\n\t", _removeMods.Select(m => m.Item1.Name.Text))}"; - ImUtf8.SameLineInner(); + ImGui.SameLine(); if (ImUtf8.ButtonEx(label, tooltip, width, _removeMods.Count == 0)) foreach (var (mod, index) in _removeMods) editor.ChangeLocalTag(mod, index, string.Empty); - - if (predefinedTagsEnabled) - { - ImUtf8.SameLineInner(); - tagManager.DrawToggleButton(); - tagManager.DrawListMulti(selector.SelectedPaths.OfType().Select(l => l.Value)); - } - ImGui.Separator(); } diff --git a/Penumbra/UI/PredefinedTagManager.cs b/Penumbra/UI/PredefinedTagManager.cs index 5a3a4b62..12355672 100644 --- a/Penumbra/UI/PredefinedTagManager.cs +++ b/Penumbra/UI/PredefinedTagManager.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; -using Dalamud.Interface; +using Dalamud.Interface; using Dalamud.Interface.ImGuiNotification; +using ImGuiNET; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using OtterGui; @@ -8,8 +8,6 @@ using OtterGui.Classes; using OtterGui.Extensions; using OtterGui.Raii; using OtterGui.Services; -using OtterGui.Text; -using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.Services; using Penumbra.UI.Classes; @@ -54,9 +52,6 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList, ISer jObj.WriteTo(jWriter); } - public bool Enabled - => Count > 0; - public void Save() => _saveService.DelaySave(this, TimeSpan.FromSeconds(5)); @@ -103,9 +98,9 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList, ISer } public void DrawAddFromSharedTagsAndUpdateTags(IReadOnlyCollection localTags, IReadOnlyCollection modTags, bool editLocal, - Mod mod) + Mods.Mod mod) { - DrawToggleButtonTopRight(); + DrawToggleButton(); if (!DrawList(localTags, modTags, editLocal, out var changedTag, out var index)) return; @@ -115,20 +110,15 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList, ISer _modManager.DataEditor.ChangeModTag(mod, index, changedTag); } - public void DrawToggleButton() - { - using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), _isListOpen); - if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Tags.ToIconString(), new Vector2(ImGui.GetFrameHeight()), - "Add Predefined Tags...", false, true)) - _isListOpen = !_isListOpen; - } - - private void DrawToggleButtonTopRight() + private void DrawToggleButton() { ImGui.SameLine(ImGui.GetContentRegionMax().X - ImGui.GetFrameHeight() - (ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ItemInnerSpacing.X : 0)); - DrawToggleButton(); + using var color = ImRaii.PushColor(ImGuiCol.Button, ImGui.GetColorU32(ImGuiCol.ButtonActive), _isListOpen); + if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Tags.ToIconString(), new Vector2(ImGui.GetFrameHeight()), + "Add Predefined Tags...", false, true)) + _isListOpen = !_isListOpen; } private bool DrawList(IReadOnlyCollection localTags, IReadOnlyCollection modTags, bool editLocal, out string changedTag, @@ -140,7 +130,7 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList, ISer if (!_isListOpen) return false; - ImUtf8.Text("Predefined Tags"u8); + ImGui.TextUnformatted("Predefined Tags"); ImGui.Separator(); var ret = false; @@ -165,101 +155,6 @@ public sealed class PredefinedTagManager : ISavable, IReadOnlyList, ISer return ret; } - private readonly List _selectedMods = []; - private readonly List<(int Index, int DataIndex)> _countedMods = []; - - private void PrepareLists(IEnumerable selection) - { - _selectedMods.Clear(); - _selectedMods.AddRange(selection); - _countedMods.EnsureCapacity(_selectedMods.Count); - while (_countedMods.Count < _selectedMods.Count) - _countedMods.Add((-1, -1)); - } - - public void DrawListMulti(IEnumerable selection) - { - if (!_isListOpen) - return; - - ImUtf8.Text("Predefined Tags"u8); - PrepareLists(selection); - - _enabledColor = ColorId.PredefinedTagAdd.Value(); - _disabledColor = ColorId.PredefinedTagRemove.Value(); - using var color = new ImRaii.Color(); - foreach (var (tag, idx) in _predefinedTags.Keys.WithIndex()) - { - var alreadyContained = 0; - var inModData = 0; - var missing = 0; - - foreach (var (modIndex, mod) in _selectedMods.Index()) - { - var tagIdx = mod.LocalTags.IndexOf(tag); - if (tagIdx >= 0) - { - ++alreadyContained; - _countedMods[modIndex] = (tagIdx, -1); - } - else - { - var dataIdx = mod.ModTags.IndexOf(tag); - if (dataIdx >= 0) - { - ++inModData; - _countedMods[modIndex] = (-1, dataIdx); - } - else - { - ++missing; - _countedMods[modIndex] = (-1, -1); - } - } - } - - using var id = ImRaii.PushId(idx); - var buttonWidth = CalcTextButtonWidth(tag); - // Prevent adding a new tag past the right edge of the popup - if (buttonWidth + ImGui.GetStyle().ItemSpacing.X >= ImGui.GetContentRegionAvail().X) - ImGui.NewLine(); - - var (usedColor, disabled, tt) = (missing, alreadyContained) switch - { - (> 0, _) => (_enabledColor, false, - $"Add this tag to {missing} mods.{(inModData > 0 ? $" {inModData} mods contain it in their mod tags and are untouched." : string.Empty)}"), - (_, > 0) => (_disabledColor, false, - $"Remove this tag from {alreadyContained} mods.{(inModData > 0 ? $" {inModData} mods contain it in their mod tags and are untouched." : string.Empty)}"), - _ => (_disabledColor, true, "This tag is already present in the mod tags of all selected mods."), - }; - color.Push(ImGuiCol.Button, usedColor); - if (ImUtf8.ButtonEx(tag, tt, new Vector2(buttonWidth, 0), disabled)) - { - if (missing > 0) - foreach (var (mod, (localIdx, _)) in _selectedMods.Zip(_countedMods)) - { - if (localIdx >= 0) - continue; - - _modManager.DataEditor.ChangeLocalTag(mod, mod.LocalTags.Count, tag); - } - else - foreach (var (mod, (localIdx, _)) in _selectedMods.Zip(_countedMods)) - { - if (localIdx < 0) - continue; - - _modManager.DataEditor.ChangeLocalTag(mod, localIdx, string.Empty); - } - } - ImGui.SameLine(); - - color.Pop(); - } - - ImGui.NewLine(); - } - private bool DrawColoredButton(string buttonLabel, int index, int tagIdx, bool inOther) { using var id = ImRaii.PushId(index); diff --git a/Penumbra/UI/ResourceWatcher/Record.cs b/Penumbra/UI/ResourceWatcher/Record.cs index ba718bc9..b8730750 100644 --- a/Penumbra/UI/ResourceWatcher/Record.cs +++ b/Penumbra/UI/ResourceWatcher/Record.cs @@ -1,7 +1,6 @@ using OtterGui.Classes; using Penumbra.Collections; using Penumbra.Enums; -using Penumbra.Interop; using Penumbra.Interop.Structs; using Penumbra.String; using Penumbra.String.Classes; @@ -35,7 +34,6 @@ internal unsafe struct Record public OptionalBool ReturnValue; public OptionalBool CustomLoad; public LoadState LoadState; - public uint OsThreadId; public static Record CreateRequest(CiByteString path, bool sync) @@ -56,7 +54,6 @@ internal unsafe struct Record AssociatedGameObject = string.Empty, LoadState = LoadState.None, Crc64 = 0, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; public static Record CreateRequest(CiByteString path, bool sync, FullPath fullPath, ResolveData resolve) @@ -77,7 +74,6 @@ internal unsafe struct Record AssociatedGameObject = string.Empty, LoadState = LoadState.None, Crc64 = fullPath.Crc64, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; public static Record CreateDefaultLoad(CiByteString path, ResourceHandle* handle, ModCollection collection, string associatedGameObject) @@ -100,7 +96,6 @@ internal unsafe struct Record AssociatedGameObject = associatedGameObject, LoadState = handle->LoadState, Crc64 = 0, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; } @@ -123,7 +118,6 @@ internal unsafe struct Record AssociatedGameObject = associatedGameObject, LoadState = handle->LoadState, Crc64 = path.Crc64, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; public static Record CreateDestruction(ResourceHandle* handle) @@ -146,7 +140,6 @@ internal unsafe struct Record AssociatedGameObject = string.Empty, LoadState = handle->LoadState, Crc64 = 0, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; } @@ -168,7 +161,6 @@ internal unsafe struct Record AssociatedGameObject = string.Empty, LoadState = handle->LoadState, Crc64 = 0, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; public static Record CreateResourceComplete(CiByteString path, ResourceHandle* handle, Utf8GamePath originalPath, ReadOnlySpan additionalData) @@ -189,7 +181,6 @@ internal unsafe struct Record AssociatedGameObject = string.Empty, LoadState = handle->LoadState, Crc64 = 0, - OsThreadId = ProcessThreadApi.GetCurrentThreadId(), }; private static CiByteString CombinedPath(CiByteString path, ReadOnlySpan additionalData) diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs index ee3613fc..d134cfe5 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.System.Resource; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using OtterGui.Widgets; diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs index 97df095e..a58d74d1 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Raii; @@ -30,8 +30,7 @@ internal sealed class ResourceWatcherTable : Table new LoadStateColumn { Label = "State" }, new RefCountColumn { Label = "#Ref" }, new DateColumn { Label = "Time" }, - new Crc64Column { Label = "Crc64" }, - new OsThreadColumn { Label = "TID" } + new Crc64Column { Label = "Crc64" } ) { } @@ -454,19 +453,4 @@ internal sealed class ResourceWatcherTable : Table public override int Compare(Record lhs, Record rhs) => lhs.RefCount.CompareTo(rhs.RefCount); } - - private sealed class OsThreadColumn : ColumnString - { - public override float Width - => 60 * UiHelpers.Scale; - - public override string ToName(Record item) - => item.OsThreadId.ToString(); - - public override void DrawColumn(Record item, int _) - => ImGuiUtil.RightAlign(ToName(item)); - - public override int Compare(Record lhs, Record rhs) - => lhs.OsThreadId.CompareTo(rhs.OsThreadId); - } } diff --git a/Penumbra/UI/Tabs/ChangedItemsTab.cs b/Penumbra/UI/Tabs/ChangedItemsTab.cs index 4dc9474f..6cee22d6 100644 --- a/Penumbra/UI/Tabs/ChangedItemsTab.cs +++ b/Penumbra/UI/Tabs/ChangedItemsTab.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Raii; diff --git a/Penumbra/UI/Tabs/CollectionsTab.cs b/Penumbra/UI/Tabs/CollectionsTab.cs index f2a041eb..05a1f33b 100644 --- a/Penumbra/UI/Tabs/CollectionsTab.cs +++ b/Penumbra/UI/Tabs/CollectionsTab.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects; using Dalamud.Plugin; +using ImGuiNET; using OtterGui.Raii; using OtterGui.Services; using OtterGui.Widgets; diff --git a/Penumbra/UI/Tabs/ConfigTabBar.cs b/Penumbra/UI/Tabs/ConfigTabBar.cs index 43ae2488..28827ad9 100644 --- a/Penumbra/UI/Tabs/ConfigTabBar.cs +++ b/Penumbra/UI/Tabs/ConfigTabBar.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Widgets; using Penumbra.Api.Enums; diff --git a/Penumbra/UI/Tabs/Debug/AtchDrawer.cs b/Penumbra/UI/Tabs/Debug/AtchDrawer.cs index f136bacd..3b25c1a9 100644 --- a/Penumbra/UI/Tabs/Debug/AtchDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/AtchDrawer.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Extensions; using OtterGui.Text; using Penumbra.GameData.Files; diff --git a/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs b/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs index 471d770a..94c6cbd6 100644 --- a/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs +++ b/Penumbra/UI/Tabs/Debug/CrashDataExtensions.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using Penumbra.CrashHandler; diff --git a/Penumbra/UI/Tabs/Debug/CrashHandlerPanel.cs b/Penumbra/UI/Tabs/Debug/CrashHandlerPanel.cs index 672b8c79..c8e7f001 100644 --- a/Penumbra/UI/Tabs/Debug/CrashHandlerPanel.cs +++ b/Penumbra/UI/Tabs/Debug/CrashHandlerPanel.cs @@ -1,6 +1,6 @@ using System.Text.Json; -using Dalamud.Bindings.ImGui; using Dalamud.Interface.DragDrop; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/Tabs/Debug/DebugConfigurationDrawer.cs b/Penumbra/UI/Tabs/Debug/DebugConfigurationDrawer.cs index 087670c1..97761091 100644 --- a/Penumbra/UI/Tabs/Debug/DebugConfigurationDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/DebugConfigurationDrawer.cs @@ -1,16 +1,15 @@ -using OtterGui.Text; - -namespace Penumbra.UI.Tabs.Debug; - +using OtterGui.Text; + +namespace Penumbra.UI.Tabs.Debug; + public static class DebugConfigurationDrawer { public static void Draw() { - using var id = ImUtf8.CollapsingHeaderId("Debugging Options"u8); + using var id = ImUtf8.CollapsingHeaderId("Debug Logging Options"u8); if (!id) return; - ImUtf8.Checkbox("Log IMC File Replacements"u8, ref DebugConfiguration.WriteImcBytesToLog); - ImUtf8.Checkbox("Scan for Skin Material Attributes"u8, ref DebugConfiguration.UseSkinMaterialProcessing); + ImUtf8.Checkbox("Log IMC File Replacements"u8, ref DebugConfiguration.WriteImcBytesToLog); } -} +} diff --git a/Penumbra/UI/Tabs/Debug/DebugTab.cs b/Penumbra/UI/Tabs/Debug/DebugTab.cs index 05f77e29..76df5acc 100644 --- a/Penumbra/UI/Tabs/Debug/DebugTab.cs +++ b/Penumbra/UI/Tabs/Debug/DebugTab.cs @@ -8,8 +8,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Group; using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.UI.Agent; -using Dalamud.Bindings.ImGui; -using Dalamud.Interface.Colors; +using ImGuiNET; using Microsoft.Extensions.DependencyInjection; using OtterGui; using OtterGui.Classes; @@ -42,7 +41,6 @@ using Penumbra.GameData.Data; using Penumbra.Interop.Hooks.PostProcessing; using Penumbra.Interop.Hooks.ResourceLoading; using Penumbra.GameData.Files.StainMapStructs; -using Penumbra.Interop; using Penumbra.String.Classes; using Penumbra.UI.AdvancedWindow.Materials; @@ -208,7 +206,6 @@ public class DebugTab : Window, ITab, IUiService _hookOverrides.Draw(); DrawPlayerModelInfo(); _globalVariablesDrawer.Draw(); - DrawCloudApi(); DrawDebugTabIpc(); } @@ -729,9 +726,6 @@ public class DebugTab : Window, ITab, IUiService if (agent->Data == null) agent = &AgentBannerMIP.Instance()->AgentBannerInterface; - ImUtf8.Text("Agent: "); - ImGui.SameLine(0, 0); - Penumbra.Dynamis.DrawPointer((nint)agent); if (agent->Data != null) { using var table = Table("###PBannerTable", 2, ImGuiTableFlags.SizingFixedFit); @@ -1051,7 +1045,7 @@ public class DebugTab : Window, ITab, IUiService if (t1) { ImGuiUtil.DrawTableColumn("Flags"); - ImGuiUtil.DrawTableColumn($"{model->StateFlags}"); + ImGuiUtil.DrawTableColumn($"{model->UnkFlags_01:X2}"); ImGuiUtil.DrawTableColumn("Has Model In Slot Loaded"); ImGuiUtil.DrawTableColumn($"{model->HasModelInSlotLoaded:X8}"); ImGuiUtil.DrawTableColumn("Has Model Files In Slot Loaded"); @@ -1202,42 +1196,6 @@ public class DebugTab : Window, ITab, IUiService } - private string _cloudTesterPath = string.Empty; - private bool? _cloudTesterReturn; - private Exception? _cloudTesterError; - - private void DrawCloudApi() - { - if (!ImUtf8.CollapsingHeader("Cloud API"u8)) - return; - - using var id = ImRaii.PushId("CloudApiTester"u8); - - if (ImUtf8.InputText("Path"u8, ref _cloudTesterPath, flags: ImGuiInputTextFlags.EnterReturnsTrue)) - { - try - { - _cloudTesterReturn = CloudApi.IsCloudSynced(_cloudTesterPath); - _cloudTesterError = null; - } - catch (Exception e) - { - _cloudTesterReturn = null; - _cloudTesterError = e; - } - } - - if (_cloudTesterReturn.HasValue) - ImUtf8.Text($"Is Cloud Synced? {_cloudTesterReturn}"); - - if (_cloudTesterError is not null) - { - using var color = ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudRed); - ImUtf8.Text($"{_cloudTesterError}"); - } - } - - /// Draw information about IPC options and availability. private void DrawDebugTabIpc() { @@ -1275,12 +1233,16 @@ public class DebugTab : Window, ITab, IUiService } public static unsafe void DrawCopyableAddress(ReadOnlySpan label, void* address) - => DrawCopyableAddress(label, (nint)address); + { + using (var _ = ImRaii.PushFont(UiBuilder.MonoFont)) + { + if (ImUtf8.Selectable($"0x{(nint)address:X16} {label}")) + ImUtf8.SetClipboardText($"0x{(nint)address:X16}"); + } + + ImUtf8.HoverTooltip("Click to copy address to clipboard."u8); + } public static unsafe void DrawCopyableAddress(ReadOnlySpan label, nint address) - { - Penumbra.Dynamis.DrawPointer(address); - ImUtf8.SameLineInner(); - ImUtf8.Text(label); - } + => DrawCopyableAddress(label, (void*)address); } diff --git a/Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs b/Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs index f0ab1125..bfe89768 100644 --- a/Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs @@ -1,9 +1,10 @@ -using Dalamud.Bindings.ImGui; +using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.System.Scheduler; using FFXIVClientStructs.FFXIV.Client.System.Scheduler.Resource; using FFXIVClientStructs.Interop; using FFXIVClientStructs.STD; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.Interop.Services; @@ -27,31 +28,14 @@ public unsafe class GlobalVariablesDrawer( return; var actionManager = (ActionTimelineManager**)ActionTimelineManager.Instance(); - using (ImUtf8.Group()) - { - Penumbra.Dynamis.DrawPointer(characterUtility.Address); - Penumbra.Dynamis.DrawPointer(residentResources.Address); - Penumbra.Dynamis.DrawPointer(ScheduleManagement.Instance()); - Penumbra.Dynamis.DrawPointer(actionManager); - Penumbra.Dynamis.DrawPointer(actionManager != null ? *actionManager : null); - Penumbra.Dynamis.DrawPointer(scheduler.Address); - Penumbra.Dynamis.DrawPointer(scheduler.Address != null ? *scheduler.Address : null); - Penumbra.Dynamis.DrawPointer(Device.Instance()); - } - - ImGui.SameLine(); - using (ImUtf8.Group()) - { - ImUtf8.Text("CharacterUtility"u8); - ImUtf8.Text("ResidentResourceManager"u8); - ImUtf8.Text("ScheduleManagement"u8); - ImUtf8.Text("ActionTimelineManager*"u8); - ImUtf8.Text("ActionTimelineManager"u8); - ImUtf8.Text("SchedulerResourceManagement*"u8); - ImUtf8.Text("SchedulerResourceManagement"u8); - ImUtf8.Text("Device"u8); - } - + DebugTab.DrawCopyableAddress("CharacterUtility"u8, characterUtility.Address); + DebugTab.DrawCopyableAddress("ResidentResourceManager"u8, residentResources.Address); + DebugTab.DrawCopyableAddress("ScheduleManagement"u8, ScheduleManagement.Instance()); + DebugTab.DrawCopyableAddress("ActionTimelineManager*"u8, actionManager); + DebugTab.DrawCopyableAddress("ActionTimelineManager"u8, actionManager != null ? *actionManager : null); + DebugTab.DrawCopyableAddress("SchedulerResourceManagement*"u8, scheduler.Address); + DebugTab.DrawCopyableAddress("SchedulerResourceManagement"u8, scheduler.Address != null ? *scheduler.Address : null); + DebugTab.DrawCopyableAddress("Device"u8, Device.Instance()); DrawCharacterUtility(); DrawResidentResources(); DrawSchedulerResourcesMap(); @@ -80,7 +64,7 @@ public unsafe class GlobalVariablesDrawer( var resource = characterUtility.Address->Resource(idx); ImUtf8.DrawTableColumn($"[{idx}]"); ImGui.TableNextColumn(); - Penumbra.Dynamis.DrawPointer(resource); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource:X}"); if (resource == null) { ImGui.TableNextRow(); @@ -91,12 +75,25 @@ public unsafe class GlobalVariablesDrawer( ImGui.TableNextColumn(); var data = (nint)resource->CsHandle.GetData(); var length = resource->CsHandle.GetLength(); - Penumbra.Dynamis.DrawPointer(data); + if (ImUtf8.Selectable($"0x{data:X}")) + if (data != nint.Zero && length > 0) + ImUtf8.SetClipboardText(string.Join("\n", + new ReadOnlySpan((byte*)data, (int)length).ToArray().Select(b => b.ToString("X2")))); + + ImUtf8.HoverTooltip("Click to copy bytes to clipboard."u8); ImUtf8.DrawTableColumn(length.ToString()); + ImGui.TableNextColumn(); if (intern.Value != -1) { - Penumbra.Dynamis.DrawPointer(characterUtility.DefaultResource(intern).Address); + ImUtf8.Selectable($"0x{characterUtility.DefaultResource(intern).Address:X}"); + if (ImGui.IsItemClicked()) + ImUtf8.SetClipboardText(string.Join("\n", + new ReadOnlySpan((byte*)characterUtility.DefaultResource(intern).Address, + characterUtility.DefaultResource(intern).Size).ToArray().Select(b => b.ToString("X2")))); + + ImUtf8.HoverTooltip("Click to copy bytes to clipboard."u8); + ImUtf8.DrawTableColumn($"{characterUtility.DefaultResource(intern).Size}"); } else @@ -126,7 +123,7 @@ public unsafe class GlobalVariablesDrawer( var resource = residentResources.Address->ResourceList[idx]; ImUtf8.DrawTableColumn($"[{idx}]"); ImGui.TableNextColumn(); - Penumbra.Dynamis.DrawPointer(resource); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource:X}"); if (resource == null) { ImGui.TableNextRow(); @@ -137,7 +134,12 @@ public unsafe class GlobalVariablesDrawer( ImGui.TableNextColumn(); var data = (nint)resource->CsHandle.GetData(); var length = resource->CsHandle.GetLength(); - Penumbra.Dynamis.DrawPointer(data); + if (ImUtf8.Selectable($"0x{data:X}")) + if (data != nint.Zero && length > 0) + ImUtf8.SetClipboardText(string.Join("\n", + new ReadOnlySpan((byte*)data, (int)length).ToArray().Select(b => b.ToString("X2")))); + + ImUtf8.HoverTooltip("Click to copy bytes to clipboard."u8); ImUtf8.DrawTableColumn(length.ToString()); } } @@ -183,15 +185,15 @@ public unsafe class GlobalVariablesDrawer( ImUtf8.DrawTableColumn($"{resource->Consumers}"); ImUtf8.DrawTableColumn($"{resource->Unk1}"); // key ImGui.TableNextColumn(); - Penumbra.Dynamis.DrawPointer(resource); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource:X}"); ImGui.TableNextColumn(); var resourceHandle = *((ResourceHandle**)resource + 3); - Penumbra.Dynamis.DrawPointer(resourceHandle); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resourceHandle:X}"); ImGui.TableNextColumn(); ImUtf8.CopyOnClickSelectable(resourceHandle->FileName().Span); ImGui.TableNextColumn(); uint dataLength = 0; - Penumbra.Dynamis.DrawPointer(resource->GetResourceData(&dataLength)); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource->GetResourceData(&dataLength):X}"); ImUtf8.DrawTableColumn($"{dataLength}"); ++_shownResourcesMap; } @@ -232,15 +234,15 @@ public unsafe class GlobalVariablesDrawer( ImUtf8.DrawTableColumn($"{resource->Consumers}"); ImUtf8.DrawTableColumn($"{resource->Unk1}"); // key ImGui.TableNextColumn(); - Penumbra.Dynamis.DrawPointer(resource); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource:X}"); ImGui.TableNextColumn(); var resourceHandle = *((ResourceHandle**)resource + 3); - Penumbra.Dynamis.DrawPointer(resourceHandle); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resourceHandle:X}"); ImGui.TableNextColumn(); ImUtf8.CopyOnClickSelectable(resourceHandle->FileName().Span); ImGui.TableNextColumn(); uint dataLength = 0; - Penumbra.Dynamis.DrawPointer(resource->GetResourceData(&dataLength)); + ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource->GetResourceData(&dataLength):X}"); ImUtf8.DrawTableColumn($"{dataLength}"); ++_shownResourcesList; } diff --git a/Penumbra/UI/Tabs/Debug/HookOverrideDrawer.cs b/Penumbra/UI/Tabs/Debug/HookOverrideDrawer.cs index f1024950..e8ff9b9c 100644 --- a/Penumbra/UI/Tabs/Debug/HookOverrideDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/HookOverrideDrawer.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Plugin; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.Interop.Hooks; diff --git a/Penumbra/UI/Tabs/Debug/ModMigratorDebug.cs b/Penumbra/UI/Tabs/Debug/ModMigratorDebug.cs index e6e01107..c8518315 100644 --- a/Penumbra/UI/Tabs/Debug/ModMigratorDebug.cs +++ b/Penumbra/UI/Tabs/Debug/ModMigratorDebug.cs @@ -1,4 +1,4 @@ -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui.Services; using OtterGui.Text; using Penumbra.Services; diff --git a/Penumbra/UI/Tabs/Debug/RenderTargetDrawer.cs b/Penumbra/UI/Tabs/Debug/RenderTargetDrawer.cs index d497f90a..c8c90e09 100644 --- a/Penumbra/UI/Tabs/Debug/RenderTargetDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/RenderTargetDrawer.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using ImGuiNET; using OtterGui; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/Tabs/Debug/ShapeInspector.cs b/Penumbra/UI/Tabs/Debug/ShapeInspector.cs index 4c3b43bf..7b940cd0 100644 --- a/Penumbra/UI/Tabs/Debug/ShapeInspector.cs +++ b/Penumbra/UI/Tabs/Debug/ShapeInspector.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; +using ImGuiNET; using OtterGui.Extensions; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/Tabs/Debug/TexHeaderDrawer.cs b/Penumbra/UI/Tabs/Debug/TexHeaderDrawer.cs index 4244e455..08d51184 100644 --- a/Penumbra/UI/Tabs/Debug/TexHeaderDrawer.cs +++ b/Penumbra/UI/Tabs/Debug/TexHeaderDrawer.cs @@ -1,6 +1,6 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface.DragDrop; using Dalamud.Interface.Utility.Raii; +using ImGuiNET; using Lumina.Data.Files; using OtterGui.Services; using OtterGui.Text; diff --git a/Penumbra/UI/Tabs/EffectiveTab.cs b/Penumbra/UI/Tabs/EffectiveTab.cs index 5691f821..ecf9a886 100644 --- a/Penumbra/UI/Tabs/EffectiveTab.cs +++ b/Penumbra/UI/Tabs/EffectiveTab.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Raii; diff --git a/Penumbra/UI/Tabs/ModsTab.cs b/Penumbra/UI/Tabs/ModsTab.cs index 79dcbb9e..613a3532 100644 --- a/Penumbra/UI/Tabs/ModsTab.cs +++ b/Penumbra/UI/Tabs/ModsTab.cs @@ -1,5 +1,5 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using Penumbra.UI.Classes; diff --git a/Penumbra/UI/Tabs/ResourceTab.cs b/Penumbra/UI/Tabs/ResourceTab.cs index 593adde1..c54e3433 100644 --- a/Penumbra/UI/Tabs/ResourceTab.cs +++ b/Penumbra/UI/Tabs/ResourceTab.cs @@ -1,9 +1,9 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Game; using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; using FFXIVClientStructs.Interop; using FFXIVClientStructs.STD; +using ImGuiNET; using OtterGui; using OtterGui.Raii; using OtterGui.Services; diff --git a/Penumbra/UI/Tabs/SettingsTab.cs b/Penumbra/UI/Tabs/SettingsTab.cs index 86c01cb2..4bbdf2a9 100644 --- a/Penumbra/UI/Tabs/SettingsTab.cs +++ b/Penumbra/UI/Tabs/SettingsTab.cs @@ -1,10 +1,10 @@ -using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Interface.Utility; using Dalamud.Plugin; using Dalamud.Plugin.Services; using Dalamud.Utility; +using ImGuiNET; using OtterGui; using OtterGui.Compression; using OtterGui.Custom; @@ -14,7 +14,6 @@ using OtterGui.Text; using OtterGui.Widgets; using Penumbra.Api; using Penumbra.Collections; -using Penumbra.Interop; using Penumbra.Interop.Hooks.PostProcessing; using Penumbra.Interop.Services; using Penumbra.Mods.Manager; @@ -37,7 +36,6 @@ public class SettingsTab : ITab, IUiService private readonly Penumbra _penumbra; private readonly FileDialogService _fileDialog; private readonly ModManager _modManager; - private readonly FileWatcher _fileWatcher; private readonly ModExportManager _modExportManager; private readonly ModFileSystemSelector _selector; private readonly CharacterUtility _characterUtility; @@ -54,24 +52,19 @@ public class SettingsTab : ITab, IUiService private readonly CollectionAutoSelector _autoSelector; private readonly CleanupService _cleanupService; private readonly AttributeHook _attributeHook; - private readonly PcpService _pcpService; private int _minimumX = int.MaxValue; private int _minimumY = int.MaxValue; private readonly TagButtons _sharedTags = new(); - private string _lastCloudSyncTestedPath = string.Empty; - private bool _lastCloudSyncTestResult = false; - public SettingsTab(IDalamudPluginInterface pluginInterface, Configuration config, FontReloader fontReloader, TutorialService tutorial, Penumbra penumbra, FileDialogService fileDialog, ModManager modManager, ModFileSystemSelector selector, - CharacterUtility characterUtility, ResidentResourceManager residentResources, ModExportManager modExportManager, - FileWatcher fileWatcher, HttpApi httpApi, + CharacterUtility characterUtility, ResidentResourceManager residentResources, ModExportManager modExportManager, HttpApi httpApi, DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig, IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService, MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService, - AttributeHook attributeHook, PcpService pcpService) + AttributeHook attributeHook) { _pluginInterface = pluginInterface; _config = config; @@ -84,7 +77,6 @@ public class SettingsTab : ITab, IUiService _characterUtility = characterUtility; _residentResources = residentResources; _modExportManager = modExportManager; - _fileWatcher = fileWatcher; _httpApi = httpApi; _dalamudSubstitutionProvider = dalamudSubstitutionProvider; _compactor = compactor; @@ -98,7 +90,6 @@ public class SettingsTab : ITab, IUiService _autoSelector = autoSelector; _cleanupService = cleanupService; _attributeHook = attributeHook; - _pcpService = pcpService; } public void DrawHeader() @@ -122,7 +113,6 @@ public class SettingsTab : ITab, IUiService DrawRootFolder(); DrawDirectoryButtons(); ImGui.NewLine(); - ImGui.NewLine(); DrawGeneralSettings(); _migrationDrawer.Draw(); @@ -215,15 +205,6 @@ public class SettingsTab : ITab, IUiService if (IsSubPathOf(gameDir, newName)) return ("Path is not allowed to be inside your game folder.", false); - if (_lastCloudSyncTestedPath != newName) - { - _lastCloudSyncTestResult = CloudApi.IsCloudSynced(newName); - _lastCloudSyncTestedPath = newName; - } - - if (_lastCloudSyncTestResult) - return ("Path is not allowed to be cloud-synced.", false); - return selected ? ($"Press Enter or Click Here to Save (Current Directory: {old})", true) : ($"Click Here to Save (Current Directory: {old})", true); @@ -525,19 +506,19 @@ public class SettingsTab : ITab, IUiService { var sortMode = _config.SortMode; ImGui.SetNextItemWidth(UiHelpers.InputTextWidth.X); - using (var combo = ImUtf8.Combo("##sortMode", sortMode.Name)) + using (var combo = ImRaii.Combo("##sortMode", sortMode.Name)) { if (combo) foreach (var val in Configuration.Constants.ValidSortModes) { - if (ImUtf8.Selectable(val.Name, val.GetType() == sortMode.GetType()) && val.GetType() != sortMode.GetType()) + if (ImGui.Selectable(val.Name, val.GetType() == sortMode.GetType()) && val.GetType() != sortMode.GetType()) { _config.SortMode = val; _selector.SetFilterDirty(); _config.Save(); } - ImUtf8.HoverTooltip(val.Description); + ImGuiUtil.HoverTooltip(val.Description); } } @@ -616,47 +597,10 @@ public class SettingsTab : ITab, IUiService Checkbox("Always Open Import at Default Directory", "Open the import window at the location specified here every time, forgetting your previous path.", _config.AlwaysOpenDefaultImport, v => _config.AlwaysOpenDefaultImport = v); - Checkbox("Handle PCP Files", - "When encountering specific mods, usually but not necessarily denoted by a .pcp file ending, Penumbra will automatically try to create an associated collection and assign it to a specific character for this mod package. This can turn this behaviour off if unwanted.", - !_config.PcpSettings.DisableHandling, v => _config.PcpSettings.DisableHandling = !v); - - var active = _config.DeleteModModifier.IsActive(); - ImGui.SameLine(); - if (ImUtf8.ButtonEx("Delete all PCP Mods"u8, "Deletes all mods tagged with 'PCP' from the mod list."u8, disabled: !active)) - _pcpService.CleanPcpMods(); - if (!active) - ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking."); - - ImGui.SameLine(); - if (ImUtf8.ButtonEx("Delete all PCP Collections"u8, "Deletes all collections whose name starts with 'PCP/' from the collection list."u8, - disabled: !active)) - _pcpService.CleanPcpCollections(); - if (!active) - ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking."); - - Checkbox("Allow Other Plugins Access to PCP Handling", - "When creating or importing PCP files, other plugins can add and interpret their own data to the character.json file.", - _config.PcpSettings.AllowIpc, v => _config.PcpSettings.AllowIpc = v); - - Checkbox("Create PCP Collections", - "When importing PCP files, create the associated collection.", - _config.PcpSettings.CreateCollection, v => _config.PcpSettings.CreateCollection = v); - - Checkbox("Assign PCP Collections", - "When importing PCP files and creating the associated collection, assign it to the associated character.", - _config.PcpSettings.AssignCollection, v => _config.PcpSettings.AssignCollection = v); DrawDefaultModImportPath(); DrawDefaultModAuthor(); DrawDefaultModImportFolder(); - DrawPcpFolder(); DrawDefaultModExportPath(); - Checkbox("Enable Directory Watcher", - "Enables a File Watcher that automatically listens for Mod files that enter a specified directory, causing Penumbra to open a popup to import these mods.", - _config.EnableDirectoryWatch, _fileWatcher.Toggle); - Checkbox("Enable Fully Automatic Import", - "Uses the File Watcher in order to skip the query popup and automatically import any new mods.", - _config.EnableAutomaticModImport, v => _config.EnableAutomaticModImport = v); - DrawFileWatcherPath(); } @@ -736,46 +680,6 @@ public class SettingsTab : ITab, IUiService + "Keep this empty to use the root directory."); } - private string? _tempWatchDirectory; - - /// Draw input for the Automatic Mod import path. - private void DrawFileWatcherPath() - { - var tmp = _tempWatchDirectory ?? _config.WatchDirectory; - var spacing = new Vector2(UiHelpers.ScaleX3); - using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, spacing); - ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton3); - if (ImGui.InputText("##fileWatchPath", ref tmp, 256)) - _tempWatchDirectory = tmp; - - if (ImGui.IsItemDeactivated() && _tempWatchDirectory is not null) - { - if (ImGui.IsItemDeactivatedAfterEdit()) - _fileWatcher.UpdateDirectory(_tempWatchDirectory); - _tempWatchDirectory = null; - } - - ImGui.SameLine(); - if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.Folder.ToIconString()}##fileWatch", UiHelpers.IconButtonSize, - "Select a directory via dialog.", false, true)) - { - var startDir = _config.WatchDirectory.Length > 0 && Directory.Exists(_config.WatchDirectory) - ? _config.WatchDirectory - : Directory.Exists(_config.ModDirectory) - ? _config.ModDirectory - : null; - _fileDialog.OpenFolderPicker("Choose Automatic Import Directory", (b, s) => - { - if (b) - _fileWatcher.UpdateDirectory(s); - }, startDir, false); - } - - style.Pop(); - ImGuiUtil.LabeledHelpMarker("Automatic Import Director", - "Choose the Directory the File Watcher listens to."); - } - /// Draw input for the default name to input as author into newly generated mods. private void DrawDefaultModAuthor() { @@ -805,21 +709,6 @@ public class SettingsTab : ITab, IUiService "Set the default Penumbra mod folder to place newly imported mods into.\nLeave blank to import into Root."); } - /// Draw input for the default folder to sort put newly imported mods into. - private void DrawPcpFolder() - { - var tmp = _config.PcpSettings.FolderName; - ImGui.SetNextItemWidth(UiHelpers.InputTextWidth.X); - if (ImUtf8.InputText("##pcpFolder"u8, ref tmp)) - _config.PcpSettings.FolderName = tmp; - - if (ImGui.IsItemDeactivatedAfterEdit()) - _config.Save(); - - ImGuiUtil.LabeledHelpMarker("Default PCP Organizational Folder", - "The folder any penumbra character packs are moved to on import.\nLeave blank to import into Root."); - } - /// Draw all settings pertaining to advanced editing of mods. private void DrawModEditorSettings() @@ -872,9 +761,8 @@ public class SettingsTab : ITab, IUiService "Normally, metadata changes that equal their default values, which are sometimes exported by TexTools, are discarded. " + "Toggle this to keep them, for example if an option in a mod is supposed to disable a metadata change from a prior option.", _config.KeepDefaultMetaChanges, v => _config.KeepDefaultMetaChanges = v); - Checkbox("Enable Custom Shape and Attribute Support", - "Penumbra will allow for custom shape keys and attributes for modded models to be considered and combined.", - _config.EnableCustomShapes, _attributeHook.SetState); + Checkbox("Enable Custom Shape and Attribute Support", "Penumbra will allow for custom shape keys and attributes for modded models to be considered and combined.", + _config.EnableCustomShapes, _attributeHook.SetState); DrawWaitForPluginsReflection(); DrawEnableHttpApiBox(); DrawEnableDebugModeBox(); @@ -1162,9 +1050,6 @@ public class SettingsTab : ITab, IUiService ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing())); if (ImGui.Button("Show Changelogs", new Vector2(width, 0))) _penumbra.ForceChangelogOpen(); - - ImGui.SetCursorPos(new Vector2(xPos, 5 * ImGui.GetFrameHeightWithSpacing())); - CustomGui.DrawKofiPatreonButton(Penumbra.Messager, new Vector2(width, 0)); } private void DrawPredefinedTagsSection() diff --git a/Penumbra/UI/UiHelpers.cs b/Penumbra/UI/UiHelpers.cs index 9fe90ee8..deba7023 100644 --- a/Penumbra/UI/UiHelpers.cs +++ b/Penumbra/UI/UiHelpers.cs @@ -1,6 +1,6 @@ using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.Utility; -using Dalamud.Bindings.ImGui; +using ImGuiNET; using OtterGui; using OtterGui.Classes; using OtterGui.Raii; @@ -13,11 +13,11 @@ public static class UiHelpers { /// Draw text given by a ByteString. public static unsafe void Text(ByteString s) - => ImGuiNative.TextUnformatted(s.Path, s.Path + s.Length); + => ImGuiNative.igTextUnformatted(s.Path, s.Path + s.Length); /// Draw text given by a byte pointer and length. public static unsafe void Text(byte* s, int length) - => ImGuiNative.TextUnformatted(s, s + length); + => ImGuiNative.igTextUnformatted(s, s + length); /// Draw text given by a byte span. public static unsafe void Text(ReadOnlySpan s) @@ -36,7 +36,7 @@ public static class UiHelpers public static unsafe bool Selectable(ByteString s, bool selected) { var tmp = (byte)(selected ? 1 : 0); - return ImGuiNative.Selectable(s.Path, tmp, ImGuiSelectableFlags.None, Vector2.Zero) != 0; + return ImGuiNative.igSelectable_Bool(s.Path, tmp, ImGuiSelectableFlags.None, Vector2.Zero) != 0; } /// @@ -45,8 +45,8 @@ public static class UiHelpers /// public static unsafe void CopyOnClickSelectable(ByteString text) { - if (ImGuiNative.Selectable(text.Path, 0, ImGuiSelectableFlags.None, Vector2.Zero) != 0) - ImGuiNative.SetClipboardText(text.Path); + if (ImGuiNative.igSelectable_Bool(text.Path, 0, ImGuiSelectableFlags.None, Vector2.Zero) != 0) + ImGuiNative.igSetClipboardText(text.Path); if (ImGui.IsItemHovered()) ImGui.SetTooltip("Click to copy to clipboard."); diff --git a/Penumbra/packages.lock.json b/Penumbra/packages.lock.json index 7499bffa..4a162f8f 100644 --- a/Penumbra/packages.lock.json +++ b/Penumbra/packages.lock.json @@ -19,9 +19,9 @@ }, "PeNet": { "type": "Direct", - "requested": "[5.1.0, )", - "resolved": "5.1.0", - "contentHash": "XSd1PUwWo5uI8iqVHk7Mm02RT1bjndtAYsaRwLmdYZoHOAmb4ohkvRcZiqxJ7iLfBfdiwm+PHKQIMqDmOavBtw==", + "requested": "[4.1.1, )", + "resolved": "4.1.1", + "contentHash": "TiRyOVcg1Bh2FyP6Dm2NEiYzemSlQderhaxuH3XWNyTYsnHrm1n/xvoTftgMwsWD4C/3kTqJw93oZOvHojJfKg==", "dependencies": { "PeNet.Asn1": "2.0.1", "System.Security.Cryptography.Pkcs": "8.0.1" @@ -29,47 +29,34 @@ }, "SharpCompress": { "type": "Direct", - "requested": "[0.40.0, )", - "resolved": "0.40.0", - "contentHash": "yP/aFX1jqGikVF7u2f05VEaWN4aCaKNLxSas82UgA2GGVECxq/BcqZx3STHCJ78qilo1azEOk1XpBglIuGMb7w==", + "requested": "[0.39.0, )", + "resolved": "0.39.0", + "contentHash": "0esqIUDlg68Z7+Weuge4QzEvNtawUO4obTJFL7xuf4DBHMxVRr+wbNgiX9arMrj3kGXQSvLe0zbZG3oxpkwJOA==", "dependencies": { "System.Buffers": "4.6.0", - "ZstdSharp.Port": "0.8.5" + "ZstdSharp.Port": "0.8.4" } }, "SharpGLTF.Core": { "type": "Direct", - "requested": "[1.0.5, )", - "resolved": "1.0.5", - "contentHash": "HNHKPqaHXm7R1nlXZ764K5UI02IeDOQ5DQKLjwYUVNTsSW27jJpw+wLGQx6ZFoiFYqUlyZjmsu+WfEak2GmJAg==" + "requested": "[1.0.3, )", + "resolved": "1.0.3", + "contentHash": "su+Flcg2g6GgOIgulRGBDMHA6zY5NBx6NYH1Ayd6iBbSbwspHsN2VQgZfANgJy92cBf7qtpjC0uMiShbO+TEEg==" }, "SharpGLTF.Toolkit": { "type": "Direct", - "requested": "[1.0.5, )", - "resolved": "1.0.5", - "contentHash": "piQKk7PH2pSWQSQmCSd8cYPaDtAy/ppAD+Mrh2RUhhHI8awl81HqqLyAauwQhJwea3LNaiJ6f4ehZuOGk89TlA==", + "requested": "[1.0.3, )", + "resolved": "1.0.3", + "contentHash": "vkEuf8ch76NNgZXU/3zoXTIXRO0o14H3aRoSFzcuUQb0PTxvV6jEfmWkUVO6JtLDuFCIimqZaf3hdxr32ltpfQ==", "dependencies": { - "SharpGLTF.Runtime": "1.0.5" + "SharpGLTF.Runtime": "1.0.3" } }, "SixLabors.ImageSharp": { "type": "Direct", - "requested": "[3.1.11, )", - "resolved": "3.1.11", - "contentHash": "JfPLyigLthuE50yi6tMt7Amrenr/fA31t2CvJyhy/kQmfulIBAqo5T/YFUSRHtuYPXRSaUHygFeh6Qd933EoSw==" - }, - "FlatSharp.Compiler": { - "type": "Transitive", - "resolved": "7.9.0", - "contentHash": "MU6808xvdbWJ3Ev+5PKalqQuzvVbn1DzzQH8txRDHGFUNDvHjd+ejqpvnYc9BSJ8Qp8VjkkpJD8OzRYilbPp3A==" - }, - "FlatSharp.Runtime": { - "type": "Transitive", - "resolved": "7.9.0", - "contentHash": "Bm8+WqzEsWNpxqrD5x4x+zQ8dyINlToCreM5FI2oNSfUVc9U9ZB+qztX/jd8rlJb3r0vBSlPwVLpw0xBtPa3Vw==", - "dependencies": { - "System.Memory": "4.5.5" - } + "requested": "[3.1.7, )", + "resolved": "3.1.7", + "contentHash": "9fIOOAsyLFid6qKypM2Iy0Z3Q9yoanV8VoYAHtI2sYGMNKzhvRTjgFDHonIiVe+ANtxIxM6SuqUzj0r91nItpA==" }, "JetBrains.Annotations": { "type": "Transitive", @@ -96,10 +83,10 @@ }, "SharpGLTF.Runtime": { "type": "Transitive", - "resolved": "1.0.5", - "contentHash": "EVP32k4LqERxSVICiupT8xQvhHSHJCiXajBjNpqdfdajtREHayuVhH0Jmk6uSjTLX8/IIH9XfT34sw3TwvCziw==", + "resolved": "1.0.3", + "contentHash": "W0bg2WyXlcSAJVu153hNUNm+BU4RP46yLwGD4099hSm8dsXG/H+J95PBoLJbIq8KGVkUWvfM0+XWHoEkCyd50A==", "dependencies": { - "SharpGLTF.Core": "1.0.5" + "SharpGLTF.Core": "1.0.3" } }, "System.Buffers": { @@ -107,11 +94,6 @@ "resolved": "4.6.0", "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA==" }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.5", - "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==" - }, "System.Security.Cryptography.Pkcs": { "type": "Transitive", "resolved": "8.0.1", @@ -132,8 +114,8 @@ }, "ZstdSharp.Port": { "type": "Transitive", - "resolved": "0.8.5", - "contentHash": "TR4j17WeVSEb3ncgL2NqlXEqcy04I+Kk9CaebNDplUeL8XOgjkZ7fP4Wg4grBdPLIqsV86p2QaXTkZoRMVOsew==" + "resolved": "0.8.4", + "contentHash": "eieSXq3kakCUXbgdxkKaRqWS6hF0KBJcqok9LlDCs60GOyrynLvPOcQ0pRw7shdPF7lh/VepJ9cP9n9HHc759g==" }, "ottergui": { "type": "Project", @@ -151,10 +133,8 @@ "penumbra.gamedata": { "type": "Project", "dependencies": { - "FlatSharp.Compiler": "[7.9.0, )", - "FlatSharp.Runtime": "[7.9.0, )", "OtterGui": "[1.0.0, )", - "Penumbra.Api": "[5.10.0, )", + "Penumbra.Api": "[5.6.1, )", "Penumbra.String": "[1.0.6, )" } }, diff --git a/repo.json b/repo.json index 7ddffd7c..a6cec268 100644 --- a/repo.json +++ b/repo.json @@ -1,16 +1,16 @@ [ { - "Author": "Ottermandias, Nylfae, Adam, Wintermute", + "Author": "Ottermandias, Adam, Wintermute", "Name": "Penumbra", "Punchline": "Runtime mod loader and manager.", "Description": "Runtime mod loader and manager.", "InternalName": "Penumbra", - "AssemblyVersion": "1.5.1.8", - "TestingAssemblyVersion": "1.5.1.8", + "AssemblyVersion": "1.4.0.1", + "TestingAssemblyVersion": "1.4.0.3", "RepoUrl": "https://github.com/xivdev/Penumbra", "ApplicableVersion": "any", - "DalamudApiLevel": 13, - "TestingDalamudApiLevel": 13, + "DalamudApiLevel": 12, + "TestingDalamudApiLevel": 12, "IsHide": "False", "IsTestingExclusive": "False", "DownloadCount": 0, @@ -18,9 +18,9 @@ "LoadPriority": 69420, "LoadRequiredState": 2, "LoadSync": true, - "DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.8/Penumbra.zip", - "DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.8/Penumbra.zip", - "DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.5.1.8/Penumbra.zip", + "DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.4.0.1/Penumbra.zip", + "DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/testing_1.4.0.3/Penumbra.zip", + "DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.4.0.1/Penumbra.zip", "IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png" } ]