Readded resource unloading.

This commit is contained in:
2024-10-20 23:11:58 +02:00
parent be78dd97ca
commit bb6900a60a
5 changed files with 105 additions and 93 deletions

View File

@@ -5,7 +5,7 @@ public class FontLoader : ResourceLoader<Font>
{
public override IEnumerable<string> SupportedExtensions => new string[]
{
"ttf"
".ttf"
};

View File

@@ -15,7 +15,7 @@ namespace Voile.Resources
public abstract IEnumerable<string> SupportedExtensions { get; }
/// <summary>
/// Loads a resource to this resource loader's resource list.
/// Loads a resource to <see cref="ResourceManager"/>'s resource list.
/// </summary>
/// <param name="path">File system path to the resource to load.</param>
/// <returns>A <see cref="Guid"/> of the loaded resource that can be later retrieved with <see cref="TryGet"/>.</returns>
@@ -24,15 +24,17 @@ namespace Voile.Resources
var resource = LoadResource(path);
var guid = Guid.NewGuid();
var oldResourceGuid = _loadedResources.FirstOrDefault(loadedResource => loadedResource.Value.Path == path).Key;
if (_loadedResources.ContainsKey(oldResourceGuid))
var loadedResources = ResourceManager.LoadedResources;
var oldResourceGuid = loadedResources.FirstOrDefault(loadedResource => loadedResource.Value.Path == path).Key;
if (loadedResources.ContainsKey(oldResourceGuid))
{
_loadedResources[oldResourceGuid] = resource;
ResourceManager.ReplaceResource(oldResourceGuid, resource);
return oldResourceGuid;
}
_loadedResources.Add(guid, resource);
ResourceManager.AddResource(guid, resource);
return guid;
}
@@ -42,32 +44,12 @@ namespace Voile.Resources
/// </summary>
public void Reload()
{
foreach (var loadedResource in _loadedResources)
foreach (var loadedResource in ResourceManager.LoadedResources)
{
Load(loadedResource.Value.Path);
}
}
/// <summary>
/// Gets a resource from a GUID.
/// </summary>
/// <param name="resourceGuid">GUID of the resource to get.</param>
/// <param name="resource">Retrieved resource. Will return a default resource if resource retrieval was not successful.</param>
/// <returns>True if resource retrieval was successful.</returns>
public bool TryGet(Guid resourceGuid, [NotNullWhen(true)] out T? resource)
{
resource = default;
if (!_loadedResources.ContainsKey(resourceGuid))
{
return false;
}
resource = _loadedResources[resourceGuid];
return true;
}
/// <summary>
/// Unloads a resource.
/// </summary>
@@ -75,14 +57,14 @@ namespace Voile.Resources
/// <returns>True if unloading was successful, otherwise false.</returns>
public bool TryUnload(Guid resourceGuid)
{
if (!_loadedResources.ContainsKey(resourceGuid))
if (!ResourceManager.LoadedResources.ContainsKey(resourceGuid))
{
return false;
}
var resource = _loadedResources[resourceGuid];
var resource = ResourceManager.LoadedResources[resourceGuid];
_loadedResources.Remove(resourceGuid);
ResourceManager.RemoveResource(resourceGuid);
resource.Dispose();
return true;
@@ -94,7 +76,5 @@ namespace Voile.Resources
/// <param name="path">File system path to the resource to load.</param>
/// <returns>Loaded resource.</returns>
protected abstract T LoadResource(string path);
protected Dictionary<Guid, T> _loadedResources = new();
}
}

View File

@@ -1,4 +1,6 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using Voile.Utils;
@@ -14,6 +16,8 @@ namespace Voile.Resources
/// </summary>
public static string ResourceRoot { get; set; } = "Resources/";
public static IReadOnlyDictionary<Guid, Resource> LoadedResources => _loadedResources;
/// <summary>
/// Emits when a resource gets loaded.
/// </summary>
@@ -27,6 +31,55 @@ namespace Voile.Resources
/// </summary>
public static Action? OnReloaded;
/// <summary>
/// Adds a resource to the list of loaded resources.
/// </summary>
/// <param name="resource"></param>
public static void AddResource(Guid resourceGuid, [DisallowNull] Resource resource)
{
_loadedResources.TryAdd(resourceGuid, resource);
}
/// <summary>
/// Replaces a resource with a different one.
/// </summary>
/// <param name="targetResourceGuid">GUID of a resource to replace.</param>
/// <param name="withResource">Resource to replace with.</param>
public static void ReplaceResource(Guid targetResourceGuid, [DisallowNull] Resource withResource)
{
_loadedResources[targetResourceGuid] = withResource;
}
/// <summary>
/// Gets a resource from a GUID.
/// </summary>
/// <param name="resourceGuid">GUID of the resource to get.</param>
/// <param name="resource">Retrieved resource. Will return a default resource if resource retrieval was not successful.</param>
/// <returns>True if resource retrieval was successful.</returns>
public static bool GetResource<T>(Guid resourceGuid, [NotNullWhen(true)] out T? resource) where T : Resource
{
resource = default;
if (!_loadedResources.ContainsKey(resourceGuid))
{
return false;
}
resource = (T)_loadedResources[resourceGuid];
return true;
}
/// <summary>
/// Removes a resource from the list of loaded resources.
/// This method only removes a resource from the list of loaded resources. If you want to unload a Resource, use Unload.
/// </summary>
/// <param name="resourceGuid">GUID of resource to remove.</param>
public static void RemoveResource(Guid resourceGuid)
{
_loadedResources.Remove(resourceGuid, out _);
}
/// <summary>
/// Loads a resource from a given file system path.
/// </summary>
@@ -56,7 +109,7 @@ namespace Voile.Resources
}
var extension = Path.GetExtension(fullPath);
var hasExtension = loader.SupportedExtensions.Any(ext => extension[1..] == ext);
var hasExtension = loader.SupportedExtensions.Any(ext => ext == extension);
if (!hasExtension)
{
@@ -65,7 +118,7 @@ namespace Voile.Resources
var resourceGuid = loader.Load(fullPath);
if (!loader.TryGet(resourceGuid, out T? loadedResource))
if (!GetResource(resourceGuid, out T? loadedResource))
{
_logger.Error($"Failed to load resource at path \"{path}\"!");
return false;
@@ -90,36 +143,49 @@ namespace Voile.Resources
OnReloaded?.Invoke();
}
// TODO
public bool TryUnload(string resourceId)
/// <summary>
/// Unloads a resource at a path.
/// </summary>
/// <param name="resourcePath">Path to the resource.</param>
/// <exception cref="KeyNotFoundException"></exception>
public void Unload(string resourcePath)
{
_logger.Info($"Unloading resource with id \"{resourceId}\"...");
_logger.Info($"Unloading resource at path \"{resourcePath}\"...");
// if (!_resourceStringMap.TryGetValue(resourceId, out Guid guid))
// {
// _logger.Error($"Resource with ID \"{resourceId}\" doesn't exist!");
// return false;
// }
if (!_resourcePathMap.ContainsKey(resourcePath))
{
throw new KeyNotFoundException($"Resource at path \"{resourcePath}\" was not found!");
}
return true;
var guid = _resourcePathMap[resourcePath];
RemoveResource(guid);
}
// TODO
public bool TryUnload(Guid resourceGuid)
/// <summary>
/// Unloads a resource by GUID.
/// </summary>
/// <param name="resourceGuid">GUID of a resource to unload.</param>
/// <exception cref="KeyNotFoundException"></exception>
public void Unload(Guid resourceGuid)
{
_logger.Info($"Unloading resource with guid \"{resourceGuid}\"...");
// if (!_loadedResources.ContainsKey(resourceGuid))
// {
// _logger.Error($"Cannot unload resource with id \"{resourceGuid}\": resource doesn't exist!");
// return false;
// }
// var resource = _loadedResources[resourceGuid];
if (!_loadedResources.ContainsKey(resourceGuid))
{
throw new KeyNotFoundException($"Resource with GUID {resourceGuid} was not found!");
}
// _loadedResources.Remove(resourceGuid);
// resource.Dispose();
RemoveResource(resourceGuid);
}
return true;
/// <summary>
/// Unloads a resource by a ResourceRef.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="resourceRef"></param>
public void Unload<T>(ResourceRef<T> resourceRef) where T : Resource
{
Unload(resourceRef.Guid);
}
public bool TrySave<T>(string path, in T resource) where T : Resource
@@ -137,42 +203,6 @@ namespace Voile.Resources
return true;
}
/// <summary>
/// Gets a <see cref="Resource"/> by a file system path.
/// </summary>
/// <typeparam name="T">Type of <see cref="Resource"/> to load.</typeparam>
/// <param name="path">Path to the resource.</param>
/// <param name="resource">Retrieved resource. Otherwise null if nothing got retrieved.</param>
/// <returns>True if resource got successfully retrieved, otherwise false.</returns>
public bool TryGetResource<T>(string path, [NotNullWhen(true)] out T? resource) where T : Resource
{
resource = null;
if (!IsResourceLoaded(path))
{
_logger.Error($"Resource \"{path}\" has not yet been loaded!");
return false;
}
var resourceGuid = _resourcePathMap[path];
if (!TryGetLoader(out ResourceLoader<T>? loader))
{
_logger.Error($"No loader available for type {typeof(T)}!");
return false;
}
if (!loader.TryGet(resourceGuid, out T? loadedResource))
{
_logger.Error($"No resource with id {path} found!");
return false;
}
resource = loadedResource;
return true;
}
/// <summary>
/// Gets a <see cref="Resource"/> by resource's <see cref="Guid"/>.
/// </summary>
@@ -187,7 +217,7 @@ namespace Voile.Resources
throw new Exception($"No loader available for type {typeof(T)}!");
}
if (!loader.TryGet(resourceGuid, out T? loadedResource))
if (!GetResource(resourceGuid, out T? loadedResource))
{
throw new Exception($"No resource with GUID \"{resourceGuid}\" found!");
}
@@ -327,5 +357,7 @@ namespace Voile.Resources
private FileSystemWatcher? _fileWatcher;
private static Dictionary<string, Guid> _resourcePathMap = new();
private static ConcurrentDictionary<Guid, Resource> _loadedResources = new();
}
}

View File

@@ -55,7 +55,7 @@ public class ParticleEmitterSettingsResource : Resource
public class ParticleEmitterSettingsResourceLoader : ResourceLoader<ParticleEmitterSettingsResource>
{
public override IEnumerable<string> SupportedExtensions => new string[] {
"toml"
".toml"
};
protected override ParticleEmitterSettingsResource LoadResource(string path)