# HG changeset patch # User frosch # Date 2010-04-26 20:35:27 # Node ID a1fdff095c29063c5c941cb7bc056c1b684775d9 # Parent 573d9325141e0caeead9fd3e5ab15a0afd851ddf (svn r19731) -Add: Spritepicker to sprite alignment tool. diff --git a/src/gfx.cpp b/src/gfx.cpp --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -24,6 +24,7 @@ #include "network/network_func.h" #include "thread/thread.h" #include "window_func.h" +#include "newgrf_debug.h" #include "table/palettes.h" #include "table/sprites.h" @@ -56,7 +57,7 @@ static byte _stringwidth_table[FS_END][2 DrawPixelInfo *_cur_dpi; byte _colour_gradient[COLOUR_END][8]; -static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL); +static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL, SpriteID sprite_id = SPR_CURSOR_MOUSE); FontSize _cur_fontsize; static FontSize _last_fontsize; @@ -1029,18 +1030,19 @@ Dimension GetSpriteSize(SpriteID sprid) */ void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub) { + SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; - GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH), ST_NORMAL), x, y, BM_TRANSPARENT, sub); + GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite); } else if (pal != PAL_NONE) { _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; - GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH), ST_NORMAL), x, y, BM_COLOUR_REMAP, sub); + GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_COLOUR_REMAP, sub, real_sprite); } else { - GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH), ST_NORMAL), x, y, BM_NORMAL, sub); + GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite); } } -static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub) +static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id) { const DrawPixelInfo *dpi = _cur_dpi; Blitter::BlitterParams bp; @@ -1121,6 +1123,22 @@ static void GfxMainBlitter(const Sprite assert(bp.skip_left + bp.width <= UnScaleByZoom(sprite->width, dpi->zoom)); assert(bp.skip_top + bp.height <= UnScaleByZoom(sprite->height, dpi->zoom)); + /* We do not want to catch the mouse. However we also use that spritenumber for unknown (text) sprites. */ + if (_newgrf_debug_sprite_picker.mode == SPM_REDRAW && sprite_id != SPR_CURSOR_MOUSE) { + Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); + void *topleft = blitter->MoveTo(bp.dst, bp.left, bp.top); + void *bottomright = blitter->MoveTo(topleft, bp.width - 1, bp.height - 1); + + void *clicked = _newgrf_debug_sprite_picker.clicked_pixel; + + if (topleft <= clicked && clicked <= bottomright) { + uint offset = (((size_t)clicked - (size_t)topleft) % bp.pitch) / blitter->GetBytesPerPixel(); + if (offset < (uint)bp.width) { + _newgrf_debug_sprite_picker.sprites.Include(sprite_id); + } + } + } + BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, dpi->zoom); } diff --git a/src/lang/english.txt b/src/lang/english.txt --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2387,6 +2387,8 @@ STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Representation of the currently selected sprite. The alignment is ignored when drawing this sprite STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Move the sprite around, changing the X and Y offsets STR_SPRITE_ALIGNER_OFFSETS :{BLACK}X offset: {NUM}, Y offset: {NUM} +STR_SPRITE_ALIGNER_PICKER_BUTTON :{BLACK}Pick sprite +STR_SPRITE_ALIGNER_PICKER_TOOLTIP :{BLACK}Pick a sprite from anywhere on the screen STR_SPRITE_ALIGNER_GOTO_CAPTION :{WHITE}Go to sprite diff --git a/src/newgrf_debug.h b/src/newgrf_debug.h --- a/src/newgrf_debug.h +++ b/src/newgrf_debug.h @@ -13,6 +13,24 @@ #define NEWGRF_DEBUG_H #include "newgrf.h" +#include "vehicle_type.h" + +/** Current state of spritepicker */ +enum NewGrfDebugSpritePickerMode { + SPM_NONE, + SPM_WAIT_CLICK, + SPM_REDRAW, +}; + +/** Spritepicker of SpriteAligner */ +struct NewGrfDebugSpritePicker { + NewGrfDebugSpritePickerMode mode; ///< Current state + void *clicked_pixel; ///< Clicked pixel (pointer to blitter buffer) + uint32 click_time; ///< Realtime tick when clicked to detect next frame + SmallVector sprites; ///< Sprites found +}; + +extern NewGrfDebugSpritePicker _newgrf_debug_sprite_picker; /** * Can we inspect the data given a certain feature and index. diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -37,6 +37,8 @@ #include "table/strings.h" +NewGrfDebugSpritePicker _newgrf_debug_sprite_picker = { SPM_NONE, NULL, 0, SmallVector() }; + /** * Get the feature index related to the window number. * @param window_number The window to get the feature index from. @@ -547,6 +549,9 @@ enum SpriteAlignerWidgets { SAW_DOWN, ///< Move the sprite down SAW_SPRITE, ///< The actual sprite SAW_OFFSETS, ///< The sprite offsets + SAW_PICKER, ///< Sprite picker + SAW_LIST, ///< Queried sprite list + SAW_SCROLLBAR,///< Scrollbar for sprite list }; /** Window used for aligning sprites. */ @@ -580,26 +585,56 @@ struct SpriteAlignerWindow : Window { } } + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) + { + if (widget != SAW_LIST) return; + + resize->height = max(11, FONT_HEIGHT_NORMAL + 1); + resize->width = 1; + + /* Resize to about 200 pixels (for the preview) */ + size->height = (1 + 200 / resize->height) * resize->height; + } + virtual void DrawWidget(const Rect &r, int widget) const { - if (widget != SAW_SPRITE) return; + switch (widget) { + case SAW_SPRITE: { + /* Center the sprite ourselves */ + const Sprite *spr = GetSprite(this->current_sprite, ST_NORMAL); + int width = r.right - r.left + 1; + int height = r.bottom - r.top + 1; + int x = r.left - spr->x_offs + (width - spr->width) / 2; + int y = r.top - spr->y_offs + (height - spr->height) / 2; - /* Center the sprite ourselves */ - const Sprite *spr = GetSprite(this->current_sprite, ST_NORMAL); - int width = r.right - r.left + 1; - int height = r.bottom - r.top + 1; - int x = r.left - spr->x_offs + (width - spr->width) / 2; - int y = r.top - spr->y_offs + (height - spr->height) / 2; + /* And draw only the part within the sprite area */ + SubSprite subspr = { + spr->x_offs + (spr->width - width) / 2 + 1, + spr->y_offs + (spr->height - height) / 2 + 1, + spr->x_offs + (spr->width + width) / 2 - 1, + spr->y_offs + (spr->height + height) / 2 - 1, + }; - /* And draw only the part within the sprite area */ - SubSprite subspr = { - spr->x_offs + (spr->width - width) / 2 + 1, - spr->y_offs + (spr->height - height) / 2 + 1, - spr->x_offs + (spr->width + width) / 2 - 1, - spr->y_offs + (spr->height + height) / 2 - 1, - }; + DrawSprite(this->current_sprite, PAL_NONE, x, y, &subspr); + break; + } + + case SAW_LIST: { + const NWidgetBase *nwid = this->GetWidget(widget); + int step_size = nwid->resize_y; - DrawSprite(this->current_sprite, PAL_NONE, x, y, &subspr); + SmallVector &list = _newgrf_debug_sprite_picker.sprites; + int max = min(this->vscroll.GetPosition() + this->vscroll.GetCapacity(), list.Length()); + + int y = r.top + WD_FRAMERECT_TOP; + for (int i = this->vscroll.GetPosition(); i < max; i++) { + SetDParam(0, list[i]); + DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_BLACK_COMMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE); + y += step_size; + } + break; + } + } } virtual void OnPaint() @@ -628,6 +663,25 @@ struct SpriteAlignerWindow : Window { this->SetDirty(); break; + case SAW_PICKER: + this->LowerWidget(SAW_PICKER); + _newgrf_debug_sprite_picker.mode = SPM_WAIT_CLICK; + this->SetDirty(); + break; + + case SAW_LIST: { + const NWidgetBase *nwid = this->GetWidget(widget); + int step_size = nwid->resize_y; + + uint i = this->vscroll.GetPosition() + (pt.y - nwid->pos_y) / step_size; + if (i < _newgrf_debug_sprite_picker.sprites.Length()) { + SpriteID spr = _newgrf_debug_sprite_picker.sprites[i]; + if (GetSpriteType(spr) == ST_NORMAL) this->current_sprite = spr; + } + this->SetDirty(); + break; + } + case SAW_UP: case SAW_DOWN: case SAW_LEFT: @@ -670,6 +724,21 @@ struct SpriteAlignerWindow : Window { } this->SetDirty(); } + + virtual void OnInvalidateData(int data) + { + if (data == 1) { + /* Sprite picker finished */ + this->RaiseWidget(SAW_PICKER); + this->vscroll.SetCount(_newgrf_debug_sprite_picker.sprites.Length()); + } + } + + virtual void OnResize() + { + this->vscroll.SetCapacityFromWidget(this, SAW_LIST); + this->GetWidget(SAW_LIST)->widget_data = (this->vscroll.GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START); + } }; static const NWidgetPart _nested_sprite_aligner_widgets[] = { @@ -680,38 +749,47 @@ static const NWidgetPart _nested_sprite_ NWidget(WWT_STICKYBOX, COLOUR_GREY), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY), - NWidget(NWID_VERTICAL), SetPIP(10, 5, 10), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 5, 10), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_PREVIOUS), SetDataTip(STR_SPRITE_ALIGNER_PREVIOUS_BUTTON, STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP), SetFill(1, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_GOTO), SetDataTip(STR_SPRITE_ALIGNER_GOTO_BUTTON, STR_SPRITE_ALIGNER_GOTO_TOOLTIP), SetFill(1, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_NEXT), SetDataTip(STR_SPRITE_ALIGNER_NEXT_BUTTON, STR_SPRITE_ALIGNER_NEXT_TOOLTIP), SetFill(1, 0), - EndContainer(), - NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10), - NWidget(NWID_SPACER), SetFill(1, 1), - NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_UP), SetDataTip(SPR_ARROW_UP, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), - NWidget(NWID_SPACER), SetFill(1, 1), - EndContainer(), - NWidget(NWID_HORIZONTAL_LTR), SetPIP(10, 5, 10), - NWidget(NWID_VERTICAL), + NWidget(NWID_HORIZONTAL), SetPIP(0, 0, 10), + NWidget(NWID_VERTICAL), SetPIP(10, 5, 10), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 5, 10), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_PREVIOUS), SetDataTip(STR_SPRITE_ALIGNER_PREVIOUS_BUTTON, STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP), SetFill(1, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_GOTO), SetDataTip(STR_SPRITE_ALIGNER_GOTO_BUTTON, STR_SPRITE_ALIGNER_GOTO_TOOLTIP), SetFill(1, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, SAW_NEXT), SetDataTip(STR_SPRITE_ALIGNER_NEXT_BUTTON, STR_SPRITE_ALIGNER_NEXT_TOOLTIP), SetFill(1, 0), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10), NWidget(NWID_SPACER), SetFill(1, 1), - NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_LEFT), SetDataTip(SPR_ARROW_LEFT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_UP), SetDataTip(SPR_ARROW_UP, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), NWidget(NWID_SPACER), SetFill(1, 1), EndContainer(), - NWidget(WWT_PANEL, COLOUR_DARK_BLUE, SAW_SPRITE), SetDataTip(STR_NULL, STR_SPRITE_ALIGNER_SPRITE_TOOLTIP), SetMinimalSize(200, 200), + NWidget(NWID_HORIZONTAL_LTR), SetPIP(10, 5, 10), + NWidget(NWID_VERTICAL), + NWidget(NWID_SPACER), SetFill(1, 1), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_LEFT), SetDataTip(SPR_ARROW_LEFT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), + NWidget(NWID_SPACER), SetFill(1, 1), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_DARK_BLUE, SAW_SPRITE), SetDataTip(STR_NULL, STR_SPRITE_ALIGNER_SPRITE_TOOLTIP), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(NWID_SPACER), SetFill(1, 1), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_RIGHT), SetDataTip(SPR_ARROW_RIGHT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), + NWidget(NWID_SPACER), SetFill(1, 1), + EndContainer(), EndContainer(), - NWidget(NWID_VERTICAL), + NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10), + NWidget(NWID_SPACER), SetFill(1, 1), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), NWidget(NWID_SPACER), SetFill(1, 1), - NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_RIGHT), SetDataTip(SPR_ARROW_RIGHT, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), - NWidget(NWID_SPACER), SetFill(1, 1), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10), + NWidget(WWT_LABEL, COLOUR_GREY, SAW_OFFSETS), SetDataTip(STR_SPRITE_ALIGNER_OFFSETS, STR_NULL), SetFill(1, 0), EndContainer(), EndContainer(), - NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10), - NWidget(NWID_SPACER), SetFill(1, 1), - NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, SAW_DOWN), SetDataTip(SPR_ARROW_DOWN, STR_SPRITE_ALIGNER_MOVE_TOOLTIP), SetResize(0, 0), - NWidget(NWID_SPACER), SetFill(1, 1), - EndContainer(), - NWidget(NWID_HORIZONTAL), SetPIP(10, 5, 10), - NWidget(WWT_LABEL, COLOUR_GREY, SAW_OFFSETS), SetDataTip(STR_SPRITE_ALIGNER_OFFSETS, STR_NULL), SetFill(1, 0), + NWidget(NWID_VERTICAL), SetPIP(10, 5, 10), + NWidget(WWT_TEXTBTN, COLOUR_GREY, SAW_PICKER), SetDataTip(STR_SPRITE_ALIGNER_PICKER_BUTTON, STR_SPRITE_ALIGNER_PICKER_TOOLTIP), SetFill(1, 0), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_MATRIX, COLOUR_GREY, SAW_LIST), SetResize(1, 1), SetDataTip(0x101, STR_NULL), SetFill(1, 1), + NWidget(WWT_SCROLLBAR, COLOUR_GREY, SAW_SCROLLBAR), + EndContainer(), EndContainer(), EndContainer(), EndContainer(), diff --git a/src/window.cpp b/src/window.cpp --- a/src/window.cpp +++ b/src/window.cpp @@ -31,6 +31,7 @@ #include "widgets/dropdown_func.h" #include "strings_func.h" #include "settings_type.h" +#include "newgrf_debug.h" #include "table/sprites.h" @@ -2190,7 +2191,24 @@ void HandleMouseEvents() _input_events_this_tick++; } - MouseLoop(click, mousewheel); + /* Handle sprite picker before any GUI interaction */ + if (_newgrf_debug_sprite_picker.mode == SPM_REDRAW && _newgrf_debug_sprite_picker.click_time != _realtime_tick) { + /* Next realtime tick? Then redraw has finished */ + _newgrf_debug_sprite_picker.mode = SPM_NONE; + InvalidateWindowData(WC_SPRITE_ALIGNER, 0, 1); + } + + if (click == MC_LEFT && _newgrf_debug_sprite_picker.mode == SPM_WAIT_CLICK) { + /* Mark whole screen dirty, and wait for the next realtime tick, when drawing is finished. */ + Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter(); + _newgrf_debug_sprite_picker.clicked_pixel = blitter->MoveTo(_screen.dst_ptr, _cursor.pos.x, _cursor.pos.y); + _newgrf_debug_sprite_picker.click_time = _realtime_tick; + _newgrf_debug_sprite_picker.sprites.Clear(); + _newgrf_debug_sprite_picker.mode = SPM_REDRAW; + MarkWholeScreenDirty(); + } else { + MouseLoop(click, mousewheel); + } /* We have moved the mouse the required distance, * no need to move it at any later time. */