-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add window drag move and drag resize without decoration example. #15814
Changes from 7 commits
41311e6
e39fc92
8a2eb58
5f4f0eb
853dcef
9e8c891
5f4952a
c08e217
0c37250
d4c91b4
e78bb49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ use bevy_ecs::{ | |
entity::{Entity, VisitEntities, VisitEntitiesMut}, | ||
prelude::{Component, ReflectComponent}, | ||
}; | ||
use bevy_math::{DVec2, IVec2, UVec2, Vec2}; | ||
use bevy_math::{CompassOctant, DVec2, IVec2, UVec2, Vec2}; | ||
use bevy_reflect::{std_traits::ReflectDefault, Reflect}; | ||
|
||
#[cfg(feature = "serialize")] | ||
|
@@ -379,7 +379,7 @@ impl Window { | |
/// | ||
/// There is no guarantee that this will work unless the left mouse button was | ||
/// pressed immediately before this function was called. | ||
pub fn start_drag_resize(&mut self, direction: ResizeDirection) { | ||
pub fn start_drag_resize(&mut self, direction: CompassOctant) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this idea of using the existing |
||
self.internal.drag_resize_request = Some(direction); | ||
} | ||
|
||
|
@@ -913,32 +913,6 @@ pub enum CursorGrabMode { | |
Locked, | ||
} | ||
|
||
/// Defines the orientation in which a window resize will be performed. | ||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Reflect)] | ||
#[cfg_attr( | ||
feature = "serialize", | ||
derive(serde::Serialize, serde::Deserialize), | ||
reflect(Serialize, Deserialize) | ||
)] | ||
pub enum ResizeDirection { | ||
/// Resize the window to the west. | ||
West, | ||
/// Resize the window to the north. | ||
North, | ||
/// Resize the window to the east. | ||
East, | ||
/// Resize the window to the south. | ||
South, | ||
/// Resize the window to the northwest. | ||
Northwest, | ||
/// Resize the window to the northeast. | ||
Northeast, | ||
/// Resize the window to the southwest. | ||
Southwest, | ||
/// Resize the window to the southeast. | ||
Southeast, | ||
} | ||
|
||
/// Stores internal [`Window`] state that isn't directly accessible. | ||
#[derive(Default, Debug, Copy, Clone, PartialEq, Reflect)] | ||
#[cfg_attr( | ||
|
@@ -955,7 +929,7 @@ pub struct InternalWindowState { | |
/// If this is true then next frame we will ask to drag-move the window. | ||
drag_move_request: bool, | ||
/// If this is `Some` then the next frame we will ask to drag-resize the window. | ||
drag_resize_request: Option<ResizeDirection>, | ||
drag_resize_request: Option<CompassOctant>, | ||
/// Unscaled cursor position. | ||
physical_cursor_position: Option<DVec2>, | ||
} | ||
|
@@ -977,7 +951,7 @@ impl InternalWindowState { | |
} | ||
|
||
/// Consumes the current resize request, if it exists. This should only be called by window backends. | ||
pub fn take_resize_request(&mut self) -> Option<ResizeDirection> { | ||
pub fn take_resize_request(&mut self) -> Option<CompassOctant> { | ||
self.drag_resize_request.take() | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,140 @@ | ||||||
//! This example illustrates drag move and drag resize without window | ||||||
//! decorations. | ||||||
//! | ||||||
//! When window decorations are not present, the user cannot drag the window. | ||||||
//! The `start_drag_move()` function will permit the application to make the | ||||||
//! window draggable. It does require that the left mouse button was pressed | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is being pressed sounds better to me. Currently the tenses are conflicting. |
||||||
//! when it is called. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When (inconsistent capitalization with other comments) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I apologize. I don't quite follow this suggestion. I have rewritten that paragraph. Please see if your comment still applies. |
||||||
use bevy::{math::CompassOctant, prelude::*}; | ||||||
|
||||||
/// Determine what do on left click. | ||||||
#[derive(Resource, Debug)] | ||||||
enum LeftClickAction { | ||||||
/// Do nothing. | ||||||
Nothing, | ||||||
/// Drag the window on left click. | ||||||
Drag, | ||||||
/// 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::Drag) | ||||||
.add_systems(Startup, setup) | ||||||
.add_systems(Update, (handle_input, move_windows)) | ||||||
.run(); | ||||||
} | ||||||
|
||||||
fn setup(mut commands: Commands) { | ||||||
// Camera | ||||||
commands.spawn(Camera3d::default()); | ||||||
|
||||||
// UI | ||||||
commands | ||||||
.spawn(( | ||||||
NodeBundle { | ||||||
style: Style { | ||||||
position_type: PositionType::Absolute, | ||||||
padding: UiRect::all(Val::Px(5.0)), | ||||||
..default() | ||||||
}, | ||||||
background_color: Color::BLACK.with_alpha(0.75).into(), | ||||||
..default() | ||||||
}, | ||||||
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("Drag")); | ||||||
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: UiTextWriter, | ||||||
) { | ||||||
use LeftClickAction::*; | ||||||
if input.just_pressed(KeyCode::KeyA) { | ||||||
*action = match *action { | ||||||
Drag => Resize, | ||||||
Resize => Nothing, | ||||||
Nothing => Drag, | ||||||
}; | ||||||
*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_windows( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
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::Drag => window.start_drag_move(), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
this would be more consistent with |
||||||
LeftClickAction::Resize => { | ||||||
let d = DIRECTIONS[dir.0]; | ||||||
window.start_drag_resize(d); | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this added by mistake?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that was a mistake. Will fix.