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}