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 StringName ActiveBulletsGroupName { get; private set; } = "ActiveBullets"; [Export] public StringName InactiveBulletsGroupName { get; private set; } = "InactiveBullets"; [Export] public Array PoolOnStart { get; private set; } [Export] public bool DebugView { get; private set; } = false; private readonly System.Collections.Generic.Dictionary> _inactiveBullets = new(); public override void _Ready() { Instance = this; } private void SpawnInitialBullets() { foreach (var bulletInfo in PoolOnStart) { for (int i = 0; i < bulletInfo.Amount; i++) { SpawnBullet(bulletInfo.Bullet, false); } } } 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.Pop() : InstantiateBullet(bulletResource); if (active) { //inactiveBullets.Remove(bullet); //activeBullets.Add(bullet); bullet.RemoveFromGroup(InactiveBulletsGroupName); bullet.AddToGroup(ActiveBulletsGroupName); bullet.Enable(); } else { //activeBullets.Add(bullet); //inactiveBullets.Remove(bullet); bullet.AddToGroup(InactiveBulletsGroupName); bullet.RemoveFromGroup(ActiveBulletsGroupName); inactiveBullets.Push(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 GetTree().GetNodesInGroup(ActiveBulletsGroupName).Cast(); //return _activeBullets.Values.SelectMany(list => list); } // public List GetActiveBulletsList(BulletResource resource) // { // return GetOrCreateList(_activeBullets, resource); // } private Stack 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); bullet.AddToGroup(InactiveBulletsGroupName); bullet.RemoveFromGroup(ActiveBulletsGroupName); inactiveBulletsList.Push(bullet); } public void DisableAllBullets() { var allActiveBullets = GetAllActiveBullets().ToImmutableList(); foreach (var bullet in allActiveBullets) { var inactiveBulletsList = GetInactiveBulletsList(bullet.BulletInfo.OriginalBulletResource); bullet.Disable(!DebugView); bullet.AddToGroup(InactiveBulletsGroupName); bullet.RemoveFromGroup(ActiveBulletsGroupName); inactiveBulletsList.Push(bullet); } // foreach (var activeBulletsList in _activeBullets) // { // activeBulletsList.Value.Clear(); // } } private Stack 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 as IBullet; } public void ClearBullets() { // TODO: Implement } }