Code/MovieResource.cs
using System;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Sandbox.MovieMaker.Compiled;
namespace Sandbox.MovieMaker;
#nullable enable
/// <summary>
/// A container for a <see cref="MovieClip"/>, including optional <see cref="EditorData"/>.
/// </summary>
[JsonConverter( typeof(MovieResourceConverter) )]
public interface IMovieResource
{
/// <summary>
/// Compiled movie clip.
/// </summary>
MovieClip? Compiled { get; set; }
/// <summary>
/// Editor-only data used to generate <see cref="Compiled"/>.
/// </summary>
JsonNode? EditorData { get; set; }
}
/// <summary>
/// An <see cref="IClip"/> stored on disk as a resource.
/// </summary>
[GameResource( "Movie Clip", "movie", $"A movie clip created with the {nameof(MoviePlayer)} component.", Icon = "video_file" )]
public sealed class MovieResource : GameResource, IMovieResource
{
/// <inheritdoc />
[Hide]
public MovieClip? Compiled { get; set; }
/// <inheritdoc />
[Hide]
public JsonNode? EditorData { get; set; }
protected override void OnJsonSerialize( JsonObject node )
{
// Here we're writing the .movie, not the .movie_c
// We only want EditorData to be written here,
// MovieCompiler will handle writing Compiled to the .movie_c
node.Remove( nameof(Compiled) );
}
}
/// <summary>
/// An <see cref="IClip"/> embedded in a property.
/// </summary>
public sealed class EmbeddedMovieResource : IMovieResource
{
/// <inheritdoc />
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
public MovieClip? Compiled { get; set; }
/// <inheritdoc />
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
public JsonNode? EditorData { get; set; }
}
file sealed class MovieResourceConverter : JsonConverter<IMovieResource>
{
public override void Write( Utf8JsonWriter writer, IMovieResource value, JsonSerializerOptions options )
{
switch ( value )
{
case MovieResource resource:
writer.WriteStringValue( resource.ResourcePath );
return;
case EmbeddedMovieResource embedded:
JsonSerializer.Serialize( writer, embedded, options );
return;
default:
throw new NotImplementedException();
}
}
public override IMovieResource Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options )
{
switch ( reader.TokenType )
{
case JsonTokenType.String:
return JsonSerializer.Deserialize<MovieResource>( ref reader, options )!;
case JsonTokenType.StartObject:
return JsonSerializer.Deserialize<EmbeddedMovieResource>( ref reader, options )!;
default:
throw new Exception( "Expected resource path or embedded resource object." );
}
}
}