OpenTTD Source 20260731-master-g77ba2b244a
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "../stdafx.h"
11#include "../table/sprites.h"
12#include "../error.h"
13#include "../settings_gui.h"
14#include "../querystring_gui.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"
29
30#include "script_gui.h"
31#include "script_log.hpp"
32#include "script_scanner.hpp"
33#include "script_config.hpp"
34#include "../ai/ai.hpp"
35#include "../ai/ai_config.hpp"
36#include "../ai/ai_info.hpp"
37#include "../ai/ai_instance.hpp"
38#include "../game/game.hpp"
40#include "../game/game_info.hpp"
42
45
46#include "table/strings.h"
47
48#include "../safeguards.h"
49
50
51static ScriptConfig *GetConfig(CompanyID slot)
52{
53 if (slot == OWNER_DEITY) return GameConfig::GetConfig();
54 return AIConfig::GetConfig(slot);
55}
56
60struct ScriptListWindow : public Window {
61 const ScriptInfoList *info_list = nullptr;
62 int selected = -1;
63 CompanyID slot{};
64 int line_height = 0;
65 Scrollbar *vscroll = nullptr;
66 bool show_all = false;
67
74 ScriptListWindow(WindowDesc &desc, CompanyID slot, bool show_all) : Window(desc),
76 {
77 if (this->slot == OWNER_DEITY) {
78 this->info_list = this->show_all ? Game::GetInfoList() : Game::GetUniqueInfoList();
79 } else {
80 this->info_list = this->show_all ? AI::GetInfoList() : AI::GetUniqueInfoList();
81 }
82
83 this->CreateNestedTree();
84 this->vscroll = this->GetScrollbar(WID_SCRL_SCROLLBAR);
85 this->FinishInitNested(); // Initializes 'this->line_height' as side effect.
86
87 this->vscroll->SetCount(this->info_list->size() + 1);
88
89 /* Try if we can find the currently selected AI */
90 if (GetConfig(this->slot)->HasScript()) {
91 ScriptInfo *info = GetConfig(this->slot)->GetInfo();
92 int i = 0;
93 for (const auto &item : *this->info_list) {
94 if (item.second == info) {
95 this->selected = i;
96 break;
97 }
98
99 i++;
100 }
101 }
102 }
103
104 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
105 {
106 if (widget != WID_SCRL_CAPTION) return this->Window::GetWidgetString(widget, stringid);
107
108 return GetString(STR_AI_LIST_CAPTION, (this->slot == OWNER_DEITY) ? STR_AI_LIST_CAPTION_GAMESCRIPT : STR_AI_LIST_CAPTION_AI);
109 }
110
111 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
112 {
113 if (widget != WID_SCRL_LIST) return;
114
115 this->line_height = GetCharacterHeight(FontSize::Normal) + padding.height;
116
117 resize.width = 1;
118 fill.height = resize.height = this->line_height;
119 size.height = 5 * this->line_height;
120 }
121
122 void DrawWidget(const Rect &r, WidgetID widget) const override
123 {
124 switch (widget) {
125 case WID_SCRL_LIST: {
126 /* Draw a list of all available Scripts. */
127 Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
128 /* First AI in the list is hardcoded to random */
129 if (this->vscroll->IsVisible(0)) {
130 DrawString(tr, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TextColour::White : TextColour::Orange);
131 tr.top += this->line_height;
132 }
133 int i = 0;
134 for (const auto &item : *this->info_list) {
135 i++;
136 if (this->vscroll->IsVisible(i)) {
137 DrawString(tr, this->show_all ? GetString(STR_AI_CONFIG_NAME_VERSION, item.second->GetName(), item.second->GetVersion()) : item.second->GetName(), (this->selected == i - 1) ? TextColour::White : TextColour::Orange);
138 tr.top += this->line_height;
139 }
140 }
141 break;
142 }
143 case WID_SCRL_INFO_BG: {
144 ScriptInfo *selected_info = nullptr;
145 int i = 0;
146 for (const auto &item : *this->info_list) {
147 i++;
148 if (this->selected == i - 1) selected_info = static_cast<ScriptInfo *>(item.second);
149 }
150 /* Some info about the currently selected Script. */
151 if (selected_info != nullptr) {
153 DrawString(tr, GetString(STR_AI_LIST_AUTHOR, selected_info->GetAuthor()));
155 DrawString(tr, GetString(STR_AI_LIST_VERSION, selected_info->GetVersion()));
157 if (!selected_info->GetURL().empty()) {
158 DrawString(tr, GetString(STR_AI_LIST_URL, selected_info->GetURL()));
160 }
162 }
163 break;
164 }
165 }
166 }
167
172 {
173 if (this->selected == -1) {
174 GetConfig(this->slot)->Change(std::nullopt);
175 } else {
176 ScriptInfoList::const_iterator it = this->info_list->cbegin();
177 std::advance(it, this->selected);
178 GetConfig(this->slot)->Change(it->second->GetName(), it->second->GetVersion());
179 }
180 if (_game_mode == GameMode::Editor) {
181 if (this->slot == OWNER_DEITY) {
182 if (Game::GetInstance() != nullptr) Game::ResetInstance();
184 } else {
185 Company *c = Company::GetIfValid(this->slot);
186 if (c != nullptr && c->ai_instance != nullptr) {
187 c->ai_instance.reset();
188 AI::StartNew(this->slot);
189 }
190 }
191 }
193 InvalidateWindowClassesData(WindowClass::ScriptSettings);
194 InvalidateWindowClassesData(WindowClass::ScriptDebug, -1);
195 CloseWindowByClass(WindowClass::QueryString);
196 InvalidateWindowClassesData(WindowClass::Textfile);
197 }
198
199 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
200 {
201 switch (widget) {
202 case WID_SCRL_LIST: { // Select one of the Scripts
203 int sel = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCRL_LIST) - 1;
204 if (sel < static_cast<int>(this->info_list->size())) {
205 this->selected = sel;
206 this->SetDirty();
207 if (click_count > 1) {
208 this->ChangeScript();
209 this->Close();
210 }
211 }
212 break;
213 }
214
215 case WID_SCRL_ACCEPT: {
216 this->ChangeScript();
217 this->Close();
218 break;
219 }
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 == GameMode::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
267
270 WindowPosition::Center, "settings_script_list", 200, 234,
271 WindowClass::ScriptList, WindowClass::None,
272 {},
274);
275
281void ShowScriptListWindow(CompanyID slot, bool show_all)
282{
283 CloseWindowByClass(WindowClass::ScriptList);
284 new ScriptListWindow(_script_list_desc, slot, show_all);
285}
286
287
292 CompanyID slot{};
294 int clicked_button = -1;
295 bool clicked_increase = false;
296 bool clicked_dropdown = false;
297 bool closing_dropdown = false;
298 int clicked_row = 0;
299 int line_height = 0;
300 Scrollbar *vscroll = nullptr;
301 typedef std::vector<const ScriptConfigItem *> VisibleSettingsList;
303
310 {
311 this->CreateNestedTree();
312 this->vscroll = this->GetScrollbar(WID_SCRS_SCROLLBAR);
313 this->FinishInitNested(this->slot); // Initializes 'this->line_height' as side effect.
314
315 this->OnInvalidateData();
316 }
317
324 {
325 this->visible_settings.clear();
326
327 for (const auto &item : *this->script_config->GetConfigList()) {
328 bool no_hide = !item.flags.Test(ScriptConfigFlag::Developer);
329 if (no_hide || _settings_client.gui.ai_developer_tools) {
330 this->visible_settings.push_back(&item);
331 }
332 }
333
334 this->vscroll->SetCount(this->visible_settings.size());
335 }
336
337 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
338 {
339 if (widget != WID_SCRS_CAPTION) return this->Window::GetWidgetString(widget, stringid);
340
341 return GetString((this->slot == OWNER_DEITY) ? STR_AI_SETTINGS_CAPTION_GAMESCRIPT : STR_AI_SETTINGS_CAPTION_AI);
342 }
343
344 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
345 {
346 if (widget != WID_SCRS_BACKGROUND) return;
347
348 this->line_height = std::max(SETTING_BUTTON_HEIGHT, GetCharacterHeight(FontSize::Normal)) + padding.height;
349
350 resize.width = 1;
351 fill.height = resize.height = this->line_height;
352 size.height = 5 * this->line_height;
353 }
354
355 void DrawWidget(const Rect &r, WidgetID widget) const override
356 {
357 if (widget != WID_SCRS_BACKGROUND) return;
358
359 Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero);
360 bool rtl = _current_text_dir == TD_RTL;
361 Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
363
364 int y = r.top;
365 int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
366 int text_y_offset = (this->line_height - GetCharacterHeight(FontSize::Normal)) / 2;
367
368 const auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->visible_settings);
369 for (auto it = first; it != last; ++it) {
370 const ScriptConfigItem &config_item = **it;
371 int current_value = this->script_config->GetSetting(config_item.name);
372 bool editable = this->IsEditableItem(config_item);
373
374 if (config_item.flags.Test(ScriptConfigFlag::Boolean)) {
375 DrawBoolButton(br.left, y + button_y_offset, Colours::Yellow, Colours::Mauve, current_value != 0, editable);
376 } else {
377 int i = static_cast<int>(std::distance(std::begin(this->visible_settings), it));
378 if (config_item.complete_labels) {
379 DrawDropDownButton(br.left, y + button_y_offset, Colours::Yellow, this->clicked_row == i && this->clicked_dropdown, editable);
380 } else {
381 DrawArrowButtons(br.left, y + button_y_offset, Colours::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);
382 }
383 }
384
385 DrawString(tr.left, tr.right, y + text_y_offset, config_item.GetString(current_value), config_item.GetColour());
386 y += this->line_height;
387 }
388 }
389
390 void OnPaint() override
391 {
392 if (this->closing_dropdown) {
393 this->closing_dropdown = false;
394 this->clicked_dropdown = false;
395 }
396 this->DrawWidgets();
397 }
398
399 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
400 {
401 switch (widget) {
402 case WID_SCRS_BACKGROUND: {
403 auto it = this->vscroll->GetScrolledItemFromWidget(this->visible_settings, pt.y, this, widget);
404 if (it == this->visible_settings.end()) break;
405
406 const ScriptConfigItem &config_item = **it;
407 if (!this->IsEditableItem(config_item)) return;
408
409 int num = it - this->visible_settings.begin();
410 if (this->clicked_row != num) {
411 this->CloseChildWindows(WindowClass::QueryString);
412 this->CloseChildWindows(WindowClass::DropdownMenu);
413 this->clicked_row = num;
414 this->clicked_dropdown = false;
415 }
416
417 bool bool_item = config_item.flags.Test(ScriptConfigFlag::Boolean);
418
419 Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero);
420 int x = pt.x - r.left;
421 if (_current_text_dir == TD_RTL) x = r.Width() - 1 - x;
422
423 /* One of the arrows is clicked (or green/red rect in case of bool value) */
424 int old_val = this->script_config->GetSetting(config_item.name);
425 if (!bool_item && IsInsideMM(x, 0, SETTING_BUTTON_WIDTH) && config_item.complete_labels) {
426 if (this->clicked_dropdown) {
427 /* unclick the dropdown */
428 this->CloseChildWindows(WindowClass::DropdownMenu);
429 this->clicked_dropdown = false;
430 this->closing_dropdown = false;
431 } else {
432 int rel_y = (pt.y - r.top) % this->line_height;
433
434 Rect wi_rect;
435 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
436 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
437 wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
438 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
439
440 /* If the mouse is still held but dragged outside of the dropdown list, keep the dropdown open */
441 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
442 this->clicked_dropdown = true;
443 this->closing_dropdown = false;
444
445 DropDownList list;
446 for (int i = config_item.min_value; i <= config_item.max_value; i++) {
447 list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_RAW_STRING, config_item.labels.find(i)->second), i));
448 }
449
450 ShowDropDownListAt(this, std::move(list), old_val, WID_SCRS_SETTING_DROPDOWN, wi_rect, Colours::Orange);
451 }
452 }
453 } else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
454 int new_val = old_val;
455 if (bool_item) {
456 new_val = !new_val;
457 } else if (x >= SETTING_BUTTON_WIDTH / 2) {
458 /* Increase button clicked */
459 new_val += config_item.step_size;
460 if (new_val > config_item.max_value) new_val = config_item.max_value;
461 this->clicked_increase = true;
462 } else {
463 /* Decrease button clicked */
464 new_val -= config_item.step_size;
465 if (new_val < config_item.min_value) new_val = config_item.min_value;
466 this->clicked_increase = false;
467 }
468
469 if (new_val != old_val) {
470 this->script_config->SetSetting(config_item.name, new_val);
471 this->clicked_button = num;
472 this->unclick_timeout.Reset();
473 }
474 } else if (!bool_item && !config_item.complete_labels) {
475 /* Display a query box so users can enter a custom value. */
476 ShowQueryString(GetString(STR_JUST_INT, old_val), STR_CONFIG_SETTING_QUERY_CAPTION, INT32_DIGITS_WITH_SIGN_AND_TERMINATION, this, CS_NUMERAL_SIGNED, {});
477 }
478 this->SetDirty();
479 break;
480 }
481
482 case WID_SCRS_RESET:
483 this->script_config->ResetEditableSettings(_game_mode == GameMode::Menu || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot)));
484 this->SetDirty();
485 break;
486 }
487 }
488
489 void OnQueryTextFinished(std::optional<std::string> str) override
490 {
491 if (!str.has_value()) return;
492 auto value = ParseInteger<int32_t>(*str, 10, true);
493 if (!value.has_value()) return;
494 this->SetValue(*value);
495 }
496
497 void OnDropdownSelect(WidgetID widget, int index, int) override
498 {
499 if (widget != WID_SCRS_SETTING_DROPDOWN) return;
500 assert(this->clicked_dropdown);
501 this->SetValue(index);
502 }
503
504 void OnDropdownClose(Point, WidgetID widget, int, int, bool) override
505 {
506 if (widget != WID_SCRS_SETTING_DROPDOWN) return;
507 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
508 * the same dropdown button was clicked again, and then not open the dropdown again.
509 * So, we only remember that it was closed, and process it on the next OnPaint, which is
510 * after OnClick. */
511 assert(this->clicked_dropdown);
512 this->closing_dropdown = true;
513 this->SetDirty();
514 }
515
516 void OnResize() override
517 {
518 this->vscroll->SetCapacityFromWidget(this, WID_SCRS_BACKGROUND);
519 }
520
522 TimeoutTimer<TimerWindow> unclick_timeout = {std::chrono::milliseconds(150), [this]() {
523 this->clicked_button = -1;
524 this->SetDirty();
525 }};
526
532 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
533 {
534 this->script_config = GetConfig(this->slot);
535 if (this->script_config->GetConfigList()->empty()) this->Close();
537 this->CloseChildWindows(WindowClass::DropdownMenu);
538 this->CloseChildWindows(WindowClass::QueryString);
539 }
540
541private:
542 bool IsEditableItem(const ScriptConfigItem &config_item) const
543 {
544 return _game_mode == GameMode::Menu
545 || _game_mode == GameMode::Editor
546 || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot))
547 || config_item.flags.Test(ScriptConfigFlag::InGame)
548 || _settings_client.gui.ai_developer_tools;
549 }
550
551 void SetValue(int value)
552 {
553 const ScriptConfigItem &config_item = *this->visible_settings[this->clicked_row];
554 if (_game_mode == GameMode::Normal && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && !config_item.flags.Test(ScriptConfigFlag::InGame)) return;
555 this->script_config->SetSetting(config_item.name, value);
556 this->SetDirty();
557 }
558};
559
578
581 WindowPosition::Center, "settings_script", 500, 208,
582 WindowClass::ScriptSettings, WindowClass::None,
583 {},
585);
586
591void ShowScriptSettingsWindow(CompanyID slot)
592{
593 CloseWindowByClass(WindowClass::ScriptList);
594 CloseWindowByClass(WindowClass::ScriptSettings);
596}
597
598
600struct ScriptTextfileWindow : public TextfileWindow {
601 CompanyID slot{};
602
604 {
605 this->ConstructWindow();
606 this->OnInvalidateData();
607 }
608
609 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
610 {
611 if (widget == WID_TF_CAPTION) {
612 return GetString(stringid, (this->slot == OWNER_DEITY) ? STR_CONTENT_TYPE_GAME_SCRIPT : STR_CONTENT_TYPE_AI, GetConfig(this->slot)->GetInfo()->GetName());
613 }
614
615 return this->Window::GetWidgetString(widget, stringid);
616 }
617
618 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
619 {
620 auto textfile = GetConfig(this->slot)->GetTextfile(file_type, this->slot);
621 if (!textfile.has_value()) {
622 this->Close();
623 } else {
624 this->LoadTextfile(textfile.value(), (this->slot == OWNER_DEITY) ? Subdirectory::Gs : Subdirectory::Ai);
625 }
626 }
627};
628
635void ShowScriptTextfileWindow(Window *parent, TextfileType file_type, CompanyID slot)
636{
637 parent->CloseChildWindowById(WindowClass::Textfile, file_type);
638 new ScriptTextfileWindow(parent, file_type, slot);
639}
640
641
650static bool SetScriptButtonColour(NWidgetCore &button, bool dead, bool paused)
651{
652 /* Dead scripts are indicated with red background and
653 * paused scripts are indicated with yellow background. */
654 Colours colour = dead ? Colours::Red :
655 (paused ? Colours::Yellow : Colours::Grey);
656 if (button.colour != colour) {
657 button.colour = colour;
658 return true;
659 }
660 return false;
661}
662
666struct ScriptDebugWindow : public Window {
667 static const uint MAX_BREAK_STR_STRING_LENGTH = 256;
668
675
676 static inline FilterState initial_state = {
677 "",
678 CompanyID::Invalid(),
679 true,
680 false,
681 };
682
684 bool autoscroll = true;
685 bool show_break_box = false;
688 int highlight_row = -1;
689 Scrollbar *vscroll = nullptr;
690 Scrollbar *hscroll = nullptr;
691 FilterState filter{};
692
693 ScriptLogTypes::LogData &GetLogData() const
694 {
695 if (this->filter.script_debug_company == OWNER_DEITY) return Game::GetInstance()->GetLogData();
696 return Company::Get(this->filter.script_debug_company)->ai_instance->GetLogData();
697 }
698
703 bool IsDead() const
704 {
705 if (this->filter.script_debug_company == OWNER_DEITY) {
707 return game == nullptr || game->IsDead();
708 }
709 return !Company::IsValidAiID(this->filter.script_debug_company) || Company::Get(this->filter.script_debug_company)->ai_instance->IsDead();
710 }
711
717 bool IsValidDebugCompany(CompanyID company) const
718 {
719 switch (company.base()) {
720 case CompanyID::Invalid().base(): return false;
721 case OWNER_DEITY.base(): return Game::GetInstance() != nullptr;
722 default: return Company::IsValidAiID(company);
723 }
724 }
725
731 {
732 /* Check if the currently selected company is still active. */
733 if (this->IsValidDebugCompany(this->filter.script_debug_company)) return;
734
735 this->filter.script_debug_company = CompanyID::Invalid();
736
737 for (const Company *c : Company::Iterate()) {
738 if (c->is_ai) {
739 this->ChangeToScript(c->index);
740 return;
741 }
742 }
743
744 /* If no AI is available, see if there is a game script. */
745 if (Game::GetInstance() != nullptr) this->ChangeToScript(OWNER_DEITY);
746 }
747
755 {
756 this->filter = ScriptDebugWindow::initial_state;
757 this->break_string_filter = {&this->filter.case_sensitive_break_check, false};
758
759 this->CreateNestedTree();
760 this->vscroll = this->GetScrollbar(WID_SCRD_VSCROLLBAR);
761 this->hscroll = this->GetScrollbar(WID_SCRD_HSCROLLBAR);
762 this->FinishInitNested(number);
763
764 this->querystrings[WID_SCRD_BREAK_STR_EDIT_BOX] = &this->break_editbox;
765
766 this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar
767
768 /* Restore the break string value from static variable, and enable the filter. */
769 this->break_editbox.text.Assign(this->filter.break_string);
770 this->break_string_filter.SetFilterTerm(this->filter.break_string);
771
772 if (show_company == CompanyID::Invalid()) {
774 } else {
775 this->ChangeToScript(show_company);
776 }
777 }
778
779 void OnInit() override
780 {
781 this->show_break_box = _settings_client.gui.ai_developer_tools;
782 this->GetWidget<NWidgetStacked>(WID_SCRD_BREAK_STRING_WIDGETS)->SetDisplayedPlane(this->show_break_box ? 0 : SZSP_HORIZONTAL);
783 if (!this->show_break_box) this->filter.break_check_enabled = false;
785
786 this->InvalidateData(-1);
787 }
788
791 {
792 ScriptDebugWindow::initial_state = this->filter;
793 }
794
795 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
796 {
797 if (widget == WID_SCRD_LOG_PANEL) {
798 fill.height = resize.height = GetCharacterHeight(FontSize::Normal) + WidgetDimensions::scaled.vsep_normal;
799 size.height = 14 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
800 }
801 }
802
803 void OnPaint() override
804 {
806 this->UpdateLogScroll();
807
808 /* Draw standard stuff */
809 this->DrawWidgets();
810 }
811
812 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
813 {
814 if (widget != WID_SCRD_NAME_TEXT) return this->Window::GetWidgetString(widget, stringid);
815
816 if (this->filter.script_debug_company == OWNER_DEITY) {
817 const GameInfo *info = Game::GetInfo();
818 assert(info != nullptr);
819 return GetString(STR_AI_DEBUG_NAME_AND_VERSION, info->GetName(), info->GetVersion());
820 }
821 if (this->filter.script_debug_company == CompanyID::Invalid() || !Company::IsValidAiID(this->filter.script_debug_company)) {
822 return {};
823 }
824
825 const AIInfo *info = Company::Get(this->filter.script_debug_company)->ai_info;
826 return GetString(STR_AI_DEBUG_NAME_AND_VERSION, info->GetName(), info->GetVersion());
827 }
828
829 void DrawWidget(const Rect &r, WidgetID widget) const override
830 {
831 switch (widget) {
833 this->DrawWidgetLog(r);
834 break;
835
836 default:
837 if (IsInsideBS(widget, WID_SCRD_COMPANY_BUTTON_START, MAX_COMPANIES)) {
839 }
840 break;
841 }
842 }
843
850 void DrawWidgetCompanyButton(const Rect &r, WidgetID widget, int start) const
851 {
852 if (this->IsWidgetDisabled(widget)) return;
853 CompanyID cid = static_cast<CompanyID>(widget - start);
855 DrawCompanyIcon(cid, CentreBounds(r.left, r.right, sprite_size.width), CentreBounds(r.top, r.bottom, sprite_size.height));
856 }
857
862 void DrawWidgetLog(const Rect &r) const
863 {
864 if (this->filter.script_debug_company == CompanyID::Invalid()) return;
865
866 const ScriptLogTypes::LogData &log = this->GetLogData();
867 if (log.empty()) return;
868
869 Rect fr = r.Shrink(WidgetDimensions::scaled.framerect);
870
871 /* Setup a clipping rectangle... */
872 DrawPixelInfo tmp_dpi;
873 if (!FillDrawPixelInfo(&tmp_dpi, fr)) return;
874 /* ...but keep coordinates relative to the window. */
875 tmp_dpi.left += fr.left;
876 tmp_dpi.top += fr.top;
877
878 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
879
880 fr = ScrollRect(fr, *this->hscroll, 1);
881
882 auto [first, last] = this->vscroll->GetVisibleRangeIterators(log);
883 for (auto it = first; it != last; ++it) {
884 const ScriptLogTypes::LogLine &line = *it;
885
886 TextColour colour;
887 switch (line.type) {
888 case ScriptLogTypes::LOG_SQ_INFO: colour = TextColour::Black; break;
889 case ScriptLogTypes::LOG_SQ_ERROR: colour = TextColour::White; break;
890 case ScriptLogTypes::LOG_INFO: colour = TextColour::Black; break;
891 case ScriptLogTypes::LOG_WARNING: colour = TextColour::Yellow; break;
892 case ScriptLogTypes::LOG_ERROR: colour = TextColour::Red; break;
893 default: colour = TextColour::Black; break;
894 }
895
896 /* Check if the current line should be highlighted */
897 if (std::distance(std::begin(log), it) == this->highlight_row) {
898 fr.bottom = fr.top + this->resize.step_height - 1;
900 if (colour == TextColour::Black) colour = TextColour::White; // Make black text readable by inverting it to white.
901 }
902
903 DrawString(fr, line.text, colour, AlignmentH::ForceLeft);
904 fr.top += this->resize.step_height;
905 }
906 }
907
912 {
913 this->SetWidgetsDisabledState(this->filter.script_debug_company == CompanyID::Invalid(), WID_SCRD_VSCROLLBAR, WID_SCRD_HSCROLLBAR);
914 if (this->filter.script_debug_company == CompanyID::Invalid()) return;
915
916 ScriptLogTypes::LogData &log = this->GetLogData();
917
918 int scroll_count = static_cast<int>(log.size());
919 if (this->vscroll->GetCount() != scroll_count) {
920 this->vscroll->SetCount(scroll_count);
921
922 /* We need a repaint */
924 }
925
926 if (log.empty()) return;
927
928 /* Detect when the user scrolls the window. Enable autoscroll when the bottom-most line becomes visible. */
929 if (this->last_vscroll_pos != this->vscroll->GetPosition()) {
930 this->autoscroll = this->vscroll->GetPosition() + this->vscroll->GetCapacity() >= static_cast<int>(log.size());
931 }
932
933 if (this->autoscroll && this->vscroll->SetPosition(static_cast<int>(log.size()))) {
934 /* We need a repaint */
937 }
938
939 this->last_vscroll_pos = this->vscroll->GetPosition();
940 }
941
946 {
947 /* Update company buttons */
948 for (CompanyID i = CompanyID::Begin(); i < MAX_COMPANIES; ++i) {
949 /* Mark dead/paused AIs by setting the background colour. */
950 bool valid = Company::IsValidAiID(i);
951 bool dead = valid && Company::Get(i)->ai_instance->IsDead();
952 bool paused = valid && Company::Get(i)->ai_instance->IsPaused();
953
955 button->SetDisabled(!valid);
956 button->SetLowered(this->filter.script_debug_company == i);
957 SetScriptButtonColour(*button, dead, paused);
958 }
959 }
960
965 {
967 bool valid = game != nullptr;
968 bool dead = valid && game->IsDead();
969 bool paused = valid && game->IsPaused();
970
972 button->SetDisabled(!valid);
973 button->SetLowered(this->filter.script_debug_company == OWNER_DEITY);
974 SetScriptButtonColour(*button, dead, paused);
975 }
976
982 void ChangeToScript(CompanyID show_script, bool new_window = false)
983 {
984 if (!this->IsValidDebugCompany(show_script)) return;
985
986 if (new_window) {
987 ScriptDebugWindow::initial_state = this->filter;
988 ShowScriptDebugWindow(show_script, true);
989 return;
990 }
991
992 this->filter.script_debug_company = show_script;
993
994 this->highlight_row = -1; // The highlight of one Script make little sense for another Script.
995
996 /* Close AI settings window to prevent confusion */
997 CloseWindowByClass(WindowClass::ScriptSettings);
998
999 this->InvalidateData(-1);
1000
1001 this->autoscroll = true;
1002 this->last_vscroll_pos = this->vscroll->GetPosition();
1003 }
1004
1005 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1006 {
1007 /* Also called for hotkeys, so check for disabledness */
1008 if (this->IsWidgetDisabled(widget)) return;
1009
1010 /* Check which button is clicked */
1012 this->ChangeToScript(static_cast<CompanyID>(widget - WID_SCRD_COMPANY_BUTTON_START), _ctrl_pressed);
1013 }
1014
1015 switch (widget) {
1018 break;
1019
1021 if (this->filter.script_debug_company == OWNER_DEITY) break;
1022 /* First kill the company of the AI, then start a new one. This should start the current AI again */
1023 Command<Commands::CompanyControl>::Post(CompanyCtrlAction::Delete, this->filter.script_debug_company, CompanyRemoveReason::Manual, ClientID::Invalid);
1024 Command<Commands::CompanyControl>::Post(CompanyCtrlAction::NewAI, this->filter.script_debug_company, CompanyRemoveReason::None, ClientID::Invalid);
1025 break;
1026
1027 case WID_SCRD_SETTINGS:
1029 break;
1030
1032 this->filter.break_check_enabled = !this->filter.break_check_enabled;
1033 this->InvalidateData(-1);
1034 break;
1035
1037 this->filter.case_sensitive_break_check = !this->filter.case_sensitive_break_check;
1038 this->InvalidateData(-1);
1039 break;
1040
1042 /* Unpause current AI / game script and mark the corresponding script button dirty. */
1043 if (!this->IsDead()) {
1044 if (this->filter.script_debug_company == OWNER_DEITY) {
1045 Game::Unpause();
1046 } else {
1047 AI::Unpause(this->filter.script_debug_company);
1048 }
1049 }
1050
1051 /* If the last AI/Game Script is unpaused, unpause the game too. */
1052 if (_pause_mode.Test(PauseMode::Normal)) {
1053 bool all_unpaused = !Game::IsPaused();
1054 if (all_unpaused) {
1055 for (const Company *c : Company::Iterate()) {
1056 if (c->is_ai && AI::IsPaused(c->index)) {
1057 all_unpaused = false;
1058 break;
1059 }
1060 }
1061 if (all_unpaused) {
1062 /* All scripts have been unpaused => unpause the game. */
1063 Command<Commands::Pause>::Post(PauseMode::Normal, false);
1064 }
1065 }
1066 }
1067
1068 this->highlight_row = -1;
1069 this->InvalidateData(-1);
1070 break;
1071 }
1072 }
1073
1074 void OnEditboxChanged(WidgetID wid) override
1075 {
1076 if (wid != WID_SCRD_BREAK_STR_EDIT_BOX) return;
1077
1078 /* Save the current string to static member so it can be restored next time the window is opened. */
1079 this->filter.break_string = this->break_editbox.text.GetText();
1080 this->break_string_filter.SetFilterTerm(this->filter.break_string);
1081 }
1082
1089 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1090 {
1091 if (this->show_break_box != _settings_client.gui.ai_developer_tools) this->ReInit();
1092
1093 /* If the log message is related to the active company tab, check the break string.
1094 * This needs to be done in gameloop-scope, so the AI is suspended immediately. */
1095 if (!gui_scope && data == this->filter.script_debug_company &&
1096 this->IsValidDebugCompany(this->filter.script_debug_company) &&
1097 this->filter.break_check_enabled && !this->break_string_filter.IsEmpty()) {
1098 /* Get the log instance of the active company */
1099 ScriptLogTypes::LogData &log = this->GetLogData();
1100
1101 if (!log.empty()) {
1102 this->break_string_filter.ResetState();
1103 this->break_string_filter.AddLine(log.back().text);
1104 if (this->break_string_filter.GetState()) {
1105 /* Pause execution of script. */
1106 if (!this->IsDead()) {
1107 if (this->filter.script_debug_company == OWNER_DEITY) {
1108 Game::Pause();
1109 } else {
1110 AI::Pause(this->filter.script_debug_company);
1111 }
1112 }
1113
1114 /* Pause the game. */
1115 if (!_pause_mode.Test(PauseMode::Normal)) {
1116 Command<Commands::Pause>::Post(PauseMode::Normal, true);
1117 }
1118
1119 /* Highlight row that matched */
1120 this->highlight_row = static_cast<int>(log.size() - 1);
1121 }
1122 }
1123 }
1124
1125 if (!gui_scope) return;
1126
1128
1129 uint max_width = 0;
1130 if (this->filter.script_debug_company != CompanyID::Invalid()) {
1131 for (auto &line : this->GetLogData()) {
1132 if (line.width == 0 || data == -1) line.width = GetStringBoundingBox(line.text).width;
1133 max_width = std::max(max_width, line.width);
1134 }
1135 }
1136
1137 this->vscroll->SetCount(this->filter.script_debug_company != CompanyID::Invalid() ? this->GetLogData().size() : 0);
1138 this->hscroll->SetCount(max_width + WidgetDimensions::scaled.frametext.Horizontal());
1139
1140 this->UpdateAIButtonsState();
1141 this->UpdateGSButtonState();
1142
1145
1146 this->SetWidgetDisabledState(WID_SCRD_SETTINGS, this->filter.script_debug_company == CompanyID::Invalid() ||
1147 GetConfig(this->filter.script_debug_company)->GetConfigList()->empty());
1148 extern CompanyID _local_company;
1150 this->filter.script_debug_company == CompanyID::Invalid() ||
1151 this->filter.script_debug_company == OWNER_DEITY ||
1152 this->filter.script_debug_company == _local_company);
1153 this->SetWidgetDisabledState(WID_SCRD_CONTINUE_BTN, this->filter.script_debug_company == CompanyID::Invalid() ||
1154 (this->filter.script_debug_company == OWNER_DEITY ? !Game::IsPaused() : !AI::IsPaused(this->filter.script_debug_company)));
1155 }
1156
1157 void OnResize() override
1158 {
1159 this->vscroll->SetCapacityFromWidget(this, WID_SCRD_LOG_PANEL, WidgetDimensions::scaled.framerect.Vertical());
1160 this->hscroll->SetCapacityFromWidget(this, WID_SCRD_LOG_PANEL, WidgetDimensions::scaled.framerect.Horizontal());
1161 }
1162
1169 {
1170 if (_game_mode != GameMode::Normal) return EventState::NotHandled;
1171 Window *w = ShowScriptDebugWindow(CompanyID::Invalid());
1172 if (w == nullptr) return EventState::NotHandled;
1173 return w->OnHotkey(hotkey);
1174 }
1175
1176 static inline HotkeyList hotkeys{"aidebug", {
1177 Hotkey('1', "company_1", WID_SCRD_COMPANY_BUTTON_START),
1178 Hotkey('2', "company_2", WID_SCRD_COMPANY_BUTTON_START + 1),
1179 Hotkey('3', "company_3", WID_SCRD_COMPANY_BUTTON_START + 2),
1180 Hotkey('4', "company_4", WID_SCRD_COMPANY_BUTTON_START + 3),
1181 Hotkey('5', "company_5", WID_SCRD_COMPANY_BUTTON_START + 4),
1182 Hotkey('6', "company_6", WID_SCRD_COMPANY_BUTTON_START + 5),
1183 Hotkey('7', "company_7", WID_SCRD_COMPANY_BUTTON_START + 6),
1184 Hotkey('8', "company_8", WID_SCRD_COMPANY_BUTTON_START + 7),
1185 Hotkey('9', "company_9", WID_SCRD_COMPANY_BUTTON_START + 8),
1186 Hotkey(0, "company_10", WID_SCRD_COMPANY_BUTTON_START + 9),
1187 Hotkey(0, "company_11", WID_SCRD_COMPANY_BUTTON_START + 10),
1188 Hotkey(0, "company_12", WID_SCRD_COMPANY_BUTTON_START + 11),
1189 Hotkey(0, "company_13", WID_SCRD_COMPANY_BUTTON_START + 12),
1190 Hotkey(0, "company_14", WID_SCRD_COMPANY_BUTTON_START + 13),
1191 Hotkey(0, "company_15", WID_SCRD_COMPANY_BUTTON_START + 14),
1192 Hotkey('S', "settings", WID_SCRD_SETTINGS),
1193 Hotkey('0', "game_script", WID_SCRD_SCRIPT_GAME),
1194 Hotkey(0, "reload", WID_SCRD_RELOAD_TOGGLE),
1195 Hotkey('B', "break_toggle", WID_SCRD_BREAK_STR_ON_OFF_BTN),
1196 Hotkey('F', "break_string", WID_SCRD_BREAK_STR_EDIT_BOX),
1197 Hotkey('C', "match_case", WID_SCRD_MATCH_CASE_BTN),
1198 Hotkey(WKC_RETURN, "continue", WID_SCRD_CONTINUE_BTN),
1200};
1201
1203std::unique_ptr<NWidgetBase> MakeCompanyButtonRowsScriptDebug()
1204{
1205 return MakeCompanyButtonRows(WID_SCRD_COMPANY_BUTTON_START, WID_SCRD_COMPANY_BUTTON_END, Colours::Grey, 5, STR_AI_DEBUG_SELECT_AI_TOOLTIP, false);
1206}
1207
1209static constexpr std::initializer_list<NWidgetPart> _nested_script_debug_widgets = {
1212 NWidget(WWT_CAPTION, Colours::Grey), SetStringTip(STR_AI_DEBUG, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1216 EndContainer(),
1220 EndContainer(),
1221 NWidget(WWT_TEXTBTN, Colours::Grey, WID_SCRD_SCRIPT_GAME), SetMinimalSize(100, 20), SetStringTip(STR_AI_GAME_SCRIPT, STR_AI_GAME_SCRIPT_TOOLTIP),
1222 NWidget(WWT_TEXTBTN, Colours::Grey, WID_SCRD_NAME_TEXT), SetResize(1, 0), SetToolTip(STR_AI_DEBUG_NAME_TOOLTIP),
1224 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_SCRD_SETTINGS), SetMinimalSize(100, 20), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP),
1225 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_SCRD_RELOAD_TOGGLE), SetMinimalSize(100, 20), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_RELOAD, STR_AI_DEBUG_RELOAD_TOOLTIP),
1226 EndContainer(),
1227 EndContainer(),
1230 /* Log panel */
1232 EndContainer(),
1233 /* Break string widgets */
1236 NWidget(WWT_IMGBTN_2, Colours::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),
1239 NWidget(WWT_LABEL, Colours::Invalid), SetPadding(2, 2, 2, 4), SetStringTip(STR_AI_DEBUG_BREAK_ON_LABEL),
1240 NWidget(WWT_EDITBOX, Colours::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),
1241 EndContainer(),
1242 EndContainer(),
1243 NWidget(WWT_TEXTBTN, Colours::Grey, WID_SCRD_MATCH_CASE_BTN), SetMinimalSize(100, 0), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_MATCH_CASE, STR_AI_DEBUG_MATCH_CASE_TOOLTIP),
1244 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_SCRD_CONTINUE_BTN), SetMinimalSize(100, 0), SetFill(0, 1), SetStringTip(STR_AI_DEBUG_CONTINUE, STR_AI_DEBUG_CONTINUE_TOOLTIP),
1245 EndContainer(),
1246 EndContainer(),
1248 EndContainer(),
1252 EndContainer(),
1253EndContainer(),
1254};
1255
1258 WindowPosition::Automatic, "script_debug", 600, 450,
1259 WindowClass::ScriptDebug, WindowClass::None,
1260 {},
1262 &ScriptDebugWindow::hotkeys
1263);
1264
1271Window *ShowScriptDebugWindow(CompanyID show_company, bool new_window)
1272{
1273 if (!_networking || _network_server) {
1274 int i = 0;
1275 if (new_window) {
1276 /* find next free window number for script debug */
1277 while (FindWindowById(WindowClass::ScriptDebug, i) != nullptr) i++;
1278 } else {
1279 /* Find existing window showing show_company. */
1280 for (Window *w : Window::Iterate()) {
1281 if (w->window_class == WindowClass::ScriptDebug && static_cast<ScriptDebugWindow *>(w)->filter.script_debug_company == show_company) {
1282 return BringWindowToFrontById(w->window_class, w->window_number);
1283 }
1284 }
1285
1286 /* Maybe there's a window showing a different company which can be switched. */
1287 ScriptDebugWindow *w = static_cast<ScriptDebugWindow *>(FindWindowByClass(WindowClass::ScriptDebug));
1288 if (w != nullptr) {
1290 w->ChangeToScript(show_company);
1291 return w;
1292 }
1293 }
1294 return new ScriptDebugWindow(_script_debug_desc, i, show_company);
1295 } else {
1296 ShowErrorMessage(GetEncodedString(STR_ERROR_AI_DEBUG_SERVER_ONLY), {}, WarningLevel::Info);
1297 }
1298
1299 return nullptr;
1300}
1301
1306{
1307 ScriptDebugWindow::initial_state.script_debug_company = CompanyID::Invalid();
1308}
1309
1312{
1313 /* Network clients can't debug AIs. */
1314 if (_networking && !_network_server) return;
1315
1316 for (const Company *c : Company::Iterate()) {
1317 if (c->is_ai && c->ai_instance->IsDead()) {
1318 ShowScriptDebugWindow(c->index);
1319 break;
1320 }
1321 }
1322
1324 if (g != nullptr && g->IsDead()) {
1326 }
1327}
Base functions for all AIs.
AIConfig stores the configuration settings of every AI.
AIInfo keeps track of all information of an AI, like Author, Description, ...
The AIInstance tracks an AI.
static AIConfig * GetConfig(CompanyID company, ScriptSettingSource source=ScriptSettingSource::Default)
Get the AI configuration of specific 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:128
static void StartNew(CompanyID company)
Start a new AI company.
Definition ai_core.cpp:36
static const ScriptInfoList * GetUniqueInfoList()
Get the list of the latest version of all registered scripts.
Definition ai_core.cpp:297
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:139
static const ScriptInfoList * GetInfoList()
Get the list of all registered scripts.
Definition ai_core.cpp:292
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
static GameConfig * GetConfig(ScriptSettingSource source=ScriptSettingSource::Default)
Get the script configuration.
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:70
static class GameInfo * GetInfo()
Get the current GameInfo.
Definition game.hpp:72
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()
Get the list of the latest version of all registered scripts.
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:108
static const ScriptInfoList * GetInfoList()
Get the list of all registered scripts.
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.
void SetSetting(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:2474
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:2548
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
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:95
Definition of stuff that is very close to a company, like the company struct itself.
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.
Command definitions related to companies.
GUI Functions related to companies.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
@ NewAI
Create a new AI company.
@ Delete
Delete a company.
@ None
Dummy reason for actions that don't need one.
@ Manual
The company is manually removed.
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:570
std::unique_ptr< DropDownListItem > MakeDropDownListStringItem(StringID str, int value, bool masked, bool shaded)
Creates new DropDownListStringItem.
Definition dropdown.cpp:49
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Functions related to errors.
@ 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
Subdirectory for all AI files.
Definition fileio_type.h:99
@ Gs
Subdirectory for all game scripts.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:88
Base functions for all Games.
GameConfig stores the configuration settings of every Game.
GameInfo keeps track of all information of an Game, like Author, Description, ...
The GameInstance tracks games.
@ ForceLeft
Force align to the left.
int CentreBounds(int min, int max, int size)
Determine where to position a centred object.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:971
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:899
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:39
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:51
void GfxFillRect(int left, int top, int right, int bottom, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:116
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, ExtendedTextColour colour, Alignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:787
int DrawString(int left, int right, int top, std::string_view str, ExtendedTextColour colour, Alignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:668
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:1572
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
Colours
One of 16 base colours used for companies and windows/widgets.
Definition gfx_type.h:283
@ Mauve
Mauve.
Definition gfx_type.h:295
@ Invalid
Invalid marker.
Definition gfx_type.h:302
@ Yellow
Yellow.
Definition gfx_type.h:288
@ Orange
Orange.
Definition gfx_type.h:297
@ Grey
Grey.
Definition gfx_type.h:299
@ Red
Red.
Definition gfx_type.h:289
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:315
@ White
White colour.
Definition gfx_type.h:330
@ Yellow
Yellow colour.
Definition gfx_type.h:326
@ Orange
Orange colour.
Definition gfx_type.h:324
@ Black
Black colour.
Definition gfx_type.h:334
@ Red
Red colour.
Definition gfx_type.h:321
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 SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FontSize::Normal)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
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 NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
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:975
Hotkey related functions.
#define Point
Macro that prevents name conflicts between included headers.
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.
Miscellaneous command definitions.
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.
Types related to the misc widgets.
@ WID_TF_CAPTION
The caption of the window.
Definition misc_widget.h:53
bool _networking
are we in networking mode?
Definition network.cpp:67
bool _network_server
network-server is active
Definition network.cpp:68
Basic functions/variables used all over the place.
@ Invalid
Client is not part of anything.
@ Normal
A game normally paused.
Definition openttd.h:72
@ Editor
In the scenario editor.
Definition openttd.h:21
@ Normal
Playing a game.
Definition openttd.h:20
@ Menu
In the main menu.
Definition openttd.h:19
static constexpr PixelColour PC_BLACK
Black palette colour.
Base for the GUIs that have an edit box in them.
A number of safeguards to prevent using unsafe methods.
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.
static constexpr std::initializer_list< NWidgetPart > _nested_script_list_widgets
Widgets for the AI list window.
void ShowScriptDebugWindowIfScriptError()
Open the AI debug window if one of the AI scripts has crashed.
Window * ShowScriptDebugWindow(CompanyID show_company, bool new_window)
Open the Script debug window and select the given company.
static WindowDesc _script_settings_desc(WindowPosition::Center, "settings_script", 500, 208, WindowClass::ScriptSettings, WindowClass::None, {}, _nested_script_settings_widgets)
Window definition for the Script settings 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 std::initializer_list< NWidgetPart > _nested_script_debug_widgets
Widgets for the Script debug window.
void ShowScriptSettingsWindow(CompanyID slot)
Open the Script settings window to change the Script settings for a Script.
void ShowScriptTextfileWindow(Window *parent, TextfileType file_type, CompanyID slot)
Open the Script version of the textfile window.
static constexpr std::initializer_list< NWidgetPart > _nested_script_settings_widgets
Widgets for the Script settings window.
static WindowDesc _script_debug_desc(WindowPosition::Automatic, "script_debug", 600, 450, WindowClass::ScriptDebug, WindowClass::None, {}, _nested_script_debug_widgets, &ScriptDebugWindow::hotkeys)
Window definition for the Script debug window.
static WindowDesc _script_list_desc(WindowPosition::Center, "settings_script_list", 200, 234, WindowClass::ScriptList, WindowClass::None, {}, _nested_script_list_widgets)
Window definition for the ai list 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.
Window for configuring the scripts.
Declarations of the class for the script scanner.
std::map< std::string, class ScriptInfo *, CaseInsensitiveComparator > ScriptInfoList
Type for the list of scripts.
Types related to the script widgets.
@ 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_SCRS_SETTING_DROPDOWN
Dynamically created dropdown for changing setting value.
@ WID_SCRS_BACKGROUND
Panel to draw the settings on.
@ 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:60
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
Draw a toggle button.
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
Functions for setting GUIs.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
This file contains all sprite-related enums and defines.
static const SpriteID SPR_COMPANY_ICON
Icon showing company colour.
Definition sprites.h:385
static const SpriteID SPR_FLAG_VEH_STOPPED
Vehicle sprite-flags (red/green).
Definition sprites.h:1097
Definition of base types and functions in a cross-platform compatible way.
Parse strings.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
@ CS_NUMERAL_SIGNED
Only numbers and '-' for negative values.
Definition string_type.h:28
Searching and filtering using a stringterm.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
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:56
Functions related to OTTD's strings.
StrongType::Typedef< uint32_t, struct StringIDTag, StrongType::Compare, StrongType::Integer > 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...
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:157
List of hotkeys for a window.
Definition hotkeys.h:46
All data for a single hotkey.
Definition hotkeys.h:22
static Pool::IterateWrapper< Company > Iterate(size_t from=0)
static Company * Get(auto index)
static Company * GetIfValid(auto index)
Data stored about a string that can be modified in the GUI.
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.
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.
~ScriptDebugWindow() override
Save the last sorting state.
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
typedef for a vector of script settings
int clicked_button
The button we clicked.
void OnResize() override
Called after the window got resized.
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void RebuildVisibleSettings()
Rebuilds the list of visible settings.
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.
void OnDropdownClose(Point, WidgetID widget, int, int, bool) override
A dropdown window associated to this window has been closed.
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.
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
void Assign(std::string_view text)
Copy a string into the textbuffer.
Definition textbuf.cpp:420
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:172
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:273
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:987
void CloseChildWindows(WindowClass wc=WindowClass::Invalid) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1084
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1112
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1817
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:320
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:792
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3258
Window * parent
Parent window.
Definition window_gui.h:328
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:565
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:513
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:515
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1807
WindowClass window_class
Window class.
Definition window_gui.h:301
void CloseChildWindowById(WindowClass wc, WindowNumber number) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1099
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition window_gui.h:410
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:441
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1841
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:989
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:322
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition window.cpp:579
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:381
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Definition window_gui.h:939
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
TextfileType
Additional text files accompanying Tar archives.
Definition of Interval and OneShot timers.
Definition of the Window system.
Rect ScrollRect(Rect r, const Scrollbar &sb, int resize_step)
Apply 'scroll' to a rect to be drawn in.
Definition widget.cpp:2565
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:3492
@ 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:42
@ WWT_LABEL
Centered label.
Definition widget_type.h:48
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:44
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX).
Definition widget_type.h:57
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:50
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX).
Definition widget_type.h:55
@ WWT_CAPTION
Window caption (window title between closebox and stickybox).
Definition widget_type.h:52
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ WWT_CLOSEBOX
Close box (at top-left of a window).
Definition widget_type.h:60
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition widget_type.h:75
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window).
Definition widget_type.h:59
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX).
Definition widget_type.h:56
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
Window * FindWindowByClass(WindowClass cls)
Find any window by its class.
Definition window.cpp:1176
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1217
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:3318
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1288
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1161
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:3336
Window functions not directly related to making/drawing windows.
@ Automatic
Find a place automatically.
Definition window_gui.h:146
@ Center
Center the window.
Definition window_gui.h:147
int WidgetID
Widget ID.
Definition window_type.h:21
EventState
State of handling an event.
@ NotHandled
The passed event is not handled.