LAnimation Reference Manual & Qt Integration Guide
The LAnimation class is a high-performance vector graphics and dynamic overlay engine built on top of the ThorVG rendering architecture. It is designed to load Adobe After Effects Lottie JSON files, render them as vector layers in memory, and publish them frame-by-frame to other targets (like LMixer or LPreview).
It supports multi-layered template loading, dynamic text replacements, shape color modifications, and frame-accurate playback control using markers.
1. API Reference & Key Methods
📌 Licensing
bool setLicense(const std::string& licenseKey)
Initializes license verification specifically for the animation instance.bool isLicensed() const
Checks if a valid license signature is active forLAnimation. If not licensed, a semi-transparent"now2sdk"watermark is overlaid on all output frames.
📌 Multi-Layer Lottie Operations
bool loadTemplate(int layerId, const std::string& jsonPath)
Loads a Lottie JSON file fromjsonPathinto the specifiedlayerId. Returnstrueif loaded successfully.void update(int layerId, const std::string& key, const std::string& value)
Dynamically replaces a placeholder text layer (key) inside the JSON template of the specified layer withvaluein-memory.void updateImage(int layerId, const std::string& assetId, const std::string& imagePath)
Replaces a raster image asset (assetIdor Lottie layer name) inside the template with a local image file (imagePath) at runtime.void updateColor(int layerId, const std::string& layerName, const std::string& hexColor1, const std::string& hexColor2 = "", const std::string& propertyName = "Color")
Modifies shape color properties inside a named layer.hexColor1andhexColor2represent RGB/ARGB color strings (e.g."#FFCC00").void addMarker(int layerId, const std::string& name, int frame)
Defines keyframe anchors for lifecycle states (Intro, Loop, Stop, Outro).void play(int layerId)
Starts rendering and playback of the specified layer animation.void stop(int layerId)
Triggers a graceful exit ("Outro") for the layer. If anOUTmarker is set, it jumps to the outro frame and unloads the layer at the end of the timeline.void close(int layerId)
Triggers a fast exit. If anOUTmarker is set, it jumps to the outro frame and unloads. If noOUTmarker is set, it unloads the layer immediately.
📌 Single-Layer Compatibility Overloads (Layer 0)
For backwards compatibility or simple single-layer templates, the following overloads default to layerId = 0:
bool loadTemplate(const std::string& jsonPath)void update(const std::string& key, const std::string& value)void updateImage(const std::string& assetId, const std::string& imagePath)void updateColor(const std::string& layerName, const std::string& hexColor1, const std::string& hexColor2 = "", const std::string& propertyName = "Color")void addMarker(const std::string& name, int frame)void stop()void close()void play()
📌 Video Format and Status
void setVideoFormat(const videoFormatProps& props)/void getVideoFormat(videoFormatProps& props)
Configures output canvas dimensions and target frame rate.double getFPS()
Returns the active template frame rate.int getWidth()/int getHeight()
Returns the output width and height dimensions of the animation canvas.
2. Markers Configuration & Lifecycle Management
Markers are critical for dividing a single Lottie template timeline into functional zones (e.g., Intro -> Loop -> Outro). Use addMarker to bind frame numbers to these states:
| Marker Name | Description | Loop Behavior |
|---|---|---|
"IN" |
Start Frame: The starting point of the animation. | Defaults to frame 0. |
"LOOP" |
Loop Start Anchor: When the animation reaches its end (totalFrames) or hitting a "STOP" marker, it wraps back to the "LOOP" frame instead of frame 0. |
Used to define the loop start point. |
"STOP" |
Idle / Hold Frame: The boundary of the loop. If the animation reaches "STOP" and the layer is not in Out mode, it loops back to "LOOP". If "LOOP" is not set, it stops playing and freezes on this frame. |
Used to hold graphics on-air. |
"OUT" |
Outro Start Frame: When stop(layerId) or close(layerId) is called, the playhead jumps directly to the "OUT" frame to play the exit animation. The layer automatically unloads at the end of the timeline. |
Triggers lower-third animations to exit. |
3. Qt Integration Example
The following Qt implementation demonstrates how to manage lower-thirds and scoreboards on separate layers with dynamic text, color changes, and timing loops.
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "now2sdk.h"
#include <QColorDialog>
#include <QFileInfo>
#include <QCoreApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWindow),
m_lAnimation(new LAnimation()),
m_lMixer(new LMixer()),
m_lPreview(new LPreview()),
m_gameTimer(new QTimer(this))
{
ui->setupUi(this);
// 1. Configure Formats
videoFormatProps vFormat;
vFormat.setVideoFormat = vF::HD1080_50p;
m_lAnimation->setVideoFormat(vFormat);
m_lMixer->setVideoFormat(vFormat);
// 2. Add Animation to Composite Layout Mixer
m_lMixer->addLayer("graphics_layer", m_lAnimation, 1, 0.0f, 0.0f, 255, 1920, 1080);
// 3. Enable Preview Window
m_lPreview->setProps("ui_framework", "qt");
m_lPreview->previewEnable(ui->previewWidget, false, true);
m_lPreview->previewObject(m_lMixer);
// 4. Connect Signals for Real-Time Updating
connect(ui->homeScoreSb, QOverload<int>::of(&QSpinBox::valueChanged), this, &MainWindow::updateScoreboard);
connect(ui->guestScoreSb, QOverload<int>::of(&QSpinBox::valueChanged), this, &MainWindow::updateScoreboard);
connect(ui->homeColorBtn, &QPushButton::clicked, this, &MainWindow::selectHomeColor);
// Game Clock
connect(m_gameTimer, &QTimer::timeout, this, &MainWindow::onClockTick);
}
MainWindow::~MainWindow() {
m_lAnimation->stop(1); // Scoreboard Layer
m_lAnimation->stop(2); // Lower Third Layer
delete m_lPreview;
delete m_lAnimation;
delete m_lMixer;
delete ui;
}
// ─── Scoreboard Layer (ID: 1) ───
void MainWindow::startScoreboard() {
QString path = QCoreApplication::applicationDirPath() + "/template/scoreboard.json";
if (m_lAnimation->loadTemplate(1, path.toStdString())) {
m_lAnimation->play(1);
updateScoreboard();
}
}
void MainWindow::updateScoreboard() {
// 1. Update text variables in the Lottie JSON
m_lAnimation->update(1, "homeclub", ui->homeNameEdit->text().toStdString());
m_lAnimation->update(1, "guestclub", ui->guestNameEdit->text().toStdString());
m_lAnimation->update(1, "homescore", std::to_string(ui->homeScoreSb->value()));
m_lAnimation->update(1, "guestscore", std::to_string(ui->guestScoreSb->value()));
// 2. Update shapes colors inside the Lottie animation
m_lAnimation->updateColor(1, "homeBG", m_homeColorHex.toStdString());
m_lAnimation->updateColor(1, "guestBG", m_guestColorHex.toStdString());
}
void MainWindow::selectHomeColor() {
QColor color = QColorDialog::getColor(Qt::red, this, "Select Home Team Color");
if (color.isValid()) {
m_homeColorHex = color.name(); // Format: #RRGGBB
updateScoreboard();
}
}
void MainWindow::onClockTick() {
m_secondsElapsed++;
int mins = m_secondsElapsed / 60;
int secs = m_secondsElapsed % 60;
QString timeStr = QString("%1:%2").arg(mins, 2, 10, QChar('0')).arg(secs, 2, 10, QChar('0'));
// Inject real-time clock text to lower third layer
m_lAnimation->update(1, "time", timeStr.toStdString());
}
// ─── Lower Third Layer (ID: 2) ───
void MainWindow::startLowerThird() {
QString path = QCoreApplication::applicationDirPath() + "/template/lowerthird.json";
if (m_lAnimation->loadTemplate(2, path.toStdString())) {
// Set lifecycle markers: STOP at frame 30, OUT at frame 31
m_lAnimation->addMarker(2, "STOP", 30);
m_lAnimation->addMarker(2, "OUT", 31);
m_lAnimation->update(2, "upText", "Alex Smith");
m_lAnimation->update(2, "downText", "Match Referee");
m_lAnimation->play(2);
}
}
void MainWindow::hideLowerThird() {
// Jumps playhead to frame 31 (OUT) to play the outro, then automatically unloads layer 2
m_lAnimation->stop(2);
}