Selaa lähdekoodia

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.
Ivan Savenko 11 kuukautta sitten
vanhempi
sitoutus
6d8e447ff3

BIN
Mods/vcmi/Content/Sprites/portalBidirectional.png


BIN
Mods/vcmi/Content/Sprites/portalEntrance.png


BIN
Mods/vcmi/Content/Sprites/portalExit.png


BIN
Mods/vcmi/Content/Sprites2x/portalBidirectional.png


BIN
Mods/vcmi/Content/Sprites2x/portalEntrance.png


BIN
Mods/vcmi/Content/Sprites2x/portalExit.png


+ 7 - 5
client/adventureMap/CMinimap.cpp

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

+ 2 - 2
client/adventureMap/CMinimap.h

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

+ 85 - 0
client/windows/InfoWindows.cpp

@@ -15,12 +15,14 @@
 #include "../PlayerLocalState.h"
 #include "../PlayerLocalState.h"
 
 
 #include "../adventureMap/AdventureMapInterface.h"
 #include "../adventureMap/AdventureMapInterface.h"
+#include "../adventureMap/CMinimap.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CGuiHandler.h"
 #include "../gui/CursorHandler.h"
 #include "../gui/CursorHandler.h"
 #include "../gui/Shortcut.h"
 #include "../gui/Shortcut.h"
 #include "../gui/WindowHandler.h"
 #include "../gui/WindowHandler.h"
 #include "../widgets/Buttons.h"
 #include "../widgets/Buttons.h"
 #include "../widgets/CComponent.h"
 #include "../widgets/CComponent.h"
+#include "../widgets/GraphicalPrimitiveCanvas.h"
 #include "../widgets/Images.h"
 #include "../widgets/Images.h"
 #include "../widgets/MiscWidgets.h"
 #include "../widgets/MiscWidgets.h"
 #include "../widgets/TextControls.h"
 #include "../widgets/TextControls.h"
@@ -331,6 +333,83 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGCreature * creature)
 	fitToScreen(10);
 	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>
 std::shared_ptr<WindowBase>
 CRClickPopup::createCustomInfoWindow(Point position, const CGObjectInstance * specific) //specific=0 => draws info about selected town/hero
 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::GARRISON:
 		case Obj::GARRISON2:
 		case Obj::GARRISON2:
 			return std::make_shared<CInfoBoxPopup>(position, dynamic_cast<const CGGarrison *>(specific));
 			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:
 		default:
 			return std::shared_ptr<WindowBase>();
 			return std::shared_ptr<WindowBase>();
 	}
 	}

+ 23 - 0
client/windows/InfoWindows.h

@@ -20,6 +20,7 @@ class CGTownInstance;
 class CGHeroInstance;
 class CGHeroInstance;
 class CGGarrison;
 class CGGarrison;
 class CGCreature;
 class CGCreature;
+class CGTeleport;
 
 
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END
 
 
@@ -29,6 +30,10 @@ class CSelectableComponent;
 class CTextBox;
 class CTextBox;
 class CButton;
 class CButton;
 class CFilledTexture;
 class CFilledTexture;
+class FilledTexturePlayerColored;
+class TransparentFilledRectangle;
+class CMinimapInstance;
+class CLabel;
 
 
 /// text + comp. + ok button
 /// text + comp. + ok button
 class CInfoWindow : public WindowBase
 class CInfoWindow : public WindowBase
@@ -110,3 +115,21 @@ public:
 	void madeChoiceAndClose();
 	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);
 	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);
+};
+

+ 4 - 3
lib/mapObjects/MiscObjects.h

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