Exemple #1
0
/** This function Draws the Window on the Output Screen */
void Window::DrawWindow()
{
	if (!Visible) return; // no point in drawing invisible windows
	Video* video = core->GetVideoDriver();
	Region clip( XPos, YPos, Width, Height );
	//Frame && Changed
	if ( (Flags & (WF_FRAME|WF_CHANGED) ) == (WF_FRAME|WF_CHANGED) ) {
		Region screen( 0, 0, core->Width, core->Height );
		video->SetScreenClip( NULL );
		//removed this?
		video->DrawRect( screen, ColorBlack );
		if (core->WindowFrames[0])
			video->BlitSprite( core->WindowFrames[0], 0, 0, true );
		if (core->WindowFrames[1])
			video->BlitSprite( core->WindowFrames[1], core->Width - core->WindowFrames[1]->Width, 0, true );
		if (core->WindowFrames[2])
			video->BlitSprite( core->WindowFrames[2], (core->Width - core->WindowFrames[2]->Width) / 2, 0, true );
		if (core->WindowFrames[3])
			video->BlitSprite( core->WindowFrames[3], (core->Width - core->WindowFrames[3]->Width) / 2, core->Height - core->WindowFrames[3]->Height, true );
	}

	video->SetScreenClip( &clip );
	//Float || Changed
	bool bgRefreshed = false;
	if (BackGround && (Flags & (WF_FLOAT|WF_CHANGED) ) ) {
		DrawBackground(NULL);
		bgRefreshed = true;
	}

	std::vector< Control*>::iterator m;
	for (m = Controls.begin(); m != Controls.end(); ++m) {
		Control* c = *m;
		// FIXME: drawing BG in the same loop as controls can produce incorrect results with overlapping controls. the only case I know of this occuring it is ok due to no BG drawing
		// furthermore, overlapping controls are still a problem when NeedsDraw() returns false for the top control, but true for the bottom (see the level up icon on char portraits)
		// we will fix both issues later by refactoring with the concept of views and subviews
		if (BackGround && !bgRefreshed && !c->IsOpaque() && c->NeedsDraw()) {
			const Region& fromClip = c->ControlFrame();
			DrawBackground(&fromClip);
		}
		if (Flags & (WF_FLOAT)) {
			// FIXME: this is a total hack. Required for anything drawing over GameControl (nothing really at all to do with floating)
			c->MarkDirty();
		}
		c->Draw( XPos, YPos );
	}
	if ( (Flags&WF_CHANGED) && (Visible == WINDOW_GRAYED) ) {
		Color black = { 0, 0, 0, 128 };
		video->DrawRect(clip, black);
	}
	video->SetScreenClip( NULL );
	Flags &= ~WF_CHANGED;
}
/** This function Draws the Window on the Output Screen */
void Window::DrawWindow()
{
	Video* video = core->GetVideoDriver();
	Region clip( XPos, YPos, Width, Height );
	//Frame && Changed
	if ( (Flags & (WF_FRAME|WF_CHANGED) )== (WF_FRAME|WF_CHANGED) ) {
		Region screen( 0, 0, core->Width, core->Height );
		video->SetClipRect( NULL );
		//removed this?
		Color black = { 0, 0, 0, 255 };
		video->DrawRect( screen, black );
		if (core->WindowFrames[0])
			video->BlitSprite( core->WindowFrames[0], 0, 0, true );
		if (core->WindowFrames[1])
			video->BlitSprite( core->WindowFrames[1], core->Width - core->WindowFrames[1]->Width, 0, true );
		if (core->WindowFrames[2])
			video->BlitSprite( core->WindowFrames[2], (core->Width - core->WindowFrames[2]->Width) / 2, 0, true );
		if (core->WindowFrames[3])
			video->BlitSprite( core->WindowFrames[3], (core->Width - core->WindowFrames[3]->Width) / 2, core->Height - core->WindowFrames[3]->Height, true );
	} else if (clip_regions.size()) {
		// clip drawing (we only do Background right now) for InvalidateForControl
		for (unsigned int i = 0; i < clip_regions.size(); i++) {
			Region to_clip = clip_regions[i];
			to_clip.x += XPos;
			to_clip.y += YPos;
			video->SetClipRect(&to_clip);
			if (BackGround) {
				video->BlitSprite( BackGround, XPos, YPos, true );
			}
		}
	}
	clip_regions.clear();
	video->SetClipRect( &clip );
	//Float || Changed
	if (BackGround && (Flags & (WF_FLOAT|WF_CHANGED) ) ) {
		video->BlitSprite( BackGround, XPos, YPos, true );
	}
	std::vector< Control*>::iterator m;
	for (m = Controls.begin(); m != Controls.end(); ++m) {
		( *m )->Draw( XPos, YPos );
	}
	if ( (Flags&WF_CHANGED) && (Visible == WINDOW_GRAYED) ) {
		Color black = { 0, 0, 0, 128 };
		video->DrawRect(clip, black);
	}
	video->SetClipRect( NULL );
	Flags &= ~WF_CHANGED;
}
// Draw fog on the small bitmap
void MapControl::DrawFog(unsigned short XWin, unsigned short YWin)
{
	Video *video = core->GetVideoDriver();

	Region old_clip;
	video->GetClipRect(old_clip);

	Region r( XWin + XPos, YWin + YPos, Width, Height );
	video->SetClipRect(&r);

	// FIXME: this is ugly, the knowledge of Map and ExploredMask
	//   sizes should be in Map.cpp
	int w = MyMap->GetWidth() / 2;
	int h = MyMap->GetHeight() / 2;

	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			Point p( (short) (MAP_MULT * x), (short) (MAP_MULT * y) );
			bool visible = MyMap->IsVisible( p, true );
			if (! visible) {
				Region rgn = Region ( MAP_TO_SCREENX(MAP_DIV * x), MAP_TO_SCREENY(MAP_DIV * y), MAP_DIV, MAP_DIV );
				video->DrawRect( rgn, colors[black] );
			}
		}
	}

	video->SetClipRect(&old_clip);
}
Exemple #4
0
/** Draws the Control on the Output Display */
void TextEdit::DrawInternal(Region& rgn)
{
	ieWord yOff = FontPosY;
	ieWord xOff = FontPosX;

	Video* video = core->GetVideoDriver();
	if (Back) {
		// FIXME: temporary hack for PST map labels.
		// once subviews branch is merged this is not needed
		video->DrawRect(rgn, ColorBlack);
		video->BlitSprite( Back, rgn.x, rgn.y, true );
		xOff += Back->XPos;
		yOff += Back->YPos;
	} else if (Text != L"") {
		// FIXME: temporary hack for PST map labels.
		// once subviews branch is merged this is not needed
		video->DrawRect(rgn, ColorBlack);
	}
	if (!font) {
		// no font was specified; happens with cheat input edits
		return;
	}

	//The aligning of textedit fields is done by absolute positioning (FontPosX, FontPosY)
	font->Print( Region( rgn.x + xOff, rgn.y + yOff, Width, Height ),
				 Text, palette, Alignment );

	if (hasFocus) {
		int w = font->StringSize(Text.substr(0, CurPos)).w;
		ieWord vcenter = (rgn.h / 2) + (Cursor->Height / 2);
		if (w > rgn.w) {
			int rows = (w / rgn.w);
			vcenter += rows * font->LineHeight;
			w = w - (rgn.w * rows);
		}
		video->BlitSprite(Cursor, w + rgn.x + xOff,
						  yOff + vcenter + rgn.y, true);
	}
}
Exemple #5
0
void Picture::Draw( int relx, int rely ){
	// DEBUG lines to see the difference between the Picture and the Image.
	Video* vid = Video::Instance();
	// The Picture size
	vid->DrawRect( GetX()+relx, GetY()+rely,
					w,h,
					color.r,color.g,color.b,alpha );
	/*
	// The Image
	if(bitmap!=NULL)
	vid->DrawRect( GetX()+relx+w/2 - bitmap->GetWidth()/2, GetY()+rely+h/2 - bitmap->GetHeight()/2,
					bitmap->GetWidth(), bitmap->GetHeight(),
					1.0,1.0,1.0,0.1 );
	*/
	if(bitmap!=NULL)
		bitmap->DrawFit( this->x+relx, this->y+rely, w, h, static_cast<float>(rotation));
}
Exemple #6
0
/** Draws the Control on the Output Display */
void Button::DrawInternal(Region& rgn)
{
	Video * video = core->GetVideoDriver();

	// Button image
	if (!( Flags & IE_GUI_BUTTON_NO_IMAGE )) {
		Sprite2D* Image = NULL;

		switch (State) {
			case IE_GUI_BUTTON_UNPRESSED:
			case IE_GUI_BUTTON_LOCKED:
			case IE_GUI_BUTTON_LOCKED_PRESSED:
				Image = buttonImages[BUTTON_IMAGE_UNPRESSED];
				break;
			case IE_GUI_BUTTON_FAKEPRESSED:
			case IE_GUI_BUTTON_PRESSED:
				Image = buttonImages[BUTTON_IMAGE_PRESSED];
				break;
			case IE_GUI_BUTTON_SELECTED:
				Image = buttonImages[BUTTON_IMAGE_SELECTED];
				break;
			case IE_GUI_BUTTON_DISABLED:
			case IE_GUI_BUTTON_FAKEDISABLED:
				Image = buttonImages[BUTTON_IMAGE_DISABLED];
				break;
		}
		if (!Image) {
			Image = buttonImages[BUTTON_IMAGE_UNPRESSED];
		}
		if (Image) {
			// FIXME: maybe it's useless...
			int xOffs = ( Width / 2 ) - ( Image->Width / 2 );
			int yOffs = ( Height / 2 ) - ( Image->Height / 2 );

			video->BlitSprite( Image, rgn.x + xOffs, rgn.y + yOffs, true );
		}
	}

	if (State == IE_GUI_BUTTON_PRESSED) {
		//shift the writing/border a bit
		rgn.x += PushOffset.x;
		rgn.y += PushOffset.y;
	}

	// Button picture
	if (AnimPicture) {
		int xOffs = ( Width / 2 ) - ( AnimPicture->Width / 2 );
		int yOffs = ( Height / 2 ) - ( AnimPicture->Height / 2 );
		Region r( rgn.x + xOffs, rgn.y + yOffs, (int)(AnimPicture->Width * Clipping), AnimPicture->Height );

		if (Flags & IE_GUI_BUTTON_CENTER_PICTURES) {
			video->BlitSprite( AnimPicture, rgn.x + xOffs + AnimPicture->XPos, rgn.y + yOffs + AnimPicture->YPos, true, &r );
		} else {
			video->BlitSprite( AnimPicture, rgn.x + xOffs, rgn.y + yOffs, true, &r );
		}
	}

	// Button picture
	int picXPos = 0, picYPos = 0;
	if (Picture && (Flags & IE_GUI_BUTTON_PICTURE) ) {
		// Picture is drawn centered
		picXPos = ( rgn.w / 2 ) - ( Picture->Width / 2 ) + rgn.x;
		picYPos = ( rgn.h / 2 ) - ( Picture->Height / 2 ) + rgn.y;
		if (Flags & IE_GUI_BUTTON_HORIZONTAL) {
			picXPos += Picture->XPos;
			picYPos += Picture->YPos;

			// Clipping: 0 = overlay over full button, 1 = no overlay
			int overlayHeight = Picture->Height * (1.0 - Clipping);
			if (overlayHeight < 0)
				overlayHeight = 0;
			if (overlayHeight >= Picture->Height)
				overlayHeight = Picture->Height;
			int buttonHeight = Picture->Height - overlayHeight;

			Region rb = Region(picXPos, picYPos, Picture->Width, buttonHeight);
			Region ro = Region(picXPos, picYPos + buttonHeight, Picture->Width, overlayHeight);

			video->BlitSprite( Picture, picXPos, picYPos, true, &rb );

			// TODO: Add an option to add BLIT_GREY to the flags
			video->BlitGameSprite( Picture, picXPos, picYPos, BLIT_TINTED, SourceRGB, 0, 0, &ro, true);

			// do NOT uncomment this, you can't change Changed or invalidate things from
			// the middle of Window::DrawWindow() -- it needs moving to somewhere else
			//CloseUpColor();
		}
		else {
			Region r( picXPos, picYPos, (int)(Picture->Width * Clipping), Picture->Height );
			video->BlitSprite( Picture, picXPos + Picture->XPos, picYPos + Picture->YPos, true, &r );
		}
	}

	// Composite pictures (paperdolls/description icons)
	if (!PictureList.empty() && (Flags & IE_GUI_BUTTON_PICTURE) ) {
		std::list<Sprite2D*>::iterator iter = PictureList.begin();
		int xOffs = 0, yOffs = 0;
		if (Flags & IE_GUI_BUTTON_CENTER_PICTURES) {
			// Center the hotspots of all pictures
			xOffs = Width/2;
			yOffs = Height/2;
		} else if (Flags & IE_GUI_BUTTON_BG1_PAPERDOLL) {
			// Display as-is
			xOffs = 0;
			yOffs = 0;
		} else {
			// Center the first picture, and align the rest to that
			xOffs = Width/2 - (*iter)->Width/2 + (*iter)->XPos;
			yOffs = Height/2 - (*iter)->Height/2 + (*iter)->YPos;
		}

		for (; iter != PictureList.end(); ++iter) {
			video->BlitSprite( *iter, rgn.x + xOffs, rgn.y + yOffs, true );
		}
	}

	// Button label
	if (hasText && ! ( Flags & IE_GUI_BUTTON_NO_TEXT )) {
		Palette* ppoi = normal_palette;
		int align = 0;

		if (State == IE_GUI_BUTTON_DISABLED)
			ppoi = disabled_palette;
		// FIXME: hopefully there's no button which sinks when selected
		//   AND has text label
		//else if (State == IE_GUI_BUTTON_PRESSED || State == IE_GUI_BUTTON_SELECTED) {

		if (Flags & IE_GUI_BUTTON_ALIGN_LEFT)
			align |= IE_FONT_ALIGN_LEFT;
		else if (Flags & IE_GUI_BUTTON_ALIGN_RIGHT)
			align |= IE_FONT_ALIGN_RIGHT;
		else
			align |= IE_FONT_ALIGN_CENTER;

		if (Flags & IE_GUI_BUTTON_ALIGN_TOP)
			align |= IE_FONT_ALIGN_TOP;
		else if (Flags & IE_GUI_BUTTON_ALIGN_BOTTOM)
			align |= IE_FONT_ALIGN_BOTTOM;
		else
			align |= IE_FONT_ALIGN_MIDDLE;

		if (! (Flags & IE_GUI_BUTTON_MULTILINE)) {
			align |= IE_FONT_SINGLE_LINE;
		}

		Region r;
		if (Picture && (Flags & IE_GUI_BUTTON_PORTRAIT) == IE_GUI_BUTTON_PORTRAIT) {
			// constrain the label (status icons) to the picture bounds
			// FIXME: we are subtracting IE_FONT_PADDING because Font indents 5px, but we dont want that here
			r = Region(picXPos - IE_FONT_PADDING, picYPos + IE_FONT_PADDING,
					   Picture->Width + IE_FONT_PADDING, Picture->Height);
		} else {
			r = Region( rgn.x, rgn.y, rgn.w - 2, rgn.h - 2);
		}

		font->Print( r, ( unsigned char * ) Text, ppoi, (ieByte) align, true );
	}

	if (! (Flags&IE_GUI_BUTTON_NO_IMAGE)) {
		for (int i = 0; i < MAX_NUM_BORDERS; i++) {
			ButtonBorder *fr = &borders[i];
			if (! fr->enabled) continue;

			Region r = Region( rgn.x + fr->dx1, rgn.y + fr->dy1, rgn.w - (fr->dx1 + fr->dx2 + 1), rgn.h - (fr->dy1 + fr->dy2 + 1) );
			video->DrawRect( r, fr->color, fr->filled );
		}
	}
}
/** 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 );
			}
		}
	}
}
/** Draws the Control on the Output Display */
void Button::Draw(unsigned short x, unsigned short y)
{
	if (!Changed && !(Owner->Flags&WF_FLOAT) ) {
		return;
	}
	Changed = false;
	if (XPos == 65535 || Width == 0) {
		return;
	}

	Video * video = core->GetVideoDriver();

	// Button image
	if (!( Flags & IE_GUI_BUTTON_NO_IMAGE )) {
		Sprite2D* Image = NULL;

		switch (State) {
			case IE_GUI_BUTTON_UNPRESSED:
			case IE_GUI_BUTTON_LOCKED:
			case IE_GUI_BUTTON_LOCKED_PRESSED:
				Image = Unpressed;
				break;

			case IE_GUI_BUTTON_SECOND:
			case IE_GUI_BUTTON_PRESSED:
				Image = Pressed;
				if (! Image)
					Image = Unpressed;
				break;

			case IE_GUI_BUTTON_SELECTED:
				Image = Selected;
				if (! Image)
					Image = Unpressed;
				break;

			case IE_GUI_BUTTON_DISABLED:
			case IE_GUI_BUTTON_THIRD:
				Image = Disabled;
				if (! Image)
					Image = Unpressed;
				break;
		}
		if (Image) {
			// FIXME: maybe it's useless...
			int xOffs = ( Width / 2 ) - ( Image->Width / 2 );
			int yOffs = ( Height / 2 ) - ( Image->Height / 2 );

			video->BlitSprite( Image, x + XPos + xOffs, y + YPos + yOffs, true );
		}
	}

	if (State == IE_GUI_BUTTON_PRESSED) {
		//shift the writing/border a bit
		x+= 2;
		y+= 2;
	}

	// Button picture
	if (Picture  && (Flags & IE_GUI_BUTTON_PICTURE) ) {
		// Picture is drawn centered
		int xOffs = ( Width / 2 ) - ( Picture->Width / 2 );
		int yOffs = ( Height / 2 ) - ( Picture->Height / 2 );
		if (Flags & IE_GUI_BUTTON_HORIZONTAL) {
			xOffs += x + XPos + Picture->XPos;
			yOffs += y + YPos + Picture->YPos;
			video->BlitSprite( Picture, xOffs, yOffs, true );
			Region r = Region( xOffs, yOffs + (int) (Picture->Height * Clipping), Picture->Width, (int) (Picture->Height*(1.0 - Clipping)) );
			video->DrawRect( r, SourceRGB, true );
			// do NOT uncomment this, you can't change Changed or invalidate things from
			// the middle of Window::DrawWindow() -- it needs moving to somewhere else
			//CloseUpColor();
		}
		else {
			Region r( x + XPos + xOffs, y + YPos + yOffs, (int)(Picture->Width * Clipping), Picture->Height );
			video->BlitSprite( Picture, x + XPos + xOffs + Picture->XPos, y + YPos + yOffs + Picture->YPos, true, &r );
		}
	}

	// Composite pictures (paperdolls/description icons)
	if (!PictureList.empty() && (Flags & IE_GUI_BUTTON_PICTURE) ) {
		std::list<Sprite2D*>::iterator iter = PictureList.begin();
		int xOffs = 0, yOffs = 0;
		if (Flags & IE_GUI_BUTTON_CENTER_PICTURES) {
			// Center the hotspots of all pictures
			xOffs = Width/2;
			yOffs = Height/2;
		} else if (Flags & IE_GUI_BUTTON_BG1_PAPERDOLL) {
			// Display as-is
			xOffs = 0;
			yOffs = 0;
		} else {
			// Center the first picture, and align the rest to that
			xOffs = Width/2 - (*iter)->Width/2 + (*iter)->XPos;
			yOffs = Height/2 - (*iter)->Height/2 + (*iter)->YPos;
		}

		for (; iter != PictureList.end(); ++iter) {
			video->BlitSprite( *iter, x + XPos + xOffs, y + YPos + yOffs, true );
		}
	}

	// Button picture
	if (AnimPicture) {
		int xOffs = ( Width / 2 ) - ( AnimPicture->Width / 2 );
		int yOffs = ( Height / 2 ) - ( AnimPicture->Height / 2 );
		Region r( x + XPos + xOffs, y + YPos + yOffs, (int)(AnimPicture->Width * Clipping), AnimPicture->Height );

		if (Flags & IE_GUI_BUTTON_CENTER_PICTURES) {
			video->BlitSprite( AnimPicture, x + XPos + xOffs + AnimPicture->XPos, y + YPos + yOffs + AnimPicture->YPos, true, &r );
		} else {
			video->BlitSprite( AnimPicture, x + XPos + xOffs, y + YPos + yOffs, true, &r );
		}
	}

	// Button label
	if (hasText && ! ( Flags & IE_GUI_BUTTON_NO_TEXT )) {
		Palette* ppoi = normal_palette;
		int align = 0;

		if (State == IE_GUI_BUTTON_DISABLED)
			ppoi = disabled_palette;
		// FIXME: hopefully there's no button which sinks when selected
		//   AND has text label
		//else if (State == IE_GUI_BUTTON_PRESSED || State == IE_GUI_BUTTON_SELECTED) {

		if (Flags & IE_GUI_BUTTON_ALIGN_LEFT)
			align |= IE_FONT_ALIGN_LEFT;
		else if (Flags & IE_GUI_BUTTON_ALIGN_RIGHT)
			align |= IE_FONT_ALIGN_RIGHT;
		else
			align |= IE_FONT_ALIGN_CENTER;

		if (Flags & IE_GUI_BUTTON_ALIGN_TOP)
			align |= IE_FONT_ALIGN_TOP;
		else if (Flags & IE_GUI_BUTTON_ALIGN_BOTTOM)
			align |= IE_FONT_ALIGN_BOTTOM;
		else
			align |= IE_FONT_ALIGN_MIDDLE;

		if (! (Flags & IE_GUI_BUTTON_MULTILINE)) {
			align |= IE_FONT_SINGLE_LINE;
		}
		font->Print( Region( x + XPos, y + YPos, Width - 2, Height - 2),
			( unsigned char * ) Text, ppoi,
			(ieByte) align, true );
	}

	if (! (Flags&IE_GUI_BUTTON_NO_IMAGE)) {
		for (int i = 0; i < MAX_NUM_BORDERS; i++) {
			ButtonBorder *fr = &borders[i];
			if (! fr->enabled) continue;

			Region r = Region( x + XPos + fr->dx1, y + YPos + fr->dy1, Width - (fr->dx1 + fr->dx2 + 1), Height - (fr->dy1 + fr->dy2 + 1) );
			video->DrawRect( r, fr->color, fr->filled );
		}
	}
}
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;
				}
			}
		}
	}
}