Skip to main content

gizmo_core/
pool.rs

1use crate::entity::Entity;
2use crate::world::World;
3use std::collections::{HashMap, VecDeque};
4
5/// Havuzda tutulacak nesnelerin durumunu belirten marker component.
6/// Bu nesneler aktif değildir, yeniden kullanılmayı beklerler.
7#[derive(Clone, Copy)]
8pub struct Pooled;
9
10crate::impl_component!(Pooled);
11
12pub struct ObjectPool {
13    /// Orijinal prefab nesnesi (bu nesne klonlanarak çoğaltılacak)
14    pub prefab_id: u32,
15    /// Kullanılmayan, havuzdaki boş nesnelerin listesi
16    pub inactive: VecDeque<Entity>,
17}
18
19impl ObjectPool {
20    pub fn new(prefab_id: u32) -> Self {
21        Self {
22            prefab_id,
23            inactive: VecDeque::new(),
24        }
25    }
26}
27
28/// Nesne Havuzu Yönetim Sistemi
29/// Mermiler, partiküller veya düşmanlar gibi sık yaratılıp yok edilen nesneleri
30/// her seferinde tahsis etmek yerine tekrar kullanmanızı sağlar.
31pub struct PoolManager {
32    pools: HashMap<String, ObjectPool>,
33}
34
35impl Default for PoolManager {
36    fn default() -> Self {
37        Self::new()
38    }
39}
40
41impl PoolManager {
42    pub fn new() -> Self {
43        Self {
44            pools: HashMap::new(),
45        }
46    }
47
48    /// Bir prefab nesnesini kaynak göstererek yeni bir havuz oluşturur.
49    /// Prefab otomatik olarak `Pooled` ile işaretlenir, böylece render ve fizik sistemleri onu atlar.
50    pub fn register_pool(&mut self, name: &str, prefab_entity: Entity) {
51        self.pools
52            .insert(name.to_string(), ObjectPool::new(prefab_entity.id()));
53    }
54
55    /// `register_pool` ile aynı, ama ek olarak prefab entity'yi `Pooled` ile işaretler.
56    /// Bu sayede prefab asla render edilmez ve fizik sistemi tarafından simüle edilmez.
57    pub fn register_pool_hidden(&mut self, world: &mut World, name: &str, prefab_entity: Entity) {
58        world.add_component(prefab_entity, Pooled);
59        self.pools
60            .insert(name.to_string(), ObjectPool::new(prefab_entity.id()));
61    }
62
63    /// Bir bundle (MeshBundle vb.) ve zincirlenmiş bileşenleri doğrudan havuza kaydeder.
64    /// Bundle anında spawn edilir ve çıkan Entity havuz referansı olarak kullanılır.
65    pub fn register<B: crate::component::Bundle>(
66        &mut self,
67        world: &mut World,
68        name: &str,
69        bundle: B,
70    ) {
71        let prefab = world.spawn_bundle(bundle);
72        self.register_pool(name, prefab);
73    }
74
75    /// Havuzdan bir nesne alır. Havuz boşsa prefab'ı klonlayarak yeni bir nesne üretir.
76    pub fn instantiate(&mut self, world: &mut World, name: &str) -> Option<Entity> {
77        let pool = self.pools.get_mut(name)?;
78
79        if let Some(entity) = pool.inactive.pop_front() {
80            // Nesne havuzdan çıkarıldı, `Pooled` tag'i siliniyor.
81            world.remove_component::<Pooled>(entity);
82            Some(entity)
83        } else {
84            // Havuz boş, prefab klonlanarak yeni obje yaratılacak!
85            // `clone_entity` fonksiyonumuz O(1) prefab kopyalama desteği sunuyor
86            let new_entities = world.clone_entity(pool.prefab_id, 1)?;
87            let new_ent = new_entities[0];
88            // Prefab Pooled olarak işaretlenmiş olabilir (register_pool_hidden),
89            // klonlanan entity'den Pooled tag'ını kaldır ki aktif olarak doğsun.
90            world.remove_component::<Pooled>(new_ent);
91            Some(new_ent)
92        }
93    }
94
95    /// Bir nesneyi tamamen yok etmek (despawn) yerine havuza geri gönderir.
96    pub fn destroy(&mut self, world: &mut World, name: &str, entity: Entity) {
97        if let Some(pool) = self.pools.get_mut(name) {
98            // Nesne pasife alındığını bilmesi için Pooled bileşeni ekleniyor.
99            world.add_component(entity, Pooled);
100            pool.inactive.push_back(entity);
101        } else {
102            // Havuz bulunamadıysa standart despawn yap.
103            world.despawn(entity);
104        }
105    }
106}