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.

161 lines
6.2KB

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