using System;
using System.Collections.Generic;
using System.Reflection;
using UdonSharpEditor;
using UnityEngine;
using VRC.Udon;
namespace UdonSharp.Serialization
{
///
/// UdonSharpBehaviour Serialization Context, confusing abbreviation isn't it?
///
internal static class USBSerializationContext
{
public static HashSet serializedBehaviourSet = new HashSet();
public static ProxySerializationPolicy currentPolicy = null;
public static int currentDepth = 0;
}
public class UdonSharpBehaviourSerializer : Serializer where T : UdonSharpBehaviour
{
public UdonSharpBehaviourSerializer(TypeSerializationMetadata typeMetadata)
: base(typeMetadata)
{
}
public override Type GetUdonStorageType()
{
return typeof(UdonBehaviour);
}
public override bool HandlesTypeSerialization(TypeSerializationMetadata typeMetadata)
{
return typeMetadata.cSharpType == typeof(UdonSharpBehaviour) || typeMetadata.cSharpType.IsSubclassOf(typeof(UdonSharpBehaviour));
}
public override void Read(ref T targetObject, IValueStorage sourceObject)
{
UdonBehaviour sourceBehaviour = (UdonBehaviour)sourceObject.Value;
if (sourceBehaviour == null)
{
targetObject = null;
return;
}
if (USBSerializationContext.currentPolicy == null)
throw new NullReferenceException("Serialization policy cannot be null");
targetObject = (T)UdonSharpEditorUtility.GetProxyBehaviour(sourceBehaviour, ProxySerializationPolicy.NoSerialization);
if (USBSerializationContext.currentDepth >= USBSerializationContext.currentPolicy.MaxSerializationDepth)
return;
if (USBSerializationContext.serializedBehaviourSet.Contains(targetObject))
return;
USBSerializationContext.serializedBehaviourSet.Add(targetObject);
USBSerializationContext.currentDepth++;
try
{
UdonSharpBehaviourFormatterEmitter.GetFormatter().Read(ref targetObject, sourceObject);
}
finally
{
USBSerializationContext.currentDepth--;
if (USBSerializationContext.currentDepth <= 0)
{
Debug.Assert(USBSerializationContext.currentDepth == 0, "Serialization depth cannot be negative");
USBSerializationContext.serializedBehaviourSet.Clear();
}
}
}
public override void Write(IValueStorage targetObject, in T sourceObject)
{
if (sourceObject == null)
{
targetObject.Value = null;
return;
}
if (USBSerializationContext.currentPolicy == null)
throw new NullReferenceException("Serialization policy cannot be null");
UdonBehaviour backingBehaviour = UdonSharpEditorUtility.GetBackingUdonBehaviour(sourceObject);
if (USBSerializationContext.currentDepth >= USBSerializationContext.currentPolicy.MaxSerializationDepth)
{
if (backingBehaviour)
targetObject.Value = backingBehaviour;
else
targetObject.Value = null;
return;
}
USBSerializationContext.currentDepth++;
try
{
if (backingBehaviour)
{
targetObject.Value = backingBehaviour;
}
else if (USBSerializationContext.currentPolicy.ChildProxyMode == ProxySerializationPolicy.ChildProxyCreateMode.Create)
{
UdonBehaviour newBehaviour = UdonSharpEditorUtility.ConvertToUdonBehaviours(new UdonSharpBehaviour[] { sourceObject })[0];
targetObject.Value = newBehaviour;
}
else if (USBSerializationContext.currentPolicy.ChildProxyMode == ProxySerializationPolicy.ChildProxyCreateMode.CreateWithUndo)
{
UdonBehaviour newBehaviour = UdonSharpEditorUtility.ConvertToUdonBehavioursWithUndo(new UdonSharpBehaviour[] { sourceObject })[0];
targetObject.Value = newBehaviour;
}
else
{
targetObject.Value = null;
}
if (USBSerializationContext.serializedBehaviourSet.Contains(sourceObject))
return;
USBSerializationContext.serializedBehaviourSet.Add(sourceObject);
UdonSharpBehaviourFormatterEmitter.GetFormatter().Write(targetObject, sourceObject);
}
finally
{
USBSerializationContext.currentDepth--;
if (USBSerializationContext.currentDepth <= 0)
{
Debug.Assert(USBSerializationContext.currentDepth == 0, "Serialization depth cannot be negative");
USBSerializationContext.serializedBehaviourSet.Clear();
}
}
}
protected override Serializer MakeSerializer(TypeSerializationMetadata typeMetadata)
{
return (Serializer)System.Activator.CreateInstance(typeof(UdonSharpBehaviourSerializer<>).MakeGenericType(typeMetadata.cSharpType), typeMetadata);
}
}
}