|  | #include <rive/node.hpp> | 
|  | #include <rive/bones/bone.hpp> | 
|  | #include <rive/shapes/shape.hpp> | 
|  | #include <utils/no_op_renderer.hpp> | 
|  | #include "rive_file_reader.hpp" | 
|  | #include "rive_testing.hpp" | 
|  | #include <cstdio> | 
|  |  | 
|  | TEST_CASE("two bone ik places bones correctly", "[file]") | 
|  | { | 
|  | auto file = ReadRiveFile("../../test/assets/two_bone_ik.riv"); | 
|  | auto artboard = file->artboard(); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Shape>("circle a") != nullptr); | 
|  | auto circleA = artboard->find<rive::Shape>("circle a"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Shape>("circle b") != nullptr); | 
|  | auto circleB = artboard->find<rive::Shape>("circle b"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Bone>("a") != nullptr); | 
|  | auto boneA = artboard->find<rive::Bone>("a"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Bone>("b") != nullptr); | 
|  | auto boneB = artboard->find<rive::Bone>("b"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Node>("target") != nullptr); | 
|  | auto target = artboard->find<rive::Node>("target"); | 
|  |  | 
|  | REQUIRE(artboard->animation("Animation 1") != nullptr); | 
|  | auto animation = artboard->animation("Animation 1"); | 
|  |  | 
|  | // Make sure dependency structure is correct. Important thing here is to | 
|  | // ensure that circle a is dependent upon the tip of the ik chain (bone b). | 
|  | // circle b is a child of bone b so it'll be there anyway, but may as well | 
|  | // validate. | 
|  | REQUIRE(std::find(boneB->dependents().begin(), boneB->dependents().end(), circleA) != | 
|  | boneB->dependents().end()); | 
|  | REQUIRE(std::find(boneB->dependents().begin(), boneB->dependents().end(), circleB) != | 
|  | boneB->dependents().end()); | 
|  |  | 
|  | animation->apply(artboard, 0.0f, 1.0f); | 
|  | artboard->advance(0.0f); | 
|  | REQUIRE(target->x() == 296.0f); | 
|  | REQUIRE(target->y() == 202.0f); | 
|  | REQUIRE(aboutEqual(boneA->worldTransform(), | 
|  | rive::Mat2D(0.11632211506366729736328125f, | 
|  | -0.993211567401885986328125f, | 
|  | 0.993211567401885986328125f, | 
|  | 0.11632211506366729736328125f, | 
|  | 26.015254974365234375f, | 
|  | 475.2149658203125f))); | 
|  |  | 
|  | REQUIRE(aboutEqual(boneB->worldTransform(), | 
|  | rive::Mat2D(0.974071562290191650390625f, | 
|  | 0.2262403070926666259765625f, | 
|  | -0.2262403070926666259765625f, | 
|  | 0.974071562290191650390625f, | 
|  | 64.31568145751953125f, | 
|  | 148.1883544921875f))); | 
|  |  | 
|  | animation->apply(artboard, 1.0f, 1.0f); | 
|  | artboard->advance(0.0f); | 
|  | REQUIRE(target->x() == 450.0f); | 
|  | REQUIRE(target->y() == 337.0f); | 
|  | REQUIRE(aboutEqual(boneA->worldTransform(), | 
|  | rive::Mat2D(0.650279819965362548828125f, | 
|  | -0.7596948146820068359375f, | 
|  | 0.7596948146820068359375f, | 
|  | 0.650279819965362548828125f, | 
|  | 26.015254974365234375f, | 
|  | 475.2149658203125f))); | 
|  |  | 
|  | REQUIRE(aboutEqual(boneB->worldTransform(), | 
|  | rive::Mat2D(0.8823678493499755859375f, | 
|  | 0.470560371875762939453125f, | 
|  | -0.47056043148040771484375f, | 
|  | 0.882367908954620361328125f, | 
|  | 240.1275634765625f, | 
|  | 225.07647705078125f))); | 
|  | } | 
|  |  | 
|  | TEST_CASE("ik keeps working after a lot of iterations", "[file]") | 
|  | { | 
|  | auto file = ReadRiveFile("../../test/assets/two_bone_ik.riv"); | 
|  | auto artboard = file->artboard(); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Shape>("circle a") != nullptr); | 
|  | auto circleA = artboard->find<rive::Shape>("circle a"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Shape>("circle b") != nullptr); | 
|  | auto circleB = artboard->find<rive::Shape>("circle b"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Bone>("a") != nullptr); | 
|  | auto boneA = artboard->find<rive::Bone>("a"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Bone>("b") != nullptr); | 
|  | auto boneB = artboard->find<rive::Bone>("b"); | 
|  |  | 
|  | REQUIRE(artboard->find<rive::Node>("target") != nullptr); | 
|  | auto target = artboard->find<rive::Node>("target"); | 
|  |  | 
|  | REQUIRE(artboard->animation("Animation 1") != nullptr); | 
|  | auto animation = artboard->animation("Animation 1"); | 
|  |  | 
|  | // Make sure dependency structure is correct. Important thing here is to | 
|  | // ensure that circle a is dependent upon the tip of the ik chain (bone b). | 
|  | // circle b is a child of bone b so it'll be there anyway, but may as well | 
|  | // validate. | 
|  | REQUIRE(std::find(boneB->dependents().begin(), boneB->dependents().end(), circleA) != | 
|  | boneB->dependents().end()); | 
|  | REQUIRE(std::find(boneB->dependents().begin(), boneB->dependents().end(), circleB) != | 
|  | boneB->dependents().end()); | 
|  |  | 
|  | for (int i = 0; i < 1000; i++) | 
|  | { | 
|  | animation->apply(artboard, 0.0f, 1.0f); | 
|  | artboard->advance(0.0f); | 
|  | REQUIRE(target->x() == 296.0f); | 
|  | REQUIRE(target->y() == 202.0f); | 
|  | REQUIRE(aboutEqual(boneA->worldTransform(), | 
|  | rive::Mat2D(0.11632211506366729736328125f, | 
|  | -0.993211567401885986328125f, | 
|  | 0.993211567401885986328125f, | 
|  | 0.11632211506366729736328125f, | 
|  | 26.015254974365234375f, | 
|  | 475.2149658203125f))); | 
|  |  | 
|  | REQUIRE(aboutEqual(boneB->worldTransform(), | 
|  | rive::Mat2D(0.974071562290191650390625f, | 
|  | 0.2262403070926666259765625f, | 
|  | -0.2262403070926666259765625f, | 
|  | 0.974071562290191650390625f, | 
|  | 64.31568145751953125f, | 
|  | 148.1883544921875f))); | 
|  |  | 
|  | animation->apply(artboard, 1.0f, 1.0f); | 
|  | artboard->advance(0.0f); | 
|  | REQUIRE(target->x() == 450.0f); | 
|  | REQUIRE(target->y() == 337.0f); | 
|  | REQUIRE(aboutEqual(boneA->worldTransform(), | 
|  | rive::Mat2D(0.650279819965362548828125f, | 
|  | -0.7596948146820068359375f, | 
|  | 0.7596948146820068359375f, | 
|  | 0.650279819965362548828125f, | 
|  | 26.015254974365234375f, | 
|  | 475.2149658203125f))); | 
|  |  | 
|  | REQUIRE(aboutEqual(boneB->worldTransform(), | 
|  | rive::Mat2D(0.8823678493499755859375f, | 
|  | 0.470560371875762939453125f, | 
|  | -0.47056043148040771484375f, | 
|  | 0.882367908954620361328125f, | 
|  | 240.1275634765625f, | 
|  | 225.07647705078125f))); | 
|  | } | 
|  | } |