changeset 15105:2327111375f3 draft

(svn r19731) -Add: Spritepicker to sprite alignment tool.
author frosch <frosch@openttd.org>
date Mon, 26 Apr 2010 20:35:27 +0000
parents c0bc7e91d0f9
children b4d5560a832b
files src/gfx.cpp src/lang/english.txt src/newgrf_debug.h src/newgrf_debug_gui.cpp src/window.cpp
diffstat 5 files changed, 180 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 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 @@
  */
 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 @@
 	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);
 }
 
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -2387,6 +2387,8 @@
 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
 
--- 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<SpriteID, 256> sprites; ///< Sprites found
+};
+
+extern NewGrfDebugSpritePicker _newgrf_debug_sprite_picker;
 
 /**
  * Can we inspect the data given a certain feature and index.
--- 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<SpriteID, 256>() };
+
 /**
  * Get the feature index related to the window number.
  * @param window_number The window to get the feature index from.
@@ -547,6 +549,9 @@
 	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 @@
 		}
 	}
 
+	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<NWidgetBase>(widget);
+				int step_size = nwid->resize_y;
 
-		DrawSprite(this->current_sprite, PAL_NONE, x, y, &subspr);
+				SmallVector<SpriteID, 256> &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 @@
 				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<NWidgetBase>(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 @@
 		}
 		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<NWidgetCore>(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 @@
 		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(),
--- 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 @@
 		_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. */