From cec9161f8f637c54b4dbe5a9b309b08f846aa7c1 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Jul 2014 18:40:13 +0300 Subject: [PATCH] Added missing files --- client/gui/MiscWidgets.cpp | 787 +++++++++++++++++++++++++++++++++++++ client/gui/MiscWidgets.h | 210 ++++++++++ 2 files changed, 997 insertions(+) create mode 100644 client/gui/MiscWidgets.cpp create mode 100644 client/gui/MiscWidgets.h diff --git a/client/gui/MiscWidgets.cpp b/client/gui/MiscWidgets.cpp new file mode 100644 index 000000000..fe75010b2 --- /dev/null +++ b/client/gui/MiscWidgets.cpp @@ -0,0 +1,787 @@ +#include "StdInc.h" +#include "MiscWidgets.h" + +#include "CGuiHandler.h" +#include "CCursorHandler.h" + +#include "../CBitmapHandler.h" +#include "../CPlayerInterface.h" +#include "../CMessage.h" +#include "../CGameInfo.h" +#include "../CAdvmapInterface.h" +#include "../CCastleInterface.h" + +#include "../../CCallback.h" + +#include "../../lib/mapObjects/CGHeroInstance.h" +#include "../../lib/CGeneralTextHandler.h" +#include "../../lib/CModHandler.h" + +/* + * MiscWidgets.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +void CSelWindow::selectionChange(unsigned to) +{ + for (unsigned i=0;i(components[i]); + if (!pom) + continue; + pom->select(i==to); + } + redraw(); +} + +CSelWindow::CSelWindow(const std::string &Text, PlayerColor player, int charperline, const std::vector &comps, const std::vector > > &Buttons, QueryID askID) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + ID = askID; + for(int i=0;i= 0) + buttons.back()->callback += boost::bind(&CSelWindow::madeChoice,this); + buttons[i]->callback += boost::bind(&CInfoWindow::close,this); //each button will close the window apart from call-defined actions + } + + text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); + + buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter + buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape + + if(buttons.size() > 1 && askID.getNum() >= 0) //cancel button functionality + buttons.back()->callback += boost::bind(&CCallback::selectionMade,LOCPLINT->cb.get(),0,askID); + + for(int i=0;irecActions = 255; + addChild(comps[i]); + components.push_back(comps[i]); + comps[i]->onSelect = boost::bind(&CSelWindow::selectionChange,this,i); + if(i<9) + comps[i]->assignedKeys.insert(SDLK_1+i); + } + CMessage::drawIWindow(this, Text, player); +} + +void CSelWindow::madeChoice() +{ + if(ID.getNum() < 0) + return; + int ret = -1; + for (int i=0;i(components[i])->selected) + { + ret = i; + } + } + LOCPLINT->cb->selectionMade(ret+1,ID); +} + +CInfoWindow::CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps, const TButtonsInfo &Buttons, bool delComps) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + + type |= BLOCK_ADV_HOTKEYS; + ID = QueryID(-1); + for(auto & Button : Buttons) + { + CAdventureMapButton *button = new CAdventureMapButton("","",boost::bind(&CInfoWindow::close,this),0,0,Button.first); + button->borderColor = Colors::METALLIC_GOLD; + button->borderEnabled = true; + button->callback.add(Button.second); //each button will close the window apart from call-defined actions + buttons.push_back(button); + } + + text = new CTextBox(Text, Rect(0, 0, 250, 100), 0, FONT_MEDIUM, CENTER, Colors::WHITE); + if(!text->slider) + { + text->resize(text->label->textSize); + } + + if(buttons.size()) + { + buttons.front()->assignedKeys.insert(SDLK_RETURN); //first button - reacts on enter + buttons.back()->assignedKeys.insert(SDLK_ESCAPE); //last button - reacts on escape + } + + for(auto & comp : comps) + { + comp->recActions = 0xff; + addChild(comp); + comp->recActions &= ~(SHOWALL | UPDATE); + components.push_back(comp); + } + setDelComps(delComps); + CMessage::drawIWindow(this,Text,player); +} + +CInfoWindow::CInfoWindow() +{ + ID = QueryID(-1); + setDelComps(false); + text = nullptr; +} + +void CInfoWindow::close() +{ + GH.popIntTotally(this); + if(LOCPLINT) + LOCPLINT->showingDialog->setn(false); +} + +void CInfoWindow::show(SDL_Surface * to) +{ + CIntObject::show(to); +} + +CInfoWindow::~CInfoWindow() +{ + if(!delComps) + { + for (auto & elem : components) + removeChild(elem); + } +} + +void CInfoWindow::showAll(SDL_Surface * to) +{ + CSimpleWindow::show(to); + CIntObject::showAll(to); +} + +void CInfoWindow::showInfoDialog(const std::string &text, const std::vector *components, bool DelComps, PlayerColor player) +{ + CInfoWindow * window = CInfoWindow::create(text, player, components, DelComps); + GH.pushInt(window); +} + +void CInfoWindow::showYesNoDialog(const std::string & text, const std::vector *components, const CFunctionList &onYes, const CFunctionList &onNo, bool DelComps, PlayerColor player) +{ + assert(!LOCPLINT || LOCPLINT->showingDialog->get()); + std::vector > > pom; + pom.push_back(std::pair >("IOKAY.DEF",0)); + pom.push_back(std::pair >("ICANCEL.DEF",0)); + CInfoWindow * temp = new CInfoWindow(text, player, components ? *components : std::vector(), pom, DelComps); + for(auto & elem : onYes.funcs) + temp->buttons[0]->callback += elem; + for(auto & elem : onNo.funcs) + temp->buttons[1]->callback += elem; + + GH.pushInt(temp); +} + +void CInfoWindow::showOkDialog(const std::string & text, const std::vector *components, const boost::function & onOk, bool delComps, PlayerColor player) +{ + std::vector > > pom; + pom.push_back(std::pair >("IOKAY.DEF",0)); + CInfoWindow * temp = new CInfoWindow(text, player, *components, pom, delComps); + temp->buttons[0]->callback += onOk; + + GH.pushInt(temp); +} + +CInfoWindow * CInfoWindow::create(const std::string &text, PlayerColor playerID /*= 1*/, const std::vector *components /*= nullptr*/, bool DelComps) +{ + std::vector > > pom; + pom.push_back(std::pair >("IOKAY.DEF",0)); + CInfoWindow * ret = new CInfoWindow(text, playerID, components ? *components : std::vector(), pom, DelComps); + return ret; +} + +std::string CInfoWindow::genText(std::string title, std::string description) +{ + return std::string("{") + title + "}" + "\n\n" + description; +} + +void CInfoWindow::setDelComps(bool DelComps) +{ + delComps = DelComps; + for(CComponent *comp : components) + { + if(delComps) + comp->recActions |= DISPOSE; + else + comp->recActions &= ~DISPOSE; + } +} + +CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free) + :free(Free),bitmap(Bitmap) +{ + init(x, y); +} + + +CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free/*=false*/) + : free(Free),bitmap(Bitmap) +{ + switch(alignment) + { + case BOTTOMRIGHT: + init(p.x - Bitmap->w, p.y - Bitmap->h); + break; + case CENTER: + init(p.x - Bitmap->w/2, p.y - Bitmap->h/2); + break; + case TOPLEFT: + init(p.x, p.y); + break; + default: + assert(0); //not implemented + } +} + +CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free) +{ + CCS->curh->hide(); + + free=Free; + bitmap=Bitmap; + + if(bitmap) + { + pos.x = screen->w/2 - bitmap->w/2; + pos.y = screen->h/2 - bitmap->h/2; + pos.h = bitmap->h; + pos.w = bitmap->w; + } +} + +void CInfoPopup::close() +{ + if(free) + SDL_FreeSurface(bitmap); + GH.popIntTotally(this); +} + +void CInfoPopup::show(SDL_Surface * to) +{ + blitAt(bitmap,pos.x,pos.y,to); +} + +CInfoPopup::~CInfoPopup() +{ + CCS->curh->show(); +} + +void CInfoPopup::init(int x, int y) +{ + CCS->curh->hide(); + + pos.x = x; + pos.y = y; + pos.h = bitmap->h; + pos.w = bitmap->w; + + // Put the window back on screen if necessary + vstd::amax(pos.x, 0); + vstd::amax(pos.y, 0); + vstd::amin(pos.x, screen->w - bitmap->w); + vstd::amin(pos.y, screen->h - bitmap->h); +} + + +void CRClickPopup::clickRight(tribool down, bool previousState) +{ + if(down) + return; + close(); +} + +void CRClickPopup::close() +{ + GH.popIntTotally(this); +} + +void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps) +{ + PlayerColor player = LOCPLINT ? LOCPLINT->playerID : PlayerColor(1); //if no player, then use blue + + CSimpleWindow * temp = new CInfoWindow(txt, player, comps); + temp->center(Point(GH.current->motion)); //center on mouse + temp->fitToScreen(10); + auto rcpi = new CRClickPopupInt(temp,true); + GH.pushInt(rcpi); +} + +void CRClickPopup::createAndPush(const std::string &txt, CComponent * component) +{ + CInfoWindow::TCompsInfo intComps; + intComps.push_back(component); + + createAndPush(txt, intComps); +} + +void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment /*= BOTTOMRIGHT*/) +{ + CIntObject *iWin = createInfoWin(p, obj); //try get custom infowindow for this obj + if(iWin) + GH.pushInt(iWin); + else + { + if (adventureInt->curHero()) + CRClickPopup::createAndPush(obj->getHoverText(adventureInt->curHero())); + else + CRClickPopup::createAndPush(obj->getHoverText(LOCPLINT->playerID)); + } +} + +CRClickPopup::CRClickPopup() +{ + addUsedEvents(RCLICK); +} + +CRClickPopup::~CRClickPopup() +{ +} + +void CRClickPopupInt::show(SDL_Surface * to) +{ + inner->show(to); +} + +CRClickPopupInt::CRClickPopupInt( IShowActivatable *our, bool deleteInt ) +{ + CCS->curh->hide(); + inner = our; + delInner = deleteInt; +} + +CRClickPopupInt::~CRClickPopupInt() +{ + if(delInner) + delete inner; + + CCS->curh->show(); +} + +void CRClickPopupInt::showAll(SDL_Surface * to) +{ + inner->showAll(to); +} + +Point CInfoBoxPopup::toScreen(Point p) +{ + vstd::abetween(p.x, adventureInt->terrain.pos.x + 100, adventureInt->terrain.pos.x + adventureInt->terrain.pos.w - 100); + vstd::abetween(p.y, adventureInt->terrain.pos.y + 100, adventureInt->terrain.pos.y + adventureInt->terrain.pos.h - 100); + + return p; +} + +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town): + CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position)) +{ + InfoAboutTown iah; + LOCPLINT->cb->getTownInfo(town, iah); + + OBJ_CONSTRUCTION_CAPTURING_ALL; + new CTownTooltip(Point(9, 10), iah); +} + +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero): + CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "HEROQVBK", toScreen(position)) +{ + InfoAboutHero iah; + LOCPLINT->cb->getHeroInfo(hero, iah); + + OBJ_CONSTRUCTION_CAPTURING_ALL; + new CHeroTooltip(Point(9, 10), iah); +} + +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr): + CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "TOWNQVBK", toScreen(position)) +{ + InfoAboutTown iah; + LOCPLINT->cb->getTownInfo(garr, iah); + + OBJ_CONSTRUCTION_CAPTURING_ALL; + new CArmyTooltip(Point(9, 10), iah); +} + +CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero +{ + if(!specific) + specific = adventureInt->selection; + + assert(specific); + + switch(specific->ID) + { + case Obj::HERO: + return new CInfoBoxPopup(position, dynamic_cast(specific)); + case Obj::TOWN: + return new CInfoBoxPopup(position, dynamic_cast(specific)); + case Obj::GARRISON: + case Obj::GARRISON2: + return new CInfoBoxPopup(position, dynamic_cast(specific)); + default: + return nullptr; + } +} + + +void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState) +{ + if((!down) && previousState) + { + std::vector comp(1, createComponent()); + LOCPLINT->showInfoDialog(text, comp); + } +} + +LRClickableAreaWTextComp::LRClickableAreaWTextComp(const Rect &Pos, int BaseType) + : LRClickableAreaWText(Pos), baseType(BaseType), bonusValue(-1) +{ +} + +CComponent * LRClickableAreaWTextComp::createComponent() const +{ + if(baseType >= 0) + return new CComponent(CComponent::Etype(baseType), type, bonusValue); + else + return nullptr; +} + +void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState) +{ + if(down) + { + if(CComponent *comp = createComponent()) + { + CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp)); + return; + } + } + + LRClickableAreaWText::clickRight(down, previousState); //only if with-component variant not occurred +} + +CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero):hero(_hero) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + + addUsedEvents(LCLICK | RCLICK | HOVER); + pos.x += x; pos.w = 58; + pos.y += y; pos.h = 64; + + if (hero) + new CAnimImage("PortraitsLarge", hero->portrait); +} + +void CHeroArea::clickLeft(tribool down, bool previousState) +{ + if((!down) && previousState && hero) + LOCPLINT->openHeroWindow(hero); +} + +void CHeroArea::clickRight(tribool down, bool previousState) +{ + if((!down) && previousState && hero) + LOCPLINT->openHeroWindow(hero); +} + +void CHeroArea::hover(bool on) +{ + if (on && hero) + GH.statusbar->setText(hero->getObjectName()); + else + GH.statusbar->clear(); +} + +void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState) +{ + if((!down) && previousState && town) + { + LOCPLINT->openTownWindow(town); + if ( type == 2 ) + LOCPLINT->castleInt->builds->buildingClicked(BuildingID::VILLAGE_HALL); + else if ( type == 3 && town->fortLevel() ) + LOCPLINT->castleInt->builds->buildingClicked(BuildingID::FORT); + } +} + +void LRClickableAreaOpenTown::clickRight(tribool down, bool previousState) +{ + if((!down) && previousState && town) + LOCPLINT->openTownWindow(town);//TODO: popup? +} + +LRClickableAreaOpenTown::LRClickableAreaOpenTown() + : LRClickableAreaWTextComp(Rect(0,0,0,0), -1) +{ +} + +void CMinorResDataBar::show(SDL_Surface * to) +{ +} + +void CMinorResDataBar::showAll(SDL_Surface * to) +{ + blitAt(bg,pos.x,pos.y,to); + for (Res::ERes i=Res::WOOD; i<=Res::GOLD; vstd::advance(i, 1)) + { + std::string text = boost::lexical_cast(LOCPLINT->cb->getResourceAmount(i)); + + graphics->fonts[FONT_SMALL]->renderTextCenter(to, text, Colors::WHITE, Point(pos.x + 50 + 76 * i, pos.y + pos.h/2)); + } + std::vector temp; + + temp.push_back(boost::lexical_cast(LOCPLINT->cb->getDate(Date::MONTH))); + temp.push_back(boost::lexical_cast(LOCPLINT->cb->getDate(Date::WEEK))); + temp.push_back(boost::lexical_cast(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK))); + + std::string datetext = CGI->generaltexth->allTexts[62]+": %s, " + CGI->generaltexth->allTexts[63] + + ": %s, " + CGI->generaltexth->allTexts[64] + ": %s"; + + graphics->fonts[FONT_SMALL]->renderTextCenter(to, CSDL_Ext::processStr(datetext,temp), Colors::WHITE, Point(pos.x+545+(pos.w-545)/2,pos.y+pos.h/2)); +} + +CMinorResDataBar::CMinorResDataBar() +{ + bg = BitmapHandler::loadBitmap("KRESBAR.bmp"); + CSDL_Ext::setDefaultColorKey(bg); + graphics->blueToPlayersAdv(bg,LOCPLINT->playerID); + pos.x = 7; + pos.y = 575; + pos.w = bg->w; + pos.h = bg->h; +} + +CMinorResDataBar::~CMinorResDataBar() +{ + SDL_FreeSurface(bg); +} + +void CArmyTooltip::init(const InfoAboutArmy &army) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + + new CLabel(66, 2, FONT_SMALL, TOPLEFT, Colors::WHITE, army.name); + + std::vector slotsPos; + slotsPos.push_back(Point(36,73)); + slotsPos.push_back(Point(72,73)); + slotsPos.push_back(Point(108,73)); + slotsPos.push_back(Point(18,122)); + slotsPos.push_back(Point(54,122)); + slotsPos.push_back(Point(90,122)); + slotsPos.push_back(Point(126,122)); + + for(auto & slot : army.army) + { + if(slot.first.getNum() >= GameConstants::ARMY_SIZE) + { + logGlobal->warnStream() << "Warning: " << army.name << " has stack in slot " << slot.first; + continue; + } + + new CAnimImage("CPRSMALL", slot.second.type->iconIndex, 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y); + + std::string subtitle; + if(army.army.isDetailed) + subtitle = boost::lexical_cast(slot.second.count); + else + { + //if =0 - we have no information about stack size at all + if (slot.second.count) + subtitle = CGI->generaltexth->arraytxt[171 + 3*(slot.second.count)]; + } + + new CLabel(slotsPos[slot.first.getNum()].x + 17, slotsPos[slot.first.getNum()].y + 41, FONT_TINY, CENTER, Colors::WHITE, subtitle); + } + +} + +CArmyTooltip::CArmyTooltip(Point pos, const InfoAboutArmy &army): + CIntObject(0, pos) +{ + init(army); +} + +CArmyTooltip::CArmyTooltip(Point pos, const CArmedInstance * army): + CIntObject(0, pos) +{ + init(InfoAboutArmy(army, true)); +} + +void CHeroTooltip::init(const InfoAboutHero &hero) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + new CAnimImage("PortraitsLarge", hero.portrait, 0, 3, 2); + + if(hero.details) + { + for (size_t i = 0; i < hero.details->primskills.size(); i++) + new CLabel(75 + 28 * i, 58, FONT_SMALL, CENTER, Colors::WHITE, + boost::lexical_cast(hero.details->primskills[i])); + + new CLabel(158, 98, FONT_TINY, CENTER, Colors::WHITE, + boost::lexical_cast(hero.details->mana)); + + new CAnimImage("IMRL22", hero.details->morale + 3, 0, 5, 74); + new CAnimImage("ILCK22", hero.details->luck + 3, 0, 5, 91); + } +} + +CHeroTooltip::CHeroTooltip(Point pos, const InfoAboutHero &hero): + CArmyTooltip(pos, hero) +{ + init(hero); +} + +CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero): + CArmyTooltip(pos, InfoAboutHero(hero, true)) +{ + init(InfoAboutHero(hero, true)); +} + +void CTownTooltip::init(const InfoAboutTown &town) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + + //order of icons in def: fort, citadel, castle, no fort + size_t fortIndex = town.fortLevel ? town.fortLevel - 1 : 3; + + new CAnimImage("ITMCLS", fortIndex, 0, 105, 31); + + assert(town.tType); + + size_t iconIndex = town.tType->clientInfo.icons[town.fortLevel > 0][town.built >= CGI->modh->settings.MAX_BUILDING_PER_TURN]; + + new CAnimImage("itpt", iconIndex, 0, 3, 2); + + if(town.details) + { + new CAnimImage("ITMTLS", town.details->hallLevel, 0, 67, 31); + + if (town.details->goldIncome) + new CLabel(157, 58, FONT_TINY, CENTER, Colors::WHITE, + boost::lexical_cast(town.details->goldIncome)); + + if(town.details->garrisonedHero) //garrisoned hero icon + new CPicture("TOWNQKGH", 149, 76); + + if(town.details->customRes)//silo is built + { + if (town.tType->primaryRes == Res::WOOD_AND_ORE )// wood & ore + { + new CAnimImage("SMALRES", Res::WOOD, 0, 7, 75); + new CAnimImage("SMALRES", Res::ORE , 0, 7, 88); + } + else + new CAnimImage("SMALRES", town.tType->primaryRes, 0, 7, 81); + } + } +} + +CTownTooltip::CTownTooltip(Point pos, const InfoAboutTown &town): + CArmyTooltip(pos, town) +{ + init(town); +} + +CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town): + CArmyTooltip(pos, InfoAboutTown(town, true)) +{ + init(InfoAboutTown(town, true)); +} + + +void MoraleLuckBox::set(const IBonusBearer *node) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:} + const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck + const int neutralDescr[] = {60, 86}; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat. + const int componentType[] = {CComponent::luck, CComponent::morale}; + const int hoverTextBase[] = {7, 4}; + const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE}; + int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal}; + + int mrlt = -9; + TModDescr mrl; + + if (node) + { + node->getModifiersWDescr(mrl, bonusType[morale]); + bonusValue = (node->*getValue[morale])(); + } + else + bonusValue = 0; + + mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good + hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt]; + baseType = componentType[morale]; + text = CGI->generaltexth->arraytxt[textId[morale]]; + boost::algorithm::replace_first(text,"%s",CGI->generaltexth->arraytxt[neutralDescr[morale]-mrlt]); + if (!mrl.size()) + text += CGI->generaltexth->arraytxt[noneTxtId]; + else + { + //it's a creature window + if ((morale && node->hasBonusOfType(Bonus::UNDEAD)) || + node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING)) + { + text += CGI->generaltexth->arraytxt[113]; //unaffected by morale + } + else + { + for(auto & elem : mrl) + { + if (elem.first) //no bonuses with value 0 + text += "\n" + elem.second; + } + } + } + + std::string imageName; + if (small) + imageName = morale ? "IMRL30": "ILCK30"; + else + imageName = morale ? "IMRL42" : "ILCK42"; + + delete image; + image = new CAnimImage(imageName, bonusValue + 3); + image->moveBy(Point(pos.w/2 - image->pos.w/2, pos.h/2 - image->pos.h/2));//center icon +} + +MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small): + image(nullptr), + morale(Morale), + small(Small) +{ + bonusValue = 0; + pos = r + pos; +} + +CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool Animated) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + pos.x+=x; + pos.y+=y; + + TFaction faction = cre->faction; + + assert(CGI->townh->factions.size() > faction); + + if(Big) + bg = new CPicture(CGI->townh->factions[faction]->creatureBg130); + else + bg = new CPicture(CGI->townh->factions[faction]->creatureBg120); + bg->needRefresh = true; + anim = new CCreatureAnim(0, 0, cre->animDefName, Rect()); + anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h); + anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON)); + + pos.w = bg->pos.w; + pos.h = bg->pos.h; +} diff --git a/client/gui/MiscWidgets.h b/client/gui/MiscWidgets.h new file mode 100644 index 000000000..75cd3cf24 --- /dev/null +++ b/client/gui/MiscWidgets.h @@ -0,0 +1,210 @@ +#pragma once + +#include "CIntObjectClasses.h" +#include "CComponent.h" + +/* + * MiscWidgets.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +class CCreatureAnim; +class CComponent; +class CGGarrison; +class CSelectableComponent; +class InfoAboutArmy; +class CArmedInstance; +class IBonusBearer; + +/// text + comp. + ok button +class CInfoWindow : public CSimpleWindow +{ //window able to delete its components when closed + bool delComps; //whether comps will be deleted + +public: + typedef std::vector > > TButtonsInfo; + typedef std::vector TCompsInfo; + QueryID ID; //for identification + CTextBox *text; + std::vector buttons; + std::vector components; + CSlider *slider; + + void setDelComps(bool DelComps); + virtual void close(); + + void show(SDL_Surface * to); + void showAll(SDL_Surface * to); + void sliderMoved(int to); + + CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true); //c-tor + CInfoWindow(); //c-tor + ~CInfoWindow(); //d-tor + + //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then) + static void showInfoDialog( const std::string & text, const std::vector *components, bool DelComps = true, PlayerColor player = PlayerColor(1)); + static void showOkDialog(const std::string & text, const std::vector *components, const boost::function & onOk, bool delComps = true, PlayerColor player = PlayerColor(1)); + static void showYesNoDialog( const std::string & text, const std::vector *components, const CFunctionList &onYes, const CFunctionList &onNo, bool DelComps = true, PlayerColor player = PlayerColor(1)); + static CInfoWindow *create(const std::string &text, PlayerColor playerID = PlayerColor(1), const std::vector *components = nullptr, bool DelComps = false); + + /// create text from title and description: {title}\n\n description + static std::string genText(std::string title, std::string description); +}; + +/// popup displayed on R-click +class CRClickPopup : public CIntObject +{ +public: + virtual void close(); + void clickRight(tribool down, bool previousState); + + CRClickPopup(); + virtual ~CRClickPopup(); //d-tor + + static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific); + static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo()); + static void createAndPush(const std::string &txt, CComponent * component); + static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT); +}; + +/// popup displayed on R-click +class CRClickPopupInt : public CRClickPopup +{ +public: + IShowActivatable *inner; + bool delInner; + + void show(SDL_Surface * to); + void showAll(SDL_Surface * to); + CRClickPopupInt(IShowActivatable *our, bool deleteInt); //c-tor + virtual ~CRClickPopupInt(); //d-tor +}; + +class CInfoPopup : public CRClickPopup +{ +public: + bool free; //TODO: comment me + SDL_Surface * bitmap; //popup background + void close(); + void show(SDL_Surface * to); + CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free=false); //c-tor + CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free=false); //c-tor + CInfoPopup(SDL_Surface * Bitmap = nullptr, bool Free = false); //default c-tor + + void init(int x, int y); + ~CInfoPopup(); //d-tor +}; + +/// popup on adventure map for town\hero objects +class CInfoBoxPopup : public CWindowObject +{ + Point toScreen(Point pos); +public: + CInfoBoxPopup(Point position, const CGTownInstance * town); + CInfoBoxPopup(Point position, const CGHeroInstance * hero); + CInfoBoxPopup(Point position, const CGGarrison * garr); +}; + +/// component selection window +class CSelWindow : public CInfoWindow +{ //warning - this window deletes its components by closing! +public: + void selectionChange(unsigned to); + void madeChoice(); //looks for selected component and calls callback + CSelWindow(const std::string& text, PlayerColor player, int charperline ,const std::vector &comps, const std::vector > > &Buttons, QueryID askID); //c-tor + CSelWindow(){}; //c-tor + //notification - this class inherits important destructor from CInfoWindow +}; + +/// base class for hero/town/garrison tooltips +class CArmyTooltip : public CIntObject +{ + void init(const InfoAboutArmy &army); +public: + CArmyTooltip(Point pos, const InfoAboutArmy &army); + CArmyTooltip(Point pos, const CArmedInstance * army); +}; + +/// Class for hero tooltip. Does not have any background! +/// background for infoBox: ADSTATHR +/// background for tooltip: HEROQVBK +class CHeroTooltip : public CArmyTooltip +{ + void init(const InfoAboutHero &hero); +public: + CHeroTooltip(Point pos, const InfoAboutHero &hero); + CHeroTooltip(Point pos, const CGHeroInstance * hero); +}; + +/// Class for town tooltip. Does not have any background! +/// background for infoBox: ADSTATCS +/// background for tooltip: TOWNQVBK +class CTownTooltip : public CArmyTooltip +{ + void init(const InfoAboutTown &town); +public: + CTownTooltip(Point pos, const InfoAboutTown &town); + CTownTooltip(Point pos, const CGTownInstance * town); +}; + +/// draws picture with creature on background, use Animated=true to get animation +class CCreaturePic : public CIntObject +{ +private: + CPicture *bg; + CCreatureAnim *anim; //displayed animation + +public: + CCreaturePic(int x, int y, const CCreature *cre, bool Big=true, bool Animated=true); //c-tor +}; + +/// Resource bar like that at the bottom of the adventure map screen +class CMinorResDataBar : public CIntObject +{ +public: + SDL_Surface *bg; //background bitmap + void show(SDL_Surface * to); + void showAll(SDL_Surface * to); + CMinorResDataBar(); //c-tor + ~CMinorResDataBar(); //d-tor +}; + +class MoraleLuckBox : public LRClickableAreaWTextComp +{ + CAnimImage *image; +public: + bool morale; //true if morale, false if luck + bool small; + + void set(const IBonusBearer *node); + + MoraleLuckBox(bool Morale, const Rect &r, bool Small=false); +}; + +/// Opens hero window by left-clicking on it +class CHeroArea: public CIntObject +{ + const CGHeroInstance * hero; +public: + + CHeroArea(int x, int y, const CGHeroInstance * _hero); + + void clickLeft(tribool down, bool previousState); + void clickRight(tribool down, bool previousState); + void hover(bool on); +}; + +/// Opens town screen by left-clicking on it +class LRClickableAreaOpenTown: public LRClickableAreaWTextComp +{ +public: + const CGTownInstance * town; + void clickLeft(tribool down, bool previousState); + void clickRight(tribool down, bool previousState); + LRClickableAreaOpenTown(); +};