ROADMAP.md

This commit is contained in:
2026-01-09 16:55:25 +00:00
parent 47c357f245
commit dda0e11682
18 changed files with 136 additions and 22 deletions

View File

@@ -7,6 +7,9 @@
"window_width": 1024,
"window_height": 768,
"lua_script": "scripts/gui_demo.lua",
"runtime": {
"scene_source": "lua"
},
"scripts_directory": "scripts",
"project_root": "../",
"shaders_directory": "shaders",

View File

@@ -7,6 +7,9 @@
"window_width": 1280,
"window_height": 720,
"lua_script": "scripts/quake3_arena.lua",
"runtime": {
"scene_source": "lua"
},
"scripts_directory": "scripts",
"project_root": "../",
"shaders_directory": "shaders",

View File

@@ -37,6 +37,16 @@
},
"additionalProperties": true
},
"runtime": {
"type": "object",
"properties": {
"scene_source": {
"type": "string",
"enum": ["config", "lua"]
}
},
"additionalProperties": true
},
"paths": {
"type": "object",
"properties": {

View File

@@ -27,6 +27,9 @@
"entry": "scripts/cube_logic.lua",
"lua_debug": false
},
"runtime": {
"scene_source": "lua"
},
"paths": {
"project_root": "../",
"scripts": "scripts",

View File

@@ -26,6 +26,9 @@
"entry": "scripts/cube_logic.lua",
"lua_debug": false
},
"runtime": {
"scene_source": "lua"
},
"paths": {
"project_root": "../",
"scripts": "scripts",

View File

@@ -7,6 +7,9 @@
"window_width": 1024,
"window_height": 768,
"lua_script": "scripts/soundboard.lua",
"runtime": {
"scene_source": "lua"
},
"scripts_directory": "scripts",
"project_root": "../",
"shaders_directory": "shaders",

View File

@@ -7,6 +7,9 @@
"display_width": 960,
"display_height": 544,
"lua_script": "scripts/cube_logic.lua",
"runtime": {
"scene_source": "lua"
},
"scripts_directory": "scripts",
"project_root": "../",
"shaders_directory": "shaders",

View File

@@ -7,6 +7,9 @@
"display_width": 960,
"display_height": 544,
"lua_script": "scripts/gui_demo.lua",
"runtime": {
"scene_source": "lua"
},
"scripts_directory": "scripts",
"project_root": "../",
"shaders_directory": "shaders",

View File

@@ -7,6 +7,9 @@
"display_width": 960,
"display_height": 544,
"lua_script": "scripts/soundboard.lua",
"runtime": {
"scene_source": "lua"
},
"scripts_directory": "scripts",
"project_root": "../",
"shaders_directory": "shaders",

View File

@@ -340,6 +340,7 @@ void ServiceBasedApp::RegisterServices() {
// Render coordinator service
registry_.RegisterService<services::IRenderCoordinatorService, services::impl::RenderCoordinatorService>(
registry_.GetService<services::ILogger>(),
registry_.GetService<services::IConfigService>(),
registry_.GetService<services::IGraphicsService>(),
registry_.GetService<services::ISceneScriptService>(),
registry_.GetService<services::IShaderScriptService>(),

View File

@@ -26,6 +26,27 @@ constexpr const char* kConfigVersionKey = "configVersion";
constexpr const char* kExtendsKey = "extends";
constexpr const char* kDeleteKey = "@delete";
const char* SceneSourceName(SceneSource source) {
switch (source) {
case SceneSource::Config:
return "config";
case SceneSource::Lua:
return "lua";
default:
return "config";
}
}
SceneSource ParseSceneSource(const std::string& value, const std::string& jsonPath) {
if (value == "config") {
return SceneSource::Config;
}
if (value == "lua") {
return SceneSource::Lua;
}
throw std::runtime_error("JSON member '" + jsonPath + "' must be 'config' or 'lua'");
}
std::filesystem::path NormalizeConfigPath(const std::filesystem::path& path) {
std::error_code ec;
auto canonicalPath = std::filesystem::weakly_canonical(path, ec);
@@ -463,6 +484,7 @@ RuntimeConfig JsonConfigService::LoadFromJson(std::shared_ptr<ILogger> logger,
const auto* windowSizeValue = windowValue
? getObjectMember(*windowValue, "size", "window.size")
: nullptr;
const auto* runtimeValue = getObjectMember(document, "runtime", "runtime");
const auto* inputValue = getObjectMember(document, "input", "input");
const auto* inputBindingsValue = inputValue
? getObjectMember(*inputValue, "bindings", "input.bindings")
@@ -528,6 +550,14 @@ RuntimeConfig JsonConfigService::LoadFromJson(std::shared_ptr<ILogger> logger,
}
config.scriptPath = scriptPath;
if (runtimeValue && runtimeValue->HasMember("scene_source")) {
const auto& value = (*runtimeValue)["scene_source"];
if (!value.IsString()) {
throw std::runtime_error("JSON member 'runtime.scene_source' must be a string");
}
config.sceneSource = ParseSceneSource(value.GetString(), "runtime.scene_source");
}
auto parseDimension = [&](const char* name, uint32_t defaultValue) -> uint32_t {
if (!document.HasMember(name)) {
return defaultValue;
@@ -1176,6 +1206,10 @@ std::string JsonConfigService::BuildConfigJson(const RuntimeConfig& config,
scriptsObject.AddMember("lua_debug", config.luaDebug, allocator);
document.AddMember("scripts", scriptsObject, allocator);
rapidjson::Value runtimeObject(rapidjson::kObjectType);
addStringMember(runtimeObject, "scene_source", SceneSourceName(config.sceneSource));
document.AddMember("runtime", runtimeObject, allocator);
rapidjson::Value windowObject(rapidjson::kObjectType);
addStringMember(windowObject, "title", config.windowTitle);
rapidjson::Value sizeObject(rapidjson::kObjectType);

View File

@@ -86,6 +86,12 @@ public:
}
return config_.windowTitle;
}
SceneSource GetSceneSource() const override {
if (logger_) {
logger_->Trace("JsonConfigService", "GetSceneSource");
}
return config_.sceneSource;
}
const InputBindings& GetInputBindings() const override {
if (logger_) {
logger_->Trace("JsonConfigService", "GetInputBindings");

View File

@@ -3,6 +3,7 @@
namespace sdl3cpp::services::impl {
RenderCoordinatorService::RenderCoordinatorService(std::shared_ptr<ILogger> logger,
std::shared_ptr<IConfigService> configService,
std::shared_ptr<IGraphicsService> graphicsService,
std::shared_ptr<ISceneScriptService> sceneScriptService,
std::shared_ptr<IShaderScriptService> shaderScriptService,
@@ -10,6 +11,7 @@ RenderCoordinatorService::RenderCoordinatorService(std::shared_ptr<ILogger> logg
std::shared_ptr<IGuiService> guiService,
std::shared_ptr<ISceneService> sceneService)
: logger_(std::move(logger)),
configService_(std::move(configService)),
graphicsService_(std::move(graphicsService)),
sceneScriptService_(std::move(sceneScriptService)),
shaderScriptService_(std::move(shaderScriptService)),
@@ -18,7 +20,8 @@ RenderCoordinatorService::RenderCoordinatorService(std::shared_ptr<ILogger> logg
sceneService_(std::move(sceneService)) {
if (logger_) {
logger_->Trace("RenderCoordinatorService", "RenderCoordinatorService",
"graphicsService=" + std::string(graphicsService_ ? "set" : "null") +
"configService=" + std::string(configService_ ? "set" : "null") +
", graphicsService=" + std::string(graphicsService_ ? "set" : "null") +
", sceneScriptService=" + std::string(sceneScriptService_ ? "set" : "null") +
", shaderScriptService=" + std::string(shaderScriptService_ ? "set" : "null") +
", guiScriptService=" + std::string(guiScriptService_ ? "set" : "null") +
@@ -41,37 +44,49 @@ void RenderCoordinatorService::RenderFrame(float time) {
return;
}
const bool useLuaScene = !configService_ || configService_->GetSceneSource() == SceneSource::Lua;
if (!useLuaScene && !configFirstLogged_) {
if (logger_) {
logger_->Warn("RenderCoordinatorService::RenderFrame: config-first scene source selected; Lua scene path disabled");
}
configFirstLogged_ = true;
}
if (!shadersLoaded_) {
if (!shaderScriptService_) {
if (!useLuaScene) {
shadersLoaded_ = true;
} else if (!shaderScriptService_) {
if (logger_) {
logger_->Error("RenderCoordinatorService::RenderFrame: Shader script service not available");
}
return;
}
if (logger_) {
logger_->Trace("RenderCoordinatorService", "RenderFrame",
"Priming bgfx with a dummy frame before shader load");
}
if (!graphicsService_->BeginFrame()) {
if (!shadersLoaded_) {
if (logger_) {
logger_->Warn("RenderCoordinatorService::RenderFrame: Swapchain out of date during shader pre-frame");
logger_->Trace("RenderCoordinatorService", "RenderFrame",
"Priming bgfx with a dummy frame before shader load");
}
if (!graphicsService_->BeginFrame()) {
if (logger_) {
logger_->Warn("RenderCoordinatorService::RenderFrame: Swapchain out of date during shader pre-frame");
}
graphicsService_->RecreateSwapchain();
return;
}
if (!graphicsService_->EndFrame()) {
if (logger_) {
logger_->Warn("RenderCoordinatorService::RenderFrame: Swapchain out of date during shader pre-frame");
}
graphicsService_->RecreateSwapchain();
return;
}
graphicsService_->RecreateSwapchain();
return;
}
if (!graphicsService_->EndFrame()) {
if (logger_) {
logger_->Warn("RenderCoordinatorService::RenderFrame: Swapchain out of date during shader pre-frame");
logger_->Trace("RenderCoordinatorService", "RenderFrame", "Loading shaders from Lua");
}
graphicsService_->RecreateSwapchain();
return;
auto shaders = shaderScriptService_->LoadShaderPathsMap();
graphicsService_->LoadShaders(shaders);
shadersLoaded_ = true;
}
if (logger_) {
logger_->Trace("RenderCoordinatorService", "RenderFrame", "Loading shaders from Lua");
}
auto shaders = shaderScriptService_->LoadShaderPathsMap();
graphicsService_->LoadShaders(shaders);
shadersLoaded_ = true;
}
if (!graphicsService_->BeginFrame()) {
@@ -88,7 +103,7 @@ void RenderCoordinatorService::RenderFrame(float time) {
guiService_->PrepareFrame(guiCommands, extent.first, extent.second);
}
if (sceneScriptService_ && sceneService_) {
if (useLuaScene && sceneScriptService_ && sceneService_) {
auto sceneObjects = sceneScriptService_->LoadSceneObjects();
sceneService_->LoadScene(sceneObjects);

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../interfaces/i_render_coordinator_service.hpp"
#include "../interfaces/i_config_service.hpp"
#include "../interfaces/i_graphics_service.hpp"
#include "../interfaces/i_gui_script_service.hpp"
#include "../interfaces/i_gui_service.hpp"
@@ -15,6 +16,7 @@ namespace sdl3cpp::services::impl {
class RenderCoordinatorService : public IRenderCoordinatorService {
public:
RenderCoordinatorService(std::shared_ptr<ILogger> logger,
std::shared_ptr<IConfigService> configService,
std::shared_ptr<IGraphicsService> graphicsService,
std::shared_ptr<ISceneScriptService> sceneScriptService,
std::shared_ptr<IShaderScriptService> shaderScriptService,
@@ -27,6 +29,7 @@ public:
private:
std::shared_ptr<ILogger> logger_;
std::shared_ptr<IConfigService> configService_;
std::shared_ptr<IGraphicsService> graphicsService_;
std::shared_ptr<ISceneScriptService> sceneScriptService_;
std::shared_ptr<IShaderScriptService> shaderScriptService_;
@@ -37,6 +40,7 @@ private:
size_t lastIndexCount_ = 0;
bool shadersLoaded_ = false;
bool geometryUploaded_ = false;
bool configFirstLogged_ = false;
};
} // namespace sdl3cpp::services::impl

View File

@@ -86,6 +86,11 @@ struct BgfxConfig {
std::string renderer = "vulkan";
};
enum class SceneSource {
Config,
Lua
};
struct MaterialXConfig {
bool enabled = false;
std::filesystem::path documentPath;
@@ -152,6 +157,7 @@ struct RuntimeConfig {
uint32_t height = 768;
std::filesystem::path scriptPath;
bool luaDebug = false;
SceneSource sceneSource = SceneSource::Config;
std::string windowTitle = "SDL3 Bgfx Demo";
MouseGrabConfig mouseGrab{};
InputBindings inputBindings{};

View File

@@ -48,6 +48,11 @@ public:
*/
virtual std::string GetWindowTitle() const = 0;
/**
* @brief Get the configured scene source.
* @return Scene source enum
*/
virtual SceneSource GetSceneSource() const = 0;
/**
* @brief Get configured input bindings.

View File

@@ -140,6 +140,9 @@ public:
std::filesystem::path GetScriptPath() const override { return {}; }
bool IsLuaDebugEnabled() const override { return false; }
std::string GetWindowTitle() const override { return ""; }
sdl3cpp::services::SceneSource GetSceneSource() const override {
return sdl3cpp::services::SceneSource::Lua;
}
const sdl3cpp::services::InputBindings& GetInputBindings() const override { return inputBindings_; }
const sdl3cpp::services::MouseGrabConfig& GetMouseGrabConfig() const override { return mouseGrabConfig_; }
const sdl3cpp::services::BgfxConfig& GetBgfxConfig() const override { return bgfxConfig_; }

View File

@@ -103,6 +103,9 @@ public:
std::filesystem::path GetScriptPath() const override { return {}; }
bool IsLuaDebugEnabled() const override { return false; }
std::string GetWindowTitle() const override { return ""; }
sdl3cpp::services::SceneSource GetSceneSource() const override {
return sdl3cpp::services::SceneSource::Lua;
}
const sdl3cpp::services::InputBindings& GetInputBindings() const override { return inputBindings_; }
const sdl3cpp::services::MouseGrabConfig& GetMouseGrabConfig() const override { return mouseGrabConfig_; }
const sdl3cpp::services::BgfxConfig& GetBgfxConfig() const override { return bgfxConfig_; }
@@ -150,6 +153,9 @@ public:
std::filesystem::path GetScriptPath() const override { return scriptPath_; }
bool IsLuaDebugEnabled() const override { return false; }
std::string GetWindowTitle() const override { return ""; }
sdl3cpp::services::SceneSource GetSceneSource() const override {
return sdl3cpp::services::SceneSource::Lua;
}
const sdl3cpp::services::InputBindings& GetInputBindings() const override { return inputBindings_; }
const sdl3cpp::services::MouseGrabConfig& GetMouseGrabConfig() const override { return mouseGrabConfig_; }
const sdl3cpp::services::BgfxConfig& GetBgfxConfig() const override { return bgfxConfig_; }