use crate::client::Me;
use crate::ecs::{CursorWorldCoordinates, DragRequestEvent, Part};
use bevy::prelude::*;
use bevy_rapier2d::dynamics::MassProperties;
use bevy_rapier2d::prelude::{AdditionalMassProperties, ReadMassProperties, RigidBody};
pub fn parts_plugin(app: &mut App) {
app.insert_resource(DragResource(None));
app.add_systems(Update, (handle_incoming_parts, handle_updated_parts));
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() {
trace!(?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);
trace!(?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,
}));
trace!(?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>,
) {
if ev.button != PointerButton::Primary {
return;
}
let Ok(_) = sprites.get(ev.target()) else {
return;
};
drag.0 = Some(ev.target());
}
fn on_part_release(
ev: Trigger<Pointer<Released>>,
mut drag: ResMut<DragResource>,
mut events: EventWriter<DragRequestEvent>,
cursor: Res<CursorWorldCoordinates>,
) {
if ev.button != PointerButton::Primary {
return;
}
if let Some(e) = drag.0
&& let Some(c) = cursor.0
{
debug!(?e, ?c, "sending drag request");
events.write(DragRequestEvent(e, c));
}
drag.0 = None;
}