// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; using UltimateXR.Avatar; using UltimateXR.Core; using UltimateXR.Core.Settings; using UltimateXR.Extensions.Unity; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Serialization; using UnityEngine.UI; #pragma warning disable 67 // Disable warnings due to unused events namespace UltimateXR.UI.UnityInputModule.Controls { /// /// Type of that implements toggle functionality. /// public partial class UxrToggleControlInput : UxrControlInput { #region Inspector Properties/Serialized Fields [FormerlySerializedAs("_initialStateIsSelected")] [SerializeField] private InitState _initialState = InitState.DontChange; [SerializeField] private bool _canToggleOnlyOnce; [SerializeField] private Text _text; [SerializeField] private List _enableWhenSelected; [SerializeField] private List _enableWhenNotSelected; [SerializeField] private List _textColorChanges; [SerializeField] private AudioClip _audioToggleOn; [SerializeField] private AudioClip _audioToggleOff; [SerializeField] [Range(0, 1)] private float _audioToggleOnVolume = 1.0f; [SerializeField] [Range(0, 1)] private float _audioToggleOffVolume = 1.0f; #endregion #region Public Types & Data /// /// Event called whenever the state is toggled. /// public event Action Toggled; /// /// Gets or sets whether the current toggled state. /// To set the state of the control without triggering any events, use instead. /// public bool IsSelected { get => _isSelected; set => SetIsSelected(value, true); } /// /// Gets or sets whether the control can be toggled or not. /// public bool CanBeToggled { get; set; } = true; /// /// Gets or sets the text value. If no component is configured it will return /// . /// public string Text { get => _text != null ? _text.text : string.Empty; set { if (_text != null) { _text.text = value; } } } #endregion #region Public Methods /// /// Changes the current state of the control like but allowing to control whether /// events are propagated or not. /// /// State (selected/not-selected) /// Whether to propagate events public void SetIsSelected(bool value, bool propagateEvents) { if (_isSelected == value && _isInitialized) { return; } _isSelected = value; foreach (GameObject goToEnable in _enableWhenSelected) { if (goToEnable == null) { if (UxrGlobalSettings.Instance.LogLevelUI >= UxrLogLevel.Warnings) { Debug.LogWarning($"{UxrConstants.UiModule} {transform.GetPathUnderScene()} has null enableWhenSelected entry"); } } else { goToEnable.SetActive(_isSelected); } } foreach (GameObject goToEnable in _enableWhenNotSelected) { if (goToEnable == null) { if (UxrGlobalSettings.Instance.LogLevelUI >= UxrLogLevel.Warnings) { Debug.LogWarning($"{UxrConstants.UiModule} {transform.GetPathUnderScene()} has null enableWhenNotSelected entry"); } } else { goToEnable.SetActive(!_isSelected); } } foreach (TextColorChange textEntry in _textColorChanges) { textEntry.TextComponent.color = _isSelected ? textEntry.ColorSelected : textEntry.ColorNotSelected; } _isInitialized = true; if (propagateEvents) { Toggled?.Invoke(this); } } #endregion #region Unity /// /// Sets up the events and initializes the current state. /// protected override void Awake() { base.Awake(); if (!_isInitialized && _initialState != InitState.DontChange) { SetIsSelected(_initialState == InitState.ToggledOn, true); } _alreadyToggled = false; } /// /// Called when the component is destroyed. /// protected override void OnDestroy() { base.OnDestroy(); _text = null; _enableWhenSelected = null; _enableWhenNotSelected = null; _textColorChanges = null; } /// /// Checks for a in any parent object to refresh the content. /// protected override void OnEnable() { base.OnEnable(); UxrToggleGroup group = GetComponentInParent(); if (group != null) { group.RefreshToggleChildrenList(); } } #endregion #region Event Trigger Methods /// /// Control was clicked. Toggle state. /// /// Event data protected override void OnClicked(PointerEventData eventData) { base.OnClicked(eventData); if (!CanBeToggled || (_alreadyToggled && _canToggleOnlyOnce)) { return; } if (Interactable) { _alreadyToggled = true; if (_canToggleOnlyOnce) { Enabled = false; } Vector3 audioPosition = UxrAvatar.LocalAvatarCamera ? UxrAvatar.LocalAvatar.CameraPosition : transform.position; if (_audioToggleOff && !_isSelected) { AudioSource.PlayClipAtPoint(_audioToggleOff, audioPosition, _audioToggleOffVolume); } else if (_audioToggleOn && _isSelected) { AudioSource.PlayClipAtPoint(_audioToggleOn, audioPosition, _audioToggleOnVolume); } SetIsSelected(!_isSelected, true); } } #endregion #region Private Types & Data private bool _isInitialized; private bool _isSelected; private bool _alreadyToggled; #endregion } } #pragma warning restore 67