blob: b3753ccf4237af13b09dbff5b1e8568e4a4fa3bf [file]
#include "rive/animation/keyframe_double.hpp"
#include "rive/generated/core_registry.hpp"
#include "rive/animation/linear_animation_instance.hpp"
#include "rive/data_bind/bindable_property_number.hpp"
using namespace rive;
// This whole class is intentionally misnamed to match our editor code. The
// editor uses doubles (float64) for numeric values but at runtime 32 bit
// floating point numbers suffice. So even though this is a "double keyframe" to
// match editor names, the actual values are stored and applied in 32 bits.
static void applyDouble(Core* object, int propertyKey, float mix, float value)
{
// Single setter — mirrors the Dart editor where the call site
// doesn't choose between animation-mode and design-mode paths.
// Generated `<name>(value)` setters internally consult
// `Core::isAnimationContextActive()`: when EditorFile has the
// animation context active they route the write to the
// per-property override overlay; otherwise to the persistent
// static field. Runtime builds compile out the overlay branch
// entirely.
if (mix == 1.0f)
{
CoreRegistry::setDouble(object, propertyKey, value);
}
else
{
float mixi = 1.0f - mix;
CoreRegistry::setDouble(
object,
propertyKey,
CoreRegistry::getDouble(object, propertyKey) * mixi + value * mix);
}
}
float KeyFrameDouble::effectiveValue(
const LinearAnimationInstance* context) const
{
if (context != nullptr)
{
if (auto* holder = context->keyFrameValueHolder(this))
{
return holder->as<BindablePropertyNumber>()->propertyValue();
}
}
return value();
}
void KeyFrameDouble::apply(Core* object,
int propertyKey,
float mix,
const LinearAnimationInstance* context)
{
applyDouble(object, propertyKey, mix, effectiveValue(context));
}
void KeyFrameDouble::applyInterpolation(Core* object,
int propertyKey,
float currentTime,
const KeyFrame* nextFrame,
float mix,
const LinearAnimationInstance* context)
{
auto kfd = nextFrame->as<KeyFrameDouble>();
const KeyFrameDouble& nextDouble = *kfd;
float fromValue = effectiveValue(context);
float toValue = nextDouble.effectiveValue(context);
float f = (currentTime - seconds()) / (nextDouble.seconds() - seconds());
float frameValue;
if (KeyFrameInterpolator* keyframeInterpolator =
effectiveInterpolator(context))
{
frameValue =
keyframeInterpolator->transformValue(fromValue, toValue, f);
}
else
{
frameValue = fromValue + (toValue - fromValue) * f;
}
applyDouble(object, propertyKey, mix, frameValue);
}