src/viewport.cpp
changeset 7726 a9c8beebf2c1
parent 7681 582e8912e8d1
child 7764 e594296e90f6
equal deleted inserted replaced
7725:a44140f11d8a 7726:a9c8beebf2c1
    34 /* XXX - maximum viewports is maximum windows - 2 (main toolbar + status bar) */
    34 /* XXX - maximum viewports is maximum windows - 2 (main toolbar + status bar) */
    35 static ViewPort _viewports[25 - 2];
    35 static ViewPort _viewports[25 - 2];
    36 static uint32 _active_viewports;    ///< bitmasked variable where each bit signifies if a viewport is in use or not
    36 static uint32 _active_viewports;    ///< bitmasked variable where each bit signifies if a viewport is in use or not
    37 assert_compile(lengthof(_viewports) < sizeof(_active_viewports) * 8);
    37 assert_compile(lengthof(_viewports) < sizeof(_active_viewports) * 8);
    38 
    38 
    39 static bool _added_tile_sprite;
       
    40 static bool _offset_ground_sprites;
       
    41 
       
    42 /* The in-game coordiante system looks like this *
    39 /* The in-game coordiante system looks like this *
    43  *                                               *
    40  *                                               *
    44  *                    ^ Z                        *
    41  *                    ^ Z                        *
    45  *                    |                          *
    42  *                    |                          *
    46  *                    |                          *
    43  *                    |                          *
   126 	ParentSpriteToDraw **parent_list;
   123 	ParentSpriteToDraw **parent_list;
   127 	ParentSpriteToDraw * const *eof_parent_list;
   124 	ParentSpriteToDraw * const *eof_parent_list;
   128 
   125 
   129 	byte combine_sprites;
   126 	byte combine_sprites;
   130 
   127 
   131 	int offs_x, offs_y; // used when drawing ground sprites relative
   128 	ParentSpriteToDraw *foundation;                      ///< Foundation sprite.
       
   129 	ChildScreenSpriteToDraw **last_foundation_child;     ///< Tail of ChildSprite list of active foundation.
       
   130 	Point foundation_offset;                             ///< Pixeloffset of ground sprites on the foundation.
   132 };
   131 };
   133 
   132 
   134 static ViewportDrawer *_cur_vd;
   133 static ViewportDrawer *_cur_vd;
   135 
   134 
   136 TileHighlightData _thd;
   135 TileHighlightData _thd;
   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
   681 	/* If the ParentSprite was clipped by the viewport bounds, do not draw the ChildSprites either */
   719 	/* If the ParentSprite was clipped by the viewport bounds, do not draw the ChildSprites either */
   682 	if (vd->last_child == NULL) return;
   720 	if (vd->last_child == NULL) return;
   683 
   721 
   684 	vd->spritelist_mem += sizeof(ChildScreenSpriteToDraw);
   722 	vd->spritelist_mem += sizeof(ChildScreenSpriteToDraw);
   685 
   723 
       
   724 	/* Append the sprite to the active ChildSprite list.
       
   725 	 * If the active ParentSprite is a foundation, update last_foundation_child as well. */
   686 	*vd->last_child = cs;
   726 	*vd->last_child = cs;
       
   727 	if (vd->last_foundation_child == vd->last_child) vd->last_foundation_child = &cs->next;
   687 	vd->last_child = &cs->next;
   728 	vd->last_child = &cs->next;
   688 
   729 
   689 	cs->image = image;
   730 	cs->image = image;
   690 	cs->pal = pal;
   731 	cs->pal = pal;
   691 	cs->sub = sub;
   732 	cs->sub = sub;
   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;
   794 	} else {
   848 	} else {
   795 		image = SPR_AUTORAIL_BASE - offset;
   849 		image = SPR_AUTORAIL_BASE - offset;
   796 		pal = PALETTE_SEL_TILE_RED;
   850 		pal = PALETTE_SEL_TILE_RED;
   797 	}
   851 	}
   798 
   852 
   799 	DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti);
   853 	DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti, 7);
   800 }
   854 }
   801 
   855 
   802 /**
   856 /**
   803  * Checks if the specified tile is selected and if so draws selection using correct selectionstyle.
   857  * Checks if the specified tile is selected and if so draws selection using correct selectionstyle.
   804  * @param *ti TileInfo Tile that is being drawn
   858  * @param *ti TileInfo Tile that is being drawn
   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]);
   911 			}
   965 			}
   912 
   966 
   913 			y_cur += 0x10;
   967 			y_cur += 0x10;
   914 			x_cur -= 0x10;
   968 			x_cur -= 0x10;
   915 
   969 
   916 			_added_tile_sprite = false;
   970 			vd->foundation = NULL;
   917 			_offset_ground_sprites = false;
   971 			vd->last_foundation_child = NULL;
   918 
   972 
   919 			_tile_type_procs[tt]->draw_tile_proc(&ti);
   973 			_tile_type_procs[tt]->draw_tile_proc(&ti);
   920 			DrawTileSelection(&ti);
   974 			DrawTileSelection(&ti);
   921 		} while (--width_cur);
   975 		} while (--width_cur);
   922 
   976