How can we have a console in a separate thread? #1150
-
|
I am looking to have a console which waits for input and passes that information for my main Bevy app to handle. But, I am completely unsure how to go about this. What would be the best way to make this work? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
|
One simple way would probably be to read from Edit: Added code from #1150 (reply in thread) to accepted answer Code hidden to save spaceuse std::io::stdin;
use bevy::prelude::*;
use crossbeam_channel::{bounded, Receiver};
fn main() {
let (tx, rx) = bounded::<String>(1);
std::thread::spawn(move || loop {
let mut buf = String::new();
stdin().read_line(&mut buf).unwrap();
tx.send(buf).unwrap();
});
App::build()
.add_event::<StdinLine>()
.add_plugins(DefaultPlugins)
.add_thread_local_resource(StdinReceiver(rx))
.add_system_to_stage(stage::PRE_EVENT, read_stdin_system.system())
.add_system(log_stdin_system.system())
.run();
}
struct StdinReceiver(Receiver<String>);
struct StdinLine(String);
fn read_stdin_system(_: &mut World, resources: &mut Resources) {
let rx = resources.get_thread_local_mut::<StdinReceiver>().unwrap();
let mut events = resources.get_mut::<Events<StdinLine>>().unwrap();
if let Ok(line) = rx.0.try_recv() {
events.send(StdinLine(line));
}
}
fn log_stdin_system(mut reader: Local<EventReader<StdinLine>>, events: Res<Events<StdinLine>>) {
for line in reader.iter(&events) {
println!("Stdin gave {:?}", line.0);
}
} |
Beta Was this translation helpful? Give feedback.
-
I've attempted to put this together and I've come up with the preceding example. But, when I attempt to add a resource it states that it cannot be shared safely between threads. The only success I've had is adding a resource of |
Beta Was this translation helpful? Give feedback.
-
|
That is awesome, thank you! I got my example working by changing it to a One question about Bevy: Why do we have to have a reference to Completed example of the original code-snippet. |
Beta Was this translation helpful? Give feedback.
One simple way would probably be to read from
stdin, which normally gets flushed every time you press enter. E.g. you can use https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_line onstd::io::stdin().For that you'd need to create a seperate thread (before calling
App::run), and then use a channel to send the data into bevy, via putting the channel in a resource. See https://stackoverflow.com/questions/30012995/how-can-i-read-non-blocking-from-stdinEdit: Added code from #1150 (reply in thread) to accepted answer
Code hidden to save space