1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

- shadows for CWindowObject-based windows

- better error messages on read error
- fixed crash on level-up window
This commit is contained in:
Ivan Savenko 2012-06-16 10:41:14 +00:00
parent 2d8a15f27c
commit 8c6965c5ee
8 changed files with 172 additions and 39 deletions

View File

@ -942,7 +942,7 @@ void CAnimation::init(CDefFile * file)
ui8 * configFile = spriteh->giveFile(name, FILE_TEXT, &size);
const JsonNode config((char*)configFile, size);
delete configFile;
delete[] configFile;
std::string basepath;
basepath = config["basepath"].String();

View File

@ -923,6 +923,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
pos.w = panel->pos.w;
pos.h = builds->pos.h + panel->pos.h;
center();
updateShadow();
garr = new CGarrisonInt(305, 387, 4, Point(0,96), panel->bg, Point(62,374), town->getUpperArmy(), town->visitingHero);
heroes = new HeroSlots(town, Point(241, 387), Point(241, 483), garr, true);
@ -1755,7 +1756,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, i
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
statusBar = new CGStatusBar(164, 370);
statusBar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
animBG = new CPicture("TPSMITBK", 64, 50);
animBG->needRefresh = true;

View File

@ -15,7 +15,6 @@ class CMinorResDataBar;
class CPicture;
class CResDataBar;
class CSpell;
class CStatusBar;
class CTextBox;
class CTownList;
struct Structure;

View File

@ -1127,6 +1127,13 @@ void CRecruitmentWindow::clickRight(tribool down, bool previousState)
void CRecruitmentWindow::showAll(SDL_Surface * to)
{
CWindowObject::showAll(to);
drawBorder(to, pos.x + 172, pos.y + 222, 67, 42, int3(239,215,123));
drawBorder(to, pos.x + 246, pos.y + 222, 67, 42, int3(239,215,123));
drawBorder(to, pos.x + 64, pos.y + 222, 99, 76, int3(239,215,123));
drawBorder(to, pos.x + 322, pos.y + 222, 99, 76, int3(239,215,123));
drawBorder(to, pos.x + 133, pos.y + 312, 66, 34, int3(173,142,66));
drawBorder(to, pos.x + 211, pos.y + 312, 66, 34, int3(173,142,66));
drawBorder(to, pos.x + 289, pos.y + 312, 66, 34, int3(173,142,66));
char pom[15];
SDL_itoa(creatures[which].amount-slider->value,pom,10); //available
@ -1167,7 +1174,7 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co
OBJ_CONSTRUCTION_CAPTURING_ALL;
which = 0;
bar = new CGStatusBar(8, 370, "APHLFTRT.bmp", 471);
bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
max = new CAdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CRecruitmentWindow::Max,this),134,313,"IRCBTNS.DEF",SDLK_m);
buy = new CAdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecruitmentWindow::Buy,this),212,313,"IBY6432.DEF",SDLK_RETURN);
cancel = new CAdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecruitmentWindow::Cancel,this),290,313,"ICN6432.DEF",SDLK_ESCAPE);
@ -1180,14 +1187,7 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co
new CLabel(205, 233, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[465]); //available t
new CLabel(279, 233, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[16]); //recruit t
new CLabel(371, 232, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[466]); //total cost t
/*drawBorder(*background,172,222,67,42,int3(239,215,123));
drawBorder(*background,246,222,67,42,int3(239,215,123));
drawBorder(*background,64,222,99,76,int3(239,215,123));
drawBorder(*background,322,222,99,76,int3(239,215,123));
drawBorder(*background,133,312,66,34,int3(173,142,66));
drawBorder(*background,211,312,66,34,int3(173,142,66));
drawBorder(*background,289,312,66,34,int3(173,142,66));
*/
//border for creatures
int curx = 192 + 50 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
for(int i=0;i<creatures.size();i++)
@ -1331,6 +1331,7 @@ CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<u
comps.back()->assignedKeys.insert(SDLK_1 + i);
}
new CAnimImage("PortraitsLarge", hero->portrait, 0, 170, 66);
new CAdventureMapButton("", "", boost::bind(&CLevelWindow::close, this), 297, 413, "IOKAY", SDLK_RETURN);
//%s has gained a level.
@ -1339,9 +1340,9 @@ CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<u
//%s is now a level %d %s.
new CLabel(192, 162, FONT_MEDIUM, CENTER, Colors::Cornsilk,
boost::str(boost::format(CGI->generaltexth->allTexts[444]) % hero->name % hero->type->heroClass->name));
boost::str(boost::format(CGI->generaltexth->allTexts[445]) % hero->name % hero->level % hero->type->heroClass->name));
new CAnimImage("PSKILL42", pskill, 0, 174, 190);
new CAnimImage("PSKIL42", pskill, 0, 174, 190);
new CLabel(192, 253, FONT_MEDIUM, CENTER, Colors::Cornsilk,
CGI->generaltexth->primarySkillNames[pskill] + " +1");
@ -2143,7 +2144,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan
madeTransaction = false;
bool sliderNeeded = true;
new CGStatusBar(302, 576);
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
std::string title;
@ -2620,7 +2621,8 @@ CAltarWindow::CAltarWindow(const IMarket *Market, const CGHeroInstance *Hero /*=
//Total experience on the Altar
new CTextBox(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, CENTER, Colors::Jasmine);
new CGStatusBar(302, 576);
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
ok = new CAdventureMapButton(CGI->generaltexth->zelp[568],boost::bind(&CGuiHandler::popIntTotally,&GH,this),516,520,"IOK6432.DEF",SDLK_RETURN);
ok->assignedKeys.insert(SDLK_ESCAPE);
@ -3221,7 +3223,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
new CLabel(320, 328, FONT_SMALL, CENTER, Colors::Cornsilk, "2500");
new CTextBox(LOCPLINT->cb->getTavernGossip(tavernObj), Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::Cornsilk);
bar = new CGStatusBar(8, 478, "APHLFTRT.bmp", 380);
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
cancel = new CAdventureMapButton(CGI->generaltexth->tavernInfo[7],"", boost::bind(&CTavernWindow::close, this), 310, 428, "ICANCEL.DEF", SDLK_ESCAPE);
recruit = new CAdventureMapButton("", "", boost::bind(&CTavernWindow::recruitb, this), 272, 355, "TPTAV01.DEF", SDLK_RETURN);
thiefGuild = new CAdventureMapButton(CGI->generaltexth->tavernInfo[5],"", boost::bind(&CTavernWindow::thievesguildb, this), 22, 428, "TPTAV02.DEF", SDLK_t);
@ -4576,12 +4578,6 @@ void CExchangeWindow::prepareBackground()
//mana points
new CAnimImage("PSKIL32", 5, 0, 139 + 490*b, 45);
new CLabel(155 + 490*b, 71, FONT_SMALL, CENTER, Colors::Cornsilk, makeNumberShort(heroInst[b]->mana));
//setting morale
//blitAt(graphics->morale30->ourImages[heroWArt.MoraleVal()+3].bitmap, 177 + 490*b, 45, bg);
//setting luck
//blitAt(graphics->luck30->ourImages[heroWArt.LuckVal()+3].bitmap, 213 + 490*b, 45, bg);
}
//printing portraits
@ -4731,7 +4727,7 @@ CShipyardWindow::CShipyardWindow(const std::vector<si32> &cost, int state, int b
}
}
statusBar = new CGStatusBar(pos.w/2, pos.h-16);
statusBar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
title = new CLabel(164, 27, FONT_BIG, CENTER, Colors::Jasmine, CGI->generaltexth->jktexts[13]);
costLabel = new CLabel(164, 220, FONT_MEDIUM, CENTER, Colors::Cornsilk, CGI->generaltexth->jktexts[14]);
@ -4886,7 +4882,7 @@ CTransformerWindow::CTransformerWindow(const CGHeroInstance * _hero, const CGTow
all = new CAdventureMapButton(CGI->generaltexth->zelp[590],boost::bind(&CTransformerWindow::addAll,this), 146,416,"ALTARMY.DEF",SDLK_a);
convert= new CAdventureMapButton(CGI->generaltexth->zelp[591],boost::bind(&CTransformerWindow::makeDeal,this), 269,416,"ALTSACR.DEF",SDLK_RETURN);
cancel = new CAdventureMapButton(CGI->generaltexth->zelp[592],boost::bind(&CTransformerWindow::close, this),392,416,"ICANCEL.DEF",SDLK_ESCAPE);
bar = new CGStatusBar(304, 469);
bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
}
void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState)
@ -5014,7 +5010,7 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket
cancel = new CAdventureMapButton(CGI->generaltexth->zelp[632],
boost::bind(&CUniversityWindow::close, this),200,313,"IOKAY.DEF",SDLK_RETURN);
bar = new CGStatusBar(232, 371);
bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
}
CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bool available ):
@ -5051,7 +5047,7 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bo
cancel = new CAdventureMapButton(CGI->generaltexth->zelp[631],boost::bind(&CUnivConfirmWindow::close, this),
252,299,"ICANCEL.DEF",SDLK_ESCAPE);
bar = new CGStatusBar(232, 371);
bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
}
void CUnivConfirmWindow::makeDeal(int skill)
@ -5092,7 +5088,7 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance *visitor, const CGObjectIn
upgradeAll = new CAdventureMapButton(CGI->generaltexth->allTexts[432],"",boost::bind(&CHillFortWindow::makeDeal, this, slotsCount),
30, 231, "", SDLK_0, &files);
quit = new CAdventureMapButton("","",boost::bind(&CHillFortWindow::close, this), 294, 275, "IOKAY.DEF", SDLK_RETURN);
bar = new CGStatusBar(327, 332);
bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
garr = new CGarrisonInt(108, 60, 18, Point(),background->bg,Point(108,60),hero,NULL);
updateGarrisons();
@ -5265,7 +5261,7 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner):
LOCPLINT->cb->getThievesGuildInfo(tgi, owner);
exitb = new CAdventureMapButton (CGI->generaltexth->allTexts[600], "", boost::bind(&CThievesGuildWindow::close,this), 748, 556, "TPMAGE1", SDLK_RETURN);
statusBar = new CGStatusBar(3, 555, "TStatBar", 742);
statusBar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
resdatabar = new CMinorResDataBar();
resdatabar->pos.x += pos.x;

View File

@ -2,6 +2,7 @@
#include "CIntObjectClasses.h"
#include "../CBitmapHandler.h"
#include "SDL_Pixels.h"
#include "SDL_Extensions.h"
#include "../Graphics.h"
#include "../CAnimation.h"
@ -1341,11 +1342,11 @@ std::string CGStatusBar::getCurrent()
return text;
}
CGStatusBar::CGStatusBar(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, const SDL_Color &Color /*= Colors::Cornsilk*/, const std::string &Text /*= ""*/)
: CLabel(x, y, Font, Align, Color, Text)
{
init();
}
//CGStatusBar::CGStatusBar(int x, int y, EFonts Font /*= FONT_SMALL*/, EAlignment Align, const SDL_Color &Color /*= Colors::Cornsilk*/, const std::string &Text /*= ""*/)
//: CLabel(x, y, Font, Align, Color, Text)
//{
// init();
//}
CGStatusBar::CGStatusBar(CPicture *BG, EFonts Font /*= FONT_SMALL*/, EAlignment Align /*= CENTER*/, const SDL_Color &Color /*= Colors::Cornsilk*/)
: CLabel(BG->pos.x, BG->pos.y, Font, Align, Color, "")
@ -1597,6 +1598,7 @@ void CFocusable::moveFocus()
CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
CIntObject(getUsedEvents(options_), Point()),
shadow(nullptr),
options(options_),
background(createBg(imageName, options & PLAYER_COLORED))
{
@ -1609,10 +1611,14 @@ CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt
pos = background->center(centerAt);
else
center(centerAt);
if (!(options & SHADOW_DISABLED))
setShadow(true);
}
CWindowObject::CWindowObject(int options_, std::string imageName):
CIntObject(getUsedEvents(options_), Point()),
shadow(nullptr),
options(options_),
background(createBg(imageName, options & PLAYER_COLORED))
{
@ -1625,6 +1631,14 @@ CWindowObject::CWindowObject(int options_, std::string imageName):
pos = background->center();
else
center(Point(screen->w/2, screen->h/2));
if (!(options & SHADOW_DISABLED))
setShadow(true);
}
CWindowObject::~CWindowObject()
{
setShadow(false);
}
CPicture * CWindowObject::createBg(std::string imageName, bool playerColored)
@ -1649,6 +1663,8 @@ void CWindowObject::setBackground(std::string filename)
if (background)
pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y));
updateShadow();
}
int CWindowObject::getUsedEvents(int options)
@ -1658,6 +1674,117 @@ int CWindowObject::getUsedEvents(int options)
return 0;
}
void CWindowObject::updateShadow()
{
setShadow(false);
if (!(options & SHADOW_DISABLED))
setShadow(true);
}
void CWindowObject::setShadow(bool on)
{
vstd::clear_pointer(shadow);
//size of shadow
static const int size = 8;
if (on == bool(shadow))
return;
//object too small to cast shadow
if (pos.h <= size || pos.w <= size)
return;
if (on)
{
//helper to set last row
auto blitAlphaRow = [](SDL_Surface *surf, size_t row)
{
Uint8 * ptr = (Uint8*)surf->pixels + surf->pitch * (row);
for (size_t i=0; i< surf->w; i++)
{
Channels::px<4>::a.set(ptr, 128);
ptr+=4;
}
};
// helper to set last column
auto blitAlphaCol = [](SDL_Surface *surf, size_t col)
{
Uint8 * ptr = (Uint8*)surf->pixels + 4 * (col);
for (size_t i=0; i< surf->h; i++)
{
Channels::px<4>::a.set(ptr, 128);
ptr+= surf->pitch;
}
};
static SDL_Surface * shadowCornerTempl = nullptr;
static SDL_Surface * shadowBottomTempl = nullptr;
static SDL_Surface * shadowRightTempl = nullptr;
//one-time initialization
if (!shadowCornerTempl)
{
//create "template" surfaces
shadowCornerTempl = CSDL_Ext::createSurfaceWithBpp<4>(size, size);
shadowBottomTempl = CSDL_Ext::createSurfaceWithBpp<4>(1, size);
shadowRightTempl = CSDL_Ext::createSurfaceWithBpp<4>(size, 1);
Uint32 shadowColor = SDL_MapRGBA(shadowCornerTempl->format, 0, 0, 0, 192);
//fill with shadow body color
SDL_FillRect(shadowCornerTempl, NULL, shadowColor);
SDL_FillRect(shadowBottomTempl, NULL, shadowColor);
SDL_FillRect(shadowRightTempl, NULL, shadowColor);
//fill last row and column with more transparent color
blitAlphaCol(shadowRightTempl , size-1);
blitAlphaCol(shadowCornerTempl, size-1);
blitAlphaRow(shadowBottomTempl, size-1);
blitAlphaRow(shadowCornerTempl, size-1);
}
OBJ_CONSTRUCTION_CAPTURING_ALL;
//FIXME: do something with this points
Point shadowStart;
if (options & BORDERED)
shadowStart = Point(size - 14, size - 14);
else
shadowStart = Point(size, size);
Point shadowPos;
if (options & BORDERED)
shadowPos = Point(pos.w + 14, pos.h + 14);
else
shadowPos = Point(pos.w, pos.h);
Point fullsize;
if (options & BORDERED)
fullsize = Point(pos.w + 28, pos.h + 29);
else
fullsize = Point(pos.w, pos.h);
//create base 8x8 piece of shadow
SDL_Surface * shadowCorner = CSDL_Ext::copySurface(shadowCornerTempl);
SDL_Surface * shadowBottom = CSDL_Ext::scaleSurfaceFast(shadowBottomTempl, fullsize.x - size, size);
SDL_Surface * shadowRight = CSDL_Ext::scaleSurfaceFast(shadowRightTempl, size, fullsize.y - size);
blitAlphaCol(shadowBottom, 0);
blitAlphaRow(shadowRight, 0);
//generate "shadow" object with these 3 pieces in it
shadow = new CIntObject;
shadow->addChild(new CPicture(shadowCorner, shadowPos.x, shadowPos.y));
shadow->addChild(new CPicture(shadowRight, shadowPos.x, shadowStart.y));
shadow->addChild(new CPicture(shadowBottom, shadowStart.x, shadowPos.y));
}
}
void CWindowObject::showAll(SDL_Surface *to)
{
CIntObject::showAll(to);

View File

@ -376,8 +376,7 @@ public:
};
/// Status bar which is shown at the bottom of the in-game screens
class CGStatusBar
: public CLabel, public IStatusBar
class CGStatusBar : public CLabel, public IStatusBar
{
void init();
public:
@ -389,7 +388,7 @@ public:
std::string getCurrent(); //returns currently displayed text
void show(SDL_Surface * to); //shows statusbar (with current text)
CGStatusBar(int x, int y, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::Cornsilk, const std::string &Text = "");
//CGStatusBar(int x, int y, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::Cornsilk, const std::string &Text = "");
CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::Cornsilk); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar
CGStatusBar(int x, int y, std::string name, int maxw=-1);
@ -472,6 +471,9 @@ class CWindowObject : public CIntObject
CPicture * createBg(std::string imageName, bool playerColored);
int getUsedEvents(int options);
CIntObject *shadow;
void setShadow(bool on);
int options;
protected:
@ -485,12 +487,14 @@ protected:
void showAll(SDL_Surface *to);
//change or set background image
void setBackground(std::string filename);
void updateShadow();
public:
enum EOptions
{
PLAYER_COLORED=1, //background will be player-colored
RCLICK_POPUP=2, // window will behave as right-click popup
BORDERED=4 // window will have border if current resolution is bigger than size of window
BORDERED=4, // window will have border if current resolution is bigger than size of window
SHADOW_DISABLED=8 //this window won't display any shadow
};
/*
@ -500,4 +504,5 @@ public:
*/
CWindowObject(int options, std::string imageName, Point centerAt);
CWindowObject(int options, std::string imageName = "");
~CWindowObject();
};

View File

@ -78,7 +78,8 @@ ui8 * CLodHandler::giveFile(std::string fname, LodFileType type, int * length)
result = -1;
if(result<0)
{
tlog1<<"Error in file reading: " << myDir << "/" << ourEntry.realName << std::endl;
tlog1<<"Error in file reading: " << ourEntry.realName << std::endl;
perror("Last error was: ");//print system error message
delete[] outp;
return NULL;
}

View File

@ -21,7 +21,11 @@ JsonNode::JsonNode(std::string filename):
{
FILE * file = fopen(filename.c_str(), "rb");
if (!file)
{
tlog1 << "Failed to open file " << filename << "\n";
perror("Last system error was ");
return;
}
fseek(file, 0, SEEK_END);
size_t datasize = ftell(file);