use super::{DefaultPoolSize, PoolSize, SamplerPool, sample_effects::EffectOf};
use crate::{
edge::Connect,
node::EffectId,
pool::{label::PoolLabelContainer, sample_effects::SampleEffects},
sample::{QueuedSample, SamplePlayer},
};
use bevy_app::prelude::*;
use bevy_ecs::{component::ComponentId, entity::EntityCloner, prelude::*};
use bevy_log::prelude::*;
use bevy_platform::collections::HashMap;
use bevy_seedling_macros::{NodeLabel, PoolLabel};
pub(super) struct DynamicPlugin;
impl Plugin for DynamicPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<Registries>();
}
}
#[derive(NodeLabel, Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "reflect", derive(bevy_reflect::Reflect))]
pub struct DynamicBus;
#[derive(PoolLabel, Clone, Copy, PartialEq, Eq, Hash, Debug)]
struct DynamicPoolLabel(usize);
struct RegistryEntry {
label: DynamicPoolLabel,
}
#[derive(Resource, Default)]
pub(super) struct Registries(HashMap<Vec<ComponentId>, RegistryEntry>);
pub(super) fn update_dynamic_pools(
queued_samples: Query<
(Entity, &SampleEffects),
(
With<QueuedSample>,
With<SamplePlayer>,
Without<PoolLabelContainer>,
),
>,
dynamic_bus: Single<Entity, With<DynamicBus>>,
mut effects: Query<&EffectId>,
mut registries: ResMut<Registries>,
mut commands: Commands,
dynamic_range: Res<DefaultPoolSize>,
) -> Result {
for (sample, sample_effects) in queued_samples.iter() {
let component_ids =
match super::fetch_effect_ids(sample_effects, &mut effects.as_query_lens()) {
Ok(ids) => ids,
Err(e) => {
error!("{e}");
continue;
}
};
match registries.0.get_mut(&component_ids) {
Some(entry) => {
commands.entity(sample).insert(entry.label);
}
None => {
let label = DynamicPoolLabel(registries.0.len());
let bus = commands
.spawn((SamplerPool(label), PoolSize(dynamic_range.0.clone())))
.connect(*dynamic_bus)
.head();
let effects: Vec<_> = sample_effects.iter().collect();
commands.queue(move |world: &mut World| {
let mut cloner = EntityCloner::build_opt_out(world);
cloner.deny::<EffectOf>();
let mut cloner = cloner.finish();
let mut cloned = Vec::new();
for effect in effects {
let effect = cloner.spawn_clone(world, effect);
cloned.push(effect);
}
world.entity_mut(bus).add_related::<EffectOf>(&cloned);
});
registries.0.insert(component_ids, RegistryEntry { label });
commands.entity(sample).insert(label);
}
}
}
Ok(())
}