瀏覽代碼

Merge pull request #5117 from IvanSavenko/teleporter_ui

Added new right-click popup to teleporters
Ivan Savenko 10 月之前
父節點
當前提交
2272707175

二進制
Mods/vcmi/Content/Sprites/portalBidirectional.png


二進制
Mods/vcmi/Content/Sprites/portalEntrance.png


二進制
Mods/vcmi/Content/Sprites/portalExit.png


二進制
Mods/vcmi/Content/Sprites2x/portalBidirectional.png


二進制
Mods/vcmi/Content/Sprites2x/portalEntrance.png


二進制
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)));
 }
 
-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();
 }
 

+ 2 - 2
client/adventureMap/CMinimap.h

@@ -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);

+ 85 - 0
client/windows/InfoWindows.cpp

@@ -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>();
 	}

+ 23 - 0
client/windows/InfoWindows.h

@@ -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);
+};
+

+ 4 - 3
lib/mapObjects/MiscObjects.h

@@ -215,14 +215,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;
@@ -232,6 +230,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);