| 1 |
|
| 2 |
|
| 3 |
use bevy::{ |
| 4 |
camera::RenderTarget, |
| 5 |
prelude::*, |
| 6 |
window::{ExitCondition, Monitor, OnMonitor, WindowMode, WindowRef}, |
| 7 |
}; |
| 8 |
|
| 9 |
fn main() { |
| 10 |
App::new() |
| 11 |
.add_plugins(DefaultPlugins.set(WindowPlugin { |
| 12 |
primary_window: None, |
| 13 |
exit_condition: ExitCondition::DontExit, |
| 14 |
..default() |
| 15 |
})) |
| 16 |
.add_systems(Update, (update, close_on_esc)) |
| 17 |
.run(); |
| 18 |
} |
| 19 |
|
| 20 |
fn update( |
| 21 |
mut commands: Commands, |
| 22 |
monitors_added: Query<(Entity, &Monitor), Added<Monitor>>, |
| 23 |
mut monitors_removed: RemovedComponents<Monitor>, |
| 24 |
windows: Query<(Entity, &OnMonitor)>, |
| 25 |
) { |
| 26 |
for (entity, monitor) in monitors_added.iter() { |
| 27 |
|
| 28 |
let name = monitor.name.clone().unwrap_or_else(|| "<no name>".into()); |
| 29 |
let size = format!("{}x{}px", monitor.physical_height, monitor.physical_width); |
| 30 |
let hz = monitor |
| 31 |
.refresh_rate_millihertz |
| 32 |
.map(|x| format!("{}Hz", x as f32 / 1000.0)) |
| 33 |
.unwrap_or_else(|| "<unknown>".into()); |
| 34 |
let position = format!( |
| 35 |
"x={} y={}", |
| 36 |
monitor.physical_position.x, monitor.physical_position.y |
| 37 |
); |
| 38 |
let scale = format!("{:.2}", monitor.scale_factor); |
| 39 |
|
| 40 |
let window = commands |
| 41 |
.spawn((Window { |
| 42 |
title: name.clone(), |
| 43 |
mode: WindowMode::Fullscreen( |
| 44 |
MonitorSelection::Entity(entity), |
| 45 |
VideoModeSelection::Current, |
| 46 |
), |
| 47 |
position: WindowPosition::Centered(MonitorSelection::Entity(entity)), |
| 48 |
..default() |
| 49 |
},)) |
| 50 |
.id(); |
| 51 |
|
| 52 |
let camera = commands |
| 53 |
.spawn((Camera2d, RenderTarget::Window(WindowRef::Entity(window)))) |
| 54 |
.id(); |
| 55 |
|
| 56 |
let info_text = format!( |
| 57 |
"Monitor: {name}\nSize: {size}\nRefresh rate: {hz}\nPosition: {position}\nScale: {scale}\n\n", |
| 58 |
); |
| 59 |
commands.spawn(( |
| 60 |
Text(info_text), |
| 61 |
Node { |
| 62 |
position_type: PositionType::Relative, |
| 63 |
height: percent(100), |
| 64 |
width: percent(100), |
| 65 |
..default() |
| 66 |
}, |
| 67 |
UiTargetCamera(camera), |
| 68 |
)); |
| 69 |
} |
| 70 |
|
| 71 |
|
| 72 |
for monitor_entity in monitors_removed.read() { |
| 73 |
for (window_entity, on_monitor) in windows.iter() { |
| 74 |
if on_monitor.0 == monitor_entity { |
| 75 |
commands.entity(window_entity).despawn(); |
| 76 |
} |
| 77 |
} |
| 78 |
} |
| 79 |
} |
| 80 |
|
| 81 |
fn close_on_esc( |
| 82 |
mut commands: Commands, |
| 83 |
focused_windows: Query<(Entity, &Window)>, |
| 84 |
input: Res<ButtonInput<KeyCode>>, |
| 85 |
) { |
| 86 |
for (window, focus) in focused_windows.iter() { |
| 87 |
if !focus.focused { |
| 88 |
continue; |
| 89 |
} |
| 90 |
|
| 91 |
if input.just_pressed(KeyCode::Escape) { |
| 92 |
commands.entity(window).despawn(); |
| 93 |
} |
| 94 |
} |
| 95 |
} |