OverviewFilesCommitsIssuesDocsReleasesPeers

ifsrenderer-linux / IFSEngine / Serialization / IfsConverter.cs

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

using IFSEngine.Model;

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

namespace IFSEngine.Serialization;

public class IfsConverter : JsonConverter<IFS>
{
    public override IFS ReadJson(JsonReader reader, Type objectType, /*[AllowNullAttribute]*/ IFS existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        double[][] xaos = jo["xaos"].ToObject<double[][]>(serializer);
        jo.Remove("xaos");
        //iterators
        List<Iterator> iterators = [];
        List<Exception> exceptions = [];
        foreach (var iteratorToken in jo["Iterators"].Children())
        {
            try
            {
                iterators.Add(iteratorToken.ToObject<Iterator>(serializer));
            }
            catch (UnknownPluginException ex) { exceptions.Add(ex); }
        }
        if (exceptions.Count > 0)
            throw new AggregateException("Failed to deserialize iterators", exceptions);
        jo.Remove("Iterators");

        //posteffect layers
        List<EffectLayer> postEffectLayers = [];
        List<Exception> postFxExceptions = [];
        if (jo.ContainsKey("PostEffects"))
        {
            foreach (var postFxToken in jo["PostEffects"].Children())
            {
                try
                {
                    postEffectLayers.Add(postFxToken.ToObject<EffectLayer>(serializer));
                }
                catch (UnknownPluginException ex) { postFxExceptions.Add(ex); }
            }
            jo.Remove("PostEffects");
        }
        if (postFxExceptions.Count > 0)
            throw new AggregateException("Failed to deserialize posteffect layers", postFxExceptions);

        serializer.Converters.Remove(this);
        var ifs = jo.ToObject<IFS>(serializer);
        serializer.Converters.Add(this);
        List<Author> authorsList = jo["Authors"].ToObject<List<Author>>();
        foreach (var author in authorsList)
            ifs.AddAuthor(author);
        foreach (var i in iterators)
            ifs.AddIterator(i, false);
        //set xaos weights separately
        var iters = ifs.Iterators.ToList();
        for (int i = 0; i < xaos.GetLength(0); i++)
        {
            iters[i].WeightTo = iters.ToDictionary(k => k, v => xaos[i][iters.IndexOf(v)]);
        }
        foreach (var postFxLayer in postEffectLayers)
            ifs.AddPostEffectLayer(postFxLayer);
        return ifs;
    }

    public override void WriteJson(JsonWriter writer, /*[AllowNullAttribute]*/ IFS value, JsonSerializer serializer)
    {
        serializer.Converters.Remove(this);
        JObject jo = JObject.FromObject(value, serializer);
        serializer.Converters.Add(this);
        //the model has the iterators in a set, they must be ordered to serialize
        List<Iterator> list = value.Iterators.ToList();
        double[][] xaos = new double[list.Count][];
        for (int i = 0; i < list.Count; i++)
        {
            xaos[i] = new double[list.Count];
            for (int j = 0; j < list.Count; j++)
            {
                list[i].WeightTo.TryGetValue(list[j], out double weight);//0 if not found
                xaos[i][j] = weight;
            }
        }
        jo["xaos"] = JToken.FromObject(xaos, serializer);
        jo.WriteTo(writer, serializer.Converters.ToArray());
    }
}