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