//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace BansheeEngine
{
/** @addtogroup Serialization
* @{
*/
///
/// Allows you to transparently retrieve and set values of an entry, whether that entry is an object field or
/// an array/list/dictionary entry.
///
public sealed class SerializableProperty : ScriptObject
{
///
/// Object field types support by the serializable property.
///
public enum FieldType
{
Int,
Float,
Bool,
String,
Color,
Vector2,
Vector3,
Vector4,
GameObjectRef,
Resource,
Object,
Array,
List,
Dictionary,
RRef,
ColorGradient,
Curve,
FloatDistribution,
ColorDistribution,
Quaternion,
Enum,
Vector2Distribution,
Vector3Distribution
}
public delegate object Getter();
public delegate void Setter(object value);
private FieldType type;
private Type internalType;
private Getter getter;
private Setter setter;
///
/// Constructor for internal use by the native code.
///
private SerializableProperty()
{ }
///
/// Creates a new serializable property.
///
/// Type of data the property contains.
/// Type of data the property contains, as C# type.
/// Method that allows you to retrieve contents of the property.
/// Method that allows you to set contents of the property
public SerializableProperty(FieldType type, Type internalType, Getter getter, Setter setter)
{
this.type = type;
this.internalType = internalType;
this.getter = getter;
this.setter = setter;
Internal_CreateInstance(this, internalType);
}
///
/// Finalizes construction of the serializable property. Must be called after creation.
///
/// Type of data the property contains.
/// Type of data the property contains, as C# type.
/// Method that allows you to retrieve contents of the property.
/// Method that allows you to set contents of the property
internal void Construct(FieldType type, Type internalType, Getter getter, Setter setter)
{
this.type = type;
this.internalType = internalType;
this.getter = getter;
this.setter = setter;
}
///
/// Returns type of data the property contains.
///
public FieldType Type
{
get { return type; }
}
///
/// Returns type of data the property contains, as C# type.
///
public Type InternalType
{
get { return internalType; }
}
///
/// Is the containing type a value type (true), or a reference type (false).
///
public bool IsValueType
{
get { return internalType.IsValueType; }
}
///
/// Retrieves the value contained in the property.
///
/// Type of the value to retrieve. Caller must ensure the type matches the property type.
/// Value of the property.
public T GetValue()
{
// Cast if possible
if (typeof(T) != internalType)
{
// Note: Not checking cast operators
if (internalType.IsPrimitive || internalType.IsEnum)
{
if (internalType == typeof(bool) || typeof(T) == typeof(bool))
throw new Exception("Attempted to retrieve a serializable value using an invalid type. " +
"Provided type: " + typeof(T) + ". Needed type: " + internalType);
return (T) Convert.ChangeType(getter(), typeof(T));
}
if(!typeof(T).IsAssignableFrom(internalType))
throw new Exception("Attempted to retrieve a serializable value using an invalid type. " +
"Provided type: " + typeof(T) + ". Needed type: " + internalType);
}
return (T)getter();
}
///
/// Changes the value of the property.
///
/// Type of the value to set. Caller must ensure the type matches the property type.
/// New value to assign to the property.
public void SetValue(T value)
{
// Cast if possible
if (typeof(T) != internalType)
{
// Note: Not checking cast operators
if (internalType.IsPrimitive || internalType.IsEnum)
{
if (internalType == typeof(bool) || typeof(T) == typeof(bool))
throw new Exception("Attempted to set a serializable value using an invalid type. " +
"Provided type: " + typeof(T) + ". Needed type: " + internalType);
setter((T) Convert.ChangeType(getter(), typeof(T)));
return;
}
if (!typeof(T).IsAssignableFrom(internalType))
throw new Exception("Attempted to set a serializable value using an invalid type. " +
"Provided type: " + typeof(T) + ". Needed type: " + internalType);
}
setter(value);
}
///
/// Returns a serializable object wrapper around the value contained in the property.
///
/// Serializable object wrapper around the value contained in the property.
public SerializableObject GetObject()
{
if (type != FieldType.Object)
throw new Exception("Attempting to retrieve object information from a field that doesn't contain an object.");
// Get the most-derived type so the serializable object lists the exact fields
object obj = GetValue