Readded resource unloading.
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -11,7 +11,7 @@
|
||||
## I/O
|
||||
|
||||
- ~~Use GUIDs and string ID maps for fetching resources instead of string IDs alone.~~
|
||||
- Reimplement unloading.
|
||||
- ~~Reimplement unloading.~~
|
||||
- Finalize ResourceManager and ResourceLoader APIs for 1.0.
|
||||
- Add async API for ResourceManager.
|
||||
- Virtual file system.
|
||||
|
||||
@@ -5,7 +5,7 @@ public class FontLoader : ResourceLoader<Font>
|
||||
{
|
||||
public override IEnumerable<string> SupportedExtensions => new string[]
|
||||
{
|
||||
"ttf"
|
||||
".ttf"
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
// }
|
||||
|
||||
return true;
|
||||
if (!_resourcePathMap.ContainsKey(resourcePath))
|
||||
{
|
||||
throw new KeyNotFoundException($"Resource at path \"{resourcePath}\" was not found!");
|
||||
}
|
||||
|
||||
// TODO
|
||||
public bool TryUnload(Guid resourceGuid)
|
||||
var guid = _resourcePathMap[resourcePath];
|
||||
RemoveResource(guid);
|
||||
}
|
||||
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user