ignore paths that are inactive in solos when calculating hit test we were not skipping collapsed shapes and paths for hit testing, so pointer events were triggering on elements that were inactive. This PR skips those paths to fix it. Note: there might be some performance improvements that can be done in the future skipping shapes that are fully hidden, but this PR most likely covers the majority of the usual cases. Diffs= 2c2d332e0 ignore paths that are inactive in solos when calculating hit test (#6276) Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head index b263d1a..5fb9c63 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -c37a28468472c8bd33beaa1b31bf190ecaa6ce06 +2c2d332e0254b56f5512de65251cbd80b891aa15
diff --git a/src/shapes/shape.cpp b/src/shapes/shape.cpp index 2d5ddde..8694105 100644 --- a/src/shapes/shape.cpp +++ b/src/shapes/shape.cpp
@@ -110,8 +110,11 @@ for (auto path : m_Paths) { - tester.setXform(path->pathTransform()); - path->buildPath(tester); + if (!path->isCollapsed()) + { + tester.setXform(path->pathTransform()); + path->buildPath(tester); + } } return tester.wasHit(); }
diff --git a/test/assets/hit_test_solos.riv b/test/assets/hit_test_solos.riv new file mode 100644 index 0000000..46619a3 --- /dev/null +++ b/test/assets/hit_test_solos.riv Binary files differ
diff --git a/test/solo_test.cpp b/test/solo_test.cpp index 8757162..4584e41 100644 --- a/test/solo_test.cpp +++ b/test/solo_test.cpp
@@ -1,6 +1,7 @@ #include <rive/solo.hpp> #include <rive/shapes/shape.hpp> #include <rive/animation/state_machine_instance.hpp> +#include <rive/animation/state_machine_input_instance.hpp> #include "rive_file_reader.hpp" #include <catch.hpp> #include <cstdio> @@ -150,3 +151,66 @@ REQUIRE(h->isCollapsed() == true); REQUIRE(i->isCollapsed() == true); } + +TEST_CASE("hit test on solos", "[solo]") +{ + auto file = ReadRiveFile("../../test/assets/hit_test_solos.riv"); + + auto artboard = file->artboard()->instance(); + + REQUIRE(artboard != nullptr); + REQUIRE(artboard->stateMachineCount() == 1); + + auto stateMachine = artboard->stateMachineAt(0); + REQUIRE(stateMachine != nullptr); + + stateMachine->advance(0.0f); + artboard->advance(0.0f); + + auto toggle = stateMachine->getBool("hovered"); + REQUIRE(toggle != nullptr); + + // Inactive shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 100.0f)); + REQUIRE(toggle->value() == true); + + // // Active shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 300.0f)); + REQUIRE(toggle->value() == false); + + // // Inactive shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 400.0f)); + REQUIRE(toggle->value() == false); + + // Switches active shape to middle one + stateMachine->advance(1.5f); + artboard->advance(1.5f); + + // Inactive shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 100.0f)); + REQUIRE(toggle->value() == false); + + // // Active shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 300.0f)); + REQUIRE(toggle->value() == true); + + // // Inactive shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 400.0f)); + REQUIRE(toggle->value() == false); + + // Switches active shape to last one + stateMachine->advance(1.0f); + artboard->advance(1.0f); + + // Inactive shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 100.0f)); + REQUIRE(toggle->value() == false); + + // // Inactive shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 300.0f)); + REQUIRE(toggle->value() == false); + + // // Active shape position + stateMachine->pointerMove(rive::Vec2D(200.0f, 400.0f)); + REQUIRE(toggle->value() == true); +}