Events Reference#

Timeline events function as callbacks to state changes being committed to the timeline. This either happens on the next frame after a state change was requested, or if the commit() function is used on a Timeline to request that the changes take place immediately.

If the state changes are applied at the normal time (i.e. the next frame), this occurs during the main RunLoop’s update event (omni::kit::kGlobalEventUpdate) at priority determined by omni::kit::update::eUsdTimelineStateRefresh. Since this happens in the main thread, this means that typically state events are dispatched from the main thread.

However, if commit() is called, these events are dispatched from the thread that calls commit(). This can lead to synchronization issues especially if these events are expected to be dispatched on the main thread.

Events#

Warning

Timeline events have a global name, but typically listeners care about a specific Timeline object. Therefore it is very important to specify a filter when observing an event, otherwise your observer will be called for all timelines. Helper functions omni::timeline::Timeline::getEventKey() and omni.timeline.Timeline.get_event_key() exist to provide easy means to filter these events.

Since all events exist in a global namespace, timeline event descriptors are composed as follows:

omni.timeline:timeline:<event name>

The <event name> component is listed below for each event.

Play#

Timeline has started to play.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

Pause#

Timeline has paused.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

Stop#

Timeline has stopped.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

Current Time Ticked (Always)#

Current time is ticked by update function. Called per subframe tick even if not playing.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • currentTime (double) - The current time in seconds.

  • dt (double) - The delta time in seconds since the previous tick.

  • tick (int) - The internal tick index.

Current Time Ticked (Playing Only)#

Current time is ticked by update function. Called per subframe tick only when playing.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • currentTime (double) - The current time in seconds.

  • dt (double) - The delta time in seconds since the previous tick.

  • tick (int) - The internal tick index.

Loop Mode Changed#

Timeline looping mode has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • looping (bool) - If true, the timeline is now set to loop; otherwise false.

Start Time Changed#

Timeline’s start time has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • startTime (double) - The start time in seconds.

End Time Changed#

Timeline’s end time has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • endTime (double) - The start time in seconds.

Time-codes per second Changed#

Timeline’s time-codes per second (animation framerate) has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • timeCodesPerSecond (double) - The number of time-codes per second.

Auto-Update Changed#

Timeline’s auto-update flag has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • autoUpdate (bool) - If true, the Timeline is now set to auto-update; otherwise false.

Pre-Rolling Changed#

Timeline’s pre-rolling flag has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • prerolling (bool) - If true, the Timeline’s pre-rolling flag is now true; otherwise false.

Tentative Time Changed#

Timeline’s tentative current time was changed by the user.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • tentativeTime (double) - The updated tentative time in seconds.

Ticks-per-Frame Changed#

Timeline’s ticks-per-frame count has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • ticksPerFrame (uint) - The updated ticks-per-frame count.

Play-every-Frame Flag Changed#

Timeline’s play-every-frame (no frame skipping) flag has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • playEveryFrame (bool) - The updated value of the play-every-frame flag.

Target Framerate Changed#

Timeline’s target framerate has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • targetFrameRate (float) - The updated target frame rate value.

Director Changed#

Timeline is now driven by a new Director timeline (or no Director).

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • hasDirector (bool) - Indicates whether this Timeline now has a Director Timeline.

  • directorName (string) - The name of the Director Timeline. If hasDirector is false, this will be an empty string.

Zoom Changed#

Timeline’s zoom range has changed.

Parameters:

  • name (string) - Timeline name. The default Timeline has an empty string as the name.

  • cleared (bool) - true if the zoom has been cleared. false if a new zoom start and end time have been set.

  • startTime (double) - If cleared=true, this will be the Timeline’s normal start time in seconds. Otherwise, this will be the Timeline’s zoom start time in seconds.

  • endTime (double) - If cleared=true, this will be the Timeline’s normal end time in seconds. Otherwise, this will be the Timeline’s zoom end time in seconds.

Converting Legacy Events#

Previously, a carb::events::IEventStream could be retrieved from a omni::timeline::Timeline but this is now deprecated in favor of using carb::eventdispatcher::IEventDispatcher. Select the tab below to see conversion examples for C++ or Python.

Main differences:

  • As mentioned above, use of a filter parameter to observeEvent() is required to ensure that only events for the desired Timeline are delivered to your observer.

  • Event Streams allowed generic subscriptions that would receive every event. This promoted time-wasting behavior where only one event was desired but the handler would still be called for every event. IEventDispatcher requires a separate observeEvent call for each event name.

Old:

// carb::events::ISubscriptionPtr m_timelineSub;
m_timelineSub = carb::events::createSubscriptionToPop(
    timeline->getTimelineEventStream(),
    [this](carb::events::IEvents* e) {
        if (e->type == static_cast<int>(carb::timeline::TimelineUpdateType::ePlay))
            handlePlay();
        else if (e->type == static_cast<int>(carb::timeline::TimelineUpdateType::Stop))
            handleStop();
        else if (e->type == static_cast<int>(carb::timeline::TimelineUpdateType::Pause))
            handlePause();
        else if (e->type == static_cast<int>(carb::timeline::TimelineUpdateType::eCurrentTimeTicked))
            handleTick(e);
        // Other events were still called, but ignored
    },
    carb::events::kDefaultOrder,
    "My subscription name"
);

New:

Since multiple calls must now be their own call to IEventDispatcher::dispatchEvent, one option to create these might be a function dispatch table:

using FuncType = void (MyClass::*)(const carb::eventdispatcher::Event&);
static std::pair<carb::RString, FuncType> kEvents[] = {
    { omni::timeline::kGlobalEventPlay, &MyClass::handlePlay }, // must be changed to take the Event parameter
    { omni::timeline::kGlobalEventStop, &MyClass::handleStop }, // must be changed to take the Event parameter
    { omni::timeline::kGlobalEventPause, &MyClass::handlePause }, // must be changed to take the Event parameter
    { omni::timeline::kGlobalEventCurrentTimeTicked, &MyClass::handleTick }, // Event type changes
};

// carb::eventdispatcher::ObserverGuard m_timelineSub[CARB_COUNTOF(kEvents)];
for (size_t i = 0; i != CARB_COUNTOF(kEvents); ++i)
{
    m_timelineSub[i] = carb::getCachedInterface<carb::eventdispatcher::IEventDispatcher>()->observeEvent(
        carb::RStringKey("My observer name"),
        carb::eventdispatcher::kDefaultOrder,
        kEvents[i].first,
        [this, func = kEvents[i].second](const auto& event) {
            (this->*func)(event);
        },
        timeline->getEventKey(), // Important to have this filter
    );
}

Old:

import omni.timeline
import carb.events

# ...

def _on_timeline_event(self, e: carb.events.IEvent):
    if e.type == int(omni.timeline.TimelineEventType.PLAY):
        self._handle_play()
    elif e.type == int(omni.timeline.TimelineEventType.STOP):
        self._handle_stop()
    elif e.type == int(omni.timeline.TimelineEventType.PAUSE):
        self._handle_pause()
    elif e.type == int(omni.timeline.TimelineEventType.CURRENT_TIME_TICKED):
        self._handle_tick(e)
    # Other events were still called, but ignored

# ...

self._timeline_sub = self._timeline.get_timeline_event_stream().create_subscription_to_pop(
    self._on_timeline_event,
    0,
    "My subscriber name"
)

New:

import omni.timeline
import carb.eventdispatcher

# ...

self._timeline_subs = [
    carb.eventdispatcher.get_eventdispatcher().observe_event(
        observer_name="My observer name",
        filter = self._timeline.get_event_key(), # important to have this filter
        event_name=name,
        on_event=func
    )
    for name, func in (
        (omni.timeline.GLOBAL_EVENT_PLAY, self._handle_play), # must be changed to ignore the Event parameter
        (omni.timeline.GLOBAL_EVENT_STOP, self._handle_stop), # must be changed to ignore the Event parameter
        (omni.timeline.GLOBAL_EVENT_PAUSE, self._handle_pause), # must be changed to ignore the Event parameter
        (omni.timeline.GLOBAL_EVENT_CURRENT_TIME_TICKED, self._handle_tick) # Event type changes
    )
]