use std::fmt::Debug; use crate::ecs::{CursorWorldCoordinates, Part}; use bevy::prelude::*; use bevy_rapier2d::dynamics::MassProperties; use bevy_rapier2d::prelude::{AdditionalMassProperties, ReadMassProperties, RigidBody}; use crate::client::Me; use crate::clientevent::{PartDragControlEvent, PartDragEvent}; pub fn parts_plugin(app: &mut App) { app.insert_resource(DragResource(None)); app.add_systems(Update, (handle_incoming_parts, handle_updated_parts, send_drag)); app.add_observer(on_part_release); } fn handle_incoming_parts( mut commands: Commands, new_parts: Query<(Entity, &Part), Added>, asset_server: Res, ) { for (new_entity, new_part) in new_parts.iter() { let mut sprite = Sprite::from_image(asset_server.load(&new_part.sprite)); sprite.custom_size = Some(Vec2::new(new_part.width, new_part.height)); commands .entity(new_entity) .insert(sprite) .insert(AdditionalMassProperties::MassProperties(MassProperties { local_center_of_mass: Vec2::ZERO, mass: new_part.mass, principal_inertia: 7.5, })) .insert(ReadMassProperties::default()) .insert(RigidBody::Dynamic) .insert(Pickable::default()) .observe(on_part_click); info!(?new_part, ?new_entity, "prepared new part"); } } fn handle_updated_parts( mut commands: Commands, updated_parts: Query<(Entity, &Part), Changed>, asset_server: Res, ) { for (updated_entity, updated_part) in updated_parts.iter() { let mut sprite = Sprite::from_image(asset_server.load(&updated_part.sprite)); sprite.custom_size = Some(Vec2::new(updated_part.width, updated_part.height)); commands .entity(updated_entity) .remove::() .remove::() .insert(sprite) .insert(AdditionalMassProperties::MassProperties(MassProperties { local_center_of_mass: Vec2::ZERO, mass: updated_part.mass, principal_inertia: 7.5, })); info!(?updated_part, ?updated_entity, "updated part"); } } #[derive(Resource)] struct DragResource(Option); fn on_part_click(ev: Trigger>, sprites: Query<&Sprite, Without>, mut drag: ResMut, mut events: EventWriter) { if ev.button != PointerButton::Primary { return; }; let Ok(sprite) = sprites.get(ev.target()) else { return; }; drag.0 = Some(ev.target()); events.write(PartDragControlEvent::Start(ev.target())); info!(?sprite, ?ev, "start drag"); } fn on_part_release(ev: Trigger>, mut drag: ResMut, mut events: EventWriter) { if ev.button != PointerButton::Primary { return; }; if let Some(e) = drag.0 { events.write(PartDragControlEvent::Stop(e)); } drag.0 = None; info!(?ev, "stop drag"); } fn send_drag(drag: ResMut, coords: Res, mut events: EventWriter) { let Some(dragging) = drag.0 else { return; }; let Some(coordinates) = coords.0 else { return; }; events.write(PartDragEvent(dragging, coordinates)); }