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 { public const string USSEntry = "transition_entry"; public const string USSEntryAsync = "transition_entry_async"; public const string USSEntered = "transition_entried"; public const string USSExit = "transition_exit"; public const string USSExitAsync = "transition_exit_async"; public const string USSExited = "transition_exited"; [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 => destroyCancellationToken.IsCancellationRequested; public string Index { get; private set; } public bool AllowCursor => allowCursor; public bool AllowInput => allowInput; 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() { 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); document.rootVisualElement.AddToClassList(USSEntry); 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; } [BIT] 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; } async UniTask IEntryElement.EntryAsync() { document.rootVisualElement.AddToClassList(USSEntry); // for (var i = 0; i < 32; i++) // { // await UniTask.NextFrame(); // } document.rootVisualElement.AddToClassList(USSEntryAsync); if (entryDuration.Allow) { var task = EntryAsync(); var durationTask = UniTask.Delay(TimeSpan.FromSeconds(entryDuration.Value), cancellationToken: destroyCancellationToken); await durationTask; document.rootVisualElement.RemoveFromClassList(USSEntry); document.rootVisualElement.RemoveFromClassList(USSEntryAsync); document.rootVisualElement.AddToClassList(USSEntered); await task; } else { await EntryAsync(); } } public virtual UniTask EntryAsync() { return UniTask.CompletedTask; } void IEntryElement.Entered() { //inputActionGroup.allowInput.AddElement(this); OnPanelEntry(); } void IEntryElement.Exit() { document.rootVisualElement.AddToClassList(USSExit); if (IsValid is false) return; //TargetOpacity = 0; //inputActionGroup.allowInput.RemoveElement(this); OnPanelExit(); } async UniTask IEntryElement.ExitAsync() { document.rootVisualElement.RemoveFromClassList(USSEntered); document.rootVisualElement.AddToClassList(USSExitAsync); // if (exitDuration.Allow is false) return; // while (CurrentOpacity > 0 && TargetOpacity is 0) // { // await UniTask.NextFrame(cancellationToken); // } if (entryDuration.Allow is false) return; await UniTask.Delay(TimeSpan.FromSeconds(entryDuration.Value), cancellationToken: destroyCancellationToken); //return UniTask.CompletedTask; } void IEntryElement.Exited() { document.rootVisualElement.RemoveFromClassList(USSExit); document.rootVisualElement.RemoveFromClassList(USSExitAsync); document.rootVisualElement.AddToClassList(USSEntry); document.rootVisualElement.SetActive(false); isActive = false; OnExit?.Invoke(); } 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); } } }