blob: 7d8558ae06ea89db7a57e403c777898dace52ba9 [file] [log] [blame]
#include "rive/file.hpp"
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/viewmodel/viewmodel.hpp"
#include "rive/viewmodel/viewmodel_instance_number.hpp"
#include "rive/viewmodel/viewmodel_instance_trigger.hpp"
#include "utils/serializing_factory.hpp"
#include "rive_file_reader.hpp"
#include <catch.hpp>
#include <cstdio>
#include <cstring>
using namespace rive;
TEST_CASE("juice silver", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/juice.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto walkAnimation = artboard->animationNamed("walk");
REQUIRE(walkAnimation != nullptr);
auto renderer = silver.makeRenderer();
// Draw first frame.
walkAnimation->advanceAndApply(0.0f);
artboard->draw(renderer.get());
int frames = (int)(walkAnimation->durationSeconds() / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
walkAnimation->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("juice"));
}
TEST_CASE("hide silver", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/hide_test.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
auto vmi = file->createViewModelInstance(1, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
silver.addFrame();
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
CHECK(silver.matches("hide_test"));
}
TEST_CASE("n-slice silver", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/n_slice_triangle.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
artboard->advance(0.0f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
CHECK(silver.matches("n_slice_triangle"));
}
TEST_CASE("lock icon listener silver", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/lock_icon_demo.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
auto stateMachine = artboard->stateMachineAt(0);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
silver.addFrame();
// Click in the middle of the state machine.
stateMachine->pointerDown(
rive::Vec2D(artboard->width() / 2.0f, artboard->height() / 2.0f));
// Advance and apply twice to take the transition and apply the next state.
stateMachine->advanceAndApply(0.1f);
stateMachine->advanceAndApply(1.0f);
artboard->draw(renderer.get());
silver.addFrame();
// Do it again to lock the icon.
stateMachine->pointerDown(
rive::Vec2D(artboard->width() / 2.0f, artboard->height() / 2.0f));
// Advance and apply twice to take the transition and apply the next state.
stateMachine->advanceAndApply(0.1f);
stateMachine->advanceAndApply(1.0f);
artboard->draw(renderer.get());
CHECK(silver.matches("lock_icon_demo"));
}
TEST_CASE("validate text run listener works", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/text_listener_simpler.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
auto stateMachine = artboard->stateMachineAt(0);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
silver.addFrame();
// Click in the middle of the state machine.
stateMachine->pointerDown(
rive::Vec2D(artboard->width() * 0.8, artboard->height() / 2.0f));
// Advance and apply twice to take the transition and apply the next state.
stateMachine->advanceAndApply(0.1f);
stateMachine->advanceAndApply(1.0f);
artboard->draw(renderer.get());
CHECK(silver.matches("text_listener_simpler"));
}
TEST_CASE("validate text with modifiers and dashes render correctly",
"[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/text_stroke_test.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
auto stateMachine = artboard->stateMachineAt(0);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
// Draw first frame.
artboard->draw(renderer.get());
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("text_stroke_test"));
}
TEST_CASE("superbowl data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/superbowl.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(10.0f / 1.0f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(1.0f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("superbowl"));
}
TEST_CASE("data viz demo data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/data_viz_demo.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
auto vmiItem1 = vmi->propertyValue("item1");
auto vmiItem1ViewModelInstance = vmiItem1->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance()
.get();
if (vmiItem1ViewModelInstance != nullptr)
{
auto valueProp = vmiItem1ViewModelInstance->propertyValue("value");
if (valueProp != nullptr)
{
valueProp->as<ViewModelInstanceNumber>()->propertyValue(20);
}
}
int frames = (int)(0.8f / 0.064f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.064f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("data_viz_demo"));
}
TEST_CASE("bank card data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/bankcard.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(2.0f / 0.1f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("bankcard"));
}
TEST_CASE("ai assistant data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/ai_assitant.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
auto leftNumber = vmi->propertyValue("left");
auto bottomNumber = vmi->propertyValue("bottom");
auto topNumber = vmi->propertyValue("top");
auto rightNumber = vmi->propertyValue("right");
int frames = (int)(1.0f / 0.33f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
leftNumber->as<ViewModelInstanceNumber>()->propertyValue(i * 10);
bottomNumber->as<ViewModelInstanceNumber>()->propertyValue(i * 5);
topNumber->as<ViewModelInstanceNumber>()->propertyValue(i * 3);
rightNumber->as<ViewModelInstanceNumber>()->propertyValue(i * 2);
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("ai_assitant"));
}
TEST_CASE("echo show demo data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/echo_show_demo.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("echo_show_demo"));
}
TEST_CASE("rewards demo data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/rewards_demo.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
auto buttonProp = vmi->propertyValue("Button");
if (buttonProp != nullptr)
{
auto buttonVm = buttonProp->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance()
.get();
if (buttonVm != nullptr)
{
auto trigger = buttonVm->propertyValue("Pressed");
trigger->as<ViewModelInstanceTrigger>()->trigger();
}
}
int frames = (int)(5.0f / 0.25f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("rewards_demo"));
}
TEST_CASE("spotify kids demo data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/spotify_kids_demo.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("spotify_kids_demo"));
}
TEST_CASE("spotify kids app icon data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/spotify_kids_app_icon.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("spotify_kids_app_icon"));
}
TEST_CASE("hunter x demo data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/hunter_x_demo.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("hunter_x_demo"));
}
TEST_CASE("health tracker data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/db_health_tracker.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("db_health_tracker"));
}
TEST_CASE("car widgets data binding", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/car_widgets_v01.riv", &silver);
auto artboard = file->artboardDefault();
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
auto vmiItem1 = vmi->propertyValue("COMPASS");
auto vmiItem1ViewModelInstance = vmiItem1->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance()
.get();
if (vmiItem1ViewModelInstance != nullptr)
{
auto valueProp = vmiItem1ViewModelInstance->propertyValue("Rotation");
if (valueProp != nullptr)
{
valueProp->as<ViewModelInstanceNumber>()->propertyValue(20);
}
}
auto vmiItem2 = vmi->propertyValue("TIRE PSI");
auto vmiItem2ViewModelInstance = vmiItem2->as<ViewModelInstanceViewModel>()
->referenceViewModelInstance()
.get();
if (vmiItem2ViewModelInstance != nullptr)
{
auto valueProp = vmiItem2ViewModelInstance->propertyValue("FL Tyre");
if (valueProp != nullptr)
{
valueProp->as<ViewModelInstanceNumber>()->propertyValue(10);
}
}
int frames = (int)(1.0f / 0.016f);
for (int i = 0; i < frames; i++)
{
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("car_widgets_v01"));
}
TEST_CASE("Vertical align on text with ellipsis", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/vertical_align_ellipsis.riv", &silver);
auto artboard = file->artboardDefault();
REQUIRE(artboard != nullptr);
silver.frameSize(artboard->width(), artboard->height());
auto stateMachine = artboard->stateMachineAt(0);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
CHECK(silver.matches("vertical_align_ellipsis"));
}
TEST_CASE("Event triggers another event", "[silver]")
{
SerializingFactory silver;
auto file = ReadRiveFile("assets/event_trigger_event.riv", &silver);
auto artboard = file->artboardDefault();
REQUIRE(artboard != nullptr);
silver.frameSize(artboard->width(), artboard->height());
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
silver.addFrame();
// Click in a square that fires a trigger. This trigger will cause a
// transition that fires an event. There is a listener on that event that
// fires a second event.
stateMachine->pointerDown(rive::Vec2D(475, 25));
stateMachine->pointerUp(rive::Vec2D(475, 25));
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
silver.addFrame();
stateMachine->advanceAndApply(0.1f);
artboard->draw(renderer.get());
CHECK(silver.matches("event_trigger_event"));
}
// TEST_CASE("Collapsed data binds from layouts with display hidden",
// "[silver]")
// {
// SerializingFactory silver;
// auto file = ReadRiveFile("assets/collapse_data_binds.riv", &silver);
// auto artboard = file->artboardNamed("test-1");
// REQUIRE(artboard != nullptr);
// silver.frameSize(artboard->width(), artboard->height());
// auto stateMachine = artboard->stateMachineAt(0);
// int viewModelId = artboard.get()->viewModelId();
// auto vmi = viewModelId == -1
// ? file->createViewModelInstance(artboard.get())
// : file->createViewModelInstance(viewModelId, 0);
// stateMachine->advanceAndApply(0.0f);
// stateMachine->bindViewModelInstance(vmi);
// stateMachine->advanceAndApply(0.016f);
// auto renderer = silver.makeRenderer();
// artboard->draw(renderer.get());
// int frames = (int)(1.0f / 0.016f);
// for (int i = 0; i < frames; i++)
// {
// silver.addFrame();
// stateMachine->advanceAndApply(0.016f);
// artboard->draw(renderer.get());
// }
// CHECK(silver.matches("collapse_data_binds-test_1"));
// }
// TEST_CASE("Collapsed data binds from property groups in solos", "[silver]")
// {
// SerializingFactory silver;
// auto file = ReadRiveFile("assets/collapse_data_binds.riv", &silver);
// auto artboard = file->artboardNamed("test-2");
// REQUIRE(artboard != nullptr);
// silver.frameSize(artboard->width(), artboard->height());
// auto stateMachine = artboard->stateMachineAt(0);
// int viewModelId = artboard.get()->viewModelId();
// auto vmi = viewModelId == -1
// ? file->createViewModelInstance(artboard.get())
// : file->createViewModelInstance(viewModelId, 0);
// stateMachine->advanceAndApply(0.0f);
// stateMachine->bindViewModelInstance(vmi);
// stateMachine->advanceAndApply(0.016f);
// auto renderer = silver.makeRenderer();
// artboard->draw(renderer.get());
// int frames = (int)(1.0f / 0.016f);
// for (int i = 0; i < frames; i++)
// {
// silver.addFrame();
// stateMachine->advanceAndApply(0.016f);
// artboard->draw(renderer.get());
// }
// CHECK(silver.matches("collapse_data_binds-test_2"));
// }