260 lines
7.6 KiB
C#
260 lines
7.6 KiB
C#
// ***********************************************************************
|
||
// Assembly : Unity
|
||
// Author : Kimch
|
||
// Created :
|
||
//
|
||
// Last Modified By : Kimch
|
||
// Last Modified On :
|
||
// ***********************************************************************
|
||
// <copyright file= "KUISwitch" company=""></copyright>
|
||
// <summary></summary>
|
||
// ***********************************************************************
|
||
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.Events;
|
||
using UnityEngine.EventSystems;
|
||
using UnityEngine.Serialization;
|
||
using UnityEngine.UI;
|
||
|
||
/// <summary>
|
||
/// Simple Switch -- something that has an 'on' and 'off' states: checkbox, Switch button, radio button, etc.
|
||
/// </summary>
|
||
[AddComponentMenu("UI/Custom/Switch", 31)]
|
||
[RequireComponent(typeof(RectTransform))]
|
||
public class KUISwitch : Selectable, IPointerClickHandler, ISubmitHandler, ICanvasElement
|
||
{
|
||
public enum SwitchTransition
|
||
{
|
||
None,
|
||
Fade
|
||
}
|
||
|
||
[Serializable]
|
||
public class SwitchEvent : UnityEvent<bool>
|
||
{ }
|
||
|
||
/// <summary>
|
||
/// Transition type.
|
||
/// </summary>
|
||
public SwitchTransition switchTransition = SwitchTransition.Fade;
|
||
|
||
/// <summary>
|
||
/// Graphic the Switch should be working with.
|
||
/// </summary>
|
||
public Graphic onGraphic;
|
||
public Graphic offGraphic;
|
||
|
||
// group that this Switch can belong to
|
||
[SerializeField]
|
||
private KUISwitchGroup m_Group;
|
||
|
||
public KUISwitchGroup group
|
||
{
|
||
get { return m_Group; }
|
||
set
|
||
{
|
||
m_Group = value;
|
||
#if UNITY_EDITOR
|
||
if (Application.isPlaying)
|
||
#endif
|
||
{
|
||
SetSwitchGroup(m_Group, true);
|
||
PlayEffect(true);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Allow for delegate-based subscriptions for faster events than 'eventReceiver', and allowing for multiple receivers.
|
||
/// </summary>
|
||
public SwitchEvent onValueChanged = new SwitchEvent();
|
||
|
||
// Whether the Switch is on
|
||
[FormerlySerializedAs("m_IsActive")]
|
||
[Tooltip("Is the Switch currently on or off?")]
|
||
[SerializeField]
|
||
private bool m_IsOn;
|
||
|
||
protected KUISwitch()
|
||
{ }
|
||
|
||
#if UNITY_EDITOR
|
||
protected override void OnValidate()
|
||
{
|
||
base.OnValidate();
|
||
|
||
#pragma warning disable CS0618 // “PrefabUtility.GetPrefabType(Object)”已过时:“Use GetPrefabAssetType and GetPrefabInstanceStatus to get the full picture about Prefab types.”
|
||
var prefabType = UnityEditor.PrefabUtility.GetPrefabType(this);
|
||
#pragma warning restore CS0618 // “PrefabUtility.GetPrefabType(Object)”已过时:“Use GetPrefabAssetType and GetPrefabInstanceStatus to get the full picture about Prefab types.”
|
||
#pragma warning disable CS0618 // “PrefabType”已过时:“PrefabType no longer tells everything about Prefab instance.”
|
||
if (prefabType != UnityEditor.PrefabType.Prefab && !Application.isPlaying)
|
||
#pragma warning restore CS0618 // “PrefabType”已过时:“PrefabType no longer tells everything about Prefab instance.”
|
||
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();
|
||
SetSwitchGroup(m_Group, false);
|
||
PlayEffect(true);
|
||
}
|
||
|
||
protected override void OnDisable()
|
||
{
|
||
SetSwitchGroup(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<6F>t have a graphic.
|
||
//if (onGraphic != null)
|
||
//{
|
||
// bool oldValue = !Mathf.Approximately(onGraphic.canvasRenderer.GetColor().a, 0);
|
||
// if (m_IsOn != oldValue)
|
||
// {
|
||
// m_IsOn = oldValue;
|
||
// Set(!oldValue);
|
||
// }
|
||
//}
|
||
|
||
base.OnDidApplyAnimationProperties();
|
||
}
|
||
|
||
private void SetSwitchGroup(KUISwitchGroup newGroup, bool setMemberValue)
|
||
{
|
||
KUISwitchGroup oldGroup = m_Group;
|
||
|
||
// Sometimes IsActive returns false in OnDisable so don't check for it.
|
||
// Rather remove the Switch too often than too little.
|
||
if (m_Group != null)
|
||
m_Group.UnregisterSwitch(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 Switch is active.
|
||
if (newGroup != null && IsActive())
|
||
newGroup.RegisterSwitch(this);
|
||
|
||
// If we are in a new group, and this Switch 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())
|
||
newGroup.NotifySwitchOn(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Whether the Switch 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.AnySwitchsOn() && !m_Group.allowSwitchOff))
|
||
{
|
||
m_IsOn = true;
|
||
m_Group.NotifySwitchOn(this);
|
||
}
|
||
}
|
||
|
||
// Always send event when Switch is clicked, even if value didn't change
|
||
// due to already active Switch in a Switch 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(switchTransition == SwitchTransition.None);
|
||
if (sendCallback)
|
||
{
|
||
UISystemProfilerApi.AddMarker("Switch.value", this);
|
||
onValueChanged.Invoke(m_IsOn);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Play the appropriate effect.
|
||
/// </summary>
|
||
private void PlayEffect(bool instant)
|
||
{
|
||
if (onGraphic == null || offGraphic == null)
|
||
return;
|
||
|
||
onGraphic.gameObject.SetActive(m_IsOn);
|
||
offGraphic.gameObject.SetActive(!m_IsOn);
|
||
|
||
//#if UNITY_EDITOR
|
||
// if (!Application.isPlaying)
|
||
// onGraphic.canvasRenderer.SetAlpha(m_IsOn ? 1f : 0f);
|
||
// else
|
||
//#endif
|
||
// onGraphic.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 InternalSwitch()
|
||
{
|
||
if (!IsActive() || !IsInteractable())
|
||
return;
|
||
|
||
isOn = !isOn;
|
||
}
|
||
|
||
/// <summary>
|
||
/// React to clicks.
|
||
/// </summary>
|
||
public virtual void OnPointerClick(PointerEventData eventData)
|
||
{
|
||
if (eventData.button != PointerEventData.InputButton.Left)
|
||
return;
|
||
|
||
InternalSwitch();
|
||
}
|
||
|
||
public virtual void OnSubmit(BaseEventData eventData)
|
||
{
|
||
InternalSwitch();
|
||
}
|
||
} |