fix follow path not working with path as target and shape with 0 opacity fixes #7155 We have to also check all paths belonging to a shape before deferring the path update Diffs= 1c7e61b8a fix follow path not working with path as target and shape with 0 opacity (#7156) Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index 3d7de34..1b876f8 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -328d307dfdfcc3c4a9d7c726f783b5325bfbef43 +1c7e61b8a075b2eaacbcce4f5438d6072b30e420
diff --git a/include/rive/shapes/path.hpp b/include/rive/shapes/path.hpp index b92428a..5732cfb 100644 --- a/include/rive/shapes/path.hpp +++ b/include/rive/shapes/path.hpp
@@ -52,6 +52,7 @@ void update(ComponentDirt value) override; void addDefaultPathSpace(PathSpace space); + bool canDeferPathUpdate(); void addVertex(PathVertex* vertex); virtual void markPathDirty();
diff --git a/src/shapes/path.cpp b/src/shapes/path.cpp index 71371f3..5354580 100644 --- a/src/shapes/path.cpp +++ b/src/shapes/path.cpp
@@ -60,6 +60,12 @@ void Path::addDefaultPathSpace(PathSpace space) { m_DefaultPathSpace |= space; } +bool Path::canDeferPathUpdate() +{ + return ((m_DefaultPathSpace & PathSpace::Clipping) != PathSpace::Clipping) && + ((m_DefaultPathSpace & PathSpace::FollowPath) != PathSpace::FollowPath); +} + const Mat2D& Path::pathTransform() const { return worldTransform(); } void Path::buildPath(CommandPath& commandPath) const
diff --git a/src/shapes/shape.cpp b/src/shapes/shape.cpp index 820b5b1..420b82d 100644 --- a/src/shapes/shape.cpp +++ b/src/shapes/shape.cpp
@@ -23,8 +23,20 @@ bool Shape::canDeferPathUpdate() { - return renderOpacity() == 0 && (pathSpace() & PathSpace::Clipping) != PathSpace::Clipping && - (pathSpace() & PathSpace::FollowPath) != PathSpace::FollowPath; + auto canDefer = renderOpacity() == 0 && + (pathSpace() & PathSpace::Clipping) != PathSpace::Clipping && + (pathSpace() & PathSpace::FollowPath) != PathSpace::FollowPath; + if (canDefer) + { + for (auto path : m_Paths) + { + if (!path->canDeferPathUpdate()) + { + return false; + } + } + } + return canDefer; } void Shape::update(ComponentDirt value)
diff --git a/test/assets/follow_path_path_0_opacity.riv b/test/assets/follow_path_path_0_opacity.riv new file mode 100644 index 0000000..ce4f0fb --- /dev/null +++ b/test/assets/follow_path_path_0_opacity.riv Binary files differ
diff --git a/test/follow_path_constraint_test.cpp b/test/follow_path_constraint_test.cpp index 2090186..faff9ec 100644 --- a/test/follow_path_constraint_test.cpp +++ b/test/follow_path_constraint_test.cpp
@@ -46,3 +46,23 @@ REQUIRE(targetComponents.x() == rectComponents.x()); REQUIRE(targetComponents.y() == rectComponents.y()); } + +TEST_CASE("follow path constraint with path at 0 opacity updates world transform", "[file]") +{ + auto file = ReadRiveFile("../../test/assets/follow_path_path_0_opacity.riv"); + + auto artboard = file->artboard(); + + REQUIRE(artboard->find<rive::TransformComponent>("target") != nullptr); + auto target = artboard->find<rive::TransformComponent>("target"); + + REQUIRE(artboard->find<rive::TransformComponent>("rect") != nullptr); + auto rectangle = artboard->find<rive::TransformComponent>("rect"); + + artboard->advance(0.0f); + + auto targetComponents = target->worldTransform().decompose(); + auto rectComponents = rectangle->worldTransform().decompose(); + REQUIRE(targetComponents.x() == rectComponents.x()); + REQUIRE(targetComponents.y() == rectComponents.y()); +}