From 6b98369bd70f117024d31a76abb14a01cdbc5a6a Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 4 Jan 2026 15:54:28 +0000 Subject: [PATCH] stuff --- src/app/service_based_app.cpp | 79 +++---- src/script/lua_bindings.cpp | 200 ++++++++++++++++-- src/script/lua_bindings.hpp | 21 ++ src/script/mesh_payload.hpp | 18 ++ src/script/script_engine.cpp | 20 +- src/script/script_engine.hpp | 14 +- src/services/impl/audio_command_service.cpp | 54 ++++- src/services/impl/audio_command_service.hpp | 14 +- src/services/impl/lua_script_service.cpp | 5 - src/services/impl/lua_script_service.hpp | 2 - src/services/impl/mesh_service.cpp | 136 +++++++++++- src/services/impl/mesh_service.hpp | 6 +- src/services/impl/physics_bridge_service.cpp | 22 +- src/services/impl/physics_bridge_service.hpp | 8 +- src/services/impl/script_engine_service.cpp | 14 +- src/services/impl/script_engine_service.hpp | 14 ++ src/services/impl/sdl_input_service.cpp | 9 +- src/services/impl/sdl_input_service.hpp | 5 +- .../interfaces/i_audio_command_service.hpp | 11 +- src/services/interfaces/i_input_service.hpp | 8 +- src/services/interfaces/i_mesh_service.hpp | 4 +- src/services/interfaces/i_script_service.hpp | 7 - 22 files changed, 545 insertions(+), 126 deletions(-) create mode 100644 src/script/mesh_payload.hpp diff --git a/src/app/service_based_app.cpp b/src/app/service_based_app.cpp index 00be649..1e29a0c 100644 --- a/src/app/service_based_app.cpp +++ b/src/app/service_based_app.cpp @@ -210,6 +210,49 @@ void ServiceBasedApp::RegisterServices() { registry_.GetService(), registry_.GetService()); + // Audio service (needed before script bindings execute) + registry_.RegisterService( + registry_.GetService()); + + // Script bridge services + registry_.RegisterService( + registry_.GetService()); + registry_.RegisterService( + registry_.GetService()); + registry_.RegisterService( + registry_.GetService(), + registry_.GetService(), + registry_.GetService()); + + // Script engine service (shared Lua runtime) + registry_.RegisterService( + scriptPath_, + registry_.GetService(), + registry_.GetService(), + registry_.GetService(), + registry_.GetService(), + runtimeConfig.luaDebug); + + // Script-facing services + registry_.RegisterService( + registry_.GetService()); + registry_.RegisterService( + registry_.GetService()); + registry_.RegisterService( + registry_.GetService()); + + // Script service (facade) + registry_.RegisterService( + registry_.GetService(), + registry_.GetService()); + + // Connect input service to GUI script service for GUI input processing + auto inputService = registry_.GetService(); + auto guiScriptService = registry_.GetService(); + if (inputService && guiScriptService) { + inputService->SetGuiScriptService(guiScriptService.get()); + } + // Vulkan device service registry_.RegisterService( registry_.GetService()); @@ -246,47 +289,11 @@ void ServiceBasedApp::RegisterServices() { registry_.GetService(), registry_.GetService()); - // Script engine service (shared Lua runtime) - registry_.RegisterService( - scriptPath_, - registry_.GetService(), - runtimeConfig.luaDebug); - - // Script-facing services - registry_.RegisterService( - registry_.GetService()); - registry_.RegisterService( - registry_.GetService()); - registry_.RegisterService( - registry_.GetService()); - registry_.RegisterService( - registry_.GetService()); - registry_.RegisterService( - registry_.GetService()); - registry_.RegisterService( - registry_.GetService()); - - // Script service (facade) - registry_.RegisterService( - registry_.GetService(), - registry_.GetService()); - - // Connect input service to script service for GUI input processing - auto inputService = registry_.GetService(); - auto scriptService = registry_.GetService(); - if (inputService && scriptService) { - inputService->SetScriptService(scriptService.get()); - } - // Scene service registry_.RegisterService( registry_.GetService(), registry_.GetService()); - // Audio service - registry_.RegisterService( - registry_.GetService()); - // GUI service registry_.RegisterService( registry_.GetService()); diff --git a/src/script/lua_bindings.cpp b/src/script/lua_bindings.cpp index 5a2785d..70ec424 100644 --- a/src/script/lua_bindings.cpp +++ b/src/script/lua_bindings.cpp @@ -1,8 +1,10 @@ #include "script/lua_bindings.hpp" #include "script/script_engine.hpp" #include "script/lua_helpers.hpp" -#include "script/mesh_loader.hpp" #include "logging/logger.hpp" +#include "services/interfaces/i_audio_command_service.hpp" +#include "services/interfaces/i_mesh_service.hpp" +#include "services/interfaces/i_physics_bridge_service.hpp" #include #include @@ -40,21 +42,66 @@ void LuaBindings::RegisterBindings(lua_State* L, ScriptEngine* engine) { lua_setglobal(L, "audio_play_sound"); } +void LuaBindings::RegisterBindings(lua_State* L, LuaBindingContext* context) { + sdl3cpp::logging::TraceGuard trace; + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &LoadMeshFromFileWithServices, 1); + lua_setglobal(L, "load_mesh_from_file"); + + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &PhysicsCreateBoxWithServices, 1); + lua_setglobal(L, "physics_create_box"); + + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &PhysicsStepSimulationWithServices, 1); + lua_setglobal(L, "physics_step_simulation"); + + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &PhysicsGetTransformWithServices, 1); + lua_setglobal(L, "physics_get_transform"); + + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &GlmMatrixFromTransform, 1); + lua_setglobal(L, "glm_matrix_from_transform"); + + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &AudioPlayBackgroundWithServices, 1); + lua_setglobal(L, "audio_play_background"); + + lua_pushlightuserdata(L, context); + lua_pushcclosure(L, &AudioPlaySoundWithServices, 1); + lua_setglobal(L, "audio_play_sound"); +} + int LuaBindings::LoadMeshFromFile(lua_State* L) { sdl3cpp::logging::TraceGuard trace;; - auto* engine = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + (void)lua_touserdata(L, lua_upvalueindex(1)); + lua_pushnil(L); + lua_pushstring(L, "Mesh service not available"); + return 2; +} + +int LuaBindings::LoadMeshFromFileWithServices(lua_State* L) { + sdl3cpp::logging::TraceGuard trace; + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (!context || !context->meshService) { + lua_pushnil(L); + lua_pushstring(L, "Mesh service not available"); + return 2; + } + const char* path = luaL_checkstring(L, 1); sdl3cpp::logging::Logger::GetInstance().TraceVariable("path", path); - + MeshPayload payload; std::string error; - if (!MeshLoader::LoadFromFile(engine->GetScriptDirectory(), path, payload, error)) { + if (!context->meshService->LoadFromFile(path, payload, error)) { lua_pushnil(L); lua_pushstring(L, error.c_str()); return 2; } - - MeshLoader::PushMeshToLua(L, payload); + + context->meshService->PushMeshToLua(L, payload); lua_pushnil(L); return 2; } @@ -95,6 +142,48 @@ int LuaBindings::PhysicsCreateBox(lua_State* L) { return 1; } +int LuaBindings::PhysicsCreateBoxWithServices(lua_State* L) { + sdl3cpp::logging::TraceGuard trace; + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (!context || !context->physicsBridgeService) { + lua_pushnil(L); + lua_pushstring(L, "Physics service not available"); + return 2; + } + + const char* name = luaL_checkstring(L, 1); + sdl3cpp::logging::Logger::GetInstance().TraceVariable("name", name); + + if (!lua_istable(L, 2) || !lua_istable(L, 4) || !lua_istable(L, 5)) { + luaL_error(L, "physics_create_box expects vector tables for half extents, origin, and rotation"); + } + + std::array halfExtents = ReadVector3(L, 2); + float mass = static_cast(luaL_checknumber(L, 3)); + std::array origin = ReadVector3(L, 4); + std::array rotation = ReadQuaternion(L, 5); + + btTransform transform; + transform.setIdentity(); + transform.setOrigin(btVector3(origin[0], origin[1], origin[2])); + transform.setRotation(btQuaternion(rotation[0], rotation[1], rotation[2], rotation[3])); + + std::string error; + if (!context->physicsBridgeService->AddBoxRigidBody( + name, + btVector3(halfExtents[0], halfExtents[1], halfExtents[2]), + mass, + transform, + error)) { + lua_pushnil(L); + lua_pushstring(L, error.c_str()); + return 2; + } + + lua_pushboolean(L, 1); + return 1; +} + int LuaBindings::PhysicsStepSimulation(lua_State* L) { auto* engine = static_cast(lua_touserdata(L, lua_upvalueindex(1))); float deltaTime = static_cast(luaL_checknumber(L, 1)); @@ -103,6 +192,18 @@ int LuaBindings::PhysicsStepSimulation(lua_State* L) { return 1; } +int LuaBindings::PhysicsStepSimulationWithServices(lua_State* L) { + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (!context || !context->physicsBridgeService) { + lua_pushinteger(L, 0); + return 1; + } + float deltaTime = static_cast(luaL_checknumber(L, 1)); + int steps = context->physicsBridgeService->StepSimulation(deltaTime); + lua_pushinteger(L, steps); + return 1; +} + int LuaBindings::PhysicsGetTransform(lua_State* L) { auto* engine = static_cast(lua_touserdata(L, lua_upvalueindex(1))); const char* name = luaL_checkstring(L, 1); @@ -141,40 +242,111 @@ int LuaBindings::PhysicsGetTransform(lua_State* L) { return 1; } +int LuaBindings::PhysicsGetTransformWithServices(lua_State* L) { + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (!context || !context->physicsBridgeService) { + lua_pushnil(L); + lua_pushstring(L, "Physics service not available"); + return 2; + } + const char* name = luaL_checkstring(L, 1); + + btTransform transform; + std::string error; + if (!context->physicsBridgeService->GetRigidBodyTransform(name, transform, error)) { + lua_pushnil(L); + lua_pushstring(L, error.c_str()); + return 2; + } + + lua_newtable(L); + lua_newtable(L); + const btVector3& origin = transform.getOrigin(); + lua_pushnumber(L, origin.x()); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, origin.y()); + lua_rawseti(L, -2, 2); + lua_pushnumber(L, origin.z()); + lua_rawseti(L, -2, 3); + lua_setfield(L, -2, "position"); + + lua_newtable(L); + const btQuaternion& orientation = transform.getRotation(); + lua_pushnumber(L, orientation.x()); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, orientation.y()); + lua_rawseti(L, -2, 2); + lua_pushnumber(L, orientation.z()); + lua_rawseti(L, -2, 3); + lua_pushnumber(L, orientation.w()); + lua_rawseti(L, -2, 4); + lua_setfield(L, -2, "rotation"); + + return 1; +} + int LuaBindings::AudioPlayBackground(lua_State* L) { - auto* engine = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + (void)lua_touserdata(L, lua_upvalueindex(1)); + (void)luaL_checkstring(L, 1); + lua_pushnil(L); + lua_pushstring(L, "Audio service not available"); + return 2; +} + +int LuaBindings::AudioPlayBackgroundWithServices(lua_State* L) { + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (!context || !context->audioCommandService) { + lua_pushnil(L); + lua_pushstring(L, "Audio service not available"); + return 2; + } const char* path = luaL_checkstring(L, 1); bool loop = true; if (lua_gettop(L) >= 2 && lua_isboolean(L, 2)) { loop = lua_toboolean(L, 2); } - + std::string error; - if (!engine->QueueAudioCommand(AudioManager::AudioCommandType::Background, path, loop, error)) { + if (!context->audioCommandService->QueueAudioCommand( + services::AudioCommandType::Background, path, loop, error)) { lua_pushnil(L); lua_pushstring(L, error.c_str()); return 2; } - + lua_pushboolean(L, 1); return 1; } int LuaBindings::AudioPlaySound(lua_State* L) { - auto* engine = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + (void)lua_touserdata(L, lua_upvalueindex(1)); + (void)luaL_checkstring(L, 1); + lua_pushnil(L); + lua_pushstring(L, "Audio service not available"); + return 2; +} + +int LuaBindings::AudioPlaySoundWithServices(lua_State* L) { + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + if (!context || !context->audioCommandService) { + lua_pushnil(L); + lua_pushstring(L, "Audio service not available"); + return 2; + } const char* path = luaL_checkstring(L, 1); bool loop = false; if (lua_gettop(L) >= 2 && lua_isboolean(L, 2)) { loop = lua_toboolean(L, 2); } - + std::string error; - if (!engine->QueueAudioCommand(AudioManager::AudioCommandType::Effect, path, loop, error)) { + if (!context->audioCommandService->QueueAudioCommand( + services::AudioCommandType::Effect, path, loop, error)) { lua_pushnil(L); lua_pushstring(L, error.c_str()); return 2; } - + lua_pushboolean(L, 1); return 1; } diff --git a/src/script/lua_bindings.hpp b/src/script/lua_bindings.hpp index 26c807b..de61f3a 100644 --- a/src/script/lua_bindings.hpp +++ b/src/script/lua_bindings.hpp @@ -1,23 +1,44 @@ #ifndef SDL3CPP_SCRIPT_LUA_BINDINGS_HPP #define SDL3CPP_SCRIPT_LUA_BINDINGS_HPP +#include + struct lua_State; +namespace sdl3cpp::services { +class IAudioCommandService; +class IMeshService; +class IPhysicsBridgeService; +} + namespace sdl3cpp::script { class ScriptEngine; +struct LuaBindingContext { + std::shared_ptr meshService; + std::shared_ptr audioCommandService; + std::shared_ptr physicsBridgeService; +}; + class LuaBindings { public: static void RegisterBindings(lua_State* L, ScriptEngine* engine); + static void RegisterBindings(lua_State* L, LuaBindingContext* context); private: static int LoadMeshFromFile(lua_State* L); + static int LoadMeshFromFileWithServices(lua_State* L); static int PhysicsCreateBox(lua_State* L); + static int PhysicsCreateBoxWithServices(lua_State* L); static int PhysicsStepSimulation(lua_State* L); + static int PhysicsStepSimulationWithServices(lua_State* L); static int PhysicsGetTransform(lua_State* L); + static int PhysicsGetTransformWithServices(lua_State* L); static int AudioPlayBackground(lua_State* L); + static int AudioPlayBackgroundWithServices(lua_State* L); static int AudioPlaySound(lua_State* L); + static int AudioPlaySoundWithServices(lua_State* L); static int GlmMatrixFromTransform(lua_State* L); }; diff --git a/src/script/mesh_payload.hpp b/src/script/mesh_payload.hpp new file mode 100644 index 0000000..9c23671 --- /dev/null +++ b/src/script/mesh_payload.hpp @@ -0,0 +1,18 @@ +#ifndef SDL3CPP_SCRIPT_MESH_PAYLOAD_HPP +#define SDL3CPP_SCRIPT_MESH_PAYLOAD_HPP + +#include +#include +#include + +namespace sdl3cpp::script { + +struct MeshPayload { + std::vector> positions; + std::vector> colors; + std::vector indices; +}; + +} // namespace sdl3cpp::script + +#endif // SDL3CPP_SCRIPT_MESH_PAYLOAD_HPP diff --git a/src/script/script_engine.cpp b/src/script/script_engine.cpp index a976f5a..2b5215e 100644 --- a/src/script/script_engine.cpp +++ b/src/script/script_engine.cpp @@ -2,7 +2,6 @@ #include "script/scene_manager.hpp" #include "script/shader_manager.hpp" #include "script/gui_manager.hpp" -#include "script/audio_manager.hpp" #include "script/lua_bindings.hpp" #include "logging/logger.hpp" @@ -16,14 +15,17 @@ namespace sdl3cpp::script { ScriptEngine::ScriptEngine(const std::filesystem::path& scriptPath, bool debugEnabled) + : ScriptEngine(scriptPath, nullptr, debugEnabled) { +} + +ScriptEngine::ScriptEngine(const std::filesystem::path& scriptPath, LuaBindingContext* bindingContext, bool debugEnabled) : L_(luaL_newstate()), scriptDirectory_(scriptPath.parent_path()), debugEnabled_(debugEnabled), physicsBridge_(std::make_unique()), sceneManager_(std::make_unique(L_)), shaderManager_(std::make_unique(L_)), - guiManager_(std::make_unique(L_)), - audioManager_(std::make_unique(scriptDirectory_)) { + guiManager_(std::make_unique(L_)) { sdl3cpp::logging::TraceGuard trace;; if (!L_) { sdl3cpp::logging::Logger::GetInstance().Error("Failed to create Lua state"); @@ -33,7 +35,11 @@ ScriptEngine::ScriptEngine(const std::filesystem::path& scriptPath, bool debugEn sdl3cpp::logging::Logger::GetInstance().Debug("Lua state created successfully"); luaL_openlibs(L_); - LuaBindings::RegisterBindings(L_, this); + if (bindingContext) { + LuaBindings::RegisterBindings(L_, bindingContext); + } else { + LuaBindings::RegisterBindings(L_, this); + } lua_pushboolean(L_, debugEnabled_); lua_setglobal(L_, "lua_debug"); @@ -109,13 +115,9 @@ std::filesystem::path ScriptEngine::GetScriptDirectory() const { return scriptDirectory_; } -bool ScriptEngine::QueueAudioCommand(AudioManager::AudioCommandType type, std::string path, bool loop, std::string& error) { - return audioManager_->QueueAudioCommand(type, path, loop, error); -} - std::string ScriptEngine::GetLuaError() { const char* message = lua_tostring(L_, -1); return message ? message : "unknown lua error"; } -} // namespace sdl3cpp::script \ No newline at end of file +} // namespace sdl3cpp::script diff --git a/src/script/script_engine.hpp b/src/script/script_engine.hpp index 90690a1..1428801 100644 --- a/src/script/script_engine.hpp +++ b/src/script/script_engine.hpp @@ -16,17 +16,15 @@ #include "script/scene_manager.hpp" #include "script/shader_manager.hpp" #include "script/gui_manager.hpp" -#include "script/audio_manager.hpp" - -namespace sdl3cpp::app { -class AudioPlayer; -} namespace sdl3cpp::script { +struct LuaBindingContext; + class ScriptEngine { public: explicit ScriptEngine(const std::filesystem::path& scriptPath, bool debugEnabled = false); + ScriptEngine(const std::filesystem::path& scriptPath, LuaBindingContext* bindingContext, bool debugEnabled = false); ~ScriptEngine(); ScriptEngine(const ScriptEngine&) = delete; @@ -41,12 +39,9 @@ public: bool HasGuiCommands() const; std::filesystem::path GetScriptDirectory() const; PhysicsBridge& GetPhysicsBridge(); - // void SetAudioPlayer(app::AudioPlayer* audioPlayer); // Removed - using services now - bool QueueAudioCommand(AudioManager::AudioCommandType type, std::string path, bool loop, std::string& error); std::string GetLuaError(); private: - void ExecuteAudioCommand(const AudioManager::AudioCommand& command); // Updated to not take AudioPlayer std::filesystem::path ResolveScriptPath(const std::string& requested) const; static std::vector ReadVertexArray(lua_State* L, int index); @@ -62,12 +57,9 @@ private: std::filesystem::path scriptDirectory_; bool debugEnabled_ = false; std::unique_ptr physicsBridge_; - app::AudioPlayer* audioPlayer_ = nullptr; - std::vector pendingAudioCommands_; std::unique_ptr sceneManager_; std::unique_ptr shaderManager_; std::unique_ptr guiManager_; - std::unique_ptr audioManager_; }; } // namespace sdl3cpp::script diff --git a/src/services/impl/audio_command_service.cpp b/src/services/impl/audio_command_service.cpp index c1d382e..0721e9d 100644 --- a/src/services/impl/audio_command_service.cpp +++ b/src/services/impl/audio_command_service.cpp @@ -1,17 +1,63 @@ #include "audio_command_service.hpp" +#include #include namespace sdl3cpp::services::impl { -AudioCommandService::AudioCommandService(std::shared_ptr engineService) - : engineService_(std::move(engineService)) { +AudioCommandService::AudioCommandService(std::shared_ptr configService, + std::shared_ptr audioService, + std::shared_ptr logger) + : configService_(std::move(configService)), + audioService_(std::move(audioService)), + logger_(std::move(logger)) { } -bool AudioCommandService::QueueAudioCommand(script::AudioManager::AudioCommandType type, +bool AudioCommandService::QueueAudioCommand(AudioCommandType type, const std::string& path, bool loop, std::string& error) { - return engineService_->GetEngine().QueueAudioCommand(type, path, loop, error); + if (!audioService_) { + error = "Audio service not available"; + return false; + } + if (!configService_) { + error = "Config service not available"; + return false; + } + + std::filesystem::path resolved(path); + if (!resolved.is_absolute()) { + std::filesystem::path scriptDir = configService_->GetScriptPath().parent_path(); + resolved = scriptDir / resolved; + } + + std::error_code ec; + resolved = std::filesystem::weakly_canonical(resolved, ec); + if (ec) { + error = "Failed to resolve audio path: " + ec.message(); + return false; + } + if (!std::filesystem::exists(resolved)) { + error = "Audio file not found: " + resolved.string(); + return false; + } + + try { + if (type == AudioCommandType::Background) { + audioService_->PlayBackground(resolved, loop); + } else { + audioService_->PlayEffect(resolved, loop); + } + } catch (const std::exception& ex) { + error = ex.what(); + return false; + } + + if (logger_) { + logger_->Debug("Queued audio command: " + resolved.string()); + } + + return true; } } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/audio_command_service.hpp b/src/services/impl/audio_command_service.hpp index 53273d5..61af8a0 100644 --- a/src/services/impl/audio_command_service.hpp +++ b/src/services/impl/audio_command_service.hpp @@ -1,7 +1,9 @@ #pragma once #include "../interfaces/i_audio_command_service.hpp" -#include "../interfaces/i_script_engine_service.hpp" +#include "../interfaces/i_audio_service.hpp" +#include "../interfaces/i_config_service.hpp" +#include "../interfaces/i_logger.hpp" #include namespace sdl3cpp::services::impl { @@ -11,15 +13,19 @@ namespace sdl3cpp::services::impl { */ class AudioCommandService : public IAudioCommandService { public: - explicit AudioCommandService(std::shared_ptr engineService); + AudioCommandService(std::shared_ptr configService, + std::shared_ptr audioService, + std::shared_ptr logger); - bool QueueAudioCommand(script::AudioManager::AudioCommandType type, + bool QueueAudioCommand(AudioCommandType type, const std::string& path, bool loop, std::string& error) override; private: - std::shared_ptr engineService_; + std::shared_ptr configService_; + std::shared_ptr audioService_; + std::shared_ptr logger_; }; } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/lua_script_service.cpp b/src/services/impl/lua_script_service.cpp index 13bd6be..36d19f2 100644 --- a/src/services/impl/lua_script_service.cpp +++ b/src/services/impl/lua_script_service.cpp @@ -110,11 +110,6 @@ script::PhysicsBridge& LuaScriptService::GetPhysicsBridge() { return engineService_->GetEngine().GetPhysicsBridge(); } -void LuaScriptService::SetAudioPlayer(app::AudioPlayer* audioPlayer) { - // Stub - audio functionality now handled through services - logger_->Trace("LuaScriptService::SetAudioPlayer: Stub implementation - using services now"); -} - std::filesystem::path LuaScriptService::GetScriptDirectory() const { if (!engineService_ || !engineService_->IsInitialized()) { return {}; diff --git a/src/services/impl/lua_script_service.hpp b/src/services/impl/lua_script_service.hpp index d613ffb..a1ea194 100644 --- a/src/services/impl/lua_script_service.hpp +++ b/src/services/impl/lua_script_service.hpp @@ -39,8 +39,6 @@ public: script::PhysicsBridge& GetPhysicsBridge() override; - void SetAudioPlayer(app::AudioPlayer* audioPlayer) override; - std::filesystem::path GetScriptDirectory() const override; std::string GetLuaError() override; diff --git a/src/services/impl/mesh_service.cpp b/src/services/impl/mesh_service.cpp index a9ecc07..d5ab1d8 100644 --- a/src/services/impl/mesh_service.cpp +++ b/src/services/impl/mesh_service.cpp @@ -1,25 +1,145 @@ #include "mesh_service.hpp" #include -#include "../../script/mesh_loader.hpp" +#include +#include +#include +#include +#include +#include +#include namespace sdl3cpp::services::impl { -MeshService::MeshService(std::shared_ptr engineService) - : engineService_(std::move(engineService)) { +MeshService::MeshService(std::shared_ptr configService) + : configService_(std::move(configService)) { } bool MeshService::LoadFromFile(const std::string& requestedPath, script::MeshPayload& outPayload, std::string& outError) { - return script::MeshLoader::LoadFromFile(engineService_->GetScriptDirectory(), - requestedPath, - outPayload, - outError); + if (!configService_) { + outError = "Config service not available"; + return false; + } + + std::filesystem::path resolved(requestedPath); + if (!resolved.is_absolute()) { + resolved = configService_->GetScriptPath().parent_path() / resolved; + } + + std::error_code ec; + resolved = std::filesystem::weakly_canonical(resolved, ec); + if (ec) { + outError = "Failed to resolve mesh path: " + ec.message(); + return false; + } + + if (!std::filesystem::exists(resolved)) { + outError = "Mesh file not found: " + resolved.string(); + return false; + } + + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile( + resolved.string(), + aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_PreTransformVertices); + + if (!scene) { + outError = importer.GetErrorString() ? importer.GetErrorString() : "Assimp failed to load mesh"; + return false; + } + + if (scene->mNumMeshes == 0) { + outError = "Scene contains no meshes"; + return false; + } + + const aiMesh* mesh = scene->mMeshes[0]; + if (!mesh->mNumVertices) { + outError = "Mesh contains no vertices"; + return false; + } + + outPayload.positions.clear(); + outPayload.colors.clear(); + outPayload.indices.clear(); + outPayload.positions.reserve(mesh->mNumVertices); + outPayload.colors.reserve(mesh->mNumVertices); + outPayload.indices.reserve(mesh->mNumFaces * 3); + + aiColor3D defaultColor(0.6f, 0.8f, 1.0f); + aiColor3D materialColor = defaultColor; + + if (mesh->mMaterialIndex < scene->mNumMaterials) { + const aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + aiColor4D diffuse; + if (material && material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse) == AI_SUCCESS) { + materialColor = aiColor3D(diffuse.r, diffuse.g, diffuse.b); + } + } + + for (unsigned i = 0; i < mesh->mNumVertices; ++i) { + const aiVector3D& vertex = mesh->mVertices[i]; + outPayload.positions.push_back({vertex.x, vertex.y, vertex.z}); + + aiColor3D color = materialColor; + if (mesh->HasVertexColors(0) && mesh->mColors[0]) { + const aiColor4D& vertexColor = mesh->mColors[0][i]; + color = aiColor3D(vertexColor.r, vertexColor.g, vertexColor.b); + } + outPayload.colors.push_back({color.r, color.g, color.b}); + } + + for (unsigned faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) { + const aiFace& face = mesh->mFaces[faceIndex]; + if (face.mNumIndices != 3) { + continue; + } + outPayload.indices.push_back(face.mIndices[0]); + outPayload.indices.push_back(face.mIndices[1]); + outPayload.indices.push_back(face.mIndices[2]); + } + + if (outPayload.indices.empty()) { + outError = "Mesh contains no triangle faces"; + return false; + } + + return true; } void MeshService::PushMeshToLua(lua_State* L, const script::MeshPayload& payload) { - script::MeshLoader::PushMeshToLua(L, payload); + lua_newtable(L); + + lua_newtable(L); + for (size_t vertexIndex = 0; vertexIndex < payload.positions.size(); ++vertexIndex) { + lua_newtable(L); + + lua_newtable(L); + for (int component = 0; component < 3; ++component) { + lua_pushnumber(L, payload.positions[vertexIndex][component]); + lua_rawseti(L, -2, component + 1); + } + lua_setfield(L, -2, "position"); + + lua_newtable(L); + for (int component = 0; component < 3; ++component) { + lua_pushnumber(L, payload.colors[vertexIndex][component]); + lua_rawseti(L, -2, component + 1); + } + lua_setfield(L, -2, "color"); + + lua_rawseti(L, -2, static_cast(vertexIndex + 1)); + } + lua_setfield(L, -2, "vertices"); + + lua_newtable(L); + for (size_t index = 0; index < payload.indices.size(); ++index) { + lua_pushinteger(L, static_cast(payload.indices[index]) + 1); + lua_rawseti(L, -2, static_cast(index + 1)); + } + lua_setfield(L, -2, "indices"); } } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/mesh_service.hpp b/src/services/impl/mesh_service.hpp index 11454c9..10ee895 100644 --- a/src/services/impl/mesh_service.hpp +++ b/src/services/impl/mesh_service.hpp @@ -1,7 +1,7 @@ #pragma once #include "../interfaces/i_mesh_service.hpp" -#include "../interfaces/i_script_engine_service.hpp" +#include "../interfaces/i_config_service.hpp" #include namespace sdl3cpp::services::impl { @@ -11,7 +11,7 @@ namespace sdl3cpp::services::impl { */ class MeshService : public IMeshService { public: - explicit MeshService(std::shared_ptr engineService); + explicit MeshService(std::shared_ptr configService); bool LoadFromFile(const std::string& requestedPath, script::MeshPayload& outPayload, @@ -19,7 +19,7 @@ public: void PushMeshToLua(lua_State* L, const script::MeshPayload& payload) override; private: - std::shared_ptr engineService_; + std::shared_ptr configService_; }; } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/physics_bridge_service.cpp b/src/services/impl/physics_bridge_service.cpp index e2bb416..8dc4272 100644 --- a/src/services/impl/physics_bridge_service.cpp +++ b/src/services/impl/physics_bridge_service.cpp @@ -3,8 +3,9 @@ namespace sdl3cpp::services::impl { -PhysicsBridgeService::PhysicsBridgeService(std::shared_ptr engineService) - : engineService_(std::move(engineService)) { +PhysicsBridgeService::PhysicsBridgeService(std::shared_ptr logger) + : logger_(std::move(logger)), + bridge_(std::make_unique()) { } bool PhysicsBridgeService::AddBoxRigidBody(const std::string& name, @@ -12,17 +13,28 @@ bool PhysicsBridgeService::AddBoxRigidBody(const std::string& name, float mass, const btTransform& transform, std::string& error) { - return engineService_->GetEngine().GetPhysicsBridge().addBoxRigidBody(name, halfExtents, mass, transform, error); + if (!bridge_) { + error = "Physics bridge not initialized"; + return false; + } + return bridge_->addBoxRigidBody(name, halfExtents, mass, transform, error); } int PhysicsBridgeService::StepSimulation(float deltaTime) { - return engineService_->GetEngine().GetPhysicsBridge().stepSimulation(deltaTime); + if (!bridge_) { + return 0; + } + return bridge_->stepSimulation(deltaTime); } bool PhysicsBridgeService::GetRigidBodyTransform(const std::string& name, btTransform& outTransform, std::string& error) const { - return engineService_->GetEngine().GetPhysicsBridge().getRigidBodyTransform(name, outTransform, error); + if (!bridge_) { + error = "Physics bridge not initialized"; + return false; + } + return bridge_->getRigidBodyTransform(name, outTransform, error); } } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/physics_bridge_service.hpp b/src/services/impl/physics_bridge_service.hpp index 9aec403..175c51a 100644 --- a/src/services/impl/physics_bridge_service.hpp +++ b/src/services/impl/physics_bridge_service.hpp @@ -1,7 +1,8 @@ #pragma once #include "../interfaces/i_physics_bridge_service.hpp" -#include "../interfaces/i_script_engine_service.hpp" +#include "../interfaces/i_logger.hpp" +#include "../../script/physics_bridge.hpp" #include namespace sdl3cpp::services::impl { @@ -11,7 +12,7 @@ namespace sdl3cpp::services::impl { */ class PhysicsBridgeService : public IPhysicsBridgeService { public: - explicit PhysicsBridgeService(std::shared_ptr engineService); + explicit PhysicsBridgeService(std::shared_ptr logger); bool AddBoxRigidBody(const std::string& name, const btVector3& halfExtents, @@ -24,7 +25,8 @@ public: std::string& error) const override; private: - std::shared_ptr engineService_; + std::shared_ptr logger_; + std::unique_ptr bridge_; }; } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/script_engine_service.cpp b/src/services/impl/script_engine_service.cpp index d824df5..649fc09 100644 --- a/src/services/impl/script_engine_service.cpp +++ b/src/services/impl/script_engine_service.cpp @@ -1,5 +1,6 @@ #include "script_engine_service.hpp" +#include "../../script/lua_bindings.hpp" #include "../../script/script_engine.hpp" #include #include @@ -8,8 +9,14 @@ namespace sdl3cpp::services::impl { ScriptEngineService::ScriptEngineService(const std::filesystem::path& scriptPath, std::shared_ptr logger, + std::shared_ptr meshService, + std::shared_ptr audioCommandService, + std::shared_ptr physicsBridgeService, bool debugEnabled) : logger_(std::move(logger)), + meshService_(std::move(meshService)), + audioCommandService_(std::move(audioCommandService)), + physicsBridgeService_(std::move(physicsBridgeService)), scriptPath_(scriptPath), debugEnabled_(debugEnabled) { } @@ -26,7 +33,12 @@ void ScriptEngineService::Initialize() { } logger_->TraceFunction(__func__); - engine_ = std::make_unique(scriptPath_, debugEnabled_); + bindingContext_ = std::make_shared(); + bindingContext_->meshService = meshService_; + bindingContext_->audioCommandService = audioCommandService_; + bindingContext_->physicsBridgeService = physicsBridgeService_; + + engine_ = std::make_unique(scriptPath_, bindingContext_.get(), debugEnabled_); initialized_ = true; logger_->Info("Script engine service initialized"); diff --git a/src/services/impl/script_engine_service.hpp b/src/services/impl/script_engine_service.hpp index fd902fb..758583d 100644 --- a/src/services/impl/script_engine_service.hpp +++ b/src/services/impl/script_engine_service.hpp @@ -1,11 +1,18 @@ #pragma once #include "../interfaces/i_script_engine_service.hpp" +#include "../interfaces/i_audio_command_service.hpp" +#include "../interfaces/i_mesh_service.hpp" +#include "../interfaces/i_physics_bridge_service.hpp" #include "../interfaces/i_logger.hpp" #include "../../di/lifecycle.hpp" #include #include +namespace sdl3cpp::script { +struct LuaBindingContext; +} + namespace sdl3cpp::services::impl { /** @@ -17,6 +24,9 @@ class ScriptEngineService : public IScriptEngineService, public: ScriptEngineService(const std::filesystem::path& scriptPath, std::shared_ptr logger, + std::shared_ptr meshService, + std::shared_ptr audioCommandService, + std::shared_ptr physicsBridgeService, bool debugEnabled = false); ~ScriptEngineService() override; @@ -31,10 +41,14 @@ public: private: std::shared_ptr logger_; + std::shared_ptr meshService_; + std::shared_ptr audioCommandService_; + std::shared_ptr physicsBridgeService_; std::filesystem::path scriptPath_; bool debugEnabled_ = false; bool initialized_ = false; std::unique_ptr engine_; + std::shared_ptr bindingContext_; }; } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/sdl_input_service.cpp b/src/services/impl/sdl_input_service.cpp index daea4b5..d65fe7c 100644 --- a/src/services/impl/sdl_input_service.cpp +++ b/src/services/impl/sdl_input_service.cpp @@ -1,5 +1,4 @@ #include "sdl_input_service.hpp" -#include "../interfaces/i_script_service.hpp" namespace sdl3cpp::services::impl { @@ -174,13 +173,13 @@ void SdlInputService::OnTextInput(const events::Event& event) { state_.textInput += textEvent.text; } -void SdlInputService::SetScriptService(IScriptService* scriptService) { - scriptService_ = scriptService; +void SdlInputService::SetGuiScriptService(IGuiScriptService* guiScriptService) { + guiScriptService_ = guiScriptService; } void SdlInputService::UpdateGuiInput() { - if (scriptService_) { - scriptService_->UpdateGuiInput(guiInputSnapshot_); + if (guiScriptService_) { + guiScriptService_->UpdateGuiInput(guiInputSnapshot_); } } diff --git a/src/services/impl/sdl_input_service.hpp b/src/services/impl/sdl_input_service.hpp index 94c7da4..f1a2218 100644 --- a/src/services/impl/sdl_input_service.hpp +++ b/src/services/impl/sdl_input_service.hpp @@ -1,6 +1,7 @@ #pragma once #include "../interfaces/i_input_service.hpp" +#include "../interfaces/i_gui_script_service.hpp" #include "../interfaces/i_logger.hpp" #include "../../events/event_bus.hpp" #include @@ -31,7 +32,7 @@ public: bool IsKeyPressed(SDL_Keycode key) const override; bool IsMouseButtonPressed(uint8_t button) const override; std::pair GetMousePosition() const override; - void SetScriptService(IScriptService* scriptService) override; + void SetGuiScriptService(IGuiScriptService* guiScriptService) override; void UpdateGuiInput() override; private: @@ -39,7 +40,7 @@ private: std::shared_ptr logger_; InputState state_; script::GuiInputSnapshot guiInputSnapshot_; - IScriptService* scriptService_ = nullptr; + IGuiScriptService* guiScriptService_ = nullptr; // Event bus listeners void OnKeyPressed(const events::Event& event); diff --git a/src/services/interfaces/i_audio_command_service.hpp b/src/services/interfaces/i_audio_command_service.hpp index 96fc45b..4061bc7 100644 --- a/src/services/interfaces/i_audio_command_service.hpp +++ b/src/services/interfaces/i_audio_command_service.hpp @@ -1,10 +1,17 @@ #pragma once -#include "../../script/audio_manager.hpp" #include namespace sdl3cpp::services { +/** + * @brief Audio command type for script bindings. + */ +enum class AudioCommandType { + Background, + Effect +}; + /** * @brief Script-facing audio command service interface. */ @@ -12,7 +19,7 @@ class IAudioCommandService { public: virtual ~IAudioCommandService() = default; - virtual bool QueueAudioCommand(script::AudioManager::AudioCommandType type, + virtual bool QueueAudioCommand(AudioCommandType type, const std::string& path, bool loop, std::string& error) = 0; diff --git a/src/services/interfaces/i_input_service.hpp b/src/services/interfaces/i_input_service.hpp index 2fc10c8..0464bef 100644 --- a/src/services/interfaces/i_input_service.hpp +++ b/src/services/interfaces/i_input_service.hpp @@ -8,7 +8,7 @@ namespace sdl3cpp::services { // Forward declaration -class IScriptService; +class IGuiScriptService; /** * @brief Input state snapshot for a single frame. @@ -83,14 +83,14 @@ public: virtual std::pair GetMousePosition() const = 0; /** - * @brief Set the script service for GUI input processing. + * @brief Set the GUI script service for GUI input processing. * * The input service will update GUI input state to the script service * when events are processed. * - * @param scriptService Pointer to the script service, or nullptr to disable + * @param guiScriptService Pointer to the GUI script service, or nullptr to disable */ - virtual void SetScriptService(IScriptService* scriptService) = 0; + virtual void SetGuiScriptService(IGuiScriptService* guiScriptService) = 0; /** * @brief Update GUI input state to the script service. diff --git a/src/services/interfaces/i_mesh_service.hpp b/src/services/interfaces/i_mesh_service.hpp index 01310b4..072eb25 100644 --- a/src/services/interfaces/i_mesh_service.hpp +++ b/src/services/interfaces/i_mesh_service.hpp @@ -1,8 +1,10 @@ #pragma once -#include "../../script/mesh_loader.hpp" +#include "../../script/mesh_payload.hpp" #include +struct lua_State; + namespace sdl3cpp::services { /** diff --git a/src/services/interfaces/i_script_service.hpp b/src/services/interfaces/i_script_service.hpp index dcc50ff..0d73dea 100644 --- a/src/services/interfaces/i_script_service.hpp +++ b/src/services/interfaces/i_script_service.hpp @@ -10,10 +10,6 @@ #include #include -namespace sdl3cpp::app { -class AudioPlayer; -} - namespace sdl3cpp::services { /** @@ -41,9 +37,6 @@ public: // Physics bridge access virtual script::PhysicsBridge& GetPhysicsBridge() = 0; - // Audio integration - virtual void SetAudioPlayer(app::AudioPlayer* audioPlayer) = 0; - // Utility virtual std::filesystem::path GetScriptDirectory() const = 0; virtual std::string GetLuaError() = 0;