/
Group.cs
148 lines (126 loc) · 4.81 KB
/
Group.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Collections.Generic;
namespace Entitas {
public class Group {
public event GroupChanged OnEntityAdded;
public event GroupChanged OnEntityRemoved;
public event GroupUpdated OnEntityUpdated;
public delegate void GroupChanged(Group group, Entity entity, int index, IComponent component);
public delegate void GroupUpdated(Group group, Entity entity, int index, IComponent previousComponent, IComponent newComponent);
public int Count { get { return _entities.Count; } }
public IMatcher matcher { get { return _matcher; } }
readonly IMatcher _matcher;
readonly HashSet<Entity> _entities = new HashSet<Entity>(EntityEqualityComparer.comparer);
Entity[] _entitiesCache;
Entity _singleEntityCache;
string _toStringCache;
public Group(IMatcher matcher) {
_matcher = matcher;
}
public void HandleEntitySilently(Entity entity) {
if (_matcher.Matches(entity)) {
addEntitySilently(entity);
} else {
removeEntitySilently(entity);
}
}
public void HandleEntity(Entity entity, int index, IComponent component) {
if (_matcher.Matches(entity)) {
addEntity(entity, index, component);
} else {
removeEntity(entity, index, component);
}
}
public void UpdateEntity(Entity entity, int index, IComponent previousComponent, IComponent newComponent) {
if (_entities.Contains(entity)) {
if (OnEntityRemoved != null) {
OnEntityRemoved(this, entity, index, previousComponent);
}
if (OnEntityAdded != null) {
OnEntityAdded(this, entity, index, newComponent);
}
if (OnEntityUpdated != null) {
OnEntityUpdated(this, entity, index, previousComponent, newComponent);
}
}
}
void addEntitySilently(Entity entity) {
var added = _entities.Add(entity);
if (added) {
_entitiesCache = null;
_singleEntityCache = null;
entity.Retain();
}
}
void addEntity(Entity entity, int index, IComponent component) {
var added = _entities.Add(entity);
if (added) {
_entitiesCache = null;
_singleEntityCache = null;
entity.Retain();
if (OnEntityAdded != null) {
OnEntityAdded(this, entity, index, component);
}
}
}
void removeEntitySilently(Entity entity) {
var removed = _entities.Remove(entity);
if (removed) {
_entitiesCache = null;
_singleEntityCache = null;
entity.Release();
}
}
void removeEntity(Entity entity, int index, IComponent component) {
var removed = _entities.Remove(entity);
if (removed) {
_entitiesCache = null;
_singleEntityCache = null;
if (OnEntityRemoved != null) {
OnEntityRemoved(this, entity, index, component);
}
entity.Release();
}
}
public bool ContainsEntity(Entity entity) {
return _entities.Contains(entity);
}
public Entity[] GetEntities() {
if (_entitiesCache == null) {
_entitiesCache = new Entity[_entities.Count];
_entities.CopyTo(_entitiesCache);
}
return _entitiesCache;
}
public Entity GetSingleEntity() {
if (_singleEntityCache == null) {
var count = _entities.Count;
if (count == 1) {
using (var enumerator = _entities.GetEnumerator()) {
enumerator.MoveNext();
_singleEntityCache = enumerator.Current;
}
} else {
if (count == 0) {
return null;
}
if (count > 1) {
throw new SingleEntityException(_matcher);
}
}
}
return _singleEntityCache;
}
public override string ToString() {
if (_toStringCache == null) {
_toStringCache = "Group(" + _matcher + ")";
}
return _toStringCache;
}
}
public class SingleEntityException : Exception {
public SingleEntityException(IMatcher matcher) :
base("Multiple entities exist matching " + matcher) {
}
}
}