//! Demonstrates dragging and dropping UI nodes use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .run(); } const COLUMNS: i16 = 10; const ROWS: i16 = 10; const TILE_SIZE: f32 = 40.; fn setup(mut commands: Commands) { commands.spawn(Camera2d); commands .spawn((Node { display: Display::Grid, align_self: AlignSelf::Center, justify_self: JustifySelf::Center, ..Default::default() }, Pickable::IGNORE, BackgroundColor(Color::srgb(0.4, 0.4, 0.4)))) .with_children(|parent| { let tile_colors = [ Color::srgb(0.2, 0.2, 0.8), Color::srgb(0.8, 0.2, 0.2) ]; for column in 0..COLUMNS { for row in 0..ROWS { let i = column + row * COLUMNS; let tile_color = tile_colors[((row % 2) + column) as usize % tile_colors.len()]; let tile_border_color = tile_color.darker(0.025); parent .spawn(( Node { width: px(TILE_SIZE), height: px(TILE_SIZE), border: px(4.).all(), grid_row: GridPlacement::start(row + 1), grid_column: GridPlacement::start(column + 1), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..Default::default() }, BorderColor::all(tile_border_color), BackgroundColor(tile_color), Outline { width: px(2.), offset: Val::ZERO, color: Color::NONE, }, Pickable { should_block_lower: false, is_hoverable: true, }, GlobalZIndex::default() )) .observe(move |on_over: On, mut query: Query<(&mut BackgroundColor, &mut BorderColor)>| { if let Ok((mut background_color, mut border_color)) = query.get_mut(on_over.event_target()) { background_color.0 = tile_color.lighter(0.1); border_color.set_all(tile_border_color.lighter(0.1)); } }) .observe(move |on_out: On, mut query: Query<(&mut BackgroundColor, &mut BorderColor)>| { if let Ok((mut background_color, mut border_color)) = query.get_mut(on_out.event_target()) { background_color.0 = tile_color; border_color.set_all(tile_border_color); } }) .observe(|on_drag_start: On, mut query: Query<(&mut Outline, &mut GlobalZIndex)>| { if let Ok((mut outline, mut global_zindex, )) = query.get_mut(on_drag_start.event_target()) { outline.color = Color::WHITE; global_zindex.0 = 1; } }) .observe(|on_drag: On, mut query: Query<&mut UiTransform>| { if let Ok(mut transform) = query.get_mut(on_drag.event_target()) { transform.translation = Val2::px(on_drag.distance.x, on_drag.distance.y); } }) .observe(move |on_drag_end: On, mut query: Query<(&mut UiTransform, &mut Outline, &mut GlobalZIndex)>| { if let Ok((mut transform, mut outline, mut global_zindex)) = query.get_mut(on_drag_end.event_target()) { transform.translation = Val2::ZERO; outline.color = Color::NONE; global_zindex.0 = 0; } }) .observe(|on_drag_drop: On, mut query: Query<&mut Node>| { if let Ok([mut a, mut b]) = query.get_many_mut([on_drag_drop.event_target(), on_drag_drop.dropped]) { core::mem::swap(&mut a.grid_row, &mut b.grid_row); core::mem::swap(&mut a.grid_column, &mut b.grid_column); } }) .with_child((Text::new(format!("{i}")), Pickable::IGNORE)); } } }); }