diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json index e2739a5..889fff9 100644 --- a/CMakeUserPresets.json +++ b/CMakeUserPresets.json @@ -4,7 +4,6 @@ "conan": {} }, "include": [ - "build/build/Release/generators/CMakePresets.json", - "build/Release/generators/CMakePresets.json" + "build/build/Release/generators/CMakePresets.json" ] } \ No newline at end of file diff --git a/config/gui_runtime.json b/config/gui_runtime.json index 8349e17..1840020 100644 --- a/config/gui_runtime.json +++ b/config/gui_runtime.json @@ -61,5 +61,6 @@ }, "gamepad_axis_action_threshold": 0.5 }, + "gui_opacity": 1.0, "config_file": "config/gui_runtime.json" } diff --git a/config/seed_runtime.json b/config/seed_runtime.json index a3159c6..6420af0 100644 --- a/config/seed_runtime.json +++ b/config/seed_runtime.json @@ -72,5 +72,6 @@ "pbr_roughness": 0.3, "pbr_metallic": 0.1 }, + "gui_opacity": 0.75, "config_file": "config/seed_runtime.json" } diff --git a/scripts/gui.lua b/scripts/gui.lua index cd58e3b..08d2904 100644 --- a/scripts/gui.lua +++ b/scripts/gui.lua @@ -125,6 +125,10 @@ Context.__index = Context function Context:new(options) options = options or {} local style = options.style or DEFAULT_STYLE + local opacity = 1.0 + if type(config) == "table" and type(config.gui_opacity) == "number" then + opacity = config.gui_opacity + end local instance = { commands = {}, input = nil, @@ -133,6 +137,7 @@ function Context:new(options) focusWidget = nil, nextFocus = nil, style = style, + opacity = opacity, mousePressed = false, mouseReleased = false, } @@ -184,15 +189,27 @@ function Context:markHot(widgetId, hovered) end end +function Context:applyOpacity(color) + if not color then + return color + end + local result = {color[1], color[2], color[3], color[4]} + if result[4] then + result[4] = result[4] * self.opacity + end + return result +end + function Context:pushRect(rect, params) params = params or {} + local color = params.color and self:applyOpacity(params.color) or params.color local command = { type = "rect", x = rect.x, y = rect.y, width = rect.width, height = rect.height, - color = params.color, + color = color, borderColor = params.borderColor, borderWidth = params.borderWidth or (params.borderColor and 1 or 0), radius = params.radius or self.style.radius, diff --git a/src/services/impl/json_config_service.cpp b/src/services/impl/json_config_service.cpp index 30fcca1..2df1aa5 100644 --- a/src/services/impl/json_config_service.cpp +++ b/src/services/impl/json_config_service.cpp @@ -361,6 +361,14 @@ RuntimeConfig JsonConfigService::LoadFromJson(std::shared_ptr logger, readFloat("pbr_metallic", config.atmospherics.pbrMetallic); } + if (document.HasMember("gui_opacity")) { + const auto& value = document["gui_opacity"]; + if (!value.IsNumber()) { + throw std::runtime_error("JSON member 'gui_opacity' must be a number"); + } + config.guiOpacity = static_cast(value.GetDouble()); + } + return config; } @@ -462,6 +470,8 @@ std::string JsonConfigService::BuildConfigJson(const RuntimeConfig& config, addStringMember("shaders_directory", "shaders"); } + document.AddMember("gui_opacity", config.guiOpacity, allocator); + rapidjson::Value extensionArray(rapidjson::kArrayType); for (const char* extension : kDeviceExtensions) { rapidjson::Value extensionValue(extension, allocator); diff --git a/src/services/impl/script_engine_service.cpp b/src/services/impl/script_engine_service.cpp index cfeb684..3bf479e 100644 --- a/src/services/impl/script_engine_service.cpp +++ b/src/services/impl/script_engine_service.cpp @@ -311,6 +311,7 @@ void ScriptEngineService::RegisterBindings(lua_State* L) { bind("window_get_relative_mouse_mode", &ScriptEngineService::WindowGetRelativeMouseMode); bind("window_set_cursor_visible", &ScriptEngineService::WindowSetCursorVisible); bind("window_is_cursor_visible", &ScriptEngineService::WindowIsCursorVisible); + bind("print", &ScriptEngineService::LuaPrint); } int ScriptEngineService::LoadMeshFromFile(lua_State* L) { @@ -794,4 +795,48 @@ int ScriptEngineService::GlmMatrixFromTransform(lua_State* L) { return lua::LuaGlmMatrixFromTransform(L); } +int ScriptEngineService::LuaPrint(lua_State* L) { + auto* context = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + auto logger = context ? context->logger : nullptr; + + int nargs = lua_gettop(L); + std::string message; + + for (int i = 1; i <= nargs; ++i) { + if (i > 1) { + message += "\t"; + } + + const char* str = nullptr; + if (lua_isstring(L, i)) { + str = lua_tostring(L, i); + } else if (lua_isnil(L, i)) { + str = "nil"; + } else if (lua_isboolean(L, i)) { + str = lua_toboolean(L, i) ? "true" : "false"; + } else if (lua_isnumber(L, i)) { + lua_pushvalue(L, i); + str = lua_tostring(L, -1); + lua_pop(L, 1); + } else { + lua_pushvalue(L, i); + str = lua_tostring(L, -1); + if (!str) { + str = lua_typename(L, lua_type(L, i)); + } + lua_pop(L, 1); + } + + if (str) { + message += str; + } + } + + if (logger) { + logger->Info("[Lua] " + message); + } + + return 0; +} + } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/script_engine_service.hpp b/src/services/impl/script_engine_service.hpp index 3ca09e0..771cc9d 100644 --- a/src/services/impl/script_engine_service.hpp +++ b/src/services/impl/script_engine_service.hpp @@ -86,6 +86,7 @@ private: static int WindowGetRelativeMouseMode(lua_State* L); static int WindowSetCursorVisible(lua_State* L); static int WindowIsCursorVisible(lua_State* L); + static int LuaPrint(lua_State* L); std::shared_ptr logger_; std::shared_ptr meshService_; diff --git a/src/services/interfaces/config_types.hpp b/src/services/interfaces/config_types.hpp index 51b663c..9bf9ff4 100644 --- a/src/services/interfaces/config_types.hpp +++ b/src/services/interfaces/config_types.hpp @@ -91,6 +91,7 @@ struct RuntimeConfig { MouseGrabConfig mouseGrab{}; InputBindings inputBindings{}; AtmosphericsConfig atmospherics{}; + float guiOpacity = 1.0f; }; } // namespace sdl3cpp::services