Skip to content
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

can change window settings at runtime #644

Merged
merged 10 commits into from
Oct 15, 2020
4 changes: 2 additions & 2 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ pub fn camera_system<T: CameraProjection + Component>(
}
for (entity, mut camera, mut camera_projection) in &mut query.iter() {
if let Some(window) = windows.get(camera.window) {
if changed_window_ids.contains(&window.id) || added_cameras.contains(&entity) {
camera_projection.update(window.width as usize, window.height as usize);
if changed_window_ids.contains(&window.id()) || added_cameras.contains(&entity) {
camera_projection.update(window.width() as usize, window.height() as usize);
camera.projection_matrix = camera_projection.get_projection_matrix();
camera.depth_calculation = camera_projection.depth_calculation();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ impl Node for WindowSwapChainNode {
// create window swapchain when window is resized or created
if self
.window_created_event_reader
.find_latest(&window_created_events, |e| e.id == window.id)
.find_latest(&window_created_events, |e| e.id == window.id())
.is_some()
|| self
.window_resized_event_reader
.find_latest(&window_resized_events, |e| e.id == window.id)
.find_latest(&window_resized_events, |e| e.id == window.id())
.is_some()
{
render_resource_context.create_swap_chain(window);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ impl Node for WindowTextureNode {

if self
.window_created_event_reader
.find_latest(&window_created_events, |e| e.id == window.id)
.find_latest(&window_created_events, |e| e.id == window.id())
.is_some()
|| self
.window_resized_event_reader
.find_latest(&window_resized_events, |e| e.id == window.id)
.find_latest(&window_resized_events, |e| e.id == window.id())
.is_some()
{
let render_resource_context = render_context.resources_mut();
if let Some(RenderResourceId::Texture(old_texture)) = output.get(WINDOW_TEXTURE) {
render_resource_context.remove_texture(old_texture);
}

self.descriptor.size.width = window.width;
self.descriptor.size.height = window.height;
self.descriptor.size.width = window.width();
self.descriptor.size.height = window.height();
let texture_resource = render_resource_context.create_texture(self.descriptor);
output.set(WINDOW_TEXTURE, RenderResourceId::Texture(texture_resource));
}
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_ui/src/flex/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl FlexSurface {

pub fn update_window(&mut self, window: &Window) {
let stretch = &mut self.stretch;
let node = self.window_nodes.entry(window.id).or_insert_with(|| {
let node = self.window_nodes.entry(window.id()).or_insert_with(|| {
stretch
.new_node(stretch::style::Style::default(), Vec::new())
.unwrap()
Expand All @@ -106,8 +106,8 @@ impl FlexSurface {
*node,
stretch::style::Style {
size: stretch::geometry::Size {
width: stretch::style::Dimension::Points(window.width as f32),
height: stretch::style::Dimension::Points(window.height as f32),
width: stretch::style::Dimension::Points(window.width() as f32),
height: stretch::style::Dimension::Points(window.height() as f32),
},
..Default::default()
},
Expand Down Expand Up @@ -179,7 +179,7 @@ pub fn flex_node_system(

// update window children (for now assuming all Nodes live in the primary window)
if let Some(primary_window) = windows.get_primary() {
flex_surface.set_window_children(primary_window.id, root_node_query.iter().iter());
flex_surface.set_window_children(primary_window.id(), root_node_query.iter().iter());
}

// update children
Expand Down
13 changes: 8 additions & 5 deletions crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,22 +274,25 @@ impl RenderResourceContext for WgpuRenderResourceContext {

let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into();
let surface = surfaces
.get(&window.id)
.get(&window.id())
.expect("No surface found for window");
let swap_chain = self
.device
.create_swap_chain(surface, &swap_chain_descriptor);

window_swap_chains.insert(window.id, swap_chain);
window_swap_chains.insert(window.id(), swap_chain);
}

fn next_swap_chain_texture(&self, window: &bevy_window::Window) -> TextureId {
if let Some(texture_id) = self.try_next_swap_chain_texture(window.id) {
if let Some(texture_id) = self.try_next_swap_chain_texture(window.id()) {
texture_id
} else {
self.resources.window_swap_chains.write().remove(&window.id);
self.resources
.window_swap_chains
.write()
.remove(&window.id());
self.create_swap_chain(window);
self.try_next_swap_chain_texture(window.id)
self.try_next_swap_chain_texture(window.id())
.expect("Failed to acquire next swap chain texture!")
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_wgpu/src/wgpu_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ impl WgpuRenderer {
#[cfg(feature = "bevy_winit")]
{
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
let winit_window = winit_windows.get_window(window.id).unwrap();
let winit_window = winit_windows.get_window(window.id()).unwrap();
let surface = unsafe { self.instance.create_surface(winit_window.deref()) };
render_resource_context.set_window_surface(window.id, surface);
render_resource_context.set_window_surface(window.id(), surface);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_wgpu/src/wgpu_type_converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,9 +563,9 @@ impl WgpuFrom<&Window> for wgpu::SwapChainDescriptor {
wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
width: window.width,
height: window.height,
present_mode: if window.vsync {
width: window.width(),
height: window.height(),
present_mode: if window.vsync() {
wgpu::PresentMode::Fifo
} else {
wgpu::PresentMode::Immediate
Expand Down
108 changes: 100 additions & 8 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,27 @@ impl Default for WindowId {

#[derive(Debug)]
pub struct Window {
pub id: WindowId,
pub width: u32,
pub height: u32,
pub title: String,
pub vsync: bool,
pub resizable: bool,
pub decorations: bool,
pub mode: WindowMode,
id: WindowId,
width: u32,
height: u32,
title: String,
vsync: bool,
resizable: bool,
decorations: bool,
mode: WindowMode,
#[cfg(target_arch = "wasm32")]
pub canvas: Option<String>,
command_queue: Vec<WindowCommand>,
}
mockersf marked this conversation as resolved.
Show resolved Hide resolved
mockersf marked this conversation as resolved.
Show resolved Hide resolved

#[derive(Debug)]
pub enum WindowCommand {
SetWindowMode { mode: WindowMode },
SetTitle { title: String },
SetResolution { width: u32, height: u32 },
SetVsync { vsync: bool },
SetResizable { resizable: bool },
SetDecorations { decorations: bool },
}

/// Defines the way a window is displayed
Expand Down Expand Up @@ -70,8 +81,89 @@ impl Window {
mode: window_descriptor.mode,
#[cfg(target_arch = "wasm32")]
canvas: window_descriptor.canvas.clone(),
command_queue: Vec::new(),
}
}

#[inline]
pub fn id(&self) -> WindowId {
self.id
}

#[inline]
pub fn width(&self) -> u32 {
self.width
}

#[inline]
pub fn height(&self) -> u32 {
self.height
}

pub fn set_resolution(&mut self, width: u32, height: u32) {
self.width = width;
self.height = height;
self.command_queue
.push(WindowCommand::SetResolution { width, height });
}

#[doc(hidden)]
pub fn update_resolution_from_backend(&mut self, width: u32, height: u32) {
self.width = width;
self.height = height;
}

pub fn title(&self) -> &str {
&self.title
}

pub fn set_title(&mut self, title: String) {
self.title = title.to_string();
self.command_queue.push(WindowCommand::SetTitle { title });
}

pub fn vsync(&self) -> bool {
self.vsync
}

pub fn set_vsync(&mut self, vsync: bool) {
self.vsync = vsync;
self.command_queue.push(WindowCommand::SetVsync { vsync });
}

pub fn resizable(&self) -> bool {
self.resizable
}

pub fn set_resizable(&mut self, resizable: bool) {
self.resizable = resizable;
self.command_queue
.push(WindowCommand::SetResizable { resizable });
}

pub fn decorations(&self) -> bool {
self.decorations
}

pub fn set_decorations(&mut self, decorations: bool) {
self.decorations = decorations;
self.command_queue
.push(WindowCommand::SetDecorations { decorations });
}

pub fn mode(&self) -> WindowMode {
self.mode
}

pub fn set_mode(&mut self, mode: WindowMode) {
self.mode = mode;
self.command_queue
.push(WindowCommand::SetWindowMode { mode });
}

pub fn drain_commands<'a>(&'a mut self) -> impl Iterator<Item = WindowCommand> + 'a {
self.command_queue.drain(..)
}
}

#[derive(Debug, Clone)]
Expand Down
10 changes: 9 additions & 1 deletion crates/bevy_window/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub struct Windows {

impl Windows {
pub fn add(&mut self, window: Window) {
self.windows.insert(window.id, window);
self.windows.insert(window.id(), window);
}

pub fn get(&self, id: WindowId) -> Option<&Window> {
Expand All @@ -23,7 +23,15 @@ impl Windows {
self.get(WindowId::primary())
}

pub fn get_primary_mut(&mut self) -> Option<&mut Window> {
self.get_mut(WindowId::primary())
}

pub fn iter(&self) -> impl Iterator<Item = &Window> {
self.windows.values()
}

pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Window> {
self.windows.values_mut()
}
}
65 changes: 57 additions & 8 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub use winit_config::*;
pub use winit_windows::*;

use bevy_app::{prelude::*, AppExit};
use bevy_ecs::Resources;
use bevy_ecs::{IntoQuerySystem, Res, ResMut, Resources};
use bevy_math::Vec2;
use bevy_window::{
CreateWindow, CursorMoved, Window, WindowCloseRequested, WindowCreated, WindowResized, Windows,
Expand All @@ -29,7 +29,57 @@ impl Plugin for WinitPlugin {
// stopping us. there are plans to remove the lifetime: https://github.com/rust-windowing/winit/pull/1456
// .add_event::<winit::event::WindowEvent>()
.init_resource::<WinitWindows>()
.set_runner(winit_runner);
.set_runner(winit_runner)
.add_system(change_window.system());
}
}

fn change_window(winit_windows: Res<WinitWindows>, mut windows: ResMut<Windows>) {
for bevy_window in windows.iter_mut() {
let id = bevy_window.id();
for command in bevy_window.drain_commands() {
match command {
bevy_window::WindowCommand::SetWindowMode { mode } => {
let window = winit_windows.get_window(id).unwrap();
match mode {
bevy_window::WindowMode::BorderlessFullscreen => {
window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(None)))
}
bevy_window::WindowMode::Fullscreen { use_size } => {
let window_size = winit_windows.get_window(id).unwrap().inner_size();
window.set_fullscreen(Some(winit::window::Fullscreen::Exclusive(
match use_size {
true => get_fitting_videomode(
&window.current_monitor().unwrap(),
window_size.width,
window_size.height,
),
false => get_best_videomode(&window.current_monitor().unwrap()),
},
)))
}
bevy_window::WindowMode::Windowed => window.set_fullscreen(None),
}
}
bevy_window::WindowCommand::SetTitle { title } => {
let window = winit_windows.get_window(id).unwrap();
window.set_title(&title);
}
bevy_window::WindowCommand::SetResolution { width, height } => {
let window = winit_windows.get_window(id).unwrap();
window.set_inner_size(winit::dpi::PhysicalSize::new(width, height));
}
bevy_window::WindowCommand::SetVsync { .. } => (),
bevy_window::WindowCommand::SetResizable { resizable } => {
let window = winit_windows.get_window(id).unwrap();
window.set_resizable(resizable);
}
bevy_window::WindowCommand::SetDecorations { decorations } => {
let window = winit_windows.get_window(id).unwrap();
window.set_decorations(decorations);
}
}
}
}
}

Expand Down Expand Up @@ -118,15 +168,14 @@ pub fn winit_runner(mut app: App) {
let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap();
let mut windows = app.resources.get_mut::<Windows>().unwrap();
let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
let mut window = windows.get_mut(window_id).unwrap();
window.width = size.width;
window.height = size.height;
let window = windows.get_mut(window_id).unwrap();
window.update_resolution_from_backend(size.width, size.height);

let mut resize_events = app.resources.get_mut::<Events<WindowResized>>().unwrap();
resize_events.send(WindowResized {
id: window_id,
height: window.height as usize,
width: window.width as usize,
height: window.height() as usize,
width: window.width() as usize,
});
}
event::Event::WindowEvent {
Expand Down Expand Up @@ -231,7 +280,7 @@ fn handle_create_window_events(
for create_window_event in create_window_event_reader.iter(&create_window_events) {
let window = Window::new(create_window_event.id, &create_window_event.descriptor);
winit_windows.create_window(event_loop, &window);
let window_id = window.id;
let window_id = window.id();
windows.add(window);
window_created_events.send(WindowCreated { id: window_id });
}
Expand Down
Loading