using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; namespace vnxbqy.UI { [DisallowMultipleComponent] [RequireComponent(typeof(WindowInfo))] public abstract class Window : WidgetBehavior { WindowInfo m_WindowInfo = null; public WindowInfo windowInfo { get { return m_WindowInfo ?? (m_WindowInfo = this.GetComponent()); } } public WindowState windowState { get; private set; } RectTransform rectTransform { get { return this.transform.AddMissingComponent(); } } RawImage windowMask; ButtonEx emptyCloseButton; bool initialized = false; float windowTimer = 0f; int m_FunctionOrder = 0; public int functionOrder { get { return m_FunctionOrder; } set { m_FunctionOrder = value; } } public bool playAnimation { get; set; } public bool executedActiveWindow { get; set; } public string fixParentName { get; set; } // 当一个界面可以挂在多个 一级界面下的时候 用于指定父级界面 internal Window Open() { if (!initialized) { InitWidgts(); AddWindowPattern(); if (windowInfo.clickEmptyToClose && emptyCloseButton == null) { AddEmptyCloseResponser(); } if (windowInfo.needMask && windowMask == null) { AddSreenMask(); } BindController(); AddListeners(); initialized = true; } executedActiveWindow = false; RectTransform parent = null; windowTimer = 0f; var parentName = string.Empty; if (!string.IsNullOrEmpty(fixParentName)) parentName = fixParentName; else { WindowConfig.FindParentWindow(this.gameObject.name, out parentName); } if (!string.IsNullOrEmpty(parentName)) { var parentWindow = WindowCenter.Instance.Get(parentName); if (parentWindow is OneLevelWin) { parent = (parentWindow as OneLevelWin).subWindowContainer; } else { parent = parentWindow.transform as RectTransform; } if (parent != null) { ResetRect(parent); } } OnPreOpen(); try { WindowCenter.Instance.NotifyBeforeOpen(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } if (parent == null) { parent = FindParent(windowInfo.windowType); if (parent != null) { ResetRect(parent); if (windowInfo.windowType >= WindowType.Normal) { rectTransform.SetAsLastSibling(); } } } windowState = WindowState.Opening; windowInfo.raycastTarget = false; if (windowInfo.needMask) { windowMask.rectTransform.MatchWhith(rectTransform.parent as RectTransform); windowMask.transform.localScale = Vector3.one * 1.01f; windowMask.transform.SetSiblingIndex(rectTransform.GetSiblingIndex()); CameraUtility.ScreenShotCut(windowMask, ActiveWindow); } else { ActiveWindow(); } return this; } internal Window Close() { OnPreClose(); windowTimer = 0f; if (playAnimation && windowInfo.tween != null) { windowInfo.tween.Play(true); } try { WindowCenter.Instance.NotifyBeforeClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } finally { windowInfo.raycastTarget = false; windowState = WindowState.Closing; executedActiveWindow = false; fixParentName = string.Empty; } return this; } internal Window CloseImmediately() { OnPreClose(); windowInfo.raycastTarget = false; try { WindowCenter.Instance.NotifyBeforeClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } if (windowInfo.needMask) { CameraUtility.StopShotCut(windowMask); windowMask.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); } if (windowInfo.windowType == WindowType.Base) { this.enabled = false; this.rectTransform.SetParentEx(WindowCenter.Instance.uiRoot.recycleBin, Vector3.zero, Vector3.zero, Vector3.one); } else { this.SetActive(false); } windowState = WindowState.Closed; try { WindowCenter.Instance.NotifyAfterClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } OnAfterClose(); executedActiveWindow = false; if (ConfigInitiator.done) { if (!WindowJumpMgr.Instance.IsJumpState) { fixParentName = string.Empty; } } else { fixParentName = string.Empty; } try { WindowCenter.Instance.JumpNotifyAfterClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } return this; } //设置大小 private void ResetRect(RectTransform parent) { var safeArea = GetComponent(); rectTransform.MatchWhith(parent); if (safeArea != null) safeArea.ApplySafeArea(); } internal void SetMask(GameObject _mask) { if (_mask != null) { _mask.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); _mask.transform.SetAsFirstSibling(); } } public virtual void CloseClick() { CloseImmediately(); } public void ChildActive() { OnActived(); } protected virtual void LateUpdate() { } protected virtual void OnActived() { } protected abstract void BindController(); protected abstract void AddListeners(); protected abstract void OnPreOpen(); protected abstract void OnAfterOpen(); protected abstract void OnPreClose(); protected abstract void OnAfterClose(); private void Update() { switch (windowState) { case WindowState.Opening: OnOpening(); break; case WindowState.Closing: OnClosing(); break; } } private void OnOpening() { if (playAnimation && windowInfo.tween != null && windowTimer < windowInfo.tween.duration) { windowTimer += Time.deltaTime; if (windowTimer > windowInfo.tween.duration) { OnAfterOpen(); try { WindowCenter.Instance.NotifyAfterOpen(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.Message); } finally { windowInfo.raycastTarget = true; windowState = WindowState.Opened; } } } else { OnAfterOpen(); try { WindowCenter.Instance.NotifyAfterOpen(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } finally { windowInfo.raycastTarget = true; windowState = WindowState.Opened; } } } private void OnClosing() { if (playAnimation && windowInfo.tween && windowTimer < windowInfo.tween.duration) { windowTimer += Time.deltaTime; if (windowTimer > windowInfo.tween.duration) { try { WindowCenter.Instance.NotifyAfterClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } finally { if (windowInfo.needMask) { CameraUtility.StopShotCut(windowMask); windowMask.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); } if (windowInfo.windowType == WindowType.Base) { this.enabled = false; this.rectTransform.SetParentEx(WindowCenter.Instance.uiRoot.recycleBin, Vector3.zero, Vector3.zero, Vector3.one); } else { this.SetActive(false); } windowState = WindowState.Closed; } OnAfterClose(); executedActiveWindow = false; fixParentName = string.Empty; try { WindowCenter.Instance.JumpNotifyAfterClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } } } else { try { WindowCenter.Instance.NotifyAfterClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } finally { if (windowInfo.needMask) { CameraUtility.StopShotCut(windowMask); windowMask.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); } if (windowInfo.windowType == WindowType.Base) { this.enabled = false; this.rectTransform.SetParentEx(WindowCenter.Instance.uiRoot.recycleBin, Vector3.zero, Vector3.zero, Vector3.one); } else { this.SetActive(false); } windowState = WindowState.Closed; } OnAfterClose(); executedActiveWindow = false; fixParentName = string.Empty; try { WindowCenter.Instance.JumpNotifyAfterClose(this); } catch (System.Exception ex) { OperationLogCollect.Instance.BugReportSys(ex.ToString()); Debug.LogError(ex.StackTrace); } } } private void ActiveWindow() { if (windowState == WindowState.Closed || windowState == WindowState.Closing) { return; } this.enabled = true; if (!this.gameObject.activeInHierarchy) { this.SetActive(true); } if (windowMask != null) { windowMask.color.SetA(1f); windowMask.SetActive(true); } var isChildWindow = WindowConfig.IsChildWindow(this.gameObject.name); if (isChildWindow) { var parentName = string.Empty; if (!string.IsNullOrEmpty(fixParentName)) parentName = fixParentName; else { WindowConfig.FindParentWindow(this.gameObject.name, out parentName); } var parentWindow = WindowCenter.Instance.Get(parentName); if (parentWindow != null && parentWindow.executedActiveWindow) { OnActived(); executedActiveWindow = true; } } else { OnActived(); executedActiveWindow = true; var childWindows = WindowConfig.GetChildWindows(this.gameObject.name); var isParentWindow = childWindows != null; if (isParentWindow) { foreach (var child in childWindows) { var window = WindowCenter.Instance.Get(child); if (window != null && (window.windowState == WindowState.Opening || window.windowState == WindowState.Opened) && !window.executedActiveWindow) { window.ChildActive(); } } } } if (playAnimation && windowInfo.tween != null) { windowInfo.tween.reversal = false; windowInfo.tween.Play(); } } private void AddWindowPattern() { var pattern = WindowConfig.GetWindowPattern(this.gameObject.name); if (!string.IsNullOrEmpty(pattern)) { var instance = UIUtility.CreateWidget(pattern, "Pivot"); instance.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); } } private void AddEmptyCloseResponser() { var emptyClose = UIUtility.CreateWidget("InvisibleButton", "EmptyClose"); var rectTransform = emptyClose.transform as RectTransform; rectTransform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); rectTransform.SetAsFirstSibling(); rectTransform.MatchWhith(this.transform as RectTransform); emptyCloseButton = emptyClose.GetComponent(); emptyCloseButton.AddListener(CloseClick); } private void AddSreenMask() { var maskObject = new GameObject("ScreenMask"); var rectTransform = maskObject.AddMissingComponent(); rectTransform.sizeDelta = new Vector2(1336, 752); rectTransform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); rectTransform.SetAsFirstSibling(); windowMask = maskObject.AddMissingComponent(); } private RectTransform FindParent(WindowType _type) { RectTransform parent = null; switch (_type) { case WindowType.Base: parent = WindowCenter.Instance.uiRoot.baseCanvas.transform as RectTransform; break; case WindowType.Normal: parent = WindowCenter.Instance.uiRoot.normalCanvas.transform as RectTransform; break; case WindowType.Modal: parent = WindowCenter.Instance.uiRoot.modalCanvas.transform as RectTransform; break; case WindowType.Tip: parent = WindowCenter.Instance.uiRoot.tipsCanvas.transform as RectTransform; break; case WindowType.System: parent = WindowCenter.Instance.uiRoot.systemCanvas.transform as RectTransform; break; case WindowType.Loading: parent = WindowCenter.Instance.uiRoot.loadingCanvas.transform as RectTransform; break; default: parent = WindowCenter.Instance.uiRoot.normalCanvas.transform as RectTransform; break; } return parent; } public enum WindowState { Closed, Opening, Opened, Closing, } } }