add advanced phase to render loop (#10318) af18705be2

* add reset phase to render loop

Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
bodymovin
2025-08-05 23:15:39 +00:00
parent 6f9821b970
commit ab86fa1075
15 changed files with 150 additions and 7 deletions

View File

@@ -1 +1 @@
559f237078e0e1430a661766c071ce22bd11abc7
af18705be2294cf120d220bd89a6d64adcd17fd1

View File

@@ -125,6 +125,7 @@ public:
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;

View File

@@ -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 uint8_t (*IsAncestorCallback)(void*, uint16_t);
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 @@ public:
AdvanceFlags flags = AdvanceFlags::AdvanceNested |
AdvanceFlags::Animate |
AdvanceFlags::NewFrame);
void reset() override;
uint8_t drawOrderChangeCounter() { return m_drawOrderChangeCounter; }
Drawable* firstDrawable() { return m_FirstDrawable; };

View File

@@ -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 ScrollConstraint;
class ArtboardComponentList : public ArtboardComponentListBase,
public ArtboardHost,
public AdvancingComponent,
public ResettingComponent,
public LayoutNodeProvider,
public DataBindListItemConsumer,
public VirtualizingComponent
@@ -43,6 +45,7 @@ public:
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 @@ public:
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 @@ public:
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 @@ private:
void attachArtboardOverride(ArtboardInstance*,
rcp<ViewModelInstanceListItem>);
void clearArtboardOverride(ArtboardInstance*);
bool m_shouldResetInstances = false;
};
} // namespace rive

View File

@@ -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 StateMachineInstance;
class File;
class NestedArtboard : public NestedArtboardBase,
public AdvancingComponent,
public ResettingComponent,
public ArtboardHost
{
protected:
@@ -101,6 +103,7 @@ public:
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,

View File

@@ -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

View File

@@ -1797,6 +1797,12 @@ void StateMachineInstance::advancedDataContext()
}
}
void StateMachineInstance::reset()
{
advancedDataContext();
m_artboardInstance->reset();
}
bool StateMachineInstance::advanceAndApply(float seconds)
{
bool keepGoing = this->advance(seconds, true);
@@ -1829,7 +1835,7 @@ bool StateMachineInstance::advanceAndApply(float seconds)
{
keepGoing = true;
}
advancedDataContext();
reset();
if (!m_artboardInstance->hasDirt(ComponentDirt::Components))
{

View File

@@ -993,6 +993,18 @@ bool Artboard::advanceInternal(float elapsedSeconds, AdvanceFlags flags)
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;

View File

@@ -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 @@ bool ArtboardComponentList::advanceComponent(float elapsedSeconds,
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::bindViewModelInstance(
}
void ArtboardComponentList::clearDataContext() {}
void ArtboardComponentList::unbind() { reset(); }
void ArtboardComponentList::unbind() { clear(); }
void ArtboardComponentList::updateDataBinds()
{
for (int i = 0; i < artboardCount(); i++)

View File

@@ -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 @@ void DataBind::source(ViewModelInstanceValue* value)
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()

View File

@@ -517,6 +517,14 @@ bool NestedArtboard::advanceComponent(float elapsedSeconds, AdvanceFlags flags)
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; }

View File

@@ -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;
}

Binary file not shown.

View File

@@ -600,4 +600,38 @@ TEST_CASE("Artboard override with vertical distribution", "[silver]")
}
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"));
}

Binary file not shown.