Penumbra/Penumbra/UI/MenuTabs/TabResourceManager.cs
2022-04-15 14:37:39 +02:00

186 lines
No EOL
6.2 KiB
C#

using System;
using System.Linq;
using System.Numerics;
using System.Reflection.Metadata.Ecma335;
using Dalamud.Interface;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
using FFXIVClientStructs.STD;
using ImGuiNET;
using Penumbra.GameData.ByteString;
using Penumbra.Interop;
using Penumbra.UI.Custom;
namespace Penumbra.UI;
public partial class SettingsInterface
{
private static string GetNodeLabel( uint label, uint type, ulong count )
{
var byte1 = type >> 24;
var byte2 = ( type >> 16 ) & 0xFF;
var byte3 = ( type >> 8 ) & 0xFF;
var byte4 = type & 0xFF;
return byte1 == 0
? $"({type:X8}) {( char )byte2}{( char )byte3}{( char )byte4} - {count}###{label}{type}Debug"
: $"({type:X8}) {( char )byte1}{( char )byte2}{( char )byte3}{( char )byte4} - {count}###{label}{type}Debug";
}
private unsafe void DrawResourceMap( ResourceCategory category, uint ext, StdMap< uint, Pointer< ResourceHandle > >* map )
{
if( map == null )
{
return;
}
var label = GetNodeLabel( ( uint )category, ext, map->Count );
if( !ImGui.TreeNodeEx( label ) )
{
return;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.TreePop );
if( map->Count == 0 || !ImGui.BeginTable( $"##{label}_table", 4, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg ) )
{
return;
}
raii.Push( ImGui.EndTable );
ImGui.TableSetupColumn( "Hash", ImGuiTableColumnFlags.WidthFixed, 100 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "Ptr", ImGuiTableColumnFlags.WidthFixed, 100 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "Path", ImGuiTableColumnFlags.WidthFixed,
ImGui.GetWindowContentRegionWidth() - 300 * ImGuiHelpers.GlobalScale );
ImGui.TableSetupColumn( "Refs", ImGuiTableColumnFlags.WidthFixed, 30 * ImGuiHelpers.GlobalScale );
ImGui.TableHeadersRow();
ResourceLoader.IterateResourceMap( map, ( hash, r ) =>
{
if( _filter.Length != 0 && !r->FileName.ToString().Contains( _filter, StringComparison.InvariantCultureIgnoreCase ) )
{
return;
}
ImGui.TableNextColumn();
ImGui.Text( $"0x{hash:X8}" );
ImGui.TableNextColumn();
var address = $"0x{( ulong )r:X}";
ImGui.Text( address );
if( ImGui.IsItemClicked() )
{
ImGui.SetClipboardText( address );
}
ref var name = ref r->FileName;
ImGui.TableNextColumn();
if( name.Capacity > 15 )
{
ImGuiNative.igTextUnformatted( name.BufferPtr, name.BufferPtr + name.Length );
}
else
{
fixed( byte* ptr = name.Buffer )
{
ImGuiNative.igTextUnformatted( ptr, ptr + name.Length );
}
}
if( ImGui.IsItemClicked() )
{
var data = ( ( Interop.Structs.ResourceHandle* )r )->GetData();
ImGui.SetClipboardText( string.Join( " ",
new ReadOnlySpan< byte >( ( byte* )data.Data, data.Length ).ToArray().Select( b => b.ToString( "X2" ) ) ) );
//ImGuiNative.igSetClipboardText( ( byte* )Structs.ResourceHandle.GetData( ( IntPtr )r ) );
}
ImGui.TableNextColumn();
ImGui.Text( r->RefCount.ToString() );
} );
}
private unsafe void DrawCategoryContainer( ResourceCategory category,
StdMap< uint, Pointer< StdMap< uint, Pointer< ResourceHandle > > > >* map )
{
if( map == null || !ImGui.TreeNodeEx( $"({( uint )category:D2}) {category} - {map->Count}###{( uint )category}Debug" ) )
{
return;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.TreePop );
ResourceLoader.IterateExtMap( map, ( ext, map ) => DrawResourceMap( category, ext, map ) );
}
private static unsafe void DrawResourceProblems()
{
if( !ImGui.CollapsingHeader( "Resource Problems##ResourceManager" )
|| !ImGui.BeginTable( "##ProblemsTable", 6, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit ) )
{
return;
}
using var end = ImGuiRaii.DeferredEnd( ImGui.EndTable );
ResourceLoader.IterateResources( ( _, r ) =>
{
if( r->RefCount < 10000 )
{
return;
}
ImGui.TableNextColumn();
ImGui.Text( r->Category.ToString() );
ImGui.TableNextColumn();
ImGui.Text( r->FileType.ToString( "X" ) );
ImGui.TableNextColumn();
ImGui.Text( r->Id.ToString( "X" ) );
ImGui.TableNextColumn();
ImGui.Text( ( ( ulong )r ).ToString( "X" ) );
ImGui.TableNextColumn();
ImGui.Text( r->RefCount.ToString() );
ImGui.TableNextColumn();
ref var name = ref r->FileName;
if( name.Capacity > 15 )
{
ImGuiNative.igTextUnformatted( name.BufferPtr, name.BufferPtr + name.Length );
}
else
{
fixed( byte* ptr = name.Buffer )
{
ImGuiNative.igTextUnformatted( ptr, ptr + name.Length );
}
}
} );
}
private string _filter = string.Empty;
private unsafe void DrawResourceManagerTab()
{
if( !ImGui.BeginTabItem( "Resource Manager Tab" ) )
{
return;
}
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTabItem );
var resourceHandler = *ResourceLoader.ResourceManager;
if( resourceHandler == null )
{
return;
}
ImGui.InputTextWithHint( "##resourceFilter", "Filter...", ref _filter, Utf8GamePath.MaxGamePathLength );
raii.Push( ImGui.EndChild );
if( !ImGui.BeginChild( "##ResourceManagerChild", -Vector2.One, true ) )
{
return;
}
ResourceLoader.IterateGraphs( DrawCategoryContainer );
}
}