Testing for Unity3D new uGUI system these day,
discover that the toggle button feature not good enough, so I design to write my own.
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Toggle))]
public class ToggleEvent : MonoBehaviour
{
/// <summary>Delegate OnValueChanged event</summary>
/// <param name="value">true/false</param>
/// <example>this.OnValueChanged += YouMethod(bool value)</example>
public delegate void ValueChanged(bool value);
public ValueChanged OnValueChanged;
protected Toggle toggle;
protected virtual void OnEnable()
{
toggle = GetComponent<Toggle>();
toggle.onValueChanged.AddListener(WhenValueChanged);
}
protected virtual void OnDisable()
{
toggle.onValueChanged.RemoveListener(WhenValueChanged);
}
protected virtual void WhenValueChanged(bool value)
{
// Debug.Log(string.Format("{0} Toggle :{1}",GetType().Name.ToString(),value.ToString()));
if (OnValueChanged != null)
OnValueChanged(value);
}
}
the concept are simple using reflection to sync the target script component’s boolean value.
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Reflection;
[RequireComponent(typeof(Toggle))]
public class ToggleSync : ToggleEvent
{
/// <summary>
/// For those too lazy to coding
/// </summary>
/// <remarks>Make sure all GameObject is allocated, component & property name are correct</remarks>
[Tooltip("Target GameObject wanted to call")]
public GameObject target;
[Tooltip("Target Component Name on GameObject, throw error when null")]
public string componentName;
// public Component targetComponent; // hard to drag component
[Tooltip("Target Property Name(Boolean) in Component, throw error when null")]
public string propertyName;
[Tooltip("Use ToggleEvent.OnValueChanged method")]
public bool UseEventDelegate = false;
protected override void OnEnable()
{
base.OnEnable();
toggle.isOn = GetValue();
}
protected override void WhenValueChanged(bool value)
{
if (UseEventDelegate)
base.WhenValueChanged(value);
SetValue(value);
}
private bool GetValue()
{
if (target == null)
return false;
Component component = target.GetComponent(componentName);
Type targetType = (component == null) ? null : component.GetType();
PropertyInfo propertyInfo = (targetType == null) ? null : targetType.GetProperty(propertyName);
return (propertyInfo==null)?false:(bool)propertyInfo.GetValue(component, null);
}
private bool SetValue(bool value)
{
if (target == null)
return false;
string msg = string.Empty;
Component component = target.GetComponent(componentName);
Type targetType = (component == null) ? null : component.GetType();
PropertyInfo propertyInfo = (targetType == null) ? null : targetType.GetProperty(propertyName);
if (ReferenceEquals(component, null))
{
msg = string.Format("{0} cannot find component {1} on {2}",
GetType().Name.ToString(),
componentName,
target.ToString());
}
else if (ReferenceEquals(targetType, null))
{
msg = string.Format("{0} component<{1}> is invaild {2}",
GetType().Name.ToString(),
componentName,
target.ToString());
}
else if (ReferenceEquals(null, propertyInfo))
{
msg = string.Format("{0} cannot find property \"{1}\" on {2}",
GetType().Name.ToString(),
propertyName,
target.ToString());
}
else if (!propertyInfo.CanWrite)
{
msg = string.Format("{0} cannot assign property value \"{1}\" on {2}",
GetType().Name.ToString(),
propertyName,
target.ToString());
}
if (msg.Equals(String.Empty))
{
propertyInfo.SetValue(component, value, null);
return true;
}
else
{
Debug.LogError(msg);
return false;
}
}
}