From d7869b838ff6b6283141203ec6b8bddffb3b8eea Mon Sep 17 00:00:00 2001 From: Mauritius Clemens <131599858+pillowtrucker@users.noreply.github.com> Date: Sun, 31 Dec 2023 07:53:35 +0100 Subject: [PATCH] update to winit 0.29.4 (#544) Co-authored-by: Connor Fitzgerald --- CHANGELOG.md | 2 + deny.toml | 6 +- examples/animation/Cargo.toml | 2 +- examples/animation/src/lib.rs | 70 +++---- examples/cube-no-framework/Cargo.toml | 2 +- examples/cube-no-framework/src/main.rs | 144 +++++++------- examples/cube/Cargo.toml | 2 +- examples/cube/src/lib.rs | 71 +++---- examples/egui/Cargo.toml | 8 +- examples/egui/src/main.rs | 96 ++++------ examples/scene-viewer/Cargo.toml | 2 +- examples/scene-viewer/src/lib.rs | 95 +++++---- examples/scene-viewer/src/platform.rs | 30 +-- examples/skinning/Cargo.toml | 2 +- examples/skinning/src/lib.rs | 69 +++---- examples/static-gltf/Cargo.toml | 2 +- examples/static-gltf/src/main.rs | 67 +++---- examples/textured-quad/Cargo.toml | 2 +- examples/textured-quad/src/main.rs | 72 +++---- rend3-egui/Cargo.toml | 4 +- rend3-framework/Cargo.toml | 2 +- rend3-framework/src/grab/wasm.rs | 6 +- rend3-framework/src/lib.rs | 256 +++++++++++-------------- rend3-framework/src/resize_observer.rs | 55 ------ rend3-types/src/lib.rs | 2 +- 25 files changed, 425 insertions(+), 644 deletions(-) delete mode 100644 rend3-framework/src/resize_observer.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index e10a7508..976bd735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ Per Keep a Changelog there are 6 main categories of changes: ### Changes - rend3: Update to wgpu 0.13, naga 0.9 @garyttierney - rend3: Convert all shaders to WGSL using a custom preprocessing solution @cwfitzgerald +- rend3: Update to winit 0.29.4 @pillowtrucker +- rend3-framework: Consolidate many arguments into single `SetupContext` and `EventContext` structs. @cwfitzgerald ### Fixes - Fixed renderpass compatibility checks to avoid issues when RODS is used. @OptimisticPeach diff --git a/deny.toml b/deny.toml index 3c631336..b83173f0 100644 --- a/deny.toml +++ b/deny.toml @@ -15,14 +15,10 @@ wildcards = "allow" skip = [ # gltf / reqwest { name = "base64", version = "0.13.1" }, - # ddsfile - { name = "num-traits", version = "0.1.43" }, - # tokio - { name = "socket2", version = "0.4.9" }, ] skip-tree = [ # winit brings in lots of duplicate deps that we can't fix - { name = "winit", version = "0.28" }, + { name = "winit", version = "0.29.4" }, # loom is depended on by tracy-client but under a custom cfg that is never on. { name = "loom", version = "0.5" }, ] diff --git a/examples/animation/Cargo.toml b/examples/animation/Cargo.toml index f69fdedc..a75061cd 100644 --- a/examples/animation/Cargo.toml +++ b/examples/animation/Cargo.toml @@ -34,7 +34,7 @@ rend3-gltf = { version = "^0.3.0", path = "../../rend3-gltf" } # std::time::Instant that works on wasm web-time = "0.2" # windowing -winit = "0.28" +winit = "0.29.4" image = { version = "0.24", default-features = false, features = ["jpeg"] } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/examples/animation/src/lib.rs b/examples/animation/src/lib.rs index 3829abe3..24131389 100644 --- a/examples/animation/src/lib.rs +++ b/examples/animation/src/lib.rs @@ -1,6 +1,7 @@ -use std::{path::Path, sync::Arc}; +use std::path::Path; use rend3::types::DirectionalLightHandle; +use winit::event::WindowEvent; const SAMPLE_COUNT: rend3::types::SampleCount = rend3::types::SampleCount::One; @@ -41,20 +42,13 @@ impl rend3_framework::App for AnimationExample { SAMPLE_COUNT } - fn setup( - &mut self, - _event_loop: &winit::event_loop::EventLoop>, - _window: &winit::window::Window, - renderer: &Arc, - _routines: &Arc, - _surface_format: rend3::types::TextureFormat, - ) { + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { let view_location = glam::Vec3::new(0.0, -1.5, 5.0); let view = glam::Mat4::from_euler(glam::EulerRot::XYZ, 0.0, 0.0, 0.0); let view = view * glam::Mat4::from_translation(view_location); // Set camera's location - renderer.set_camera_data(rend3::types::Camera { + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Perspective { vfov: 60.0, near: 0.1 }, view, }); @@ -65,7 +59,7 @@ impl rend3_framework::App for AnimationExample { let gltf_data = std::fs::read(path).unwrap(); let parent_directory = path.parent().unwrap(); let (loaded_scene, loaded_instance) = pollster::block_on(rend3_gltf::load_gltf( - renderer, + context.renderer, &gltf_data, &rend3_gltf::GltfLoadSettings::default(), |p| async move { rend3_gltf::filesystem_io_func(&parent_directory, &p).await }, @@ -75,7 +69,7 @@ impl rend3_framework::App for AnimationExample { // Create a single directional light // // We need to keep the directional light handle alive. - let directional_light_handle = renderer.add_directional_light(rend3::types::DirectionalLight { + let directional_light_handle = context.renderer.add_directional_light(rend3::types::DirectionalLight { color: glam::Vec3::ONE, intensity: 5.0, // Direction will be normalized @@ -98,7 +92,7 @@ impl rend3_framework::App for AnimationExample { let gltf_data = std::fs::read(path).unwrap(); let parent_directory = path.parent().unwrap(); let (loaded_scene, loaded_instance) = pollster::block_on(rend3_gltf::load_gltf( - renderer, + context.renderer, &gltf_data, &rend3_gltf::GltfLoadSettings::default(), |p| async move { rend3_gltf::filesystem_io_func(&parent_directory, &p).await }, @@ -116,49 +110,35 @@ impl rend3_framework::App for AnimationExample { self.animated_objects = vec![animated_object, animated_object2]; } - fn handle_event( - &mut self, - window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &rend3_routine::base::BaseRenderGraph, - surface: Option<&Arc>, - resolution: glam::UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { + #[allow(clippy::single_match)] match event { - // Close button was clicked, we should close. - rend3_framework::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. + // Render! + winit::event::Event::WindowEvent { + window_id: _, + event: WindowEvent::RedrawRequested, } => { - control_flow(winit::event_loop::ControlFlow::Exit); - } - rend3_framework::Event::MainEventsCleared => { let now = web_time::Instant::now(); self.animated_objects.iter_mut().for_each(|animated_object| { let delta = now.duration_since(animated_object.last_frame_time).as_secs_f32(); animated_object.last_frame_time = now; - update(renderer, delta, animated_object); + update(context.renderer, delta, animated_object); }); - window.request_redraw(); - } - // Render! - rend3_framework::Event::RedrawRequested(_) => { + context.window.request_redraw(); + // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Lock the routines - let pbr_routine = rend3_framework::lock(&routines.pbr); - let tonemapping_routine = rend3_framework::lock(&routines.tonemapping); + let pbr_routine = rend3_framework::lock(&context.routines.pbr); + let tonemapping_routine = rend3_framework::lock(&context.routines.tonemapping); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -168,10 +148,10 @@ impl rend3_framework::App for AnimationExample { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph without a skybox - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -182,7 +162,7 @@ impl rend3_framework::App for AnimationExample { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: SAMPLE_COUNT, }, }, @@ -193,7 +173,7 @@ impl rend3_framework::App for AnimationExample { ); // Dispatch a render using the built up rendergraph! - graph.execute(renderer, &mut eval_output); + graph.execute(context.renderer, &mut eval_output); // Present the frame frame.present(); diff --git a/examples/cube-no-framework/Cargo.toml b/examples/cube-no-framework/Cargo.toml index 3740bb42..d71f7e3d 100644 --- a/examples/cube-no-framework/Cargo.toml +++ b/examples/cube-no-framework/Cargo.toml @@ -25,7 +25,7 @@ rend3-routine = { version = "^0.3.0", path = "../../rend3-routine" } # Provides `block_on` to wait for futures from sync code pollster = "0.3" # windowing -winit = "0.28" +winit = "0.29.4" [target.'cfg(target_arch = "wasm32")'.dependencies] console_log = "1" diff --git a/examples/cube-no-framework/src/main.rs b/examples/cube-no-framework/src/main.rs index 471076b5..31c0cc47 100644 --- a/examples/cube-no-framework/src/main.rs +++ b/examples/cube-no-framework/src/main.rs @@ -60,7 +60,7 @@ fn main() { env_logger::init(); // Create event loop and window - let event_loop = winit::event_loop::EventLoop::new(); + let event_loop = winit::event_loop::EventLoop::new().unwrap(); let window = { let mut builder = winit::window::WindowBuilder::new(); builder = builder.with_title("rend3 cube"); @@ -176,76 +176,78 @@ fn main() { let mut resolution = glam::UVec2::new(window_size.width, window_size.height); - event_loop.run(move |event, _, control| match event { - // Close button was clicked, we should close. - winit::event::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. - } => { - *control = winit::event_loop::ControlFlow::Exit; - } - // Window was resized, need to resize renderer. - winit::event::Event::WindowEvent { - event: winit::event::WindowEvent::Resized(physical_size), - .. - } => { - resolution = glam::UVec2::new(physical_size.width, physical_size.height); - // Reconfigure the surface for the new size. - rend3::configure_surface( - &surface, - &renderer.device, - preferred_format, - glam::UVec2::new(resolution.x, resolution.y), - rend3::types::PresentMode::Fifo, - ); - // Tell the renderer about the new aspect ratio. - renderer.set_aspect_ratio(resolution.x as f32 / resolution.y as f32); - } - // Render! - winit::event::Event::MainEventsCleared => { - // Get a frame - let frame = surface.get_current_texture().unwrap(); - - // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); - // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); - - // Build a rendergraph - let mut graph = rend3::graph::RenderGraph::new(); - - // Import the surface texture into the render graph. - let frame_handle = - graph.add_imported_render_target(&frame, 0..1, 0..1, rend3::graph::ViewportRect::from_size(resolution)); - // Add the default rendergraph without a skybox - base_rendergraph.add_to_graph( - &mut graph, - rend3_routine::base::BaseRenderGraphInputs { - eval_output: &eval_output, - routines: rend3_routine::base::BaseRenderGraphRoutines { - pbr: &pbr_routine, - skybox: None, - tonemapping: &tonemapping_routine, + event_loop + .run(move |event, _event_loop_window_target| match event { + // Window was resized, need to resize renderer. + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(physical_size), + .. + } => { + resolution = glam::UVec2::new(physical_size.width, physical_size.height); + // Reconfigure the surface for the new size. + rend3::configure_surface( + &surface, + &renderer.device, + preferred_format, + glam::UVec2::new(resolution.x, resolution.y), + rend3::types::PresentMode::Fifo, + ); + // Tell the renderer about the new aspect ratio. + renderer.set_aspect_ratio(resolution.x as f32 / resolution.y as f32); + } + // Render! + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + // Get a frame + let frame = surface.get_current_texture().unwrap(); + + // Swap the instruction buffers so that our frame's changes can be processed. + renderer.swap_instruction_buffers(); + // Evaluate our frame's world-change instructions + let mut eval_output = renderer.evaluate_instructions(); + + // Build a rendergraph + let mut graph = rend3::graph::RenderGraph::new(); + + // Import the surface texture into the render graph. + let frame_handle = graph.add_imported_render_target( + &frame, + 0..1, + 0..1, + rend3::graph::ViewportRect::from_size(resolution), + ); + // Add the default rendergraph without a skybox + base_rendergraph.add_to_graph( + &mut graph, + rend3_routine::base::BaseRenderGraphInputs { + eval_output: &eval_output, + routines: rend3_routine::base::BaseRenderGraphRoutines { + pbr: &pbr_routine, + skybox: None, + tonemapping: &tonemapping_routine, + }, + target: rend3_routine::base::OutputRenderTarget { + handle: frame_handle, + resolution, + samples: rend3::types::SampleCount::One, + }, }, - target: rend3_routine::base::OutputRenderTarget { - handle: frame_handle, - resolution, - samples: rend3::types::SampleCount::One, + rend3_routine::base::BaseRenderGraphSettings { + ambient_color: glam::Vec4::ZERO, + clear_color: glam::Vec4::new(0.10, 0.05, 0.10, 1.0), // Nice scene-referred purple }, - }, - rend3_routine::base::BaseRenderGraphSettings { - ambient_color: glam::Vec4::ZERO, - clear_color: glam::Vec4::new(0.10, 0.05, 0.10, 1.0), // Nice scene-referred purple - }, - ); - - // Dispatch a render using the built up rendergraph! - graph.execute(&renderer, &mut eval_output); - - // Present the frame - frame.present(); - } - // Other events we don't care about - _ => {} - }); + ); + + // Dispatch a render using the built up rendergraph! + graph.execute(&renderer, &mut eval_output); + + // Present the frame + frame.present(); + } + // Other events we don't care about + _ => {} + }) + .expect(""); } diff --git a/examples/cube/Cargo.toml b/examples/cube/Cargo.toml index 09797839..29d59db0 100644 --- a/examples/cube/Cargo.toml +++ b/examples/cube/Cargo.toml @@ -28,7 +28,7 @@ rend3-routine = { version = "^0.3.0", path = "../../rend3-routine" } # Framework that deals with the event loop, setting up the renderer, and platform differences. rend3-framework = { version = "^0.3.0", path = "../../rend3-framework" } # windowing -winit = "0.28" +winit = "0.29.4" [target.'cfg(target_arch = "wasm32")'.dependencies] console_log = "1" diff --git a/examples/cube/src/lib.rs b/examples/cube/src/lib.rs index 1446dde7..fcba6468 100644 --- a/examples/cube/src/lib.rs +++ b/examples/cube/src/lib.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use winit::event::WindowEvent; fn vertex(pos: [f32; 3]) -> glam::Vec3 { glam::Vec3::from(pos) @@ -69,14 +69,7 @@ impl rend3_framework::App for CubeExample { SAMPLE_COUNT } - fn setup( - &mut self, - _event_loop: &winit::event_loop::EventLoop>, - _window: &winit::window::Window, - renderer: &Arc, - _routines: &Arc, - _surface_format: rend3::types::TextureFormat, - ) { + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { // Create mesh and calculate smooth normals based on vertices let mesh = create_mesh(); @@ -84,14 +77,14 @@ impl rend3_framework::App for CubeExample { // // All handles are refcounted, so we only need to hang onto the handle until we // make an object. - let mesh_handle = renderer.add_mesh(mesh).unwrap(); + let mesh_handle = context.renderer.add_mesh(mesh).unwrap(); // Add PBR material with all defaults except a single color. let material = rend3_routine::pbr::PbrMaterial { albedo: rend3_routine::pbr::AlbedoComponent::Value(glam::Vec4::new(0.5, 0.5, 0.5, 1.0)), ..rend3_routine::pbr::PbrMaterial::default() }; - let material_handle = renderer.add_material(material); + let material_handle = context.renderer.add_material(material); // Combine the mesh and the material with a location to give an object. let object = rend3::types::Object { @@ -103,14 +96,14 @@ impl rend3_framework::App for CubeExample { // even if they are deleted. // // We need to keep the object handle alive. - self.object_handle = Some(renderer.add_object(object)); + self.object_handle = Some(context.renderer.add_object(object)); let view_location = glam::Vec3::new(3.0, 3.0, -5.0); let view = glam::Mat4::from_euler(glam::EulerRot::XYZ, -0.55, 0.5, 0.0); let view = view * glam::Mat4::from_translation(-view_location); // Set camera's location - renderer.set_camera_data(rend3::types::Camera { + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Perspective { vfov: 60.0, near: 0.1 }, view, }); @@ -118,7 +111,7 @@ impl rend3_framework::App for CubeExample { // Create a single directional light // // We need to keep the directional light handle alive. - self.directional_light_handle = Some(renderer.add_directional_light(rend3::types::DirectionalLight { + self.directional_light_handle = Some(context.renderer.add_directional_light(rend3::types::DirectionalLight { color: glam::Vec3::ONE, intensity: 1.0, // Direction will be normalized @@ -135,7 +128,7 @@ impl rend3_framework::App for CubeExample { for (position, color) in lights { self.point_lights - .push(renderer.add_point_light(rend3::types::PointLight { + .push(context.renderer.add_point_light(rend3::types::PointLight { position, color, radius: 2.0, @@ -144,41 +137,25 @@ impl rend3_framework::App for CubeExample { } } - fn handle_event( - &mut self, - window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &rend3_routine::base::BaseRenderGraph, - surface: Option<&Arc>, - resolution: glam::UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { + #[allow(clippy::single_match)] match event { - // Close button was clicked, we should close. - rend3_framework::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. - } => { - control_flow(winit::event_loop::ControlFlow::Exit); - } - rend3_framework::Event::MainEventsCleared => { - window.request_redraw(); - } // Render! - rend3_framework::Event::RedrawRequested(_) => { + winit::event::Event::WindowEvent { + window_id: _, + event: WindowEvent::RedrawRequested, + } => { // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Lock the routines - let pbr_routine = rend3_framework::lock(&routines.pbr); - let tonemapping_routine = rend3_framework::lock(&routines.tonemapping); + let pbr_routine = rend3_framework::lock(&context.routines.pbr); + let tonemapping_routine = rend3_framework::lock(&context.routines.tonemapping); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -188,10 +165,10 @@ impl rend3_framework::App for CubeExample { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph without a skybox - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -202,7 +179,7 @@ impl rend3_framework::App for CubeExample { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: SAMPLE_COUNT, }, }, @@ -213,10 +190,12 @@ impl rend3_framework::App for CubeExample { ); // Dispatch a render using the built up rendergraph! - graph.execute(renderer, &mut eval_output); + graph.execute(context.renderer, &mut eval_output); // Present the frame frame.present(); + + context.window.request_redraw() } // Other events we don't care about _ => {} diff --git a/examples/egui/Cargo.toml b/examples/egui/Cargo.toml index e443ed20..5968016d 100644 --- a/examples/egui/Cargo.toml +++ b/examples/egui/Cargo.toml @@ -13,9 +13,9 @@ path = "src/main.rs" [dependencies] # The egui immediate mode gui library -egui = "0.24.0" +egui = {git = "https://github.com/emilk/egui.git", branch="master"} # Winit integration with egui (turn off the clipboard feature) -egui-winit = { version = "0.24", default-features = false, features = ["links", "wayland"] } +egui-winit = { git = "https://github.com/emilk/egui.git", branch="master", default-features = false, features = ["links", "wayland"] } # logging env_logger = { version = "0.10", default-features = false, features = ["auto-color", "humantime"] } # Linear algebra library @@ -31,7 +31,7 @@ rend3-framework = { version = "^0.3.0", path = "../../rend3-framework" } # Programmable render list that dictates how the scene renders rend3-routine = { version = "^0.3.0",path = "../../rend3-routine" } # Windowing -winit = "0.28" +winit = "0.29.4" # Opening URL's webbrowser = "0.8.2" # Creating textures @@ -39,4 +39,4 @@ wgpu = "0.18" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # Winit integration with egui -egui-winit = { version = "0.24", default-features = false, features = ["clipboard", "links", "wayland"] } +egui-winit = { git = "https://github.com/emilk/egui.git", branch="master", default-features = false, features = ["clipboard", "links", "wayland"] } diff --git a/examples/egui/src/main.rs b/examples/egui/src/main.rs index e4011b4d..cc5b3200 100644 --- a/examples/egui/src/main.rs +++ b/examples/egui/src/main.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use winit::event::WindowEvent; struct EguiExampleData { _object_handle: rend3::types::ObjectHandle, @@ -25,24 +25,17 @@ impl rend3_framework::App for EguiExample { SAMPLE_COUNT } - fn setup( - &mut self, - _event_loop: &winit::event_loop::EventLoop>, - window: &winit::window::Window, - renderer: &Arc, - _routines: &Arc, - surface_format: rend3::types::TextureFormat, - ) { - let window_size = window.inner_size(); + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { + let window_size = context.window.inner_size(); // Create the egui render routine let mut egui_routine = rend3_egui::EguiRenderRoutine::new( - renderer, - surface_format, + context.renderer, + context.surface_format, rend3::types::SampleCount::One, window_size.width, window_size.height, - window.scale_factor() as f32, + context.window.scale_factor() as f32, ); // Create mesh and calculate smooth normals based on vertices @@ -52,7 +45,7 @@ impl rend3_framework::App for EguiExample { // // All handles are refcounted, so we only need to hang onto the handle until we // make an object. - let mesh_handle = renderer.add_mesh(mesh).unwrap(); + let mesh_handle = context.renderer.add_mesh(mesh).unwrap(); // Add PBR material with all defaults except a single color. let material = rend3_routine::pbr::PbrMaterial { @@ -60,7 +53,7 @@ impl rend3_framework::App for EguiExample { transparency: rend3_routine::pbr::Transparency::Blend, ..rend3_routine::pbr::PbrMaterial::default() }; - let material_handle = renderer.add_material(material); + let material_handle = context.renderer.add_material(material); // Combine the mesh and the material with a location to give an object. let object = rend3::types::Object { @@ -73,7 +66,7 @@ impl rend3_framework::App for EguiExample { // even if they are deleted. // // We need to keep the object handle alive. - let _object_handle = renderer.add_object(object); + let _object_handle = context.renderer.add_object(object); let camera_pitch = std::f32::consts::FRAC_PI_4; let camera_yaw = -std::f32::consts::FRAC_PI_4; @@ -84,7 +77,7 @@ impl rend3_framework::App for EguiExample { let view = view * glam::Mat4::from_translation((-camera_location).into()); // Set camera location data - renderer.set_camera_data(rend3::types::Camera { + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Perspective { vfov: 60.0, near: 0.1 }, view, }); @@ -92,7 +85,7 @@ impl rend3_framework::App for EguiExample { // Create a single directional light // // We need to keep the directional light handle alive. - let _directional_handle = renderer.add_directional_light(rend3::types::DirectionalLight { + let _directional_handle = context.renderer.add_directional_light(rend3::types::DirectionalLight { color: glam::Vec3::ONE, intensity: 10.0, // Direction will be normalized @@ -102,12 +95,13 @@ impl rend3_framework::App for EguiExample { }); // Create the egui context - let context = egui::Context::default(); + let egui_context = egui::Context::default(); // Create the winit/egui integration. let platform = egui_winit::State::new( + egui_context.clone(), egui::ViewportId::default(), - &window, - Some(window.scale_factor() as f32), + &context.window, + Some(context.window.scale_factor() as f32), None, ); @@ -123,7 +117,7 @@ impl rend3_framework::App for EguiExample { self.rust_logo = rend3_egui::EguiRenderRoutine::create_egui_texture( &mut egui_routine.internal, - renderer, + context.renderer, format, &image_rgba, dimensions, @@ -138,35 +132,28 @@ impl rend3_framework::App for EguiExample { _directional_handle, egui_routine, - context, + context: egui_context, platform, color, }); } - fn handle_event( - &mut self, - window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &rend3_routine::base::BaseRenderGraph, - surface: Option<&Arc>, - resolution: glam::UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { let data = self.data.as_mut().unwrap(); match event { - rend3_framework::Event::RedrawRequested(..) => { - data.context.begin_frame(data.platform.take_egui_input(window)); + winit::event::Event::WindowEvent { + window_id: _, + event: WindowEvent::RedrawRequested, + } => { + data.context.begin_frame(data.platform.take_egui_input(context.window)); // Insert egui commands here let ctx = &data.context; egui::Window::new("Change color").resizable(true).show(ctx, |ui| { ui.label("Change the color of the cube"); if ui.color_edit_button_rgba_unmultiplied(&mut data.color).changed() { - renderer.update_material( + context.renderer.update_material( &data.material_handle.clone(), rend3_routine::pbr::PbrMaterial { albedo: rend3_routine::pbr::AlbedoComponent::Value(glam::Vec4::from(data.color)), @@ -192,7 +179,7 @@ impl rend3_framework::App for EguiExample { let egui::FullOutput { shapes, textures_delta, .. } = data.context.end_frame(); - let paint_jobs = data.context.tessellate(shapes, window.scale_factor() as f32); + let paint_jobs = data.context.tessellate(shapes, context.window.scale_factor() as f32); let input = rend3_egui::Input { clipped_meshes: &paint_jobs, @@ -201,16 +188,16 @@ impl rend3_framework::App for EguiExample { }; // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Lock the routines - let pbr_routine = rend3_framework::lock(&routines.pbr); - let tonemapping_routine = rend3_framework::lock(&routines.tonemapping); + let pbr_routine = rend3_framework::lock(&context.routines.pbr); + let tonemapping_routine = rend3_framework::lock(&context.routines.tonemapping); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -220,10 +207,10 @@ impl rend3_framework::App for EguiExample { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph without a skybox - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -234,7 +221,7 @@ impl rend3_framework::App for EguiExample { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: SAMPLE_COUNT, }, }, @@ -248,29 +235,24 @@ impl rend3_framework::App for EguiExample { data.egui_routine.add_to_graph(&mut graph, input, frame_handle); // Dispatch a render using the built up rendergraph! - graph.execute(renderer, &mut eval_output); + graph.execute(context.renderer, &mut eval_output); // Present the frame frame.present(); - control_flow(winit::event_loop::ControlFlow::Poll); + context.window.request_redraw(); } - rend3_framework::Event::MainEventsCleared => { - window.request_redraw(); - } - rend3_framework::Event::WindowEvent { event, .. } => { + winit::event::Event::WindowEvent { event, .. } => { // Pass the window events to the egui integration. - if data.platform.on_window_event(&data.context, &event).consumed { + if data.platform.on_window_event(context.window, &event).consumed { return; } + #[allow(clippy::single_match)] match event { winit::event::WindowEvent::Resized(size) => { data.egui_routine - .resize(size.width, size.height, window.scale_factor() as f32); - } - winit::event::WindowEvent::CloseRequested => { - control_flow(winit::event_loop::ControlFlow::Exit); + .resize(size.width, size.height, context.window.scale_factor() as f32); } _ => {} } diff --git a/examples/scene-viewer/Cargo.toml b/examples/scene-viewer/Cargo.toml index b4da83d8..9ed22f14 100644 --- a/examples/scene-viewer/Cargo.toml +++ b/examples/scene-viewer/Cargo.toml @@ -64,7 +64,7 @@ tracy-client = { version = "0.16", optional = true } web-time = "0.2" wgpu = "0.18.0" wgpu-profiler = "0.15.0" -winit = "0.28" +winit = "0.29.4" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4" diff --git a/examples/scene-viewer/src/lib.rs b/examples/scene-viewer/src/lib.rs index 870cb632..ed2a5a1f 100644 --- a/examples/scene-viewer/src/lib.rs +++ b/examples/scene-viewer/src/lib.rs @@ -12,11 +12,15 @@ use rend3::{ }; use rend3_framework::{lock, AssetPath, Mutex}; use rend3_gltf::GltfSceneInstance; -use rend3_routine::{base::BaseRenderGraph, pbr::NormalTextureYDirection, skybox::SkyboxRoutine}; +use rend3_routine::{pbr::NormalTextureYDirection, skybox::SkyboxRoutine}; use web_time::Instant; use wgpu_profiler::GpuTimerScopeResult; +#[cfg(target_arch = "wasm32")] +use winit::keyboard::PhysicalKey::Code; +#[cfg(not(target_arch = "wasm32"))] +use winit::platform::scancode::PhysicalKeyExtScancode; use winit::{ - event::{DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, WindowEvent}, + event::{DeviceEvent, ElementState, Event, KeyEvent, MouseButton, WindowEvent}, window::{Fullscreen, WindowBuilder}, }; @@ -453,18 +457,11 @@ impl rend3_framework::App for SceneViewer { } } - fn setup<'a>( - &'a mut self, - _event_loop: &winit::event_loop::EventLoop>, - window: &'a winit::window::Window, - renderer: &'a Arc, - routines: &'a Arc, - _surface_format: rend3::types::TextureFormat, - ) { - self.grabber = Some(rend3_framework::Grabber::new(window)); + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { + self.grabber = Some(rend3_framework::Grabber::new(context.window)); if let Some(direction) = self.directional_light_direction { - self.directional_light = Some(renderer.add_directional_light(DirectionalLight { + self.directional_light = Some(context.renderer.add_directional_light(DirectionalLight { color: Vec3::splat(1.0), intensity: self.directional_light_intensity, direction, @@ -475,8 +472,8 @@ impl rend3_framework::App for SceneViewer { let gltf_settings = self.gltf_settings; let file_to_load = self.file_to_load.take(); - let renderer = Arc::clone(renderer); - let routines = Arc::clone(routines); + let renderer = Arc::clone(context.renderer); + let routines = Arc::clone(context.routines); spawn(async move { let loader = rend3_framework::AssetLoader::new_local( concat!(env!("CARGO_MANIFEST_DIR"), "/resources/"), @@ -500,20 +497,13 @@ impl rend3_framework::App for SceneViewer { }); } - fn handle_event( - &mut self, - window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &BaseRenderGraph, - surface: Option<&Arc>, - resolution: UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { match event { - Event::MainEventsCleared => { - profiling::scope!("MainEventsCleared"); + Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + profiling::scope!("RedrawRequested"); let now = Instant::now(); let delta_time = now - self.timestamp_last_frame; @@ -584,7 +574,7 @@ impl rend3_framework::App for SceneViewer { } if button_pressed(&self.scancode_status, platform::Scancodes::ESCAPE) { - self.grabber.as_mut().unwrap().request_ungrab(window); + self.grabber.as_mut().unwrap().request_ungrab(context.window); } if button_pressed(&self.scancode_status, platform::Scancodes::P) { @@ -597,30 +587,27 @@ impl rend3_framework::App for SceneViewer { } } - window.request_redraw() - } - Event::RedrawRequested(_) => { let view = Mat4::from_euler(glam::EulerRot::XYZ, -self.camera_pitch, -self.camera_yaw, 0.0); let view = view * Mat4::from_translation((-self.camera_location).into()); - renderer.set_camera_data(Camera { + context.renderer.set_camera_data(Camera { projection: CameraProjection::Perspective { vfov: 60.0, near: 0.1 }, view, }); // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Lock all the routines - let pbr_routine = lock(&routines.pbr); - let mut skybox_routine = lock(&routines.skybox); - let tonemapping_routine = lock(&routines.tonemapping); + let pbr_routine = lock(&context.routines.pbr); + let mut skybox_routine = lock(&context.routines.skybox); + let tonemapping_routine = lock(&context.routines.tonemapping); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Evaluate changes to routines. - skybox_routine.evaluate(renderer); + skybox_routine.evaluate(context.renderer); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -629,10 +616,10 @@ impl rend3_framework::App for SceneViewer { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -643,7 +630,7 @@ impl rend3_framework::App for SceneViewer { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: self.samples, }, }, @@ -654,28 +641,37 @@ impl rend3_framework::App for SceneViewer { ); // Dispatch a render using the built up rendergraph! - self.previous_profiling_stats = graph.execute(renderer, &mut eval_output); + self.previous_profiling_stats = graph.execute(context.renderer, &mut eval_output); frame.present(); // mark the end of the frame for tracy/other profilers profiling::finish_frame!(); + + context.window.request_redraw() } Event::WindowEvent { event: WindowEvent::Focused(focus), .. } => { if !focus { - self.grabber.as_mut().unwrap().request_ungrab(window); + self.grabber.as_mut().unwrap().request_ungrab(context.window); } } + Event::WindowEvent { event: WindowEvent::KeyboardInput { - input: KeyboardInput { scancode, state, .. }, + event: KeyEvent { + physical_key, state, .. + }, .. }, .. } => { + #[cfg(not(target_arch = "wasm32"))] + let scancode = PhysicalKeyExtScancode::to_scancode(physical_key).unwrap(); + #[cfg(target_arch = "wasm32")] + let scancode = if let Code(kk) = physical_key { kk as u32 } else { 0 }; log::info!("WE scancode {:x}", scancode); self.scancode_status.insert( scancode, @@ -685,6 +681,7 @@ impl rend3_framework::App for SceneViewer { }, ); } + Event::WindowEvent { event: WindowEvent::MouseInput { @@ -697,7 +694,7 @@ impl rend3_framework::App for SceneViewer { let grabber = self.grabber.as_mut().unwrap(); if !grabber.grabbed() { - grabber.request_grab(window); + grabber.request_grab(context.window); } } Event::DeviceEvent { @@ -737,12 +734,6 @@ impl rend3_framework::App for SceneViewer { std::f32::consts::FRAC_PI_2 - 0.0001, ) } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - control_flow(winit::event_loop::ControlFlow::Exit); - } _ => {} } } diff --git a/examples/scene-viewer/src/platform.rs b/examples/scene-viewer/src/platform.rs index b357d40b..1685e2e4 100644 --- a/examples/scene-viewer/src/platform.rs +++ b/examples/scene-viewer/src/platform.rs @@ -1,5 +1,4 @@ #![allow(non_snake_case, unused)] - cfg_if::cfg_if!( if #[cfg(target_os = "macos")] { // https://stackoverflow.com/a/16125341 reference @@ -21,20 +20,21 @@ cfg_if::cfg_if!( } } else if #[cfg(target_arch = "wasm32")] { pub mod Scancodes { - pub const W: u32 = 0x57; - pub const A: u32 = 0x41; - pub const S: u32 = 0x53; - pub const D: u32 = 0x44; - pub const Q: u32 = 0x51; - pub const Z: u32 = 0x5a; - pub const P: u32 = 0x50; - pub const SEMICOLON: u32 = 0xba; - pub const QUOTE: u32 = 0xde; - pub const COMMA: u32 = 0xbc; - pub const PERIOD: u32 = 0xbe; - pub const SHIFT: u32 = 0x10; - pub const ESCAPE: u32 = 0x1b; - pub const LALT: u32 = 0x12; + use winit::keyboard::KeyCode; + pub const W: u32 = KeyCode::KeyW as u32; + pub const A: u32 = KeyCode::KeyA as u32; + pub const S: u32 = KeyCode::KeyS as u32; + pub const D: u32 = KeyCode::KeyD as u32; + pub const Q: u32 = KeyCode::KeyQ as u32; + pub const Z: u32 = KeyCode::KeyZ as u32; + pub const P: u32 = KeyCode::KeyP as u32; + pub const SEMICOLON: u32 = KeyCode::Semicolon as u32; + pub const QUOTE: u32 = KeyCode::Quote as u32; + pub const COMMA: u32 = KeyCode::Comma as u32; + pub const PERIOD: u32 = KeyCode::Period as u32; + pub const SHIFT: u32 = KeyCode::ShiftLeft as u32; + pub const ESCAPE: u32 = KeyCode::Escape as u32; + pub const LALT: u32 = KeyCode::AltLeft as u32; } } else { pub mod Scancodes { diff --git a/examples/skinning/Cargo.toml b/examples/skinning/Cargo.toml index 8fd5b352..40c1ad78 100644 --- a/examples/skinning/Cargo.toml +++ b/examples/skinning/Cargo.toml @@ -32,7 +32,7 @@ rend3-framework = { version = "^0.3.0", path = "../../rend3-framework" } # Import gltf models rend3-gltf = { version = "^0.3.0", path = "../../rend3-gltf" } # windowing -winit = "0.28" +winit = "0.29.4" [target.'cfg(target_arch = "wasm32")'.dependencies] console_log = "1" diff --git a/examples/skinning/src/lib.rs b/examples/skinning/src/lib.rs index fbd33350..e0735a26 100644 --- a/examples/skinning/src/lib.rs +++ b/examples/skinning/src/lib.rs @@ -1,6 +1,7 @@ -use std::{path::Path, sync::Arc, time::Instant}; +use std::{path::Path, time::Instant}; use rend3_gltf::GltfSceneInstance; +use winit::event::WindowEvent; const SAMPLE_COUNT: rend3::types::SampleCount = rend3::types::SampleCount::One; @@ -63,14 +64,7 @@ impl rend3_framework::App for SkinningExample { SAMPLE_COUNT } - fn setup( - &mut self, - _event_loop: &winit::event_loop::EventLoop>, - _window: &winit::window::Window, - renderer: &Arc, - _routines: &Arc, - _surface_format: rend3::types::TextureFormat, - ) { + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { // Store the startup time. Use later to animate the joint rotation self.start_time = Some(Instant::now()); @@ -79,7 +73,7 @@ impl rend3_framework::App for SkinningExample { let view = view * glam::Mat4::from_translation(-view_location); // Set camera's location - renderer.set_camera_data(rend3::types::Camera { + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Perspective { vfov: 60.0, near: 0.1 }, view, }); @@ -89,7 +83,7 @@ impl rend3_framework::App for SkinningExample { let gltf_data = std::fs::read(path).unwrap(); let parent_directory = path.parent().unwrap(); let (loaded_scene, loaded_instance) = pollster::block_on(rend3_gltf::load_gltf( - renderer, + context.renderer, &gltf_data, &rend3_gltf::GltfLoadSettings::default(), |p| async move { rend3_gltf::filesystem_io_func(&parent_directory, &p).await }, @@ -108,7 +102,7 @@ impl rend3_framework::App for SkinningExample { // Create a single directional light // // We need to keep the directional light handle alive. - self.directional_light_handle = Some(renderer.add_directional_light(rend3::types::DirectionalLight { + self.directional_light_handle = Some(context.renderer.add_directional_light(rend3::types::DirectionalLight { color: glam::Vec3::ONE, intensity: 10.0, // Direction will be normalized @@ -118,42 +112,27 @@ impl rend3_framework::App for SkinningExample { })); } - fn handle_event( - &mut self, - window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &rend3_routine::base::BaseRenderGraph, - surface: Option<&Arc>, - resolution: glam::UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { + #[allow(clippy::single_match)] match event { - // Close button was clicked, we should close. - rend3_framework::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. - } => { - control_flow(winit::event_loop::ControlFlow::Exit); - } - rend3_framework::Event::MainEventsCleared => { - self.update_skeleton(renderer); - window.request_redraw(); - } // Render! - rend3_framework::Event::RedrawRequested(_) => { + winit::event::Event::WindowEvent { + window_id: _, + event: WindowEvent::RedrawRequested, + } => { + self.update_skeleton(context.renderer); + // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Lock the routines - let pbr_routine = rend3_framework::lock(&routines.pbr); - let tonemapping_routine = rend3_framework::lock(&routines.tonemapping); + let pbr_routine = rend3_framework::lock(&context.routines.pbr); + let tonemapping_routine = rend3_framework::lock(&context.routines.tonemapping); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -162,10 +141,10 @@ impl rend3_framework::App for SkinningExample { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph without a skybox - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -176,7 +155,7 @@ impl rend3_framework::App for SkinningExample { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: SAMPLE_COUNT, }, }, @@ -187,9 +166,11 @@ impl rend3_framework::App for SkinningExample { ); // Dispatch a render using the built up rendergraph! - graph.execute(renderer, &mut eval_output); + graph.execute(context.renderer, &mut eval_output); frame.present(); + + context.window.request_redraw(); } // Other events we don't care about _ => {} diff --git a/examples/static-gltf/Cargo.toml b/examples/static-gltf/Cargo.toml index cdc607f6..74bbccc9 100644 --- a/examples/static-gltf/Cargo.toml +++ b/examples/static-gltf/Cargo.toml @@ -27,4 +27,4 @@ rend3-framework = { version = "^0.3.0", path = "../../rend3-framework" } # Programmable render list that dictates how the scene renders rend3-routine = { version = "^0.3.0", path = "../../rend3-routine" } # windowing -winit = "0.28" +winit = "0.29.4" diff --git a/examples/static-gltf/src/main.rs b/examples/static-gltf/src/main.rs index bfd3b9f5..7a0e517e 100644 --- a/examples/static-gltf/src/main.rs +++ b/examples/static-gltf/src/main.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use winit::event::WindowEvent; + fn load_gltf( renderer: &Arc, path: &'static str, @@ -64,18 +66,11 @@ impl rend3_framework::App for GltfExample { SAMPLE_COUNT } - fn setup( - &mut self, - _event_loop: &winit::event_loop::EventLoop>, - _window: &winit::window::Window, - renderer: &Arc, - _routines: &Arc, - _surface_format: rend3::types::TextureFormat, - ) { + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { // Create mesh and calculate smooth normals based on vertices. // // We do not need to keep these handles alive once we make the object - let (mesh, material) = load_gltf(renderer, concat!(env!("CARGO_MANIFEST_DIR"), "/data.glb")); + let (mesh, material) = load_gltf(context.renderer, concat!(env!("CARGO_MANIFEST_DIR"), "/data.glb")); // Combine the mesh and the material with a location to give an object. let object = rend3::types::Object { @@ -84,14 +79,14 @@ impl rend3_framework::App for GltfExample { transform: glam::Mat4::from_scale(glam::Vec3::new(1.0, 1.0, -1.0)), }; // We need to keep the object alive. - self.object_handle = Some(renderer.add_object(object)); + self.object_handle = Some(context.renderer.add_object(object)); let view_location = glam::Vec3::new(3.0, 3.0, -5.0); let view = glam::Mat4::from_euler(glam::EulerRot::XYZ, -0.55, 0.5, 0.0); let view = view * glam::Mat4::from_translation(-view_location); // Set camera's location - renderer.set_camera_data(rend3::types::Camera { + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Perspective { vfov: 60.0, near: 0.1 }, view, }); @@ -99,7 +94,7 @@ impl rend3_framework::App for GltfExample { // Create a single directional light // // We need to keep the directional light handle alive. - self.directional_light_handle = Some(renderer.add_directional_light(rend3::types::DirectionalLight { + self.directional_light_handle = Some(context.renderer.add_directional_light(rend3::types::DirectionalLight { color: glam::Vec3::ONE, intensity: 4.0, // Direction will be normalized @@ -109,41 +104,25 @@ impl rend3_framework::App for GltfExample { })); } - fn handle_event( - &mut self, - window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &rend3_routine::base::BaseRenderGraph, - surface: Option<&Arc>, - resolution: glam::UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { + #[allow(clippy::single_match)] match event { - // Close button was clicked, we should close. - rend3_framework::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. - } => { - control_flow(winit::event_loop::ControlFlow::Exit); - } - rend3_framework::Event::MainEventsCleared => { - window.request_redraw(); - } // Render! - rend3_framework::Event::RedrawRequested(..) => { + winit::event::Event::WindowEvent { + window_id: _, + event: WindowEvent::RedrawRequested, + } => { // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Lock the routines - let pbr_routine = rend3_framework::lock(&routines.pbr); - let tonemapping_routine = rend3_framework::lock(&routines.tonemapping); + let pbr_routine = rend3_framework::lock(&context.routines.pbr); + let tonemapping_routine = rend3_framework::lock(&context.routines.tonemapping); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -153,10 +132,10 @@ impl rend3_framework::App for GltfExample { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph without a skybox - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -167,7 +146,7 @@ impl rend3_framework::App for GltfExample { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: SAMPLE_COUNT, }, }, @@ -177,10 +156,12 @@ impl rend3_framework::App for GltfExample { }, ); // Dispatch a render using the built up rendergraph! - graph.execute(renderer, &mut eval_output); + graph.execute(context.renderer, &mut eval_output); // Present the frame frame.present(); + + context.window.request_redraw(); } // Other events we don't care about _ => {} diff --git a/examples/textured-quad/Cargo.toml b/examples/textured-quad/Cargo.toml index cdf2fc71..0caac72f 100644 --- a/examples/textured-quad/Cargo.toml +++ b/examples/textured-quad/Cargo.toml @@ -25,6 +25,6 @@ rend3-framework = { version = "^0.3.0", path = "../../rend3-framework" } # Programmable render list that dictates how the scene renders rend3-routine = { version = "^0.3.0", path = "../../rend3-routine" } # windowing -winit = "0.28" +winit = "0.29.4" # Load image image = { version = "0.24", default-features = false, features = ["png"]} diff --git a/examples/textured-quad/src/main.rs b/examples/textured-quad/src/main.rs index 26906b15..9723371e 100644 --- a/examples/textured-quad/src/main.rs +++ b/examples/textured-quad/src/main.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use image::GenericImageView; fn vertex(pos: [f32; 3]) -> glam::Vec3 { @@ -47,14 +45,7 @@ impl rend3_framework::App for TexturedQuadExample { SAMPLE_COUNT } - fn setup( - &mut self, - _event_loop: &winit::event_loop::EventLoop>, - window: &winit::window::Window, - renderer: &Arc, - _routines: &Arc, - _surface_format: rend3::types::TextureFormat, - ) { + fn setup(&mut self, context: rend3_framework::SetupContext<'_>) { // Create mesh and calculate smooth normals based on vertices let mesh = create_quad(300.0); @@ -62,7 +53,7 @@ impl rend3_framework::App for TexturedQuadExample { // // All handles are refcounted, so we only need to hang onto the handle until we // make an object. - let mesh_handle = renderer.add_mesh(mesh).unwrap(); + let mesh_handle = context.renderer.add_mesh(mesh).unwrap(); // Add texture to renderer's world. let image_checker = @@ -76,7 +67,7 @@ impl rend3_framework::App for TexturedQuadExample { mip_count: rend3::types::MipmapCount::ONE, mip_source: rend3::types::MipmapSource::Uploaded, }; - let texture_checker_handle = renderer.add_texture_2d(texture_checker).unwrap(); + let texture_checker_handle = context.renderer.add_texture_2d(texture_checker).unwrap(); // Add PBR material with all defaults except a single color. let material = rend3_routine::pbr::PbrMaterial { @@ -85,7 +76,7 @@ impl rend3_framework::App for TexturedQuadExample { sample_type: rend3_routine::pbr::SampleType::Nearest, ..rend3_routine::pbr::PbrMaterial::default() }; - let material_handle = renderer.add_material(material); + let material_handle = context.renderer.add_material(material); // Combine the mesh and the material with a location to give an object. let object = rend3::types::Object { @@ -102,20 +93,17 @@ impl rend3_framework::App for TexturedQuadExample { // even if they are deleted. // // We need to keep the object handle alive. - let _object_handle = renderer.add_object(object); + let _object_handle = context.renderer.add_object(object); let view_location = glam::Vec3::new(0.0, 0.0, -1.0); let view = glam::Mat4::from_euler(glam::EulerRot::XYZ, 0.0, 0.0, 0.0); let view = view * glam::Mat4::from_translation(-view_location); // Set camera's location - renderer.set_camera_data(rend3::types::Camera { + let inner_size = context.window.inner_size(); + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Orthographic { - size: glam::Vec3A::new( - window.inner_size().width as f32, - window.inner_size().height as f32, - CAMERA_DEPTH, - ), + size: glam::Vec3A::new(inner_size.width as f32, inner_size.width as f32, CAMERA_DEPTH), }, view, }); @@ -123,25 +111,8 @@ impl rend3_framework::App for TexturedQuadExample { self.data = Some(TexturedQuadExampleData { _object_handle, view }) } - fn handle_event( - &mut self, - _window: &winit::window::Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &rend3_routine::base::BaseRenderGraph, - surface: Option<&Arc>, - resolution: glam::UVec2, - event: rend3_framework::Event<'_, ()>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { + fn handle_event(&mut self, context: rend3_framework::EventContext<'_>, event: winit::event::Event<()>) { match event { - // Close button was clicked, we should close. - winit::event::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. - } => { - control_flow(winit::event_loop::ControlFlow::Exit); - } // Window was resized, need to resize renderer. winit::event::Event::WindowEvent { event: winit::event::WindowEvent::Resized(size), @@ -149,7 +120,7 @@ impl rend3_framework::App for TexturedQuadExample { } => { let size = glam::UVec2::new(size.width, size.height); // Reset camera - renderer.set_camera_data(rend3::types::Camera { + context.renderer.set_camera_data(rend3::types::Camera { projection: rend3::types::CameraProjection::Orthographic { size: glam::Vec3A::new(size.x as f32, size.y as f32, CAMERA_DEPTH), }, @@ -157,18 +128,21 @@ impl rend3_framework::App for TexturedQuadExample { }); } // Render! - winit::event::Event::MainEventsCleared => { + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { // Get a frame - let frame = surface.unwrap().get_current_texture().unwrap(); + let frame = context.surface.unwrap().get_current_texture().unwrap(); // Swap the instruction buffers so that our frame's changes can be processed. - renderer.swap_instruction_buffers(); + context.renderer.swap_instruction_buffers(); // Evaluate our frame's world-change instructions - let mut eval_output = renderer.evaluate_instructions(); + let mut eval_output = context.renderer.evaluate_instructions(); // Lock the routines - let pbr_routine = rend3_framework::lock(&routines.pbr); - let tonemapping_routine = rend3_framework::lock(&routines.tonemapping); + let pbr_routine = rend3_framework::lock(&context.routines.pbr); + let tonemapping_routine = rend3_framework::lock(&context.routines.tonemapping); // Build a rendergraph let mut graph = rend3::graph::RenderGraph::new(); @@ -178,10 +152,10 @@ impl rend3_framework::App for TexturedQuadExample { &frame, 0..1, 0..1, - rend3::graph::ViewportRect::from_size(resolution), + rend3::graph::ViewportRect::from_size(context.resolution), ); // Add the default rendergraph - base_rendergraph.add_to_graph( + context.base_rendergraph.add_to_graph( &mut graph, rend3_routine::base::BaseRenderGraphInputs { eval_output: &eval_output, @@ -192,7 +166,7 @@ impl rend3_framework::App for TexturedQuadExample { }, target: rend3_routine::base::OutputRenderTarget { handle: frame_handle, - resolution, + resolution: context.resolution, samples: SAMPLE_COUNT, }, }, @@ -203,7 +177,7 @@ impl rend3_framework::App for TexturedQuadExample { ); // Dispatch a render using the built up rendergraph! - graph.execute(renderer, &mut eval_output); + graph.execute(context.renderer, &mut eval_output); // Present the frame frame.present(); diff --git a/rend3-egui/Cargo.toml b/rend3-egui/Cargo.toml index aad916af..47cca58e 100644 --- a/rend3-egui/Cargo.toml +++ b/rend3-egui/Cargo.toml @@ -12,8 +12,8 @@ categories = ["game-development", "graphics", "rendering", "rendering::engine", rust-version = "1.71" [dependencies] -egui = "0.24.0" -egui-wgpu = "0.24" +egui = {git = "https://github.com/emilk/egui.git", branch="master"} +egui-wgpu = {git = "https://github.com/emilk/egui.git", branch="master"} glam = "0.24" rend3 = { version = "^0.3.0", path = "../rend3" } wgpu = "0.18.0" diff --git a/rend3-framework/Cargo.toml b/rend3-framework/Cargo.toml index 0ed672f3..217fd4ae 100644 --- a/rend3-framework/Cargo.toml +++ b/rend3-framework/Cargo.toml @@ -21,7 +21,7 @@ profiling = { version = "1", default-features = false } rend3 = { version = "0.3.0", path = "../rend3" } rend3-routine = { version = "0.3.0", path = "../rend3-routine" } thiserror = { version = "1" } -winit = "0.28" +winit = "0.29.4" wgpu = "0.18.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/rend3-framework/src/grab/wasm.rs b/rend3-framework/src/grab/wasm.rs index 3097acd0..85d2dafd 100644 --- a/rend3-framework/src/grab/wasm.rs +++ b/rend3-framework/src/grab/wasm.rs @@ -25,7 +25,7 @@ impl Grabber { let inner_clone = Arc::clone(&inner); - let canvas = window.canvas(); + let canvas = window.canvas().unwrap(); let document = canvas.owner_document().unwrap(); let function: Box = Box::new(move || { @@ -50,7 +50,7 @@ impl Grabber { } pub fn request_grab(&mut self, window: &Window) { - let canvas = window.canvas(); + let canvas = window.canvas().unwrap(); let document = canvas.owner_document().unwrap(); canvas.request_pointer_lock(); @@ -62,7 +62,7 @@ impl Grabber { } pub fn request_ungrab(&mut self, window: &Window) { - let canvas = window.canvas(); + let canvas = window.canvas().unwrap(); let document = canvas.owner_document().unwrap(); document diff --git a/rend3-framework/src/lib.rs b/rend3-framework/src/lib.rs index b44df0cc..15b2be8b 100644 --- a/rend3-framework/src/lib.rs +++ b/rend3-framework/src/lib.rs @@ -10,32 +10,39 @@ use rend3::{ use rend3_routine::base::BaseRenderGraph; use wgpu::{Instance, PresentMode}; use winit::{ - dpi::PhysicalSize, - event::WindowEvent, + error::EventLoopError, + event::Event, event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget}, - window::{Window, WindowBuilder, WindowId}, + window::{Window, WindowBuilder}, }; mod assets; mod grab; -#[cfg(target_arch = "wasm32")] -mod resize_observer; pub use assets::*; pub use grab::*; pub use parking_lot::{Mutex, MutexGuard}; -pub type Event<'a, T> = winit::event::Event<'a, UserResizeEvent>; - -/// User event which the framework uses to resize on wasm. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum UserResizeEvent { - /// Used to fire off resizing on wasm - Resize { - window_id: WindowId, - size: PhysicalSize, - }, - /// Custom user event type - Other(T), + +/// Context passed to the setup function. Contains +/// everything needed to setup examples +pub struct SetupContext<'a, T: 'static = ()> { + pub event_loop: &'a EventLoop, + pub window: &'a Window, + pub renderer: &'a Arc, + pub routines: &'a Arc, + pub surface_format: rend3::types::TextureFormat, +} + +/// Context passed to the event handler. +pub struct EventContext<'a, T: 'static = ()> { + pub window: &'a Window, + pub renderer: &'a Arc, + pub routines: &'a Arc, + pub base_rendergraph: &'a BaseRenderGraph, + pub surface: Option<&'a Arc>, + pub resolution: UVec2, + pub control_flow: &'a mut dyn FnMut(winit::event_loop::ControlFlow), + pub event_loop_window_target: &'a EventLoopWindowTarget, } pub trait App { @@ -58,17 +65,17 @@ pub trait App { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); } - fn create_window(&mut self, builder: WindowBuilder) -> (EventLoop>, Window) { + fn create_window(&mut self, builder: WindowBuilder) -> Result<(EventLoop, Window), EventLoopError> { profiling::scope!("creating window"); - let event_loop = EventLoopBuilder::with_user_event().build(); + let event_loop = EventLoopBuilder::with_user_event().build()?; let window = builder.build(&event_loop).expect("Could not build window"); #[cfg(target_arch = "wasm32")] { use winit::platform::web::WindowExtWebSys; - let canvas = window.canvas(); + let canvas = window.canvas().unwrap(); let style = canvas.style(); style.set_property("width", "100%").unwrap(); style.set_property("height", "100%").unwrap(); @@ -80,7 +87,7 @@ pub trait App { .expect("couldn't append canvas to document body"); } - (event_loop, window) + Ok((event_loop, window)) } fn create_iad<'a>(&'a mut self) -> Pin> + 'a>> { @@ -108,15 +115,8 @@ pub trait App { 1.0 } - fn setup( - &mut self, - event_loop: &EventLoop>, - window: &Window, - renderer: &Arc, - routines: &Arc, - surface_format: rend3::types::TextureFormat, - ) { - let _ = (event_loop, window, renderer, routines, surface_format); + fn setup(&mut self, context: SetupContext<'_, T>) { + let _ = context; } /// RedrawRequested/RedrawEventsCleared will only be fired if the window @@ -124,27 +124,8 @@ pub trait App { /// in RedrawRequested and use MainEventsCleared for things that need to /// keep running when minimized. #[allow(clippy::too_many_arguments)] - fn handle_event( - &mut self, - window: &Window, - renderer: &Arc, - routines: &Arc, - base_rendergraph: &BaseRenderGraph, - surface: Option<&Arc>, - resolution: UVec2, - event: Event<'_, T>, - control_flow: impl FnOnce(winit::event_loop::ControlFlow), - ) { - let _ = ( - window, - renderer, - routines, - base_rendergraph, - resolution, - surface, - event, - control_flow, - ); + fn handle_event(&mut self, context: EventContext<'_, T>, event: Event) { + let _ = (context, event); } } @@ -163,52 +144,12 @@ pub struct DefaultRoutines { pub tonemapping: Mutex, } -#[cfg(not(target_arch = "wasm32"))] -fn winit_run(event_loop: winit::event_loop::EventLoop, event_handler: F) -> ! -where - F: FnMut(winit::event::Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow) + 'static, - T: 'static, -{ - event_loop.run(event_handler) -} - -#[cfg(target_arch = "wasm32")] -fn winit_run(event_loop: EventLoop, event_handler: F) -where - F: FnMut(winit::event::Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow) + 'static, - T: 'static, -{ - use wasm_bindgen::prelude::*; - - let winit_closure = Closure::once_into_js(move || event_loop.run(event_handler)); - - // make sure to handle JS exceptions thrown inside start. - // Otherwise wasm_bindgen_futures Queue would break and never handle any tasks - // again. This is required, because winit uses JS exception for control flow - // to escape from `run`. - if let Err(error) = call_catch(&winit_closure) { - let is_control_flow_exception = error - .dyn_ref::() - .map_or(false, |e| e.message().includes("Using exceptions for control flow", 0)); - - if !is_control_flow_exception { - web_sys::console::error_1(&error); - } - } - - #[wasm_bindgen] - extern "C" { - #[wasm_bindgen(catch, js_namespace = Function, js_name = "prototype.call.call")] - fn call_catch(this: &JsValue) -> Result<(), JsValue>; - } -} - pub async fn async_start + 'static, T: 'static>(mut app: A, window_builder: WindowBuilder) { app.register_logger(); app.register_panic_hook(); // Create the window invisible until we are rendering - let (event_loop, window) = app.create_window(window_builder.with_visible(false)); + let (event_loop, window) = app.create_window(window_builder.with_visible(false)).unwrap(); let window_size = window.inner_size(); let iad = app.create_iad().await.unwrap(); @@ -278,16 +219,19 @@ pub async fn async_start + 'static, T: 'static>(mut app: A, window_bui }); drop(data_core); - app.setup(&event_loop, &window, &renderer, &routines, format); - - #[cfg(target_arch = "wasm32")] - let _observer = resize_observer::ResizeObserver::new(&window, event_loop.create_proxy()); + app.setup(SetupContext { + event_loop: &event_loop, + window: &window, + renderer: &renderer, + routines: &routines, + surface_format: format, + }); // We're ready, so lets make things visible window.set_visible(true); let mut suspended = cfg!(target_os = "android"); - let mut last_user_control_mode = ControlFlow::Poll; + let mut last_user_control_mode = ControlFlow::Wait; let mut stored_surface_info = StoredSurfaceInfo { size: glam::UVec2::new(window_size.width, window_size.height), scale_factor: app.scale_factor(), @@ -295,60 +239,84 @@ pub async fn async_start + 'static, T: 'static>(mut app: A, window_bui present_mode: app.present_mode(), }; - winit_run(event_loop, move |event, _event_loop, control_flow| { - let event = match event { - Event::UserEvent(UserResizeEvent::Resize { size, window_id }) => Event::WindowEvent { - window_id, - event: WindowEvent::Resized(size), - }, - e => e, - }; - - if let Some(suspend) = handle_surface( - &app, - &window, - &event, - &iad.instance, - &mut surface, - &renderer, - format, - &mut stored_surface_info, - ) { - suspended = suspend; + cfg_if::cfg_if! { + if #[cfg(target_arch = "wasm32")] { + use winit::platform::web::EventLoopExtWebSys; + let event_loop_function = EventLoop::spawn; + } else { + let event_loop_function = EventLoop::run; } + } - // We move to Wait when we get suspended so we don't spin at 50k FPS. - match event { - Event::Suspended => { - *control_flow = ControlFlow::Wait; + // On native this is a result, but on wasm it's a unit type. + #[allow(clippy::let_unit_value)] + let _ = (event_loop_function)( + event_loop, + move |event: Event, event_loop_window_target: &EventLoopWindowTarget| { + let mut control_flow = event_loop_window_target.control_flow(); + if let Some(suspend) = handle_surface( + &app, + &window, + &event, + &iad.instance, + &mut surface, + &renderer, + format, + &mut stored_surface_info, + ) { + suspended = suspend; } - Event::Resumed => { - *control_flow = last_user_control_mode; + + // We move to Wait when we get suspended so we don't spin at 50k FPS. + match event { + Event::Suspended => { + control_flow = ControlFlow::Wait; + } + Event::Resumed => { + control_flow = last_user_control_mode; + } + _ => {} } - _ => {} - } - // We need to block all updates - if let Event::RedrawRequested(_) | Event::RedrawEventsCleared | Event::MainEventsCleared = event { - if suspended { + // Close button was clicked, we should close. + if let winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } = event + { + event_loop_window_target.exit(); return; } - } - app.handle_event( - &window, - &renderer, - &routines, - &base_rendergraph, - surface.as_ref(), - stored_surface_info.size, - event, - |c: ControlFlow| { - *control_flow = c; - last_user_control_mode = c; - }, - ) - }); + // We need to block all updates + if let Event::WindowEvent { + window_id: _, + event: winit::event::WindowEvent::RedrawRequested, + } = event + { + if suspended { + return; + } + } + + app.handle_event( + EventContext { + window: &window, + renderer: &renderer, + routines: &routines, + base_rendergraph: &base_rendergraph, + surface: surface.as_ref(), + resolution: stored_surface_info.size, + control_flow: &mut |c: ControlFlow| { + control_flow = c; + last_user_control_mode = c; + }, + event_loop_window_target, + }, + event, + ); + }, + ); } struct StoredSurfaceInfo { @@ -405,7 +373,7 @@ fn handle_surface, T: 'static>( #[cfg(target_arch = "wasm32")] { use winit::platform::web::WindowExtWebSys; - let canvas = window.canvas(); + let canvas = window.canvas().unwrap(); let style = canvas.style(); style.set_property("width", "100%").unwrap(); diff --git a/rend3-framework/src/resize_observer.rs b/rend3-framework/src/resize_observer.rs deleted file mode 100644 index c684e56c..00000000 --- a/rend3-framework/src/resize_observer.rs +++ /dev/null @@ -1,55 +0,0 @@ -use wasm_bindgen::prelude::*; -use winit::{dpi::PhysicalSize, event_loop::EventLoopProxy, platform::web::WindowExtWebSys, window::Window}; - -use crate::UserResizeEvent; - -//from https://github.com/seed-rs/seed/pull/534/files - -#[wasm_bindgen(inline_js = r#" -export function __wasm_rend3_framework_register_resize_observer_impl(element, send_msg_resized) { - const resizeObserver = new ResizeObserver(entries => { - const entry = entries[0]; - let size = 0; - // Browsers use different structures to store the size. Don't ask me why.. - if (entry.borderBoxSize instanceof ResizeObserverSize) { - size = entry.borderBoxSize; - } else if (entry.borderBoxSize[0] instanceof ResizeObserverSize) { - size = entry.borderBoxSize[0]; - } else { - console.error("Cannot get borderBoxSize from ResizeObserver entry!"); - } - const height = size.blockSize * window.devicePixelRatio; - const width = size.inlineSize * window.devicePixelRatio; - send_msg_resized(width, height); - }); - resizeObserver.observe(element); -} -"#)] -extern "C" { - fn __wasm_rend3_framework_register_resize_observer_impl(element: &web_sys::Element, callback: &JsValue); -} - -pub struct ResizeObserver { - _callback: JsValue, -} -impl ResizeObserver { - pub fn new(window: &Window, proxy: EventLoopProxy>) -> Self { - let canvas = window.canvas(); - let id = window.id(); - let callback: Box = Box::new(move |width, height| { - let _res = proxy.send_event(UserResizeEvent::Resize { - window_id: id, - size: PhysicalSize { width, height }, - }); - - canvas.set_width(width); - canvas.set_height(height); - }); - - let js_value = Closure::wrap(callback).into_js_value(); - - __wasm_rend3_framework_register_resize_observer_impl(&window.canvas(), &js_value); - - Self { _callback: js_value } - } -} diff --git a/rend3-types/src/lib.rs b/rend3-types/src/lib.rs index 6bb96c94..1e601bdf 100644 --- a/rend3-types/src/lib.rs +++ b/rend3-types/src/lib.rs @@ -773,7 +773,7 @@ impl Mesh { debug_assert_ne!(normal_index, uv_0_index); // Assert that all indices are in bounds. - debug_assert!(self.attributes.get(0).is_some()); + debug_assert!(self.attributes.first().is_some()); debug_assert!(self.attributes.get(tangent_index).is_some()); debug_assert!(self.attributes.get(normal_index).is_some()); debug_assert!(self.attributes.get(uv_0_index).is_some());