blob: 8ef6d10a7ad4cad5ce7378665c8911f7c7b6a72b [file]
#include "rive/constraints/distance_constraint.hpp"
#include "rive/bones/bone.hpp"
#include "rive/artboard.hpp"
#include <algorithm>
using namespace rive;
enum class Mode
{
Closer = 0,
Further = 1,
Exact = 2
};
void DistanceConstraint::constrain(TransformComponent* component)
{
auto* tgt = target();
if (tgt == nullptr || tgt->isCollapsed())
{
return;
}
Mat2D& world = component->mutableWorldTransform();
const Vec2D anchor = component->localAnchor();
const Vec2D anchorWorld = Vec2D(world[0] * anchor.x + world[2] * anchor.y,
world[1] * anchor.x + world[3] * anchor.y);
const Vec2D targetTranslation = tgt->worldTranslation();
const Vec2D ourTranslation = component->worldTranslation() + anchorWorld;
Vec2D toTarget = ourTranslation - targetTranslation;
float currentDistance = toTarget.length();
switch (static_cast<Mode>(modeValue()))
{
case Mode::Closer:
if (currentDistance < distance())
{
return;
}
break;
case Mode::Further:
if (currentDistance > distance())
{
return;
}
break;
case Mode::Exact:
break;
}
if (currentDistance < 0.001f)
{
return;
}
toTarget *= (distance() / currentDistance);
Vec2D position = targetTranslation + toTarget;
position = Vec2D::lerp(ourTranslation, position, strength());
world[4] = position.x - anchorWorld.x;
world[5] = position.y - anchorWorld.y;
}
void DistanceConstraint::distanceChanged() { markConstraintDirty(); }
void DistanceConstraint::modeValueChanged() { markConstraintDirty(); }