blob: 1e2f5c9c428759f7386bf8b29ec68a578755a747 [file]
#ifndef _RIVE_BLEND_ACCUMULATOR_HPP_
#define _RIVE_BLEND_ACCUMULATOR_HPP_
#include "rive/shapes/paint/color.hpp"
#include <cstdint>
#include <vector>
namespace rive
{
class Core;
// Collects what a blend state's animations write, so each property is set
// once, to its final value. Applied straight to the objects, a blended
// property went through intermediate values every frame (the reset value, then
// one lerp per animation), each of which marked it changed and dirtied
// everything depending on it, even when the blend came out where it already
// was. Setting only the final value lets an unchanged property stay clean.
//
// Values mix exactly as they would on the objects: the first write of a frame
// starts from the reset value when there is one, else from the object's
// current value.
class BlendAccumulator
{
public:
// Starts this frame's value for a property at its reset value.
void seedDouble(Core* object, int propertyKey, float value);
void seedColor(Core* object, int propertyKey, ColorInt value);
void applyDouble(Core* object, int propertyKey, float mix, float value);
void applyColor(Core* object, int propertyKey, float mix, ColorInt value);
// Sets every property written since the last flush, in the order they
// were first written.
void flush();
private:
struct Value
{
Core* object;
int propertyKey;
bool isColor;
uint32_t frame;
float doubleValue;
ColorInt colorValue;
};
// This frame's value for the property, added (and loaded from the object)
// on the first write of the frame.
Value& value(Core* object, int propertyKey, bool isColor, bool seeding);
uint32_t find(Core* object, int propertyKey) const;
void index(uint32_t valueIndex);
// Kept across frames: a blend writes the same properties every frame, so
// after the first one nothing is allocated.
std::vector<Value> m_values;
// Open addressing over m_values: holds index + 1, 0 when empty. Its size
// is a power of two, at least twice the number of values.
std::vector<uint32_t> m_index;
std::vector<uint32_t> m_written;
uint32_t m_frame = 1;
};
} // namespace rive
#endif