ソースを参照

- recursive directory parser for LodHandler - for creature abilities and new main menu images
- fixed screen updating on closing window
- minor fixes

Ivan Savenko 14 年 前
コミット
61af4c745e

+ 5 - 2
client/AdventureMapButton.cpp

@@ -54,8 +54,11 @@ void CButtonBase::update()
 		else if (newPos == 1) newPos = 0;
 	}
 	image->setFrame(newPos);
-	showAll(screen);
-	showAll(screen2);//Any way to remove one of showAll()?
+	if (active)
+	{
+		showAll(screen);
+		showAll(screen2);//Any way to remove one of showAll()?
+	}
 }
 
 void CButtonBase::addTextOverlay( const std::string &Text, EFonts font, SDL_Color color)

+ 13 - 0
client/CAdvmapInterface.cpp

@@ -97,7 +97,20 @@ CMinimap::CMinimap(bool draw)
 CMinimap::~CMinimap()
 {
 	SDL_FreeSurface(temps);
+	
+	for(int g=0; g<map.size(); ++g)
+		SDL_FreeSurface(map[g]);
+	map.clear();
+
+	for(int g=0; g<FoW.size(); ++g)
+		SDL_FreeSurface(FoW[g]);
+	FoW.clear();
+
+	for(int g=0; g<flObjs.size(); ++g)
+		SDL_FreeSurface(flObjs[g]);
+	flObjs.clear();
 }
+
 void CMinimap::draw(SDL_Surface * to)
 {
 	int3 mapSizes = LOCPLINT->cb->getMapSize();

+ 13 - 7
client/CAnimation.cpp

@@ -74,6 +74,7 @@ class TextParser
 	int type;
 	size_t position;
 	std::string text;
+	std::string getLine();
 public:
 	TextParser(const std::string &name);
 	int getType() const;
@@ -875,6 +876,13 @@ TextParser::TextParser(const std::string &name):
 		type = 2;
 }
 
+std::string TextParser::getLine()
+{
+	size_t lineStart = position+1;
+	position = text.find('\n', lineStart);
+	return text.substr(lineStart, position-lineStart);
+}
+
 int TextParser::getType() const
 {
 	return type;
@@ -882,22 +890,20 @@ int TextParser::getType() const
 
 void TextParser::parseFile(std::map<size_t, std::vector <std::string> > &result)
 {
+	std::string baseDir = getLine();
+
 	while (position != std::string::npos)
 	{
-		size_t lineStart = position+1;
-		position = text.find('\n', lineStart);
-		std::string buf = text.substr(lineStart, position-lineStart);
+		std::string buf = getLine();
 		size_t currentBlock = atoi(buf.c_str());
 
 		while (position != std::string::npos)
 		{
-			lineStart = position+1;
-			position = text.find('\n', lineStart);
-			std::string res = text.substr(lineStart, position-lineStart);
+			std::string res = getLine();
 			boost::algorithm::trim(res);
 			if (res.empty())
 				break;
-			result[currentBlock].push_back(res);
+			result[currentBlock].push_back(baseDir+'/'+res);
 		}
 	}
 }

+ 1 - 0
client/CBitmapHandler.cpp

@@ -188,6 +188,7 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
 		ret = IMG_Load_RW( SDL_RWFromMem((void*)file, size), 1);
 		if (!ret)
 			tlog1<<"Failed to open "<<fname<<" via SDL_Image\n";
+		delete [] file;
 	}
 	return ret;
 }

+ 6 - 6
client/CMessage.cpp

@@ -59,25 +59,25 @@ namespace NMessage
 void CMessage::init()
 {
 	{
+		piecesOfBox.resize(PLAYER_LIMIT);
 		for (int i=0;i<PLAYER_LIMIT;i++)
 		{
-			//FIXME: memory leak. Use SDL_Surface::refcount++ for each required surface
-			//that should not be deleted by CDefHandler destructor
 			CDefHandler * bluePieces = CDefHandler::giveDef("DIALGBOX.DEF");
-			std::vector<SDL_Surface *> n;
-			piecesOfBox.push_back(n);
 			if (i==1)
 			{
 				for (size_t j=0;j<bluePieces->ourImages.size();++j)
 				{
 					piecesOfBox[i].push_back(bluePieces->ourImages[j].bitmap);
+					bluePieces->ourImages[j].bitmap->refcount++;
 				}
 			}
 			for (size_t j=0;j<bluePieces->ourImages.size();++j)
 			{
 				graphics->blueToPlayersAdv(bluePieces->ourImages[j].bitmap,i);
 				piecesOfBox[i].push_back(bluePieces->ourImages[j].bitmap);
+				bluePieces->ourImages[j].bitmap->refcount++;
 			}
+			delete bluePieces;
 		}
 		NMessage::background = BitmapHandler::loadBitmap("DIBOXBCK.BMP");
 		SDL_SetColorKey(background,SDL_SRCCOLORKEY,SDL_MapRGB(background->format,0,255,255));
@@ -123,7 +123,7 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineSi
 {
 	std::vector<std::string> ret;
 
-	boost::algorithm::trim_right_if(text,boost::algorithm::is_any_of(" "));
+	boost::algorithm::trim_right_if(text,boost::algorithm::is_any_of(std::string(" ")));
 
 	while (text.length())
 	{
@@ -191,7 +191,7 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineSi
 		}
 
 		if(!allowLeadingWhitespace || !lineManuallyBroken)
-			boost::algorithm::trim_left_if(text,boost::algorithm::is_any_of(" ")); 
+			boost::algorithm::trim_left_if(text,boost::algorithm::is_any_of(std::string(" "))); 
 
 		if (opened)
 		{

+ 1 - 1
client/CPreGame.cpp

@@ -254,7 +254,7 @@ CMenuScreen::CMenuScreen( EState which )
 			buttons[1] = new AdventureMapButton("", "", bind(&CGPreGame::openCampaignScreen, CGP, CCampaignScreen::ROE) , 494, 117, "ZSSROE.DEF", SDLK_m); // ROE
 			buttons[2] = new AdventureMapButton("", "", bind(&CGPreGame::openCampaignScreen, CGP, CCampaignScreen::AB), 486, 241, "ZSSARM.DEF", SDLK_c); // AB
 			buttons[3] = new AdventureMapButton("", "", bind(&CGPreGame::openSel, CGP, campaignList, SINGLE_PLAYER), 550, 358, "ZSSCUS.DEF", SDLK_t); // Custom
-			buttons[4] = new AdventureMapButton("", "", bind(&CMenuScreen::moveTo, this, CGP->scrs[newGame]), 582, 464, "ZSSEXIT.DEF", SDLK_ESCAPE); // Back
+			buttons[4] = new AdventureMapButton("", "", bind(&CMenuScreen::moveTo, this, CGP->scrs[newGame]), 582, 464, "ZTBACK.DEF", SDLK_ESCAPE); // Back
 
 		}
 		break;

+ 2 - 1
client/GUIBase.cpp

@@ -53,7 +53,6 @@ void CGuiHandler::popInt( IShowActivable *top )
 	if(listInt.size())
 		listInt.front()->activate();
 	totalRedraw();
-	fakeMouseMove();
 }
 
 void CGuiHandler::popIntTotally( IShowActivable *top )
@@ -61,6 +60,7 @@ void CGuiHandler::popIntTotally( IShowActivable *top )
 	assert(listInt.front() == top);
 	popInt(top);
 	delete top;
+	fakeMouseMove();
 }
 
 void CGuiHandler::pushInt( IShowActivable *newInt )
@@ -94,6 +94,7 @@ void CGuiHandler::popInts( int howMany )
 		listInt.front()->activate();
 		totalRedraw();
 	}
+	fakeMouseMove();
 }
 
 IShowActivable * CGuiHandler::topInt()

+ 6 - 0
client/GUIBase.h

@@ -83,6 +83,12 @@ struct Point
 		return Point(x+b.x,y+b.y);
 	}
 
+	template<typename T>
+	Point operator*(const T &mul) const
+	{
+		return Point(x*mul, y*mul);
+	}
+
 	template<typename T>
 	Point& operator+=(const T &b)
 	{

+ 42 - 10
client/GUIClasses.cpp

@@ -351,11 +351,6 @@ void CGarrisonSlot::showAll(SDL_Surface * to)
 	}
 	else//empty slot
 	{
-		Rect pos1 = pos, pos2 = pos; //positions on the garr bg sur and scren
-		pos1.x = owner->surOffset.x+ pos.x-owner->pos.x;
-		pos1.y = owner->surOffset.y+ pos.y-owner->pos.y;
-
-		CSDL_Ext::blitSurface(owner->sur,&pos1,to,&pos2);
 		if(owner->splitting && owner->highlighted->our())
 			blitAt(imgs[-1],pos,to);
 	}
@@ -463,10 +458,10 @@ void CGarrisonInt::splitStacks(int am2)
 }
 
 CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset, 
-                            SDL_Surface *&pomsur, const Point& SurOffset, 
+                            SDL_Surface *pomsur, const Point& SurOffset, 
                             const CArmedInstance *s1, const CArmedInstance *s2, 
                             bool _removableUnits, bool smallImgs, bool _twoRows )
-	: interx(inx), garOffset(garsOffset), surOffset(SurOffset), highlighted(NULL), sur(pomsur), splitting(false),
+	: interx(inx), garOffset(garsOffset), highlighted(NULL), splitting(false),
 	smallIcons(smallImgs), removableUnits (_removableUnits), twoRows(_twoRows)
 {
 	setArmy(s1, false);
@@ -4590,6 +4585,13 @@ CArtPlace::CArtPlace(const CArtifactInstance* Art)
 {
 }
 
+CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art):
+	picked(false), marked(false), locked(false), ourArt(Art)
+{
+	pos += position;
+	pos.w = pos.h = 44;
+}
+
 void CArtPlace::activate()
 {
 	if(!active)
@@ -5114,7 +5116,7 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero)
 		backpackPos = 0;
 
 	// Fill the slots for worn artifacts and backpack.
-	for (int g = 0; g < 19 ; g++)
+	for (int g = 0; g < artWorn.size() ; g++)
 		setSlotData(artWorn[g], g);
 	scrollBackpack(0);
 }
@@ -5262,6 +5264,36 @@ void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, int slotID)
 	artPlace->setArtifact(NULL);
 }
 
+CArtifactsOfHero::CArtifactsOfHero(std::vector<CArtPlace *> ArtWorn, std::vector<CArtPlace *> Backpack,
+	AdventureMapButton *leftScroll, AdventureMapButton *rightScroll, bool createCommonPart):
+
+	curHero(NULL),
+	artWorn(ArtWorn), backpack(Backpack),
+	backpackPos(0), commonInfo(NULL), updateState(false),
+	leftArtRoll(leftScroll), rightArtRoll(rightScroll),
+	allowedAssembling(true), highlightModeCallback(0)
+{
+	if(createCommonPart)
+	{
+		commonInfo = new CArtifactsOfHero::SCommonPart;
+		commonInfo->participants.insert(this);
+	}
+	
+	// Init slots for worn artifacts.
+	for (size_t g = 0; g < artWorn.size() ; g++)
+	{
+		artWorn[g]->ourOwner = this;
+		eraseSlotData(artWorn[g], g);
+	}
+
+	// Init slots for the backpack.
+	for(size_t s=0; s<backpack.size(); ++s)
+	{
+		backpack[s]->ourOwner = this;
+		eraseSlotData(backpack[s], 19 + s);
+	}
+}
+
 CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart /*= false*/)
  : curHero(NULL), backpackPos(0), commonInfo(NULL), updateState(false), allowedAssembling(true), highlightModeCallback(0)
 {
@@ -5285,8 +5317,8 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart
 		genRect(44,44,381,296);
 
 	// Create slots for worn artifacts.
-	for (int g = 0; g < 19 ; g++)
-	{	
+	for (size_t g = 0; g < 19 ; g++)
+	{
 		artWorn[g] = new CArtPlace(NULL);
 		artWorn[g]->pos = slotPos[g] + pos;
 		artWorn[g]->ourOwner = this;

+ 14 - 6
client/GUIClasses.h

@@ -238,12 +238,10 @@ class CGarrisonInt :public CIntObject
 {
 public:
 	int interx; //space between slots
-	Point garOffset, //offset between garrisons (not used if only one hero)
-	      surOffset; //offset between garrison position on the bg surface and position on the screen
+	Point garOffset; //offset between garrisons (not used if only one hero)
 	CGarrisonSlot *highlighted; //chosen slot
 	std::vector<AdventureMapButton *> splitButtons; //may be empty if no buttons
 
-	SDL_Surface *&sur; //bg surface
 	int p2, //TODO: comment me
 	    shiftPos;//1st slot of the second row, set shiftPoint for effect
 	bool splitting, pb, 
@@ -270,8 +268,14 @@ public:
 
 	void splitClick(); //handles click on split button
 	void splitStacks(int am2); //TODO: comment me
-	//x, y - position; inx - distance between slots; pomsur - background surface, SurOffset - ?; s1, s2 - top and bottom armies; removableUnits - you can take units from top; smallImgs - units images size 64x58 or 32x32; twoRows - display slots in 2 row (1st row = 4, 2nd = 3)
-	CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, bool _twoRows=false); //c-tor
+	//x, y - position;
+	//inx - distance between slots;
+	//pomsur, SurOffset - UNUSED
+	//s1, s2 - top and bottom armies;
+	//removableUnits - you can take units from top;
+	//smallImgs - units images size 64x58 or 32x32;
+	//twoRows - display slots in 2 row (1st row = 4, 2nd = 3)
+	CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false, bool _twoRows=false); //c-tor
 	~CGarrisonInt(); //d-tor
 };
 
@@ -964,6 +968,7 @@ public:
 	const CArtifactInstance * ourArt;
 
 	CArtPlace(const CArtifactInstance * Art); //c-tor
+	CArtPlace(Point position, const CArtifactInstance * Art = NULL); //c-tor
 	void clickLeft(tribool down, bool previousState);
 	void clickRight(tribool down, bool previousState);
 	void select ();
@@ -1038,7 +1043,10 @@ public:
 	void updateSlot(int i);
 	void eraseSlotData (CArtPlace* artPlace, int slotID);
 
-	CArtifactsOfHero(const Point& position, bool createCommonPart = false); //c-tor
+	CArtifactsOfHero(const Point& position, bool createCommonPart = false);
+	//Alternative constructor, used if custom artifacts positioning required (Kingdom interface)
+	CArtifactsOfHero(std::vector<CArtPlace *> ArtWorn, std::vector<CArtPlace *> Backpack,
+		AdventureMapButton *leftScroll, AdventureMapButton *rightScroll, bool createCommonPart = false);
 	~CArtifactsOfHero(); //d-tor
 	void updateParentWindow();
 	friend class CArtPlace;

+ 2 - 3
client/mapHandler.cpp

@@ -1042,13 +1042,12 @@ CMapHandler::~CMapHandler()
 	for(int i=0; i < staticRiverDefs.size(); i++)
 		delete staticRiverDefs[i];
 
-	//TODO: why this code makes VCMI crash?
-	/*for(int i=0; i < terrainGraphics.size(); ++i)
+	for(int i=0; i < terrainGraphics.size(); ++i)
 	{
 		for(int j=0; j < terrainGraphics[i].size(); ++j)
 			SDL_FreeSurface(terrainGraphics[i][j]);
 	}
-	terrainGraphics.clear();*/
+	terrainGraphics.clear();
 }
 
 CMapHandler::CMapHandler()

+ 2 - 0
lib/CCreatureSet.cpp

@@ -755,6 +755,8 @@ std::string CStackInstance::bonusToGraphics(Bonus *bonus) const
 		case Bonus::SPELL_RESISTANCE_AURA:
 			fileName = "E_UNIC.bmp"; break;
 	}
+	if(!fileName.empty())
+		fileName = "zvs/Lib1.res/" + fileName;
 	return fileName;
 }
 

+ 17 - 6
lib/CLodHandler.cpp

@@ -7,7 +7,7 @@
 #include <cctype>
 #include <cstring>
 #include <iostream>
-#include "boost/filesystem/operations.hpp"
+#include "boost/filesystem.hpp"
 #include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/thread.hpp>
@@ -68,8 +68,6 @@ unsigned char * CLodHandler::giveFile(const std::string defName, LodFileType typ
 	if ( dotPos != -1 )
 		fname.erase(dotPos);
 
-	int count = entries.size();
-
 	boost::unordered_set<Entry>::const_iterator en_it = entries.find(Entry(fname, type));
 	
 	if(en_it == entries.end()) //nothing's been found
@@ -292,15 +290,28 @@ void CLodHandler::init(const std::string lodFile, const std::string dirName)
 
 	delete [] lodEntries;
 
-	boost::filesystem::directory_iterator enddir;
+	boost::filesystem::recursive_directory_iterator enddir;
 	if(boost::filesystem::exists(dirName))
 	{
-		for (boost::filesystem::directory_iterator dir(dirName);dir!=enddir;dir++)
+		std::vector<std::string> path;
+		for (boost::filesystem::recursive_directory_iterator dir(dirName); dir!=enddir; dir++)
 		{
+			//If a directory was found - add name to vector to recreate full path later
+			if (boost::filesystem::is_directory(dir->status()))
+			{
+				path.resize(dir.level()+1);
+				path.back() = dir->path().leaf();
+			}
 			if(boost::filesystem::is_regular(dir->status()))
 			{
 				Entry e;
-				e.realName = dir->path().leaf();
+
+				//we can't get relative path with boost at the moment - need to create path to file manually
+				for (size_t i=0; i<dir.level() && i<path.size(); i++)
+					e.realName += path[i] + '/';
+
+				e.realName += dir->path().leaf();
+
 				initEntry(e, e.realName);
 
 				if(vstd::contains(entries, e)) //file present in .lod - overwrite its entry

+ 1 - 1
lib/NetPacks.h

@@ -1364,7 +1364,7 @@ struct SetStackEffect : public CPackForClient //3010
 
 	std::vector<ui32> stacks; //affected stacks (IDs)
 	std::vector<Bonus> effect; //bonuses to apply
-	std::vector<std::pair<ui32, Bonus>> uniqueBonuses; //bonuses per single stack
+	std::vector<std::pair<ui32, Bonus> > uniqueBonuses; //bonuses per single stack
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & stacks & effect & uniqueBonuses;