| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 | 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;            }        }    }}
 |