void TileOverlay::Draw(Region viewport, std::vector< TileOverlay*> &overlays)
{
	Video* vid = core->GetVideoDriver();
	Region vp = vid->GetViewport();

	// if the video's viewport is partially outside of the map, bump it back
	BumpViewport(viewport, vp);
	// determine which tiles are visible
	int sx = vp.x / 64;
	int sy = vp.y / 64;
	int dx = ( vp.x + vp.w + 63 ) / 64;
	int dy = ( vp.y + vp.h + 63 ) / 64;

	for (int y = sy; y < dy && y < h; y++) {
		for (int x = sx; x < dx && x < w; x++) {
			Tile* tile = tiles[( y* w ) + x];

			//draw door tiles if there are any
			Animation* anim = tile->anim[tile->tileIndex];
			if (!anim && tile->tileIndex) {
				anim = tile->anim[0];
			}
			vid->BlitTile( anim->NextFrame(), 0, viewport.x + ( x * 64 ),
				viewport.y + ( y * 64 ), &viewport, false );
			if (!tile->om || tile->tileIndex) {
				continue;
			}

			//draw overlay tiles, they should be half transparent
			int mask = 2;
			for (size_t z = 1;z<overlays.size();z++) {
				TileOverlay * ov = overlays[z];
				if (ov && ov->count > 0) {
					Tile *ovtile = ov->tiles[0]; //allow only 1x1 tiles now
					if (tile->om & mask) {
						if (RedrawTile) {
							vid->BlitTile( ovtile->anim[0]->NextFrame(),
						                   tile->anim[0]->NextFrame(),
							               viewport.x + ( x * 64 ),
							               viewport.y + ( y * 64 ),
							               &viewport, false );
						} else {
							Sprite2D* mask = 0;
							if (tile->anim[1])
								mask = tile->anim[1]->NextFrame();
							vid->BlitTile( ovtile->anim[0]->NextFrame(),
						                   mask,
							               viewport.x + ( x * 64 ),
							               viewport.y + ( y * 64 ),
							               &viewport, true );
						}
					}
				}
				mask<<=1;
			}
		}
	}
}
/** Draws the Control on the Output Display */
void MapControl::Draw(unsigned short XWin, unsigned short YWin)
{
	if (!Width || !Height) {
		return;
	}
	if (Owner->Visible!=WINDOW_VISIBLE) {
		return;
	}

	if (Changed) {
		Realize();
		Changed = false;
	}

	// we're going to paint over labels/etc, so they need to repaint!
	bool seen_this = false;
	unsigned int i;
	for (i = 0; i < Owner->GetControlCount(); i++) {
		Control *ctrl = Owner->GetControl(i);
		if (!ctrl) continue;

		// we could try working out which controls overlap,
		// but the later controls are cheap to paint..
		if (ctrl == this) { seen_this = true; continue; }
		if (!seen_this) continue;

		ctrl->Changed = true;
	}

	Video* video = core->GetVideoDriver();
	Region r( XWin + XPos, YWin + YPos, Width, Height );

	if (MapMOS) {
		video->BlitSprite( MapMOS, MAP_TO_SCREENX(0), MAP_TO_SCREENY(0), true, &r );
	}

	if (core->FogOfWar&FOG_DRAWFOG)
		DrawFog(XWin, YWin);

	Region vp = video->GetViewport();

	vp.x = GAME_TO_SCREENX(vp.x);
	vp.y = GAME_TO_SCREENY(vp.y);
	vp.w = ViewWidth;
	vp.h = ViewHeight;

	if ((vp.x + vp.w) >= MAP_TO_SCREENX( Width ))
		vp.w = MAP_TO_SCREENX( Width ) - vp.x;
	if ((vp.y + vp.h) >= MAP_TO_SCREENY( Height ))
		vp.h = MAP_TO_SCREENY( Height ) - vp.y;

	video->DrawRect( vp, colors[green], false, false );

	// Draw PCs' ellipses
	Game *game = core->GetGame();
	i = game->GetPartySize(true);
	while (i--) {
		Actor* actor = game->GetPC( i, true );
		if (MyMap->HasActor(actor) ) {
			video->DrawEllipse( (short) GAME_TO_SCREENX(actor->Pos.x), (short) GAME_TO_SCREENY(actor->Pos.y), 3, 2, actor->Selected ? colors[green] : colors[darkgreen], false );
		}
	}
	// Draw Map notes, could be turned off in bg2
	// we use the common control value to handle it, because then we
	// don't need another interface
	if (Value!=MAP_NO_NOTES) {
		i = MyMap -> GetMapNoteCount();
		while (i--) {
			MapNote * mn = MyMap -> GetMapNote(i);
			Sprite2D *anim = Flag[mn->color&7];
			Point pos = mn->Pos;
			if (convertToGame) {
				vp.x = GAME_TO_SCREENX(mn->Pos.x);
				vp.y = GAME_TO_SCREENY(mn->Pos.y);
			} else { //pst style
				vp.x = MAP_TO_SCREENX(mn->Pos.x);
				vp.y = MAP_TO_SCREENY(mn->Pos.y);
				pos.x = pos.x * MAP_MULT / MAP_DIV;
				pos.y = pos.y * MAP_MULT / MAP_DIV;
			}

			//Skip unexplored map notes
			bool visible = MyMap->IsVisible( pos, true );
			if (!visible)
				continue;

			if (anim) {
				video->BlitSprite( anim, vp.x - anim->Width/2, vp.y - anim->Height/2, true, &r );
			} else {
				video->DrawEllipse( (short) vp.x, (short) vp.y, 6, 5, colors[mn->color&7], false );
			}
		}
	}
}
void TileMap::DrawFogOfWar(ieByte* explored_mask, ieByte* visible_mask, Region viewport)
{
	// viewport - pos & size of the control
	int w = XCellCount * CELL_RATIO;
	int h = YCellCount * CELL_RATIO;
	if (LargeMap) {
		w++;
		h++;
	}
	Color black = { 0, 0, 0, 255 };

	Video* vid = core->GetVideoDriver();
	Region vp = vid->GetViewport();

	vp.w = viewport.w;
	vp.h = viewport.h;
	if (( vp.x + vp.w ) > w * CELL_SIZE) {
		vp.x = ( w * CELL_SIZE - vp.w );
	}
	if (vp.x < 0) {
		vp.x = 0;
	}
	if (( vp.y + vp.h ) > h * CELL_SIZE) {
		vp.y = ( h * CELL_SIZE - vp.h );
	}
	if (vp.y < 0) {
		vp.y = 0;
	}
	int sx = ( vp.x ) / CELL_SIZE;
	int sy = ( vp.y ) / CELL_SIZE;
	int dx = sx + vp.w / CELL_SIZE + 2;
	int dy = sy + vp.h / CELL_SIZE + 2;
	int x0 = sx * CELL_SIZE - vp.x;
	int y0 = sy * CELL_SIZE - vp.y;
	if (LargeMap) {
		x0 -= CELL_SIZE / 2;
		y0 -= CELL_SIZE / 2;
		dx++;
		dy++;
	}
	for (int y = sy; y < dy && y < h; y++) {
		for (int x = sx; x < dx && x < w; x++) {
			Region r = Region(x0 + viewport.x + ( (x - sx) * CELL_SIZE ), y0 + viewport.y + ( (y - sy) * CELL_SIZE ), CELL_SIZE, CELL_SIZE);
			if (! IS_EXPLORED( x, y )) {
				// Unexplored tiles are all black
				vid->DrawRect(r, black, true, true);
				continue;  // Don't draw 'invisible' fog
			}
			else {
				// If an explored tile is adjacent to an
				//   unexplored one, we draw border sprite
				//   (gradient black <-> transparent)
				// Tiles in four cardinal directions have these
				//   values.
				//
				//      1
				//    2   8
				//      4
				//
				// Values of those unexplored are
				//   added together, the resulting number being
				//   an index of shadow sprite to use. For now,
				//   some tiles are made 'on the fly' by
				//   drawing two or more tiles

				int e = ! IS_EXPLORED( x, y - 1);
				if (! IS_EXPLORED( x - 1, y )) e |= 2;
				if (! IS_EXPLORED( x, y + 1 )) e |= 4;
				if (! IS_EXPLORED( x + 1, y )) e |= 8;

				switch (e) {
				case 1:
				case 2:
				case 3:
				case 4:
				case 6:
				case 8:
				case 9:
				case 12:
					FOG( e );
					break;
				case 5:
					FOG( 1 );
					FOG( 4 );
					break;
				case 7:
					FOG( 3 );
					FOG( 6 );
					break;
				case 10:
					FOG( 2 );
					FOG( 8 );
					break;
				case 11:
					FOG( 3 );
					FOG( 9 );
					break;
				case 13:
					FOG( 9 );
					FOG( 12 );
					break;
				case 14:
					FOG( 6 );
					FOG( 12 );
					break;
				case 15: //this is black too
					vid->DrawRect(r, black, true, true);
					break;
				}
			}

			if (! IS_VISIBLE( x, y )) {
				// Invisible tiles are all gray
				FOG( 16 );
				continue;  // Don't draw 'invisible' fog
			}
			else {
				// If a visible tile is adjacent to an
				//   invisible one, we draw border sprite
				//   (gradient gray <-> transparent)
				// Tiles in four cardinal directions have these
				//   values.
				//
				//      1
				//    2   8
				//      4
				//
				// Values of those invisible are
				//   added together, the resulting number being
				//   an index of shadow sprite to use. For now,
				//   some tiles are made 'on the fly' by
				//   drawing two or more tiles

				int e = ! IS_VISIBLE( x, y - 1);
				if (! IS_VISIBLE( x - 1, y )) e |= 2;
				if (! IS_VISIBLE( x, y + 1 )) e |= 4;
				if (! IS_VISIBLE( x + 1, y )) e |= 8;

				switch (e) {
				case 1:
				case 2:
				case 3:
				case 4:
				case 6:
				case 8:
				case 9:
				case 12:
					FOG( 16 + e );
					break;
				case 5:
					FOG( 16 + 1 );
					FOG( 16 + 4 );
					break;
				case 7:
					FOG( 16 + 3 );
					FOG( 16 + 6 );
					break;
				case 10:
					FOG( 16 + 2 );
					FOG( 16 + 8 );
					break;
				case 11:
					FOG( 16 + 3 );
					FOG( 16 + 9 );
					break;
				case 13:
					FOG( 16 + 9 );
					FOG( 16 + 12 );
					break;
				case 14:
					FOG( 16 + 6 );
					FOG( 16 + 12 );
					break;
				case 15: //this is unseen too
					FOG( 16 );
					break;
				}
			}
		}
	}
}