mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-17 01:32:21 +02:00
- ComponentBox usage in 2 windows: levelup and build screen
- Components have selectable image size - fixed #794
This commit is contained in:
@ -1128,6 +1128,15 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
|
|||||||
std::set<int> toBuild = cb->getBuildingRequiments(t, building);
|
std::set<int> toBuild = cb->getBuildingRequiments(t, building);
|
||||||
toBuild.insert(building);
|
toBuild.insert(building);
|
||||||
|
|
||||||
|
BOOST_FOREACH(int buildID, toBuild)
|
||||||
|
{
|
||||||
|
int canBuild = cb->canBuildStructure(t, buildID);
|
||||||
|
if (canBuild == EBuildingState::HAVE_CAPITAL
|
||||||
|
|| canBuild == EBuildingState::FORBIDDEN
|
||||||
|
|| canBuild == EBuildingState::NO_WATER)
|
||||||
|
return false; //we won't be able to build this
|
||||||
|
}
|
||||||
|
|
||||||
if (maxDays && toBuild.size() > maxDays)
|
if (maxDays && toBuild.size() > maxDays)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1211,8 +1220,8 @@ void VCAI::buildStructure(const CGTownInstance * t)
|
|||||||
if (tryBuildAnyStructure(t, std::vector<int>(essential, essential + ARRAY_COUNT(essential))))
|
if (tryBuildAnyStructure(t, std::vector<int>(essential, essential + ARRAY_COUNT(essential))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//we're running out of gold - try to build something gold-producing. Multiplier can be tweaked
|
//we're running out of gold - try to build something gold-producing. Multiplier can be tweaked, 6 is minimum due to buildings costs
|
||||||
if (currentRes[Res::GOLD] < income[Res::GOLD] * 4)
|
if (currentRes[Res::GOLD] < income[Res::GOLD] * 6)
|
||||||
if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
|
if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -791,7 +791,6 @@ void CInfoBar::CVisibleInfo::loadComponent(const Component compToDisplay, std::s
|
|||||||
comp->moveTo(Point(pos.x+52, pos.y+54));
|
comp->moveTo(Point(pos.x+52, pos.y+54));
|
||||||
|
|
||||||
new CTextBox(message, Rect(8, 8, 164, 50), 0, FONT_SMALL, CENTER, Colors::Cornsilk);
|
new CTextBox(message, Rect(8, 8, 164, 50), 0, FONT_SMALL, CENTER, Colors::Cornsilk);
|
||||||
new CLabel(91, 158, FONT_SMALL, CENTER, Colors::Cornsilk, comp->getSubtitle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInfoBar::CVisibleInfo::updateEnemyTurn(double progress)
|
void CInfoBar::CVisibleInfo::updateEnemyTurn(double progress)
|
||||||
|
@ -1405,61 +1405,33 @@ std::string CBuildWindow::getTextForState(int state)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, int State, bool rightClick):
|
CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Building, int state, bool rightClick):
|
||||||
CWindowObject(PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0), "TPUBUILD"),
|
CWindowObject(PLAYER_COLORED | (rightClick ? RCLICK_POPUP : 0), "TPUBUILD"),
|
||||||
town(Town),
|
town(Town),
|
||||||
building(Building),
|
building(Building)
|
||||||
state(State)
|
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
|
|
||||||
buildingPic = new CAnimImage(graphics->buildingPics[town->subID], building->bid, 0, 125, 50);
|
new CAnimImage(graphics->buildingPics[town->subID], building->bid, 0, 125, 50);
|
||||||
Rect barRect(9, 494, 380, 18);
|
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||||
statusBar = new CGStatusBar(new CPicture(*background, barRect, 9, 494, false));
|
|
||||||
|
|
||||||
title = new CLabel(197, 30, FONT_MEDIUM, CENTER, Colors::Cornsilk,
|
new CLabel(197, 30, FONT_MEDIUM, CENTER, Colors::Cornsilk,
|
||||||
boost::str(boost::format(CGI->generaltexth->hcommands[7]) % building->Name()));
|
boost::str(boost::format(CGI->generaltexth->hcommands[7]) % building->Name()));
|
||||||
buildingDescr = new CTextBox(building->Description(), Rect(33, 135, 329, 67), 0, FONT_MEDIUM, CENTER);
|
new CTextBox(building->Description(), Rect(33, 135, 329, 67), 0, FONT_MEDIUM, CENTER);
|
||||||
buildingState = new CTextBox(getTextForState(state), Rect(33, 216, 329, 67), 0, FONT_SMALL, CENTER);
|
new CTextBox(getTextForState(state), Rect(33, 216, 329, 67), 0, FONT_SMALL, CENTER);
|
||||||
|
|
||||||
|
//Create components for all required resources
|
||||||
|
std::vector<CComponent *> components;
|
||||||
|
|
||||||
//Create objects for all required resources
|
|
||||||
for(int i = 0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
for(int i = 0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
||||||
{
|
{
|
||||||
if(building->resources[i])
|
if(building->resources[i])
|
||||||
{
|
{
|
||||||
resPicture.push_back(new CAnimImage("RESOURCE", i));
|
components.push_back(new CComponent(CComponent::resource, i, building->resources[i], CComponent::small));
|
||||||
resAmount.push_back(new CLabel(0,0, FONT_SMALL, CENTER, Colors::Cornsilk,
|
|
||||||
boost::lexical_cast<std::string>(building->resources[i])));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui32 rowSize[2];
|
new CComponentBox(components, Rect(25, 300, pos.w - 50, 130));
|
||||||
int posY;
|
|
||||||
if (resAmount.size() > 4)
|
|
||||||
{//Resources will be placed in multiple rows
|
|
||||||
rowSize[0] = (resAmount.size()+1)/2;
|
|
||||||
posY = 303;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{//one row
|
|
||||||
rowSize[0] = resAmount.size();
|
|
||||||
posY = 340;
|
|
||||||
}
|
|
||||||
rowSize[1] = resAmount.size() - rowSize[0];
|
|
||||||
|
|
||||||
ui32 index=0;
|
|
||||||
for (size_t row=0; row<2; row++)
|
|
||||||
{
|
|
||||||
int posX = pos.w/2 - rowSize[row] * 40 + 24;
|
|
||||||
for (size_t i=0; i<rowSize[row]; i++)
|
|
||||||
{//Move current resource to correct position
|
|
||||||
resPicture[index]->moveBy(Point(posX, posY));
|
|
||||||
resAmount[index]->moveBy(Point(posX+16, posY+48));
|
|
||||||
posX += 80;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
posY +=75;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!rightClick)
|
if(!rightClick)
|
||||||
{ //normal window
|
{ //normal window
|
||||||
|
@ -267,20 +267,10 @@ class CBuildWindow: public CWindowObject
|
|||||||
{
|
{
|
||||||
const CGTownInstance *town;
|
const CGTownInstance *town;
|
||||||
const CBuilding *building;
|
const CBuilding *building;
|
||||||
int state; //state - same as CHallInterface::CBuildingBox::state
|
|
||||||
|
|
||||||
CAnimImage *buildingPic;
|
|
||||||
CAdventureMapButton *buy;
|
CAdventureMapButton *buy;
|
||||||
CAdventureMapButton *cancel;
|
CAdventureMapButton *cancel;
|
||||||
|
|
||||||
CLabel * title;
|
|
||||||
CTextBox * buildingDescr;
|
|
||||||
CTextBox * buildingState;
|
|
||||||
CGStatusBar *statusBar;
|
|
||||||
|
|
||||||
std::vector<CAnimImage *> resPicture;
|
|
||||||
std::vector<CLabel *> resAmount;
|
|
||||||
|
|
||||||
std::string getTextForState(int state);
|
std::string getTextForState(int state);
|
||||||
void buyFunc();
|
void buyFunc();
|
||||||
|
|
||||||
|
@ -768,12 +768,12 @@ void CInfoPopup::init(int x, int y)
|
|||||||
vstd::amin(pos.y, screen->h - bitmap->h);
|
vstd::amin(pos.y, screen->h - bitmap->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
CComponent::CComponent(Etype Type, int Subtype, int Val, bool showSubtitles):
|
CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize):
|
||||||
image(nullptr),
|
image(nullptr),
|
||||||
perDay(false)
|
perDay(false)
|
||||||
{
|
{
|
||||||
addUsedEvents(RCLICK);
|
addUsedEvents(RCLICK);
|
||||||
init(Type, Subtype, Val, showSubtitles);
|
init(Type, Subtype, Val, imageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
CComponent::CComponent(const Component &c):
|
CComponent::CComponent(const Component &c):
|
||||||
@ -786,66 +786,79 @@ CComponent::CComponent(const Component &c):
|
|||||||
perDay = true;
|
perDay = true;
|
||||||
|
|
||||||
if(c.id == Component::EXPERIENCE)
|
if(c.id == Component::EXPERIENCE)
|
||||||
init(experience,c.subtype,c.val, true);
|
init(experience,c.subtype,c.val, large);
|
||||||
else if(c.id == Component::SPELL)
|
else if(c.id == Component::SPELL)
|
||||||
init(spell,c.subtype,c.val, true);
|
init(spell,c.subtype,c.val, large);
|
||||||
else
|
else
|
||||||
init((Etype)c.id,c.subtype,c.val, true);
|
init((Etype)c.id,c.subtype,c.val, large);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CComponent::init(Etype Type, int Subtype, int Val, bool showSubtitles)
|
void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
|
|
||||||
compType = Type;
|
compType = Type;
|
||||||
subtype = Subtype;
|
subtype = Subtype;
|
||||||
val = Val;
|
val = Val;
|
||||||
|
size = imageSize;
|
||||||
|
|
||||||
setSurface(getFileName(), getIndex());
|
setSurface(getFileName()[size], getIndex());
|
||||||
|
|
||||||
pos.w = image->pos.w;
|
pos.w = image->pos.w;
|
||||||
pos.h = image->pos.h;
|
pos.h = image->pos.h;
|
||||||
|
|
||||||
if (showSubtitles)
|
pos.h += 4; //distance between text and image
|
||||||
|
|
||||||
|
std::vector<std::string> textLines = CMessage::breakText(getSubtitle(), std::max<int>(80, pos.w), FONT_SMALL);
|
||||||
|
BOOST_FOREACH(auto & line, textLines)
|
||||||
{
|
{
|
||||||
pos.h += 4; //distance between text and image
|
int height = graphics->fonts[FONT_SMALL]->height;
|
||||||
|
CLabel * label = new CLabel(pos.w/2, pos.h + height/2, FONT_SMALL, CENTER, Colors::Cornsilk, line);
|
||||||
|
|
||||||
std::vector<std::string> textLines = CMessage::breakText(getSubtitle(), std::max<int>(64, pos.w), FONT_SMALL);
|
pos.h += height;
|
||||||
BOOST_FOREACH(auto & line, textLines)
|
if (label->pos.w > pos.w)
|
||||||
{
|
{
|
||||||
int height = graphics->fonts[FONT_SMALL]->height;
|
pos.x -= (label->pos.w - pos.w)/2;
|
||||||
CLabel * label = new CLabel(pos.w/2, pos.h + height/2, FONT_SMALL, CENTER, Colors::Cornsilk, line);
|
pos.w = label->pos.w;
|
||||||
|
|
||||||
pos.h += height;
|
|
||||||
if (label->pos.w > pos.w)
|
|
||||||
{
|
|
||||||
pos.x -= (label->pos.w - pos.w)/2;
|
|
||||||
pos.w = label->pos.w;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CComponent::getFileName()
|
const std::vector<std::string> CComponent::getFileName()
|
||||||
{
|
{
|
||||||
|
static const std::string primSkillsArr [] = {"PSKIL32", "PSKIL32", "PSKIL42", "PSKILL"};
|
||||||
|
static const std::string secSkillsArr [] = {"SECSK32", "SECSK32", "SECSKILL", "SECSK82"};
|
||||||
|
static const std::string resourceArr [] = {"SMALRES", "RESOURCE", "RESOUR82", "RESOUR82"};
|
||||||
|
static const std::string creatureArr [] = {"CPRSMALL", "CPRSMALL", "TWCRPORT", "TWCRPORT"};
|
||||||
|
static const std::string artifactArr[] = {"Artifact", "Artifact", "Artifact", "Artifact"};
|
||||||
|
static const std::string spellsArr [] = {"SpellInt", "SpellInt", "SPELLSCR", "SPELLSCR"};
|
||||||
|
static const std::string moraleArr [] = {"IMRL22", "IMRL30", "IMRL42", "imrl82"};
|
||||||
|
static const std::string luckArr [] = {"ILCK22", "ILCK30", "ILCK42", "ilck82"};
|
||||||
|
static const std::string heroArr [] = {"PortraitsSmall", "PortraitsSmall", "PortraitsLarge", "PortraitsLarge"};
|
||||||
|
static const std::string flagArr [] = {"CREST58", "CREST58", "CREST58", "CREST58"};
|
||||||
|
|
||||||
|
auto gen = [](const std::string * arr)
|
||||||
|
{
|
||||||
|
return std::vector<std::string>(arr, arr + 4);
|
||||||
|
};
|
||||||
|
|
||||||
switch(compType)
|
switch(compType)
|
||||||
{
|
{
|
||||||
case primskill: return "PSKILL";
|
case primskill: return gen(primSkillsArr);
|
||||||
case secskill: return "SECSK82";
|
case secskill: return gen(secSkillsArr);
|
||||||
case resource: return "RESOUR82";
|
case resource: return gen(resourceArr);
|
||||||
case creature: return "TWCRPORT";
|
case creature: return gen(creatureArr);
|
||||||
case artifact: return "ARTIFACT";
|
case artifact: return gen(artifactArr);
|
||||||
case experience: return "PSKILL";
|
case experience: return gen(primSkillsArr);
|
||||||
case secskill44: return "SECSKILL";
|
case spell: return gen(spellsArr);
|
||||||
case spell: return "SPELLSCR";
|
case morale: return gen(moraleArr);
|
||||||
case morale: return "IMRL82";
|
case luck: return gen(luckArr);
|
||||||
case luck: return "ILCK82";
|
case building: return std::vector<std::string>(4, graphics->buildingPics[subtype]);
|
||||||
case building: return graphics->buildingPics[subtype];
|
case hero: return gen(heroArr);
|
||||||
case hero: return "PortraitsLarge";
|
case flag: return gen(flagArr);
|
||||||
case flag: return "CREST58";
|
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
return "";
|
return std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CComponent::getIndex()
|
size_t CComponent::getIndex()
|
||||||
@ -858,7 +871,6 @@ size_t CComponent::getIndex()
|
|||||||
case creature: return subtype+2;
|
case creature: return subtype+2;
|
||||||
case artifact: return subtype;
|
case artifact: return subtype;
|
||||||
case experience: return 4;
|
case experience: return 4;
|
||||||
case secskill44: return subtype*3 + 3 + val - 1;
|
|
||||||
case spell: return subtype;
|
case spell: return subtype;
|
||||||
case morale: return val+3;
|
case morale: return val+3;
|
||||||
case luck: return val+3;
|
case luck: return val+3;
|
||||||
@ -881,7 +893,6 @@ std::string CComponent::getDescription()
|
|||||||
case creature: return "";
|
case creature: return "";
|
||||||
case artifact: return CGI->arth->artifacts[subtype]->Description();
|
case artifact: return CGI->arth->artifacts[subtype]->Description();
|
||||||
case experience: return CGI->generaltexth->allTexts[241];
|
case experience: return CGI->generaltexth->allTexts[241];
|
||||||
case secskill44: return CGI->generaltexth->skillInfoTexts[subtype][val-1];
|
|
||||||
case spell: return CGI->spellh->spells[subtype]->descriptions[val];
|
case spell: return CGI->spellh->spells[subtype]->descriptions[val];
|
||||||
case morale: return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)];
|
case morale: return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)];
|
||||||
case luck: return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)];
|
case luck: return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)];
|
||||||
@ -909,12 +920,11 @@ std::string CComponent::getSubtitleInternal()
|
|||||||
switch(compType)
|
switch(compType)
|
||||||
{
|
{
|
||||||
case primskill: return boost::str(boost::format("%+d %s") % val % (subtype < 4 ? CGI->generaltexth->primarySkillNames[subtype] : CGI->generaltexth->allTexts[387]));
|
case primskill: return boost::str(boost::format("%+d %s") % val % (subtype < 4 ? CGI->generaltexth->primarySkillNames[subtype] : CGI->generaltexth->allTexts[387]));
|
||||||
case secskill: return CGI->generaltexth->levels[val-1] + " " + CGI->generaltexth->skillName[subtype];
|
case secskill: return CGI->generaltexth->levels[val-1] + "\n" + CGI->generaltexth->skillName[subtype];
|
||||||
case resource: return boost::lexical_cast<std::string>(val);
|
case resource: return boost::lexical_cast<std::string>(val);
|
||||||
case creature: return (val? boost::lexical_cast<std::string>(val) + " " : "") + CGI->creh->creatures[subtype]->*(val != 1 ? &CCreature::namePl : &CCreature::nameSing);
|
case creature: return (val? boost::lexical_cast<std::string>(val) + " " : "") + CGI->creh->creatures[subtype]->*(val != 1 ? &CCreature::namePl : &CCreature::nameSing);
|
||||||
case artifact: return CGI->arth->artifacts[subtype]->Name();
|
case artifact: return CGI->arth->artifacts[subtype]->Name();
|
||||||
case experience: return (subtype && val==1) ? CGI->generaltexth->allTexts[442] : boost::lexical_cast<std::string>(val);
|
case experience: return (subtype && val==1) ? CGI->generaltexth->allTexts[442] : boost::lexical_cast<std::string>(val);
|
||||||
case secskill44: return CGI->generaltexth->levels[val-1] + " " + CGI->generaltexth->skillName[subtype];
|
|
||||||
case spell: return CGI->spellh->spells[subtype]->name;
|
case spell: return CGI->spellh->spells[subtype]->name;
|
||||||
case morale: return "";
|
case morale: return "";
|
||||||
case luck: return "";
|
case luck: return "";
|
||||||
@ -961,8 +971,8 @@ CSelectableComponent::CSelectableComponent(const Component &c, boost::function<v
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect):
|
CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize, boost::function<void()> OnSelect):
|
||||||
CComponent(Type,Sub,Val),onSelect(OnSelect)
|
CComponent(Type,Sub,Val, imageSize),onSelect(OnSelect)
|
||||||
{
|
{
|
||||||
type |= REDRAW_PARENT;
|
type |= REDRAW_PARENT;
|
||||||
addUsedEvents(LCLICK | KEYBOARD);
|
addUsedEvents(LCLICK | KEYBOARD);
|
||||||
@ -989,13 +999,15 @@ void CSelectableComponent::showAll(SDL_Surface * to)
|
|||||||
|
|
||||||
void CComponentBox::selectionChanged(CSelectableComponent * newSelection)
|
void CComponentBox::selectionChanged(CSelectableComponent * newSelection)
|
||||||
{
|
{
|
||||||
assert(newSelection != selected);
|
if (newSelection == selected)
|
||||||
|
return;
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
selected->select(false);
|
selected->select(false);
|
||||||
|
|
||||||
selected = newSelection;
|
selected = newSelection;
|
||||||
onSelect(selectedIndex());
|
if (onSelect)
|
||||||
|
onSelect(selectedIndex());
|
||||||
|
|
||||||
if (selected)
|
if (selected)
|
||||||
selected->select(true);
|
selected->select(true);
|
||||||
@ -1008,14 +1020,35 @@ int CComponentBox::selectedIndex()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point CComponentBox::getOrTextPos(CComponent *left, CComponent *right)
|
||||||
|
{
|
||||||
|
int leftSubtitle = ( left->pos.w - left->image->pos.w) / 2;
|
||||||
|
int rightSubtitle = (right->pos.w - right->image->pos.w) / 2;
|
||||||
|
int fullDistance = getDistance(left, right) + leftSubtitle + rightSubtitle;
|
||||||
|
|
||||||
|
return Point(fullDistance/2 - leftSubtitle, (left->image->pos.h + right->image->pos.h) / 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CComponentBox::getDistance(CComponent *left, CComponent *right)
|
||||||
|
{
|
||||||
|
static const int betweenImagesMin = 50;
|
||||||
|
static const int betweenSubtitlesMin = 10;
|
||||||
|
|
||||||
|
int leftSubtitle = ( left->pos.w - left->image->pos.w) / 2;
|
||||||
|
int rightSubtitle = (right->pos.w - right->image->pos.w) / 2;
|
||||||
|
int subtitlesOffset = leftSubtitle + rightSubtitle;
|
||||||
|
|
||||||
|
return std::max(betweenSubtitlesMin, betweenImagesMin - subtitlesOffset);
|
||||||
|
}
|
||||||
|
|
||||||
void CComponentBox::placeComponents(bool selectable)
|
void CComponentBox::placeComponents(bool selectable)
|
||||||
{
|
{
|
||||||
|
static const int betweenRows = 22;
|
||||||
|
|
||||||
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
if (components.empty())
|
if (components.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static const int betweenComponents = 50;
|
|
||||||
static const int betweenRows = 22;
|
|
||||||
|
|
||||||
//prepare components
|
//prepare components
|
||||||
BOOST_FOREACH(auto & comp, components)
|
BOOST_FOREACH(auto & comp, components)
|
||||||
{
|
{
|
||||||
@ -1032,35 +1065,46 @@ void CComponentBox::placeComponents(bool selectable)
|
|||||||
comps(Comps), width (Width), height (Height){};
|
comps(Comps), width (Width), height (Height){};
|
||||||
};
|
};
|
||||||
std::vector<RowData> rows;
|
std::vector<RowData> rows;
|
||||||
//rows.push_back({0, 0, 0}); //there is NO such syntax!
|
|
||||||
rows.push_back (RowData (0,0,0));
|
rows.push_back (RowData (0,0,0));
|
||||||
|
|
||||||
//split components in rows
|
//split components in rows
|
||||||
BOOST_FOREACH(auto & comp, components)
|
CComponent * prevComp = nullptr;
|
||||||
|
|
||||||
|
BOOST_FOREACH(CComponent * comp, components)
|
||||||
{
|
{
|
||||||
//make sure that components are smaller than our width
|
//make sure that components are smaller than our width
|
||||||
assert(pos.w == 0 || pos.w < comp->pos.w);
|
//assert(pos.w == 0 || pos.w < comp->pos.w);
|
||||||
|
|
||||||
|
const int distance = prevComp ? getDistance(prevComp, comp) : 0;
|
||||||
|
|
||||||
//start next row
|
//start next row
|
||||||
if (pos.w != 0 && rows.back().width + comp->pos.w > pos.w)
|
if (pos.w != 0 && rows.back().width + comp->pos.w + distance > pos.w)
|
||||||
|
{
|
||||||
|
prevComp = nullptr;
|
||||||
rows.push_back (RowData (0,0,0));
|
rows.push_back (RowData (0,0,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevComp)
|
||||||
|
rows.back().width += distance;
|
||||||
|
|
||||||
rows.back().comps++;
|
rows.back().comps++;
|
||||||
rows.back().width += comp->pos.w;
|
rows.back().width += comp->pos.w;
|
||||||
|
|
||||||
vstd::amax(rows.back().height, comp->pos.h);
|
vstd::amax(rows.back().height, comp->pos.h);
|
||||||
|
prevComp = comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos.w == 0)
|
if (pos.w == 0)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(auto & row, rows)
|
BOOST_FOREACH(auto & row, rows)
|
||||||
vstd::amax(pos.w, row.width + (row.comps - 1) * betweenComponents);
|
vstd::amax(pos.w, row.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
int height = (rows.size() - 1) * betweenRows;
|
int height = (rows.size() - 1) * betweenRows;
|
||||||
BOOST_FOREACH(auto & row, rows)
|
BOOST_FOREACH(auto & row, rows)
|
||||||
height += row.height;
|
height += row.height;
|
||||||
|
|
||||||
assert(pos.h == 0 || pos.h < height);
|
//assert(pos.h == 0 || pos.h < height);
|
||||||
if (pos.h == 0)
|
if (pos.h == 0)
|
||||||
pos.h = height;
|
pos.h = height;
|
||||||
|
|
||||||
@ -1070,12 +1114,26 @@ void CComponentBox::placeComponents(bool selectable)
|
|||||||
//move components to their positions
|
//move components to their positions
|
||||||
for (size_t row = 0; row < rows.size(); row++)
|
for (size_t row = 0; row < rows.size(); row++)
|
||||||
{
|
{
|
||||||
|
prevComp = nullptr;
|
||||||
|
|
||||||
int currentX = (pos.w - rows[row].width) / 2;
|
int currentX = (pos.w - rows[row].width) / 2;
|
||||||
for (size_t col = 0; col < rows[row].comps; col++)
|
for (size_t col = 0; col < rows[row].comps; col++)
|
||||||
{
|
{
|
||||||
|
if (prevComp)
|
||||||
|
{
|
||||||
|
if (selectable)
|
||||||
|
{
|
||||||
|
Point orPos = Point(currentX, currentY) + getOrTextPos(prevComp, *iter);
|
||||||
|
|
||||||
|
new CLabel(orPos.x, orPos.y, FONT_MEDIUM, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[4]);
|
||||||
|
}
|
||||||
|
currentX += getDistance(prevComp, *iter);
|
||||||
|
}
|
||||||
|
|
||||||
(*iter)->moveBy(Point(currentX, currentY));
|
(*iter)->moveBy(Point(currentX, currentY));
|
||||||
currentX += (*iter)->pos.w + betweenComponents;
|
currentX += (*iter)->pos.w;
|
||||||
iter++;
|
|
||||||
|
prevComp = *(iter++);
|
||||||
}
|
}
|
||||||
currentY += rows[row].height + betweenRows;
|
currentY += rows[row].height + betweenRows;
|
||||||
}
|
}
|
||||||
@ -1085,6 +1143,8 @@ CComponentBox::CComponentBox(CComponent * _components, Rect position):
|
|||||||
components(1, _components),
|
components(1, _components),
|
||||||
selected(nullptr)
|
selected(nullptr)
|
||||||
{
|
{
|
||||||
|
type |= REDRAW_PARENT;
|
||||||
|
pos = position + pos;
|
||||||
placeComponents(false);
|
placeComponents(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1092,14 +1152,29 @@ CComponentBox::CComponentBox(std::vector<CComponent *> _components, Rect positio
|
|||||||
components(_components),
|
components(_components),
|
||||||
selected(nullptr)
|
selected(nullptr)
|
||||||
{
|
{
|
||||||
|
type |= REDRAW_PARENT;
|
||||||
|
pos = position + pos;
|
||||||
placeComponents(false);
|
placeComponents(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CComponentBox::CComponentBox(std::vector<CSelectableComponent *> _components, Rect position, boost::function<void(int newID)> _onSelect):
|
CComponentBox::CComponentBox(std::vector<CSelectableComponent *> _components, Rect position, boost::function<void(int newID)> _onSelect):
|
||||||
components(_components.begin(), _components.end()),
|
components(_components.begin(), _components.end()),
|
||||||
selected(nullptr)
|
selected(nullptr),
|
||||||
|
onSelect(_onSelect)
|
||||||
{
|
{
|
||||||
|
type |= REDRAW_PARENT;
|
||||||
|
pos = position + pos;
|
||||||
placeComponents(true);
|
placeComponents(true);
|
||||||
|
|
||||||
|
assert(!components.empty());
|
||||||
|
|
||||||
|
int key = SDLK_1;
|
||||||
|
BOOST_FOREACH(auto & comp, _components)
|
||||||
|
{
|
||||||
|
comp->onSelect = boost::bind(&CComponentBox::selectionChanged, this, comp);
|
||||||
|
comp->assignedKeys.insert(key++);
|
||||||
|
}
|
||||||
|
selectionChanged(_components.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSelWindow::selectionChange(unsigned to)
|
void CSelWindow::selectionChange(unsigned to)
|
||||||
@ -1552,17 +1627,6 @@ CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<u
|
|||||||
|
|
||||||
LOCPLINT->showingDialog->setn(true);
|
LOCPLINT->showingDialog->setn(true);
|
||||||
|
|
||||||
for(size_t i=0;i<skills.size();i++)
|
|
||||||
{
|
|
||||||
comps.push_back(new CSelectableComponent(
|
|
||||||
CComponent::secskill44,
|
|
||||||
skills[i],
|
|
||||||
hero->getSecSkillLevel( static_cast<CGHeroInstance::SecondarySkill>(skills[i]) )+1,
|
|
||||||
boost::bind(&CLevelWindow::selectionChanged,this,i)));
|
|
||||||
|
|
||||||
comps.back()->assignedKeys.insert(SDLK_1 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
new CAnimImage("PortraitsLarge", hero->portrait, 0, 170, 66);
|
new CAnimImage("PortraitsLarge", hero->portrait, 0, 170, 66);
|
||||||
new CAdventureMapButton("", "", boost::bind(&CLevelWindow::close, this), 297, 413, "IOKAY", SDLK_RETURN);
|
new CAdventureMapButton("", "", boost::bind(&CLevelWindow::close, this), 297, 413, "IOKAY", SDLK_RETURN);
|
||||||
|
|
||||||
@ -1579,49 +1643,30 @@ CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<u
|
|||||||
new CLabel(192, 253, FONT_MEDIUM, CENTER, Colors::Cornsilk,
|
new CLabel(192, 253, FONT_MEDIUM, CENTER, Colors::Cornsilk,
|
||||||
CGI->generaltexth->primarySkillNames[pskill] + " +1");
|
CGI->generaltexth->primarySkillNames[pskill] + " +1");
|
||||||
|
|
||||||
// "or"
|
if (!skills.empty())
|
||||||
std::string text = CGI->generaltexth->allTexts[4];
|
|
||||||
|
|
||||||
int fontWidth = graphics->fonts[FONT_MEDIUM]->getWidth(text.c_str())/2;
|
|
||||||
|
|
||||||
int curx = pos.w/2 - ( skills.size()*44 + (skills.size()-1)*(36+fontWidth) )/2;
|
|
||||||
|
|
||||||
for(size_t i=0; i<comps.size(); i++)
|
|
||||||
{
|
{
|
||||||
comps[i]->moveTo(Point(pos.x + curx, pos.y + 326));
|
std::vector<CSelectableComponent *> comps;
|
||||||
if( i < (comps.size()-1) )
|
|
||||||
|
for(size_t i=0;i<skills.size();i++)
|
||||||
{
|
{
|
||||||
curx += comps[i]->pos.w + 10; //skill width + margin to "or"
|
comps.push_back(new CSelectableComponent(
|
||||||
new CLabel(curx, 346, FONT_MEDIUM, CENTER, Colors::Cornsilk, text);
|
CComponent::secskill,
|
||||||
curx += fontWidth+10;
|
skills[i],
|
||||||
|
hero->getSecSkillLevel( static_cast<CGHeroInstance::SecondarySkill>(skills[i]) )+1,
|
||||||
|
CComponent::medium));
|
||||||
}
|
}
|
||||||
|
box = new CComponentBox(comps, Rect(25, 300, pos.w - 50, 100));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if(!comps.empty())
|
box = nullptr;
|
||||||
{
|
|
||||||
comps[0]->select(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CLevelWindow::selectionChanged(unsigned to)
|
|
||||||
{
|
|
||||||
for(int i=0;i<comps.size();i++)
|
|
||||||
if(i==to)
|
|
||||||
comps[i]->select(true);
|
|
||||||
else
|
|
||||||
comps[i]->select(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CLevelWindow::~CLevelWindow()
|
CLevelWindow::~CLevelWindow()
|
||||||
{
|
{
|
||||||
for(int i=0;i<comps.size();i++)
|
//FIXME: call callback if there was nothing to select?
|
||||||
{
|
if (box && box->selectedIndex() != -1)
|
||||||
if(comps[i]->selected)
|
cb(box->selectedIndex());
|
||||||
{
|
|
||||||
cb(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOCPLINT->showingDialog->setn(false);
|
LOCPLINT->showingDialog->setn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,22 +176,31 @@ class CComponent : public virtual CIntObject
|
|||||||
public:
|
public:
|
||||||
enum Etype
|
enum Etype
|
||||||
{
|
{
|
||||||
primskill, secskill, resource, creature, artifact, experience, secskill44, spell, morale, luck, building, hero, flag
|
primskill, secskill, resource, creature, artifact, experience, spell, morale, luck, building, hero, flag
|
||||||
|
};
|
||||||
|
|
||||||
|
//NOTE: not all types have exact these sizes or have less than 4 of them. In such cases closest one will be used
|
||||||
|
enum ESize
|
||||||
|
{
|
||||||
|
tiny, // ~22-24px
|
||||||
|
small, // ~30px
|
||||||
|
medium,// ~42px
|
||||||
|
large // ~82px
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t getIndex();
|
size_t getIndex();
|
||||||
std::string getFileName();
|
const std::vector<std::string> getFileName();
|
||||||
void setSurface(std::string defName, int imgPos);
|
void setSurface(std::string defName, int imgPos);
|
||||||
std::string getSubtitleInternal();
|
std::string getSubtitleInternal();
|
||||||
|
|
||||||
void init(Etype Type, int Subtype, int Val, bool showSubtitles);
|
void init(Etype Type, int Subtype, int Val, ESize imageSize);
|
||||||
|
|
||||||
protected:
|
|
||||||
CAnimImage *image; //our image
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
CAnimImage *image; //our image
|
||||||
|
|
||||||
Etype compType; //component type
|
Etype compType; //component type
|
||||||
|
ESize size; //component size.
|
||||||
int subtype; //type-dependant subtype. See getSomething methods for details
|
int subtype; //type-dependant subtype. See getSomething methods for details
|
||||||
int val; // value \ strength \ amount of component. See getSomething methods for details
|
int val; // value \ strength \ amount of component. See getSomething methods for details
|
||||||
bool perDay; // add "per day" text to subtitle
|
bool perDay; // add "per day" text to subtitle
|
||||||
@ -199,7 +208,7 @@ public:
|
|||||||
std::string getDescription();
|
std::string getDescription();
|
||||||
std::string getSubtitle();
|
std::string getSubtitle();
|
||||||
|
|
||||||
CComponent(Etype Type, int Subtype, int Val, bool showSubtitles = true); //c-tor
|
CComponent(Etype Type, int Subtype, int Val, ESize imageSize=large);//c-tor
|
||||||
CComponent(const Component &c); //c-tor
|
CComponent(const Component &c); //c-tor
|
||||||
|
|
||||||
void clickRight(tribool down, bool previousState); //call-in
|
void clickRight(tribool down, bool previousState); //call-in
|
||||||
@ -217,7 +226,7 @@ public:
|
|||||||
void select(bool on);
|
void select(bool on);
|
||||||
|
|
||||||
void clickLeft(tribool down, bool previousState); //call-in
|
void clickLeft(tribool down, bool previousState); //call-in
|
||||||
CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect = 0); //c-tor
|
CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, boost::function<void()> OnSelect = 0); //c-tor
|
||||||
CSelectableComponent(const Component &c, boost::function<void()> OnSelect = 0); //c-tor
|
CSelectableComponent(const Component &c, boost::function<void()> OnSelect = 0); //c-tor
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -231,6 +240,13 @@ class CComponentBox : public CIntObject
|
|||||||
boost::function<void(int newID)> onSelect;
|
boost::function<void(int newID)> onSelect;
|
||||||
|
|
||||||
void selectionChanged(CSelectableComponent * newSelection);
|
void selectionChanged(CSelectableComponent * newSelection);
|
||||||
|
|
||||||
|
//get position of "or" text between these comps
|
||||||
|
//it will place "or" equidistant to both images
|
||||||
|
Point getOrTextPos(CComponent *left, CComponent * right);
|
||||||
|
|
||||||
|
//get distance between these copmonents
|
||||||
|
int getDistance(CComponent *left, CComponent * right);
|
||||||
void placeComponents(bool selectable);
|
void placeComponents(bool selectable);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -459,13 +475,15 @@ public:
|
|||||||
/// Raised up level windowe where you can select one out of two skills
|
/// Raised up level windowe where you can select one out of two skills
|
||||||
class CLevelWindow : public CWindowObject
|
class CLevelWindow : public CWindowObject
|
||||||
{
|
{
|
||||||
public:
|
CComponentBox * box; //skills to select
|
||||||
std::vector<CSelectableComponent *> comps; //skills to select
|
|
||||||
boost::function<void(ui32)> cb;
|
boost::function<void(ui32)> cb;
|
||||||
|
|
||||||
|
void selectionChanged(unsigned to);
|
||||||
|
public:
|
||||||
|
|
||||||
CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback); //c-tor
|
CLevelWindow(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback); //c-tor
|
||||||
~CLevelWindow(); //d-tor
|
~CLevelWindow(); //d-tor
|
||||||
void selectionChanged(unsigned to);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Resource bar like that at the bottom of the adventure map screen
|
/// Resource bar like that at the bottom of the adventure map screen
|
||||||
|
@ -108,13 +108,6 @@ void CGuiHandler::totalRedraw()
|
|||||||
{
|
{
|
||||||
for(int i=0;i<objsToBlit.size();i++)
|
for(int i=0;i<objsToBlit.size();i++)
|
||||||
objsToBlit[i]->showAll(screen2);
|
objsToBlit[i]->showAll(screen2);
|
||||||
|
|
||||||
// static int a = 0;
|
|
||||||
// if(a)
|
|
||||||
// {
|
|
||||||
// SDL_SaveBMP(screen, "s1.bmp");
|
|
||||||
// SDL_SaveBMP(screen2, "s2.bmp");
|
|
||||||
// }
|
|
||||||
blitAt(screen2,0,0,screen);
|
blitAt(screen2,0,0,screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +424,7 @@ SDLKey CGuiHandler::numToDigit( SDLKey key )
|
|||||||
case SDLK_KP_ENTER:
|
case SDLK_KP_ENTER:
|
||||||
return SDLK_RETURN;
|
return SDLK_RETURN;
|
||||||
default:
|
default:
|
||||||
tlog3 << "Illegal numkey conversion!" << std::endl;
|
//tlog3 << "Illegal numkey conversion!" << std::endl;
|
||||||
return SDLK_UNKNOWN;
|
return SDLK_UNKNOWN;
|
||||||
}
|
}
|
||||||
#undef REMOVE_KP
|
#undef REMOVE_KP
|
||||||
|
@ -456,7 +456,8 @@ bool CIntObject::captureThisEvent(const SDL_KeyboardEvent & key)
|
|||||||
|
|
||||||
void CKeyShortcut::keyPressed(const SDL_KeyboardEvent & key)
|
void CKeyShortcut::keyPressed(const SDL_KeyboardEvent & key)
|
||||||
{
|
{
|
||||||
if(vstd::contains(assignedKeys,key.keysym.sym))
|
if(vstd::contains(assignedKeys,key.keysym.sym)
|
||||||
|
|| vstd::contains(assignedKeys, CGuiHandler::numToDigit(key.keysym.sym)))
|
||||||
{
|
{
|
||||||
bool prev = pressedL;
|
bool prev = pressedL;
|
||||||
if(key.state == SDL_PRESSED)
|
if(key.state == SDL_PRESSED)
|
||||||
|
Reference in New Issue
Block a user