1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

Added new right-click popup to teleporters

Whirlpool, Subterranean Gates, and all Monoliths now show custom popup
on right-click that show all linked objects (exits and entrances).

Only revealed objects are visible, rest are hidden behind fow.

Exits, entrances, and bidirectional objects have different icon that
indicates direction.
This commit is contained in:
Ivan Savenko
2024-12-20 15:43:24 +00:00
parent 0a30e86f10
commit 6d8e447ff3
11 changed files with 121 additions and 10 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

View File

@@ -71,16 +71,18 @@ void CMinimapInstance::redrawMinimap()
minimap->drawPoint(Point(x, y), getTileColor(int3(x, y, level)));
}
CMinimapInstance::CMinimapInstance(CMinimap *Parent, int Level):
parent(Parent),
CMinimapInstance::CMinimapInstance(const Point & position, const Point & dimensions, int Level):
minimap(new Canvas(Point(LOCPLINT->cb->getMapSize().x, LOCPLINT->cb->getMapSize().y), CanvasScalingPolicy::IGNORE)),
level(Level)
{
pos.w = parent->pos.w;
pos.h = parent->pos.h;
pos += position;
pos.w = dimensions.x;
pos.h = dimensions.y;
redrawMinimap();
}
CMinimapInstance::~CMinimapInstance() = default;
void CMinimapInstance::showAll(Canvas & to)
{
to.drawScaled(*minimap, pos.topLeft(), pos.dimensions());
@@ -203,7 +205,7 @@ void CMinimap::update()
return;
OBJECT_CONSTRUCTION;
minimap = std::make_shared<CMinimapInstance>(this, level);
minimap = std::make_shared<CMinimapInstance>(Point(0,0), pos.dimensions(), level);
redraw();
}

View File

@@ -20,7 +20,6 @@ class CMinimap;
class CMinimapInstance : public CIntObject
{
CMinimap * parent;
std::unique_ptr<Canvas> minimap;
int level;
@@ -29,7 +28,8 @@ class CMinimapInstance : public CIntObject
void redrawMinimap();
public:
CMinimapInstance(CMinimap * parent, int level);
CMinimapInstance(const Point & position, const Point & dimensions, int level);
~CMinimapInstance();
void showAll(Canvas & to) override;
void refreshTile(const int3 & pos);

View File

@@ -15,12 +15,14 @@
#include "../PlayerLocalState.h"
#include "../adventureMap/AdventureMapInterface.h"
#include "../adventureMap/CMinimap.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../gui/Shortcut.h"
#include "../gui/WindowHandler.h"
#include "../widgets/Buttons.h"
#include "../widgets/CComponent.h"
#include "../widgets/GraphicalPrimitiveCanvas.h"
#include "../widgets/Images.h"
#include "../widgets/MiscWidgets.h"
#include "../widgets/TextControls.h"
@@ -331,6 +333,83 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGCreature * creature)
fitToScreen(10);
}
TeleporterPopup::TeleporterPopup(const Point & position, const CGTeleport * teleporter)
: CWindowObject(BORDERED | RCLICK_POPUP)
{
OBJECT_CONSTRUCTION;
pos.w = 322;
pos.h = 200;
Rect areaSurface(11, 41, 144, 144);
Rect areaUnderground(167, 41, 144, 144);
Rect borderSurface(10, 40, 147, 147);
Rect borderUnderground(166, 40, 147, 147);
bool singleLevelMap = LOCPLINT->cb->getMapSize().y == 0;
if (singleLevelMap)
{
areaSurface.x += 144;
borderSurface.x += 144;
}
filledBackground = std::make_shared<FilledTexturePlayerColored>(Rect(0, 0, pos.w, pos.h));
backgroundSurface = std::make_shared<TransparentFilledRectangle>(borderSurface, Colors::TRANSPARENCY, Colors::YELLOW);
surface = std::make_shared<CMinimapInstance>(areaSurface.topLeft(), areaSurface.dimensions(), 0);
if (!singleLevelMap)
{
backgroundUnderground = std::make_shared<TransparentFilledRectangle>(borderUnderground, Colors::TRANSPARENCY, Colors::YELLOW);
undergroud = std::make_shared<CMinimapInstance>(areaUnderground.topLeft(), areaUnderground.dimensions(), 1);
}
labelTitle = std::make_shared<CLabel>(pos.w / 2, 20, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, teleporter->getPopupText(LOCPLINT->playerID));
const auto & entrances = teleporter->getAllEntrances();
const auto & exits = teleporter->getAllExits();
std::set<ObjectInstanceID> allTeleporters;
allTeleporters.insert(entrances.begin(), entrances.end());
allTeleporters.insert(exits.begin(), exits.end());
for (const auto exit : allTeleporters)
{
const auto * exitObject = LOCPLINT->cb->getObj(exit, false);
if (!exitObject)
continue;
int3 position = exitObject->visitablePos();
int positionX = 144 * position.x / LOCPLINT->cb->getMapSize().x;
int positionY = 144 * position.y / LOCPLINT->cb->getMapSize().y;
Point iconPosition(positionX, positionY);
iconPosition -= Point(8,8); // compensate for 16x16 icon half-size
if (position.z == 0)
iconPosition += areaSurface.topLeft();
else
iconPosition += areaUnderground.topLeft();
ImagePath image;
if (!vstd::contains(entrances, exit))
image = ImagePath::builtin("portalExit");
else if (!vstd::contains(exits, exit))
image = ImagePath::builtin("portalEntrance");
else
image = ImagePath::builtin("portalBidirectional");
iconsOverlay.push_back(std::make_shared<CPicture>(image, iconPosition));
}
center(position);
}
std::shared_ptr<WindowBase>
CRClickPopup::createCustomInfoWindow(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
{
@@ -354,6 +433,12 @@ CRClickPopup::createCustomInfoWindow(Point position, const CGObjectInstance * sp
case Obj::GARRISON:
case Obj::GARRISON2:
return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGGarrison *>(specific));
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
case Obj::MONOLITH_ONE_WAY_EXIT:
case Obj::MONOLITH_TWO_WAY:
case Obj::SUBTERRANEAN_GATE:
case Obj::WHIRLPOOL:
return std::make_shared<TeleporterPopup>(position, dynamic_cast<const CGTeleport *>(specific));
default:
return std::shared_ptr<WindowBase>();
}

View File

@@ -20,6 +20,7 @@ class CGTownInstance;
class CGHeroInstance;
class CGGarrison;
class CGCreature;
class CGTeleport;
VCMI_LIB_NAMESPACE_END
@@ -29,6 +30,10 @@ class CSelectableComponent;
class CTextBox;
class CButton;
class CFilledTexture;
class FilledTexturePlayerColored;
class TransparentFilledRectangle;
class CMinimapInstance;
class CLabel;
/// text + comp. + ok button
class CInfoWindow : public WindowBase
@@ -110,3 +115,21 @@ public:
void madeChoiceAndClose();
CSelWindow(const std::string & text, PlayerColor player, int charperline, const std::vector<std::shared_ptr<CSelectableComponent>> & comps, const std::vector<std::pair<AnimationPath,CFunctionList<void()> > > &Buttons, QueryID askID);
};
class TeleporterPopup : public CWindowObject
{
std::shared_ptr<FilledTexturePlayerColored> filledBackground;
std::shared_ptr<TransparentFilledRectangle> backgroundSurface;
std::shared_ptr<TransparentFilledRectangle> backgroundUnderground;
std::shared_ptr<CMinimapInstance> surface;
std::shared_ptr<CMinimapInstance> undergroud;
std::shared_ptr<CLabel> labelTitle;
std::vector<std::shared_ptr<CPicture>> iconsOverlay;
public:
TeleporterPopup(const Point & position, const CGTeleport * teleporter);
};

View File

@@ -214,14 +214,12 @@ class DLL_LINKAGE CGTeleport : public CGObjectInstance
bool isChannelEntrance(const ObjectInstanceID & id) const;
bool isChannelExit(const ObjectInstanceID & id) const;
std::vector<ObjectInstanceID> getAllEntrances(bool excludeCurrent = false) const;
protected:
enum EType {UNKNOWN, ENTRANCE, EXIT, BOTH};
EType type = EType::UNKNOWN;
ObjectInstanceID getRandomExit(const CGHeroInstance * h) const;
std::vector<ObjectInstanceID> getAllExits(bool excludeCurrent = false) const;
public:
using CGObjectInstance::CGObjectInstance;
@@ -231,6 +229,9 @@ public:
bool isEntrance() const;
bool isExit() const;
std::vector<ObjectInstanceID> getAllEntrances(bool excludeCurrent = false) const;
std::vector<ObjectInstanceID> getAllExits(bool excludeCurrent = false) const;
virtual void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const = 0;
static bool isTeleport(const CGObjectInstance * dst);