The message & command buses
Two pieces of application plumbing
Platform carries two generic pieces of infrastructure that every interactive application needs and that are not document concepts: a Message Bus for change notifications and a Command Bus for undoable edits. They live here, not in Prism Core, precisely because they are domain-agnostic plumbing — neither knows anything about Prism documents, so a renderer or a game reuses them just as a document editor does.
The Message Bus
A lightweight publish/notify channel — "this changed, redraw later" — with no payload, RAII subscriptions, and batching. It decouples the thing that changed from the things that react:
events::Bus bus;
auto sub = bus.subscribe(Channel::Selection, [&]{ rebuildPanels(); }); // RAII; unsubscribes on scope exit
bus.publish(Channel::Selection); // fan out
{
events::Batch b(bus); // coalesce a burst of changes into one notification
/* many edits … */
} // one publish on scope exit
It is the signal that drives Prism UI's dirty-region repaint: an edit publishes, the affected regions mark dirty, and the app loop redraws them on its own schedule — never synchronously from inside the edit.
The Command Bus
A header-only, fully generic CommandBus<Ctx> providing apply / undo / redo and transactions over any context type, with an after-run hook. It has zero dependency on Core — you parameterise it on your own document type:
command::CommandBus<Document> bus;
bus.onAfterRun = [&]{ /* publish a change, redraw */ };
bus.run<SetProperty>("/world/ball.radius", Value(2.0f)); // applies + records for undo
bus.undo(); // and back
{
command::Transaction tx(bus); // group several commands into one undo step
bus.run<AddPrim>("/world/light", "object");
bus.run<SetProperty>("/world/light.intensity", Value(80.0f));
}
Concrete commands (SetProperty, AddPrim, a snapshot command) are not in Platform — the consumer writes them against CommandBus<MyDocument>. The bus provides the apply/undo/redo machinery and the transaction grouping; you provide what a command does.
Why this is the editing seam
Together the two buses are how an application edits its document uniformly. The Editor runs CommandBus<Document> so every change — a UI control, a typed source edit, or an agent's tool call over MCP — is one undoable command, and onAfterRun publishes on the Message Bus so the panels rebuild. Because the command bus is generic and the message bus is payload-free, this exact pattern works for any C++ application built on Platform — which is the point of putting them here rather than welding them to one document model.