diff --git a/Source/Demos/Platformer/AutofacDependencyResolver.cs b/Source/Demos/Platformer/AutofacDependencyResolver.cs deleted file mode 100644 index 8fba167a..00000000 --- a/Source/Demos/Platformer/AutofacDependencyResolver.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Linq; -using Autofac; -using MonoGame.Extended.Entities; -using MonoGame.Extended.Entities.Legacy; - -namespace Platformer -{ - public class AutofacDependencyResolver : DefaultDependencyResolver - { - private readonly IContainer _container; - - public AutofacDependencyResolver(IContainer container) - { - _container = container; - } - - public override object Resolve(Type type, params object[] args) - { - if (_container.IsRegistered(type)) - { - var instance = _container.Resolve(type, args.Select((a, i) => new PositionalParameter(i, a))); - - if (instance != null) - return instance; - } - - return base.Resolve(type, args); - } - } -} \ No newline at end of file diff --git a/Source/Demos/Platformer/EntityFactory.cs b/Source/Demos/Platformer/EntityFactory.cs index 959b3a94..d295464e 100644 --- a/Source/Demos/Platformer/EntityFactory.cs +++ b/Source/Demos/Platformer/EntityFactory.cs @@ -4,7 +4,7 @@ using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended; using MonoGame.Extended.Animations; using MonoGame.Extended.Animations.SpriteSheets; -using MonoGame.Extended.Entities.Legacy; +using MonoGame.Extended.Entities; using MonoGame.Extended.TextureAtlases; using Platformer.Collisions; using Platformer.Components; @@ -13,12 +13,12 @@ namespace Platformer { public class EntityFactory { - private readonly EntityManager _entityManager; + private readonly EntityWorld _world; private readonly ContentManager _contentManager; - public EntityFactory(EntityManager entityManager, ContentManager contentManager) + public EntityFactory(EntityWorld world, ContentManager contentManager) { - _entityManager = entityManager; + _world = world; _contentManager = contentManager; } @@ -27,7 +27,7 @@ namespace Platformer var dudeTexture = _contentManager.Load("hero"); var dudeAtlas = TextureAtlas.Create("dudeAtlas", dudeTexture, 16, 16); - var entity = _entityManager.CreateEntity(); + var entity = _world.CreateEntity(); var animationFactory = new SpriteSheetAnimationFactory(dudeAtlas); animationFactory.Add("idle", new SpriteSheetAnimationData(new[] { 0, 1, 2, 1 })); animationFactory.Add("walk", new SpriteSheetAnimationData(new[] { 6, 7, 8, 9, 10, 11 }, frameDuration: 0.1f)); @@ -40,7 +40,7 @@ namespace Platformer entity.Attach(new AnimatedSprite(animationFactory, "idle")); entity.Attach(new Transform2(position, 0, Vector2.One * 4)); entity.Attach(new Body { Position = position, Size = new Vector2(32, 64), BodyType = BodyType.Dynamic }); - entity.Attach(); + entity.Attach(new Player()); return entity; } @@ -49,12 +49,12 @@ namespace Platformer var dudeTexture = _contentManager.Load("blueguy"); var dudeAtlas = TextureAtlas.Create("blueguyAtlas", dudeTexture, 16, 16); - var entity = _entityManager.CreateEntity(); + var entity = _world.CreateEntity(); var animationFactory = new SpriteSheetAnimationFactory(dudeAtlas); animationFactory.Add("idle", new SpriteSheetAnimationData(new[] { 0, 1, 2, 3, 2, 1 })); animationFactory.Add("walk", new SpriteSheetAnimationData(new[] { 6, 7, 8, 9, 10, 11 }, frameDuration: 0.1f)); animationFactory.Add("jump", new SpriteSheetAnimationData(new[] { 10, 12 }, frameDuration: 1.0f, isLooping: false)); - entity.Attach(new AnimatedSprite(animationFactory, "idle")); + entity.Attach(new AnimatedSprite(animationFactory, "idle") { Effect = SpriteEffects.FlipHorizontally }); entity.Attach(new Transform2(position, 0, Vector2.One * 4)); entity.Attach(new Body { Position = position, Size = new Vector2(32, 64), BodyType = BodyType.Dynamic }); return entity; @@ -62,7 +62,7 @@ namespace Platformer public void CreateTile(int x, int y, int width, int height) { - var entity = _entityManager.CreateEntity(); + var entity = _world.CreateEntity(); entity.Attach(new Body { Position = new Vector2(x * width + width * 0.5f, y * height + height * 0.5f), diff --git a/Source/Demos/Platformer/GameBase.cs b/Source/Demos/Platformer/GameBase.cs index a29d9e81..2f0c4516 100644 --- a/Source/Demos/Platformer/GameBase.cs +++ b/Source/Demos/Platformer/GameBase.cs @@ -1,19 +1,13 @@ -using System.Reflection; -using Autofac; +using Autofac; using Microsoft.Xna.Framework; -using MonoGame.Extended.Entities; -using MonoGame.Extended.Entities.Legacy; namespace Platformer { - // TODO: Are we really benefiting from a base class here? public abstract class GameBase : Game { // ReSharper disable once NotAccessedField.Local protected GraphicsDeviceManager GraphicsDeviceManager { get; } protected IContainer Container { get; private set; } - protected EntityComponentSystem EntityComponentSystem { get; private set; } - //protected KeyboardInputService KeyboardInputService { get; } public int Width { get; } public int Height { get; } @@ -30,43 +24,18 @@ namespace Platformer IsMouseVisible = true; Window.AllowUserResizing = true; Content.RootDirectory = "Content"; - //KeyboardInputService = new KeyboardInputService(); - } - - protected override void Dispose(bool disposing) - { - EntityComponentSystem.Dispose(); - base.Dispose(disposing); } protected override void Initialize() { var containerBuilder = new ContainerBuilder(); - //containerBuilder.RegisterInstance(KeyboardInputService); - RegisterDependencies(containerBuilder); Container = containerBuilder.Build(); - EntityComponentSystem = new EntityComponentSystem(this, new AutofacDependencyResolver(Container)); - EntityComponentSystem.Scan(Assembly.GetEntryAssembly(), Assembly.GetExecutingAssembly()); base.Initialize(); } protected abstract void RegisterDependencies(ContainerBuilder builder); - - protected override void Update(GameTime gameTime) - { - //KeyboardInputService.Update(); - EntityComponentSystem.Update(gameTime); - base.Update(gameTime); - } - - protected override void Draw(GameTime gameTime) - { - //GraphicsDeviceManager.GraphicsDevice.Clear(Color.Black); - EntityComponentSystem.Draw(gameTime); - base.Draw(gameTime); - } } } \ No newline at end of file diff --git a/Source/Demos/Platformer/GameMain.cs b/Source/Demos/Platformer/GameMain.cs index 33506120..1bfd054d 100644 --- a/Source/Demos/Platformer/GameMain.cs +++ b/Source/Demos/Platformer/GameMain.cs @@ -1,9 +1,8 @@ -using System; -using Autofac; +using Autofac; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended; -using MonoGame.Extended.Entities.Legacy; +using MonoGame.Extended.Entities; using MonoGame.Extended.Tiled; using MonoGame.Extended.Tiled.Renderers; using Platformer.Systems; @@ -16,7 +15,7 @@ namespace Platformer private TiledMapRenderer _renderer; private EntityFactory _entityFactory; private OrthographicCamera _camera; - private Entity _playerEntity; + private EntityWorld _world; public GameMain() { @@ -28,15 +27,17 @@ namespace Platformer builder.RegisterInstance(new SpriteBatch(GraphicsDevice)); builder.RegisterInstance(_camera); - builder.RegisterType(); - builder.RegisterType(); - builder.RegisterType(); } protected override void LoadContent() { - _entityFactory = new EntityFactory(EntityComponentSystem.EntityManager, Content); - _playerEntity = _entityFactory.CreatePlayer(new Vector2(100, 240)); + _world = new EntityWorld(); + _world.RegisterSystem(new WorldSystem()); + _world.RegisterSystem(new PlayerSystem()); + _world.RegisterSystem(new RenderSystem(new SpriteBatch(GraphicsDevice), _camera)); + + _entityFactory = new EntityFactory(_world, Content); + // TOOD: Load maps and collision data more nicely :) _map = Content.Load("test-map"); _renderer = new TiledMapRenderer(GraphicsDevice, _map); @@ -59,10 +60,9 @@ namespace Platformer } } - - - //_entityFactory.CreateBlue(new Vector2(600, 100)); - + _entityFactory.CreateBlue(new Vector2(600, 240)); + _entityFactory.CreateBlue(new Vector2(700, 100)); + _entityFactory.CreatePlayer(new Vector2(100, 240)); } protected override void Update(GameTime gameTime) @@ -77,14 +77,17 @@ namespace Platformer _renderer.Update(gameTime); //_camera.LookAt(_playerEntity.Get().Position); + _world.Update(gameTime); + base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); - + _renderer.Draw(_camera.GetViewMatrix()); + _world.Draw(gameTime); base.Draw(gameTime); } diff --git a/Source/Demos/Platformer/Systems/PlayerSystem.cs b/Source/Demos/Platformer/Systems/PlayerSystem.cs index 3cc1ee23..4fda8846 100644 --- a/Source/Demos/Platformer/Systems/PlayerSystem.cs +++ b/Source/Demos/Platformer/Systems/PlayerSystem.cs @@ -4,28 +4,45 @@ using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MonoGame.Extended; using MonoGame.Extended.Animations; -using MonoGame.Extended.Entities.Legacy; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; using MonoGame.Extended.Input; using Platformer.Collisions; using Platformer.Components; namespace Platformer.Systems { - [Aspect(AspectType.All, typeof(Body), typeof(Player), typeof(Transform2), typeof(AnimatedSprite))] - [EntitySystem(GameLoopType.Update, Layer = 0)] public class PlayerSystem : EntityProcessingSystem { - protected override void Process(GameTime gameTime, Entity entity) + private ComponentMapper _playerMapper; + private ComponentMapper _spriteMapper; + private ComponentMapper _transformMapper; + private ComponentMapper _bodyMapper; + + public PlayerSystem() + : base(Aspect.All(typeof(Body), typeof(Player), typeof(Transform2), typeof(AnimatedSprite))) { - var player = entity.Get(); - var sprite = entity.Get(); - var transform = entity.Get(); - var body = entity.Get(); + } + + public override void Initialize(IComponentMapperService mapperService) + { + _playerMapper = mapperService.GetMapper(); + _spriteMapper = mapperService.GetMapper(); + _transformMapper = mapperService.GetMapper(); + _bodyMapper = mapperService.GetMapper(); + } + + public override void Process(GameTime gameTime, int entityId) + { + var player = _playerMapper.Get(entityId); + var sprite = _spriteMapper.Get(entityId); + var transform = _transformMapper.Get(entityId); + var body = _bodyMapper.Get(entityId); var keyboardState = KeyboardExtended.GetState(); - + if (player.CanJump) { - if(keyboardState.WasKeyJustUp(Keys.Up)) + if (keyboardState.WasKeyJustUp(Keys.Up)) body.Velocity.Y -= 550 + Math.Abs(body.Velocity.X) * 0.4f; if (keyboardState.WasKeyJustUp(Keys.Z)) @@ -34,7 +51,7 @@ namespace Platformer.Systems player.State = player.State == State.Idle ? State.Punching : State.Kicking; } } - + if (keyboardState.IsKeyDown(Keys.Right)) { body.Velocity.X += 150; @@ -57,7 +74,7 @@ namespace Platformer.Systems if (body.Velocity.Y > 0) player.State = State.Falling; - + if (body.Velocity.EqualsWithTolerence(Vector2.Zero, 5)) player.State = State.Idle; } diff --git a/Source/Demos/Platformer/Systems/RenderSystem.cs b/Source/Demos/Platformer/Systems/RenderSystem.cs index 4dd045c1..7da9c796 100644 --- a/Source/Demos/Platformer/Systems/RenderSystem.cs +++ b/Source/Demos/Platformer/Systems/RenderSystem.cs @@ -2,41 +2,52 @@ using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended; using MonoGame.Extended.Animations; -using MonoGame.Extended.Entities.Legacy; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; using MonoGame.Extended.Sprites; namespace Platformer.Systems { - [Aspect(AspectType.All, typeof(AnimatedSprite), typeof(Transform2))] - [EntitySystem(GameLoopType.Draw, Layer = 0)] - public class RenderSystem : EntityProcessingSystem + public class RenderSystem : EntityDrawSystem { private readonly SpriteBatch _spriteBatch; private readonly OrthographicCamera _camera; + private ComponentMapper _animatedSpriteMapper; + private ComponentMapper _spriteMapper; + private ComponentMapper _transforMapper; public RenderSystem(SpriteBatch spriteBatch, OrthographicCamera camera) + : base(Aspect.All(typeof(Transform2)).One(typeof(AnimatedSprite), typeof(Sprite))) { _spriteBatch = spriteBatch; _camera = camera; } - protected override void Begin(GameTime gameTime) + public override void Initialize(IComponentMapperService mapperService) + { + _transforMapper = mapperService.GetMapper(); + _animatedSpriteMapper = mapperService.GetMapper(); + _spriteMapper = mapperService.GetMapper(); + } + + public override void Draw(GameTime gameTime) { _spriteBatch.Begin(samplerState: SamplerState.PointClamp, transformMatrix: _camera.GetViewMatrix()); - } - protected override void Process(GameTime gameTime, Entity entity) - { - var sprite = entity.Get(); - var transform = entity.Get(); + foreach (var entity in ActiveEntities) + { + var sprite = _animatedSpriteMapper.Has(entity) + ? _animatedSpriteMapper.Get(entity) + : _spriteMapper.Get(entity); + var transform = _transforMapper.Get(entity); - sprite.Update(gameTime.GetElapsedSeconds()); - //_spriteBatch.FillRectangle(new RectangleF(transform.Position, new Size2(32f, 32f)), sprite.Color); - _spriteBatch.Draw(sprite, transform); - } + if(sprite is AnimatedSprite animatedSprite) + animatedSprite.Update(gameTime.GetElapsedSeconds()); + + _spriteBatch.Draw(sprite, transform); + + } - protected override void End(GameTime gameTime) - { _spriteBatch.End(); } } diff --git a/Source/Demos/Platformer/Systems/WorldSystem.cs b/Source/Demos/Platformer/Systems/WorldSystem.cs index 73fac24c..68925d1d 100644 --- a/Source/Demos/Platformer/Systems/WorldSystem.cs +++ b/Source/Demos/Platformer/Systems/WorldSystem.cs @@ -1,46 +1,51 @@ using Microsoft.Xna.Framework; using MonoGame.Extended; -using MonoGame.Extended.Entities.Legacy; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; using Platformer.Collisions; namespace Platformer.Systems { - [Aspect(AspectType.All, typeof(Body), typeof(Transform2))] - [EntitySystem(GameLoopType.Update, Layer = 0)] public class WorldSystem : EntityProcessingSystem { private readonly World _world; + private ComponentMapper _transformMapper; + private ComponentMapper _bodyMapper; public WorldSystem() + : base(Aspect.All(typeof(Body), typeof(Transform2))) { - _world = new World(new Vector2(0, 60));// {OnCollision = OnCollision}; + _world = new World(new Vector2(0, 60)); } - public override void OnEntityAdded(Entity entity) + public override void Initialize(IComponentMapperService mapperService) { - var body = entity.Get(); + _transformMapper = mapperService.GetMapper(); + _bodyMapper = mapperService.GetMapper(); + } + + protected override void OnEntityAdded(int entityId) + { + var body = _bodyMapper.Get(entityId); _world.AddBody(body); } - public override void OnEntityRemoved(Entity entity) + protected override void OnEntityRemoved(int entityId) { - var body = entity.Get(); + var body = _bodyMapper.Get(entityId); _world.RemoveBody(body); } - - protected override void Process(GameTime gameTime) + + public override void Update(GameTime gameTime) { - var elapsedSeconds = gameTime.GetElapsedSeconds(); - _world.Update(elapsedSeconds); - - base.Process(gameTime); + base.Update(gameTime); + _world.Update(gameTime.GetElapsedSeconds()); } - protected override void Process(GameTime gameTime, Entity entity) + public override void Process(GameTime gameTime, int entityId) { - var transform = entity.Get(); - var body = entity.Get(); - + var transform = _transformMapper.Get(entityId); + var body = _bodyMapper.Get(entityId); transform.Position = body.Position; } } diff --git a/Source/MonoGame.Extended.Entities/ComponentManager.cs b/Source/MonoGame.Extended.Entities/ComponentManager.cs index df093a5f..58977b8c 100644 --- a/Source/MonoGame.Extended.Entities/ComponentManager.cs +++ b/Source/MonoGame.Extended.Entities/ComponentManager.cs @@ -52,21 +52,24 @@ namespace MonoGame.Extended.Entities return id; } - public BitArray GetComponentBits(int entityId) + public void RefreshComponentBits(int entityId, ref BitArray bits) { - var bits = new BitArray(16); - for (var componentId = 0; componentId < _componentMappers.Count; componentId++) - { - if (_componentMappers[componentId].Has(entityId)) - bits[componentId] = true; - } + bits[componentId] = _componentMappers[componentId].Has(entityId); - return bits; + for (var i = _componentMappers.Count; i < bits.Length; i++) + bits[i] = false; } public override void Update(GameTime gameTime) { } + + public long GetCompositionIdentity(BitArray bits) + { + var array = new int[2]; + bits.CopyTo(array, 0); + return (uint)array[0] + ((long)(uint)array[1] << 32); + } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Entity.cs b/Source/MonoGame.Extended.Entities/Entity.cs index 6f26b765..918989e0 100644 --- a/Source/MonoGame.Extended.Entities/Entity.cs +++ b/Source/MonoGame.Extended.Entities/Entity.cs @@ -11,18 +11,37 @@ namespace MonoGame.Extended.Entities public Entity(int id, EntityManager entityManager, ComponentManager componentManager) { Id = id; + + _componentBits = new BitArray(16); _entityManager = entityManager; _componentManager = componentManager; } - public int Id { get; } - public BitArray ComponentBits => _componentManager.GetComponentBits(Id); + public int Id { get; internal set; } + + private BitArray _componentBits; + private bool _componentsChanged; + + public BitArray ComponentBits + { + get + { + if (_componentsChanged) + { + _componentManager.RefreshComponentBits(Id, ref _componentBits); + _componentsChanged = false; + } + + return _componentBits; + } + } public void Attach(T component) where T : class { var mapper = _componentManager.GetMapper(); mapper.Put(Id, component); + _componentsChanged = true; } public void Detach() @@ -30,6 +49,7 @@ namespace MonoGame.Extended.Entities { var mapper = _componentManager.GetMapper(); mapper.Delete(Id); + _componentsChanged = true; } public T Get() @@ -41,7 +61,7 @@ namespace MonoGame.Extended.Entities public void Destory() { - _entityManager.DestroyEntity(this); + _entityManager.DestroyEntity(Id); } public bool Equals(Entity other) diff --git a/Source/MonoGame.Extended.Entities/EntityManager.cs b/Source/MonoGame.Extended.Entities/EntityManager.cs index d6912f2b..d8b152d9 100644 --- a/Source/MonoGame.Extended.Entities/EntityManager.cs +++ b/Source/MonoGame.Extended.Entities/EntityManager.cs @@ -7,10 +7,15 @@ namespace MonoGame.Extended.Entities { public class EntityManager : UpdateSystem { + private const int _defaultBagSize = 128; + public EntityManager(ComponentManager componentManager) { _componentManager = componentManager; - Entities = new Bag(128); + _newEntities = new Bag(_defaultBagSize); + _removedEntities = new Bag(_defaultBagSize); + + Entities = new Bag(_defaultBagSize); } private readonly ComponentManager _componentManager; @@ -18,7 +23,10 @@ namespace MonoGame.Extended.Entities public Bag Entities { get; } - public event EventHandler EntityAdded; + private Bag _newEntities; + private Bag _removedEntities; + + public event EventHandler EntityAdded; public event EventHandler EntityRemoved; public Entity CreateEntity() @@ -27,7 +35,7 @@ namespace MonoGame.Extended.Entities var id = _nextId++; var entity = new Entity(id, this, _componentManager); Entities[id] = entity; - EntityAdded?.Invoke(this, entity); + _newEntities.Add(id); return entity; } @@ -45,6 +53,14 @@ namespace MonoGame.Extended.Entities public override void Update(GameTime gameTime) { + foreach (var newEntity in _newEntities) + EntityAdded?.Invoke(this, newEntity); + + foreach (var removedEntity in _removedEntities) + EntityRemoved?.Invoke(this, removedEntity); + + _newEntities.Clear(); + _removedEntities.Clear(); } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/EntitySubscription.cs b/Source/MonoGame.Extended.Entities/EntitySubscription.cs index 2ca76230..4aff5230 100644 --- a/Source/MonoGame.Extended.Entities/EntitySubscription.cs +++ b/Source/MonoGame.Extended.Entities/EntitySubscription.cs @@ -21,9 +21,8 @@ namespace MonoGame.Extended.Entities _entityManager.EntityAdded += OnEntityAdded; } - // TODO: It's a bit heavy handed to rebuild the actives every time one entity is added or removed. - private void OnEntityAdded(object sender, Entity e) => RebuildActives(); - private void OnEntityRemoved(object sender, int e) => RebuildActives(); + private void OnEntityAdded(object sender, int id) => _activeEntities.Add(id); + private void OnEntityRemoved(object sender, int id) => _activeEntities.Remove(id); public void Dispose() { @@ -47,6 +46,7 @@ namespace MonoGame.Extended.Entities foreach (var entity in _entityManager.Entities) { + // TODO: Technically, many entities will probably share the same set of components. odb calls this the composition identity. if (_aspect.IsInterested(entity.ComponentBits)) { _activeEntities[count] = entity.Id; diff --git a/Source/MonoGame.Extended.Entities/EntityWorld.cs b/Source/MonoGame.Extended.Entities/EntityWorld.cs index cd2ae4af..1959ec99 100644 --- a/Source/MonoGame.Extended.Entities/EntityWorld.cs +++ b/Source/MonoGame.Extended.Entities/EntityWorld.cs @@ -22,6 +22,17 @@ namespace MonoGame.Extended.Entities _drawSystems = new Bag(); } + public override void Dispose() + { + foreach (var updateSystem in _updateSystems) + updateSystem.Dispose(); + + foreach (var drawSystem in _drawSystems) + drawSystem.Dispose(); + + base.Dispose(); + } + internal EntityManager EntityManager { get; } internal ComponentManager ComponentManager { get; } diff --git a/Source/MonoGame.Extended.Entities/Legacy/Aspect.cs b/Source/MonoGame.Extended.Entities/Legacy/Aspect.cs deleted file mode 100644 index cb229720..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/Aspect.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Aspect.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. AllOf rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Specify a Filter class to filter what Entities (with what Components) a EntitySystem will ProcessInternal. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace MonoGame.Extended.Entities.Legacy -{ - public class Aspect - { - // match entities with components using boolean logic: - // (A and B and C and ..) AND (D or E or F or ...) AND NOT(G or H or I or ..) - - // match components that have: - // all of the set {A, B, C, ..} and - // have any of the set {D, E, F, ..} but - // do not have any of the set {G, H, I, ..} - // all(A, B, C, ..).any(D, E, F, ..).no(G, H, I, ..) - - // e.g does match - // components: 010001110 - // andMask: 000001110 - // orMask: 111000000 - // norMask: 000000001 - - // e.g does match - // components: 100011110 - // andMask: 000001110 - // orMask: 111000000 - // norMask: 000000001 - - // e.g does not match - // components: 100001111 - // andMask: 000011110 - // orMask: 111000000 - // norMask: 000000001 - - // e.g does not match - // components: 000001111 - // andMask: 000011110 - // orMask: 111000000 - // norMask: 000100000 - - internal BitVector AndMask; - internal BitVector OrMask; - internal BitVector NorMask; - internal static BitVector Result; - - public Aspect(BitVector andMask, BitVector orMask, BitVector norMask) - { - if (Result == null) - Result = new BitVector(andMask.Length); - AndMask = new BitVector(andMask); - OrMask = orMask.EqualsZero() ? new BitVector(andMask.Length, true) : new BitVector(orMask); - NorMask = new BitVector(norMask); - } - - public bool Matches(BitVector componentBits) - { - AndMask.And(componentBits, ref Result); - if (!Result.Equals(AndMask)) - return false; - NorMask.And(componentBits, ref Result); - if (!Result.EqualsZero()) - return false; - OrMask.And(componentBits, ref Result); - return !Result.EqualsZero(); - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/AspectAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/AspectAttribute.cs deleted file mode 100644 index eb90bb3f..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/AspectAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace MonoGame.Extended.Entities.Legacy -{ - public enum AspectType - { - All, - None, - Any - } - - [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] - public class AspectAttribute : Attribute - { - public AspectType Type { get; } - public Type[] Components { get; } - - public AspectAttribute(AspectType type, params Type[] components) - { - Type = type; - Components = components; - } - } -} diff --git a/Source/MonoGame.Extended.Entities/Legacy/BitVector.cs b/Source/MonoGame.Extended.Entities/Legacy/BitVector.cs deleted file mode 100644 index b24d6f8f..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/BitVector.cs +++ /dev/null @@ -1,167 +0,0 @@ -/* - -Orignal code from: https://referencesource.microsoft.com/#q=BitArray -Renamed to BitVector to avoid name clash -Modified for performance; removed checks and modified bitwise operations - -https://github.com/Microsoft/referencesource/blob/master/LICENSE.txt - -The MIT License (MIT) - -Copyright (c) Microsoft Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -// ==++== -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// ==--== -/*============================================================================= -** -** Class: BitVector -** -** Microsoft -** -** -** Purpose: The BitVector class manages a compact array of bit values. -** -** -=============================================================================*/ - -using System; - -namespace MonoGame.Extended.Entities.Legacy -{ - public sealed class BitVector - { - // XPerY=n means that n Xs can be stored in 1 Y. - private const int _bitsPerInt32 = 32; - - private readonly int[] _array; - private readonly int _intLength; - - public int Length { get; } - - public BitVector(int length, bool defaultValue = false) - { - if (length < 0) - throw new ArgumentOutOfRangeException(nameof(length)); - - _array = new int[GetArrayLength(length, _bitsPerInt32)]; - Length = length; - - var fillValue = defaultValue ? unchecked((int)0xffffffff) : 0; - - for (var i = 0; i < _array.Length; i++) - _array[i] = fillValue; - - _intLength = GetArrayLength(Length, _bitsPerInt32); - } - - public BitVector(BitVector bits) - { - if (bits == null) - throw new ArgumentNullException(nameof(bits)); - - var arrayLength = GetArrayLength(bits.Length, _bitsPerInt32); - _array = new int[arrayLength]; - Length = bits.Length; - _intLength = GetArrayLength(Length, _bitsPerInt32); - - Array.Copy(bits._array, _array, arrayLength); - } - - public bool this[int index] - { - get { return (_array[index / 32] & (1 << (index % 32))) != 0; } - set - { - if (value) - _array[index / 32] |= 1 << (index % 32); - else - _array[index / 32] &= ~(1 << (index % 32)); - } - } - - public void SetAll(bool value) - { - var fillValue = value ? unchecked((int)0xffffffff) : 0; - for (var i = 0; i < _intLength; ++i) - _array[i] = fillValue; - } - - public void And(BitVector value, ref BitVector result) - { - for (var i = 0; i < _intLength; ++i) - result._array[i] = _array[i] & value._array[i]; - } - - public bool Equals(BitVector value) - { - for (var i = 0; i < _intLength; ++i) - if (_array[i] != value._array[i]) - return false; - - return true; - } - - public bool EqualsZero() - { - for (var i = 0; i < _intLength; ++i) - if (_array[i] != 0) - return false; - - return true; - } - - /// - /// Used for conversion between different representations of bit array. - /// Returns (n+(div-1))/div, rearranged to avoid arithmetic overflow. - /// For example, in the bit to int case, the straightforward calc would - /// be (n+31)/32, but that would cause overflow. So instead it's - /// rearranged to ((n-1)/32) + 1, with special casing for 0. - /// - /// Usage: - /// GetArrayLength(77, BitsPerInt32): returns how many ints must be - /// allocated to store 77 bits. - /// - /// - /// use a conversion constant, e.g. BytesPerInt32 to get - /// how many ints are required to store n bytes - /// - private static int GetArrayLength(int n, int div) - { - return n > 0 ? (n - 1) / div + 1 : 0; - } - - public override string ToString() - { - string result = null; - for (var i = 0; i < Length; ++i) - { - result += this[i] ? 1 : 0; - } - - return result; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/DefaultDependencyResolver.cs b/Source/MonoGame.Extended.Entities/Legacy/DefaultDependencyResolver.cs deleted file mode 100644 index 50ef786c..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/DefaultDependencyResolver.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace MonoGame.Extended.Entities.Legacy -{ - public class DefaultDependencyResolver : DependencyResolver - { - public DefaultDependencyResolver() - { - } - - public override object Resolve(Type type, params object[] args) - { - return Activator.CreateInstance(type, args); - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/DependencyResolver.cs b/Source/MonoGame.Extended.Entities/Legacy/DependencyResolver.cs deleted file mode 100644 index a4a3be91..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/DependencyResolver.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace MonoGame.Extended.Entities.Legacy -{ - public abstract class DependencyResolver - { - public abstract object Resolve(Type type, params object[] args); - - public T Resolve(Type type, params object[] args) - { - return (T)Resolve(type, args); - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/Entity.cs b/Source/MonoGame.Extended.Entities/Legacy/Entity.cs deleted file mode 100644 index d428e22e..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/Entity.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Entity.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Basic unity of this entity system. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; -using System.Runtime.CompilerServices; -using MonoGame.Extended.Collections; - -// ReSharper disable InconsistentNaming - -namespace MonoGame.Extended.Entities.Legacy -{ - public sealed class Entity : IPoolable - { - private static readonly uint ToBeAddedMask; - private static readonly uint ToBeRemovedMask; - private static readonly uint ToRefreshComponentsMask; - - static Entity() - { - ToBeAddedMask = BitVector32.CreateMask(); - ToBeRemovedMask = BitVector32.CreateMask(ToBeAddedMask); - ToRefreshComponentsMask = BitVector32.CreateMask(ToBeRemovedMask); - } - - private ReturnToPoolDelegate _returnToPoolDelegate; - private BitVector32 _flags; - - internal EntityManager Manager; - internal readonly BitVector SystemBits; - internal readonly BitVector ComponentBits; - - internal string _group; - internal string _name; - - public bool IsActive - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return !_flags[ToBeRemovedMask]; } - } - - public bool WaitingToBeAdded - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return _flags[ToBeAddedMask]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal set { _flags[ToBeAddedMask] = value; } - } - - public bool WaitingToBeRemoved - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return _flags[ToBeRemovedMask]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal set { _flags[ToBeRemovedMask] = value; } - } - - internal bool WaitingToRefreshComponents - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return _flags[ToRefreshComponentsMask]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set { _flags[ToRefreshComponentsMask] = value; } - } - - public string Name - { - get { return _name; } - set - { - _name = value; - Manager.AddEntityName(value, this); - } - } - - //public string Group - //{ - // get { return _group; } - // set - // { - // _group = value; - // Manager.AddEntityToGroup(value, this); - // } - //} - - IPoolable IPoolable.NextNode { get; set; } - IPoolable IPoolable.PreviousNode { get; set; } - - internal Entity(int systemTypeCount, int componentTypeCount) - { - SystemBits = new BitVector(systemTypeCount); - ComponentBits = new BitVector(componentTypeCount); - } - - public void Destroy() - { - Manager.MarkEntityToBeRemoved(this); - } - - public T Attach(T component) where T : class - { - return Manager.AddComponent(this, component); - } - - public T Attach(Action configure) where T : class - { - var component = Attach(); - configure(component); - return component; - } - - public T Attach() where T : class - { - return Manager.AddComponent(this); - } - - public void Detach() where T : class - { - Manager.MarkComponentToBeRemoved(this); - } - - public T Get() where T : class - { - return Manager.GetComponent(this); - } - - private void Reset() - { - _name = null; - _group = null; - SystemBits.SetAll(false); - ComponentBits.SetAll(false); - _flags = 0; - } - - public override string ToString() - { - return $"{RuntimeHelpers.GetHashCode(this):X8} {Name}"; - } - - void IPoolable.Initialize(ReturnToPoolDelegate returnDelegate) - { - Reset(); - _returnToPoolDelegate = returnDelegate; - } - - void IPoolable.Return() - { - Return(); - } - - internal void Return() - { - Reset(); - - if (_returnToPoolDelegate == null) - { - return; - } - - _returnToPoolDelegate.Invoke(this); - _returnToPoolDelegate = null; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentDelegate.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentDelegate.cs deleted file mode 100644 index 4df6aa41..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentDelegate.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace MonoGame.Extended.Entities.Legacy -{ - public delegate void EntityComponentDelegate(Entity entity, object component); -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPool.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPool.cs deleted file mode 100644 index fac8073a..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPool.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MonoGame.Extended.Collections; - -namespace MonoGame.Extended.Entities.Legacy -{ - internal interface IComponentPool - { - object New(); - } - - internal class ComponentPool : ObjectPool, IComponentPool where T : class, IPoolable, new() - { - public ComponentPool(int intitialSize = 16, ObjectPoolIsFullPolicy isFullPolicy = ObjectPoolIsFullPolicy.ReturnNull) - : base(CreateObject, intitialSize, isFullPolicy) - { - } - - private static T CreateObject() - { - return new T(); - } - - object IComponentPool.New() - { - return base.New(); - } - } -} diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPoolAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPoolAttribute.cs deleted file mode 100644 index 08652c7d..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPoolAttribute.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/ComponentType.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Class ArtemisComponentPool. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; -using MonoGame.Extended.Collections; - -namespace MonoGame.Extended.Entities.Legacy -{ - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class EntityComponentPoolAttribute : Attribute - { - public int InitialSize { get; set; } = 10; - public ObjectPoolIsFullPolicy IsFullPolicy { get; set; } = ObjectPoolIsFullPolicy.IncreaseSize; - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentSystem.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentSystem.cs deleted file mode 100644 index d5e9ab9c..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentSystem.cs +++ /dev/null @@ -1,252 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/EntityWorld.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// The Entity World Class. Main interface of the Entity System. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Microsoft.Xna.Framework; -using MonoGame.Extended.Animations; -using MonoGame.Extended.Sprites; - -namespace MonoGame.Extended.Entities.Legacy -{ - public sealed class EntityComponentSystem : DrawableGameComponent - { - private readonly SystemManager _systemManager; - private readonly DependencyResolver _dependencyResolver; - - public EntityManager EntityManager { get; } - - public EntityComponentSystem(Game game, DependencyResolver dependencyResolver = null) - : base(game) - { - _dependencyResolver = dependencyResolver ?? new DefaultDependencyResolver(); - _systemManager = new SystemManager(this); - EntityManager = new EntityManager(_systemManager, _dependencyResolver); - } - - public void Scan(params Assembly[] assemblies) - { - var exportedTypes = assemblies - .Concat(new [] - { - typeof(Sprite).GetTypeInfo().Assembly, - typeof(AnimatedSprite).GetTypeInfo().Assembly - }) - .SelectMany(a => a.ExportedTypes) - .Distinct() - .Select(x => x.GetTypeInfo()) - .ToArray(); - - var componentTypes = exportedTypes - .Where(t => t.IsDefined(typeof(EntityComponentAttribute))) - .ToList(); - - var systemTypes = exportedTypes - .Where(t => typeof(ProcessingSystem).GetTypeInfo().IsAssignableFrom(t)) - .ToList(); - - var templateTypes = exportedTypes - .Where(t => typeof(EntityTemplate).GetTypeInfo().IsAssignableFrom(t)) - .ToList(); - - var registeredComponentCount = RegisterComponents(componentTypes); - RegisterEntityTemplates(templateTypes); - CreateSystems(systemTypes, registeredComponentCount); - } - - private int RegisterComponents(List componentTypeInfos) - { - List registeredComponentTypeInfos; - List> registeredPooledComponentTypeInfos; - GetRegisteredComponents(componentTypeInfos, out registeredComponentTypeInfos, out registeredPooledComponentTypeInfos); - - EntityManager.CreateComponentTypesFrom(registeredComponentTypeInfos); - EntityManager.CreateComponentPoolsFrom(registeredPooledComponentTypeInfos); - return registeredComponentTypeInfos.Count; - } - - // ReSharper disable once ParameterTypeCanBeEnumerable.Local - private static void GetRegisteredComponents(List componentTypeInfos, out List registeredComponentTypeInfos, out List> pooledComponentTypeInfos) - { - registeredComponentTypeInfos = new List(); - pooledComponentTypeInfos = new List>(); - - var componentAttributeType = typeof(EntityComponentAttribute); - var componentPoolAttributeType = typeof(EntityComponentPoolAttribute); - - foreach (var typeInfo in componentTypeInfos) - { - EntityComponentAttribute componentAttribute = null; - EntityComponentPoolAttribute componentPoolAttribute = null; - - var attributes = typeInfo.GetCustomAttributes(false); - foreach (var attribute in attributes) - { - var attributeType = attribute.GetType(); - - if (attributeType == componentAttributeType) - componentAttribute = (EntityComponentAttribute)attribute; - - if (attributeType == componentPoolAttributeType) - componentPoolAttribute = (EntityComponentPoolAttribute)attribute; - } - - if (componentAttribute == null) - continue; - - registeredComponentTypeInfos.Add(typeInfo); - - if (componentPoolAttribute == null) - continue; - - pooledComponentTypeInfos.Add(new Tuple(typeInfo, componentPoolAttribute)); - } - } - - // ReSharper disable once ParameterTypeCanBeEnumerable.Local - private void RegisterEntityTemplates(List entityTempalteTypeInfos) - { - var entityTemplateAttributeType = typeof(EntityTemplateAttribute); - - foreach (var typeInfo in entityTempalteTypeInfos) - { - EntityTemplateAttribute entityTemplateAttribute = null; - - var attributes = typeInfo.GetCustomAttributes(false); - foreach (var attribute in attributes) - { - var attributeType = attribute.GetType(); - - if (attributeType == entityTemplateAttributeType) - entityTemplateAttribute = (EntityTemplateAttribute)attribute; - } - - if (entityTemplateAttribute == null) - return; - - var entityTemplate = _dependencyResolver.Resolve(typeInfo.AsType()); - entityTemplate.Manager = this; - EntityManager.AddEntityTemplate(entityTemplateAttribute.Name, entityTemplate); - } - } - - // ReSharper disable once ParameterTypeCanBeEnumerable.Local - private void CreateSystems(List systemTypeInfos, int componentCount) - { - var systemAttributeType = typeof(EntitySystemAttribute); - var aspectAttributeType = typeof(AspectAttribute); - - var andMask = new BitVector(componentCount); - var orMask = new BitVector(componentCount); - var norMask = new BitVector(componentCount); - - foreach (var typeInfo in systemTypeInfos) - { - EntitySystemAttribute systemAttribute = null; - - andMask.SetAll(false); - orMask.SetAll(false); - norMask.SetAll(false); - - var attributes = typeInfo.GetCustomAttributes(false); - foreach (var attribute in attributes) - { - var attributeType = attribute.GetType(); - - if (attributeType == systemAttributeType) - systemAttribute = (EntitySystemAttribute)attribute; - - if(attributeType != aspectAttributeType) - continue; - - var aspectAttribute = (AspectAttribute)attribute; - switch (aspectAttribute.Type) - { - case AspectType.All: - EntityManager.FillComponentBits(andMask, aspectAttribute.Components); - break; - case AspectType.Any: - EntityManager.FillComponentBits(orMask, aspectAttribute.Components); - break; - case AspectType.None: - EntityManager.FillComponentBits(norMask, aspectAttribute.Components); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - } - - if (systemAttribute == null) - return; - - var processingSystem = _dependencyResolver.Resolve(typeInfo.AsType()); - - if (processingSystem is EntityProcessingSystem entityProcessingSystem) - entityProcessingSystem.Aspect = new Aspect(andMask, orMask, norMask); - - _systemManager.AddSystem(processingSystem, systemAttribute.GameLoopType, systemAttribute.Layer, SystemExecutionType.Synchronous); - } - } - - public override void Initialize() - { - base.Initialize(); - - _systemManager.InitializeIfNecessary(); - } - - protected override void UnloadContent() - { - base.UnloadContent(); - - foreach (var system in _systemManager.Systems) - system.UnloadContent(); - } - - public override void Update(GameTime gameTime) - { - _systemManager.InitializeIfNecessary(); - - EntityManager.RemoveMarkedComponents(); - EntityManager.ProcessMarkedEntitiesWith(_systemManager.ProcessingSystems); - - _systemManager.Update(gameTime); - } - - public override void Draw(GameTime gameTime) - { - _systemManager.Draw(gameTime); - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentType.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentType.cs deleted file mode 100644 index 0c7181db..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityComponentType.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/ComponentType.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Represents a Component Type. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; -using System.Diagnostics; - -namespace MonoGame.Extended.Entities.Legacy -{ - [DebuggerDisplay("Index:{" + nameof(Index) + "}")] - public sealed class EntityComponentType - { - private static int _nextIndex; - - public int Index { get; } - public Type Type { get; } - - internal EntityComponentType(Type type) - { - Index = _nextIndex++; - Type = type; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityDelegate.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityDelegate.cs deleted file mode 100644 index ec270b54..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityDelegate.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace MonoGame.Extended.Entities.Legacy -{ - public delegate void EntityDelegate(Entity entity); -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityManager.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityManager.cs deleted file mode 100644 index b9dff309..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityManager.cs +++ /dev/null @@ -1,498 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Manager/EntityManager.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright � 2013 GAMADU.COM. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// The Entity Manager. -// -// ----------------- - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using MonoGame.Extended.Collections; - -namespace MonoGame.Extended.Entities.Legacy -{ - public class EntityManager - { - private readonly DependencyResolver _dependencyResolver; - private readonly SystemManager _systemManager; - private readonly ObjectPool _pool; - private readonly Dictionary _entitiesByName; - private readonly Dictionary _entityTemplatesByName; - private readonly Dictionary> _entitiesByGroup; - private readonly List _markedEntities; - - private readonly Dictionary _componentPoolsByComponentTypeIndex; - private readonly Bag> _entitiesToComponentsBag; - private readonly List _componentsToRemove; - - private readonly Dictionary _componentTypes = new Dictionary(); - - public int TotalEntitiesCount => _pool.TotalCount; - public int ActiveEntitiesCount => _pool.InUseCount; - - public event EntityDelegate EntityCreated; - public event EntityDelegate EntityAdded; - public event EntityDelegate EntityRemoved; - public event EntityDelegate EntityDestroyed; - - internal EntityManager(SystemManager systemManager, DependencyResolver dependencyResolver) - { - _dependencyResolver = dependencyResolver; - _systemManager = systemManager; - - _pool = new ObjectPool(CreateEntityObject, 100, ObjectPoolIsFullPolicy.IncreaseSize); - _pool.ItemUsed += OnEntityCreated; - _pool.ItemReturned += OnEntityDestroyed; - - _entitiesByName = new Dictionary(); - _entityTemplatesByName = new Dictionary(); - _entitiesByGroup = new Dictionary>(); - - _markedEntities = new List(); - - _componentPoolsByComponentTypeIndex = new Dictionary(); - _entitiesToComponentsBag = new Bag>(); - _componentsToRemove = new List(); - } - - private Entity CreateEntityObject() - { - return new Entity(_systemManager.ProcessingSystems.Count, _componentTypes.Count); - } - - public Entity CreateEntity(string name = null) - { - var entity = _pool.New(); - entity.Name = name; - MarkEntityToBeAdded(entity); - return entity; - } - - public Entity CreateEntityFromTemplate(string name) - { - if (string.IsNullOrEmpty(name)) - throw new ArgumentNullException(nameof(name)); - - var entity = _pool.New(); - MarkEntityToBeAdded(entity); - - EntityTemplate entityTemplate; - _entityTemplatesByName.TryGetValue(name, out entityTemplate); - - if (entityTemplate == null) - throw new InvalidOperationException($"EntityTemplate '{name}' is not registered."); - - entityTemplate.Build(entity); - return entity; - } - - internal void AddEntityTemplate(string name, EntityTemplate template) - { - Debug.Assert(!string.IsNullOrEmpty(name)); - Debug.Assert(template != null); - Debug.Assert(!_entityTemplatesByName.ContainsKey(name)); - - _entityTemplatesByName.Add(name, template); - } - - public Entity GetEntityByName(string name) - { - if (string.IsNullOrEmpty(name)) - return null; - - Entity entity; - _entitiesByName.TryGetValue(name, out entity); - if (entity != null) - return entity; - RemoveEntityName(name); - return null; - } - - internal void AddEntityName(string name, Entity entity) - { - Debug.Assert(entity != null); - - if (string.IsNullOrEmpty(name)) - return; - if (!string.IsNullOrEmpty(entity._name)) - RemoveEntityName(entity._name); - _entitiesByName.Add(name, entity); - } - - internal void RemoveEntityName(string name) - { - _entitiesByName.Remove(name); - } - - public Bag GetEntitiesByGroup(string groupName) - { - if (string.IsNullOrEmpty(groupName)) - return null; - - Bag bag; - _entitiesByGroup.TryGetValue(groupName, out bag); - return bag; - } - - //internal void AddEntityToGroup(string group, Entity entity) - //{ - // Debug.Assert(entity != null); - - // if (string.IsNullOrEmpty(group)) - // return; - - // RemoveEntityFromGroup(entity); - - // entity._group = group; - - // Bag entities; - - // if (!_entitiesByGroup.TryGetValue(group, out entities)) - // { - // entities = new Bag(); - // _entitiesByGroup.Add(group, entities); - // } - - // entities.Add(entity); - //} - - //internal void RemoveEntityFromGroup(Entity entity) - //{ - // Bag entities; - - // if (_entitiesByGroup.TryGetValue(entity._group, out entities)) - // entities.Remove(entity); - //} - - internal void DestroyEntity(Entity entity) - { - Debug.Assert(entity != null); - - //RemoveEntityFromGroup(entity); - RemoveComponents(entity); - entity.Return(); - } - - internal void MarkEntityToBeAdded(Entity entity) - { - Debug.Assert(entity != null); - - entity.WaitingToBeAdded = true; - if (entity.WaitingToRefreshComponents) - return; - entity.WaitingToRefreshComponents = true; - _markedEntities.Add(entity); - } - - internal void MarkEntityToBeRefreshed(Entity entity) - { - Debug.Assert(entity != null); - - if (entity.WaitingToRefreshComponents) - return; - entity.WaitingToRefreshComponents = true; - _markedEntities.Add(entity); - } - - internal void MarkEntityToBeRemoved(Entity entity) - { - Debug.Assert(entity != null); - - entity.WaitingToBeRemoved = true; - - if (entity.WaitingToRefreshComponents) - return; - - entity.WaitingToRefreshComponents = true; - _markedEntities.Add(entity); - OnEntityRemoved(entity); - } - - internal void ProcessMarkedEntitiesWith(List processingSystems) - { - Debug.Assert(processingSystems != null); - - foreach (var entity in _markedEntities) - { - foreach (var system in processingSystems) - system.RefreshEntityComponents(entity); - - if (entity.WaitingToBeAdded) - { - entity.WaitingToBeAdded = false; - OnEntityAdded(entity); - } - - if (entity.WaitingToBeRemoved) - { - entity.WaitingToBeRemoved = false; - DestroyEntity(entity); - } - - entity.WaitingToRefreshComponents = false; - } - - _markedEntities.Clear(); - } - - private void OnEntityCreated(Entity entity) - { - entity.Manager = this; - EntityCreated?.Invoke(entity); - } - - private void OnEntityDestroyed(Entity entity) - { - EntityDestroyed?.Invoke(entity); - } - - private void OnEntityAdded(Entity entity) - { - EntityAdded?.Invoke(entity); - } - - private void OnEntityRemoved(Entity entity) - { - EntityRemoved?.Invoke(entity); - } - - internal T AddComponent(Entity entity, T component) where T : class - { - Debug.Assert(entity != null); - var type = typeof(T); - EntityComponentType entityComponentType; - - if (!_componentTypes.TryGetValue(type, out entityComponentType)) - _componentTypes[type] = entityComponentType = new EntityComponentType(type); - - return (T) AddComponent(entity, entityComponentType, component); - } - - internal T AddComponent(Entity entity) where T : class - { - Debug.Assert(entity != null); - - var componentType = GetComponentTypeFrom(typeof(T)); - return (T) AddComponent(entity, componentType, null); - } - - internal object AddComponent(Entity entity, EntityComponentType componentType, object component = null) - { - Debug.Assert(entity != null); - Debug.Assert(componentType != null); - - if (componentType.Index >= _entitiesToComponentsBag.Capacity) - _entitiesToComponentsBag[componentType.Index] = null; - - var componentsByEntity = _entitiesToComponentsBag[componentType.Index]; - - if (componentsByEntity == null) - _entitiesToComponentsBag[componentType.Index] = componentsByEntity = new Dictionary(); - - if (component == null) - { - IComponentPool componentPool; - - if (_componentPoolsByComponentTypeIndex.TryGetValue(componentType.Index, out componentPool)) - { - component = componentPool.New(); - - if (component == null) - return null; - } - else - { - component = _dependencyResolver.Resolve(componentType.Type); - } - } - - componentsByEntity[entity] = component; - entity.ComponentBits[componentType.Index] = true; - MarkEntityToBeRefreshed(entity); - return component; - } - - internal T GetComponent(Entity entity) where T : class - { - Debug.Assert(entity != null); - - var componentType = GetComponentTypeFrom(typeof(T)); - return (T)GetComponent(entity, componentType); - } - - internal object GetComponent(Entity entity, EntityComponentType componentType) - { - Debug.Assert(entity != null); - Debug.Assert(componentType != null); - Debug.Assert(componentType.Index < _entitiesToComponentsBag.Count); - - var components = _entitiesToComponentsBag[componentType.Index]; - - if (components == null) - return null; - - object component; - components.TryGetValue(entity, out component); - return component; - } - - internal void MarkComponentToBeRemoved(Entity entity) where T : class - { - Debug.Assert(entity != null); - - MarkComponentToBeRemoved(entity, GetComponentTypeFrom(typeof(T))); - } - - internal void MarkComponentToBeRemoved(Entity entity, EntityComponentType componentType) - { - Debug.Assert(entity != null); - Debug.Assert(componentType != null); - - var pair = new EntityComponentTypePair(entity, componentType); - if (!_componentsToRemove.Contains(pair)) - _componentsToRemove.Add(pair); - } - - internal void RemoveMarkedComponents() - { - for (var i = _componentsToRemove.Count - 1; i >= 0; --i) - { - var pair = _componentsToRemove[i]; - var entity = pair.Entity; - var componentType = pair.ComponentType; - var components = _entitiesToComponentsBag[componentType.Index]; - - Debug.Assert(components != null); - - object component; - if (!components.TryGetValue(entity, out component)) - continue; - - entity.ComponentBits[componentType.Index] = false; - MarkEntityToBeRefreshed(entity); - - components.Remove(entity); - (component as IPoolable)?.Return(); - (component as IDisposable)?.Dispose(); - } - - _componentsToRemove.Clear(); - } - - internal void RemoveComponents(Entity entity) - { - Debug.Assert(entity != null); - - MarkEntityToBeRefreshed(entity); - - for (var i = _entitiesToComponentsBag.Count - 1; i >= 0; --i) - { - var components = _entitiesToComponentsBag[i]; - - object component; - - if (components == null || !components.TryGetValue(entity, out component)) - continue; - - components.Remove(entity); - (component as IPoolable)?.Return(); - (component as IDisposable)?.Dispose(); - } - } - - internal void CreateComponentTypesFrom(List componentTypeInfos) - { - foreach (var componentTypeInfo in componentTypeInfos) - { - var type = componentTypeInfo.AsType(); - var componentType = new EntityComponentType(type); - _componentTypes.Add(type, componentType); - } - } - - internal EntityComponentType GetComponentTypeFrom(Type type) - { - EntityComponentType result; - - if (!_componentTypes.TryGetValue(type, out result)) - throw new InvalidOperationException($"{type.Name} is not marked with the EntityComponent attribute"); - - return result; - } - - internal void FillComponentBits(BitVector bits, Type[] types) - { - foreach (var type in types) - { - var componentType = GetComponentTypeFrom(type); - bits[componentType.Index] = true; - } - } - - internal void CreateComponentPoolsFrom(List> componentTypeInfos) - { - foreach (var tuple in componentTypeInfos) - { - var type = tuple.Item1.AsType(); - var attribute = tuple.Item2; - var componentType = GetComponentTypeFrom(type); - CreateComponentPool(componentType, attribute.InitialSize, attribute.IsFullPolicy); - } - } - - private void CreateComponentPool(EntityComponentType componentType, int initialSize, ObjectPoolIsFullPolicy isFullPolicy) - { - Debug.Assert(componentType != null); - Debug.Assert(initialSize > 0); - Debug.Assert(!_componentPoolsByComponentTypeIndex.ContainsKey(componentType.Index)); - - var poolType = typeof(ComponentPool<>).MakeGenericType(componentType.Type); - var componentPool = (IComponentPool)_dependencyResolver.Resolve(poolType, initialSize, isFullPolicy); - - _componentPoolsByComponentTypeIndex.Add(componentType.Index, componentPool); - } - - internal struct EntityComponentTypePair - { - public Entity Entity; - public EntityComponentType ComponentType; - - public EntityComponentTypePair(Entity entity, EntityComponentType componentType) - { - Entity = entity; - ComponentType = componentType; - } - } - } -} diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityProcessingSystem.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityProcessingSystem.cs deleted file mode 100644 index e47740ff..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityProcessingSystem.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Original code derived from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/System/EntityProcessingSystem.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Class EntityProcessingSystem. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System.Collections.Generic; -using Microsoft.Xna.Framework; - -namespace MonoGame.Extended.Entities.Legacy -{ - public abstract class EntityProcessingSystem : ProcessingSystem - { - protected EntityProcessingSystem() - { - } - - private readonly Dictionary _activeEntitiesLookup = new Dictionary(); - - internal int Index; - internal Aspect Aspect; - - private readonly List _activeEntities = new List(); - public IReadOnlyCollection ActiveEntities => _activeEntities; - - internal virtual void RefreshEntityComponents(Entity entity) - { - var contains = entity.SystemBits[Index]; - var isInterested = Aspect.Matches(entity.ComponentBits); - - if (contains) - Remove(entity); - else if (isInterested) - Add(entity); - } - - public virtual void OnEntityAdded(Entity entity) { } - public virtual void OnEntityDisabled(Entity entity) { } - public virtual void OnEntityEnabled(Entity entity) { } - public virtual void OnEntityRemoved(Entity entity) { } - - protected override void Process(GameTime gameTime) - { - base.Process(gameTime); - - for (var i = _activeEntities.Count - 1; i >= 0; i--) - { - var entity = _activeEntities[i]; - Process(gameTime, entity); - } - } - - protected abstract void Process(GameTime gameTime, Entity entity); - - protected bool IsInterestedIn(Entity entity) - { - return Aspect.Matches(entity.ComponentBits); - } - - internal void Add(Entity entity) - { - if (entity == null) - return; - - entity.SystemBits[Index] = true; - - if (_activeEntitiesLookup.ContainsKey(entity)) - return; - - _activeEntitiesLookup.Add(entity, _activeEntities.Count); - _activeEntities.Add(entity); - - OnEntityAdded(entity); - } - - internal void Remove(Entity entity) - { - if (entity == null) - return; - - entity.SystemBits[Index] = false; - - int activeEntityIndex; - if (!_activeEntitiesLookup.TryGetValue(entity, out activeEntityIndex)) - return; - _activeEntitiesLookup.Remove(entity); - - var swapEntity = _activeEntities[_activeEntities.Count - 1]; - - if (entity != swapEntity) - _activeEntitiesLookup[swapEntity] = activeEntityIndex; - - _activeEntities[activeEntityIndex] = swapEntity; - _activeEntities.RemoveAt(_activeEntities.Count - 1); - - OnEntityRemoved(entity); - } - } -} diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntitySystemAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/EntitySystemAttribute.cs deleted file mode 100644 index f5892738..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntitySystemAttribute.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Attributes/EntitySystem.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Class ArtemisEntitySystem. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; - -namespace MonoGame.Extended.Entities.Legacy -{ - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class EntitySystemAttribute : Attribute - { - public GameLoopType GameLoopType { get; } - public int Layer { get; set; } - - public EntitySystemAttribute(GameLoopType gameLoopType) - { - GameLoopType = gameLoopType; - Layer = 0; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityTemplate.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityTemplate.cs deleted file mode 100644 index 1660e95c..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityTemplate.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Interface/IEntityTemplate.cs.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Interface IEntityTemplate. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace MonoGame.Extended.Entities.Legacy -{ - public abstract class EntityTemplate - { - protected internal EntityComponentSystem Manager { get; internal set; } - - protected internal virtual void Initialize() - { - } - - protected internal abstract void Build(Entity entity); - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/EntityTemplateAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityTemplateAttribute.cs deleted file mode 100644 index e2c4f052..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/EntityTemplateAttribute.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Attributes/ArtemisComponentPool.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Class ArtemisEntityTemplate. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; - -namespace MonoGame.Extended.Entities.Legacy -{ - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public sealed class EntityTemplateAttribute : Attribute - { - public string Name { get; } - - public EntityTemplateAttribute(string name) - { - if (string.IsNullOrEmpty(name)) - throw new ArgumentNullException(nameof(name)); - - Name = name; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/PoolableComponent.cs b/Source/MonoGame.Extended.Entities/Legacy/PoolableComponent.cs deleted file mode 100644 index cf68579d..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/PoolableComponent.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/ComponentPoolable.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Class ComponentPool-able. -// -// -------------------------------------------------------------------------------------------------------------------- - -using MonoGame.Extended.Collections; - -namespace MonoGame.Extended.Entities.Legacy -{ - public abstract class PoolableComponent : IPoolable - { - private ReturnToPoolDelegate _returnToPool; - IPoolable IPoolable.NextNode { get; set; } - IPoolable IPoolable.PreviousNode { get; set; } - - protected PoolableComponent() - { - } - - public virtual void Reset() - { - } - - void IPoolable.Initialize(ReturnToPoolDelegate returnDelegate) - { - _returnToPool = returnDelegate; - Reset(); - } - - void IPoolable.Return() - { - Return(); - } - - internal void Return() - { - Reset(); - - if (_returnToPool == null) - return; - - _returnToPool.Invoke(this); - _returnToPool = null; - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/ProcessingSystem.cs b/Source/MonoGame.Extended.Entities/Legacy/ProcessingSystem.cs deleted file mode 100644 index 3e0061af..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/ProcessingSystem.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/System/EntitySystem.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. Contains rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Base of all Entity Systems. Provide basic functionalities. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; - -namespace MonoGame.Extended.Entities.Legacy -{ - public abstract class ProcessingSystem - { - private TimeSpan _timer; - - internal EntityComponentSystem EntityComponentSystem; - public bool IsEnabled { get; set; } - public Game Game => EntityComponentSystem.Game; - public GraphicsDevice GraphicsDevice => EntityComponentSystem.GraphicsDevice; - public EntityManager EntityManager => EntityComponentSystem.EntityManager; - - public TimeSpan ProcessingDelay { get; set; } - - protected ProcessingSystem() - { - IsEnabled = true; - _timer = TimeSpan.Zero; - } - - public virtual void Initialize() - { - } - - public virtual void LoadContent() - { - } - - public virtual void UnloadContent() - { - } - - internal void ProcessInternal(GameTime gameTime) - { - if (!CheckProcessing(gameTime)) - return; - Begin(gameTime); - Process(gameTime); - End(gameTime); - } - - public void Toggle() - { - IsEnabled = !IsEnabled; - } - - protected virtual void Begin(GameTime gameTime) - { - } - - protected virtual bool CheckProcessing(GameTime gameTime) - { - // ReSharper disable once InvertIf - if (ProcessingDelay != TimeSpan.Zero) - { - _timer += gameTime.ElapsedGameTime; - if (_timer <= ProcessingDelay) - return false; - _timer -= ProcessingDelay; - } - return IsEnabled; - } - - protected virtual void Process(GameTime gameTime) - { - } - - protected virtual void End(GameTime gameTime) - { - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Legacy/SystemManager.cs b/Source/MonoGame.Extended.Entities/Legacy/SystemManager.cs deleted file mode 100644 index b53f4bda..00000000 --- a/Source/MonoGame.Extended.Entities/Legacy/SystemManager.cs +++ /dev/null @@ -1,227 +0,0 @@ -// Original code dervied from: -// https://github.com/thelinuxlich/artemis_CSharp/blob/master/Artemis_XNA_INDEPENDENT/Manager/SystemManager.cs - -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright © 2013 GAMADU.COM. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY GAMADU.COM 'AS IS' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GAMADU.COM OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of GAMADU.COM. -// -// -// Class SystemManager. -// -// -------------------------------------------------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Microsoft.Xna.Framework; -using MonoGame.Extended.Collections; - -namespace MonoGame.Extended.Entities.Legacy -{ - public enum GameLoopType - { - Update, - Draw - } - - public enum SystemExecutionType - { - Synchronous, - //Asynchronous, - } - - internal sealed class SystemManager - { - private readonly EntityComponentSystem _manager; - private SystemLayer[] _updateLayers; - private SystemLayer[] _drawLayers; - private readonly SystemLayer _dummyLayer; - private bool _hasInitialized; - - internal List Systems; - internal List ProcessingSystems; - - internal SystemManager(EntityComponentSystem manager) - { - _manager = manager; - _updateLayers = new SystemLayer[0]; - _drawLayers = new SystemLayer[0]; - _dummyLayer = new SystemLayer(); - Systems = new List(); - ProcessingSystems = new List(); - } - - internal void InitializeIfNecessary() - { - if (_hasInitialized) - return; - - _hasInitialized = true; - - foreach (var system in Systems) - { - system.Initialize(); - system.LoadContent(); - } - } - - internal void Update(GameTime gameTime) - { - ProcessLayers(gameTime, _updateLayers); - } - - internal void Draw(GameTime gameTime) - { - ProcessLayers(gameTime, _drawLayers); - } - - // ReSharper disable once SuggestBaseTypeForParameter - private static void ProcessLayers(GameTime gameTime, SystemLayer[] layers) - { - Debug.Assert(layers != null); - - // ReSharper disable once ForCanBeConvertedToForeach - for (var i = 0; i < layers.Length; ++i) - { - var system = layers[i]; - if (system.SynchronousSystems.Count > 0) - ProcessSystemsSynchronous(gameTime, system.SynchronousSystems); - //if (system.AsynchronousSystems.TotalCount > 0) - // ProcessSystemsAsynchronous(gameTime, system.AsynchronousSystems); - } - } - - private static void ProcessSystemsSynchronous(GameTime gameTime, Bag systems) - { - Debug.Assert(systems != null); - - for (int index = 0, j = systems.Count; index < j; ++index) - systems[index].ProcessInternal(gameTime); - } - - //// ReSharper disable once ParameterTypeCanBeEnumerable.Local - //private static void ProcessSystemsAsynchronous(Bag systems) - //{ - // // block - // // does not garantee async... - // Parallel.ForEach(systems, system => system.ProcessInternal()); - //} - - internal T AddSystem(T system, GameLoopType gameLoopType, int layer, SystemExecutionType executionType) where T : ProcessingSystem - { - Debug.Assert(system != null); - - return (T)AddSystem(system.GetType(), system, gameLoopType, layer, executionType); - } - - private ProcessingSystem AddSystem(Type systemType, ProcessingSystem system, GameLoopType gameLoopType, int layer, SystemExecutionType executionType) - { - Debug.Assert(systemType != null); - Debug.Assert(system != null); - - if (Systems.Contains(system)) - throw new InvalidOperationException($"System '{systemType}' has already been added."); - - system.EntityComponentSystem = _manager; - - Systems.Add(system); - - if (system is EntityProcessingSystem processingSystem) - { - processingSystem.Index = ProcessingSystems.Count; - ProcessingSystems.Add(processingSystem); - } - - switch (gameLoopType) - { - case GameLoopType.Draw: - AddSystemTo(ref _drawLayers, system, layer, executionType); - break; - case GameLoopType.Update: - AddSystemTo(ref _updateLayers, system, layer, executionType); - break; - default: - throw new ArgumentOutOfRangeException(nameof(gameLoopType), gameLoopType, null); - } - - return system; - } - - private void AddSystemTo(ref SystemLayer[] layers, ProcessingSystem system, int layerIndex, SystemExecutionType executionType) - { - Debug.Assert(layers != null); - - _dummyLayer.LayerIndex = layerIndex; - var index = Array.BinarySearch(layers, _dummyLayer); - SystemLayer layer; - if (index >= 0) - { - layer = layers[index]; - } - else - { - layer = new SystemLayer(layerIndex); - Array.Resize(ref layers, layers.Length + 1); - layers[layers.Length - 1] = layer; - Array.Sort(layers); - } - - switch (executionType) - { - case SystemExecutionType.Synchronous: - layer.SynchronousSystems.Add(system); - break; - //case SystemExecutionType.Asynchronous: - // layer.AsynchronousSystems.Attach(system); - // break; - default: - throw new ArgumentOutOfRangeException(nameof(executionType), executionType, null); - } - } - - private sealed class SystemLayer : IComparable - { - public int LayerIndex; - - public readonly Bag SynchronousSystems; - //public readonly Bag AsynchronousSystems; - - public SystemLayer(int layerIndex = 0) - { - LayerIndex = layerIndex; - //AsynchronousSystems = new Bag(); - SynchronousSystems = new Bag(); - } - - public int CompareTo(SystemLayer other) - { - // ReSharper disable once ImpureMethodCallOnReadonlyValueField - return LayerIndex.CompareTo(other.LayerIndex); - } - } - } -} diff --git a/Source/MonoGame.Extended.Entities/Systems/EntityProcessingSystem.cs b/Source/MonoGame.Extended.Entities/Systems/EntityProcessingSystem.cs index 716648dc..39f0b8ca 100644 --- a/Source/MonoGame.Extended.Entities/Systems/EntityProcessingSystem.cs +++ b/Source/MonoGame.Extended.Entities/Systems/EntityProcessingSystem.cs @@ -14,13 +14,13 @@ namespace MonoGame.Extended.Entities.Systems Begin(); foreach (var entityId in ActiveEntities) - Process(entityId); + Process(gameTime, entityId); End(); } public virtual void Begin() { } - public abstract void Process(int entityId); + public abstract void Process(GameTime gameTime, int entityId); public virtual void End() { } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs b/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs index d42c8acd..9b5c4ede 100644 --- a/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs +++ b/Source/MonoGame.Extended.Entities/Systems/EntityUpdateSystem.cs @@ -20,9 +20,16 @@ namespace MonoGame.Extended.Entities.Systems { _world = value; _subscription = new EntitySubscription(_world.EntityManager, _aspectBuilder.Build(_world.ComponentManager)); + + // TODO: Undisposed events. + _world.EntityManager.EntityAdded += (sender, entityId) => OnEntityAdded(entityId); + _world.EntityManager.EntityRemoved += (sender, entityId) => OnEntityRemoved(entityId); } } + protected virtual void OnEntityAdded(int entityId) { } + protected virtual void OnEntityRemoved(int entityId) { } + public Bag ActiveEntities => _subscription.ActiveEntities; public abstract void Initialize(IComponentMapperService mapperService); diff --git a/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs b/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs index 5fa8ac8d..cf47cad1 100644 --- a/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs +++ b/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs @@ -1,13 +1,16 @@ -using Microsoft.Xna.Framework; +using System; +using Microsoft.Xna.Framework; namespace MonoGame.Extended.Entities.Systems { - public abstract class UpdateSystem + public abstract class UpdateSystem : IDisposable { protected UpdateSystem() { } + public virtual void Dispose() { } + public abstract void Update(GameTime gameTime); } } \ No newline at end of file diff --git a/Source/MonoGame.Extended/Collections/Bag.cs b/Source/MonoGame.Extended/Collections/Bag.cs index b8473782..e2884486 100644 --- a/Source/MonoGame.Extended/Collections/Bag.cs +++ b/Source/MonoGame.Extended/Collections/Bag.cs @@ -82,6 +82,9 @@ namespace MonoGame.Extended.Collections public void Clear() { + if(Count == 0) + return; + Count = 0; // non-primitive types are cleared so the garbage collector can release them @@ -100,7 +103,7 @@ namespace MonoGame.Extended.Collections return false; } - public T Remove(int index) + public T RemoveAt(int index) { var result = _items[index]; --Count; diff --git a/Source/MonoGame.Extended/SimpleDrawableGameComponent.cs b/Source/MonoGame.Extended/SimpleDrawableGameComponent.cs index 4425e5d0..5487c641 100644 --- a/Source/MonoGame.Extended/SimpleDrawableGameComponent.cs +++ b/Source/MonoGame.Extended/SimpleDrawableGameComponent.cs @@ -12,7 +12,7 @@ namespace MonoGame.Extended private bool _isVisible = true; public bool Visible { - get { return _isVisible; } + get => _isVisible; set { if (_isVisible == value) @@ -28,7 +28,7 @@ namespace MonoGame.Extended private int _drawOrder; public int DrawOrder { - get { return _drawOrder; } + get => _drawOrder; set { if (_drawOrder == value) diff --git a/Source/MonoGame.Extended/SimpleGameComponent.cs b/Source/MonoGame.Extended/SimpleGameComponent.cs index 36115111..57cccfcd 100644 --- a/Source/MonoGame.Extended/SimpleGameComponent.cs +++ b/Source/MonoGame.Extended/SimpleGameComponent.cs @@ -11,7 +11,7 @@ namespace MonoGame.Extended { } - public void Dispose() + public virtual void Dispose() { if (_isInitialized) { @@ -23,7 +23,7 @@ namespace MonoGame.Extended private bool _isEnabled = true; public bool IsEnabled { - get { return _isEnabled; } + get => _isEnabled; set { if (_isEnabled == value) @@ -51,7 +51,7 @@ namespace MonoGame.Extended private int _updateOrder; public int UpdateOrder { - get { return _updateOrder; } + get => _updateOrder; set { if (_updateOrder == value) diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentManagerTests.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentManagerTests.cs index 0802dfd0..4fa712b0 100644 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentManagerTests.cs +++ b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentManagerTests.cs @@ -1,4 +1,5 @@ -using MonoGame.Extended.Sprites; +using System.Collections; +using MonoGame.Extended.Sprites; using Xunit; namespace MonoGame.Extended.Entities.Tests @@ -28,5 +29,20 @@ namespace MonoGame.Extended.Entities.Tests Assert.Equal(1, componentManager.GetComponentTypeId(typeof(Sprite))); Assert.Equal(0, componentManager.GetComponentTypeId(typeof(Transform2))); } + + [Fact] + public void GetCompositionIdentity() + { + var compositionBits = new BitArray(3) + { + [0] = true, + [1] = false, + [2] = true + }; + var componentManager = new ComponentManager(); + var identity = componentManager.GetCompositionIdentity(compositionBits); + + Assert.Equal(0b101, identity); + } } } \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/EntityTemplateTests.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/EntityTemplateTests.cs deleted file mode 100644 index 617e0a06..00000000 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/EntityTemplateTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -using MonoGame.Extended.Entities.Legacy; -using MonoGame.Extended.Gui.Tests.Implementation; -using Xunit; - -namespace MonoGame.Extended.Entities.Tests -{ - public class EntityTemplateTests - { - [Fact] - public void ECS_CreateEntityFromTemplate_Basic_Test() - { - // Seems to work with null. - var ecs = new EntityComponentSystem(null); - ecs.Scan(typeof(EntityTemplateBasic).Assembly); - var manager = ecs.EntityManager; - var entity = manager.CreateEntityFromTemplate(EntityTemplateBasic.Name); - - Assert.NotNull(entity); - Assert.NotNull(entity.Get()); - } - - [Fact] - public void ECS_CreateEntityFromTemplate_UsingManager_Test() - { - // Seems to work with null. - var ecs = new EntityComponentSystem(null); - ecs.Scan(typeof(EntityTemplateUsingManager).Assembly); - var manager = ecs.EntityManager; - var entity = manager.CreateEntityFromTemplate(EntityTemplateUsingManager.Name); - - Assert.NotNull(entity); - Assert.NotNull(entity.Get()); - } - } -} \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityComponentBasic.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityComponentBasic.cs deleted file mode 100644 index 49053c83..00000000 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityComponentBasic.cs +++ /dev/null @@ -1,10 +0,0 @@ -using MonoGame.Extended.Entities; - -namespace MonoGame.Extended.Gui.Tests.Implementation -{ - [EntityComponent] - public class EntityComponentBasic - { - public int Number { get; set; } - } -} \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityTemplateBasic.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityTemplateBasic.cs deleted file mode 100644 index 3f96a7fd..00000000 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityTemplateBasic.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MonoGame.Extended.Entities.Legacy; - -namespace MonoGame.Extended.Gui.Tests.Implementation -{ - [EntityTemplate(Name)] - public class EntityTemplateBasic : EntityTemplate - { - public const string Name = nameof(EntityTemplateBasic); - - protected override void Build(Entity entity) - { - entity.Attach(); - } - } -} \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityTemplateUsingManager.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityTemplateUsingManager.cs deleted file mode 100644 index b1f5ee06..00000000 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/EntityTemplateUsingManager.cs +++ /dev/null @@ -1,16 +0,0 @@ -using MonoGame.Extended.Entities.Legacy; - -namespace MonoGame.Extended.Gui.Tests.Implementation -{ - [EntityTemplate(Name)] - public class EntityTemplateUsingManager : EntityTemplate - { - public const string Name = nameof(EntityTemplateUsingManager); - - protected override void Build(Entity entity) - { - var num = Manager.EntityManager.TotalEntitiesCount; - entity.Attach(c => c.Number = num); - } - } -} \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/README.md b/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/README.md deleted file mode 100644 index d5356ff1..00000000 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/Implementation/README.md +++ /dev/null @@ -1,5 +0,0 @@ - -# Implementation - -This folder is for making a testable implementation using the ECS library. -This implementation is used in the unit tests in this project. \ No newline at end of file