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)