diff --git a/Penumbra.GameData/Structs/CharacterEquip.cs b/Penumbra.GameData/Structs/CharacterEquip.cs deleted file mode 100644 index d045bd58..00000000 --- a/Penumbra.GameData/Structs/CharacterEquip.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using Penumbra.GameData.Enums; -using Penumbra.String.Functions; - -namespace Penumbra.GameData.Structs; - -public readonly unsafe struct CharacterEquip -{ - public const int Slots = 10; - public const int Size = CharacterArmor.Size * Slots; - - public static readonly CharacterEquip Null = new(null); - - private readonly CharacterArmor* _armor; - - public IntPtr Address - => ( IntPtr )_armor; - - public ref CharacterArmor this[ int idx ] - => ref _armor[ idx ]; - - public ref CharacterArmor this[ uint idx ] - => ref _armor[ idx ]; - - public ref CharacterArmor this[ EquipSlot slot ] - => ref _armor[ IndexOf( slot ) ]; - - public ref CharacterArmor Head - => ref _armor[ 0 ]; - - public ref CharacterArmor Body - => ref _armor[ 1 ]; - - public ref CharacterArmor Hands - => ref _armor[ 2 ]; - - public ref CharacterArmor Legs - => ref _armor[ 3 ]; - - public ref CharacterArmor Feet - => ref _armor[ 4 ]; - - public ref CharacterArmor Ears - => ref _armor[ 5 ]; - - public ref CharacterArmor Neck - => ref _armor[ 6 ]; - - public ref CharacterArmor Wrists - => ref _armor[ 7 ]; - - public ref CharacterArmor RFinger - => ref _armor[ 8 ]; - - public ref CharacterArmor LFinger - => ref _armor[ 9 ]; - - public CharacterEquip( CharacterArmor* val ) - => _armor = val; - - public static implicit operator CharacterEquip( CharacterArmor* val ) - => new(val); - - public static implicit operator CharacterEquip( IntPtr val ) - => new(( CharacterArmor* )val); - - public static implicit operator CharacterEquip( ReadOnlySpan< CharacterArmor > val ) - { - if( val.Length != 10 ) - { - throw new ArgumentException( "Invalid number of equipment pieces in span." ); - } - - fixed( CharacterArmor* ptr = val ) - { - return new CharacterEquip( ptr ); - } - } - - public static implicit operator bool( CharacterEquip equip ) - => equip._armor != null; - - public static bool operator true( CharacterEquip equip ) - => equip._armor != null; - - public static bool operator false( CharacterEquip equip ) - => equip._armor == null; - - public static bool operator !( CharacterEquip equip ) - => equip._armor == null; - - private static int IndexOf( EquipSlot slot ) - { - return slot switch - { - EquipSlot.Head => 0, - EquipSlot.Body => 1, - EquipSlot.Hands => 2, - EquipSlot.Legs => 3, - EquipSlot.Feet => 4, - EquipSlot.Ears => 5, - EquipSlot.Neck => 6, - EquipSlot.Wrists => 7, - EquipSlot.RFinger => 8, - EquipSlot.LFinger => 9, - _ => throw new ArgumentOutOfRangeException( nameof( slot ), slot, null ), - }; - } - - - public void Load( CharacterEquip source ) - { - MemoryUtility.MemCpyUnchecked( _armor, source._armor, sizeof( CharacterArmor ) * 10 ); - } - - public bool Equals( CharacterEquip other ) - => MemoryUtility.MemCmpUnchecked( ( void* )_armor, ( void* )other._armor, sizeof( CharacterArmor ) * 10 ) == 0; -} \ No newline at end of file diff --git a/Penumbra/Api/PenumbraApi.cs b/Penumbra/Api/PenumbraApi.cs index 369374c6..9b7e6410 100644 --- a/Penumbra/Api/PenumbraApi.cs +++ b/Penumbra/Api/PenumbraApi.cs @@ -258,16 +258,17 @@ public class PenumbraApi : IDisposable, IPenumbraApi if (!Enum.IsDefined(tab)) return PenumbraApiEc.InvalidArgument; - if (tab != TabType.None) - _configWindow.SelectTab(tab); - if (tab == TabType.Mods && (modDirectory.Length > 0 || modName.Length > 0)) { if (_modManager.TryGetMod(modDirectory, modName, out var mod)) - _configWindow.SelectMod(mod); + _communicator.SelectTab.Invoke(tab, mod); else return PenumbraApiEc.ModMissing; } + else if (tab != TabType.None) + { + _communicator.SelectTab.Invoke(tab); + } return PenumbraApiEc.Success; } @@ -1127,7 +1128,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi { if (manips.Add(manip)) continue; - + Penumbra.Log.Warning($"Manipulation {manip} {manip.EntryToString()} is invalid and was skipped."); manips = null; return false; diff --git a/Penumbra/Communication/SelectTab.cs b/Penumbra/Communication/SelectTab.cs new file mode 100644 index 00000000..3dcf6d1b --- /dev/null +++ b/Penumbra/Communication/SelectTab.cs @@ -0,0 +1,29 @@ +using System; +using OtterGui.Classes; +using Penumbra.Api.Enums; +using Penumbra.Mods; + +namespace Penumbra.Communication; + +/// +/// Trigger to select a tab and mod in the Config Window. +/// +/// Parameter is the selected tab. +/// Parameter is the selected mod, if any. +/// +/// +public sealed class SelectTab : EventWrapper, SelectTab.Priority> +{ + public enum Priority + { + /// + ConfigTabBar = 0, + } + + public SelectTab() + : base(nameof(SelectTab)) + { } + + public void Invoke(TabType tab = TabType.None, Mod? mod = null) + => Invoke(this, tab, mod); +} diff --git a/Penumbra/Interop/ResourceTree/ResourceTree.cs b/Penumbra/Interop/ResourceTree/ResourceTree.cs index 80e56231..e7de1a4a 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTree.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTree.cs @@ -89,7 +89,7 @@ public class ResourceTree ? imcNode.WithName(imcNode.Name ?? $"{subObjectNamePrefix} #{subObjectIndex}, IMC #{i}") : imcNode); - var mdl = (RenderModel*)subObject->ModelArray[i]; + var mdl = (RenderModel*)subObject->Models[i]; var mdlNode = subObjectContext.CreateNodeFromRenderModel(mdl); if (mdlNode != null) subObjectNodes.Add(globalContext.WithNames diff --git a/Penumbra/Mods/Manager/ModDataEditor.cs b/Penumbra/Mods/Manager/ModDataEditor.cs index d8116998..b6a0036f 100644 --- a/Penumbra/Mods/Manager/ModDataEditor.cs +++ b/Penumbra/Mods/Manager/ModDataEditor.cs @@ -267,7 +267,6 @@ public class ModDataEditor _communicatorService.ModDataChanged.Invoke(ModDataChangeType.Favorite, mod, null); } - private void ChangeTag(Mod mod, int tagIdx, string newTag, bool local) { var which = local ? mod.LocalTags : mod.ModTags; diff --git a/Penumbra/Services/CommunicatorService.cs b/Penumbra/Services/CommunicatorService.cs index 3e499317..784b7f89 100644 --- a/Penumbra/Services/CommunicatorService.cs +++ b/Penumbra/Services/CommunicatorService.cs @@ -63,6 +63,9 @@ public class CommunicatorService : IDisposable /// public readonly ChangedItemClick ChangedItemClick = new(); + /// + public readonly SelectTab SelectTab = new(); + public void Dispose() { CollectionChange.Dispose(); @@ -82,5 +85,6 @@ public class CommunicatorService : IDisposable PostSettingsPanelDraw.Dispose(); ChangedItemHover.Dispose(); ChangedItemClick.Dispose(); + SelectTab.Dispose(); } } diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index ebd04ef6..2ce27052 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -5,8 +5,6 @@ using Dalamud.Plugin; using ImGuiNET; using OtterGui; using OtterGui.Raii; -using Penumbra.Api.Enums; -using Penumbra.Mods; using Penumbra.Services; using Penumbra.UI.Classes; using Penumbra.UI.Tabs; @@ -24,12 +22,6 @@ public sealed class ConfigWindow : Window private ConfigTabBar _configTabs = null!; private string? _lastException; - public void SelectTab(TabType tab) - => _configTabs.SelectTab = tab; - - public void SelectMod(Mod mod) - => _configTabs.Mods.SelectMod = mod; - public ConfigWindow(PerformanceTracker tracker, DalamudPluginInterface pi, Configuration config, ValidityChecker checker, TutorialService tutorial) : base(GetLabel(checker)) @@ -41,14 +33,14 @@ public sealed class ConfigWindow : Window RespectCloseHotkey = true; tutorial.UpdateTutorialStep(); - IsOpen = _config.DebugMode; + IsOpen = _config.DebugMode; } public void Setup(Penumbra penumbra, ConfigTabBar configTabs) { - _penumbra = penumbra; - _configTabs = configTabs; - SelectTab(_config.SelectedTab); + _penumbra = penumbra; + _configTabs = configTabs; + _configTabs.SelectTab = _config.SelectedTab; } public override bool DrawConditions() diff --git a/Penumbra/UI/Tabs/ChangedItemsTab.cs b/Penumbra/UI/Tabs/ChangedItemsTab.cs index 7e725e18..9b929c60 100644 --- a/Penumbra/UI/Tabs/ChangedItemsTab.cs +++ b/Penumbra/UI/Tabs/ChangedItemsTab.cs @@ -10,6 +10,7 @@ using OtterGui.Widgets; using Penumbra.Api.Enums; using Penumbra.Collections.Manager; using Penumbra.Mods; +using Penumbra.Services; using Penumbra.UI.Classes; namespace Penumbra.UI.Tabs; @@ -19,18 +20,17 @@ public class ChangedItemsTab : ITab private readonly CollectionManager _collectionManager; private readonly ChangedItemDrawer _drawer; private readonly CollectionSelectHeader _collectionHeader; - private ConfigTabBar? _tabBar = null; + private readonly CommunicatorService _communicator; - public ChangedItemsTab(CollectionManager collectionManager, CollectionSelectHeader collectionHeader, ChangedItemDrawer drawer) + public ChangedItemsTab(CollectionManager collectionManager, CollectionSelectHeader collectionHeader, ChangedItemDrawer drawer, + CommunicatorService communicator) { _collectionManager = collectionManager; _collectionHeader = collectionHeader; _drawer = drawer; + _communicator = communicator; } - public void SetTabBar(ConfigTabBar tabBar) - => _tabBar = tabBar; - public ReadOnlySpan Label => "Changed Items"u8; @@ -106,22 +106,18 @@ public class ChangedItemsTab : ITab if (mods.Count <= 0) return; - var first = mods[0]; + var first = mods[0]; using var style = ImRaii.PushStyle(ImGuiStyleVar.SelectableTextAlign, new Vector2(0, 0.5f)); - if (ImGui.Selectable(first.Name, false, ImGuiSelectableFlags.None, new Vector2(0, ImGui.GetFrameHeight())) - && ImGui.GetIO().KeyCtrl - && _tabBar != null - && first is Mod mod) - { - _tabBar.SelectTab = TabType.Mods; - _tabBar.Mods.SelectMod = mod; - } + if (ImGui.Selectable(first.Name, false, ImGuiSelectableFlags.None, new Vector2(0, ImGui.GetFrameHeight())) + && ImGui.GetIO().KeyCtrl + && first is Mod mod) + _communicator.SelectTab.Invoke(TabType.Mods, mod); if (ImGui.IsItemHovered()) { - using var _ = ImRaii.Tooltip(); - ImGui.TextUnformatted("Hold Control and click to jump to mod.\n"); - if (mods.Count > 1) + using var _ = ImRaii.Tooltip(); + ImGui.TextUnformatted("Hold Control and click to jump to mod.\n"); + if (mods.Count > 1) ImGui.TextUnformatted("Other mods affecting this item:\n" + string.Join("\n", mods.Skip(1).Select(m => m.Name))); } } diff --git a/Penumbra/UI/Tabs/ConfigTabBar.cs b/Penumbra/UI/Tabs/ConfigTabBar.cs index 4105f2e3..49b6348a 100644 --- a/Penumbra/UI/Tabs/ConfigTabBar.cs +++ b/Penumbra/UI/Tabs/ConfigTabBar.cs @@ -2,11 +2,15 @@ using System; using ImGuiNET; using OtterGui.Widgets; using Penumbra.Api.Enums; +using Penumbra.Mods; +using Penumbra.Services; namespace Penumbra.UI.Tabs; -public class ConfigTabBar +public class ConfigTabBar : IDisposable { + private readonly CommunicatorService _communicator; + public readonly SettingsTab Settings; public readonly ModsTab Mods; public readonly CollectionsTab Collections; @@ -22,9 +26,12 @@ public class ConfigTabBar /// The tab to select on the next Draw call, if any. public TabType SelectTab = TabType.None; - public ConfigTabBar(SettingsTab settings, ModsTab mods, CollectionsTab collections, ChangedItemsTab changedItems, EffectiveTab effective, - DebugTab debug, ResourceTab resource, ResourceWatcher watcher, OnScreenTab onScreenTab) + public ConfigTabBar(CommunicatorService communicator, SettingsTab settings, ModsTab mods, CollectionsTab collections, + ChangedItemsTab changedItems, EffectiveTab effective, DebugTab debug, ResourceTab resource, ResourceWatcher watcher, + OnScreenTab onScreenTab) { + _communicator = communicator; + Settings = settings; Mods = mods; Collections = collections; @@ -46,9 +53,12 @@ public class ConfigTabBar Resource, Watcher, }; - ChangedItems.SetTabBar(this); + _communicator.SelectTab.Subscribe(OnSelectTab, Communication.SelectTab.Priority.ConfigTabBar); } + public void Dispose() + => _communicator.SelectTab.Unsubscribe(OnSelectTab); + public TabType Draw() { if (TabBar.Draw(string.Empty, ImGuiTabBarFlags.NoTooltip, ToLabel(SelectTab), out var currentLabel, () => { }, Tabs)) @@ -87,4 +97,11 @@ public class ConfigTabBar // @formatter:on return TabType.None; } + + private void OnSelectTab(TabType tab, Mod? mod) + { + SelectTab = tab; + if (mod != null) + Mods.SelectMod = mod; + } } diff --git a/Penumbra/UI/Tabs/DebugTab.cs b/Penumbra/UI/Tabs/DebugTab.cs index 9acecce9..2fd21c6f 100644 --- a/Penumbra/UI/Tabs/DebugTab.cs +++ b/Penumbra/UI/Tabs/DebugTab.cs @@ -696,7 +696,7 @@ public class DebugTab : Window, ITab if (imc != null) UiHelpers.Text(imc); - var mdl = (RenderModel*)model->ModelArray[i]; + var mdl = (RenderModel*)model->Models[i]; ImGui.TableNextColumn(); ImGui.TextUnformatted(mdl == null ? "NULL" : $"0x{(ulong)mdl:X}"); if (mdl == null || mdl->ResourceHandle == null || mdl->ResourceHandle->Category != ResourceCategory.Chara)