mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Expose set_cursor_hittest() from winit (#6664)
# Objective
- Bevy should be usable to create 'overlay' type apps, where the input is not captured by Bevy, but passed down/into a target app, or to allow passive displays/widgets etc.
## Solution
- the `winit:🪟:Window` already has a `set_cursor_hittest()` which basically does this for mouse input events, so I've exposed it (trying to copy the style laid out in the existing wrappings, and added a simple demo.
---
## Changelog
- Added `hittest` to `WindowAttributes`
- Added the `hittest`'s setters/getters
- Modified the `WindowBuilder`
- Modifed the `WindowDescriptor`'s `Default` impl.
- Added an example `cargo run --example fallthrough`
This commit is contained in:
parent
55ca7fc88e
commit
b3e45b75d6
5 changed files with 98 additions and 1 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -1442,6 +1442,16 @@ description = "Illustrates creating and updating a button"
|
|||
category = "UI (User Interface)"
|
||||
wasm = true
|
||||
|
||||
[[example]]
|
||||
name = "window_fallthrough"
|
||||
path = "examples/ui/window_fallthrough.rs"
|
||||
|
||||
[package.metadata.example.window_fallthrough]
|
||||
name = "Window Fallthrough"
|
||||
description = "Illustrates how to access `winit::window::Window`'s `hittest` functionality."
|
||||
category = "UI (User Interface)"
|
||||
wasm = false
|
||||
|
||||
[[example]]
|
||||
name = "font_atlas_debug"
|
||||
path = "examples/ui/font_atlas_debug.rs"
|
||||
|
|
|
@ -286,6 +286,7 @@ pub struct Window {
|
|||
cursor_icon: CursorIcon,
|
||||
cursor_visible: bool,
|
||||
cursor_grab_mode: CursorGrabMode,
|
||||
hittest: bool,
|
||||
physical_cursor_position: Option<DVec2>,
|
||||
raw_handle: Option<RawHandleWrapper>,
|
||||
focused: bool,
|
||||
|
@ -351,6 +352,10 @@ pub enum WindowCommand {
|
|||
SetCursorPosition {
|
||||
position: Vec2,
|
||||
},
|
||||
/// Set whether or not mouse events within *this* window are captured, or fall through to the Window below.
|
||||
SetCursorHitTest {
|
||||
hittest: bool,
|
||||
},
|
||||
/// Set whether or not the window is maximized.
|
||||
SetMaximized {
|
||||
maximized: bool,
|
||||
|
@ -435,6 +440,7 @@ impl Window {
|
|||
cursor_visible: window_descriptor.cursor_visible,
|
||||
cursor_grab_mode: window_descriptor.cursor_grab_mode,
|
||||
cursor_icon: CursorIcon::Default,
|
||||
hittest: true,
|
||||
physical_cursor_position: None,
|
||||
raw_handle,
|
||||
focused: false,
|
||||
|
@ -777,7 +783,20 @@ impl Window {
|
|||
self.command_queue
|
||||
.push(WindowCommand::SetCursorPosition { position });
|
||||
}
|
||||
|
||||
/// Modifies whether the window catches cursor events.
|
||||
///
|
||||
/// If true, the window will catch the cursor events.
|
||||
/// If false, events are passed through the window such that any other window behind it receives them. By default hittest is enabled.
|
||||
pub fn set_cursor_hittest(&mut self, hittest: bool) {
|
||||
self.hittest = hittest;
|
||||
self.command_queue
|
||||
.push(WindowCommand::SetCursorHitTest { hittest });
|
||||
}
|
||||
/// Get whether or not the hittest is active.
|
||||
#[inline]
|
||||
pub fn hittest(&self) -> bool {
|
||||
self.hittest
|
||||
}
|
||||
#[allow(missing_docs)]
|
||||
#[inline]
|
||||
pub fn update_focused_status_from_backend(&mut self, focused: bool) {
|
||||
|
@ -961,6 +980,8 @@ pub struct WindowDescriptor {
|
|||
pub cursor_visible: bool,
|
||||
/// Sets whether and how the window grabs the cursor.
|
||||
pub cursor_grab_mode: CursorGrabMode,
|
||||
/// Sets whether or not the window listens for 'hits' of mouse activity over _this_ window.
|
||||
pub hittest: bool,
|
||||
/// Sets the [`WindowMode`](crate::WindowMode).
|
||||
///
|
||||
/// The monitor to go fullscreen on can be selected with the `monitor` field.
|
||||
|
@ -1013,6 +1034,7 @@ impl Default for WindowDescriptor {
|
|||
decorations: true,
|
||||
cursor_grab_mode: CursorGrabMode::None,
|
||||
cursor_visible: true,
|
||||
hittest: true,
|
||||
mode: WindowMode::Windowed,
|
||||
transparent: false,
|
||||
canvas: None,
|
||||
|
|
|
@ -230,6 +230,10 @@ fn change_window(
|
|||
let window = winit_windows.get_window(id).unwrap();
|
||||
window.set_always_on_top(always_on_top);
|
||||
}
|
||||
bevy_window::WindowCommand::SetCursorHitTest { hittest } => {
|
||||
let window = winit_windows.get_window(id).unwrap();
|
||||
window.set_cursor_hittest(hittest).unwrap();
|
||||
}
|
||||
bevy_window::WindowCommand::Close => {
|
||||
// Since we have borrowed `windows` to iterate through them, we can't remove the window from it.
|
||||
// Add the removal requests to a queue to solve this
|
||||
|
|
|
@ -319,6 +319,7 @@ Example | Description
|
|||
[UI](../examples/ui/ui.rs) | Illustrates various features of Bevy UI
|
||||
[UI Scaling](../examples/ui/ui_scaling.rs) | Illustrates how to scale the UI
|
||||
[UI Z-Index](../examples/ui/z_index.rs) | Demonstrates how to control the relative depth (z-position) of UI elements
|
||||
[Window Fallthrough](../examples/ui/window_fallthrough.rs) | Illustrates how to access `winit::window::Window`'s `hittest` functionality.
|
||||
|
||||
## Window
|
||||
|
||||
|
|
60
examples/ui/window_fallthrough.rs
Normal file
60
examples/ui/window_fallthrough.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
//! This example illustrates how have a mouse's clicks/wheel/movement etc fall through the spawned transparent window to a window below.
|
||||
//! If you build this, and hit 'P' it should toggle on/off the mouse's passthrough.
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
fn main() {
|
||||
// Set the window's parameters, note we're setting always_on_top to be true.
|
||||
let window_desc = WindowDescriptor {
|
||||
transparent: true,
|
||||
decorations: true,
|
||||
always_on_top: true,
|
||||
..default()
|
||||
};
|
||||
|
||||
App::new()
|
||||
.insert_resource(ClearColor(Color::NONE)) // Use a transparent window, to make effects obvious.
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
window: window_desc,
|
||||
..default()
|
||||
}))
|
||||
.add_startup_system(setup)
|
||||
.add_system(toggle_mouse_passthrough) // This allows us to hit 'P' to toggle on/off the mouse's passthrough
|
||||
.run();
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
// UI camera
|
||||
commands.spawn(Camera2dBundle::default());
|
||||
// Text with one section
|
||||
commands.spawn((
|
||||
// Create a TextBundle that has a Text with a single section.
|
||||
TextBundle::from_section(
|
||||
// Accepts a `String` or any type that converts into a `String`, such as `&str`
|
||||
"Hit 'P' then scroll/click around!",
|
||||
TextStyle {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 100.0, // Nice and big so you can see it!
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
// Set the style of the TextBundle itself.
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
position: UiRect {
|
||||
bottom: Val::Px(5.),
|
||||
right: Val::Px(10.),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
}),
|
||||
));
|
||||
}
|
||||
// A simple system to handle some keyboard input and toggle on/off the hittest.
|
||||
fn toggle_mouse_passthrough(keyboard_input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
|
||||
if keyboard_input.just_pressed(KeyCode::P) {
|
||||
let window = windows.primary_mut();
|
||||
let hittest: bool = window.hittest();
|
||||
window.set_cursor_hittest(!hittest);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue