Skip to main content

window_manager_demo/
window_manager_demo.rs

1//! WindowManager Example - Simplified Multi-Window Management
2//!
3//! Demonstrates the `WindowManager` abstraction for managing multiple windows:
4//! - Creates 3 windows with different clear colors (Red, Green, Blue)
5//! - Automatic window resize handling
6//! - Shared graphics context management
7//! - Eliminates HashMap boilerplate
8//!
9//! ## Features Showcased
10//! - `WindowManager` for simplified window management
11//! - Automatic resize event handling
12//! - Shared `GraphicsContext` across windows
13//! - Per-window rendering with different clear colors
14//!
15//! ## Usage
16//! ```bash
17//! cargo run -p astrelis-render --example window_manager_demo
18//! ```
19//!
20//! ## Comparison
21//! Compare this to `multi_window.rs` to see the boilerplate reduction!
22
23use astrelis_core::logging;
24use astrelis_render::{Color, GraphicsContext, WindowContextDescriptor, WindowManager};
25use astrelis_winit::{
26    FrameTime, WindowId,
27    app::{App, AppCtx, run_app},
28    event::EventBatch,
29    window::{WindowDescriptor, WinitPhysicalSize},
30};
31use std::collections::HashMap;
32
33struct WindowManagerApp {
34    window_manager: WindowManager,
35    window_colors: HashMap<WindowId, Color>,
36}
37
38fn main() {
39    logging::init();
40
41    run_app(|ctx| {
42        let graphics_ctx =
43            GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
44        let mut window_manager = WindowManager::new(graphics_ctx);
45        let mut window_colors = HashMap::new();
46
47        // Create 3 windows with different colors
48        let colors = [
49            Color::rgb(0.8, 0.2, 0.2), // Red
50            Color::rgb(0.2, 0.8, 0.2), // Green
51            Color::rgb(0.2, 0.2, 0.8), // Blue
52        ];
53
54        for (i, color) in colors.iter().enumerate() {
55            let window_id = window_manager
56                .create_window_with_descriptor(
57                    ctx,
58                    WindowDescriptor {
59                        title: format!("Window {} - WindowManager Demo", i + 1),
60                        size: Some(WinitPhysicalSize::new(400.0, 300.0)),
61                        ..Default::default()
62                    },
63                    WindowContextDescriptor {
64                        format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
65                        ..Default::default()
66                    },
67                )
68                .expect("Failed to create window");
69
70            window_colors.insert(window_id, *color);
71        }
72
73        Box::new(WindowManagerApp {
74            window_manager,
75            window_colors,
76        })
77    });
78}
79
80impl App for WindowManagerApp {
81    fn update(&mut self, _ctx: &mut AppCtx, _time: &FrameTime) {
82        // Global logic - called once per frame
83        // (none needed for this example)
84    }
85
86    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
87        // Get the color for this window
88        let Some(&color) = self.window_colors.get(&window_id) else {
89            return;
90        };
91
92        // WindowManager automatically handles:
93        // 1. Window lookup (no manual HashMap.get_mut)
94        // 2. Resize events (automatic)
95        // 3. Event dispatching
96        self.window_manager
97            .render_window(window_id, events, |window, _events| {
98                // No need to manually handle resize events!
99                // WindowManager already did that for us
100
101                // Just render!
102                let Some(frame) = window.begin_frame() else {
103                    return; // Surface not available
104                };
105
106                {
107                    let _pass = frame
108                        .render_pass()
109                        .clear_color(color)
110                        .label("window_manager_pass")
111                        .build();
112                    // Additional rendering would go here
113                }
114                // Frame auto-submits on drop
115            });
116    }
117}