emoon / rust_minifb

Cross platfrom window and framebuffer crate for Rust
MIT License
1.01k stars 97 forks source link

Is it possible to get data out of the InputCallback? #210

Closed shraiwi closed 4 years ago

shraiwi commented 4 years ago

Is there an example explaining how to get data from an InputCallback-implementing struct into the main() function? I want to create a mutable buffer containing all of the key presses from the user which is accessible from the main() function.

emoon commented 4 years ago

Hi,

Is there some specific reason you can't use something like this https://github.com/emoon/rust_minifb/blob/master/examples/noise.rs#L49-L57 in the main function when updating the window?

shraiwi commented 4 years ago

The main issue I had with that is that the characters when I poll are not passed as a unicode character, while the handler gives me a unicode character. I'm trying to make something like a note-taking app. Sorry for being vague about that :/

emoon commented 4 years ago

I see. I also see now that the API for the callback isn't done in a good way :( It should be redesigned to allow you to pass data on in the main loop.

A workaround for now would be to use https://docs.rs/lazy_static/1.4.0/lazy_static/ and have a global variable you can fill (a Vec for example) and then access the data within the main loop as well.

I hope this works good enough for you.

shraiwi commented 4 years ago

I will try that, thank you!

emoon commented 4 years ago

np! please let me know if you can't get it working and I can try to assist.

shraiwi commented 4 years ago

I'm actually having a little trouble using the lazy_static! macro. Could you explain to me how to use it? (I just picked up rust a few days ago, so this is all very new to me)

emoon commented 4 years ago

Yes, I will write something up.

emoon commented 4 years ago

Ok, this is not the most pretty code but should do the trick :)

use minifb::{Key, Window, WindowOptions};
use std::cell::RefCell;
use std::rc::Rc;

const WIDTH: usize = 640;
const HEIGHT: usize = 360;

type KeyVec = Rc<RefCell<Vec<u32>>>;

struct Input {
    keys: KeyVec,
}

impl Input {
    fn new(data: &KeyVec) -> Input {
        Input { keys: data.clone() }
    }
}

impl minifb::InputCallback for Input {
    fn add_char(&mut self, uni_char: u32) {
        self.keys.borrow_mut().push(uni_char);
    }
}

fn main() {
    let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];

    let mut window = Window::new(
        "Test - ESC to exit",
        WIDTH,
        HEIGHT,
        WindowOptions::default(),
    )
    .unwrap_or_else(|e| {
        panic!("{}", e);
    });

    let keys_data = KeyVec::new(RefCell::new(Vec::new()));

    let input = Box::new(Input::new(&keys_data));

    // Limit to max ~60 fps update rate
    window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
    window.set_input_callback(input);

    while window.is_open() && !window.is_key_down(Key::Escape) {
        for i in buffer.iter_mut() {
            *i = 0; // write something more funny here!
        }

        // We unwrap here as we want this code to exit if it fails. Real applications may want to handle this in a different way
        window
            .update_with_buffer(&buffer, WIDTH, HEIGHT)
            .unwrap();

        let mut keys = keys_data.borrow_mut();

        for t in keys.iter() {
            println!("keys {}", t);
        }

        keys.clear();
    }
}
emoon commented 4 years ago

As you can see above I was able to get it working without using lazy_static

shraiwi commented 4 years ago

Thank you so much!! I've been trying to get this to work for days!

shraiwi commented 4 years ago

By the way, is there a possibility of making this an example script for others?

emoon commented 4 years ago

Yeah. I will add it as an example

emoon commented 3 years ago

Example has now been added here https://github.com/emoon/rust_minifb/blob/master/examples/char_callback.rs