OpenTTD Source 15.0-beta2
script_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
7
10#include "../stdafx.h"
11#include "../table/sprites.h"
12#include "../error.h"
13#include "../settings_gui.h"
14#include "../querystring_gui.h"
15#include "../stringfilter_type.h"
16#include "../company_base.h"
17#include "../company_gui.h"
18#include "../dropdown_type.h"
19#include "../dropdown_func.h"
20#include "../window_func.h"
21#include "../network/network.h"
22#include "../hotkeys.h"
23#include "../company_cmd.h"
24#include "../misc_cmd.h"
25#include "../strings_func.h"
26#include "../timer/timer.h"
27#include "../timer/timer_window.h"
28
29#include "script_gui.h"
30#include "script_log.hpp"
31#include "script_scanner.hpp"
32#include "script_config.hpp"
33#include "../ai/ai.hpp"
34#include "../ai/ai_config.hpp"
35#include "../ai/ai_info.hpp"
36#include "../ai/ai_instance.hpp"
37#include "../game/game.hpp"
38#include "../game/game_config.hpp"
39#include "../game/game_info.hpp"
40#include "../game/game_instance.hpp"
41
42#include "table/strings.h"
43
44#include "../safeguards.h"
45
46
47static ScriptConfig *GetConfig(CompanyID slot)
48{
49 if (slot == OWNER_DEITY) return GameConfig::GetConfig();
50 return AIConfig::GetConfig(slot);
51}
52
56struct ScriptListWindow : public Window {
57 const ScriptInfoList *info_list = nullptr;
58 int selected = -1;
60 int line_height = 0;
61 Scrollbar *vscroll = nullptr;
62 bool show_all = false;
63
72 {
73 if (slot == OWNER_DEITY) {
74 this->info_list = this->show_all ? Game::GetInfoList() : Game::GetUniqueInfoList();
75 } else {
76 this->info_list = this->show_all ? AI::GetInfoList() : AI::GetUniqueInfoList();
77 }
78
79 this->CreateNestedTree();
80 this->vscroll = this->GetScrollbar(WID_SCRL_SCROLLBAR);
81 this->FinishInitNested(); // Initializes 'this->line_height' as side effect.
82
83 this->vscroll->SetCount(this->info_list->size() + 1);
84
85 /* Try if we can find the currently selected AI */
86 if (GetConfig(slot)->HasScript()) {
87 ScriptInfo *info = GetConfig(slot)->GetInfo();
88 int i = 0;
89 for (const auto &item : *this->info_list) {
90 if (item.second == info) {
91 this->selected = i;
92 break;
93 }
94
95 i++;
96 }
97 }
98 }
99
100 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
101 {
102 if (widget != WID_SCRL_CAPTION) return this->Window::GetWidgetString(widget, stringid);
103
104 return GetString(STR_AI_LIST_CAPTION, (this->slot == OWNER_DEITY) ? STR_AI_LIST_CAPTION_GAMESCRIPT : STR_AI_LIST_CAPTION_AI);
105 }
106
107 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
108 {
109 if (widget != WID_SCRL_LIST) return;
110
111 this->line_height = GetCharacterHeight(FS_NORMAL) + padding.height;
112
113 resize.width = 1;
114 resize.height = this->line_height;
115 size.height = 5 * this->line_height;
116 }
117
118 void DrawWidget(const Rect &r, WidgetID widget) const override
119 {
120 switch (widget) {
121 case WID_SCRL_LIST: {
122 /* Draw a list of all available Scripts. */
123 Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
124 /* First AI in the list is hardcoded to random */
125 if (this->vscroll->IsVisible(0)) {
126 DrawString(tr, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_ORANGE);
127 tr.top += this->line_height;
128 }
129 int i = 0;
130 for (const auto &item : *this->info_list) {
131 i++;
132 if (this->vscroll->IsVisible(i)) {
133 DrawString(tr, this->show_all ? GetString(STR_AI_CONFIG_NAME_VERSION, item.second->GetName(), item.second->GetVersion()) : item.second->GetName(), (this->selected == i - 1) ? TC_WHITE : TC_ORANGE);
134 tr.top += this->line_height;
135 }
136 }
137 break;
138 }
139 case WID_SCRL_INFO_BG: {
140 ScriptInfo *selected_info = nullptr;
141 int i = 0;
142 for (const auto &item : *this->info_list) {
143 i++;
144 if (this->selected == i - 1) selected_info = static_cast<ScriptInfo *>(item.second);
145 }
146 /* Some info about the currently selected Script. */
147 if (selected_info != nullptr) {
149 DrawString(tr, GetString(STR_AI_LIST_AUTHOR, selected_info->GetAuthor()));
151 DrawString(tr, GetString(STR_AI_LIST_VERSION, selected_info->GetVersion()));
153 if (!selected_info->GetURL().empty()) {
154 DrawString(tr, GetString(STR_AI_LIST_URL, selected_info->GetURL()));
156 }
157 DrawStringMultiLine(tr, selected_info->GetDescription(), TC_WHITE);
158 }
159 break;
160 }
161 }
162 }
163
168 {
169 if (this->selected == -1) {
170 GetConfig(slot)->Change(std::nullopt);
171 } else {
172 ScriptInfoList::const_iterator it = this->info_list->cbegin();
173 std::advance(it, this->selected);
174 GetConfig(slot)->Change(it->second->GetName(), it->second->GetVersion());
175 }
176 if (_game_mode == GM_EDITOR) {
177 if (slot == OWNER_DEITY) {
178 if (Game::GetInstance() != nullptr) Game::ResetInstance();
180 } else {
182 if (c != nullptr && c->ai_instance != nullptr) {
183 c->ai_instance.reset();
185 }
186 }
187 }
193 }
194
195 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
196 {
197 switch (widget) {
198 case WID_SCRL_LIST: { // Select one of the Scripts
199 int sel = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCRL_LIST) - 1;
200 if (sel < (int)this->info_list->size()) {
201 this->selected = sel;
202 this->SetDirty();
203 if (click_count > 1) {
204 this->ChangeScript();
205 this->Close();
206 }
207 }
208 break;
209 }
210
211 case WID_SCRL_ACCEPT: {
212 this->ChangeScript();
213 this->Close();
214 break;
215 }
216
217 case WID_SCRL_CANCEL:
218 this->Close();
219 break;
220 }
221 }
222
223 void OnResize() override
224 {
225 this->vscroll->SetCapacityFromWidget(this, WID_SCRL_LIST);
226 }
227
233 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
234 {
235 if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot)) {
236 this->Close();
237 return;
238 }
239
240 if (!gui_scope) return;
241
242 this->vscroll->SetCount(this->info_list->size() + 1);
243
244 /* selected goes from -1 .. length of ai list - 1. */
245 this->selected = std::min(this->selected, this->vscroll->GetCount() - 2);
246 }
247};
248
252 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
253 NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_SCRL_CAPTION),
254 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
255 EndContainer(),
257 NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_SCRL_LIST), SetMinimalSize(188, 112), SetFill(1, 1), SetResize(1, 1), SetMatrixDataTip(1, 0, STR_AI_LIST_TOOLTIP), SetScrollbar(WID_SCRL_SCROLLBAR),
259 EndContainer(),
261 EndContainer(),
264 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRL_ACCEPT), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_LIST_ACCEPT, STR_AI_LIST_ACCEPT_TOOLTIP),
265 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRL_CANCEL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_LIST_CANCEL, STR_AI_LIST_CANCEL_TOOLTIP),
266 EndContainer(),
267 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
268 EndContainer(),
269};
270
273 WDP_CENTER, "settings_script_list", 200, 234,
275 {},
277);
278
284void ShowScriptListWindow(CompanyID slot, bool show_all)
285{
287 new ScriptListWindow(_script_list_desc, slot, show_all);
288}
289
290
297 int clicked_button = -1;
298 bool clicked_increase = false;
299 bool clicked_dropdown = false;
300 bool closing_dropdown = false;
301 int clicked_row = 0;
302 int line_height = 0;
303 Scrollbar *vscroll = nullptr;
304 typedef std::vector<const ScriptConfigItem *> VisibleSettingsList;
306
313 {
314 this->CreateNestedTree();
315 this->vscroll = this->GetScrollbar(WID_SCRS_SCROLLBAR);
316 this->FinishInitNested(slot); // Initializes 'this->line_height' as side effect.
317
318 this->OnInvalidateData();
319 }
320
327 {
328 visible_settings.clear();
329
330 for (const auto &item : *this->script_config->GetConfigList()) {
331 bool no_hide = !item.flags.Test(ScriptConfigFlag::Developer);
332 if (no_hide || _settings_client.gui.ai_developer_tools) {
333 visible_settings.push_back(&item);
334 }
335 }
336
337 this->vscroll->SetCount(this->visible_settings.size());
338 }
339
340 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
341 {
342 if (widget != WID_SCRS_CAPTION) return this->Window::GetWidgetString(widget, stringid);
343
344 return GetString((this->slot == OWNER_DEITY) ? STR_AI_SETTINGS_CAPTION_GAMESCRIPT : STR_AI_SETTINGS_CAPTION_AI);
345 }
346
347 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
348 {
349 if (widget != WID_SCRS_BACKGROUND) return;
350
351 this->line_height = std::max(SETTING_BUTTON_HEIGHT, GetCharacterHeight(FS_NORMAL)) + padding.height;
352
353 resize.width = 1;
354 resize.height = this->line_height;
355 size.height = 5 * this->line_height;
356 }
357
358 void DrawWidget(const Rect &r, WidgetID widget) const override
359 {
360 if (widget != WID_SCRS_BACKGROUND) return;
361
362 Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
363 bool rtl = _current_text_dir == TD_RTL;
364 Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
366
367 int y = r.top;
368 int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
369 int text_y_offset = (this->line_height - GetCharacterHeight(FS_NORMAL)) / 2;
370
371 const auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->visible_settings);
372 for (auto it = first; it != last; ++it) {
373 const ScriptConfigItem &config_item = **it;
374 int current_value = this->script_config->GetSetting(config_item.name);
375 bool editable = this->IsEditableItem(config_item);
376
377 if (config_item.flags.Test(ScriptConfigFlag::Boolean)) {
378 DrawBoolButton(br.left, y + button_y_offset, current_value != 0, editable);
379 } else {
380 int i = static_cast<int>(std::distance(std::begin(this->visible_settings), it));
381 if (config_item.complete_labels) {
382 DrawDropDownButton(br.left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && clicked_dropdown, editable);
383 } else {
384 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);
385 }
386 }
387
388 DrawString(tr.left, tr.right, y + text_y_offset, config_item.GetString(current_value), config_item.GetColour());
389 y += this->line_height;
390 }
391 }
392
393 void OnPaint() override
394 {
395 if (this->closing_dropdown) {
396 this->closing_dropdown = false;
397 this->clicked_dropdown = false;
398 }
399 this->DrawWidgets();
400 }
401
402 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
403 {
404 switch (widget) {
405 case WID_SCRS_BACKGROUND: {
406 auto it = this->vscroll->GetScrolledItemFromWidget(this->visible_settings, pt.y, this, widget);
407 if (it == this->visible_settings.end()) break;
408
409 const ScriptConfigItem &config_item = **it;
410 if (!this->IsEditableItem(config_item)) return;
411
412 int num = it - this->visible_settings.begin();
413 if (this->clicked_row != num) {
416 this->clicked_row = num;
417 this->clicked_dropdown = false;
418 }
419
420 bool bool_item = config_item.flags.Test(ScriptConfigFlag::Boolean);
421
422 Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero);
423 int x = pt.x - r.left;
424 if (_current_text_dir == TD_RTL) x = r.Width() - 1 - x;
425
426 /* One of the arrows is clicked (or green/red rect in case of bool value) */
427 int old_val = this->script_config->GetSetting(config_item.name);
428 if (!bool_item && IsInsideMM(x, 0, SETTING_BUTTON_WIDTH) && config_item.complete_labels) {
429 if (this->clicked_dropdown) {
430 /* unclick the dropdown */
432 this->clicked_dropdown = false;
433 this->closing_dropdown = false;
434 } else {
435 int rel_y = (pt.y - r.top) % this->line_height;
436
437 Rect wi_rect;
438 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
439 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
440 wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
441 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
442
443 /* If the mouse is still held but dragged outside of the dropdown list, keep the dropdown open */
444 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
445 this->clicked_dropdown = true;
446 this->closing_dropdown = false;
447
448 DropDownList list;
449 for (int i = config_item.min_value; i <= config_item.max_value; i++) {
450 list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_RAW_STRING, config_item.labels.find(i)->second), i));
451 }
452
453 ShowDropDownListAt(this, std::move(list), old_val, WID_SCRS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
454 }
455 }
456 } else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
457 int new_val = old_val;
458 if (bool_item) {
459 new_val = !new_val;
460 } else if (x >= SETTING_BUTTON_WIDTH / 2) {
461 /* Increase button clicked */
462 new_val += config_item.step_size;
463 if (new_val > config_item.max_value) new_val = config_item.max_value;
464 this->clicked_increase = true;
465 } else {
466 /* Decrease button clicked */
467 new_val -= config_item.step_size;
468 if (new_val < config_item.min_value) new_val = config_item.min_value;
469 this->clicked_increase = false;
470 }
471
472 if (new_val != old_val) {
473 this->script_config->SetSetting(config_item.name, new_val);
474 this->clicked_button = num;
475 this->unclick_timeout.Reset();
476 }
477 } else if (!bool_item && !config_item.complete_labels) {
478 /* Display a query box so users can enter a custom value. */
479 ShowQueryString(GetString(STR_JUST_INT, old_val), STR_CONFIG_SETTING_QUERY_CAPTION, INT32_DIGITS_WITH_SIGN_AND_TERMINATION, this, CS_NUMERAL_SIGNED, {});
480 }
481 this->SetDirty();
482 break;
483 }
484
485 case WID_SCRS_ACCEPT:
486 this->Close();
487 break;
488
489 case WID_SCRS_RESET:
490 this->script_config->ResetEditableSettings(_game_mode == GM_MENU || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot)));
491 this->SetDirty();
492 break;
493 }
494 }
495
496 void OnQueryTextFinished(std::optional<std::string> str) override
497 {
498 if (!str.has_value() || str->empty()) return;
499 int32_t value = atoi(str->c_str());
500
501 SetValue(value);
502 }
503
504 void OnDropdownSelect(WidgetID widget, int index) override
505 {
506 if (widget != WID_SCRS_SETTING_DROPDOWN) return;
507 assert(this->clicked_dropdown);
508 SetValue(index);
509 }
510
511 void OnDropdownClose(Point, WidgetID widget, int, bool) override
512 {
513 if (widget != WID_SCRS_SETTING_DROPDOWN) return;
514 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
515 * the same dropdown button was clicked again, and then not open the dropdown again.
516 * So, we only remember that it was closed, and process it on the next OnPaint, which is
517 * after OnClick. */
518 assert(this->clicked_dropdown);
519 this->closing_dropdown = true;
520 this->SetDirty();
521 }
522
523 void OnResize() override
524 {
525 this->vscroll->SetCapacityFromWidget(this, WID_SCRS_BACKGROUND);
526 }
527
529 TimeoutTimer<TimerWindow> unclick_timeout = {std::chrono::milliseconds(150), [this]() {
530 this->clicked_button = -1;
531 this->SetDirty();
532 }};
533
539 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
540 {
541 this->script_config = GetConfig(this->slot);
542 if (this->script_config->GetConfigList()->empty()) this->Close();
546 }
547
548private:
549 bool IsEditableItem(const ScriptConfigItem &config_item) const
550 {
551 return _game_mode == GM_MENU
552 || _game_mode == GM_EDITOR
553 || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot))
554 || config_item.flags.Test(ScriptConfigFlag::InGame)
556 }
557
558 void SetValue(int value)
559 {
560 const ScriptConfigItem &config_item = *this->visible_settings[this->clicked_row];
561 if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && !config_item.flags.Test(ScriptConfigFlag::InGame)) return;
562 this->script_config->SetSetting(config_item.name, value);
563 this->SetDirty();
564 }
565};
566
570 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
571 NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_SCRS_CAPTION),
572 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
573 EndContainer(),
577 EndContainer(),
580 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRS_ACCEPT), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_SETTINGS_CLOSE),
581 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRS_RESET), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_AI_SETTINGS_RESET),
582 EndContainer(),
583 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
584 EndContainer(),
585};
586
589 WDP_CENTER, "settings_script", 500, 208,
591 {},
593);
594
605
606
610
612 {
613 this->ConstructWindow();
614 this->OnInvalidateData();
615 }
616
617 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
618 {
619 if (widget == WID_TF_CAPTION) {
620 return GetString(stringid, (slot == OWNER_DEITY) ? STR_CONTENT_TYPE_GAME_SCRIPT : STR_CONTENT_TYPE_AI, GetConfig(slot)->GetInfo()->GetName());
621 }
622
623 return this->Window::GetWidgetString(widget, stringid);
624 }
625
626 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
627 {
628 auto textfile = GetConfig(slot)->GetTextfile(file_type, slot);
629 if (!textfile.has_value()) {
630 this->Close();
631 } else {
632 this->LoadTextfile(textfile.value(), (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR);
633 }
634 }
635};
636
643{
644 CloseWindowById(WC_TEXTFILE, file_type);
645 new ScriptTextfileWindow(file_type, slot);
646}
647
648
657static bool SetScriptButtonColour(NWidgetCore &button, bool dead, bool paused)
658{
659 /* Dead scripts are indicated with red background and
660 * paused scripts are indicated with yellow background. */
661 Colours colour = dead ? COLOUR_RED :
662 (paused ? COLOUR_YELLOW : COLOUR_GREY);
663 if (button.colour != colour) {
664 button.colour = colour;
665 return true;
666 }
667 return false;
668}
669
673struct ScriptDebugWindow : public Window {
674 static const uint MAX_BREAK_STR_STRING_LENGTH = 256;
675
682
683 static inline FilterState initial_state = {
684 "",
685 CompanyID::Invalid(),
686 true,
687 false,
688 };
689
691 bool autoscroll = true;
692 bool show_break_box = false;
695 int highlight_row = -1;
696 Scrollbar *vscroll = nullptr;
697 Scrollbar *hscroll = nullptr;
698 FilterState filter{};
699
700 ScriptLogTypes::LogData &GetLogData() const
701 {
702 if (this->filter.script_debug_company == OWNER_DEITY) return Game::GetInstance()->GetLogData();
703 return Company::Get(this->filter.script_debug_company)->ai_instance->GetLogData();
704 }
705
710 bool IsDead() const
711 {
712 if (this->filter.script_debug_company == OWNER_DEITY) {
714 return game == nullptr || game->IsDead();
715 }
716 return !Company::IsValidAiID(this->filter.script_debug_company) || Company::Get(this->filter.script_debug_company)->ai_instance->IsDead();
717 }
718
724 bool IsValidDebugCompany(CompanyID company) const
725 {
726 switch (company.base()) {
727 case CompanyID::Invalid().base(): return false;
728 case OWNER_DEITY.base(): return Game::GetInstance() != nullptr;
729 default: return Company::IsValidAiID(company);
730 }
731 }
732
738 {
739 /* Check if the currently selected company is still active. */
740 if (this->IsValidDebugCompany(this->filter.script_debug_company)) return;
741
742 this->filter.script_debug_company = CompanyID::Invalid();
743
744 for (const Company *c : Company::Iterate()) {
745 if (c->is_ai) {
746 ChangeToScript(c->index);
747 return;
748 }
749 }
750
751 /* If no AI is available, see if there is a game script. */
753 }
754
761 {
762 this->filter = ScriptDebugWindow::initial_state;
763 this->break_string_filter = {&this->filter.case_sensitive_break_check, false};
764
765 this->CreateNestedTree();
766 this->vscroll = this->GetScrollbar(WID_SCRD_VSCROLLBAR);
767 this->hscroll = this->GetScrollbar(WID_SCRD_HSCROLLBAR);
768 this->FinishInitNested(number);
769
771
772 this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar
773
774 /* Restore the break string value from static variable, and enable the filter. */
775 this->break_editbox.text.Assign(this->filter.break_string);
777
778 if (show_company == CompanyID::Invalid()) {
780 } else {
781 this->ChangeToScript(show_company);
782 }
783 }
784
785 void OnInit() override
786 {
787 this->show_break_box = _settings_client.gui.ai_developer_tools;
788 this->GetWidget<NWidgetStacked>(WID_SCRD_BREAK_STRING_WIDGETS)->SetDisplayedPlane(this->show_break_box ? 0 : SZSP_HORIZONTAL);
789 if (!this->show_break_box) this->filter.break_check_enabled = false;
791
792 this->InvalidateData(-1);
793 }
794
796 {
797 ScriptDebugWindow::initial_state = this->filter;
798 }
799
800 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
801 {
802 if (widget == WID_SCRD_LOG_PANEL) {
804 size.height = 14 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
805 }
806 }
807
808 void OnPaint() override
809 {
811 this->UpdateLogScroll();
812
813 /* Draw standard stuff */
814 this->DrawWidgets();
815 }
816
817 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
818 {
819 if (widget != WID_SCRD_NAME_TEXT) return this->Window::GetWidgetString(widget, stringid);
820
821 if (this->filter.script_debug_company == OWNER_DEITY) {
822 const GameInfo *info = Game::GetInfo();
823 assert(info != nullptr);
824 return GetString(STR_AI_DEBUG_NAME_AND_VERSION, info->GetName(), info->GetVersion());
825 }
826 if (this->filter.script_debug_company == CompanyID::Invalid() || !Company::IsValidAiID(this->filter.script_debug_company)) {
827 return {};
828 }
829
830 const AIInfo *info = Company::Get(this->filter.script_debug_company)->ai_info;
831 return GetString(STR_AI_DEBUG_NAME_AND_VERSION, info->GetName(), info->GetVersion());
832 }
833
834 void DrawWidget(const Rect &r, WidgetID widget) const override
835 {
836 switch (widget) {
838 this->DrawWidgetLog(r);
839 break;
840
841 default:
842 if (IsInsideBS(widget, WID_SCRD_COMPANY_BUTTON_START, MAX_COMPANIES)) {
844 }
845 break;
846 }
847 }
848
855 void DrawWidgetCompanyButton(const Rect &r, WidgetID widget, int start) const
856 {
857 if (this->IsWidgetDisabled(widget)) return;
858 CompanyID cid = (CompanyID)(widget - start);
859 Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
860 DrawCompanyIcon(cid, CenterBounds(r.left, r.right, sprite_size.width), CenterBounds(r.top, r.bottom, sprite_size.height));
861 }
862
867 void DrawWidgetLog(const Rect &r) const
868 {
869 if (this->filter.script_debug_company == CompanyID::Invalid()) return;
870
871 const ScriptLogTypes::LogData &log = this->GetLogData();
872 if (log.empty()) return;
873
874 Rect fr = r.Shrink(WidgetDimensions::scaled.framerect);
875
876 /* Setup a clipping rectangle... */
877 DrawPixelInfo tmp_dpi;
878 if (!FillDrawPixelInfo(&tmp_dpi, fr)) return;
879 /* ...but keep coordinates relative to the window. */
880 tmp_dpi.left += fr.left;
881 tmp_dpi.top += fr.top;
882
883 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
884
885 fr = ScrollRect(fr, *this->hscroll, 1);
886
887 auto [first, last] = this->vscroll->GetVisibleRangeIterators(log);
888 for (auto it = first; it != last; ++it) {
889 const ScriptLogTypes::LogLine &line = *it;
890
891 TextColour colour;
892 switch (line.type) {
893 case ScriptLogTypes::LOG_SQ_INFO: colour = TC_BLACK; break;
894 case ScriptLogTypes::LOG_SQ_ERROR: colour = TC_WHITE; break;
895 case ScriptLogTypes::LOG_INFO: colour = TC_BLACK; break;
896 case ScriptLogTypes::LOG_WARNING: colour = TC_YELLOW; break;
897 case ScriptLogTypes::LOG_ERROR: colour = TC_RED; break;
898 default: colour = TC_BLACK; break;
899 }
900
901 /* Check if the current line should be highlighted */
902 if (std::distance(std::begin(log), it) == this->highlight_row) {
903 fr.bottom = fr.top + this->resize.step_height - 1;
905 if (colour == TC_BLACK) colour = TC_WHITE; // Make black text readable by inverting it to white.
906 }
907
908 DrawString(fr, line.text, colour, SA_LEFT | SA_FORCE);
909 fr.top += this->resize.step_height;
910 }
911 }
912
917 {
918 this->SetWidgetsDisabledState(this->filter.script_debug_company == CompanyID::Invalid(), WID_SCRD_VSCROLLBAR, WID_SCRD_HSCROLLBAR);
919 if (this->filter.script_debug_company == CompanyID::Invalid()) return;
920
921 ScriptLogTypes::LogData &log = this->GetLogData();
922
923 int scroll_count = (int)log.size();
924 if (this->vscroll->GetCount() != scroll_count) {
925 this->vscroll->SetCount(scroll_count);
926
927 /* We need a repaint */
929 }
930
931 if (log.empty()) return;
932
933 /* Detect when the user scrolls the window. Enable autoscroll when the bottom-most line becomes visible. */
934 if (this->last_vscroll_pos != this->vscroll->GetPosition()) {
935 this->autoscroll = this->vscroll->GetPosition() + this->vscroll->GetCapacity() >= (int)log.size();
936 }
937
938 if (this->autoscroll && this->vscroll->SetPosition((int)log.size())) {
939 /* We need a repaint */
942 }
943
944 this->last_vscroll_pos = this->vscroll->GetPosition();
945 }
946
951 {
952 /* Update company buttons */
953 for (CompanyID i = CompanyID::Begin(); i < MAX_COMPANIES; ++i) {
954 /* Mark dead/paused AIs by setting the background colour. */
955 bool valid = Company::IsValidAiID(i);
956 bool dead = valid && Company::Get(i)->ai_instance->IsDead();
957 bool paused = valid && Company::Get(i)->ai_instance->IsPaused();
958
959 NWidgetCore *button = this->GetWidget<NWidgetCore>(WID_SCRD_COMPANY_BUTTON_START + i);
960 button->SetDisabled(!valid);
961 button->SetLowered(this->filter.script_debug_company == i);
962 SetScriptButtonColour(*button, dead, paused);
963 }
964 }
965
970 {
972 bool valid = game != nullptr;
973 bool dead = valid && game->IsDead();
974 bool paused = valid && game->IsPaused();
975
976 NWidgetCore *button = this->GetWidget<NWidgetCore>(WID_SCRD_SCRIPT_GAME);
977 button->SetDisabled(!valid);
978 button->SetLowered(this->filter.script_debug_company == OWNER_DEITY);
979 SetScriptButtonColour(*button, dead, paused);
980 }
981
987 void ChangeToScript(CompanyID show_script, bool new_window = false)
988 {
989 if (!this->IsValidDebugCompany(show_script)) return;
990
991 if (new_window) {
992 ScriptDebugWindow::initial_state = this->filter;
993 ShowScriptDebugWindow(show_script, true);
994 return;
995 }
996
997 this->filter.script_debug_company = show_script;
998
999 this->highlight_row = -1; // The highlight of one Script make little sense for another Script.
1000
1001 /* Close AI settings window to prevent confusion */
1003
1004 this->InvalidateData(-1);
1005
1006 this->autoscroll = true;
1007 this->last_vscroll_pos = this->vscroll->GetPosition();
1008 }
1009
1010 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1011 {
1012 /* Also called for hotkeys, so check for disabledness */
1013 if (this->IsWidgetDisabled(widget)) return;
1014
1015 /* Check which button is clicked */
1018 }
1019
1020 switch (widget) {
1023 break;
1024
1026 if (this->filter.script_debug_company == OWNER_DEITY) break;
1027 /* First kill the company of the AI, then start a new one. This should start the current AI again */
1030 break;
1031
1032 case WID_SCRD_SETTINGS:
1034 break;
1035
1037 this->filter.break_check_enabled = !this->filter.break_check_enabled;
1038 this->InvalidateData(-1);
1039 break;
1040
1042 this->filter.case_sensitive_break_check = !this->filter.case_sensitive_break_check;
1043 this->InvalidateData(-1);
1044 break;
1045
1047 /* Unpause current AI / game script and mark the corresponding script button dirty. */
1048 if (!this->IsDead()) {
1049 if (this->filter.script_debug_company == OWNER_DEITY) {
1050 Game::Unpause();
1051 } else {
1052 AI::Unpause(this->filter.script_debug_company);
1053 }
1054 }
1055
1056 /* If the last AI/Game Script is unpaused, unpause the game too. */
1058 bool all_unpaused = !Game::IsPaused();
1059 if (all_unpaused) {
1060 for (const Company *c : Company::Iterate()) {
1061 if (c->is_ai && AI::IsPaused(c->index)) {
1062 all_unpaused = false;
1063 break;
1064 }
1065 }
1066 if (all_unpaused) {
1067 /* All scripts have been unpaused => unpause the game. */
1069 }
1070 }
1071 }
1072
1073 this->highlight_row = -1;
1074 this->InvalidateData(-1);
1075 break;
1076 }
1077 }
1078
1079 void OnEditboxChanged(WidgetID wid) override
1080 {
1081 if (wid != WID_SCRD_BREAK_STR_EDIT_BOX) return;
1082
1083 /* Save the current string to static member so it can be restored next time the window is opened. */
1084 this->filter.break_string = this->break_editbox.text.GetText();
1086 }
1087
1094 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1095 {
1096 if (this->show_break_box != _settings_client.gui.ai_developer_tools) this->ReInit();
1097
1098 /* If the log message is related to the active company tab, check the break string.
1099 * This needs to be done in gameloop-scope, so the AI is suspended immediately. */
1100 if (!gui_scope && data == this->filter.script_debug_company &&
1101 this->IsValidDebugCompany(this->filter.script_debug_company) &&
1102 this->filter.break_check_enabled && !this->break_string_filter.IsEmpty()) {
1103 /* Get the log instance of the active company */
1104 ScriptLogTypes::LogData &log = this->GetLogData();
1105
1106 if (!log.empty()) {
1108 this->break_string_filter.AddLine(log.back().text);
1109 if (this->break_string_filter.GetState()) {
1110 /* Pause execution of script. */
1111 if (!this->IsDead()) {
1112 if (this->filter.script_debug_company == OWNER_DEITY) {
1113 Game::Pause();
1114 } else {
1115 AI::Pause(this->filter.script_debug_company);
1116 }
1117 }
1118
1119 /* Pause the game. */
1122 }
1123
1124 /* Highlight row that matched */
1125 this->highlight_row = (int)(log.size() - 1);
1126 }
1127 }
1128 }
1129
1130 if (!gui_scope) return;
1131
1133
1134 uint max_width = 0;
1135 if (this->filter.script_debug_company != CompanyID::Invalid()) {
1136 for (auto &line : this->GetLogData()) {
1137 if (line.width == 0 || data == -1) line.width = GetStringBoundingBox(line.text).width;
1138 max_width = std::max(max_width, line.width);
1139 }
1140 }
1141
1142 this->vscroll->SetCount(this->filter.script_debug_company != CompanyID::Invalid() ? this->GetLogData().size() : 0);
1143 this->hscroll->SetCount(max_width + WidgetDimensions::scaled.frametext.Horizontal());
1144
1145 this->UpdateAIButtonsState();
1146 this->UpdateGSButtonState();
1147
1150
1151 this->SetWidgetDisabledState(WID_SCRD_SETTINGS, this->filter.script_debug_company == CompanyID::Invalid() ||
1152 GetConfig(this->filter.script_debug_company)->GetConfigList()->empty());
1155 this->filter.script_debug_company == CompanyID::Invalid() ||
1156 this->filter.script_debug_company == OWNER_DEITY ||
1157 this->filter.script_debug_company == _local_company);
1158 this->SetWidgetDisabledState(WID_SCRD_CONTINUE_BTN, this->filter.script_debug_company == CompanyID::Invalid() ||
1159 (this->filter.script_debug_company == OWNER_DEITY ? !Game::IsPaused() : !AI::IsPaused(this->filter.script_debug_company)));
1160 }
1161
1162 void OnResize() override
1163 {
1164 this->vscroll->SetCapacityFromWidget(this, WID_SCRD_LOG_PANEL, WidgetDimensions::scaled.framerect.Vertical());
1165 this->hscroll->SetCapacityFromWidget(this, WID_SCRD_LOG_PANEL, WidgetDimensions::scaled.framerect.Horizontal());
1166 }
1167
1174 {
1175 if (_game_mode != GM_NORMAL) return ES_NOT_HANDLED;
1176 Window *w = ShowScriptDebugWindow(CompanyID::Invalid());
1177 if (w == nullptr) return ES_NOT_HANDLED;
1178 return w->OnHotkey(hotkey);
1179 }
1180
1181 static inline HotkeyList hotkeys{"aidebug", {
1182 Hotkey('1', "company_1", WID_SCRD_COMPANY_BUTTON_START),
1183 Hotkey('2', "company_2", WID_SCRD_COMPANY_BUTTON_START + 1),
1184 Hotkey('3', "company_3", WID_SCRD_COMPANY_BUTTON_START + 2),
1185 Hotkey('4', "company_4", WID_SCRD_COMPANY_BUTTON_START + 3),
1186 Hotkey('5', "company_5", WID_SCRD_COMPANY_BUTTON_START + 4),
1187 Hotkey('6', "company_6", WID_SCRD_COMPANY_BUTTON_START + 5),
1188 Hotkey('7', "company_7", WID_SCRD_COMPANY_BUTTON_START + 6),
1189 Hotkey('8', "company_8", WID_SCRD_COMPANY_BUTTON_START + 7),
1190 Hotkey('9', "company_9", WID_SCRD_COMPANY_BUTTON_START + 8),
1191 Hotkey(0, "company_10", WID_SCRD_COMPANY_BUTTON_START + 9),
1192 Hotkey(0, "company_11", WID_SCRD_COMPANY_BUTTON_START + 10),
1193 Hotkey(0, "company_12", WID_SCRD_COMPANY_BUTTON_START + 11),
1194 Hotkey(0, "company_13", WID_SCRD_COMPANY_BUTTON_START + 12),
1195 Hotkey(0, "company_14", WID_SCRD_COMPANY_BUTTON_START + 13),
1196 Hotkey(0, "company_15", WID_SCRD_COMPANY_BUTTON_START + 14),
1197 Hotkey('S', "settings", WID_SCRD_SETTINGS),
1198 Hotkey('0', "game_script", WID_SCRD_SCRIPT_GAME),
1199 Hotkey(0, "reload", WID_SCRD_RELOAD_TOGGLE),
1200 Hotkey('B', "break_toggle", WID_SCRD_BREAK_STR_ON_OFF_BTN),
1201 Hotkey('F', "break_string", WID_SCRD_BREAK_STR_EDIT_BOX),
1202 Hotkey('C', "match_case", WID_SCRD_MATCH_CASE_BTN),
1203 Hotkey(WKC_RETURN, "continue", WID_SCRD_CONTINUE_BTN),
1205};
1206
1208std::unique_ptr<NWidgetBase> MakeCompanyButtonRowsScriptDebug()
1209{
1210 return MakeCompanyButtonRows(WID_SCRD_COMPANY_BUTTON_START, WID_SCRD_COMPANY_BUTTON_END, COLOUR_GREY, 5, STR_AI_DEBUG_SELECT_AI_TOOLTIP, false);
1211}
1212
1216 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1217 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_AI_DEBUG, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1218 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1219 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1220 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1221 EndContainer(),
1223 NWidget(WWT_PANEL, COLOUR_GREY, WID_SCRD_VIEW),
1225 EndContainer(),
1226 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCRD_SCRIPT_GAME), SetMinimalSize(100, 20), SetStringTip(STR_AI_GAME_SCRIPT, STR_AI_GAME_SCRIPT_TOOLTIP),
1227 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCRD_NAME_TEXT), SetResize(1, 0), SetToolTip(STR_AI_DEBUG_NAME_TOOLTIP),
1229 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCRD_SETTINGS), SetMinimalSize(100, 20), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP),
1230 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCRD_RELOAD_TOGGLE), SetMinimalSize(100, 20), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_RELOAD, STR_AI_DEBUG_RELOAD_TOOLTIP),
1231 EndContainer(),
1232 EndContainer(),
1235 /* Log panel */
1237 EndContainer(),
1238 /* Break string widgets */
1241 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_SCRD_BREAK_STR_ON_OFF_BTN), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG), SetFill(0, 1), SetSpriteTip(SPR_FLAG_VEH_STOPPED, STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP),
1242 NWidget(WWT_PANEL, COLOUR_GREY),
1244 NWidget(WWT_LABEL, INVALID_COLOUR), SetPadding(2, 2, 2, 4), SetStringTip(STR_AI_DEBUG_BREAK_ON_LABEL),
1245 NWidget(WWT_EDITBOX, COLOUR_GREY, WID_SCRD_BREAK_STR_EDIT_BOX), SetFill(1, 1), SetResize(1, 0), SetPadding(2, 2, 2, 2), SetStringTip(STR_AI_DEBUG_BREAK_STR_OSKTITLE, STR_AI_DEBUG_BREAK_STR_TOOLTIP),
1246 EndContainer(),
1247 EndContainer(),
1248 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCRD_MATCH_CASE_BTN), SetMinimalSize(100, 0), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_MATCH_CASE, STR_AI_DEBUG_MATCH_CASE_TOOLTIP),
1249 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCRD_CONTINUE_BTN), SetMinimalSize(100, 0), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_CONTINUE, STR_AI_DEBUG_CONTINUE_TOOLTIP),
1250 EndContainer(),
1251 EndContainer(),
1253 EndContainer(),
1256 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1257 EndContainer(),
1258EndContainer(),
1259};
1260
1263 WDP_AUTO, "script_debug", 600, 450,
1265 {},
1267 &ScriptDebugWindow::hotkeys
1268);
1269
1275Window *ShowScriptDebugWindow(CompanyID show_company, bool new_window)
1276{
1277 if (!_networking || _network_server) {
1278 int i = 0;
1279 if (new_window) {
1280 /* find next free window number for script debug */
1281 while (FindWindowById(WC_SCRIPT_DEBUG, i) != nullptr) i++;
1282 } else {
1283 /* Find existing window showing show_company. */
1284 for (Window *w : Window::Iterate()) {
1285 if (w->window_class == WC_SCRIPT_DEBUG && static_cast<ScriptDebugWindow *>(w)->filter.script_debug_company == show_company) {
1286 return BringWindowToFrontById(w->window_class, w->window_number);
1287 }
1288 }
1289
1290 /* Maybe there's a window showing a different company which can be switched. */
1292 if (w != nullptr) {
1294 w->ChangeToScript(show_company);
1295 return w;
1296 }
1297 }
1298 return new ScriptDebugWindow(_script_debug_desc, i, show_company);
1299 } else {
1300 ShowErrorMessage(GetEncodedString(STR_ERROR_AI_DEBUG_SERVER_ONLY), {}, WL_INFO);
1301 }
1302
1303 return nullptr;
1304}
1305
1310{
1311 ScriptDebugWindow::initial_state.script_debug_company = CompanyID::Invalid();
1312}
1313
1316{
1317 /* Network clients can't debug AIs. */
1318 if (_networking && !_network_server) return;
1319
1320 for (const Company *c : Company::Iterate()) {
1321 if (c->is_ai && c->ai_instance->IsDead()) {
1322 ShowScriptDebugWindow(c->index);
1323 break;
1324 }
1325 }
1326
1328 if (g != nullptr && g->IsDead()) {
1330 }
1331}
static AIConfig * GetConfig(CompanyID company, ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
Definition ai_config.cpp:20
All static information from an AI like name, version, etc.
Definition ai_info.hpp:16
static void Pause(CompanyID company)
Suspend the AI and then pause execution of the script.
Definition ai_core.cpp:124
static void StartNew(CompanyID company)
Start a new AI company.
Definition ai_core.cpp:36
static const ScriptInfoList * GetUniqueInfoList()
Wrapper function for AIScanner::GetUniqueAIInfoList.
Definition ai_core.cpp:303
static bool IsPaused(CompanyID company)
Checks if the AI is paused.
Definition ai_core.cpp:145
static void Unpause(CompanyID company)
Resume execution of the AI.
Definition ai_core.cpp:137
static const ScriptInfoList * GetInfoList()
Wrapper function for AIScanner::GetAIInfoList.
Definition ai_core.cpp:298
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
static GameConfig * GetConfig(ScriptSettingSource source=SSS_DEFAULT)
Get the config of a company.
All static information from an Game like name, version, etc.
Definition game_info.hpp:16
Runtime information about a game script like a pointer to the squirrel vm and the current state.
static void StartNew()
Start up a new GameScript.
Definition game_core.cpp:72
static class GameInfo * GetInfo()
Get the current GameInfo.
Definition game.hpp:70
static void Unpause()
Resume execution of the Game Script.
static bool IsPaused()
Checks if the Game Script is paused.
static void ResetInstance()
Reset the current active instance.
static const ScriptInfoList * GetUniqueInfoList()
Wrapper function for GameScanner::GetUniqueInfoList.
static void Pause()
Suspends the Game Script and then pause the execution of the script.
static class GameInstance * GetInstance()
Get the current active instance.
Definition game.hpp:96
static const ScriptInfoList * GetInfoList()
Wrapper function for GameScanner::GetInfoList.
Base class for a 'real' widget.
Colours colour
Colour of this widget.
void SetLowered(bool lowered)
Lower or raise the widget.
void SetDisabled(bool disabled)
Disable (grey-out) or enable the widget.
Script settings.
std::optional< std::string > GetTextfile(TextfileType type, CompanyID slot) const
Search a textfile file next to this script.
void Change(std::optional< std::string > name, int version=-1, bool force_exact_match=false)
Set another Script to be loaded in this slot.
class ScriptInfo * GetInfo() const
Get the ScriptInfo linked to this ScriptConfig.
void SetSetting(const std::string_view name, int value)
Set the value of a setting for this config.
const ScriptConfigItemList * GetConfigList()
Get the config list for this ScriptConfig.
int GetSetting(const std::string &name) const
Get the value of a setting for this config.
void ResetEditableSettings(bool yet_to_start)
Reset only editable and visible settings to their default value.
All static information from an Script like name, version, etc.
const std::string & GetName() const
Get the Name of the script.
const std::string & GetAuthor() const
Get the Author of the script.
const std::string & GetURL() const
Get the website for this script.
int GetVersion() const
Get the version of the script.
const std::string & GetDescription() const
Get the description of the script.
bool IsPaused()
Checks if the script is paused.
ScriptLogTypes::LogData & GetLogData()
Get the log pointer of this script.
bool IsDead() const
Return the "this script died" value.
Scrollbar data structure.
bool IsVisible(size_type item) const
Checks whether given current item is visible in the list.
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
void SetCount(size_t num)
Sets the number of elements in the list.
auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2449
bool SetPosition(size_type position)
Sets the position of the first visible element.
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2523
size_type GetCount() const
Gets the number of elements in the list.
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
void SetStepSize(size_t stepsize)
Set the distance to scroll when using the buttons or the wheel.
size_type GetPosition() const
Gets the position of the first visible element in the list.
A timeout timer will fire once after the interval.
Definition timer.h:116
void Reset()
Reset the timer, so it will fire again after the timeout.
Definition timer.h:140
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
void DrawCompanyIcon(CompanyID c, int x, int y)
Draw the icon of a company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
@ CCA_NEW_AI
Create a new AI company.
@ CCA_DELETE
Delete a company.
@ CRR_NONE
Dummy reason for actions that don't need one.
@ CRR_MANUAL
The company is manually removed.
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:389
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
@ AI_DIR
Subdirectory for all AI files.
@ GAME_DIR
Subdirectory for all game scripts.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:923
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:50
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition gfx.cpp:1519
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:245
@ SA_LEFT
Left align the text.
Definition gfx_type.h:377
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:389
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:296
constexpr NWidgetPart SetMatrixDataTip(uint32_t cols, uint32_t rows, StringID tip={})
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:945
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
@ WID_TF_CAPTION
The caption of the window.
Definition misc_widget.h:50
bool _networking
are we in networking mode?
Definition network.cpp:66
bool _network_server
network-server is active
Definition network.cpp:67
@ INVALID_CLIENT_ID
Client is not part of anything.
uint8_t valid
Bits indicating what variable is valid (for each bit, 0 is invalid, 1 is valid).
@ Normal
A game normally paused.
static const uint8_t PC_BLACK
Black palette colour.
ScriptConfig stores the configuration settings of every Script.
static const int INT32_DIGITS_WITH_SIGN_AND_TERMINATION
Maximum of 10 digits for MIN / MAX_INT32, 1 for the sign and 1 for '\0'.
@ Boolean
This value is a boolean (either 0 (false) or 1 (true) ).
@ Developer
This setting will only be visible when the Script development tools are active.
@ InGame
This setting can be changed while the Script is running.
void ShowScriptDebugWindowIfScriptError()
Open the AI debug window if one of the AI scripts has crashed.
static constexpr NWidgetPart _nested_script_list_widgets[]
Widgets for the AI list window.
Window * ShowScriptDebugWindow(CompanyID show_company, bool new_window)
Open the Script debug window and select the given company.
static WindowDesc _script_debug_desc(WDP_AUTO, "script_debug", 600, 450, WC_SCRIPT_DEBUG, WC_NONE, {}, _nested_script_debug_widgets, &ScriptDebugWindow::hotkeys)
Window definition for the Script debug window.
std::unique_ptr< NWidgetBase > MakeCompanyButtonRowsScriptDebug()
Make a number of rows with buttons for each company for the Script debug window.
static bool SetScriptButtonColour(NWidgetCore &button, bool dead, bool paused)
Set the widget colour of a button based on the state of the script.
static constexpr NWidgetPart _nested_script_debug_widgets[]
Widgets for the Script debug window.
void ShowScriptTextfileWindow(TextfileType file_type, CompanyID slot)
Open the Script version of the textfile window.
static WindowDesc _script_list_desc(WDP_CENTER, "settings_script_list", 200, 234, WC_SCRIPT_LIST, WC_NONE, {}, _nested_script_list_widgets)
Window definition for the ai list window.
void ShowScriptSettingsWindow(CompanyID slot)
Open the Script settings window to change the Script settings for a Script.
static WindowDesc _script_settings_desc(WDP_CENTER, "settings_script", 500, 208, WC_SCRIPT_SETTINGS, WC_NONE, {}, _nested_script_settings_widgets)
Window definition for the Script settings window.
static constexpr NWidgetPart _nested_script_settings_widgets[]
Widgets for the Script settings window.
void ShowScriptListWindow(CompanyID slot, bool show_all)
Open the Script list window to chose a script for the given company slot.
void InitializeScriptGui()
Reset the Script windows to their initial state.
Declarations of the class for the script scanner.
std::map< std::string, class ScriptInfo *, CaseInsensitiveComparator > ScriptInfoList
Type for the list of scripts.
@ WID_SCRD_NAME_TEXT
Name of the current selected.
@ WID_SCRD_BREAK_STRING_WIDGETS
The panel to handle the breaking on string.
@ WID_SCRD_SCRIPT_GAME
Game Script button.
@ WID_SCRD_RELOAD_TOGGLE
Reload button.
@ WID_SCRD_HSCROLLBAR
Horizontal scrollbar of the log panel.
@ WID_SCRD_SETTINGS
Settings button.
@ WID_SCRD_BREAK_STR_EDIT_BOX
Edit box for the string to break on.
@ WID_SCRD_COMPANY_BUTTON_START
Buttons in the VIEW.
@ WID_SCRD_VIEW
The row of company buttons.
@ WID_SCRD_MATCH_CASE_BTN
Checkbox to use match caching or not.
@ WID_SCRD_BREAK_STR_ON_OFF_BTN
Enable breaking on string.
@ WID_SCRD_VSCROLLBAR
Vertical scrollbar of the log panel.
@ WID_SCRD_LOG_PANEL
Panel where the log is in.
@ WID_SCRD_CONTINUE_BTN
Continue button.
@ WID_SCRD_COMPANY_BUTTON_END
Last possible button in the VIEW.
@ WID_SCRL_ACCEPT
Accept button.
@ WID_SCRL_INFO_BG
Panel to draw some Script information on.
@ WID_SCRL_CAPTION
Caption of the window.
@ WID_SCRL_LIST
The matrix with all available Scripts.
@ WID_SCRL_SCROLLBAR
Scrollbar next to the Script list.
@ WID_SCRL_CANCEL
Cancel button.
@ WID_SCRS_SETTING_DROPDOWN
Dynamically created dropdown for changing setting value.
@ WID_SCRS_BACKGROUND
Panel to draw the settings on.
@ WID_SCRS_ACCEPT
Accept button.
@ WID_SCRS_SCROLLBAR
Scrollbar to scroll through all settings.
@ WID_SCRS_RESET
Reset button.
@ WID_SCRS_CAPTION
Caption of the window.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:58
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
void DrawBoolButton(int x, int y, bool state, bool clickable)
Draw a toggle button.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
@ CS_NUMERAL_SIGNED
Only numbers and '-' for negative values.
Definition string_type.h:28
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:91
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
GUISettings gui
settings related to the GUI
static bool IsValidAiID(auto index)
Is this company a valid company, controlled by the computer (a NoAI program)?
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Definition gfx_type.h:158
bool ai_developer_tools
activate AI/GS developer tools
List of hotkeys for a window.
Definition hotkeys.h:37
All data for a single hotkey.
Definition hotkeys.h:21
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Data stored about a string that can be modified in the GUI.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:213
Info about a single Script setting.
ScriptConfigFlags flags
Flags for the configuration setting.
std::string GetString(int value) const
Get string to display this setting in the configuration interface.
LabelMapping labels
Text labels for the integer values.
std::string name
The name of the configuration setting.
int min_value
The minimal value this configuration setting can have.
int max_value
The maximal value this configuration setting can have.
int step_size
The step size in the gui.
bool complete_labels
True if all values have a label.
TextColour GetColour() const
Get text colour to display this setting in the configuration interface.
bool break_check_enabled
Stop an AI when it prints a matching string.
bool case_sensitive_break_check
Is the matching done case-sensitive.
std::string break_string
The string to match to the AI output.
CompanyID script_debug_company
The AI that is (was last) being debugged.
Window with everything an AI prints via ScriptLog.
void UpdateAIButtonsState()
Update state of all Company (AI) buttons.
void DrawWidgetLog(const Rect &r) const
Draw the AI/GS log.
void UpdateGSButtonState()
Update state of game script button.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnInit() override
Notification that the nested widget tree gets initialized.
static EventState ScriptDebugGlobalHotkeys(int hotkey)
Handler for global hotkeys of the ScriptDebugWindow.
void SelectValidDebugCompany()
Ensure that script_debug_company refers to a valid AI company or GS, or is set to CompanyID::Invalid(...
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
int last_vscroll_pos
Last position of the scrolling.
void DrawWidgetCompanyButton(const Rect &r, WidgetID widget, int start) const
Draw a company button icon.
static const uint MAX_BREAK_STR_STRING_LENGTH
Maximum length of the break string.
QueryString break_editbox
Break editbox.
void OnPaint() override
The window must be repainted.
Scrollbar * hscroll
Cache of the horizontal scrollbar.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
void OnResize() override
Called after the window got resized.
int highlight_row
The output row that matches the given string, or -1.
ScriptDebugWindow(WindowDesc &desc, WindowNumber number, Owner show_company)
Constructor for the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void UpdateLogScroll()
Update the scrollbar and scroll position of the log panel.
StringFilter break_string_filter
Log filter for break.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
bool autoscroll
Whether automatically scrolling should be enabled or not.
bool IsDead() const
Check whether the currently selected AI/GS is dead.
bool IsValidDebugCompany(CompanyID company) const
Check whether a company is a valid AI company or GS.
void ChangeToScript(CompanyID show_script, bool new_window=false)
Change all settings to select another Script.
Scrollbar * vscroll
Cache of the vertical scrollbar.
bool show_break_box
Whether the break/debug box is visible.
Window that let you choose an available Script.
int line_height
Height of a row in the matrix widget.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
bool show_all
Whether to show all available versions.
void OnResize() override
Called after the window got resized.
CompanyID slot
The company we're selecting a new Script for.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
int selected
The currently selected Script.
Scrollbar * vscroll
Cache of the vertical scrollbar.
ScriptListWindow(WindowDesc &desc, CompanyID slot, bool show_all)
Constructor for the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void ChangeScript()
Changes the Script of the current slot.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
const ScriptInfoList * info_list
The list of Scripts.
Window for settings the parameters of an AI.
int clicked_row
The clicked row of settings.
void OnPaint() override
The window must be repainted.
std::vector< const ScriptConfigItem * > VisibleSettingsList
typdef for a vector of script settings
int clicked_button
The button we clicked.
void OnResize() override
Called after the window got resized.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnDropdownClose(Point, WidgetID widget, int, bool) override
A dropdown window associated to this window has been closed.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void RebuildVisibleSettings()
Rebuilds the list of visible settings.
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
CompanyID slot
The currently show company's setting.
int line_height
Height of a row in the matrix widget.
ScriptSettingsWindow(WindowDesc &desc, CompanyID slot)
Constructor for the window.
bool clicked_dropdown
Whether the dropdown is open.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
TimeoutTimer< TimerWindow > unclick_timeout
When reset, unclick the button after a small timeout.
bool clicked_increase
Whether we clicked the increase or decrease button.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
ScriptConfig * script_config
The configuration we're modifying.
VisibleSettingsList visible_settings
List of visible AI settings.
bool closing_dropdown
True, if the dropdown list is currently closing.
Scrollbar * vscroll
Cache of the vertical scrollbar.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
Window for displaying the textfile of a AI.
CompanyID slot
View the textfile of this CompanyID slot.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
String filter and state.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
bool GetState() const
Get the matching state of the current item.
void Assign(const std::string_view text)
Copy a string into the textbuffer.
Definition textbuf.cpp:420
const char * GetText() const
Get the current text.
Definition textbuf.cpp:284
Window for displaying a textfile.
TextfileType file_type
Type of textfile to view.
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
High level window description.
Definition window_gui.h:168
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:957
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1052
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3164
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:556
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1040
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1726
WindowClass window_class
Window class.
Definition window_gui.h:302
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition window_gui.h:411
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:313
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition window.cpp:570
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Definition window_gui.h:923
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
TextfileType
Additional text files accompanying Tar archives.
Rect ScrollRect(Rect r, const Scrollbar &sb, int resize_step)
Apply 'scroll' to a rect to be drawn in.
Definition widget.cpp:2540
std::unique_ptr< NWidgetBase > MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip, bool resizable)
Make a number of rows with button-like graphics, for enabling/disabling each company.
Definition widget.cpp:3422
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_IMGBTN_2
(Toggle) Button with diff image when clicked
Definition widget_type.h:43
@ WWT_LABEL
Centered label.
Definition widget_type.h:47
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:61
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:45
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:49
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition widget_type.h:74
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
@ EqualSize
Containers should keep all their (resizing) children equally large.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1143
Window * FindWindowByClass(WindowClass cls)
Find any window by its class.
Definition window.cpp:1116
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1155
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3224
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1226
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1101
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3241
@ WDP_CENTER
Center the window.
Definition window_gui.h:146
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
@ WN_GAME_OPTIONS_GS
GS settings.
Definition window_type.h:25
@ WN_GAME_OPTIONS_AI
AI settings.
Definition window_type.h:24
EventState
State of handling an event.
@ ES_NOT_HANDLED
The passed event is not handled.
@ WC_SCRIPT_SETTINGS
Script settings; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_SCRIPT_LIST
Scripts list; Window numbers:
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ WC_SCRIPT_DEBUG
Script debug window; Window numbers:
@ WC_TEXTFILE
textfile; Window numbers:
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
@ WC_QUERY_STRING
Query string window; Window numbers: