Index: binaries/data/mods/mod/gui/gui.rnc
===================================================================
--- binaries/data/mods/mod/gui/gui.rnc
+++ binaries/data/mods/mod/gui/gui.rnc
@@ -103,6 +103,7 @@
attribute sprite2_pressed { text }?&
attribute sprite_selectarea { text }?&
attribute square_side { xsd:decimal }?&
+ attribute step_size positive-decimal }?&
attribute textcolor { ccolor }?&
attribute textcolor_disabled { ccolor }?&
attribute textcolor_over { ccolor }?&
Index: binaries/data/mods/mod/gui/gui.rng
===================================================================
--- binaries/data/mods/mod/gui/gui.rng
+++ binaries/data/mods/mod/gui/gui.rng
@@ -410,6 +410,11 @@
+
+
+
+
+
Index: binaries/data/mods/public/gui/common/gamedescription.js
===================================================================
--- binaries/data/mods/public/gui/common/gamedescription.js
+++ binaries/data/mods/public/gui/common/gamedescription.js
@@ -196,31 +196,25 @@
let title = translateVictoryCondition(victoryCondition.Name);
if (victoryCondition.Name == "wonder")
- {
- let wonderDuration = Math.round(g_GameAttributes.settings.WonderDuration);
title = sprintf(
translatePluralWithContext(
"victory condition",
"Wonder (%(min)s minute)",
"Wonder (%(min)s minutes)",
- wonderDuration
+ g_GameAttributes.settings.WonderDuration
),
- { "min": wonderDuration });
- }
+ { "min": g_GameAttributes.settings.WonderDuration });
let isCaptureTheRelic = victoryCondition.Name == "capture_the_relic";
if (isCaptureTheRelic)
- {
- let relicDuration = Math.round(g_GameAttributes.settings.RelicDuration);
title = sprintf(
translatePluralWithContext(
"victory condition",
"Capture the Relic (%(min)s minute)",
"Capture the Relic (%(min)s minutes)",
- relicDuration
+ g_GameAttributes.settings.RelicDuration
),
- { "min": relicDuration });
- }
+ { "min": g_GameAttributes.settings.RelicDuration });
titles.push({
"label": title,
@@ -230,7 +224,7 @@
if (isCaptureTheRelic)
titles.push({
"label": translate("Relic Count"),
- "value": Math.round(g_GameAttributes.settings.RelicCount)
+ "value": g_GameAttributes.settings.RelicCount
});
if (victoryCondition.Name == "regicide")
@@ -275,17 +269,16 @@
"value": translate("If one player wins, his or her allies win too. If one group of allies remains, they win.")
});
- let ceasefire = Math.round(g_GameAttributes.settings.Ceasefire);
titles.push({
"label": translate("Ceasefire"),
"value":
- ceasefire == 0 ?
+ g_GameAttributes.settings.Ceasefire == 0 ?
translate("disabled") :
sprintf(translatePlural(
"For the first minute, other players will stay neutral.",
"For the first %(min)s minutes, other players will stay neutral.",
- ceasefire),
- { "min": ceasefire })
+ g_GameAttributes.settings.Ceasefire),
+ { "min": g_GameAttributes.settings.Ceasefire })
});
if (g_GameAttributes.map == "random")
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/GameSettingControlSlider.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/GameSettingControlSlider.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/GameSettingControlSlider.js
@@ -19,6 +19,8 @@
if (this.MaxValue !== undefined)
this.slider.max_value = this.MaxValue;
+
+ this.slider.step_size = this.StepSize;
}
setControl(gameSettingControlManager)
@@ -75,5 +77,4 @@
}
}
-GameSettingControlSlider.prototype.UnknownValue =
- translateWithContext("settings value", "Unknown");
+GameSettingControlSlider.prototype.StepSize = 1;
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/Ceasefire.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/Ceasefire.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/Ceasefire.js
@@ -34,11 +34,10 @@
onGameAttributesBatchChange()
{
- let value = Math.round(g_GameAttributes.settings.Ceasefire);
+ let value = g_GameAttributes.settings.Ceasefire;
this.sprintfValue.minutes = value;
-
this.setSelectedValue(
- g_GameAttributes.settings.Ceasefire,
+ value,
value == 0 ?
this.NoCeasefireCaption :
sprintf(this.CeasefireCaption(value), this.sprintfValue));
@@ -50,11 +49,6 @@
this.gameSettingsControl.updateGameAttributes();
this.gameSettingsControl.setNetworkGameAttributes();
}
-
- onGameAttributesFinalize()
- {
- g_GameAttributes.settings.Ceasefire = Math.round(g_GameAttributes.settings.Ceasefire);
- }
};
GameSettingControls.Ceasefire.prototype.TitleCaption =
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicCount.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicCount.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicCount.js
@@ -60,10 +60,10 @@
if (this.available)
{
- let value = Math.round(g_GameAttributes.settings.RelicCount);
+ let value = g_GameAttributes.settings.RelicCount;
this.sprintfValue.number = value;
this.setSelectedValue(
- g_GameAttributes.settings.RelicCount,
+ value,
value == 0 ? this.InstantVictory : sprintf(this.CaptionRelicCount(value), this.sprintfValue));
}
}
@@ -74,12 +74,6 @@
this.gameSettingsControl.updateGameAttributes();
this.gameSettingsControl.setNetworkGameAttributes();
}
-
- onGameAttributesFinalize()
- {
- if (this.available)
- g_GameAttributes.settings.RelicCount = Math.round(g_GameAttributes.settings.RelicCount);
- }
};
GameSettingControls.RelicCount.prototype.TitleCaption =
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicDuration.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicDuration.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/RelicDuration.js
@@ -60,10 +60,10 @@
if (this.available)
{
- let value = Math.round(g_GameAttributes.settings.RelicDuration);
+ let value = g_GameAttributes.settings.RelicDuration;
this.sprintfValue.min = value;
this.setSelectedValue(
- g_GameAttributes.settings.RelicDuration,
+ value,
value == 0 ? this.InstantVictory : sprintf(this.CaptionVictoryTime(value), this.sprintfValue));
}
}
@@ -74,12 +74,6 @@
this.gameSettingsControl.updateGameAttributes();
this.gameSettingsControl.setNetworkGameAttributes();
}
-
- onGameAttributesFinalize()
- {
- if (this.available)
- g_GameAttributes.settings.RelicDuration = Math.round(g_GameAttributes.settings.RelicDuration);
- }
};
GameSettingControls.RelicDuration.prototype.TitleCaption =
Index: binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/SeaLevelRiseTime.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/SeaLevelRiseTime.js
+++ binaries/data/mods/public/gui/gamesetup/Pages/GameSetupPage/GameSettings/Single/Sliders/SeaLevelRiseTime.js
@@ -47,11 +47,10 @@
if (!this.values)
return;
- let value = Math.round(g_GameAttributes.settings.SeaLevelRiseTime);
+ let value = g_GameAttributes.settings.SeaLevelRiseTime;
this.sprintfValue.minutes = value;
-
this.setSelectedValue(
- g_GameAttributes.settings.SeaLevelRiseTime,
+ value,
sprintf(this.SeaLevelRiseTimeCaption(value), this.sprintfValue));
}
@@ -61,12 +60,6 @@
this.gameSettingsControl.updateGameAttributes();
this.gameSettingsControl.setNetworkGameAttributes();
}
-
- onGameAttributesFinalize()
- {
- if (this.values)
- g_GameAttributes.settings.SeaLevelRiseTime = Math.round(g_GameAttributes.settings.SeaLevelRiseTime);
- }
};
GameSettingControls.SeaLevelRiseTime.prototype.TitleCaption =
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
@@ -151,19 +151,24 @@
"configToValue": value => +value,
"valueToGui": (value, control) => {
control.value = +value;
+ control.children[0].caption = value;
},
"guiToValue": control => control.value,
"guiSetter": "onValueChange",
"initGUI": (option, control) => {
- control.max_value = option.max;
control.min_value = option.min;
+ control.max_value = option.max;
+ control.step_size = option.step_size;
},
"tooltip": (value, option) =>
sprintf(translateWithContext("slider number", "Value: %(val)s (min: %(min)s, max: %(max)s)"), {
- "val": value.toFixed(2),
- "min": option.min.toFixed(2),
- "max": option.max.toFixed(2)
- })
+ "val": value,
+ "min": option.min,
+ "max": option.max
+ }),
+ "onGUISet": (value, control, option) => {
+ control.children[0].caption = value;
+ }
}
};
@@ -241,6 +246,9 @@
if (optionType.sanitizeValue)
optionType.sanitizeValue(value, control, option);
+ if (optionType.onGUISet)
+ optionType.onGUISet(value, control, option);
+
control.tooltip = option.tooltip + (optionType.tooltip ? "\n" + optionType.tooltip(value, option) : "");
Engine.ConfigDB_CreateValue("user", option.config, String(value));
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
@@ -69,12 +69,13 @@
]
},
{
- "type": "number",
+ "type": "slider",
"label": "Observer limit",
"tooltip": "Prevent further observers from joining if the limit is reached.",
"config": "network.observerlimit",
"min": 0,
- "max": 32
+ "max": 32,
+ "step_size": 1
},
{
"type": "boolean",
@@ -123,7 +124,8 @@
"tooltip": "Number of shader effects. REQUIRES GAME RESTART",
"config": "materialmgr.quality",
"min": 0,
- "max": 10
+ "max": 10,
+ "step_size": 1
},
{
"type": "boolean",
@@ -242,7 +244,8 @@
"tooltip": "To save CPU workload, throttle render frequency in all menus. Set to maximum to disable throttling.",
"config": "adaptivefps.menu",
"min": 20,
- "max": 100
+ "max": 100,
+ "step_size": 1
},
{
"type": "slider",
@@ -250,7 +253,8 @@
"tooltip": "To save CPU workload, throttle render frequency in running games. Set to maximum to disable throttling.",
"config": "adaptivefps.session",
"min": 20,
- "max": 100
+ "max": 100,
+ "step_size": 1
}
]
},
@@ -265,7 +269,8 @@
"config": "sound.mastergain",
"function": "SetMasterGain",
"min": 0,
- "max": 2
+ "max": 200,
+ "step_size": 10
},
{
"type": "slider",
@@ -274,7 +279,8 @@
"config": "sound.musicgain",
"function": "SetMusicGain",
"min": 0,
- "max": 2
+ "max": 2,
+ "step_size": 0.01
},
{
"type": "slider",
@@ -283,7 +289,8 @@
"config": "sound.ambientgain",
"function": "SetAmbientGain",
"min": 0,
- "max": 2
+ "max": 2,
+ "step_size": 0.01
},
{
"type": "slider",
@@ -292,7 +299,8 @@
"config": "sound.actiongain",
"function": "SetActionGain",
"min": 0,
- "max": 2
+ "max": 2,
+ "step_size": 0.01
},
{
"type": "slider",
@@ -301,7 +309,8 @@
"config": "sound.uigain",
"function": "SetUIGain",
"min": 0,
- "max": 2
+ "max": 2,
+ "step_size": 0.01
},
{
"type": "boolean",
@@ -427,15 +436,17 @@
"tooltip": "The wounded unit hotkey considers the selected units as wounded if their health percentage falls below this number.",
"config": "gui.session.woundedunithotkeythreshold",
"min": 0,
- "max": 100
+ "max": 100,
+ "step_size": 1
},
{
- "type": "number",
+ "type": "slider",
"label": "Batch training size",
"tooltip": "Number of units trained per batch by default.",
"config": "gui.session.batchtrainingsize",
"min": 1,
- "max": 20
+ "max": 20,
+ "step_size": 1
},
{
"type": "slider",
@@ -443,7 +454,8 @@
"tooltip": "Number of times you have to scroll to increase/decrease the batchsize by 1.",
"config": "gui.session.scrollbatchratio",
"min": 0.1,
- "max": 30
+ "max": 30,
+ "step_size": 0.1
},
{
"type": "boolean",
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
@@ -26,14 +26,16 @@
Index: source/gui/GUISettingTypes.h
===================================================================
--- source/gui/GUISettingTypes.h
+++ source/gui/GUISettingTypes.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Wildfire Games.
+/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -31,6 +31,7 @@
TYPE(i32)
TYPE(u32)
TYPE(float)
+TYPE(double)
TYPE(EAlign)
TYPE(EVAlign)
TYPE(CPos)
Index: source/gui/GUIStringConversions.cpp
===================================================================
--- source/gui/GUIStringConversions.cpp
+++ source/gui/GUIStringConversions.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019 Wildfire Games.
+/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -59,6 +59,13 @@
}
template <>
+bool CGUI::ParseString(const CGUI* UNUSED(pGUI), const CStrW& Value, double& Output)
+{
+ Output = Value.ToDouble();
+ return true;
+}
+
+template <>
bool CGUI::ParseString(const CGUI* UNUSED(pGUI), const CStrW& Value, CRect& Output)
{
const unsigned int NUM_COORDS = 4;
Index: source/gui/ObjectTypes/CSlider.h
===================================================================
--- source/gui/ObjectTypes/CSlider.h
+++ source/gui/ObjectTypes/CSlider.h
@@ -48,28 +48,21 @@
/**
* Change settings and send the script event
*/
- void UpdateValue();
+ void UpdateValue(const double value);
CRect GetButtonRect() const;
- /**
- * @return ratio between the value of the slider and its actual size in the GUI
- */
- float GetSliderRatio() const;
-
- void IncrementallyChangeValue(const float value);
+ void IncrementallyChangeValue(const double value);
// Settings
- float m_ButtonSide;
+ double m_ButtonSide;
i32 m_CellID;
- float m_MinValue;
- float m_MaxValue;
+ double m_MinValue;
+ double m_MaxValue;
CGUISpriteInstance m_Sprite;
CGUISpriteInstance m_SpriteBar;
- float m_Value;
-
-private:
- CPos m_Mouse;
+ double m_Value;
+ double m_StepSize;
};
#endif // INCLUDED_CSLIDER
Index: source/gui/ObjectTypes/CSlider.cpp
===================================================================
--- source/gui/ObjectTypes/CSlider.cpp
+++ source/gui/ObjectTypes/CSlider.cpp
@@ -31,6 +31,7 @@
m_CellID(),
m_MaxValue(),
m_MinValue(),
+ m_StepSize(),
m_Sprite(),
m_SpriteBar(),
m_Value()
@@ -39,6 +40,7 @@
RegisterSetting("cell_id", m_CellID);
RegisterSetting("max_value", m_MaxValue);
RegisterSetting("min_value", m_MinValue);
+ RegisterSetting("step_size", m_StepSize);
RegisterSetting("sprite", m_Sprite);
RegisterSetting("sprite_bar", m_SpriteBar);
RegisterSetting("value", m_Value);
@@ -56,15 +58,9 @@
IGUIButtonBehavior::ResetStates();
}
-float CSlider::GetSliderRatio() const
+void CSlider::IncrementallyChangeValue(const double difference)
{
- return (m_MaxValue - m_MinValue) / (m_CachedActualSize.GetWidth() - m_ButtonSide);
-}
-
-void CSlider::IncrementallyChangeValue(const float difference)
-{
- m_Value = Clamp(m_Value + difference, m_MinValue, m_MaxValue);
- UpdateValue();
+ UpdateValue(Clamp(m_Value + difference, m_MinValue, m_MaxValue));
}
void CSlider::HandleMessage(SGUIMessage& Message)
@@ -83,14 +79,14 @@
{
if (m_Pressed)
break;
- IncrementallyChangeValue(-0.01f);
+ IncrementallyChangeValue(-m_StepSize);
break;
}
case GUIM_MOUSE_WHEEL_UP:
{
if (m_Pressed)
break;
- IncrementallyChangeValue(0.01f);
+ IncrementallyChangeValue(+m_StepSize);
break;
}
case GUIM_MOUSE_PRESS_LEFT:
@@ -99,8 +95,10 @@
{
if (m_Pressed)
{
- m_Mouse = m_pGUI.GetMousePos();
- IncrementallyChangeValue((m_Mouse.x - GetButtonRect().CenterPoint().x) * GetSliderRatio());
+ const double ratio = (m_MaxValue - m_MinValue) / (m_CachedActualSize.GetWidth() - m_ButtonSide);
+ const double value = ((m_pGUI.GetMousePos().x - m_CachedActualSize.left - m_ButtonSide / 2.f) * ratio) + m_MinValue;
+ const double valueStep = round(value / m_StepSize) * m_StepSize;
+ UpdateValue(Clamp(valueStep, m_MinValue, m_MaxValue));
}
break;
}
@@ -119,16 +117,21 @@
m_pGUI.DrawSprite(m_Sprite, m_CellID, bz, GetButtonRect());
}
-void CSlider::UpdateValue()
+void CSlider::UpdateValue(const double value)
{
- SetSetting("value", m_Value, true);
+ if (value == m_Value)
+ return;
+
+ const float numPlaces = -round(log10(m_StepSize));
+ const float num = std::max(1.f, pow(10.f, numPlaces));
+ SetSetting("value", round(value * num) / num, true);
ScriptEvent(EventNameValueChange);
}
CRect CSlider::GetButtonRect() const
{
- float ratio = m_MaxValue > m_MinValue ? (m_Value - m_MinValue) / (m_MaxValue - m_MinValue) : 0.0f;
- float x = m_CachedActualSize.left + ratio * (m_CachedActualSize.GetWidth() - m_ButtonSide);
- float y = m_CachedActualSize.top + (m_CachedActualSize.GetHeight() - m_ButtonSide) / 2.0;
+ const double ratio = m_MaxValue > m_MinValue ? (m_Value - m_MinValue) / (m_MaxValue - m_MinValue) : 0.0f;
+ const double x = m_CachedActualSize.left + ratio * (m_CachedActualSize.GetWidth() - m_ButtonSide);
+ const double y = m_CachedActualSize.top + (m_CachedActualSize.GetHeight() - m_ButtonSide) / 2.0;
return CRect(x, y, x + m_ButtonSide, y + m_ButtonSide);
}