wde_renderer/core/
window.rs

1//! Window plugin and related components
2//! This module contains the window plugin and related components.
3//! It is responsible for creating and managing the window.
4
5use bevy::{
6    a11y::AccessibilityPlugin,
7    app::{PluginGroup, PluginGroupBuilder},
8    ecs::message::Message,
9    prelude::{Event, MessageReader, MessageWriter, Query, ResMut},
10    utils::default,
11    window::{PresentMode, Window, WindowPlugin, WindowResized, WindowTheme},
12    winit::WinitPlugin
13};
14use wde_wgpu::instance;
15
16use crate::core::RenderInstance;
17
18use super::extract_macros::ExtractWorld;
19
20/// An event that is sent when the surface is resized.
21/// This event is sent with the new width and height of the surface. It is used to update the surface configuration and resize the swap chain.
22#[derive(Debug, Event, Message)]
23pub struct SurfaceResized {
24    pub width: u32,
25    pub height: u32
26}
27
28pub(crate) struct WindowPlugins;
29impl PluginGroup for WindowPlugins {
30    fn build(self) -> PluginGroupBuilder {
31        let mut group = PluginGroupBuilder::start::<Self>();
32
33        // Add window and winit plugins
34        group = group
35            .add(WindowPlugin {
36                primary_window: Some(Window {
37                    title: "WaterDropEngine".into(),
38                    name: Some("waterdropengine".into()),
39                    resolution: (600, 500).into(),
40                    present_mode: PresentMode::AutoVsync,
41                    fit_canvas_to_parent: true,
42                    prevent_default_event_handling: false,
43                    window_theme: Some(WindowTheme::Dark),
44                    enabled_buttons: bevy::window::EnabledButtons {
45                        maximize: true,
46                        ..Default::default()
47                    },
48                    visible: true,
49                    ..default()
50                }),
51                ..default()
52            })
53            .add::<WinitPlugin>(WinitPlugin::default())
54            .add(AccessibilityPlugin);
55
56        group
57    }
58}
59
60/// Send surface resized events with the physical window size.
61pub(crate) fn send_surface_resized(
62    mut events_writer: MessageWriter<SurfaceResized>,
63    mut events_reader: MessageReader<WindowResized>,
64    window: Query<&Window>
65) {
66    for _ in events_reader.read() {
67        if let Ok(window) = window.single() {
68            let (width, height) = (
69                window.resolution.physical_width().max(1),
70                window.resolution.physical_height().max(1)
71            );
72
73            // Check if window was minimized
74            if width == 0 && height == 0 {
75                continue;
76            }
77
78            // Send the surface resized event
79            events_writer.write(SurfaceResized { width, height });
80        }
81    }
82}
83
84/// Extract the window size from the primary window and update the surface configuration.
85pub(crate) fn extract_surface_size(
86    render_instance: ResMut<RenderInstance>,
87    windows: ExtractWorld<Query<&Window>>
88) {
89    // Check if there is a window
90    if windows.iter().count() == 0 {
91        return;
92    }
93
94    // Get the window size
95    let window = windows.single().unwrap();
96    let (width, height) = (
97        window.resolution.physical_width().max(1),
98        window.resolution.physical_height().max(1)
99    );
100
101    // Check if size different from old one
102    let mut render_instance = render_instance.0.write().unwrap();
103    let old_size = render_instance.surface_config.as_ref().unwrap();
104    if width == old_size.width && height == old_size.height {
105        return;
106    }
107
108    // Update the surface configuration
109    let surface_config = render_instance.surface_config.as_mut().unwrap();
110    surface_config.width = width;
111    surface_config.height = height;
112
113    instance::resize(
114        &render_instance.device,
115        render_instance.surface.as_ref().unwrap(),
116        render_instance.surface_config.as_ref().unwrap()
117    );
118}