From 238b7f84d8a69aa34133e865c58ae8026f57b59f Mon Sep 17 00:00:00 2001 From: Yves Date: Sun, 29 Sep 2013 18:56:50 +0000 Subject: [PATCH] Changes the ConfigDB to expose global functions to scripts instead of properties and custom objects. Fixes #2172 Refs #1886 This was SVN commit r13914. --- .../gui/common/functions_utility_music.js | 4 +- .../data/mods/public/gui/session/input.js | 2 +- .../mods/public/gui/session/unit_commands.js | 2 +- source/gui/scripting/ScriptFunctions.cpp | 2 + source/ps/ConfigDB.cpp | 186 ------------------ source/ps/ConfigDB.h | 32 +-- source/ps/GameSetup/GameSetup.cpp | 2 - source/ps/scripting/JSInterface_ConfigDB.cpp | 111 +++++++++++ source/ps/scripting/JSInterface_ConfigDB.h | 36 ++++ 9 files changed, 155 insertions(+), 222 deletions(-) create mode 100644 source/ps/scripting/JSInterface_ConfigDB.cpp create mode 100644 source/ps/scripting/JSInterface_ConfigDB.h diff --git a/binaries/data/mods/public/gui/common/functions_utility_music.js b/binaries/data/mods/public/gui/common/functions_utility_music.js index d21eca7b6d..f9631d8d0d 100644 --- a/binaries/data/mods/public/gui/common/functions_utility_music.js +++ b/binaries/data/mods/public/gui/common/functions_utility_music.js @@ -118,7 +118,7 @@ function crossFade (outHandle, inHandle, fadeDuration) if (inHandle) { inHandle.play(); - fadeIn(inHandle, g_ConfigDB.system["sound.mastergain"], fadeDuration); + fadeIn(inHandle, Engine.ConfigDB_GetValue("user", "sound.mastergain"), fadeDuration); } return true; @@ -168,4 +168,4 @@ function crossFade (outHandle, inHandle, fadeDuration) //{ // var buttonSound = new Sound(BUTTON_SOUND); // buttonSound.play(); -//} \ No newline at end of file +//} diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js index 329e5cd3aa..301a808248 100644 --- a/binaries/data/mods/public/gui/session/input.js +++ b/binaries/data/mods/public/gui/session/input.js @@ -1539,7 +1539,7 @@ var jumpCameraPositions = [], jumpCameraLast; function jumpCamera(index) { - var position = jumpCameraPositions[index], distanceThreshold = g_ConfigDB.system["camerajump.threshold"]; + var position = jumpCameraPositions[index], distanceThreshold = Engine.ConfigDB_GetValue("user", "camerajump.threshold"); if (position) { if (jumpCameraLast && diff --git a/binaries/data/mods/public/gui/session/unit_commands.js b/binaries/data/mods/public/gui/session/unit_commands.js index 10e2aa6572..0c846dbeab 100644 --- a/binaries/data/mods/public/gui/session/unit_commands.js +++ b/binaries/data/mods/public/gui/session/unit_commands.js @@ -446,7 +446,7 @@ function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c case TRAINING: var tooltip = getEntityNamesFormatted(template); - var key = g_ConfigDB.system["hotkey.session.queueunit." + (i + 1)]; + var key = Engine.ConfigDB_GetValue("user", "hotkey.session.queueunit." + (i + 1)); if (key) tooltip = "[color=\"255 251 131\"][font=\"serif-bold-16\"][" + key + "][/font][/color] " + tooltip; diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index 59052c507e..f98c9d22e2 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -41,6 +41,7 @@ #include "ps/ProfileViewer.h" #include "ps/Pyrogenesis.h" #include "ps/SavedGame.h" +#include "ps/scripting/JSInterface_ConfigDB.h" #include "ps/scripting/JSInterface_Console.h" #include "ps/UserReport.h" #include "ps/GameSetup/Atlas.h" @@ -656,6 +657,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) JSI_GameView::RegisterScriptFunctions(scriptInterface); JSI_Renderer::RegisterScriptFunctions(scriptInterface); JSI_Console::RegisterScriptFunctions(scriptInterface); + JSI_ConfigDB::RegisterScriptFunctions(scriptInterface); // GUI manager functions: scriptInterface.RegisterFunction("GetActiveGui"); diff --git a/source/ps/ConfigDB.cpp b/source/ps/ConfigDB.cpp index 3af2521e06..855094b800 100644 --- a/source/ps/ConfigDB.cpp +++ b/source/ps/ConfigDB.cpp @@ -24,202 +24,16 @@ #include "ConfigDB.h" #include "CLogger.h" #include "Filesystem.h" -#include "scripting/ScriptingHost.h" #include "lib/allocators/shared_ptr.h" -#include "scriptinterface/ScriptInterface.h" - typedef std::map TConfigMap; TConfigMap CConfigDB::m_Map[CFG_LAST]; VfsPath CConfigDB::m_ConfigFile[CFG_LAST]; -#define GET_NS_PRIVATE(cx, obj) (EConfigNamespace)((intptr_t)JS_GetPrivate(cx, obj) >> 1) - -namespace ConfigNamespace_JS -{ - JSBool GetProperty(JSContext* cx, JSObject* obj, jsid id, jsval* vp) - { - EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj); - if (cfgNs < 0 || cfgNs >= CFG_LAST) - return JS_FALSE; - - jsval idval; - if (!JS_IdToValue(cx, id, &idval)) - return JS_FALSE; - - std::string propName; - if (!ScriptInterface::FromJSVal(cx, idval, propName)) - return JS_FALSE; - - CConfigValue *val = g_ConfigDB.GetValue(cfgNs, propName); - if (val) - { - JSString *js_str = JS_NewStringCopyN(cx, val->m_String.c_str(), val->m_String.size()); - *vp = STRING_TO_JSVAL(js_str); - } - return JS_TRUE; - } - - JSBool SetProperty(JSContext* cx, JSObject* obj, jsid id, JSBool UNUSED(strict), jsval* vp) - { - EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, obj); - if (cfgNs < 0 || cfgNs >= CFG_LAST) - return JS_FALSE; - - jsval idval; - if (!JS_IdToValue(cx, id, &idval)) - return JS_FALSE; - - std::string propName; - if (!ScriptInterface::FromJSVal(cx, idval, propName)) - return JS_FALSE; - - CConfigValue *val = g_ConfigDB.CreateValue(cfgNs, propName); - - if (!ScriptInterface::FromJSVal(cx, *vp, val->m_String)) - return JS_FALSE; - - return JS_TRUE; - } - - JSClass Class = { - "ConfigNamespace", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, - GetProperty, SetProperty, - JS_EnumerateStub, JS_ResolveStub, - JS_ConvertStub, JS_FinalizeStub - }; - - JSBool Construct(JSContext* cx, uintN argc, jsval* vp) - { - UNUSED2(argc); - - JSObject *newObj = JS_NewObject(cx, &Class, NULL, NULL); - JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObj)); - return JS_TRUE; - } - - void SetNamespace(JSContext *cx, JSObject *obj, EConfigNamespace cfgNs) - { - JS_SetPrivate(cx, obj, (void *)((uintptr_t)cfgNs << 1)); // JS requires bottom bit = 0 - } - - JSBool WriteFile(JSContext* cx, uintN argc, jsval* vp) - { - EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, JS_THIS_OBJECT(cx, vp)); - if (cfgNs < 0 || cfgNs >= CFG_LAST) - return JS_FALSE; - - if (argc != 1) - return JS_FALSE; - - VfsPath path; - if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], path)) - return JS_FALSE; - - bool res = g_ConfigDB.WriteFile(cfgNs, path); - - JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(res)); - return JS_TRUE; - } - - JSBool Reload(JSContext* cx, uintN argc, jsval* vp) - { - if (argc != 0) - return JS_FALSE; - - EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, JS_THIS_OBJECT(cx, vp)); - if (cfgNs < 0 || cfgNs >= CFG_LAST) - return JS_FALSE; - - JSBool ret = g_ConfigDB.Reload(cfgNs); - JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret)); - return JS_TRUE; - } - - JSBool SetFile(JSContext* cx, uintN argc, jsval* vp) - { - EConfigNamespace cfgNs = GET_NS_PRIVATE(cx, JS_THIS_OBJECT(cx, vp)); - if (cfgNs < 0 || cfgNs >= CFG_LAST) - return JS_FALSE; - - if (argc != 1) - return JS_FALSE; - - VfsPath path; - if (!ScriptInterface::FromJSVal(cx, JS_ARGV(cx, vp)[0], path)) - return JS_FALSE; - - g_ConfigDB.SetConfigFile(cfgNs, path); - - JS_SET_RVAL(cx, vp, JSVAL_VOID); - return JS_TRUE; - } - - JSFunctionSpec Funcs[] = { - { "writeFile", WriteFile, 2, 0 }, - { "reload", Reload, 0, 0 }, - { "setFile", SetFile, 2, 0 }, - {0} - }; -}; - -namespace ConfigDB_JS -{ - JSClass Class = { - "ConfigDB", 0, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_StrictPropertyStub, - JS_EnumerateStub, JS_ResolveStub, - JS_ConvertStub, JS_FinalizeStub - }; - - JSPropertySpec Props[] = { - {0} - }; - - JSFunctionSpec Funcs[] = { - {0} - }; - - JSBool Construct(JSContext* cx, uintN argc, jsval* vp) - { - UNUSED2(argc); - - JSObject *newObj = JS_NewObject(cx, &Class, NULL, NULL); - JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObj)); - - int flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT; -#define cfg_ns(_propname, _enum) STMT (\ - JSObject *nsobj=g_ScriptingHost.CreateCustomObject("ConfigNamespace"); \ - ENSURE(nsobj); \ - ConfigNamespace_JS::SetNamespace(cx, nsobj, _enum); \ - ENSURE(JS_DefineProperty(cx, newObj, _propname, OBJECT_TO_JSVAL(nsobj), NULL, NULL, flags)); ) - - cfg_ns("default", CFG_DEFAULT); - cfg_ns("system", CFG_SYSTEM); - cfg_ns("user", CFG_USER); - cfg_ns("mod", CFG_MOD); - -#undef cfg_ns - - return JS_TRUE; - } - -}; - CConfigDB::CConfigDB() { } -void CConfigDB::RegisterJSConfigDB() -{ - g_ScriptingHost.DefineCustomObjectType(&ConfigDB_JS::Class, ConfigDB_JS::Construct, 0, ConfigDB_JS::Props, ConfigDB_JS::Funcs, NULL, NULL); - g_ScriptingHost.DefineCustomObjectType(&ConfigNamespace_JS::Class, ConfigNamespace_JS::Construct, 0, NULL, ConfigNamespace_JS::Funcs, NULL, NULL); - JSObject *js_ConfigDB = g_ScriptingHost.CreateCustomObject("ConfigDB"); - g_ScriptingHost.SetGlobal("g_ConfigDB", OBJECT_TO_JSVAL(js_ConfigDB)); -} - CConfigValue *CConfigDB::GetValue(EConfigNamespace ns, const CStr& name) { CConfigValueSet* values = GetValues(ns, name); diff --git a/source/ps/ConfigDB.h b/source/ps/ConfigDB.h index 8f1e039551..498825f993 100644 --- a/source/ps/ConfigDB.h +++ b/source/ps/ConfigDB.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,30 +21,7 @@ TDD : http://www.wildfiregames.com/forum/index.php?showtopic=1125 OVERVIEW: - JavaScript: - All the javascript interfaces are provided through the global object - g_ConfigDB. - - g_ConfigDB Properties: - system: - All CFG_SYSTEM values are linked to properties of this object. - a=g_ConfigDB.system.foo; is equivalent to C++ code - g_ConfigDB.GetValue(CFG_SYSTEM, "foo"); - mod: Ditto, but linked to CFG_MOD - user: Ditto, but linked to CFG_USER - default: Ditto, but linked to CFG_DEFAULT - - g_ConfigDB Functions: None so far - - ConfigNamespace Functions: (applicable to the system, mod or user - properties of g_ConfigDB) - - boolean WriteFile(boolean useVFS, string path): - JS interface to g_ConfigDB.WriteFile - should work exactly the - same. - - boolean Reload() => g_ConfigDB.Reload() - void SetFile() => g_ConfigDB.SetConfigFile() + JavaScript: Check this documentation: http://trac.wildfiregames.com/wiki/Exposed_ConfigDB_Functions */ #ifndef INCLUDED_CONFIGDB @@ -81,11 +58,6 @@ class CConfigDB: public Singleton public: CConfigDB(); - - // NOTE: Construct the Singleton Object *after* JavaScript init, so that - // the JS interface can be registered. ConfigDB (C++) needs to be initialized before - // The ScriptInterface because the ScriptInterface requires some configuration information too. - void RegisterJSConfigDB(); /** * Attempt to find a config variable with the given name; will search diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index e2a4d9181d..aaff10dfaa 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -919,8 +919,6 @@ void Init(const CmdLineArgs& args, int flags) InitScripting(); // before GUI - g_ConfigDB.RegisterJSConfigDB(); // after scripting - // Optionally start profiler HTTP output automatically // (By default it's only enabled by a hotkey, for security/performance) bool profilerHTTPEnable = false; diff --git a/source/ps/scripting/JSInterface_ConfigDB.cpp b/source/ps/scripting/JSInterface_ConfigDB.cpp new file mode 100644 index 0000000000..3a0f97bbf4 --- /dev/null +++ b/source/ps/scripting/JSInterface_ConfigDB.cpp @@ -0,0 +1,111 @@ +/* Copyright (C) 2013 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "JSInterface_ConfigDB.h" + +#include "ps/ConfigDB.h" +#include "ps/CLogger.h" +#include "scriptinterface/ScriptInterface.h" + +bool JSI_ConfigDB::GetConfigNamespace(std::wstring cfgNsString, EConfigNamespace& cfgNs) +{ + if (cfgNsString == L"default") + cfgNs = CFG_DEFAULT; + else if (cfgNsString == L"system") + cfgNs = CFG_SYSTEM; + else if (cfgNsString == L"user") + cfgNs = CFG_USER; + else if (cfgNsString == L"mod") + cfgNs = CFG_MOD; + else + { + LOGERROR(L"Invalid namespace name passed to the ConfigDB!"); + return false; + } + return true; +} + +std::string JSI_ConfigDB::GetValue(void* UNUSED(cbdata), std::wstring cfgNsString, std::string name) +{ + EConfigNamespace cfgNs; + if (!GetConfigNamespace(cfgNsString, cfgNs)) + return std::string(); + + CConfigValue *val = g_ConfigDB.GetValue(cfgNs, name); + if (val) + { + return val->m_String; + } + else + { + LOGWARNING(L"Config setting %hs does not exist!", name.c_str()); + return std::string(); + } +} + +bool JSI_ConfigDB::CreateValue(void* UNUSED(cbdata), std::wstring cfgNsString, std::string name, std::string value) +{ + EConfigNamespace cfgNs; + if (!GetConfigNamespace(cfgNsString, cfgNs)) + return false; + + CConfigValue *val = g_ConfigDB.CreateValue(cfgNs, name); + val->m_String = value; + return true; +} + +bool JSI_ConfigDB::WriteFile(void* UNUSED(cbdata), std::wstring cfgNsString, Path path) +{ + EConfigNamespace cfgNs; + if (!GetConfigNamespace(cfgNsString, cfgNs)) + return false; + + bool ret = g_ConfigDB.WriteFile(cfgNs, path); + return ret; +} + +bool JSI_ConfigDB::Reload(void* UNUSED(cbdata), std::wstring cfgNsString) +{ + EConfigNamespace cfgNs; + if (!GetConfigNamespace(cfgNsString, cfgNs)) + return false; + + bool ret = g_ConfigDB.Reload(cfgNs); + return ret; +} + +bool JSI_ConfigDB::SetFile(void* UNUSED(cbdata), std::wstring cfgNsString, Path path) +{ + EConfigNamespace cfgNs; + if (!GetConfigNamespace(cfgNsString, cfgNs)) + return false; + + g_ConfigDB.SetConfigFile(cfgNs, path); + return true; +} + +void JSI_ConfigDB::RegisterScriptFunctions(ScriptInterface& scriptInterface) +{ + scriptInterface.RegisterFunction("ConfigDB_GetValue"); + scriptInterface.RegisterFunction("ConfigDB_CreateValue"); + scriptInterface.RegisterFunction("ConfigDB_WriteFile"); + scriptInterface.RegisterFunction("ConfigDB_SetFile"); + scriptInterface.RegisterFunction("ConfigDB_Reload"); + +} diff --git a/source/ps/scripting/JSInterface_ConfigDB.h b/source/ps/scripting/JSInterface_ConfigDB.h new file mode 100644 index 0000000000..575b6632dd --- /dev/null +++ b/source/ps/scripting/JSInterface_ConfigDB.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2013 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_JSI_CONFIGDB +#define INCLUDED_JSI_CONFIGDB + +#include "ps/ConfigDB.h" + +class ScriptInterface; + +namespace JSI_ConfigDB +{ + bool GetConfigNamespace(std::wstring cfgNsString, EConfigNamespace& cfgNs); + std::string GetValue(void* cbdata, std::wstring cfgNsString, std::string name); + bool CreateValue(void* cbdata, std::wstring cfgNsString, std::string name, std::string value); + bool WriteFile(void* cbdata, std::wstring cfgNsString, Path path); + bool Reload(void* cbdata, std::wstring cfgNsString); + bool SetFile(void* cbdata, std::wstring cfgNsString, Path path); + void RegisterScriptFunctions(ScriptInterface& scriptInterface); +} + +#endif