In Macroquad, how can you load_textures without blocking the UI?
Details
Macroquad seems to use async as a means of emulating generators. There seems to be no executor as such.
Macroquad's load_* functions are all async, and, without an executor, .await seems to be the only way of getting them to run.
I want to do my load_'ing off the UI thread, which, without something like block_on(), implies using .await inside a closure passed to thread::spawn, which I don't know how to do.
Have you considered creating a tokioRuntime (or any async executor runtime, really) before the loop starts, and spawning the async tasks on it? If you use tokio in particular if you call .enter() on the Runtime and store that handle in a variable then you'll be able to use tokio::spawn without having to explicitly pass a reference to the runtime around.
Yes, I did a quick 'n' dirty trial with futures rather than tokio and ran into some problems whose details I forget. Perhaps I should give this a more serious go.
But I would expect not-blocking-the-UI to be a pretty common requirement, so I'm surprised that I cannot find a prominent solution.
I've tried a bunch of variations on the following theme, both using tokio and futures
use macroquad::prelude::*;
use tokio::runtime::Runtime;
#[macroquad::main("XXX")]
async fn main() {
let mut args = std::env::args();
let _executable = args.next();
let path = args.next().unwrap(); // path to JPEG or other image
let (tx, rx) = std::sync::mpsc::channel();
let rt = Runtime::new().unwrap();
let _rt_guard = rt.enter();
tokio::spawn(async move {
for _ in 0..10 {
let texture = rt.block_on(load_texture(&path)).unwrap();
tx.send(texture).unwrap();
}
});
let mut textures = vec![];
loop {
clear_background(GRAY);
draw_text(&format!("loaded {} textures.", textures.len()),
100.0, 100.0, 100.0, BLACK);
if let Ok(texture) = rx.try_recv() {
textures.push(texture);
}
next_frame().await
}
}
So far, all attempts that compile have run into some run-time crash.