//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using System.Runtime.CompilerServices;
namespace BansheeEngine
{
/** @addtogroup Serialization
* @{
*/
///
/// Flags that are used to define properties of a single field in a managed object.
///
public enum SerializableFieldAttributes // Note: Must match C++ enum ScriptFieldFlags
{
///
/// Field will be automatically serialized.
///
Serializable = 1 << 0,
///
/// Field will be visible in the default inspector.
///
Inspectable = 1 << 1,
///
/// Integer or floating point field with min/max range.
///
Ranged = 1 << 2,
///
/// Integer or floating point field with a minimum increment/decrement step.
///
Stepped = 1 << 3,
///
/// Field can be animated through the animation window.
///
Animable = 1 << 4,
///
/// Integer field rendered as a layer selection dropdown.
///
LayerMask = 1 << 5,
///
/// Field containing a reference type being passed by copy instead of by reference.
///
PassByCopy = 1 << 6,
///
/// Field containing a reference type that should never be null.
///
NotNull = 1 << 7,
///
/// Field represents a property that wraps a native object. Getters and setters of such a property issue calls into
/// native code to update the native object.
///
NativeWrapper = 1 << 8,
///
/// When a field changes those changes need to be applied to the parent object by calling the field setter. Only
/// applicable to properties containing reference types.
///
ApplyOnDirty = 1 << 9,
///
/// When a quaternion is displayed in the inspector, by default it will be displayed as converted into euler angles.
/// Use this flag to force it to be displayed as a quaternion (4D value) with no conversion instead.
///
DisplayAsQuaternion = 1 << 10
}
///
/// Allows you to access meta-data about field in an object. Similar to Reflection but simpler and faster.
///
public class SerializableField : ScriptObject
{
private SerializableObject parent;
private SerializableProperty.FieldType type;
private int flags;
private Type internalType;
private string name;
///
/// Constructor for internal use by the runtime.
///
/// Object that conains the field.
/// Name of the field.
/// Flags that control whether the field is inspectable or serializable.
/// Internal C# type of the field.
private SerializableField(SerializableObject parent, string name, int flags, Type internalType)
{
this.parent = parent;
this.name = name;
this.flags = flags;
this.type = SerializableProperty.DetermineFieldType(internalType);
this.internalType = internalType;
}
public SerializableFieldAttributes Flags
{
get { return (SerializableFieldAttributes) flags; }
}
///
/// Returns the type of data contained in the field.
///
public SerializableProperty.FieldType Type
{
get { return type; }
}
///
/// Returns the actual type of the object contained in the field.
///
public Type InternalType
{
get { return internalType; }
}
///
/// Returns the name of the field.
///
public string Name
{
get { return name; }
}
///
/// Returns the requested style of the field, that may be used for controlling how the field is displayed and how
/// is its input filtered.
///
public SerializableFieldStyle Style
{
get
{
SerializableFieldStyle style;
Internal_GetStyle(mCachedPtr, out style);
return style;
}
}
///
/// Returns a serializable property for the field.
///
/// Serializable property that allows you to manipulate contents of the field.
public SerializableProperty GetProperty()
{
SerializableProperty.Getter getter = () =>
{
object parentObject = parent.GetReferencedObject();
if (parentObject != null)
return Internal_GetValue(mCachedPtr, parentObject);
else
return null;
};
bool applyOnChange = Flags.HasFlag(SerializableFieldAttributes.ApplyOnDirty) ||
Flags.HasFlag(SerializableFieldAttributes.PassByCopy);
SerializableProperty.Setter setter = (object value) =>
{
object parentObject = parent.GetReferencedObject();
if (parentObject != null)
{
Internal_SetValue(mCachedPtr, parentObject, value);
// If value type we cannot just modify the parent object because it's just a copy
if ((applyOnChange || parentObject.GetType().IsValueType) && parent.parentProperty != null)
parent.parentProperty.SetValue(parentObject);
}
};
SerializableProperty newProperty = Internal_CreateProperty(mCachedPtr);
newProperty.Construct(type, internalType, getter, setter);
return newProperty;
}
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern SerializableProperty Internal_CreateProperty(IntPtr nativeInstance);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern object Internal_GetValue(IntPtr nativeInstance, object instance);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_SetValue(IntPtr nativeInstance, object instance, object value);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void Internal_GetStyle(IntPtr nativeInstance, out SerializableFieldStyle style);
}
///
/// Contains information about a style of a serializable field.
///
public struct SerializableFieldStyle // Note: Must match C++ struct SerializableMemberStyle
{
///
/// True if the range of the field is limited, false if unlimited.
///
public bool HasRange;
///
/// Returns the lower bound of the range. Only relevant if is true.
///
public float RangeMin;
///
/// Returns the upper bound of the range. Only relevant if is true.
///
public float RangeMax;
///
/// True if the field value can only be incremented in specific increments.
///
public bool HasStep;
///
/// Minimum increment the field value can be increment/decremented by. Only relevant if is true.
///
public float StepIncrement;
///
/// If true, number fields will be displayed as sliders instead of regular input boxes.
///
public bool DisplayAsSlider;
///
/// If true, 64-bit fields will be displayed as a layer mask drop down menu.
///
public bool DisplayAsLayerMask;
}
/** @} */
}