# Conflicts: # Source/Platforms/DotNet/NUnit/agents/net40/nunit-agent.exe # Source/Platforms/DotNet/NUnit/agents/net40/nunit.engine.api.dll # Source/Platforms/DotNet/NUnit/agents/net40/nunit.engine.core.dll # Source/Platforms/DotNet/NUnit/agents/net7.0/nunit.agent.addins # Source/Platforms/DotNet/NUnit/nunit.engine.api.dll # Source/Platforms/DotNet/NUnit/nunit.engine.core.dll # Source/Platforms/DotNet/NUnit/nunit.engine.dll # Source/Platforms/DotNet/NUnit/nunit3-console.exe # Source/Platforms/DotNet/NUnit/nunit3-console.exe.config # Source/Platforms/DotNet/NUnit/testcentric.engine.metadata.dll # Source/Tools/Flax.Build/Deps/Downloader.cs # Source/Tools/Flax.Stats/CodeFrame.cs # Source/Tools/Flax.Stats/CodeFrameNode.cs # Source/Tools/Flax.Stats/Flax.Stats.Build.cs # Source/Tools/Flax.Stats/Languages.cs # Source/Tools/Flax.Stats/Program.cs # Source/Tools/Flax.Stats/TaskType.cs # Source/Tools/Flax.Stats/Tools.cs # Source/Tools/FlaxEngine.Tests/TestEditorUtils.cs
1298 lines
50 KiB
C#
1298 lines
50 KiB
C#
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
#if FLAX_EDITOR
|
|
using FlaxEditor.Scripting;
|
|
using FlaxEditor.Utilities;
|
|
#endif
|
|
using FlaxEngine;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace FlaxEngine.Utilities
|
|
{
|
|
/// <summary>
|
|
/// Editor utilities and helper functions for Variant type.
|
|
/// </summary>
|
|
public static class VariantUtils
|
|
{
|
|
internal enum VariantType
|
|
{
|
|
Null = 0,
|
|
Void,
|
|
|
|
Bool,
|
|
Int,
|
|
Uint,
|
|
Int64,
|
|
Uint64,
|
|
Float,
|
|
Double,
|
|
Pointer,
|
|
|
|
String,
|
|
Object,
|
|
Structure,
|
|
Asset,
|
|
Blob,
|
|
Enum,
|
|
|
|
Float2,
|
|
Float3,
|
|
Float4,
|
|
Color,
|
|
Guid,
|
|
BoundingBox,
|
|
BoundingSphere,
|
|
Quaternion,
|
|
Transform,
|
|
Rectangle,
|
|
Ray,
|
|
Matrix,
|
|
|
|
Array,
|
|
Dictionary,
|
|
ManagedObject,
|
|
Typename,
|
|
|
|
Int2,
|
|
Int3,
|
|
Int4,
|
|
|
|
Int16,
|
|
Uint16,
|
|
|
|
Double2,
|
|
Double3,
|
|
Double4,
|
|
|
|
#if USE_LARGE_WORLDS
|
|
Vector2 = Double2,
|
|
Vector3 = Double3,
|
|
Vector4 = Double4,
|
|
#else
|
|
Vector2 = Float2,
|
|
Vector3 = Float3,
|
|
Vector4 = Float4,
|
|
#endif
|
|
}
|
|
|
|
#if FLAX_EDITOR
|
|
internal static VariantType ToVariantType(this Type type)
|
|
{
|
|
VariantType variantType;
|
|
if (type == null)
|
|
variantType = VariantType.Null;
|
|
else if (type == typeof(void))
|
|
variantType = VariantType.Void;
|
|
else if (type == typeof(bool))
|
|
variantType = VariantType.Bool;
|
|
else if (type == typeof(short))
|
|
variantType = VariantType.Int16;
|
|
else if (type == typeof(ushort))
|
|
variantType = VariantType.Uint16;
|
|
else if (type == typeof(int))
|
|
variantType = VariantType.Int;
|
|
else if (type == typeof(uint))
|
|
variantType = VariantType.Uint;
|
|
else if (type == typeof(long))
|
|
variantType = VariantType.Int64;
|
|
else if (type == typeof(ulong))
|
|
variantType = VariantType.Uint64;
|
|
else if (type.IsEnum)
|
|
variantType = VariantType.Enum;
|
|
else if (type == typeof(float))
|
|
variantType = VariantType.Float;
|
|
else if (type == typeof(double))
|
|
variantType = VariantType.Double;
|
|
else if (type == typeof(IntPtr))
|
|
variantType = VariantType.Pointer;
|
|
else if (type == typeof(string))
|
|
variantType = VariantType.String;
|
|
else if (type == typeof(Type))
|
|
variantType = VariantType.Typename;
|
|
else if (type == typeof(ScriptType))
|
|
variantType = VariantType.Typename;
|
|
else if (typeof(Asset).IsAssignableFrom(type))
|
|
variantType = VariantType.Asset;
|
|
else if (typeof(FlaxEngine.Object).IsAssignableFrom(type))
|
|
variantType = VariantType.Object;
|
|
else if (type == typeof(BoundingBox))
|
|
variantType = VariantType.BoundingBox;
|
|
else if (type == typeof(Transform))
|
|
variantType = VariantType.Transform;
|
|
else if (type == typeof(Ray))
|
|
variantType = VariantType.Ray;
|
|
else if (type == typeof(Matrix))
|
|
variantType = VariantType.Matrix;
|
|
else if (type == typeof(Float2))
|
|
variantType = VariantType.Float2;
|
|
else if (type == typeof(Float3))
|
|
variantType = VariantType.Float3;
|
|
else if (type == typeof(Float4))
|
|
variantType = VariantType.Float4;
|
|
else if (type == typeof(Double2))
|
|
variantType = VariantType.Double2;
|
|
else if (type == typeof(Double3))
|
|
variantType = VariantType.Double3;
|
|
else if (type == typeof(Double4))
|
|
variantType = VariantType.Double4;
|
|
else if (type == typeof(Vector2))
|
|
variantType = VariantType.Vector2;
|
|
else if (type == typeof(Vector3))
|
|
variantType = VariantType.Vector3;
|
|
else if (type == typeof(Vector4))
|
|
variantType = VariantType.Vector4;
|
|
else if (type == typeof(Int2))
|
|
variantType = VariantType.Int2;
|
|
else if (type == typeof(Int3))
|
|
variantType = VariantType.Int3;
|
|
else if (type == typeof(Int4))
|
|
variantType = VariantType.Int4;
|
|
else if (type == typeof(Color))
|
|
variantType = VariantType.Color;
|
|
else if (type == typeof(Guid))
|
|
variantType = VariantType.Guid;
|
|
else if (type == typeof(Quaternion))
|
|
variantType = VariantType.Quaternion;
|
|
else if (type == typeof(Rectangle))
|
|
variantType = VariantType.Rectangle;
|
|
else if (type == typeof(BoundingSphere))
|
|
variantType = VariantType.BoundingSphere;
|
|
else if (type.IsValueType)
|
|
variantType = VariantType.Structure;
|
|
else if (type == typeof(byte[]))
|
|
variantType = VariantType.Blob;
|
|
else if (type.IsArray)
|
|
variantType = VariantType.Array;
|
|
else if (type == typeof(Dictionary<object, object>) || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>)))
|
|
variantType = VariantType.Dictionary;
|
|
else if (type.IsPointer || type.IsByRef)
|
|
{
|
|
// Find underlying type without `*` or `&`
|
|
var typeName = type.FullName;
|
|
type = TypeUtils.GetManagedType(typeName.Substring(0, typeName.Length - 1));
|
|
return ToVariantType(type);
|
|
}
|
|
else
|
|
variantType = VariantType.ManagedObject;
|
|
return variantType;
|
|
}
|
|
|
|
internal static void WriteVariantType(this BinaryWriter stream, ScriptType type)
|
|
{
|
|
if (type == ScriptType.Null)
|
|
{
|
|
stream.Write((byte)0);
|
|
stream.Write(0);
|
|
return;
|
|
}
|
|
if (type.Type != null)
|
|
{
|
|
WriteVariantType(stream, type.Type);
|
|
}
|
|
else
|
|
{
|
|
if (type.IsEnum)
|
|
stream.Write((byte)VariantType.Enum);
|
|
else if (type.IsValueType)
|
|
stream.Write((byte)VariantType.Structure);
|
|
else
|
|
stream.Write((byte)VariantType.Object);
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.TypeName, 77);
|
|
}
|
|
}
|
|
|
|
internal static void WriteVariantType(this BinaryWriter stream, Type type)
|
|
{
|
|
if (type == null)
|
|
{
|
|
stream.Write((byte)0);
|
|
stream.Write(0);
|
|
return;
|
|
}
|
|
var variantType = ToVariantType(type);
|
|
stream.Write((byte)variantType);
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Object:
|
|
if (type != typeof(FlaxEngine.Object))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
case VariantType.Asset:
|
|
if (type != typeof(Asset))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
case VariantType.Enum:
|
|
case VariantType.Structure:
|
|
case VariantType.ManagedObject:
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
break;
|
|
case VariantType.Typename:
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.GetTypeName(), 77);
|
|
break;
|
|
case VariantType.Array:
|
|
if (type != typeof(object[]))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
case VariantType.Dictionary:
|
|
if (type != typeof(Dictionary<object, object>))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.GetTypeName(), 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
default:
|
|
stream.Write(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
internal static ScriptType ReadVariantScriptType(this BinaryReader stream)
|
|
{
|
|
var variantType = (VariantType)stream.ReadByte();
|
|
var typeNameLength = stream.ReadInt32();
|
|
if (typeNameLength == int.MaxValue)
|
|
{
|
|
typeNameLength = stream.ReadInt32();
|
|
var data = new byte[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadByte();
|
|
data[i] = (byte)(c ^ 77);
|
|
}
|
|
var typeName = System.Text.Encoding.ASCII.GetString(data);
|
|
return TypeUtils.GetType(typeName);
|
|
}
|
|
if (typeNameLength > 0)
|
|
{
|
|
// [Deprecated on 27.08.2020, expires on 27.08.2021]
|
|
var data = new char[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadUInt16();
|
|
data[i] = (char)(c ^ 77);
|
|
}
|
|
var typeName = new string(data);
|
|
return TypeUtils.GetType(typeName);
|
|
}
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Null: return ScriptType.Null;
|
|
case VariantType.Void: return new ScriptType(typeof(void));
|
|
case VariantType.Bool: return new ScriptType(typeof(bool));
|
|
case VariantType.Int16: return new ScriptType(typeof(short));
|
|
case VariantType.Uint16: return new ScriptType(typeof(ushort));
|
|
case VariantType.Int: return new ScriptType(typeof(int));
|
|
case VariantType.Uint: return new ScriptType(typeof(uint));
|
|
case VariantType.Int64: return new ScriptType(typeof(long));
|
|
case VariantType.Uint64: return new ScriptType(typeof(ulong));
|
|
case VariantType.Float: return new ScriptType(typeof(float));
|
|
case VariantType.Double: return new ScriptType(typeof(double));
|
|
case VariantType.Pointer: return new ScriptType(typeof(IntPtr));
|
|
case VariantType.String: return new ScriptType(typeof(string));
|
|
case VariantType.Typename: return new ScriptType(typeof(Type));
|
|
case VariantType.Object: return ScriptType.FlaxObject;
|
|
case VariantType.Asset: return new ScriptType(typeof(Asset));
|
|
case VariantType.Float2: return new ScriptType(typeof(Float2));
|
|
case VariantType.Float3: return new ScriptType(typeof(Float3));
|
|
case VariantType.Float4: return new ScriptType(typeof(Float4));
|
|
case VariantType.Double2: return new ScriptType(typeof(Double2));
|
|
case VariantType.Double3: return new ScriptType(typeof(Double3));
|
|
case VariantType.Double4: return new ScriptType(typeof(Double4));
|
|
case VariantType.Int2: return new ScriptType(typeof(Int2));
|
|
case VariantType.Int3: return new ScriptType(typeof(Int3));
|
|
case VariantType.Int4: return new ScriptType(typeof(Int4));
|
|
case VariantType.Color: return new ScriptType(typeof(Color));
|
|
case VariantType.Guid: return new ScriptType(typeof(Guid));
|
|
case VariantType.BoundingBox: return new ScriptType(typeof(BoundingBox));
|
|
case VariantType.BoundingSphere: return new ScriptType(typeof(BoundingSphere));
|
|
case VariantType.Quaternion: return new ScriptType(typeof(Quaternion));
|
|
case VariantType.Transform: return new ScriptType(typeof(Transform));
|
|
case VariantType.Rectangle: return new ScriptType(typeof(Rectangle));
|
|
case VariantType.Ray: return new ScriptType(typeof(Ray));
|
|
case VariantType.Matrix: return new ScriptType(typeof(Matrix));
|
|
case VariantType.Array: return new ScriptType(typeof(object[]));
|
|
case VariantType.Dictionary: return new ScriptType(typeof(Dictionary<object, object>));
|
|
case VariantType.ManagedObject: return ScriptType.Object;
|
|
case VariantType.Blob: return new ScriptType(typeof(byte[]));
|
|
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType} without typename.");
|
|
}
|
|
}
|
|
|
|
internal static Type ReadVariantType(this BinaryReader stream)
|
|
{
|
|
var variantType = (VariantType)stream.ReadByte();
|
|
var typeNameLength = stream.ReadInt32();
|
|
if (typeNameLength == int.MaxValue)
|
|
{
|
|
typeNameLength = stream.ReadInt32();
|
|
var data = new byte[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadByte();
|
|
data[i] = (byte)(c ^ 77);
|
|
}
|
|
var typeName = System.Text.Encoding.ASCII.GetString(data);
|
|
return TypeUtils.GetManagedType(typeName);
|
|
}
|
|
if (typeNameLength > 0)
|
|
{
|
|
// [Deprecated on 27.08.2020, expires on 27.08.2021]
|
|
var data = new char[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadUInt16();
|
|
data[i] = (char)(c ^ 77);
|
|
}
|
|
var typeName = new string(data);
|
|
return TypeUtils.GetManagedType(typeName);
|
|
}
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Null: return null;
|
|
case VariantType.Void: return typeof(void);
|
|
case VariantType.Bool: return typeof(bool);
|
|
case VariantType.Int16: return typeof(short);
|
|
case VariantType.Uint16: return typeof(ushort);
|
|
case VariantType.Int: return typeof(int);
|
|
case VariantType.Uint: return typeof(uint);
|
|
case VariantType.Int64: return typeof(long);
|
|
case VariantType.Uint64: return typeof(ulong);
|
|
case VariantType.Float: return typeof(float);
|
|
case VariantType.Double: return typeof(double);
|
|
case VariantType.Pointer: return typeof(IntPtr);
|
|
case VariantType.String: return typeof(string);
|
|
case VariantType.Typename: return typeof(Type);
|
|
case VariantType.Object: return typeof(FlaxEngine.Object);
|
|
case VariantType.Asset: return typeof(Asset);
|
|
case VariantType.Float2: return typeof(Float2);
|
|
case VariantType.Float3: return typeof(Float3);
|
|
case VariantType.Float4: return typeof(Float4);
|
|
case VariantType.Double2: return typeof(Double2);
|
|
case VariantType.Double3: return typeof(Double3);
|
|
case VariantType.Double4: return typeof(Double4);
|
|
case VariantType.Int2: return typeof(Int2);
|
|
case VariantType.Int3: return typeof(Int3);
|
|
case VariantType.Int4: return typeof(Int4);
|
|
case VariantType.Color: return typeof(Color);
|
|
case VariantType.Guid: return typeof(Guid);
|
|
case VariantType.BoundingBox: return typeof(BoundingBox);
|
|
case VariantType.BoundingSphere: return typeof(BoundingSphere);
|
|
case VariantType.Quaternion: return typeof(Quaternion);
|
|
case VariantType.Transform: return typeof(Transform);
|
|
case VariantType.Rectangle: return typeof(Rectangle);
|
|
case VariantType.Ray: return typeof(Ray);
|
|
case VariantType.Matrix: return typeof(Matrix);
|
|
case VariantType.Array: return typeof(object[]);
|
|
case VariantType.Dictionary: return typeof(Dictionary<object, object>);
|
|
case VariantType.ManagedObject: return typeof(object);
|
|
case VariantType.Blob: return typeof(byte[]);
|
|
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType} without typename.");
|
|
}
|
|
}
|
|
|
|
internal static unsafe object ReadVariant(this BinaryReader stream)
|
|
{
|
|
Type type = null;
|
|
var variantType = (VariantType)stream.ReadByte();
|
|
var typeNameLength = stream.ReadInt32();
|
|
string typeName = string.Empty;
|
|
if (typeNameLength == int.MaxValue)
|
|
{
|
|
typeNameLength = stream.ReadInt32();
|
|
var data = new byte[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadByte();
|
|
data[i] = (byte)(c ^ 77);
|
|
}
|
|
typeName = System.Text.Encoding.ASCII.GetString(data);
|
|
type = TypeUtils.GetManagedType(typeName);
|
|
}
|
|
else if (typeNameLength > 0)
|
|
{
|
|
// [Deprecated on 27.08.2020, expires on 27.08.2021]
|
|
var data = new char[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadUInt16();
|
|
data[i] = (char)(c ^ 77);
|
|
}
|
|
typeName = new string(data);
|
|
type = TypeUtils.GetManagedType(typeName);
|
|
}
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Null:
|
|
case VariantType.Void: return null;
|
|
case VariantType.Bool: return stream.ReadByte() != 0;
|
|
case VariantType.Int16: return stream.ReadInt16();
|
|
case VariantType.Uint16: return stream.ReadUInt16();
|
|
case VariantType.Int: return stream.ReadInt32();
|
|
case VariantType.Uint: return stream.ReadUInt32();
|
|
case VariantType.Int64: return stream.ReadInt64();
|
|
case VariantType.Uint64: return stream.ReadUInt64();
|
|
case VariantType.Float: return stream.ReadSingle();
|
|
case VariantType.Double: return stream.ReadDouble();
|
|
case VariantType.Pointer: return new IntPtr((void*)stream.ReadUInt64());
|
|
case VariantType.String:
|
|
{
|
|
typeNameLength = stream.ReadInt32();
|
|
var data = new char[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadUInt16();
|
|
data[i] = (char)(c ^ -14);
|
|
}
|
|
return new string(data);
|
|
}
|
|
case VariantType.Object:
|
|
{
|
|
var id = stream.ReadGuid();
|
|
return FlaxEngine.Object.Find(ref id, type ?? typeof(FlaxEngine.Object));
|
|
}
|
|
case VariantType.Asset:
|
|
{
|
|
var id = stream.ReadGuid();
|
|
return FlaxEngine.Object.Find(ref id, type ?? typeof(Asset));
|
|
}
|
|
case VariantType.Blob: return stream.ReadBytes(stream.ReadInt32());
|
|
case VariantType.Enum:
|
|
{
|
|
if (type == null)
|
|
throw new Exception("Missing enum type of the Variant.");
|
|
return Enum.ToObject(type, stream.ReadUInt64());
|
|
}
|
|
case VariantType.Float2: return stream.ReadFloat2();
|
|
case VariantType.Float3: return stream.ReadFloat3();
|
|
case VariantType.Float4: return stream.ReadFloat4();
|
|
case VariantType.Double2: return stream.ReadDouble2();
|
|
case VariantType.Double3: return stream.ReadDouble3();
|
|
case VariantType.Double4: return stream.ReadDouble4();
|
|
case VariantType.Int2: return stream.ReadInt2();
|
|
case VariantType.Int3: return stream.ReadInt3();
|
|
case VariantType.Int4: return stream.ReadInt4();
|
|
case VariantType.Color: return stream.ReadColor();
|
|
case VariantType.Guid: return stream.ReadGuid();
|
|
case VariantType.BoundingBox: return stream.ReadBoundingBox();
|
|
case VariantType.BoundingSphere: return stream.ReadBoundingSphere();
|
|
case VariantType.Quaternion: return stream.ReadQuaternion();
|
|
case VariantType.Transform: return stream.ReadTransform();
|
|
case VariantType.Rectangle: return stream.ReadRectangle();
|
|
case VariantType.Ray: return stream.ReadRay();
|
|
case VariantType.Matrix: return stream.ReadMatrix();
|
|
case VariantType.Array:
|
|
{
|
|
if (type == null)
|
|
type = typeof(object[]);
|
|
else if (!type.IsArray)
|
|
throw new Exception("Invalid type for the Variant array " + typeName);
|
|
var count = stream.ReadInt32();
|
|
var result = Array.CreateInstance(type.GetElementType(), count);
|
|
for (int i = 0; i < count; i++)
|
|
result.SetValue(stream.ReadVariant(), i);
|
|
return result;
|
|
}
|
|
case VariantType.Dictionary:
|
|
{
|
|
if (type == null)
|
|
type = typeof(Dictionary<object, object>);
|
|
else if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Dictionary<,>))
|
|
throw new Exception("Invalid type for the Variant dictionary " + typeName);
|
|
var count = stream.ReadInt32();
|
|
var result = (IDictionary)Activator.CreateInstance(type);
|
|
for (int i = 0; i < count; i++)
|
|
result.Add(stream.ReadVariant(), stream.ReadVariant());
|
|
return result;
|
|
}
|
|
case VariantType.Typename:
|
|
{
|
|
typeNameLength = stream.ReadInt32();
|
|
var data = new byte[typeNameLength];
|
|
for (int i = 0; i < typeNameLength; i++)
|
|
{
|
|
var c = stream.ReadByte();
|
|
data[i] = (byte)(c ^ -14);
|
|
}
|
|
typeName = System.Text.Encoding.ASCII.GetString(data);
|
|
return TypeUtils.GetType(typeName);
|
|
}
|
|
case VariantType.ManagedObject:
|
|
case VariantType.Structure:
|
|
{
|
|
if (type == null)
|
|
throw new Exception("Missing type of the Variant typename " + typeName);
|
|
var format = stream.ReadByte();
|
|
if (format == 0)
|
|
{
|
|
// No Data
|
|
}
|
|
else if (format == 1)
|
|
{
|
|
// Json
|
|
var json = stream.ReadStrAnsi(-71);
|
|
if (json.Length != 0)
|
|
return FlaxEngine.Json.JsonSerializer.Deserialize(json, type);
|
|
return Activator.CreateInstance(type);
|
|
}
|
|
return null;
|
|
}
|
|
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType}." + (type != null ? $" Type: {type.GetTypeDisplayName()}" : string.Empty));
|
|
}
|
|
}
|
|
|
|
internal static void WriteVariant(this BinaryWriter stream, object value)
|
|
{
|
|
if (value == null)
|
|
{
|
|
stream.Write((byte)0);
|
|
stream.Write(0);
|
|
return;
|
|
}
|
|
var type = value.GetType();
|
|
var variantType = ToVariantType(type);
|
|
stream.Write((byte)variantType);
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Object:
|
|
if (type != typeof(FlaxEngine.Object))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
case VariantType.Asset:
|
|
if (type != typeof(Asset))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
case VariantType.Enum:
|
|
case VariantType.Structure:
|
|
case VariantType.ManagedObject:
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
break;
|
|
case VariantType.Array:
|
|
if (type != typeof(object[]))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.FullName, 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
case VariantType.Dictionary:
|
|
if (type != typeof(Dictionary<object, object>))
|
|
{
|
|
stream.Write(int.MaxValue);
|
|
stream.WriteStrAnsi(type.GetTypeName(), 77);
|
|
}
|
|
else
|
|
stream.Write(0);
|
|
break;
|
|
default:
|
|
stream.Write(0);
|
|
break;
|
|
}
|
|
Guid id;
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Bool:
|
|
stream.Write((byte)((bool)value ? 1 : 0));
|
|
break;
|
|
case VariantType.Int16:
|
|
stream.Write((short)value);
|
|
break;
|
|
case VariantType.Uint16:
|
|
stream.Write((ushort)value);
|
|
break;
|
|
case VariantType.Int:
|
|
stream.Write((int)value);
|
|
break;
|
|
case VariantType.Uint:
|
|
stream.Write((uint)value);
|
|
break;
|
|
case VariantType.Int64:
|
|
stream.Write((long)value);
|
|
break;
|
|
case VariantType.Uint64:
|
|
stream.Write((ulong)value);
|
|
break;
|
|
case VariantType.Float:
|
|
stream.Write((float)value);
|
|
break;
|
|
case VariantType.Double:
|
|
stream.Write((double)value);
|
|
break;
|
|
case VariantType.Pointer:
|
|
stream.Write((ulong)(IntPtr)value);
|
|
break;
|
|
case VariantType.String:
|
|
stream.WriteStr((string)value, -14);
|
|
break;
|
|
case VariantType.Object:
|
|
id = ((FlaxEngine.Object)value).ID;
|
|
stream.WriteGuid(ref id);
|
|
break;
|
|
case VariantType.Asset:
|
|
id = ((Asset)value).ID;
|
|
stream.WriteGuid(ref id);
|
|
break;
|
|
case VariantType.Blob:
|
|
stream.Write(((byte[])value).Length);
|
|
stream.Write((byte[])value);
|
|
break;
|
|
case VariantType.Enum:
|
|
stream.Write(Convert.ToUInt64(value));
|
|
break;
|
|
case VariantType.Float2:
|
|
{
|
|
var asVector2 = value is Float2 v ? v : (Float2)(Vector2)value;
|
|
stream.Write(asVector2);
|
|
break;
|
|
}
|
|
case VariantType.Float3:
|
|
{
|
|
var asVector3 = value is Float3 v ? v : (Float3)(Vector3)value;
|
|
stream.Write(asVector3);
|
|
break;
|
|
}
|
|
case VariantType.Float4:
|
|
{
|
|
var asVector4 = value is Float4 v ? v : (Float4)(Vector4)value;
|
|
stream.Write(asVector4);
|
|
break;
|
|
}
|
|
case VariantType.Double2:
|
|
{
|
|
var asVector2 = value is Double2 v ? v : (Double2)(Vector2)value;
|
|
stream.Write(asVector2);
|
|
break;
|
|
}
|
|
case VariantType.Double3:
|
|
{
|
|
var asVector3 = value is Double3 v ? v : (Double3)(Vector3)value;
|
|
stream.Write(asVector3);
|
|
break;
|
|
}
|
|
case VariantType.Double4:
|
|
{
|
|
var asVector4 = value is Double4 v ? v : (Double4)(Vector4)value;
|
|
stream.Write(asVector4);
|
|
break;
|
|
}
|
|
case VariantType.Int2:
|
|
stream.Write((Int2)value);
|
|
break;
|
|
case VariantType.Int3:
|
|
stream.Write((Int3)value);
|
|
break;
|
|
case VariantType.Int4:
|
|
stream.Write((Int4)value);
|
|
break;
|
|
case VariantType.Color:
|
|
stream.Write((Color)value);
|
|
break;
|
|
case VariantType.Guid:
|
|
id = (Guid)value;
|
|
stream.WriteGuid(ref id);
|
|
break;
|
|
case VariantType.BoundingBox:
|
|
stream.Write((BoundingBox)value);
|
|
break;
|
|
case VariantType.BoundingSphere:
|
|
stream.Write((BoundingSphere)value);
|
|
break;
|
|
case VariantType.Quaternion:
|
|
stream.Write((Quaternion)value);
|
|
break;
|
|
case VariantType.Transform:
|
|
stream.Write((Transform)value);
|
|
break;
|
|
case VariantType.Rectangle:
|
|
stream.Write((Rectangle)value);
|
|
break;
|
|
case VariantType.Ray:
|
|
stream.Write((Ray)value);
|
|
break;
|
|
case VariantType.Matrix:
|
|
stream.Write((Matrix)value);
|
|
break;
|
|
case VariantType.Array:
|
|
{
|
|
var array = (Array)value;
|
|
stream.Write(array.Length);
|
|
foreach (var e in array)
|
|
stream.WriteVariant(e);
|
|
break;
|
|
}
|
|
case VariantType.Dictionary:
|
|
{
|
|
var dictionary = (IDictionary)value;
|
|
stream.Write(dictionary.Count);
|
|
foreach (var key in dictionary.Keys)
|
|
{
|
|
stream.WriteVariant(key);
|
|
stream.WriteVariant(dictionary[key]);
|
|
}
|
|
break;
|
|
}
|
|
case VariantType.Typename:
|
|
if (value is Type)
|
|
stream.WriteStrAnsi(((Type)value).GetTypeName(), -14);
|
|
else if (value is ScriptType)
|
|
stream.WriteStrAnsi(((ScriptType)value).TypeName, -14);
|
|
break;
|
|
case VariantType.ManagedObject:
|
|
case VariantType.Structure:
|
|
{
|
|
stream.Write((byte)1);
|
|
var json = FlaxEngine.Json.JsonSerializer.Serialize(value, type);
|
|
stream.WriteStrAnsi(json, -71);
|
|
break;
|
|
}
|
|
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType} for type {type.FullName}.");
|
|
}
|
|
}
|
|
|
|
internal static void WriteVariantType(this JsonWriter stream, Type value)
|
|
{
|
|
var variantType = ToVariantType(value);
|
|
var withoutTypeName = true;
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Object:
|
|
if (value != typeof(FlaxEngine.Object))
|
|
withoutTypeName = false;
|
|
break;
|
|
case VariantType.Asset:
|
|
if (value != typeof(Asset))
|
|
withoutTypeName = false;
|
|
break;
|
|
case VariantType.Enum:
|
|
case VariantType.Structure:
|
|
case VariantType.ManagedObject:
|
|
withoutTypeName = false;
|
|
break;
|
|
case VariantType.Array:
|
|
if (value != typeof(object[]))
|
|
withoutTypeName = false;
|
|
break;
|
|
case VariantType.Dictionary:
|
|
if (value != typeof(Dictionary<object, object>))
|
|
withoutTypeName = false;
|
|
break;
|
|
}
|
|
if (withoutTypeName)
|
|
{
|
|
stream.WriteValue((int)variantType);
|
|
}
|
|
else
|
|
{
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Type");
|
|
stream.WriteValue((int)variantType);
|
|
|
|
stream.WritePropertyName("TypeName");
|
|
stream.WriteValue(value.GetTypeName());
|
|
|
|
stream.WriteEndObject();
|
|
}
|
|
}
|
|
|
|
internal static void WriteVariant(this JsonWriter stream, object value)
|
|
{
|
|
var type = value?.GetType();
|
|
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Type");
|
|
stream.WriteVariantType(type);
|
|
|
|
stream.WritePropertyName("Value");
|
|
var variantType = ToVariantType(type);
|
|
// ReSharper disable PossibleNullReferenceException
|
|
switch (variantType)
|
|
{
|
|
case VariantType.Null:
|
|
case VariantType.Void:
|
|
stream.WriteStartObject();
|
|
stream.WriteEndObject();
|
|
break;
|
|
case VariantType.Bool:
|
|
stream.WriteValue((bool)value);
|
|
break;
|
|
case VariantType.Int16:
|
|
stream.WriteValue((short)value);
|
|
break;
|
|
case VariantType.Uint16:
|
|
stream.WriteValue((ushort)value);
|
|
break;
|
|
case VariantType.Int:
|
|
stream.WriteValue((int)value);
|
|
break;
|
|
case VariantType.Uint:
|
|
stream.WriteValue((uint)value);
|
|
break;
|
|
case VariantType.Int64:
|
|
stream.WriteValue((long)value);
|
|
break;
|
|
case VariantType.Uint64:
|
|
stream.WriteValue((ulong)value);
|
|
break;
|
|
case VariantType.Float:
|
|
stream.WriteValue((float)value);
|
|
break;
|
|
case VariantType.Double:
|
|
stream.WriteValue((double)value);
|
|
break;
|
|
case VariantType.Pointer:
|
|
stream.WriteValue((ulong)(IntPtr)value);
|
|
break;
|
|
case VariantType.String:
|
|
stream.WriteValue((string)value);
|
|
break;
|
|
case VariantType.Object:
|
|
stream.WriteValue(((FlaxEngine.Object)value).ID);
|
|
break;
|
|
case VariantType.Asset:
|
|
stream.WriteValue(((Asset)value).ID);
|
|
break;
|
|
case VariantType.Blob:
|
|
stream.WriteValue(Convert.ToBase64String((byte[])value));
|
|
break;
|
|
case VariantType.Enum:
|
|
stream.WriteValue(Convert.ToUInt64(value));
|
|
break;
|
|
case VariantType.Float2:
|
|
{
|
|
var asVector2 = value is Float2 v ? v : (Float2)(Vector2)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asVector2.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asVector2.Y);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Float3:
|
|
{
|
|
var asVector3 = value is Float3 v ? v : (Float3)(Vector3)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asVector3.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asVector3.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asVector3.Z);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Float4:
|
|
{
|
|
var asVector4 = value is Float4 v ? v : (Float4)(Vector4)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asVector4.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asVector4.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asVector4.Z);
|
|
stream.WritePropertyName("W");
|
|
stream.WriteValue(asVector4.W);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Double2:
|
|
{
|
|
var asVector2 = value is Double2 v ? v : (Double2)(Vector2)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asVector2.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asVector2.Y);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Double3:
|
|
{
|
|
var asVector3 = value is Double3 v ? v : (Double3)(Vector3)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asVector3.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asVector3.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asVector3.Z);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Double4:
|
|
{
|
|
var asVector4 = value is Double4 v ? v : (Double4)(Vector4)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asVector4.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asVector4.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asVector4.Z);
|
|
stream.WritePropertyName("W");
|
|
stream.WriteValue(asVector4.W);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Int2:
|
|
{
|
|
var asInt2 = (Int2)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asInt2.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asInt2.Y);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Int3:
|
|
{
|
|
var asInt3 = (Int3)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asInt3.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asInt3.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asInt3.Z);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Int4:
|
|
{
|
|
var asInt4 = (Int4)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asInt4.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asInt4.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asInt4.Z);
|
|
stream.WritePropertyName("W");
|
|
stream.WriteValue(asInt4.W);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Color:
|
|
{
|
|
var asColor = (Color)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("R");
|
|
stream.WriteValue(asColor.R);
|
|
stream.WritePropertyName("G");
|
|
stream.WriteValue(asColor.G);
|
|
stream.WritePropertyName("B");
|
|
stream.WriteValue(asColor.B);
|
|
stream.WritePropertyName("A");
|
|
stream.WriteValue(asColor.A);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Guid:
|
|
stream.WriteValue((Guid)value);
|
|
break;
|
|
case VariantType.BoundingBox:
|
|
{
|
|
var asBoundingBox = (BoundingBox)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Minimum");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asBoundingBox.Minimum.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asBoundingBox.Minimum.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asBoundingBox.Minimum.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WritePropertyName("Maximum");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asBoundingBox.Maximum.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asBoundingBox.Maximum.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asBoundingBox.Maximum.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.BoundingSphere:
|
|
{
|
|
var asBoundingSphere = (BoundingSphere)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Center");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asBoundingSphere.Center.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asBoundingSphere.Center.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asBoundingSphere.Center.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WritePropertyName("Radius");
|
|
stream.WriteValue(asBoundingSphere.Radius);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Quaternion:
|
|
{
|
|
var asQuaternion = (Quaternion)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asQuaternion.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asQuaternion.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asQuaternion.Z);
|
|
stream.WritePropertyName("W");
|
|
stream.WriteValue(asQuaternion.W);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Transform:
|
|
{
|
|
var asTransform = (Transform)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Translation");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asTransform.Translation.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asTransform.Translation.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asTransform.Translation.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WritePropertyName("Orientation");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asTransform.Orientation.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asTransform.Orientation.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asTransform.Orientation.Z);
|
|
stream.WritePropertyName("W");
|
|
stream.WriteValue(asTransform.Orientation.W);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WritePropertyName("Scale");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asTransform.Scale.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asTransform.Scale.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asTransform.Scale.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Rectangle:
|
|
{
|
|
var asRectangle = (Rectangle)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Location");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asRectangle.Location.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asRectangle.Location.Y);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WritePropertyName("Size");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asRectangle.Size.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asRectangle.Size.Y);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Ray:
|
|
{
|
|
var asRay = (Ray)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("Position");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asRay.Position.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asRay.Position.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asRay.Position.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WritePropertyName("Direction");
|
|
stream.WriteStartObject();
|
|
stream.WritePropertyName("X");
|
|
stream.WriteValue(asRay.Direction.X);
|
|
stream.WritePropertyName("Y");
|
|
stream.WriteValue(asRay.Direction.Y);
|
|
stream.WritePropertyName("Z");
|
|
stream.WriteValue(asRay.Direction.Z);
|
|
stream.WriteEndObject();
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Matrix:
|
|
{
|
|
var asMatrix = (Matrix)value;
|
|
stream.WriteStartObject();
|
|
|
|
stream.WritePropertyName("M11");
|
|
stream.WriteValue(asMatrix.M11);
|
|
stream.WritePropertyName("M12");
|
|
stream.WriteValue(asMatrix.M12);
|
|
stream.WritePropertyName("M13");
|
|
stream.WriteValue(asMatrix.M13);
|
|
stream.WritePropertyName("M14");
|
|
stream.WriteValue(asMatrix.M14);
|
|
|
|
stream.WritePropertyName("M21");
|
|
stream.WriteValue(asMatrix.M21);
|
|
stream.WritePropertyName("M22");
|
|
stream.WriteValue(asMatrix.M22);
|
|
stream.WritePropertyName("M23");
|
|
stream.WriteValue(asMatrix.M23);
|
|
stream.WritePropertyName("M24");
|
|
stream.WriteValue(asMatrix.M24);
|
|
|
|
stream.WritePropertyName("M31");
|
|
stream.WriteValue(asMatrix.M31);
|
|
stream.WritePropertyName("M32");
|
|
stream.WriteValue(asMatrix.M32);
|
|
stream.WritePropertyName("M33");
|
|
stream.WriteValue(asMatrix.M33);
|
|
stream.WritePropertyName("M34");
|
|
stream.WriteValue(asMatrix.M34);
|
|
|
|
stream.WritePropertyName("M41");
|
|
stream.WriteValue(asMatrix.M41);
|
|
stream.WritePropertyName("M42");
|
|
stream.WriteValue(asMatrix.M42);
|
|
stream.WritePropertyName("M43");
|
|
stream.WriteValue(asMatrix.M43);
|
|
stream.WritePropertyName("M44");
|
|
stream.WriteValue(asMatrix.M44);
|
|
|
|
stream.WriteEndObject();
|
|
break;
|
|
}
|
|
case VariantType.Array:
|
|
{
|
|
stream.WriteStartArray();
|
|
foreach (var e in (Array)value)
|
|
stream.WriteVariant(e);
|
|
stream.WriteEndArray();
|
|
break;
|
|
}
|
|
case VariantType.Dictionary:
|
|
{
|
|
stream.WriteStartArray();
|
|
var dictionary = (IDictionary)value;
|
|
foreach (var key in dictionary.Keys)
|
|
{
|
|
stream.WritePropertyName("Key");
|
|
stream.WriteVariant(key);
|
|
stream.WritePropertyName("Value");
|
|
stream.WriteVariant(dictionary[key]);
|
|
}
|
|
stream.WriteEndArray();
|
|
break;
|
|
}
|
|
case VariantType.Typename:
|
|
if (value is Type)
|
|
stream.WriteValue(((Type)value).GetTypeName());
|
|
else if (value is ScriptType)
|
|
stream.WriteValue(((ScriptType)value).TypeName);
|
|
break;
|
|
case VariantType.ManagedObject:
|
|
case VariantType.Structure:
|
|
{
|
|
var json = FlaxEngine.Json.JsonSerializer.Serialize(value, type);
|
|
stream.WriteRaw(json);
|
|
break;
|
|
}
|
|
default: throw new ArgumentOutOfRangeException($"Unknown Variant Type {variantType} for type {type.GetTypeDisplayName()}.");
|
|
}
|
|
// ReSharper restore PossibleNullReferenceException
|
|
|
|
stream.WriteEndObject();
|
|
}
|
|
#endif
|
|
}
|
|
}
|