Added alternate toggle control at request of Martin Sharkbomb, adds events to the toggle group for value changed
Plus a property to access the single selected toggle (although I'd recommend using the ActiveToggles IEnumerable --HG-- branch : develop_5.3pull/413/head
parent
f74241cb13
commit
84edb62e91
|
@ -0,0 +1,241 @@
|
|||
using System;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple toggle -- something that has an 'on' and 'off' states: checkbox, toggle button, radio button, etc.
|
||||
/// </summary>
|
||||
[AddComponentMenu("UI/Extensions/Extensions Toggle", 31)]
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
public class ExtensionsToggle : Selectable, IPointerClickHandler, ISubmitHandler, ICanvasElement
|
||||
{
|
||||
public enum ToggleTransition
|
||||
{
|
||||
None,
|
||||
Fade
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ToggleEvent : UnityEvent<bool>
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Transition type.
|
||||
/// </summary>
|
||||
public ToggleTransition toggleTransition = ToggleTransition.Fade;
|
||||
|
||||
/// <summary>
|
||||
/// Graphic the toggle should be working with.
|
||||
/// </summary>
|
||||
public Graphic graphic;
|
||||
|
||||
// group that this toggle can belong to
|
||||
[SerializeField]
|
||||
private ExtensionsToggleGroup m_Group;
|
||||
|
||||
public ExtensionsToggleGroup group
|
||||
{
|
||||
get { return m_Group; }
|
||||
set
|
||||
{
|
||||
m_Group = value;
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
SetToggleGroup(m_Group, true);
|
||||
PlayEffect(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
||||
/// </summary>
|
||||
public ToggleEvent onValueChanged = new ToggleEvent();
|
||||
|
||||
// Whether the toggle is on
|
||||
[FormerlySerializedAs("m_IsActive")]
|
||||
[Tooltip("Is the toggle currently on or off?")]
|
||||
[SerializeField]
|
||||
private bool m_IsOn;
|
||||
|
||||
protected ExtensionsToggle()
|
||||
{ }
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
Set(m_IsOn, false);
|
||||
PlayEffect(toggleTransition == ToggleTransition.None);
|
||||
|
||||
var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
|
||||
if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
|
||||
CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this);
|
||||
}
|
||||
|
||||
#endif // if UNITY_EDITOR
|
||||
|
||||
public virtual void Rebuild(CanvasUpdate executing)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (executing == CanvasUpdate.Prelayout)
|
||||
onValueChanged.Invoke(m_IsOn);
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual void LayoutComplete()
|
||||
{ }
|
||||
|
||||
public virtual void GraphicUpdateComplete()
|
||||
{ }
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
SetToggleGroup(m_Group, false);
|
||||
PlayEffect(true);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
SetToggleGroup(null, false);
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
protected override void OnDidApplyAnimationProperties()
|
||||
{
|
||||
// Check if isOn has been changed by the animation.
|
||||
// Unfortunately there is no way to check if we don�t have a graphic.
|
||||
if (graphic != null)
|
||||
{
|
||||
bool oldValue = !Mathf.Approximately(graphic.canvasRenderer.GetColor().a, 0);
|
||||
if (m_IsOn != oldValue)
|
||||
{
|
||||
m_IsOn = oldValue;
|
||||
Set(!oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnDidApplyAnimationProperties();
|
||||
}
|
||||
|
||||
private void SetToggleGroup(ExtensionsToggleGroup newGroup, bool setMemberValue)
|
||||
{
|
||||
ExtensionsToggleGroup oldGroup = m_Group;
|
||||
|
||||
// Sometimes IsActive returns false in OnDisable so don't check for it.
|
||||
// Rather remove the toggle too often than too little.
|
||||
if (m_Group != null)
|
||||
m_Group.UnregisterToggle(this);
|
||||
|
||||
// At runtime the group variable should be set but not when calling this method from OnEnable or OnDisable.
|
||||
// That's why we use the setMemberValue parameter.
|
||||
if (setMemberValue)
|
||||
m_Group = newGroup;
|
||||
|
||||
// Only register to the new group if this Toggle is active.
|
||||
if (m_Group != null && IsActive())
|
||||
m_Group.RegisterToggle(this);
|
||||
|
||||
// If we are in a new group, and this toggle is on, notify group.
|
||||
// Note: Don't refer to m_Group here as it's not guaranteed to have been set.
|
||||
if (newGroup != null && newGroup != oldGroup && isOn && IsActive())
|
||||
m_Group.NotifyToggleOn(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the toggle is currently active.
|
||||
/// </summary>
|
||||
public bool isOn
|
||||
{
|
||||
get { return m_IsOn; }
|
||||
set
|
||||
{
|
||||
Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Set(bool value)
|
||||
{
|
||||
Set(value, true);
|
||||
}
|
||||
|
||||
void Set(bool value, bool sendCallback)
|
||||
{
|
||||
if (m_IsOn == value)
|
||||
return;
|
||||
|
||||
// if we are in a group and set to true, do group logic
|
||||
m_IsOn = value;
|
||||
if (m_Group != null && IsActive())
|
||||
{
|
||||
if (m_IsOn || (!m_Group.AnyTogglesOn() && !m_Group.allowSwitchOff))
|
||||
{
|
||||
m_IsOn = true;
|
||||
m_Group.NotifyToggleOn(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Always send event when toggle is clicked, even if value didn't change
|
||||
// due to already active toggle in a toggle group being clicked.
|
||||
// Controls like Dropdown rely on this.
|
||||
// It's up to the user to ignore a selection being set to the same value it already was, if desired.
|
||||
PlayEffect(toggleTransition == ToggleTransition.None);
|
||||
if (sendCallback)
|
||||
onValueChanged.Invoke(m_IsOn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play the appropriate effect.
|
||||
/// </summary>
|
||||
private void PlayEffect(bool instant)
|
||||
{
|
||||
if (graphic == null)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
graphic.canvasRenderer.SetAlpha(m_IsOn ? 1f : 0f);
|
||||
else
|
||||
#endif
|
||||
graphic.CrossFadeAlpha(m_IsOn ? 1f : 0f, instant ? 0f : 0.1f, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assume the correct visual state.
|
||||
/// </summary>
|
||||
protected override void Start()
|
||||
{
|
||||
PlayEffect(true);
|
||||
}
|
||||
|
||||
private void InternalToggle()
|
||||
{
|
||||
if (!IsActive() || !IsInteractable())
|
||||
return;
|
||||
|
||||
isOn = !isOn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// React to clicks.
|
||||
/// </summary>
|
||||
public virtual void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
return;
|
||||
|
||||
InternalToggle();
|
||||
}
|
||||
|
||||
public virtual void OnSubmit(BaseEventData eventData)
|
||||
{
|
||||
InternalToggle();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc733ccacdce62148ac1f46d1dd84ff6
|
||||
timeCreated: 1450456340
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
[AddComponentMenu("UI/Extensions/Extensions Toggle Group")]
|
||||
[DisallowMultipleComponent]
|
||||
public class ExtensionsToggleGroup : UIBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private bool m_AllowSwitchOff = false;
|
||||
public bool allowSwitchOff { get { return m_AllowSwitchOff; } set { m_AllowSwitchOff = value; } }
|
||||
|
||||
private List<ExtensionsToggle> m_Toggles = new List<ExtensionsToggle>();
|
||||
|
||||
[Serializable]
|
||||
public class ToggleGroupEvent : UnityEvent<bool>
|
||||
{ }
|
||||
|
||||
public ToggleGroupEvent onToggleGroupChanged = new ToggleGroupEvent();
|
||||
public ToggleGroupEvent onToggleGroupToggleChanged = new ToggleGroupEvent();
|
||||
|
||||
public ExtensionsToggle SelectedToggle { get; private set; }
|
||||
|
||||
|
||||
protected ExtensionsToggleGroup()
|
||||
{ }
|
||||
|
||||
private void ValidateToggleIsInGroup(ExtensionsToggle toggle)
|
||||
{
|
||||
if (toggle == null || !m_Toggles.Contains(toggle))
|
||||
throw new ArgumentException(string.Format("Toggle {0} is not part of ToggleGroup {1}", new object[] { toggle, this }));
|
||||
}
|
||||
|
||||
public void NotifyToggleOn(ExtensionsToggle toggle)
|
||||
{
|
||||
ValidateToggleIsInGroup(toggle);
|
||||
|
||||
// disable all toggles in the group
|
||||
for (var i = 0; i < m_Toggles.Count; i++)
|
||||
{
|
||||
if (m_Toggles[i] == toggle)
|
||||
{
|
||||
SelectedToggle = toggle;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_Toggles[i].isOn = false;
|
||||
}
|
||||
onToggleGroupChanged.Invoke(AnyTogglesOn());
|
||||
}
|
||||
|
||||
public void UnregisterToggle(ExtensionsToggle toggle)
|
||||
{
|
||||
if (m_Toggles.Contains(toggle))
|
||||
{
|
||||
m_Toggles.Remove(toggle);
|
||||
toggle.onValueChanged.RemoveListener(NotifyToggleChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyToggleChanged(bool isOn)
|
||||
{
|
||||
onToggleGroupToggleChanged.Invoke(isOn);
|
||||
}
|
||||
|
||||
public void RegisterToggle(ExtensionsToggle toggle)
|
||||
{
|
||||
if (!m_Toggles.Contains(toggle))
|
||||
{
|
||||
m_Toggles.Add(toggle);
|
||||
toggle.onValueChanged.AddListener(NotifyToggleChanged);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AnyTogglesOn()
|
||||
{
|
||||
return m_Toggles.Find(x => x.isOn) != null;
|
||||
}
|
||||
|
||||
public IEnumerable<ExtensionsToggle> ActiveToggles()
|
||||
{
|
||||
return m_Toggles.Where(x => x.isOn);
|
||||
}
|
||||
|
||||
public void SetAllTogglesOff()
|
||||
{
|
||||
bool oldAllowSwitchOff = m_AllowSwitchOff;
|
||||
m_AllowSwitchOff = true;
|
||||
|
||||
for (var i = 0; i < m_Toggles.Count; i++)
|
||||
m_Toggles[i].isOn = false;
|
||||
|
||||
m_AllowSwitchOff = oldAllowSwitchOff;
|
||||
}
|
||||
|
||||
public void HasTheGroupToggle(bool value)
|
||||
{
|
||||
Debug.Log("Testing, the group has toggled [" + value + "]");
|
||||
}
|
||||
|
||||
public void HasAToggleFlipped(bool value)
|
||||
{
|
||||
Debug.Log("Testing, a toggle has toggled [" + value + "]");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf31acdd4bba9fc45b8a5cc6de985aee
|
||||
timeCreated: 1450454546
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue