Skip to content

Instantly share code, notes, and snippets.

@derkork
Created March 24, 2022 09:15
Show Gist options
  • Save derkork/90b4bb36c6e8752344f54f0656ae0f43 to your computer and use it in GitHub Desktop.
Save derkork/90b4bb36c6e8752344f54f0656ae0f43 to your computer and use it in GitHub Desktop.
public static class ResourceQueue
{
public static async Task<T> Load<T>(string path, [CanBeNull] Delegates.ReportProgress reportProgress = null)
where T : Resource
{
if (ResourceLoader.HasCached(path))
{
GD.Print("Is in cache: " + path);
return ResourceLoader.Load<T>(path);
}
var reader = LoadInBackground<T>(path);
while (await reader.WaitToReadAsync())
{
if (!reader.TryRead(out var progress))
{
continue;
}
if (progress.Finished)
{
return progress.Resource;
}
reportProgress?.Invoke(path, progress.Progress);
}
throw new InvalidOperationException("We should never be here.");
}
private static ChannelReader<ResourceLoadingProgress<T>> LoadInBackground<T>(string path) where T : Resource
{
GD.Print("Loading in background: " + path);
var result = Channel.CreateUnbounded<ResourceLoadingProgress<T>>();
Task.Run(async () =>
{
var interactiveLoader = ResourceLoader.LoadInteractive(path);
do
{
var error = interactiveLoader.Poll();
if (error == Error.FileEof || error != Error.Ok)
{
if (error != Error.FileEof)
{
GD.Print("Loading failed. Error: " + error);
}
// send resource
await result.Writer.WriteAsync(new ResourceLoadingProgress<T>((T) interactiveLoader.GetResource()));
result.Writer.Complete();
return;
}
// send a progress update
await result.Writer.WriteAsync(new ResourceLoadingProgress<T>(interactiveLoader.GetStage() /
(float) interactiveLoader.GetStageCount()));
} while (true);
});
return result.Reader;
}
}
@derkork
Copy link
Author

derkork commented Mar 24, 2022

Usage:

 var scene = await ResourceQueue.Load<PackedScene>(path, progressReporter);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment