diff --git a/engine/src/transform/plugin.cpp b/engine/src/transform/plugin.cpp index 4d385e4a8..3408460dd 100644 --- a/engine/src/transform/plugin.cpp +++ b/engine/src/transform/plugin.cpp @@ -1,6 +1,18 @@ #include using cubos::core::ecs::Traversal; +using cubos::engine::Commands; +using cubos::engine::Entity; +using cubos::engine::Query; + +template +void addComponent(Commands cmds, Query query) +{ + for (auto [e] : query) + { + cmds.add(e, T{}); + } +} void cubos::engine::transformPlugin(Cubos& cubos) { @@ -11,110 +23,68 @@ void cubos::engine::transformPlugin(Cubos& cubos) cubos.addComponent(); cubos.addRelation(); - cubos.system("add LocalToWorld to entities with Position") - .tagged("cubos.transform.missing.local_to_world") + cubos.observer("add LocalToWorld when Position is added") + .onAdd() .without() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, LocalToWorld{}); - } - }); + .call(addComponent); - cubos.system("add LocalToWorld to entities with Rotation") - .tagged("cubos.transform.missing.local_to_world") + cubos.observer("add LocalToWorld when Rotation is added") + .onAdd() .without() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, LocalToWorld{}); - } - }); + .call(addComponent); - cubos.system("add LocalToWorld to entities with Scale") - .tagged("cubos.transform.missing.local_to_world") + cubos.observer("add LocalToWorld when Scale is added") + .onAdd() .without() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, LocalToWorld{}); - } - }); + .call(addComponent); - cubos.tag("cubos.transform.missing.local_to_world").before("cubos.transform.missing"); - - cubos.system("add Position to entities with LocalToWorld") - .tagged("cubos.transform.missing") + cubos.observer("add Position when LocalToWorld is added") + .onAdd() .without() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, Position{}); - } - }); + .call(addComponent); - cubos.system("add Rotation to entities with LocalToWorld") - .tagged("cubos.transform.missing") + cubos.observer("add Rotation when LocalToWorld is added") + .onAdd() .without() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, Rotation{}); - } - }); + .call(addComponent); - cubos.system("add Scale to entities with LocalToWorld") - .tagged("cubos.transform.missing") + cubos.observer("add Scale when LocalToWorld is added") + .onAdd() .without() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, Scale{}); - } - }); + .call(addComponent); - cubos.system("add LocalToParent to entities with LocalToWord and ChildOf other entity with LocalToWorld") - .tagged("cubos.transform.missing") - .entity() + cubos.observer("add LocalToParent to entities with LocalToWorld") + .onAdd() .without() - .with() - .related() - .with() - .call([](Commands cmds, Query query) { - for (auto [e] : query) - { - cmds.add(e, LocalToParent{}); - } - }); - - cubos.tag("cubos.transform.missing").before("cubos.transform.update.relative"); + .call(addComponent); - cubos.system("update relative transform matrix") - .tagged("cubos.transform.update.relative") - .before("cubos.transform.update") - .call([](Query, const Position&, const Rotation&, const Scale&> query) { - for (auto [localToWorld, localToParent, position, rotation, scale] : query) + cubos.system("update LocalToParent's") + .tagged("cubos.transform.update") + .before("cubos.transform.update.propagate") + .call([](Query query) { + for (auto [localToParent, position, rotation, scale] : query) { - auto& mat = localToParent ? localToParent->mat : localToWorld.mat; - mat = glm::scale(glm::translate(glm::mat4(1.0F), position.vec) * glm::toMat4(rotation.quat), - glm::vec3(scale.factor)); + localToParent.mat = + glm::scale(glm::translate(glm::mat4(1.0F), position.vec) * glm::toMat4(rotation.quat), + glm::vec3(scale.factor)); } }); - cubos.system("update LocalToWorlds of children") + cubos.system("update LocalToWorld's of children") .tagged("cubos.transform.update") + .tagged("cubos.transform.update.propagate") .with() .with() .related(Traversal::Down) .with() - .call([](Query query) { - for (auto [localToWorld, localToParent, parentLocalToWorld] : query) + .call([](Query children, + Query all) { + for (auto [localToWorld, localToParent] : all) + { + localToWorld.mat = localToParent.mat; + } + + for (auto [localToWorld, localToParent, parentLocalToWorld] : children) { localToWorld.mat = parentLocalToWorld.mat * localToParent.mat; } diff --git a/engine/tests/transform.cpp b/engine/tests/transform.cpp index ee3522c14..7c5a139b7 100644 --- a/engine/tests/transform.cpp +++ b/engine/tests/transform.cpp @@ -156,7 +156,12 @@ TEST_CASE("cubos::engine::transformPlugin") CHECK(point.z == doctest::Approx(0.0F)); CHECK(point.w == doctest::Approx(1.0F)); - CHECK_FALSE(localToParent); + REQUIRE(localToParent); + point = localToParent->mat * glm::vec4(0.0F, 0.0F, 0.0F, 1.0F); + CHECK(point.x == doctest::Approx(5.0F)); + CHECK(point.y == doctest::Approx(0.0F)); + CHECK(point.z == doctest::Approx(0.0F)); + CHECK(point.w == doctest::Approx(1.0F)); } } });