mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Add some methods and interface to view currently Changed Items.
This commit is contained in:
parent
982385ccbb
commit
0c0eeec158
9 changed files with 219 additions and 40 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Lumina.Data;
|
using Lumina.Data;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
@ -43,5 +44,8 @@ namespace Penumbra.Api
|
||||||
|
|
||||||
// Try to load a given gamePath with the resolved path from Penumbra.
|
// Try to load a given gamePath with the resolved path from Penumbra.
|
||||||
public T? GetFile<T>( string gamePath, string characterName ) where T : FileResource;
|
public T? GetFile<T>( string gamePath, string characterName ) where T : FileResource;
|
||||||
|
|
||||||
|
// Gets a dictionary of effected items from a collection
|
||||||
|
public IReadOnlyDictionary< string, object? > GetChangedItemsForCollection(string collectionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Lumina.Data;
|
using Lumina.Data;
|
||||||
|
using Lumina.Data.Parsing;
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Util;
|
using Penumbra.GameData.Util;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
|
|
@ -131,5 +135,32 @@ namespace Penumbra.Api
|
||||||
|
|
||||||
public T? GetFile< T >( string gamePath, string characterName ) where T : FileResource
|
public T? GetFile< T >( string gamePath, string characterName ) where T : FileResource
|
||||||
=> GetFileIntern< T >( ResolvePath( gamePath, characterName ) );
|
=> GetFileIntern< T >( ResolvePath( gamePath, characterName ) );
|
||||||
|
|
||||||
|
public IReadOnlyDictionary< string, object? > GetChangedItemsForCollection( string collectionName )
|
||||||
|
{
|
||||||
|
CheckInitialized();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var modManager = Service< ModManager >.Get();
|
||||||
|
if( !modManager.Collections.Collections.TryGetValue( collectionName, out var collection ) )
|
||||||
|
{
|
||||||
|
collection = ModCollection.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( collection.Cache != null )
|
||||||
|
{
|
||||||
|
return collection.Cache.ChangedItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginLog.Warning( $"Collection {collectionName} does not exist or is not loaded." );
|
||||||
|
return new Dictionary< string, object? >();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"Could not obtain Changed Items for {collectionName}:\n{e}" );
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Dalamud.Game.ClientState.Objects.Types;
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
|
@ -18,15 +19,17 @@ namespace Penumbra.Api
|
||||||
|
|
||||||
public const string LabelProviderChangedItemTooltip = "Penumbra.ChangedItemTooltip";
|
public const string LabelProviderChangedItemTooltip = "Penumbra.ChangedItemTooltip";
|
||||||
public const string LabelProviderChangedItemClick = "Penumbra.ChangedItemClick";
|
public const string LabelProviderChangedItemClick = "Penumbra.ChangedItemClick";
|
||||||
|
public const string LabelProviderGetChangedItems = "Penumbra.GetChangedItems";
|
||||||
|
|
||||||
internal ICallGateProvider< int >? ProviderApiVersion;
|
internal ICallGateProvider< int >? ProviderApiVersion;
|
||||||
internal ICallGateProvider< string, int, object >? ProviderRedrawName;
|
internal ICallGateProvider< string, int, object >? ProviderRedrawName;
|
||||||
internal ICallGateProvider< GameObject, int, object >? ProviderRedrawObject;
|
internal ICallGateProvider< GameObject, int, object >? ProviderRedrawObject;
|
||||||
internal ICallGateProvider< int, object >? ProviderRedrawAll;
|
internal ICallGateProvider< int, object >? ProviderRedrawAll;
|
||||||
internal ICallGateProvider< string, string >? ProviderResolveDefault;
|
internal ICallGateProvider< string, string >? ProviderResolveDefault;
|
||||||
internal ICallGateProvider< string, string, string >? ProviderResolveCharacter;
|
internal ICallGateProvider< string, string, string >? ProviderResolveCharacter;
|
||||||
internal ICallGateProvider< ChangedItemType, uint, object >? ProviderChangedItemTooltip;
|
internal ICallGateProvider< ChangedItemType, uint, object >? ProviderChangedItemTooltip;
|
||||||
internal ICallGateProvider< MouseButton, ChangedItemType, uint, object >? ProviderChangedItemClick;
|
internal ICallGateProvider< MouseButton, ChangedItemType, uint, object >? ProviderChangedItemClick;
|
||||||
|
internal ICallGateProvider< string, IReadOnlyDictionary< string, object? > >? ProviderGetChangedItems;
|
||||||
|
|
||||||
internal readonly IPenumbraApi Api;
|
internal readonly IPenumbraApi Api;
|
||||||
|
|
||||||
|
|
@ -137,6 +140,16 @@ namespace Penumbra.Api
|
||||||
{
|
{
|
||||||
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
|
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProviderGetChangedItems = pi.GetIpcProvider< string, IReadOnlyDictionary< string, object? > >( LabelProviderGetChangedItems );
|
||||||
|
ProviderGetChangedItems.RegisterFunc( api.GetChangedItemsForCollection );
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
@ -147,6 +160,7 @@ namespace Penumbra.Api
|
||||||
ProviderRedrawAll?.UnregisterAction();
|
ProviderRedrawAll?.UnregisterAction();
|
||||||
ProviderResolveDefault?.UnregisterFunc();
|
ProviderResolveDefault?.UnregisterFunc();
|
||||||
ProviderResolveCharacter?.UnregisterFunc();
|
ProviderResolveCharacter?.UnregisterFunc();
|
||||||
|
ProviderGetChangedItems?.UnregisterFunc();
|
||||||
Api.ChangedItemClicked -= OnClick;
|
Api.ChangedItemClicked -= OnClick;
|
||||||
Api.ChangedItemTooltip -= OnTooltip;
|
Api.ChangedItemTooltip -= OnTooltip;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
@ -24,10 +25,20 @@ namespace Penumbra.Mods
|
||||||
|
|
||||||
public readonly Dictionary< string, Mod.Mod > AvailableMods = new();
|
public readonly Dictionary< string, Mod.Mod > AvailableMods = new();
|
||||||
|
|
||||||
public readonly Dictionary< GamePath, FileInfo > ResolvedFiles = new();
|
private readonly SortedList< string, object? > _changedItems = new();
|
||||||
public readonly Dictionary< GamePath, GamePath > SwappedFiles = new();
|
public readonly Dictionary< GamePath, FileInfo > ResolvedFiles = new();
|
||||||
public readonly HashSet< FileInfo > MissingFiles = new();
|
public readonly Dictionary< GamePath, GamePath > SwappedFiles = new();
|
||||||
public readonly MetaManager MetaManipulations;
|
public readonly HashSet< FileInfo > MissingFiles = new();
|
||||||
|
public readonly MetaManager MetaManipulations;
|
||||||
|
|
||||||
|
public IReadOnlyDictionary< string, object? > ChangedItems
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SetChangedItems();
|
||||||
|
return _changedItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ModCollectionCache( string collectionName, DirectoryInfo tempDir )
|
public ModCollectionCache( string collectionName, DirectoryInfo tempDir )
|
||||||
=> MetaManipulations = new MetaManager( collectionName, ResolvedFiles, tempDir );
|
=> MetaManipulations = new MetaManager( collectionName, ResolvedFiles, tempDir );
|
||||||
|
|
@ -52,6 +63,7 @@ namespace Penumbra.Mods
|
||||||
SwappedFiles.Clear();
|
SwappedFiles.Clear();
|
||||||
MissingFiles.Clear();
|
MissingFiles.Clear();
|
||||||
RegisteredFiles.Clear();
|
RegisteredFiles.Clear();
|
||||||
|
_changedItems.Clear();
|
||||||
|
|
||||||
foreach( var mod in AvailableMods.Values
|
foreach( var mod in AvailableMods.Values
|
||||||
.Where( m => m.Settings.Enabled )
|
.Where( m => m.Settings.Enabled )
|
||||||
|
|
@ -65,6 +77,35 @@ namespace Penumbra.Mods
|
||||||
AddMetaFiles();
|
AddMetaFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetChangedItems()
|
||||||
|
{
|
||||||
|
if( _changedItems.Count > 0 || ResolvedFiles.Count + SwappedFiles.Count + MetaManipulations.Count == 0 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Skip meta files because IMCs would result in far too many false-positive items,
|
||||||
|
// since they are per set instead of per item-slot/item/variant.
|
||||||
|
var metaFiles = MetaManipulations.Files.Select( p => p.Item1 ).ToHashSet();
|
||||||
|
var identifier = GameData.GameData.GetIdentifier();
|
||||||
|
foreach( var resolved in ResolvedFiles.Keys.Where( file => !metaFiles.Contains( file ) ) )
|
||||||
|
{
|
||||||
|
identifier.Identify( _changedItems, resolved );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( var swapped in SwappedFiles.Keys )
|
||||||
|
{
|
||||||
|
identifier.Identify( _changedItems, swapped );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
PluginLog.Error( $"Unknown Error:\n{e}" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void AddFiles( Mod.Mod mod )
|
private void AddFiles( Mod.Mod mod )
|
||||||
{
|
{
|
||||||
|
|
@ -97,7 +138,7 @@ namespace Penumbra.Mods
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mod.Cache.AddConflict( oldMod, gamePath );
|
mod.Cache.AddConflict( oldMod, gamePath );
|
||||||
if( !ReferenceEquals( mod, oldMod ) && mod.Settings.Priority == oldMod.Settings.Priority)
|
if( !ReferenceEquals( mod, oldMod ) && mod.Settings.Priority == oldMod.Settings.Priority )
|
||||||
{
|
{
|
||||||
oldMod.Cache.AddConflict( mod, gamePath );
|
oldMod.Cache.AddConflict( mod, gamePath );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
72
Penumbra/UI/MenuTabs/TabChangedItems.cs
Normal file
72
Penumbra/UI/MenuTabs/TabChangedItems.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.UI.Custom;
|
||||||
|
using Penumbra.Util;
|
||||||
|
|
||||||
|
namespace Penumbra.UI
|
||||||
|
{
|
||||||
|
public partial class SettingsInterface
|
||||||
|
{
|
||||||
|
private class TabChangedItems
|
||||||
|
{
|
||||||
|
private const string LabelTab = "Changed Items";
|
||||||
|
private readonly ModManager _modManager;
|
||||||
|
private readonly SettingsInterface _base;
|
||||||
|
|
||||||
|
private string _filter = string.Empty;
|
||||||
|
private string _filterLower = string.Empty;
|
||||||
|
|
||||||
|
public TabChangedItems( SettingsInterface ui )
|
||||||
|
{
|
||||||
|
_base = ui;
|
||||||
|
_modManager = Service< ModManager >.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
var items = _modManager.Collections.ActiveCollection.Cache?.ChangedItems ?? new Dictionary< string, object? >();
|
||||||
|
var forced = _modManager.Collections.ForcedCollection.Cache?.ChangedItems ?? new Dictionary< string, object? >();
|
||||||
|
var count = items.Count + forced.Count;
|
||||||
|
if( count > 0 && !ImGui.BeginTabItem( LabelTab ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
|
||||||
|
|
||||||
|
ImGui.SetNextItemWidth( -1 );
|
||||||
|
if( ImGui.InputTextWithHint( "##ChangedItemsFilter", "Filter...", ref _filter, 64 ) )
|
||||||
|
{
|
||||||
|
_filterLower = _filter.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !ImGui.BeginTable( "##ChangedItemsTable", 1, ImGuiTableFlags.RowBg, AutoFillSize ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
raii.Push( ImGui.EndTable );
|
||||||
|
|
||||||
|
var list = items.AsEnumerable();
|
||||||
|
if( forced.Count > 0 )
|
||||||
|
{
|
||||||
|
list = list.Concat( forced ).OrderBy( kvp => kvp.Key );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _filter.Any() )
|
||||||
|
{
|
||||||
|
list = list.Where( kvp => kvp.Key.ToLowerInvariant().Contains( _filterLower ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( var (name, data) in list )
|
||||||
|
{
|
||||||
|
ImGui.TableNextRow();
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
_base.DrawChangedItem( name, data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -185,30 +185,7 @@ namespace Penumbra.UI
|
||||||
raii.Push( ImGui.EndListBox );
|
raii.Push( ImGui.EndListBox );
|
||||||
foreach( var (name, data) in Mod.Data.ChangedItems )
|
foreach( var (name, data) in Mod.Data.ChangedItems )
|
||||||
{
|
{
|
||||||
var ret = ImGui.Selectable( name ) ? MouseButton.Left : MouseButton.None;
|
_base.DrawChangedItem( name, data );
|
||||||
ret = ImGui.IsItemClicked( ImGuiMouseButton.Right ) ? MouseButton.Right : ret;
|
|
||||||
ret = ImGui.IsItemClicked( ImGuiMouseButton.Middle ) ? MouseButton.Middle : ret;
|
|
||||||
|
|
||||||
if( ret != MouseButton.None )
|
|
||||||
{
|
|
||||||
_base._penumbra.Api.InvokeClick( ret, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( _base._penumbra.Api.HasTooltip && ImGui.IsItemHovered() )
|
|
||||||
{
|
|
||||||
ImGui.BeginTooltip();
|
|
||||||
raii.Push( ImGui.EndTooltip );
|
|
||||||
_base._penumbra.Api.InvokeTooltip( data );
|
|
||||||
raii.Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( data is Item it )
|
|
||||||
{
|
|
||||||
var modelId = $"({( ( Quad )it.ModelMain ).A})";
|
|
||||||
var offset = ImGui.CalcTextSize( modelId ).X - ImGui.GetStyle().ItemInnerSpacing.X;
|
|
||||||
ImGui.SameLine(ImGui.GetWindowContentRegionWidth() - offset);
|
|
||||||
ImGui.TextColored( new Vector4(0.5f, 0.5f, 0.5f, 1 ), modelId );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ using System.Text.RegularExpressions;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Penumbra.GameData.Enums;
|
|
||||||
using Penumbra.Interop;
|
using Penumbra.Interop;
|
||||||
using Penumbra.Mods;
|
using Penumbra.Mods;
|
||||||
using Penumbra.UI.Custom;
|
using Penumbra.UI.Custom;
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ namespace Penumbra.UI
|
||||||
private readonly TabSettings _settingsTab;
|
private readonly TabSettings _settingsTab;
|
||||||
private readonly TabImport _importTab;
|
private readonly TabImport _importTab;
|
||||||
private readonly TabBrowser _browserTab;
|
private readonly TabBrowser _browserTab;
|
||||||
|
private readonly TabEffective _effectiveTab;
|
||||||
|
private readonly TabChangedItems _changedItems;
|
||||||
internal readonly TabCollections CollectionsTab;
|
internal readonly TabCollections CollectionsTab;
|
||||||
internal readonly TabInstalled InstalledTab;
|
internal readonly TabInstalled InstalledTab;
|
||||||
private readonly TabEffective _effectiveTab;
|
|
||||||
|
|
||||||
public SettingsMenu( SettingsInterface ui )
|
public SettingsMenu( SettingsInterface ui )
|
||||||
{
|
{
|
||||||
|
|
@ -32,6 +33,7 @@ namespace Penumbra.UI
|
||||||
InstalledTab = new TabInstalled( _base );
|
InstalledTab = new TabInstalled( _base );
|
||||||
CollectionsTab = new TabCollections( InstalledTab.Selector );
|
CollectionsTab = new TabCollections( InstalledTab.Selector );
|
||||||
_effectiveTab = new TabEffective();
|
_effectiveTab = new TabEffective();
|
||||||
|
_changedItems = new TabChangedItems( _base );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
@ -72,7 +74,7 @@ namespace Penumbra.UI
|
||||||
{
|
{
|
||||||
_browserTab.Draw();
|
_browserTab.Draw();
|
||||||
InstalledTab.Draw();
|
InstalledTab.Draw();
|
||||||
|
_changedItems.Draw();
|
||||||
if( Penumbra.Config.ShowAdvanced )
|
if( Penumbra.Config.ShowAdvanced )
|
||||||
{
|
{
|
||||||
_effectiveTab.Draw();
|
_effectiveTab.Draw();
|
||||||
|
|
|
||||||
39
Penumbra/UI/UiHelpers.cs
Normal file
39
Penumbra/UI/UiHelpers.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Lumina.Data.Parsing;
|
||||||
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
using Penumbra.GameData.Enums;
|
||||||
|
using Penumbra.UI.Custom;
|
||||||
|
|
||||||
|
namespace Penumbra.UI
|
||||||
|
{
|
||||||
|
public partial class SettingsInterface
|
||||||
|
{
|
||||||
|
internal void DrawChangedItem( string name, object? data )
|
||||||
|
{
|
||||||
|
var ret = ImGui.Selectable( name ) ? MouseButton.Left : MouseButton.None;
|
||||||
|
ret = ImGui.IsItemClicked( ImGuiMouseButton.Right ) ? MouseButton.Right : ret;
|
||||||
|
ret = ImGui.IsItemClicked( ImGuiMouseButton.Middle ) ? MouseButton.Middle : ret;
|
||||||
|
|
||||||
|
if( ret != MouseButton.None )
|
||||||
|
{
|
||||||
|
_penumbra.Api.InvokeClick( ret, data );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _penumbra.Api.HasTooltip && ImGui.IsItemHovered() )
|
||||||
|
{
|
||||||
|
ImGui.BeginTooltip();
|
||||||
|
using var tooltip = ImGuiRaii.DeferredEnd( ImGui.EndTooltip );
|
||||||
|
_penumbra.Api.InvokeTooltip( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( data is Item it )
|
||||||
|
{
|
||||||
|
var modelId = $"({( ( Quad )it.ModelMain ).A})";
|
||||||
|
var offset = ImGui.CalcTextSize( modelId ).X - ImGui.GetStyle().ItemInnerSpacing.X;
|
||||||
|
ImGui.SameLine( ImGui.GetWindowContentRegionWidth() - offset );
|
||||||
|
ImGui.TextColored( new Vector4( 0.5f, 0.5f, 0.5f, 1 ), modelId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue