summaryrefslogtreecommitdiffstats
path: root/examples/integration/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/integration/src/main.rs')
-rw-r--r--examples/integration/src/main.rs577
1 files changed, 307 insertions, 270 deletions
diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs
index c2833210..e1c7d62f 100644
--- a/examples/integration/src/main.rs
+++ b/examples/integration/src/main.rs
@@ -18,305 +18,342 @@ use iced_winit::winit;
use iced_winit::Clipboard;
use winit::{
- event::{Event, WindowEvent},
+ event::WindowEvent,
event_loop::{ControlFlow, EventLoop},
keyboard::ModifiersState,
};
use std::sync::Arc;
-#[cfg(target_arch = "wasm32")]
-use wasm_bindgen::JsCast;
-#[cfg(target_arch = "wasm32")]
-use web_sys::HtmlCanvasElement;
-#[cfg(target_arch = "wasm32")]
-use winit::platform::web::WindowBuilderExtWebSys;
-
-pub fn main() -> Result<(), Box<dyn std::error::Error>> {
- #[cfg(target_arch = "wasm32")]
- let canvas_element = {
- console_log::init().expect("Initialize logger");
-
- std::panic::set_hook(Box::new(console_error_panic_hook::hook));
-
- web_sys::window()
- .and_then(|win| win.document())
- .and_then(|doc| doc.get_element_by_id("iced_canvas"))
- .and_then(|element| element.dyn_into::<HtmlCanvasElement>().ok())
- .expect("Get canvas element")
- };
-
- #[cfg(not(target_arch = "wasm32"))]
+pub fn main() -> Result<(), winit::error::EventLoopError> {
tracing_subscriber::fmt::init();
// Initialize winit
let event_loop = EventLoop::new()?;
- #[cfg(target_arch = "wasm32")]
- let window = winit::window::WindowBuilder::new()
- .with_canvas(Some(canvas_element))
- .build(&event_loop)?;
-
- #[cfg(not(target_arch = "wasm32"))]
- let window = winit::window::Window::new(&event_loop)?;
-
- let window = Arc::new(window);
-
- let physical_size = window.inner_size();
- let mut viewport = Viewport::with_physical_size(
- Size::new(physical_size.width, physical_size.height),
- window.scale_factor(),
- );
- let mut cursor_position = None;
- let mut modifiers = ModifiersState::default();
- let mut clipboard = Clipboard::connect(&window);
-
- // Initialize wgpu
- #[cfg(target_arch = "wasm32")]
- let default_backend = wgpu::Backends::GL;
- #[cfg(not(target_arch = "wasm32"))]
- let default_backend = wgpu::Backends::PRIMARY;
-
- let backend =
- wgpu::util::backend_bits_from_env().unwrap_or(default_backend);
-
- let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
- backends: backend,
- ..Default::default()
- });
- let surface = instance.create_surface(window.clone())?;
-
- let (format, adapter, device, queue) =
- futures::futures::executor::block_on(async {
- let adapter = wgpu::util::initialize_adapter_from_env_or_default(
- &instance,
- Some(&surface),
- )
- .await
- .expect("Create adapter");
-
- let adapter_features = adapter.features();
-
- #[cfg(target_arch = "wasm32")]
- let needed_limits = wgpu::Limits::downlevel_webgl2_defaults()
- .using_resolution(adapter.limits());
-
- #[cfg(not(target_arch = "wasm32"))]
- let needed_limits = wgpu::Limits::default();
-
- let capabilities = surface.get_capabilities(&adapter);
-
- let (device, queue) = adapter
- .request_device(
- &wgpu::DeviceDescriptor {
- label: None,
- required_features: adapter_features
- & wgpu::Features::default(),
- required_limits: needed_limits,
+ #[allow(clippy::large_enum_variant)]
+ enum Runner {
+ Loading,
+ Ready {
+ window: Arc<winit::window::Window>,
+ device: wgpu::Device,
+ queue: wgpu::Queue,
+ surface: wgpu::Surface<'static>,
+ format: wgpu::TextureFormat,
+ engine: Engine,
+ renderer: Renderer,
+ scene: Scene,
+ state: program::State<Controls>,
+ cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
+ clipboard: Clipboard,
+ viewport: Viewport,
+ modifiers: ModifiersState,
+ resized: bool,
+ debug: Debug,
+ },
+ }
+
+ impl winit::application::ApplicationHandler for Runner {
+ fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
+ if let Self::Loading = self {
+ let window = Arc::new(
+ event_loop
+ .create_window(
+ winit::window::WindowAttributes::default(),
+ )
+ .expect("Create window"),
+ );
+
+ let physical_size = window.inner_size();
+ let viewport = Viewport::with_physical_size(
+ Size::new(physical_size.width, physical_size.height),
+ window.scale_factor(),
+ );
+ let clipboard = Clipboard::connect(&window);
+
+ let backend =
+ wgpu::util::backend_bits_from_env().unwrap_or_default();
+
+ let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
+ backends: backend,
+ ..Default::default()
+ });
+ let surface = instance
+ .create_surface(window.clone())
+ .expect("Create window surface");
+
+ let (format, adapter, device, queue) =
+ futures::futures::executor::block_on(async {
+ let adapter =
+ wgpu::util::initialize_adapter_from_env_or_default(
+ &instance,
+ Some(&surface),
+ )
+ .await
+ .expect("Create adapter");
+
+ let adapter_features = adapter.features();
+
+ let capabilities = surface.get_capabilities(&adapter);
+
+ let (device, queue) = adapter
+ .request_device(
+ &wgpu::DeviceDescriptor {
+ label: None,
+ required_features: adapter_features
+ & wgpu::Features::default(),
+ required_limits: wgpu::Limits::default(),
+ },
+ None,
+ )
+ .await
+ .expect("Request device");
+
+ (
+ capabilities
+ .formats
+ .iter()
+ .copied()
+ .find(wgpu::TextureFormat::is_srgb)
+ .or_else(|| {
+ capabilities.formats.first().copied()
+ })
+ .expect("Get preferred format"),
+ adapter,
+ device,
+ queue,
+ )
+ });
+
+ surface.configure(
+ &device,
+ &wgpu::SurfaceConfiguration {
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
+ format,
+ width: physical_size.width,
+ height: physical_size.height,
+ present_mode: wgpu::PresentMode::AutoVsync,
+ alpha_mode: wgpu::CompositeAlphaMode::Auto,
+ view_formats: vec![],
+ desired_maximum_frame_latency: 2,
},
- None,
- )
- .await
- .expect("Request device");
-
- (
- capabilities
- .formats
- .iter()
- .copied()
- .find(wgpu::TextureFormat::is_srgb)
- .or_else(|| capabilities.formats.first().copied())
- .expect("Get preferred format"),
- adapter,
+ );
+
+ // Initialize scene and GUI controls
+ let scene = Scene::new(&device, format);
+ let controls = Controls::new();
+
+ // Initialize iced
+ let mut debug = Debug::new();
+ let engine =
+ Engine::new(&adapter, &device, &queue, format, None);
+ let mut renderer = Renderer::new(
+ &device,
+ &engine,
+ Font::default(),
+ Pixels::from(16),
+ );
+
+ let state = program::State::new(
+ controls,
+ viewport.logical_size(),
+ &mut renderer,
+ &mut debug,
+ );
+
+ // You should change this if you want to render continuously
+ event_loop.set_control_flow(ControlFlow::Wait);
+
+ *self = Self::Ready {
+ window,
+ device,
+ queue,
+ surface,
+ format,
+ engine,
+ renderer,
+ scene,
+ state,
+ cursor_position: None,
+ modifiers: ModifiersState::default(),
+ clipboard,
+ viewport,
+ resized: false,
+ debug,
+ };
+ }
+ }
+
+ fn window_event(
+ &mut self,
+ event_loop: &winit::event_loop::ActiveEventLoop,
+ _window_id: winit::window::WindowId,
+ event: WindowEvent,
+ ) {
+ let Self::Ready {
+ window,
device,
queue,
- )
- });
-
- surface.configure(
- &device,
- &wgpu::SurfaceConfiguration {
- usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
- format,
- width: physical_size.width,
- height: physical_size.height,
- present_mode: wgpu::PresentMode::AutoVsync,
- alpha_mode: wgpu::CompositeAlphaMode::Auto,
- view_formats: vec![],
- desired_maximum_frame_latency: 2,
- },
- );
-
- let mut resized = false;
-
- // Initialize scene and GUI controls
- let scene = Scene::new(&device, format);
- let controls = Controls::new();
-
- // Initialize iced
- let mut debug = Debug::new();
- let mut engine = Engine::new(&adapter, &device, &queue, format, None);
- let mut renderer =
- Renderer::new(&device, &engine, Font::default(), Pixels::from(16));
-
- let mut state = program::State::new(
- controls,
- viewport.logical_size(),
- &mut renderer,
- &mut debug,
- );
-
- // Run event loop
- event_loop.run(move |event, window_target| {
- // You should change this if you want to render continuously
- window_target.set_control_flow(ControlFlow::Wait);
-
- match event {
- Event::WindowEvent {
- event: WindowEvent::RedrawRequested,
- ..
- } => {
- if resized {
- let size = window.inner_size();
-
- viewport = Viewport::with_physical_size(
- Size::new(size.width, size.height),
- window.scale_factor(),
- );
-
- surface.configure(
- &device,
- &wgpu::SurfaceConfiguration {
- format,
- usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
- width: size.width,
- height: size.height,
- present_mode: wgpu::PresentMode::AutoVsync,
- alpha_mode: wgpu::CompositeAlphaMode::Auto,
- view_formats: vec![],
- desired_maximum_frame_latency: 2,
- },
- );
-
- resized = false;
- }
-
- match surface.get_current_texture() {
- Ok(frame) => {
- let mut encoder = device.create_command_encoder(
- &wgpu::CommandEncoderDescriptor { label: None },
+ surface,
+ format,
+ engine,
+ renderer,
+ scene,
+ state,
+ viewport,
+ cursor_position,
+ modifiers,
+ clipboard,
+ resized,
+ debug,
+ } = self
+ else {
+ return;
+ };
+
+ match event {
+ WindowEvent::RedrawRequested => {
+ if *resized {
+ let size = window.inner_size();
+
+ *viewport = Viewport::with_physical_size(
+ Size::new(size.width, size.height),
+ window.scale_factor(),
);
- let program = state.program();
-
- let view = frame.texture.create_view(
- &wgpu::TextureViewDescriptor::default(),
+ surface.configure(
+ device,
+ &wgpu::SurfaceConfiguration {
+ format: *format,
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
+ width: size.width,
+ height: size.height,
+ present_mode: wgpu::PresentMode::AutoVsync,
+ alpha_mode: wgpu::CompositeAlphaMode::Auto,
+ view_formats: vec![],
+ desired_maximum_frame_latency: 2,
+ },
);
- {
- // We clear the frame
- let mut render_pass = Scene::clear(
- &view,
- &mut encoder,
- program.background_color(),
+ *resized = false;
+ }
+
+ match surface.get_current_texture() {
+ Ok(frame) => {
+ let mut encoder = device.create_command_encoder(
+ &wgpu::CommandEncoderDescriptor { label: None },
);
- // Draw the scene
- scene.draw(&mut render_pass);
- }
+ let program = state.program();
- // And then iced on top
- renderer.present(
- &mut engine,
- &device,
- &queue,
- &mut encoder,
- None,
- frame.texture.format(),
- &view,
- &viewport,
- &debug.overlay(),
- );
+ let view = frame.texture.create_view(
+ &wgpu::TextureViewDescriptor::default(),
+ );
+
+ {
+ // We clear the frame
+ let mut render_pass = Scene::clear(
+ &view,
+ &mut encoder,
+ program.background_color(),
+ );
+
+ // Draw the scene
+ scene.draw(&mut render_pass);
+ }
+
+ // And then iced on top
+ renderer.present(
+ engine,
+ device,
+ queue,
+ &mut encoder,
+ None,
+ frame.texture.format(),
+ &view,
+ viewport,
+ &debug.overlay(),
+ );
- // Then we submit the work
- queue.submit(Some(encoder.finish()));
- frame.present();
+ // Then we submit the work
+ engine.submit(queue, encoder);
+ frame.present();
- // Update the mouse cursor
- window.set_cursor_icon(
- iced_winit::conversion::mouse_interaction(
- state.mouse_interaction(),
- ),
- );
- }
- Err(error) => match error {
- wgpu::SurfaceError::OutOfMemory => {
- panic!(
- "Swapchain error: {error}. \
- Rendering cannot continue."
- )
- }
- _ => {
- // Try rendering again next frame.
- window.request_redraw();
+ // Update the mouse cursor
+ window.set_cursor(
+ iced_winit::conversion::mouse_interaction(
+ state.mouse_interaction(),
+ ),
+ );
}
- },
- }
- }
- Event::WindowEvent { event, .. } => {
- match event {
- WindowEvent::CursorMoved { position, .. } => {
- cursor_position = Some(position);
- }
- WindowEvent::ModifiersChanged(new_modifiers) => {
- modifiers = new_modifiers.state();
- }
- WindowEvent::Resized(_) => {
- resized = true;
- }
- WindowEvent::CloseRequested => {
- window_target.exit();
+ Err(error) => match error {
+ wgpu::SurfaceError::OutOfMemory => {
+ panic!(
+ "Swapchain error: {error}. \
+ Rendering cannot continue."
+ )
+ }
+ _ => {
+ // Try rendering again next frame.
+ window.request_redraw();
+ }
+ },
}
- _ => {}
}
-
- // Map window event to iced event
- if let Some(event) = iced_winit::conversion::window_event(
- window::Id::MAIN,
- event,
- window.scale_factor(),
- modifiers,
- ) {
- state.queue_event(event);
+ WindowEvent::CursorMoved { position, .. } => {
+ *cursor_position = Some(position);
+ }
+ WindowEvent::ModifiersChanged(new_modifiers) => {
+ *modifiers = new_modifiers.state();
}
+ WindowEvent::Resized(_) => {
+ *resized = true;
+ }
+ WindowEvent::CloseRequested => {
+ event_loop.exit();
+ }
+ _ => {}
}
- _ => {}
- }
- // If there are events pending
- if !state.is_queue_empty() {
- // We update iced
- let _ = state.update(
- viewport.logical_size(),
- cursor_position
- .map(|p| {
- conversion::cursor_position(p, viewport.scale_factor())
- })
- .map(mouse::Cursor::Available)
- .unwrap_or(mouse::Cursor::Unavailable),
- &mut renderer,
- &Theme::Dark,
- &renderer::Style {
- text_color: Color::WHITE,
- },
- &mut clipboard,
- &mut debug,
- );
-
- // and request a redraw
- window.request_redraw();
+ // Map window event to iced event
+ if let Some(event) = iced_winit::conversion::window_event(
+ window::Id::MAIN,
+ event,
+ window.scale_factor(),
+ *modifiers,
+ ) {
+ state.queue_event(event);
+ }
+
+ // If there are events pending
+ if !state.is_queue_empty() {
+ // We update iced
+ let _ = state.update(
+ viewport.logical_size(),
+ cursor_position
+ .map(|p| {
+ conversion::cursor_position(
+ p,
+ viewport.scale_factor(),
+ )
+ })
+ .map(mouse::Cursor::Available)
+ .unwrap_or(mouse::Cursor::Unavailable),
+ renderer,
+ &Theme::Dark,
+ &renderer::Style {
+ text_color: Color::WHITE,
+ },
+ clipboard,
+ debug,
+ );
+
+ // and request a redraw
+ window.request_redraw();
+ }
}
- })?;
+ }
- Ok(())
+ let mut runner = Runner::Loading;
+ event_loop.run_app(&mut runner)
}