forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 1
/
window_drag_move.rs
142 lines (132 loc) · 4.46 KB
/
window_drag_move.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! This example illustrates drag move and drag resize without window
//! decorations.
//!
//! When window decorations are not present, the user cannot drag a window by
//! its titlebar to change its position. The `start_drag_move()` function
//! permits a users to drag a window by left clicking anywhere in the window;
//! left click must be pressed and other constraints can be imposed. For
//! instance an application could require a user to hold down alt and left click
//! to drag a window.
//!
//! The `start_drag_resize()` function behaves similarly but permits a window to
//! be resized.
use bevy::{math::CompassOctant, prelude::*};
/// Determine what do on left click.
#[derive(Resource, Debug)]
enum LeftClickAction {
/// Do nothing.
Nothing,
/// Move the window on left click.
Move,
/// Resize the window on left click.
Resize,
}
/// What direction index should the window resize toward.
#[derive(Resource)]
struct ResizeDir(usize);
/// Directions that the drag resizes the window toward.
const DIRECTIONS: [CompassOctant; 8] = [
CompassOctant::North,
CompassOctant::NorthEast,
CompassOctant::East,
CompassOctant::SouthEast,
CompassOctant::South,
CompassOctant::SouthWest,
CompassOctant::West,
CompassOctant::NorthWest,
];
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
decorations: false,
..default()
}),
..default()
}))
.insert_resource(ResizeDir(7))
.insert_resource(LeftClickAction::Move)
.add_systems(Startup, setup)
.add_systems(Update, (handle_input, move_or_resize_windows))
.run();
}
fn setup(mut commands: Commands) {
// Camera
commands.spawn(Camera3d::default());
// UI
commands
.spawn((
Node {
position_type: PositionType::Absolute,
padding: UiRect::all(Val::Px(5.0)),
..default()
},
BackgroundColor(Color::BLACK.with_alpha(0.75)),
GlobalZIndex(i32::MAX),
))
.with_children(|p| {
p.spawn(Text::default()).with_children(|p| {
p.spawn(TextSpan::new(
"Demonstrate drag move and drag resize without window decorations.\n\n",
));
p.spawn(TextSpan::new("Controls:\n"));
p.spawn(TextSpan::new("A - change left click action ["));
p.spawn(TextSpan::new("Move"));
p.spawn(TextSpan::new("]\n"));
p.spawn(TextSpan::new("S / D - change resize direction ["));
p.spawn(TextSpan::new("NorthWest"));
p.spawn(TextSpan::new("]\n"));
});
});
}
fn handle_input(
input: Res<ButtonInput<KeyCode>>,
mut action: ResMut<LeftClickAction>,
mut dir: ResMut<ResizeDir>,
example_text: Query<Entity, With<Text>>,
mut writer: TextUiWriter,
) {
use LeftClickAction::*;
if input.just_pressed(KeyCode::KeyA) {
*action = match *action {
Move => Resize,
Resize => Nothing,
Nothing => Move,
};
*writer.text(example_text.single(), 4) = format!("{:?}", *action);
}
if input.just_pressed(KeyCode::KeyS) {
dir.0 = dir
.0
.checked_sub(1)
.unwrap_or(DIRECTIONS.len().saturating_sub(1));
*writer.text(example_text.single(), 7) = format!("{:?}", DIRECTIONS[dir.0]);
}
if input.just_pressed(KeyCode::KeyD) {
dir.0 = (dir.0 + 1) % DIRECTIONS.len();
*writer.text(example_text.single(), 7) = format!("{:?}", DIRECTIONS[dir.0]);
}
}
fn move_or_resize_windows(
mut windows: Query<&mut Window>,
action: Res<LeftClickAction>,
input: Res<ButtonInput<MouseButton>>,
dir: Res<ResizeDir>,
) {
// Both `start_drag_move()` and `start_drag_resize()` must be called after a
// left mouse button press as done here.
//
// winit 0.30.5 may panic when initiated without a left mouse button press.
if input.just_pressed(MouseButton::Left) {
for mut window in windows.iter_mut() {
match *action {
LeftClickAction::Nothing => (),
LeftClickAction::Move => window.start_drag_move(),
LeftClickAction::Resize => {
let d = DIRECTIONS[dir.0];
window.start_drag_resize(d);
}
}
}
}
}