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 } }