Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -108,23 +108,20 @@ "type": "boolean", "label": "Prefer GLSL", "tooltip": "Use OpenGL 2.0 shaders (recommended).", - "config": "preferglsl", - "function": "Renderer_SetPreferGLSLEnabled" + "config": "preferglsl" }, { "type": "boolean", "label": "Fog", "tooltip": "Enable Fog.", "dependencies": ["preferglsl"], - "config": "fog", - "function": "Renderer_SetFogEnabled" + "config": "fog" }, { "type": "boolean", "label": "Post Processing", "tooltip": "Use screen-space postprocessing filters (HDR, Bloom, DOF, etc).", - "config": "postproc", - "function": "Renderer_SetPostProcEnabled" + "config": "postproc" }, { "type": "slider", @@ -138,8 +135,7 @@ "type": "boolean", "label": "Shadows", "tooltip": "Enable shadows.", - "config": "shadows", - "function": "Renderer_SetShadowsEnabled" + "config": "shadows" }, { "type": "dropdown", @@ -147,7 +143,6 @@ "tooltip": "Shadow map resolution. High values can crash the game when using a graphics card with low memory!", "dependencies": ["shadows"], "config": "shadowquality", - "function": "Renderer_RecreateShadowMap", "list": [ { "value": -2, "label": "Very Low" }, { "value": -1, "label": "Low" }, @@ -161,83 +156,72 @@ "label": "Shadow Filtering", "tooltip": "Smooth shadows.", "dependencies": ["shadows"], - "config": "shadowpcf", - "function": "Renderer_SetShadowPCFEnabled" + "config": "shadowpcf" }, { "type": "boolean", "label": "Unit Silhouettes", "tooltip": "Show outlines of units behind buildings.", - "config": "silhouettes", - "function": "Renderer_SetSilhouettesEnabled" + "config": "silhouettes" }, { "type": "boolean", "label": "Particles", "tooltip": "Enable particles.", - "config": "particles", - "function": "Renderer_SetParticlesEnabled" + "config": "particles" }, { "type": "boolean", "label": "Water Effects", "tooltip": "When OFF, use the lowest settings possible to render water. This makes other settings irrelevant.", - "config": "watereffects", - "function": "Renderer_SetWaterEffectsEnabled" + "config": "watereffects" }, { "type": "boolean", "label": "HQ Water Effects", "tooltip": "Use higher-quality effects for water, rendering coastal waves, shore foam, and ships trails.", "dependencies": ["watereffects"], - "config": "waterfancyeffects", - "function": "Renderer_SetWaterFancyEffectsEnabled" + "config": "waterfancyeffects" }, { "type": "boolean", "label": "Real Water Depth", "tooltip": "Use actual water depth in rendering calculations.", "dependencies": ["watereffects"], - "config": "waterrealdepth", - "function": "Renderer_SetWaterRealDepthEnabled" + "config": "waterrealdepth" }, { "type": "boolean", "label": "Water Reflections", "tooltip": "Allow water to reflect a mirror image.", "dependencies": ["watereffects"], - "config": "waterreflection", - "function": "Renderer_SetWaterReflectionEnabled" + "config": "waterreflection" }, { "type": "boolean", "label": "Water Refraction", "tooltip": "Use a real water refraction map and not transparency.", "dependencies": ["watereffects"], - "config": "waterrefraction", - "function": "Renderer_SetWaterRefractionEnabled" + "config": "waterrefraction" }, { "type": "boolean", "label": "Shadows on Water", "tooltip": "Cast shadows on water.", "dependencies": ["watereffects"], - "config": "shadowsonwater", - "function": "Renderer_SetWaterShadowsEnabled" + "config": "shadowsonwater" }, { "type": "boolean", "label": "Smooth LOS", "tooltip": "Lift darkness and fog-of-war smoothly.", - "config": "smoothlos", - "function": "Renderer_SetSmoothLOSEnabled" + "config": "smoothlos" }, { "type": "boolean", "label": "Show Sky", "tooltip": "Render Sky.", - "config": "showsky", - "function": "Renderer_SetShowSkyEnabled" + "config": "showsky" }, { "type": "boolean", Index: binaries/data/mods/public/gui/session/session.js =================================================================== --- binaries/data/mods/public/gui/session/session.js +++ binaries/data/mods/public/gui/session/session.js @@ -923,7 +923,7 @@ let isPlayingCinemaPath = GetSimState().cinemaPlaying && !g_Disconnected; Engine.GetGUIObjectByName("session").hidden = !g_ShowGUI || isPlayingCinemaPath; - Engine.Renderer_SetSilhouettesEnabled(!isPlayingCinemaPath && Engine.ConfigDB_GetValue("user", "silhouettes") == "true"); + Engine.ConfigDB_CreateValue("user", "silhouettes", !isPlayingCinemaPath && Engine.ConfigDB_GetValue("user", "silhouettes") == "true" ? "true" : "false"); } function updateGUIObjects() Index: source/ps/ConfigDB.h =================================================================== --- source/ps/ConfigDB.h +++ source/ps/ConfigDB.h @@ -161,8 +161,16 @@ bool WriteValueToFile(EConfigNamespace ns, const CStr& name, const CStr& value); + /** + * Register a simple lambda that will be called anytime the value changes in any namespace + * This is simple on purpose, the hook is responsible for checking if it should do something. + * When RegisterHook is called, the hook is immediately triggered. + */ + void RegisterHook(const CStr& name, std::function hook); + private: static std::map m_Map[]; + static std::multimap> m_Hooks; static VfsPath m_ConfigFile[]; static bool m_HasChanges[]; }; Index: source/ps/ConfigDB.cpp =================================================================== --- source/ps/ConfigDB.cpp +++ source/ps/ConfigDB.cpp @@ -36,6 +36,8 @@ VfsPath CConfigDB::m_ConfigFile[CFG_LAST]; bool CConfigDB::m_HasChanges[CFG_LAST]; +std::multimap> CConfigDB::m_Hooks; + static std::recursive_mutex cfgdb_mutex; // These entries will not be printed to logfiles, so that logfiles can be shared without leaking personal or sensitive data @@ -202,6 +204,8 @@ it = m_Map[ns].insert(m_Map[ns].begin(), make_pair(name, CConfigValueSet(1))); it->second[0] = value; + + std::for_each(m_Hooks.lower_bound(name), m_Hooks.upper_bound(name), [](std::pair>& hook) { hook.second(); }); } void CConfigDB::SetValueBool(EConfigNamespace ns, const CStr& name, const bool value) @@ -219,6 +223,8 @@ if (it == m_Map[ns].end()) return; m_Map[ns].erase(it); + + std::for_each(m_Hooks.lower_bound(name), m_Hooks.upper_bound(name), [](std::pair>& hook) { hook.second(); }); } void CConfigDB::SetConfigFile(EConfigNamespace ns, const VfsPath& path) @@ -452,4 +458,10 @@ return ret; } +void CConfigDB::RegisterHook(const CStr& name, std::function hook) +{ + m_Hooks.insert({name, hook}); + hook(); +} + #undef CHECK_NS Index: source/renderer/RenderingOptions.cpp =================================================================== --- source/renderer/RenderingOptions.cpp +++ source/renderer/RenderingOptions.cpp @@ -23,6 +23,7 @@ #include "ps/ConfigDB.h" #include "ps/CStr.h" #include "renderer/Renderer.h" +#include "renderer/ShadowMap.h" SRenderingOptions g_RenderingOptions; @@ -82,35 +83,55 @@ void SRenderingOptions::ReadConfig() { - CFG_GET_VAL("shadows", m_Shadows); - CFG_GET_VAL("shadowpcf", m_ShadowPCF); +#define DEFAULT_HOOK(config, variable) g_ConfigDB.RegisterHook(config, [this]() { CFG_GET_VAL(config, variable); } ); - CFG_GET_VAL("preferglsl", m_PreferGLSL); - CFG_GET_VAL("postproc", m_PostProc); - CFG_GET_VAL("smoothlos", m_SmoothLOS); + g_ConfigDB.RegisterHook("shadowquality", []() { + g_Renderer.GetShadowMap().RecreateTexture(); + }); - CStr renderPath; - CFG_GET_VAL("renderpath", renderPath); - SetRenderPath(RenderPathEnum::FromString(renderPath)); + g_ConfigDB.RegisterHook("shadows", [this]() { + bool enabled; + CFG_GET_VAL("shadows", enabled); + SetShadows(enabled); + }); + g_ConfigDB.RegisterHook("shadowpcf", [this]() { + bool enabled; + CFG_GET_VAL("shadowpcf", enabled); + SetShadowPCF(enabled); + }); + DEFAULT_HOOK("postproc", m_PostProc); + DEFAULT_HOOK("smoothlos", m_SmoothLOS); - CFG_GET_VAL("watereffects", m_WaterEffects); - CFG_GET_VAL("waterfancyeffects", m_WaterFancyEffects); - CFG_GET_VAL("waterrealdepth", m_WaterRealDepth); - CFG_GET_VAL("waterrefraction", m_WaterRefraction); - CFG_GET_VAL("waterreflection", m_WaterReflection); - CFG_GET_VAL("watershadows", m_WaterShadows); + g_ConfigDB.RegisterHook("renderpath", [this]() { + CStr renderPath; + CFG_GET_VAL("renderpath", renderPath); + SetRenderPath(RenderPathEnum::FromString(renderPath)); + }); - CFG_GET_VAL("particles", m_Particles); - CFG_GET_VAL("fog", m_Fog); - CFG_GET_VAL("silhouettes", m_Silhouettes); - CFG_GET_VAL("showsky", m_ShowSky); + DEFAULT_HOOK("watereffects", m_WaterEffects); + DEFAULT_HOOK("waterfancyeffects", m_WaterFancyEffects); + DEFAULT_HOOK("waterrealdepth", m_WaterRealDepth); + DEFAULT_HOOK("waterrefraction", m_WaterRefraction); + DEFAULT_HOOK("waterreflection", m_WaterReflection); + DEFAULT_HOOK("watershadows", m_WaterShadows); - CFG_GET_VAL("novbo", m_NoVBO); + DEFAULT_HOOK("particles", m_Particles); + g_ConfigDB.RegisterHook("fog", [this]() { + bool enabled; + CFG_GET_VAL("fog", enabled); + SetFog(enabled); + }); + DEFAULT_HOOK("silhouettes", m_Silhouettes); + DEFAULT_HOOK("showsky", m_ShowSky); - CFG_GET_VAL("forcealphatest", m_ForceAlphaTest); - CFG_GET_VAL("gpuskinning", m_GPUSkinning); + DEFAULT_HOOK("novbo", m_NoVBO); - CFG_GET_VAL("renderactors", m_RenderActors); + DEFAULT_HOOK("forcealphatest", m_ForceAlphaTest); + DEFAULT_HOOK("gpuskinning", m_GPUSkinning); + + DEFAULT_HOOK("renderactors", m_RenderActors); + +#undef DEFAULT_HOOK } void SRenderingOptions::SetShadows(bool value) Index: source/renderer/scripting/JSInterface_Renderer.h =================================================================== --- source/renderer/scripting/JSInterface_Renderer.h +++ source/renderer/scripting/JSInterface_Renderer.h @@ -27,25 +27,8 @@ namespace JSI_Renderer { std::string GetRenderPath(ScriptInterface::CxPrivate* pCxPrivate); - void SetRenderPath(ScriptInterface::CxPrivate* pCxPrivate, const std::string& name); - void RecreateShadowMap(ScriptInterface::CxPrivate* pCxPrivate); bool TextureExists(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& filename); - DECLARE_BOOLEAN_SCRIPT_SETTING(Shadows); - DECLARE_BOOLEAN_SCRIPT_SETTING(ShadowPCF); - DECLARE_BOOLEAN_SCRIPT_SETTING(Particles); - DECLARE_BOOLEAN_SCRIPT_SETTING(PreferGLSL); - DECLARE_BOOLEAN_SCRIPT_SETTING(WaterEffects); - DECLARE_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects); - DECLARE_BOOLEAN_SCRIPT_SETTING(WaterRealDepth); - DECLARE_BOOLEAN_SCRIPT_SETTING(WaterReflection); - DECLARE_BOOLEAN_SCRIPT_SETTING(WaterRefraction); - DECLARE_BOOLEAN_SCRIPT_SETTING(WaterShadows); - DECLARE_BOOLEAN_SCRIPT_SETTING(Fog); - DECLARE_BOOLEAN_SCRIPT_SETTING(Silhouettes); - DECLARE_BOOLEAN_SCRIPT_SETTING(ShowSky); - DECLARE_BOOLEAN_SCRIPT_SETTING(SmoothLOS); - DECLARE_BOOLEAN_SCRIPT_SETTING(PostProc); DECLARE_BOOLEAN_SCRIPT_SETTING(DisplayFrustum); void RegisterScriptFunctions(const ScriptInterface& scriptInterface); Index: source/renderer/scripting/JSInterface_Renderer.cpp =================================================================== --- source/renderer/scripting/JSInterface_Renderer.cpp +++ source/renderer/scripting/JSInterface_Renderer.cpp @@ -36,21 +36,6 @@ g_RenderingOptions.Set##NAME(enabled); \ } -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Shadows); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(ShadowPCF); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Particles); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(PreferGLSL); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterEffects); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterRealDepth); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterReflection); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterRefraction); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(WaterShadows); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Fog); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(Silhouettes); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(ShowSky); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(SmoothLOS); -IMPLEMENT_BOOLEAN_SCRIPT_SETTING(PostProc); IMPLEMENT_BOOLEAN_SCRIPT_SETTING(DisplayFrustum); #undef IMPLEMENT_BOOLEAN_SCRIPT_SETTING @@ -60,16 +45,6 @@ return RenderPathEnum::ToString(g_RenderingOptions.GetRenderPath()); } -void JSI_Renderer::SetRenderPath(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& name) -{ - g_RenderingOptions.SetRenderPath(RenderPathEnum::FromString(name)); -} - -void JSI_Renderer::RecreateShadowMap(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) -{ - g_Renderer.GetShadowMap().RecreateTexture(); -} - bool JSI_Renderer::TextureExists(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& filename) { return g_Renderer.GetTextureManager().TextureExists(filename); @@ -82,24 +57,7 @@ void JSI_Renderer::RegisterScriptFunctions(const ScriptInterface& scriptInterface) { scriptInterface.RegisterFunction("Renderer_GetRenderPath"); - scriptInterface.RegisterFunction("Renderer_SetRenderPath"); - scriptInterface.RegisterFunction("Renderer_RecreateShadowMap"); scriptInterface.RegisterFunction("TextureExists"); - REGISTER_BOOLEAN_SCRIPT_SETTING(Shadows); - REGISTER_BOOLEAN_SCRIPT_SETTING(ShadowPCF); - REGISTER_BOOLEAN_SCRIPT_SETTING(Particles); - REGISTER_BOOLEAN_SCRIPT_SETTING(PreferGLSL); - REGISTER_BOOLEAN_SCRIPT_SETTING(WaterEffects); - REGISTER_BOOLEAN_SCRIPT_SETTING(WaterFancyEffects); - REGISTER_BOOLEAN_SCRIPT_SETTING(WaterRealDepth); - REGISTER_BOOLEAN_SCRIPT_SETTING(WaterReflection); - REGISTER_BOOLEAN_SCRIPT_SETTING(WaterRefraction); - REGISTER_BOOLEAN_SCRIPT_SETTING(WaterShadows); - REGISTER_BOOLEAN_SCRIPT_SETTING(Fog); - REGISTER_BOOLEAN_SCRIPT_SETTING(Silhouettes); - REGISTER_BOOLEAN_SCRIPT_SETTING(ShowSky); - REGISTER_BOOLEAN_SCRIPT_SETTING(SmoothLOS); - REGISTER_BOOLEAN_SCRIPT_SETTING(PostProc); REGISTER_BOOLEAN_SCRIPT_SETTING(DisplayFrustum); }