using System; using System.Collections; using System.Collections.Generic; using EcsRx.Blueprints; using EcsRx.Entities; using EcsRx.Events.Collections; using EcsRx.Extensions; using EcsRx.Lookups; using EcsRx.MicroRx.Disposables; using EcsRx.MicroRx.Extensions; using EcsRx.MicroRx.Subjects; namespace EcsRx.Collections.Entity { public class EntityCollection : IEntityCollection, IDisposable { public int Id { get; } public IEntityFactory EntityFactory { get; } public readonly EntityLookup EntityLookup; public readonly IDictionary EntitySubscriptions; public IObservable EntityAdded => _onEntityAdded; public IObservable EntityRemoved => _onEntityRemoved; public IObservable EntityComponentsAdded => _onEntityComponentsAdded; public IObservable EntityComponentsRemoving => _onEntityComponentsRemoving; public IObservable EntityComponentsRemoved => _onEntityComponentsRemoved; private readonly Subject _onEntityAdded; private readonly Subject _onEntityRemoved; private readonly Subject _onEntityComponentsAdded; private readonly Subject _onEntityComponentsRemoving; private readonly Subject _onEntityComponentsRemoved; public EntityCollection(int id, IEntityFactory entityFactory) { EntityLookup = new EntityLookup(); EntitySubscriptions = new Dictionary(); Id = id; EntityFactory = entityFactory; _onEntityAdded = new Subject(); _onEntityRemoved = new Subject(); _onEntityComponentsAdded = new Subject(); _onEntityComponentsRemoving = new Subject(); _onEntityComponentsRemoved = new Subject(); } public void SubscribeToEntity(IEntity entity) { var entityDisposable = new CompositeDisposable(); entity.ComponentsAdded.Subscribe(x => _onEntityComponentsAdded.OnNext(new ComponentsChangedEvent(entity, x))).AddTo(entityDisposable); entity.ComponentsRemoving.Subscribe(x => _onEntityComponentsRemoving.OnNext(new ComponentsChangedEvent(entity, x))).AddTo(entityDisposable); entity.ComponentsRemoved.Subscribe(x => _onEntityComponentsRemoved.OnNext(new ComponentsChangedEvent(entity, x))).AddTo(entityDisposable); EntitySubscriptions.Add(entity.Id, entityDisposable); } public void UnsubscribeFromEntity(int entityId) { EntitySubscriptions.RemoveAndDispose(entityId); } public IEntity CreateEntity(IBlueprint blueprint = null) { var entity = EntityFactory.Create(null); EntityLookup.Add(entity); _onEntityAdded.OnNext(new CollectionEntityEvent(entity)); SubscribeToEntity(entity); blueprint?.Apply(entity); return entity; } public IEntity GetEntity(int id) { return EntityLookup[id]; } public void RemoveEntity(int id, bool disposeOnRemoval = true) { var entity = GetEntity(id); EntityLookup.Remove(id); var entityId = entity.Id; if (disposeOnRemoval) { entity.Dispose(); EntityFactory.Destroy(entityId); } UnsubscribeFromEntity(entityId); _onEntityRemoved.OnNext(new CollectionEntityEvent(entity)); } public void AddEntity(IEntity entity) { EntityLookup.Add(entity); _onEntityAdded.OnNext(new CollectionEntityEvent(entity)); SubscribeToEntity(entity); } public bool ContainsEntity(int id) { return EntityLookup.Contains(id); } public IEnumerator GetEnumerator() { return EntityLookup.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Dispose() { _onEntityAdded.Dispose(); _onEntityRemoved.Dispose(); _onEntityComponentsAdded.Dispose(); _onEntityComponentsRemoving.Dispose(); _onEntityComponentsRemoved.Dispose(); EntityLookup.Clear(); EntitySubscriptions.RemoveAndDisposeAll(); } public int Count => EntityLookup.Count; public IEntity this[int index] => EntityLookup.GetByIndex(index); } }