Lifetime issues trying to script Speedy2D with Rhai
superlou opened this issue · comments
I'm trying to script Speedy2d so that the user can develop digital signage applications without having to recompile: https://gist.github.com/superlou/a24e2ef881e6058d0890df78ccc3151f.
However, I'm caught up in trying to figure out some way to pass the short-lived &mut Graphics2D to the scripting engine. The closest I've gotten in via an Rc<RefCell<Option>, which eventually gives the kind-of "duh" error shown in the gist. However, if I use lifetimes, Rust can't guarantee the life of the graphics put into the Rc<RefCell<...>> doesn't outlast the function. Is there a simpler approach friendly to Speedy2D's on_draw that I'm missing?
Thanks for the question! It's only possible to use Graphics2D
inside the on_draw
callback, so it isn't possible to take a reference to this and use it elsewhere.
Instead of storing a reference to the Graphics2D
object, a different approach might be instead to store the things you want to draw.
For example, you could have an enum representing possible draw operations:
enum DrawOperation {
ClearBackground(Color),
DrawRectangle(Rect, Color),
...
}
struct SignWindowHandler {
engine: Engine,
ast: AST,
scope: Scope<'static>,
last_frame_time: Instant,
pending_ops: Vec<DrawOperation>,
}
You can then run these inside on_draw
by looping through them.
A few other things to bear in mind:
- I'm not sure exactly how the scripting engine works, but if it runs in a different thread, you may need to protect the
Vec
with a mutex. - It would also be good to group operations into frames, to avoid only part of a frame being drawn. The
Vec
inSignWindowHandler
could contain all the operations necessary to draw the most recent frame, and you could replace the whole contents when the script wants to draw a different frame.
Hope that all makes sense!
That works. I was trying to think of reasons where delaying the draw commands during script execution would result in different behavior. So long as the draw commands are pure, I think running them as a frame after the script runs should be fine.
I don't think I need the mutex because it's in the same thread, but I'll watch out for that.
My rough repo is https://github.com/superlou/signrs. Thanks!