UI message bus
Supported bindings: ossia
Some UIs may have more complicated logic that cannot just be represented through widgets changing single controls: pressing a button may trigger the loading of a file, the entire reconfiguration of the UI, etc.
Thus, the engine may have to be notified of such changes happening in the UI. The way this is generally done is through thread-safe queues exchanging messages.
An experimental implementation of this has been done in ossia score. Here is a skeleton for how to write such a plug-in:
using message_to_ui = ...;
using message_to_engine = ...;
struct MyProcessor {
// Receive a message on the processing thread from the UI
void process_message(message_to_engine msg)
{
// 3. The engine received the message from the UI.
// It can for instance send a confirmation that the message has been received:
send_message(message_to_ui{ ... });
}
// Send a message from the processing thread to the ui
std::function<void(message_to_ui)> send_message;
struct ui {
// Define the UI here as seen previously.
struct bus {
// 1. Set up connections from UI widgets to the message bus
void init(ui& ui)
{
ui.some.widget.on_some_event = [&] {
// 2. Some action occured on the UI: this callback is called.
// We send a message to the engine:
this->send_message(message_to_engine{...});
};
}
// Receive a message on the UI thread from the processing thread
static void process_message(ui& self, processor_to_ui msg)
{
// 4. The UI has received the confirmation from the engine,
// we made a safe round-trip between our threads :-)
}
// Send a message from the ui to the processing thread
std::function<void(ui_to_processor)> send_message;
}
};
}
Note that message_to_ui
and message_to_engine
can be any simple type:
- Ints, floats, strings, etc.
std::vector
std::variant
- Any combination and nesting of those in an aggregate struct.
For example, the following type will automatically be serialized & deserialized:
struct ui_to_processor {
int foo;
std::string bar;
std::variant<float, double> x;
std::vector<float> y;
struct {
int x, y;
} baz;
};
So far this has only been tested on a single computer but this could be tried over a network too.