QuantumBadger / Speedy2D

Rust library for hardware accelerated drawing of 2D shapes, images, and text, with an easy to use API.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 in SignWindowHandler 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!