/// <summary> /// 分配的UI深度 /// </summary> private int AssignDepths(IStackableWrapper wrapper) { int stackDepth = _nextStackDepth; int originStartSortingOrder = wrapper.lastSortingOrder = wrapper.firstSortingOrder = GetHighestSortingOrder(); if (wrapper.stackable is Component) { List <UIPanel> panels = new List <UIPanel>(); List <Renderer> renderers = new List <Renderer>(); panels.AddRange(((Component)wrapper.stackable).GetComponentsInChildren <UIPanel>(true)); renderers.AddRange(((Component)wrapper.stackable).GetComponentsInChildren <Renderer>(true)); panels.Sort((UIPanel panel1, UIPanel panel2) => panel1.sortingOrder != panel2.sortingOrder ? panel1.sortingOrder - panel2.sortingOrder : panel1.depth - panel2.depth); renderers.Sort((Renderer r1, Renderer r2) => r1.sortingOrder - r2.sortingOrder); if (wrapper.inputBlockerInstance != null) { if (panels.Count == 0) { EB.Debug.LogWarning("AssignDepths: need panel above blocker on {0}", wrapper.stackable); UIPanel uiPanel = ((Component)wrapper.stackable).gameObject.AddComponent <UIPanel>(); panels.Add(uiPanel); } UIPanel blockerPanel = wrapper.inputBlockerInstance.GetComponent <UIPanel>(); blockerPanel.depth = panels[0].depth - 1; blockerPanel.sortingOrder = panels[0].sortingOrder; panels.Insert(0, blockerPanel); } if (panels.Count > 0) { int currentOffset = 0; int previousDepth = panels[0].depth; panels[0].renderQueue = UIPanel.RenderQueue.StartAt; panels[0].depth = stackDepth; wrapper.firstStackDepth = panels[0].depth; int previousSortingOrder = originStartSortingOrder = panels[0].sortingOrder; panels[0].sortingOrder = wrapper.firstSortingOrder; int sortingOrder = panels[0].sortingOrder; for (int i = 1; i < panels.Count; i++) { int currentSortingOrderOffset = panels[i].sortingOrder - previousSortingOrder; previousSortingOrder = panels[i].sortingOrder; panels[i].sortingOrder = sortingOrder + currentSortingOrderOffset; sortingOrder = panels[i].sortingOrder; wrapper.lastSortingOrder = Mathf.Max(sortingOrder, wrapper.lastSortingOrder); if (currentSortingOrderOffset > 0) { previousDepth = panels[i].depth; panels[i].depth = stackDepth + currentSortingOrderOffset + 100; stackDepth = panels[i].depth; } else { currentOffset = panels[i].depth - previousDepth; previousDepth = panels[i].depth; panels[i].depth = stackDepth + currentOffset; stackDepth = panels[i].depth; } } panels[0].SetDirty(); } else { wrapper.firstStackDepth = stackDepth; } if (renderers.Count > 0) { int previousSortingOrder = originStartSortingOrder; int sortingOrder = wrapper.firstSortingOrder; List <Material> materials = new List <Material>(); for (int i = 0; i < renderers.Count; i++) { if (renderers[i].materials != null) { materials.AddRange(renderers[i].materials); } SetSortingOrder sso = renderers[i].GetComponent <SetSortingOrder>(); int currentSortingOrder = sso != null ? sso.SortingOrder : 0; int currentSortingOrderOffset = currentSortingOrder - previousSortingOrder; previousSortingOrder = currentSortingOrder; sortingOrder = sortingOrder + currentSortingOrderOffset; if (sso != null) { sso.SortingOrder = sortingOrder; } wrapper.lastSortingOrder = Mathf.Max(sortingOrder, wrapper.lastSortingOrder); } if (materials.Count > 0) { materials.Sort((Material m1, Material m2) => m1.renderQueue - m2.renderQueue); } } } else { wrapper.firstStackDepth = stackDepth; } stackDepth += 10; return(stackDepth); }
/// <summary> /// 入栈的协程 /// </summary> /// <param name="stackable"></param> /// <param name="manualDepth"></param> /// <returns></returns> private IEnumerator EnStackCoroutine(IStackableUI stackable) { if (stackable != null && !stackable.Equals(null)) { // disable Main Camera if (stackable.IsFullscreen()) { _isFullScreenOpened = true; GameUtils.SetMainCameraActive(stackable.IsRenderingWorldWhileFullscreen()); } // OnBlur Event on top ui if (_backStack.Count > 0) { if (_enstackFlag == 0 && _backstackFlag == 0) { _backStack.Peek().stackable.OnBlur(); } } _enstackFlag = 0; _backstackFlag = 0; // Create wrapper IStackableWrapper wrapper = new IStackableWrapper(); wrapper.stackable = stackable; // Insert an input blocker if needed if (stackable.ShowUIBlocker) { _isInputBlockerVisible = true; wrapper.inputBlockerInstance = GameObject.Instantiate(inputBlockerPrefab); wrapper.inputBlockerInstance.name = string.Format("InputBlockerFor{0}", stackable.ToString()); wrapper.inputBlockerInstance.transform.SetParent(gameObject.transform); wrapper.inputBlockerInstance.transform.localPosition = Vector3.zero; wrapper.inputBlockerInstance.transform.localScale = Vector3.one; wrapper.inputBlockerInstance.GetComponentInChildren <UISprite>().alpha = 0.05f; TweenAlpha ta = wrapper.inputBlockerInstance.GetComponentInChildren <TweenAlpha>(); ta.tweenFactor = 1.0f; //0.0f ta.PlayForward(); } // Warn other screens that we're about to stack someone if (onEnstack != null) { onEnstack(stackable); } _nextStackDepth = AssignDepths(wrapper); // Hide below, set visible variables EB.Collections.Stack <IStackableWrapper> tempStack = new EB.Collections.Stack <IStackableWrapper>(); while (_backStack.Count > 0) { tempStack.Push(_backStack.Pop()); if (stackable.IsFullscreen()) { tempStack.Peek().stackable.Show(false); } if (tempStack.Peek().inputBlockerInstance != null && (stackable.ShowUIBlocker || stackable.IsFullscreen())) { if (stackable.IsFullscreen() && wrapper.inputBlockerInstance == null) { _isInputBlockerVisible = false; } // hide blocker for next frame var tempPanel = tempStack.Peek().inputBlockerInstance.GetComponent <UIPanel>(); if (wrapper.inputBlockerInstance && wrapper.inputBlockerInstance.name.Contains("DataPanelNew")) { tempPanel.alpha = 0.0f; } else { EB.Coroutines.EndOfFrame(delegate() { tempPanel.alpha = 0.0f; }); } } } while (tempStack.Count > 0) { _backStack.Push(tempStack.Pop()); } // Fix again if (_isInputBlockerVisible && stackable.IsFullscreen() && wrapper.inputBlockerInstance == null) { _isInputBlockerVisible = false; } // Place stackable _backStack.Push(wrapper); _fullStack.Push(wrapper); // OnFocus Event _enstackFlag = ++s_seed; int currentFlag = _enstackFlag; yield return(StartCoroutine(stackable.OnAddToStack())); if (_enstackFlag == currentFlag && !IsLoadingScreenUp) { _enstackFlag = 0; stackable.OnFocus(); } } }
/// <summary> /// 执行ui出栈操作,移除栈顶ui /// </summary> /// <param name="isPartOfExitStack">是否是退出状态的一部分,从而决定是否做些uicontroller中的一些逻辑或回调</param> /// <returns></returns> private IEnumerator BackstackCoroutine(bool isPartOfExitStack) { if (_backStack.Count == 0) { EB.Debug.LogWarning("BackstackCoroutine: backStack is empty"); yield break; } IStackableWrapper wrapper = _backStack.Pop(); EB.Debug.LogUI("界面UIStack:【<color=#00ff00>{0}</color>】在<color=#fff348>UIStack</color>中<color=#ff0000>从栈顶出栈</color>", wrapper.stackable); // Clear eventual stacked renderers from the full stack while (_fullStack.Pop() != wrapper) { ; } if (onBackstack != null) { onBackstack(wrapper.stackable); } if (wrapper.inputBlockerInstance != null) { // Value might be changed later depending on whether we find another input blocker before the next panel _isInputBlockerVisible = false; TweenAlpha ta = wrapper.inputBlockerInstance.GetComponentInChildren <TweenAlpha>(); ta.tweenFactor = 1.0f; EventDelegate.Add(ta.onFinished, () => Destroy(wrapper.inputBlockerInstance)); ta.PlayReverse(); } if (wrapper.firstStackDepth >= 0 && wrapper.firstStackDepth < _nextStackDepth) { _nextStackDepth = wrapper.firstStackDepth; } // Let the other windows know what happened, show what needs to be shown, etc. if (_backStack.Count > 0) { EB.Collections.Stack <IStackableWrapper> tempStack = new EB.Collections.Stack <IStackableWrapper>(); while (_backStack.Count > 0 && !_backStack.Peek().stackable.IsFullscreen()) { tempStack.Push(_backStack.Pop()); if (wrapper.stackable.IsFullscreen()) { tempStack.Peek().stackable.Show(true); } if (tempStack.Peek().inputBlockerInstance != null && !_isInputBlockerVisible) { // show top blocker //TweenAlpha tempTa = tempStack.Peek().inputBlockerInstance.GetComponentInChildren<TweenAlpha>(); _isInputBlockerVisible = true; tempStack.Peek().inputBlockerInstance.GetComponent <UIPanel>().alpha = 1f; // tempTa.to; // update tween parameters if (wrapper.inputBlockerInstance != null) { TweenAlpha ta = wrapper.inputBlockerInstance.GetComponentInChildren <TweenAlpha>(); ta.tweenFactor = 0.0f; wrapper.inputBlockerInstance.GetComponentInChildren <UISprite>().alpha = 0.05f; } } } if (wrapper.stackable.IsFullscreen()) { // If the count is positive, it means that we've hit a full screen if (_backStack.Count > 0) { // show top full screen _backStack.Peek().stackable.Show(true); if (_backStack.Peek().inputBlockerInstance != null && !_isInputBlockerVisible) { // show top blocker TweenAlpha tempTa = tempStack.Peek().inputBlockerInstance.GetComponentInChildren <TweenAlpha>(); _isInputBlockerVisible = true; _backStack.Peek().inputBlockerInstance.GetComponent <UIPanel>().alpha = tempTa.to; // update tween parameters if (wrapper.inputBlockerInstance != null) { TweenAlpha ta = wrapper.inputBlockerInstance.GetComponentInChildren <TweenAlpha>(); ta.tweenFactor = 0.0f; wrapper.inputBlockerInstance.GetComponentInChildren <UISprite>().alpha = 0.05f; } } GameUtils.SetMainCameraActive(_backStack.Peek().stackable.IsRenderingWorldWhileFullscreen()); } else { // No full screen, show the HUD _isFullScreenOpened = false; } } while (tempStack.Count > 0) { _backStack.Push(tempStack.Pop()); } } else { // There's nothing in the stack, so no full screen, no blocker _isFullScreenOpened = false; _isInputBlockerVisible = false; } if (!_isFullScreenOpened && !IsLoadingScreenUp) { GameUtils.SetMainCameraActive(true); } if (wrapper.stackable == _currentQueuedStackableDisplayed) { _currentQueuedStackableDisplayed = null; } if (_enstackFlag == 0 && _backstackFlag == 0 && !isPartOfExitStack) { wrapper.stackable.OnBlur(); } _enstackFlag = 0; _backstackFlag = 0; _backstackFlag = ++s_seed; var currentFlag = _backstackFlag; wrapper.stackable.ClearData(); yield return(StartCoroutine(wrapper.stackable.OnRemoveFromStack())); if (currentFlag == _backstackFlag) { _backstackFlag = 0; if (_backStack.Count > 0 && !isPartOfExitStack) { //EB.Debug.LogWarning("Backstack: finish {0} onfocus", backStack.Peek().stackable); _backStack.Peek().stackable.OnFocus(); } else { //EB.Debug.LogWarning("Backstack: finish"); } if (!isPartOfExitStack) { OnFinishedBackstacking(); } } }
/// <summary> /// 把ui从堆栈中移除(可以不是栈顶的ui) /// </summary> /// <param name="ui"></param> /// <returns></returns> private IEnumerator Remove(IStackableUI ui) { EB.Debug.LogUI("界面UIStack:【<color=#00ff00>{0}</color>】在<color=#fff348>UIStack</color>中<color=#ff0000>从非栈顶出栈</color>,调用Remove方法", ui); // assume invisible first, update later _isInputBlockerVisible = false; _isFullScreenOpened = false; // remove from backStack IStackableWrapper wrapper = null; EB.Collections.Stack <IStackableWrapper> tmp = new EB.Collections.Stack <IStackableWrapper>(); while (_backStack.Count > 0) { var top = _backStack.Pop(); if (top.stackable != ui) { if (top.stackable.IsFullscreen()) { _isFullScreenOpened = true; } if (top.inputBlockerInstance != null && !_isInputBlockerVisible) { _isInputBlockerVisible = true; top.inputBlockerInstance.GetComponent <UIPanel>().alpha = top.inputBlockerInstance.GetComponentInChildren <TweenAlpha>().to; } tmp.Push(top); } else { wrapper = top; break; } } IStackableWrapper[] below = _backStack.ToArray(); while (tmp.Count > 0) { _backStack.Push(tmp.Pop()); } // remove from fullStack EB.Collections.Stack <StackedItem> fullTmp = new EB.Collections.Stack <StackedItem>(); while (_fullStack.Count > 0) { var top = _fullStack.Pop(); if (top != wrapper) { fullTmp.Push(top); } else { break; } } while (fullTmp.Count > 0) { _fullStack.Push(fullTmp.Pop()); } // update visibility for (int i = 0; i < below.Length; ++i) { if (!_isFullScreenOpened) { below[i].stackable.Show(true); if (below[i].inputBlockerInstance != null && !_isInputBlockerVisible) { _isInputBlockerVisible = true; below[i].inputBlockerInstance.GetComponent <UIPanel>().alpha = below[i].inputBlockerInstance.GetComponentInChildren <TweenAlpha>().to; } if (below[i].stackable.IsFullscreen()) { _isFullScreenOpened = true; GameUtils.SetMainCameraActive(below[i].stackable.IsRenderingWorldWhileFullscreen()); } } if (_isFullScreenOpened) { break; } } if (!_isFullScreenOpened && !IsLoadingScreenUp) { GameUtils.SetMainCameraActive(true); } // remove if (wrapper.inputBlockerInstance != null) { TweenAlpha ta = wrapper.inputBlockerInstance.GetComponentInChildren <TweenAlpha>(); ta.tweenFactor = _isInputBlockerVisible ? 0.1f : 1.0f; EventDelegate.Add(ta.onFinished, () => Destroy(wrapper.inputBlockerInstance)); ta.PlayReverse(); } ui.ClearData(); yield return(StartCoroutine(ui.OnRemoveFromStack())); }