|
|
@@ -1,5 +1,5 @@
|
|
|
-use std::iter;
|
|
|
use rand::Rng;
|
|
|
+use std::iter;
|
|
|
|
|
|
use cgmath::prelude::*;
|
|
|
use wgpu::util::DeviceExt;
|
|
|
@@ -9,7 +9,7 @@ use winit::{
|
|
|
window::Window,
|
|
|
};
|
|
|
|
|
|
-use sapvi::gfx::{model, texture};
|
|
|
+use sapvi::gfx::{camera, model, texture};
|
|
|
|
|
|
use model::{DrawLight, DrawModel, Vertex};
|
|
|
|
|
|
@@ -27,34 +27,8 @@ fn get_time() -> f32 {
|
|
|
|
|
|
const FONT_BYTES: &[u8] = include_bytes!("../../res/font/PressStart2P-Regular.ttf");
|
|
|
|
|
|
-#[rustfmt::skip]
|
|
|
-pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
|
|
|
- 1.0, 0.0, 0.0, 0.0,
|
|
|
- 0.0, 1.0, 0.0, 0.0,
|
|
|
- 0.0, 0.0, 0.5, 0.0,
|
|
|
- 0.0, 0.0, 0.5, 1.0,
|
|
|
-);
|
|
|
-
|
|
|
const NUM_INSTANCES_PER_ROW: u32 = 10;
|
|
|
|
|
|
-struct Camera {
|
|
|
- eye: cgmath::Point3<f32>,
|
|
|
- target: cgmath::Point3<f32>,
|
|
|
- up: cgmath::Vector3<f32>,
|
|
|
- aspect: f32,
|
|
|
- fovy: f32,
|
|
|
- znear: f32,
|
|
|
- zfar: f32,
|
|
|
-}
|
|
|
-
|
|
|
-impl Camera {
|
|
|
- fn build_view_projection_matrix(&self) -> cgmath::Matrix4<f32> {
|
|
|
- let view = cgmath::Matrix4::look_at(self.eye, self.target, self.up);
|
|
|
- let proj = cgmath::perspective(cgmath::Deg(self.fovy), self.aspect, self.znear, self.zfar);
|
|
|
- proj * view
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
#[repr(C)]
|
|
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
|
struct Uniforms {
|
|
|
@@ -70,113 +44,9 @@ impl Uniforms {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fn update_view_proj(&mut self, camera: &Camera) {
|
|
|
- // We don't specifically need homogeneous coordinates since we're just using
|
|
|
- // a vec3 in the shader. We're using Point3 for the camera.eye, and this is
|
|
|
- // the easiest way to convert to Vector4. We're using Vector4 because of
|
|
|
- // the uniforms 16 byte spacing requirement
|
|
|
- self.view_position = camera.eye.to_homogeneous().into();
|
|
|
- // self.view_proj = OPENGL_TO_WGPU_MATRIX * camera.build_view_projection_matrix();
|
|
|
- self.view_proj = camera.build_view_projection_matrix().into();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-struct CameraController {
|
|
|
- speed: f32,
|
|
|
- is_up_pressed: bool,
|
|
|
- is_down_pressed: bool,
|
|
|
- is_forward_pressed: bool,
|
|
|
- is_backward_pressed: bool,
|
|
|
- is_left_pressed: bool,
|
|
|
- is_right_pressed: bool,
|
|
|
-}
|
|
|
-
|
|
|
-impl CameraController {
|
|
|
- fn new(speed: f32) -> Self {
|
|
|
- Self {
|
|
|
- speed,
|
|
|
- is_up_pressed: false,
|
|
|
- is_down_pressed: false,
|
|
|
- is_forward_pressed: false,
|
|
|
- is_backward_pressed: false,
|
|
|
- is_left_pressed: false,
|
|
|
- is_right_pressed: false,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fn process_events(&mut self, event: &WindowEvent) -> bool {
|
|
|
- match event {
|
|
|
- WindowEvent::KeyboardInput {
|
|
|
- input:
|
|
|
- KeyboardInput {
|
|
|
- state,
|
|
|
- virtual_keycode: Some(keycode),
|
|
|
- ..
|
|
|
- },
|
|
|
- ..
|
|
|
- } => {
|
|
|
- let is_pressed = *state == ElementState::Pressed;
|
|
|
- match keycode {
|
|
|
- VirtualKeyCode::Space => {
|
|
|
- self.is_up_pressed = is_pressed;
|
|
|
- true
|
|
|
- }
|
|
|
- VirtualKeyCode::LShift => {
|
|
|
- self.is_down_pressed = is_pressed;
|
|
|
- true
|
|
|
- }
|
|
|
- VirtualKeyCode::W | VirtualKeyCode::Up => {
|
|
|
- self.is_forward_pressed = is_pressed;
|
|
|
- true
|
|
|
- }
|
|
|
- VirtualKeyCode::A | VirtualKeyCode::Left => {
|
|
|
- self.is_left_pressed = is_pressed;
|
|
|
- true
|
|
|
- }
|
|
|
- VirtualKeyCode::S | VirtualKeyCode::Down => {
|
|
|
- self.is_backward_pressed = is_pressed;
|
|
|
- true
|
|
|
- }
|
|
|
- VirtualKeyCode::D | VirtualKeyCode::Right => {
|
|
|
- self.is_right_pressed = is_pressed;
|
|
|
- true
|
|
|
- }
|
|
|
- _ => false,
|
|
|
- }
|
|
|
- }
|
|
|
- _ => false,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fn update_camera(&self, camera: &mut Camera) {
|
|
|
- let forward = camera.target - camera.eye;
|
|
|
- let forward_norm = forward.normalize();
|
|
|
- let forward_mag = forward.magnitude();
|
|
|
-
|
|
|
- // Prevents glitching when camera gets too close to the
|
|
|
- // center of the scene.
|
|
|
- if self.is_forward_pressed && forward_mag > self.speed {
|
|
|
- camera.eye += forward_norm * self.speed;
|
|
|
- }
|
|
|
- if self.is_backward_pressed {
|
|
|
- camera.eye -= forward_norm * self.speed;
|
|
|
- }
|
|
|
-
|
|
|
- let right = forward_norm.cross(camera.up);
|
|
|
-
|
|
|
- // Redo radius calc in case the up/ down is pressed.
|
|
|
- let forward = camera.target - camera.eye;
|
|
|
- let forward_mag = forward.magnitude();
|
|
|
-
|
|
|
- if self.is_right_pressed {
|
|
|
- // Rescale the distance between the target and eye so
|
|
|
- // that it doesn't change. The eye therefore still
|
|
|
- // lies on the circle made by the target and eye.
|
|
|
- camera.eye = camera.target - (forward + right * self.speed).normalize() * forward_mag;
|
|
|
- }
|
|
|
- if self.is_left_pressed {
|
|
|
- camera.eye = camera.target - (forward - right * self.speed).normalize() * forward_mag;
|
|
|
- }
|
|
|
+ fn update_view_proj(&mut self, camera: &camera::Camera, projection: &camera::Projection) {
|
|
|
+ self.view_position = camera.position.to_homogeneous().into();
|
|
|
+ self.view_proj = (projection.calc_matrix() * camera.calc_matrix()).into()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -325,8 +195,11 @@ struct State {
|
|
|
swap_chain: wgpu::SwapChain,
|
|
|
render_pipeline: wgpu::RenderPipeline,
|
|
|
obj_model: model::Model,
|
|
|
- camera: Camera,
|
|
|
- camera_controller: CameraController,
|
|
|
+
|
|
|
+ camera: camera::Camera, // UPDATED!
|
|
|
+ projection: camera::Projection, // NEW!
|
|
|
+ camera_controller: camera::CameraController, // UPDATED!
|
|
|
+
|
|
|
uniforms: Uniforms,
|
|
|
uniform_buffer: wgpu::Buffer,
|
|
|
uniform_bind_group: wgpu::BindGroup,
|
|
|
@@ -355,6 +228,7 @@ struct State {
|
|
|
staging_belt: wgpu::util::StagingBelt,
|
|
|
|
|
|
is_space_pressed: bool,
|
|
|
+ mouse_pressed: bool,
|
|
|
}
|
|
|
|
|
|
fn create_render_pipeline(
|
|
|
@@ -475,20 +349,13 @@ impl State {
|
|
|
label: Some("texture_bind_group_layout"),
|
|
|
});
|
|
|
|
|
|
- let camera = Camera {
|
|
|
- eye: (0.0, 5.0, -10.0).into(),
|
|
|
- target: (0.0, 0.0, 0.0).into(),
|
|
|
- up: cgmath::Vector3::unit_y(),
|
|
|
- aspect: sc_desc.width as f32 / sc_desc.height as f32,
|
|
|
- fovy: 45.0,
|
|
|
- znear: 0.1,
|
|
|
- zfar: 100.0,
|
|
|
- };
|
|
|
-
|
|
|
- let camera_controller = CameraController::new(0.2);
|
|
|
+ let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
|
|
|
+ let projection =
|
|
|
+ camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
|
|
|
+ let camera_controller = camera::CameraController::new(4.0, 0.4);
|
|
|
|
|
|
let mut uniforms = Uniforms::new();
|
|
|
- uniforms.update_view_proj(&camera);
|
|
|
+ uniforms.update_view_proj(&camera, &projection);
|
|
|
|
|
|
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
|
label: Some("Uniform Buffer"),
|
|
|
@@ -503,31 +370,14 @@ impl State {
|
|
|
let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
|
|
|
let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
|
|
|
|
|
|
- let time = get_time() * 100.0;
|
|
|
- println!("{} {} {}", x, z, time);
|
|
|
- let y = ((x + time).sin() + (z + time).sin()) * 20.0;
|
|
|
+ let y = 0.0;
|
|
|
|
|
|
let position = cgmath::Vector3 { x, y, z };
|
|
|
|
|
|
- let rotation =
|
|
|
- cgmath::Quaternion::from_axis_angle(
|
|
|
- cgmath::Vector3::unit_z(),
|
|
|
- cgmath::Deg(180.0 + 0.0),
|
|
|
- );
|
|
|
-
|
|
|
- /*
|
|
|
- let rotation = if position.is_zero() {
|
|
|
- cgmath::Quaternion::from_axis_angle(
|
|
|
- cgmath::Vector3::unit_z(),
|
|
|
- cgmath::Deg(180.0 + 0.0),
|
|
|
- )
|
|
|
- } else {
|
|
|
- cgmath::Quaternion::from_axis_angle(
|
|
|
- position.clone().normalize(),
|
|
|
- cgmath::Deg(180.0 + 45.0),
|
|
|
- )
|
|
|
- };
|
|
|
- */
|
|
|
+ let rotation = cgmath::Quaternion::from_axis_angle(
|
|
|
+ cgmath::Vector3::unit_z(),
|
|
|
+ cgmath::Deg(180.0 + 0.0),
|
|
|
+ );
|
|
|
|
|
|
Instance { position, rotation }
|
|
|
})
|
|
|
@@ -701,8 +551,7 @@ impl State {
|
|
|
|
|
|
let cartoon_bytes = include_bytes!("../../res/img/absolutely-proprietary2.png");
|
|
|
let cartoon_texture =
|
|
|
- texture::Texture::from_bytes(&device, &queue, cartoon_bytes, "stallman2")
|
|
|
- .unwrap();
|
|
|
+ texture::Texture::from_bytes(&device, &queue, cartoon_bytes, "stallman2").unwrap();
|
|
|
|
|
|
let cartoon_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
|
layout: &texture_bind_group_layout,
|
|
|
@@ -719,9 +568,6 @@ impl State {
|
|
|
label: Some("cartoon_bind_group"),
|
|
|
});
|
|
|
|
|
|
- let vs_module = device.create_shader_module(&wgpu::include_spirv!("../../res/shader/ui_shader.vert.spv"));
|
|
|
- let fs_module = device.create_shader_module(&wgpu::include_spirv!("../../res/shader/ui_shader.frag.spv"));
|
|
|
-
|
|
|
let render_pipeline_layout =
|
|
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
|
|
label: Some("Render Pipeline Layout"),
|
|
|
@@ -729,47 +575,15 @@ impl State {
|
|
|
push_constant_ranges: &[],
|
|
|
});
|
|
|
|
|
|
- let ui_render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
|
- label: Some("Render Pipeline"),
|
|
|
- layout: Some(&render_pipeline_layout),
|
|
|
- vertex: wgpu::VertexState {
|
|
|
- module: &vs_module,
|
|
|
- entry_point: "main",
|
|
|
- buffers: &[model::ModelVertex::desc()],
|
|
|
- },
|
|
|
- fragment: Some(wgpu::FragmentState {
|
|
|
- module: &fs_module,
|
|
|
- entry_point: "main",
|
|
|
- targets: &[wgpu::ColorTargetState {
|
|
|
- format: sc_desc.format,
|
|
|
- alpha_blend: wgpu::BlendState::REPLACE,
|
|
|
- color_blend: wgpu::BlendState::REPLACE,
|
|
|
- write_mask: wgpu::ColorWrite::ALL,
|
|
|
- }],
|
|
|
- }),
|
|
|
- primitive: wgpu::PrimitiveState {
|
|
|
- topology: wgpu::PrimitiveTopology::TriangleList,
|
|
|
- strip_index_format: None,
|
|
|
- front_face: wgpu::FrontFace::Ccw,
|
|
|
- cull_mode: wgpu::CullMode::Back,
|
|
|
- // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
|
|
|
- polygon_mode: wgpu::PolygonMode::Fill,
|
|
|
- },
|
|
|
- depth_stencil: Some(wgpu::DepthStencilState {
|
|
|
- format: texture::Texture::DEPTH_FORMAT,
|
|
|
- depth_write_enabled: true,
|
|
|
- depth_compare: wgpu::CompareFunction::Less,
|
|
|
- stencil: wgpu::StencilState::default(),
|
|
|
- bias: wgpu::DepthBiasState::default(),
|
|
|
- // Setting this to true requires Features::DEPTH_CLAMPING
|
|
|
- clamp_depth: false,
|
|
|
- }),
|
|
|
- multisample: wgpu::MultisampleState {
|
|
|
- count: 1,
|
|
|
- mask: !0,
|
|
|
- alpha_to_coverage_enabled: false,
|
|
|
- },
|
|
|
- });
|
|
|
+ let ui_render_pipeline = create_render_pipeline(
|
|
|
+ &device,
|
|
|
+ &render_pipeline_layout,
|
|
|
+ sc_desc.format,
|
|
|
+ Some(texture::Texture::DEPTH_FORMAT),
|
|
|
+ &[model::ModelVertex::desc()],
|
|
|
+ wgpu::include_spirv!("../../res/shader/ui_shader.vert.spv"),
|
|
|
+ wgpu::include_spirv!("../../res/shader/ui_shader.frag.spv"),
|
|
|
+ );
|
|
|
|
|
|
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
|
label: Some("Vertex Buffer"),
|
|
|
@@ -796,8 +610,11 @@ impl State {
|
|
|
swap_chain,
|
|
|
render_pipeline,
|
|
|
obj_model,
|
|
|
+
|
|
|
camera,
|
|
|
+ projection,
|
|
|
camera_controller,
|
|
|
+
|
|
|
uniform_buffer,
|
|
|
uniform_bind_group,
|
|
|
uniforms,
|
|
|
@@ -823,11 +640,12 @@ impl State {
|
|
|
staging_belt,
|
|
|
|
|
|
is_space_pressed: true,
|
|
|
+ mouse_pressed: false,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
|
|
- self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
|
|
|
+ self.projection.resize(new_size.width, new_size.height);
|
|
|
self.size = new_size;
|
|
|
self.sc_desc.width = new_size.width;
|
|
|
self.sc_desc.height = new_size.height;
|
|
|
@@ -836,17 +654,42 @@ impl State {
|
|
|
texture::Texture::create_depth_texture(&self.device, &self.sc_desc, "depth_texture");
|
|
|
}
|
|
|
|
|
|
- fn input(&mut self, event: &WindowEvent) -> bool {
|
|
|
- self.camera_controller.process_events(event)
|
|
|
+ fn input(&mut self, event: &DeviceEvent) -> bool {
|
|
|
+ match event {
|
|
|
+ DeviceEvent::Key(KeyboardInput {
|
|
|
+ virtual_keycode: Some(key),
|
|
|
+ state,
|
|
|
+ ..
|
|
|
+ }) => self.camera_controller.process_keyboard(*key, *state),
|
|
|
+ DeviceEvent::MouseWheel { delta, .. } => {
|
|
|
+ self.camera_controller.process_scroll(delta);
|
|
|
+ true
|
|
|
+ }
|
|
|
+ DeviceEvent::Button {
|
|
|
+ button: 1, // Left Mouse Button
|
|
|
+ state,
|
|
|
+ } => {
|
|
|
+ self.mouse_pressed = *state == ElementState::Pressed;
|
|
|
+ true
|
|
|
+ }
|
|
|
+ DeviceEvent::MouseMotion { delta } => {
|
|
|
+ if self.mouse_pressed {
|
|
|
+ self.camera_controller.process_mouse(delta.0, delta.1);
|
|
|
+ }
|
|
|
+ true
|
|
|
+ }
|
|
|
+ _ => false,
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- fn update(&mut self) {
|
|
|
+ fn update(&mut self, dt: std::time::Duration) {
|
|
|
if rand::thread_rng().gen_range(0, 5) == 0 {
|
|
|
self.is_space_pressed = !self.is_space_pressed;
|
|
|
}
|
|
|
|
|
|
- self.camera_controller.update_camera(&mut self.camera);
|
|
|
- self.uniforms.update_view_proj(&self.camera);
|
|
|
+ self.camera_controller.update_camera(&mut self.camera, dt);
|
|
|
+ self.uniforms
|
|
|
+ .update_view_proj(&self.camera, &self.projection);
|
|
|
self.queue.write_buffer(
|
|
|
&self.uniform_buffer,
|
|
|
0,
|
|
|
@@ -862,15 +705,14 @@ impl State {
|
|
|
let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
|
|
|
|
|
|
//println!("{} {} {}", x, z, time);
|
|
|
- let y = ((x/3.0 + time).sin() + (z/3.0 + time).cos()) * 1.5;
|
|
|
+ let y = ((x / 3.0 + time).sin() + (z / 3.0 + time).cos()) * 1.5;
|
|
|
|
|
|
let position = cgmath::Vector3 { x, y, z };
|
|
|
|
|
|
- let rotation =
|
|
|
- cgmath::Quaternion::from_axis_angle(
|
|
|
- cgmath::Vector3::unit_z(),
|
|
|
- cgmath::Deg(180.0 + 0.0),
|
|
|
- );
|
|
|
+ let rotation = cgmath::Quaternion::from_axis_angle(
|
|
|
+ cgmath::Vector3::unit_z(),
|
|
|
+ cgmath::Deg(180.0 + 0.0),
|
|
|
+ );
|
|
|
|
|
|
Instance { position, rotation }
|
|
|
})
|
|
|
@@ -878,8 +720,11 @@ impl State {
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
|
|
|
- self.queue.write_buffer(&self.instance_buffer, 0,
|
|
|
- bytemuck::cast_slice(&instance_data));
|
|
|
+ self.queue.write_buffer(
|
|
|
+ &self.instance_buffer,
|
|
|
+ 0,
|
|
|
+ bytemuck::cast_slice(&instance_data),
|
|
|
+ );
|
|
|
|
|
|
// Update the light
|
|
|
let old_position: cgmath::Vector3<_> = self.light.position.into();
|
|
|
@@ -964,18 +809,18 @@ impl State {
|
|
|
};
|
|
|
draw_text(&play_text, &mut self.glyph_brush);
|
|
|
|
|
|
- self.glyph_brush
|
|
|
- .draw_queued(
|
|
|
- &self.device,
|
|
|
- &mut self.staging_belt,
|
|
|
- &mut encoder,
|
|
|
- &frame.view,
|
|
|
- self.sc_desc.width,
|
|
|
- self.sc_desc.height,
|
|
|
- )
|
|
|
- .unwrap();
|
|
|
+ self.glyph_brush
|
|
|
+ .draw_queued(
|
|
|
+ &self.device,
|
|
|
+ &mut self.staging_belt,
|
|
|
+ &mut encoder,
|
|
|
+ &frame.view,
|
|
|
+ self.sc_desc.width,
|
|
|
+ self.sc_desc.height,
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
|
|
|
- self.staging_belt.finish();
|
|
|
+ self.staging_belt.finish();
|
|
|
|
|
|
self.queue.submit(iter::once(encoder.finish()));
|
|
|
|
|
|
@@ -990,20 +835,21 @@ fn draw_text(text: &Text, glyph_brush: &mut wgpu_glyph::GlyphBrush<()>) {
|
|
|
wgpu_glyph::HorizontalAlign::Left
|
|
|
});
|
|
|
|
|
|
- let section =
|
|
|
- wgpu_glyph::Section {
|
|
|
- screen_position: text.position.into(),
|
|
|
- bounds: text.bounds.into(),
|
|
|
- layout,
|
|
|
- ..Default::default()
|
|
|
- }
|
|
|
- .add_text(wgpu_glyph::Text::new(&text.text).with_color(text.color).with_scale(
|
|
|
- if text.focused {
|
|
|
+ let section = wgpu_glyph::Section {
|
|
|
+ screen_position: text.position.into(),
|
|
|
+ bounds: text.bounds.into(),
|
|
|
+ layout,
|
|
|
+ ..Default::default()
|
|
|
+ }
|
|
|
+ .add_text(
|
|
|
+ wgpu_glyph::Text::new(&text.text)
|
|
|
+ .with_color(text.color)
|
|
|
+ .with_scale(if text.focused {
|
|
|
text.size + 8.0
|
|
|
} else {
|
|
|
text.size
|
|
|
- },
|
|
|
- ));
|
|
|
+ }),
|
|
|
+ );
|
|
|
|
|
|
glyph_brush.queue(section);
|
|
|
}
|
|
|
@@ -1018,39 +864,47 @@ fn main() {
|
|
|
.unwrap();
|
|
|
use futures::executor::block_on;
|
|
|
let mut state = block_on(State::new(&window));
|
|
|
+ let mut last_render_time = std::time::Instant::now();
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
|
*control_flow = ControlFlow::Poll;
|
|
|
match event {
|
|
|
Event::MainEventsCleared => window.request_redraw(),
|
|
|
+ Event::DeviceEvent {
|
|
|
+ ref event,
|
|
|
+ .. // We're not using device_id currently
|
|
|
+ } => {
|
|
|
+ state.input(event);
|
|
|
+ }
|
|
|
Event::WindowEvent {
|
|
|
ref event,
|
|
|
window_id,
|
|
|
} if window_id == window.id() => {
|
|
|
- if !state.input(event) {
|
|
|
- match event {
|
|
|
- WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
|
|
- WindowEvent::KeyboardInput { input, .. } => match input {
|
|
|
- KeyboardInput {
|
|
|
- state: ElementState::Pressed,
|
|
|
- virtual_keycode: Some(VirtualKeyCode::Escape),
|
|
|
- ..
|
|
|
- } => {
|
|
|
- *control_flow = ControlFlow::Exit;
|
|
|
- }
|
|
|
- _ => {}
|
|
|
- },
|
|
|
- WindowEvent::Resized(physical_size) => {
|
|
|
- state.resize(*physical_size);
|
|
|
- }
|
|
|
- WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
|
|
|
- state.resize(**new_inner_size);
|
|
|
+ match event {
|
|
|
+ WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
|
|
+ WindowEvent::KeyboardInput { input, .. } => match input {
|
|
|
+ KeyboardInput {
|
|
|
+ state: ElementState::Pressed,
|
|
|
+ virtual_keycode: Some(VirtualKeyCode::Escape),
|
|
|
+ ..
|
|
|
+ } => {
|
|
|
+ *control_flow = ControlFlow::Exit;
|
|
|
}
|
|
|
_ => {}
|
|
|
+ },
|
|
|
+ WindowEvent::Resized(physical_size) => {
|
|
|
+ state.resize(*physical_size);
|
|
|
+ }
|
|
|
+ WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
|
|
|
+ state.resize(**new_inner_size);
|
|
|
}
|
|
|
+ _ => {}
|
|
|
}
|
|
|
}
|
|
|
Event::RedrawRequested(_) => {
|
|
|
- state.update();
|
|
|
+ let now = std::time::Instant::now();
|
|
|
+ let dt = now - last_render_time;
|
|
|
+ last_render_time = now;
|
|
|
+ state.update(dt);
|
|
|
match state.render() {
|
|
|
Ok(_) => {}
|
|
|
// Recreate the swap_chain if lost
|