mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
Display the additional path data in ResourceTree
This commit is contained in:
parent
b2e1bff782
commit
a6661f15e8
5 changed files with 28 additions and 24 deletions
|
|
@ -3,8 +3,9 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.ResourceTree;
|
using Penumbra.Interop.PathResolving;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
|
using static Penumbra.Interop.Structs.StructExtensions;
|
||||||
using Model = Penumbra.GameData.Interop.Model;
|
using Model = Penumbra.GameData.Interop.Model;
|
||||||
|
|
||||||
namespace Penumbra.Interop.MaterialPreview;
|
namespace Penumbra.Interop.MaterialPreview;
|
||||||
|
|
@ -78,8 +79,12 @@ public readonly record struct MaterialInfo(ObjectIndex ObjectIndex, DrawObjectTy
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var mtrlHandle = material->MaterialResourceHandle;
|
var mtrlHandle = material->MaterialResourceHandle;
|
||||||
var path = ResolveContext.GetResourceHandlePath(&mtrlHandle->ResourceHandle);
|
if (mtrlHandle == null)
|
||||||
if (path == needle)
|
continue;
|
||||||
|
|
||||||
|
PathDataHandler.Split(mtrlHandle->ResourceHandle.FileName.AsSpan(), out var path, out _);
|
||||||
|
var fileName = ByteString.FromSpanUnsafe(path, true);
|
||||||
|
if (fileName == needle)
|
||||||
result.Add(new MaterialInfo(index, type, i, j));
|
result.Add(new MaterialInfo(index, type, i, j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ internal partial record ResolveContext
|
||||||
var imcFileData = imc->GetDataSpan();
|
var imcFileData = imc->GetDataSpan();
|
||||||
if (imcFileData.IsEmpty)
|
if (imcFileData.IsEmpty)
|
||||||
{
|
{
|
||||||
Penumbra.Log.Warning($"IMC resource handle with path {GetResourceHandlePath(imc, false)} doesn't have a valid data span");
|
Penumbra.Log.Warning($"IMC resource handle with path {imc->FileName.AsByteString()} doesn't have a valid data span");
|
||||||
return variant.Id;
|
return variant.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,12 +111,18 @@ internal unsafe partial record ResolveContext(
|
||||||
if (resourceHandle == null)
|
if (resourceHandle == null)
|
||||||
throw new ArgumentNullException(nameof(resourceHandle));
|
throw new ArgumentNullException(nameof(resourceHandle));
|
||||||
|
|
||||||
var fullPath = Utf8GamePath.FromByteString(GetResourceHandlePath(resourceHandle), out var p) ? new FullPath(p) : FullPath.Empty;
|
var fileName = resourceHandle->FileName.AsSpan();
|
||||||
|
var additionalData = ByteString.Empty;
|
||||||
|
if (PathDataHandler.Split(fileName, out fileName, out var data))
|
||||||
|
additionalData = ByteString.FromSpanUnsafe(data, false).Clone();
|
||||||
|
|
||||||
|
var fullPath = Utf8GamePath.FromSpan(fileName, out var p) ? new FullPath(p.Clone()) : FullPath.Empty;
|
||||||
|
|
||||||
var node = new ResourceNode(type, objectAddress, (nint)resourceHandle, GetResourceHandleLength(resourceHandle), this)
|
var node = new ResourceNode(type, objectAddress, (nint)resourceHandle, GetResourceHandleLength(resourceHandle), this)
|
||||||
{
|
{
|
||||||
GamePath = gamePath,
|
GamePath = gamePath,
|
||||||
FullPath = fullPath,
|
FullPath = fullPath,
|
||||||
|
AdditionalData = additionalData,
|
||||||
};
|
};
|
||||||
if (autoAdd)
|
if (autoAdd)
|
||||||
Global.Nodes.Add((gamePath, (nint)resourceHandle), node);
|
Global.Nodes.Add((gamePath, (nint)resourceHandle), node);
|
||||||
|
|
@ -365,21 +371,6 @@ internal unsafe partial record ResolveContext(
|
||||||
return i >= 0 && i < array.Length ? array[i] : null;
|
return i >= 0 && i < array.Length ? array[i] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ByteString GetResourceHandlePath(ResourceHandle* handle, bool stripPrefix = true)
|
|
||||||
{
|
|
||||||
if (handle == null)
|
|
||||||
return ByteString.Empty;
|
|
||||||
|
|
||||||
var name = handle->FileName.AsByteString();
|
|
||||||
if (name.IsEmpty)
|
|
||||||
return ByteString.Empty;
|
|
||||||
|
|
||||||
if (stripPrefix && PathDataHandler.Split(name.Span, out var path, out _))
|
|
||||||
name = ByteString.FromSpanUnsafe(path, name.IsNullTerminated, name.IsAsciiLowerCase, name.IsAscii);
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ulong GetResourceHandleLength(ResourceHandle* handle)
|
private static ulong GetResourceHandleLength(ResourceHandle* handle)
|
||||||
{
|
{
|
||||||
if (handle == null)
|
if (handle == null)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
|
using Penumbra.String;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
using ChangedItemIcon = Penumbra.UI.ChangedItemDrawer.ChangedItemIcon;
|
using ChangedItemIcon = Penumbra.UI.ChangedItemDrawer.ChangedItemIcon;
|
||||||
|
|
||||||
|
|
@ -15,6 +16,7 @@ public class ResourceNode : ICloneable
|
||||||
public readonly nint ResourceHandle;
|
public readonly nint ResourceHandle;
|
||||||
public Utf8GamePath[] PossibleGamePaths;
|
public Utf8GamePath[] PossibleGamePaths;
|
||||||
public FullPath FullPath;
|
public FullPath FullPath;
|
||||||
|
public ByteString AdditionalData;
|
||||||
public readonly ulong Length;
|
public readonly ulong Length;
|
||||||
public readonly List<ResourceNode> Children;
|
public readonly List<ResourceNode> Children;
|
||||||
internal ResolveContext? ResolveContext;
|
internal ResolveContext? ResolveContext;
|
||||||
|
|
@ -40,6 +42,7 @@ public class ResourceNode : ICloneable
|
||||||
ObjectAddress = objectAddress;
|
ObjectAddress = objectAddress;
|
||||||
ResourceHandle = resourceHandle;
|
ResourceHandle = resourceHandle;
|
||||||
PossibleGamePaths = Array.Empty<Utf8GamePath>();
|
PossibleGamePaths = Array.Empty<Utf8GamePath>();
|
||||||
|
AdditionalData = ByteString.Empty;
|
||||||
Length = length;
|
Length = length;
|
||||||
Children = new List<ResourceNode>();
|
Children = new List<ResourceNode>();
|
||||||
ResolveContext = resolveContext;
|
ResolveContext = resolveContext;
|
||||||
|
|
@ -56,6 +59,7 @@ public class ResourceNode : ICloneable
|
||||||
ResourceHandle = other.ResourceHandle;
|
ResourceHandle = other.ResourceHandle;
|
||||||
PossibleGamePaths = other.PossibleGamePaths;
|
PossibleGamePaths = other.PossibleGamePaths;
|
||||||
FullPath = other.FullPath;
|
FullPath = other.FullPath;
|
||||||
|
AdditionalData = other.AdditionalData;
|
||||||
Length = other.Length;
|
Length = other.Length;
|
||||||
Children = other.Children;
|
Children = other.Children;
|
||||||
ResolveContext = other.ResolveContext;
|
ResolveContext = other.ResolveContext;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using OtterGui.Raii;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using Penumbra.Interop.ResourceTree;
|
using Penumbra.Interop.ResourceTree;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
using Penumbra.String;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow;
|
namespace Penumbra.UI.AdvancedWindow;
|
||||||
|
|
||||||
|
|
@ -177,6 +178,9 @@ public class ResourceTreeViewer
|
||||||
return NodeVisibility.Hidden;
|
return NodeVisibility.Hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string GetAdditionalDataSuffix(ByteString data)
|
||||||
|
=> !debugMode || data.IsEmpty ? string.Empty : $"\n\nAdditional Data: {data}";
|
||||||
|
|
||||||
foreach (var (resourceNode, index) in resourceNodes.WithIndex())
|
foreach (var (resourceNode, index) in resourceNodes.WithIndex())
|
||||||
{
|
{
|
||||||
var visibility = GetNodeVisibility(resourceNode);
|
var visibility = GetNodeVisibility(resourceNode);
|
||||||
|
|
@ -260,13 +264,13 @@ public class ResourceTreeViewer
|
||||||
ImGui.Selectable(resourceNode.FullPath.ToPath(), false, 0, new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
ImGui.Selectable(resourceNode.FullPath.ToPath(), false, 0, new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
||||||
if (ImGui.IsItemClicked())
|
if (ImGui.IsItemClicked())
|
||||||
ImGui.SetClipboardText(resourceNode.FullPath.ToPath());
|
ImGui.SetClipboardText(resourceNode.FullPath.ToPath());
|
||||||
ImGuiUtil.HoverTooltip($"{resourceNode.FullPath.ToPath()}\n\nClick to copy to clipboard.");
|
ImGuiUtil.HoverTooltip($"{resourceNode.FullPath.ToPath()}\n\nClick to copy to clipboard.{GetAdditionalDataSuffix(resourceNode.AdditionalData)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.Selectable("(unavailable)", false, ImGuiSelectableFlags.Disabled,
|
ImGui.Selectable("(unavailable)", false, ImGuiSelectableFlags.Disabled,
|
||||||
new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
||||||
ImGuiUtil.HoverTooltip("The actual path to this file is unavailable.\nIt may be managed by another plug-in.");
|
ImGuiUtil.HoverTooltip($"The actual path to this file is unavailable.\nIt may be managed by another plug-in.{GetAdditionalDataSuffix(resourceNode.AdditionalData)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
mutedColor.Dispose();
|
mutedColor.Dispose();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue