OverviewFilesCommitsIssuesDocsReleasesPeers

ifsrenderer-linux / IFSEngine / Serialization / EffectLayerConverter.cs

64 lines · csharp ref:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

using IFSEngine.Model;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace IFSEngine.Serialization;

public class EffectLayerConverter : JsonConverter<EffectLayer>
{
    private readonly bool _ignoreVersion;
    private readonly IEnumerable<EffectPlugin> _loadedPostFxs;

    public EffectLayerConverter(IEnumerable<EffectPlugin> postfxs, bool ignoreVersion)
    {
        _loadedPostFxs = postfxs;
        _ignoreVersion = ignoreVersion;
    }

    public override EffectLayer ReadJson(JsonReader reader, Type objectType, EffectLayer existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        //(string Name, string Version) = jo.ToObject<ValueTuple<string, string>>(serializer);
        var Name = jo[nameof(EffectPlugin.Name)]?.ToObject<string>(serializer);
        var Version = jo[nameof(EffectPlugin.Version)]?.ToObject<string>(serializer);
        var realParams = jo[nameof(EffectLayer.RealParams)]?.ToObject<Dictionary<string, double>>(serializer) ?? [];
        var vec3Params = jo[nameof(EffectLayer.Vec3Params)]?.ToObject<Dictionary<string, Vector3>>(serializer) ?? [];
        bool enabled = jo.TryGetValue(nameof(EffectLayer.Enabled), out var enabledToken) && enabledToken?.ToObject<bool>(serializer) == true;

        var fx = _loadedPostFxs.FirstOrDefault(i => i.Name == Name && i.Version == Version);
        if (fx is null && _ignoreVersion)
            fx = _loadedPostFxs.FirstOrDefault(i => i.Name == Name);
        if (fx is null)
            throw new UnknownPluginException(Name, Version);

        var instance = jo.ToObject<EffectLayer>();
        instance.SetEffect(fx);
        //merge serialized params with plugin defaults
        foreach (var k in instance.RealParams.Keys.Union(fx.RealParams.Keys).ToList())
            instance.RealParams[k] = realParams.TryGetValue(k, out double val) ? val : fx.RealParams.GetValueOrDefault(k, 0);
        foreach (var k in instance.Vec3Params.Keys.Union(fx.Vec3Params.Keys).ToList())
            instance.Vec3Params[k] = vec3Params.TryGetValue(k, out Vector3 val) ? val : fx.Vec3Params.GetValueOrDefault(k, Vector3.Zero);
        return instance;
    }

    public override void WriteJson(JsonWriter writer, EffectLayer value, JsonSerializer serializer)
    {
        JObject jo = new()
        {
            [nameof(EffectLayer.Id)] = JToken.FromObject(value.Id),
            [nameof(EffectPlugin.Name)] = JToken.FromObject(value.Effect.Name),
            [nameof(EffectPlugin.Version)] = JToken.FromObject(value.Effect.Version),
            [nameof(EffectLayer.Enabled)] = JToken.FromObject(value.Enabled),
            [nameof(EffectLayer.RealParams)] = JToken.FromObject(value.RealParams),
            [nameof(EffectLayer.Vec3Params)] = JToken.FromObject(value.Vec3Params)
        };
        jo.WriteTo(writer);
    }
}