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.

EntityViewUtility.cs 5.0KB

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
4 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
4 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
4 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
4 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
4 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
4 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
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System;
  2. using System.Collections.Generic;
  3. using Svelto.DataStructures;
  4. using Svelto.ECS.Internal;
  5. using Svelto.Utilities;
  6. namespace Svelto.ECS
  7. {
  8. #if DEBUG && !PROFILER
  9. struct ECSTuple<T1, T2>
  10. {
  11. public readonly T1 implementorType;
  12. public T2 numberOfImplementations;
  13. public ECSTuple(T1 implementor, T2 v)
  14. {
  15. implementorType = implementor;
  16. numberOfImplementations = v;
  17. }
  18. }
  19. #endif
  20. static class EntityViewUtility
  21. {
  22. public static void FillEntityView<T>(this IEntityBuilder entityBuilder
  23. , ref T entityView
  24. , FasterList<KeyValuePair<Type, ActionCast<T>>>
  25. entityViewBlazingFastReflection
  26. , IEnumerable<object> implementors,
  27. #if DEBUG && !PROFILER
  28. Dictionary<Type, ECSTuple<object, int>> implementorsByType
  29. #else
  30. Dictionary<Type, object> implementorsByType
  31. #endif
  32. , Dictionary<Type, Type[]> cachedTypes
  33. )
  34. {
  35. //efficient way to collect the fields of every EntityViewType
  36. var setters =
  37. FasterList<KeyValuePair<Type, ActionCast<T>>>.NoVirt.ToArrayFast(entityViewBlazingFastReflection, out var count);
  38. foreach (var implementor in implementors)
  39. {
  40. if (implementor != null)
  41. {
  42. var type = implementor.GetType();
  43. if (cachedTypes.TryGetValue(type, out var interfaces) == false)
  44. interfaces = cachedTypes[type] = type.GetInterfacesEx();
  45. for (var iindex = 0; iindex < interfaces.Length; iindex++)
  46. {
  47. var componentType = interfaces[iindex];
  48. #if DEBUG && !PROFILER
  49. if (implementorsByType.TryGetValue(componentType, out var implementorData))
  50. {
  51. implementorData.numberOfImplementations++;
  52. implementorsByType[componentType] = implementorData;
  53. }
  54. else
  55. implementorsByType[componentType] = new ECSTuple<object, int>(implementor, 1);
  56. #else
  57. implementorsByType[componentType] = implementor;
  58. #endif
  59. }
  60. }
  61. #if DEBUG && !PROFILER
  62. else
  63. {
  64. Console.Log(NULL_IMPLEMENTOR_ERROR.FastConcat(" entityView ",
  65. entityBuilder.GetEntityType().ToString()));
  66. }
  67. #endif
  68. }
  69. for (var i = 0; i < count; i++)
  70. {
  71. var fieldSetter = setters[i];
  72. var fieldType = fieldSetter.Key;
  73. #if DEBUG && !PROFILER
  74. ECSTuple<object, int> component;
  75. #else
  76. object component;
  77. #endif
  78. if (implementorsByType.TryGetValue(fieldType, out component) == false)
  79. {
  80. var e = new ECSException(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name +
  81. " - EntityView: " + entityBuilder.GetEntityType().Name);
  82. throw e;
  83. }
  84. #if DEBUG && !PROFILER
  85. if (component.numberOfImplementations > 1)
  86. throw new ECSException(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat(
  87. "Component Type: ", fieldType.Name,
  88. " implementor: ",
  89. component.implementorType
  90. .ToString()) +
  91. " - EntityView: " +
  92. entityBuilder.GetEntityType().Name);
  93. #endif
  94. #if DEBUG && !PROFILER
  95. fieldSetter.Value(ref entityView, component.implementorType);
  96. #else
  97. fieldSetter.Value(ref entityView, component);
  98. #endif
  99. }
  100. implementorsByType.Clear();
  101. }
  102. const string DUPLICATE_IMPLEMENTOR_ERROR =
  103. "<color=teal>Svelto.ECS</color> the same component is implemented with more than one implementor. This is " +
  104. "considered an error and MUST be fixed. ";
  105. const string NULL_IMPLEMENTOR_ERROR =
  106. "<color=teal>Svelto.ECS</color> Null implementor, please be careful about the implementors passed to avoid " +
  107. "performance loss ";
  108. const string NOT_FOUND_EXCEPTION = "<color=teal>Svelto.ECS</color> Implementor not found for an EntityView. ";
  109. }
  110. }