Reputation: 3
I'm trying to use the winit Rust crate to update an application every interval of time. I think I'm setting the control flow correctly, but I don't seem to be receiving any events at 60 FPS.
I'm running Cargo 1.79.0 on Windows 11 Home 23H2 with winit 0.30.5.
This is my code, based on the winit example code found on docs.rs:
use std::time::{Duration, Instant};
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::{Window, WindowId};
const NANOS_PER_SEC: u64 = 1_000_000_000;
#[derive(Default)]
struct App {
window: Option<Window>,
t: Option<std::time::Instant>,
}
impl ApplicationHandler for App {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
match event {
WindowEvent::CloseRequested => {
println!("The close button was pressed; stopping");
event_loop.exit();
},
WindowEvent::RedrawRequested => {
// Redraw the application.
//
// It's preferable for applications that do not render continuously to render in
// this event rather than in AboutToWait, since rendering in here allows
// the program to gracefully handle redraws requested by the OS.
// Draw.
if let Some(t) = self.t {
println!("FPS: {:>6.2}", 1000.0 / t.elapsed().as_millis() as f64);
}
self.t = Some(std::time::Instant::now());
// Queue a RedrawRequested event.
//
// You only need to call this if you've determined that you need to redraw in
// applications which do not always need to. Applications that redraw continuously
// can render here instead.
self.window.as_ref().unwrap().request_redraw();
}
_ => ()
}
}
}
fn main() {
let event_loop = EventLoop::new().unwrap();
event_loop.set_control_flow(ControlFlow::WaitUntil(Instant::now() + Duration::from_nanos(NANOS_PER_SEC / 60)));
let mut app = App::default();
event_loop.run_app(&mut app).unwrap();
}
Basically, what do I add to the ApplicationHandler implementation to run some code 60 times a second?
Upvotes: 0
Views: 485
Reputation: 1025
Cannot find any defer request redraw function, the way achieve it should be just keep queueing redraw request and check the last redraw time to see if it's time to redraw
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::{Window, WindowId};
const DT_FPS_60_NANO: u128 = 1_000_000_000 / 60;
struct App {
window: Option<Window>,
last_redraw: std::time::Instant,
}
impl ApplicationHandler for App {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.window = Some(
event_loop
.create_window(Window::default_attributes())
.unwrap(),
);
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
match event {
WindowEvent::CloseRequested => {
println!("The close button was pressed; stopping");
event_loop.exit();
}
WindowEvent::RedrawRequested => {
// Queue another RedrawRequest
self.window.as_ref().unwrap().request_redraw();
// Check if should redraw
if self.last_redraw.elapsed().as_nanos() > DT_FPS_60_NANO {
// actually redraw
println!("FPS: {:>6.2}", 1000.0 / self.last_redraw.elapsed().as_millis() as f64);
// record the last redraw time
self.last_redraw = std::time::Instant::now();
}
}
_ => {}
}
}
}
fn main() {
let event_loop = EventLoop::new().unwrap();
let mut app = App {
window: None,
last_redraw: std::time::Instant::now(),
};
event_loop.set_control_flow(ControlFlow::Poll);
event_loop.run_app(&mut app).unwrap();
}
Upvotes: -1