blob: 58c00583e178ab8948505d0c3deb1ff9314e60f0 [file]
#ifndef _RIVE_NESTED_ANIMATION_HPP_
#define _RIVE_NESTED_ANIMATION_HPP_
#include "rive/event.hpp"
#include "rive/event_report.hpp"
#include "rive/generated/nested_animation_base.hpp"
#include "rive/nested_artboard.hpp"
#include <stdio.h>
namespace rive
{
class ArtboardInstance;
class NestedEventNotifier;
class NestedEventListener
{
public:
NestedEventListener() = default;
// A copy starts unregistered: the notifiers only hold the original.
NestedEventListener(const NestedEventListener&) {}
NestedEventListener& operator=(const NestedEventListener&) { return *this; }
virtual ~NestedEventListener();
virtual void notify(
const std::vector<EventReport>& events,
NestedArtboard* context) = 0;
// Unregisters from every notifier this listener was added to.
void removeFromNestedEventNotifiers();
private:
friend class NestedEventNotifier;
// Links are kept on both sides so whichever is destroyed first unlinks from
// the other. A host can delete a state machine and keep its artboard, whose
// nested machines would otherwise report to the deleted one.
std::vector<NestedEventNotifier*> m_nestedEventNotifiers;
};
class NestedEventNotifier
{
public:
NestedEventNotifier() = default;
// A copy starts with no listeners: they registered with the original.
NestedEventNotifier(const NestedEventNotifier&) {}
NestedEventNotifier& operator=(const NestedEventNotifier&) { return *this; }
~NestedEventNotifier()
{
m_nestedArtboard = nullptr;
for (auto listener : m_nestedEventListeners)
{
unlinkListener(listener);
}
m_nestedEventListeners.clear();
}
void addNestedEventListener(NestedEventListener* listener)
{
m_nestedEventListeners.push_back(listener);
listener->m_nestedEventNotifiers.push_back(this);
}
void removeNestedEventListener(NestedEventListener* listener)
{
auto nested = std::remove(
m_nestedEventListeners.begin(),
m_nestedEventListeners.end(),
listener);
m_nestedEventListeners.erase(nested, m_nestedEventListeners.end());
unlinkListener(listener);
}
std::vector<NestedEventListener*> nestedEventListeners()
{
return m_nestedEventListeners;
}
void setNestedArtboard(NestedArtboard* artboard)
{
m_nestedArtboard = artboard;
}
NestedArtboard* nestedArtboard() { return m_nestedArtboard; }
void notifyListeners(const std::vector<Event*>& events)
{
std::vector<EventReport> eventReports;
for (auto event : events)
{
eventReports.push_back(EventReport(event, 0));
}
for (auto listener : m_nestedEventListeners)
{
listener->notify(eventReports, m_nestedArtboard);
}
}
private:
// Drops this notifier from the listener's side of the link.
void unlinkListener(NestedEventListener* listener)
{
auto& notifiers = listener->m_nestedEventNotifiers;
notifiers.erase(
std::remove(notifiers.begin(), notifiers.end(), this),
notifiers.end());
}
NestedArtboard* m_nestedArtboard = nullptr;
std::vector<NestedEventListener*> m_nestedEventListeners;
};
inline NestedEventListener::~NestedEventListener()
{
removeFromNestedEventNotifiers();
}
inline void NestedEventListener::removeFromNestedEventNotifiers()
{
// removeNestedEventListener edits m_nestedEventNotifiers, so walk a copy.
auto notifiers = m_nestedEventNotifiers;
for (auto notifier : notifiers)
{
notifier->removeNestedEventListener(this);
}
}
class NestedAnimation : public NestedAnimationBase
{
public:
bool validate(CoreContext* context) override;
StatusCode onAddedDirty(CoreContext* context) override;
// Advance animations and apply them to the artboard.
virtual bool advance(float elapsedSeconds, bool newFrame) = 0;
// Initialize the animation (make instances as necessary) from the
// source artboard.
virtual void initializeAnimation(ArtboardInstance*) = 0;
// Clear the nested animation dependencies
virtual void releaseDependencies() = 0;
#ifdef WITH_RIVE_EDITOR
void editorPrepareForDestruction() override
{
releaseDependencies();
Component::editorPrepareForDestruction();
}
// Body in `editor_native/.../component_parent_editor.cpp`. See
// `Component::editorParentChanged` for the lifecycle contract.
void editorParentChanged(ContainerComponent* from, ContainerComponent* to)
override;
#endif
};
} // namespace rive
#endif