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.rs289
1 files changed, 289 insertions, 0 deletions
diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs
new file mode 100644
index 00000000..2a56b6fa
--- /dev/null
+++ b/examples/integration/src/main.rs
@@ -0,0 +1,289 @@
+mod controls;
+mod scene;
+
+use controls::Controls;
+use scene::Scene;
+
+use iced_wgpu::{wgpu, Backend, Renderer, Settings, Viewport};
+use iced_winit::{
+ conversion, futures, program, renderer, winit, Clipboard, Color, Debug,
+ Size,
+};
+
+use winit::{
+ dpi::PhysicalPosition,
+ event::{Event, ModifiersState, WindowEvent},
+ event_loop::{ControlFlow, EventLoop},
+};
+
+#[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() {
+ #[cfg(target_arch = "wasm32")]
+ let canvas_element = {
+ console_log::init_with_level(log::Level::Debug)
+ .expect("could not 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("Canvas with id `iced_canvas` is missing")
+ };
+ #[cfg(not(target_arch = "wasm32"))]
+ env_logger::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)
+ .expect("Failed to build winit window");
+
+ #[cfg(not(target_arch = "wasm32"))]
+ let window = winit::window::Window::new(&event_loop).unwrap();
+
+ 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 = PhysicalPosition::new(-1.0, -1.0);
+ 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(backend);
+ let surface = unsafe { instance.create_surface(&window) };
+
+ let (format, (device, queue)) = futures::executor::block_on(async {
+ let adapter = wgpu::util::initialize_adapter_from_env_or_default(
+ &instance,
+ backend,
+ Some(&surface),
+ )
+ .await
+ .expect("No suitable GPU adapters found on the system!");
+
+ 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();
+
+ (
+ surface
+ .get_supported_formats(&adapter)
+ .first()
+ .copied()
+ .expect("Get preferred format"),
+ adapter
+ .request_device(
+ &wgpu::DeviceDescriptor {
+ label: None,
+ features: adapter_features & wgpu::Features::default(),
+ limits: needed_limits,
+ },
+ None,
+ )
+ .await
+ .expect("Request device"),
+ )
+ });
+
+ 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,
+ },
+ );
+
+ let mut resized = false;
+
+ // Initialize staging belt
+ let mut staging_belt = wgpu::util::StagingBelt::new(5 * 1024);
+
+ // Initialize scene and GUI controls
+ let scene = Scene::new(&device, format);
+ let controls = Controls::new();
+
+ // Initialize iced
+ let mut debug = Debug::new();
+ let mut renderer =
+ Renderer::new(Backend::new(&device, Settings::default(), format));
+
+ let mut state = program::State::new(
+ controls,
+ viewport.logical_size(),
+ &mut renderer,
+ &mut debug,
+ );
+
+ // Run event loop
+ event_loop.run(move |event, _, control_flow| {
+ // You should change this if you want to render continuosly
+ *control_flow = ControlFlow::Wait;
+
+ match event {
+ Event::WindowEvent { event, .. } => {
+ match event {
+ WindowEvent::CursorMoved { position, .. } => {
+ cursor_position = position;
+ }
+ WindowEvent::ModifiersChanged(new_modifiers) => {
+ modifiers = new_modifiers;
+ }
+ WindowEvent::Resized(_) => {
+ resized = true;
+ }
+ WindowEvent::CloseRequested => {
+ *control_flow = ControlFlow::Exit;
+ }
+ _ => {}
+ }
+
+ // Map window event to iced event
+ if let Some(event) = iced_winit::conversion::window_event(
+ &event,
+ window.scale_factor(),
+ modifiers,
+ ) {
+ state.queue_event(event);
+ }
+ }
+ Event::MainEventsCleared => {
+ // If there are events pending
+ if !state.is_queue_empty() {
+ // We update iced
+ let _ = state.update(
+ viewport.logical_size(),
+ conversion::cursor_position(
+ cursor_position,
+ viewport.scale_factor(),
+ ),
+ &mut renderer,
+ &iced_wgpu::Theme::Dark,
+ &renderer::Style { text_color: Color::WHITE },
+ &mut clipboard,
+ &mut debug,
+ );
+
+ // and request a redraw
+ window.request_redraw();
+ }
+ }
+ Event::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
+ },
+ );
+
+ resized = false;
+ }
+
+ match surface.get_current_texture() {
+ Ok(frame) => {
+ let mut encoder = device.create_command_encoder(
+ &wgpu::CommandEncoderDescriptor { label: None },
+ );
+
+ let program = state.program();
+
+ 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.with_primitives(|backend, primitive| {
+ backend.present(
+ &device,
+ &mut staging_belt,
+ &mut encoder,
+ &view,
+ primitive,
+ &viewport,
+ &debug.overlay(),
+ );
+ });
+
+ // Then we submit the work
+ staging_belt.finish();
+ queue.submit(Some(encoder.finish()));
+ frame.present();
+
+ // Update the mouse cursor
+ window.set_cursor_icon(
+ iced_winit::conversion::mouse_interaction(
+ state.mouse_interaction(),
+ ),
+ );
+
+ // And recall staging buffers
+ staging_belt.recall();
+
+ }
+ Err(error) => match error {
+ wgpu::SurfaceError::OutOfMemory => {
+ panic!("Swapchain error: {error}. Rendering cannot continue.")
+ }
+ _ => {
+ // Try rendering again next frame.
+ window.request_redraw();
+ }
+ },
+ }
+ }
+ _ => {}
+ }
+ })
+}