467 *vd->last_tile = ts; |
466 *vd->last_tile = ts; |
468 vd->last_tile = &ts->next; |
467 vd->last_tile = &ts->next; |
469 } |
468 } |
470 |
469 |
471 /** |
470 /** |
|
471 * Adds a child sprite to the active foundation. |
|
472 * |
|
473 * The pixel offset of the sprite relative to the ParentSprite is the sum of the offset passed to OffsetGroundSprite() and extra_offs_?. |
|
474 * |
|
475 * @param image the image to draw. |
|
476 * @param pal the provided palette. |
|
477 * @param sub Only draw a part of the sprite. |
|
478 * @param extra_offs_x Pixel X offset for the sprite position. |
|
479 * @param extra_offs_y Pixel Y offset for the sprite position. |
|
480 */ |
|
481 static void AddChildSpriteToFoundation(SpriteID image, SpriteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y) |
|
482 { |
|
483 ViewportDrawer *vd = _cur_vd; |
|
484 assert(vd->foundation != NULL); |
|
485 Point offs = vd->foundation_offset; |
|
486 |
|
487 /* Change the active ChildSprite list to the one of the foundation */ |
|
488 ChildScreenSpriteToDraw **old_child = vd->last_child; |
|
489 vd->last_child = vd->last_foundation_child; |
|
490 |
|
491 AddChildSpriteScreen(image, pal, offs.x + extra_offs_x, offs.y + extra_offs_y, false, sub); |
|
492 |
|
493 /* Switch back to last ChildSprite list */ |
|
494 vd->last_child = old_child; |
|
495 } |
|
496 |
|
497 /** |
472 * Draws a ground sprite for the current tile. |
498 * Draws a ground sprite for the current tile. |
473 * If the current tile is drawn on top of a foundation the sprite is added as child sprite to the "foundation"-ParentSprite. |
499 * If the current tile is drawn on top of a foundation the sprite is added as child sprite to the "foundation"-ParentSprite. |
474 * |
500 * |
475 * @param image the image to draw. |
501 * @param image the image to draw. |
476 * @param pal the provided palette. |
502 * @param pal the provided palette. |
477 * @param sub Only draw a part of the sprite. |
503 * @param sub Only draw a part of the sprite. |
478 */ |
504 */ |
479 void DrawGroundSprite(SpriteID image, SpriteID pal, const SubSprite *sub) |
505 void DrawGroundSprite(SpriteID image, SpriteID pal, const SubSprite *sub) |
480 { |
506 { |
481 if (_offset_ground_sprites) { |
507 ViewportDrawer *vd = _cur_vd; |
482 /* offset ground sprite because of foundation? */ |
508 if (vd->foundation != NULL) { |
483 AddChildSpriteScreen(image, pal, _cur_vd->offs_x, _cur_vd->offs_y, false, sub); |
509 AddChildSpriteToFoundation(image, pal, sub, 0, 0); |
484 } else { |
510 } else { |
485 _added_tile_sprite = true; |
|
486 DrawGroundSpriteAt(image, pal, _cur_ti->x, _cur_ti->y, _cur_ti->z, sub); |
511 DrawGroundSpriteAt(image, pal, _cur_ti->x, _cur_ti->y, _cur_ti->z, sub); |
487 } |
512 } |
488 } |
513 } |
489 |
514 |
490 |
515 |
|
516 /** |
|
517 * Called when a foundation has been drawn for the current tile. |
|
518 * Successive ground sprites for the current tile will be drawn as child sprites of the "foundation"-ParentSprite, not as TileSprites. |
|
519 * |
|
520 * @param x sprite x-offset (screen coordinates) of ground sprites relative to the "foundation"-ParentSprite. |
|
521 * @param y sprite y-offset (screen coordinates) of ground sprites relative to the "foundation"-ParentSprite. |
|
522 */ |
491 void OffsetGroundSprite(int x, int y) |
523 void OffsetGroundSprite(int x, int y) |
492 { |
524 { |
493 _cur_vd->offs_x = x; |
525 ViewportDrawer *vd = _cur_vd; |
494 _cur_vd->offs_y = y; |
526 assert(vd->foundation == NULL); |
495 _offset_ground_sprites = true; |
527 |
|
528 /* vd->last_child == NULL if foundation sprite was clipped by the viewport bounds */ |
|
529 if (vd->last_child != NULL) vd->foundation = vd->parent_list[-1]; |
|
530 |
|
531 vd->foundation_offset.x = x; |
|
532 vd->foundation_offset.y = y; |
|
533 vd->last_foundation_child = vd->last_child; |
496 } |
534 } |
497 |
535 |
498 /** |
536 /** |
499 * Adds a child sprite to a parent sprite. |
537 * Adds a child sprite to a parent sprite. |
500 * In contrast to "AddChildSpriteScreen()" the sprite position is in world coordinates |
538 * In contrast to "AddChildSpriteScreen()" the sprite position is in world coordinates |
721 |
762 |
722 return ss; |
763 return ss; |
723 } |
764 } |
724 |
765 |
725 |
766 |
726 static void DrawSelectionSprite(SpriteID image, SpriteID pal, const TileInfo *ti) |
767 /** |
727 { |
768 * Draws sprites between ground sprite and everything above. |
728 if (_added_tile_sprite && !(_thd.drawstyle & HT_LINE)) { // draw on real ground |
769 * |
729 DrawGroundSpriteAt(image, pal, ti->x, ti->y, ti->z + 7); |
770 * The sprite is either drawn as TileSprite or as ChildSprite of the active foundation. |
730 } else { // draw on top of foundation |
771 * |
731 AddSortableSpriteToDraw(image, pal, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7); |
772 * @param image the image to draw. |
|
773 * @param pal the provided palette. |
|
774 * @param ti TileInfo Tile that is being drawn |
|
775 * @param z_offset Z offset relative to the groundsprite. Only used for the sprite position, not for sprite sorting. |
|
776 */ |
|
777 static void DrawSelectionSprite(SpriteID image, SpriteID pal, const TileInfo *ti, int z_offset) |
|
778 { |
|
779 /* FIXME: This is not totally valid for some autorail highlights, that extent over the edges of the tile. */ |
|
780 if (_cur_vd->foundation == NULL) { |
|
781 /* draw on real ground */ |
|
782 DrawGroundSpriteAt(image, pal, ti->x, ti->y, ti->z + z_offset); |
|
783 } else { |
|
784 /* draw on top of foundation */ |
|
785 AddChildSpriteToFoundation(image, pal, NULL, 0, -z_offset); |
732 } |
786 } |
733 } |
787 } |
734 |
788 |
735 /** |
789 /** |
736 * Draws a selection rectangle on a tile. |
790 * Draws a selection rectangle on a tile. |
738 * @param ti TileInfo Tile that is being drawn |
792 * @param ti TileInfo Tile that is being drawn |
739 * @param pal Palette to apply. |
793 * @param pal Palette to apply. |
740 */ |
794 */ |
741 static void DrawTileSelectionRect(const TileInfo *ti, SpriteID pal) |
795 static void DrawTileSelectionRect(const TileInfo *ti, SpriteID pal) |
742 { |
796 { |
743 DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], pal, ti); |
797 DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], pal, ti, 7); |
744 } |
798 } |
745 |
799 |
746 static bool IsPartOfAutoLine(int px, int py) |
800 static bool IsPartOfAutoLine(int px, int py) |
747 { |
801 { |
748 px -= _thd.selstart.x; |
802 px -= _thd.selstart.x; |
819 IS_INSIDE_1D(ti->y, _thd.pos.y, _thd.size.y)) { |
873 IS_INSIDE_1D(ti->y, _thd.pos.y, _thd.size.y)) { |
820 if (_thd.drawstyle & HT_RECT) { |
874 if (_thd.drawstyle & HT_RECT) { |
821 DrawTileSelectionRect(ti, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE); |
875 DrawTileSelectionRect(ti, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE); |
822 } else if (_thd.drawstyle & HT_POINT) { |
876 } else if (_thd.drawstyle & HT_POINT) { |
823 /* Figure out the Z coordinate for the single dot. */ |
877 /* Figure out the Z coordinate for the single dot. */ |
824 byte z = ti->z; |
878 byte z = 0; |
825 if (ti->tileh & SLOPE_N) { |
879 if (ti->tileh & SLOPE_N) { |
826 z += TILE_HEIGHT; |
880 z += TILE_HEIGHT; |
827 if (ti->tileh == SLOPE_STEEP_N) z += TILE_HEIGHT; |
881 if (ti->tileh == SLOPE_STEEP_N) z += TILE_HEIGHT; |
828 } |
882 } |
829 DrawGroundSpriteAt(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti->x, ti->y, z); |
883 DrawSelectionSprite(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti, z); |
830 } else if (_thd.drawstyle & HT_RAIL /*&& _thd.place_mode == VHM_RAIL*/) { |
884 } else if (_thd.drawstyle & HT_RAIL /*&& _thd.place_mode == VHM_RAIL*/) { |
831 /* autorail highlight piece under cursor */ |
885 /* autorail highlight piece under cursor */ |
832 uint type = _thd.drawstyle & 0xF; |
886 uint type = _thd.drawstyle & 0xF; |
833 assert(type <= 5); |
887 assert(type <= 5); |
834 DrawAutorailSelection(ti, _AutorailType[type][0]); |
888 DrawAutorailSelection(ti, _AutorailType[type][0]); |