Pārlūkot izejas kodu

* Reverted previously changed PreGame code
* Added the missing AB video resource file in linux code, AB campaign selection videos should now play BUT they don't => it seems that ffmpeg can't handle older BINK videos
* Fixed a visual glitch which could be seen at the WOG animation in the main menu on a linux machine
* Fixed the random crashes bug on mouse centering at startup on linux
* Fixed a visual bug at the bonus selection screen when starting a campaign-map
* Changed some positions in the bonus selection screen, no bonus pre selection, you cannot start the campaign when no bonus is selected (like in h3)
* Added a border functionality to the AdventureMapButton
* InfoWindow buttons and some other buttons have now the border which heroes 3 buttons have
* Fixed a app crash when you start a campaign two times in one session

beegee1 14 gadi atpakaļ
vecāks
revīzija
45fba15511

+ 1 - 0
StartInfo.h

@@ -93,6 +93,7 @@ struct StartInfo
 	StartInfo()
 	{
 		mode = INVALID;
+		choosenCampaignBonus = -1;
 	}
 };
 

+ 28 - 6
client/AdventureMapButton.cpp

@@ -107,7 +107,8 @@ void CButtonBase::block(bool on)
 
 AdventureMapButton::AdventureMapButton ()
 {
-	hoverable = actOnDown = false;
+	hoverable = actOnDown = borderEnabled = false;
+	borderColor.x = -1;
 	used = LCLICK | RCLICK | HOVER | KEYBOARD;
 }
 
@@ -208,7 +209,8 @@ void AdventureMapButton::init(const CFunctionList<void()> &Callback, const std::
 	currentImage = -1;
 	used = LCLICK | RCLICK | HOVER | KEYBOARD;
 	callback = Callback;
-	actOnDown = hoverable = false;
+	actOnDown = hoverable = borderEnabled = false;
+	borderColor.x = -1;
 	assignedKeys.insert(key);
 	hoverTexts = Name;
 	helpBox=HelpBox;
@@ -256,14 +258,34 @@ void AdventureMapButton::setPlayerColor(int player)
 	image->playerColored(player);
 }
 
-void CHighlightableButton::select(bool on)
+void AdventureMapButton::show(SDL_Surface *to)
 {
-	setState(on?HIGHLIGHTED:NORMAL);
+	showAll(to);
+}
+
+void AdventureMapButton::showAll(SDL_Surface *to)
+{
+	CIntObject::showAll(to);
 
-	if(on)
+	if (borderEnabled && borderColor.x >= 0)
+		CSDL_Ext::drawBorder(to, pos.x - 1, pos.y - 1, pos.w + 2, pos.h + 2, borderColor);
+}
+
+void CHighlightableButton::select(bool on)
+{
+	if (on)
+	{
+		setState(HIGHLIGHTED);
 		callback();
-	else 
+		borderEnabled = true;
+	}
+	else
+	{
+		setState(NORMAL);
 		callback2();
+		borderEnabled = false;
+	}
+	
 	if(hoverTexts.size()>1)
 	{
 		hover(false);

+ 5 - 1
client/AdventureMapButton.h

@@ -71,7 +71,9 @@ public:
 	std::string helpBox; //for right-click help
 	CFunctionList<void()> callback;
 	bool actOnDown,//runs when mouse is pressed down over it, not when up
-	     hoverable;//if true, button will be highlighted when hovered
+	     hoverable,//if true, button will be highlighted when hovered
+		 borderEnabled;
+	int3 borderColor;
 
 	void clickRight(tribool down, bool previousState);
 	virtual void clickLeft(tribool down, bool previousState);
@@ -87,6 +89,8 @@ public:
 	void setIndex(size_t index, bool playerColoredButton=false);
 	void setImage(CAnimation* anim, bool playerColoredButton=false);
 	void setPlayerColor(int player);
+	void show(SDL_Surface *to);
+	void showAll(SDL_Surface *to);
 };
 
 /// A button which can be selected/deselected

+ 2 - 0
client/CBattleInterface.cpp

@@ -3972,6 +3972,8 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect
 	SDL_FreeSurface(background);
 	background = pom;
 	exit = new AdventureMapButton (std::string(), std::string(), boost::bind(&CBattleResultWindow::bExitf,this), 384 + pos.x, 505 + pos.y, "iok6432.def", SDLK_RETURN);
+	exit->borderColor = int3(173, 142, 66);
+	exit->borderEnabled = true;
 
 	if(br.winner==0) //attacker won
 	{

+ 5 - 0
client/CCastleInterface.cpp

@@ -1477,8 +1477,13 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin
 	{
 		buy = new AdventureMapButton(boost::str(boost::format(CGI->generaltexth->allTexts[595]) % building->Name()),
 		          "", boost::bind(&CBuildWindow::buyFunc,this), 45, 446,"IBUY30", SDLK_RETURN);
+		buy->borderColor = int3(173, 142, 66);
+		buy->borderEnabled = true;
+		
 		cancel = new AdventureMapButton(boost::str(boost::format(CGI->generaltexth->allTexts[596]) % building->Name()),
 		             "", boost::bind(&CBuildWindow::close,this), 290, 445, "ICANCEL", SDLK_ESCAPE);
+		cancel->borderColor = int3(173, 142, 66);
+		cancel->borderEnabled = true;
 		buy->block(state!=7);
 	}
 }

+ 2 - 0
client/CCursorHandler.cpp

@@ -193,7 +193,9 @@ void CCursorHandler::centerCursor()
 	SDL_Surface *cursor = this->cursors[mode]->ourImages[number].bitmap;
 	this->xpos = (screen->w / 2.) - (cursor->w / 2.);
 	this->ypos = (screen->h / 2.) - (cursor->h / 2.);
+	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);	
 	SDL_WarpMouse(this->xpos, this->ypos);
+	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
 }
 
 CCursorHandler::~CCursorHandler()

+ 0 - 1
client/CPlayerInterface.cpp

@@ -1341,7 +1341,6 @@ void CPlayerInterface::update()
 		GH.drawFPSCounter();
 
 	// draw the mouse cursor and update the screen
-	// todo: bad way of updating the cursor, update screen should be the last statement of the rendering process
 	CCS->curh->draw1();
 	CSDL_Ext::update(screen);
 	CCS->curh->draw2();

+ 50 - 34
client/CPreGame.cpp

@@ -277,8 +277,7 @@ void CMenuScreen::showAll( SDL_Surface * to )
 
 void CMenuScreen::show( SDL_Surface * to )
 {
-	CIntObject::show(to);
-	//CCS->videoh->update(pos.x + 8, pos.y + 105, screen, true, false);
+	showAll(to);
 }
 
 void CMenuScreen::moveTo( CMenuScreen *next )
@@ -339,8 +338,6 @@ void CGPreGame::disposeGraphics()
 
 void CGPreGame::update()
 {
-	SDL_FillRect(screen, 0, 0);
-	
 	if (GH.listInt.size() == 0)
 	{
 		CCS->musich->playMusic(musicBase::mainMenu, -1);
@@ -358,14 +355,15 @@ void CGPreGame::update()
 	if (GH.curInt == 0) // no redraw, when a new game was created
 		return;
 
-	GH.totalRedraw();
+	GH.topInt()->show(screen);
 
 	if (conf.cc.showFPS)
 		GH.drawFPSCounter();
 
 	// draw the mouse cursor and update the screen
-	CCS->curh->draw(screen);
+	CCS->curh->draw1();
 	CSDL_Ext::update(screen);
+	CCS->curh->draw2();
 }
 
 CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMultiMode MultiPlayer /*= CMenuScreen::SINGLE_PLAYER*/, const std::map<ui32, std::string> *Names /*= NULL*/)
@@ -2616,6 +2614,7 @@ CBonusSelection::CBonusSelection( CCampaignState * _ourCampaign )
 
 	startB = new AdventureMapButton("", "", bind(&CBonusSelection::startMap, this), 475, 536, "CBBEGIB.DEF", SDLK_RETURN);
 	backB = new AdventureMapButton("", "", bind(&CBonusSelection::goBack, this), 624, 536, "CBCANCB.DEF", SDLK_ESCAPE);
+	startB->setState(CButtonBase::BLOCKED);
 
 	//campaign name
 	if (ourCampaign->camp->header.name.length())
@@ -2637,7 +2636,7 @@ CBonusSelection::CBonusSelection( CCampaignState * _ourCampaign )
 	mapDesc = new CTextBox("", Rect(480, 280, 286, 117), 1);
 
 	//bonus choosing
-	printAtMiddleLoc(CGI->generaltexth->allTexts[71], 562, 438, FONT_MEDIUM, zwykly, background); //Choose a bonus:
+	printAtLoc(CGI->generaltexth->allTexts[71], 511, 432, FONT_MEDIUM, zwykly, background); //Choose a bonus:
 	bonuses = new CHighlightableButtonsGroup(bind(&CBonusSelection::selectBonus, this, _1));
 
 	//set left part of window
@@ -2673,18 +2672,21 @@ CBonusSelection::CBonusSelection( CCampaignState * _ourCampaign )
 	SDL_FreeSurface(panel);
 
 	//difficulty
-	printAtMiddleLoc(CGI->generaltexth->allTexts[492], 715, 438, FONT_MEDIUM, zwykly, background); //Difficulty
-	{//difficulty pics
-		for (int b=0; b<ARRAY_COUNT(diffPics); ++b)
-		{
-			CDefEssential * cde = CDefHandler::giveDefEss("GSPBUT" + boost::lexical_cast<std::string>(b+3) + ".DEF");
-			SDL_Surface * surfToDuplicate = cde->ourImages[0].bitmap;
-			diffPics[b] = SDL_ConvertSurface(surfToDuplicate, surfToDuplicate->format,
-				surfToDuplicate->flags);
+	std::vector<std::string> difficulty;
+	boost::split(difficulty, CGI->generaltexth->allTexts[492], boost::is_any_of(" "));
+	printAtLoc(difficulty.back(), 689, 432, FONT_MEDIUM, zwykly, background); //Difficulty
+	
+	//difficulty pics
+	for (int b=0; b<ARRAY_COUNT(diffPics); ++b)
+	{
+		CDefEssential * cde = CDefHandler::giveDefEss("GSPBUT" + boost::lexical_cast<std::string>(b+3) + ".DEF");
+		SDL_Surface * surfToDuplicate = cde->ourImages[0].bitmap;
+		diffPics[b] = SDL_ConvertSurface(surfToDuplicate, surfToDuplicate->format,
+			surfToDuplicate->flags);
 
-			delete cde;
-		}
+		delete cde;
 	}
+	
 	//difficulty selection buttons
 	if (ourCampaign->camp->header.difficultyChoosenByPlayer)
 	{
@@ -3010,26 +3012,20 @@ void CBonusSelection::updateBonusSelection()
 				break;
 			}
 
-			bonuses->addButton(new CHighlightableButton(desc, desc, 0, 475 + i*68, 455, "", i));
+			CHighlightableButton *bonusButton = new CHighlightableButton(desc, desc, 0, 475 + i*68, 455, "", i);
 
 			if (picNumber != -1)
 				picName += ":" + boost::lexical_cast<std::string>(picNumber);
 
 			CAnimation * anim = new CAnimation();
 			anim->setCustom(picName, 0);
-			anim->setCustom("TWCRPORT:1", 1);//create separate surface with yellow border
-			bonuses->buttons.back()->setImage(anim);
-			//FIXME: use show base
-
+			bonusButton->setImage(anim);
+			bonusButton->borderColor = int3(242, 226, 110); // yellow border
+			bonuses->addButton(bonusButton);
 		}
 	if (active)
 		for (size_t i=0; i<bonuses->buttons.size(); i++)
 			bonuses->buttons[i]->activate();
-
-	if (bonuses->buttons.size() > 0)
-	{
-		bonuses->select(0, 0);
-	}
 }
 
 void CBonusSelection::startMap()
@@ -3041,14 +3037,28 @@ void CBonusSelection::startMap()
 	}
 	else
 	{
-		GH.popInts(3);
+		// Deletes either the Custom campaign selection screen + Bonus selection screen or
+		// one of the main campaign selection screens + Bonus selection screen and
+		// deactivates the main menu
+		GH.popInts(2);
+		GH.popInt(GH.topInt()); 
 	}
 	::startGame(si);
 }
 
 void CBonusSelection::selectBonus( int id )
 {
-	sInfo.choosenCampaignBonus = id;
+	// Total redraw is needed because the border around the bonus images
+	// have to be undrawn/drawn.
+	if (id != sInfo.choosenCampaignBonus)
+	{
+		sInfo.choosenCampaignBonus = id;
+		GH.totalRedraw();
+
+		if (startB->getState() == CButtonBase::BLOCKED)
+			startB->setState(CButtonBase::NORMAL);
+	}
+	
 
 	const CCampaignScenario &scenario = ourCampaign->camp->scenarios[sInfo.whichMapInCampaign];
 	const std::vector<CScenarioTravel::STravelBonus> & bonDescs = scenario.travelOptions.bonusesToChoose;
@@ -3436,6 +3446,7 @@ CCampaignScreen::~CCampaignScreen()
 	if (noCamp != 0)
 		SDL_FreeSurface(noCamp);
 
+	//campButtons.clear();
 	CCS->videoh->open("ACREDIT.SMK");
 }
 
@@ -3470,11 +3481,17 @@ void CCampaignScreen::drawCampaignPlaceholder()
 	blitAt(noCamp, noCampRect, bg);
 }
 
-void CCampaignScreen::showAll(SDL_Surface *to)
+void CCampaignScreen::show(SDL_Surface *to)
 {
 	// Draw background image and all interactive objects like buttons
 	blitAt(bg, pos.x, pos.y, to);
-	CIntObject::showAll(to);
+	
+	for (int i = 0; i < this->campButtons.size(); i++)
+	{
+		campButtons[i]->show(to);
+	}
+
+	back->showAll(to);
 }
 
 CCampaignScreen::CCampaignButton::CCampaignButton(SDL_Surface *bg, const std::string image, const int x, const int y, CampaignStatus status)
@@ -3507,7 +3524,6 @@ CCampaignScreen::CCampaignButton::CCampaignButton(SDL_Surface *bg, const std::st
 	// Create the button hover effect
 	hoverLabel = new CLabel(pos.w / 2., pos.h + 20, FONT_MEDIUM, CENTER, tytulowy, "");
 	hoverLabel->ignoreLeadingWhitespace = false;
-	hoverLabel->autoRedraw = false;
 }
 
 CCampaignScreen::CCampaignButton::~CCampaignButton()
@@ -3532,9 +3548,9 @@ void CCampaignScreen::CCampaignButton::hover(bool on)
 
 }
 
-void CCampaignScreen::CCampaignButton::showAll(SDL_Surface *to)
+void CCampaignScreen::CCampaignButton::show(SDL_Surface *to)
 {
-	CIntObject::showAll(to);
+	hoverLabel->showAll(to);
 
 	if (status == CCampaignScreen::DISABLED || video == "" || button == 0)
 		return;

+ 2 - 2
client/CPreGame.h

@@ -449,7 +449,7 @@ class CCampaignScreen : public CIntObject
 
 			CCampaignButton(SDL_Surface *bg, const std::string image, const int x, const int y, CampaignStatus status); // c-tor
 			~CCampaignButton(); // d-tor
-			void showAll(SDL_Surface *to);
+			void show(SDL_Surface *to);
 		};
 
 		std::vector<CCampaignButton*> campButtons; // a container which holds all buttons where you can start a campaign
@@ -463,7 +463,7 @@ public:
 
 	CCampaignScreen(CampaignSet campaigns, std::map<std::string, CampaignStatus>& camps);
 	~CCampaignScreen();
-	void showAll(SDL_Surface *to);
+	void show(SDL_Surface *to);
 };
 
 /// Handles background screen, loads graphics for victory/loss condition and random town or hero selection

+ 13 - 1
client/CVideoHandler.cpp

@@ -660,6 +660,7 @@ CVideoPlayer::CVideoPlayer()
 	av_register_protocol(&lod_protocol);
 
 	vidh = new CVidHandler(std::string(DATA_DIR "/Data/VIDEO.VID"));
+	vidh_ab = new CVidHandler(std::string(DATA_DIR "/Data/H3ab_ahd.vid"));
 }
 
 // loop = to loop through the video
@@ -675,6 +676,9 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
 	doLoop = loop;
 
 	data = vidh->extract(fname, length);
+	if (!data) {
+		data = vidh_ab->extract(fname, length);		
+	}	
 
 	if (data) {
 		// Create our URL name with the 'lod' protocol as a prefix and a
@@ -751,6 +755,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay)
 							 codecContext->pix_fmt, codecContext->width, codecContext->height, 
 							 PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
 	} else {
+
 		PixelFormat screenFormat = PIX_FMT_NONE;
 		switch(screen->format->BytesPerPixel)
 		{
@@ -872,8 +877,15 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo
 		refreshCount = refreshWait;
 		if (nextFrame())
 			show(x,y,dst,update);
-		else
+		else {
 			open(fname);
+			nextFrame();			
+			
+			// The y position is wrong at the first frame.
+			// Note: either the windows player or the linux player is
+			// broken. Compensate here until the bug is found.			
+			show(x, y--, dst, update);
+		}
 	} 
 	else {
 		redraw(x, y, dst, update);

+ 1 - 0
client/CVideoHandler.h

@@ -225,6 +225,7 @@ private:
 	SDL_Rect pos;				// destination on screen
 
 	CVidHandler *vidh;
+	CVidHandler *vidh_ab;
 
 	int refreshWait; // Wait several refresh before updating the image
 	int refreshCount;

+ 2 - 23
client/GUIBase.cpp

@@ -106,24 +106,11 @@ IShowActivable * CGuiHandler::topInt()
 }
 
 void CGuiHandler::totalRedraw()
-{
-	//this->invalidateTotalRedraw = true;
-	internalTotalRedraw();
-}
-
-void CGuiHandler::internalTotalRedraw()
 {
 	for(int i=0;i<objsToBlit.size();i++)
 		objsToBlit[i]->showAll(screen2);
 
 	blitAt(screen2,0,0,screen);
-
-	//Any reason to blit last object second time?
-	//if(objsToBlit.size())
-	//	objsToBlit.back()->showAll(screen);
-
-	this->invalidateTotalRedraw = false;
-	this->invalidateSimpleRedraw = false;
 }
 
 void CGuiHandler::updateTime()
@@ -316,19 +303,11 @@ void CGuiHandler::handleMouseMotion(SDL_Event *sEvent)
 }
 
 void CGuiHandler::simpleRedraw()
-{
-	//this->invalidateSimpleRedraw = true;
-	internalSimpleRedraw();
-}
-
-void CGuiHandler::internalSimpleRedraw()
 {
 	//update only top interface and draw background
 	if(objsToBlit.size() > 1)
 		blitAt(screen2,0,0,screen); //blit background
 	objsToBlit.back()->show(screen); //blit active interface/window
-	
-	this->invalidateSimpleRedraw = false;
 }
 
 void CGuiHandler::handleMoveInterested( const SDL_MouseMotionEvent & motion )
@@ -364,7 +343,7 @@ void CGuiHandler::run()
 	setThreadName(-1, "CGuiHandler::run");
 	try
 	{
-		//CCS->curh->centerCursor();//Is this essential? random crashes on Linux
+		CCS->curh->centerCursor();//Is this essential? random crashes on Linux
 
 		mainFPSmng->init(); // resets internal clock, needed for FPS manager
 		while(!terminate)
@@ -1068,4 +1047,4 @@ Rect Rect::around(const Rect &r, int width /*= 1*/) /*creates rect around anothe
 Rect Rect::centerIn(const Rect &r)
 {
 	return Rect(r.x + (r.w - w) / 2, r.y + (r.h - h) / 2, w, h);
-}
+}

+ 0 - 7
client/GUIBase.h

@@ -517,13 +517,6 @@ public:
 /// Handles GUI logic and drawing
 class CGuiHandler
 {
-private:
-	bool invalidateTotalRedraw;
-	bool invalidateSimpleRedraw;
-
-	void internalTotalRedraw();
-	void internalSimpleRedraw();
-
 public:
 	FPSManager *mainFPSmng; //to keep const framerate
 	timeHandler th;

+ 5 - 2
client/GUIClasses.cpp

@@ -494,8 +494,11 @@ CInfoWindow::CInfoWindow(std::string Text, int player, const TCompsInfo &comps,
 	ID = -1;
 	for(int i=0;i<Buttons.size();i++)
 	{
-		buttons.push_back(new AdventureMapButton("","",boost::bind(&CInfoWindow::close,this),0,0,Buttons[i].first));
-		buttons[i]->callback.add(Buttons[i].second); //each button will close the window apart from call-defined actions
+		AdventureMapButton *button = new AdventureMapButton("","",boost::bind(&CInfoWindow::close,this),0,0,Buttons[i].first);
+		button->borderColor = int3(173, 142, 66);
+		button->borderEnabled = true;
+		button->callback.add(Buttons[i].second); //each button will close the window apart from call-defined actions
+		buttons.push_back(button);
 	}
 
 	text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, zwykly);