src/viewport.cpp
changeset 5919 2b58160d667d
parent 5853 df216f54532c
child 5924 077448ca4bf2
equal deleted inserted replaced
5918:602e158900a2 5919:2b58160d667d
    55 	uint32 params[2];
    55 	uint32 params[2];
    56 	uint16 width;
    56 	uint16 width;
    57 } StringSpriteToDraw;
    57 } StringSpriteToDraw;
    58 
    58 
    59 typedef struct TileSpriteToDraw {
    59 typedef struct TileSpriteToDraw {
    60 	uint32 image;
    60 	SpriteID image;
       
    61 	SpriteID pal;
    61 	struct TileSpriteToDraw *next;
    62 	struct TileSpriteToDraw *next;
    62 	int32 x;
    63 	int32 x;
    63 	int32 y;
    64 	int32 y;
    64 	byte z;
    65 	byte z;
    65 } TileSpriteToDraw;
    66 } TileSpriteToDraw;
    66 
    67 
    67 typedef struct ChildScreenSpriteToDraw {
    68 typedef struct ChildScreenSpriteToDraw {
    68 	uint32 image;
    69 	SpriteID image;
       
    70 	SpriteID pal;
    69 	int32 x;
    71 	int32 x;
    70 	int32 y;
    72 	int32 y;
    71 	struct ChildScreenSpriteToDraw *next;
    73 	struct ChildScreenSpriteToDraw *next;
    72 } ChildScreenSpriteToDraw;
    74 } ChildScreenSpriteToDraw;
    73 
    75 
    74 typedef struct ParentSpriteToDraw {
    76 typedef struct ParentSpriteToDraw {
    75 	uint32 image;
    77 	SpriteID image;
       
    78 	SpriteID pal;
    76 	int32 left;
    79 	int32 left;
    77 	int32 top;
    80 	int32 top;
    78 	int32 right;
    81 	int32 right;
    79 	int32 bottom;
    82 	int32 bottom;
    80 	int32 xmin;
    83 	int32 xmin;
   404 
   407 
   405 	SetWindowWidgetDisabledState(w, widget_zoom_out, vp->zoom == 2);
   408 	SetWindowWidgetDisabledState(w, widget_zoom_out, vp->zoom == 2);
   406 	InvalidateWidget(w, widget_zoom_out);
   409 	InvalidateWidget(w, widget_zoom_out);
   407 }
   410 }
   408 
   411 
   409 void DrawGroundSpriteAt(uint32 image, int32 x, int32 y, byte z)
   412 void DrawGroundSpriteAt(SpriteID image, SpriteID pal, int32 x, int32 y, byte z)
   410 {
   413 {
   411 	ViewportDrawer *vd = _cur_vd;
   414 	ViewportDrawer *vd = _cur_vd;
   412 	TileSpriteToDraw *ts;
   415 	TileSpriteToDraw *ts;
   413 
   416 
   414 	assert((image & SPRITE_MASK) < MAX_SPRITES);
   417 	assert((image & SPRITE_MASK) < MAX_SPRITES);
   420 	ts = (TileSpriteToDraw*)vd->spritelist_mem;
   423 	ts = (TileSpriteToDraw*)vd->spritelist_mem;
   421 
   424 
   422 	vd->spritelist_mem += sizeof(TileSpriteToDraw);
   425 	vd->spritelist_mem += sizeof(TileSpriteToDraw);
   423 
   426 
   424 	ts->image = image;
   427 	ts->image = image;
       
   428 	ts->pal = pal;
   425 	ts->next = NULL;
   429 	ts->next = NULL;
   426 	ts->x = x;
   430 	ts->x = x;
   427 	ts->y = y;
   431 	ts->y = y;
   428 	ts->z = z;
   432 	ts->z = z;
   429 	*vd->last_tile = ts;
   433 	*vd->last_tile = ts;
   430 	vd->last_tile = &ts->next;
   434 	vd->last_tile = &ts->next;
   431 }
   435 }
   432 
   436 
   433 void DrawGroundSprite(uint32 image)
   437 void DrawGroundSprite(SpriteID image, SpriteID pal)
   434 {
   438 {
   435 	if (_offset_ground_sprites) {
   439 	if (_offset_ground_sprites) {
   436 		// offset ground sprite because of foundation?
   440 		// offset ground sprite because of foundation?
   437 		AddChildSpriteScreen(image, _cur_vd->offs_x, _cur_vd->offs_y);
   441 		AddChildSpriteScreen(image, pal, _cur_vd->offs_x, _cur_vd->offs_y);
   438 	} else {
   442 	} else {
   439 		_added_tile_sprite = true;
   443 		_added_tile_sprite = true;
   440 		DrawGroundSpriteAt(image, _cur_ti->x, _cur_ti->y, _cur_ti->z);
   444 		DrawGroundSpriteAt(image, pal, _cur_ti->x, _cur_ti->y, _cur_ti->z);
   441 	}
   445 	}
   442 }
   446 }
   443 
   447 
   444 
   448 
   445 void OffsetGroundSprite(int x, int y)
   449 void OffsetGroundSprite(int x, int y)
   447 	_cur_vd->offs_x = x;
   451 	_cur_vd->offs_x = x;
   448 	_cur_vd->offs_y = y;
   452 	_cur_vd->offs_y = y;
   449 	_offset_ground_sprites = true;
   453 	_offset_ground_sprites = true;
   450 }
   454 }
   451 
   455 
   452 static void AddCombinedSprite(uint32 image, int x, int y, byte z)
   456 static void AddCombinedSprite(SpriteID image, SpriteID pal, int x, int y, byte z)
   453 {
   457 {
   454 	const ViewportDrawer *vd = _cur_vd;
   458 	const ViewportDrawer *vd = _cur_vd;
   455 	Point pt = RemapCoords(x, y, z);
   459 	Point pt = RemapCoords(x, y, z);
   456 	const Sprite* spr = GetSprite(image & SPRITE_MASK);
   460 	const Sprite* spr = GetSprite(image & SPRITE_MASK);
   457 
   461 
   459 			pt.x + spr->x_offs + spr->width <= vd->dpi.left ||
   463 			pt.x + spr->x_offs + spr->width <= vd->dpi.left ||
   460 			pt.y + spr->y_offs >= vd->dpi.top + vd->dpi.height ||
   464 			pt.y + spr->y_offs >= vd->dpi.top + vd->dpi.height ||
   461 			pt.y + spr->y_offs + spr->height <= vd->dpi.top)
   465 			pt.y + spr->y_offs + spr->height <= vd->dpi.top)
   462 		return;
   466 		return;
   463 
   467 
   464 	AddChildSpriteScreen(image, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top);
   468 	AddChildSpriteScreen(image, pal, pt.x - vd->parent_list[-1]->left, pt.y - vd->parent_list[-1]->top);
   465 }
   469 }
   466 
   470 
   467 
   471 
   468 void AddSortableSpriteToDraw(uint32 image, int x, int y, int w, int h, byte dz, byte z)
   472 void AddSortableSpriteToDraw(SpriteID image, SpriteID pal, int x, int y, int w, int h, byte dz, byte z)
   469 {
   473 {
   470 	ViewportDrawer *vd = _cur_vd;
   474 	ViewportDrawer *vd = _cur_vd;
   471 	ParentSpriteToDraw *ps;
   475 	ParentSpriteToDraw *ps;
   472 	const Sprite *spr;
   476 	const Sprite *spr;
   473 	Point pt;
   477 	Point pt;
   474 
   478 
   475 	assert((image & SPRITE_MASK) < MAX_SPRITES);
   479 	assert((image & SPRITE_MASK) < MAX_SPRITES);
   476 
   480 
   477 	if (vd->combine_sprites == 2) {
   481 	if (vd->combine_sprites == 2) {
   478 		AddCombinedSprite(image, x, y, z);
   482 		AddCombinedSprite(image, pal, x, y, z);
   479 		return;
   483 		return;
   480 	}
   484 	}
   481 
   485 
   482 	vd->last_child = NULL;
   486 	vd->last_child = NULL;
   483 
   487 
   508 	}
   512 	}
   509 
   513 
   510 	vd->spritelist_mem += sizeof(ParentSpriteToDraw);
   514 	vd->spritelist_mem += sizeof(ParentSpriteToDraw);
   511 
   515 
   512 	ps->image = image;
   516 	ps->image = image;
       
   517 	ps->pal = pal;
   513 	ps->xmin = x;
   518 	ps->xmin = x;
   514 	ps->xmax = x + w - 1;
   519 	ps->xmax = x + w - 1;
   515 
   520 
   516 	ps->ymin = y;
   521 	ps->ymin = y;
   517 	ps->ymax = y + h - 1;
   522 	ps->ymax = y + h - 1;
   536 void EndSpriteCombine(void)
   541 void EndSpriteCombine(void)
   537 {
   542 {
   538 	_cur_vd->combine_sprites = 0;
   543 	_cur_vd->combine_sprites = 0;
   539 }
   544 }
   540 
   545 
   541 void AddChildSpriteScreen(uint32 image, int x, int y)
   546 void AddChildSpriteScreen(SpriteID image, SpriteID pal, int x, int y)
   542 {
   547 {
   543 	ViewportDrawer *vd = _cur_vd;
   548 	ViewportDrawer *vd = _cur_vd;
   544 	ChildScreenSpriteToDraw *cs;
   549 	ChildScreenSpriteToDraw *cs;
   545 
   550 
   546 	assert((image & SPRITE_MASK) < MAX_SPRITES);
   551 	assert((image & SPRITE_MASK) < MAX_SPRITES);
   557 
   562 
   558 	*vd->last_child = cs;
   563 	*vd->last_child = cs;
   559 	vd->last_child = &cs->next;
   564 	vd->last_child = &cs->next;
   560 
   565 
   561 	cs->image = image;
   566 	cs->image = image;
       
   567 	cs->pal = pal;
   562 	cs->x = x;
   568 	cs->x = x;
   563 	cs->y = y;
   569 	cs->y = y;
   564 	cs->next = NULL;
   570 	cs->next = NULL;
   565 }
   571 }
   566 
   572 
   591 
   597 
   592 	return ss;
   598 	return ss;
   593 }
   599 }
   594 
   600 
   595 
   601 
   596 static void DrawSelectionSprite(uint32 image, const TileInfo *ti)
   602 static void DrawSelectionSprite(SpriteID image, SpriteID pal, const TileInfo *ti)
   597 {
   603 {
   598 	if (_added_tile_sprite && !(_thd.drawstyle & HT_LINE)) { // draw on real ground
   604 	if (_added_tile_sprite && !(_thd.drawstyle & HT_LINE)) { // draw on real ground
   599 		DrawGroundSpriteAt(image, ti->x, ti->y, ti->z + 7);
   605 		DrawGroundSpriteAt(image, pal, ti->x, ti->y, ti->z + 7);
   600 	} else { // draw on top of foundation
   606 	} else { // draw on top of foundation
   601 		AddSortableSpriteToDraw(image, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
   607 		AddSortableSpriteToDraw(image, pal, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
   602 	}
   608 	}
   603 }
   609 }
   604 
   610 
   605 static bool IsPartOfAutoLine(int px, int py)
   611 static bool IsPartOfAutoLine(int px, int py)
   606 {
   612 {
   634 
   640 
   635 #include "table/autorail.h"
   641 #include "table/autorail.h"
   636 
   642 
   637 static void DrawTileSelection(const TileInfo *ti)
   643 static void DrawTileSelection(const TileInfo *ti)
   638 {
   644 {
   639 	uint32 image;
   645 	SpriteID image;
       
   646 	SpriteID pal;
   640 
   647 
   641 	// Draw a red error square?
   648 	// Draw a red error square?
   642 	if (_thd.redsq != 0 && _thd.redsq == ti->tile) {
   649 	if (_thd.redsq != 0 && _thd.redsq == ti->tile) {
   643 		DrawSelectionSprite(PALETTE_TILE_RED_PULSATING | (SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh]), ti);
   650 		DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], PALETTE_TILE_RED_PULSATING, ti);
   644 		return;
   651 		return;
   645 	}
   652 	}
   646 
   653 
   647 	// no selection active?
   654 	// no selection active?
   648 	if (_thd.drawstyle == 0) return;
   655 	if (_thd.drawstyle == 0) return;
   650 	// Inside the inner area?
   657 	// Inside the inner area?
   651 	if (IS_INSIDE_1D(ti->x, _thd.pos.x, _thd.size.x) &&
   658 	if (IS_INSIDE_1D(ti->x, _thd.pos.x, _thd.size.x) &&
   652 			IS_INSIDE_1D(ti->y, _thd.pos.y, _thd.size.y)) {
   659 			IS_INSIDE_1D(ti->y, _thd.pos.y, _thd.size.y)) {
   653 		if (_thd.drawstyle & HT_RECT) {
   660 		if (_thd.drawstyle & HT_RECT) {
   654 			image = SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh];
   661 			image = SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh];
   655 			if (_thd.make_square_red) image |= PALETTE_SEL_TILE_RED;
   662 			DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : PAL_NONE, ti);
   656 			DrawSelectionSprite(image, ti);
       
   657 		} else if (_thd.drawstyle & HT_POINT) {
   663 		} else if (_thd.drawstyle & HT_POINT) {
   658 			// Figure out the Z coordinate for the single dot.
   664 			// Figure out the Z coordinate for the single dot.
   659 			byte z = ti->z;
   665 			byte z = ti->z;
   660 			if (ti->tileh & SLOPE_N) {
   666 			if (ti->tileh & SLOPE_N) {
   661 				z += TILE_HEIGHT;
   667 				z += TILE_HEIGHT;
   662 				if (ti->tileh == SLOPE_STEEP_N) z += TILE_HEIGHT;
   668 				if (ti->tileh == SLOPE_STEEP_N) z += TILE_HEIGHT;
   663 			}
   669 			}
   664 			DrawGroundSpriteAt(_cur_dpi->zoom != 2 ? SPR_DOT : SPR_DOT_SMALL, ti->x, ti->y, z);
   670 			DrawGroundSpriteAt(_cur_dpi->zoom != 2 ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti->x, ti->y, z);
   665 		} else if (_thd.drawstyle & HT_RAIL /*&& _thd.place_mode == VHM_RAIL*/) {
   671 		} else if (_thd.drawstyle & HT_RAIL /*&& _thd.place_mode == VHM_RAIL*/) {
   666 			// autorail highlight piece under cursor
   672 			// autorail highlight piece under cursor
   667 			uint type = _thd.drawstyle & 0xF;
   673 			uint type = _thd.drawstyle & 0xF;
       
   674 			int offset;
       
   675 
   668 			assert(type <= 5);
   676 			assert(type <= 5);
   669 			image = SPR_AUTORAIL_BASE + _AutorailTilehSprite[ti->tileh][_AutorailType[type][0]];
   677 
   670 
   678 			offset = _AutorailTilehSprite[ti->tileh][_AutorailType[type][0]];
   671 			if (_thd.make_square_red) image |= PALETTE_SEL_TILE_RED;
   679 			if (offset >= 0) {
   672 			DrawSelectionSprite(image, ti);
   680 				image = SPR_AUTORAIL_BASE + offset;
       
   681 				pal = PAL_NONE;
       
   682 			} else {
       
   683 				image = SPR_AUTORAIL_BASE - offset;
       
   684 				pal = PALETTE_TO_RED;
       
   685 			}
       
   686 
       
   687 			DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti);
   673 
   688 
   674 		} else if (IsPartOfAutoLine(ti->x, ti->y)) {
   689 		} else if (IsPartOfAutoLine(ti->x, ti->y)) {
   675 			// autorail highlighting long line
   690 			// autorail highlighting long line
   676 			int dir = _thd.drawstyle & ~0xF0;
   691 			int dir = _thd.drawstyle & ~0xF0;
       
   692 			int offset;
   677 			uint side;
   693 			uint side;
   678 
   694 
   679 			if (dir < 2) {
   695 			if (dir < 2) {
   680 				side = 0;
   696 				side = 0;
   681 			} else {
   697 			} else {
   682 				TileIndex start = TileVirtXY(_thd.selstart.x, _thd.selstart.y);
   698 				TileIndex start = TileVirtXY(_thd.selstart.x, _thd.selstart.y);
   683 				side = delta(delta(TileX(start), TileX(ti->tile)), delta(TileY(start), TileY(ti->tile)));
   699 				side = delta(delta(TileX(start), TileX(ti->tile)), delta(TileY(start), TileY(ti->tile)));
   684 			}
   700 			}
   685 
   701 
   686 			image = SPR_AUTORAIL_BASE + _AutorailTilehSprite[ti->tileh][_AutorailType[dir][side]];
   702 			offset = _AutorailTilehSprite[ti->tileh][_AutorailType[dir][side]];
   687 
   703 			if (offset >= 0) {
   688 			if (_thd.make_square_red) image |= PALETTE_SEL_TILE_RED;
   704 				image = SPR_AUTORAIL_BASE + offset;
   689 			DrawSelectionSprite(image, ti);
   705 				pal = PAL_NONE;
       
   706 			} else {
       
   707 				image = SPR_AUTORAIL_BASE - offset;
       
   708 				pal = PALETTE_TO_RED;
       
   709 			}
       
   710 
       
   711 			DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti);
   690 		}
   712 		}
   691 		return;
   713 		return;
   692 	}
   714 	}
   693 
   715 
   694 	// Check if it's inside the outer area?
   716 	// Check if it's inside the outer area?
   695 	if (_thd.outersize.x &&
   717 	if (_thd.outersize.x &&
   696 			_thd.size.x < _thd.size.x + _thd.outersize.x &&
   718 			_thd.size.x < _thd.size.x + _thd.outersize.x &&
   697 			IS_INSIDE_1D(ti->x, _thd.pos.x + _thd.offs.x, _thd.size.x + _thd.outersize.x) &&
   719 			IS_INSIDE_1D(ti->x, _thd.pos.x + _thd.offs.x, _thd.size.x + _thd.outersize.x) &&
   698 			IS_INSIDE_1D(ti->y, _thd.pos.y + _thd.offs.y, _thd.size.y + _thd.outersize.y)) {
   720 			IS_INSIDE_1D(ti->y, _thd.pos.y + _thd.offs.y, _thd.size.y + _thd.outersize.y)) {
   699 		// Draw a blue rect.
   721 		// Draw a blue rect.
   700 		DrawSelectionSprite(PALETTE_SEL_TILE_BLUE | (SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh]), ti);
   722 		DrawSelectionSprite(SPR_SELECT_TILE + _tileh_to_sprite[ti->tileh], PALETTE_SEL_TILE_BLUE, ti);
   701 		return;
   723 		return;
   702 	}
   724 	}
   703 }
   725 }
   704 
   726 
   705 static void ViewportAddLandscape(void)
   727 static void ViewportAddLandscape(void)
  1054 
  1076 
  1055 static void ViewportDrawTileSprites(TileSpriteToDraw *ts)
  1077 static void ViewportDrawTileSprites(TileSpriteToDraw *ts)
  1056 {
  1078 {
  1057 	do {
  1079 	do {
  1058 		Point pt = RemapCoords(ts->x, ts->y, ts->z);
  1080 		Point pt = RemapCoords(ts->x, ts->y, ts->z);
  1059 		DrawSprite(ts->image, pt.x, pt.y);
  1081 		DrawSprite(ts->image, ts->pal, pt.x, pt.y);
  1060 		ts = ts->next;
  1082 		ts = ts->next;
  1061 	} while (ts != NULL);
  1083 	} while (ts != NULL);
  1062 }
  1084 }
  1063 
  1085 
  1064 static void ViewportSortParentSprites(ParentSpriteToDraw *psd[])
  1086 static void ViewportSortParentSprites(ParentSpriteToDraw *psd[])
  1126 	for (; *psd != NULL; psd++) {
  1148 	for (; *psd != NULL; psd++) {
  1127 		const ParentSpriteToDraw* ps = *psd;
  1149 		const ParentSpriteToDraw* ps = *psd;
  1128 		Point pt = RemapCoords(ps->xmin, ps->ymin, ps->zmin);
  1150 		Point pt = RemapCoords(ps->xmin, ps->ymin, ps->zmin);
  1129 		const ChildScreenSpriteToDraw* cs;
  1151 		const ChildScreenSpriteToDraw* cs;
  1130 
  1152 
  1131 		DrawSprite(ps->image, pt.x, pt.y);
  1153 		DrawSprite(ps->image, ps->pal, pt.x, pt.y);
  1132 
  1154 
  1133 		for (cs = ps->child; cs != NULL; cs = cs->next) {
  1155 		for (cs = ps->child; cs != NULL; cs = cs->next) {
  1134 			DrawSprite(cs->image, ps->left + cs->x, ps->top + cs->y);
  1156 			DrawSprite(cs->image, cs->pal, ps->left + cs->x, ps->top + cs->y);
  1135 		}
  1157 		}
  1136 	}
  1158 	}
  1137 }
  1159 }
  1138 
  1160 
  1139 static void ViewportDrawStrings(DrawPixelInfo *dpi, const StringSpriteToDraw *ss)
  1161 static void ViewportDrawStrings(DrawPixelInfo *dpi, const StringSpriteToDraw *ss)
  2410 	w->wndproc(w, &e);
  2432 	w->wndproc(w, &e);
  2411 
  2433 
  2412 	return false;
  2434 	return false;
  2413 }
  2435 }
  2414 
  2436 
  2415 void SetObjectToPlaceWnd(CursorID icon, byte mode, Window *w)
  2437 void SetObjectToPlaceWnd(CursorID icon, SpriteID pal, byte mode, Window *w)
  2416 {
  2438 {
  2417 	SetObjectToPlace(icon, mode, w->window_class, w->window_number);
  2439 	SetObjectToPlace(icon, pal, mode, w->window_class, w->window_number);
  2418 }
  2440 }
  2419 
  2441 
  2420 #include "table/animcursors.h"
  2442 #include "table/animcursors.h"
  2421 
  2443 
  2422 void SetObjectToPlace(CursorID icon, byte mode, WindowClass window_class, WindowNumber window_num)
  2444 void SetObjectToPlace(CursorID icon, SpriteID pal, byte mode, WindowClass window_class, WindowNumber window_num)
  2423 {
  2445 {
  2424 	Window *w;
  2446 	Window *w;
  2425 
  2447 
  2426 	// undo clicking on button
  2448 	// undo clicking on button
  2427 	if (_thd.place_mode != 0) {
  2449 	if (_thd.place_mode != 0) {
  2449 		VpStartPreSizing();
  2471 		VpStartPreSizing();
  2450 
  2472 
  2451 	if ( (int)icon < 0)
  2473 	if ( (int)icon < 0)
  2452 		SetAnimatedMouseCursor(_animcursors[~icon]);
  2474 		SetAnimatedMouseCursor(_animcursors[~icon]);
  2453 	else
  2475 	else
  2454 		SetMouseCursor(icon);
  2476 		SetMouseCursor(icon, pal);
  2455 }
  2477 }
  2456 
  2478 
  2457 void ResetObjectToPlace(void)
  2479 void ResetObjectToPlace(void)
  2458 {
  2480 {
  2459 	SetObjectToPlace(SPR_CURSOR_MOUSE, VHM_NONE, 0, 0);
  2481 	SetObjectToPlace(SPR_CURSOR_MOUSE, PAL_NONE, VHM_NONE, 0, 0);
  2460 }
  2482 }