AsyncCreationHelper.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using FairyGUI.Utils;
  5. namespace FairyGUI
  6. {
  7. public class AsyncCreationHelper
  8. {
  9. public static void CreateObject(PackageItem item, UIPackage.CreateObjectCallback callback)
  10. {
  11. Timers.inst.StartCoroutine(_CreateObject(item, callback));
  12. }
  13. static IEnumerator _CreateObject(PackageItem item, UIPackage.CreateObjectCallback callback)
  14. {
  15. Stats.LatestObjectCreation = 0;
  16. Stats.LatestGraphicsCreation = 0;
  17. float frameTime = UIConfig.frameTimeForAsyncUIConstruction;
  18. List<DisplayListItem> itemList = new List<DisplayListItem>();
  19. DisplayListItem di = new DisplayListItem(item, ObjectType.Component);
  20. di.childCount = CollectComponentChildren(item, itemList);
  21. itemList.Add(di);
  22. int cnt = itemList.Count;
  23. List<GObject> objectPool = new List<GObject>(cnt);
  24. GObject obj;
  25. float t = Time.realtimeSinceStartup;
  26. bool alreadyNextFrame = false;
  27. for (int i = 0; i < cnt; i++)
  28. {
  29. di = itemList[i];
  30. if (di.packageItem != null)
  31. {
  32. obj = UIObjectFactory.NewObject(di.packageItem);
  33. objectPool.Add(obj);
  34. UIPackage._constructing++;
  35. if (di.packageItem.type == PackageItemType.Component)
  36. {
  37. int poolStart = objectPool.Count - di.childCount - 1;
  38. ((GComponent)obj).ConstructFromResource(objectPool, poolStart);
  39. objectPool.RemoveRange(poolStart, di.childCount);
  40. }
  41. else
  42. {
  43. obj.ConstructFromResource();
  44. }
  45. UIPackage._constructing--;
  46. }
  47. else
  48. {
  49. obj = UIObjectFactory.NewObject(di.type);
  50. objectPool.Add(obj);
  51. if (di.type == ObjectType.List && di.listItemCount > 0)
  52. {
  53. int poolStart = objectPool.Count - di.listItemCount - 1;
  54. for (int k = 0; k < di.listItemCount; k++) //把他们都放到pool里,这样GList在创建时就不需要创建对象了
  55. ((GList)obj).itemPool.ReturnObject(objectPool[k + poolStart]);
  56. objectPool.RemoveRange(poolStart, di.listItemCount);
  57. }
  58. }
  59. if ((i % 5 == 0) && Time.realtimeSinceStartup - t >= frameTime)
  60. {
  61. yield return null;
  62. t = Time.realtimeSinceStartup;
  63. alreadyNextFrame = true;
  64. }
  65. }
  66. if (!alreadyNextFrame) //强制至至少下一帧才调用callback,避免调用者逻辑出错
  67. yield return null;
  68. callback(objectPool[0]);
  69. }
  70. /// <summary>
  71. /// 收集创建目标对象所需的所有类型信息
  72. /// </summary>
  73. /// <param name="item"></param>
  74. /// <param name="list"></param>
  75. static int CollectComponentChildren(PackageItem item, List<DisplayListItem> list)
  76. {
  77. ByteBuffer buffer = item.rawData;
  78. buffer.Seek(0, 2);
  79. int dcnt = buffer.ReadShort();
  80. DisplayListItem di;
  81. PackageItem pi;
  82. for (int i = 0; i < dcnt; i++)
  83. {
  84. int dataLen = buffer.ReadShort();
  85. int curPos = buffer.position;
  86. buffer.Seek(curPos, 0);
  87. ObjectType type = (ObjectType)buffer.ReadByte();
  88. string src = buffer.ReadS();
  89. string pkgId = buffer.ReadS();
  90. buffer.position = curPos;
  91. if (src != null)
  92. {
  93. UIPackage pkg;
  94. if (pkgId != null)
  95. pkg = UIPackage.GetById(pkgId);
  96. else
  97. pkg = item.owner;
  98. pi = pkg != null ? pkg.GetItem(src) : null;
  99. di = new DisplayListItem(pi, type);
  100. if (pi != null && pi.type == PackageItemType.Component)
  101. di.childCount = CollectComponentChildren(pi, list);
  102. }
  103. else
  104. {
  105. di = new DisplayListItem(null, type);
  106. if (type == ObjectType.List) //list
  107. di.listItemCount = CollectListChildren(buffer, list);
  108. }
  109. list.Add(di);
  110. buffer.position = curPos + dataLen;
  111. }
  112. return dcnt;
  113. }
  114. static int CollectListChildren(ByteBuffer buffer, List<DisplayListItem> list)
  115. {
  116. buffer.Seek(buffer.position, 8);
  117. string defaultItem = buffer.ReadS();
  118. int listItemCount = 0;
  119. int itemCount = buffer.ReadShort();
  120. for (int i = 0; i < itemCount; i++)
  121. {
  122. int nextPos = buffer.ReadShort();
  123. nextPos += buffer.position;
  124. string url = buffer.ReadS();
  125. if (url == null)
  126. url = defaultItem;
  127. if (!string.IsNullOrEmpty(url))
  128. {
  129. PackageItem pi = UIPackage.GetItemByURL(url);
  130. if (pi != null)
  131. {
  132. DisplayListItem di = new DisplayListItem(pi, pi.objectType);
  133. if (pi.type == PackageItemType.Component)
  134. di.childCount = CollectComponentChildren(pi, list);
  135. list.Add(di);
  136. listItemCount++;
  137. }
  138. }
  139. buffer.position = nextPos;
  140. }
  141. return listItemCount;
  142. }
  143. /// <summary>
  144. ///
  145. /// </summary>
  146. class DisplayListItem
  147. {
  148. public PackageItem packageItem;
  149. public ObjectType type;
  150. public int childCount;
  151. public int listItemCount;
  152. public DisplayListItem(PackageItem pi, ObjectType type)
  153. {
  154. this.packageItem = pi;
  155. this.type = type;
  156. }
  157. }
  158. }
  159. }