OpenTTD Source  20241124-master-g9399a92a4f
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 
45 static ScriptConfig *GetConfig(CompanyID slot)
46 {
47  if (slot == OWNER_DEITY) return GameConfig::GetConfig();
48  return AIConfig::GetConfig(slot);
49 }
50 
54 struct ScriptListWindow : public Window {
56  int selected;
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 
103  SetDParam(0, (this->slot == OWNER_DEITY) ? STR_AI_LIST_CAPTION_GAMESCRIPT : STR_AI_LIST_CAPTION_AI);
104  }
105 
106  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
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. */
122  Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
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  }
128  StringID str = this->show_all ? STR_AI_CONFIG_NAME_VERSION : STR_JUST_RAW_STRING;
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) {
150  Rect tr = r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
151  SetDParamStr(0, selected_info->GetAuthor());
152  DrawString(tr, STR_AI_LIST_AUTHOR);
154  SetDParam(0, selected_info->GetVersion());
155  DrawString(tr, STR_AI_LIST_VERSION);
157  if (!selected_info->GetURL().empty()) {
158  SetDParamStr(0, selected_info->GetURL());
159  DrawString(tr, STR_AI_LIST_URL);
161  }
162  SetDParamStr(0, selected_info->GetDescription());
163  DrawStringMultiLine(tr, STR_JUST_RAW_STRING, TC_WHITE);
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 
277 void ShowScriptListWindow(CompanyID slot, bool show_all)
278 {
280  new ScriptListWindow(_script_list_desc, slot, show_all);
281 }
282 
283 
287 struct ScriptSettingsWindow : public Window {
297  typedef std::vector<const ScriptConfigItem *> VisibleSettingsList;
299 
306  slot(slot),
307  clicked_button(-1),
308  clicked_dropdown(false),
309  closing_dropdown(false)
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;
329  if (no_hide || _settings_client.gui.ai_developer_tools) {
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 
341  SetDParam(0, (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(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;
361  Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
362  Rect tr = ir.Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, 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 {
381  str = STR_AI_SETTINGS_SETTING;
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);
388  SetDParam(idx++, current_value == 0 ? STR_CONFIG_SETTING_OFF : STR_CONFIG_SETTING_ON);
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()) {
399  SetDParam(idx++, STR_JUST_RAW_STRING);
400  SetDParamStr(idx++, config_iterator->second);
401  } else {
402  SetDParam(idx++, STR_JUST_INT);
403  SetDParam(idx++, current_value);
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);
499  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, INT32_DIGITS_WITH_SIGN_AND_TERMINATION, this, CS_NUMERAL_SIGNED, QSF_NONE);
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();
563  this->RebuildVisibleSettings();
566  }
567 
568 private:
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(),
595  NWidget(WWT_MATRIX, COLOUR_MAUVE, WID_SCRS_BACKGROUND), SetMinimalSize(188, 182), SetResize(1, 1), SetFill(1, 0), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_SCRS_SCROLLBAR),
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 
620 {
624 }
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) {
640  SetDParam(0, (slot == OWNER_DEITY) ? STR_CONTENT_TYPE_GAME_SCRIPT : STR_CONTENT_TYPE_AI);
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 
676 static 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 
692 struct ScriptDebugWindow : public Window {
693  static const uint MAX_BREAK_STR_STRING_LENGTH = 256;
694 
695  struct FilterState {
696  std::string break_string;
700  };
701 
702  static inline FilterState initial_state = {
703  "",
705  true,
706  false,
707  };
708 
711  bool autoscroll;
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 
762  this->filter.script_debug_company = INVALID_COMPANY;
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. */
772  if (Game::GetInstance() != nullptr) ChangeToScript(OWNER_DEITY);
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 
802  if (show_company == INVALID_COMPANY) {
803  this->SelectValidDebugCompany();
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 
824  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
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  {
834  this->SelectValidDebugCompany();
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);
848  SetDParam(0, STR_AI_DEBUG_NAME_AND_VERSION);
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)) {
852  SetDParam(0, STR_EMPTY);
853  } else {
854  const AIInfo *info = Company::Get(this->filter.script_debug_company)->ai_info;
855  assert(info != nullptr);
856  SetDParam(0, STR_AI_DEBUG_NAME_AND_VERSION);
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) {
865  case WID_SCRD_LOG_PANEL:
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... */
905  DrawPixelInfo tmp_dpi;
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 
911  AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
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;
932  GfxFillRect(fr, PC_BLACK);
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 
987  NWidgetCore *button = this->GetWidget<NWidgetCore>(WID_SCRD_COMPANY_BUTTON_START + i);
988  button->SetDisabled(!valid);
989  button->SetLowered(this->filter.script_debug_company == i);
990  SetScriptButtonColour(*button, dead, paused);
991  }
992  }
993 
998  {
1000  bool valid = game != nullptr;
1001  bool dead = valid && game->IsDead();
1002  bool paused = valid && game->IsPaused();
1003 
1004  NWidgetCore *button = this->GetWidget<NWidgetCore>(WID_SCRD_SCRIPT_GAME);
1005  button->SetDisabled(!valid);
1006  button->SetLowered(this->filter.script_debug_company == OWNER_DEITY);
1007  SetScriptButtonColour(*button, dead, paused);
1008  }
1009 
1015  void ChangeToScript(CompanyID show_script, bool new_window = false)
1016  {
1017  if (!this->IsValidDebugCompany(show_script)) return;
1018 
1019  if (new_window) {
1020  ScriptDebugWindow::initial_state = this->filter;
1021  ShowScriptDebugWindow(show_script, true);
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) {
1049  case WID_SCRD_SCRIPT_GAME:
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 
1074  case WID_SCRD_CONTINUE_BTN:
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 
1107  void OnEditboxChanged(WidgetID wid) override
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 
1160  this->SelectValidDebugCompany();
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());
1181  extern CompanyID _local_company;
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 
1236 std::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(),
1286 EndContainer(),
1287 };
1288 
1291  WDP_AUTO, "script_debug", 600, 450,
1293  0,
1295  &ScriptDebugWindow::hotkeys
1296 );
1297 
1303 Window *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.
Definition: game_config.cpp:18
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 GameInstance * GetGameInstance()
Get the current GameScript instance.
Definition: game.hpp:70
static void Unpause()
Resume execution of the Game Script.
Definition: game_core.cpp:136
static bool IsPaused()
Checks if the Game Script is paused.
Definition: game_core.cpp:141
static class GameInstance * GetInstance()
Get the current active instance.
Definition: game.hpp:101
static const ScriptInfoList * GetUniqueInfoList()
Wrapper function for GameScanner::GetUniqueInfoList.
Definition: game_core.cpp:232
static void Pause()
Suspends the Game Script and then pause the execution of the script.
Definition: game_core.cpp:131
static class GameInfo * GetInfo()
Get the current GameInfo.
Definition: game.hpp:75
static const ScriptInfoList * GetInfoList()
Wrapper function for GameScanner::GetInfoList.
Definition: game_core.cpp:227
Base class for a 'real' widget.
Definition: widget_type.h:370
Colours colour
Colour of this widget.
Definition: widget_type.h:391
void SetLowered(bool lowered)
Lower or raise the widget.
Definition: widget_type.h:428
void SetDisabled(bool disabled)
Disable (grey-out) or enable the widget.
Definition: widget_type.h:443
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.
Definition: script_info.hpp:30
const std::string & GetAuthor() const
Get the Author of the script.
Definition: script_info.hpp:41
int GetVersion() const
Get the version of the script.
Definition: script_info.hpp:61
const std::string & GetName() const
Get the Name of the script.
Definition: script_info.hpp:46
const std::string & GetDescription() const
Get the description of the script.
Definition: script_info.hpp:56
const std::string & GetURL() const
Get the website for this script.
Definition: script_info.hpp:76
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.
Definition: widget_type.h:694
bool IsVisible(size_type item) const
Checks whether given current item is visible in the list.
Definition: widget_type.h:750
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:731
void SetCount(size_t num)
Sets the number of elements in the list.
Definition: widget_type.h:780
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.
Definition: widget_type.h:879
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:2320
bool SetPosition(size_type position)
Sets the position of the first visible element.
Definition: widget_type.h:810
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:2394
size_type GetCount() const
Gets the number of elements in the list.
Definition: widget_type.h:722
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
Definition: widget_type.h:860
void SetStepSize(size_t stepsize)
Set the distance to scroll when using the buttons or the wheel.
Definition: widget_type.h:768
size_type GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:740
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:68
int vsep_normal
Normal vertical spacing.
Definition: window_gui.h:60
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition: window_gui.h:67
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.
Definition: company_cmd.cpp:52
@ CCA_NEW_AI
Create a new AI company.
Definition: company_type.h:69
@ CCA_DELETE
Delete a company.
Definition: company_type.h:70
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ INVALID_COMPANY
An invalid company.
Definition: company_type.h:30
@ COMPANY_FIRST
First company, same as owner.
Definition: company_type.h:22
@ OWNER_DEITY
The object is owned by a superuser / goal script.
Definition: company_type.h:27
@ MAX_COMPANIES
Maximum number of companies.
Definition: company_type.h:23
@ CRR_NONE
Dummy reason for actions that don't need one.
Definition: company_type.h:63
@ CRR_MANUAL
The company is manually removed.
Definition: company_type.h:57
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.
Definition: dropdown_type.h:50
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Definition: error_gui.cpp:367
@ 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.
Definition: fileio_type.h:126
@ GAME_DIR
Subdirectory for all game scripts.
Definition: fileio_type.h:128
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.
Definition: widget_type.h:1330
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition: widget_type.h:1181
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1284
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.
Definition: widget_type.h:1228
constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1202
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
Definition: widget_type.h:1137
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
Definition: widget_type.h:1309
constexpr NWidgetPart SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1214
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition: widget_type.h:1191
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:1149
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlags::ResizeX)
Widget part function for setting the aspect ratio.
Definition: widget_type.h:1295
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Definition: widget_type.h:1126
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.
Definition: math_func.hpp:252
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition: math_func.hpp:268
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1079
@ 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.
Definition: network_type.h:50
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.
Definition: palette_func.h:67
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.
Definition: script_gui.cpp:243
static bool SetScriptButtonColour(NWidgetCore &button, bool dead, bool paused)
Set the widget colour of a button based on the state of the script.
Definition: script_gui.cpp:676
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.
Definition: script_gui.cpp:661
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.
Definition: script_gui.cpp:619
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 constexpr NWidgetPart _nested_script_settings_widgets[]
Widgets for the Script settings window.
Definition: script_gui.cpp:588
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.
Definition: script_gui.cpp:277
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.
Definition: script_widget.h:39
@ WID_SCRD_BREAK_STRING_WIDGETS
The panel to handle the breaking on string.
Definition: script_widget.h:47
@ WID_SCRD_SCRIPT_GAME
Game Script button.
Definition: script_widget.h:41
@ WID_SCRD_RELOAD_TOGGLE
Reload button.
Definition: script_widget.h:42
@ WID_SCRD_HSCROLLBAR
Horizontal scrollbar of the log panel.
Definition: script_widget.h:52
@ WID_SCRD_SETTINGS
Settings button.
Definition: script_widget.h:40
@ WID_SCRD_BREAK_STR_EDIT_BOX
Edit box for the string to break on.
Definition: script_widget.h:49
@ WID_SCRD_COMPANY_BUTTON_START
Buttons in the VIEW.
Definition: script_widget.h:45
@ WID_SCRD_VIEW
The row of company buttons.
Definition: script_widget.h:38
@ WID_SCRD_MATCH_CASE_BTN
Checkbox to use match caching or not.
Definition: script_widget.h:50
@ WID_SCRD_BREAK_STR_ON_OFF_BTN
Enable breaking on string.
Definition: script_widget.h:48
@ WID_SCRD_VSCROLLBAR
Vertical scrollbar of the log panel.
Definition: script_widget.h:44
@ WID_SCRD_LOG_PANEL
Panel where the log is in.
Definition: script_widget.h:43
@ WID_SCRD_CONTINUE_BTN
Continue button.
Definition: script_widget.h:51
@ WID_SCRD_COMPANY_BUTTON_END
Last possible button in the VIEW.
Definition: script_widget.h:46
@ WID_SCRL_ACCEPT
Accept button.
Definition: script_widget.h:21
@ WID_SCRL_INFO_BG
Panel to draw some Script information on.
Definition: script_widget.h:20
@ WID_SCRL_CAPTION
Caption of the window.
Definition: script_widget.h:17
@ WID_SCRL_LIST
The matrix with all available Scripts.
Definition: script_widget.h:18
@ WID_SCRL_SCROLLBAR
Scrollbar next to the Script list.
Definition: script_widget.h:19
@ WID_SCRL_CANCEL
Cancel button.
Definition: script_widget.h:22
@ WID_SCRS_SETTING_DROPDOWN
Dynamically created dropdown for changing setting value.
Definition: script_widget.h:33
@ WID_SCRS_BACKGROUND
Panel to draw the settings on.
Definition: script_widget.h:28
@ WID_SCRS_ACCEPT
Accept button.
Definition: script_widget.h:30
@ WID_SCRS_SCROLLBAR
Scrollbar to scroll through all settings.
Definition: script_widget.h:29
@ WID_SCRS_RESET
Reset button.
Definition: script_widget.h:31
@ WID_SCRS_CAPTION
Caption of the window.
Definition: script_widget.h:27
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.
Definition: settings_gui.h:17
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Definition: settings_gui.h:19
@ 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:357
@ TD_RTL
Text is written right-to-left by default.
Definition: strings_type.h:24
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
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)?
Definition: company_base.h:159
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.
Definition: widget_type.h:1075
Coordinates of a point in 2D.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
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.
Info about a single Script setting.
ScriptConfigFlags flags
Flags for the configuration setting.
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.
std::string description
The description of the configuration setting.
bool complete_labels
True if all values have a label.
bool break_check_enabled
Stop an AI when it prints a matching string.
Definition: script_gui.cpp:698
bool case_sensitive_break_check
Is the matching done case-sensitive.
Definition: script_gui.cpp:699
std::string break_string
The string to match to the AI output.
Definition: script_gui.cpp:696
CompanyID script_debug_company
The AI that is (was last) being debugged.
Definition: script_gui.cpp:697
Window with everything an AI prints via ScriptLog.
Definition: script_gui.cpp:692
void UpdateAIButtonsState()
Update state of all Company (AI) buttons.
Definition: script_gui.cpp:978
void DrawWidgetLog(const Rect &r) const
Draw the AI/GS log.
Definition: script_gui.cpp:895
void UpdateGSButtonState()
Update state of game script button.
Definition: script_gui.cpp:997
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: script_gui.cpp:809
int redraw_timer
Timer for redrawing the window, otherwise it'll happen every tick.
Definition: script_gui.cpp:709
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.
Definition: script_gui.cpp:757
int last_vscroll_pos
Last position of the scrolling.
Definition: script_gui.cpp:710
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
void DrawWidgetCompanyButton(const Rect &r, WidgetID widget, int start) const
Draw a company button icon.
Definition: script_gui.cpp:883
static const uint MAX_BREAK_STR_STRING_LENGTH
Maximum length of the break string.
Definition: script_gui.cpp:693
QueryString break_editbox
Break editbox.
Definition: script_gui.cpp:713
void OnPaint() override
The window must be repainted.
Definition: script_gui.cpp:832
Scrollbar * hscroll
Cache of the horizontal scrollbar.
Definition: script_gui.cpp:717
void OnResize() override
Called after the window got resized.
int highlight_row
The output row that matches the given string, or -1.
Definition: script_gui.cpp:715
ScriptDebugWindow(WindowDesc &desc, WindowNumber number, Owner show_company)
Constructor for the window.
Definition: script_gui.cpp:780
void UpdateLogScroll()
Update the scrollbar and scroll position of the log panel.
Definition: script_gui.cpp:944
StringFilter break_string_filter
Log filter for break.
Definition: script_gui.cpp:714
bool autoscroll
Whether automatically scrolling should be enabled or not.
Definition: script_gui.cpp:711
bool IsDead() const
Check whether the currently selected AI/GS is dead.
Definition: script_gui.cpp:730
bool IsValidDebugCompany(CompanyID company) const
Check whether a company is a valid AI company or GS.
Definition: script_gui.cpp:744
void ChangeToScript(CompanyID show_script, bool new_window=false)
Change all settings to select another Script.
Scrollbar * vscroll
Cache of the vertical scrollbar.
Definition: script_gui.cpp:716
bool show_break_box
Whether the break/debug box is visible.
Definition: script_gui.cpp:712
Window that let you choose an available Script.
Definition: script_gui.cpp:54
int line_height
Height of a row in the matrix widget.
Definition: script_gui.cpp:58
bool show_all
Whether to show all available versions.
Definition: script_gui.cpp:60
void OnResize() override
Called after the window got resized.
Definition: script_gui.cpp:216
CompanyID slot
The company we're selecting a new Script for.
Definition: script_gui.cpp:57
int selected
The currently selected Script.
Definition: script_gui.cpp:56
Scrollbar * vscroll
Cache of the vertical scrollbar.
Definition: script_gui.cpp:59
ScriptListWindow(WindowDesc &desc, CompanyID slot, bool show_all)
Constructor for the window.
Definition: script_gui.cpp:68
void ChangeScript()
Changes the Script of the current slot.
Definition: script_gui.cpp:173
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: script_gui.cpp:226
const ScriptInfoList * info_list
The list of Scripts.
Definition: script_gui.cpp:55
Window for settings the parameters of an AI.
Definition: script_gui.cpp:287
int clicked_row
The clicked row of settings.
Definition: script_gui.cpp:294
void OnPaint() override
The window must be repainted.
Definition: script_gui.cpp:412
std::vector< const ScriptConfigItem * > VisibleSettingsList
typdef for a vector of script settings
Definition: script_gui.cpp:297
int clicked_button
The button we clicked.
Definition: script_gui.cpp:290
void OnResize() override
Called after the window got resized.
Definition: script_gui.cpp:543
void OnDropdownClose(Point, WidgetID widget, int, bool) override
A dropdown window associated to this window has been closed.
Definition: script_gui.cpp:531
void RebuildVisibleSettings()
Rebuilds the list of visible settings.
Definition: script_gui.cpp:323
CompanyID slot
The currently show company's setting.
Definition: script_gui.cpp:288
int line_height
Height of a row in the matrix widget.
Definition: script_gui.cpp:295
ScriptSettingsWindow(WindowDesc &desc, CompanyID slot)
Constructor for the window.
Definition: script_gui.cpp:305
bool clicked_dropdown
Whether the dropdown is open.
Definition: script_gui.cpp:292
TimeoutTimer< TimerWindow > unclick_timeout
When reset, unclick the button after a small timeout.
Definition: script_gui.cpp:549
bool clicked_increase
Whether we clicked the increase or decrease button.
Definition: script_gui.cpp:291
ScriptConfig * script_config
The configuration we're modifying.
Definition: script_gui.cpp:289
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: script_gui.cpp:559
VisibleSettingsList visible_settings
List of visible AI settings.
Definition: script_gui.cpp:298
bool closing_dropdown
True, if the dropdown list is currently closing.
Definition: script_gui.cpp:293
Scrollbar * vscroll
Cache of the vertical scrollbar.
Definition: script_gui.cpp:296
Window for displaying the textfile of a AI.
Definition: script_gui.cpp:628
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: script_gui.cpp:645
CompanyID slot
View the textfile of this CompanyID slot.
Definition: script_gui.cpp:629
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
Definition: textbuf_type.h:32
Window for displaying a textfile.
Definition: textfile_gui.h:21
TextfileType file_type
Type of textfile to view.
Definition: textfile_gui.h:22
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
Iterable ensemble of all valid Windows.
Definition: window_gui.h:913
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:731
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition: window.cpp:3151
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 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
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:302
TextfileType
Additional text files accompanying Tar archives.
Definition: textfile_type.h:14
Rect ScrollRect(Rect r, const Scrollbar &sb, int resize_step)
Apply 'scroll' to a rect to be drawn in.
Definition: widget.cpp:2411
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:3300
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:482
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:524
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:112
@ 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:84
@ 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:83
@ 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 * 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
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:3211
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:3228
@ 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.
Definition: window_type.h:737
EventState
State of handling an event.
Definition: window_type.h:743
@ ES_NOT_HANDLED
The passed event is not handled.
Definition: window_type.h:745
@ WC_SCRIPT_SETTINGS
Script settings; Window numbers:
Definition: window_type.h:175
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:45
@ WC_SCRIPT_LIST
Scripts list; Window numbers:
Definition: window_type.h:284
@ WC_GAME_OPTIONS
Game options window; Window numbers:
Definition: window_type.h:624
@ WC_SCRIPT_DEBUG
Script debug window; Window numbers:
Definition: window_type.h:674
@ WC_TEXTFILE
textfile; Window numbers:
Definition: window_type.h:187
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
Definition: window_type.h:156
@ WC_QUERY_STRING
Query string window; Window numbers:
Definition: window_type.h:123