mirror of
https://github.com/bevyengine/bevy.git
synced 2026-07-01 00:05:45 -04:00
947c8f2279
# Objective Currently there is no easy way to tell what Monitor a Window is on, which is sometimes required for this like settings menus, without having to tie yourself to `bevy_winit`. This also fixes #19169 ## Solution This implements a Many-to-One relationship in `bevy_window`, which is the `HasWindows` and `OnMonitor` relationship, which connects Monitors and Windows together. As a note there is currently one potential issue, in that the relationship does not exist immediately when the Window is made, but instead exists shortly after when the system to sync changes between winit and the window component occurs. I'm not sure how to fix this as, due to ordering, the Window technically exists prior to any Monitor Entities being made at times. ## Testing I've tested this on Void Linux X86-64, using the provided example. I have not tested anything else.
96 lines
2.9 KiB
Rust
96 lines
2.9 KiB
Rust
//! Displays information about available monitors (displays).
|
|
|
|
use bevy::{
|
|
camera::RenderTarget,
|
|
prelude::*,
|
|
window::{ExitCondition, Monitor, OnMonitor, WindowMode, WindowRef},
|
|
};
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
|
primary_window: None,
|
|
exit_condition: ExitCondition::DontExit,
|
|
..default()
|
|
}))
|
|
.add_systems(Update, (update, close_on_esc))
|
|
.run();
|
|
}
|
|
|
|
fn update(
|
|
mut commands: Commands,
|
|
monitors_added: Query<(Entity, &Monitor), Added<Monitor>>,
|
|
mut monitors_removed: RemovedComponents<Monitor>,
|
|
windows: Query<(Entity, &OnMonitor)>,
|
|
) {
|
|
for (entity, monitor) in monitors_added.iter() {
|
|
// Spawn a new window on each monitor
|
|
let name = monitor.name.clone().unwrap_or_else(|| "<no name>".into());
|
|
let size = format!("{}x{}px", monitor.physical_height, monitor.physical_width);
|
|
let hz = monitor
|
|
.refresh_rate_millihertz
|
|
.map(|x| format!("{}Hz", x as f32 / 1000.0))
|
|
.unwrap_or_else(|| "<unknown>".into());
|
|
let position = format!(
|
|
"x={} y={}",
|
|
monitor.physical_position.x, monitor.physical_position.y
|
|
);
|
|
let scale = format!("{:.2}", monitor.scale_factor);
|
|
|
|
let window = commands
|
|
.spawn((Window {
|
|
title: name.clone(),
|
|
mode: WindowMode::Fullscreen(
|
|
MonitorSelection::Entity(entity),
|
|
VideoModeSelection::Current,
|
|
),
|
|
position: WindowPosition::Centered(MonitorSelection::Entity(entity)),
|
|
..default()
|
|
},))
|
|
.id();
|
|
|
|
let camera = commands
|
|
.spawn((Camera2d, RenderTarget::Window(WindowRef::Entity(window))))
|
|
.id();
|
|
|
|
let info_text = format!(
|
|
"Monitor: {name}\nSize: {size}\nRefresh rate: {hz}\nPosition: {position}\nScale: {scale}\n\n",
|
|
);
|
|
commands.spawn((
|
|
Text(info_text),
|
|
Node {
|
|
position_type: PositionType::Relative,
|
|
height: percent(100),
|
|
width: percent(100),
|
|
..default()
|
|
},
|
|
UiTargetCamera(camera),
|
|
));
|
|
}
|
|
|
|
// Remove windows for removed monitors
|
|
for monitor_entity in monitors_removed.read() {
|
|
for (window_entity, on_monitor) in windows.iter() {
|
|
if on_monitor.0 == monitor_entity {
|
|
commands.entity(window_entity).despawn();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn close_on_esc(
|
|
mut commands: Commands,
|
|
focused_windows: Query<(Entity, &Window)>,
|
|
input: Res<ButtonInput<KeyCode>>,
|
|
) {
|
|
for (window, focus) in focused_windows.iter() {
|
|
if !focus.focused {
|
|
continue;
|
|
}
|
|
|
|
if input.just_pressed(KeyCode::Escape) {
|
|
commands.entity(window).despawn();
|
|
}
|
|
}
|
|
}
|