| #include "rive/artboard.hpp" | |
| #include "rive/file.hpp" | |
| #include "rive/file_asset_resolver.hpp" | |
| #include "rive/playable.hpp" | |
| #include "rive/animation/linear_animation_instance.hpp" | |
| #include "rive/animation/state_machine_instance.hpp" | |
| using namespace rive; | |
| Playable::Playable() {} | |
| Playable::~Playable() {} | |
| std::unique_ptr<Playable> Playable::animationAt(File* file, | |
| size_t artboardIndex, | |
| size_t animationIndex) { | |
| auto abi = file->artboardAt(artboardIndex); | |
| if (abi) { | |
| auto lai = abi->animationAt(animationIndex); | |
| if (lai) { | |
| std::unique_ptr<Playable> play(new Playable); | |
| play->m_ABI = std::move(abi); | |
| play->m_LAI = std::move(lai); | |
| return play; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| std::unique_ptr<Playable> Playable::stateMachineAt(File* file, | |
| size_t artboardIndex, | |
| size_t machineIndex) { | |
| auto abi = file->artboardAt(artboardIndex); | |
| if (abi) { | |
| auto smi = abi->stateMachineAt(machineIndex); | |
| if (smi) { | |
| std::unique_ptr<Playable> play(new Playable); | |
| play->m_ABI = std::move(abi); | |
| play->m_SMI = std::move(smi); | |
| return play; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| std::unique_ptr<Playable> Playable::import(Span<const uint8_t> bytes, | |
| Factory* factory, | |
| FileAssetResolver* resolver) | |
| { | |
| auto file = File::import(bytes, factory, nullptr, resolver); | |
| if (!file) { | |
| return nullptr; | |
| } | |
| auto play = Playable::stateMachineAt(file.get(), 0, 0); | |
| if (!play) { | |
| play = Playable::animationAt(file.get(), 0, 0); | |
| } | |
| if (play) { | |
| play->m_File = std::move(file); | |
| } | |
| return play; | |
| } | |
| AABB Playable::bounds() const { | |
| return m_ABI->bounds(); | |
| } | |
| float Playable::durationSeconds() const { | |
| return m_SMI ? -1 : m_LAI->durationSeconds(); | |
| } | |
| // returns true if draw() should be called | |
| bool Playable::advance(float elapsedSeconds) { | |
| bool needsRedraw; | |
| if (m_SMI) { | |
| needsRedraw = m_SMI->advance(elapsedSeconds); | |
| } else { | |
| needsRedraw = m_LAI->advance(elapsedSeconds); | |
| m_LAI->apply(); | |
| } | |
| return needsRedraw; | |
| } | |
| void Playable::draw(Renderer* renderer) { | |
| m_ABI->draw(renderer); | |
| } | |
| void Playable::pointerEvent(Vec2D pos, PointerState state) { | |
| if (m_SMI) { | |
| switch (state) { | |
| case PointerState::kDown: | |
| m_SMI->pointerDown(pos); | |
| break; | |
| case PointerState::kMoved: | |
| m_SMI->pointerMove(pos); | |
| break; | |
| case PointerState::kUp: | |
| m_SMI->pointerUp(pos); | |
| break; | |
| } | |
| } | |
| // else the animation just ignores the pointer events | |
| } | |
| // StateMachine Inputs | |
| size_t Playable::inputCount() const { | |
| return m_SMI ? m_SMI->inputCount() : 0; | |
| } | |
| SMIInput* Playable::inputAt(size_t index) const { | |
| return m_SMI ? m_SMI->input(index) : nullptr; | |
| } | |
| SMIBool* Playable::boolNamed(const std::string& name) const { | |
| return m_SMI ? m_SMI->getBool(name) : nullptr; | |
| } | |
| SMINumber* Playable::numberNamed(const std::string& name) const { | |
| return m_SMI ? m_SMI->getNumber(name) : nullptr; | |
| } | |
| SMITrigger* Playable::triggerNamed(const std::string& name) const { | |
| return m_SMI ? m_SMI->getTrigger(name) : nullptr; | |
| } |