Skip to content

Commit 1da3114

Browse files
committed
feat(examples): add drag and drop picking
1 parent ffc66f1 commit 1da3114

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4591,6 +4591,18 @@ description = "Demonstrates picking debug overlay"
45914591
category = "Picking"
45924592
wasm = true
45934593

4594+
[[example]]
4595+
name = "dragdrop_picking"
4596+
path = "examples/picking/dragdrop_picking.rs"
4597+
doc-scrape-examples = true
4598+
required-features = ["mesh_picking"]
4599+
4600+
[package.metadata.example.dragdrop_picking]
4601+
name = "Drag and Drop"
4602+
description = "Demonstrates drag and drop using picking events"
4603+
category = "Picking"
4604+
wasm = true
4605+
45944606
[[example]]
45954607
name = "animation_masks"
45964608
path = "examples/animation/animation_masks.rs"

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ Example | Description
416416

417417
Example | Description
418418
--- | ---
419+
[Drag and Drop](../examples/picking/dragdrop_picking.rs) | Demonstrates drag and drop using picking events
419420
[Mesh Picking](../examples/picking/mesh_picking.rs) | Demonstrates picking meshes
420421
[Picking Debug Tools](../examples/picking/debug_picking.rs) | Demonstrates picking debug overlay
421422
[Showcases simple picking events and usage](../examples/picking/simple_picking.rs) | Demonstrates how to use picking events to spawn simple objects
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
//! Demonstrates drag and drop functionality using picking events.
2+
3+
use bevy::prelude::*;
4+
5+
#[derive(Component)]
6+
struct DropArea;
7+
8+
#[derive(Component)]
9+
struct DraggableButton;
10+
11+
#[derive(Component)]
12+
struct GhostPreview;
13+
14+
#[derive(Component)]
15+
struct DroppedElement;
16+
17+
const AREA_SIZE: f32 = 500.0;
18+
const BUTTON_WIDTH: f32 = 150.0;
19+
const BUTTON_HEIGHT: f32 = 50.0;
20+
const ELEMENT_SIZE: f32 = 25.0;
21+
22+
fn main() {
23+
App::new()
24+
.add_plugins((DefaultPlugins, MeshPickingPlugin))
25+
.add_systems(Startup, setup)
26+
.run();
27+
}
28+
29+
fn setup(
30+
mut commands: Commands,
31+
mut meshes: ResMut<Assets<Mesh>>,
32+
mut materials: ResMut<Assets<ColorMaterial>>,
33+
) {
34+
commands.spawn(Camera2d);
35+
36+
commands
37+
.spawn((
38+
Node {
39+
width: Val::Percent(100.0),
40+
height: Val::Percent(100.0),
41+
align_items: AlignItems::Center,
42+
justify_content: JustifyContent::Start,
43+
..default()
44+
},
45+
Pickable::IGNORE,
46+
))
47+
.with_children(|parent| {
48+
parent
49+
.spawn((
50+
DraggableButton,
51+
Node {
52+
width: Val::Px(BUTTON_WIDTH),
53+
height: Val::Px(BUTTON_HEIGHT),
54+
margin: UiRect::all(Val::Px(10.0)),
55+
justify_content: JustifyContent::Center,
56+
align_items: AlignItems::Center,
57+
..default()
58+
},
59+
BackgroundColor(Color::srgb(1.0, 0.0, 0.0)),
60+
))
61+
.with_child((
62+
Text::new("Drag from me"),
63+
TextColor(Color::WHITE),
64+
Pickable::IGNORE,
65+
))
66+
.observe(
67+
|mut event: On<Pointer<DragStart>>,
68+
mut button_color: Single<&mut BackgroundColor, With<DraggableButton>>| {
69+
button_color.0 = Color::srgb(1.0, 0.5, 0.0);
70+
event.propagate(false);
71+
},
72+
)
73+
.observe(
74+
|mut event: On<Pointer<DragEnd>>,
75+
mut button_color: Single<&mut BackgroundColor, With<DraggableButton>>| {
76+
button_color.0 = Color::srgb(1.0, 0.0, 0.0);
77+
event.propagate(false);
78+
},
79+
);
80+
});
81+
82+
commands
83+
.spawn((
84+
DropArea,
85+
Mesh2d(meshes.add(Rectangle::new(AREA_SIZE, AREA_SIZE))),
86+
MeshMaterial2d(materials.add(Color::srgb(0.1, 0.4, 0.1))),
87+
Transform::IDENTITY,
88+
))
89+
.observe(on_drag_enter)
90+
.observe(on_drag_over)
91+
.observe(on_drag_drop)
92+
.observe(on_drag_leave);
93+
94+
commands.spawn((
95+
Text2d::new("Drop here"),
96+
TextColor(Color::WHITE),
97+
Pickable::IGNORE,
98+
));
99+
}
100+
101+
fn on_drag_enter(
102+
mut event: On<Pointer<DragEnter>>,
103+
button: Single<Entity, With<DraggableButton>>,
104+
mut commands: Commands,
105+
mut meshes: ResMut<Assets<Mesh>>,
106+
mut materials: ResMut<Assets<ColorMaterial>>,
107+
) {
108+
if event.dragged == *button {
109+
let Some(position) = event.hit.position else {
110+
return;
111+
};
112+
commands.spawn((
113+
GhostPreview,
114+
Mesh2d(meshes.add(Circle::new(ELEMENT_SIZE))),
115+
MeshMaterial2d(materials.add(Color::srgba(1.0, 1.0, 0.6, 0.5))),
116+
Transform::from_translation(position),
117+
Pickable::IGNORE,
118+
));
119+
event.propagate(false);
120+
}
121+
}
122+
123+
fn on_drag_over(
124+
mut event: On<Pointer<DragOver>>,
125+
button: Single<Entity, With<DraggableButton>>,
126+
mut ghost_transform: Single<&mut Transform, With<GhostPreview>>,
127+
) {
128+
if event.dragged == *button {
129+
let Some(position) = event.hit.position else {
130+
return;
131+
};
132+
ghost_transform.translation = position;
133+
event.propagate(false);
134+
}
135+
}
136+
137+
fn on_drag_drop(
138+
mut event: On<Pointer<DragDrop>>,
139+
button: Single<Entity, With<DraggableButton>>,
140+
mut commands: Commands,
141+
ghost: Single<Entity, With<GhostPreview>>,
142+
mut meshes: ResMut<Assets<Mesh>>,
143+
mut materials: ResMut<Assets<ColorMaterial>>,
144+
) {
145+
if event.dropped == *button {
146+
commands.entity(*ghost).despawn();
147+
let Some(position) = event.hit.position else {
148+
return;
149+
};
150+
commands.spawn((
151+
DroppedElement,
152+
Mesh2d(meshes.add(Circle::new(ELEMENT_SIZE))),
153+
MeshMaterial2d(materials.add(Color::srgb(1.0, 1.0, 0.6))),
154+
Transform::from_translation(position),
155+
Pickable::IGNORE,
156+
));
157+
event.propagate(false);
158+
}
159+
}
160+
161+
fn on_drag_leave(
162+
mut event: On<Pointer<DragLeave>>,
163+
button: Single<Entity, With<DraggableButton>>,
164+
mut commands: Commands,
165+
ghost: Single<Entity, With<GhostPreview>>,
166+
) {
167+
if event.dragged == *button {
168+
commands.entity(*ghost).despawn();
169+
event.propagate(false);
170+
}
171+
}

0 commit comments

Comments
 (0)