Index: binaries/data/mods/mod/gui/common/functions_msgbox.js
===================================================================
--- binaries/data/mods/mod/gui/common/functions_msgbox.js
+++ binaries/data/mods/mod/gui/common/functions_msgbox.js
@@ -15,6 +15,24 @@
});
}
+function timedConfirmation(mbWidth, mbHeight, mbMessage, mbTimeout, mbTitle, mbButtonCaptions, mbBtnCode, mbCallbackArgs)
+{
+ Engine.PushGuiPage(
+ "page_timedconfirmation.xml",
+ {
+ "width": mbWidth,
+ "height": mbHeight,
+ "message": mbMessage,
+ "timeout": mbTimeout,
+ "title": mbTitle,
+ "buttonCaptions": mbButtonCaptions
+ },
+ btnCode => {
+ if (mbBtnCode !== undefined && mbBtnCode[btnCode])
+ mbBtnCode[btnCode](mbCallbackArgs ? mbCallbackArgs[btnCode] : undefined);
+ });
+}
+
function openURL(url)
{
Engine.OpenURL(url);
Index: binaries/data/mods/mod/gui/timedconfirmation/timedconfirmation.js
===================================================================
--- /dev/null
+++ binaries/data/mods/mod/gui/timedconfirmation/timedconfirmation.js
@@ -0,0 +1,83 @@
+/**
+ * Currently limited to at most 3 buttons per message box.
+ * The convention is to have "cancel" appear first.
+ */
+function init(data)
+{
+ // Set title
+ Engine.GetGUIObjectByName("mbTitleBar").caption = data.title;
+
+ // Set subject
+ let mbTextObj = Engine.GetGUIObjectByName("mbText");
+ let mbTimerObj = Engine.GetGUIObjectByName("mbTimer");
+ mbTextObj.caption = data.message;
+
+ updateDisplayedTimer(data.timeout);
+
+ mbTimerObj.caption = data.timeout;
+ if (data.font) {
+ mbTextObj.font = data.font;
+ }
+
+ // Default behaviour
+ let mbCancelHotkey = Engine.GetGUIObjectByName("mbCancelHotkey");
+ mbCancelHotkey.onPress = Engine.PopGuiPage;
+
+ // Calculate size
+ let mbLRDiff = data.width / 2;
+ let mbUDDiff = data.height / 2;
+ Engine.GetGUIObjectByName("mbMain").size = "50%-" + mbLRDiff + " 50%-" + mbUDDiff + " 50%+" + mbLRDiff + " 50%+" + mbUDDiff;
+
+ let captions = data.buttonCaptions || [translate("OK")];
+
+ // Set button captions and visibility
+ let mbButton = [];
+ captions.forEach((caption, i) => {
+ mbButton[i] = Engine.GetGUIObjectByName("mbButton" + (i + 1));
+ mbButton[i].caption = caption;
+ mbButton[i].hidden = false;
+ mbButton[i].onPress = () => {
+ Engine.PopGuiPage(i);
+ };
+
+ // Convention: Cancel is the first button
+ if (i == 0)
+ mbCancelHotkey.onPress = mbButton[i].onPress;
+ });
+
+ // Distribute buttons horizontally
+ let y1 = "100%-46";
+ let y2 = "100%-18";
+ switch (captions.length)
+ {
+ case 1:
+ mbButton[0].size = "18 " + y1 + " 100%-18 " + y2;
+ break;
+ case 2:
+ mbButton[0].size = "18 " + y1 + " 50%-5 " + y2;
+ mbButton[1].size = "50%+5 " + y1 + " 100%-18 " + y2;
+ break;
+ case 3:
+ mbButton[0].size = "18 " + y1 + " 33%-5 " + y2;
+ mbButton[1].size = "33%+5 " + y1 + " 66%-5 " + y2;
+ mbButton[2].size = "66%+5 " + y1 + " 100%-18 " + y2;
+ break;
+ }
+}
+
+function onTick() {
+ let mbTimerObj = Engine.GetGUIObjectByName("mbTimer");
+ let time = +mbTimerObj.caption;
+ --time;
+ if (time < 1) {
+ let action = Engine.GetGUIObjectByName("mbButton1");
+ action.onPress();
+ }
+ mbTimerObj.caption = time;
+ updateDisplayedTimer(time);
+}
+
+function updateDisplayedTimer(time) {
+ let mbTimerDisplayObj = Engine.GetGUIObjectByName("mbTimerDisplay");
+ mbTimerDisplayObj.caption = Math.ceil(time/100);
+}
Index: binaries/data/mods/mod/gui/timedconfirmation/timedconfirmation.xml
===================================================================
--- /dev/null
+++ binaries/data/mods/mod/gui/timedconfirmation/timedconfirmation.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
Index: binaries/data/mods/public/gui/options/options.js
===================================================================
--- binaries/data/mods/public/gui/options/options.js
+++ binaries/data/mods/public/gui/options/options.js
@@ -146,6 +146,35 @@
};
}
},
+ "dropdownNumber":
+ {
+ "configToValue": value => +value,
+ "valueToGui": (value, control) => {
+ control.selected = control.list_data.indexOf(""+value);
+ },
+ "guiToValue": control => +control.list_data[control.selected],
+ "guiSetter": "onSelectionChange",
+ "initGUI": (option, control) => {
+ control.list = option.list.map(e => e.label);
+ control.list_data = option.list.map(e => e.value);
+ control.onHoverChange = () => {
+ let item = option.list[control.hovered];
+ control.tooltip = item && item.tooltip || option.tooltip;
+ };
+ },
+ "timeout": (option, oldValue, hasChanges, newValue) => {
+ if (!option.timeout)
+ return;
+ timedConfirmation(
+ 500, 200,
+ translate("Do you want to keep changes?"),
+ 500,
+ translate("Warning"),
+ [translate("No"), translate("Yes")],
+ [() => {this.revertChange(option, +oldValue, hasChanges);}, null]
+ );
+ }
+ },
"slider":
{
"configToValue": value => +value,
@@ -242,14 +271,20 @@
if (optionType.sanitizeValue)
optionType.sanitizeValue(value, control, option);
+ let oldValue = optionType.configToValue(Engine.ConfigDB_GetValue("user", option.config));
+
control.tooltip = option.tooltip + (optionType.tooltip ? "\n" + optionType.tooltip(value, option) : "");
+ let hasChanges = Engine.ConfigDB_HasChanges("user");
Engine.ConfigDB_CreateValue("user", option.config, String(value));
Engine.ConfigDB_SetChanges("user", true);
g_ChangedKeys.add(option.config);
fireConfigChangeHandlers(new Set([option.config]));
+ if (option.timeout)
+ optionType.timeout(option, oldValue, hasChanges, value);
+
if (option.function)
Engine[option.function](value);
@@ -315,6 +350,18 @@
revertChanges();
}
+function revertChange(option, oldValue, hadChanges)
+{
+ if (!hadChanges)
+ Engine.ConfigDB_SetChanges("user", false);
+
+ Engine.ConfigDB_CreateValue("user", option.config, String(oldValue));
+ if (option.function)
+ Engine[option.function](oldValue);
+
+ displayOptions();
+}
+
function revertChanges()
{
Engine.ConfigDB_Reload("user");
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
@@ -149,6 +149,23 @@
"config": "adaptivefps.session",
"min": 20,
"max": 100
+ },
+ {
+ "type": "dropdownNumber",
+ "label": "GUI scale",
+ "timeout": 500,
+ "tooltip": "GUI scale",
+ "config": "gui.scale",
+ "function": "SetGUIScale",
+ "list": [
+ { "value": 0.75, "label": "75%" },
+ { "value": 1.00, "label": "100%" },
+ { "value": 1.25, "label": "125%" },
+ { "value": 1.75, "label": "175%" },
+ { "value": 2.00, "label": "200%" },
+ { "value": 2.25, "label": "225%" },
+ { "value": 2.50, "label": "250%" }
+ ]
}
]
},
Index: binaries/data/mods/public/gui/options/options.xml
===================================================================
--- binaries/data/mods/public/gui/options/options.xml
+++ binaries/data/mods/public/gui/options/options.xml
@@ -33,6 +33,7 @@
+
Index: source/ps/GameSetup/Config.cpp
===================================================================
--- source/ps/GameSetup/Config.cpp
+++ source/ps/GameSetup/Config.cpp
@@ -51,7 +51,6 @@
CFG_GET_VAL("gui.scale", g_GuiScale);
}
-
static void ProcessCommandLineArgs(const CmdLineArgs& args)
{
// TODO: all these options (and the ones processed elsewhere) should
Index: source/ps/VideoMode.h
===================================================================
--- source/ps/VideoMode.h
+++ source/ps/VideoMode.h
@@ -47,6 +47,11 @@
bool ResizeWindow(int w, int h);
/**
+ * Tell dependent compoenent to recompute sizes because scaling have changed.
+ */
+ void Rescale();
+
+ /**
* Switch to fullscreen or windowed mode.
*/
bool SetFullscreen(bool fullscreen);
Index: source/ps/VideoMode.cpp
===================================================================
--- source/ps/VideoMode.cpp
+++ source/ps/VideoMode.cpp
@@ -359,6 +359,12 @@
return true;
}
+void CVideoMode::Rescale()
+{
+ ENSURE(m_IsInitialised);
+ UpdateRenderer(m_CurrentW, m_CurrentH);
+}
+
bool CVideoMode::SetFullscreen(bool fullscreen)
{
// This might get called before initialisation by psDisplayError;
Index: source/ps/scripting/JSInterface_ConfigDB.cpp
===================================================================
--- source/ps/scripting/JSInterface_ConfigDB.cpp
+++ source/ps/scripting/JSInterface_ConfigDB.cpp
@@ -24,9 +24,12 @@
#include "scriptinterface/FunctionWrapper.h"
#include "scriptinterface/ScriptRequest.h"
+#include "ps/VideoMode.h"
+
#include
#include
+extern float g_GuiScale;
namespace JSI_ConfigDB
{
// These entries will not be readable nor writable for JS, so that e.g. malicious mods can't leak personal or sensitive data
@@ -188,6 +191,12 @@
return true;
}
+void SetGUIScale(float scale)
+{
+ g_GuiScale = scale;
+ g_VideoMode.Rescale();
+}
+
void RegisterScriptFunctions(const ScriptRequest& rq)
{
ScriptFunction::Register<&HasChanges>(rq, "ConfigDB_HasChanges");
@@ -201,5 +210,6 @@
ScriptFunction::Register<&CreateAndWriteValueToFile>(rq, "ConfigDB_CreateAndWriteValueToFile");
ScriptFunction::Register<&SetFile>(rq, "ConfigDB_SetFile");
ScriptFunction::Register<&Reload>(rq, "ConfigDB_Reload");
+ ScriptFunction::Register<&SetGUIScale>(rq, "SetGUIScale");
}
}