using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections;
namespace UIWidgets {
///
/// Switch event.
///
public class SwitchEvent : UnityEvent {
}
///
/// Switch direction.
///
public enum SwitchDirection {
LeftToRight,
RightToLeft,
BottomToTop,
TopToBottom,
}
///
/// Switch.
///
[AddComponentMenu("UI/UIWidgets/Switch")]
public class Switch : Selectable, ISubmitHandler, IPointerClickHandler {
///
/// Is on?
///
[SerializeField]
protected bool isOn;
///
/// Gets or sets a value indicating whether this instance is on.
///
/// true if this instance is on; otherwise, false.
public virtual bool IsOn {
get {
return isOn;
}
set {
if (isOn!=value)
{
isOn = value;
if (Group!=null)
{
if (isOn || (!Group.AnySwitchesOn() && !Group.AllowSwitchOff))
{
isOn = true;
Group.NotifySwitchOn(this);
}
}
Changed();
}
}
}
///
/// Switch group.
///
[SerializeField]
protected SwitchGroup Group;
///
/// Gets or sets the switch group.
///
/// The switch group.
public virtual SwitchGroup SwitchGroup
{
get {
return Group;
}
set {
if (Group != null)
{
Group.UnregisterSwitch(this);
}
Group = value;
if (Group != null)
{
Group.RegisterSwitch(this);
if (IsOn)
{
Group.NotifySwitchOn(this);
}
}
}
}
///
/// The direction.
///
[SerializeField]
protected SwitchDirection direction = SwitchDirection.LeftToRight;
///
/// Gets or sets the direction.
///
/// The direction.
public SwitchDirection Direction {
get {
return direction;
}
set {
direction = value;
SetMarkPosition(false);
}
}
///
/// The mark.
///
[SerializeField]
public RectTransform Mark;
///
/// The mark.
///
[SerializeField]
public Graphic MarkGraphic;
///
/// The background.
///
[SerializeField]
public Graphic Background;
[SerializeField]
Color markOnColor = new Color(1f, 1f, 1f, 1f);
///
/// Gets or sets the color of the mark for On state.
///
/// The color of the mark for On state.
public Color MarkOnColor {
get {
return markOnColor;
}
set {
markOnColor = value;
SetMarkColor();
}
}
[SerializeField]
Color markOffColor = new Color(1f, 215f/255f, 115f/255f, 1f);
///
/// Gets or sets the color of the mark for Off State.
///
/// The color of the mark for Off State.
public Color MarkOffColor {
get {
return markOffColor;
}
set {
markOffColor = value;
SetMarkColor();
}
}
[SerializeField]
Color backgroundOnColor = new Color(1f, 1f, 1f, 1f);
///
/// Gets or sets the color of the background for On state.
///
/// The color of the background on.
public Color BackgroundOnColor {
get {
return backgroundOnColor;
}
set {
backgroundOnColor = value;
SetBackgroundColor();
}
}
[SerializeField]
Color backgroundOffColor = new Color(1f, 215f/255f, 115f/255f, 1f);
///
/// Gets or sets the color of the background for Off State.
///
/// The color of the background off.
public Color BackgroundOffColor {
get {
return backgroundOffColor;
}
set {
backgroundOffColor = value;
SetBackgroundColor();
}
}
///
/// The duration of the animation.
///
[SerializeField]
public float AnimationDuration = 0.3f;
///
/// Use unscaled time.
///
[SerializeField]
public bool UnscaledTime;
///
/// Callback executed when the IsOn of the switch is changed.
///
[SerializeField]
public SwitchEvent OnValueChanged = new SwitchEvent();
protected override void Awake ()
{
base.Awake();
SwitchGroup = Group;
}
///
/// Changed this instance.
///
protected virtual void Changed()
{
SetMarkPosition();
SetBackgroundColor();
SetMarkColor();
OnValueChanged.Invoke(IsOn);
}
///
/// The current corutine.
///
protected Coroutine CurrentCorutine;
///
/// Sets the mark position.
///
/// If set to true animate.
protected virtual void SetMarkPosition(bool animate=true)
{
if (CurrentCorutine!=null)
{
StopCoroutine(CurrentCorutine);
}
if (animate)
{
StartCoroutine(AnimateSwitch(IsOn, AnimationDuration));
}
else
{
SetMarkPosition(GetPosition(IsOn));
}
}
///
/// Animates the switch.
///
/// The switch.
/// IsOn.
/// Time.
protected virtual IEnumerator AnimateSwitch(bool state, float time)
{
SetMarkPosition(GetPosition(!IsOn));
var prev_position = GetPosition(!IsOn);
var next_position = GetPosition(IsOn);
var end_time = GetTime() + time;
while (GetTime() <= end_time)
{
var distance = 1 - ((end_time - GetTime()) / time);
var pos = Mathf.Lerp(prev_position, next_position, distance);
SetMarkPosition(pos);
yield return null;
}
SetMarkPosition(GetPosition(IsOn));
}
protected float GetTime()
{
return UnscaledTime ? Time.unscaledTime : Time.time;
}
///
/// Sets the mark position.
///
/// Position.
protected virtual void SetMarkPosition(float position)
{
if (Mark==null)
{
return ;
}
if (IsHorizontal())
{
Mark.anchorMin = new Vector2(position, Mark.anchorMin.y);
Mark.anchorMax = new Vector2(position, Mark.anchorMax.y);
Mark.pivot = new Vector2(position, Mark.pivot.y);
}
else
{
Mark.anchorMin = new Vector2(Mark.anchorMin.x, position);
Mark.anchorMax = new Vector2(Mark.anchorMax.x, position);
Mark.pivot = new Vector2(Mark.pivot.x, position);
}
}
///
/// Determines whether this instance is horizontal.
///
/// true if this instance is horizontal; otherwise, false.
protected bool IsHorizontal()
{
return Direction==SwitchDirection.LeftToRight || Direction==SwitchDirection.RightToLeft;
}
///
/// Gets the position.
///
/// The position.
/// State.
protected float GetPosition(bool state)
{
switch (Direction)
{
case SwitchDirection.LeftToRight:
case SwitchDirection.BottomToTop:
return (state) ? 1f : 0f;
//break;
case SwitchDirection.RightToLeft:
case SwitchDirection.TopToBottom:
return (state) ? 0f : 1f;
//break;
}
return 0f;
}
///
/// Sets the color of the background.
///
protected virtual void SetBackgroundColor()
{
if (Background==null)
{
return ;
}
Background.color = (IsOn) ? BackgroundOnColor : BackgroundOffColor;
}
///
/// Sets the color of the mark.
///
protected virtual void SetMarkColor()
{
if (MarkGraphic==null)
{
return ;
}
MarkGraphic.color = (IsOn) ? MarkOnColor : MarkOffColor;
}
///
/// Calls the changed.
///
protected virtual void CallChanged()
{
if (!IsActive() || !IsInteractable())
{
return ;
}
IsOn = !IsOn;
}
#region ISubmitHandler implementation
///
/// Called by a BaseInputModule when an OnSubmit event occurs.
///
/// Event data.
public virtual void OnSubmit(BaseEventData eventData)
{
CallChanged();
}
#endregion
#region IPointerClickHandler implementation
///
/// Called by a BaseInputModule when an OnPointerClick event occurs.
///
/// Event data.
public virtual void OnPointerClick(PointerEventData eventData)
{
if (eventData.button != PointerEventData.InputButton.Left)
{
return ;
}
CallChanged();
}
#endregion
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
SetMarkPosition(false);
SetBackgroundColor();
SetMarkColor();
}
#endif
}
}