Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
7.6KB

  1. #if UNITY_5 || UNITY_5_3_OR_NEWER
  2. using System;
  3. using Svelto.ECS.Hybrid;
  4. using UnityEngine;
  5. namespace Svelto.ECS.Extensions.Unity
  6. {
  7. public static class SveltoGUIHelper
  8. {
  9. /// <summary>
  10. /// This is the suggested way to create GUIs from prefabs now.
  11. /// </summary>
  12. /// <param name="startIndex"></param>
  13. /// <param name="contextHolder"></param>
  14. /// <param name="factory"></param>
  15. /// <param name="group"></param>
  16. /// <param name="searchImplementorsInChildren"></param>
  17. /// <param name="groupNamePostfix"></param>
  18. /// <typeparam name="T"></typeparam>
  19. /// <returns></returns>
  20. public static T CreateFromPrefab<T>(ref uint startIndex, Transform contextHolder, IEntityFactory factory,
  21. ExclusiveGroup group, bool searchImplementorsInChildren = false, string groupNamePostfix = null) where T : MonoBehaviour, IEntityDescriptorHolder
  22. {
  23. Create<T>(new EGID(startIndex++, group), contextHolder, factory, out var holder);
  24. var children = contextHolder.GetComponentsInChildren<IEntityDescriptorHolder>(true);
  25. foreach (var child in children)
  26. {
  27. if (child.GetType() != typeof(T))
  28. {
  29. var monoBehaviour = child as MonoBehaviour;
  30. IImplementor[] childImplementors;
  31. if (searchImplementorsInChildren == false)
  32. childImplementors = monoBehaviour.GetComponents<IImplementor>();
  33. else
  34. childImplementors = monoBehaviour.GetComponentsInChildren<IImplementor>(true);
  35. startIndex = InternalBuildAll(startIndex, child, factory, group, childImplementors,
  36. groupNamePostfix);
  37. }
  38. }
  39. return holder;
  40. }
  41. /// <summary>
  42. /// Creates all the entities in a hierarchy. This was commonly used to create entities from gameobjects
  43. /// already present in the scene
  44. /// </summary>
  45. /// <param name="startIndex"></param>
  46. /// <param name="group"></param>
  47. /// <param name="contextHolder"></param>
  48. /// <param name="factory"></param>
  49. /// <param name="groupNamePostfix"></param>
  50. /// <typeparam name="T"></typeparam>
  51. /// <returns></returns>
  52. public static uint CreateAll<T>(uint startIndex, ExclusiveGroup group,
  53. Transform contextHolder, IEntityFactory factory, string groupNamePostfix = null) where T : MonoBehaviour, IEntityDescriptorHolder
  54. {
  55. var holders = contextHolder.GetComponentsInChildren<T>(true);
  56. foreach (var holder in holders)
  57. {
  58. var implementors = holder.GetComponents<IImplementor>();
  59. try
  60. {
  61. startIndex = InternalBuildAll(startIndex, holder, factory, group, implementors, groupNamePostfix);
  62. }
  63. catch (Exception ex)
  64. {
  65. throw new Exception($"When building entity from game object {Path(holder.transform)}", ex);
  66. }
  67. }
  68. return startIndex;
  69. }
  70. static string Path(Transform go)
  71. {
  72. string s = go.name;
  73. while (go.parent != null)
  74. {
  75. go = go.parent;
  76. s = go.name + "/" + s;
  77. }
  78. return s;
  79. }
  80. public static EntityInitializer Create<T>(EGID ID, Transform contextHolder, IEntityFactory factory,
  81. out T holder, bool searchImplementorsInChildren = false)
  82. where T : MonoBehaviour, IEntityDescriptorHolder
  83. {
  84. holder = contextHolder.GetComponentInChildren<T>(true);
  85. if (holder == null)
  86. {
  87. throw new Exception($"Could not find holder {typeof(T).Name} in {contextHolder.name}");
  88. }
  89. var implementors = searchImplementorsInChildren == false ? holder.GetComponents<IImplementor>() : holder.GetComponentsInChildren<IImplementor>(true) ;
  90. return factory.BuildEntity(ID, holder.GetDescriptor(), implementors);
  91. }
  92. public static EntityInitializer Create<T>(EGID ID, Transform contextHolder,
  93. IEntityFactory factory, bool searchImplementorsInChildren = false)
  94. where T : MonoBehaviour, IEntityDescriptorHolder
  95. {
  96. var holder = contextHolder.GetComponentInChildren<T>(true);
  97. if (holder == null)
  98. {
  99. throw new Exception($"Could not find holder {typeof(T).Name} in {contextHolder.name}");
  100. }
  101. var implementors = searchImplementorsInChildren == false ? holder.GetComponents<IImplementor>() : holder.GetComponentsInChildren<IImplementor>(true) ;
  102. return factory.BuildEntity(ID, holder.GetDescriptor(), implementors);
  103. }
  104. static uint InternalBuildAll(uint startIndex, IEntityDescriptorHolder descriptorHolder,
  105. IEntityFactory factory, ExclusiveGroup group, IImplementor[] implementors, string groupNamePostfix)
  106. {
  107. ExclusiveGroupStruct realGroup = group;
  108. if (string.IsNullOrEmpty(descriptorHolder.groupName) == false)
  109. {
  110. realGroup = ExclusiveGroup.Search(!string.IsNullOrEmpty(groupNamePostfix)
  111. ? $"{descriptorHolder.groupName}{groupNamePostfix}"
  112. : descriptorHolder.groupName);
  113. }
  114. EGID egid;
  115. var holderId = descriptorHolder.id;
  116. if (holderId == 0)
  117. egid = new EGID(startIndex++, realGroup);
  118. else
  119. egid = new EGID(holderId, realGroup);
  120. var init = factory.BuildEntity(egid, descriptorHolder.GetDescriptor(), implementors);
  121. init.Init(new EntityHierarchyComponent(group));
  122. return startIndex;
  123. }
  124. /// <summary>
  125. /// Works like CreateAll but only builds entities with holders that have the same group specified
  126. /// This is a very specific case, basically used only by ControlsScreenRowFactory. Not sure what the real
  127. /// use case is.
  128. /// </summary>
  129. /// <param name="startId"></param>
  130. /// <param name="group">The group to match</param>
  131. /// <param name="contextHolder"></param>
  132. /// <param name="factory"></param>
  133. /// <typeparam name="T">EntityDescriptorHolder type</typeparam>
  134. /// <returns>Next available ID</returns>
  135. public static uint CreateAllInMatchingGroup<T>(uint startId, ExclusiveGroup exclusiveGroup,
  136. Transform contextHolder, IEntityFactory factory) where T : MonoBehaviour, IEntityDescriptorHolder
  137. {
  138. var holders = contextHolder.GetComponentsInChildren<T>(true);
  139. foreach (var holder in holders)
  140. {
  141. if (string.IsNullOrEmpty(holder.groupName) == false)
  142. {
  143. var realGroup = ExclusiveGroup.Search(holder.groupName);
  144. if (realGroup != exclusiveGroup)
  145. continue;
  146. }
  147. else
  148. {
  149. continue;
  150. }
  151. var implementors = holder.GetComponents<IImplementor>();
  152. startId = InternalBuildAll(startId, holder, factory, exclusiveGroup, implementors, null);
  153. }
  154. return startId;
  155. }
  156. }
  157. }
  158. #endif