multi_window/
multi_window.rs

1//! Multi-window example demonstrating multiple RenderableWindows.
2//!
3//! This example creates 3 windows, each with a different clear color:
4//! - Red window
5//! - Green window
6//! - Blue window
7//!
8//! Each window shares the same GraphicsContext and renders independently
9//! using the RenderPassBuilder API.
10
11use astrelis_core::logging;
12use astrelis_render::{
13    GraphicsContext, RenderTarget, RenderableWindow, WindowContextDescriptor,
14};
15use astrelis_winit::{
16    WindowId,
17    app::run_app,
18    window::{WindowBackend, WindowDescriptor, WinitPhysicalSize},
19};
20use std::collections::HashMap;
21use std::sync::Arc;
22
23struct App {
24    context: Arc<GraphicsContext>,
25    windows: HashMap<WindowId, (RenderableWindow, wgpu::Color)>,
26}
27
28fn main() {
29    logging::init();
30
31    run_app(|ctx| {
32        let graphics_ctx = GraphicsContext::new_owned_sync_or_panic();
33
34        let mut windows = HashMap::new();
35
36        // Create 3 windows with different colors
37        let colors = [
38            wgpu::Color {
39                r: 0.8,
40                g: 0.2,
41                b: 0.2,
42                a: 1.0,
43            },
44            wgpu::Color {
45                r: 0.2,
46                g: 0.8,
47                b: 0.2,
48                a: 1.0,
49            },
50            wgpu::Color {
51                r: 0.2,
52                g: 0.2,
53                b: 0.8,
54                a: 1.0,
55            },
56        ];
57
58        for (i, color) in colors.iter().enumerate() {
59            let window = ctx
60                .create_window(WindowDescriptor {
61                    title: format!("Window {} - Multi-Window Example", i + 1),
62                    size: Some(WinitPhysicalSize::new(400.0, 300.0)),
63                    ..Default::default()
64                })
65                .expect("Failed to create window");
66
67            let renderable_window = RenderableWindow::new_with_descriptor(
68                window,
69                graphics_ctx.clone(),
70                WindowContextDescriptor {
71                    format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
72                    ..Default::default()
73                },
74            ).expect("Failed to create renderable window");
75
76            let window_id = renderable_window.id();
77            windows.insert(window_id, (renderable_window, *color));
78        }
79
80        Box::new(App {
81            context: graphics_ctx,
82            windows,
83        })
84    });
85}
86
87impl astrelis_winit::app::App for App {
88    fn update(&mut self, _ctx: &mut astrelis_winit::app::AppCtx, _time: &astrelis_winit::FrameTime) {
89        // Global logic - called once per frame
90        // (none needed for this example)
91    }
92
93    fn render(
94        &mut self,
95        _ctx: &mut astrelis_winit::app::AppCtx,
96        window_id: WindowId,
97        events: &mut astrelis_winit::event::EventBatch,
98    ) {
99        // Get the window and color for this specific window
100        let Some((window, color)) = self.windows.get_mut(&window_id) else {
101            return;
102        };
103
104        // Handle window-specific resize events
105        events.dispatch(|event| {
106            if let astrelis_winit::event::Event::WindowResized(size) = event {
107                window.resized(*size);
108                astrelis_winit::event::HandleStatus::consumed()
109            } else {
110                astrelis_winit::event::HandleStatus::ignored()
111            }
112        });
113
114        // Render this specific window
115        let mut frame = window.begin_drawing();
116
117        // Render with automatic scoping (no manual {} block needed)
118        frame.clear_and_render(
119            RenderTarget::Surface,
120            astrelis_render::Color::rgba(color.r as f32, color.g as f32, color.b as f32, color.a as f32),
121            |_pass| {
122                // Just clearing - no rendering commands needed
123            },
124        );
125
126        frame.finish();
127    }
128}