1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- background for main menu can be scaled. Won't work as default due to non-scalable video

This commit is contained in:
Ivan Savenko 2012-05-20 11:03:21 +00:00
parent 88639be91b
commit 59255a4cad
8 changed files with 68 additions and 28 deletions

View File

@ -129,7 +129,8 @@ SDL_Surface * BitmapHandler::loadBitmapFromLod(CLodHandler *lod, std::string fna
}
if (!lod->haveFile(fname, FILE_GRAPHICS))
{
tlog2<<"Entry for file "<<fname<<" was not found"<<std::endl;
//it is possible that this image will be found in another lod archive. Disabling this warning
//tlog2<<"Entry for file "<<fname<<" was not found"<<std::endl;
return NULL;
}

View File

@ -209,30 +209,22 @@ CMenuScreen::CMenuScreen(const JsonNode& configNode):
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
background = new CPicture(config["background"].String());
if (config["scalable"].Bool())
{
if (background->bg->format->palette)
background->convertToScreenBPP();
background->scaleTo(Point(screen->w, screen->h));
}
pos = background->center();
BOOST_FOREACH(const JsonNode& node, config["items"].Vector())
menuNameToEntry.push_back(node["name"].String());
BOOST_FOREACH(const JsonNode& node, config["images"].Vector())
images.push_back(createPicture(node));
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");
@ -358,13 +350,22 @@ CAdventureMapButton* CMenuEntry::createButton(CMenuScreen* parent, const JsonNod
if (!button["help"].isNull() && button["help"].Float() > 0)
help = CGI->generaltexth->zelp[button["help"].Float()];
return new CAdventureMapButton(help, command, button["x"].Float(), button["y"].Float(), button["name"].String(), button["hotkey"].Float());
int posx = button["x"].Float();
if (posx < 0)
posx = pos.w + posx;
int posy = button["y"].Float();
if (posy < 0)
posy = pos.h + posy;
return new CAdventureMapButton(help, command, posx, posy, button["name"].String(), button["hotkey"].Float());
}
CMenuEntry::CMenuEntry(CMenuScreen* parent, const JsonNode &config)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
type |= REDRAW_PARENT;
pos = parent->pos;
BOOST_FOREACH(const JsonNode& node, config["images"].Vector())
images.push_back(createPicture(node));

View File

@ -51,6 +51,7 @@ class CMenuScreen : public CIntObject
CTabbedInt *tabs;
CPicture * background;
std::vector<CPicture*> images;
CIntObject *createTab(size_t index);

View File

@ -70,6 +70,21 @@ CPicture::CPicture(SDL_Surface *BG, const Rect &SrcRect, int x /*= 0*/, int y /*
freeSurf = free;
}
void CPicture::setSurface(SDL_Surface *to)
{
bg = to;
if (srcRect)
{
pos.w = srcRect->w;
pos.h = srcRect->h;
}
else
{
pos.w = bg->w;
pos.h = bg->h;
}
}
CPicture::~CPicture()
{
if(freeSurf)
@ -115,6 +130,17 @@ void CPicture::convertToScreenBPP()
SDL_FreeSurface(hlp);
}
void CPicture::scaleTo(Point size)
{
SDL_Surface * scaled = CSDL_Ext::scaleSurface(bg, size.x, size.y);
if(freeSurf)
SDL_FreeSurface(bg);
setSurface(scaled);
freeSurf = false;
}
void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color)
{
pos += r;

View File

@ -34,6 +34,7 @@ public:
// Image class
class CPicture : public CIntObject
{
void setSurface(SDL_Surface *to);
public:
SDL_Surface * bg;
Rect * srcRect; //if NULL then whole surface will be used
@ -53,6 +54,7 @@ public:
~CPicture();
void init();
void scaleTo(Point size);
void createSimpleRect(const Rect &r, bool screenFormat, ui32 color);
void show(SDL_Surface * to);
void showAll(SDL_Surface * to);

View File

@ -1125,14 +1125,14 @@ void scaleSurfaceInternal(SDL_Surface *surf, SDL_Surface *ret)
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
//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
//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;
@ -1145,7 +1145,7 @@ void scaleSurfaceInternal(SDL_Surface *surf, SDL_Surface *ret)
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);
//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);
@ -1156,12 +1156,14 @@ void scaleSurfaceInternal(SDL_Surface *surf, SDL_Surface *ret)
}
}
/// scaling via bilinear interpolation algorithm.
/// NOTE: best results are for scaling in range 50%...200%
// scaling via bilinear interpolation algorithm.
// NOTE: best results are for scaling in range 50%...200%.
// And upscaling looks awful right now - should be fixed somehow
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
@ -1169,6 +1171,10 @@ SDL_Surface * CSDL_Ext::scaleSurface(SDL_Surface *surf, int width, int height)
return nullptr;
}
//Same size? return copy - this should more be faster
if (width == surf->w && height == surf->h)
return copySurface(surf);
SDL_Surface *ret = newSurface(width, height, surf);
switch(surf->format->BytesPerPixel)

View File

@ -174,6 +174,7 @@ 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
//scale surface to required size. Won't work with indexed surfaces
SDL_Surface * scaleSurface(SDL_Surface *surf, int width, int height);
template<int bpp>

View File

@ -2,8 +2,10 @@
//Main menu window, consists of several sub-menus aka items
"window":
{
"background" : "ZPIC1005",
//"scalable" : true, //background will be scaled to screen size
"video" : {"x": 8, "y": 105, "name":"ACREDIT.SMK" },//Floating WoG logo
"images" : [ {"x": 0, "y": 0, "name":"ZPIC1005"} ],//Background image
//"images" : [],//Optioal, contains any additional images in the same format as video
"items" :
[
{
@ -27,7 +29,7 @@
{"x": 545, "y": 358, "name":"ZTTUTOR", "hotkey" : 116, "help": 13, "command": "start tutorial"},
{"x": 582, "y": 464, "name":"ZTBACK", "hotkey" : 27, "help": 14, "command": "to main"}
],
"images": [ {"x": 114, "y": 312, "name":"ZNEWGAM"} ]
"images": [ {"x": 114, "y": 312, "name":"ZNEWGAM"} ]
},
{
"name" : "load",
@ -39,7 +41,7 @@
{"x": 545, "y": 358, "name":"ZTTUTOR", "hotkey" : 116, "help": 13, "command": "load tutorial"},
{"x": 582, "y": 464, "name":"ZTBACK", "hotkey" : 27, "help": 14, "command": "to main"}
],
"images": [ {"x": 114, "y": 312, "name":"ZLOADGAM"} ]
"images": [ {"x": 114, "y": 312, "name":"ZLOADGAM"} ]
},
{
"name" : "campaign",