add advanced phase to render loop (#10318) af18705be2 * add reset phase to render loop Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index 8949345..b1ecd35 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -559f237078e0e1430a661766c071ce22bd11abc7 +af18705be2294cf120d220bd89a6d64adcd17fd1
diff --git a/include/rive/animation/state_machine_instance.hpp b/include/rive/animation/state_machine_instance.hpp index 71443a2..f53f129 100644 --- a/include/rive/animation/state_machine_instance.hpp +++ b/include/rive/animation/state_machine_instance.hpp
@@ -125,6 +125,7 @@ bool advanceAndApply(float secs) override; void advancedDataContext(); + void reset(); std::string name() const override; HitResult pointerMove(Vec2D position, float timeStamp = 0) override; HitResult pointerDown(Vec2D position) override;
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp index 052ab82..c879f42 100644 --- a/include/rive/artboard.hpp +++ b/include/rive/artboard.hpp
@@ -2,6 +2,7 @@ #define _RIVE_ARTBOARD_HPP_ #include "rive/advance_flags.hpp" +#include "rive/resetting_component.hpp" #include "rive/animation/linear_animation.hpp" #include "rive/animation/state_machine.hpp" #include "rive/core_context.hpp" @@ -55,7 +56,10 @@ typedef float (*RootTransformCallback)(void*, float, float, bool); #endif -class Artboard : public ArtboardBase, public CoreContext, public Virtualizable +class Artboard : public ArtboardBase, + public CoreContext, + public Virtualizable, + public ResettingComponent { friend class File; friend class ArtboardImporter; @@ -198,6 +202,7 @@ AdvanceFlags flags = AdvanceFlags::AdvanceNested | AdvanceFlags::Animate | AdvanceFlags::NewFrame); + void reset() override; uint8_t drawOrderChangeCounter() { return m_drawOrderChangeCounter; } Drawable* firstDrawable() { return m_FirstDrawable; };
diff --git a/include/rive/artboard_component_list.hpp b/include/rive/artboard_component_list.hpp index b9fac24..5820a91 100644 --- a/include/rive/artboard_component_list.hpp +++ b/include/rive/artboard_component_list.hpp
@@ -3,6 +3,7 @@ #include "rive/generated/artboard_component_list_base.hpp" #include "rive/layout/artboard_component_list_override.hpp" #include "rive/advancing_component.hpp" +#include "rive/resetting_component.hpp" #include "rive/animation/state_machine_instance.hpp" #include "rive/artboard.hpp" #include "rive/property_recorder.hpp" @@ -21,6 +22,7 @@ class ArtboardComponentList : public ArtboardComponentListBase, public ArtboardHost, public AdvancingComponent, + public ResettingComponent, public LayoutNodeProvider, public DataBindListItemConsumer, public VirtualizingComponent @@ -43,6 +45,7 @@ bool advanceComponent(float elapsedSeconds, AdvanceFlags flags = AdvanceFlags::Animate | AdvanceFlags::NewFrame) override; + void reset() override; AABB layoutBounds() override; AABB layoutBoundsForNode(int index) override; void markHostingLayoutDirty(ArtboardInstance* artboardInstance) override; @@ -74,7 +77,7 @@ bool shouldForceUpdateLayoutBounds = false) override; bool isLayoutProvider() override { return true; } size_t numLayoutNodes() override { return m_listItems.size(); } - void reset(); + void clear(); void file(File*) override; File* file() const override; Core* clone() const override; @@ -89,6 +92,7 @@ m_visibleStartIndex = start; m_visibleEndIndex = end; } + void shouldResetInstances(bool value) { m_shouldResetInstances = value; } void setVirtualizablePosition(int index, Vec2D position) override; void createArtboardAt(int index); void addArtboardAt(std::unique_ptr<ArtboardInstance> artboard, int index); @@ -149,6 +153,7 @@ void attachArtboardOverride(ArtboardInstance*, rcp<ViewModelInstanceListItem>); void clearArtboardOverride(ArtboardInstance*); + bool m_shouldResetInstances = false; }; } // namespace rive
diff --git a/include/rive/nested_artboard.hpp b/include/rive/nested_artboard.hpp index e9fb6cf..5d7902d 100644 --- a/include/rive/nested_artboard.hpp +++ b/include/rive/nested_artboard.hpp
@@ -8,6 +8,7 @@ #include "rive/hit_info.hpp" #include "rive/span.hpp" #include "rive/advancing_component.hpp" +#include "rive/resetting_component.hpp" #include "rive/viewmodel/viewmodel_instance_artboard.hpp" #include <stdio.h> @@ -22,6 +23,7 @@ class File; class NestedArtboard : public NestedArtboardBase, public AdvancingComponent, + public ResettingComponent, public ArtboardHost { protected: @@ -101,6 +103,7 @@ bool advanceComponent(float elapsedSeconds, AdvanceFlags flags = AdvanceFlags::Animate | AdvanceFlags::NewFrame) override; + void reset() override; Artboard* parentArtboard() override { return artboard(); } Vec2D hostTransformPoint(const Vec2D&, ArtboardInstance*) override; bool hitTestHost(const Vec2D& position,
diff --git a/include/rive/resetting_component.hpp b/include/rive/resetting_component.hpp new file mode 100644 index 0000000..5e4c30b --- /dev/null +++ b/include/rive/resetting_component.hpp
@@ -0,0 +1,15 @@ +#ifndef _RIVE_RESETTING_COMPONENT_HPP_ +#define _RIVE_RESETTING_COMPONENT_HPP_ + +namespace rive +{ +class Component; +class ResettingComponent +{ +public: + virtual void reset() = 0; + static ResettingComponent* from(Component* component); +}; +} // namespace rive + +#endif
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 1b59c20..563430b 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp
@@ -1797,6 +1797,12 @@ } } +void StateMachineInstance::reset() +{ + advancedDataContext(); + m_artboardInstance->reset(); +} + bool StateMachineInstance::advanceAndApply(float seconds) { bool keepGoing = this->advance(seconds, true); @@ -1829,7 +1835,7 @@ { keepGoing = true; } - advancedDataContext(); + reset(); if (!m_artboardInstance->hasDirt(ComponentDirt::Components)) {
diff --git a/src/artboard.cpp b/src/artboard.cpp index ef427c8..659e8d5 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -993,6 +993,18 @@ return didUpdate; } +void Artboard::reset() +{ + for (auto dep : m_DependencyOrder) + { + auto adv = ResettingComponent::from(dep); + if (adv != nullptr) + { + adv->reset(); + } + } +} + bool Artboard::advance(float elapsedSeconds, AdvanceFlags flags) { AdvanceFlags advancingFlags = flags;
diff --git a/src/artboard_component_list.cpp b/src/artboard_component_list.cpp index dd5eea7..746ad7f 100644 --- a/src/artboard_component_list.cpp +++ b/src/artboard_component_list.cpp
@@ -10,9 +10,9 @@ using namespace rive; ArtboardComponentList::ArtboardComponentList() {} -ArtboardComponentList::~ArtboardComponentList() { reset(); } +ArtboardComponentList::~ArtboardComponentList() { clear(); } -void ArtboardComponentList::reset() +void ArtboardComponentList::clear() { for (auto& artboard : m_artboardInstancesMap) { @@ -334,6 +334,26 @@ return keepGoing; } +void ArtboardComponentList::reset() +{ + for (auto& item : m_listItems) + { + if (m_shouldResetInstances) + { + auto viewModelInstance = item->viewModelInstance(); + if (viewModelInstance != nullptr) + { + viewModelInstance->advanced(); + } + } + auto itr = m_artboardInstancesMap.find(item); + if (itr != m_artboardInstancesMap.end()) + { + m_artboardInstancesMap[item]->reset(); + } + } +} + AABB ArtboardComponentList::layoutBounds() { return AABB(0, 0, m_layoutSize.x, m_layoutSize.y); @@ -577,7 +597,7 @@ } void ArtboardComponentList::clearDataContext() {} -void ArtboardComponentList::unbind() { reset(); } +void ArtboardComponentList::unbind() { clear(); } void ArtboardComponentList::updateDataBinds() { for (int i = 0; i < artboardCount(); i++)
diff --git a/src/data_bind/data_bind.cpp b/src/data_bind/data_bind.cpp index 687f2c7..fb274ca 100644 --- a/src/data_bind/data_bind.cpp +++ b/src/data_bind/data_bind.cpp
@@ -28,6 +28,7 @@ #include "rive/data_bind/converters/formula/formula_token.hpp" #include "rive/animation/transition_viewmodel_condition.hpp" #include "rive/animation/state_machine.hpp" +#include "rive/artboard_component_list.hpp" #include "rive/importers/artboard_importer.hpp" #include "rive/importers/state_machine_importer.hpp" #include "rive/importers/backboard_importer.hpp" @@ -152,6 +153,16 @@ value->ref(); } m_Source = value; + + // We treat this as a special case. If an ArtboardComponentList's list + // property is bound to a number instance, we know that the component + // will be provided with dettached view model instances that need to be + // advanced explicitly + if (m_Source && target() && target()->is<ArtboardComponentList>()) + { + target()->as<ArtboardComponentList>()->shouldResetInstances( + m_Source->coreType() == ViewModelInstanceNumberBase::typeKey); + } } void DataBind::clearSource()
diff --git a/src/nested_artboard.cpp b/src/nested_artboard.cpp index b26f872..1dcd524 100644 --- a/src/nested_artboard.cpp +++ b/src/nested_artboard.cpp
@@ -517,6 +517,14 @@ return keepGoing; } +void NestedArtboard::reset() +{ + if (m_Artboard) + { + m_Artboard->reset(); + } +} + void NestedArtboard::file(File* value) { m_file = value; } File* NestedArtboard::file() const { return m_file; }
diff --git a/src/resetting_component.cpp b/src/resetting_component.cpp new file mode 100644 index 0000000..074c99a --- /dev/null +++ b/src/resetting_component.cpp
@@ -0,0 +1,23 @@ +#include "rive/component.hpp" +#include "rive/resetting_component.hpp" +#include "rive/artboard.hpp" +#include "rive/artboard_component_list.hpp" +#include "rive/nested_artboard.hpp" +#include "rive/nested_artboard_layout.hpp" +#include "rive/nested_artboard_leaf.hpp" + +using namespace rive; + +ResettingComponent* ResettingComponent::from(Component* component) +{ + switch (component->coreType()) + { + case NestedArtboardLeaf::typeKey: + case NestedArtboardLayout::typeKey: + case NestedArtboard::typeKey: + return component->as<NestedArtboard>(); + case ArtboardComponentListBase::typeKey: + return component->as<ArtboardComponentList>(); + } + return nullptr; +} \ No newline at end of file
diff --git a/tests/unit_tests/assets/reset_phase.riv b/tests/unit_tests/assets/reset_phase.riv new file mode 100644 index 0000000..d1e7e67 --- /dev/null +++ b/tests/unit_tests/assets/reset_phase.riv Binary files differ
diff --git a/tests/unit_tests/runtime/component_list_test.cpp b/tests/unit_tests/runtime/component_list_test.cpp index fa4ff65..d2ff7cb 100644 --- a/tests/unit_tests/runtime/component_list_test.cpp +++ b/tests/unit_tests/runtime/component_list_test.cpp
@@ -600,4 +600,38 @@ } CHECK(silver.matches("artboard_list_overrides_vertical")); +} + +TEST_CASE("Number to Lists reset triggers correctly", "[silver]") +{ + rive::SerializingFactory silver; + auto file = ReadRiveFile("assets/reset_phase.riv", &silver); + + auto artboard = file->artboardNamed("multi-main"); + + 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)(3.0f / 0.16f); + for (int i = 0; i < frames; i++) + { + silver.addFrame(); + stateMachine->advanceAndApply(0.16f); + artboard->draw(renderer.get()); + } + + CHECK(silver.matches("reset_phase_multi_main")); } \ No newline at end of file
diff --git a/tests/unit_tests/silvers/reset_phase_multi_main.sriv b/tests/unit_tests/silvers/reset_phase_multi_main.sriv new file mode 100644 index 0000000..f39dc82 --- /dev/null +++ b/tests/unit_tests/silvers/reset_phase_multi_main.sriv Binary files differ