Index: src/variables.h =================================================================== --- src/variables.h (revision 11158) +++ src/variables.h (working copy) @@ -337,6 +337,8 @@ extern const TileTypeProcs * const _tile_type_procs[16]; +extern bool _draw_bounding_boxes; + /* misc */ VARDEF char _screenshot_name[128]; VARDEF byte _vehicle_design_names; Index: src/gfx.h =================================================================== --- src/gfx.h (revision 11158) +++ src/gfx.h (working copy) @@ -268,6 +268,7 @@ void GfxFillRect(int left, int top, int right, int bottom, int color); void GfxDrawLine(int left, int top, int right, int bottom, int color); +void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); BoundingRect GetStringBoundingBox(const char *str); uint32 FormatStringLinebreaks(char *str, int maxw); Index: src/viewport.cpp =================================================================== --- src/viewport.cpp (revision 11158) +++ src/viewport.cpp (working copy) @@ -515,7 +515,7 @@ ViewportDrawer *vd = _cur_vd; ParentSpriteToDraw *ps; Point pt; - int32 right, bottom; + int32 left, right, top, bottom; assert((image & SPRITE_MASK) < MAX_SPRITES); @@ -552,22 +552,32 @@ pt = RemapCoords(x, y, z); ps->x = pt.x; ps->y = pt.y; + + /* Compute screen extents of sprite */ if (image == SPR_EMPTY_BOUNDING_BOX) { - ps->left = RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x; - right = RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x; - ps->top = RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y; - bottom = RemapCoords(x + w , y + h , z + bb_offset_z).y; + left = ps->left = RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x; + right = RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x + 1; + top = ps->top = RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y; + bottom = RemapCoords(x + w , y + h , z + bb_offset_z).y + 1; } else { const Sprite *spr = GetSprite(image & SPRITE_MASK); - ps->left = (pt.x += spr->x_offs); - right = (pt.x + spr->width ); - ps->top = (pt.y += spr->y_offs); - bottom = (pt.y + spr->height); + left = ps->left = (pt.x += spr->x_offs); + right = (pt.x + spr->width ); + top = ps->top = (pt.y += spr->y_offs); + bottom = (pt.y + spr->height); } - if (ps->left >= vd->dpi.left + vd->dpi.width || - right <= vd->dpi.left || - ps->top >= vd->dpi.top + vd->dpi.height || - bottom <= vd->dpi.top) { + if (_draw_bounding_boxes && (image != SPR_EMPTY_BOUNDING_BOX)) { + /* Compute maximal extents of sprite and it's bounding box */ + left = min(left , RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x); + right = max(right , RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x + 1); + top = min(top , RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y); + bottom = max(bottom, RemapCoords(x + w , y + h , z + bb_offset_z).y + 1); + } + /* Do not add the sprite to the viewport, if it is outside */ + if (left >= vd->dpi.left + vd->dpi.width || + right <= vd->dpi.left || + top >= vd->dpi.top + vd->dpi.height || + bottom <= vd->dpi.top) { return; } @@ -616,6 +626,7 @@ } cs = (ChildScreenSpriteToDraw*)vd->spritelist_mem; + /* If the ParentSprite was clipped by the viewport bounds, do not draw the ChildSprites either */ if (vd->last_child == NULL) return; vd->spritelist_mem += sizeof(ChildScreenSpriteToDraw); @@ -1232,6 +1243,26 @@ } } +/** + * Draws the bounding boxes of all ParentSprites + * @param psd Array of ParentSprites + */ +static void ViewportDrawBoundingBoxes(ParentSpriteToDraw *psd[]) +{ + for (; *psd != NULL; psd++) { + const ParentSpriteToDraw* ps = *psd; + Point pt1 = RemapCoords(ps->xmax + 1, ps->ymax + 1, ps->zmax + 1); // top front corner + Point pt2 = RemapCoords(ps->xmin , ps->ymax + 1, ps->zmax + 1); // top left corner + Point pt3 = RemapCoords(ps->xmax + 1, ps->ymin , ps->zmax + 1); // top right corner + Point pt4 = RemapCoords(ps->xmax + 1, ps->ymax + 1, ps->zmin ); // bottom front corner + + DrawBox( pt1.x, pt1.y, + pt2.x - pt1.x, pt2.y - pt1.y, + pt3.x - pt1.x, pt3.y - pt1.y, + pt4.x - pt1.x, pt4.y - pt1.y); + } +} + static void ViewportDrawStrings(DrawPixelInfo *dpi, const StringSpriteToDraw *ss) { DrawPixelInfo dp; @@ -1355,6 +1386,7 @@ ViewportSortParentSprites(parent_list); ViewportDrawParentSprites(parent_list); + if (_draw_bounding_boxes) ViewportDrawBoundingBoxes(parent_list); if (vd.first_string != NULL) ViewportDrawStrings(&vd.dpi, vd.first_string); Index: src/gfx.cpp =================================================================== --- src/gfx.cpp (revision 11158) +++ src/gfx.cpp (working copy) @@ -139,7 +139,51 @@ blitter->DrawLine(dpi->dst_ptr, x, y, x2, y2, dpi->width, dpi->height, color); } +/** + * Draws the projection of a parallelepiped. + * This can be used to draw boxes in world coordinates. + * + * @param x Screen X-coordinate of top front corner. + * @param y Screen Y-coordinate of top front corner. + * @param dx1 Screen X-length of first edge. + * @param dy1 Screen Y-length of first edge. + * @param dx2 Screen X-length of second edge. + * @param dy2 Screen Y-length of second edge. + * @param dx3 Screen X-length of third edge. + * @param dy3 Screen Y-length of third edge. + */ +void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3) +{ + /* .... + * .. .... + * .. .... + * .. ^ + * <--__(dx1,dy1) /(dx2,dy2) + * : --__ / : + * : --__ / : + * : *(x,y) : + * : | : + * : | .. + * .... |(dx3,dy3) + * .... | .. + * ....V. + */ + static const byte color = 255; + + GfxDrawLine(x, y, x + dx1, y + dy1, color); + GfxDrawLine(x, y, x + dx2, y + dy2, color); + GfxDrawLine(x, y, x + dx3, y + dy3, color); + + GfxDrawLine(x + dx1, y + dy1, x + dx1 + dx2, y + dy1 + dy2, color); + GfxDrawLine(x + dx1, y + dy1, x + dx1 + dx3, y + dy1 + dy3, color); + GfxDrawLine(x + dx2, y + dy2, x + dx2 + dx1, y + dy2 + dy1, color); + GfxDrawLine(x + dx2, y + dy2, x + dx2 + dx3, y + dy2 + dy3, color); + GfxDrawLine(x + dx3, y + dy3, x + dx3 + dx1, y + dy3 + dy1, color); + GfxDrawLine(x + dx3, y + dy3, x + dx3 + dx2, y + dy3 + dy2, color); +} + + /** Truncate a given string to a maximum width if neccessary. * If the string is truncated, add three dots ('...') to show this. * @param *str string that is checked and possibly truncated Index: src/main_gui.cpp =================================================================== --- src/main_gui.cpp (revision 11158) +++ src/main_gui.cpp (working copy) @@ -59,7 +59,9 @@ extern void GenerateIndustries(); extern bool GenerateTowns(); +bool _draw_bounding_boxes = false; + void CcGiveMoney(bool success, TileIndex tile, uint32 p1, uint32 p2) { #ifdef ENABLE_NETWORK @@ -2208,6 +2210,13 @@ break; } + if (e->we.keypress.keycode == ('B' | WKC_CTRL)) { + e->we.keypress.cont = false; + _draw_bounding_boxes = !_draw_bounding_boxes; + MarkWholeScreenDirty(); + break; + } + if (_game_mode == GM_MENU) break; switch (e->we.keypress.keycode) {