mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Merge pull request #4210 from Laserlicht/graphics_improvements
[1.6] Graphics improvements
This commit is contained in:
@@ -402,7 +402,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genBonusWindow()
|
||||
textBonusDescription = std::make_shared<CTextBox>(getDescription(), Rect(10, 100, pos.w - 20, 70), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||
}
|
||||
|
||||
OptionsTab::SelectionWindow::SelectionWindow(const PlayerColor & color, SelType _type)
|
||||
OptionsTab::SelectionWindow::SelectionWindow(const PlayerColor & color, SelType _type, int sliderPos)
|
||||
: CWindowObject(BORDERED), color(color)
|
||||
{
|
||||
addUsedEvents(LCLICK | SHOW_POPUP);
|
||||
@@ -434,15 +434,18 @@ OptionsTab::SelectionWindow::SelectionWindow(const PlayerColor & color, SelType
|
||||
if(initialFaction.isValid())
|
||||
allowedBonus.push_back(PlayerStartingBonus::RESOURCE);
|
||||
|
||||
recreate();
|
||||
recreate(sliderPos);
|
||||
}
|
||||
|
||||
int OptionsTab::SelectionWindow::calcLines(FactionID faction)
|
||||
std::tuple<int, int> OptionsTab::SelectionWindow::calcLines(FactionID faction)
|
||||
{
|
||||
double additionalItems = 1; // random
|
||||
int additionalItems = 1; // random
|
||||
|
||||
if(!faction.isValid())
|
||||
return std::ceil(((double)allowedFactions.size() + additionalItems) / elementsPerLine);
|
||||
return std::make_tuple(
|
||||
std::ceil(((double)allowedFactions.size() + additionalItems) / MAX_ELEM_PER_LINES),
|
||||
(allowedFactions.size() + additionalItems) % MAX_ELEM_PER_LINES
|
||||
);
|
||||
|
||||
int count = 0;
|
||||
for(auto & elemh : allowedHeroes)
|
||||
@@ -452,7 +455,10 @@ int OptionsTab::SelectionWindow::calcLines(FactionID faction)
|
||||
count++;
|
||||
}
|
||||
|
||||
return std::ceil(std::max((double)count + additionalItems, (double)allowedFactions.size() + additionalItems) / (double)elementsPerLine);
|
||||
return std::make_tuple(
|
||||
std::ceil(((double)count + additionalItems) / MAX_ELEM_PER_LINES),
|
||||
(count + additionalItems) % MAX_ELEM_PER_LINES
|
||||
);
|
||||
}
|
||||
|
||||
void OptionsTab::SelectionWindow::apply()
|
||||
@@ -482,13 +488,17 @@ void OptionsTab::SelectionWindow::setSelection()
|
||||
|
||||
void OptionsTab::SelectionWindow::reopen()
|
||||
{
|
||||
auto window = std::shared_ptr<SelectionWindow>(new SelectionWindow(color, type));
|
||||
close();
|
||||
if(CSH->isMyColor(color) || CSH->isHost())
|
||||
GH.windows().pushWindow(window);
|
||||
if(type == SelType::HERO && SEL->getStartInfo()->playerInfos.find(color)->second.castle == FactionID::RANDOM)
|
||||
close();
|
||||
else{
|
||||
auto window = std::shared_ptr<SelectionWindow>(new SelectionWindow(color, type, slider ? slider->getValue() : 0));
|
||||
close();
|
||||
if(CSH->isMyColor(color) || CSH->isHost())
|
||||
GH.windows().pushWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsTab::SelectionWindow::recreate()
|
||||
void OptionsTab::SelectionWindow::recreate(int sliderPos)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
@@ -497,32 +507,19 @@ void OptionsTab::SelectionWindow::recreate()
|
||||
elementsPerLine = allowedBonus.size();
|
||||
else
|
||||
{
|
||||
// try to make squarish
|
||||
if(type == SelType::TOWN)
|
||||
elementsPerLine = floor(sqrt(allowedFactions.size()));
|
||||
if(type == SelType::HERO)
|
||||
{
|
||||
int count = 0;
|
||||
for(auto & elem : allowedHeroes)
|
||||
{
|
||||
const CHero * type = elem.toHeroType();
|
||||
if(type->heroClass->faction == selectedFaction)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
elementsPerLine = floor(sqrt(count));
|
||||
}
|
||||
|
||||
amountLines = calcLines((type > SelType::TOWN) ? selectedFaction : FactionID::RANDOM);
|
||||
std::tie(amountLines, elementsPerLine) = calcLines((type > SelType::TOWN) ? selectedFaction : FactionID::RANDOM);
|
||||
if(amountLines > 1 || elementsPerLine == 0)
|
||||
elementsPerLine = MAX_ELEM_PER_LINES;
|
||||
}
|
||||
|
||||
int x = (elementsPerLine) * (ICON_BIG_WIDTH-1);
|
||||
int y = (amountLines) * (ICON_BIG_HEIGHT-1);
|
||||
int y = (std::min(amountLines, MAX_LINES)) * (ICON_BIG_HEIGHT-1);
|
||||
|
||||
pos = Rect(0, 0, x, y);
|
||||
int sliderWidth = ((amountLines > MAX_LINES) ? 16 : 0);
|
||||
|
||||
backgroundTexture = std::make_shared<FilledTexturePlayerColored>(ImagePath::builtin("DiBoxBck"), pos);
|
||||
pos = Rect(pos.x, pos.y, x + sliderWidth, y);
|
||||
|
||||
backgroundTexture = std::make_shared<FilledTexturePlayerColored>(ImagePath::builtin("DiBoxBck"), Rect(0, 0, pos.w - sliderWidth, pos.h));
|
||||
backgroundTexture->playerColored(PlayerColor(1));
|
||||
updateShadow();
|
||||
|
||||
@@ -532,7 +529,15 @@ void OptionsTab::SelectionWindow::recreate()
|
||||
genContentHeroes();
|
||||
if(type == SelType::BONUS)
|
||||
genContentBonus();
|
||||
genContentGrid(amountLines);
|
||||
genContentGrid(std::min(amountLines, MAX_LINES));
|
||||
|
||||
if(!slider && amountLines > MAX_LINES)
|
||||
{
|
||||
slider = std::make_shared<CSlider>(Point(x, 0), y, std::bind(&OptionsTab::SelectionWindow::sliderMove, this, _1), MAX_LINES, amountLines, 0, Orientation::VERTICAL, CSlider::BLUE);
|
||||
slider->setPanningStep(ICON_BIG_HEIGHT);
|
||||
slider->setScrollBounds(Rect(-pos.w + slider->pos.w, 0, x + slider->pos.w, y));
|
||||
slider->scrollTo(sliderPos);
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
@@ -570,22 +575,26 @@ void OptionsTab::SelectionWindow::genContentFactions()
|
||||
if(selectedFaction == FactionID::RANDOM)
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), 6, (ICON_SMALL_HEIGHT/2)));
|
||||
|
||||
factions.clear();
|
||||
for(auto & elem : allowedFactions)
|
||||
{
|
||||
int x = i % elementsPerLine;
|
||||
int y = i / elementsPerLine;
|
||||
int y = (i / elementsPerLine) - (slider ? slider->getValue() : 0);
|
||||
|
||||
PlayerSettings set = PlayerSettings();
|
||||
set.castle = elem;
|
||||
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::TOWN);
|
||||
|
||||
factions.push_back(elem);
|
||||
i++;
|
||||
|
||||
if(y < 0 || y > MAX_LINES - 1)
|
||||
continue;
|
||||
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(true), helper.getImageIndex(true), 0, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin(selectedFaction == elem ? "lobby/townBorderBigActivated" : "lobby/townBorderBig"), x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, (selectedFaction == elem) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
factions.push_back(elem);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,33 +611,36 @@ void OptionsTab::SelectionWindow::genContentHeroes()
|
||||
if(selectedHero == HeroTypeID::RANDOM)
|
||||
components.push_back(std::make_shared<CPicture>(ImagePath::builtin("lobby/townBorderSmallActivated"), 6, (ICON_SMALL_HEIGHT/2)));
|
||||
|
||||
heroes.clear();
|
||||
for(auto & elem : allowedHeroes)
|
||||
{
|
||||
const CHero * type = elem.toHeroType();
|
||||
|
||||
if(type->heroClass->faction == selectedFaction)
|
||||
{
|
||||
if(type->heroClass->faction != selectedFaction)
|
||||
continue;
|
||||
|
||||
int x = i % elementsPerLine;
|
||||
int y = i / elementsPerLine;
|
||||
int x = i % elementsPerLine;
|
||||
int y = (i / elementsPerLine) - (slider ? slider->getValue() : 0);
|
||||
|
||||
PlayerSettings set = PlayerSettings();
|
||||
set.hero = elem;
|
||||
PlayerSettings set = PlayerSettings();
|
||||
set.hero = elem;
|
||||
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::HERO);
|
||||
CPlayerSettingsHelper helper = CPlayerSettingsHelper(set, SelType::HERO);
|
||||
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(true), helper.getImageIndex(true), 0, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, (selectedHero == elem) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
ImagePath image = ImagePath::builtin("lobby/townBorderBig");
|
||||
if(selectedHero == elem)
|
||||
image = ImagePath::builtin("lobby/townBorderBigActivated");
|
||||
if(unusableHeroes.count(elem))
|
||||
image = ImagePath::builtin("lobby/townBorderBigGrayedOut");
|
||||
components.push_back(std::make_shared<CPicture>(image, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
heroes.push_back(elem);
|
||||
heroes.push_back(elem);
|
||||
i++;
|
||||
|
||||
i++;
|
||||
}
|
||||
if(y < 0 || y > MAX_LINES - 1)
|
||||
continue;
|
||||
|
||||
components.push_back(std::make_shared<CAnimImage>(helper.getImageName(true), helper.getImageIndex(true), 0, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
drawOutlinedText(x * (ICON_BIG_WIDTH-1) + TEXT_POS_X, y * (ICON_BIG_HEIGHT-1) + TEXT_POS_Y, (selectedHero == elem) ? Colors::YELLOW : Colors::WHITE, helper.getName());
|
||||
ImagePath image = ImagePath::builtin("lobby/townBorderBig");
|
||||
if(selectedHero == elem)
|
||||
image = ImagePath::builtin("lobby/townBorderBigActivated");
|
||||
if(unusableHeroes.count(elem))
|
||||
image = ImagePath::builtin("lobby/townBorderBigGrayedOut");
|
||||
components.push_back(std::make_shared<CPicture>(image, x * (ICON_BIG_WIDTH-1), y * (ICON_BIG_HEIGHT-1)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,7 +671,7 @@ void OptionsTab::SelectionWindow::genContentBonus()
|
||||
int OptionsTab::SelectionWindow::getElement(const Point & cursorPosition)
|
||||
{
|
||||
int x = (cursorPosition.x - pos.x) / (ICON_BIG_WIDTH-1);
|
||||
int y = (cursorPosition.y - pos.y) / (ICON_BIG_HEIGHT-1);
|
||||
int y = (cursorPosition.y - pos.y) / (ICON_BIG_HEIGHT-1) + (slider ? slider->getValue() : 0);
|
||||
|
||||
return x + y * elementsPerLine;
|
||||
}
|
||||
@@ -741,6 +753,14 @@ void OptionsTab::SelectionWindow::setElement(int elem, bool doApply)
|
||||
apply();
|
||||
}
|
||||
|
||||
void OptionsTab::SelectionWindow::sliderMove(int slidPos)
|
||||
{
|
||||
if(!slider)
|
||||
return; // ignore spurious call when slider is being created
|
||||
recreate();
|
||||
redraw();
|
||||
}
|
||||
|
||||
bool OptionsTab::SelectionWindow::receiveEvent(const Point & position, int eventType) const
|
||||
{
|
||||
return true; // capture click also outside of window
|
||||
@@ -748,6 +768,9 @@ bool OptionsTab::SelectionWindow::receiveEvent(const Point & position, int event
|
||||
|
||||
void OptionsTab::SelectionWindow::clickReleased(const Point & cursorPosition)
|
||||
{
|
||||
if(slider && slider->pos.isInside(cursorPosition))
|
||||
return;
|
||||
|
||||
if(!pos.isInside(cursorPosition))
|
||||
{
|
||||
close();
|
||||
@@ -761,7 +784,7 @@ void OptionsTab::SelectionWindow::clickReleased(const Point & cursorPosition)
|
||||
|
||||
void OptionsTab::SelectionWindow::showPopupWindow(const Point & cursorPosition)
|
||||
{
|
||||
if(!pos.isInside(cursorPosition))
|
||||
if(!pos.isInside(cursorPosition) || (slider && slider->pos.isInside(cursorPosition)))
|
||||
return;
|
||||
|
||||
int elem = getElement(cursorPosition);
|
||||
|
@@ -26,6 +26,7 @@ class CAnimImage;
|
||||
class CComponentBox;
|
||||
class CTextBox;
|
||||
class CButton;
|
||||
class CSlider;
|
||||
|
||||
class FilledTexturePlayerColored;
|
||||
|
||||
@@ -105,8 +106,13 @@ private:
|
||||
const int TEXT_POS_X = 29;
|
||||
const int TEXT_POS_Y = 56;
|
||||
|
||||
const int MAX_LINES = 5;
|
||||
const int MAX_ELEM_PER_LINES = 5;
|
||||
|
||||
int elementsPerLine;
|
||||
|
||||
std::shared_ptr<CSlider> slider;
|
||||
|
||||
PlayerColor color;
|
||||
SelType type;
|
||||
|
||||
@@ -134,13 +140,15 @@ private:
|
||||
void genContentBonus();
|
||||
|
||||
void drawOutlinedText(int x, int y, ColorRGBA color, std::string text);
|
||||
int calcLines(FactionID faction);
|
||||
std::tuple<int, int> calcLines(FactionID faction);
|
||||
void apply();
|
||||
void recreate();
|
||||
void recreate(int sliderPos = 0);
|
||||
void setSelection();
|
||||
int getElement(const Point & cursorPosition);
|
||||
void setElement(int element, bool doApply);
|
||||
|
||||
void sliderMove(int slidPos);
|
||||
|
||||
bool receiveEvent(const Point & position, int eventType) const override;
|
||||
void clickReleased(const Point & cursorPosition) override;
|
||||
void showPopupWindow(const Point & cursorPosition) override;
|
||||
@@ -148,7 +156,7 @@ private:
|
||||
public:
|
||||
void reopen();
|
||||
|
||||
SelectionWindow(const PlayerColor & color, SelType _type);
|
||||
SelectionWindow(const PlayerColor & color, SelType _type, int sliderPos = 0);
|
||||
};
|
||||
|
||||
/// Image with current town/hero/bonus
|
||||
|
@@ -669,15 +669,50 @@ CTavernWindow::HeroSelector::HeroSelector(std::map<HeroTypeID, CGHeroInstance*>
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
pos = Rect(0, 0, 16 * 48, (inviteableHeroes.size() / 16 + (inviteableHeroes.size() % 16 != 0)) * 32);
|
||||
pos = Rect(
|
||||
pos.x,
|
||||
pos.y,
|
||||
ELEM_PER_LINES * 48,
|
||||
std::min((int)(inviteableHeroes.size() / ELEM_PER_LINES + (inviteableHeroes.size() % ELEM_PER_LINES != 0)), MAX_LINES) * 32
|
||||
);
|
||||
background = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, pos.w, pos.h));
|
||||
|
||||
if(inviteableHeroes.size() / ELEM_PER_LINES > MAX_LINES)
|
||||
{
|
||||
pos.w += 16;
|
||||
slider = std::make_shared<CSlider>(Point(pos.w - 16, 0), pos.h, std::bind(&CTavernWindow::HeroSelector::sliderMove, this, _1), MAX_LINES, std::ceil((double)inviteableHeroes.size() / ELEM_PER_LINES), 0, Orientation::VERTICAL, CSlider::BROWN);
|
||||
slider->setPanningStep(32);
|
||||
slider->setScrollBounds(Rect(-pos.w + slider->pos.w, 0, pos.w, pos.h));
|
||||
}
|
||||
|
||||
recreate();
|
||||
center();
|
||||
}
|
||||
|
||||
void CTavernWindow::HeroSelector::sliderMove(int slidPos)
|
||||
{
|
||||
if(!slider)
|
||||
return; // ignore spurious call when slider is being created
|
||||
recreate();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CTavernWindow::HeroSelector::recreate()
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
|
||||
int sliderLine = slider ? slider->getValue() : 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int y = -sliderLine;
|
||||
portraits.clear();
|
||||
portraitAreas.clear();
|
||||
for(auto & h : inviteableHeroes)
|
||||
{
|
||||
portraits.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), (*CGI->heroh)[h.first]->imageIndex, 0, x * 48, y * 32));
|
||||
portraitAreas.push_back(std::make_shared<LRClickableArea>(Rect(x * 48, y * 32, 48, 32), [this, h](){ close(); onChoose(inviteableHeroes[h.first]); }, [this, h](){ GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(inviteableHeroes[h.first])); }));
|
||||
if(y >= 0 && y <= MAX_LINES - 1)
|
||||
{
|
||||
portraits.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("PortraitsSmall"), (*CGI->heroh)[h.first]->imageIndex, 0, x * 48, y * 32));
|
||||
portraitAreas.push_back(std::make_shared<LRClickableArea>(Rect(x * 48, y * 32, 48, 32), [this, h](){ close(); onChoose(inviteableHeroes[h.first]); }, [this, h](){ GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(inviteableHeroes[h.first])); }));
|
||||
}
|
||||
|
||||
if(x > 0 && x % 15 == 0)
|
||||
{
|
||||
@@ -687,8 +722,6 @@ CTavernWindow::HeroSelector::HeroSelector(std::map<HeroTypeID, CGHeroInstance*>
|
||||
else
|
||||
x++;
|
||||
}
|
||||
|
||||
center();
|
||||
}
|
||||
|
||||
CShipyardWindow::CShipyardWindow(const TResources & cost, int state, BoatId boatType, const std::function<void()> & onBuy)
|
||||
|
@@ -238,6 +238,10 @@ public:
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<CFilledTexture> background;
|
||||
std::shared_ptr<CSlider> slider;
|
||||
|
||||
const int MAX_LINES = 18;
|
||||
const int ELEM_PER_LINES = 16;
|
||||
|
||||
HeroSelector(std::map<HeroTypeID, CGHeroInstance*> InviteableHeroes, std::function<void(CGHeroInstance*)> OnChoose);
|
||||
|
||||
@@ -247,6 +251,9 @@ public:
|
||||
|
||||
std::vector<std::shared_ptr<CAnimImage>> portraits;
|
||||
std::vector<std::shared_ptr<LRClickableArea>> portraitAreas;
|
||||
|
||||
void recreate();
|
||||
void sliderMove(int slidPos);
|
||||
};
|
||||
|
||||
//recruitable heroes
|
||||
|
Reference in New Issue
Block a user