blob: 297cedb26821729ec8d3c78320e6f71e75de3eb2 [file] [log] [blame]
#ifndef _RIVE_ARTBOARD_HPP_
#define _RIVE_ARTBOARD_HPP_
#include "rive/animation/linear_animation.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/core_context.hpp"
#include "rive/generated/artboard_base.hpp"
#include "rive/hit_info.hpp"
#include "rive/message.hpp"
#include "rive/pointer_event.hpp"
#include "rive/math/aabb.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/shape_paint_container.hpp"
#include <queue>
#include <vector>
namespace rive {
class File;
class Drawable;
class Node;
class DrawTarget;
class ArtboardImporter;
class NestedArtboard;
class ArtboardInstance;
class LinearAnimationInstance;
class StateMachineInstance;
class Artboard : public ArtboardBase, public CoreContext, public ShapePaintContainer {
friend class File;
friend class ArtboardImporter;
friend class Component;
private:
std::vector<Core*> m_Objects;
std::vector<LinearAnimation*> m_Animations;
std::vector<StateMachine*> m_StateMachines;
std::vector<Component*> m_DependencyOrder;
std::vector<Drawable*> m_Drawables;
std::vector<DrawTarget*> m_DrawTargets;
std::vector<NestedArtboard*> m_NestedArtboards;
unsigned int m_DirtDepth = 0;
std::unique_ptr<CommandPath> m_BackgroundPath;
std::unique_ptr<CommandPath> m_ClipPath;
Drawable* m_FirstDrawable = nullptr;
bool m_IsInstance = false;
bool m_FrameOrigin = true;
std::queue<Message> m_MessageQueue;
void sortDependencies();
void sortDrawOrder();
#ifdef TESTING
public:
#endif
void addObject(Core* object);
void addAnimation(LinearAnimation* object);
void addStateMachine(StateMachine* object);
void addNestedArtboard(NestedArtboard* object);
void testing_only_enque_message(const Message&);
public:
~Artboard();
StatusCode initialize();
Core* resolve(uint32_t id) const override;
uint32_t idOf(Core* object) const;
// EXPERIMENTAL -- for internal testing only for now.
// DO NOT RELY ON THIS as it may change/disappear in the future.
Core* hitTest(HitInfo*, const Mat2D* = nullptr);
void onComponentDirty(Component* component);
/// Update components that depend on each other in DAG order.
bool updateComponents();
void update(ComponentDirt value) override;
void onDirty(ComponentDirt dirt) override;
bool advance(double elapsedSeconds);
// Call this to forward pointer events to the artboard
// They will be processed when advance() is called.
//
void postPointerEvent(const PointerEvent&);
// Returns true iff calling popMessage() will return true.
bool hasMessages() const;
// If there are any queued messages...
// copies the first message into msg parameter
// removes that message from the queue
// returns true
// else
// ignores msg parameter
// returns false
//
bool nextMessage(Message* msg);
enum class DrawOption {
kNormal,
kHideBG,
kHideFG,
};
void draw(Renderer* renderer, DrawOption = DrawOption::kNormal);
CommandPath* clipPath() const { return m_ClipPath.get(); }
CommandPath* backgroundPath() const { return m_BackgroundPath.get(); }
const std::vector<Core*>& objects() const { return m_Objects; }
AABB bounds() const;
bool isTranslucent(const LinearAnimation*) const;
bool isTranslucent(const LinearAnimationInstance*) const;
template <typename T = Component> T* find(std::string name) {
for (auto object : m_Objects) {
if (object != nullptr && object->is<T>() && object->as<T>()->name() == name) {
return reinterpret_cast<T*>(object);
}
}
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;
StateMachine* firstStateMachine() const;
StateMachine* stateMachine(std::string name) const;
StateMachine* stateMachine(size_t index) const;
/// Make an instance of a state machine given the name of the source state machine in this
/// artboard. The StateMachineInstance must be explictly deleted when no longer needed.
StateMachineInstance* stateMachineInstance(std::string name);
/// Make an instance of a state machine given the index of the source state machine in this
/// artboard. The StateMachineInstance must be explictly deleted when no longer needed.
StateMachineInstance* stateMachineInstance(size_t index);
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
bool isInstance() const { return m_IsInstance; }
/// Returns true when the artboard will shift the origin from the top
/// left to the relative width/height of the artboard itself. This is
/// what the editor does visually when you change the origin value to
/// give context as to where the origin lies within the framed bounds.
bool frameOrigin() const { return m_FrameOrigin; }
/// When composing multiple artboards together in a common world-space,
/// it may be desireable to have them share the same space regardless of
/// origin offset from the bounding artboard. Set frameOrigin to false
/// to move the bounds relative to the origin instead of the origin
/// relative to the bounds.
void frameOrigin(bool value);
StatusCode import(ImportStack& importStack) override;
};
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
#endif