00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include <stdarg.h>
00014 #include "window_gui.h"
00015 #include "window_func.h"
00016 #include "fileio_func.h"
00017 #include "spritecache.h"
00018 #include "string_func.h"
00019 #include "strings_func.h"
00020 #include "textbuf_gui.h"
00021
00022 #include "engine_base.h"
00023 #include "industry.h"
00024 #include "object_base.h"
00025 #include "station_base.h"
00026 #include "town.h"
00027 #include "vehicle_base.h"
00028
00029 #include "newgrf_airporttiles.h"
00030 #include "newgrf_debug.h"
00031 #include "newgrf_object.h"
00032 #include "newgrf_spritegroup.h"
00033 #include "newgrf_station.h"
00034 #include "newgrf_town.h"
00035
00036 #include "table/strings.h"
00037
00039 NewGrfDebugSpritePicker _newgrf_debug_sprite_picker = { SPM_NONE, NULL, 0, SmallVector<SpriteID, 256>() };
00040
00046 static inline uint GetFeatureIndex(uint window_number)
00047 {
00048 return GB(window_number, 0, 27);
00049 }
00050
00058 static inline uint GetInspectWindowNumber(GrfSpecFeature feature, uint index)
00059 {
00060 assert((index >> 27) == 0);
00061 return (feature << 27) | index;
00062 }
00063
00068 enum NIType {
00069 NIT_INT,
00070 NIT_CARGO,
00071 };
00072
00074 struct NIProperty {
00075 const char *name;
00076 ptrdiff_t offset;
00077 byte read_size;
00078 byte prop;
00079 byte type;
00080 };
00081
00082
00087 struct NICallback {
00088 const char *name;
00089 ptrdiff_t offset;
00090 byte read_size;
00091 byte cb_bit;
00092 uint16 cb_id;
00093 };
00095 static const int CBM_NO_BIT = UINT8_MAX;
00096
00098 struct NIVariable {
00099 const char *name;
00100 byte var;
00101 };
00102
00104 class NIHelper {
00105 public:
00107 virtual ~NIHelper() {}
00108
00114 virtual bool IsInspectable(uint index) const = 0;
00115
00121 virtual uint GetParent(uint index) const = 0;
00122
00128 virtual const void *GetInstance(uint index) const = 0;
00129
00135 virtual const void *GetSpec(uint index) const = 0;
00136
00141 virtual void SetStringParameters(uint index) const = 0;
00142
00151 virtual uint Resolve(uint index, uint var, uint param, bool *avail) const
00152 {
00153 ResolverObject ro;
00154 memset(&ro, 0, sizeof(ro));
00155 this->Resolve(&ro, index);
00156 return ro.GetVariable(&ro, var, param, avail);
00157 }
00158
00159 protected:
00166 virtual void Resolve(ResolverObject *ro, uint index) const {}
00167
00173 void SetSimpleStringParameters(StringID string, uint32 index) const
00174 {
00175 SetDParam(0, string);
00176 SetDParam(1, index);
00177 }
00178
00179
00186 void SetObjectAtStringParameters(StringID string, uint32 index, TileIndex tile) const
00187 {
00188 SetDParam(0, STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT);
00189 SetDParam(1, string);
00190 SetDParam(2, index);
00191 SetDParam(3, tile);
00192 }
00193 };
00194
00195
00197 struct NIFeature {
00198 const NIProperty *properties;
00199 const NICallback *callbacks;
00200 const NIVariable *variables;
00201 const NIHelper *helper;
00202 uint psa_size;
00203 size_t psa_offset;
00204 };
00205
00206
00207 #include "table/newgrf_debug_data.h"
00208
00214 static inline GrfSpecFeature GetFeatureNum(uint window_number)
00215 {
00216 return (GrfSpecFeature)GB(window_number, 27, 8);
00217 }
00218
00224 static inline const NIFeature *GetFeature(uint window_number)
00225 {
00226 GrfSpecFeature idx = GetFeatureNum(window_number);
00227 return idx < GSF_FAKE_END ? _nifeatures[idx] : NULL;
00228 }
00229
00236 static inline const NIHelper *GetFeatureHelper(uint window_number)
00237 {
00238 return GetFeature(window_number)->helper;
00239 }
00240
00241
00243 enum NewGRFInspectWidgets {
00244 NIW_CAPTION,
00245 NIW_PARENT,
00246 NIW_MAINPANEL,
00247 NIW_SCROLLBAR,
00248 };
00249
00251 struct NewGRFInspectWindow : Window {
00252 static const int LEFT_OFFSET = 5;
00253 static const int RIGHT_OFFSET = 5;
00254 static const int TOP_OFFSET = 5;
00255 static const int BOTTOM_OFFSET = 5;
00256
00258 static byte var60params[GSF_FAKE_END][0x20];
00259
00261 byte current_edit_param;
00262
00263 Scrollbar *vscroll;
00264
00270 static bool HasVariableParameter(uint variable)
00271 {
00272 return IsInsideBS(variable, 0x60, 0x20);
00273 }
00274
00275 NewGRFInspectWindow(const WindowDesc *desc, WindowNumber wno) : Window()
00276 {
00277 this->CreateNestedTree(desc);
00278 this->vscroll = this->GetScrollbar(NIW_SCROLLBAR);
00279 this->FinishInitNested(desc, wno);
00280
00281 this->vscroll->SetCount(0);
00282 this->SetWidgetDisabledState(NIW_PARENT, GetFeatureHelper(this->window_number)->GetParent(GetFeatureIndex(this->window_number)) == UINT32_MAX);
00283 }
00284
00285 virtual void SetStringParameters(int widget) const
00286 {
00287 if (widget != NIW_CAPTION) return;
00288
00289 GetFeatureHelper(this->window_number)->SetStringParameters(GetFeatureIndex(this->window_number));
00290 }
00291
00292 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00293 {
00294 if (widget != NIW_MAINPANEL) return;
00295
00296 resize->height = max(11, FONT_HEIGHT_NORMAL + 1);
00297 resize->width = 1;
00298
00299 size->height = 5 * resize->height + TOP_OFFSET + BOTTOM_OFFSET;
00300 }
00301
00308 void WARN_FORMAT(4, 5) DrawString(const Rect &r, int offset, const char *format, ...) const
00309 {
00310 char buf[1024];
00311
00312 va_list va;
00313 va_start(va, format);
00314 vsnprintf(buf, lengthof(buf), format, va);
00315 va_end(va);
00316
00317 offset -= this->vscroll->GetPosition();
00318 if (offset < 0 || offset >= this->vscroll->GetCapacity()) return;
00319
00320 ::DrawString(r.left + LEFT_OFFSET, r.right + RIGHT_OFFSET, r.top + TOP_OFFSET + (offset * this->resize.step_height), buf, TC_BLACK);
00321 }
00322
00323 virtual void DrawWidget(const Rect &r, int widget) const
00324 {
00325 if (widget != NIW_MAINPANEL) return;
00326
00327 uint index = GetFeatureIndex(this->window_number);
00328 const NIFeature *nif = GetFeature(this->window_number);
00329 const NIHelper *nih = nif->helper;
00330 const void *base = nih->GetInstance(index);
00331 const void *base_spec = nih->GetSpec(index);
00332
00333 uint i = 0;
00334 if (nif->variables != NULL) {
00335 this->DrawString(r, i++, "Variables:");
00336 for (const NIVariable *niv = nif->variables; niv->name != NULL; niv++) {
00337 bool avail = true;
00338 uint param = HasVariableParameter(niv->var) ? NewGRFInspectWindow::var60params[GetFeatureNum(this->window_number)][niv->var - 0x60] : 0;
00339 uint value = nih->Resolve(index, niv->var, param, &avail);
00340
00341 if (!avail) continue;
00342
00343 if (HasVariableParameter(niv->var)) {
00344 this->DrawString(r, i++, " %02x[%02x]: %08x (%s)", niv->var, param, value, niv->name);
00345 } else {
00346 this->DrawString(r, i++, " %02x: %08x (%s)", niv->var, value, niv->name);
00347 }
00348 }
00349 }
00350
00351 if (nif->psa_size != 0) {
00352 this->DrawString(r, i++, "Persistent storage:");
00353 assert(nif->psa_size % 4 == 0);
00354 int32 *psa = (int32*)((byte*)base + nif->psa_offset);
00355 for (uint j = 0; j < nif->psa_size; j += 4, psa += 4) {
00356 this->DrawString(r, i++, " %i: %i %i %i %i", j, psa[0], psa[1], psa[2], psa[3]);
00357 }
00358 }
00359
00360 if (nif->properties != NULL) {
00361 this->DrawString(r, i++, "Properties:");
00362 for (const NIProperty *nip = nif->properties; nip->name != NULL; nip++) {
00363 void *ptr = (byte*)base + nip->offset;
00364 uint value;
00365 switch (nip->read_size) {
00366 case 1: value = *(uint8 *)ptr; break;
00367 case 2: value = *(uint16 *)ptr; break;
00368 case 4: value = *(uint32 *)ptr; break;
00369 default: NOT_REACHED();
00370 }
00371
00372 StringID string;
00373 SetDParam(0, value);
00374 switch (nip->type) {
00375 case NIT_INT:
00376 string = STR_JUST_INT;
00377 break;
00378
00379 case NIT_CARGO:
00380 string = value != INVALID_CARGO ? CargoSpec::Get(value)->name : STR_QUANTITY_N_A;
00381 break;
00382
00383 default:
00384 NOT_REACHED();
00385 }
00386
00387 char buffer[64];
00388 GetString(buffer, string, lastof(buffer));
00389 this->DrawString(r, i++, " %02x: %s (%s)", nip->prop, buffer, nip->name);
00390 }
00391 }
00392
00393 if (nif->callbacks != NULL) {
00394 this->DrawString(r, i++, "Callbacks:");
00395 for (const NICallback *nic = nif->callbacks; nic->name != NULL; nic++) {
00396 if (nic->cb_bit != CBM_NO_BIT) {
00397 void *ptr = (byte*)base_spec + nic->offset;
00398 uint value;
00399 switch (nic->read_size) {
00400 case 1: value = *(uint8 *)ptr; break;
00401 case 2: value = *(uint16 *)ptr; break;
00402 case 4: value = *(uint32 *)ptr; break;
00403 default: NOT_REACHED();
00404 }
00405
00406 if (!HasBit(value, nic->cb_bit)) continue;
00407 this->DrawString(r, i++, " %03x: %s", nic->cb_id, nic->name);
00408 } else {
00409 this->DrawString(r, i++, " %03x: %s (unmasked)", nic->cb_id, nic->name);
00410 }
00411 }
00412 }
00413
00414
00415
00416
00417 const_cast<NewGRFInspectWindow*>(this)->vscroll->SetCount(i);
00418 }
00419
00420 virtual void OnClick(Point pt, int widget, int click_count)
00421 {
00422 switch (widget) {
00423 case NIW_PARENT: {
00424 uint index = GetFeatureHelper(this->window_number)->GetParent(GetFeatureIndex(this->window_number));
00425 ::ShowNewGRFInspectWindow((GrfSpecFeature)GB(index, 27, 8), GetFeatureIndex(index));
00426 break;
00427 }
00428
00429 case NIW_MAINPANEL: {
00430
00431 const NIFeature *nif = GetFeature(this->window_number);
00432 if (nif->variables == NULL) return;
00433
00434
00435 int line = this->vscroll->GetScrolledRowFromWidget(pt.y, this, NIW_MAINPANEL, TOP_OFFSET);
00436 if (line == INT_MAX) return;
00437
00438
00439 for (const NIVariable *niv = nif->variables; niv->name != NULL; niv++, line--) {
00440 if (line != 1) continue;
00441
00442 if (!HasVariableParameter(niv->var)) break;
00443
00444 this->current_edit_param = niv->var;
00445 ShowQueryString(STR_EMPTY, STR_NEWGRF_INSPECT_QUERY_CAPTION, 3, this, CS_HEXADECIMAL, QSF_NONE);
00446 }
00447 }
00448 }
00449 }
00450
00451 virtual void OnQueryTextFinished(char *str)
00452 {
00453 if (StrEmpty(str)) return;
00454
00455 NewGRFInspectWindow::var60params[GetFeatureNum(this->window_number)][this->current_edit_param - 0x60] = strtol(str, NULL, 16);
00456 this->SetDirty();
00457 }
00458
00459 virtual void OnResize()
00460 {
00461 this->vscroll->SetCapacityFromWidget(this, NIW_MAINPANEL, TOP_OFFSET + BOTTOM_OFFSET);
00462 }
00463 };
00464
00465 byte NewGRFInspectWindow::var60params[GSF_FAKE_END][0x20] = { {0} };
00466
00467 static const NWidgetPart _nested_newgrf_inspect_widgets[] = {
00468 NWidget(NWID_HORIZONTAL),
00469 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
00470 NWidget(WWT_CAPTION, COLOUR_GREY, NIW_CAPTION), SetDataTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00471 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, NIW_PARENT), SetDataTip(STR_NEWGRF_INSPECT_PARENT_BUTTON, STR_NEWGRF_INSPECT_PARENT_TOOLTIP),
00472 NWidget(WWT_SHADEBOX, COLOUR_GREY),
00473 NWidget(WWT_STICKYBOX, COLOUR_GREY),
00474 EndContainer(),
00475 NWidget(NWID_HORIZONTAL),
00476 NWidget(WWT_PANEL, COLOUR_GREY, NIW_MAINPANEL), SetMinimalSize(300, 0), SetScrollbar(NIW_SCROLLBAR), EndContainer(),
00477 NWidget(NWID_VERTICAL),
00478 NWidget(NWID_VSCROLLBAR, COLOUR_GREY, NIW_SCROLLBAR),
00479 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
00480 EndContainer(),
00481 EndContainer(),
00482 };
00483
00484 static const WindowDesc _newgrf_inspect_desc(
00485 WDP_AUTO, 400, 300,
00486 WC_NEWGRF_INSPECT, WC_NONE,
00487 WDF_UNCLICK_BUTTONS,
00488 _nested_newgrf_inspect_widgets, lengthof(_nested_newgrf_inspect_widgets)
00489 );
00490
00499 void ShowNewGRFInspectWindow(GrfSpecFeature feature, uint index)
00500 {
00501 if (!IsNewGRFInspectable(feature, index)) return;
00502
00503 WindowNumber wno = GetInspectWindowNumber(feature, index);
00504 AllocateWindowDescFront<NewGRFInspectWindow>(&_newgrf_inspect_desc, wno);
00505 }
00506
00515 void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
00516 {
00517 if (feature == GSF_INVALID) return;
00518
00519 WindowNumber wno = GetInspectWindowNumber(feature, index);
00520 DeleteWindowById(WC_NEWGRF_INSPECT, wno);
00521
00522
00523
00524
00525 InvalidateWindowData(WC_LAND_INFO, 0, 1);
00526 }
00527
00537 bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
00538 {
00539 const NIFeature *nif = GetFeature(GetInspectWindowNumber(feature, index));
00540 if (nif == NULL) return false;
00541 return nif->helper->IsInspectable(index);
00542 }
00543
00549 GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
00550 {
00551 switch (GetTileType(tile)) {
00552 default: return GSF_INVALID;
00553 case MP_RAILWAY: return GSF_RAILTYPES;
00554 case MP_ROAD: return IsLevelCrossing(tile) ? GSF_RAILTYPES : GSF_INVALID;
00555 case MP_HOUSE: return GSF_HOUSES;
00556 case MP_INDUSTRY: return GSF_INDUSTRYTILES;
00557 case MP_OBJECT: return GSF_OBJECTS;
00558
00559 case MP_STATION:
00560 switch (GetStationType(tile)) {
00561 case STATION_RAIL: return GSF_STATIONS;
00562 case STATION_AIRPORT: return GSF_AIRPORTTILES;
00563 default: return GSF_INVALID;
00564 }
00565 }
00566 }
00567
00573 GrfSpecFeature GetGrfSpecFeature(VehicleType type)
00574 {
00575 switch (type) {
00576 case VEH_TRAIN: return GSF_TRAINS;
00577 case VEH_ROAD: return GSF_ROADVEHICLES;
00578 case VEH_SHIP: return GSF_SHIPS;
00579 case VEH_AIRCRAFT: return GSF_AIRCRAFT;
00580 default: return GSF_INVALID;
00581 }
00582 }
00583
00584
00585
00586
00587
00589 enum SpriteAlignerWidgets {
00590 SAW_CAPTION,
00591 SAW_PREVIOUS,
00592 SAW_GOTO,
00593 SAW_NEXT,
00594 SAW_UP,
00595 SAW_LEFT,
00596 SAW_RIGHT,
00597 SAW_DOWN,
00598 SAW_SPRITE,
00599 SAW_OFFSETS,
00600 SAW_PICKER,
00601 SAW_LIST,
00602 SAW_SCROLLBAR,
00603 };
00604
00606 struct SpriteAlignerWindow : Window {
00607 SpriteID current_sprite;
00608 Scrollbar *vscroll;
00609
00610 SpriteAlignerWindow(const WindowDesc *desc, WindowNumber wno) : Window()
00611 {
00612 this->CreateNestedTree(desc);
00613 this->vscroll = this->GetScrollbar(SAW_SCROLLBAR);
00614 this->FinishInitNested(desc, wno);
00615
00616
00617 while (GetSpriteType(this->current_sprite) != ST_NORMAL) this->current_sprite++;
00618 }
00619
00620 virtual void SetStringParameters(int widget) const
00621 {
00622 switch (widget) {
00623 case SAW_CAPTION:
00624 SetDParam(0, this->current_sprite);
00625 SetDParamStr(1, FioGetFilename(GetOriginFileSlot(this->current_sprite)));
00626 break;
00627
00628 case SAW_OFFSETS: {
00629 const Sprite *spr = GetSprite(this->current_sprite, ST_NORMAL);
00630 SetDParam(0, spr->x_offs);
00631 SetDParam(1, spr->y_offs);
00632 break;
00633 }
00634
00635 default:
00636 break;
00637 }
00638 }
00639
00640 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00641 {
00642 if (widget != SAW_LIST) return;
00643
00644 resize->height = max(11, FONT_HEIGHT_NORMAL + 1);
00645 resize->width = 1;
00646
00647
00648 size->height = (1 + 200 / resize->height) * resize->height;
00649 }
00650
00651 virtual void DrawWidget(const Rect &r, int widget) const
00652 {
00653 switch (widget) {
00654 case SAW_SPRITE: {
00655
00656 const Sprite *spr = GetSprite(this->current_sprite, ST_NORMAL);
00657 int width = r.right - r.left + 1;
00658 int height = r.bottom - r.top + 1;
00659 int x = r.left - spr->x_offs + (width - spr->width) / 2;
00660 int y = r.top - spr->y_offs + (height - spr->height) / 2;
00661
00662
00663 SubSprite subspr = {
00664 spr->x_offs + (spr->width - width) / 2 + 1,
00665 spr->y_offs + (spr->height - height) / 2 + 1,
00666 spr->x_offs + (spr->width + width) / 2 - 1,
00667 spr->y_offs + (spr->height + height) / 2 - 1,
00668 };
00669
00670 DrawSprite(this->current_sprite, PAL_NONE, x, y, &subspr);
00671 break;
00672 }
00673
00674 case SAW_LIST: {
00675 const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget);
00676 int step_size = nwid->resize_y;
00677
00678 SmallVector<SpriteID, 256> &list = _newgrf_debug_sprite_picker.sprites;
00679 int max = min<int>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), list.Length());
00680
00681 int y = r.top + WD_FRAMERECT_TOP;
00682 for (int i = this->vscroll->GetPosition(); i < max; i++) {
00683 SetDParam(0, list[i]);
00684 DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_BLACK_COMMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
00685 y += step_size;
00686 }
00687 break;
00688 }
00689 }
00690 }
00691
00692 virtual void OnClick(Point pt, int widget, int click_count)
00693 {
00694 switch (widget) {
00695 case SAW_PREVIOUS:
00696 do {
00697 this->current_sprite = (this->current_sprite == 0 ? GetMaxSpriteID() : this->current_sprite) - 1;
00698 } while (GetSpriteType(this->current_sprite) != ST_NORMAL);
00699 this->SetDirty();
00700 break;
00701
00702 case SAW_GOTO:
00703 ShowQueryString(STR_EMPTY, STR_SPRITE_ALIGNER_GOTO_CAPTION, 7, this, CS_NUMERAL, QSF_NONE);
00704 break;
00705
00706 case SAW_NEXT:
00707 do {
00708 this->current_sprite = (this->current_sprite + 1) % GetMaxSpriteID();
00709 } while (GetSpriteType(this->current_sprite) != ST_NORMAL);
00710 this->SetDirty();
00711 break;
00712
00713 case SAW_PICKER:
00714 this->LowerWidget(SAW_PICKER);
00715 _newgrf_debug_sprite_picker.mode = SPM_WAIT_CLICK;
00716 this->SetDirty();
00717 break;
00718
00719 case SAW_LIST: {
00720 const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget);
00721 int step_size = nwid->resize_y;
00722
00723 uint i = this->vscroll->GetPosition() + (pt.y - nwid->pos_y) / step_size;
00724 if (i < _newgrf_debug_sprite_picker.sprites.Length()) {
00725 SpriteID spr = _newgrf_debug_sprite_picker.sprites[i];
00726 if (GetSpriteType(spr) == ST_NORMAL) this->current_sprite = spr;
00727 }
00728 this->SetDirty();
00729 break;
00730 }
00731
00732 case SAW_UP:
00733 case SAW_DOWN:
00734 case SAW_LEFT:
00735 case SAW_RIGHT: {
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 Sprite *spr = const_cast<Sprite *>(GetSprite(this->current_sprite, ST_NORMAL));
00750 switch (widget) {
00751 case SAW_UP: spr->y_offs--; break;
00752 case SAW_DOWN: spr->y_offs++; break;
00753 case SAW_LEFT: spr->x_offs--; break;
00754 case SAW_RIGHT: spr->x_offs++; break;
00755 }
00756
00757
00758 MarkWholeScreenDirty();
00759 break;
00760 }
00761 }
00762 }
00763
00764 virtual void OnQueryTextFinished(char *str)
00765 {
00766 if (StrEmpty(str)) return;
00767
00768 this->current_sprite = atoi(str);
00769 if (this->current_sprite >= GetMaxSpriteID()) this->current_sprite = 0;
00770 while (GetSpriteType(this->current_sprite) != ST_NORMAL) {
00771 this->current_sprite = (this->current_sprite + 1) % GetMaxSpriteID();
00772 }
00773 this->SetDirty();
00774 }
00775
00781 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
00782 {
00783 if (!gui_scope) return;
00784 if (data == 1) {
00785
00786 this->RaiseWidget(SAW_PICKER);
00787 this->vscroll->SetCount(_newgrf_debug_sprite_picker.sprites.Length());
00788 }
00789 }
00790
00791 virtual void OnResize()
00792 {
00793 this->vscroll->SetCapacityFromWidget(this, SAW_LIST);
00794 this->GetWidget<NWidgetCore>(SAW_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
00795 }
00796 };
00797
00798 static const NWidgetPart _nested_sprite_aligner_widgets[] = {
00799 NWidget(NWID_HORIZONTAL),
00800 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
00801 NWidget(WWT_CAPTION, COLOUR_GREY, SAW_CAPTION), SetDataTip(STR_SPRITE_ALIGNER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00802 NWidget(WWT_SHADEBOX, COLOUR_GREY),
00803 NWidget(WWT_STICKYBOX, COLOUR_GREY),
00804 EndContainer(),
00805 NWidget(WWT_PANEL, COLOUR_GREY),
00806 NWidget(NWID_HORIZONTAL), SetPIP(0, 0, 10),
00807 NWidget(NWID_VERTICAL), SetPIP(10, 5, 10),
00808 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 5, 10),
00809 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_PREVIOUS), SetDataTip(STR_SPRITE_ALIGNER_PREVIOUS_BUTTON, STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP), SetFill(1, 0),
00810 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_GOTO), SetDataTip(STR_SPRITE_ALIGNER_GOTO_BUTTON, STR_SPRITE_ALIGNER_GOTO_TOOLTIP), SetFill(1, 0),
00811 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_NEXT), SetDataTip(STR_SPRITE_ALIGNER_NEXT_BUTTON, STR_SPRITE_ALIGNER_NEXT_TOOLTIP), SetFill(1, 0),
00812 EndContainer(),
00813 NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10),
00814 NWidget(NWID_SPACER), SetFill(1, 1),
00815 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_UP), SetDataTip(SPR_ARROW_UP, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0),
00816 NWidget(NWID_SPACER), SetFill(1, 1),
00817 EndContainer(),
00818 NWidget(NWID_HORIZONTAL_LTR), SetPIP(10, 5, 10),
00819 NWidget(NWID_VERTICAL),
00820 NWidget(NWID_SPACER), SetFill(1, 1),
00821 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_LEFT), SetDataTip(SPR_ARROW_LEFT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0),
00822 NWidget(NWID_SPACER), SetFill(1, 1),
00823 EndContainer(),
00824 NWidget(WWT_PANEL, COLOUR_DARK_BLUE, SAW_SPRITE), SetDataTip(STR_NULL, STR_SPRITE_ALIGNER_SPRITE_TOOLTIP),
00825 EndContainer(),
00826 NWidget(NWID_VERTICAL),
00827 NWidget(NWID_SPACER), SetFill(1, 1),
00828 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_RIGHT), SetDataTip(SPR_ARROW_RIGHT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0),
00829 NWidget(NWID_SPACER), SetFill(1, 1),
00830 EndContainer(),
00831 EndContainer(),
00832 NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10),
00833 NWidget(NWID_SPACER), SetFill(1, 1),
00834 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0),
00835 NWidget(NWID_SPACER), SetFill(1, 1),
00836 EndContainer(),
00837 NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10),
00838 NWidget(WWT_LABEL, COLOUR_GREY, SAW_OFFSETS), SetDataTip(STR_SPRITE_ALIGNER_OFFSETS, STR_NULL), SetFill(1, 0),
00839 EndContainer(),
00840 EndContainer(),
00841 NWidget(NWID_VERTICAL), SetPIP(10, 5, 10),
00842 NWidget(WWT_TEXTBTN, COLOUR_GREY, SAW_PICKER), SetDataTip(STR_SPRITE_ALIGNER_PICKER_BUTTON, STR_SPRITE_ALIGNER_PICKER_TOOLTIP), SetFill(1, 0),
00843 NWidget(NWID_HORIZONTAL),
00844 NWidget(WWT_MATRIX, COLOUR_GREY, SAW_LIST), SetResize(1, 1), SetDataTip(0x101, STR_NULL), SetFill(1, 1), SetScrollbar(SAW_SCROLLBAR),
00845 NWidget(NWID_VSCROLLBAR, COLOUR_GREY, SAW_SCROLLBAR),
00846 EndContainer(),
00847 EndContainer(),
00848 EndContainer(),
00849 EndContainer(),
00850 };
00851
00852 static const WindowDesc _sprite_aligner_desc(
00853 WDP_AUTO, 400, 300,
00854 WC_SPRITE_ALIGNER, WC_NONE,
00855 WDF_UNCLICK_BUTTONS,
00856 _nested_sprite_aligner_widgets, lengthof(_nested_sprite_aligner_widgets)
00857 );
00858
00862 void ShowSpriteAlignerWindow()
00863 {
00864 AllocateWindowDescFront<SpriteAlignerWindow>(&_sprite_aligner_desc, 0);
00865 }