using System; using System.Collections; using System.Collections.Generic; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Serialization; using UnityEngine.UIElements; // ReSharper disable MemberCanBeProtected.Global // ReSharper disable ClassWithVirtualMembersNeverInherited.Global // ReSharper disable UnusedMember.Global namespace BITKit.UX { public class UIToolKitPanel : MonoBehaviour,IUXPanel { [RuntimeInitializeOnLoadMethod] private static void Reload() { inputActionGroup = new InputActionGroup { allowGlobalActivation = false, Source = nameof(UIToolKitPanel) }; inputActionGroup.allowInput.AddElement(0); } public UIToolKitPanel() { Index = GetType().FullName; } [Header(Constant.Header.Components)] [SerializeField] protected UIDocument document; [Header(Constant.Header.Settings)] [SerializeField, ReadOnly] private bool isActive; [SerializeField,ReadOnly] private float currentOpacity; [Header(Constant.Header.Settings)] [SerializeField] private bool isWindow; [SerializeField] private bool closeWhenClickOutside; [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 static InputActionGroup inputActionGroup = new() { allowGlobalActivation = false, Source = nameof(UIToolKitPanel) }; public bool IsWindow => isWindow; 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); } } protected virtual void Awake() { cancellationToken = gameObject.GetCancellationTokenOnDestroy(); Index= typeof(UIToolKitPanel) == GetType() ? gameObject.name : GetType().Name; document.rootVisualElement.SetActive(false); background?.SetOpacity(0); if (IsWindow) document.sortingOrder++; } protected virtual void Start() { BITKit.UX.UXUtils.Inject(this); UXService.Register(this); destroyCancellationToken.Register(() => { UXService.UnRegister(this); }); if (IsValid && autoEntry) UXService.Entry(this); var returnButton = document.rootVisualElement.Q("return-button"); returnButton?.RegisterCallback(x => { if (x.button is 0) OnReturn(); }); var invisible = document.rootVisualElement.Create(); invisible.name = "invisible_return_generate"; invisible.style.position = Position.Absolute; invisible.pickingMode = PickingMode.Ignore; invisible.style.left = 0; invisible.style.right = 0; invisible.style.top = 0; invisible.style.bottom = 0; invisible.SendToBack(); if (closeWhenClickOutside) { invisible.RegisterCallback(x => { OnReturn(); }); invisible.pickingMode = PickingMode.Position; } if (isWindow) { invisible.style.backgroundColor = new Color(0, 0, 0, 0.9f); } } public bool IsEntered { get; set; } public void Entry() { UXService.Entry(this); } protected virtual void OnReturn() { UXService.Return(); } protected virtual void OnEnable(){} protected virtual void OnDisable(){} protected virtual void OnPanelEntry(){} protected virtual void OnPanelExit(){} void IEntryElement.Entry() { try { CurrentOpacity = 0; TargetOpacity = 1f; document.rootVisualElement.SetActive(true); OnEntry?.Invoke(); } catch (Exception e) { Debug.Log(gameObject.name); throw; } isActive = true; } public virtual async UniTask EntryAsync() { if (entryDuration.Allow is false) return; while (CurrentOpacity < 1 && TargetOpacity is 1) { await UniTask.NextFrame(cancellationToken); if(destroyCancellationToken.IsCancellationRequested)return; } } void IEntryElement.Entered() { //inputActionGroup.allowInput.AddElement(this); OnPanelEntry(); } void IEntryElement.Exit() { if (IsValid is false) return; TargetOpacity = 0; //inputActionGroup.allowInput.RemoveElement(this); OnPanelExit(); } 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); isActive = false; } public event Action OnEntry; public event Action OnExit; public virtual void OnUpdate(float deltaTime) { var duration = 1f; if (TargetOpacity is not 0) { 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); } } }