From 76f3c79b8b4045a6f4a3844b6a65d5bc44dc64a6 Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Mon, 17 Oct 2022 11:41:57 +0100 Subject: [PATCH] lua integration test --- CMakeLists.txt | 20 ++-- Config.cmake.in | 1 + demo/CMakeLists.txt | 5 +- demo/data/rollball.lua | 1 + demo/data/rollball.yml | 2 + demo/demo/main.cpp | 2 + demo/demo/rollball.cpp | 20 ++++ demo/include/rollball.hpp | 2 + include/fggl/script/engine.hpp | 53 ++++++++++ integrations/lua/CMakeLists.txt | 19 ++++ .../lua/include/fggl/script/lua/engine.hpp | 67 +++++++++++++ .../lua/include/fggl/script/lua/module.hpp | 46 +++++++++ integrations/lua/src/engine.cpp | 98 +++++++++++++++++++ integrations/lua/src/module.cpp | 35 +++++++ 14 files changed, 364 insertions(+), 7 deletions(-) create mode 100644 demo/data/rollball.lua create mode 100644 include/fggl/script/engine.hpp create mode 100644 integrations/lua/CMakeLists.txt create mode 100644 integrations/lua/include/fggl/script/lua/engine.hpp create mode 100644 integrations/lua/include/fggl/script/lua/module.hpp create mode 100644 integrations/lua/src/engine.cpp create mode 100644 integrations/lua/src/module.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e7c22b..396a756 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,11 +63,22 @@ if (FGGL_DOCS) endif() endif() +## +# Optional/Extra modules +## + +# 3rd party integrations +add_subdirectory( integrations/bullet ) +add_subdirectory( integrations/lua ) + +# Tools +add_subdirectory( tools/pack ) + # Demo project if (FGGL_EXAMPLES) - add_subdirectory(demo) - target_compile_options( demo PRIVATE -Wall -Wextra -Wodr -Wdouble-promotion -fno-strict-aliasing -fno-strict-overflow ) - set_property(TARGET demo PROPERTY INTERPROCEDURAL_OPTIMIZATION True) + add_subdirectory(demo) + target_compile_options( demo PRIVATE -Wall -Wextra -Wodr -Wdouble-promotion -fno-strict-aliasing -fno-strict-overflow ) + set_property(TARGET demo PROPERTY INTERPROCEDURAL_OPTIMIZATION True) endif() ## @@ -127,6 +138,3 @@ export(EXPORT "${PROJECT_NAME}Targets" NAMESPACE ${namespace}:: ) -# 3rd party integrations -add_subdirectory( integrations/bullet ) -add_subdirectory( tools/pack ) diff --git a/Config.cmake.in b/Config.cmake.in index fe72022..7d3cb0a 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -3,6 +3,7 @@ include(CMakeFindDependencyMacro) find_dependency(glm) find_dependency(fmt) +find_dependency(Lua) find_dependency(spdlog) find_dependency(Freetype) find_dependency(OpenAL CONFIG) diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 37e86da..facfd04 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -11,7 +11,6 @@ add_executable(demo demo/robot/programmer.cpp ) - target_include_directories(demo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -19,11 +18,15 @@ target_include_directories(demo target_link_libraries( demo fggl ) #target_link_libraries(demo fggl fgglbt) +target_link_libraries( demo fggl-lua ) find_package(spdlog) target_link_libraries(demo spdlog::spdlog) #target_include_directories(FgglDemo PUBLIC ${PROJECT_BINARY_DIR}) +#find_package(Lua) +#target_link_libraries(demo ${LUA_LIBRARIES}) + # resources file(GLOB_RECURSE data data/*) file(COPY ${data} DESTINATION data ) diff --git a/demo/data/rollball.lua b/demo/data/rollball.lua new file mode 100644 index 0000000..1221bc1 --- /dev/null +++ b/demo/data/rollball.lua @@ -0,0 +1 @@ +print("File has been loaded!") \ No newline at end of file diff --git a/demo/data/rollball.yml b/demo/data/rollball.yml index 966d1f8..f9895a6 100644 --- a/demo/data/rollball.yml +++ b/demo/data/rollball.yml @@ -120,3 +120,5 @@ scene: components: Transform: origin: [6, -0.5, 15] +scripts: + - "rollball.lua" \ No newline at end of file diff --git a/demo/demo/main.cpp b/demo/demo/main.cpp index da2ae94..37b95f6 100644 --- a/demo/demo/main.cpp +++ b/demo/demo/main.cpp @@ -41,6 +41,7 @@ #include "fggl/scenes/menu.hpp" #include "fggl/modules/manager.hpp" #include "fggl/assets/module.hpp" +#include "fggl/script/lua/module.hpp" #include "GameScene.h" #include "rollball.hpp" @@ -83,6 +84,7 @@ int main(int argc, const char* argv[]) { moduleManager.use<fggl::display::GLFW>(); moduleManager.use<fggl::assets::AssetFolders>(); moduleManager.use<fggl::entity::ECS>(); + moduleManager.use<fggl::script::Lua>(); #ifdef FGGL_MODULE_BULLET moduleManager.use<fggl::phys::Bullet3>(); diff --git a/demo/demo/rollball.cpp b/demo/demo/rollball.cpp index cccdac0..39fb33b 100644 --- a/demo/demo/rollball.cpp +++ b/demo/demo/rollball.cpp @@ -125,6 +125,10 @@ namespace demo { auto* entFactory = m_owner.service<fggl::entity::EntityFactory>(); m_phys = physService->create(&world(), entFactory); + auto* scriptProvider = m_owner.service<fggl::script::ScriptProvider>(); + m_scripts = scriptProvider->create(); + + // asset loader auto* assetLoader = m_owner.service<fggl::assets::Loader>(); assetLoader->load("rollball.yml", fggl::entity::PROTOTYPE_ASSET); @@ -145,9 +149,20 @@ namespace demo { // create a 20x20 grid setup_environment(world(), m_owner.service<fggl::entity::EntityFactory>(), WORLD_SIZE, state); + + // activate scripts + if ( m_scripts != nullptr ) { + m_scripts->onActivate(); + m_scripts->load("rollball.lua"); + } } void RollBall::deactivate() { + // deactivate scripts + if ( m_scripts != nullptr ) { + m_scripts->onActivate(); + } + // we need to clean up physics if ( m_phys != nullptr ) { delete m_phys; @@ -235,6 +250,11 @@ namespace demo { spinCubes(world, deltaTime); state.time += deltaTime; } + + // tick scripts + if ( m_scripts != nullptr ) { + m_scripts->onUpdate(); + } } void RollBall::closestPickup(fggl::entity::EntityManager &world) { diff --git a/demo/include/rollball.hpp b/demo/include/rollball.hpp index fc23e5c..a470bfc 100644 --- a/demo/include/rollball.hpp +++ b/demo/include/rollball.hpp @@ -27,6 +27,7 @@ #include "fggl/scenes/game.hpp" #include "fggl/phys/service.hpp" +#include "fggl/script/engine.hpp" namespace demo { @@ -64,6 +65,7 @@ namespace demo { constexpr static fggl::math::vec3 HINT_COLOUR{0.5f, 0.0f, 0.0f}; RollState state; fggl::phys::PhysicsEngine* m_phys; + fggl::script::ScriptEngine* m_scripts; fggl::math::vec3 cameraOffset = {-15.0F, 15.0F, 0.0F}; void closestPickup(fggl::entity::EntityManager& world); diff --git a/include/fggl/script/engine.hpp b/include/fggl/script/engine.hpp new file mode 100644 index 0000000..f81d7f1 --- /dev/null +++ b/include/fggl/script/engine.hpp @@ -0,0 +1,53 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 15/10/22. +// + +#ifndef FGGL_SCRIPT_ENGINE_H +#define FGGL_SCRIPT_ENGINE_H + +#include "fggl/modules/module.hpp" + +namespace fggl::script { + + class ScriptEngine { + public: + virtual ~ScriptEngine() = default; + + // TODO use protected virtual pattern + + // scene callbacks + virtual void onActivate() = 0; + virtual void onDeactivate() = 0; + virtual void onUpdate() = 0; + + // trigger callback + virtual void onEvent(const std::string& name) = 0; + + // run code in engine + virtual bool run(const char* script) = 0; + virtual bool load(const char* filename) = 0; + }; + + class ScriptProvider { + public: + constexpr static const modules::ModuleService service = modules::make_service("fggl::script::service"); + virtual ScriptEngine* create() = 0; + }; + +} + +#endif //FGGL_SCRIPT_ENGINE_H diff --git a/integrations/lua/CMakeLists.txt b/integrations/lua/CMakeLists.txt new file mode 100644 index 0000000..e889372 --- /dev/null +++ b/integrations/lua/CMakeLists.txt @@ -0,0 +1,19 @@ +add_library(fggl-lua) + +find_package(Lua REQUIRED) +target_link_libraries(fggl-lua PUBLIC ${LUA_LIBRARIES}) + +# Link to FGGL +target_link_libraries(fggl-lua PUBLIC fggl) + +# sources and include directories +target_sources(fggl-lua + PRIVATE + src/engine.cpp + src/module.cpp +) +target_include_directories(fggl-lua + PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include> + $<INSTALL_INTERFACE:include> +) diff --git a/integrations/lua/include/fggl/script/lua/engine.hpp b/integrations/lua/include/fggl/script/lua/engine.hpp new file mode 100644 index 0000000..0442c74 --- /dev/null +++ b/integrations/lua/include/fggl/script/lua/engine.hpp @@ -0,0 +1,67 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 15/10/22. +// + +#ifndef FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_ENGINE_HPP +#define FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_ENGINE_HPP + +#include "fggl/script/engine.hpp" +#include "fggl/data/storage.hpp" + +extern "C" { + #include <lua.h> + #include <lauxlib.h> + #include <lualib.h> +}; + +namespace fggl::script::lua { + + class LuaScriptEngine : public ScriptEngine { + public: + LuaScriptEngine(data::Storage* storage); + virtual ~LuaScriptEngine(); + + void onActivate() override; + void onDeactivate() override; + void onUpdate() override; + + void onEvent(const std::string& name) override; + + // running scripts + bool run(const char* script) override; + bool load(const char* filename) override; + + private: + data::Storage* m_storage; + lua_State* m_state; + void release(); + }; + + class LuaScriptProvider : public ScriptProvider { + public: + LuaScriptProvider(data::Storage* storage); + + virtual ~LuaScriptProvider() = default; + LuaScriptEngine* create() override; + + private: + data::Storage* m_storage; + }; + +} + +#endif //FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_ENGINE_HPP diff --git a/integrations/lua/include/fggl/script/lua/module.hpp b/integrations/lua/include/fggl/script/lua/module.hpp new file mode 100644 index 0000000..5f9bd96 --- /dev/null +++ b/integrations/lua/include/fggl/script/lua/module.hpp @@ -0,0 +1,46 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 15/10/22. +// + +#ifndef FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_MODULE_HPP +#define FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_MODULE_HPP + +#include "fggl/modules/module.hpp" +#include "fggl/entity/module.hpp" +#include "fggl/script/engine.hpp" +#include "fggl/data/module.hpp" + +namespace fggl::script::lua { + struct Lua { + constexpr static const char* name = "fggl::script::lua"; + constexpr static const std::array<modules::ModuleService, 1> provides = { + script::ScriptProvider::service + }; + constexpr static const std::array<modules::ModuleService, 1> depends = { + data::SERVICE_STORAGE + }; + static bool factory(modules::ModuleService name, modules::Services& serviceManager); + }; + +} // namespace fggl::script::lua + +namespace fggl::script { + using Lua = lua::Lua; + +} // namespace fggl::script + +#endif //FGGL_INTEGRATIONS_LUA_SCRIPT_LUA_MODULE_HPP diff --git a/integrations/lua/src/engine.cpp b/integrations/lua/src/engine.cpp new file mode 100644 index 0000000..984b588 --- /dev/null +++ b/integrations/lua/src/engine.cpp @@ -0,0 +1,98 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 15/10/22. +// + +#include "fggl/script/lua/engine.hpp" +#include "fggl/debug/logging.hpp" + +#include <cassert> + +namespace fggl::script::lua { + + LuaScriptProvider::LuaScriptProvider(data::Storage *storage) : m_storage(storage) { + } + + LuaScriptEngine *LuaScriptProvider::create() { + return new LuaScriptEngine(m_storage); + } + + LuaScriptEngine::LuaScriptEngine(data::Storage* storage) : m_state(luaL_newstate()), m_storage(storage) { + luaL_openlibs(m_state); + } + + LuaScriptEngine::~LuaScriptEngine() { + release(); + } + + void LuaScriptEngine::release() { + if ( m_state != nullptr ) { + lua_close(m_state); + m_state = nullptr; + } + } + + void LuaScriptEngine::onActivate() { + lua_getglobal(m_state, "print"); + lua_pushstring(m_state, "LUA activate triggered"); + lua_call(m_state, 1, 0); + } + + void LuaScriptEngine::onDeactivate() { + lua_getglobal(m_state, "print"); + lua_pushstring(m_state, "LUA deactivate triggered"); + lua_call(m_state, 1, 0); + } + + void LuaScriptEngine::onUpdate() { + lua_getglobal(m_state, "print"); + lua_pushstring(m_state, "LUA update triggered"); + lua_call(m_state, 1, 0); + } + + void LuaScriptEngine::onEvent(const std::string &name) { + lua_getglobal(m_state, "print"); + lua_pushstring(m_state, "LUA event triggered"); + lua_call(m_state, 1, 0); + } + + bool LuaScriptEngine::run(const char *script) { + auto result = luaL_dostring(m_state, script); + if ( !result ) { + fggl::debug::warning("lua error: {}", lua_tostring(m_state, -1)); + } + return result; + } + + bool LuaScriptEngine::load(const char *filename) { + assert( filename != nullptr); + auto path = m_storage->resolvePath(data::StorageType::Data, filename); + + if ( !std::filesystem::exists(path) ) { + fggl::debug::warning("lua error: file does not exist: {}", path.c_str()); + return false; + } + + // load the file ( OK = 0 = false because reasons...) + auto result = !luaL_dofile(m_state, path.c_str()); + if ( !result ) { + fggl::debug::warning("lua error: {}", lua_tostring(m_state, -1)); + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/integrations/lua/src/module.cpp b/integrations/lua/src/module.cpp new file mode 100644 index 0000000..af4b1e3 --- /dev/null +++ b/integrations/lua/src/module.cpp @@ -0,0 +1,35 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 15/10/22. +// + +#include "fggl/script/lua/module.hpp" +#include "fggl/script/lua/engine.hpp" + +namespace fggl::script::lua { + + bool Lua::factory(modules::ModuleService service, modules::Services &serviceManager) { + + if ( service == ScriptProvider::service ) { + auto storageService = serviceManager.get<data::Storage>(); + serviceManager.bind<ScriptProvider,LuaScriptProvider>(storageService); + return true; + } + + return false; + } + +} \ No newline at end of file -- GitLab