427 lines
8.1 KiB
C#
427 lines
8.1 KiB
C#
//----------------------------------------------
|
|
// NGUI: Next-Gen UI kit
|
|
// Copyright © 2011-2015 Tasharen Entertainment
|
|
//----------------------------------------------
|
|
|
|
#if UNITY_EDITOR || !UNITY_FLASH
|
|
#define REFLECTION_SUPPORT
|
|
#endif
|
|
|
|
#if REFLECTION_SUPPORT
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
#endif
|
|
|
|
using UnityEngine;
|
|
using System;
|
|
|
|
/// <summary>
|
|
/// Reference to a specific field or property that can be set via inspector.
|
|
/// </summary>
|
|
|
|
[System.Serializable]
|
|
public class PropertyReference
|
|
{
|
|
[SerializeField] Component mTarget;
|
|
[SerializeField] string mName;
|
|
|
|
#if REFLECTION_SUPPORT
|
|
FieldInfo mField = null;
|
|
PropertyInfo mProperty = null;
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Event delegate's target object.
|
|
/// </summary>
|
|
|
|
public Component target
|
|
{
|
|
get
|
|
{
|
|
return mTarget;
|
|
}
|
|
set
|
|
{
|
|
mTarget = value;
|
|
#if REFLECTION_SUPPORT
|
|
mProperty = null;
|
|
mField = null;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event delegate's method name.
|
|
/// </summary>
|
|
|
|
public string name
|
|
{
|
|
get
|
|
{
|
|
return mName;
|
|
}
|
|
set
|
|
{
|
|
mName = value;
|
|
#if REFLECTION_SUPPORT
|
|
mProperty = null;
|
|
mField = null;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether this delegate's values have been set.
|
|
/// </summary>
|
|
|
|
public bool isValid { get { return (mTarget != null && !string.IsNullOrEmpty(mName)); } }
|
|
|
|
/// <summary>
|
|
/// Whether the target script is actually enabled.
|
|
/// </summary>
|
|
|
|
public bool isEnabled
|
|
{
|
|
get
|
|
{
|
|
if (mTarget == null) return false;
|
|
MonoBehaviour mb = (mTarget as MonoBehaviour);
|
|
return (mb == null || mb.enabled);
|
|
}
|
|
}
|
|
|
|
public PropertyReference () { }
|
|
public PropertyReference (Component target, string fieldName)
|
|
{
|
|
mTarget = target;
|
|
mName = fieldName;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper function that returns the property type.
|
|
/// </summary>
|
|
|
|
public Type GetPropertyType ()
|
|
{
|
|
#if REFLECTION_SUPPORT
|
|
if (mProperty == null && mField == null && isValid) Cache();
|
|
if (mProperty != null) return mProperty.PropertyType;
|
|
if (mField != null) return mField.FieldType;
|
|
#endif
|
|
#if UNITY_EDITOR || !UNITY_FLASH
|
|
return typeof(void);
|
|
#else
|
|
return null;
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Equality operator.
|
|
/// </summary>
|
|
|
|
public override bool Equals (object obj)
|
|
{
|
|
if (obj == null)
|
|
{
|
|
return !isValid;
|
|
}
|
|
|
|
if (obj is PropertyReference)
|
|
{
|
|
PropertyReference pb = obj as PropertyReference;
|
|
return (mTarget == pb.mTarget && string.Equals(mName, pb.mName));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static int s_Hash = "PropertyBinding".GetHashCode();
|
|
|
|
/// <summary>
|
|
/// Used in equality operators.
|
|
/// </summary>
|
|
|
|
public override int GetHashCode () { return s_Hash; }
|
|
|
|
/// <summary>
|
|
/// Set the delegate callback using the target and method names.
|
|
/// </summary>
|
|
|
|
public void Set (Component target, string methodName)
|
|
{
|
|
mTarget = target;
|
|
mName = methodName;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear the event delegate.
|
|
/// </summary>
|
|
|
|
public void Clear ()
|
|
{
|
|
mTarget = null;
|
|
mName = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset the cached references.
|
|
/// </summary>
|
|
|
|
public void Reset ()
|
|
{
|
|
#if REFLECTION_SUPPORT
|
|
mField = null;
|
|
mProperty = null;
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert the delegate to its string representation.
|
|
/// </summary>
|
|
|
|
public override string ToString () { return ToString(mTarget, name); }
|
|
|
|
/// <summary>
|
|
/// Convenience function that converts the specified component + property pair into its string representation.
|
|
/// </summary>
|
|
|
|
static public string ToString (Component comp, string property)
|
|
{
|
|
if (comp != null)
|
|
{
|
|
string typeName = comp.GetType().ToString();
|
|
int period = typeName.LastIndexOf('.');
|
|
if (period > 0) typeName = typeName.Substring(period + 1);
|
|
|
|
if (!string.IsNullOrEmpty(property)) return typeName + "." + property;
|
|
else return typeName + ".[property]";
|
|
}
|
|
return null;
|
|
}
|
|
|
|
#if REFLECTION_SUPPORT
|
|
/// <summary>
|
|
/// Retrieve the property's value.
|
|
/// </summary>
|
|
|
|
[DebuggerHidden]
|
|
[DebuggerStepThrough]
|
|
public object Get ()
|
|
{
|
|
if (mProperty == null && mField == null && isValid) Cache();
|
|
|
|
if (mProperty != null)
|
|
{
|
|
if (mProperty.CanRead)
|
|
return mProperty.GetValue(mTarget, null);
|
|
}
|
|
else if (mField != null)
|
|
{
|
|
return mField.GetValue(mTarget);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assign the bound property's value.
|
|
/// </summary>
|
|
|
|
[DebuggerHidden]
|
|
[DebuggerStepThrough]
|
|
public bool Set (object value)
|
|
{
|
|
if (mProperty == null && mField == null && isValid) Cache();
|
|
if (mProperty == null && mField == null) return false;
|
|
|
|
if (value == null)
|
|
{
|
|
try
|
|
{
|
|
if (mProperty != null)
|
|
{
|
|
if (mProperty.CanWrite)
|
|
{
|
|
mProperty.SetValue(mTarget, null, null);
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mField.SetValue(mTarget, null);
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception) { return false; }
|
|
}
|
|
|
|
// Can we set the value?
|
|
if (!Convert(ref value))
|
|
{
|
|
if (Application.isPlaying)
|
|
UnityEngine.Debug.LogError("Unable to convert " + value.GetType() + " to " + GetPropertyType());
|
|
}
|
|
else if (mField != null)
|
|
{
|
|
mField.SetValue(mTarget, value);
|
|
return true;
|
|
}
|
|
else if (mProperty.CanWrite)
|
|
{
|
|
mProperty.SetValue(mTarget, value, null);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cache the field or property.
|
|
/// </summary>
|
|
|
|
[DebuggerHidden]
|
|
[DebuggerStepThrough]
|
|
bool Cache ()
|
|
{
|
|
if (mTarget != null && !string.IsNullOrEmpty(mName))
|
|
{
|
|
Type type = mTarget.GetType();
|
|
#if NETFX_CORE
|
|
mField = type.GetRuntimeField(mName);
|
|
mProperty = type.GetRuntimeProperty(mName);
|
|
#else
|
|
mField = type.GetField(mName);
|
|
mProperty = type.GetProperty(mName);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
mField = null;
|
|
mProperty = null;
|
|
}
|
|
return (mField != null || mProperty != null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether we can assign the property using the specified value.
|
|
/// </summary>
|
|
|
|
bool Convert (ref object value)
|
|
{
|
|
if (mTarget == null) return false;
|
|
|
|
Type to = GetPropertyType();
|
|
Type from;
|
|
|
|
if (value == null)
|
|
{
|
|
#if NETFX_CORE
|
|
if (!to.GetTypeInfo().IsClass) return false;
|
|
#else
|
|
if (!to.IsClass) return false;
|
|
#endif
|
|
from = to;
|
|
}
|
|
else from = value.GetType();
|
|
return Convert(ref value, from, to);
|
|
}
|
|
#else // Everything below = no reflection support
|
|
public object Get ()
|
|
{
|
|
Debug.LogError("Reflection is not supported on this platform");
|
|
return null;
|
|
}
|
|
|
|
public bool Set (object value)
|
|
{
|
|
Debug.LogError("Reflection is not supported on this platform");
|
|
return false;
|
|
}
|
|
|
|
bool Cache () { return false; }
|
|
bool Convert (ref object value) { return false; }
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Whether we can convert one type to another for assignment purposes.
|
|
/// </summary>
|
|
|
|
static public bool Convert (Type from, Type to)
|
|
{
|
|
object temp = null;
|
|
return Convert(ref temp, from, to);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether we can convert one type to another for assignment purposes.
|
|
/// </summary>
|
|
|
|
static public bool Convert (object value, Type to)
|
|
{
|
|
if (value == null)
|
|
{
|
|
value = null;
|
|
return Convert(ref value, to, to);
|
|
}
|
|
return Convert(ref value, value.GetType(), to);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether we can convert one type to another for assignment purposes.
|
|
/// </summary>
|
|
|
|
static public bool Convert (ref object value, Type from, Type to)
|
|
{
|
|
#if REFLECTION_SUPPORT
|
|
// If the value can be assigned as-is, we're done
|
|
#if NETFX_CORE
|
|
if (to.GetTypeInfo().IsAssignableFrom(from.GetTypeInfo())) return true;
|
|
#else
|
|
if (to.IsAssignableFrom(from)) return true;
|
|
#endif
|
|
|
|
#else
|
|
if (from == to) return true;
|
|
#endif
|
|
// If the target type is a string, just convert the value
|
|
if (to == typeof(string))
|
|
{
|
|
value = (value != null) ? value.ToString() : "null";
|
|
return true;
|
|
}
|
|
|
|
// If the value is null we should not proceed further
|
|
if (value == null) return false;
|
|
|
|
if (to == typeof(int))
|
|
{
|
|
if (from == typeof(string))
|
|
{
|
|
int val;
|
|
|
|
if (int.TryParse((string)value, out val))
|
|
{
|
|
value = val;
|
|
return true;
|
|
}
|
|
}
|
|
else if (from == typeof(float))
|
|
{
|
|
value = Mathf.RoundToInt((float)value);
|
|
return true;
|
|
}
|
|
}
|
|
else if (to == typeof(float))
|
|
{
|
|
if (from == typeof(string))
|
|
{
|
|
float val;
|
|
|
|
if (float.TryParse((string)value, out val))
|
|
{
|
|
value = val;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|