From a13a62537b6eb08fcdae248fa41a93b1da1f211e Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sat, 19 May 2012 21:38:01 +0000 Subject: [PATCH] - fixed crash in hero window (#963) - added unused for now image scaling algorithm --- AI/VCAI/VCAI.cpp | 9 ++-- client/CHeroWindow.cpp | 6 +++ client/CPreGame.cpp | 15 ++++++ client/GUIClasses.cpp | 4 ++ client/UIFramework/SDL_Extensions.cpp | 74 ++++++++++++++++++++++++++- client/UIFramework/SDL_Extensions.h | 2 + 6 files changed, 105 insertions(+), 5 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 6ace5a004..27364bb5e 100644 --- a/AI/VCAI/VCAI.cpp +++ b/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(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(goldSource, goldSource + ARRAY_COUNT(goldSource)))) return; @@ -1221,7 +1222,7 @@ void VCAI::buildStructure(const CGTownInstance * t) return; if (tryBuildNextStructure(t, std::vector(spells, spells + ARRAY_COUNT(spells)))) return; - if (tryBuildNextStructure(t, std::vector(extra, extra + ARRAY_COUNT(extra)))) + if (tryBuildAnyStructure(t, std::vector(extra, extra + ARRAY_COUNT(extra)))) return; } diff --git a/client/CHeroWindow.cpp b/client/CHeroWindow.cpp index 112fd912e..fcd70835c 100644 --- a/client/CHeroWindow.cpp +++ b/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 diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index df8a35f7f..0756c98f8 100644 --- a/client/CPreGame.cpp +++ b/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"); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 87fe0da2e..2fb32ac57 100644 --- a/client/GUIClasses.cpp +++ b/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 } diff --git a/client/UIFramework/SDL_Extensions.cpp b/client/UIFramework/SDL_Extensions.cpp index f7fe27499..821954cbe 100644 --- a/client/UIFramework/SDL_Extensions.cpp +++ b/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 +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::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::r.set(dest, resR); + Channels::px::g.set(dest, resG); + Channels::px::b.set(dest, resB); + Channels::px::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) diff --git a/client/UIFramework/SDL_Extensions.h b/client/UIFramework/SDL_Extensions.h index f9b1103c5..5ff1ee86e 100644 --- a/client/UIFramework/SDL_Extensions.h +++ b/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 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