OpenTTD Source  20241108-master-g80f628063a
newgrf_debug_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 "core/backup_type.hpp"
12 #include "core/geometry_func.hpp"
13 #include "window_gui.h"
14 #include "window_func.h"
16 #include "spritecache.h"
17 #include "string_func.h"
18 #include "strings_func.h"
19 #include "textbuf_gui.h"
20 #include "vehicle_gui.h"
21 #include "zoom_func.h"
22 
23 #include "engine_base.h"
24 #include "industry.h"
25 #include "object_base.h"
26 #include "station_base.h"
27 #include "town.h"
28 #include "vehicle_base.h"
29 #include "train.h"
30 #include "roadveh.h"
31 
32 #include "newgrf_act5.h"
33 #include "newgrf_airport.h"
34 #include "newgrf_airporttiles.h"
35 #include "newgrf_debug.h"
36 #include "newgrf_object.h"
37 #include "newgrf_spritegroup.h"
38 #include "newgrf_station.h"
39 #include "newgrf_town.h"
40 #include "newgrf_railtype.h"
41 #include "newgrf_industries.h"
42 #include "newgrf_industrytiles.h"
43 
45 
46 #include "table/strings.h"
47 
48 #include "safeguards.h"
49 
51 NewGrfDebugSpritePicker _newgrf_debug_sprite_picker = { SPM_NONE, nullptr, std::vector<SpriteID>() };
52 
58 static inline uint GetFeatureIndex(uint window_number)
59 {
60  return GB(window_number, 0, 24);
61 }
62 
70 static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index)
71 {
72  assert((index >> 24) == 0);
73  return (feature << 24) | index;
74 }
75 
80 enum NIType {
83 };
84 
85 typedef const void *NIOffsetProc(const void *b);
86 
88 struct NIProperty {
89  const char *name;
90  NIOffsetProc *offset_proc;
91  uint8_t read_size;
92  uint8_t prop;
93  uint8_t type;
94 };
95 
96 
101 struct NICallback {
102  const char *name;
103  NIOffsetProc *offset_proc;
104  uint8_t read_size;
105  uint8_t cb_bit;
106  uint16_t cb_id;
107 };
109 static const int CBM_NO_BIT = UINT8_MAX;
110 
112 struct NIVariable {
113  const char *name;
114  uint8_t var;
115 };
116 
118 class NIHelper {
119 public:
121  virtual ~NIHelper() = default;
122 
128  virtual bool IsInspectable(uint index) const = 0;
129 
135  virtual uint GetParent(uint index) const = 0;
136 
142  virtual const void *GetInstance(uint index) const = 0;
143 
149  virtual const void *GetSpec(uint index) const = 0;
150 
155  virtual void SetStringParameters(uint index) const = 0;
156 
162  virtual uint32_t GetGRFID(uint index) const = 0;
163 
172  virtual uint Resolve(uint index, uint var, uint param, bool &avail) const = 0;
173 
178  virtual bool PSAWithParameter() const
179  {
180  return false;
181  }
182 
189  virtual const std::span<int32_t> GetPSA([[maybe_unused]] uint index, [[maybe_unused]] uint32_t grfid) const
190  {
191  return {};
192  }
193 
194 protected:
200  void SetSimpleStringParameters(StringID string, uint32_t index) const
201  {
202  SetDParam(0, string);
203  SetDParam(1, index);
204  }
205 
206 
213  void SetObjectAtStringParameters(StringID string, uint32_t index, TileIndex tile) const
214  {
215  SetDParam(0, STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT);
216  SetDParam(1, string);
217  SetDParam(2, index);
218  SetDParam(3, tile);
219  }
220 };
221 
222 
224 struct NIFeature {
228  const NIHelper *helper;
229 };
230 
231 /* Load all the NewGRF debug data; externalised as it is just a huge bunch of tables. */
232 #include "table/newgrf_debug_data.h"
233 
239 static inline GrfSpecFeature GetFeatureNum(uint window_number)
240 {
241  return (GrfSpecFeature)GB(window_number, 24, 8);
242 }
243 
249 static inline const NIFeature *GetFeature(uint window_number)
250 {
251  GrfSpecFeature idx = GetFeatureNum(window_number);
252  return idx < GSF_FAKE_END ? _nifeatures[idx] : nullptr;
253 }
254 
261 static inline const NIHelper *GetFeatureHelper(uint window_number)
262 {
263  return GetFeature(window_number)->helper;
264 }
265 
269  static uint32_t var60params[GSF_FAKE_END][0x20];
270 
272  uint32_t caller_grfid;
273 
276 
279 
280  Scrollbar *vscroll;
281 
287  static bool HasVariableParameter(uint variable)
288  {
289  return IsInsideBS(variable, 0x60, 0x20);
290  }
291 
296  void SetCallerGRFID(uint32_t grfid)
297  {
298  this->caller_grfid = grfid;
299  this->SetDirty();
300  }
301 
305  bool HasChainIndex() const
306  {
308  return f == GSF_TRAINS || f == GSF_ROADVEHICLES;
309  }
310 
315  uint GetFeatureIndex() const
316  {
317  uint index = ::GetFeatureIndex(this->window_number);
318  if (this->chain_index > 0) {
319  assert(this->HasChainIndex());
320  const Vehicle *v = Vehicle::Get(index);
321  v = v->Move(this->chain_index);
322  if (v != nullptr) index = v->index;
323  }
324  return index;
325  }
326 
331  {
332  if (this->chain_index == 0) return;
333 
334  assert(this->HasChainIndex());
335 
336  const Vehicle *v = Vehicle::Get(::GetFeatureIndex(this->window_number));
337  v = v->Move(this->chain_index);
338  if (v == nullptr) this->chain_index = 0;
339  }
340 
342  {
343  this->CreateNestedTree();
344  this->vscroll = this->GetScrollbar(WID_NGRFI_SCROLLBAR);
345  this->FinishInitNested(wno);
346 
347  this->vscroll->SetCount(0);
348  this->SetWidgetDisabledState(WID_NGRFI_PARENT, GetFeatureHelper(this->window_number)->GetParent(this->GetFeatureIndex()) == UINT32_MAX);
349 
350  this->OnInvalidateData(0, true);
351  }
352 
353  void SetStringParameters(WidgetID widget) const override
354  {
355  if (widget != WID_NGRFI_CAPTION) return;
356 
358  }
359 
360  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
361  {
362  switch (widget) {
363  case WID_NGRFI_VEH_CHAIN: {
364  assert(this->HasChainIndex());
366  size.height = std::max(size.height, GetVehicleImageCellSize((VehicleType)(VEH_TRAIN + (f - GSF_TRAINS)), EIT_IN_DEPOT).height + 2 + WidgetDimensions::scaled.bevel.Vertical());
367  break;
368  }
369 
370  case WID_NGRFI_MAINPANEL:
371  resize.height = std::max(11, GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal);
372  resize.width = 1;
373 
374  size.height = 5 * resize.height + WidgetDimensions::scaled.frametext.Vertical();
375  break;
376  }
377  }
378 
385  void DrawString(const Rect &r, int offset, const std::string &string) const
386  {
387  offset -= this->vscroll->GetPosition();
388  if (offset < 0 || offset >= this->vscroll->GetCapacity()) return;
389 
390  ::DrawString(r.Shrink(WidgetDimensions::scaled.frametext).Shrink(0, offset * this->resize.step_height, 0, 0), string, TC_BLACK);
391  }
392 
397  void DrawVehicleChainWidget(const Rect &r) const
398  {
399  const Vehicle *v = Vehicle::Get(this->GetFeatureIndex());
400  int total_width = 0;
401  int sel_start = 0;
402  int sel_end = 0;
403  for (const Vehicle *u = v->First(); u != nullptr; u = u->Next()) {
404  if (u == v) sel_start = total_width;
405  switch (u->type) {
406  case VEH_TRAIN: total_width += Train::From(u)->GetDisplayImageWidth(); break;
407  case VEH_ROAD: total_width += RoadVehicle::From(u)->GetDisplayImageWidth(); break;
408  default: NOT_REACHED();
409  }
410  if (u == v) sel_end = total_width;
411  }
412 
413  Rect br = r.Shrink(WidgetDimensions::scaled.bevel);
414  int width = br.Width();
415  int skip = 0;
416  if (total_width > width) {
417  int sel_center = (sel_start + sel_end) / 2;
418  if (sel_center > width / 2) skip = std::min(total_width - width, sel_center - width / 2);
419  }
420 
422  int h = GetVehicleImageCellSize((VehicleType)(VEH_TRAIN + (f - GSF_TRAINS)), EIT_IN_DEPOT).height;
423  int y = CenterBounds(br.top, br.bottom, h);
425 
426  /* Highlight the articulated part (this is different to the whole-vehicle highlighting of DrawVehicleImage */
427  if (_current_text_dir == TD_RTL) {
428  DrawFrameRect(r.right - sel_end + skip, y, r.right - sel_start + skip, y + h, COLOUR_WHITE, FR_BORDERONLY);
429  } else {
430  DrawFrameRect(r.left + sel_start - skip, y, r.left + sel_end - skip, y + h, COLOUR_WHITE, FR_BORDERONLY);
431  }
432  }
433 
438  void DrawMainPanelWidget(const Rect &r) const
439  {
440  uint index = this->GetFeatureIndex();
441  const NIFeature *nif = GetFeature(this->window_number);
442  const NIHelper *nih = nif->helper;
443  const void *base = nih->GetInstance(index);
444  const void *base_spec = nih->GetSpec(index);
445 
446  uint i = 0;
447  if (nif->variables != nullptr) {
448  this->DrawString(r, i++, "Variables:");
449  for (const NIVariable *niv = nif->variables; niv->name != nullptr; niv++) {
450  bool avail = true;
451  uint param = HasVariableParameter(niv->var) ? NewGRFInspectWindow::var60params[GetFeatureNum(this->window_number)][niv->var - 0x60] : 0;
452  uint value = nih->Resolve(index, niv->var, param, avail);
453 
454  if (!avail) continue;
455 
456  if (HasVariableParameter(niv->var)) {
457  this->DrawString(r, i++, fmt::format(" {:02x}[{:02x}]: {:08x} ({})", niv->var, param, value, niv->name));
458  } else {
459  this->DrawString(r, i++, fmt::format(" {:02x}: {:08x} ({})", niv->var, value, niv->name));
460  }
461  }
462  }
463 
464  auto psa = nih->GetPSA(index, this->caller_grfid);
465  if (!psa.empty()) {
466  if (nih->PSAWithParameter()) {
467  this->DrawString(r, i++, fmt::format("Persistent storage [{:08X}]:", BSWAP32(this->caller_grfid)));
468  } else {
469  this->DrawString(r, i++, "Persistent storage:");
470  }
471  assert(psa.size() % 4 == 0);
472  for (size_t j = 0; j < psa.size(); j += 4) {
473  this->DrawString(r, i++, fmt::format(" {}: {} {} {} {}", j, psa[j], psa[j + 1], psa[j + 2], psa[j + 3]));
474  }
475  }
476 
477  if (nif->properties != nullptr) {
478  this->DrawString(r, i++, "Properties:");
479  for (const NIProperty *nip = nif->properties; nip->name != nullptr; nip++) {
480  const void *ptr = nip->offset_proc(base);
481  uint value;
482  switch (nip->read_size) {
483  case 1: value = *(const uint8_t *)ptr; break;
484  case 2: value = *(const uint16_t *)ptr; break;
485  case 4: value = *(const uint32_t *)ptr; break;
486  default: NOT_REACHED();
487  }
488 
489  StringID string;
490  SetDParam(0, value);
491  switch (nip->type) {
492  case NIT_INT:
493  string = STR_JUST_INT;
494  break;
495 
496  case NIT_CARGO:
497  string = IsValidCargoID(value) ? CargoSpec::Get(value)->name : STR_QUANTITY_N_A;
498  break;
499 
500  default:
501  NOT_REACHED();
502  }
503 
504  this->DrawString(r, i++, fmt::format(" {:02x}: {} ({})", nip->prop, GetString(string), nip->name));
505  }
506  }
507 
508  if (nif->callbacks != nullptr) {
509  this->DrawString(r, i++, "Callbacks:");
510  for (const NICallback *nic = nif->callbacks; nic->name != nullptr; nic++) {
511  if (nic->cb_bit != CBM_NO_BIT) {
512  const void *ptr = nic->offset_proc(base_spec);
513  uint value;
514  switch (nic->read_size) {
515  case 1: value = *(const uint8_t *)ptr; break;
516  case 2: value = *(const uint16_t *)ptr; break;
517  case 4: value = *(const uint32_t *)ptr; break;
518  default: NOT_REACHED();
519  }
520 
521  if (!HasBit(value, nic->cb_bit)) continue;
522  this->DrawString(r, i++, fmt::format(" {:03x}: {}", nic->cb_id, nic->name));
523  } else {
524  this->DrawString(r, i++, fmt::format(" {:03x}: {} (unmasked)", nic->cb_id, nic->name));
525  }
526  }
527  }
528 
529  /* Not nice and certainly a hack, but it beats duplicating
530  * this whole function just to count the actual number of
531  * elements. Especially because they need to be redrawn. */
532  const_cast<NewGRFInspectWindow*>(this)->vscroll->SetCount(i);
533  }
534 
535  void DrawWidget(const Rect &r, WidgetID widget) const override
536  {
537  switch (widget) {
538  case WID_NGRFI_VEH_CHAIN:
539  this->DrawVehicleChainWidget(r);
540  break;
541 
542  case WID_NGRFI_MAINPANEL:
543  this->DrawMainPanelWidget(r);
544  break;
545  }
546  }
547 
548  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
549  {
550  switch (widget) {
551  case WID_NGRFI_PARENT: {
552  const NIHelper *nih = GetFeatureHelper(this->window_number);
553  uint index = nih->GetParent(this->GetFeatureIndex());
554  ::ShowNewGRFInspectWindow(GetFeatureNum(index), ::GetFeatureIndex(index), nih->GetGRFID(this->GetFeatureIndex()));
555  break;
556  }
557 
558  case WID_NGRFI_VEH_PREV:
559  if (this->chain_index > 0) {
560  this->chain_index--;
561  this->InvalidateData();
562  }
563  break;
564 
565  case WID_NGRFI_VEH_NEXT:
566  if (this->HasChainIndex()) {
567  uint index = this->GetFeatureIndex();
568  Vehicle *v = Vehicle::Get(index);
569  if (v != nullptr && v->Next() != nullptr) {
570  this->chain_index++;
571  this->InvalidateData();
572  }
573  }
574  break;
575 
576  case WID_NGRFI_MAINPANEL: {
577  /* Does this feature have variables? */
578  const NIFeature *nif = GetFeature(this->window_number);
579  if (nif->variables == nullptr) return;
580 
581  /* Get the line, make sure it's within the boundaries. */
582  int32_t line = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NGRFI_MAINPANEL, WidgetDimensions::scaled.frametext.top);
583  if (line == INT32_MAX) return;
584 
585  /* Find the variable related to the line */
586  for (const NIVariable *niv = nif->variables; niv->name != nullptr; niv++, line--) {
587  if (line != 1) continue; // 1 because of the "Variables:" line
588 
589  if (!HasVariableParameter(niv->var)) break;
590 
591  this->current_edit_param = niv->var;
592  ShowQueryString(STR_EMPTY, STR_NEWGRF_INSPECT_QUERY_CAPTION, 9, this, CS_HEXADECIMAL, QSF_NONE);
593  }
594  }
595  }
596  }
597 
598  void OnQueryTextFinished(std::optional<std::string> str) override
599  {
600  if (!str.has_value() || str->empty()) return;
601 
602  NewGRFInspectWindow::var60params[GetFeatureNum(this->window_number)][this->current_edit_param - 0x60] = std::strtol(str->c_str(), nullptr, 16);
603  this->SetDirty();
604  }
605 
606  void OnResize() override
607  {
608  this->vscroll->SetCapacityFromWidget(this, WID_NGRFI_MAINPANEL, WidgetDimensions::scaled.frametext.Vertical());
609  }
610 
616  void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
617  {
618  if (!gui_scope) return;
619  if (this->HasChainIndex()) {
620  this->ValidateChainIndex();
621  this->SetWidgetDisabledState(WID_NGRFI_VEH_PREV, this->chain_index == 0);
622  Vehicle *v = Vehicle::Get(this->GetFeatureIndex());
623  this->SetWidgetDisabledState(WID_NGRFI_VEH_NEXT, v == nullptr || v->Next() == nullptr);
624  }
625  }
626 };
627 
628 /* static */ uint32_t NewGRFInspectWindow::var60params[GSF_FAKE_END][0x20] = { {0} }; // Use spec to have 0s in whole array
629 
630 static constexpr NWidgetPart _nested_newgrf_inspect_chain_widgets[] = {
632  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
633  NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
634  NWidget(WWT_SHADEBOX, COLOUR_GREY),
635  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
636  NWidget(WWT_STICKYBOX, COLOUR_GREY),
637  EndContainer(),
638  NWidget(WWT_PANEL, COLOUR_GREY),
642  NWidget(WWT_EMPTY, COLOUR_GREY, WID_NGRFI_VEH_CHAIN), SetFill(1, 0), SetResize(1, 0),
643  EndContainer(),
644  EndContainer(),
649  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
650  EndContainer(),
651  EndContainer(),
652 };
653 
654 static constexpr NWidgetPart _nested_newgrf_inspect_widgets[] = {
656  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
657  NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
658  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_NGRFI_PARENT), SetDataTip(STR_NEWGRF_INSPECT_PARENT_BUTTON, STR_NEWGRF_INSPECT_PARENT_TOOLTIP),
659  NWidget(WWT_SHADEBOX, COLOUR_GREY),
660  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
661  NWidget(WWT_STICKYBOX, COLOUR_GREY),
662  EndContainer(),
667  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
668  EndContainer(),
669  EndContainer(),
670 };
671 
672 static WindowDesc _newgrf_inspect_chain_desc(
673  WDP_AUTO, "newgrf_inspect_chain", 400, 300,
675  0,
676  _nested_newgrf_inspect_chain_widgets
677 );
678 
679 static WindowDesc _newgrf_inspect_desc(
680  WDP_AUTO, "newgrf_inspect", 400, 300,
682  0,
683  _nested_newgrf_inspect_widgets
684 );
685 
695 void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index, const uint32_t grfid)
696 {
697  if (!IsNewGRFInspectable(feature, index)) return;
698 
699  WindowNumber wno = GetInspectWindowNumber(feature, index);
700  WindowDesc &desc = (feature == GSF_TRAINS || feature == GSF_ROADVEHICLES) ? _newgrf_inspect_chain_desc : _newgrf_inspect_desc;
701  NewGRFInspectWindow *w = AllocateWindowDescFront<NewGRFInspectWindow>(desc, wno, true);
702  w->SetCallerGRFID(grfid);
703 }
704 
714 {
715  if (feature == GSF_INVALID) return;
716 
717  WindowNumber wno = GetInspectWindowNumber(feature, index);
719 }
720 
729 void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
730 {
731  if (feature == GSF_INVALID) return;
732 
733  WindowNumber wno = GetInspectWindowNumber(feature, index);
735 
736  /* Reinitialise the land information window to remove the "debug" sprite if needed.
737  * Note: Since we might be called from a command here, it is important to not execute
738  * the invalidation immediately. The landinfo window tests commands itself. */
740 }
741 
751 bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
752 {
753  const NIFeature *nif = GetFeature(GetInspectWindowNumber(feature, index));
754  if (nif == nullptr) return false;
755  return nif->helper->IsInspectable(index);
756 }
757 
764 {
765  switch (GetTileType(tile)) {
766  default: return GSF_INVALID;
767  case MP_RAILWAY: return GSF_RAILTYPES;
768  case MP_ROAD: return IsLevelCrossing(tile) ? GSF_RAILTYPES : GSF_ROADTYPES;
769  case MP_HOUSE: return GSF_HOUSES;
770  case MP_INDUSTRY: return GSF_INDUSTRYTILES;
771  case MP_OBJECT: return GSF_OBJECTS;
772 
773  case MP_STATION:
774  switch (GetStationType(tile)) {
775  case STATION_RAIL: return GSF_STATIONS;
776  case STATION_AIRPORT: return GSF_AIRPORTTILES;
777  case STATION_BUS: return GSF_ROADSTOPS;
778  case STATION_TRUCK: return GSF_ROADSTOPS;
779  default: return GSF_INVALID;
780  }
781  }
782 }
783 
790 {
791  switch (type) {
792  case VEH_TRAIN: return GSF_TRAINS;
793  case VEH_ROAD: return GSF_ROADVEHICLES;
794  case VEH_SHIP: return GSF_SHIPS;
795  case VEH_AIRCRAFT: return GSF_AIRCRAFT;
796  default: return GSF_INVALID;
797  }
798 }
799 
800 
801 /**** Sprite Aligner ****/
802 
805  typedef std::pair<int16_t, int16_t> XyOffs;
806 
808  Scrollbar *vscroll;
809  std::map<SpriteID, XyOffs> offs_start_map;
810 
811  static inline ZoomLevel zoom = ZOOM_LVL_END;
812  static bool centre;
813  static bool crosshair;
814  const Action5Type *act5_type = nullptr;
815 
817  {
818  /* On first opening, set initial zoom to current zoom level. */
819  if (SpriteAlignerWindow::zoom == ZOOM_LVL_END) SpriteAlignerWindow::zoom = _gui_zoom;
820  SpriteAlignerWindow::zoom = Clamp(SpriteAlignerWindow::zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max);
821 
822  /* Oh yes, we assume there is at least one normal sprite! */
823  while (GetSpriteType(this->current_sprite) != SpriteType::Normal) this->current_sprite++;
824  this->SelectAction5Type();
825 
826  this->CreateNestedTree();
827  this->vscroll = this->GetScrollbar(WID_SA_SCROLLBAR);
828  this->vscroll->SetCount(_newgrf_debug_sprite_picker.sprites.size());
829  this->FinishInitNested(wno);
830 
831  this->SetWidgetLoweredState(WID_SA_CENTRE, SpriteAlignerWindow::centre);
832  this->SetWidgetLoweredState(WID_SA_CROSSHAIR, SpriteAlignerWindow::crosshair);
833 
834  this->InvalidateData(0, true);
835  }
836 
837  void SetStringParameters(WidgetID widget) const override
838  {
839  const Sprite *spr = GetSprite(this->current_sprite, SpriteType::Normal);
840  switch (widget) {
841  case WID_SA_CAPTION:
842  if (this->act5_type != nullptr) {
843  SetDParam(0, STR_SPRITE_ALIGNER_CAPTION_ACTION5);
844  SetDParam(1, this->act5_type - GetAction5Types().data());
845  SetDParam(2, this->current_sprite - this->act5_type->sprite_base);
846  SetDParamStr(3, GetOriginFile(this->current_sprite)->GetSimplifiedFilename());
847  SetDParam(4, GetSpriteLocalID(this->current_sprite));
848  } else if (this->current_sprite < SPR_OPENTTD_BASE) {
849  SetDParam(0, STR_SPRITE_ALIGNER_CAPTION_ACTIONA);
850  SetDParam(1, this->current_sprite);
851  SetDParamStr(2, GetOriginFile(this->current_sprite)->GetSimplifiedFilename());
852  SetDParam(3, GetSpriteLocalID(this->current_sprite));
853  } else {
854  SetDParam(0, STR_SPRITE_ALIGNER_CAPTION_NO_ACTION);
855  SetDParamStr(1, GetOriginFile(this->current_sprite)->GetSimplifiedFilename());
856  SetDParam(2, GetSpriteLocalID(this->current_sprite));
857  }
858  break;
859 
860  case WID_SA_OFFSETS_ABS:
861  SetDParam(0, UnScaleByZoom(spr->x_offs, SpriteAlignerWindow::zoom));
862  SetDParam(1, UnScaleByZoom(spr->y_offs, SpriteAlignerWindow::zoom));
863  break;
864 
865  case WID_SA_OFFSETS_REL: {
866  /* Relative offset is new absolute offset - starting absolute offset.
867  * Show 0, 0 as the relative offsets if entry is not in the map (meaning they have not been changed yet).
868  */
869  const auto key_offs_pair = this->offs_start_map.find(this->current_sprite);
870  if (key_offs_pair != this->offs_start_map.end()) {
871  SetDParam(0, UnScaleByZoom(spr->x_offs - key_offs_pair->second.first, SpriteAlignerWindow::zoom));
872  SetDParam(1, UnScaleByZoom(spr->y_offs - key_offs_pair->second.second, SpriteAlignerWindow::zoom));
873  } else {
874  SetDParam(0, 0);
875  SetDParam(1, 0);
876  }
877  break;
878  }
879 
880  default:
881  break;
882  }
883  }
884 
885  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
886  {
887  switch (widget) {
888  case WID_SA_SPRITE:
889  size.height = ScaleGUITrad(200);
890  break;
891 
892  case WID_SA_LIST: {
893  Dimension d = {};
894  for (const auto &spritefile : GetCachedSpriteFiles()) {
895  SetDParamStr(0, spritefile->GetSimplifiedFilename());
896  SetDParamMaxDigits(1, 6);
897  d = maxdim(d, GetStringBoundingBox(STR_SPRITE_ALIGNER_SPRITE));
898  }
899  size.width = d.width + padding.width;
900  resize.height = GetCharacterHeight(FS_NORMAL) + padding.height;
901  resize.width = 1;
902  fill.height = resize.height;
903  break;
904  }
905 
906  default:
907  break;
908  }
909  }
910 
911  void DrawWidget(const Rect &r, WidgetID widget) const override
912  {
913  switch (widget) {
914  case WID_SA_SPRITE: {
915  /* Center the sprite ourselves */
916  const Sprite *spr = GetSprite(this->current_sprite, SpriteType::Normal);
917  Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
918  int x;
919  int y;
920  if (SpriteAlignerWindow::centre) {
921  x = -UnScaleByZoom(spr->x_offs, SpriteAlignerWindow::zoom) + (ir.Width() - UnScaleByZoom(spr->width, SpriteAlignerWindow::zoom)) / 2;
922  y = -UnScaleByZoom(spr->y_offs, SpriteAlignerWindow::zoom) + (ir.Height() - UnScaleByZoom(spr->height, SpriteAlignerWindow::zoom)) / 2;
923  } else {
924  x = ir.Width() / 2;
925  y = ir.Height() / 2;
926  }
927 
928  DrawPixelInfo new_dpi;
929  if (!FillDrawPixelInfo(&new_dpi, ir)) break;
930  AutoRestoreBackup dpi_backup(_cur_dpi, &new_dpi);
931 
932  DrawSprite(this->current_sprite, PAL_NONE, x, y, nullptr, SpriteAlignerWindow::zoom);
933 
934  Rect outline = {0, 0, UnScaleByZoom(spr->width, SpriteAlignerWindow::zoom) - 1, UnScaleByZoom(spr->height, SpriteAlignerWindow::zoom) - 1};
935  outline = outline.Translate(x + UnScaleByZoom(spr->x_offs, SpriteAlignerWindow::zoom), y + UnScaleByZoom(spr->y_offs, SpriteAlignerWindow::zoom));
936  DrawRectOutline(outline.Expand(1), PC_LIGHT_BLUE, 1, 1);
937 
938  if (SpriteAlignerWindow::crosshair) {
939  GfxDrawLine(x, 0, x, ir.Height() - 1, PC_WHITE, 1, 1);
940  GfxDrawLine(0, y, ir.Width() - 1, y, PC_WHITE, 1, 1);
941  }
942  break;
943  }
944 
945  case WID_SA_LIST: {
946  /* Don't redraw sprite list while it is still being filled by picker. */
947  if (_newgrf_debug_sprite_picker.mode == SPM_REDRAW) break;
948 
949  const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget);
950  int step_size = nwid->resize_y;
951 
952  const std::vector<SpriteID> &list = _newgrf_debug_sprite_picker.sprites;
953 
954  Rect ir = r.Shrink(WidgetDimensions::scaled.matrix);
955  auto [first, last] = this->vscroll->GetVisibleRangeIterators(list);
956  for (auto it = first; it != last; ++it) {
957  const SpriteFile *file = GetOriginFile(*it);
958  if (file == nullptr) {
959  SetDParam(0, *it);
960  DrawString(ir, STR_JUST_COMMA, *it == this->current_sprite ? TC_WHITE : (TC_GREY | TC_NO_SHADE), SA_RIGHT | SA_FORCE);
961  } else {
963  SetDParam(1, GetSpriteLocalID(*it));
964  DrawString(ir, STR_SPRITE_ALIGNER_SPRITE, *it == this->current_sprite ? TC_WHITE : TC_BLACK);
965  }
966  ir.top += step_size;
967  }
968  break;
969  }
970  }
971  }
972 
973  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
974  {
975  switch (widget) {
976  case WID_SA_PREVIOUS:
977  do {
978  this->current_sprite = (this->current_sprite == 0 ? GetMaxSpriteID() : this->current_sprite) - 1;
979  } while (GetSpriteType(this->current_sprite) != SpriteType::Normal);
980  this->SelectAction5Type();
981  this->SetDirty();
982  break;
983 
984  case WID_SA_GOTO:
985  ShowQueryString(STR_EMPTY, STR_SPRITE_ALIGNER_GOTO_CAPTION, 7, this, CS_NUMERAL, QSF_NONE);
986  break;
987 
988  case WID_SA_NEXT:
989  do {
990  this->current_sprite = (this->current_sprite + 1) % GetMaxSpriteID();
991  } while (GetSpriteType(this->current_sprite) != SpriteType::Normal);
992  this->SelectAction5Type();
993  this->SetDirty();
994  break;
995 
996  case WID_SA_PICKER:
997  this->LowerWidget(WID_SA_PICKER);
998  _newgrf_debug_sprite_picker.mode = SPM_WAIT_CLICK;
999  this->SetDirty();
1000  break;
1001 
1002  case WID_SA_LIST: {
1003  auto it = this->vscroll->GetScrolledItemFromWidget(_newgrf_debug_sprite_picker.sprites, pt.y, this, widget);
1004  if (it != _newgrf_debug_sprite_picker.sprites.end()) {
1005  SpriteID spr = *it;
1006  if (GetSpriteType(spr) == SpriteType::Normal) this->current_sprite = spr;
1007  }
1008  this->SelectAction5Type();
1009  this->SetDirty();
1010  break;
1011  }
1012 
1013  case WID_SA_UP:
1014  case WID_SA_DOWN:
1015  case WID_SA_LEFT:
1016  case WID_SA_RIGHT: {
1017  /*
1018  * Yes... this is a hack.
1019  *
1020  * No... I don't think it is useful to make this less of a hack.
1021  *
1022  * If you want to align sprites, you just need the number. Generally
1023  * the sprite caches are big enough to not remove the sprite from the
1024  * cache. If that's not the case, just let the NewGRF developer
1025  * increase the cache size instead of storing thousands of offsets
1026  * for the incredibly small chance that it's actually going to be
1027  * used by someone and the sprite cache isn't big enough for that
1028  * particular NewGRF developer.
1029  */
1030  Sprite *spr = const_cast<Sprite *>(GetSprite(this->current_sprite, SpriteType::Normal));
1031 
1032  /* Remember the original offsets of the current sprite, if not already in mapping. */
1033  if (this->offs_start_map.count(this->current_sprite) == 0) {
1034  this->offs_start_map[this->current_sprite] = XyOffs(spr->x_offs, spr->y_offs);
1035  }
1036  int amt = ScaleByZoom(_ctrl_pressed ? 8 : 1, SpriteAlignerWindow::zoom);
1037  switch (widget) {
1038  /* Move eight units at a time if ctrl is pressed. */
1039  case WID_SA_UP: spr->y_offs -= amt; break;
1040  case WID_SA_DOWN: spr->y_offs += amt; break;
1041  case WID_SA_LEFT: spr->x_offs -= amt; break;
1042  case WID_SA_RIGHT: spr->x_offs += amt; break;
1043  }
1044  /* Of course, we need to redraw the sprite, but where is it used?
1045  * Everywhere is a safe bet. */
1047  break;
1048  }
1049 
1050  case WID_SA_RESET_REL:
1051  /* Reset the starting offsets for the current sprite. */
1052  this->offs_start_map.erase(this->current_sprite);
1053  this->SetDirty();
1054  break;
1055 
1056  case WID_SA_CENTRE:
1057  SpriteAlignerWindow::centre = !SpriteAlignerWindow::centre;
1058  this->SetWidgetLoweredState(widget, SpriteAlignerWindow::centre);
1059  this->SetDirty();
1060  break;
1061 
1062  case WID_SA_CROSSHAIR:
1063  SpriteAlignerWindow::crosshair = !SpriteAlignerWindow::crosshair;
1064  this->SetWidgetLoweredState(widget, SpriteAlignerWindow::crosshair);
1065  this->SetDirty();
1066  break;
1067 
1068  default:
1069  if (IsInsideBS(widget, WID_SA_ZOOM, ZOOM_LVL_END)) {
1070  SpriteAlignerWindow::zoom = ZoomLevel(widget - WID_SA_ZOOM);
1071  this->InvalidateData(0, true);
1072  }
1073  break;
1074  }
1075  }
1076 
1077  void OnQueryTextFinished(std::optional<std::string> str) override
1078  {
1079  if (!str.has_value() || str->empty()) return;
1080 
1081  this->current_sprite = atoi(str->c_str());
1082  if (this->current_sprite >= GetMaxSpriteID()) this->current_sprite = 0;
1083  while (GetSpriteType(this->current_sprite) != SpriteType::Normal) {
1084  this->current_sprite = (this->current_sprite + 1) % GetMaxSpriteID();
1085  }
1086  this->SelectAction5Type();
1087  this->SetDirty();
1088  }
1089 
1095  void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1096  {
1097  if (!gui_scope) return;
1098  if (data == 1) {
1099  /* Sprite picker finished */
1100  this->RaiseWidget(WID_SA_PICKER);
1101  this->vscroll->SetCount(_newgrf_debug_sprite_picker.sprites.size());
1102  }
1103 
1104  SpriteAlignerWindow::zoom = Clamp(SpriteAlignerWindow::zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max);
1105  for (ZoomLevel z = ZOOM_LVL_BEGIN; z < ZOOM_LVL_END; z++) {
1106  this->SetWidgetsDisabledState(z < _settings_client.gui.zoom_min || z > _settings_client.gui.zoom_max, WID_SA_ZOOM + z);
1107  this->SetWidgetsLoweredState(SpriteAlignerWindow::zoom == z, WID_SA_ZOOM + z);
1108  }
1109  }
1110 
1111  void OnResize() override
1112  {
1113  this->vscroll->SetCapacityFromWidget(this, WID_SA_LIST);
1114  }
1115 
1116 private:
1117  void SelectAction5Type()
1118  {
1119  const auto act5types = GetAction5Types();
1120  for (auto it = std::begin(act5types); it != std::end(act5types); ++it) {
1121  if (it->sprite_base <= this->current_sprite && this->current_sprite < it->sprite_base + it->max_sprites) {
1122  this->act5_type = &*it;
1123  return;
1124  }
1125  }
1126  this->act5_type = nullptr;
1127  }
1128 };
1129 
1130 bool SpriteAlignerWindow::centre = true;
1131 bool SpriteAlignerWindow::crosshair = true;
1132 
1133 static constexpr NWidgetPart _nested_sprite_aligner_widgets[] = {
1135  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1136  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SA_CAPTION), SetDataTip(STR_JUST_STRING4, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1137  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1138  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1139  EndContainer(),
1140  NWidget(WWT_PANEL, COLOUR_GREY),
1144  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SA_PREVIOUS), SetDataTip(STR_SPRITE_ALIGNER_PREVIOUS_BUTTON, STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1145  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SA_GOTO), SetDataTip(STR_SPRITE_ALIGNER_GOTO_BUTTON, STR_SPRITE_ALIGNER_GOTO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1146  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SA_NEXT), SetDataTip(STR_SPRITE_ALIGNER_NEXT_BUTTON, STR_SPRITE_ALIGNER_NEXT_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1147  EndContainer(),
1149  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 0),
1150  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SA_UP), SetDataTip(SPR_ARROW_UP, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), SetMinimalSize(11, 11),
1151  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 0),
1152  EndContainer(),
1155  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(0, 1),
1156  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SA_LEFT), SetDataTip(SPR_ARROW_LEFT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), SetMinimalSize(11, 11),
1157  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(0, 1),
1158  EndContainer(),
1159  NWidget(WWT_PANEL, COLOUR_DARK_BLUE, WID_SA_SPRITE), SetDataTip(STR_NULL, STR_SPRITE_ALIGNER_SPRITE_TOOLTIP), SetResize(1, 1), SetFill(1, 1),
1160  EndContainer(),
1162  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(0, 1),
1163  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SA_RIGHT), SetDataTip(SPR_ARROW_RIGHT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), SetMinimalSize(11, 11),
1164  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(0, 1),
1165  EndContainer(),
1166  EndContainer(),
1168  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 0),
1169  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SA_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), SetMinimalSize(11, 11),
1170  NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 0),
1171  EndContainer(),
1172  NWidget(WWT_LABEL, COLOUR_GREY, WID_SA_OFFSETS_ABS), SetDataTip(STR_SPRITE_ALIGNER_OFFSETS_ABS, STR_NULL), SetFill(1, 0), SetResize(1, 0),
1173  NWidget(WWT_LABEL, COLOUR_GREY, WID_SA_OFFSETS_REL), SetDataTip(STR_SPRITE_ALIGNER_OFFSETS_REL, STR_NULL), SetFill(1, 0), SetResize(1, 0),
1175  NWidget(WWT_TEXTBTN_2, COLOUR_GREY, WID_SA_CENTRE), SetDataTip(STR_SPRITE_ALIGNER_CENTRE_OFFSET, STR_NULL), SetFill(1, 0), SetResize(1, 0),
1176  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SA_RESET_REL), SetDataTip(STR_SPRITE_ALIGNER_RESET_BUTTON, STR_SPRITE_ALIGNER_RESET_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1177  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_CROSSHAIR), SetDataTip(STR_SPRITE_ALIGNER_CROSSHAIR, STR_NULL), SetFill(1, 0), SetResize(1, 0),
1178  EndContainer(),
1179  EndContainer(),
1181  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_PICKER), SetDataTip(STR_SPRITE_ALIGNER_PICKER_BUTTON, STR_SPRITE_ALIGNER_PICKER_TOOLTIP), SetFill(1, 0),
1183  NWidget(WWT_MATRIX, COLOUR_GREY, WID_SA_LIST), SetResize(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetFill(1, 1), SetScrollbar(WID_SA_SCROLLBAR),
1184  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_SA_SCROLLBAR),
1185  EndContainer(),
1187  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_ZOOM + ZOOM_LVL_IN_4X), SetDataTip(STR_CONFIG_SETTING_ZOOM_LVL_MIN, STR_NULL), SetFill(1, 0),
1188  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_ZOOM + ZOOM_LVL_IN_2X), SetDataTip(STR_CONFIG_SETTING_ZOOM_LVL_IN_2X, STR_NULL), SetFill(1, 0),
1189  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_ZOOM + ZOOM_LVL_NORMAL), SetDataTip(STR_CONFIG_SETTING_ZOOM_LVL_NORMAL, STR_NULL), SetFill(1, 0),
1190  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_ZOOM + ZOOM_LVL_OUT_2X), SetDataTip(STR_CONFIG_SETTING_ZOOM_LVL_OUT_2X, STR_NULL), SetFill(1, 0),
1191  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_ZOOM + ZOOM_LVL_OUT_4X), SetDataTip(STR_CONFIG_SETTING_ZOOM_LVL_OUT_4X, STR_NULL), SetFill(1, 0),
1192  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SA_ZOOM + ZOOM_LVL_OUT_8X), SetDataTip(STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X, STR_NULL), SetFill(1, 0),
1193  EndContainer(),
1194  EndContainer(),
1195  EndContainer(),
1197  NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1198  NWidget(WWT_RESIZEBOX, COLOUR_GREY), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
1199  EndContainer(),
1200  EndContainer(),
1201 };
1202 
1203 static WindowDesc _sprite_aligner_desc(
1204  WDP_AUTO, "sprite_aligner", 400, 300,
1206  0,
1207  _nested_sprite_aligner_widgets
1208 );
1209 
1214 {
1215  AllocateWindowDescFront<SpriteAlignerWindow>(_sprite_aligner_desc, 0);
1216 }
Class for backupping variables and making sure they are restored later.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
static uint32_t BSWAP32(uint32_t x)
Perform a 32 bits endianness bitswap on x.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
Helper class to wrap some functionality/queries in.
virtual const void * GetInstance(uint index) const =0
Get the instance given an index.
virtual uint Resolve(uint index, uint var, uint param, bool &avail) const =0
Resolve (action2) variable for a given index.
virtual bool IsInspectable(uint index) const =0
Is the item with the given index inspectable?
virtual uint32_t GetGRFID(uint index) const =0
Get the GRFID of the file that includes this item.
virtual ~NIHelper()=default
Silence a warning.
void SetSimpleStringParameters(StringID string, uint32_t index) const
Helper to make setting the strings easier.
virtual const void * GetSpec(uint index) const =0
Get (NewGRF) specs given an index.
virtual bool PSAWithParameter() const
Used to decide if the PSA needs a parameter or not.
void SetObjectAtStringParameters(StringID string, uint32_t index, TileIndex tile) const
Helper to make setting the strings easier for objects at a specific tile.
virtual const std::span< int32_t > GetPSA([[maybe_unused]] uint index, [[maybe_unused]] uint32_t grfid) const
Gets the span containing the persistent storage.
virtual void SetStringParameters(uint index) const =0
Set the string parameters to write the right data for a STRINGn.
virtual uint GetParent(uint index) const =0
Get the parent "window_number" of a given instance.
Baseclass for nested widgets.
Definition: widget_type.h:144
uint resize_y
Vertical resize step (0 means not resizable).
Definition: widget_type.h:236
const std::string & GetSimplifiedFilename() const
Get the simplified filename of the opened file.
Scrollbar data structure.
Definition: widget_type.h:694
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
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
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
Definition: widget_type.h:860
size_type GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:740
RandomAccessFile with some extra information specific for sprite files.
RectPadding frametext
Padding inside frame with text.
Definition: window_gui.h:43
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition: window_gui.h:68
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition: window_gui.h:67
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type)
Get the GUI cell size for a vehicle image.
Definition: depot_gui.cpp:161
Base class for engines.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition: fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:851
void DrawRectOutline(const Rect &r, int colour, int width, int dash)
Draw the outline of a Rect.
Definition: gfx.cpp:456
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 DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:988
ZoomLevel _gui_zoom
GUI Zoom level.
Definition: gfx.cpp:61
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
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
@ Normal
The most basic (normal) sprite.
@ SA_RIGHT
Right align the text (must be a single bit).
Definition: gfx_type.h:345
@ 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
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition: gfx_type.h:284
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition: widget_type.h:1181
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1260
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 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
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1529
Base of all industries.
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 T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
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
std::span< const Action5Type > GetAction5Types()
Get list of all action 5 types.
Definition: newgrf.cpp:6389
GrfSpecFeature
Definition: newgrf.h:67
@ GSF_INVALID
An invalid spec feature.
Definition: newgrf.h:94
@ GSF_FAKE_END
End of the fake features.
Definition: newgrf.h:92
Information about NewGRF Action 5.
NewGRF handling of airports.
NewGRF handling of airport tiles.
Functions/types related to NewGRF debugging.
Data 'tables' for NewGRF debugging.
static const NIFeature *const _nifeatures[]
Table with all NIFeatures.
static uint GetInspectWindowNumber(GrfSpecFeature feature, uint index)
Get the window number for the inspect window given a feature and index.
static const int CBM_NO_BIT
Mask to show no bit needs to be enabled for the callback.
NIType
The type of a property to show.
@ NIT_INT
The property is a simple integer.
@ NIT_CARGO
The property is a cargo.
void ShowSpriteAlignerWindow()
Show the window for aligning sprites.
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
void InvalidateNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Invalidate the inspect window for a given feature and index.
void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index, const uint32_t grfid)
Show the inspect window for a given feature and index.
static const NIFeature * GetFeature(uint window_number)
Get the NIFeature related to the window number.
bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
Can we inspect the data given a certain feature and index.
static uint GetFeatureIndex(uint window_number)
Get the feature index related to the window number.
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
static GrfSpecFeature GetFeatureNum(uint window_number)
Get the feature number related to the window number.
static const NIHelper * GetFeatureHelper(uint window_number)
Get the NIHelper related to the window number.
NewGrfDebugSpritePicker _newgrf_debug_sprite_picker
The sprite picker.
Types related to the newgrf debug widgets.
@ WID_NGRFI_VEH_CHAIN
Display for vehicle chain.
@ WID_NGRFI_PARENT
Inspect the parent.
@ WID_NGRFI_MAINPANEL
Panel widget containing the actual data.
@ WID_NGRFI_VEH_NEXT
Go to next vehicle in chain.
@ WID_NGRFI_CAPTION
The caption bar of course.
@ WID_NGRFI_VEH_PREV
Go to previous vehicle in chain.
@ WID_NGRFI_SCROLLBAR
Scrollbar.
@ WID_SA_NEXT
Skip to the next sprite.
@ WID_SA_CAPTION
Caption of the window.
@ WID_SA_SPRITE
The actual sprite.
@ WID_SA_PICKER
Sprite picker.
@ WID_SA_SCROLLBAR
Scrollbar for sprite list.
@ WID_SA_OFFSETS_ABS
The sprite offsets (absolute).
@ WID_SA_PREVIOUS
Skip to the previous sprite.
@ WID_SA_OFFSETS_REL
The sprite offsets (relative).
@ WID_SA_CROSSHAIR
Toggle crosshair.
@ WID_SA_GOTO
Go to a given sprite.
@ WID_SA_DOWN
Move the sprite down.
@ WID_SA_ZOOM
Zoom level buttons (from ZOOM_LVL_BEGIN to ZOOM_LVL_END).
@ WID_SA_UP
Move the sprite up.
@ WID_SA_RESET_REL
Reset relative sprite offset.
@ WID_SA_LIST
Queried sprite list.
@ WID_SA_RIGHT
Move the sprite to the right.
@ WID_SA_LEFT
Move the sprite to the left.
@ WID_SA_CENTRE
Toggle centre sprite.
Functions for NewGRF industries.
NewGRF handling of industry tiles.
Functions related to NewGRF objects.
NewGRF handling of rail types.
Action 2 handling.
Header file for NewGRF stations.
Functions to handle the town part of NewGRF towns.
Base for all objects.
static const uint8_t PC_WHITE
White palette colour.
Definition: palette_func.h:70
static const uint8_t PC_LIGHT_BLUE
Light blue palette colour.
Definition: palette_func.h:88
Class related to random access to files.
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition: road_map.h:85
Road vehicle states.
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
SpriteType GetSpriteType(SpriteID sprite)
Get the sprite type of a given sprite.
std::span< const std::unique_ptr< SpriteFile > > GetCachedSpriteFiles()
Get the list of cached SpriteFiles.
Definition: spritecache.cpp:81
SpriteFile * GetOriginFile(SpriteID sprite)
Get the SpriteFile of a given sprite.
uint GetMaxSpriteID()
Get a reasonable (upper bound) estimate of the maximum SpriteID used in OpenTTD; there will be no spr...
uint32_t GetSpriteLocalID(SpriteID sprite)
Get the GRF-local sprite id of a given sprite.
Functions to cache sprites in memory.
static const SpriteID SPR_OPENTTD_BASE
Extra graphic spritenumbers.
Definition: sprites.h:56
Base classes/functions for stations.
StationType GetStationType(Tile t)
Get the station type of this tile.
Definition: station_map.h:44
Definition of base types and functions in a cross-platform compatible way.
Functions related to low-level strings.
@ CS_HEXADECIMAL
Only hexadecimal characters.
Definition: string_type.h:30
@ CS_NUMERAL
Only numeric ones.
Definition: string_type.h:26
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
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:319
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
void SetDParamMaxDigits(size_t n, uint count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:143
Functions related to OTTD's strings.
@ 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
Information about a single action 5 type.
Definition: newgrf_act5.h:21
SpriteID sprite_base
Load the sprites starting from this sprite.
Definition: newgrf_act5.h:23
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:134
StringID name
Name of this type of cargo.
Definition: cargotype.h:88
GUISettings gui
settings related to the GUI
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Definition: gfx_type.h:157
ZoomLevel zoom_min
minimum zoom out level
ZoomLevel zoom_max
maximum zoom out level
Representation of the available callbacks with information on when they actually apply.
NIOffsetProc * offset_proc
Callback proc to get the actual variable address in memory.
const char * name
The human readable name of the callback.
uint8_t cb_bit
The bit that needs to be set for this callback to be enabled.
uint16_t cb_id
The number of the callback.
uint8_t read_size
The number of bytes (i.e. byte, word, dword etc) to read.
Container for all information for a given feature.
const NIHelper * helper
The class container all helper functions.
const NICallback * callbacks
The callbacks associated with this feature.
const NIVariable * variables
The variables associated with this feature.
const NIProperty * properties
The properties associated with this feature.
Representation of the data from a NewGRF property.
uint8_t read_size
Number of bytes (i.e. byte, word, dword etc)
const char * name
A (human readable) name for the property.
NIOffsetProc * offset_proc
Callback proc to get the actual variable address in memory.
uint8_t prop
The number of the property.
Representation on the NewGRF variables.
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:1075
Window used for inspecting NewGRFs.
static bool HasVariableParameter(uint variable)
Check whether the given variable has a parameter.
static uint32_t var60params[GSF_FAKE_END][0x20]
The value for the variable 60 parameters.
void DrawMainPanelWidget(const Rect &r) const
Helper function to draw the main panel widget.
void ValidateChainIndex()
Ensure that this->chain_index is in range.
void DrawString(const Rect &r, int offset, const std::string &string) const
Helper function to draw a string (line) in the window.
bool HasChainIndex() const
Check whether this feature has chain index, i.e.
uint32_t caller_grfid
GRFID of the caller of this window, 0 if it has no caller.
void DrawVehicleChainWidget(const Rect &r) const
Helper function to draw the vehicle chain widget.
uint GetFeatureIndex() const
Get the feature index.
void SetCallerGRFID(uint32_t grfid)
Set the GRFID of the item opening this window.
uint8_t current_edit_param
The currently edited parameter, to update the right one.
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
void OnResize() override
Called after the window got resized.
uint chain_index
For ground vehicles: Index in vehicle chain.
Spritepicker of SpriteAligner.
Definition: newgrf_debug.h:25
NewGrfDebugSpritePickerMode mode
Current state.
Definition: newgrf_debug.h:26
std::vector< SpriteID > sprites
Sprites found.
Definition: newgrf_debug.h:28
Coordinates of a point in 2D.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
int Height() const
Get height of Rect.
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
Rect Expand(int s) const
Copy and expand Rect by s pixels.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Window used for aligning sprites.
std::pair< int16_t, int16_t > XyOffs
Pair for x and y offsets of the sprite before alignment. First value contains the x offset,...
const Action5Type * act5_type
Sprite Area of current selected sprite.
void OnResize() override
Called after the window got resized.
SpriteID current_sprite
The currently shown sprite.
std::map< SpriteID, XyOffs > offs_start_map
Mapping of starting offsets for the sprites which have been aligned in the sprite aligner window.
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Data structure describing a sprite.
Definition: spritecache.h:17
uint16_t width
Width of the sprite.
Definition: spritecache.h:19
uint16_t height
Height of the sprite.
Definition: spritecache.h:18
int16_t y_offs
Number of pixels to shift the sprite downwards.
Definition: spritecache.h:21
int16_t x_offs
Number of pixels to shift the sprite to the right.
Definition: spritecache.h:20
uint height
Vehicle cell height.
Definition: vehicle_gui.h:84
Vehicle data structure.
Definition: vehicle_base.h:244
Vehicle * Move(int n)
Get the vehicle at offset n of this vehicle chain.
Definition: vehicle_base.h:674
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:645
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:632
High level window description.
Definition: window_gui.h:159
Data structure for an opened window.
Definition: window_gui.h:273
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1733
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 RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition: window_gui.h:475
virtual void ShowNewGRFInspectWindow() const
Show the NewGRF inspection window.
Definition: window_gui.h:861
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
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition: window_gui.h:532
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:447
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition: window_gui.h:466
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:314
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:387
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:312
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:311
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:302
Stuff related to the text buffer GUI.
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
@ MP_ROAD
A tile with road (or tram tracks)
Definition: tile_type.h:50
@ MP_STATION
A tile of a station.
Definition: tile_type.h:53
@ MP_HOUSE
A house by a town.
Definition: tile_type.h:51
@ MP_RAILWAY
A railway.
Definition: tile_type.h:49
@ MP_INDUSTRY
Part of an industry.
Definition: tile_type.h:56
@ MP_OBJECT
Contains objects such as transmitters and owned land.
Definition: tile_type.h:58
Base of the town class.
Base for the train class.
Base class for all vehicles.
void DrawVehicleImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a vehicle chain.
Functions related to the vehicle's GUIs.
@ EIT_IN_DEPOT
Vehicle drawn in depot.
Definition: vehicle_type.h:80
@ EIT_IN_DETAILS
Vehicle drawn in vehicle details, refit window, ...
Definition: vehicle_type.h:81
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:54
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:281
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:31
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:32
@ 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_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:113
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:114
@ WWT_LABEL
Centered label.
Definition: widget_type.h:57
@ NWID_SPACER
Invisible widget that takes some space.
Definition: widget_type.h:79
@ 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
@ WWT_TEXTBTN_2
(Toggle) Button with diff text when clicked
Definition: widget_type.h:56
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition: widget_type.h:48
@ 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_HORIZONTAL_LTR
Horizontal container that doesn't change the order of the widgets for RTL languages.
Definition: widget_type.h:76
@ RWV_HIDE_BEVEL
Bevel of resize box is hidden.
Definition: widget_type.h:40
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
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
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ FR_BORDERONLY
Draw border only, no background.
Definition: window_gui.h:27
@ WDP_AUTO
Find a place automatically.
Definition: window_gui.h:147
int WidgetID
Widget ID.
Definition: window_type.h:18
int32_t WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:737
@ WC_LAND_INFO
Land info window; Window numbers:
Definition: window_type.h:150
@ WC_SPRITE_ALIGNER
Sprite aligner (debug); Window numbers:
Definition: window_type.h:686
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:45
@ WC_NEWGRF_INSPECT
NewGRF inspect (debug); Window numbers:
Definition: window_type.h:680
Functions related to zooming.
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_MIN) When shifting right,...
Definition: zoom_func.h:22
int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:117
int UnScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZOOM_LVL_MIN) When shifting right,...
Definition: zoom_func.h:34
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:16
@ ZOOM_LVL_NORMAL
The normal zoom level.
Definition: zoom_type.h:21
@ ZOOM_LVL_BEGIN
Begin for iteration.
Definition: zoom_type.h:18
@ ZOOM_LVL_OUT_4X
Zoomed 4 times out.
Definition: zoom_type.h:23
@ ZOOM_LVL_OUT_2X
Zoomed 2 times out.
Definition: zoom_type.h:22
@ ZOOM_LVL_OUT_8X
Zoomed 8 times out.
Definition: zoom_type.h:24
@ ZOOM_LVL_IN_2X
Zoomed 2 times in.
Definition: zoom_type.h:20
@ ZOOM_LVL_END
End for iteration.
Definition: zoom_type.h:25
@ ZOOM_LVL_IN_4X
Zoomed 4 times in.
Definition: zoom_type.h:19