ResourceTree: Reverse-resolve in bulk

This commit is contained in:
Exter-N 2023-09-19 01:32:31 +02:00
parent 69012e5ecd
commit f02a37b939
5 changed files with 311 additions and 170 deletions

View file

@ -4,80 +4,89 @@ using ChangedItemIcon = Penumbra.UI.ChangedItemDrawer.ChangedItemIcon;
namespace Penumbra.Interop.ResourceTree;
public class ResourceNode
public class ResourceNode : ICloneable
{
public readonly string? Name;
public readonly ChangedItemIcon Icon;
public string? Name;
public string? FallbackName;
public ChangedItemIcon Icon;
public readonly ResourceType Type;
public readonly nint ObjectAddress;
public readonly nint ResourceHandle;
public readonly Utf8GamePath GamePath;
public readonly Utf8GamePath[] PossibleGamePaths;
public readonly FullPath FullPath;
public Utf8GamePath[] PossibleGamePaths;
public FullPath FullPath;
public readonly ulong Length;
public readonly bool Internal;
public readonly List<ResourceNode> Children;
internal ResolveContext? ResolveContext;
public ResourceNode(UIData uiData, ResourceType type, nint objectAddress, nint resourceHandle, Utf8GamePath gamePath, FullPath fullPath,
ulong length, bool @internal)
public Utf8GamePath GamePath
{
Name = uiData.Name;
Icon = uiData.Icon;
Type = type;
ObjectAddress = objectAddress;
ResourceHandle = resourceHandle;
GamePath = gamePath;
PossibleGamePaths = new[]
get => PossibleGamePaths.Length == 1 ? PossibleGamePaths[0] : Utf8GamePath.Empty;
set
{
gamePath,
};
FullPath = fullPath;
Length = length;
Internal = @internal;
Children = new List<ResourceNode>();
if (value.IsEmpty)
PossibleGamePaths = Array.Empty<Utf8GamePath>();
else
PossibleGamePaths = new[] { value };
}
}
public ResourceNode(UIData uiData, ResourceType type, nint objectAddress, nint resourceHandle, Utf8GamePath[] possibleGamePaths,
FullPath fullPath,
ulong length, bool @internal)
internal ResourceNode(ResourceType type, nint objectAddress, nint resourceHandle, ulong length, bool @internal, ResolveContext? resolveContext)
{
Name = uiData.Name;
Icon = uiData.Icon;
Type = type;
ObjectAddress = objectAddress;
ResourceHandle = resourceHandle;
GamePath = possibleGamePaths.Length == 1 ? possibleGamePaths[0] : Utf8GamePath.Empty;
PossibleGamePaths = possibleGamePaths;
FullPath = fullPath;
PossibleGamePaths = Array.Empty<Utf8GamePath>();
Length = length;
Internal = @internal;
Children = new List<ResourceNode>();
ResolveContext = resolveContext;
}
private ResourceNode(UIData uiData, ResourceNode originalResourceNode)
private ResourceNode(ResourceNode other)
{
Name = uiData.Name;
Icon = uiData.Icon;
Type = originalResourceNode.Type;
ObjectAddress = originalResourceNode.ObjectAddress;
ResourceHandle = originalResourceNode.ResourceHandle;
GamePath = originalResourceNode.GamePath;
PossibleGamePaths = originalResourceNode.PossibleGamePaths;
FullPath = originalResourceNode.FullPath;
Length = originalResourceNode.Length;
Internal = originalResourceNode.Internal;
Children = originalResourceNode.Children;
Name = other.Name;
FallbackName = other.FallbackName;
Icon = other.Icon;
Type = other.Type;
ObjectAddress = other.ObjectAddress;
ResourceHandle = other.ResourceHandle;
PossibleGamePaths = other.PossibleGamePaths;
FullPath = other.FullPath;
Length = other.Length;
Internal = other.Internal;
Children = other.Children;
ResolveContext = other.ResolveContext;
}
public ResourceNode WithUIData(string? name, ChangedItemIcon icon)
=> string.Equals(Name, name, StringComparison.Ordinal) && Icon == icon ? this : new ResourceNode(new UIData(name, icon), this);
public ResourceNode Clone()
=> new(this);
public ResourceNode WithUIData(UIData uiData)
=> string.Equals(Name, uiData.Name, StringComparison.Ordinal) && Icon == uiData.Icon ? this : new ResourceNode(uiData, this);
object ICloneable.Clone()
=> Clone();
public readonly record struct UIData(string? Name, ChangedItemIcon Icon)
public void ProcessPostfix(Action<ResourceNode, ResourceNode?> action, ResourceNode? parent)
{
public readonly UIData PrependName(string prefix)
=> Name == null ? this : new UIData(prefix + Name, Icon);
foreach (var child in Children)
child.ProcessPostfix(action, this);
action(this, parent);
}
public void SetUiData(UiData uiData)
{
Name = uiData.Name;
Icon = uiData.Icon;
}
public void PrependName(string prefix)
{
if (Name != null)
Name = prefix + Name;
}
public readonly record struct UiData(string? Name, ChangedItemIcon Icon)
{
public readonly UiData PrependName(string prefix)
=> Name == null ? this : new UiData(prefix + Name, Icon);
}
}