diff --git a/libpivot/sources/engine.cxx b/libpivot/sources/engine.cxx index 4e2d3659..5055990a 100644 --- a/libpivot/sources/engine.cxx +++ b/libpivot/sources/engine.cxx @@ -47,6 +47,16 @@ namespace pivot Engine::Engine() : m_scripting_engine(m_system_index, m_component_index, pivot::ecs::script::interpreter::builtins::BuiltinContext{ + .loadScene = + [this](const std::string &scene) { + // Check that the scene is loaded + if (!this->m_scene_manager.getSceneId(scene).has_value()) { + logger.warn("loadScene") << "The scene " << scene << " doesn't exist."; + return; + } + // Set the scene as the active one + this->changeCurrentScene(this->m_scene_manager.getSceneId(scene).value()); + }, .isKeyPressed = std::bind_front(&Engine::isKeyPressed, this), .selectCamera = std::bind_front(&Engine::setCurrentCamera, this), }), diff --git a/libscript/CMakeLists.txt b/libscript/CMakeLists.txt index f6503b82..34908680 100644 --- a/libscript/CMakeLists.txt +++ b/libscript/CMakeLists.txt @@ -20,6 +20,7 @@ build_tests( tests/test_interpreter.cxx tests/test_builtins.cxx tests/test_escaped.cxx + tests/test_loadScene.cxx tests/test_decimals.cxx tests/test_multibyte.cxx tests/test_negative_numbers.cxx diff --git a/libscript/include/pivot/script/Builtins.hxx b/libscript/include/pivot/script/Builtins.hxx index c982b789..5f0bdb8b 100644 --- a/libscript/include/pivot/script/Builtins.hxx +++ b/libscript/include/pivot/script/Builtins.hxx @@ -19,13 +19,17 @@ struct BuiltinContext { /// Functor returning true if a specific key is pressed std::function isKeyPressed; + /// Functor calling the setScene from ecs::ScenemManager + std::function loadScene; + /// Select an entity as the new current camera std::function)> selectCamera; /// Mock builtin context for unit testing static BuiltinContext mock() { - return BuiltinContext{.isKeyPressed = [](auto) { return false; }, .selectCamera = [](auto) {}}; + return BuiltinContext{ + .isKeyPressed = [](auto) { return false; }, .loadScene = [](auto) {}, .selectCamera = [](auto) {}}; } }; @@ -40,6 +44,10 @@ data::Value builtin_print(const std::vector ¶ms, const BuiltinC /// Same as above but take a ostream to write to data::Value builtin_print_stream(const std::vector ¶ms, std::ostream &stream); +/// void loadScene(String scene) +/// Loads the scene string passed as parameter into the editor +data::Value builtin_loadScene(const std::vector ¶ms, const BuiltinContext &context); + // Math built-ins /// Number cos(Number radAngle) /// Returns the cosine of the parameter (in radian) diff --git a/libscript/sources/Builtins.cxx b/libscript/sources/Builtins.cxx index d0bd4867..1fa4176e 100644 --- a/libscript/sources/Builtins.cxx +++ b/libscript/sources/Builtins.cxx @@ -57,6 +57,12 @@ data::Value builtin_print_stream(const std::vector ¶ms, std::os return data::Value(); } +data::Value builtin_loadScene(const std::vector ¶ms, const BuiltinContext &context) +{ + context.loadScene(std::get(params.at(0))); + return data::Value(); +} + data::Value builtin_cos(const std::vector ¶ms, const BuiltinContext &) { return std::cos(std::get(params.at(0))); diff --git a/libscript/sources/Interpreter.cxx b/libscript/sources/Interpreter.cxx index fb6b1f1b..f1dbe66a 100644 --- a/libscript/sources/Interpreter.cxx +++ b/libscript/sources/Interpreter.cxx @@ -44,6 +44,7 @@ using ParameterPair = std::pair>>; /// This map will map the name of a builtin, to its callback paired with its signature const std::unordered_map> gBuiltinsCallbacks = { {"isPressed", {interpreter::builtins::builtin_isPressed, {1, {{data::BasicType::String}}}}}, + {"loadScene", {interpreter::builtins::builtin_loadScene, {1, {{data::BasicType::String}}}}}, {"selectCamera", {interpreter::builtins::builtin_selectCamera, {1, {{data::BasicType::EntityRef}}}}}, {"cos", {interpreter::builtins::builtin_cos, {1, {{data::BasicType::Number}}}}}, {"sin", {interpreter::builtins::builtin_sin, {1, {{data::BasicType::Number}}}}}, diff --git a/libscript/tests/test_loadScene.cxx b/libscript/tests/test_loadScene.cxx new file mode 100644 index 00000000..5ffdf6b2 --- /dev/null +++ b/libscript/tests/test_loadScene.cxx @@ -0,0 +1,58 @@ +#include "pivot/ecs/Core/SceneManager.hxx" +#include "pivot/script/Engine.hxx" +#include +#include +#include + +using namespace pivot::ecs; + +TEST_CASE("Scripting-Interpreter-LoadScene") +{ + std::cout << "------Interpreter LoadScene------start (lambda must be the same as in engine.cxx)" << std::endl; + + component::Index cind; + systems::Index sind; + pivot::ecs::SceneManager scenemgr; + // Register 2 scenes, and set Scene2 as current active scene + scenemgr.registerScene("Scene1"); + scenemgr.registerScene("Scene2"); + scenemgr.setCurrentSceneId(scenemgr.getSceneId("Scene2").value()); + script::Engine engine(sind, cind, + pivot::ecs::script::interpreter::builtins::BuiltinContext{ + [](auto) { return false; }, + [&scenemgr](const std::string &scene) { + // Check that the scene is loaded + if (!scenemgr.getSceneId(scene).has_value()) { + logger.warn("loadScene") << "The scene " << scene << " doesn't exist."; + return; + } + // Set the scene as the active one + scenemgr.setCurrentSceneId(scenemgr.getSceneId(scene).value()); + }}); + // std::string file = "C:/Users/Najo/eip/pivot/libscript/tests/loadScene.pvt"; + // engine.loadFile(file); + std::string fileContent = "component C\n" + "\tString str\n" + "system S(anyEntity) event Tick(Number deltaTime)\n" + "\tloadScene(\"Scene1\")\n"; + engine.loadFile(fileContent, true); + + REQUIRE(sind.getDescription("S").has_value()); + REQUIRE(cind.getDescription("C").has_value()); + + auto Cdescription = cind.getDescription("C").value(); + auto Sdescription = sind.getDescription("S").value(); + auto array1 = Cdescription.createContainer(Cdescription); + std::vector entity = {data::Record{{"str", "foo"}}}; + array1->setValueForEntity(0, entity.at(0)); + component::ArrayCombination combinations{{std::ref(*array1)}}; + event::EventWithComponent evt = { + .event = event::Event{.description = Sdescription.eventListener, .entities = {1, 2}, .payload = 0.12}}; + + Sdescription.system(Sdescription, combinations, evt); + + // Check that after execution, current active scene is Scene1 + REQUIRE(scenemgr.getCurrentSceneId() == 0); + + std::cout << "------Interpreter LoadScene------end" << std::endl; +}