2025-06-07 17:43:34 +08:00

190 lines
6.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FairyGUI.Utils;
namespace FairyGUI
{
public class AsyncCreationHelper
{
public static void CreateObject(PackageItem item, UIPackage.CreateObjectCallback callback)
{
Timers.inst.StartCoroutine(_CreateObject(item, callback));
}
static IEnumerator _CreateObject(PackageItem item, UIPackage.CreateObjectCallback callback)
{
Stats.LatestObjectCreation = 0;
Stats.LatestGraphicsCreation = 0;
float frameTime = UIConfig.frameTimeForAsyncUIConstruction;
List<DisplayListItem> itemList = new List<DisplayListItem>();
DisplayListItem di = new DisplayListItem(item, ObjectType.Component);
di.childCount = CollectComponentChildren(item, itemList);
itemList.Add(di);
int cnt = itemList.Count;
List<GObject> objectPool = new List<GObject>(cnt);
GObject obj;
float t = Time.realtimeSinceStartup;
bool alreadyNextFrame = false;
for (int i = 0; i < cnt; i++)
{
di = itemList[i];
if (di.packageItem != null)
{
obj = UIObjectFactory.NewObject(di.packageItem);
objectPool.Add(obj);
UIPackage._constructing++;
if (di.packageItem.type == PackageItemType.Component)
{
int poolStart = objectPool.Count - di.childCount - 1;
((GComponent)obj).ConstructFromResource(objectPool, poolStart);
objectPool.RemoveRange(poolStart, di.childCount);
}
else
{
obj.ConstructFromResource();
}
UIPackage._constructing--;
}
else
{
obj = UIObjectFactory.NewObject(di.type);
objectPool.Add(obj);
if (di.type == ObjectType.List && di.listItemCount > 0)
{
int poolStart = objectPool.Count - di.listItemCount - 1;
for (int k = 0; k < di.listItemCount; k++) //把他们都放到pool里这样GList在创建时就不需要创建对象了
((GList)obj).itemPool.ReturnObject(objectPool[k + poolStart]);
objectPool.RemoveRange(poolStart, di.listItemCount);
}
}
if ((i % 5 == 0) && Time.realtimeSinceStartup - t >= frameTime)
{
yield return null;
t = Time.realtimeSinceStartup;
alreadyNextFrame = true;
}
}
if (!alreadyNextFrame) //强制至至少下一帧才调用callback避免调用者逻辑出错
yield return null;
callback(objectPool[0]);
}
/// <summary>
/// 收集创建目标对象所需的所有类型信息
/// </summary>
/// <param name="item"></param>
/// <param name="list"></param>
static int CollectComponentChildren(PackageItem item, List<DisplayListItem> list)
{
ByteBuffer buffer = item.rawData;
buffer.Seek(0, 2);
int dcnt = buffer.ReadShort();
DisplayListItem di;
PackageItem pi;
for (int i = 0; i < dcnt; i++)
{
int dataLen = buffer.ReadShort();
int curPos = buffer.position;
buffer.Seek(curPos, 0);
ObjectType type = (ObjectType)buffer.ReadByte();
string src = buffer.ReadS();
string pkgId = buffer.ReadS();
buffer.position = curPos;
if (src != null)
{
UIPackage pkg;
if (pkgId != null)
pkg = UIPackage.GetById(pkgId);
else
pkg = item.owner;
pi = pkg != null ? pkg.GetItem(src) : null;
di = new DisplayListItem(pi, type);
if (pi != null && pi.type == PackageItemType.Component)
di.childCount = CollectComponentChildren(pi, list);
}
else
{
di = new DisplayListItem(null, type);
if (type == ObjectType.List) //list
di.listItemCount = CollectListChildren(buffer, list);
}
list.Add(di);
buffer.position = curPos + dataLen;
}
return dcnt;
}
static int CollectListChildren(ByteBuffer buffer, List<DisplayListItem> list)
{
buffer.Seek(buffer.position, 8);
string defaultItem = buffer.ReadS();
int listItemCount = 0;
int itemCount = buffer.ReadShort();
for (int i = 0; i < itemCount; i++)
{
int nextPos = buffer.ReadShort();
nextPos += buffer.position;
string url = buffer.ReadS();
if (url == null)
url = defaultItem;
if (!string.IsNullOrEmpty(url))
{
PackageItem pi = UIPackage.GetItemByURL(url);
if (pi != null)
{
DisplayListItem di = new DisplayListItem(pi, pi.objectType);
if (pi.type == PackageItemType.Component)
di.childCount = CollectComponentChildren(pi, list);
list.Add(di);
listItemCount++;
}
}
buffer.position = nextPos;
}
return listItemCount;
}
/// <summary>
///
/// </summary>
class DisplayListItem
{
public PackageItem packageItem;
public ObjectType type;
public int childCount;
public int listItemCount;
public DisplayListItem(PackageItem pi, ObjectType type)
{
this.packageItem = pi;
this.type = type;
}
}
}
}