OpenTTD Source 20241224-master-gee860a5c8e
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 "../timer/timer.h"
26#include "../timer/timer_window.h"
27
28#include "script_gui.h"
29#include "script_log.hpp"
30#include "script_scanner.hpp"
31#include "script_config.hpp"
32#include "../ai/ai.hpp"
33#include "../ai/ai_config.hpp"
34#include "../ai/ai_info.hpp"
35#include "../ai/ai_instance.hpp"
36#include "../game/game.hpp"
37#include "../game/game_config.hpp"
38#include "../game/game_info.hpp"
39#include "../game/game_instance.hpp"
40#include "table/strings.h"
41
42#include "../safeguards.h"
43
44
45static ScriptConfig *GetConfig(CompanyID slot)
46{
47 if (slot == OWNER_DEITY) return GameConfig::GetConfig();
48 return AIConfig::GetConfig(slot);
49}
50
54struct ScriptListWindow : public Window {
60 bool show_all;
61
70 {
71 if (slot == OWNER_DEITY) {
72 this->info_list = this->show_all ? Game::GetInfoList() : Game::GetUniqueInfoList();
73 } else {
74 this->info_list = this->show_all ? AI::GetInfoList() : AI::GetUniqueInfoList();
75 }
76
77 this->CreateNestedTree();
78 this->vscroll = this->GetScrollbar(WID_SCRL_SCROLLBAR);
79 this->FinishInitNested(); // Initializes 'this->line_height' as side effect.
80
81 this->vscroll->SetCount(this->info_list->size() + 1);
82
83 /* Try if we can find the currently selected AI */
84 this->selected = -1;
85 if (GetConfig(slot)->HasScript()) {
86 ScriptInfo *info = GetConfig(slot)->GetInfo();
87 int i = 0;
88 for (const auto &item : *this->info_list) {
89 if (item.second == info) {
90 this->selected = i;
91 break;
92 }
93
94 i++;
95 }
96 }
97 }
98
99 void SetStringParameters(WidgetID widget) const override
100 {
101 if (widget != WID_SCRL_CAPTION) return;
102
104 }
105
107 {
108 if (widget != WID_SCRL_LIST) return;
109
110 this->line_height = GetCharacterHeight(FS_NORMAL) + padding.height;
111
112 resize.width = 1;
113 resize.height = this->line_height;
114 size.height = 5 * this->line_height;
115 }
116
117 void DrawWidget(const Rect &r, WidgetID widget) const override
118 {
119 switch (widget) {
120 case WID_SCRL_LIST: {
121 /* Draw a list of all available Scripts. */
123 /* First AI in the list is hardcoded to random */
124 if (this->vscroll->IsVisible(0)) {
125 DrawString(tr, this->slot == OWNER_DEITY ? STR_AI_CONFIG_NONE : STR_AI_CONFIG_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_ORANGE);
126 tr.top += this->line_height;
127 }
129 int i = 0;
130 for (const auto &item : *this->info_list) {
131 i++;
132 if (this->vscroll->IsVisible(i)) {
133 SetDParamStr(0, item.second->GetName());
134 SetDParam(1, item.second->GetVersion());
135 DrawString(tr, str, (this->selected == i - 1) ? TC_WHITE : TC_ORANGE);
136 tr.top += this->line_height;
137 }
138 }
139 break;
140 }
141 case WID_SCRL_INFO_BG: {
142 ScriptInfo *selected_info = nullptr;
143 int i = 0;
144 for (const auto &item : *this->info_list) {
145 i++;
146 if (this->selected == i - 1) selected_info = static_cast<ScriptInfo *>(item.second);
147 }
148 /* Some info about the currently selected Script. */
149 if (selected_info != nullptr) {
151 SetDParamStr(0, selected_info->GetAuthor());
154 SetDParam(0, selected_info->GetVersion());
157 if (!selected_info->GetURL().empty()) {
158 SetDParamStr(0, selected_info->GetURL());
161 }
162 SetDParamStr(0, selected_info->GetDescription());
164 }
165 break;
166 }
167 }
168 }
169
174 {
175 if (this->selected == -1) {
176 GetConfig(slot)->Change(std::nullopt);
177 } else {
178 ScriptInfoList::const_iterator it = this->info_list->cbegin();
179 std::advance(it, this->selected);
180 GetConfig(slot)->Change(it->second->GetName(), it->second->GetVersion());
181 }
186 }
187
188 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
189 {
190 switch (widget) {
191 case WID_SCRL_LIST: { // Select one of the Scripts
192 int sel = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCRL_LIST) - 1;
193 if (sel < (int)this->info_list->size()) {
194 this->selected = sel;
195 this->SetDirty();
196 if (click_count > 1) {
197 this->ChangeScript();
198 this->Close();
199 }
200 }
201 break;
202 }
203
204 case WID_SCRL_ACCEPT: {
205 this->ChangeScript();
206 this->Close();
207 break;
208 }
209
210 case WID_SCRL_CANCEL:
211 this->Close();
212 break;
213 }
214 }
215
216 void OnResize() override
217 {
218 this->vscroll->SetCapacityFromWidget(this, WID_SCRL_LIST);
219 }
220
226 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
227 {
228 if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot)) {
229 this->Close();
230 return;
231 }
232
233 if (!gui_scope) return;
234
235 this->vscroll->SetCount(this->info_list->size() + 1);
236
237 /* selected goes from -1 .. length of ai list - 1. */
238 this->selected = std::min(this->selected, this->vscroll->GetCount() - 2);
239 }
240};
241
245 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
246 NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_SCRL_CAPTION), SetDataTip(STR_AI_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
247 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
248 EndContainer(),
250 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),
252 EndContainer(),
254 EndContainer(),
257 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRL_ACCEPT), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_LIST_ACCEPT, STR_AI_LIST_ACCEPT_TOOLTIP),
258 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRL_CANCEL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_LIST_CANCEL, STR_AI_LIST_CANCEL_TOOLTIP),
259 EndContainer(),
260 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
261 EndContainer(),
262};
263
266 WDP_CENTER, "settings_script_list", 200, 234,
268 0,
270);
271
277void ShowScriptListWindow(CompanyID slot, bool show_all)
278{
280 new ScriptListWindow(_script_list_desc, slot, show_all);
281}
282
283
297 typedef std::vector<const ScriptConfigItem *> VisibleSettingsList;
299
306 slot(slot),
307 clicked_button(-1),
310 {
311 this->CreateNestedTree();
312 this->vscroll = this->GetScrollbar(WID_SCRS_SCROLLBAR);
313 this->FinishInitNested(slot); // Initializes 'this->line_height' as side effect.
314
315 this->OnInvalidateData();
316 }
317
324 {
325 visible_settings.clear();
326
327 for (const auto &item : *this->script_config->GetConfigList()) {
328 bool no_hide = (item.flags & SCRIPTCONFIG_DEVELOPER) == 0;
330 visible_settings.push_back(&item);
331 }
332 }
333
334 this->vscroll->SetCount(this->visible_settings.size());
335 }
336
337 void SetStringParameters(WidgetID widget) const override
338 {
339 if (widget != WID_SCRS_CAPTION) return;
340
342 }
343
345 {
346 if (widget != WID_SCRS_BACKGROUND) return;
347
348 this->line_height = std::max(SETTING_BUTTON_HEIGHT, GetCharacterHeight(FS_NORMAL)) + padding.height;
349
350 resize.width = 1;
351 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.framerect);
360 bool rtl = _current_text_dir == TD_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(FS_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 StringID str;
375 TextColour colour;
376 uint idx = 0;
377 if (config_item.description.empty()) {
378 str = STR_JUST_STRING1;
379 colour = TC_ORANGE;
380 } else {
382 colour = TC_LIGHT_BLUE;
383 SetDParamStr(idx++, config_item.description);
384 }
385
386 if ((config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0) {
387 DrawBoolButton(br.left, y + button_y_offset, current_value != 0, editable);
389 } else {
390 int i = static_cast<int>(std::distance(std::begin(this->visible_settings), it));
391 if (config_item.complete_labels) {
392 DrawDropDownButton(br.left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && clicked_dropdown, editable);
393 } else {
394 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);
395 }
396
397 auto config_iterator = config_item.labels.find(current_value);
398 if (config_iterator != config_item.labels.end()) {
400 SetDParamStr(idx++, config_iterator->second);
401 } else {
404 }
405 }
406
407 DrawString(tr.left, tr.right, y + text_y_offset, str, colour);
408 y += this->line_height;
409 }
410 }
411
412 void OnPaint() override
413 {
414 if (this->closing_dropdown) {
415 this->closing_dropdown = false;
416 this->clicked_dropdown = false;
417 }
418 this->DrawWidgets();
419 }
420
421 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
422 {
423 switch (widget) {
424 case WID_SCRS_BACKGROUND: {
425 auto it = this->vscroll->GetScrolledItemFromWidget(this->visible_settings, pt.y, this, widget);
426 if (it == this->visible_settings.end()) break;
427
428 const ScriptConfigItem &config_item = **it;
429 if (!this->IsEditableItem(config_item)) return;
430
431 int num = it - this->visible_settings.begin();
432 if (this->clicked_row != num) {
435 this->clicked_row = num;
436 this->clicked_dropdown = false;
437 }
438
439 bool bool_item = (config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0;
440
441 Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero);
442 int x = pt.x - r.left;
443 if (_current_text_dir == TD_RTL) x = r.Width() - 1 - x;
444
445 /* One of the arrows is clicked (or green/red rect in case of bool value) */
446 int old_val = this->script_config->GetSetting(config_item.name);
447 if (!bool_item && IsInsideMM(x, 0, SETTING_BUTTON_WIDTH) && config_item.complete_labels) {
448 if (this->clicked_dropdown) {
449 /* unclick the dropdown */
451 this->clicked_dropdown = false;
452 this->closing_dropdown = false;
453 } else {
454 int rel_y = (pt.y - r.top) % this->line_height;
455
456 Rect wi_rect;
457 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
458 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
459 wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
460 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
461
462 /* If the mouse is still held but dragged outside of the dropdown list, keep the dropdown open */
463 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
464 this->clicked_dropdown = true;
465 this->closing_dropdown = false;
466
467 DropDownList list;
468 for (int i = config_item.min_value; i <= config_item.max_value; i++) {
469 list.push_back(MakeDropDownListStringItem(config_item.labels.find(i)->second, i));
470 }
471
472 ShowDropDownListAt(this, std::move(list), old_val, WID_SCRS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
473 }
474 }
475 } else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
476 int new_val = old_val;
477 if (bool_item) {
478 new_val = !new_val;
479 } else if (x >= SETTING_BUTTON_WIDTH / 2) {
480 /* Increase button clicked */
481 new_val += config_item.step_size;
482 if (new_val > config_item.max_value) new_val = config_item.max_value;
483 this->clicked_increase = true;
484 } else {
485 /* Decrease button clicked */
486 new_val -= config_item.step_size;
487 if (new_val < config_item.min_value) new_val = config_item.min_value;
488 this->clicked_increase = false;
489 }
490
491 if (new_val != old_val) {
492 this->script_config->SetSetting(config_item.name, new_val);
493 this->clicked_button = num;
494 this->unclick_timeout.Reset();
495 }
496 } else if (!bool_item && !config_item.complete_labels) {
497 /* Display a query box so users can enter a custom value. */
498 SetDParam(0, old_val);
500 }
501 this->SetDirty();
502 break;
503 }
504
505 case WID_SCRS_ACCEPT:
506 this->Close();
507 break;
508
509 case WID_SCRS_RESET:
510 this->script_config->ResetEditableSettings(_game_mode == GM_MENU || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot)));
511 this->SetDirty();
512 break;
513 }
514 }
515
516 void OnQueryTextFinished(std::optional<std::string> str) override
517 {
518 if (!str.has_value() || str->empty()) return;
519 int32_t value = atoi(str->c_str());
520
521 SetValue(value);
522 }
523
524 void OnDropdownSelect(WidgetID widget, int index) override
525 {
526 if (widget != WID_SCRS_SETTING_DROPDOWN) return;
527 assert(this->clicked_dropdown);
528 SetValue(index);
529 }
530
531 void OnDropdownClose(Point, WidgetID widget, int, bool) override
532 {
533 if (widget != WID_SCRS_SETTING_DROPDOWN) return;
534 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
535 * the same dropdown button was clicked again, and then not open the dropdown again.
536 * So, we only remember that it was closed, and process it on the next OnPaint, which is
537 * after OnClick. */
538 assert(this->clicked_dropdown);
539 this->closing_dropdown = true;
540 this->SetDirty();
541 }
542
543 void OnResize() override
544 {
545 this->vscroll->SetCapacityFromWidget(this, WID_SCRS_BACKGROUND);
546 }
547
549 TimeoutTimer<TimerWindow> unclick_timeout = {std::chrono::milliseconds(150), [this]() {
550 this->clicked_button = -1;
551 this->SetDirty();
552 }};
553
559 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
560 {
561 this->script_config = GetConfig(this->slot);
562 if (this->script_config->GetConfigList()->empty()) this->Close();
566 }
567
568private:
569 bool IsEditableItem(const ScriptConfigItem &config_item) const
570 {
571 return _game_mode == GM_MENU
572 || _game_mode == GM_EDITOR
573 || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot))
574 || (config_item.flags & SCRIPTCONFIG_INGAME) != 0
576 }
577
578 void SetValue(int value)
579 {
580 const ScriptConfigItem &config_item = *this->visible_settings[this->clicked_row];
581 if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
582 this->script_config->SetSetting(config_item.name, value);
583 this->SetDirty();
584 }
585};
586
590 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
591 NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_SCRS_CAPTION), SetDataTip(STR_AI_SETTINGS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
592 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
593 EndContainer(),
597 EndContainer(),
600 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRS_ACCEPT), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_SETTINGS_CLOSE, STR_NULL),
601 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_SCRS_RESET), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_AI_SETTINGS_RESET, STR_NULL),
602 EndContainer(),
603 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
604 EndContainer(),
605};
606
609 WDP_CENTER, "settings_script", 500, 208,
611 0,
613);
614
625
626
630
632 {
633 this->ConstructWindow();
634 this->OnInvalidateData();
635 }
636
637 void SetStringParameters(WidgetID widget) const override
638 {
639 if (widget == WID_TF_CAPTION) {
641 SetDParamStr(1, GetConfig(slot)->GetInfo()->GetName());
642 }
643 }
644
645 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
646 {
647 auto textfile = GetConfig(slot)->GetTextfile(file_type, slot);
648 if (!textfile.has_value()) {
649 this->Close();
650 } else {
651 this->LoadTextfile(textfile.value(), (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR);
652 }
653 }
654};
655
662{
663 CloseWindowById(WC_TEXTFILE, file_type);
664 new ScriptTextfileWindow(file_type, slot);
665}
666
667
676static bool SetScriptButtonColour(NWidgetCore &button, bool dead, bool paused)
677{
678 /* Dead scripts are indicated with red background and
679 * paused scripts are indicated with yellow background. */
680 Colours colour = dead ? COLOUR_RED :
681 (paused ? COLOUR_YELLOW : COLOUR_GREY);
682 if (button.colour != colour) {
683 button.colour = colour;
684 return true;
685 }
686 return false;
687}
688
692struct ScriptDebugWindow : public Window {
693 static const uint MAX_BREAK_STR_STRING_LENGTH = 256;
694
701
702 static inline FilterState initial_state = {
703 "",
705 true,
706 false,
707 };
708
718 FilterState filter;
719
720 ScriptLogTypes::LogData &GetLogData() const
721 {
722 if (this->filter.script_debug_company == OWNER_DEITY) return Game::GetInstance()->GetLogData();
723 return Company::Get(this->filter.script_debug_company)->ai_instance->GetLogData();
724 }
725
730 bool IsDead() const
731 {
732 if (this->filter.script_debug_company == OWNER_DEITY) {
734 return game == nullptr || game->IsDead();
735 }
736 return !Company::IsValidAiID(this->filter.script_debug_company) || Company::Get(this->filter.script_debug_company)->ai_instance->IsDead();
737 }
738
744 bool IsValidDebugCompany(CompanyID company) const
745 {
746 switch (company) {
747 case INVALID_COMPANY: return false;
748 case OWNER_DEITY: return Game::GetInstance() != nullptr;
749 default: return Company::IsValidAiID(company);
750 }
751 }
752
758 {
759 /* Check if the currently selected company is still active. */
760 if (this->IsValidDebugCompany(this->filter.script_debug_company)) return;
761
763
764 for (const Company *c : Company::Iterate()) {
765 if (c->is_ai) {
766 ChangeToScript(c->index);
767 return;
768 }
769 }
770
771 /* If no AI is available, see if there is a game script. */
773 }
774
781 {
782 this->filter = ScriptDebugWindow::initial_state;
783 this->break_string_filter = {&this->filter.case_sensitive_break_check, false};
784
785 this->CreateNestedTree();
786 this->vscroll = this->GetScrollbar(WID_SCRD_VSCROLLBAR);
787 this->hscroll = this->GetScrollbar(WID_SCRD_HSCROLLBAR);
788 this->FinishInitNested(number);
789
790 this->last_vscroll_pos = 0;
791 this->autoscroll = true;
792 this->highlight_row = -1;
793
795
796 this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar
797
798 /* Restore the break string value from static variable, and enable the filter. */
799 this->break_editbox.text.Assign(this->filter.break_string);
800 this->break_string_filter.SetFilterTerm(this->filter.break_string);
801
804 } else {
805 this->ChangeToScript(show_company);
806 }
807 }
808
809 void OnInit() override
810 {
811 this->show_break_box = _settings_client.gui.ai_developer_tools;
812 this->GetWidget<NWidgetStacked>(WID_SCRD_BREAK_STRING_WIDGETS)->SetDisplayedPlane(this->show_break_box ? 0 : SZSP_HORIZONTAL);
813 if (!this->show_break_box) this->filter.break_check_enabled = false;
815
816 this->InvalidateData(-1);
817 }
818
820 {
821 ScriptDebugWindow::initial_state = this->filter;
822 }
823
825 {
826 if (widget == WID_SCRD_LOG_PANEL) {
828 size.height = 14 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
829 }
830 }
831
832 void OnPaint() override
833 {
835 this->UpdateLogScroll();
836
837 /* Draw standard stuff */
838 this->DrawWidgets();
839 }
840
841 void SetStringParameters(WidgetID widget) const override
842 {
843 if (widget != WID_SCRD_NAME_TEXT) return;
844
845 if (this->filter.script_debug_company == OWNER_DEITY) {
846 const GameInfo *info = Game::GetInfo();
847 assert(info != nullptr);
849 SetDParamStr(1, info->GetName());
850 SetDParam(2, info->GetVersion());
851 } else if (this->filter.script_debug_company == INVALID_COMPANY || !Company::IsValidAiID(this->filter.script_debug_company)) {
853 } else {
854 const AIInfo *info = Company::Get(this->filter.script_debug_company)->ai_info;
855 assert(info != nullptr);
857 SetDParamStr(1, info->GetName());
858 SetDParam(2, info->GetVersion());
859 }
860 }
861
862 void DrawWidget(const Rect &r, WidgetID widget) const override
863 {
864 switch (widget) {
866 this->DrawWidgetLog(r);
867 break;
868
869 default:
872 }
873 break;
874 }
875 }
876
883 void DrawWidgetCompanyButton(const Rect &r, WidgetID widget, int start) const
884 {
885 if (this->IsWidgetDisabled(widget)) return;
886 CompanyID cid = (CompanyID)(widget - start);
887 Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
888 DrawCompanyIcon(cid, CenterBounds(r.left, r.right, sprite_size.width), CenterBounds(r.top, r.bottom, sprite_size.height));
889 }
890
895 void DrawWidgetLog(const Rect &r) const
896 {
897 if (this->filter.script_debug_company == INVALID_COMPANY) return;
898
899 const ScriptLogTypes::LogData &log = this->GetLogData();
900 if (log.empty()) return;
901
902 Rect fr = r.Shrink(WidgetDimensions::scaled.framerect);
903
904 /* Setup a clipping rectangle... */
906 if (!FillDrawPixelInfo(&tmp_dpi, fr)) return;
907 /* ...but keep coordinates relative to the window. */
908 tmp_dpi.left += fr.left;
909 tmp_dpi.top += fr.top;
910
912
913 fr = ScrollRect(fr, *this->hscroll, 1);
914
915 auto [first, last] = this->vscroll->GetVisibleRangeIterators(log);
916 for (auto it = first; it != last; ++it) {
917 const ScriptLogTypes::LogLine &line = *it;
918
919 TextColour colour;
920 switch (line.type) {
921 case ScriptLogTypes::LOG_SQ_INFO: colour = TC_BLACK; break;
922 case ScriptLogTypes::LOG_SQ_ERROR: colour = TC_WHITE; break;
923 case ScriptLogTypes::LOG_INFO: colour = TC_BLACK; break;
924 case ScriptLogTypes::LOG_WARNING: colour = TC_YELLOW; break;
925 case ScriptLogTypes::LOG_ERROR: colour = TC_RED; break;
926 default: colour = TC_BLACK; break;
927 }
928
929 /* Check if the current line should be highlighted */
930 if (std::distance(std::begin(log), it) == this->highlight_row) {
931 fr.bottom = fr.top + this->resize.step_height - 1;
933 if (colour == TC_BLACK) colour = TC_WHITE; // Make black text readable by inverting it to white.
934 }
935
936 DrawString(fr, line.text, colour, SA_LEFT | SA_FORCE);
937 fr.top += this->resize.step_height;
938 }
939 }
940
945 {
947 if (this->filter.script_debug_company == INVALID_COMPANY) return;
948
949 ScriptLogTypes::LogData &log = this->GetLogData();
950
951 int scroll_count = (int)log.size();
952 if (this->vscroll->GetCount() != scroll_count) {
953 this->vscroll->SetCount(scroll_count);
954
955 /* We need a repaint */
957 }
958
959 if (log.empty()) return;
960
961 /* Detect when the user scrolls the window. Enable autoscroll when the bottom-most line becomes visible. */
962 if (this->last_vscroll_pos != this->vscroll->GetPosition()) {
963 this->autoscroll = this->vscroll->GetPosition() + this->vscroll->GetCapacity() >= (int)log.size();
964 }
965
966 if (this->autoscroll && this->vscroll->SetPosition((int)log.size())) {
967 /* We need a repaint */
970 }
971
972 this->last_vscroll_pos = this->vscroll->GetPosition();
973 }
974
979 {
980 /* Update company buttons */
981 for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
982 /* Mark dead/paused AIs by setting the background colour. */
983 bool valid = Company::IsValidAiID(i);
984 bool dead = valid && Company::Get(i)->ai_instance->IsDead();
985 bool paused = valid && Company::Get(i)->ai_instance->IsPaused();
986
988 button->SetDisabled(!valid);
989 button->SetLowered(this->filter.script_debug_company == i);
991 }
992 }
993
998 {
1000 bool valid = game != nullptr;
1001 bool dead = valid && game->IsDead();
1002 bool paused = valid && game->IsPaused();
1003
1005 button->SetDisabled(!valid);
1006 button->SetLowered(this->filter.script_debug_company == OWNER_DEITY);
1008 }
1009
1016 {
1017 if (!this->IsValidDebugCompany(show_script)) return;
1018
1019 if (new_window) {
1020 ScriptDebugWindow::initial_state = this->filter;
1022 return;
1023 }
1024
1025 this->filter.script_debug_company = show_script;
1026
1027 this->highlight_row = -1; // The highlight of one Script make little sense for another Script.
1028
1029 /* Close AI settings window to prevent confusion */
1031
1032 this->InvalidateData(-1);
1033
1034 this->autoscroll = true;
1035 this->last_vscroll_pos = this->vscroll->GetPosition();
1036 }
1037
1038 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1039 {
1040 /* Also called for hotkeys, so check for disabledness */
1041 if (this->IsWidgetDisabled(widget)) return;
1042
1043 /* Check which button is clicked */
1046 }
1047
1048 switch (widget) {
1051 break;
1052
1054 if (this->filter.script_debug_company == OWNER_DEITY) break;
1055 /* First kill the company of the AI, then start a new one. This should start the current AI again */
1058 break;
1059
1060 case WID_SCRD_SETTINGS:
1062 break;
1063
1065 this->filter.break_check_enabled = !this->filter.break_check_enabled;
1066 this->InvalidateData(-1);
1067 break;
1068
1070 this->filter.case_sensitive_break_check = !this->filter.case_sensitive_break_check;
1071 this->InvalidateData(-1);
1072 break;
1073
1075 /* Unpause current AI / game script and mark the corresponding script button dirty. */
1076 if (!this->IsDead()) {
1077 if (this->filter.script_debug_company == OWNER_DEITY) {
1078 Game::Unpause();
1079 } else {
1080 AI::Unpause(this->filter.script_debug_company);
1081 }
1082 }
1083
1084 /* If the last AI/Game Script is unpaused, unpause the game too. */
1086 bool all_unpaused = !Game::IsPaused();
1087 if (all_unpaused) {
1088 for (const Company *c : Company::Iterate()) {
1089 if (c->is_ai && AI::IsPaused(c->index)) {
1090 all_unpaused = false;
1091 break;
1092 }
1093 }
1094 if (all_unpaused) {
1095 /* All scripts have been unpaused => unpause the game. */
1097 }
1098 }
1099 }
1100
1101 this->highlight_row = -1;
1102 this->InvalidateData(-1);
1103 break;
1104 }
1105 }
1106
1108 {
1109 if (wid != WID_SCRD_BREAK_STR_EDIT_BOX) return;
1110
1111 /* Save the current string to static member so it can be restored next time the window is opened. */
1112 this->filter.break_string = this->break_editbox.text.buf;
1113 this->break_string_filter.SetFilterTerm(this->filter.break_string);
1114 }
1115
1122 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1123 {
1124 if (this->show_break_box != _settings_client.gui.ai_developer_tools) this->ReInit();
1125
1126 /* If the log message is related to the active company tab, check the break string.
1127 * This needs to be done in gameloop-scope, so the AI is suspended immediately. */
1128 if (!gui_scope && data == this->filter.script_debug_company &&
1129 this->IsValidDebugCompany(this->filter.script_debug_company) &&
1130 this->filter.break_check_enabled && !this->break_string_filter.IsEmpty()) {
1131 /* Get the log instance of the active company */
1132 ScriptLogTypes::LogData &log = this->GetLogData();
1133
1134 if (!log.empty()) {
1135 this->break_string_filter.ResetState();
1136 this->break_string_filter.AddLine(log.back().text);
1137 if (this->break_string_filter.GetState()) {
1138 /* Pause execution of script. */
1139 if (!this->IsDead()) {
1140 if (this->filter.script_debug_company == OWNER_DEITY) {
1141 Game::Pause();
1142 } else {
1143 AI::Pause(this->filter.script_debug_company);
1144 }
1145 }
1146
1147 /* Pause the game. */
1150 }
1151
1152 /* Highlight row that matched */
1153 this->highlight_row = (int)(log.size() - 1);
1154 }
1155 }
1156 }
1157
1158 if (!gui_scope) return;
1159
1161
1162 uint max_width = 0;
1163 if (this->filter.script_debug_company != INVALID_COMPANY) {
1164 for (auto &line : this->GetLogData()) {
1165 if (line.width == 0 || data == -1) line.width = GetStringBoundingBox(line.text).width;
1166 max_width = std::max(max_width, line.width);
1167 }
1168 }
1169
1170 this->vscroll->SetCount(this->filter.script_debug_company != INVALID_COMPANY ? this->GetLogData().size() : 0);
1171 this->hscroll->SetCount(max_width + WidgetDimensions::scaled.frametext.Horizontal());
1172
1173 this->UpdateAIButtonsState();
1174 this->UpdateGSButtonState();
1175
1178
1180 GetConfig(this->filter.script_debug_company)->GetConfigList()->empty());
1183 this->filter.script_debug_company == INVALID_COMPANY ||
1184 this->filter.script_debug_company == OWNER_DEITY ||
1185 this->filter.script_debug_company == _local_company);
1187 (this->filter.script_debug_company == OWNER_DEITY ? !Game::IsPaused() : !AI::IsPaused(this->filter.script_debug_company)));
1188 }
1189
1190 void OnResize() override
1191 {
1192 this->vscroll->SetCapacityFromWidget(this, WID_SCRD_LOG_PANEL, WidgetDimensions::scaled.framerect.Vertical());
1193 this->hscroll->SetCapacityFromWidget(this, WID_SCRD_LOG_PANEL, WidgetDimensions::scaled.framerect.Horizontal());
1194 }
1195
1202 {
1203 if (_game_mode != GM_NORMAL) return ES_NOT_HANDLED;
1205 if (w == nullptr) return ES_NOT_HANDLED;
1206 return w->OnHotkey(hotkey);
1207 }
1208
1209 static inline HotkeyList hotkeys{"aidebug", {
1210 Hotkey('1', "company_1", WID_SCRD_COMPANY_BUTTON_START),
1211 Hotkey('2', "company_2", WID_SCRD_COMPANY_BUTTON_START + 1),
1212 Hotkey('3', "company_3", WID_SCRD_COMPANY_BUTTON_START + 2),
1213 Hotkey('4', "company_4", WID_SCRD_COMPANY_BUTTON_START + 3),
1214 Hotkey('5', "company_5", WID_SCRD_COMPANY_BUTTON_START + 4),
1215 Hotkey('6', "company_6", WID_SCRD_COMPANY_BUTTON_START + 5),
1216 Hotkey('7', "company_7", WID_SCRD_COMPANY_BUTTON_START + 6),
1217 Hotkey('8', "company_8", WID_SCRD_COMPANY_BUTTON_START + 7),
1218 Hotkey('9', "company_9", WID_SCRD_COMPANY_BUTTON_START + 8),
1219 Hotkey(0, "company_10", WID_SCRD_COMPANY_BUTTON_START + 9),
1220 Hotkey(0, "company_11", WID_SCRD_COMPANY_BUTTON_START + 10),
1221 Hotkey(0, "company_12", WID_SCRD_COMPANY_BUTTON_START + 11),
1222 Hotkey(0, "company_13", WID_SCRD_COMPANY_BUTTON_START + 12),
1223 Hotkey(0, "company_14", WID_SCRD_COMPANY_BUTTON_START + 13),
1224 Hotkey(0, "company_15", WID_SCRD_COMPANY_BUTTON_START + 14),
1225 Hotkey('S', "settings", WID_SCRD_SETTINGS),
1226 Hotkey('0', "game_script", WID_SCRD_SCRIPT_GAME),
1227 Hotkey(0, "reload", WID_SCRD_RELOAD_TOGGLE),
1228 Hotkey('B', "break_toggle", WID_SCRD_BREAK_STR_ON_OFF_BTN),
1229 Hotkey('F', "break_string", WID_SCRD_BREAK_STR_EDIT_BOX),
1230 Hotkey('C', "match_case", WID_SCRD_MATCH_CASE_BTN),
1231 Hotkey(WKC_RETURN, "continue", WID_SCRD_CONTINUE_BTN),
1233};
1234
1236std::unique_ptr<NWidgetBase> MakeCompanyButtonRowsScriptDebug()
1237{
1238 return MakeCompanyButtonRows(WID_SCRD_COMPANY_BUTTON_START, WID_SCRD_COMPANY_BUTTON_END, COLOUR_GREY, 5, STR_AI_DEBUG_SELECT_AI_TOOLTIP, false);
1239}
1240
1244 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1245 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_AI_DEBUG, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1246 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1247 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1248 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1249 EndContainer(),
1251 NWidget(WWT_PANEL, COLOUR_GREY, WID_SCRD_VIEW),
1253 EndContainer(),
1254 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCRD_SCRIPT_GAME), SetMinimalSize(100, 20), SetDataTip(STR_AI_GAME_SCRIPT, STR_AI_GAME_SCRIPT_TOOLTIP),
1255 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCRD_NAME_TEXT), SetResize(1, 0), SetDataTip(STR_JUST_STRING2, STR_AI_DEBUG_NAME_TOOLTIP),
1257 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCRD_SETTINGS), SetMinimalSize(100, 20), SetFill(0, 1), SetDataTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP),
1258 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCRD_RELOAD_TOGGLE), SetMinimalSize(100, 20), SetFill(0, 1), SetDataTip(STR_AI_DEBUG_RELOAD, STR_AI_DEBUG_RELOAD_TOOLTIP),
1259 EndContainer(),
1260 EndContainer(),
1263 /* Log panel */
1265 EndContainer(),
1266 /* Break string widgets */
1269 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_SCRD_BREAK_STR_ON_OFF_BTN), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG), SetFill(0, 1), SetDataTip(SPR_FLAG_VEH_STOPPED, STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP),
1270 NWidget(WWT_PANEL, COLOUR_GREY),
1272 NWidget(WWT_LABEL, COLOUR_GREY), SetPadding(2, 2, 2, 4), SetDataTip(STR_AI_DEBUG_BREAK_ON_LABEL, 0x0),
1273 NWidget(WWT_EDITBOX, COLOUR_GREY, WID_SCRD_BREAK_STR_EDIT_BOX), SetFill(1, 1), SetResize(1, 0), SetPadding(2, 2, 2, 2), SetDataTip(STR_AI_DEBUG_BREAK_STR_OSKTITLE, STR_AI_DEBUG_BREAK_STR_TOOLTIP),
1274 EndContainer(),
1275 EndContainer(),
1276 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCRD_MATCH_CASE_BTN), SetMinimalSize(100, 0), SetFill(0, 1), SetDataTip(STR_AI_DEBUG_MATCH_CASE, STR_AI_DEBUG_MATCH_CASE_TOOLTIP),
1277 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCRD_CONTINUE_BTN), SetMinimalSize(100, 0), SetFill(0, 1), SetDataTip(STR_AI_DEBUG_CONTINUE, STR_AI_DEBUG_CONTINUE_TOOLTIP),
1278 EndContainer(),
1279 EndContainer(),
1281 EndContainer(),
1284 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1285 EndContainer(),
1286EndContainer(),
1287};
1288
1291 WDP_AUTO, "script_debug", 600, 450,
1293 0,
1295 &ScriptDebugWindow::hotkeys
1296);
1297
1303Window *ShowScriptDebugWindow(CompanyID show_company, bool new_window)
1304{
1305 if (!_networking || _network_server) {
1306 int i = 0;
1307 if (new_window) {
1308 /* find next free window number for script debug */
1309 while (FindWindowById(WC_SCRIPT_DEBUG, i) != nullptr) i++;
1310 } else {
1311 /* Find existing window showing show_company. */
1312 for (Window *w : Window::Iterate()) {
1313 if (w->window_class == WC_SCRIPT_DEBUG && static_cast<ScriptDebugWindow *>(w)->filter.script_debug_company == show_company) {
1314 return BringWindowToFrontById(w->window_class, w->window_number);
1315 }
1316 }
1317
1318 /* Maybe there's a window showing a different company which can be switched. */
1320 if (w != nullptr) {
1322 w->ChangeToScript(show_company);
1323 return w;
1324 }
1325 }
1326 return new ScriptDebugWindow(_script_debug_desc, i, show_company);
1327 } else {
1328 ShowErrorMessage(STR_ERROR_AI_DEBUG_SERVER_ONLY, INVALID_STRING_ID, WL_INFO);
1329 }
1330
1331 return nullptr;
1332}
1333
1338{
1339 ScriptDebugWindow::initial_state.script_debug_company = INVALID_COMPANY;
1340}
1341
1344{
1345 /* Network clients can't debug AIs. */
1346 if (_networking && !_network_server) return;
1347
1348 for (const Company *c : Company::Iterate()) {
1349 if (c->is_ai && c->ai_instance->IsDead()) {
1350 ShowScriptDebugWindow(c->index);
1351 break;
1352 }
1353 }
1354
1356 if (g != nullptr && g->IsDead()) {
1358 }
1359}
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 const ScriptInfoList * GetUniqueInfoList()
Wrapper function for AIScanner::GetUniqueAIInfoList.
Definition ai_core.cpp:311
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:306
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 class GameInfo * GetInfo()
Get the current GameInfo.
Definition game.hpp:75
static void Unpause()
Resume execution of the Game Script.
static bool IsPaused()
Checks if the Game Script is paused.
static const ScriptInfoList * GetUniqueInfoList()
Wrapper function for GameScanner::GetUniqueInfoList.
static class GameInstance * GetGameInstance()
Get the current GameScript instance.
Definition game.hpp:70
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:101
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< const 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.
int GetVersion() const
Get the version 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:2377
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:2451
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:42
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:60
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:96
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.
@ CCA_NEW_AI
Create a new AI company.
@ CCA_DELETE
Delete a company.
Owner
Enum for all companies/owners.
@ INVALID_COMPANY
An invalid company.
@ COMPANY_FIRST
First company, same as owner.
@ OWNER_DEITY
The object is owned by a superuser / goal script.
@ MAX_COMPANIES
Maximum number of companies.
@ 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:386
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
@ 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:922
PauseMode _pause_mode
The current pause mode.
Definition gfx.cpp:50
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:851
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:657
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:114
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:774
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:1548
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
@ SA_LEFT
Left align the text.
Definition gfx_type.h:343
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:355
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:260
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 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 SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
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 SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
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 SetAspect(float ratio, AspectFlags flags=AspectFlags::ResizeX)
Widget part function for setting the aspect ratio.
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:940
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 T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
void ShowQueryString(StringID 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:65
bool _network_server
network-server is active
Definition network.cpp:66
@ 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).
@ PM_UNPAUSED
A normal unpaused game.
Definition openttd.h:69
@ PM_PAUSED_NORMAL
A game normally paused.
Definition openttd.h:70
static const uint8_t PC_BLACK
Black palette colour.
ScriptConfig stores the configuration settings of every Script.
@ SCRIPTCONFIG_INGAME
This setting can be changed while the Script is running.
@ SCRIPTCONFIG_BOOLEAN
This value is a boolean (either 0 (false) or 1 (true) ).
@ SCRIPTCONFIG_DEVELOPER
This setting will only be visible when the Script development tools are active.
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'.
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.
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 WindowDesc _script_list_desc(WDP_CENTER, "settings_script_list", 200, 234, WC_SCRIPT_LIST, WC_NONE, 0, _nested_script_list_widgets)
Window definition for the ai list window.
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_debug_desc(WDP_AUTO, "script_debug", 600, 450, WC_SCRIPT_DEBUG, WC_NONE, 0, _nested_script_debug_widgets, &ScriptDebugWindow::hotkeys)
Window definition for the Script debug window.
void ShowScriptSettingsWindow(CompanyID slot)
Open the Script settings window to change the Script settings for a Script.
static constexpr NWidgetPart _nested_script_settings_widgets[]
Widgets for the Script settings window.
static WindowDesc _script_settings_desc(WDP_CENTER, "settings_script", 500, 208, WC_SCRIPT_SETTINGS, WC_NONE, 0, _nested_script_settings_widgets)
Window definition 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:56
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
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:104
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition strings.cpp:371
@ TD_RTL
Text is written right-to-left by default.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
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(size_t 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
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 bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(size_t 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:214
Info about a single Script setting.
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.
int redraw_timer
Timer for redrawing the window, otherwise it'll happen every tick.
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 INVALID_COMPANY.
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.
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters 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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters 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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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.
String filter and state.
void SetFilterTerm(const char *str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
bool GetState() const
Get the matching state of the current item.
void Assign(StringID string)
Render a string into the textbuffer.
Definition textbuf.cpp:431
char *const buf
buffer in which text is saved
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:159
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:952
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1047
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
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:732
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3159
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:551
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1035
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:521
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
WindowClass window_class
Window class.
Definition window_gui.h:301
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition window_gui.h:416
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:447
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition window.cpp:565
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:387
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Definition window_gui.h:927
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
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:2468
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:3358
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
@ 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:53
@ WWT_LABEL
Centered label.
Definition widget_type.h:57
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:71
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:75
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:55
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:50
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:66
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:59
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:64
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition widget_type.h:84
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:80
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:1140
Window * FindWindowByClass(WindowClass cls)
Find any window by its class.
Definition window.cpp:1113
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1152
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:3219
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1223
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1098
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:3236
@ WDP_CENTER
Center the window.
Definition window_gui.h:148
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:147
int WidgetID
Widget ID.
Definition window_type.h:18
@ WN_GAME_OPTIONS_GS
GS settings.
Definition window_type.h:23
@ WN_GAME_OPTIONS_AI
AI settings.
Definition window_type.h:22
int32_t WindowNumber
Number to differentiate different windows of the same class.
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:45
@ 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: