Add resizable and windowmode options to window creation

This commit is contained in:
Wouter Standaert 2020-08-13 10:47:40 +02:00
parent a7f1889a35
commit a738771c93
4 changed files with 101 additions and 9 deletions

View file

@ -34,6 +34,20 @@ pub struct Window {
pub height: u32,
pub title: String,
pub vsync: bool,
pub resizable: bool,
pub mode: WindowMode,
}
/// Defines the way a window is displayed
/// The use_size option that is used in the Fullscreen variant
/// defines whether a videomode is chosen that best fits the width and height
/// in the Window structure, or if these are ignored.
/// E.g. when use_size is set to false the best video mode possible is chosen.
#[derive(Debug, Clone, Copy)]
pub enum WindowMode {
Windowed,
BorderlessFullscreen,
Fullscreen { use_size: bool },
}
impl Window {
@ -44,6 +58,8 @@ impl Window {
width: window_descriptor.width,
title: window_descriptor.title.clone(),
vsync: window_descriptor.vsync,
resizable: window_descriptor.resizable,
mode: window_descriptor.mode,
}
}
}
@ -54,6 +70,8 @@ pub struct WindowDescriptor {
pub height: u32,
pub title: String,
pub vsync: bool,
pub resizable: bool,
pub mode: WindowMode,
}
impl Default for WindowDescriptor {
@ -63,6 +81,8 @@ impl Default for WindowDescriptor {
width: 1280,
height: 720,
vsync: true,
resizable: true,
mode: WindowMode::Windowed,
}
}
}

View file

@ -1,4 +1,4 @@
use bevy_window::{Window, WindowId};
use bevy_window::{Window, WindowId, WindowMode};
use std::collections::HashMap;
#[derive(Default)]
@ -17,18 +17,39 @@ impl WinitWindows {
#[cfg(target_os = "windows")]
let winit_window_builder = {
use winit::platform::windows::WindowBuilderExtWindows;
winit::window::WindowBuilder::new()
.with_drag_and_drop(false)
winit::window::WindowBuilder::new().with_drag_and_drop(false)
};
#[cfg(not(target_os = "windows"))]
let winit_window_builder = winit::window::WindowBuilder::new();
let mut winit_window_builder = winit::window::WindowBuilder::new();
let winit_window = winit_window_builder
.with_title(&window.title)
.with_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height))
.build(&event_loop)
.unwrap();
winit_window_builder = winit_window_builder.with_title(&window.title);
let winit_window = match window.mode {
WindowMode::BorderlessFullscreen => {
let winit_window = winit_window_builder.build(&event_loop).unwrap();
winit_window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(
winit_window.current_monitor(),
)));
winit_window
}
WindowMode::Fullscreen { use_size } => {
let winit_window = winit_window_builder.build(&event_loop).unwrap();
winit_window.set_fullscreen(Some(winit::window::Fullscreen::Exclusive(
match use_size {
true => get_fitting_videomode(&winit_window.current_monitor(), &window),
false => get_best_videomode(&winit_window.current_monitor()),
},
)));
winit_window
}
_ => winit_window_builder
.with_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height))
.with_resizable(window.resizable)
.build(&event_loop)
.unwrap(),
};
self.window_id_to_winit.insert(window.id, winit_window.id());
self.winit_to_window_id.insert(winit_window.id(), window.id);
@ -46,3 +67,49 @@ impl WinitWindows {
self.winit_to_window_id.get(&id).cloned()
}
}
fn get_fitting_videomode(
monitor: &winit::monitor::MonitorHandle,
window: &Window,
) -> winit::monitor::VideoMode {
let mut modes = monitor.video_modes().collect::<Vec<_>>();
fn abs_diff(a: u32, b: u32) -> u32 {
if a > b {
return a - b;
}
b - a
}
modes.sort_by(|a, b| {
use std::cmp::Ordering::*;
match abs_diff(a.size().width, window.width).cmp(&abs_diff(b.size().width, window.width)) {
Equal => {
match abs_diff(a.size().height, window.height)
.cmp(&abs_diff(b.size().height, window.height))
{
Equal => b.refresh_rate().cmp(&a.refresh_rate()),
default => default,
}
}
default => default,
}
});
modes.first().unwrap().clone()
}
fn get_best_videomode(monitor: &winit::monitor::MonitorHandle) -> winit::monitor::VideoMode {
let mut modes = monitor.video_modes().collect::<Vec<_>>();
modes.sort_by(|a, b| {
use std::cmp::Ordering::*;
match b.size().width.cmp(&a.size().width) {
Equal => match b.size().height.cmp(&a.size().height) {
Equal => b.refresh_rate().cmp(&a.refresh_rate()),
default => default,
},
default => default,
}
});
modes.first().unwrap().clone()
}

View file

@ -39,6 +39,7 @@ fn setup(
height: 600,
vsync: false,
title: "second window".to_string(),
..Default::default()
},
});

View file

@ -1,4 +1,5 @@
use bevy::prelude::*;
use bevy_window::WindowMode;
/// This example illustrates how to customize the default window settings
fn main() {
@ -8,6 +9,9 @@ fn main() {
width: 300,
height: 300,
vsync: true,
resizable: false,
mode: WindowMode::Fullscreen { use_size: false },
..Default::default()
})
.add_default_plugins()
.run();