skip constraints in editor when target is collapsed

Diffs=
ed4474d1a skip constraints in editor when target is collapsed (#6294)

Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head
index 5fb9c63..c640d70 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-2c2d332e0254b56f5512de65251cbd80b891aa15
+ed4474d1ab3aa1e68d47cfcb2c178f39c376257e
diff --git a/include/rive/transform_component.hpp b/include/rive/transform_component.hpp
index 1c4e9a9..8b13bce 100644
--- a/include/rive/transform_component.hpp
+++ b/include/rive/transform_component.hpp
@@ -17,6 +17,7 @@
     std::vector<Constraint*> m_Constraints;
 
 public:
+    bool collapse(bool value) override;
     const std::vector<Constraint*>& constraints() const { return m_Constraints; }
     StatusCode onAddedClean(CoreContext* context) override;
     void buildDependencies() override;
@@ -45,6 +46,7 @@
 
     void addConstraint(Constraint* constraint);
     virtual AABB localBounds() const;
+    void markDirtyIfConstrained();
 };
 } // namespace rive
 
diff --git a/src/constraints/distance_constraint.cpp b/src/constraints/distance_constraint.cpp
index 498b906..7565ed7 100644
--- a/src/constraints/distance_constraint.cpp
+++ b/src/constraints/distance_constraint.cpp
@@ -14,7 +14,7 @@
 
 void DistanceConstraint::constrain(TransformComponent* component)
 {
-    if (m_Target == nullptr)
+    if (m_Target == nullptr || m_Target->isCollapsed())
     {
         return;
     }
diff --git a/src/constraints/follow_path_constraint.cpp b/src/constraints/follow_path_constraint.cpp
index bd1d488..14e2493 100644
--- a/src/constraints/follow_path_constraint.cpp
+++ b/src/constraints/follow_path_constraint.cpp
@@ -86,7 +86,7 @@
 
 void FollowPathConstraint::constrain(TransformComponent* component)
 {
-    if (m_Target == nullptr)
+    if (m_Target == nullptr || m_Target->isCollapsed())
     {
         return;
     }
diff --git a/src/constraints/ik_constraint.cpp b/src/constraints/ik_constraint.cpp
index a269109..c8638f4 100644
--- a/src/constraints/ik_constraint.cpp
+++ b/src/constraints/ik_constraint.cpp
@@ -219,7 +219,7 @@
 
 void IKConstraint::constrain(TransformComponent* component)
 {
-    if (m_Target == nullptr)
+    if (m_Target == nullptr || m_Target->isCollapsed())
     {
         return;
     }
diff --git a/src/constraints/rotation_constraint.cpp b/src/constraints/rotation_constraint.cpp
index a0003f7..b37dc4a 100644
--- a/src/constraints/rotation_constraint.cpp
+++ b/src/constraints/rotation_constraint.cpp
@@ -7,6 +7,10 @@
 
 void RotationConstraint::constrain(TransformComponent* component)
 {
+    if (m_Target != nullptr && m_Target->isCollapsed())
+    {
+        return;
+    }
     const Mat2D& transformA = component->worldTransform();
     Mat2D transformB;
     m_ComponentsA = transformA.decompose();
diff --git a/src/constraints/scale_constraint.cpp b/src/constraints/scale_constraint.cpp
index e59bce2..f4bb455 100644
--- a/src/constraints/scale_constraint.cpp
+++ b/src/constraints/scale_constraint.cpp
@@ -7,6 +7,10 @@
 
 void ScaleConstraint::constrain(TransformComponent* component)
 {
+    if (m_Target != nullptr && m_Target->isCollapsed())
+    {
+        return;
+    }
     const Mat2D& transformA = component->worldTransform();
     Mat2D transformB;
     m_ComponentsA = transformA.decompose();
diff --git a/src/constraints/transform_constraint.cpp b/src/constraints/transform_constraint.cpp
index fa30ac4..a6b64cb 100644
--- a/src/constraints/transform_constraint.cpp
+++ b/src/constraints/transform_constraint.cpp
@@ -16,7 +16,7 @@
 
 void TransformConstraint::constrain(TransformComponent* component)
 {
-    if (m_Target == nullptr)
+    if (m_Target == nullptr || m_Target->isCollapsed())
     {
         return;
     }
diff --git a/src/constraints/translation_constraint.cpp b/src/constraints/translation_constraint.cpp
index 452ae3a..8febfb6 100644
--- a/src/constraints/translation_constraint.cpp
+++ b/src/constraints/translation_constraint.cpp
@@ -8,6 +8,10 @@
 
 void TranslationConstraint::constrain(TransformComponent* component)
 {
+    if (m_Target != nullptr && m_Target->isCollapsed())
+    {
+        return;
+    }
     Mat2D& transformA = component->mutableWorldTransform();
     Vec2D translationA(transformA[4], transformA[5]);
     Vec2D translationB;
diff --git a/src/transform_component.cpp b/src/transform_component.cpp
index e87ad41..0e9c1ab 100644
--- a/src/transform_component.cpp
+++ b/src/transform_component.cpp
@@ -14,6 +14,34 @@
     return StatusCode::Ok;
 }
 
+bool TransformComponent::collapse(bool value)
+{
+    if (!Super::collapse(value))
+    {
+        return false;
+    }
+    for (auto d : dependents())
+    {
+        if (d->is<TransformComponent>())
+        {
+            auto dependent = d->as<TransformComponent>();
+            dependent->markDirtyIfConstrained();
+        }
+    }
+    return true;
+}
+
+// If the component has any constraints applied we mark it as dirty
+// because one of its constraining targets has changed its collapse
+// status.
+void TransformComponent::markDirtyIfConstrained()
+{
+    if (m_Constraints.size() > 0)
+    {
+        addDirt(ComponentDirt::WorldTransform, true);
+    }
+}
+
 void TransformComponent::buildDependencies()
 {
     if (parent() != nullptr)