Browse Source

Basic version of zoomable adventure map

Ivan Savenko 2 years ago
parent
commit
3e9da333cf

+ 5 - 0
client/adventureMap/AdventureMapInterface.cpp

@@ -798,6 +798,11 @@ void AdventureMapInterface::hotkeySwitchMapLevel()
 	widget->getMapView()->onMapLevelSwitched();
 }
 
+void AdventureMapInterface::hotkeyZoom(int delta)
+{
+	widget->getMapView()->onMapZoomLevelChanged( 1.0 + delta / 10.0);
+}
+
 void AdventureMapInterface::onScreenResize()
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;

+ 1 - 0
client/adventureMap/AdventureMapInterface.h

@@ -109,6 +109,7 @@ public:
 	void hotkeyEndingTurn();
 	void hotkeyNextTown();
 	void hotkeySwitchMapLevel();
+	void hotkeyZoom(int delta);
 
 	/// Called by PlayerInterface when specified player is ready to start his turn
 	void onHotseatWaitStarted(PlayerColor playerID);

+ 7 - 0
client/adventureMap/AdventureMapShortcuts.cpp

@@ -80,6 +80,8 @@ std::vector<AdventureMapShortcutState> AdventureMapShortcuts::getShortcuts()
 		{ EShortcut::ADVENTURE_VISIT_OBJECT,     optionHeroSelected(),   [this]() { this->visitObject(); } },
 		{ EShortcut::ADVENTURE_VIEW_SELECTED,    optionInMapView(),      [this]() { this->openObject(); } },
 		{ EShortcut::GAME_OPEN_MARKETPLACE,      optionInMapView(),      [this]() { this->showMarketplace(); } },
+		{ EShortcut::ADVENTURE_ZOOM_IN,          optionSidePanelActive(),[this]() { this->zoom(+1); } },
+		{ EShortcut::ADVENTURE_ZOOM_OUT,         optionSidePanelActive(),[this]() { this->zoom(-1); } },
 		{ EShortcut::ADVENTURE_NEXT_TOWN,        optionInMapView(),      [this]() { this->nextTown(); } },
 		{ EShortcut::ADVENTURE_NEXT_OBJECT,      optionInMapView(),      [this]() { this->nextObject(); } },
 		{ EShortcut::ADVENTURE_MOVE_HERO_SW,     optionHeroSelected(),   [this]() { this->moveHeroDirectional({-1, +1}); } },
@@ -336,6 +338,11 @@ void AdventureMapShortcuts::nextTown()
 	owner.hotkeyNextTown();
 }
 
+void AdventureMapShortcuts::zoom( int distance)
+{
+	owner.hotkeyZoom(distance);
+}
+
 void AdventureMapShortcuts::nextObject()
 {
 	const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero();

+ 1 - 0
client/adventureMap/AdventureMapShortcuts.h

@@ -61,6 +61,7 @@ class AdventureMapShortcuts
 	void showMarketplace();
 	void nextTown();
 	void nextObject();
+	void zoom( int distance);
 	void moveHeroDirectional(const Point & direction);
 
 public:

+ 2 - 0
client/gui/Shortcut.h

@@ -105,6 +105,8 @@ enum class EShortcut
 	ADVENTURE_CAST_SPELL,
 	ADVENTURE_THIEVES_GUILD,
 	ADVENTURE_EXIT_WORLD_VIEW,
+	ADVENTURE_ZOOM_IN,
+	ADVENTURE_ZOOM_OUT,
 
 	// Move hero one tile in specified direction. Bound to cursors & numpad buttons
 	ADVENTURE_MOVE_HERO_SW,

+ 4 - 0
client/gui/ShortcutHandler.cpp

@@ -116,6 +116,8 @@ std::vector<EShortcut> ShortcutHandler::translateKeycode(SDL_Keycode key) const
 		{SDLK_q,         EShortcut::ADVENTURE_QUEST_LOG       },
 		{SDLK_c,         EShortcut::ADVENTURE_CAST_SPELL      },
 		{SDLK_g,         EShortcut::ADVENTURE_THIEVES_GUILD   },
+		{SDLK_KP_PLUS,   EShortcut::ADVENTURE_ZOOM_IN         },
+		{SDLK_KP_MINUS,  EShortcut::ADVENTURE_ZOOM_OUT        },
 		{SDLK_q,         EShortcut::BATTLE_TOGGLE_QUEUE       },
 		{SDLK_c,         EShortcut::BATTLE_USE_CREATURE_SPELL },
 		{SDLK_s,         EShortcut::BATTLE_SURRENDER          },
@@ -253,6 +255,8 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const
 		{"adventureCastSpell",       EShortcut::ADVENTURE_CAST_SPELL      },
 		{"adventureThievesGuild",    EShortcut::ADVENTURE_THIEVES_GUILD   },
 		{"adventureExitWorldView",   EShortcut::ADVENTURE_EXIT_WORLD_VIEW },
+		{"adventureZoomIn",          EShortcut::ADVENTURE_ZOOM_IN         },
+		{"adventureZoomOut",         EShortcut::ADVENTURE_ZOOM_OUT        },
 		{"battleToggleQueue",        EShortcut::BATTLE_TOGGLE_QUEUE       },
 		{"battleUseCreatureSpell",   EShortcut::BATTLE_USE_CREATURE_SPELL },
 		{"battleSurrender",          EShortcut::BATTLE_SURRENDER          },

+ 5 - 0
client/mapView/MapView.cpp

@@ -154,6 +154,11 @@ void MapView::onViewWorldActivated(uint32_t tileSize)
 	controller->setTileSize(Point(tileSize, tileSize));
 }
 
+void MapView::onMapZoomLevelChanged(double zoomFactor)
+{
+	controller->modifyTileSize(zoomFactor);
+}
+
 void MapView::onViewMapActivated()
 {
 	controller->activateAdventureContext();

+ 3 - 0
client/mapView/MapView.h

@@ -79,6 +79,9 @@ public:
 	/// Switches view to downscaled View World
 	void onViewWorldActivated(uint32_t tileSize);
 
+	/// Changes zoom level / tile size of current view by specified factor
+	void onMapZoomLevelChanged(double zoomFactor);
+
 	/// Switches view from View World mode back to standard view
 	void onViewMapActivated();
 };

+ 21 - 0
client/mapView/MapViewController.cpp

@@ -75,6 +75,27 @@ void MapViewController::setTileSize(const Point & tileSize)
 	setViewCenter(model->getMapViewCenter(), model->getLevel());
 }
 
+void MapViewController::modifyTileSize(double zoomFactor)
+{
+	Point currentZoom = model->getSingleTileSize();
+	Point desiredZoom = currentZoom * zoomFactor;
+
+	if (desiredZoom == currentZoom && zoomFactor < 1.0)
+		desiredZoom -= Point(1,1);
+
+	if (desiredZoom == currentZoom && zoomFactor > 1.0)
+		desiredZoom += Point(1,1);
+
+	Point minimal = model->getSingleTileSizeLowerLimit();
+	Point maximal = model->getSingleTileSizeUpperLimit();
+	Point actualZoom = {
+		std::clamp(desiredZoom.x, minimal.x, maximal.x),
+		std::clamp(desiredZoom.y, minimal.y, maximal.y)
+	};
+
+	setTileSize(actualZoom);
+}
+
 MapViewController::MapViewController(std::shared_ptr<MapViewModel> model, std::shared_ptr<MapViewCache> view)
 	: state(new MapRendererContextState())
 	, model(std::move(model))

+ 1 - 0
client/mapView/MapViewController.h

@@ -83,6 +83,7 @@ public:
 	void setViewCenter(const int3 & position);
 	void setViewCenter(const Point & position, int level);
 	void setTileSize(const Point & tileSize);
+	void modifyTileSize(double zoomFactor);
 	void tick(uint32_t timePassed);
 	void afterRender();
 

+ 11 - 1
client/mapView/MapViewModel.cpp

@@ -33,6 +33,16 @@ void MapViewModel::setLevel(int newLevel)
 	mapLevel = newLevel;
 }
 
+Point MapViewModel::getSingleTileSizeUpperLimit() const
+{
+	return Point(128, 128); // arbitrary-seleted upscaling limit
+}
+
+Point MapViewModel::getSingleTileSizeLowerLimit() const
+{
+	return Point(4, 4); // arbitrary-seleted upscaling limit
+}
+
 Point MapViewModel::getSingleTileSize() const
 {
 	return tileSize;
@@ -90,7 +100,7 @@ int3 MapViewModel::getTileAtPoint(const Point & position) const
 
 Point MapViewModel::getCacheDimensionsPixels() const
 {
-	return getTilesVisibleDimensions() * getSingleTileSize();
+	return getTilesVisibleDimensions() * getSingleTileSizeUpperLimit();
 }
 
 Rect MapViewModel::getCacheTileArea(const int3 & coordinates) const

+ 6 - 0
client/mapView/MapViewModel.h

@@ -25,6 +25,12 @@ public:
 	void setViewDimensions(const Point & newValue);
 	void setLevel(int newLevel);
 
+	/// returns maximal possible size for a single tile
+	Point getSingleTileSizeUpperLimit() const;
+
+	/// returns minimal possible size for a single tile
+	Point getSingleTileSizeLowerLimit() const;
+
 	/// returns current size of map tile in pixels
 	Point getSingleTileSize() const;