Skip to main content
Rive’s View Models expose strongly-typed properties (numbers, strings, colors, booleans, enums, triggers, lists, nested view models, image and artboard references) that an artboard binds to. From C++ you instance a view model, mutate properties, and the bound visuals update on the next advanceAndApply.

Concepts

  • ViewModelRuntime — schema for a view model defined in the editor. Lives in the File.
  • ViewModelInstanceRuntime — typed wrapper around an instance of that schema. Exposes the property API (propertyNumber, propertyString, etc). You own it via rcp<>.
  • ViewModelInstance — the underlying bindable instance. Artboard and StateMachineInstance bind to this type. Get one from a ViewModelInstanceRuntime with .instance().
  • ViewModelInstance*Runtime — typed handles for individual properties (…NumberRuntime, …StringRuntime, etc).

Creating an Instance

The simplest path is to ask the file for the artboard’s default view model, then create a default instance from it:
For full control, look up a specific view model schema by index or name and create instances from it:
Bind the same ViewModelInstance to both the artboard and the state machine. The artboard binding drives layout-affecting properties; the state-machine binding drives state-machine transitions and listener conditions.

Reading & Writing Properties

All accessors are path-based — /-separated for nested view models.

Nested View Models

You can also swap a nested view model wholesale — useful for swapping a list cell’s data without rebuilding the artboard:

Lists

List items are themselves ViewModelInstanceRuntimes — same property API as above.

Image & Artboard Properties

Lifecycle

  • A ViewModelInstanceRuntime is a thin wrapper over a ViewModelInstance. Hold the rcp<> for as long as anything binds to it.
  • Property handles (ViewModelInstanceNumberRuntime*, etc) are owned by the parent instance. Cache the pointer — it stays valid for the instance’s lifetime.
  • After mutating properties, the next sm->advanceAndApply(dt) propagates the changes through data binds and into rendering.

When Properties Don’t Exist

Every propertyX(name) getter returns nullptr if the name doesn’t resolve, so you can probe an instance safely:
For introspection, walk the schema: