//********************************** 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; } /** @} */ }