using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Cirno.Scripts.Resources; using Cirno.Scripts.Weapons; using Godot; using Godot.Collections; namespace Cirno.Scripts.Controllers; public partial class PoolingManager : Node { public static PoolingManager Instance { get; private set; } [Export] public Array PoolOnStart { get; private set; } [Export] public bool DebugView { get; private set; } = false; private readonly System.Collections.Generic.Dictionary> _activeBullets = new(); private readonly System.Collections.Generic.Dictionary> _inactiveBullets = new(); public override void _Ready() { Instance = this; } public IBullet SpawnBullet(BulletResource bulletResource, bool active = true) { // Look for bullet among the inactive ones // If present move it to active, set it as active and return it // Otherwise spawn it and add it to active and return it var activeBullets = GetActiveBulletsList(bulletResource); var inactiveBullets = GetInactiveBulletsList(bulletResource); var bullet = inactiveBullets.Count > 0 ? inactiveBullets.First() : InstantiateBullet(bulletResource); if (active) { inactiveBullets.Remove(bullet); activeBullets.Add(bullet); bullet.Enable(); } else { activeBullets.Add(bullet); inactiveBullets.Remove(bullet); bullet.Disable(); } return bullet; } public T SpawnBullet(BulletResource bulletResource, bool active = true) where T : IBullet { return (T)SpawnBullet(bulletResource, active); } public IEnumerable GetAllActiveBullets() { return _activeBullets.Values.SelectMany(list => list); } public IEnumerable GetAllInActiveBullets() { return _activeBullets.Values.SelectMany(list => list); } public List GetActiveBulletsList(BulletResource resource) { return GetOrCreateList(_activeBullets, resource); } private List GetInactiveBulletsList(BulletResource resource) { return GetOrCreateList(_inactiveBullets, resource); } public void DisableBullet(IBullet bullet) { var activeBulletsList = GetActiveBulletsList(bullet.BulletInfo.OriginalBulletResource); var inactiveBulletsList = GetInactiveBulletsList(bullet.BulletInfo.OriginalBulletResource); bullet.Disable(!DebugView); activeBulletsList.Remove(bullet); inactiveBulletsList.Add(bullet); } public void DisableAllBullets() { var allActiveBullets = GetAllActiveBullets().ToImmutableList(); foreach (var bullet in allActiveBullets) { var inactiveBulletsList = GetInactiveBulletsList(bullet.BulletInfo.OriginalBulletResource); bullet.Disable(!DebugView); inactiveBulletsList.Add(bullet); } foreach (var activeBulletsList in _activeBullets) { activeBulletsList.Value.Clear(); } } private List GetOrCreateList(System.Collections.Generic.Dictionary> dict, BulletResource resource) { if (dict.TryGetValue(resource, out var list)) return list; list = []; dict[resource] = list; return list; } private IBullet InstantiateBullet(BulletResource bulletData) { var bullet = bulletData.BulletScene.Instantiate(); this.AddChild(bullet); //this.CreateChild(bulletData.BulletScene); return bullet; } } public partial class PooledBulletInfo : Resource { public BulletResource Bullet { get; private set; } public int Amount { get; private set; } }