SCToggleBase.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Events;
  4. using UnityEngine.EventSystems;
  5. using UnityEngine.Serialization;
  6. namespace SC.XR.Unity
  7. {
  8. public abstract class SCToggleBase : MonoBehaviour, IPointerClickHandler
  9. {
  10. [Serializable]
  11. public class ToggleEvent : UnityEvent<bool>
  12. {
  13. }
  14. [SerializeField]
  15. private SCToggleGroup3D m_Group;
  16. public SCToggleGroup3D group
  17. {
  18. get { return m_Group; }
  19. set
  20. {
  21. m_Group = value;
  22. #if UNITY_EDITOR
  23. if (Application.isPlaying)
  24. #endif
  25. {
  26. SetToggleGroup(m_Group, true);
  27. PlayEffect();
  28. }
  29. }
  30. }
  31. public ToggleEvent onValueChanged = new ToggleEvent();
  32. [FormerlySerializedAs("m_IsActive")]
  33. [Tooltip("Is the toggle currently on or off?")]
  34. [SerializeField]
  35. protected bool m_IsOn;
  36. protected SCToggleBase()
  37. { }
  38. protected virtual void OnEnable()
  39. {
  40. SetToggleGroup(m_Group, false);
  41. PlayEffect();
  42. }
  43. protected void OnDisable()
  44. {
  45. SetToggleGroup(null, false);
  46. }
  47. #if UNITY_EDITOR
  48. protected void OnValidate()
  49. {
  50. PlayEffect();
  51. }
  52. #endif // if UNITY_EDITOR
  53. private void SetToggleGroup(SCToggleGroup3D newGroup, bool setMemberValue)
  54. {
  55. SCToggleGroup3D oldGroup = m_Group;
  56. // Sometimes IsActive returns false in OnDisable so don't check for it.
  57. // Rather remove the toggle too often than too little.
  58. if (m_Group != null)
  59. m_Group.UnregisterToggle(this);
  60. // At runtime the group variable should be set but not when calling this method from OnEnable or OnDisable.
  61. // That's why we use the setMemberValue parameter.
  62. if (setMemberValue)
  63. m_Group = newGroup;
  64. // Only register to the new group if this Toggle is active.
  65. if (newGroup != null)
  66. newGroup.RegisterToggle(this);
  67. // If we are in a new group, and this toggle is on, notify group.
  68. // Note: Don't refer to m_Group here as it's not guaranteed to have been set.
  69. if (newGroup != null && newGroup != oldGroup && isOn)
  70. newGroup.NotifyToggleOn(this);
  71. }
  72. public bool isOn
  73. {
  74. get { return m_IsOn; }
  75. set
  76. {
  77. Set(value);
  78. }
  79. }
  80. void Set(bool value)
  81. {
  82. Set(value, true);
  83. }
  84. void Set(bool value, bool sendCallback)
  85. {
  86. if (m_IsOn == value)
  87. return;
  88. // if we are in a group and set to true, do group logic
  89. m_IsOn = value;
  90. if (m_Group != null)
  91. {
  92. if (m_IsOn || (!m_Group.AnyTogglesOn() && !m_Group.allowSwitchOff))
  93. {
  94. m_IsOn = true;
  95. m_Group.NotifyToggleOn(this);
  96. }
  97. }
  98. // Always send event when toggle is clicked, even if value didn't change
  99. // due to already active toggle in a toggle group being clicked.
  100. // Controls like Dropdown rely on this.
  101. // It's up to the user to ignore a selection being set to the same value it already was, if desired.
  102. PlayEffect();
  103. if (sendCallback)
  104. {
  105. UISystemProfilerApi.AddMarker("Toggle.value", this);
  106. onValueChanged.Invoke(m_IsOn);
  107. }
  108. }
  109. protected abstract void PlayEffect();
  110. protected void Start()
  111. {
  112. PlayEffect();
  113. }
  114. private void InternalToggle()
  115. {
  116. isOn = !isOn;
  117. }
  118. /// <summary>
  119. /// React to clicks.
  120. /// </summary>
  121. public virtual void OnPointerClick(PointerEventData eventData)
  122. {
  123. InternalToggle();
  124. }
  125. }
  126. }