Files
Voile/Voile/Source/Resources/Resource.cs
2025-06-29 16:51:06 +02:00

110 lines
3.4 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Voile.Resources;
namespace Voile
{
/// <summary>
/// Wraps a reference to an asset of a given type.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class ResourceRef<T> where T : Resource
{
/// <summary>
/// Resource GUID this ResourceRef maps to.
/// </summary>
public readonly Guid Guid = Guid.Empty;
public bool HasValue => Guid != Guid.Empty;
/// <summary>
/// Retrieves a <see cref="Resource"/>.<br />
/// This will throw an <see cref="InvalidOperationException"/> if the resource wasn't loaded or is invalid. <br />
/// You can check if resource was loaded with <see cref="HasValue"/>, or consider using <see cref="TryGetValue"/>.
/// </summary>
public T Value => ResourceManager.GetResource<T>(Guid)
?? throw new InvalidOperationException($"Resource with GUID {Guid} is not loaded or invalid.");
/// <summary>
/// Retrieves a resource or <c>null</c> if the resource wasn't loaded or is invalid.
/// </summary>
public T? ValueOrNull => ResourceManager.GetResource<T>(Guid);
/// <summary>
/// Tries to retrieve a <see cref="Resource"/>.
/// </summary>
/// <param name="value">An instance of a retrieved <see cref="Resource"/>.</param>
/// <returns><c>true</c> if the resource was successfully retrieved, otherwise <c>false</c>.</returns>
public bool TryGetValue([NotNullWhen(true)] out T? value)
{
value = ResourceManager.GetResource<T>(Guid);
return value != null;
}
/// <summary>
/// Create an empty <see cref="ResourceRef"/>.
/// </summary>
/// <returns></returns>
public static ResourceRef<T> Empty()
{
return new ResourceRef<T>(Guid.Empty);
}
public ResourceRef(Guid guid)
{
Guid = guid;
}
public override bool Equals(object? obj)
{
return obj is ResourceRef<T> other && Guid.Equals(other.Guid);
}
public override int GetHashCode()
{
return Guid.GetHashCode();
}
public static bool operator ==(ResourceRef<T>? left, ResourceRef<T>? right)
{
if (ReferenceEquals(left, right)) return true;
if (left is null || right is null) return false;
return left.Guid == right.Guid;
}
public static bool operator !=(ResourceRef<T>? left, ResourceRef<T>? right)
{
return !(left == right);
}
}
/// <summary>
/// Represents data usable by Voile.
/// </summary>
public abstract class Resource
{
/// <summary>
/// Path to this resource.
/// </summary>
public string Path { get; private set; } = string.Empty;
public Resource(string path)
{
Path = path;
}
}
/// <summary>
/// Represents a Resource that requires systems to react to its changes.
/// </summary>
public interface IUpdatableResource
{
/// <summary>
/// Gets a value indicating whether this resource's state has changed and needs to be reloaded.
/// </summary>
bool Dirty { get; }
/// <summary>
/// Marks this resource as updated.
/// </summary>
void MarkUpdated();
}
}