Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/picking/dragdrop_picking.rs
9328 views
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: percent(100),
40
height: percent(100),
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: px(BUTTON_WIDTH),
53
height: px(BUTTON_HEIGHT),
54
margin: UiRect::all(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
children![(
89
Text2d::new("Drop here"),
90
TextFont::from_font_size(50.),
91
TextColor(Color::BLACK),
92
Pickable::IGNORE,
93
Transform::from_translation(Vec3::Z),
94
)],
95
))
96
.observe(on_drag_enter)
97
.observe(on_drag_over)
98
.observe(on_drag_drop)
99
.observe(on_drag_leave);
100
}
101
102
fn on_drag_enter(
103
mut event: On<Pointer<DragEnter>>,
104
button: Single<Entity, With<DraggableButton>>,
105
mut commands: Commands,
106
mut meshes: ResMut<Assets<Mesh>>,
107
mut materials: ResMut<Assets<ColorMaterial>>,
108
) {
109
if event.dragged == *button {
110
let Some(position) = event.hit.position else {
111
return;
112
};
113
commands.spawn((
114
GhostPreview,
115
Mesh2d(meshes.add(Circle::new(ELEMENT_SIZE))),
116
MeshMaterial2d(materials.add(Color::srgba(1.0, 1.0, 0.6, 0.5))),
117
Transform::from_translation(position + 2. * Vec3::Z),
118
Pickable::IGNORE,
119
));
120
event.propagate(false);
121
}
122
}
123
124
fn on_drag_over(
125
mut event: On<Pointer<DragOver>>,
126
button: Single<Entity, With<DraggableButton>>,
127
mut ghost_transform: Single<&mut Transform, With<GhostPreview>>,
128
) {
129
if event.dragged == *button {
130
let Some(position) = event.hit.position else {
131
return;
132
};
133
ghost_transform.translation = position;
134
event.propagate(false);
135
}
136
}
137
138
fn on_drag_drop(
139
mut event: On<Pointer<DragDrop>>,
140
button: Single<Entity, With<DraggableButton>>,
141
mut commands: Commands,
142
ghost: Single<Entity, With<GhostPreview>>,
143
mut meshes: ResMut<Assets<Mesh>>,
144
mut materials: ResMut<Assets<ColorMaterial>>,
145
) {
146
if event.dropped == *button {
147
commands.entity(*ghost).despawn();
148
let Some(position) = event.hit.position else {
149
return;
150
};
151
commands.spawn((
152
DroppedElement,
153
Mesh2d(meshes.add(Circle::new(ELEMENT_SIZE))),
154
MeshMaterial2d(materials.add(Color::srgb(1.0, 1.0, 0.6))),
155
Transform::from_translation(position + 2. * Vec3::Z),
156
Pickable::IGNORE,
157
));
158
event.propagate(false);
159
}
160
}
161
162
fn on_drag_leave(
163
mut event: On<Pointer<DragLeave>>,
164
button: Single<Entity, With<DraggableButton>>,
165
mut commands: Commands,
166
ghost: Single<Entity, With<GhostPreview>>,
167
) {
168
if event.dragged == *button {
169
commands.entity(*ghost).despawn();
170
event.propagate(false);
171
}
172
}
173
174