Skip to content

Commit

Permalink
Fix window exits on multiple windows
Browse files Browse the repository at this point in the history
  • Loading branch information
hakolao committed Jan 29, 2022
1 parent 03d929a commit 2ffe78e
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
2 changes: 0 additions & 2 deletions examples/circle/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ impl PluginGroup for PluginBundle {
group.add(bevy::diagnostic::DiagnosticsPlugin::default());
group.add(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default());
group.add(bevy::input::InputPlugin::default());
// Needed for the `VulkanoWinitPlugin`
group.add(bevy::window::WindowPlugin::default());
// Don't add default bevy plugins or WinitPlugin. This owns "core loop" (runner).
// Bevy winit and render should be excluded
group.add(VulkanoWinitPlugin::default());
Expand Down
9 changes: 5 additions & 4 deletions examples/multi_window_gui/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use bevy::window::CreateWindow;
use bevy::{
app::AppExit,
window::{CreateWindow, WindowCloseRequested},
};
#[cfg(feature = "example_has_gui")]
use bevy::{
app::PluginGroupBuilder,
Expand All @@ -21,8 +24,6 @@ impl PluginGroup for PluginBundle {
group.add(bevy::diagnostic::DiagnosticsPlugin::default());
group.add(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default());
group.add(bevy::input::InputPlugin::default());
// Needed for the `VulkanoWinitPlugin`
group.add(bevy::window::WindowPlugin::default());
// Don't add default bevy plugins or WinitPlugin. This owns "core loop" (runner).
// Bevy winit and render should be excluded
group.add(VulkanoWinitPlugin::default());
Expand Down Expand Up @@ -55,7 +56,7 @@ fn main() {
CoreStage::PostUpdate,
SystemSet::new()
.with_system(main_render_system_primary_window)
.with_system(main_render_system_primary_window),
.with_system(main_render_system_secondary_window),
)
.run();
}
Expand Down
58 changes: 48 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use bevy::{
window::{
CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter,
WindowBackendScaleFactorChanged, WindowCloseRequested, WindowCreated, WindowFocused,
WindowMoved, WindowResized, WindowScaleFactorChanged, Windows,
WindowId, WindowMoved, WindowResized, WindowScaleFactorChanged, Windows,
},
};
pub use pipeline_frame_data::*;
Expand All @@ -50,6 +50,7 @@ pub use winit_window_renderer::*;

/// Vulkano related configurations
pub struct VulkanoWinitConfig {
pub add_primary_window: bool,
pub instance_extensions: InstanceExtensions,
pub device_extensions: DeviceExtensions,
pub features: Features,
Expand All @@ -59,6 +60,7 @@ pub struct VulkanoWinitConfig {
impl Default for VulkanoWinitConfig {
fn default() -> Self {
VulkanoWinitConfig {
add_primary_window: true,
instance_extensions: InstanceExtensions {
ext_debug_utils: true,
..vulkano_win::required_extensions()
Expand Down Expand Up @@ -87,19 +89,30 @@ impl Plugin for VulkanoWinitPlugin {
app.insert_resource(VulkanoWinitConfig::default());
}
let config = app.world.get_resource::<VulkanoWinitConfig>().unwrap();

// Add WindowPlugin
let add_primary_window = config.add_primary_window;

// Create vulkano context
let vulkano_context = VulkanoContext::new(config);

// Insert vulkano context resource & pipeline data
app.init_resource::<VulkanoWinitWindows>()
.init_resource::<PipelineData>()
.insert_resource(vulkano_context);
// Insert window plugin, vulkano context, windows resource & pipeline data
app.add_plugin(bevy::window::WindowPlugin {
add_primary_window,
// We don't want to run exit_on_close_system from WindowPlugin, because it closes the entire app on each window close
exit_on_close: false,
})
.init_resource::<VulkanoWinitWindows>()
.init_resource::<PipelineData>()
.insert_resource(vulkano_context);

// Create initial window
handle_initial_window_events(&mut app.world, &event_loop);

app.insert_non_send_resource(event_loop)
.set_runner(winit_runner)
.add_system_to_stage(CoreStage::PreUpdate, update_on_resize_system)
.add_system_to_stage(CoreStage::PreUpdate, exit_on_window_close_system)
.add_system_to_stage(CoreStage::PostUpdate, change_window.exclusive_system());
}
}
Expand Down Expand Up @@ -383,11 +396,11 @@ pub fn winit_runner_with(mut app: App) {
} else {
return;
};
vulkano_winit_windows
.get_vulkano_window_mut(window_id)
.unwrap()
.gui()
.update(event_wrapper);
if let Some(vulkano_window) =
vulkano_winit_windows.get_vulkano_window_mut(window_id)
{
vulkano_window.gui().update(event_wrapper);
}
}
_ => (),
}
Expand Down Expand Up @@ -727,3 +740,28 @@ fn handle_initial_window_events(world: &mut World, event_loop: &EventLoop<()>) {
});
}
}

pub fn exit_on_window_close_system(
mut app_exit_events: EventWriter<AppExit>,
mut window_close_requested_events: EventReader<WindowCloseRequested>,
mut windows: ResMut<VulkanoWinitWindows>,
mut pipeline_data: ResMut<PipelineData>,
) {
for event in window_close_requested_events.iter() {
// Close app on primary window exit
if event.id == WindowId::primary() {
app_exit_events.send(AppExit);
}
// But don't close app on secondary window exit. Instead cleanup...
else {
let window_id = event.id;
pipeline_data.remove(window_id);
let winit_id = if let Some(winit_window) = windows.get_winit_window(window_id) {
winit_window.id()
} else {
continue;
};
windows.windows.remove(&winit_id);
}
}
}
4 changes: 4 additions & 0 deletions src/pipeline_frame_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ impl PipelineData {
self.frame_data.insert(data.window_id, data);
}

pub fn remove(&mut self, id: WindowId) {
self.frame_data.remove(&id);
}

pub fn get(&self, id: WindowId) -> Option<&PipelineFrameData> {
self.frame_data.get(&id)
}
Expand Down

0 comments on commit 2ffe78e

Please sign in to comment.