diff options
Diffstat (limited to 'examples/integration/src/main.rs')
-rw-r--r-- | examples/integration/src/main.rs | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs new file mode 100644 index 00000000..ed36f736 --- /dev/null +++ b/examples/integration/src/main.rs @@ -0,0 +1,204 @@ +mod controls; +mod scene; + +use controls::Controls; +use scene::Scene; + +use iced_wgpu::{ + wgpu, window::SwapChain, Primitive, Renderer, Settings, Target, +}; +use iced_winit::{winit, Cache, Clipboard, MouseCursor, Size, UserInterface}; + +use winit::{ + event::{DeviceEvent, Event, ModifiersState, WindowEvent}, + event_loop::{ControlFlow, EventLoop}, +}; + +pub fn main() { + env_logger::init(); + + // Initialize winit + let event_loop = EventLoop::new(); + let window = winit::window::Window::new(&event_loop).unwrap(); + let mut logical_size = + window.inner_size().to_logical(window.scale_factor()); + let mut modifiers = ModifiersState::default(); + + // Initialize WGPU + let adapter = wgpu::Adapter::request(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::Default, + backends: wgpu::BackendBit::PRIMARY, + }) + .expect("Request adapter"); + + let (mut device, mut queue) = + adapter.request_device(&wgpu::DeviceDescriptor { + extensions: wgpu::Extensions { + anisotropic_filtering: false, + }, + limits: wgpu::Limits::default(), + }); + + let surface = wgpu::Surface::create(&window); + + let mut swap_chain = { + let size = window.inner_size(); + + SwapChain::new(&device, &surface, size.width, size.height) + }; + let mut resized = false; + + // Initialize iced + let mut events = Vec::new(); + let mut cache = Some(Cache::default()); + let mut renderer = Renderer::new(&mut device, Settings::default()); + let mut output = (Primitive::None, MouseCursor::OutOfBounds); + let clipboard = Clipboard::new(&window); + + // Initialize scene and GUI controls + let mut scene = Scene::new(&device); + let mut controls = Controls::new(); + + // 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::DeviceEvent { + event: DeviceEvent::ModifiersChanged(new_modifiers), + .. + } => { + modifiers = new_modifiers; + } + Event::WindowEvent { event, .. } => { + match event { + WindowEvent::Resized(new_size) => { + logical_size = + new_size.to_logical(window.scale_factor()); + 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, + ) { + events.push(event); + } + } + Event::MainEventsCleared => { + // If no relevant events happened, we can simply skip this + if events.is_empty() { + return; + } + + // We need to: + // 1. Process events of our user interface. + // 2. Update state as a result of any interaction. + // 3. Generate a new output for our renderer. + + // First, we build our user interface. + let mut user_interface = UserInterface::build( + controls.view(&scene), + Size::new(logical_size.width, logical_size.height), + cache.take().unwrap(), + &mut renderer, + ); + + // Then, we process the events, obtaining messages in return. + let messages = user_interface.update( + events.drain(..), + clipboard.as_ref().map(|c| c as _), + &renderer, + ); + + let user_interface = if messages.is_empty() { + // If there are no messages, no interactions we care about have + // happened. We can simply leave our user interface as it is. + user_interface + } else { + // If there are messages, we need to update our state + // accordingly and rebuild our user interface. + // We can only do this if we drop our user interface first + // by turning it into its cache. + cache = Some(user_interface.into_cache()); + + // In this example, `Controls` is the only part that cares + // about messages, so updating our state is pretty + // straightforward. + for message in messages { + controls.update(message, &mut scene); + } + + // Once the state has been changed, we rebuild our updated + // user interface. + UserInterface::build( + controls.view(&scene), + Size::new(logical_size.width, logical_size.height), + cache.take().unwrap(), + &mut renderer, + ) + }; + + // Finally, we just need to draw a new output for our renderer, + output = user_interface.draw(&mut renderer); + + // update our cache, + cache = Some(user_interface.into_cache()); + + // and request a redraw + window.request_redraw(); + } + Event::RedrawRequested(_) => { + if resized { + let size = window.inner_size(); + + swap_chain = SwapChain::new( + &device, + &surface, + size.width, + size.height, + ); + } + + let (frame, viewport) = swap_chain.next_frame(); + + let mut encoder = device.create_command_encoder( + &wgpu::CommandEncoderDescriptor { todo: 0 }, + ); + + // We draw the scene first + scene.draw(&mut encoder, &frame.view); + + // And then iced on top + let mouse_cursor = renderer.draw( + &mut device, + &mut encoder, + Target { + texture: &frame.view, + viewport, + }, + &output, + window.scale_factor(), + &["Some debug information!"], + ); + + // Then we submit the work + queue.submit(&[encoder.finish()]); + + // And update the mouse cursor + window.set_cursor_icon(iced_winit::conversion::mouse_cursor( + mouse_cursor, + )); + } + _ => {} + } + }) +} |