use bevy::prelude::Component;
use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider};
use crate::config::part::PartConfig;
use crate::ecs::{Part, PartHandle};
pub fn part_management_plugin(app: &mut App) {
app.add_systems(PreUpdate, (handle_ready_parts, handle_part_reloading));
}
#[derive(Bundle)]
pub struct SpawnPartBundle {
pub req: SpawnPartRequest,
pub transform: Transform,
}
#[derive(Component)]
pub struct SpawnPartRequest(pub Handle<PartConfig>);
// wait for parts assets to be ready, then spawn the full part
fn handle_ready_parts(loading_parts: Query<(Entity, &SpawnPartRequest)>, mut commands: Commands, assets: Res<Assets<PartConfig>>) {
for (entity, loading_part) in &loading_parts {
if let Some(strong_config) = assets.get(&loading_part.0) {
// config is strong; spawn 'er in!
commands.entity(entity)
.insert(calculate_bundle(strong_config, &loading_part.0))
.remove::<SpawnPartRequest>();
}
}
}
fn handle_part_reloading(existing_parts: Query<(Entity, &PartHandle)>, assets: Res<Assets<PartConfig>>, mut asset_events: EventReader<AssetEvent<PartConfig>>, mut commands: Commands) {
for event in asset_events.read() {
match event {
AssetEvent::Modified { id } => {
let config = assets.get(*id).unwrap();
for existing_part in existing_parts.iter() {
if existing_part.1.0.id() == *id {
commands.entity(existing_part.0)
.insert(calculate_bundle(config, &existing_part.1.0));
}
}
},
_ => {}
}
}
}
fn calculate_bundle(config: &PartConfig, handle: &Handle<PartConfig>) -> impl Bundle {
let part = Part {
strong_config: config.clone(),
};
let part_handle = PartHandle(handle.clone());
let collider = Collider::cuboid(config.physics.width / 2.0, config.physics.height / 2.0);
let additional_mass_properties = AdditionalMassProperties::Mass(config.physics.mass);
(
part,
part_handle,
collider,
additional_mass_properties,
)
}