mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 13:11:19 +01:00
* make file ref counted * migrate File to refcnt * add bindable artboard class to keep file reference * feat(unity): support rcp file and BindableArtboard class (#10228) * refactor(apple): use updated file bindable artboard apis (#10229) * update command queue to support bindable artboards * use bindable artboards on command queue * self manage view model instances in js runtime * change remaining viewModelInstanceRuntimes to rcp * refactor(apple): update view model instances to use rcp (#10298) * refactor(unity): support rcp ViewModelInstanceRuntime (#10309) * rebase fix * deprecate getArtboard in favor of getBindableArtboard * fix merge * remove unused lambda capture * fix rive binding * feat(Android): RCP File, VMI, and add bindable artboards (#10456) * refactor: C++ refactors - Import from long (incorrect) -> jlong - Header clang-tidy fix - Use reinterpret_cast instead of C-style cast - Break out some variables instead of long one liners - Use auto - Remove unused env and thisObj # Conflicts: # packages/runtime_android/kotlin/src/main/cpp/src/helpers/general.cpp * docs: Improve documentation on the File class * feat: Support bindable artboard type and RCP VMIs # Conflicts: # packages/runtime_android/kotlin/src/androidTest/java/app/rive/runtime/kotlin/core/RiveDataBindingTest.kt * feat: Support RCP files * refactor: Change from +1/-1 ref to just release * fix: Moved to the more appropriate null pointer for GetStringUTFChars * replace unref with release Co-authored-by: Adam <67035612+damzobridge@users.noreply.github.com> Co-authored-by: David Skuza <david@rive.app> Co-authored-by: Erik <erik@rive.app> Co-authored-by: hernan <hernan@rive.app>
255 lines
9.2 KiB
C++
255 lines
9.2 KiB
C++
#include <rive/file.hpp>
|
|
#include <rive/node.hpp>
|
|
#include <rive/assets/image_asset.hpp>
|
|
#include <rive/shapes/rectangle.hpp>
|
|
#include <rive/shapes/shape.hpp>
|
|
#include <utils/no_op_renderer.hpp>
|
|
#include <rive/shapes/paint/solid_color.hpp>
|
|
#include <rive/shapes/paint/color.hpp>
|
|
#include <rive/shapes/paint/fill.hpp>
|
|
#include <rive/shapes/image.hpp>
|
|
#include <rive/shapes/paint/solid_color.hpp>
|
|
#include <rive/text/text_value_run.hpp>
|
|
#include <rive/custom_property_number.hpp>
|
|
#include <rive/custom_property_string.hpp>
|
|
#include <rive/custom_property_boolean.hpp>
|
|
#include <rive/constraints/follow_path_constraint.hpp>
|
|
#include <rive/viewmodel/viewmodel_instance_artboard.hpp>
|
|
#include <rive/viewmodel/viewmodel_instance_viewmodel.hpp>
|
|
#include <rive/viewmodel/viewmodel_instance_trigger.hpp>
|
|
#include "rive/animation/state_machine_instance.hpp"
|
|
#include "rive/nested_artboard.hpp"
|
|
#include "rive_file_reader.hpp"
|
|
#include "utils/serializing_factory.hpp"
|
|
#include <catch.hpp>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
using namespace rive;
|
|
|
|
TEST_CASE("Test data binding artboards from same and different sources",
|
|
"[data binding]")
|
|
{
|
|
// Note: the data_binding_artboards_source_test has a view model created
|
|
// that matches the view model the original artboards have. This is a
|
|
// temporary "hack" to validate that the artboard gets correctly bound
|
|
SerializingFactory silver;
|
|
auto file = ReadRiveFile("assets/data_binding_artboards_test.riv", &silver);
|
|
auto sourceFile =
|
|
ReadRiveFile("assets/data_binding_artboards_source_test.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 vmiArtboard =
|
|
vmi->propertyValue("ab")->as<ViewModelInstanceArtboard>();
|
|
auto vmiChild = vmi->propertyValue("ch")
|
|
->as<ViewModelInstanceViewModel>()
|
|
->referenceViewModelInstance()
|
|
.get();
|
|
auto vmTrigger =
|
|
vmiChild->propertyValue("tr")->as<ViewModelInstanceTrigger>();
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to local artboard at index 1
|
|
|
|
auto ch1Source = file->bindableArtboardNamed("ch1");
|
|
vmiArtboard->asset(ch1Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to local artboard at index 2
|
|
|
|
auto ch2Source = file->bindableArtboardNamed("ch2");
|
|
vmiArtboard->asset(ch2Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to external artboard "source_1"
|
|
auto source1 = sourceFile->bindableArtboardNamed("source_1");
|
|
vmiArtboard->asset(source1);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Fire trigger once to change text color
|
|
vmTrigger->trigger();
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Fire trigger once to change text color again
|
|
vmTrigger->trigger();
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to external artboard "source_2"
|
|
auto source2 = sourceFile->bindableArtboardNamed("source_2");
|
|
vmiArtboard->asset(source2);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to external artboard "source_1"
|
|
vmiArtboard->asset(source1);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change back to local artboard at index 1
|
|
vmiArtboard->asset(ch2Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// reset the artboard to null
|
|
vmiArtboard->asset(nullptr);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change back to local artboard at index 1
|
|
vmiArtboard->asset(ch2Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
CHECK(silver.matches("data_binding_artboards_test"));
|
|
}
|
|
|
|
TEST_CASE("Test recursive data binding artboards is skipped", "[data binding]")
|
|
{
|
|
// Note: the data_binding_artboards_source_test has a view model created
|
|
// that matches the view model the original artboards have. This is a
|
|
// temporary "hack" to validate that the artboard gets correctly bound
|
|
SerializingFactory silver;
|
|
auto file = ReadRiveFile("assets/data_binding_artboards_test.riv", &silver);
|
|
|
|
auto artboard = file->artboardNamed("recursive-grand-parent");
|
|
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 vmiArtboard =
|
|
vmi->propertyValue("ab")->as<ViewModelInstanceArtboard>();
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to artboard "recursive-grand-child-1"
|
|
auto child1Source = file->bindableArtboardNamed("recursive-grand-child-1");
|
|
vmiArtboard->asset(child1Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Changing source to artboard "recursive-parent" does not change the
|
|
// content because it's an ancestor of itself
|
|
auto parentSource = file->bindableArtboardNamed("recursive-parent");
|
|
vmiArtboard->asset(parentSource);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Changing source to artboard "recursive-grand-parent" does not change the
|
|
// content because it's an ancestor of itself
|
|
auto grandParentSource =
|
|
file->bindableArtboardNamed("recursive-grand-parent");
|
|
vmiArtboard->asset(grandParentSource);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
// Change source to artboard "recursive-grand-child-2"
|
|
auto child2Source = file->bindableArtboardNamed("recursive-grand-child-2");
|
|
vmiArtboard->asset(child2Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
|
|
CHECK(silver.matches("data_binding_artboards_test_recursive"));
|
|
}
|
|
|
|
TEST_CASE("Test default data binding artboard from different source",
|
|
"[data binding]")
|
|
{
|
|
// Note: the data_binding_artboards_source_test has a view model created
|
|
// that matches the view model the original artboards have. This is a
|
|
// temporary "hack" to validate that the artboard gets correctly bound
|
|
SerializingFactory silver;
|
|
auto file = ReadRiveFile("assets/data_binding_artboards_test.riv", &silver);
|
|
auto sourceFile =
|
|
ReadRiveFile("assets/data_binding_artboards_source_test.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 vmiArtboard =
|
|
vmi->propertyValue("ab")->as<ViewModelInstanceArtboard>();
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
// Change source to local artboard at index 1
|
|
|
|
auto ch1Source = file->bindableArtboardNamed("ch1");
|
|
vmiArtboard->asset(ch1Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
// Change source to local artboard at index 2
|
|
|
|
auto ch2Source = file->bindableArtboardNamed("ch2");
|
|
vmiArtboard->asset(ch2Source);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
// Change source to default bindable artboard
|
|
auto source1 = sourceFile->bindableArtboardDefault();
|
|
vmiArtboard->asset(source1);
|
|
silver.addFrame();
|
|
stateMachine->advanceAndApply(0.1f);
|
|
artboard->draw(renderer.get());
|
|
CHECK(silver.matches("data_binding_artboards_default_test"));
|
|
} |