Mirror of Svelto.ECS because we're a fan of it
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

117 lines
5.8KB

  1. using System;
  2. using Svelto.Common;
  3. using Svelto.DataStructures;
  4. namespace Svelto.ECS
  5. {
  6. //Hi! I've been following your discussion on discord and have just a few questions on how to use this snippet properly:
  7. //
  8. //Did I get the idea right: this snippet allows us to swap group tags (from current to target) even if target combination of tags not declared in groups class (like GameGroups.cs in Doofuses iteration 3 example)? If so:
  9. //On discord you wrote:
  10. //The specialized engines define the swaps like this:
  11. //GroupCompound<SHIP, AI>.BuildGroup.SetTagSwap<SHIP, SUNK_SHIP>(GroupCompound<SUNK_SHIP, AI>.BuildGroup);
  12. //GroupCompound<SHIP, PLAYER>.BuildGroup.SetTagSwap<SHIP, SUNK_SHIP>(GroupCompound<SUNK_SHIP, PLAYER>.BuildGroup);
  13. //
  14. //And any engine can do this:
  15. //var targetGroup = egid.groupID.GetSwapTag<SUNK_SHIP, SHIP>();
  16. //_functions.SwapEntityGroup<ShipEntityDescriptor>(egid, targetGroup);
  17. //
  18. //by specialized / any did you mean not abstract / abstract or something else?
  19. //
  20. //When _removeTransitions, _addTransitions, _swapTransitions should be filled?
  21. //@jlreymendez
  22. //Author
  23. //jlreymendez commented on Aug 10, 2020
  24. //Hey!
  25. //
  26. //1- Yeah, it would allow you to swap to targets that are not directly declared in a group class. In reality you are declaring them when you declare the SetTagSwap, SetTagAddition and SetTagRemoval.
  27. //
  28. //2- Yes, correct by specialized I mean something not abstract, an engine that knows all the tags that apply to an entity. Thus it would allow you to create a comprehensive list of the swaps like you see in that code. Remember that when you do SetTagSwap<SHIP, SUNK_SHIP> the reverse will also be declared automatically.
  29. //
  30. //This is the latest from that code you shared:
  31. //
  32. //
  33. // // Register possible transitions.
  34. // GroupCompound<SHIP, AI, PIRATE>.BuildGroup.SetTagSwap<SHIP, SUNK_SHIP>(GroupCompound<SUNK_SHIP, AI, PIRATE>.BuildGroup);
  35. // GroupCompound<SHIP, AI, MERCHANT>.BuildGroup.SetTagSwap<SHIP, SUNK_SHIP>(GroupCompound<SUNK_SHIP, AI, MERCHANT>.BuildGroup);
  36. // GroupCompound<SHIP, AI, NORMAL>.BuildGroup.SetTagSwap<SHIP, SUNK_SHIP>(GroupCompound<SUNK_SHIP, AI, NORMAL>.BuildGroup);
  37. //
  38. // GroupCompound<SHIP, PLAYER>.BuildGroup.SetTagSwap<SHIP, SUNK_SHIP>(GroupCompound<SUNK_SHIP, PLAYER>.BuildGroup);
  39. //
  40. //3- You would fill them at initialization time, I did it in the Ready() of the engine before entering the game loop. But you could do it in the constructor of the engine. Wherever you find it appropriate before you need to start swapping or changing tags.
  41. public static class ExclusiveBuildGroupExtensions
  42. {
  43. internal static FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>>
  44. _removeTransitions =
  45. new FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>>();
  46. internal static FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>>
  47. _addTransitions =
  48. new FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>>();
  49. internal static FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>>
  50. _swapTransitions =
  51. new FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>>();
  52. public static void SetTagAddition<T>
  53. (this ExclusiveBuildGroup group, ExclusiveBuildGroup target, bool setReverse = true) where T : GroupTag<T>
  54. {
  55. if (_addTransitions.TryGetValue(@group, out var transitions) == false)
  56. {
  57. transitions = new FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>();
  58. _addTransitions[@group] = transitions;
  59. }
  60. var type = new RefWrapper<Type>(typeof(T));
  61. transitions[type] = target;
  62. if (setReverse)
  63. {
  64. SetTagRemoval<T>(target, group, false);
  65. }
  66. }
  67. public static void SetTagRemoval<T>
  68. (this ExclusiveBuildGroup group, ExclusiveBuildGroup target, bool setReverse = true) where T : GroupTag<T>
  69. {
  70. if (_removeTransitions.TryGetValue(@group, out var transitions) == false)
  71. {
  72. transitions = new FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>();
  73. _removeTransitions[@group] = transitions;
  74. }
  75. var type = new RefWrapper<Type>(typeof(T));
  76. transitions[type] = target;
  77. if (setReverse)
  78. {
  79. SetTagAddition<T>(target, group, false);
  80. }
  81. }
  82. public static void SetTagSwap<TRemove, TAdd>
  83. (this ExclusiveBuildGroup group, ExclusiveBuildGroup target, bool setReverse = true)
  84. where TRemove : GroupTag<TRemove> where TAdd : GroupTag<TAdd>
  85. {
  86. if (_swapTransitions.TryGetValue(@group, out var transitions) == false)
  87. {
  88. transitions = new FasterDictionary<RefWrapper<Type>, ExclusiveBuildGroup>();
  89. _swapTransitions[group] = transitions;
  90. }
  91. var type = new RefWrapper<Type>(typeof(TAdd));
  92. transitions[type] = target;
  93. // To avoid needing to check if the group already has the tag when swapping (prevent ecs exceptions).
  94. // The current groups adds the removed tag pointing to itself.
  95. type = new RefWrapper<Type>(typeof(TRemove));
  96. transitions[type] = group;
  97. if (setReverse)
  98. {
  99. SetTagSwap<TAdd, TRemove>(target, group, false);
  100. }
  101. }
  102. }
  103. }