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.

SveltoGUIHelper.cs 7.6KB

Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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