2022-11-10 20:39:09 +00:00
|
|
|
/*
|
|
|
|
* This file is part of OpenTTD.
|
|
|
|
* OpenTTD 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, version 2.
|
|
|
|
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** @file game_gui.cpp %Window for configuring the Game Script */
|
|
|
|
|
|
|
|
#include "../stdafx.h"
|
|
|
|
#include "../error.h"
|
|
|
|
#include "../settings_gui.h"
|
|
|
|
#include "../querystring_gui.h"
|
|
|
|
#include "../window_func.h"
|
|
|
|
#include "../network/network.h"
|
|
|
|
#include "../network/network_content.h"
|
|
|
|
#include "../widgets/dropdown_func.h"
|
2023-02-11 22:11:21 +00:00
|
|
|
#include "../settings_type.h"
|
2022-11-10 20:39:09 +00:00
|
|
|
|
2023-02-04 03:17:55 +00:00
|
|
|
#include "game.hpp"
|
2022-11-10 20:39:09 +00:00
|
|
|
#include "game_gui.hpp"
|
2023-02-04 03:17:55 +00:00
|
|
|
#include "game_config.hpp"
|
|
|
|
#include "game_info.hpp"
|
|
|
|
#include "../script/script_gui.h"
|
2023-02-03 20:39:06 +00:00
|
|
|
#include "../script_config.hpp"
|
2022-11-10 20:39:09 +00:00
|
|
|
#include "../table/strings.h"
|
|
|
|
|
|
|
|
#include "../safeguards.h"
|
|
|
|
|
|
|
|
|
|
|
|
/** Widgets for the configure GS window. */
|
|
|
|
static const NWidgetPart _nested_gs_config_widgets[] = {
|
|
|
|
NWidget(NWID_HORIZONTAL),
|
|
|
|
NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
|
|
|
|
NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_CAPTION_GAMESCRIPT, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
|
|
|
NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(WWT_PANEL, COLOUR_MAUVE, WID_GSC_BACKGROUND), SetFill(1, 0), SetResize(1, 0),
|
|
|
|
NWidget(NWID_SPACER), SetMinimalSize(0, 3), SetFill(1, 0), SetResize(1, 0),
|
|
|
|
NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_GAMESCRIPT, STR_NULL), SetFill(1, 0), SetResize(1, 0), SetPadding(0, 5, 4, 5),
|
|
|
|
NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_GSC_GSLIST), SetMinimalSize(288, 14), SetFill(1, 0), SetResize(1, 0), SetMatrixDataTip(1, 1, STR_AI_CONFIG_GAMELIST_TOOLTIP),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(NWID_SPACER), SetMinimalSize(0, 6), SetFill(1, 0), SetResize(1, 0),
|
|
|
|
NWidget(WWT_FRAME, COLOUR_MAUVE), SetDataTip(STR_AI_CONFIG_GAMESCRIPT_PARAM, STR_NULL), SetFill(1, 0), SetResize(1, 0), SetPadding(0, 5, 4, 5),
|
|
|
|
NWidget(NWID_HORIZONTAL),
|
|
|
|
NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_GSC_SETTINGS), SetFill(1, 0), SetResize(1, 1), SetMinimalSize(188, 182), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_GSC_SCROLLBAR),
|
|
|
|
NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GSC_SCROLLBAR),
|
|
|
|
EndContainer(),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_GSC_CHANGE), SetFill(1, 0), SetResize(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_AI_CONFIG_CHANGE_GAMESCRIPT, STR_AI_CONFIG_CHANGE_TOOLTIP),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_GSC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetMinimalSize(93, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_GSC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_GSC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, WID_GSC_CONTENT_DOWNLOAD), SetFill(1, 0), SetResize(1, 0), SetMinimalSize(279, 0), SetPadding(0, 7, 9, 7), SetDataTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(NWID_HORIZONTAL),
|
|
|
|
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GSC_ACCEPT), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_AI_SETTINGS_CLOSE, STR_NULL),
|
|
|
|
NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GSC_RESET), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_AI_SETTINGS_RESET, STR_NULL),
|
|
|
|
EndContainer(),
|
|
|
|
NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
|
|
|
|
EndContainer(),
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Window definition for the configure GS window. */
|
|
|
|
static WindowDesc _gs_config_desc(
|
|
|
|
WDP_CENTER, "settings_gs_config", 500, 350,
|
|
|
|
WC_GAME_OPTIONS, WC_NONE,
|
|
|
|
0,
|
|
|
|
_nested_gs_config_widgets, lengthof(_nested_gs_config_widgets)
|
|
|
|
);
|
|
|
|
|
2022-11-26 23:04:04 +00:00
|
|
|
bool UserIsAllowedToChangeGameScript()
|
|
|
|
{
|
|
|
|
return _game_mode != GM_NORMAL || _settings_client.gui.ai_developer_tools;
|
|
|
|
}
|
|
|
|
|
2022-11-10 20:39:09 +00:00
|
|
|
/**
|
|
|
|
* Window to configure which GSs will start.
|
|
|
|
*/
|
|
|
|
struct GSConfigWindow : public Window {
|
2023-02-03 23:55:11 +00:00
|
|
|
ScriptConfig *gs_config; ///< The configuration we're modifying.
|
2022-11-10 20:39:09 +00:00
|
|
|
int line_height; ///< Height of a single GS-name line.
|
|
|
|
int clicked_button; ///< The button we clicked.
|
|
|
|
bool clicked_increase; ///< Whether we clicked the increase or decrease button.
|
|
|
|
bool clicked_dropdown; ///< Whether the dropdown is open.
|
|
|
|
bool closing_dropdown; ///< True, if the dropdown list is currently closing.
|
|
|
|
GUITimer timeout; ///< Timeout for unclicking the button.
|
|
|
|
int clicked_row; ///< The clicked row of settings.
|
2023-02-03 23:55:11 +00:00
|
|
|
Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
|
|
|
|
typedef std::vector<const ScriptConfigItem *> VisibleSettingsList; ///< typdef for a vector of script settings
|
2022-11-10 20:39:09 +00:00
|
|
|
VisibleSettingsList visible_settings; ///< List of visible GS settings
|
|
|
|
|
|
|
|
GSConfigWindow() : Window(&_gs_config_desc),
|
|
|
|
clicked_button(-1),
|
|
|
|
clicked_dropdown(false),
|
|
|
|
closing_dropdown(false),
|
|
|
|
timeout(0)
|
|
|
|
{
|
|
|
|
this->gs_config = GameConfig::GetConfig();
|
|
|
|
|
|
|
|
this->CreateNestedTree(); // Initializes 'this->line_height' as a side effect.
|
|
|
|
this->vscroll = this->GetScrollbar(WID_GSC_SCROLLBAR);
|
|
|
|
this->FinishInitNested(WN_GAME_OPTIONS_GS);
|
|
|
|
this->OnInvalidateData(0);
|
|
|
|
|
|
|
|
this->RebuildVisibleSettings();
|
|
|
|
}
|
|
|
|
|
2022-11-26 23:04:04 +00:00
|
|
|
~GSConfigWindow()
|
2022-11-10 20:39:09 +00:00
|
|
|
{
|
2023-06-01 20:08:12 +00:00
|
|
|
HideDropDownMenu(this);
|
2023-02-11 22:11:21 +00:00
|
|
|
DeleteWindowByClass(WC_SCRIPT_LIST);
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rebuilds the list of visible settings. GS settings with the flag
|
|
|
|
* GSCONFIG_GS_DEVELOPER set will only be visible if the game setting
|
|
|
|
* gui.ai_developer_tools is enabled.
|
|
|
|
*/
|
|
|
|
void RebuildVisibleSettings()
|
|
|
|
{
|
|
|
|
visible_settings.clear();
|
|
|
|
|
2023-02-03 23:55:11 +00:00
|
|
|
for (const auto &item : *this->gs_config->GetConfigList()) {
|
2022-11-10 20:39:09 +00:00
|
|
|
bool no_hide = (item.flags & SCRIPTCONFIG_DEVELOPER) == 0;
|
|
|
|
if (no_hide || _settings_client.gui.ai_developer_tools) {
|
|
|
|
visible_settings.push_back(&item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-07 15:10:56 +00:00
|
|
|
this->vscroll->SetCount(this->visible_settings.size());
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 23:55:11 +00:00
|
|
|
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
2022-11-10 20:39:09 +00:00
|
|
|
{
|
|
|
|
switch (widget) {
|
|
|
|
case WID_GSC_SETTINGS:
|
2021-05-03 15:56:02 +00:00
|
|
|
this->line_height = std::max(SETTING_BUTTON_HEIGHT, FONT_HEIGHT_NORMAL) + padding.height;
|
2022-11-10 20:39:09 +00:00
|
|
|
resize->width = 1;
|
|
|
|
resize->height = this->line_height;
|
|
|
|
size->height = 5 * this->line_height;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WID_GSC_GSLIST:
|
2021-05-03 15:56:02 +00:00
|
|
|
this->line_height = FONT_HEIGHT_NORMAL + padding.height;
|
2022-11-10 20:39:09 +00:00
|
|
|
size->height = 1 * this->line_height;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Can the GS config be edited?
|
|
|
|
* @return True if the given GS Config slot can be edited, otherwise false.
|
|
|
|
*/
|
|
|
|
static bool IsEditable()
|
|
|
|
{
|
2022-11-26 23:04:04 +00:00
|
|
|
return UserIsAllowedToChangeGameScript() || Game::GetInstance() != nullptr;
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
|
2023-02-03 23:55:11 +00:00
|
|
|
void DrawWidget(const Rect &r, int widget) const override
|
2022-11-10 20:39:09 +00:00
|
|
|
{
|
|
|
|
switch (widget) {
|
|
|
|
case WID_GSC_GSLIST: {
|
|
|
|
StringID text = STR_AI_CONFIG_NONE;
|
|
|
|
|
|
|
|
if (GameConfig::GetConfig()->GetInfo() != nullptr) {
|
|
|
|
SetDParamStr(0, GameConfig::GetConfig()->GetInfo()->GetName());
|
|
|
|
text = STR_JUST_RAW_STRING;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There is only one slot, unlike with the GS GUI, so it should never be white */
|
2022-09-23 08:36:22 +00:00
|
|
|
DrawString(r.Shrink(WidgetDimensions::scaled.matrix), text, (IsEditable() ? TC_ORANGE : TC_SILVER));
|
2022-11-10 20:39:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WID_GSC_SETTINGS: {
|
2023-02-03 23:55:11 +00:00
|
|
|
ScriptConfig *config = this->gs_config;
|
2022-11-10 20:39:09 +00:00
|
|
|
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
|
|
|
int i = 0;
|
|
|
|
for (; !this->vscroll->IsVisible(i); i++) it++;
|
|
|
|
|
2022-09-23 08:36:22 +00:00
|
|
|
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
|
2022-11-10 20:39:09 +00:00
|
|
|
bool rtl = _current_text_dir == TD_RTL;
|
2022-10-15 15:55:47 +00:00
|
|
|
Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
|
2022-09-23 08:36:22 +00:00
|
|
|
Rect tr = ir.Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
|
2022-11-10 20:39:09 +00:00
|
|
|
|
|
|
|
int y = r.top;
|
|
|
|
int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
|
|
|
int text_y_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
|
|
|
|
for (; this->vscroll->IsVisible(i) && it != visible_settings.end(); i++, it++) {
|
2023-02-03 23:55:11 +00:00
|
|
|
const ScriptConfigItem &config_item = **it;
|
2022-11-10 20:39:09 +00:00
|
|
|
int current_value = config->GetSetting((config_item).name);
|
|
|
|
bool editable = this->IsEditableItem(config_item);
|
|
|
|
|
|
|
|
StringID str;
|
|
|
|
TextColour colour;
|
|
|
|
uint idx = 0;
|
2023-05-05 14:48:53 +00:00
|
|
|
if (config_item.description.empty()) {
|
2023-02-03 23:55:11 +00:00
|
|
|
str = STR_JUST_STRING;
|
|
|
|
colour = TC_ORANGE;
|
2022-11-10 20:39:09 +00:00
|
|
|
} else {
|
|
|
|
str = STR_AI_SETTINGS_SETTING;
|
|
|
|
colour = TC_LIGHT_BLUE;
|
|
|
|
SetDParamStr(idx++, config_item.description);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0) {
|
2022-10-15 15:55:47 +00:00
|
|
|
DrawBoolButton(br.left, y + button_y_offset, current_value != 0, editable);
|
2022-11-10 20:39:09 +00:00
|
|
|
SetDParam(idx++, current_value == 0 ? STR_CONFIG_SETTING_OFF : STR_CONFIG_SETTING_ON);
|
|
|
|
} else {
|
|
|
|
if (config_item.complete_labels) {
|
2022-10-15 15:55:47 +00:00
|
|
|
DrawDropDownButton(br.left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && clicked_dropdown, editable);
|
2022-11-10 20:39:09 +00:00
|
|
|
} else {
|
2022-10-15 15:55:47 +00:00
|
|
|
DrawArrowButtons(br.left, y + button_y_offset, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + (this->clicked_increase != rtl) : 0, editable && current_value > config_item.min_value, editable && current_value < config_item.max_value);
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
2023-05-05 14:48:53 +00:00
|
|
|
auto config_iterator = config_item.labels.find(current_value);
|
|
|
|
if (config_iterator != config_item.labels.end()) {
|
2022-11-10 20:39:09 +00:00
|
|
|
SetDParam(idx++, STR_JUST_RAW_STRING);
|
2023-05-05 14:48:53 +00:00
|
|
|
SetDParamStr(idx++, config_iterator->second);
|
2022-11-10 20:39:09 +00:00
|
|
|
} else {
|
|
|
|
SetDParam(idx++, STR_JUST_INT);
|
|
|
|
SetDParam(idx++, current_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-15 15:55:47 +00:00
|
|
|
DrawString(tr.left, tr.right, y + text_y_offset, str, colour);
|
2022-11-10 20:39:09 +00:00
|
|
|
y += this->line_height;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnPaint() override
|
|
|
|
{
|
|
|
|
if (this->closing_dropdown) {
|
|
|
|
this->closing_dropdown = false;
|
|
|
|
this->clicked_dropdown = false;
|
|
|
|
}
|
|
|
|
this->DrawWidgets();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnClick(Point pt, int widget, int click_count) override
|
|
|
|
{
|
2023-04-25 17:43:45 +00:00
|
|
|
if (widget >= WID_GSC_TEXTFILE && widget < WID_GSC_TEXTFILE + TFT_CONTENT_END) {
|
2022-11-10 20:39:09 +00:00
|
|
|
if (GameConfig::GetConfig() == nullptr) return;
|
|
|
|
|
|
|
|
ShowScriptTextfileWindow((TextfileType)(widget - WID_GSC_TEXTFILE), (CompanyID)OWNER_DEITY);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (widget) {
|
|
|
|
case WID_GSC_GSLIST: {
|
|
|
|
this->InvalidateData();
|
2023-04-10 14:11:53 +00:00
|
|
|
if (click_count > 1 && UserIsAllowedToChangeGameScript()) ShowScriptListWindow((CompanyID)OWNER_DEITY, _ctrl_pressed);
|
2022-11-10 20:39:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WID_GSC_CHANGE: // choose other Game Script
|
2023-04-07 17:33:07 +00:00
|
|
|
ShowScriptListWindow((CompanyID)OWNER_DEITY, _ctrl_pressed);
|
2022-11-10 20:39:09 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WID_GSC_CONTENT_DOWNLOAD:
|
|
|
|
if (!_network_available) {
|
|
|
|
ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR);
|
|
|
|
} else {
|
|
|
|
ShowNetworkContentListWindow(nullptr, CONTENT_TYPE_GAME);
|
|
|
|
}
|
|
|
|
break;
|
2022-10-15 15:55:47 +00:00
|
|
|
|
2022-11-10 20:39:09 +00:00
|
|
|
case WID_GSC_SETTINGS: {
|
2023-05-03 10:17:52 +00:00
|
|
|
auto it = this->vscroll->GetScrolledItemFromWidget(this->visible_settings, pt.y, this, widget);
|
|
|
|
if (it == this->visible_settings.end()) break;
|
2022-11-10 20:39:09 +00:00
|
|
|
|
2023-05-03 10:17:52 +00:00
|
|
|
const ScriptConfigItem &config_item = **it;
|
2022-11-10 20:39:09 +00:00
|
|
|
if (!this->IsEditableItem(config_item)) return;
|
|
|
|
|
2023-05-03 10:17:52 +00:00
|
|
|
int num = it - this->visible_settings.begin();
|
2022-11-10 20:39:09 +00:00
|
|
|
if (this->clicked_row != num) {
|
2022-11-26 23:04:04 +00:00
|
|
|
this->DeleteChildWindows(WC_QUERY_STRING);
|
2022-11-10 20:39:09 +00:00
|
|
|
HideDropDownMenu(this);
|
|
|
|
this->clicked_row = num;
|
|
|
|
this->clicked_dropdown = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool bool_item = (config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0;
|
|
|
|
|
2023-05-03 10:17:52 +00:00
|
|
|
Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero);
|
2022-10-15 15:55:47 +00:00
|
|
|
int x = pt.x - r.left;
|
|
|
|
if (_current_text_dir == TD_RTL) x = r.Width() - 1 - x;
|
2022-11-10 20:39:09 +00:00
|
|
|
|
|
|
|
/* One of the arrows is clicked (or green/red rect in case of bool value) */
|
|
|
|
int old_val = this->gs_config->GetSetting(config_item.name);
|
|
|
|
if (!bool_item && IsInsideMM(x, 0, SETTING_BUTTON_WIDTH) && config_item.complete_labels) {
|
|
|
|
if (this->clicked_dropdown) {
|
|
|
|
/* unclick the dropdown */
|
|
|
|
HideDropDownMenu(this);
|
|
|
|
this->clicked_dropdown = false;
|
|
|
|
this->closing_dropdown = false;
|
|
|
|
} else {
|
2022-10-15 15:55:47 +00:00
|
|
|
int rel_y = (pt.y - r.top) % this->line_height;
|
2022-11-10 20:39:09 +00:00
|
|
|
|
|
|
|
Rect wi_rect;
|
|
|
|
wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
|
|
|
|
wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
|
|
|
|
wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
|
|
|
wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
|
|
|
|
|
|
|
|
/* If the mouse is still held but dragged outside of the dropdown list, keep the dropdown open */
|
|
|
|
if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
|
|
|
|
this->clicked_dropdown = true;
|
|
|
|
this->closing_dropdown = false;
|
|
|
|
|
|
|
|
DropDownList list;
|
|
|
|
for (int i = config_item.min_value; i <= config_item.max_value; i++) {
|
2023-05-05 14:48:53 +00:00
|
|
|
list.emplace_back(new DropDownListCharStringItem(config_item.labels.find(i)->second, i, false));
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
|
2023-04-11 19:07:50 +00:00
|
|
|
ShowDropDownListAt(this, std::move(list), old_val, -1, wi_rect, COLOUR_ORANGE);
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
|
|
|
|
int new_val = old_val;
|
|
|
|
if (bool_item) {
|
|
|
|
new_val = !new_val;
|
|
|
|
} else if (x >= SETTING_BUTTON_WIDTH / 2) {
|
|
|
|
/* Increase button clicked */
|
|
|
|
new_val += config_item.step_size;
|
|
|
|
if (new_val > config_item.max_value) new_val = config_item.max_value;
|
|
|
|
this->clicked_increase = true;
|
|
|
|
} else {
|
|
|
|
/* Decrease button clicked */
|
|
|
|
new_val -= config_item.step_size;
|
|
|
|
if (new_val < config_item.min_value) new_val = config_item.min_value;
|
|
|
|
this->clicked_increase = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_val != old_val) {
|
|
|
|
this->gs_config->SetSetting(config_item.name, new_val);
|
|
|
|
this->clicked_button = num;
|
|
|
|
this->timeout.SetInterval(150);
|
|
|
|
}
|
|
|
|
} else if (!bool_item && !config_item.complete_labels) {
|
|
|
|
/* Display a query box so users can enter a custom value. */
|
|
|
|
SetDParam(0, old_val);
|
2023-02-03 20:39:06 +00:00
|
|
|
ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, INT32_DIGITS_WITH_SIGN_AND_TERMINATION, this, CS_NUMERAL_SIGNED, QSF_NONE);
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
this->SetDirty();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WID_GSC_ACCEPT:
|
2022-11-26 23:04:04 +00:00
|
|
|
delete this;
|
2022-11-10 20:39:09 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WID_GSC_RESET:
|
|
|
|
this->gs_config->ResetEditableSettings(_game_mode == GM_MENU);
|
|
|
|
this->SetDirty();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-03 23:55:11 +00:00
|
|
|
void OnQueryTextFinished(char *str) override
|
2022-11-10 20:39:09 +00:00
|
|
|
{
|
|
|
|
if (StrEmpty(str)) return;
|
|
|
|
int32 value = atoi(str);
|
|
|
|
SetValue(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnDropdownSelect(int widget, int index) override
|
|
|
|
{
|
|
|
|
assert(this->clicked_dropdown);
|
|
|
|
SetValue(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override
|
|
|
|
{
|
|
|
|
/* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
|
|
|
|
* the same dropdown button was clicked again, and then not open the dropdown again.
|
|
|
|
* So, we only remember that it was closed, and process it on the next OnPaint, which is
|
|
|
|
* after OnClick. */
|
|
|
|
assert(this->clicked_dropdown);
|
|
|
|
this->closing_dropdown = true;
|
|
|
|
this->SetDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnResize() override
|
|
|
|
{
|
|
|
|
this->vscroll->SetCapacityFromWidget(this, WID_GSC_SETTINGS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnRealtimeTick(uint delta_ms) override
|
|
|
|
{
|
|
|
|
if (this->timeout.Elapsed(delta_ms)) {
|
|
|
|
this->clicked_button = -1;
|
|
|
|
this->SetDirty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Some data on this window has become invalid.
|
|
|
|
* @param data Information about the changed data.
|
|
|
|
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
|
|
|
*/
|
|
|
|
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
|
|
|
{
|
|
|
|
if (!gui_scope) return;
|
|
|
|
|
2022-11-26 23:04:04 +00:00
|
|
|
this->gs_config = GameConfig::GetConfig();
|
|
|
|
|
|
|
|
this->SetWidgetDisabledState(WID_GSC_CHANGE, !UserIsAllowedToChangeGameScript() || !IsEditable());
|
2022-11-10 20:39:09 +00:00
|
|
|
|
2023-04-25 17:43:45 +00:00
|
|
|
for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
|
2022-11-10 20:39:09 +00:00
|
|
|
this->SetWidgetDisabledState(WID_GSC_TEXTFILE + tft, GameConfig::GetConfig()->GetTextfile(tft, (CompanyID)OWNER_DEITY) == nullptr);
|
|
|
|
}
|
|
|
|
this->RebuildVisibleSettings();
|
|
|
|
HideDropDownMenu(this);
|
2022-11-26 23:04:04 +00:00
|
|
|
this->DeleteChildWindows(WC_QUERY_STRING);
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
bool IsEditableItem(const ScriptConfigItem &config_item) const
|
|
|
|
{
|
2022-11-11 22:48:07 +00:00
|
|
|
return _game_mode == GM_MENU
|
|
|
|
|| _game_mode == GM_EDITOR
|
|
|
|
|| (config_item.flags & SCRIPTCONFIG_INGAME) != 0
|
|
|
|
|| _settings_client.gui.ai_developer_tools;
|
2022-11-10 20:39:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetValue(int value)
|
|
|
|
{
|
2023-05-09 20:22:36 +00:00
|
|
|
const ScriptConfigItem &config_item = *this->visible_settings[this->clicked_row];
|
2022-11-10 20:39:09 +00:00
|
|
|
if (_game_mode == GM_NORMAL && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
|
|
|
this->gs_config->SetSetting(config_item.name, value);
|
|
|
|
this->SetDirty();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Open the GS config window. */
|
|
|
|
void ShowGSConfigWindow()
|
|
|
|
{
|
2022-11-26 23:04:04 +00:00
|
|
|
DeleteWindowByClass(WC_GAME_OPTIONS);
|
2022-11-10 20:39:09 +00:00
|
|
|
new GSConfigWindow();
|
|
|
|
}
|