summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/ComponentManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/ComponentManager.cs')
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/ComponentManager.cs90
1 files changed, 90 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/ComponentManager.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/ComponentManager.cs
new file mode 100644
index 0000000..a59c87c
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Entities/ComponentManager.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Microsoft.Xna.Framework;
+using MonoGame.Extended.Collections;
+using MonoGame.Extended.Entities.Systems;
+
+namespace MonoGame.Extended.Entities
+{
+ public interface IComponentMapperService
+ {
+ ComponentMapper<T> GetMapper<T>() where T : class;
+ }
+
+ public class ComponentManager : UpdateSystem, IComponentMapperService
+ {
+ public ComponentManager()
+ {
+ _componentMappers = new Bag<ComponentMapper>();
+ _componentTypes = new Dictionary<Type, int>();
+ }
+
+ private readonly Bag<ComponentMapper> _componentMappers;
+ private readonly Dictionary<Type, int> _componentTypes;
+
+ public Action<int> ComponentsChanged;
+
+ private ComponentMapper<T> CreateMapperForType<T>(int componentTypeId)
+ where T : class
+ {
+ // TODO: We can probably do better than this without a huge performance penalty by creating our own bit vector that grows after the first 32 bits.
+ if (componentTypeId >= 32)
+ throw new InvalidOperationException("Component type limit exceeded. We currently only allow 32 component types for performance reasons.");
+
+ var mapper = new ComponentMapper<T>(componentTypeId, ComponentsChanged);
+ _componentMappers[componentTypeId] = mapper;
+ return mapper;
+ }
+
+ public ComponentMapper GetMapper(int componentTypeId)
+ {
+ return _componentMappers[componentTypeId];
+ }
+
+ public ComponentMapper<T> GetMapper<T>()
+ where T : class
+ {
+ var componentTypeId = GetComponentTypeId(typeof(T));
+
+ if (_componentMappers[componentTypeId] != null)
+ return _componentMappers[componentTypeId] as ComponentMapper<T>;
+
+ return CreateMapperForType<T>(componentTypeId);
+ }
+
+ public int GetComponentTypeId(Type type)
+ {
+ if (_componentTypes.TryGetValue(type, out var id))
+ return id;
+
+ id = _componentTypes.Count;
+ _componentTypes.Add(type, id);
+ return id;
+ }
+
+ public BitVector32 CreateComponentBits(int entityId)
+ {
+ var componentBits = new BitVector32();
+ var mask = BitVector32.CreateMask();
+
+ for (var componentId = 0; componentId < _componentMappers.Count; componentId++)
+ {
+ componentBits[mask] = _componentMappers[componentId]?.Has(entityId) ?? false;
+ mask = BitVector32.CreateMask(mask);
+ }
+
+ return componentBits;
+ }
+
+ public void Destroy(int entityId)
+ {
+ foreach (var componentMapper in _componentMappers)
+ componentMapper?.Delete(entityId);
+ }
+
+ public override void Update(GameTime gameTime)
+ {
+ }
+ }
+}