diff --git a/client/gui/TextAlignment.h b/client/gui/TextAlignment.h index 8cb379e70..5c716ba31 100644 --- a/client/gui/TextAlignment.h +++ b/client/gui/TextAlignment.h @@ -9,4 +9,4 @@ */ #pragma once -enum class ETextAlignment {TOPLEFT, CENTER, BOTTOMRIGHT}; +enum class ETextAlignment {TOPLEFT, TOPCENTER, CENTER, BOTTOMRIGHT}; diff --git a/client/render/Canvas.cpp b/client/render/Canvas.cpp index dded81c9e..8a20e3d3d 100644 --- a/client/render/Canvas.cpp +++ b/client/render/Canvas.cpp @@ -149,6 +149,7 @@ void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Col switch (alignment) { case ETextAlignment::TOPLEFT: return graphics->fonts[font]->renderTextLeft (surface, text, colorDest, renderArea.topLeft() + position); + case ETextAlignment::TOPCENTER: return graphics->fonts[font]->renderTextCenter(surface, text, colorDest, renderArea.topLeft() + position); case ETextAlignment::CENTER: return graphics->fonts[font]->renderTextCenter(surface, text, colorDest, renderArea.topLeft() + position); case ETextAlignment::BOTTOMRIGHT: return graphics->fonts[font]->renderTextRight (surface, text, colorDest, renderArea.topLeft() + position); } @@ -159,6 +160,7 @@ void Canvas::drawText(const Point & position, const EFonts & font, const SDL_Col switch (alignment) { case ETextAlignment::TOPLEFT: return graphics->fonts[font]->renderTextLinesLeft (surface, text, colorDest, renderArea.topLeft() + position); + case ETextAlignment::TOPCENTER: return graphics->fonts[font]->renderTextLinesCenter(surface, text, colorDest, renderArea.topLeft() + position); case ETextAlignment::CENTER: return graphics->fonts[font]->renderTextLinesCenter(surface, text, colorDest, renderArea.topLeft() + position); case ETextAlignment::BOTTOMRIGHT: return graphics->fonts[font]->renderTextLinesRight (surface, text, colorDest, renderArea.topLeft() + position); } diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 6a973bb18..0fe9a83b9 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -17,6 +17,7 @@ #include "../CPlayerInterface.h" #include "../CGameInfo.h" +#include "../PlayerLocalState.h" #include "../widgets/TextControls.h" #include "../widgets/CGarrisonInt.h" #include "../windows/CCastleInterface.h" @@ -31,6 +32,7 @@ #include "../../lib/CModHandler.h" #include "../../lib/GameSettings.h" #include "../../lib/TextOperations.h" +#include "../../lib/mapObjects/CGCreature.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGTownInstance.h" @@ -436,6 +438,27 @@ void CInteractableTownTooltip::init(const InfoAboutTown & town) } } +CreatureTooltip::CreatureTooltip(Point pos, const CGCreature * creature) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; + + auto creatureData = (*CGI->creh)[creature->stacks.begin()->second->getCreatureID()].get(); + creatureImage = std::make_shared(graphics->getAnimation("TWCRPORT"), creatureData->getIconIndex()); + creatureImage->center(Point(parent->pos.x + parent->pos.w / 2, parent->pos.y + creatureImage->pos.h / 2 + 11)); + + bool isHeroSelected = LOCPLINT->localState->getCurrentHero() != nullptr; + std::string textContent = isHeroSelected + ? creature->getHoverText(LOCPLINT->localState->getCurrentHero()) + : creature->getHoverText(LOCPLINT->playerID); + + //TODO: window is bigger than OH3 + //TODO: vertical alignment does not match H3. Commented below example that matches H3 for creatures count but supports only 1 line: + /*std::shared_ptr = std::make_shared(parent->pos.w / 2, 103, + FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, creature->getHoverText(LOCPLINT->playerID));*/ + + tooltipTextbox = std::make_shared(textContent, Rect(15, 95, 230, 150), 0, FONT_SMALL, ETextAlignment::TOPCENTER, Colors::WHITE); +} + void MoraleLuckBox::set(const AFactionMember * node) { OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); diff --git a/client/widgets/MiscWidgets.h b/client/widgets/MiscWidgets.h index f2e316cb3..ed45f0ab7 100644 --- a/client/widgets/MiscWidgets.h +++ b/client/widgets/MiscWidgets.h @@ -14,6 +14,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CGGarrison; +class CGCreature; struct InfoAboutArmy; class CArmedInstance; class AFactionMember; @@ -21,6 +22,7 @@ class AFactionMember; VCMI_LIB_NAMESPACE_END class CLabel; +class CTextBox; class CGarrisonInt; class CCreatureAnim; class CComponent; @@ -147,6 +149,15 @@ public: void setAmount(int newAmount); }; +class CreatureTooltip : public CIntObject +{ + std::shared_ptr creatureImage; + std::shared_ptr tooltipTextbox; + +public: + CreatureTooltip(Point pos, const CGCreature * creature); +}; + /// Resource bar like that at the bottom of the adventure map screen class CMinorResDataBar : public CIntObject { diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 62d7ddd5d..e4e61a0c5 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -158,6 +158,12 @@ void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what) where.y += getBorderSize().y; } + if(alignment == ETextAlignment::TOPCENTER) + { + where.x += (int(destRect.w) - int(f->getStringWidth(what) - delimitersCount)) / 2; + where.y += getBorderSize().y; + } + if(alignment == ETextAlignment::CENTER) { where.x += (int(destRect.w) - int(f->getStringWidth(what) - delimitersCount)) / 2; @@ -268,6 +274,7 @@ Rect CMultiLineLabel::getTextLocation() switch(alignment) { case ETextAlignment::TOPLEFT: return Rect(pos.topLeft(), textSize); + case ETextAlignment::TOPCENTER: return Rect(pos.topLeft(), textSize); case ETextAlignment::CENTER: return Rect(pos.topLeft() + textOffset / 2, textSize); case ETextAlignment::BOTTOMRIGHT: return Rect(pos.topLeft() + textOffset, textSize); } @@ -477,6 +484,7 @@ Point CGStatusBar::getBorderSize() switch(alignment) { case ETextAlignment::TOPLEFT: return Point(borderSize.x, borderSize.y); + case ETextAlignment::TOPCENTER: return Point(pos.w / 2, borderSize.y); case ETextAlignment::CENTER: return Point(pos.w / 2, pos.h / 2); case ETextAlignment::BOTTOMRIGHT: return Point(pos.w - borderSize.x, pos.h - borderSize.y); } diff --git a/client/windows/InfoWindows.cpp b/client/windows/InfoWindows.cpp index 4b9a541bb..55d716884 100644 --- a/client/windows/InfoWindows.cpp +++ b/client/windows/InfoWindows.cpp @@ -35,6 +35,7 @@ #include "../../lib/CConfigHandler.h" #include "../../lib/CondSh.h" #include "../../lib/CGeneralTextHandler.h" //for Unicode related stuff +#include "../../lib/mapObjects/CGCreature.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/MiscObjects.h" @@ -243,6 +244,9 @@ CInfoPopup::CInfoPopup(SDL_Surface * Bitmap, const Point &p, ETextAlignment alig case ETextAlignment::TOPLEFT: init(p.x, p.y); break; + case ETextAlignment::TOPCENTER: + init(p.x - Bitmap->w/2, p.y); + break; default: assert(0); //not implemented } @@ -333,7 +337,7 @@ void CRClickPopup::createAndPush(const std::string & txt, std::shared_ptr(Point(9, 10), iah); } -std::shared_ptr CRClickPopup::createInfoWin(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero +CInfoBoxPopup::CInfoBoxPopup(Point position, const CGCreature * creature) + : CWindowObject(RCLICK_POPUP | BORDERED, "DIBOXBCK", toScreen(position)) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + tooltip = std::make_shared(Point(9, 10), creature); +} + +std::shared_ptr CRClickPopup::createCustomInfoWindow(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero { if(nullptr == specific) specific = LOCPLINT->localState->getCurrentArmy(); if(nullptr == specific) { - logGlobal->error("createInfoWin: no object to describe"); + logGlobal->error("createCustomInfoWindow: no object to describe"); return nullptr; } @@ -418,6 +429,8 @@ std::shared_ptr CRClickPopup::createInfoWin(Point position, const CG return std::make_shared(position, dynamic_cast(specific)); case Obj::TOWN: return std::make_shared(position, dynamic_cast(specific)); + case Obj::MONSTER: + return std::make_shared(position, dynamic_cast(specific)); case Obj::GARRISON: case Obj::GARRISON2: return std::make_shared(position, dynamic_cast(specific)); diff --git a/client/windows/InfoWindows.h b/client/windows/InfoWindows.h index caf9bfa03..ec84a6693 100644 --- a/client/windows/InfoWindows.h +++ b/client/windows/InfoWindows.h @@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CGGarrison; +class CGCreature; class Rect; VCMI_LIB_NAMESPACE_END @@ -78,7 +79,7 @@ public: virtual void close(); bool isPopupWindow() const override; - static std::shared_ptr createInfoWin(Point position, const CGObjectInstance * specific); + static std::shared_ptr createCustomInfoWindow(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, std::shared_ptr component); static void createAndPush(const CGObjectInstance * obj, const Point & p, ETextAlignment alignment = ETextAlignment::BOTTOMRIGHT); @@ -108,15 +109,16 @@ public: ~CInfoPopup(); }; -/// popup on adventure map for town\hero objects +/// popup on adventure map for town\hero and other objects with customized popup content class CInfoBoxPopup : public CWindowObject { - std::shared_ptr tooltip; + std::shared_ptr tooltip; Point toScreen(Point pos); public: CInfoBoxPopup(Point position, const CGTownInstance * town); CInfoBoxPopup(Point position, const CGHeroInstance * hero); CInfoBoxPopup(Point position, const CGGarrison * garr); + CInfoBoxPopup(Point position, const CGCreature * creature); }; /// component selection window diff --git a/lib/mapObjects/CGCreature.cpp b/lib/mapObjects/CGCreature.cpp index 27dfa1f58..a5ecd1b60 100644 --- a/lib/mapObjects/CGCreature.cpp +++ b/lib/mapObjects/CGCreature.cpp @@ -53,7 +53,7 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const ms.appendRawString(" "); ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID); - ms.appendRawString("\n"); + ms.appendRawString("\n\n"); int decision = takenAction(hero, true);