Expose artboard instances directly on File
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp index 0315a82..ad19de3 100644 --- a/include/rive/artboard.hpp +++ b/include/rive/artboard.hpp
@@ -24,6 +24,7 @@ class NestedArtboard; class ArtboardInstance; class LinearAnimationInstance; + class StateMachineInstance; class Artboard : public ArtboardBase, public CoreContext, public ShapePaintContainer { friend class File; @@ -123,18 +124,23 @@ return nullptr; } + size_t animationCount() const { return m_Animations.size(); } + std::string animationNameAt(size_t index) const; + + size_t stateMachineCount() const { return m_StateMachines.size(); } + std::string stateMachineNameAt(size_t index) const; + LinearAnimation* firstAnimation() const; LinearAnimation* animation(std::string name) const; LinearAnimation* animation(size_t index) const; - size_t animationCount() const { return m_Animations.size(); } StateMachine* firstStateMachine() const; StateMachine* stateMachine(std::string name) const; StateMachine* stateMachine(size_t index) const; - size_t stateMachineCount() const { return m_StateMachines.size(); } /// Make an instance of this artboard, must be explictly deleted when no /// longer needed. + // Deprecated... std::unique_ptr<ArtboardInstance> instance() const; /// Returns true if the artboard is an instance of another @@ -157,6 +163,11 @@ class ArtboardInstance : public Artboard { public: + std::unique_ptr<LinearAnimationInstance> animationAt(size_t index); + std::unique_ptr<LinearAnimationInstance> animationNamed(std::string name); + + std::unique_ptr<StateMachineInstance> stateMachineAt(size_t index); + std::unique_ptr<StateMachineInstance> stateMachineNamed(std::string name); }; } // namespace rive
diff --git a/include/rive/file.hpp b/include/rive/file.hpp index 29f28e2..ab85e86 100644 --- a/include/rive/file.hpp +++ b/include/rive/file.hpp
@@ -66,8 +66,15 @@ /// @returns the file's backboard. All files have exactly one backboard. Backboard* backboard() const { return m_Backboard.get(); } - /// @returns the default artboard. This is typically the first artboard - /// found in the file's artboard list. + /// @returns the number of artboards in the file. + size_t artboardCount() const { return m_Artboards.size(); } + std::string artboardNameAt(size_t index) const; + + // Instances + std::unique_ptr<ArtboardInstance> artboardDefault() const; + std::unique_ptr<ArtboardInstance> artboardAt(size_t index) const; + std::unique_ptr<ArtboardInstance> artboardNamed(std::string name) const; + Artboard* artboard() const; /// @returns the named artboard. If no artboard is found with that name, @@ -78,9 +85,6 @@ /// index is out of range. Artboard* artboard(size_t index) const; - /// @returns the number of artboards in the file. - size_t artboardCount() const { return m_Artboards.size(); } - private: ImportResult read(BinaryReader& reader, const RuntimeHeader& header); };
diff --git a/skia/thumbnail_generator/src/main.cpp b/skia/thumbnail_generator/src/main.cpp index 226b2ed..e17b9f1 100644 --- a/skia/thumbnail_generator/src/main.cpp +++ b/skia/thumbnail_generator/src/main.cpp
@@ -55,7 +55,7 @@ fprintf(stderr, "Failed to read rive file.\n"); return 1; } - auto artboard = file->artboard(); + auto artboard = file->artboardDefault(); artboard->advance(0.0f); delete[] bytes;
diff --git a/skia/viewer/src/main.cpp b/skia/viewer/src/main.cpp index 6136e5f..d7cf24c 100644 --- a/skia/viewer/src/main.cpp +++ b/skia/viewer/src/main.cpp
@@ -36,6 +36,13 @@ std::unique_ptr<rive::ArtboardInstance> artboardInstance; std::unique_ptr<rive::StateMachineInstance> stateMachineInstance; std::unique_ptr<rive::LinearAnimationInstance> animationInstance; + +// ImGui wants raw pointers to names, but our public API returns +// names as strings (by value), so we cache these names each time we +// load a file +std::vector<std::string> animationNames; +std::vector<std::string> stateMachineNames; + // We hold onto the file's bytes for the lifetime of the file, in case we want // to change animations or state-machines, we just rebuild the rive::File from // it. @@ -44,6 +51,19 @@ int animationIndex = 0; int stateMachineIndex = -1; +static void loadNames(const rive::Artboard* ab) { + animationNames.clear(); + stateMachineNames.clear(); + if (ab) { + for (size_t i = 0; i < ab->animationCount(); ++i) { + animationNames.push_back(ab->animationNameAt(i)); + } + for (size_t i = 0; i < ab->stateMachineCount(); ++i) { + stateMachineNames.push_back(ab->stateMachineNameAt(i)); + } + } +} + void initStateMachine(int index) { stateMachineIndex = index; animationIndex = -1; @@ -60,11 +80,12 @@ artboardInstance = nullptr; currentFile = std::move(file); - artboardInstance = currentFile->artboard()->instance(); + artboardInstance = currentFile->artboardDefault(); artboardInstance->advance(0.0f); + loadNames(artboardInstance.get()); if (index >= 0 && index < artboardInstance->stateMachineCount()) { - stateMachineInstance = std::make_unique<rive::StateMachineInstance>(artboardInstance->stateMachine(index), artboardInstance.get()); + stateMachineInstance = artboardInstance->stateMachineAt(index); } } @@ -84,11 +105,12 @@ artboardInstance = nullptr; currentFile = std::move(file); - artboardInstance = currentFile->artboard()->instance(); + artboardInstance = currentFile->artboardDefault(); artboardInstance->advance(0.0f); + loadNames(artboardInstance.get()); if (index >= 0 && index < artboardInstance->animationCount()) { - animationInstance = std::make_unique<rive::LinearAnimationInstance>(artboardInstance->animation(index), artboardInstance.get()); + animationInstance = artboardInstance->animationAt(index); } } @@ -298,12 +320,11 @@ "Animations", &animationIndex, [](void* data, int index, const char** name) { - const char* animationName = artboardInstance->animation(index)->name().c_str(); - *name = animationName; + *name = animationNames[index].c_str(); return true; }, artboardInstance.get(), - artboardInstance->animationCount(), + animationNames.size(), 4)) { stateMachineIndex = -1; @@ -313,12 +334,11 @@ "State Machines", &stateMachineIndex, [](void* data, int index, const char** name) { - const char* machineName = artboardInstance->stateMachine(index)->name().c_str(); - *name = machineName; + *name = stateMachineNames[index].c_str(); return true; }, artboardInstance.get(), - artboardInstance->stateMachineCount(), + stateMachineNames.size(), 4)) { animationIndex = -1;
diff --git a/src/artboard.cpp b/src/artboard.cpp index 77d2122..7402623 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -450,6 +450,16 @@ return this->isTranslucent(inst->animation()); } +std::string Artboard::animationNameAt(size_t index) const { + auto la = this->animation(index); + return la ? la->name() : nullptr; +} + +std::string Artboard::stateMachineNameAt(size_t index) const { + auto sm = this->stateMachine(index); + return sm ? sm->name() : nullptr; +} + LinearAnimation* Artboard::firstAnimation() const { if (m_Animations.empty()) { return nullptr; @@ -609,3 +619,32 @@ return true; } } + +////////// ArtboardInstance + +#include "rive/animation/linear_animation_instance.hpp" +#include "rive/animation/state_machine_instance.hpp" + +std::unique_ptr<LinearAnimationInstance> +ArtboardInstance::animationAt(size_t index) { + auto la = this->animation(index); + return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr; +} + +std::unique_ptr<LinearAnimationInstance> +ArtboardInstance::animationNamed(std::string name) { + auto la = this->animation(name); + return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr; +} + +std::unique_ptr<StateMachineInstance> +ArtboardInstance::stateMachineAt(size_t index) { + auto sm = this->stateMachine(index); + return sm ? std::make_unique<StateMachineInstance>(sm, this) : nullptr; +} + +std::unique_ptr<StateMachineInstance> +ArtboardInstance::stateMachineNamed(std::string name) { + auto sm = this->stateMachine(name); + return sm ? std::make_unique<StateMachineInstance>(sm, this) : nullptr; +}
diff --git a/src/file.cpp b/src/file.cpp index eb4577d..bf5bd04 100644 --- a/src/file.cpp +++ b/src/file.cpp
@@ -257,3 +257,23 @@ } return m_Artboards[index].get(); } + +std::string File::artboardNameAt(size_t index) const { + auto ab = this->artboard(index); + return ab ? ab->name() : ""; +} + +std::unique_ptr<ArtboardInstance> File::artboardDefault() const { + auto ab = this->artboard(); + return ab ? ab->instance() : nullptr; +} + +std::unique_ptr<ArtboardInstance> File::artboardAt(size_t index) const { + auto ab = this->artboard(index); + return ab ? ab->instance() : nullptr; +} + +std::unique_ptr<ArtboardInstance> File::artboardNamed(std::string name) const { + auto ab = this->artboard(name); + return ab ? ab->instance() : nullptr; +}
diff --git a/test/image_mesh_test.cpp b/test/image_mesh_test.cpp index d1575f2..6b817ed 100644 --- a/test/image_mesh_test.cpp +++ b/test/image_mesh_test.cpp
@@ -31,9 +31,9 @@ RiveFileReader reader("../../test/assets/tape.riv"); auto file = reader.file(); - auto instance1 = file->artboard()->instance(); - auto instance2 = file->artboard()->instance(); - auto instance3 = file->artboard()->instance(); + auto instance1 = file->artboardDefault(); + auto instance2 = file->artboardDefault(); + auto instance3 = file->artboardDefault(); auto node1 = instance1->find("Tape body.png"); auto node2 = instance2->find("Tape body.png");
diff --git a/test/instancing_test.cpp b/test/instancing_test.cpp index 40fe2a5..2d8672a 100644 --- a/test/instancing_test.cpp +++ b/test/instancing_test.cpp
@@ -50,7 +50,7 @@ REQUIRE(file->artboard() != nullptr); REQUIRE(!file->artboard()->isInstance()); - auto artboard = file->artboard()->instance(); + auto artboard = file->artboardDefault(); REQUIRE(artboard->isInstance()); @@ -86,7 +86,7 @@ REQUIRE(file != nullptr); REQUIRE(file->artboard() != nullptr); - auto artboard = file->artboard()->instance(); + auto artboard = file->artboardDefault(); REQUIRE(file->artboard()->animationCount() == artboard->animationCount()); REQUIRE(file->artboard()->firstAnimation() == artboard->firstAnimation());