// Copyright (c) Wojciech Figat. All rights reserved.
#if USE_LARGE_WORLDS
using Real = System.Double;
#else
using Real = System.Single;
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
#if FLAX_EDITOR
using FlaxEditor.Scripting;
using FlaxEditor.Utilities;
#endif
using Newtonsoft.Json;
namespace FlaxEngine.Utilities
{
///
/// Editor utilities and helper functions for Variant type.
///
public static class VariantUtils
{
///
/// Casts the generic value to a given type. Matches native Variant casting logic that favors returning null/zero value rather than error.
///
/// The destination value type.
/// The input value to cast.
/// The result value.
internal static T Cast(object value)
{
if (value == null)
return default;
var type = value.GetType();
if (type != typeof(T) && !typeof(T).IsAssignableFrom(type))
{
if (typeof(T) == typeof(Vector2))
{
if (value is Float2 asFloat2)
return (T)(object)new Vector2((Real)asFloat2.X, (Real)asFloat2.Y);
if (value is Float3 asFloat3)
return (T)(object)new Vector2((Real)asFloat3.X, (Real)asFloat3.Y);
if (value is Float4 asFloat4)
return (T)(object)new Vector2((Real)asFloat4.X, (Real)asFloat4.Y);
}
else if (typeof(T) == typeof(Vector3))
{
if (value is Float2 asFloat2)
return (T)(object)new Vector3((Real)asFloat2.X, (Real)asFloat2.Y, (Real)0);
if (value is Float3 asFloat3)
return (T)(object)new Vector3((Real)asFloat3.X, (Real)asFloat3.Y, (Real)asFloat3.Z);
if (value is Float4 asFloat4)
return (T)(object)new Vector3((Real)asFloat4.X, (Real)asFloat4.Y, (Real)asFloat4.Z);
}
else if (typeof(T) == typeof(Vector4))
{
if (value is Float2 asFloat2)
return (T)(object)new Vector4((Real)asFloat2.X, (Real)asFloat2.Y, (Real)0, (Real)0);
if (value is Float3 asFloat3)
return (T)(object)new Vector4((Real)asFloat3.X, (Real)asFloat3.Y, (Real)asFloat3.Z, (Real)0);
if (value is Vector4 asFloat4)
return (T)(object)new Vector4((Real)asFloat4.X, (Real)asFloat4.Y, (Real)asFloat4.Z, (Real)asFloat4.W);
}
else if (typeof(T) == typeof(Float2))
{
if (value is Vector2 asVector2)
return (T)(object)new Float2((float)asVector2.X, (float)asVector2.Y);
if (value is Vector3 asVector3)
return (T)(object)new Float2((float)asVector3.X, (float)asVector3.Y);
if (value is Vector4 asVector4)
return (T)(object)new Float2((float)asVector4.X, (float)asVector4.Y);
}
else if (typeof(T) == typeof(Float3))
{
if (value is Vector2 asVector2)
return (T)(object)new Float3((float)asVector2.X, (float)asVector2.Y, (float)0);
if (value is Vector3 asVector3)
return (T)(object)new Float3((float)asVector3.X, (float)asVector3.Y, (float)asVector3.Z);
if (value is Vector4 asFloat4)
return (T)(object)new Float3((float)asFloat4.X, (float)asFloat4.Y, (float)asFloat4.Z);
}
else if (typeof(T) == typeof(Float4))
{
if (value is Vector2 asVector2)
return (T)(object)new Float4((float)asVector2.X, (float)asVector2.Y, (float)0, (float)0);
if (value is Vector3 asVector3)
return (T)(object)new Float4((float)asVector3.X, (float)asVector3.Y, (float)asVector3.Z, (float)0);
if (value is Vector4 asVector4)
return (T)(object)new Float4((float)asVector4.X, (float)asVector4.Y, (float)asVector4.Z, (float)asVector4.W);
}
return (T)Convert.ChangeType(value, typeof(T));
}
return (T)value;
}
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