Skip to content

Commit

Permalink
Add load state to resource watcher.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ottermandias committed Sep 18, 2023
1 parent 5506dcc commit 5067ab2
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Penumbra/Interop/Structs/ResourceHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ public unsafe struct ShaderPackageResourceHandle
public ShaderPackage* ShaderPackage;
}

public enum LoadState : byte
{
Success = 0x07,
Async = 0x03,
Failure = 0x09,
FailedSubResource = 0x0A,
None = 0xFF,
}

[StructLayout(LayoutKind.Explicit)]
public unsafe struct ResourceHandle
{
Expand Down Expand Up @@ -99,6 +108,9 @@ public bool GamePath(out Utf8GamePath path)
[FieldOffset(0x58)]
public int FileNameLength;

[FieldOffset(0xA9)]
public LoadState LoadState;

[FieldOffset(0xAC)]
public uint RefCount;

Expand Down
6 changes: 6 additions & 0 deletions Penumbra/UI/ResourceWatcher/Record.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ internal unsafe struct Record
public OptionalBool Synchronously;
public OptionalBool ReturnValue;
public OptionalBool CustomLoad;
public LoadState LoadState;

public static Record CreateRequest(ByteString path, bool sync)
=> new()
Expand All @@ -47,6 +48,7 @@ public static Record CreateRequest(ByteString path, bool sync)
ReturnValue = OptionalBool.Null,
CustomLoad = OptionalBool.Null,
AssociatedGameObject = string.Empty,
LoadState = LoadState.None,
};

public static Record CreateDefaultLoad(ByteString path, ResourceHandle* handle, ModCollection collection, string associatedGameObject)
Expand All @@ -67,6 +69,7 @@ public static Record CreateDefaultLoad(ByteString path, ResourceHandle* handle,
ReturnValue = OptionalBool.Null,
CustomLoad = false,
AssociatedGameObject = associatedGameObject,
LoadState = handle->LoadState,
};
}

Expand All @@ -87,6 +90,7 @@ public static Record CreateLoad(ByteString path, ByteString originalPath, Resour
ReturnValue = OptionalBool.Null,
CustomLoad = true,
AssociatedGameObject = associatedGameObject,
LoadState = handle->LoadState,
};

public static Record CreateDestruction(ResourceHandle* handle)
Expand All @@ -107,6 +111,7 @@ public static Record CreateDestruction(ResourceHandle* handle)
ReturnValue = OptionalBool.Null,
CustomLoad = OptionalBool.Null,
AssociatedGameObject = string.Empty,
LoadState = handle->LoadState,
};
}

Expand All @@ -126,5 +131,6 @@ public static Record CreateFileLoad(ByteString path, ResourceHandle* handle, boo
ReturnValue = ret,
CustomLoad = custom,
AssociatedGameObject = string.Empty,
LoadState = handle->LoadState,
};
}
89 changes: 89 additions & 0 deletions Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
using OtterGui.Raii;
using OtterGui.Table;
using Penumbra.Enums;
using Penumbra.Interop.Structs;
using Penumbra.String;
using Penumbra.UI.Classes;

namespace Penumbra.UI.ResourceWatcher;

Expand All @@ -24,6 +26,7 @@ public ResourceWatcherTable(Configuration config, IReadOnlyCollection<Record> re
new ResourceCategoryColumn(config) { Label = "Category" },
new ResourceTypeColumn(config) { Label = "Type" },
new HandleColumn { Label = "Resource" },
new LoadStateColumn { Label = "State" },
new RefCountColumn { Label = "#Ref" },
new DateColumn { Label = "Time" }
)
Expand Down Expand Up @@ -241,6 +244,92 @@ public override void DrawColumn(Record item, int idx)
}
}

private sealed class LoadStateColumn : ColumnFlags<LoadStateColumn.LoadStateFlag, Record>
{
public override float Width
=> 50 * UiHelpers.Scale;

[Flags]
public enum LoadStateFlag : byte
{
Success = 0x01,
Async = 0x02,
Failed = 0x04,
FailedSub = 0x08,
Unknown = 0x10,
None = 0xFF,
}

protected override string[] Names
=> new[]
{
"Loaded",
"Loading",
"Failed",
"Dependency Failed",
"Unknown",
"None",
};

public LoadStateColumn()
{
AllFlags = Enum.GetValues<LoadStateFlag>().Aggregate((v, f) => v | f);
_filterValue = AllFlags;
}

private LoadStateFlag _filterValue;

public override LoadStateFlag FilterValue
=> _filterValue;

protected override void SetValue(LoadStateFlag value, bool enable)
{
if (enable)
_filterValue |= value;
else
_filterValue &= ~value;
}

public override bool FilterFunc(Record item)
=> item.LoadState switch
{
LoadState.None => FilterValue.HasFlag(LoadStateFlag.None),
LoadState.Success => FilterValue.HasFlag(LoadStateFlag.Success),
LoadState.Async => FilterValue.HasFlag(LoadStateFlag.Async),
LoadState.Failure => FilterValue.HasFlag(LoadStateFlag.Failed),
LoadState.FailedSubResource => FilterValue.HasFlag(LoadStateFlag.FailedSub),
_ => FilterValue.HasFlag(LoadStateFlag.Unknown),
};

public override void DrawColumn(Record item, int _)
{
if (item.LoadState == LoadState.None)
return;

var (icon, color, tt) = item.LoadState switch
{
LoadState.Success => (FontAwesomeIcon.CheckCircle, ColorId.IncreasedMetaValue.Value(),
$"Successfully loaded ({(byte)item.LoadState})."),
LoadState.Async => (FontAwesomeIcon.Clock, ColorId.FolderLine.Value(), $"Loading asynchronously ({(byte)item.LoadState})."),
LoadState.Failure => (FontAwesomeIcon.Times, ColorId.DecreasedMetaValue.Value(),
$"Failed to load ({(byte)item.LoadState})."),
LoadState.FailedSubResource => (FontAwesomeIcon.ExclamationCircle, ColorId.DecreasedMetaValue.Value(),
$"Dependencies failed to load ({(byte)item.LoadState})."),
_ => (FontAwesomeIcon.QuestionCircle, ColorId.UndefinedMod.Value(), $"Unknown state ({(byte)item.LoadState})."),
};
using (var font = ImRaii.PushFont(UiBuilder.IconFont))
{
using var c = ImRaii.PushColor(ImGuiCol.Text, color);
ImGui.TextUnformatted(icon.ToIconString());
}

ImGuiUtil.HoverTooltip(tt);
}

public override int Compare(Record lhs, Record rhs)
=> lhs.LoadState.CompareTo(rhs.LoadState);
}

private sealed class HandleColumn : ColumnString<Record>
{
public override float Width
Expand Down

0 comments on commit 5067ab2

Please sign in to comment.