using System; using System.Collections; using System.Collections.Generic; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; // ReSharper disable MemberCanBeProtected.Global // ReSharper disable ClassWithVirtualMembersNeverInherited.Global // ReSharper disable UnusedMember.Global namespace BITKit.UX { public class UIToolKitPanel : MonoBehaviour,IUXPanel { public UIToolKitPanel() { Index = GetType().FullName; } [Header(Constant.Header.Components)] [SerializeField] protected UIDocument document; [Header(Constant.Header.Settings)] [SerializeField] private bool isAnimate; [SerializeField] private bool allowCursor; [SerializeField] private bool allowInput; [SerializeField] private bool autoEntry; [Header(Constant.Header.Settings)] [SerializeField] private Optional entryDuration; [SerializeField] private Optional exitDuration; protected readonly InputActionGroup inputActionGroup = new() { allowGlobalActivation = false }; public bool IsAnimate => isAnimate; public bool IsValid => cancellationToken.IsCancellationRequested is false; public string Index { get; private set; } public bool AllowCursor => allowCursor; public bool AllowInput => allowInput; protected CancellationToken cancellationToken { get; private set; } protected float TargetOpacity { get; private set; } protected virtual VisualElement background => document.rootVisualElement; protected float CurrentOpacity { get => background?.GetOpacity() ?? _currentOpacity; set { _currentOpacity = value; background?.SetOpacity(value); } } private float _currentOpacity; protected virtual void Awake() { cancellationToken = gameObject.GetCancellationTokenOnDestroy(); Index= typeof(UIToolKitPanel) == GetType() ? gameObject.name : GetType().Name; document.rootVisualElement.SetActive(false); background?.SetOpacity(0); } protected virtual void Start() { if(IsValid && autoEntry) UXService.Entry(this); } public bool IsEntered { get; set; } public void Entry() { UXService.Entry(this); } protected virtual void OnEnable()=>UXService.Register(this); protected virtual void OnDisable()=>UXService.UnRegister(this); void IEntryElement.Entry() { CurrentOpacity = 0; TargetOpacity = 1; OnEntryOrExit(true); document.rootVisualElement.SetActive(true); OnEntry?.Invoke(); } async UniTask IEntryElement.EntryAsync() { if (entryDuration.Allow is false) return; while (CurrentOpacity < 1 && TargetOpacity is 1) { await UniTask.NextFrame(cancellationToken); } } void IEntryElement.Entered() { inputActionGroup.allowInput.AddElement(this); } void IEntryElement.Exit() { if (IsValid is false) return; TargetOpacity = 0; OnEntryOrExit(false); inputActionGroup.allowInput.RemoveElement(this); } async UniTask IEntryElement.ExitAsync() { if (exitDuration.Allow is false) return; while (CurrentOpacity > 0 && TargetOpacity is 0) { await UniTask.NextFrame(cancellationToken); } OnExit?.Invoke(); } void IEntryElement.Exited() { document.rootVisualElement.SetActive(false); } public event Action OnEntry; public event Action OnExit; protected virtual void OnEntryOrExit(bool isEntry) { } public virtual void OnUpdate(float deltaTime) { var duration = 1f; if (TargetOpacity is 1) { if (entryDuration.Allow is false) { CurrentOpacity = TargetOpacity; return; } duration = entryDuration.Value; } else { if (exitDuration.Allow is false) { CurrentOpacity = TargetOpacity; return; } duration = exitDuration.Value; } CurrentOpacity = Mathf.MoveTowards(CurrentOpacity,TargetOpacity,1f/duration * Time.deltaTime); } } }