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