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<Part>>,
asset_server: Res<AssetServer>,
) {
for (new_entity, new_part) in new_parts.iter() {
info!(?new_entity, ?new_part, "new part");
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<Part>>,
asset_server: Res<AssetServer>,
) {
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::<Sprite>()
.remove::<AdditionalMassProperties>()
.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<Entity>);
fn on_part_click(ev: Trigger<Pointer<Pressed>>, sprites: Query<&Sprite, Without<Me>>, mut drag: ResMut<DragResource>, mut events: EventWriter<PartDragControlEvent>) {
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<Pointer<Released>>, mut drag: ResMut<DragResource>, mut events: EventWriter<PartDragControlEvent>) {
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<DragResource>, coords: Res<CursorWorldCoordinates>, mut events: EventWriter<PartDragEvent>) {
let Some(dragging) = drag.0 else { return; };
let Some(coordinates) = coords.0 else { return; };
events.write(PartDragEvent(dragging, coordinates));
}