| #include "rive/constraints/translation_constraint.hpp" | |
| #include "rive/transform_component.hpp" | |
| #include "rive/math/mat2d.hpp" | |
| #include "rive/math/vec2d.hpp" | |
| #include <cmath> | |
| using namespace rive; | |
| void TranslationConstraint::constrain(TransformComponent* component) { | |
| Mat2D& transformA = component->mutableWorldTransform(); | |
| Vec2D translationA(transformA[4], transformA[5]); | |
| Vec2D translationB; | |
| if (m_Target == nullptr) { | |
| translationB = translationA; | |
| } else { | |
| Mat2D transformB(m_Target->worldTransform()); | |
| if (sourceSpace() == TransformSpace::local) { | |
| const Mat2D& targetParentWorld = getParentWorld(*m_Target); | |
| Mat2D inverse; | |
| if (!targetParentWorld.invert(&inverse)) { | |
| return; | |
| } | |
| transformB = inverse * transformB; | |
| } | |
| translationB[0] = transformB[4]; | |
| translationB[1] = transformB[5]; | |
| if (!doesCopy()) { | |
| translationB[0] = destSpace() == TransformSpace::local ? 0.0f : translationA[0]; | |
| } else { | |
| translationB[0] *= copyFactor(); | |
| if (offset()) { | |
| translationB[0] += component->x(); | |
| } | |
| } | |
| if (!doesCopyY()) { | |
| translationB[1] = destSpace() == TransformSpace::local ? 0.0f : translationA[1]; | |
| } else { | |
| translationB[1] *= copyFactorY(); | |
| if (offset()) { | |
| translationB[1] += component->y(); | |
| } | |
| } | |
| if (destSpace() == TransformSpace::local) { | |
| // Destination space is in parent transform coordinates. | |
| translationB = getParentWorld(*component) * translationB; | |
| } | |
| } | |
| bool clampLocal = minMaxSpace() == TransformSpace::local; | |
| if (clampLocal) { | |
| // Apply min max in local space, so transform to local coordinates | |
| // first. | |
| Mat2D inverse; | |
| if (!getParentWorld(*component).invert(&inverse)) { | |
| return; | |
| } | |
| // Get our target world coordinates in parent local. | |
| translationB = inverse * translationB; | |
| } | |
| if (max() && translationB[0] > maxValue()) { | |
| translationB[0] = maxValue(); | |
| } | |
| if (min() && translationB[0] < minValue()) { | |
| translationB[0] = minValue(); | |
| } | |
| if (maxY() && translationB[1] > maxValueY()) { | |
| translationB[1] = maxValueY(); | |
| } | |
| if (minY() && translationB[1] < minValueY()) { | |
| translationB[1] = minValueY(); | |
| } | |
| if (clampLocal) { | |
| // Transform back to world. | |
| translationB = getParentWorld(*component) * translationB; | |
| } | |
| float t = strength(); | |
| float ti = 1.0f - t; | |
| // Just interpolate world translation | |
| transformA[4] = translationA[0] * ti + translationB[0] * t; | |
| transformA[5] = translationA[1] * ti + translationB[1] * t; | |
| } |