Entitas  0.35.0
Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
Group.cs
1 using System.Collections.Generic;
2 using System.Linq;
3 
4 namespace Entitas {
5 
6  public enum GroupEventType : byte {
7  OnEntityAdded,
8  OnEntityRemoved,
9  OnEntityAddedOrRemoved
10  }
11 
12  /// Use pool.GetGroup(matcher) to get a group of entities which match
13  /// the specified matcher. Calling pool.GetGroup(matcher) with the
14  /// same matcher will always return the same instance of the group.
15  /// The created group is managed by the pool and will always be up to date.
16  /// It will automatically add entities that match the matcher or
17  /// remove entities as soon as they don't match the matcher anymore.
18  public class Group {
19 
20  /// Occurs when an entity gets added.
21  public event GroupChanged OnEntityAdded;
22 
23  /// Occurs when an entity gets removed.
24  public event GroupChanged OnEntityRemoved;
25 
26  /// Occurs when a component of an entity in the group gets replaced.
27  public event GroupUpdated OnEntityUpdated;
28 
29  public delegate void GroupChanged(
30  Group group, Entity entity, int index, IComponent component
31  );
32 
33  public delegate void GroupUpdated(
34  Group group, Entity entity, int index,
35  IComponent previousComponent, IComponent newComponent
36  );
37 
38  /// Returns the number of entities in the group.
39  public int count { get { return _entities.Count; } }
40 
41  /// Returns the matcher which was used to create this group.
42  public IMatcher matcher { get { return _matcher; } }
43 
44  readonly IMatcher _matcher;
45 
46  readonly HashSet<Entity> _entities = new HashSet<Entity>(
47  EntityEqualityComparer.comparer
48  );
49 
50  Entity[] _entitiesCache;
51  Entity _singleEntityCache;
52  string _toStringCache;
53 
54  /// Use pool.GetGroup(matcher) to get a group of entities which match
55  /// the specified matcher.
57  _matcher = matcher;
58  }
59 
60  /// This is used by the pool to manage the group.
61  public void HandleEntitySilently(Entity entity) {
62  if(_matcher.Matches(entity)) {
63  addEntitySilently(entity);
64  } else {
65  removeEntitySilently(entity);
66  }
67  }
68 
69  /// This is used by the pool to manage the group.
70  public void HandleEntity(
71  Entity entity, int index, IComponent component) {
72  if(_matcher.Matches(entity)) {
73  addEntity(entity, index, component);
74  } else {
75  removeEntity(entity, index, component);
76  }
77  }
78 
79  /// This is used by the pool to manage the group.
80  public void UpdateEntity(
81  Entity entity,
82  int index,
83  IComponent previousComponent,
84  IComponent newComponent) {
85  if(_entities.Contains(entity)) {
86  if(OnEntityRemoved != null) {
87  OnEntityRemoved(this, entity, index, previousComponent);
88  }
89  if(OnEntityAdded != null) {
90  OnEntityAdded(this, entity, index, newComponent);
91  }
92  if(OnEntityUpdated != null) {
94  this, entity, index, previousComponent, newComponent
95  );
96  }
97  }
98  }
99 
100  /// This is called by pool.Reset() and pool.ClearGroups() to remove
101  /// all event handlers.
102  /// This is useful when you want to soft-restart your application.
103  public void RemoveAllEventHandlers() {
104  OnEntityAdded = null;
105  OnEntityRemoved = null;
106  OnEntityUpdated = null;
107  }
108 
109  internal GroupChanged handleEntity(Entity entity) {
110  return _matcher.Matches(entity)
111  ? (addEntitySilently(entity) ? OnEntityAdded : null)
112  : (removeEntitySilently(entity) ? OnEntityRemoved : null);
113  }
114 
115  bool addEntitySilently(Entity entity) {
116  if(entity.isEnabled) {
117  var added = _entities.Add(entity);
118  if(added) {
119  _entitiesCache = null;
120  _singleEntityCache = null;
121  entity.Retain(this);
122  }
123 
124  return added;
125  }
126 
127  return false;
128  }
129 
130  void addEntity(Entity entity, int index, IComponent component) {
131  if(addEntitySilently(entity) && OnEntityAdded != null) {
132  OnEntityAdded(this, entity, index, component);
133  }
134  }
135 
136  bool removeEntitySilently(Entity entity) {
137  var removed = _entities.Remove(entity);
138  if(removed) {
139  _entitiesCache = null;
140  _singleEntityCache = null;
141  entity.Release(this);
142  }
143 
144  return removed;
145  }
146 
147  void removeEntity(Entity entity, int index, IComponent component) {
148  var removed = _entities.Remove(entity);
149  if(removed) {
150  _entitiesCache = null;
151  _singleEntityCache = null;
152  if(OnEntityRemoved != null) {
153  OnEntityRemoved(this, entity, index, component);
154  }
155  entity.Release(this);
156  }
157  }
158 
159  /// Determines whether this group has the specified entity.
160  public bool ContainsEntity(Entity entity) {
161  return _entities.Contains(entity);
162  }
163 
164  /// Returns all entities which are currently in this group.
165  public Entity[] GetEntities() {
166  if(_entitiesCache == null) {
167  _entitiesCache = new Entity[_entities.Count];
168  _entities.CopyTo(_entitiesCache);
169  }
170 
171  return _entitiesCache;
172  }
173 
174  /// Returns the only entity in this group. It will return null
175  /// if the group is empty. It will throw an exception if the group
176  /// has more than one entity.
178  if(_singleEntityCache == null) {
179  var c = _entities.Count;
180  if(c == 1) {
181  using (var enumerator = _entities.GetEnumerator()) {
182  enumerator.MoveNext();
183  _singleEntityCache = enumerator.Current;
184  }
185  } else if(c == 0) {
186  return null;
187  } else {
188  throw new GroupSingleEntityException(this);
189  }
190  }
191 
192  return _singleEntityCache;
193  }
194 
195  public override string ToString() {
196  if(_toStringCache == null) {
197  _toStringCache = "Group(" + _matcher + ")";
198  }
199  return _toStringCache;
200  }
201  }
202 
204  public GroupSingleEntityException(Group group) :
205  base(
206  "Cannot get the single entity from " + group +
207  "!\nGroup contains " + group.count + " entities:",
208  string.Join("\n",
209  group.GetEntities().Select(e => e.ToString()).ToArray()
210  )
211  ) {
212  }
213  }
214 }
Group(IMatcher matcher)
Definition: Group.cs:56
void RemoveAllEventHandlers()
Definition: Group.cs:103
IMatcher matcher
Returns the matcher which was used to create this group.
Definition: Group.cs:42
void HandleEntity(Entity entity, int index, IComponent component)
This is used by the pool to manage the group.
Definition: Group.cs:70
void UpdateEntity(Entity entity, int index, IComponent previousComponent, IComponent newComponent)
This is used by the pool to manage the group.
Definition: Group.cs:80
bool isEnabled
Definition: Entity.cs:52
Entity GetSingleEntity()
Definition: Group.cs:177
void Release(object owner)
Definition: Entity.cs:402
GroupChanged OnEntityRemoved
Occurs when an entity gets removed.
Definition: Group.cs:24
Entity [] GetEntities()
Returns all entities which are currently in this group.
Definition: Group.cs:165
GroupUpdated OnEntityUpdated
Occurs when a component of an entity in the group gets replaced.
Definition: Group.cs:27
void HandleEntitySilently(Entity entity)
This is used by the pool to manage the group.
Definition: Group.cs:61
int count
Returns the number of entities in the group.
Definition: Group.cs:39
GroupChanged OnEntityAdded
Occurs when an entity gets added.
Definition: Group.cs:21
Base exception used by Entitas.
Entity Retain(object owner)
Definition: Entity.cs:377
bool ContainsEntity(Entity entity)
Determines whether this group has the specified entity.
Definition: Group.cs:160