blob: d70fa12cb2599a52ca75977bbf521453781547d6 [file]
#include "rive/animation/keyframe_uint.hpp"
#include "rive/animation/keyframe_interpolator.hpp"
#include "rive/generated/core_registry.hpp"
#include <cmath>
using namespace rive;
// Uints hold by default -- most are enums, ids or mode flags. Defs opting in
// with "interpolates": true tween instead, via the generated
// CoreRegistry::isInterpolatableUint. Rounding and mixing must match
// packages/rive_core/lib/animation/keyframe_uint.dart or editor preview and
// runtime playback drift.
// Clamps negatives to zero: a cubic interpolator can overshoot below zero and
// the destination property is unsigned.
static uint32_t roundToUint(float value)
{
return value <= 0.0f ? 0u : static_cast<uint32_t>(std::lround(value));
}
static void applyUint(Core* object, int propertyKey, float mix, uint32_t value)
{
if (mix == 1.0f)
{
CoreRegistry::setUint(object, propertyKey, value);
}
else
{
float mixi = 1.0f - mix;
CoreRegistry::setUint(
object,
propertyKey,
roundToUint(CoreRegistry::getUint(object, propertyKey) * mixi +
value * mix));
}
}
void KeyFrameUint::apply(Core* object,
int propertyKey,
float mix,
const LinearAnimationInstance* context)
{
(void)context;
if (CoreRegistry::isInterpolatableUint(propertyKey))
{
applyUint(object, propertyKey, mix, value());
return;
}
CoreRegistry::setUint(object, propertyKey, value());
}
void KeyFrameUint::applyInterpolation(Core* object,
int propertyKey,
float currentTime,
const KeyFrame* nextFrame,
float mix,
const LinearAnimationInstance* context)
{
if (!CoreRegistry::isInterpolatableUint(propertyKey))
{
CoreRegistry::setUint(object, propertyKey, value());
return;
}
const KeyFrameUint& nextUint = *nextFrame->as<KeyFrameUint>();
float fromValue = static_cast<float>(value());
float toValue = static_cast<float>(nextUint.value());
float f = (currentTime - seconds()) / (nextUint.seconds() - seconds());
float frameValue;
if (KeyFrameInterpolator* keyframeInterpolator =
effectiveInterpolator(context))
{
frameValue =
keyframeInterpolator->transformValue(fromValue, toValue, f);
}
else
{
frameValue = fromValue + (toValue - fromValue) * f;
}
applyUint(object, propertyKey, mix, roundToUint(frameValue));
}