use bevy::asset::Handle; use bevy::prelude::*; use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider}; use crate::config::part::PartConfig; use crate::ecs::Part; pub fn part_config_plugin(app: &mut App) { app.add_systems(PreUpdate, handle_spawn_part_requests) .add_systems(Update, (update_part_requests, hotreload)); } #[derive(Component, Debug)] pub struct SpawnPart(pub String); #[derive(Component)] struct LoadingPart(Handle); #[derive(Component, Debug)] struct PartType(AssetId); // watch for new SpawnPart components and start loading their config files fn handle_spawn_part_requests(new_parts: Query<(Entity, &SpawnPart), Added>, mut commands: Commands, asset_server: Res) { for (new_part, request) in &new_parts { info!(?new_part, ?request, "answering part request"); commands.entity(new_part) .remove::() .insert(LoadingPart(asset_server.load(request.0.clone()))); } } fn update_part_requests( mut ev_config: EventReader>, loading_parts: Query<(Entity, &LoadingPart)>, assets: ResMut>, mut commands: Commands ) { for ev in ev_config.read() { match ev { AssetEvent::Added { id } => { info!(?id, "asset added"); for (loading_part, req) in &loading_parts { if req.0.id() == *id { let Some(asset) = assets.get(*id) else { continue; }; spawn_part(commands.reborrow(), loading_part, asset, id); } } }, AssetEvent::Modified { id } => { warn!("asset modification missed!"); } _ => {} } } } fn hotreload( mut ev_config: EventReader>, existing_parts: Query<(Entity, &PartType)>, assets: ResMut>, mut commands: Commands ) { for ev in ev_config.read() { match ev { AssetEvent::Modified { id } => { info!(?id, "updating part"); for (existing_part, ptype) in &existing_parts { if ptype.0 == *id { let Some(asset) = assets.get(ptype.0) else { continue; }; spawn_part(commands.reborrow(), existing_part, asset, id); } } } AssetEvent::Added { id } => { warn!("asset addition missed!"); } _ => {} } } } fn spawn_part(mut commands: Commands, entity: Entity, part: &PartConfig, id: &AssetId) { commands.entity(entity) .remove::() .insert(Part { sprite: part.part.sprite_disconnected.clone(), width: part.physics.width, height: part.physics.height, mass: part.physics.mass, }) .insert(Collider::cuboid(part.physics.width / 2.0, part.physics.height / 2.0)) .insert(AdditionalMassProperties::Mass(part.physics.mass)) .insert(PartType(*id)); }