using System.Collections.Generic; using System.Linq; namespace MonoGame.Extended.Collisions.QuadTree; public class QuadTreeSpace: ISpaceAlgorithm { private readonly QuadTree _collisionTree; private readonly List _actors = new(); private readonly Dictionary _targetDataDictionary = new(); public QuadTreeSpace(RectangleF boundary) { _collisionTree = new QuadTree(boundary); } /// /// Inserts the target into the collision tree. /// The target will have its OnCollision called when collisions occur. /// /// Target to insert. public void Insert(ICollisionActor target) { if (!_targetDataDictionary.ContainsKey(target)) { var data = new QuadtreeData(target); _targetDataDictionary.Add(target, data); _collisionTree.Insert(data); _actors.Add(target); } } /// /// Removes the target from the collision tree. /// /// Target to remove. public bool Remove(ICollisionActor target) { if (_targetDataDictionary.ContainsKey(target)) { var data = _targetDataDictionary[target]; data.RemoveFromAllParents(); _targetDataDictionary.Remove(target); _collisionTree.Shake(); _actors.Remove(target); return true; } return false; } /// /// Restructure a inner collection, if layer is dynamic, because actors can change own position /// public void Reset() { _collisionTree.ClearAll(); foreach (var value in _targetDataDictionary.Values) { _collisionTree.Insert(value); } _collisionTree.Shake(); } /// /// foreach support /// /// public List.Enumerator GetEnumerator() => _actors.GetEnumerator(); /// public IEnumerable Query(RectangleF boundsBoundingRectangle) { return _collisionTree.Query(ref boundsBoundingRectangle).Select(x => x.Target); } }