Entitas  0.35.0
Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
ReactiveSystem.cs
1 using System.Collections.Generic;
2 
3 namespace Entitas {
4 
5  /// A ReactiveSystem manages your implementation of a IReactiveSystem,
6  /// IMultiReactiveSystem or IEntityCollectorSystem subsystem.
7  /// It will only call subsystem.Execute() if there were changes based on
8  /// the triggers and eventTypes specified by your subsystem
9  /// and will only pass in changed entities. A common use-case is to react
10  /// to changes, e.g. a change of the position of an entity to update the
11  /// gameObject.transform.position of the related gameObject.
12  /// Recommended way to create systems in general:
13  /// pool.CreateSystem(new MySystem()); This will automatically wrap MySystem
14  /// in a ReactiveSystem if it implements IReactiveSystem,
15  /// IMultiReactiveSystem or IEntityCollectorSystem.
16  public class ReactiveSystem : IExecuteSystem {
17 
18  /// Returns the subsystem which will be managed by this
19  /// instance of ReactiveSystem.
20  public IReactiveExecuteSystem subsystem { get { return _subsystem; } }
21 
22  readonly IReactiveExecuteSystem _subsystem;
23  readonly EntityCollector _collector;
24  readonly IMatcher _ensureComponents;
25  readonly IMatcher _excludeComponents;
26  readonly bool _clearAfterExecute;
27  readonly List<Entity> _buffer;
28  string _toStringCache;
29 
30  /// Recommended way to create systems in general:
31  /// pool.CreateSystem(new MySystem());
32  public ReactiveSystem(Pool pool, IReactiveSystem subSystem) : this(
33  subSystem, createEntityCollector(pool, new [] { subSystem.trigger })
34  ) {
35  }
36 
37  /// Recommended way to create systems in general:
38  /// pool.CreateSystem(new MySystem());
39  public ReactiveSystem(Pool pool, IMultiReactiveSystem subSystem) :
40  this(subSystem, createEntityCollector(pool, subSystem.triggers)) {
41  }
42 
43  /// Recommended way to create systems in general:
44  /// pool.CreateSystem(new MySystem());
46  this(subSystem, subSystem.entityCollector) {
47  }
48 
50  EntityCollector collector) {
51  _subsystem = subSystem;
52  var ensureComponents = subSystem as IEnsureComponents;
53  if(ensureComponents != null) {
54  _ensureComponents = ensureComponents.ensureComponents;
55  }
56  var excludeComponents = subSystem as IExcludeComponents;
57  if(excludeComponents != null) {
58  _excludeComponents = excludeComponents.excludeComponents;
59  }
60 
61  _clearAfterExecute = (subSystem as IClearReactiveSystem) != null;
62 
63  _collector = collector;
64  _buffer = new List<Entity>();
65  }
66 
67  static EntityCollector createEntityCollector(
68  Pool pool, TriggerOnEvent[] triggers) {
69  var triggersLength = triggers.Length;
70  var groups = new Group[triggersLength];
71  var eventTypes = new GroupEventType[triggersLength];
72  for (int i = 0; i < triggersLength; i++) {
73  var trigger = triggers[i];
74  groups[i] = pool.GetGroup(trigger.trigger);
75  eventTypes[i] = trigger.eventType;
76  }
77 
78  return new EntityCollector(groups, eventTypes);
79  }
80 
81  /// Activates the ReactiveSystem and starts observing changes
82  /// based on the triggers and eventTypes specified by the subsystem.
83  /// ReactiveSystem are activated by default.
84  public void Activate() {
85  _collector.Activate();
86  }
87 
88  /// Deactivates the ReactiveSystem.
89  /// No changes will be tracked while deactivated.
90  /// This will also clear the ReactiveSystems.
91  /// ReactiveSystem are activated by default
92  public void Deactivate() {
93  _collector.Deactivate();
94  }
95 
96  /// Clears all accumulated changes.
97  public void Clear() {
98  _collector.ClearCollectedEntities();
99  }
100 
101  /// Will call subsystem.Execute() with changed entities
102  /// if there are any. Otherwise it will not call subsystem.Execute().
103  public void Execute() {
104  if(_collector.collectedEntities.Count != 0) {
105  if(_ensureComponents != null) {
106  if(_excludeComponents != null) {
107  foreach(var e in _collector.collectedEntities) {
108  if(_ensureComponents.Matches(e) &&
109  !_excludeComponents.Matches(e)) {
110  _buffer.Add(e.Retain(this));
111  }
112  }
113  } else {
114  foreach(var e in _collector.collectedEntities) {
115  if(_ensureComponents.Matches(e)) {
116  _buffer.Add(e.Retain(this));
117  }
118  }
119  }
120  } else if(_excludeComponents != null) {
121  foreach(var e in _collector.collectedEntities) {
122  if(!_excludeComponents.Matches(e)) {
123  _buffer.Add(e.Retain(this));
124  }
125  }
126  } else {
127  foreach(var e in _collector.collectedEntities) {
128  _buffer.Add(e.Retain(this));
129  }
130  }
131 
132  _collector.ClearCollectedEntities();
133  if(_buffer.Count != 0) {
134  _subsystem.Execute(_buffer);
135  for (int i = 0; i < _buffer.Count; i++) {
136  _buffer[i].Release(this);
137  }
138  _buffer.Clear();
139  if(_clearAfterExecute) {
140  _collector.ClearCollectedEntities();
141  }
142  }
143  }
144  }
145 
146  public override string ToString() {
147  if(_toStringCache == null) {
148  _toStringCache = "ReactiveSystem(" + subsystem + ")";
149  }
150 
151  return _toStringCache;
152  }
153 
154  ~ReactiveSystem () {
155  Deactivate();
156  }
157  }
158 }
ReactiveSystem(Pool pool, IReactiveSystem subSystem)
virtual Group GetGroup(IMatcher matcher)
Definition: Pool.cs:230
IReactiveExecuteSystem subsystem
ReactiveSystem(Pool pool, IMultiReactiveSystem subSystem)
void Clear()
Clears all accumulated changes.
ReactiveSystem(IEntityCollectorSystem subSystem)