Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asset lookup registration rework #15

Merged
merged 4 commits into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions Src/IO/Asset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public abstract class Asset
/// <summary> The state of this asset. </summary>
public AssetState State { get; internal set; }

/// <summary> The source of this asset. Can be null. </summary>
public AssetSource Source { get; internal set; }
/// <summary> The file source of this asset. Can be null. </summary>
public AssetFileEntry? File { get; internal set; }

/// <summary> Whether or not this asset is currently being loaded. </summary>
public bool IsLoading => State == AssetState.Loading;
Expand Down Expand Up @@ -111,7 +111,7 @@ private async Task Load(AssetRequestMode mode)
var asyncContext = new ContinuationScheduler(this);

string extension = Path.GetExtension(AssetPath);
var readerByExtension = Assets.ReadersByDataType<T>.ReaderByExtension;
var readerByExtension = Assets.AssetTypeData<T>.ReaderByExtension;

if (readerByExtension.Count == 0) {
throw new InvalidOperationException($"No asset reader found with a return type of '{typeof(T).Name}'.");
Expand All @@ -125,23 +125,26 @@ private async Task Load(AssetRequestMode mode)
await Task.Yield(); // This transfers the method's execution to a worker thread.
}

using var stream = Source.OpenStream(AssetPath);

Value = await assetReader.ReadFromStream(stream, AssetPath, new MainThreadCreationContext(asyncContext));
Value = await assetReader.ReadAsset(File, new MainThreadCreationContext(asyncContext));

State = AssetState.Loaded;
}

private void SafelyWaitForLoad(Task loadTask, bool tracked)
{
if (State == AssetState.Loaded)
if (State == AssetState.Loaded) {
return;
}

if (!loadTask.IsCompleted && Assets.IsMainThread) {
while (Continuation == null) {
while (Continuation == null && State != AssetState.Loaded) {
Thread.Yield();
}

if (State == AssetState.Loaded) {
return;
}

if (tracked) {
lock (Assets.RequestLock) {
Continuation();
Expand Down
21 changes: 21 additions & 0 deletions Src/IO/AssetFileEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.IO;

namespace Dissonance.Engine.IO
{
public class AssetFileEntry
{
public readonly string Path;
public readonly AssetSource Source;

public AssetFileEntry(string path, AssetSource source)
{
Path = path;
Source = source;
}

public Stream OpenStream()
{
return Source.OpenStream(Path);
}
}
}
48 changes: 38 additions & 10 deletions Src/IO/AssetLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal static class AssetLookup

internal static class AssetLookup<T>
{
private static readonly ConcurrentDictionary<string, Asset<T>> lookup = new();
private static readonly ConcurrentDictionary<string, (string assetPath, Asset<T> asset)> lookup = new();

public static int Count => lookup.Count;

Expand All @@ -24,21 +24,49 @@ static AssetLookup()
};
}

public static void Register(string name, Asset<T> asset)
public static void Register(string name, string path, Asset<T> asset)
{
if (lookup.ContainsKey(name)) {
//throw new Exception($"Cannot register two {typeof(T).Name} with the same name: {name}.");
if (lookup.TryGetValue(name, out var existingTuple) && existingTuple.assetPath == path) {
lookup[name] = (null, null); // This marks the registry as ambiguous.
} else {
lookup[name] = (path, asset);
}
}

public static Asset<T> Get(string fullName, AssetRequestMode mode = AssetRequestMode.DoNotLoad)
{
var tuple = lookup[fullName];

asset = null; // This marks the registry as ambiguous.
if (tuple.assetPath == null && tuple.asset == null) {
throw new ArgumentException($"Key '{fullName}' is ambiguous.");
}

lookup[name] = asset;
if (tuple.asset == null) {
tuple.asset = Assets.Get<T>(tuple.assetPath, mode);
lookup[fullName] = tuple;
}

return tuple.asset;
}

public static Asset<T> Get(string fullName)
=> lookup[fullName] ?? throw new ArgumentException($"Key '{fullName}' is ambiguous.");
public static bool TryGet(string fullName, out Asset<T> result, AssetRequestMode mode = AssetRequestMode.DoNotLoad)
{
var tuple = lookup[fullName];

if (tuple.assetPath == null && tuple.asset == null) {
result = null;

return false;
}

public static bool TryGetValue(string fullName, out Asset<T> value)
=> lookup.TryGetValue(fullName, out value) && value != null;
if (tuple.asset == null) {
tuple.asset = Assets.Get<T>(tuple.assetPath, mode);
lookup[fullName] = tuple;
}

result = tuple.asset;

return true;
}
}
}
Loading