blob: d952451caa2f4204a4c3433a4b29e66fdbbfe42c [file] [log] [blame]
#include "rive/animation/keyed_property.hpp"
#include "rive/animation/keyed_object.hpp"
#include "rive/animation/keyframe.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/importers/keyed_object_importer.hpp"
using namespace rive;
KeyedProperty::KeyedProperty() {}
KeyedProperty::~KeyedProperty() {}
void KeyedProperty::addKeyFrame(std::unique_ptr<KeyFrame> keyframe) {
m_KeyFrames.push_back(std::move(keyframe));
}
void KeyedProperty::apply(Core* object, float seconds, float mix) {
assert(!m_KeyFrames.empty());
int idx = 0;
int mid = 0;
float closestSeconds = 0.0f;
int start = 0;
auto numKeyFrames = static_cast<int>(m_KeyFrames.size());
int end = numKeyFrames - 1;
while (start <= end) {
mid = (start + end) >> 1;
closestSeconds = m_KeyFrames[mid]->seconds();
if (closestSeconds < seconds) {
start = mid + 1;
} else if (closestSeconds > seconds) {
end = mid - 1;
} else {
idx = start = mid;
break;
}
idx = start;
}
int pk = propertyKey();
if (idx == 0) {
m_KeyFrames[0]->apply(object, pk, mix);
} else {
if (idx < numKeyFrames) {
KeyFrame* fromFrame = m_KeyFrames[idx - 1].get();
KeyFrame* toFrame = m_KeyFrames[idx].get();
if (seconds == toFrame->seconds()) {
toFrame->apply(object, pk, mix);
} else {
if (fromFrame->interpolationType() == 0) {
fromFrame->apply(object, pk, mix);
} else {
fromFrame->applyInterpolation(object, pk, seconds, toFrame, mix);
}
}
} else {
m_KeyFrames[idx - 1]->apply(object, pk, mix);
}
}
}
StatusCode KeyedProperty::onAddedDirty(CoreContext* context) {
StatusCode code;
for (auto& keyframe : m_KeyFrames) {
if ((code = keyframe->onAddedDirty(context)) != StatusCode::Ok) {
return code;
}
}
return StatusCode::Ok;
}
StatusCode KeyedProperty::onAddedClean(CoreContext* context) {
StatusCode code;
for (auto& keyframe : m_KeyFrames) {
if ((code = keyframe->onAddedClean(context)) != StatusCode::Ok) {
return code;
}
}
return StatusCode::Ok;
}
StatusCode KeyedProperty::import(ImportStack& importStack) {
auto importer = importStack.latest<KeyedObjectImporter>(KeyedObjectBase::typeKey);
if (importer == nullptr) {
return StatusCode::MissingObject;
}
importer->addKeyedProperty(std::unique_ptr<KeyedProperty>(this));
return Super::import(importStack);
}