mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
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:
@@ -1 +1 @@
|
||||
559f237078e0e1430a661766c071ce22bd11abc7
|
||||
af18705be2294cf120d220bd89a6d64adcd17fd1
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; };
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
15
include/rive/resetting_component.hpp
Normal file
15
include/rive/resetting_component.hpp
Normal 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
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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; }
|
||||
|
||||
23
src/resetting_component.cpp
Normal file
23
src/resetting_component.cpp
Normal 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;
|
||||
}
|
||||
BIN
tests/unit_tests/assets/reset_phase.riv
Normal file
BIN
tests/unit_tests/assets/reset_phase.riv
Normal file
Binary file not shown.
@@ -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"));
|
||||
}
|
||||
BIN
tests/unit_tests/silvers/reset_phase_multi_main.sriv
Normal file
BIN
tests/unit_tests/silvers/reset_phase_multi_main.sriv
Normal file
Binary file not shown.
Reference in New Issue
Block a user