瀏覽代碼

- fixed crash in hero window (#963)
- added unused for now image scaling algorithm

Ivan Savenko 13 年之前
父節點
當前提交
a13a62537b
共有 6 個文件被更改,包括 105 次插入5 次删除
  1. 5 4
      AI/VCAI/VCAI.cpp
  2. 6 0
      client/CHeroWindow.cpp
  3. 15 0
      client/CPreGame.cpp
  4. 4 0
      client/GUIClasses.cpp
  5. 73 1
      client/UIFramework/SDL_Extensions.cpp
  6. 2 0
      client/UIFramework/SDL_Extensions.h

+ 5 - 4
AI/VCAI/VCAI.cpp

@@ -1172,8 +1172,9 @@ void VCAI::buildStructure(const CGTownInstance * t)
 {
 	using namespace EBuilding;
 	//TODO make *real* town development system
-	//TODO: faction-specific development
+	//TODO: faction-specific development: use special buildings, build dwellings in better order, etc
 	//TODO: build resource silo, defences when needed
+	//Possible - allow "locking" on specific building (build prerequisites and then building itself)
 
 	//Set of buildings for different goals. Does not include any prerequisites.
 	const int essential[] = {TAVERN, TOWN_HALL};
@@ -1190,8 +1191,8 @@ void VCAI::buildStructure(const CGTownInstance * t)
 	if (tryBuildAnyStructure(t, std::vector<int>(essential, essential + ARRAY_COUNT(essential))))
 		return;
 
-	//we're running out of gold - try to build something gold-producing. Minimal amount can be tweaked
-	if (currentRes[Res::GOLD] + income[Res::GOLD] < 5000)
+	//we're running out of gold - try to build something gold-producing. Multiplier can be tweaked
+	if (currentRes[Res::GOLD] < income[Res::GOLD] * 4)
 		if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
 			return;
 
@@ -1221,7 +1222,7 @@ void VCAI::buildStructure(const CGTownInstance * t)
 		return;
 	if (tryBuildNextStructure(t, std::vector<int>(spells, spells + ARRAY_COUNT(spells))))
 		return;
-	if (tryBuildNextStructure(t, std::vector<int>(extra, extra + ARRAY_COUNT(extra))))
+	if (tryBuildAnyStructure(t, std::vector<int>(extra, extra + ARRAY_COUNT(extra))))
 		return;
 }
 

+ 6 - 0
client/CHeroWindow.cpp

@@ -210,9 +210,15 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
 		}
 
 		int serial = LOCPLINT->cb->getHeroSerial(curHero, false);
+		if (listSelection && active)
+			listSelection->deactivate();
 		delChildNUll(listSelection);
 		if (serial >= 0)
+		{
 			listSelection = new CPicture("HPSYYY", 612, 33 + serial * 54);
+			if (active)
+				listSelection->activate();
+		}
 	}
 
 	//primary skills support

+ 15 - 0
client/CPreGame.cpp

@@ -218,6 +218,21 @@ CMenuScreen::CMenuScreen(const JsonNode& configNode):
 	if (!images.empty())
 		pos = images[0]->center();
 
+	//Work in progress, move along
+	/*
+	clock_t startTime = clock();
+	if (!images.empty())
+	{
+		SDL_Surface * scaled = images[0]->bg;
+		scaled = CSDL_Ext::scaleSurface(scaled, screen->w, screen->h);
+		SDL_FreeSurface(images[0]->bg);
+		images[0]->bg = scaled;
+		images[0]->pos.w = scaled->w;
+		images[0]->pos.h = scaled->h;
+	}
+	clock_t finishTime = clock();
+	tlog1<< "Image scaled in " << finishTime - startTime <<"\n";
+*/
 	//Hardcoded entry
 	menuNameToEntry.push_back("credits");
 

+ 4 - 0
client/GUIClasses.cpp

@@ -6207,8 +6207,12 @@ void MoraleLuckBox::set(const IBonusBearer *node)
 		imageName = morale ? "IMRL30": "ILCK30";
 	else
 		imageName = morale ? "IMRL42" : "ILCK42";
+	if (image && active)
+		image->deactivate();
 	delChildNUll(image);
 	image = new CAnimImage(imageName, bonusValue + 3);
+	if (active)
+		image->activate();
 	image->moveBy(Point(pos.w/2 - image->pos.w/2, pos.h/2 - image->pos.h/2));//center icon
 }
 

+ 73 - 1
client/UIFramework/SDL_Extensions.cpp

@@ -1095,7 +1095,7 @@ void CSDL_Ext::applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mo
 		}
 		break;
 	default:
-		throw std::runtime_error("Unsuppoerted efftct!");
+		throw std::runtime_error("Unsupported effect!");
 	}
 }
 
@@ -1109,6 +1109,78 @@ void CSDL_Ext::applyEffect( SDL_Surface * surf, const SDL_Rect * rect, int mode
 	}
 }
 
+template<int bpp>
+void scaleSurfaceInternal(SDL_Surface *surf, SDL_Surface *ret)
+{
+	const float factorX = float(surf->w - 1) / float(ret->w),
+	            factorY = float(surf->h - 1) / float(ret->h);
+
+	for(int y = 0; y < ret->h; y++)
+	{
+		for(int x = 0; x < ret->w; x++)
+		{
+			//coordinates we want to interpolate
+			float origX = x * factorX,
+			      origY = y * factorY;
+
+			float x1 = floor(origX), x2 = floor(origX+1),
+			      y1 = floor(origY), y2 = floor(origY+1);
+			assert( x1 >= 0 && y1 >= 0 && x2 < surf->w && y2 < surf->h);//All pixels are in range
+
+			// Calculate weights of each source pixel
+			float w11 = ((origX - x1) * (origY - y1));
+			float w12 = ((origX - x1) * (y2 - origY));
+			float w21 = ((x2 - origX) * (origY - y1));
+			float w22 = ((x2 - origX) * (y2 - origY));
+			assert( w11 + w12 + w21 + w22 > 0.99 && w11 + w12 + w21 + w22 < 1.01);//total weight is ~1.0
+
+			// Get pointers to source pixels
+			Uint8 *p11 = (Uint8*)surf->pixels + int(y1) * surf->pitch + int(x1) * bpp;
+			Uint8 *p12 = p11 + bpp;
+			Uint8 *p21 = p11 + surf->pitch;
+			Uint8 *p22 = p21 + bpp;
+			// Calculate resulting channels
+#define PX(X, PTR) Channels::px<bpp>::X.get(PTR)
+			int resR = PX(r, p11) * w11 + PX(r, p12) * w12 + PX(r, p21) * w21 + PX(r, p22) * w22;
+			int resG = PX(g, p11) * w11 + PX(g, p12) * w12 + PX(g, p21) * w21 + PX(g, p22) * w22;
+			int resB = PX(b, p11) * w11 + PX(b, p12) * w12 + PX(b, p21) * w21 + PX(b, p22) * w22;
+			int resA = PX(a, p11) * w11 + PX(a, p12) * w12 + PX(a, p21) * w21 + PX(a, p22) * w22;
+			assert(resR < 256 && resG < 256 && resB < 256 && resA < 256);
+#undef PX
+			Uint8 *dest = (Uint8*)ret->pixels + y * ret->pitch + x * bpp;
+			Channels::px<bpp>::r.set(dest, resR);
+			Channels::px<bpp>::g.set(dest, resG);
+			Channels::px<bpp>::b.set(dest, resB);
+			Channels::px<bpp>::a.set(dest, resA);
+		}
+	}
+}
+
+/// scaling via bilinear interpolation algorithm.
+/// NOTE: best results are for scaling in range 50%...200%
+SDL_Surface * CSDL_Ext::scaleSurface(SDL_Surface *surf, int width, int height)
+{
+	if (!surf || !width || !height)
+		return nullptr;
+	if (surf->format->palette)
+	{
+		//it is possible implement but only to power of 2 sizes. May be needed for view world spells
+		tlog0 << "scale surface error: Can't scale indexed surface!\n";
+		return nullptr;
+	}
+
+	SDL_Surface *ret = newSurface(width, height, surf);
+
+	switch(surf->format->BytesPerPixel)
+	{
+	case 2: scaleSurfaceInternal<2>(surf, ret); break;
+	case 3: scaleSurfaceInternal<3>(surf, ret); break;
+	case 4: scaleSurfaceInternal<4>(surf, ret); break;
+	}
+
+	return ret;
+}
+
 void CSDL_Ext::blitSurface( SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect )
 {
 	if (dst != screen)

+ 2 - 0
client/UIFramework/SDL_Extensions.h

@@ -174,6 +174,8 @@ namespace CSDL_Ext
 	SDL_Surface * createSurfaceWithBpp(int width, int height); //create surface with give bits per pixels value
 	void VflipSurf(SDL_Surface * surf); //fluipis given surface by vertical axis
 
+	SDL_Surface * scaleSurface(SDL_Surface *surf, int width, int height);
+
 	template<int bpp>
 	void applyEffectBpp( SDL_Surface * surf, const SDL_Rect * rect, int mode );
 	void applyEffect(SDL_Surface * surf, const SDL_Rect * rect, int mode); //mode: 0 - sepia, 1 - grayscale