Browse Source

First part of GUI reorganization: extracted CGuiHandler from CPlayerInterface.
Minor fixes for Creature Generators and recruitment window.

Michał W. Urbańczyk 16 years ago
parent
commit
a91ab8872b

+ 1 - 1
client/AdventureMapButton.cpp

@@ -401,7 +401,7 @@ void CSlider::clickLeft (tribool down)
 {
 	if(down)
 	{
-		float pw = LOCPLINT->current->motion.x-pos.x-24;
+		float pw = GH.current->motion.x-pos.x-24;
 		float rw = pw / ((float)(pos.w-48));
 		if (rw>1) return;
 		if (rw<0) return;

+ 2 - 0
client/AdventureMapButton.h

@@ -15,6 +15,8 @@
  *
  */
 
+class CDefEssential;
+
 namespace config{struct ButtonInfo;}
 
 class AdventureMapButton 

+ 66 - 26
client/CAdvmapInterface.cpp

@@ -278,15 +278,15 @@ void CMinimap::clickLeft (tribool down)
 		MotionInterested::activate();
 	else if (!down)
 	{
-		if (std::find(LOCPLINT->motioninterested.begin(),LOCPLINT->motioninterested.end(),this)!=LOCPLINT->motioninterested.end())
+		if (std::find(GH.motioninterested.begin(),GH.motioninterested.end(),this)!=GH.motioninterested.end())
 			MotionInterested::deactivate();
 	}
 	ClickableL::clickLeft(down);
 	if (!((bool)down))
 		return;
 
-	float dx=((float)(LOCPLINT->current->motion.x-pos.x))/((float)pos.w),
-		dy=((float)(LOCPLINT->current->motion.y-pos.y))/((float)pos.h);
+	float dx=((float)(GH.current->motion.x-pos.x))/((float)pos.w),
+		dy=((float)(GH.current->motion.y-pos.y))/((float)pos.h);
 
 	int3 newCPos;
 	newCPos.x = (CGI->mh->sizes.x*dx);
@@ -576,9 +576,9 @@ void CTerrainRect::clickRight(tribool down)
 				if(LOCPLINT->cb->getHeroInfo(obj, iah))
 				{
 					SDL_Surface *iwin = graphics->drawHeroInfoWin(iah);
-					CInfoPopup * ip = new CInfoPopup(iwin, LOCPLINT->current->motion.x-iwin->w,
-													  LOCPLINT->current->motion.y-iwin->h, true);
-					LOCPLINT->pushInt(ip);
+					CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x-iwin->w,
+													  GH.current->motion.y-iwin->h, true);
+					GH.pushInt(ip);
 				}
 				else
 				{
@@ -588,10 +588,10 @@ void CTerrainRect::clickRight(tribool down)
 			else
 			{
 				CInfoPopup * ip = new CInfoPopup(graphics->heroWins[obj->subID],
-					LOCPLINT->current->motion.x-graphics->heroWins[obj->subID]->w,
-					LOCPLINT->current->motion.y-graphics->heroWins[obj->subID]->h,false
+					GH.current->motion.x-graphics->heroWins[obj->subID]->w,
+					GH.current->motion.y-graphics->heroWins[obj->subID]->h,false
 					);
-				LOCPLINT->pushInt(ip);
+				GH.pushInt(ip);
 			}
 			break;
 		}
@@ -603,9 +603,9 @@ void CTerrainRect::clickRight(tribool down)
 				if(LOCPLINT->cb->getTownInfo(obj, iah))
 				{
 					SDL_Surface *iwin = graphics->drawTownInfoWin(iah);
-					CInfoPopup * ip = new CInfoPopup(iwin, LOCPLINT->current->motion.x-iwin->w,
-						LOCPLINT->current->motion.y-iwin->h, true);
-					LOCPLINT->pushInt(ip);
+					CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x-iwin->w,
+						GH.current->motion.y-iwin->h, true);
+					GH.pushInt(ip);
 				}
 				else
 				{
@@ -615,10 +615,10 @@ void CTerrainRect::clickRight(tribool down)
 			else
 			{
 				CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id],
-					LOCPLINT->current->motion.x-graphics->townWins[obj->id]->w,
-					LOCPLINT->current->motion.y-graphics->townWins[obj->id]->h,false
+					GH.current->motion.x-graphics->townWins[obj->id]->w,
+					GH.current->motion.y-graphics->townWins[obj->id]->h,false
 					);
-				LOCPLINT->pushInt(ip);
+				GH.pushInt(ip);
 			}
 			break;
 		}
@@ -1041,14 +1041,14 @@ void CTerrainRect::show(SDL_Surface * to)
 int3 CTerrainRect::whichTileIsIt(const int & x, const int & y)
 {
 	int3 ret;
-	ret.x = LOCPLINT->adventureInt->position.x + ((LOCPLINT->current->motion.x-CGI->mh->offsetX-pos.x)/32);
-	ret.y = LOCPLINT->adventureInt->position.y + ((LOCPLINT->current->motion.y-CGI->mh->offsetY-pos.y)/32);
+	ret.x = LOCPLINT->adventureInt->position.x + ((GH.current->motion.x-CGI->mh->offsetX-pos.x)/32);
+	ret.y = LOCPLINT->adventureInt->position.y + ((GH.current->motion.y-CGI->mh->offsetY-pos.y)/32);
 	ret.z = LOCPLINT->adventureInt->position.z;
 	return ret;
 }
 int3 CTerrainRect::whichTileIsIt()
 {
-	return whichTileIsIt(LOCPLINT->current->motion.x,LOCPLINT->current->motion.y);
+	return whichTileIsIt(GH.current->motion.x,GH.current->motion.y);
 }
 
 void CResDataBar::clickRight (tribool down)
@@ -1405,7 +1405,7 @@ void CAdvMapInt::fshowSpellbok()
 
 
 	CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), (static_cast<const CGHeroInstance*>(LOCPLINT->adventureInt->selection)), false);
-	LOCPLINT->pushInt(spellWindow);
+	GH.pushInt(spellWindow);
 }
 
 void CAdvMapInt::fadventureOPtions()
@@ -1415,7 +1415,7 @@ void CAdvMapInt::fadventureOPtions()
 void CAdvMapInt::fsystemOptions()
 {
 	CSystemOptionsWindow * sysopWindow = new CSystemOptionsWindow(genRect(487, 481, 159, 57), LOCPLINT);
-	LOCPLINT->pushInt(sysopWindow);
+	GH.pushInt(sysopWindow);
 }
 
 void CAdvMapInt::fnextHero()
@@ -1486,8 +1486,8 @@ void CAdvMapInt::deactivate()
 	heroList.deactivate();
 	townList.deactivate();
 	terrain.deactivate();
-	if(std::find(LOCPLINT->timeinterested.begin(),LOCPLINT->timeinterested.end(),&infoBar)!=LOCPLINT->timeinterested.end())
-		LOCPLINT->timeinterested.erase(std::find(LOCPLINT->timeinterested.begin(),LOCPLINT->timeinterested.end(),&infoBar));
+	if(std::find(GH.timeinterested.begin(),GH.timeinterested.end(),&infoBar)!=GH.timeinterested.end())
+		GH.timeinterested.erase(std::find(GH.timeinterested.begin(),GH.timeinterested.end(),&infoBar));
 	infoBar.mode=-1;
 
 	LOCPLINT->cingconsole->deactivate();
@@ -1541,7 +1541,7 @@ void CAdvMapInt::show(SDL_Surface *to)
 	//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
 	if((animValHitCount % (4/LOCPLINT->sysOpts.mapScrollingSpeed)) == 0 
 		&& 
-			(LOCPLINT->topInt() == this)
+			(GH.topInt() == this)
 			|| SDL_GetKeyState(NULL)[SDLK_LCTRL] 
 			|| SDL_GetKeyState(NULL)[SDLK_RCTRL]
 	)
@@ -1642,7 +1642,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
 	case SDLK_t:
 		{
 			//act on key down if marketplace windows is not already opened
-			if(key.state != SDL_PRESSED  ||  dynamic_cast<CMarketplaceWindow*>(LOCPLINT->topInt())) return;
+			if(key.state != SDL_PRESSED  ||  dynamic_cast<CMarketplaceWindow*>(GH.topInt())) return;
 
 			//check if we have aby marketplace
 			std::vector<const CGTownInstance*> towns = LOCPLINT->cb->getTownsInfo();
@@ -1652,7 +1652,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
 					break;
 
 			if(i != towns.size()) //if any town has marketplace, open window
-				LOCPLINT->pushInt(new CMarketplaceWindow); 
+				GH.pushInt(new CMarketplaceWindow); 
 			else //if not - complain
 				LOCPLINT->showInfoDialog("No available marketplace!", std::vector<SComponent*>(), soundBase::sound_todo);
 			return;
@@ -1678,7 +1678,7 @@ void CAdvMapInt::handleRightClick(std::string text, tribool down, CIntObject * c
 		temp->pos.y=screen->h/2-(temp->pos.h/2);
 		temp->owner = client;
 		CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
-		LOCPLINT->pushInt(rcpi);
+		GH.pushInt(rcpi);
 	}
 }
 int3 CAdvMapInt::verifyPos(int3 ver)
@@ -1731,3 +1731,43 @@ void CAdvMapInt::select(const CArmedInstance *sel )
 	heroList.draw(screen);
 	infoBar.draw(screen);
 }
+
+void CAdvMapInt::mouseMoved( const SDL_MouseMotionEvent & sEvent )
+{
+	//adventure map scrolling with mouse
+	if(!SDL_GetKeyState(NULL)[SDLK_LCTRL]  &&  active)
+	{
+		if(sEvent.x<15)
+		{
+			scrollingDir |= LEFT;
+		}
+		else
+		{
+			scrollingDir &= ~LEFT;
+		}
+		if(sEvent.x>screen->w-15)
+		{
+			scrollingDir |= RIGHT;
+		}
+		else
+		{
+			scrollingDir &= ~RIGHT;
+		}
+		if(sEvent.y<15)
+		{
+			scrollingDir |= UP;
+		}
+		else
+		{
+			scrollingDir &= ~UP;
+		}
+		if(sEvent.y>screen->h-15)
+		{
+			scrollingDir |= DOWN;
+		}
+		else
+		{
+			scrollingDir &= ~DOWN;
+		}
+	}
+}

+ 2 - 1
client/CAdvmapInterface.h

@@ -115,7 +115,7 @@ public:
 	CDefHandler * getAnim(int mode);
 };
 /*****************************/
-class CAdvMapInt : public CMainInterface, public KeyInterested //adventure map interface
+class CAdvMapInt : public CMainInterface, public KeyInterested, public MotionInterested //adventure map interface
 {
 public:
 	CAdvMapInt(int Player);
@@ -185,5 +185,6 @@ public:
 	int3 verifyPos(int3 ver);
 	void handleRightClick(std::string text, boost::logic::tribool down, CIntObject * client);
 	void keyPressed(const SDL_KeyboardEvent & key);
+	void mouseMoved (const SDL_MouseMotionEvent & sEvent);
 };
 #endif // __CADVMAPINTERFACE_H__

+ 9 - 9
client/CBattleInterface.cpp

@@ -288,14 +288,14 @@ void CBattleInterface::setPrintCellBorders(bool set)
 {
 	settings.printCellBorders = set;
 	redrawBackgroundWithHexes(activeStack);
-	LOCPLINT->totalRedraw();
+	GH.totalRedraw();
 }
 
 void CBattleInterface::setPrintStackRange(bool set)
 {
 	settings.printStackRange = set;
 	redrawBackgroundWithHexes(activeStack);
-	LOCPLINT->totalRedraw();
+	GH.totalRedraw();
 }
 
 void CBattleInterface::setPrintMouseShadow(bool set)
@@ -940,7 +940,7 @@ void CBattleInterface::bOptionsf()
 
 	SDL_Rect temp_rect = genRect(431, 481, 160, 84);
 	CBattleOptionsWindow * optionsWin = new CBattleOptionsWindow(temp_rect, this);
-	LOCPLINT->pushInt(optionsWin);
+	GH.pushInt(optionsWin);
 }
 
 void CBattleInterface::bSurrenderf()
@@ -973,7 +973,7 @@ void CBattleInterface::bSpellf()
 	else
 		chi = defendingHeroInstance;
 	CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), chi);
-	LOCPLINT->pushInt(spellWindow);
+	GH.pushInt(spellWindow);
 }
 
 void CBattleInterface::bWaitf()
@@ -1744,7 +1744,7 @@ void CBattleInterface::battleFinished(const BattleResult& br)
 	SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
 	CGI->musich->stopMusic();
 	resWindow = new CBattleResultWindow(br, temp_rect, this);
-	LOCPLINT->pushInt(resWindow);
+	GH.pushInt(resWindow);
 }
 
 void CBattleInterface::spellCast(SpellCast * sc)
@@ -2372,7 +2372,7 @@ void CBattleHero::clickLeft(boost::logic::tribool down)
 		CGI->curh->changeGraphic(0,0);
 
 		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), myHero);
-		LOCPLINT->pushInt(spellWindow);
+		GH.pushInt(spellWindow);
 	}
 }
 
@@ -2542,7 +2542,7 @@ void CBattleHex::clickRight(boost::logic::tribool down)
 				pom->effects.insert(myst.effects[vb].id);
 			}
 			pom->currentHealth = myst.firstHPleft;
-			LOCPLINT->pushInt(new CCreInfoWindow(myst.creature->idNumber, 0, myst.amount, pom, 0, 0, NULL));
+			GH.pushInt(new CCreInfoWindow(myst.creature->idNumber, 0, myst.amount, pom, 0, 0, NULL));
 		}
 		delete pom;
 	}
@@ -2817,7 +2817,7 @@ void CBattleResultWindow::show(SDL_Surface *to)
 
 void CBattleResultWindow::bExitf()
 {
-	LOCPLINT->popInts(2); //first - we; second - battle interface
+	GH.popInts(2); //first - we; second - battle interface
 	LOCPLINT->showingDialog->setn(false);
 	CGI->videoh->close();
 }
@@ -2928,5 +2928,5 @@ void CBattleOptionsWindow::bDefaultf()
 
 void CBattleOptionsWindow::bExitf()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }

+ 24 - 24
client/CCastleInterface.cpp

@@ -130,14 +130,14 @@ void CBuildingRect::hover(bool on)
 
 			//call mouseMoved in other buildings, cursor might have been moved while they were inactive (eg. because of r-click popup)
 			for(size_t i = 0; i < LOCPLINT->castleInt->buildings.size(); i++)
-				LOCPLINT->castleInt->buildings[i]->mouseMoved(LOCPLINT->current->motion);
+				LOCPLINT->castleInt->buildings[i]->mouseMoved(GH.current->motion);
 		}
 	}
 }
 void CBuildingRect::clickLeft (tribool down)
 {
 
-	if(area && (LOCPLINT->castleInt->hBuild==this) && !(indeterminate(down)) && (CSDL_Ext::SDL_GetPixel(area,LOCPLINT->current->motion.x-pos.x,LOCPLINT->current->motion.y-pos.y) != 0)) //na polu
+	if(area && (LOCPLINT->castleInt->hBuild==this) && !(indeterminate(down)) && (CSDL_Ext::SDL_GetPixel(area,GH.current->motion.x-pos.x,GH.current->motion.y-pos.y) != 0)) //na polu
 	{
 		if(pressedL && !down)
 			LOCPLINT->castleInt->buildingClicked(str->ID);
@@ -151,7 +151,7 @@ void CBuildingRect::clickRight (tribool down)
 {
 	if((!area) || (!((bool)down)) || (this!=LOCPLINT->castleInt->hBuild))
 		return;
-	if((CSDL_Ext::SDL_GetPixel(area,LOCPLINT->current->motion.x-pos.x,LOCPLINT->current->motion.y-pos.y) != 0)) //na polu
+	if((CSDL_Ext::SDL_GetPixel(area,GH.current->motion.x-pos.x,GH.current->motion.y-pos.y) != 0)) //na polu
 	{
 		CBuilding *bld = CGI->buildh->buildings[str->townID][str->ID];
 		assert(bld);
@@ -165,7 +165,7 @@ void CBuildingRect::clickRight (tribool down)
 			bld->Name());
 		vinya->pos.x = screen->w/2 - vinya->bitmap->w/2;
 		vinya->pos.y = screen->h/2 - vinya->bitmap->h/2;
-		LOCPLINT->pushInt(vinya);
+		GH.pushInt(vinya);
 	}
 }
 void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
@@ -301,7 +301,7 @@ void CHeroGSlot::clickLeft(boost::logic::tribool down)
 		}
 		hover(false);hover(true); //refresh statusbar
 	}
-	//if(indeterminate(down) && !isItIn(&other->pos,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+	//if(indeterminate(down) && !isItIn(&other->pos,GH.current->motion.x,GH.current->motion.y))
 	//{
 	//	other->highlight = highlight = false;
 	//	show(screen2);
@@ -515,7 +515,7 @@ void CCastleInterface::close()
 	if(town->visitingHero)
 		LOCPLINT->adventureInt->select(town->visitingHero);
 	LOCPLINT->castleInt = NULL;
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 	CGI->musich->stopMusic(5000);
 }
 
@@ -589,7 +589,7 @@ void CCastleInterface::buildingClicked(int building)
 		case 7: case 8: case 9: //fort/citadel/castle
 			{
 				CFortScreen *fs = new CFortScreen(this);
-				LOCPLINT->pushInt(fs);
+				GH.pushInt(fs);
 				break;
 			}
 		case 10: case 11: case 12: case 13: //hall
@@ -598,7 +598,7 @@ void CCastleInterface::buildingClicked(int building)
 		case 14:  //marketplace
 			{
 				CMarketplaceWindow *cmw = new CMarketplaceWindow(0);
-				LOCPLINT->pushInt(cmw);
+				GH.pushInt(cmw);
 				break;
 			}
 		case 15: //resource silo
@@ -622,7 +622,7 @@ void CCastleInterface::buildingClicked(int building)
 				if(vstd::contains(hero->artifWorn,ui16(aid+9))) //hero already has machine
 					possible = false;
 
-				LOCPLINT->pushInt(new CBlacksmithDialog(possible,CArtHandler::convertMachineID(aid,false),aid,hero->id));
+				GH.pushInt(new CBlacksmithDialog(possible,CArtHandler::convertMachineID(aid,false),aid,hero->id));
 				break;
 			}
 		//TODO: case 17: //special 1
@@ -659,7 +659,7 @@ void CCastleInterface::buildingClicked(int building)
 void CCastleInterface::enterHall()
 {
 	CHallInterface *h = new CHallInterface(this);
-	LOCPLINT->pushInt(h);
+	GH.pushInt(h);
 }
 
 void CCastleInterface::showAll( SDL_Surface * to/*=NULL*/)
@@ -746,8 +746,8 @@ void CCastleInterface::townChange()
 {
 	const CGTownInstance * nt = townlist->items[townlist->selected];
 	int tpos = townlist->selected - townlist->from;
-	LOCPLINT->popIntTotally(this);
-	LOCPLINT->pushInt(new CCastleInterface(nt, tpos));
+	GH.popIntTotally(this);
+	GH.pushInt(new CCastleInterface(nt, tpos));
 }
 
 void CCastleInterface::show(SDL_Surface * to)
@@ -979,20 +979,20 @@ CRecruitmentWindow * CCastleInterface::showRecruitmentWindow( int building )
 	//CRecruitmentWindow *rw = new CRecruitmentWindow(crs,boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
 
 	CRecruitmentWindow *rw = new CRecruitmentWindow(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2));
-	LOCPLINT->pushInt(rw);
+	GH.pushInt(rw);
 	return rw;
 }
 
 void CCastleInterface::enterMageGuild()
 {
-	LOCPLINT->pushInt(new CMageGuildScreen(this));
+	GH.pushInt(new CMageGuildScreen(this));
 }
 
 void CCastleInterface::enterTavern()
 {
 	std::vector<const CGHeroInstance*> h = LOCPLINT->cb->getAvailableHeroes(town);
 	CTavernWindow *tv = new CTavernWindow(h[0],h[1],"GOSSIP TEST");
-	LOCPLINT->pushInt(tv);
+	GH.pushInt(tv);
 }
 
 void CCastleInterface::keyPressed( const SDL_KeyboardEvent & key )
@@ -1047,7 +1047,7 @@ void CHallInterface::CBuildingBox::clickLeft (tribool down)
 {
 	if(pressedL && (!down))
 	{
-		LOCPLINT->pushInt(new CHallInterface::CBuildWindow(LOCPLINT->castleInt->town->subID,BID,state,0));
+		GH.pushInt(new CHallInterface::CBuildWindow(LOCPLINT->castleInt->town->subID,BID,state,0));
 	}
 	ClickableL::clickLeft(down);
 }
@@ -1055,7 +1055,7 @@ void CHallInterface::CBuildingBox::clickRight (tribool down)
 {
 	if(down)
 	{
-		LOCPLINT->pushInt(new CHallInterface::CBuildWindow(LOCPLINT->castleInt->town->subID,BID,state,1));
+		GH.pushInt(new CHallInterface::CBuildWindow(LOCPLINT->castleInt->town->subID,BID,state,1));
 	}
 	ClickableR::clickRight(down);
 }
@@ -1197,7 +1197,7 @@ CHallInterface::~CHallInterface()
 }
 void CHallInterface::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 void CHallInterface::show(SDL_Surface * to)
 {
@@ -1257,13 +1257,13 @@ void CHallInterface::CBuildWindow::deactivate()
 void CHallInterface::CBuildWindow::Buy()
 {
 	int building = bid;
-	LOCPLINT->popInts(2); //we - build window and hall screen
+	GH.popInts(2); //we - build window and hall screen
 	LOCPLINT->cb->buildBuilding(LOCPLINT->castleInt->town,building);
 }
 
 void CHallInterface::CBuildWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CHallInterface::CBuildWindow::clickRight (tribool down)
@@ -1463,7 +1463,7 @@ void CFortScreen::deactivate()
 
 void CFortScreen::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 CFortScreen::CFortScreen( CCastleInterface * owner )
@@ -1635,7 +1635,7 @@ CMageGuildScreen::~CMageGuildScreen()
 
 void CMageGuildScreen::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CMageGuildScreen::show(SDL_Surface * to)
@@ -1687,7 +1687,7 @@ void CMageGuildScreen::Scroll::clickRight (tribool down)
 			spell->name,30,30);
 		vinya->pos.x = screen->w/2 - vinya->bitmap->w/2;
 		vinya->pos.y = screen->h/2 - vinya->bitmap->h/2;
-		LOCPLINT->pushInt(vinya);
+		GH.pushInt(vinya);
 	}
 }
 
@@ -1781,5 +1781,5 @@ CBlacksmithDialog::~CBlacksmithDialog()
 
 void CBlacksmithDialog::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }

+ 1 - 1
client/CHeroWindow.cpp

@@ -289,7 +289,7 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
 
 void CHeroWindow::quit()
 {
-	LOCPLINT->popInt(this);
+	GH.popInt(this);
 	dispose();
 }
 

+ 3 - 2
client/CMT.cpp

@@ -59,6 +59,7 @@
 
 std::string NAME_AFFIX = "client";
 std::string NAME = NAME_VER + std::string(" (") + NAME_AFFIX + ')'; //application name
+CGuiHandler GH;
 SDL_Surface *screen = NULL, //main screen surface 
 	*screen2 = NULL,//and hlp surface (used to store not-active interfaces layer) 
 	*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
@@ -269,7 +270,7 @@ int main(int argc, char** argv)
 				boost::unique_lock<boost::recursive_mutex> lock(*LOCPLINT->pim);
 				bool full = !(screen->flags&SDL_FULLSCREEN);
 				setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
-				LOCPLINT->totalRedraw();
+				GH.totalRedraw();
 			}
 			eventsM.lock();
 			events.push(ev);
@@ -306,7 +307,7 @@ void processCommand(const std::string &message, CClient *&client)
 		switch (what)
 		{
 		case 0:
-			LOCPLINT->topInt()->activate();
+			GH.topInt()->activate();
 			break;
 		case 1:
 			LOCPLINT->adventureInt->activate();

+ 30 - 293
client/CPlayerInterface.cpp

@@ -169,14 +169,11 @@ void CPlayerInterface::yourTurn()
 			adventureInt->select(adventureInt->townList.items[0]);
 
 		adventureInt->showAll(screen);
-		pushInt(adventureInt);
+		GH.pushInt(adventureInt);
 		adventureInt->KeyInterested::activate();
 
-		timeHandler th;
-		th.getDif();
 		while(makingTurn) // main loop
 		{
-
 			updateWater();
 			pim->lock();
 
@@ -185,51 +182,17 @@ void CPlayerInterface::yourTurn()
 			if(dialogs.size() && !showingDialog->get())
 			{
 				showingDialog->set(true);
-				pushInt(dialogs.front());
+				GH.pushInt(dialogs.front());
 				dialogs.pop_front();
 			}
 
-			int tv = th.getDif();
-			std::list<TimeInterested*> hlp = timeinterested;
-			for (std::list<TimeInterested*>::iterator i=hlp.begin(); i != hlp.end();i++)
-			{
-				if(!vstd::contains(timeinterested,*i)) continue;
-				if ((*i)->toNextTick>=0)
-					(*i)->toNextTick-=tv;
-				if ((*i)->toNextTick<0)
-					(*i)->tick();
-			}
-
-			while(true)
-			{
-				SDL_Event *ev = NULL;
-				{
-					boost::unique_lock<boost::mutex> lock(eventsM);
-					if(!events.size())
-					{
-						break;
-					}
-					else
-					{
-						ev = events.front();
-						events.pop();
-					}
-				}
-				handleEvent(ev);
-				delete ev;
-			}
+			GH.updateTime();
+			GH.handleEvents();
 
-			if(!adventureInt->active && adventureInt->scrollingDir) //player force map scrolling though interface is disabled
-			{
-				totalRedraw();
-			}
+			if(!adventureInt->active && adventureInt->scrollingDir) //player forces map scrolling though interface is disabled
+				GH.totalRedraw();
 			else
-			{
-				//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
-			}
+				GH.simpleRedraw();
 
 			CGI->curh->draw1();
 			CSDL_Ext::update(screen);
@@ -239,7 +202,7 @@ void CPlayerInterface::yourTurn()
 		}
 
 		adventureInt->KeyInterested::deactivate();
-		popInt(adventureInt);
+		GH.popInt(adventureInt);
 
 		cb->endTurn();
 	} HANDLE_EXCEPTION
@@ -303,7 +266,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
 	{
 		ho->isStanding = true;
 		stillMoveHero.setn(STOP_MOVE);
-		LOCPLINT->totalRedraw();
+		GH.totalRedraw();
 		return;
 	}
 
@@ -767,7 +730,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
 		}
 	}
 
-	if(stillMoveHero.get() == 1)
+	if(stillMoveHero.get() == WAITING_MOVE)
 		stillMoveHero.setn(DURING_MOVE);
 
 }
@@ -789,7 +752,7 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
 void CPlayerInterface::openTownWindow(const CGTownInstance * town)
 {
 	castleInt = new CCastleInterface(town);
-	LOCPLINT->pushInt(castleInt);
+	GH.pushInt(castleInt);
 }
 
 SDL_Surface * CPlayerInterface::infoWin(const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
@@ -829,166 +792,6 @@ SDL_Surface * CPlayerInterface::infoWin(const CGObjectInstance * specific) //spe
 	}
 }
 
-void CPlayerInterface::handleMouseMotion(SDL_Event *sEvent)
-{
-	//sending active, hovered hoverable objects hover() call
-	std::vector<Hoverable*> hlp;
-	for(std::list<Hoverable*>::iterator i=hoverable.begin(); i != hoverable.end();i++)
-	{
-		if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-		{
-			if (!(*i)->hovered)
-				hlp.push_back((*i));
-		}
-		else if ((*i)->hovered)
-		{
-			(*i)->hover(false);
-		}
-	}
-	for(int i=0; i<hlp.size();i++)
-		hlp[i]->hover(true);
-
-	//sending active, MotionInterested objects mouseMoved() call
-	std::list<MotionInterested*> miCopy = motioninterested;
-	for(std::list<MotionInterested*>::iterator i=miCopy.begin(); i != miCopy.end();i++)
-	{
-		if ((*i)->strongInterest || isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-		{
-			(*i)->mouseMoved(sEvent->motion);
-		}
-	}
-
-	//adventure map scrolling with mouse
-	if(!SDL_GetKeyState(NULL)[SDLK_LCTRL]  &&  adventureInt->active)
-	{
-		if(sEvent->motion.x<15)
-		{
-			adventureInt->scrollingDir |= CAdvMapInt::LEFT;
-		}
-		else
-		{
-			adventureInt->scrollingDir &= ~CAdvMapInt::LEFT;
-		}
-		if(sEvent->motion.x>screen->w-15)
-		{
-			adventureInt->scrollingDir |= CAdvMapInt::RIGHT;
-		}
-		else
-		{
-			adventureInt->scrollingDir &= ~CAdvMapInt::RIGHT;
-		}
-		if(sEvent->motion.y<15)
-		{
-			adventureInt->scrollingDir |= CAdvMapInt::UP;
-		}
-		else
-		{
-			adventureInt->scrollingDir &= ~CAdvMapInt::UP;
-		}
-		if(sEvent->motion.y>screen->h-15)
-		{
-			adventureInt->scrollingDir |= CAdvMapInt::DOWN;
-		}
-		else
-		{
-			adventureInt->scrollingDir &= ~CAdvMapInt::DOWN;
-		}
-	}
-}
-void CPlayerInterface::handleEvent(SDL_Event *sEvent)
-{
-	current = sEvent;
-
-	if (sEvent->type==SDL_KEYDOWN || sEvent->type==SDL_KEYUP)
-	{
-		SDL_KeyboardEvent key = sEvent->key;
-
-		//translate numpad keys
-		if (key.keysym.sym >= SDLK_KP0  && key.keysym.sym <= SDLK_KP9)
-		{
-			key.keysym.sym = (SDLKey) (key.keysym.sym - SDLK_KP0 + SDLK_0);
-		}
-		else if(key.keysym.sym == SDLK_KP_ENTER)
-		{
-			key.keysym.sym = (SDLKey)SDLK_RETURN;
-		}
-
-		bool keysCaptured = false;
-		for(std::list<KeyInterested*>::iterator i=keyinterested.begin(); i != keyinterested.end();i++)
-		{
-			if((*i)->captureAllKeys)
-			{
-				keysCaptured = true;
-				break;
-			}
-		}
-
-		std::list<KeyInterested*> miCopy = keyinterested;
-		for(std::list<KeyInterested*>::iterator i=miCopy.begin(); i != miCopy.end();i++)
-			if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureAllKeys))
-				(**i).keyPressed(key);
-	}
-	else if(sEvent->type==SDL_MOUSEMOTION)
-	{
-		CGI->curh->cursorMove(sEvent->motion.x, sEvent->motion.y);
-		handleMouseMotion(sEvent);
-	}
-	else if ((sEvent->type==SDL_MOUSEBUTTONDOWN) && (sEvent->button.button == SDL_BUTTON_LEFT))
-	{
-		std::list<ClickableL*> hlp = lclickable;
-		for(std::list<ClickableL*>::iterator i=hlp.begin(); i != hlp.end();i++)
-		{
-			if(!vstd::contains(lclickable,*i)) continue;
-			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-			{
-				(*i)->clickLeft(true);
-			}
-		}
-	}
-	else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT))
-	{
-		std::list<ClickableL*> hlp = lclickable;
-		for(std::list<ClickableL*>::iterator i=hlp.begin(); i != hlp.end();i++)
-		{
-			if(!vstd::contains(lclickable,*i)) continue;
-			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-			{
-				(*i)->clickLeft(false);
-			}
-			else
-				(*i)->clickLeft(boost::logic::indeterminate);
-		}
-	}
-	else if ((sEvent->type==SDL_MOUSEBUTTONDOWN) && (sEvent->button.button == SDL_BUTTON_RIGHT))
-	{
-		std::list<ClickableR*> hlp = rclickable;
-		for(std::list<ClickableR*>::iterator i=hlp.begin(); i != hlp.end();i++)
-		{
-			if(!vstd::contains(rclickable,*i)) continue;
-			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-			{
-				(*i)->clickRight(true);
-			}
-		}
-	}
-	else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_RIGHT))
-	{
-		std::list<ClickableR*> hlp = rclickable;
-		for(std::list<ClickableR*>::iterator i=hlp.begin(); i != hlp.end();i++)
-		{
-			if(!vstd::contains(rclickable,*i)) continue;
-			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
-			{
-				(*i)->clickRight(false);
-			}
-			else
-				(*i)->clickRight(boost::logic::indeterminate);
-		}
-	}
-	current = NULL;
-
-} //event end
-
 int3 CPlayerInterface::repairScreenPos(int3 pos)
 {
 	if(pos.x<-CGI->mh->frameW)
@@ -1021,7 +824,7 @@ void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
 void CPlayerInterface::receivedResource(int type, int val)
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	LOCPLINT->totalRedraw();
+	GH.totalRedraw();
 }
 
 void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16>& skills, boost::function<void(ui32)> &callback)
@@ -1031,7 +834,7 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std:
 
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback);
-	LOCPLINT->pushInt(lw);
+	GH.pushInt(lw);
 }
 void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
 {
@@ -1064,7 +867,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
 		c->garr->set2 = town->visitingHero ? &town->visitingHero->army : NULL;
 		c->garr->recreateSlots();
 	}
-	LOCPLINT->totalRedraw();
+	GH.totalRedraw();
 }
 void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town)
 {
@@ -1102,7 +905,7 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 	}
 
 	bool wasGarrison = false;
-	for(std::list<IShowActivable*>::iterator i = listInt.begin(); i != listInt.end(); i++)
+	for(std::list<IShowActivable*>::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++)
 	{
 		if((*i)->type & IShowActivable::WITH_GARRISON)
 		{
@@ -1112,7 +915,7 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
 		}
 	}
 
-	LOCPLINT->totalRedraw();
+	GH.totalRedraw();
 }
 
 void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished
@@ -1151,7 +954,7 @@ void CPlayerInterface::battleStart(CCreatureSet *army1, CCreatureSet *army2, int
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	battleInt = new CBattleInterface(army1, army2, hero1, hero2, genRect(600, 800, (conf.cc.resx - 800)/2, (conf.cc.resy - 600)/2));
 	CGI->musich->playMusicFromSet(CGI->musich->battleMusics, -1);
-	pushInt(battleInt);
+	GH.pushInt(battleInt);
 }
 
 void CPlayerInterface::battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles) //called when battlefield is prepared, prior the battle beginning
@@ -1413,11 +1216,11 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 	pom.push_back(std::pair<std::string,CFunctionList<void()> >("IOKAY.DEF",0));
 	CInfoWindow * temp = new CInfoWindow(text,playerID,0,components,pom,false);
 
-	if(makingTurn && listInt.size())
+	if(makingTurn && GH.listInt.size())
 	{
 		CGI->soundh->playSound(static_cast<soundBase::soundID>(soundID));
 		showingDialog->set(true);
-		pushInt(temp);
+		GH.pushInt(temp);
 	}
 	else
 	{
@@ -1439,7 +1242,7 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, const std::vecto
 	for(int i=0;i<onNo.funcs.size();i++)
 		temp->buttons[1]->callback += onNo.funcs[i];
 
-	LOCPLINT->pushInt(temp);
+	GH.pushInt(temp);
 }
 
 void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel )
@@ -1471,7 +1274,7 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
 		}
 
 		CSelWindow * temp = new CSelWindow(text,playerID,35,intComps,pom,askID);
-		pushInt(temp);
+		GH.pushInt(temp);
 		intComps[0]->clickLeft(true);
 	}
 
@@ -1496,7 +1299,7 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	adventureInt->heroWindow->setHero(hero);
 	adventureInt->heroWindow->quitButton->callback = boost::bind(&CHeroWindow::quit,adventureInt->heroWindow);
-	pushInt(adventureInt->heroWindow);
+	GH.pushInt(adventureInt->heroWindow);
 }
 
 void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
@@ -1509,7 +1312,7 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
 		adventureInt->heroWindow->activate();
 		return;
 	}
-	CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(listInt.front());
+	CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(GH.topInt());
 	if(cew) //exchange window is open
 	{
 		cew->deactivate();
@@ -1535,13 +1338,13 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	if(castleInt && town->ID == TOWNI_TYPE)
 	{
-		CFortScreen *fs = dynamic_cast<CFortScreen*>(listInt.front());
+		CFortScreen *fs = dynamic_cast<CFortScreen*>(GH.topInt());
 		if(fs)
 			fs->draw(castleInt,false);
 	}
-	else if(listInt.size() && (town->ID == 17  ||  town->ID == 20)) //external dwelling
+	else if(GH.listInt.size() && (town->ID == 17  ||  town->ID == 20)) //external dwelling
 	{
-		CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(listInt.front());
+		CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(GH.topInt());
 		if(crw)
 			crw->initCres();
 	}
@@ -1663,73 +1466,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
 	}
 	CGarrisonWindow *cgw = new CGarrisonWindow(up,down);
 	cgw->quit->callback += onEnd;
-	pushInt(cgw);
-}
-
-void CPlayerInterface::popInt( IShowActivable *top )
-{
-	assert(listInt.front() == top);
-	top->deactivate();
-	listInt.pop_front();
-	objsToBlit -= top;
-	if(listInt.size())
-		listInt.front()->activate();
-	totalRedraw();
-}
-
-void CPlayerInterface::popIntTotally( IShowActivable *top )
-{
-	assert(listInt.front() == top);
-	popInt(top);
-	delete top;
-}
-
-void CPlayerInterface::pushInt( IShowActivable *newInt )
-{
-	//a new interface will be present, we'll need to use buffer surface (unless it's advmapint that will alter screenBuf on activate anyway)
-	screenBuf = screen2; 
-
-	if(listInt.size())
-		listInt.front()->deactivate();
-	listInt.push_front(newInt);
-	newInt->activate();
-	objsToBlit += newInt;
-	LOCPLINT->totalRedraw();
-}
-
-void CPlayerInterface::popInts( int howMany )
-{
-	if(!howMany) return; //senseless but who knows...
-
-	assert(listInt.size() > howMany);
-	listInt.front()->deactivate();
-	for(int i=0; i < howMany; i++)
-	{
-		objsToBlit -= listInt.front();
-		delete listInt.front();
-		listInt.pop_front();
-	}
-	listInt.front()->activate();
-	totalRedraw();
-}
-
-IShowActivable * CPlayerInterface::topInt()
-{
-	if(!listInt.size())
-		return NULL;
-	else 
-		return listInt.front();
-}
-
-void CPlayerInterface::totalRedraw()
-{
-	for(int i=0;i<objsToBlit.size();i++)
-		objsToBlit[i]->showAll(screen2);
-
-	blitAt(screen2,0,0,screen);
-
-	if(objsToBlit.size())
-		objsToBlit.back()->showAll(screen);
+	GH.pushInt(cgw);
 }
 
 void CPlayerInterface::requestRealized( PackageApplied *pa )
@@ -1740,7 +1477,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
 
 void CPlayerInterface::heroExchangeStarted(si32 hero1, si32 hero2)
 {
-	pushInt(new CExchangeWindow(hero2, hero1));
+	GH.pushInt(new CExchangeWindow(hero2, hero1));
 }
 
 void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
@@ -1780,7 +1517,7 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, const C
 	waitWhileDialog();
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	CRecruitmentWindow *cr = new CRecruitmentWindow(dwelling, level, dst, boost::bind(&CCallback::recruitCreatures, cb, dwelling, _1, _2));
-	pushInt(cr);
+	GH.pushInt(cr);
 }
 
 void CPlayerInterface::waitWhileDialog()
@@ -1797,7 +1534,7 @@ void CPlayerInterface::showShipyardDialog(const IShipyard *obj)
 	std::vector<si32> cost;
 	obj->getBoatCost(cost);
 	CShipyardWindow *csw = new CShipyardWindow(cost, state, boost::bind(&CCallback::buildBoat, cb, obj));
-	pushInt(csw);
+	GH.pushInt(csw);
 }
 
 void CPlayerInterface::newObject( const CGObjectInstance * obj )

+ 2 - 22
client/CPlayerInterface.h

@@ -114,39 +114,23 @@ public:
 
 	SystemOptions sysOpts;
 
-	SDL_Event * current; //current event
 	CAdvMapInt * adventureInt;
 	CCastleInterface * castleInt; //NULL if castle window isn't opened
 	CBattleInterface * battleInt; //NULL if no battle
-	CInGameConsole * cingconsole;
 	FPSmanager * mainFPSmng; //to keep const framerate
+	CInGameConsole * cingconsole;
 	IStatusBar *statusbar; //current statusbar - will be used to show hover tooltips
 	
 	CCallback * cb; //to communicate with engine
 	const BattleAction *curAction; //during the battle - action currently performed by active stack (or NULL)
 
 	std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
-	std::list<IShowActivable *> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
-	void totalRedraw(); //forces total redraw (using showAll)
-	void popInt(IShowActivable *top); //removes given interface from the top and activates next
-	void popIntTotally(IShowActivable *top); //deactivates, deletes, removes given interface from the top and activates next
-	void pushInt(IShowActivable *newInt); //deactivate old top interface, activates this one and pushes to the top
-	void popInts(int howMany); //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front
-	IShowActivable *topInt(); //returns top interface
+
 
 	std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
 	void recreateWanderingHeroes();
 	const CGHeroInstance *getWHero(int pos); //returns NULL if position is not valid
 
-	//GUI elements
-	std::list<ClickableL*> lclickable;
-	std::list<ClickableR*> rclickable;
-	std::list<Hoverable*> hoverable;
-	std::list<KeyInterested*> keyinterested;
-	std::list<MotionInterested*> motioninterested;
-	std::list<TimeInterested*> timeinterested;
-	std::vector<IShowable*> objsToBlit;
-
 	//overloaded funcs from CGameInterface
 	void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished
 	void garrisonChanged(const CGObjectInstance * obj);
@@ -206,10 +190,6 @@ public:
 	void openTownWindow(const CGTownInstance * town); //shows townscreen
 	void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
 	SDL_Surface * infoWin(const CGObjectInstance * specific); //specific=0 => draws info about selected town/hero
-	void handleEvent(SDL_Event * sEvent);
-	void handleKeyDown(SDL_Event *sEvent);
-	void handleKeyUp(SDL_Event *sEvent);
-	void handleMouseMotion(SDL_Event *sEvent);
 	void init(ICallback * CB);
 	int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
 	void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components = std::vector<SComponent*>(), int soundID = 0);

+ 2 - 2
client/CSpellWindow.cpp

@@ -318,7 +318,7 @@ CSpellWindow::~CSpellWindow()
 
 void CSpellWindow::fexitb()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CSpellWindow::fadvSpellsb()
@@ -672,7 +672,7 @@ void CSpellWindow::SpellArea::clickRight(boost::logic::tribool down)
 			CGI->spellh->spells[mySpell].name,30,30);
 		vinya->pos.x = screen->w/2 - vinya->bitmap->w/2;
 		vinya->pos.y = screen->h/2 - vinya->bitmap->h/2;
-		LOCPLINT->pushInt(vinya);
+		GH.pushInt(vinya);
 	}
 }
 

+ 1 - 1
client/Client.cpp

@@ -346,7 +346,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 	CGI->mh->init();
 	tlog0 <<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
 
-	for (size_t i=0; i<CGI->state->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
+	for (size_t i=0; i<gs->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
 	{ 
 		ui8 color = gs->scenarioOps->playerInfos[i].color;
 		CCallback *cb = new CCallback(gs,color,this);

+ 255 - 19
client/GUIBase.cpp

@@ -1,7 +1,11 @@
-#include "GUIBase.h"
 #include "SDL_Extensions.h"
-#include "CPlayerInterface.h"
-
+#include <cassert>
+#include <boost/thread/locks.hpp>
+#include "GUIBase.h"
+#include <boost/thread/mutex.hpp>
+#include <queue>
+#include "CGameInfo.h"
+#include "CCursorHandler.h"
 /*
  * GUIBase.cpp, part of VCMI engine
  *
@@ -12,6 +16,9 @@
  *
  */
 
+extern std::queue<SDL_Event*> events;
+extern boost::mutex eventsM;
+
 void KeyShortcut::keyPressed(const SDL_KeyboardEvent & key)
 {
 	if(vstd::contains(assignedKeys,key.keysym.sym))
@@ -78,12 +85,11 @@ void ClickableL::clickLeft(boost::logic::tribool down)
 }
 void ClickableL::activate()
 {
-	LOCPLINT->lclickable.push_front(this);
+	GH.lclickable.push_front(this);
 }
 void ClickableL::deactivate()
 {
-	LOCPLINT->lclickable.erase
-		(std::find(LOCPLINT->lclickable.begin(),LOCPLINT->lclickable.end(),this));
+	GH.lclickable.erase(std::find(GH.lclickable.begin(),GH.lclickable.end(),this));
 }
 
 ClickableR::ClickableR()
@@ -103,11 +109,11 @@ void ClickableR::clickRight(boost::logic::tribool down)
 }
 void ClickableR::activate()
 {
-	LOCPLINT->rclickable.push_front(this);
+	GH.rclickable.push_front(this);
 }
 void ClickableR::deactivate()
 {
-	LOCPLINT->rclickable.erase(std::find(LOCPLINT->rclickable.begin(),LOCPLINT->rclickable.end(),this));
+	GH.rclickable.erase(std::find(GH.rclickable.begin(),GH.rclickable.end(),this));
 }
 //ClickableR
 
@@ -116,12 +122,12 @@ Hoverable::~Hoverable()
 
 void Hoverable::activate()
 {
-	LOCPLINT->hoverable.push_front(this);
+	GH.hoverable.push_front(this);
 }
 
 void Hoverable::deactivate()
 {
-	LOCPLINT->hoverable.erase(std::find(LOCPLINT->hoverable.begin(),LOCPLINT->hoverable.end(),this));
+	GH.hoverable.erase(std::find(GH.hoverable.begin(),GH.hoverable.end(),this));
 }
 void Hoverable::hover(bool on)
 {
@@ -134,35 +140,265 @@ KeyInterested::~KeyInterested()
 
 void KeyInterested::activate()
 {
-	LOCPLINT->keyinterested.push_front(this);
+	GH.keyinterested.push_front(this);
 }
 
 void KeyInterested::deactivate()
 {
-	LOCPLINT->
-		keyinterested.erase(std::find(LOCPLINT->keyinterested.begin(),LOCPLINT->keyinterested.end(),this));
+	GH.keyinterested.erase(std::find(GH.keyinterested.begin(),GH.keyinterested.end(),this));
 }
 //KeyInterested
 
 void MotionInterested::activate()
 {
-	LOCPLINT->motioninterested.push_front(this);
+	GH.motioninterested.push_front(this);
 }
 
 void MotionInterested::deactivate()
 {
-	LOCPLINT->
-		motioninterested.erase(std::find(LOCPLINT->motioninterested.begin(),LOCPLINT->motioninterested.end(),this));
+	GH.motioninterested.erase(std::find(GH.motioninterested.begin(),GH.motioninterested.end(),this));
 }
 
 void TimeInterested::activate()
 {
-	LOCPLINT->timeinterested.push_back(this);
+	GH.timeinterested.push_back(this);
 }
 
 void TimeInterested::deactivate()
 {
-	LOCPLINT->
-		timeinterested.erase(std::find(LOCPLINT->timeinterested.begin(),LOCPLINT->timeinterested.end(),this));
+	GH.timeinterested.erase(std::find(GH.timeinterested.begin(),GH.timeinterested.end(),this));
+}
+
+void CGuiHandler::popInt( IShowActivable *top )
+{
+	assert(listInt.front() == top);
+	top->deactivate();
+	listInt.pop_front();
+	objsToBlit -= top;
+	if(listInt.size())
+		listInt.front()->activate();
+	totalRedraw();
+}
+
+void CGuiHandler::popIntTotally( IShowActivable *top )
+{
+	assert(listInt.front() == top);
+	popInt(top);
+	delete top;
+}
+
+void CGuiHandler::pushInt( IShowActivable *newInt )
+{
+	//a new interface will be present, we'll need to use buffer surface (unless it's advmapint that will alter screenBuf on activate anyway)
+	screenBuf = screen2; 
+
+	if(listInt.size())
+		listInt.front()->deactivate();
+	listInt.push_front(newInt);
+	newInt->activate();
+	objsToBlit.push_back(newInt);
+	totalRedraw();
+}
+
+void CGuiHandler::popInts( int howMany )
+{
+	if(!howMany) return; //senseless but who knows...
+
+	assert(listInt.size() > howMany);
+	listInt.front()->deactivate();
+	for(int i=0; i < howMany; i++)
+	{
+		objsToBlit -= listInt.front();
+		delete listInt.front();
+		listInt.pop_front();
+	}
+	listInt.front()->activate();
+	totalRedraw();
+}
+
+IShowActivable * CGuiHandler::topInt()
+{
+	if(!listInt.size())
+		return NULL;
+	else 
+		return listInt.front();
+}
+
+void CGuiHandler::totalRedraw()
+{
+	for(int i=0;i<objsToBlit.size();i++)
+		objsToBlit[i]->showAll(screen2);
+
+	blitAt(screen2,0,0,screen);
+
+	if(objsToBlit.size())
+		objsToBlit.back()->showAll(screen);
+}
+
+void CGuiHandler::updateTime()
+{
+	int tv = th.getDif();
+	std::list<TimeInterested*> hlp = timeinterested;
+	for (std::list<TimeInterested*>::iterator i=hlp.begin(); i != hlp.end();i++)
+	{
+		if(!vstd::contains(timeinterested,*i)) continue;
+		if ((*i)->toNextTick>=0)
+			(*i)->toNextTick-=tv;
+		if ((*i)->toNextTick<0)
+			(*i)->tick();
+	}
+}
+
+void CGuiHandler::handleEvents()
+{
+	while(true)
+	{
+		SDL_Event *ev = NULL;
+		{
+			boost::unique_lock<boost::mutex> lock(eventsM);
+			if(!events.size())
+			{
+				return;
+			}
+			else
+			{
+				ev = events.front();
+				events.pop();
+			}
+		}
+		handleEvent(ev);
+		delete ev;
+	}
 }
 
+void CGuiHandler::handleEvent(SDL_Event *sEvent)
+{
+	current = sEvent;
+
+	if (sEvent->type==SDL_KEYDOWN || sEvent->type==SDL_KEYUP)
+	{
+		SDL_KeyboardEvent key = sEvent->key;
+
+		//translate numpad keys
+		if (key.keysym.sym >= SDLK_KP0  && key.keysym.sym <= SDLK_KP9)
+		{
+			key.keysym.sym = (SDLKey) (key.keysym.sym - SDLK_KP0 + SDLK_0);
+		}
+		else if(key.keysym.sym == SDLK_KP_ENTER)
+		{
+			key.keysym.sym = (SDLKey)SDLK_RETURN;
+		}
+
+		bool keysCaptured = false;
+		for(std::list<KeyInterested*>::iterator i=keyinterested.begin(); i != keyinterested.end();i++)
+		{
+			if((*i)->captureAllKeys)
+			{
+				keysCaptured = true;
+				break;
+			}
+		}
+
+		std::list<KeyInterested*> miCopy = keyinterested;
+		for(std::list<KeyInterested*>::iterator i=miCopy.begin(); i != miCopy.end();i++)
+			if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureAllKeys))
+				(**i).keyPressed(key);
+	}
+	else if(sEvent->type==SDL_MOUSEMOTION)
+	{
+		CGI->curh->cursorMove(sEvent->motion.x, sEvent->motion.y);
+		handleMouseMotion(sEvent);
+	}
+	else if ((sEvent->type==SDL_MOUSEBUTTONDOWN) && (sEvent->button.button == SDL_BUTTON_LEFT))
+	{
+		std::list<ClickableL*> hlp = lclickable;
+		for(std::list<ClickableL*>::iterator i=hlp.begin(); i != hlp.end();i++)
+		{
+			if(!vstd::contains(lclickable,*i)) continue;
+			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+			{
+				(*i)->clickLeft(true);
+			}
+		}
+	}
+	else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT))
+	{
+		std::list<ClickableL*> hlp = lclickable;
+		for(std::list<ClickableL*>::iterator i=hlp.begin(); i != hlp.end();i++)
+		{
+			if(!vstd::contains(lclickable,*i)) continue;
+			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+			{
+				(*i)->clickLeft(false);
+			}
+			else
+				(*i)->clickLeft(boost::logic::indeterminate);
+		}
+	}
+	else if ((sEvent->type==SDL_MOUSEBUTTONDOWN) && (sEvent->button.button == SDL_BUTTON_RIGHT))
+	{
+		std::list<ClickableR*> hlp = rclickable;
+		for(std::list<ClickableR*>::iterator i=hlp.begin(); i != hlp.end();i++)
+		{
+			if(!vstd::contains(rclickable,*i)) continue;
+			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+			{
+				(*i)->clickRight(true);
+			}
+		}
+	}
+	else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_RIGHT))
+	{
+		std::list<ClickableR*> hlp = rclickable;
+		for(std::list<ClickableR*>::iterator i=hlp.begin(); i != hlp.end();i++)
+		{
+			if(!vstd::contains(rclickable,*i)) continue;
+			if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+			{
+				(*i)->clickRight(false);
+			}
+			else
+				(*i)->clickRight(boost::logic::indeterminate);
+		}
+	}
+	current = NULL;
+
+} //event end
+
+void CGuiHandler::handleMouseMotion(SDL_Event *sEvent)
+{
+	//sending active, hovered hoverable objects hover() call
+	std::vector<Hoverable*> hlp;
+	for(std::list<Hoverable*>::iterator i=hoverable.begin(); i != hoverable.end();i++)
+	{
+		if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+		{
+			if (!(*i)->hovered)
+				hlp.push_back((*i));
+		}
+		else if ((*i)->hovered)
+		{
+			(*i)->hover(false);
+		}
+	}
+	for(int i=0; i<hlp.size();i++)
+		hlp[i]->hover(true);
+
+	//sending active, MotionInterested objects mouseMoved() call
+	std::list<MotionInterested*> miCopy = motioninterested;
+	for(std::list<MotionInterested*>::iterator i=miCopy.begin(); i != miCopy.end();i++)
+	{
+		if ((*i)->strongInterest || isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y))
+		{
+			(*i)->mouseMoved(sEvent->motion);
+		}
+	}
+}
+
+void CGuiHandler::simpleRedraw()
+{
+	//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
+}

+ 36 - 0
client/GUIBase.h

@@ -4,6 +4,9 @@
 #include "../global.h"
 #include "SDL.h"
 #include <set>
+#include <list>
+#include "../timeHandler.h"
+
 
 #ifdef max
 #undef max
@@ -381,6 +384,39 @@ public:
 	virtual void deactivate();
 };
 
+class CGuiHandler
+{
+public:
+	timeHandler th;
+	std::list<IShowActivable *> listInt; //list of interfaces - front=foreground; back = background (includes adventure map, window interfaces, all kind of active dialogs, and so on)
+
+	//active GUI elements (listening for events
+	std::list<ClickableL*> lclickable;
+	std::list<ClickableR*> rclickable;
+	std::list<Hoverable*> hoverable;
+	std::list<KeyInterested*> keyinterested;
+	std::list<MotionInterested*> motioninterested;
+	std::list<TimeInterested*> timeinterested;
+
+	//objs to blit
+	std::vector<IShowable*> objsToBlit;
+
+	SDL_Event * current; //current event
+
+	void totalRedraw(); //forces total redraw (using showAll)
+	void simpleRedraw(); //update only top interface and draw background from buffer
+	void popInt(IShowActivable *top); //removes given interface from the top and activates next
+	void popIntTotally(IShowActivable *top); //deactivates, deletes, removes given interface from the top and activates next
+	void pushInt(IShowActivable *newInt); //deactivate old top interface, activates this one and pushes to the top
+	void popInts(int howMany); //pops one or more interfaces - deactivates top, deletes and removes given number of interfaces, activates new front
+	IShowActivable *topInt(); //returns top interface
+	void updateTime(); //handles timeInterested
+	void handleEvents(); //takes events from queue and calls interested objects
+	void handleEvent(SDL_Event *sEvent);
+
+	void handleMouseMotion(SDL_Event *sEvent);
+};
 
+extern CGuiHandler GH; //global gui handler
 
 #endif //__GUIBASE_H__

+ 90 - 70
client/GUIClasses.cpp

@@ -168,10 +168,10 @@ const CArmedInstance * CGarrisonSlot::getObj()
 
 void CGarrisonSlot::clickRight (tribool down)
 {
-	StackState *pom = getStackState(getObj(),ID, LOCPLINT->topInt() == LOCPLINT->castleInt);
+	StackState *pom = getStackState(getObj(),ID, GH.topInt() == LOCPLINT->castleInt);
 	if(down && creature)
 	{
-		LOCPLINT->pushInt(new CCreInfoWindow(creature->idNumber, 0, count, pom, 0, 0, NULL));
+		GH.pushInt(new CCreInfoWindow(creature->idNumber, 0, count, pom, 0, 0, NULL));
 	}
 	delete pom;
 }
@@ -189,7 +189,7 @@ void CGarrisonSlot::clickLeft(tribool down)
 		{
 			if(owner->highlighted == this) //view info
 			{
-				StackState *pom2 = getStackState(getObj(), ID, LOCPLINT->topInt() == LOCPLINT->castleInt);
+				StackState *pom2 = getStackState(getObj(), ID, GH.topInt() == LOCPLINT->castleInt);
 				UpgradeInfo pom = LOCPLINT->cb->getUpgradeInfo(getObj(), ID);
 
 				CCreInfoWindow *creWindow = NULL;
@@ -208,7 +208,7 @@ void CGarrisonSlot::clickLeft(tribool down)
 						boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID), NULL);
 				}
 
-				LOCPLINT->pushInt(creWindow);
+				GH.pushInt(creWindow);
 
 				owner->highlighted = NULL;
 				show(screen2);
@@ -245,7 +245,7 @@ void CGarrisonSlot::clickLeft(tribool down)
 
 
 				CSplitWindow * spw = new CSplitWindow(owner->highlighted->creature->idNumber, totalAmount, owner, last, count);
-				LOCPLINT->pushInt(spw);
+				GH.pushInt(spw);
 				refr = true;
 			}
 			else if(creature != owner->highlighted->creature) //swap
@@ -602,7 +602,7 @@ CInfoWindow::CInfoWindow()
 }
 void CInfoWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 	LOCPLINT->showingDialog->setn(false);
 }
 void CInfoWindow::show(SDL_Surface * to)
@@ -655,7 +655,7 @@ void CRClickPopup::deactivate()
 
 void CRClickPopup::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free)
@@ -683,7 +683,7 @@ void CInfoPopup::close()
 {
 	if(free)
 		SDL_FreeSurface(bitmap);
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 void CInfoPopup::show(SDL_Surface * to)
 {
@@ -1024,7 +1024,7 @@ void CStatusBar::print(const std::string & text)
 	if(LOCPLINT->cingconsole->enteredText == "" || text == LOCPLINT->cingconsole->enteredText) //for appropriate support for in-game console
 	{
 		current=text;
-		show(LOCPLINT->topInt()==LOCPLINT->adventureInt ? screen : screen2); //if there are now windows opened, update statusbar on screen, else to cache surface
+		show(GH.topInt()==LOCPLINT->adventureInt ? screen : screen2); //if there are now windows opened, update statusbar on screen, else to cache surface
 	}
 }
 
@@ -1135,7 +1135,7 @@ void CHeroList::clickLeft(tribool down)
 	if (down)
 	{
 		/***************************ARROWS*****************************************/
-		if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+		if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y))
 		{
 			if(from>0)
 			{
@@ -1144,7 +1144,7 @@ void CHeroList::clickLeft(tribool down)
 			}
 			return;
 		}
-		else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+		else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y))
 		{
 			if(heroes.size()-from>SIZE)
 			{
@@ -1154,7 +1154,7 @@ void CHeroList::clickLeft(tribool down)
 			return;
 		}
 		/***************************HEROES*****************************************/
-		int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y;
+		int hx = GH.current->motion.x, hy = GH.current->motion.y;
 		hx-=pos.x;
 		hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h;
 		int ny = hy/32;
@@ -1201,7 +1201,7 @@ void CHeroList::clickLeft(tribool down)
 
 void CHeroList::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 {
-	if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+	if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y))
 	{
 		if (from>0)
 			LOCPLINT->adventureInt->statusbar.print(CGI->generaltexth->zelp[303].first);
@@ -1209,7 +1209,7 @@ void CHeroList::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 			LOCPLINT->adventureInt->statusbar.clear();
 		return;
 	}
-	else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+	else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y))
 	{
 		if ((heroes.size()-from)  >  SIZE)
 			LOCPLINT->adventureInt->statusbar.print(CGI->generaltexth->zelp[304].first);
@@ -1218,7 +1218,7 @@ void CHeroList::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 		return;
 	}
 	//if not buttons then heroes
-	int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y;
+	int hx = GH.current->motion.x, hy = GH.current->motion.y;
 	hx-=pos.x;
 	hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h;
 	int ny = hy/32;
@@ -1239,18 +1239,18 @@ void CHeroList::clickRight(tribool down)
 	if (down)
 	{
 		/***************************ARROWS*****************************************/
-		if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y) && from>0)
+		if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y) && from>0)
 		{
 			LOCPLINT->adventureInt->handleRightClick(CGI->generaltexth->zelp[303].second,down,this);
 		}
-		else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y) && (heroes.size()-from>5))
+		else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y) && (heroes.size()-from>5))
 		{
 			LOCPLINT->adventureInt->handleRightClick(CGI->generaltexth->zelp[304].second,down,this);
 		}
 		else
 		{
 			//if not buttons then heroes
-			int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y;
+			int hx = GH.current->motion.x, hy = GH.current->motion.y;
 			hx-=pos.x;
 			hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h;
 			int ny = hy/32;
@@ -1261,10 +1261,10 @@ void CHeroList::clickRight(tribool down)
 
 			//show popup
 			CInfoPopup * ip = new CInfoPopup(graphics->heroWins[heroes[from+ny]->subID],
-				LOCPLINT->current->motion.x-graphics->heroWins[heroes[from+ny]->subID]->w,
-				LOCPLINT->current->motion.y-graphics->heroWins[heroes[from+ny]->subID]->h,
+				GH.current->motion.x-graphics->heroWins[heroes[from+ny]->subID]->w,
+				GH.current->motion.y-graphics->heroWins[heroes[from+ny]->subID]->h,
 				false);
-			LOCPLINT->pushInt(ip);
+			GH.pushInt(ip);
 		}
 	}
 	else
@@ -1410,7 +1410,7 @@ void CTownList::select(int which)
 
 void CTownList::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 {
-	if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+	if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y))
 	{
 		if (from>0)
 			LOCPLINT->statusbar->print(CGI->generaltexth->zelp[306].first);
@@ -1418,7 +1418,7 @@ void CTownList::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 			LOCPLINT->statusbar->clear();
 		return;
 	}
-	else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+	else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y))
 	{
 		if ((items.size()-from)  >  SIZE)
 			LOCPLINT->statusbar->print(CGI->generaltexth->zelp[307].first);
@@ -1427,7 +1427,7 @@ void CTownList::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 		return;
 	}
 	//if not buttons then towns
-	int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y;
+	int hx = GH.current->motion.x, hy = GH.current->motion.y;
 	hx-=pos.x;
 	hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h;
 	int ny = hy/32;
@@ -1444,7 +1444,7 @@ void CTownList::clickLeft(tribool down)
 	if (down)
 	{
 		/***************************ARROWS*****************************************/
-		if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+		if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y))
 		{
 			if(from>0)
 			{
@@ -1453,7 +1453,7 @@ void CTownList::clickLeft(tribool down)
 			}
 			return;
 		}
-		else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+		else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y))
 		{
 			if(items.size()-from > SIZE)
 			{
@@ -1463,13 +1463,13 @@ void CTownList::clickLeft(tribool down)
 			return;
 		}
 		/***************************TOWNS*****************************************/
-		int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y;
+		int hx = GH.current->motion.x, hy = GH.current->motion.y;
 		hx-=pos.x;
 		hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h;
 		int ny = hy/32;
 		if (ny>SIZE || ny<0)
 			return;
-		if(LOCPLINT->topInt() == LOCPLINT->adventureInt
+		if(GH.topInt() == LOCPLINT->adventureInt
 		  && (ny+from)==selected 
 		  && LOCPLINT->adventureInt->selection->ID == TOWNI_TYPE
 		  )
@@ -1518,16 +1518,16 @@ void CTownList::clickRight(tribool down)
 	if (down)
 	{
 		/***************************ARROWS*****************************************/
-		if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y) && from>0)
+		if(isItIn(&arrupp,GH.current->motion.x,GH.current->motion.y) && from>0)
 		{
 			LOCPLINT->adventureInt->handleRightClick(CGI->generaltexth->zelp[306].second,down,this);
 		}
-		else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y) && (items.size()-from>5))
+		else if(isItIn(&arrdop,GH.current->motion.x,GH.current->motion.y) && (items.size()-from>5))
 		{
 			LOCPLINT->adventureInt->handleRightClick(CGI->generaltexth->zelp[307].second,down,this);
 		}
 		//if not buttons then towns
-		int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y;
+		int hx = GH.current->motion.x, hy = GH.current->motion.y;
 		hx-=pos.x;
 		hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h;
 		int ny = hy/32;
@@ -1539,10 +1539,10 @@ void CTownList::clickRight(tribool down)
 		//show popup
 		CInfoPopup * ip = new CInfoPopup(
 			graphics->townWins[items[from+ny]->id],
-			LOCPLINT->current->motion.x-graphics->townWins[items[from+ny]->id]->w,
-			LOCPLINT->current->motion.y-graphics->townWins[items[from+ny]->id]->h,
+			GH.current->motion.x-graphics->townWins[items[from+ny]->id]->w,
+			GH.current->motion.y-graphics->townWins[items[from+ny]->id]->h,
 			false);
-		LOCPLINT->pushInt(ip);
+		GH.pushInt(ip);
 	}
 	else
 	{
@@ -1622,7 +1622,7 @@ SDL_Surface * CCreaturePic::getPic(bool nextFrame)
 }
 void CRecruitmentWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 void CRecruitmentWindow::Max()
 {
@@ -1630,7 +1630,27 @@ void CRecruitmentWindow::Max()
 }
 void CRecruitmentWindow::Buy()
 {
-	recruit(creatures[which].ID, slider->value);
+	int crid = creatures[which].ID,
+		dstslot = dst->army.getSlotFor(crid);
+
+	if(dstslot < 0) //no available slot
+	{
+		std::string txt;
+		if(dst->ID == HEROI_TYPE)
+		{
+			txt = CGI->generaltexth->allTexts[425]; //The %s would join your hero, but there aren't enough provisions to support them.
+			boost::algorithm::replace_first(txt, "%s", slider->value > 1 ? CGI->creh->creatures[crid].namePl : CGI->creh->creatures[crid].nameSing);
+		}
+		else
+		{
+			txt = CGI->generaltexth->allTexts[17]; //There is no room in the garrison for this army.
+		}
+
+		LOCPLINT->showInfoDialog(txt);
+		return;
+	}
+
+	recruit(crid, slider->value);
 	if(level >= 0)
 		close();
 	else
@@ -1647,10 +1667,10 @@ void CRecruitmentWindow::sliderMoved(int to)
 }
 void CRecruitmentWindow::clickLeft(tribool down)
 {
-	int curx = 192 + 51 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2);
+	int curx = 192 + 51 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
 	for(int i=0;i<creatures.size();i++)
 	{
-		if(isItIn(&genRect(132,102,pos.x+curx,pos.y+64),LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+		if(isItIn(&genRect(132,CREATURE_WIDTH,pos.x+curx,pos.y+64),GH.current->motion.x,GH.current->motion.y))
 		{
 			which = i;
 			int newAmount = std::min(amounts[i],creatures[i].amount);
@@ -1659,34 +1679,34 @@ void CRecruitmentWindow::clickLeft(tribool down)
 				slider->moveTo(newAmount);
 			else
 				slider->moveTo(slider->value);
-			curx = 192 + 51 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
+			curx = 192 + 51 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
 			for(int j=0;j<creatures.size();j++)
 			{
 				if(which==j)
-					drawBorder(bitmap,curx,64,102,132,int3(255,0,0));
+					drawBorder(bitmap,curx,64,CREATURE_WIDTH,132,int3(255,0,0));
 				else
-					drawBorder(bitmap,curx,64,102,132,int3(239,215,123));
-				curx += 115;
+					drawBorder(bitmap,curx,64,CREATURE_WIDTH,132,int3(239,215,123));
+				curx += TOTAL_CREATURE_WIDTH;
 			}
 			break;
 		}
-		curx += 115;
+		curx += TOTAL_CREATURE_WIDTH;
 	}
 }
 void CRecruitmentWindow::clickRight( boost::logic::tribool down )
 {
 	if(down)
 	{
-		int curx = 192 + 51 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
+		int curx = 192 + 51 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
 		for(int i=0;i<creatures.size();i++)
 		{
-			if(isItIn(&genRect(132,102,pos.x+curx,pos.y+64),LOCPLINT->current->motion.x,LOCPLINT->current->motion.y))
+			if(isItIn(&genRect(132,CREATURE_WIDTH,pos.x+curx,pos.y+64),GH.current->motion.x,GH.current->motion.y))
 			{
 				CCreInfoWindow *popup = new CCreInfoWindow(creatures[i].ID, 0, 0, NULL, NULL, NULL, NULL);
-				LOCPLINT->pushInt(popup);
+				GH.pushInt(popup);
 				break;
 			}
-			curx += 115;
+			curx += TOTAL_CREATURE_WIDTH;
 		}
 	}
 }
@@ -1740,11 +1760,11 @@ void CRecruitmentWindow::show(SDL_Surface * to)
 		curx+=32;
 	}
 
-	curx = pos.x + 192 + 102 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
+	curx = pos.x + 192 + CREATURE_WIDTH - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
 	for(int i=0; i<creatures.size(); ++i)
 	{
 		creatures[i].pic->blitPic(to, curx-50, pos.y+130-65, !(animCounter%4));
-		curx += 115;
+		curx += TOTAL_CREATURE_WIDTH;
 	}
 
 	++animCounter;
@@ -1785,7 +1805,7 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co
 	drawBorder(bitmap,289,312,66,34,int3(173,142,66));
 
 	//border for creatures
-	int curx = 192 + 51 - (102*creatures.size()/2) - (13*(creatures.size()-1)/2);
+	int curx = 192 + 51 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
 	for(int i=0;i<creatures.size();i++)
 	{
 		creatures[i].pos.x = curx+1;
@@ -1793,10 +1813,10 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co
 		creatures[i].pos.w = 100;
 		creatures[i].pos.h = 130;
 		if(which==i)
-			drawBorder(bitmap,curx,64,102,132,int3(255,0,0));
+			drawBorder(bitmap,curx,64,CREATURE_WIDTH,132,int3(255,0,0));
 		else
-			drawBorder(bitmap,curx,64,102,132,int3(239,215,123));
-		curx += 115;
+			drawBorder(bitmap,curx,64,CREATURE_WIDTH,132,int3(239,215,123));
+		curx += TOTAL_CREATURE_WIDTH;
 	}
 
 	if(!creatures[0].amount ||  !amounts[0])
@@ -1919,7 +1939,7 @@ void CSplitWindow::split()
 
 void CSplitWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CSplitWindow::sliderMoved(int to)
@@ -1980,7 +2000,7 @@ void CSplitWindow::clickLeft( boost::logic::tribool down )
 {
 	if(down)
 	{
-		Point click(LOCPLINT->current->motion.x,LOCPLINT->current->motion.y);
+		Point click(GH.current->motion.x,GH.current->motion.y);
 		click -= pos.topLeft();
 		if(Rect(19,216,105,40).isIn(click)) //left picture
 			which = 0;
@@ -2219,7 +2239,7 @@ void CCreInfoWindow::activate()
 
 void CCreInfoWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CCreInfoWindow::clickRight(boost::logic::tribool down)
@@ -2262,7 +2282,7 @@ void CLevelWindow::close()
 			break;
 		}
 	}
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 	LOCPLINT->showingDialog->setn(false);
 }
 
@@ -2432,7 +2452,7 @@ void CMarketplaceWindow::CTradeableItem::show(SDL_Surface * to)
 
 void CMarketplaceWindow::CTradeableItem::clickLeft( boost::logic::tribool down )
 {
-	CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(LOCPLINT->topInt());
+	CMarketplaceWindow *mw = dynamic_cast<CMarketplaceWindow *>(GH.topInt());
 	assert(mw);
 	if(down)
 	{
@@ -2539,7 +2559,7 @@ CMarketplaceWindow::CMarketplaceWindow(int Mode)
 	slider = new CSlider(pos.x+231,pos.y+490,137,boost::bind(&CMarketplaceWindow::sliderMoved,this,_1),0,0);
 	setMode(mode);
 	hLeft = hRight = NULL;
-	ok = new AdventureMapButton("","",boost::bind(&CPlayerInterface::popIntTotally,LOCPLINT,this),pos.x+516,pos.y+520,"IOK6432.DEF",SDLK_RETURN);
+	ok = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally,&GH,this),pos.x+516,pos.y+520,"IOK6432.DEF",SDLK_RETURN);
 	ok->assignedKeys.insert(SDLK_ESCAPE);
 	deal = new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::makeDeal,this),pos.x+307,pos.y+520,"TPMRKB.DEF");
 	max = new AdventureMapButton("","",boost::bind(&CMarketplaceWindow::setMax,this),pos.x+229,pos.y+520,"IRCBTNS.DEF");
@@ -2758,7 +2778,7 @@ void CSystemOptionsWindow::bquitf()
 
 void CSystemOptionsWindow::breturnf()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 
@@ -2908,7 +2928,7 @@ void CTavernWindow::deactivate()
 
 void CTavernWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CTavernWindow::show(SDL_Surface * to)
@@ -2966,7 +2986,7 @@ void CTavernWindow::HeroPortrait::clickRight(boost::logic::tribool down)
 	if(down)
 	{
 		LOCPLINT->adventureInt->heroWindow->setHero(h);
-		LOCPLINT->pushInt(new CRClickPopupInt(LOCPLINT->adventureInt->heroWindow,false));
+		GH.pushInt(new CRClickPopupInt(LOCPLINT->adventureInt->heroWindow,false));
 	}
 }
 CTavernWindow::HeroPortrait::HeroPortrait(int &sel, int id, int x, int y, const CGHeroInstance *H)
@@ -3154,7 +3174,7 @@ void CInGameConsole::keyPressed (const SDL_KeyboardEvent & key)
 void CInGameConsole::startEnteringText()
 {
 	enteredText = "_";
-	if(LOCPLINT->topInt() == LOCPLINT->adventureInt)
+	if(GH.topInt() == LOCPLINT->adventureInt)
 	{
 		LOCPLINT->statusbar->print(enteredText);
 	}
@@ -3175,7 +3195,7 @@ void CInGameConsole::endEnteringText(bool printEnteredText)
 		print(txt);
 	}
 	enteredText = "";
-	if(LOCPLINT->topInt() == LOCPLINT->adventureInt)
+	if(GH.topInt() == LOCPLINT->adventureInt)
 	{
 		LOCPLINT->statusbar->clear();
 	}
@@ -3188,7 +3208,7 @@ void CInGameConsole::endEnteringText(bool printEnteredText)
 
 void CInGameConsole::refreshEnteredText()
 {
-	if(LOCPLINT->topInt() == LOCPLINT->adventureInt)
+	if(GH.topInt() == LOCPLINT->adventureInt)
 	{
 		LOCPLINT->statusbar->print(enteredText);
 	}
@@ -3205,7 +3225,7 @@ CInGameConsole::CInGameConsole() : prevEntDisp(-1), defaultTimeout(10000), maxDi
 
 void CGarrisonWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CGarrisonWindow::activate()
@@ -3314,7 +3334,7 @@ void CArtPlace::clickLeft(boost::logic::tribool down)
 		if(ourArt->id == 0)
 		{
 			CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (conf.cc.resx - 620)/2, (conf.cc.resy - 595)/2), ourOwner->curHero);
-			LOCPLINT->pushInt(spellWindow);
+			GH.pushInt(spellWindow);
 		}
 	}
 	if(!down && !clicked && pressedL) //not clicked before
@@ -3707,7 +3727,7 @@ CArtifactsOfHero::~CArtifactsOfHero()
 
 void CExchangeWindow::close()
 {
-	LOCPLINT->popIntTotally(this);
+	GH.popIntTotally(this);
 }
 
 void CExchangeWindow::activate()
@@ -4089,8 +4109,8 @@ CShipyardWindow::CShipyardWindow(const std::vector<si32> &cost, int state, const
 		}
 	}
 
-	quit = new AdventureMapButton(CGI->generaltexth->allTexts[599], "", boost::bind(&CPlayerInterface::popIntTotally, LOCPLINT, this), pos.x+224, pos.y+312, "ICANCEL.DEF", SDLK_RETURN);
-	build = new AdventureMapButton(CGI->generaltexth->allTexts[598], "", boost::bind(&CPlayerInterface::popIntTotally, LOCPLINT, this), pos.x+42, pos.y+312, "IBY6432.DEF", SDLK_RETURN);
+	quit = new AdventureMapButton(CGI->generaltexth->allTexts[599], "", boost::bind(&CGuiHandler::popIntTotally, &GH, this), pos.x+224, pos.y+312, "ICANCEL.DEF", SDLK_RETURN);
+	build = new AdventureMapButton(CGI->generaltexth->allTexts[598], "", boost::bind(&CGuiHandler::popIntTotally, &GH, this), pos.x+42, pos.y+312, "IBY6432.DEF", SDLK_RETURN);
 	build->callback += onBuy;
 
 	if(!affordable)

+ 4 - 0
client/GUIClasses.h

@@ -327,6 +327,10 @@ public:
 class CRecruitmentWindow : public IShowActivable, public ClickableL, public ClickableR
 {
 public:
+	static const int SPACE_BETWEEN = 8;
+	static const int CREATURE_WIDTH = 102;
+	static const int TOTAL_CREATURE_WIDTH = SPACE_BETWEEN + CREATURE_WIDTH;
+
 	struct creinfo
 	{
 		SDL_Rect pos;

+ 1 - 1
client/SDL_Extensions.h

@@ -1,9 +1,9 @@
 #ifndef __SDL_EXTENSIONS_H__
 #define __SDL_EXTENSIONS_H__
+#include "../global.h"
 #include "SDL.h"
 #include "SDL_ttf.h"
 #include <string>
-#include "../int3.h"
 #include <vector>
 #include <sstream>
 

+ 16 - 9
hch/CObjectHandler.cpp

@@ -986,7 +986,7 @@ void CGDwelling::initObj()
 			if(crs->level > 4)
 			{
 				army.slots[0].first = crs->idNumber;
-				army.slots[0].second = crs->getRandomAmount(ran);
+				army.slots[0].second = (8 - crs->level) * 3;
 			}
 		}
 		break;
@@ -1001,17 +1001,19 @@ void CGDwelling::initObj()
 			creatures[3].second.push_back(117); //Diamond Golem
 			//guards
 			army.slots[0].first = 116;
-			army.slots[0].second = VLC->creh->creatures[116].getRandomAmount(ran);
+			army.slots[0].second = 9;
+			army.slots[1].first = 117;
+			army.slots[1].second = 6;
 		}
 		else if(subID == 0) // Elemental Conflux 
 		{
 			creatures[0].second.push_back(112); //Air Elemental
-			creatures[1].second.push_back(113); //Earth Elemental
-			creatures[2].second.push_back(114); //Fire Elemental
+			creatures[1].second.push_back(114); //Fire Elemental
+			creatures[2].second.push_back(113); //Earth Elemental
 			creatures[3].second.push_back(115); //Water Elemental
 			//guards
 			army.slots[0].first = 113;
-			army.slots[0].second = VLC->creh->creatures[113].getRandomAmount(ran);
+			army.slots[0].second = 12;
 		}
 		else
 		{
@@ -1047,9 +1049,11 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 	BlockingDialog bd;
 	bd.player = h->tempOwner;
 	bd.flags = BlockingDialog::ALLOW_CANCEL;
-	bd.text.addTxt(MetaString::ADVOB_TXT, 35); //{%s}	Would you like to recruit %s?
-	bd.text.addReplacement(MetaString::CREGENS, subID);
-	bd.text.addReplacement(MetaString::CRE_PL_NAMES, creatures[0].second[0]);
+	bd.text.addTxt(MetaString::ADVOB_TXT, ID == 17 ? 35 : 36); //{%s} Would you like to recruit %s?
+	bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
+	for(size_t i = 0; i < creatures.size(); i++)
+		bd.text.addReplacement(MetaString::CRE_PL_NAMES, creatures[i].second[0]);
+
 	cb->showBlockingDialog(&bd, boost::bind(&CGDwelling::heroAcceptsCreatures, this, h, _1));
 }
 
@@ -1071,7 +1075,10 @@ void CGDwelling::newTurn() const
 	{
 		if(creatures[i].second.size())
 		{
-			sac.creatures[i].first += VLC->creh->creatures[creatures[i].second[0]].growth;
+			if(false /*accumulate creatures*/)
+				sac.creatures[i].first += VLC->creh->creatures[creatures[i].second[0]].growth;
+			else
+				sac.creatures[i].first = VLC->creh->creatures[creatures[i].second[0]].growth;
 			change = true;
 		}
 	}