249 lines
8.5 KiB
C#
249 lines
8.5 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using Debug = UnityEngine.Debug;
|
||
|
||
namespace XUI {
|
||
public class UIStack : UIPool {
|
||
[Tooltip("是否为每个组创建一个物体")]
|
||
public bool CreateGroupGameObject = true;
|
||
|
||
public bool CreateCanvasPerObject = true;
|
||
|
||
private int CanvasSortOffset = 20;
|
||
private Canvas ThisCanvas;
|
||
|
||
[System.NonSerialized]
|
||
public Stack<UIPage> Pages = new Stack<UIPage>();
|
||
|
||
protected override void Awake() {
|
||
base.Awake();
|
||
this.ThisCanvas = GetComponent<Canvas>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 叠加一个组
|
||
/// </summary>
|
||
/// <param name="prefabs"></param>
|
||
public UIGroup Overlay(IEnumerable<GameObject> prefabs, params object[] args) {
|
||
if (this.Pages.Count == 0) {
|
||
this.Pages.Push(new UIPage());
|
||
}
|
||
var page = this.Pages.Peek();
|
||
var lastGroup = page.Last;
|
||
if (lastGroup != null) {
|
||
lastGroup.Value.SendBeenOverlay();
|
||
}
|
||
var group = new UIGroup(this, prefabs);
|
||
|
||
page.AddLast(group);
|
||
UpdateCanvasOrder();
|
||
group.SendEnterStack(args);
|
||
return group;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 覆盖一个组
|
||
/// </summary>
|
||
/// <param name="prefabs"></param>
|
||
/// <param name="destroyBefore"></param>
|
||
public UIGroup Cover(IEnumerable<GameObject> prefabs, bool destroyBefore, params object[] args) {
|
||
//关闭底下的界面
|
||
if (this.Pages.Count > 0) {
|
||
var lastPage = this.Pages.Peek();
|
||
lastPage.SendBeenCover();
|
||
foreach (var @group in lastPage) {
|
||
foreach (var uiPageItem in @group) {
|
||
uiPageItem.Instance.SetActive(false);
|
||
// Despawn(uiPageItem.Instance, destroyBefore);//这里不使用回收,为了避免复用之后,退回该界面状态丢失
|
||
}
|
||
}
|
||
}
|
||
//生成新层
|
||
UIPage newPage = new UIPage();
|
||
this.Pages.Push(newPage);
|
||
|
||
var newGroup = new UIGroup(this, prefabs);
|
||
newPage.AddLast(newGroup);
|
||
UpdateCanvasOrder();
|
||
newGroup.SendEnterStack(args);
|
||
return newGroup;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 退回到上一界面
|
||
/// </summary>
|
||
public virtual void Back(bool destroy = true) {
|
||
if (this.Pages.Count == 0) {
|
||
UnityEngine.Debug.LogError("没有任何界面可以回退");
|
||
return;
|
||
}
|
||
//回收最前面的界面
|
||
var lastPage = this.Pages.Peek();
|
||
var lastGroup = lastPage.Last.Value;
|
||
lastPage.RemoveLast();
|
||
lastGroup.SendLeaveStack();
|
||
lastGroup.Despawn(destroy);
|
||
//显示上一个界面,如果当前页面还有组,则只需通知,如果当前页面没有组了,则需要把下一页全部显示出来
|
||
if (lastPage.Count == 0) {
|
||
this.Pages.Pop();
|
||
if (this.Pages.Count == 0) {
|
||
return;
|
||
}
|
||
lastPage = this.Pages.Peek();
|
||
foreach (var g in lastPage) {
|
||
foreach (var i in g) {
|
||
i.Instance.SetActive(true);
|
||
}
|
||
// g.Spawn();
|
||
}
|
||
lastPage.SendDeCover(); //注意:这里要先spawn在发消息
|
||
} else {
|
||
lastPage.Last.Value.SendDeOverlay();
|
||
}
|
||
UpdateCanvasOrder();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除指定的group
|
||
/// </summary>
|
||
/// <param name="group"></param>
|
||
/// <param name="destroy"></param>
|
||
public void BackSpecified(UIGroup @group, bool destroy = true)
|
||
{
|
||
if (this.Pages.Count == 0) {
|
||
UnityEngine.Debug.LogError("fail");
|
||
return;
|
||
}
|
||
|
||
var lastPage = this.Pages.Peek();
|
||
var lastGroup = lastPage.Last.Value;
|
||
|
||
var tmpPage = new Stack<UIPage>();
|
||
var tmpStack = new Stack<UIGroup>();
|
||
|
||
while (lastGroup != group) { //查找,直到指定界面
|
||
tmpStack.Push(lastGroup);
|
||
lastPage.RemoveLast();
|
||
if (lastPage.Count == 0)
|
||
{
|
||
var tmpPopPage = this.Pages.Pop();
|
||
tmpPage.Push(tmpPopPage);
|
||
//将推出的页面重新入栈
|
||
while (tmpStack.Count > 0)
|
||
{
|
||
tmpPopPage.AddLast(tmpStack.Pop());
|
||
}
|
||
if (this.Pages.Count == 0) {
|
||
return;
|
||
}
|
||
lastPage = this.Pages.Peek();
|
||
}
|
||
lastGroup = lastPage.Last.Value;
|
||
}
|
||
|
||
//回收指定的界面
|
||
lastPage = this.Pages.Peek();
|
||
lastGroup = lastPage.Last.Value;
|
||
lastPage.RemoveLast();
|
||
lastGroup.SendLeaveStack();
|
||
lastGroup.Despawn(destroy);
|
||
|
||
//将退出的页面重新入栈
|
||
while (tmpStack.Count > 0)
|
||
{
|
||
lastPage.AddLast(tmpStack.Pop());
|
||
}
|
||
|
||
while (tmpPage.Count > 0)
|
||
{
|
||
this.Pages.Push(tmpPage.Pop());
|
||
}
|
||
|
||
UpdateCanvasOrder();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 退回到指定界面Group
|
||
/// </summary>
|
||
public void BackTo(UIGroup group, bool destroy = true) {
|
||
if (this.Pages.Count == 0) {
|
||
UnityEngine.Debug.LogError("fail");
|
||
return;
|
||
}
|
||
var lastPage = this.Pages.Peek();
|
||
var lastGroup = lastPage.Last.Value;
|
||
bool decover = false;
|
||
bool deoverlay = false;
|
||
while (lastGroup != group) { //一直回收,直到指定界面
|
||
lastPage.RemoveLast();
|
||
lastGroup.SendLeaveStack();
|
||
lastGroup.Despawn(destroy);
|
||
deoverlay = true;
|
||
if (lastPage.Count == 0) {
|
||
this.Pages.Pop();
|
||
if (this.Pages.Count == 0) {
|
||
return;
|
||
}
|
||
lastPage = this.Pages.Peek();
|
||
decover = true;
|
||
deoverlay = false;
|
||
}
|
||
lastGroup = lastPage.Last.Value;
|
||
}
|
||
//达到指定页面
|
||
if (decover) { //如果经历过翻页,需要生成它
|
||
// lastGroup.Spawn();
|
||
foreach (var i in lastGroup) {
|
||
i.Instance.SetActive(true);
|
||
}
|
||
lastPage.SendDeCover(); //注意:这里要先spawn在发消息
|
||
}
|
||
if (deoverlay) { //如果被叠加过,需要发送反叠加消息
|
||
lastGroup.SendDeOverlay();
|
||
}
|
||
UpdateCanvasOrder();
|
||
}
|
||
|
||
public void UpdateCanvasOrder() {
|
||
if (!this.CreateCanvasPerObject) {
|
||
return;
|
||
}
|
||
var page = this.Pages.Peek();
|
||
if (page == null) {
|
||
return;
|
||
}
|
||
int i = 0;
|
||
foreach (var group in page) {
|
||
foreach (var item in @group) {
|
||
if (item.Instance.activeSelf) {
|
||
item.InstanceCanvas.overrideSorting = true;
|
||
item.InstanceCanvas.sortingLayerID = this.ThisCanvas.sortingLayerID;
|
||
item.InstanceCanvas.sortingOrder = i * this.CanvasSortOffset + this.ThisCanvas.sortingOrder;
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
internal UIItem PrefabToUIItem(GameObject prefab, GameObject parent) {
|
||
var ins = Spawn(prefab);
|
||
if (parent != null) {
|
||
ins.transform.SetParent(parent.transform);
|
||
}
|
||
Canvas canvas = null;
|
||
if (this.CreateCanvasPerObject) {
|
||
canvas = ins.GetOrAddComponent<Canvas>();
|
||
ins.GetOrAddComponent<GraphicRaycaster>();
|
||
}
|
||
return new UIItem(prefab, ins, canvas);
|
||
}
|
||
|
||
public virtual void OnUIGroupCreated(UIGroup uiGroup) {
|
||
}
|
||
}
|
||
} |