#make EventWriter lifetime 'static in system

23 messages · Page 1 of 1 (latest)

gloomy kestrel
#

I want to send my EventWriter to a wasm_bindgen, so on js event I can trigger an event and do some stuff.
I'm gettinr error that ev_cursor_moved has lifetime of '1, but needs 'static.
How can I make this work?

fn cursor_event_listener(mut ev_cursor_moved: EventWriter<WindowCursorMovedEvent>) {
    if let Some(window) = window() {
        let cb_window = window.clone();
        let cb = Closure::wrap(Box::new(move |e: JsValue| {
            let event: MouseEvent = e.dyn_into().expect("closure input isn't MouseEvent");
            let cursor_pos = Vec3::new(event.client_x() as f32, event.client_y() as f32, 0.);
            let doc_elemnt = cb_window
                .document()
                .expect("window missing document?")
                .document_element()
                .expect("document missing root element");
            let window_size = Vec3::new(
                doc_elemnt.client_width() as f32,
                doc_elemnt.client_height() as f32,
                0.,
            );
            ev_cursor_moved.send(WindowCursorMovedEvent {
                0: WindowCursorData {
                    window_size,
                    cursor_pos,
                },
            });
        }) as Box<dyn FnMut(JsValue)>);

        window
            .add_event_listener_with_callback("mousemove", &cb.as_ref().unchecked_ref())
            .expect("Failed adding on mousemove event listenter");

        cb.forget();
    }
}
error: lifetime may not live long enough
   --> src/components/threed/camera_animator.rs:209:32
    |
206 |   fn cursor_event_listener(mut ev_cursor_moved: EventWriter<WindowCurso...
    |                            ------------------- has type `bevy::prelude::Ev
entWriter<'1, WindowCursorMovedEvent>`
...
209 |           let cb = Closure::wrap(Box::new(move |e: JsValue| {
    |  ________________________________^
210 | |             let event: MouseEvent = e.dyn_into().expect("closure inpu...
211 | |             let cursor_pos = Vec3::new(event.client_x() as f32, event...
212 | |             let doc_elemnt = cb_window
...   |
227 | |             });
228 | |         }) as Box<dyn FnMut(JsValue)>);
    | |_____________________________________^ cast requires that `'1` must outli
ve `'static`
#

They should technically live the same duration, when I change page I think they will both get dropped. Unless EventWriter only lives 1 frame? I'm calling this system on Startup

heady tiger
#

EventWriter lives on for the duration of your function. Think about it. You are getting object directly by value, not a reference, there is no way that EventWriter can leave longer than your function 🙂 The trick is that inside it has ResMut that lives longer and is shared(so you can consider EventWriter a throw away wrapper).

#

Generally you can't store Bevy things outside of Bevy lifecycle as bevy needs full ownership. If you need to move it to other threads you need to clone everything or wrap it in Arc. If you want to add external communication you need to use standard Rust primiteves and write systems that will read/write from these primitives(like channels)

gloomy kestrel
#

I guess channels would be the next best thing

#

Tho I can't imagine how that would work, would it try to receive every frame, and if nothing is on the line next frame goes? Is that possible?

heady tiger
#

Yes, you create a read and write channel. You send write channel to your web thread, and you create an Entity with a component that can store the read channel. Then you write a system that gets that entity and checks every frame if there is something to process

gloomy kestrel
#

I genuinely am not even sure if they're threads

#

I don't think so tbh

#

But okay I'll give it a try, thank you :)

heady tiger
#

If that is not part of Bevy(manged by Bevy) then it must spawn some threads under the hood, otherwise how would it ever executer that listener code? 🙂

gloomy kestrel
#

Javascript

#

This is all browser based

#

And afaik callbacks are not async

#

Hence often they require Promise wrapping

#

I assume, the amount of layers bevy is under in my project is frightening, I don't even know how it actually manages to get something to render under leptos x)

heady tiger
#

Sounds like fun : d

gloomy kestrel
#

Webdev is both the easiest and the hardest

pallid dove
lavish raptor
#

I made a small example for yew some time ago, but it should work fairly similar for leptos: https://github.com/kristoff3r/yew-bevy-example/

Back then bevy-crossbeam-event didn't exist iirc, so you can probably replace some of the boilerplate with that

gloomy kestrel
lavish raptor
gloomy kestrel
#

oh tthat's wht you mean