1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

Completely removed old TerrainRect class

This commit is contained in:
Ivan Savenko 2023-02-23 19:46:41 +02:00
parent fbb8c18c23
commit 45e2875342
25 changed files with 555 additions and 516 deletions

View File

@ -10,7 +10,6 @@ set(client_SRCS
adventureMap/CList.cpp
adventureMap/CMinimap.cpp
adventureMap/CResDataBar.cpp
adventureMap/CTerrainRect.cpp
battle/BattleActionsController.cpp
battle/BattleAnimationClasses.cpp
@ -50,6 +49,7 @@ set(client_SRCS
mapRenderer/MapRenderer.cpp
mapRenderer/MapRendererContext.cpp
mapRenderer/MapView.cpp
mapRenderer/MapViewActions.cpp
mapRenderer/MapViewCache.cpp
mapRenderer/MapViewController.cpp
mapRenderer/MapViewModel.cpp
@ -127,7 +127,6 @@ set(client_HEADERS
adventureMap/CList.h
adventureMap/CMinimap.h
adventureMap/CResDataBar.h
adventureMap/CTerrainRect.h
battle/BattleActionsController.h
battle/BattleAnimationClasses.h
@ -172,7 +171,7 @@ set(client_HEADERS
mapRenderer/MapRenderer.h
mapRenderer/MapRendererContext.h
mapRenderer/MapView.h
mapRenderer/MapViewCache.cpp
mapRenderer/MapViewActions.h
mapRenderer/MapViewCache.h
mapRenderer/MapViewController.h
mapRenderer/MapViewModel.h

View File

@ -14,7 +14,6 @@
#include "adventureMap/CAdvMapInt.h"
#include "mapRenderer/mapHandler.h"
#include "adventureMap/CList.h"
#include "adventureMap/CTerrainRect.h"
#include "adventureMap/CInfoBar.h"
#include "adventureMap/CMinimap.h"
#include "battle/BattleInterface.h"
@ -382,13 +381,11 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
return;
}
adventureInt->minimap->redraw();
adventureInt->heroList->redraw();
CGI->mh->waitForOngoingAnimations();
//move finished
adventureInt->minimap->redraw();
adventureInt->heroList->update(hero);
//check if user cancelled movement
@ -1480,7 +1477,7 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog();
CCS->curh->hide();
adventureInt->centerOn (pos);
adventureInt->centerOnTile(pos);
if (focusTime)
{
GH.totalRedraw();

View File

@ -15,11 +15,13 @@
#include "CInGameConsole.h"
#include "CMinimap.h"
#include "CResDataBar.h"
#include "CTerrainRect.h"
#include "CList.h"
#include "CInfoBar.h"
#include "../mapRenderer/mapHandler.h"
#include "../mapRenderer/MapView.h"
#include "../mapRenderer/MapViewModel.h"
#include "../mapRenderer/MapViewController.h"
#include "../windows/CKingdomInterface.h"
#include "../windows/CSpellWindow.h"
#include "../windows/CTradeWindow.h"
@ -87,7 +89,7 @@ CAdvMapInt::CAdvMapInt():
townList(new CTownList(ADVOPT.tlistSize, Point(ADVOPT.tlistX, ADVOPT.tlistY), ADVOPT.tlistAU, ADVOPT.tlistAD)),
infoBar(new CInfoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192))),
resdatabar(new CResDataBar),
terrain(new CTerrainRect),
terrain(new MapView(Point(ADVOPT.advmapX, ADVOPT.advmapY), Point(ADVOPT.advmapW, ADVOPT.advmapH))),
state(NA),
spellBeingCasted(nullptr),
selection(nullptr),
@ -258,7 +260,7 @@ void CAdvMapInt::fworldViewBack()
auto hero = curHero();
if (hero)
centerOn(hero);
centerOnObject(hero);
}
void CAdvMapInt::fworldViewScale1x()
@ -284,15 +286,18 @@ void CAdvMapInt::fswitchLevel()
if (maxLevels < 2)
return;
terrain->setLevel((terrain->getLevel() + 1) % maxLevels);
terrain->onMapLevelSwitched();
}
underground->setIndex(terrain->getLevel(), true);
void CAdvMapInt::onMapViewMoved(const Rect & visibleArea, int mapLevel)
{
underground->setIndex(mapLevel, true);
underground->redraw();
worldViewUnderground->setIndex(terrain->getLevel(), true);
worldViewUnderground->setIndex(mapLevel, true);
worldViewUnderground->redraw();
minimap->setLevel(terrain->getLevel());
minimap->onMapViewMoved(visibleArea, mapLevel);
}
void CAdvMapInt::fshowQuestlog()
@ -332,7 +337,7 @@ void CAdvMapInt::fshowSpellbok()
if (!curHero()) //checking necessary values
return;
centerOn(selection);
centerOnObject(selection);
GH.pushIntT<CSpellWindow>(curHero(), LOCPLINT, false);
}
@ -570,6 +575,7 @@ void CAdvMapInt::show(SDL_Surface * to)
gems[i]->setFrame(LOCPLINT->playerID.getNum());
}
minimap->show(to);
terrain->show(to);
for(int i = 0; i < 4; i++)
@ -589,16 +595,16 @@ void CAdvMapInt::handleMapScrollingUpdate()
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
if(scrollingDir & LEFT)
terrain->moveViewBy(Point(-scrollDistance, 0));
terrain->onMapScrolled(Point(-scrollDistance, 0));
if(scrollingDir & RIGHT)
terrain->moveViewBy(Point(+scrollDistance, 0));
terrain->onMapScrolled(Point(+scrollDistance, 0));
if(scrollingDir & UP)
terrain->moveViewBy(Point(0, -scrollDistance));
terrain->onMapScrolled(Point(0, -scrollDistance));
if(scrollingDir & DOWN)
terrain->moveViewBy(Point(0, +scrollDistance));
terrain->onMapScrolled(Point(0, +scrollDistance));
if(scrollingDir)
{
@ -619,21 +625,14 @@ void CAdvMapInt::selectionChanged()
select(to);
}
void CAdvMapInt::centerOn(int3 on)
void CAdvMapInt::centerOnTile(int3 on)
{
terrain->setViewCenter(on);
underground->setIndex(on.z,true); //change underground switch button image
underground->redraw();
worldViewUnderground->setIndex(on.z, true);
worldViewUnderground->redraw();
minimap->setLevel(terrain->getLevel());
minimap->redraw();
terrain->onCenteredTile(on);
}
void CAdvMapInt::centerOn(const CGObjectInstance * obj)
void CAdvMapInt::centerOnObject(const CGObjectInstance * obj)
{
centerOn(obj->getSightCenter());
terrain->onCenteredObject(obj);
}
void CAdvMapInt::keyReleased(const SDL_Keycode &key)
@ -812,7 +811,7 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
if(*direction == Point(0,0))
{
centerOn(h);
centerOnObject(h);
return;
}
@ -871,7 +870,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
CCS->musich->playMusicFromSet("terrain", tile->terType->getJsonKey(), true, false);
}
if(centerView)
centerOn(sel);
centerOnObject(sel);
if(sel->ID==Obj::TOWN)
{
@ -1046,7 +1045,7 @@ const CGObjectInstance* CAdvMapInt::getActiveObject(const int3 &mapPos)
return bobjs.front();*/
}
void CAdvMapInt::tileLClicked(const int3 &mapPos)
void CAdvMapInt::onTileLeftClicked(const int3 &mapPos)
{
if(mode != EAdvMapMode::NORMAL)
return;
@ -1130,7 +1129,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
}
}
void CAdvMapInt::tileHovered(const int3 &mapPos)
void CAdvMapInt::onTileHovered(const int3 &mapPos)
{
if(mode != EAdvMapMode::NORMAL //disable in world view
|| !selection) //may occur just at the start of game (fake move before full intiialization)
@ -1290,7 +1289,7 @@ void CAdvMapInt::showMoveDetailsInStatusbar(const CGHeroInstance & hero, const C
statusbar->write(result);
}
void CAdvMapInt::tileRClicked(const int3 &mapPos)
void CAdvMapInt::onTileRightClicked(const int3 &mapPos)
{
if(mode != EAdvMapMode::NORMAL)
return;
@ -1375,11 +1374,6 @@ Rect CAdvMapInt::terrainAreaPixels() const
return terrain->pos;
}
Rect CAdvMapInt::terrainAreaTiles() const
{
return terrain->visibleTilesArea();
}
const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *obj) const
{
const IShipyard *ret = IShipyard::castFrom(obj);
@ -1440,9 +1434,7 @@ void CAdvMapInt::exitWorldView()
infoBar->activate();
redraw();
terrain->setTileSize(32);
terrain->setTerrainVisibility(false);
terrain->setOverlayVisibility({});
terrain->onViewMapActivated();
}
void CAdvMapInt::openWorldView(int tileSize)
@ -1459,7 +1451,7 @@ void CAdvMapInt::openWorldView(int tileSize)
infoBar->deactivate();
redraw();
terrain->setTileSize(tileSize);
terrain->onViewWorldActivated(tileSize);
}
void CAdvMapInt::openWorldView()
@ -1470,6 +1462,5 @@ void CAdvMapInt::openWorldView()
void CAdvMapInt::openWorldView(const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain)
{
openWorldView(11);
terrain->setTerrainVisibility(showTerrain);
terrain->setOverlayVisibility(objectPositions);
terrain->onViewSpellActivated(11, objectPositions, showTerrain);
}

View File

@ -33,7 +33,7 @@ class CGStatusBar;
class CAdvMapPanel;
class CAdvMapWorldViewPanel;
class CAnimation;
class CTerrainRect;
class MapView;
class CResDataBar;
class CHeroList;
class CTownList;
@ -55,7 +55,6 @@ class CAdvMapInt : public CIntObject
{
//TODO: remove
friend class CPlayerInterface;
friend class CTerrainRect;
private:
enum EDirections {LEFT=1, RIGHT=2, UP=4, DOWN=8};
@ -94,7 +93,7 @@ private:
std::shared_ptr<CButton> endTurn;
std::shared_ptr<CButton> worldViewUnderground;
std::shared_ptr<CTerrainRect> terrain;
std::shared_ptr<MapView> terrain;
std::shared_ptr<CMinimap> minimap;
std::shared_ptr<CHeroList> heroList;
std::shared_ptr<CTownList> townList;
@ -160,9 +159,13 @@ public:
// public interface
/// called by MapView whenever currently visible area changes
/// visibleArea describen now visible map section measured in tiles
void onMapViewMoved(const Rect & visibleArea, int mapLevel);
void select(const CArmedInstance *sel, bool centerView = true);
void centerOn(int3 on);
void centerOn(const CGObjectInstance *obj);
void centerOnTile(int3 on);
void centerOnObject(const CGObjectInstance *obj);
bool isHeroSleeping(const CGHeroInstance *hero);
void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
@ -178,9 +181,9 @@ public:
void quickCombatLock(); //should be called when quick battle started
void quickCombatUnlock();
void tileLClicked(const int3 &mapPos);
void tileHovered(const int3 &mapPos);
void tileRClicked(const int3 &mapPos);
void onTileLeftClicked(const int3 & mapPos);
void onTileHovered(const int3 & mapPos);
void onTileRightClicked(const int3 & mapPos);
void enterCastingMode(const CSpell * sp);
void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1));
@ -194,9 +197,6 @@ public:
/// returns area of screen covered by terrain (main game area)
Rect terrainAreaPixels() const;
/// returs visible section of game map, in tiles
Rect terrainAreaTiles() const;
/// exits currently opened world view mode and returns to normal map
void exitWorldView();

View File

@ -12,7 +12,6 @@
#include "CMinimap.h"
#include "CAdvMapInt.h"
#include "CTerrainRect.h"
#include "../widgets/Images.h"
#include "../CGameInfo.h"
@ -126,7 +125,7 @@ Point CMinimap::tileToPixels(const int3 &tile) const
void CMinimap::moveAdvMapSelection()
{
int3 newLocation = pixelToTile(GH.getCursorPosition() - pos.topLeft());
adventureInt->centerOn(newLocation);
adventureInt->centerOnTile(newLocation);
if (!(adventureInt->active & GENERAL))
GH.totalRedraw(); //redraw this as well as inactive adventure map
@ -162,13 +161,14 @@ void CMinimap::mouseMoved(const Point & cursorPosition)
void CMinimap::showAll(SDL_Surface * to)
{
CSDL_Ext::CClipRectGuard guard(to, pos);
CIntObject::showAll(to);
if(minimap)
{
Canvas target(to);
int3 mapSizes = LOCPLINT->cb->getMapSize();
Rect screenArea = adventureInt->terrainAreaTiles();
//draw radar
Rect radar =
@ -180,7 +180,6 @@ void CMinimap::showAll(SDL_Surface * to)
};
Canvas clippedTarget(target, pos);
CSDL_Ext::CClipRectGuard guard(to, pos);
clippedTarget.drawBorderDashed(radar, CSDL_Ext::fromSDL(Colors::PURPLE));
}
}
@ -195,14 +194,21 @@ void CMinimap::update()
redraw();
}
void CMinimap::setLevel(int newLevel)
void CMinimap::onMapViewMoved(const Rect & visibleArea, int mapLevel)
{
if (level == newLevel)
if (screenArea == visibleArea && level == mapLevel)
return;
level = newLevel;
screenArea = visibleArea;
if(level != mapLevel)
{
level = mapLevel;
update();
}
else
redraw();
}
void CMinimap::setAIRadar(bool on)
{

View File

@ -41,6 +41,7 @@ class CMinimap : public CIntObject
{
std::shared_ptr<CPicture> aiShield; //the graphic displayed during AI turn
std::shared_ptr<CMinimapInstance> minimap;
Rect screenArea;
int level;
void clickLeft(tribool down, bool previousState) override;
@ -59,11 +60,10 @@ protected:
Point tileToPixels(const int3 & position) const;
public:
explicit CMinimap(const Rect & position);
void onMapViewMoved(const Rect & visibleArea, int mapLevel);
void update();
void setLevel(int level);
void setAIRadar(bool on);
void showAll(SDL_Surface * to) override;

View File

@ -1,263 +0,0 @@
/*
* CTerrainRect.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "CTerrainRect.h"
#include "CAdvMapInt.h"
#include "../CGameInfo.h"
#include "../CMT.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../mapRenderer/mapHandler.h"
#include "../render/CAnimation.h"
#include "../render/IImage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../widgets/TextControls.h"
#include "../mapRenderer/MapView.h"
#include "../mapRenderer/MapViewController.h"
#include "../mapRenderer/MapViewModel.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/CPathfinder.h"
#define ADVOPT (conf.go()->ac)
CTerrainRect::CTerrainRect()
: curHoveredTile(-1, -1, -1)
, isSwiping(false)
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
, swipeEnabled(settings["general"]["swipe"].Bool())
#else
, swipeEnabled(settings["general"]["swipeDesktop"].Bool())
#endif
, swipeMovementRequested(false)
, swipeTargetPosition(Point(0, 0))
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos.x=ADVOPT.advmapX;
pos.y=ADVOPT.advmapY;
pos.w=ADVOPT.advmapW;
pos.h=ADVOPT.advmapH;
addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE);
renderer = std::make_shared<MapView>( Point(0,0), pos.dimensions() );
}
void CTerrainRect::setViewCenter(const int3 &coordinates)
{
renderer->getController()->setViewCenter(coordinates);
}
void CTerrainRect::setViewCenter(const Point & position, int level)
{
renderer->getController()->setViewCenter(position, level);
}
void CTerrainRect::deactivate()
{
CIntObject::deactivate();
curHoveredTile = int3(-1,-1,-1); //we lost info about hovered tile when disabling
}
void CTerrainRect::clickLeft(tribool down, bool previousState)
{
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if(indeterminate(down))
return;
if(swipeEnabled)
{
if(handleSwipeStateChange((bool)down == true))
{
return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
}
}
else
{
if(down == false)
return;
}
int3 mp = whichTileIsIt();
if(mp.x < 0 || mp.y < 0 || mp.x >= LOCPLINT->cb->getMapSize().x || mp.y >= LOCPLINT->cb->getMapSize().y)
return;
adventureInt->tileLClicked(mp);
}
void CTerrainRect::clickRight(tribool down, bool previousState)
{
if(isSwiping)
return;
if(adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
int3 mp = whichTileIsIt();
if(CGI->mh->isInMap(mp) && down)
adventureInt->tileRClicked(mp);
}
void CTerrainRect::clickMiddle(tribool down, bool previousState)
{
handleSwipeStateChange((bool)down == true);
}
void CTerrainRect::mouseMoved(const Point & cursorPosition)
{
handleHover(cursorPosition);
handleSwipeMove(cursorPosition);
}
void CTerrainRect::handleSwipeMove(const Point & cursorPosition)
{
// unless swipe is enabled, swipe move only works with middle mouse button
if(!swipeEnabled && !GH.isMouseButtonPressed(MouseButton::MIDDLE))
return;
// on mobile platforms with enabled swipe any button is enough
if(swipeEnabled && (!GH.isMouseButtonPressed() || GH.multifinger))
return;
if(!isSwiping)
{
static constexpr int touchSwipeSlop = 16;
// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
if(std::abs(cursorPosition.x - swipeInitialRealPos.x) > touchSwipeSlop ||
std::abs(cursorPosition.y - swipeInitialRealPos.y) > touchSwipeSlop)
{
isSwiping = true;
}
}
if(isSwiping)
{
swipeTargetPosition.x = swipeInitialViewPos.x + swipeInitialRealPos.x - cursorPosition.x;
swipeTargetPosition.y = swipeInitialViewPos.y + swipeInitialRealPos.y - cursorPosition.y;
swipeMovementRequested = true;
}
}
bool CTerrainRect::handleSwipeStateChange(bool btnPressed)
{
if(btnPressed)
{
swipeInitialRealPos = Point(GH.getCursorPosition().x, GH.getCursorPosition().y);
swipeInitialViewPos = getViewCenter();
return true;
}
if(isSwiping) // only accept this touch if it wasn't a swipe
{
isSwiping = false;
return true;
}
return false;
}
void CTerrainRect::handleHover(const Point & cursorPosition)
{
int3 tHovered = whichTileIsIt(cursorPosition);
if(!CGI->mh->isInMap(tHovered))
{
CCS->curh->set(Cursor::Map::POINTER);
return;
}
if (tHovered != curHoveredTile)
{
curHoveredTile = tHovered;
adventureInt->tileHovered(tHovered);
}
}
void CTerrainRect::hover(bool on)
{
if (!on)
{
GH.statusbar->clear();
CCS->curh->set(Cursor::Map::POINTER);
}
//Hoverable::hover(on);
}
int3 CTerrainRect::whichTileIsIt(const Point &position)
{
return renderer->getModel()->getTileAtPoint(position - pos);
}
int3 CTerrainRect::whichTileIsIt()
{
return whichTileIsIt(GH.getCursorPosition());
}
Rect CTerrainRect::visibleTilesArea()
{
return renderer->getModel()->getTilesTotalRect();
}
void CTerrainRect::setLevel(int level)
{
renderer->getController()->setViewCenter(renderer->getModel()->getMapViewCenter(), level);
}
void CTerrainRect::moveViewBy(const Point & delta)
{
// ignore scrolling attempts while we are swiping
if (isSwiping || swipeMovementRequested)
return;
renderer->getController()->setViewCenter(renderer->getModel()->getMapViewCenter() + delta, getLevel());
}
Point CTerrainRect::getViewCenter()
{
return renderer->getModel()->getMapViewCenter();
}
int CTerrainRect::getLevel()
{
return renderer->getModel()->getLevel();
}
void CTerrainRect::setTileSize(int sizePixels)
{
renderer->getController()->setTileSize(Point(sizePixels, sizePixels));
}
void CTerrainRect::setTerrainVisibility(bool showAllTerrain)
{
renderer->getController()->setTerrainVisibility(showAllTerrain);
}
void CTerrainRect::setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions)
{
renderer->getController()->setOverlayVisibility(objectPositions);
}
void CTerrainRect::show(SDL_Surface * to)
{
if(swipeMovementRequested)
{
setViewCenter(swipeTargetPosition, getLevel());
CCS->curh->set(Cursor::Map::POINTER);
swipeMovementRequested = false;
}
CIntObject::show(to);
}

View File

@ -1,79 +0,0 @@
/*
* CTerrainRect.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../../lib/int3.h"
VCMI_LIB_NAMESPACE_BEGIN
struct CGPath;
struct ObjectPosInfo;
VCMI_LIB_NAMESPACE_END
class MapView;
/// Holds information about which tiles of the terrain are shown/not shown at the screen
class CTerrainRect : public CIntObject
{
std::shared_ptr<MapView> renderer;
bool swipeEnabled;
bool swipeMovementRequested;
Point swipeTargetPosition;
Point swipeInitialViewPos;
Point swipeInitialRealPos;
bool isSwiping;
void handleHover(const Point & cursorPosition);
void handleSwipeMove(const Point & cursorPosition);
/// handles start/finish of swipe (press/release of corresponding button); returns true if state change was handled
bool handleSwipeStateChange(bool btnPressed);
int3 curHoveredTile;
int3 whichTileIsIt(const Point & position); //x,y are cursor position
int3 whichTileIsIt(); //uses current cursor pos
Point getViewCenter();
public:
CTerrainRect();
/// Handle swipe & selection of object
void setViewCenter(const int3 & coordinates);
void setViewCenter(const Point & position, int level);
/// Edge scrolling
void moveViewBy(const Point & delta);
/// Toggle undeground view button
void setLevel(int level);
int getLevel();
/// World view & View Earth/Air spells
void setTerrainVisibility(bool showAllTerrain);
void setOverlayVisibility(const std::vector<ObjectPosInfo> & objectPositions);
void setTileSize(int sizePixels);
/// Minimap access
/// @returns number of visible tiles on screen respecting current map scaling
Rect visibleTilesArea();
// CIntObject interface implementation
void deactivate() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void clickMiddle(tribool down, bool previousState) override;
void hover(bool on) override;
void mouseMoved (const Point & cursorPosition) override;
void show(SDL_Surface * to) override;
//void showAll(SDL_Surface * to) override;
//void showAnim(SDL_Surface * to);
};

View File

@ -70,6 +70,10 @@ public:
/// if true, rendered images will be converted to grayscale
virtual bool filterGrayscale() const = 0;
virtual bool showRoads() const = 0;
virtual bool showRivers() const = 0;
virtual bool showBorder() const = 0;
/// if true, world view overlay will be shown
virtual bool showOverlay() const = 0;

View File

@ -35,7 +35,7 @@ struct NeighborTilesInfo
//012
std::bitset<8> d;
NeighborTilesInfo(const IMapRendererContext & context, const int3 & pos)
NeighborTilesInfo(IMapRendererContext & context, const int3 & pos)
{
auto checkTile = [&](int dx, int dy)
{
@ -128,7 +128,7 @@ MapRendererTerrain::MapRendererTerrain()
storage.load(terrain->getIndex(), terrain->tilesFilename, EImageBlitMode::OPAQUE);
}
void MapRendererTerrain::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererTerrain::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
const TerrainTile & mapTile = context.getMapTile(coordinates);
@ -152,7 +152,7 @@ void MapRendererTerrain::renderTile(const IMapRendererContext & context, Canvas
target.draw(image, Point(0, 0));
}
uint8_t MapRendererTerrain::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererTerrain::checksum(IMapRendererContext & context, const int3 & coordinates)
{
const TerrainTile & mapTile = context.getMapTile(coordinates);
@ -168,7 +168,7 @@ MapRendererRiver::MapRendererRiver()
storage.load(river->getIndex(), river->tilesFilename, EImageBlitMode::COLORKEY);
}
void MapRendererRiver::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererRiver::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
const TerrainTile & mapTile = context.getMapTile(coordinates);
@ -202,7 +202,7 @@ void MapRendererRiver::renderTile(const IMapRendererContext & context, Canvas &
target.draw(image, Point(0, 0));
}
uint8_t MapRendererRiver::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererRiver::checksum(IMapRendererContext & context, const int3 & coordinates)
{
const TerrainTile & mapTile = context.getMapTile(coordinates);
@ -220,7 +220,7 @@ MapRendererRoad::MapRendererRoad()
storage.load(road->getIndex(), road->tilesFilename, EImageBlitMode::COLORKEY);
}
void MapRendererRoad::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererRoad::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
const int3 coordinatesAbove = coordinates - int3(0, 1, 0);
@ -250,18 +250,19 @@ void MapRendererRoad::renderTile(const IMapRendererContext & context, Canvas & t
}
}
uint8_t MapRendererRoad::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererRoad::checksum(IMapRendererContext & context, const int3 & coordinates)
{
return 0;
}
MapRendererBorder::MapRendererBorder()
{
emptyFill = std::make_unique<Canvas>(Point(32,32));
animation = std::make_unique<CAnimation>("EDG");
animation->preload();
}
size_t MapRendererBorder::getIndexForTile(const IMapRendererContext & context, const int3 & tile)
size_t MapRendererBorder::getIndexForTile(IMapRendererContext & context, const int3 & tile)
{
assert(!context.isInMap(tile));
@ -299,13 +300,20 @@ size_t MapRendererBorder::getIndexForTile(const IMapRendererContext & context, c
return 0;
}
void MapRendererBorder::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererBorder::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
if (context.showBorder())
{
const auto & image = animation->getImage(getIndexForTile(context, coordinates));
target.draw(image, Point(0, 0));
}
else
{
target.draw(*emptyFill, Point(0,0));
}
}
uint8_t MapRendererBorder::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererBorder::checksum(IMapRendererContext & context, const int3 & coordinates)
{
return 0;
}
@ -333,7 +341,7 @@ MapRendererFow::MapRendererFow()
}
}
void MapRendererFow::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererFow::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
assert(!context.isVisible(coordinates));
@ -356,7 +364,7 @@ void MapRendererFow::renderTile(const IMapRendererContext & context, Canvas & ta
}
}
uint8_t MapRendererFow::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererFow::checksum(IMapRendererContext & context, const int3 & coordinates)
{
const NeighborTilesInfo neighborInfo(context, coordinates);
int retBitmapID = neighborInfo.getBitmapID();
@ -470,7 +478,7 @@ std::shared_ptr<CAnimation> MapRendererObjects::getOverlayAnimation(const CGObje
return nullptr;
}
std::shared_ptr<IImage> MapRendererObjects::getImage(const IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation>& animation) const
std::shared_ptr<IImage> MapRendererObjects::getImage(IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation>& animation) const
{
if(!animation)
return nullptr;
@ -485,7 +493,7 @@ std::shared_ptr<IImage> MapRendererObjects::getImage(const IMapRendererContext &
return animation->getImage(frameIndex, groupIndex);
}
void MapRendererObjects::renderImage(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage>& image)
void MapRendererObjects::renderImage(IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage>& image)
{
if(!image)
return;
@ -517,14 +525,14 @@ void MapRendererObjects::renderImage(const IMapRendererContext & context, Canvas
}
}
void MapRendererObjects::renderObject(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * instance)
void MapRendererObjects::renderObject(IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * instance)
{
renderImage(context, target, coordinates, instance, getImage(context, instance, getBaseAnimation(instance)));
renderImage(context, target, coordinates, instance, getImage(context, instance, getFlagAnimation(instance)));
renderImage(context, target, coordinates, instance, getImage(context, instance, getOverlayAnimation(instance)));
}
void MapRendererObjects::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererObjects::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
for(const auto & objectID : context.getObjects(coordinates))
{
@ -541,7 +549,7 @@ void MapRendererObjects::renderTile(const IMapRendererContext & context, Canvas
}
}
uint8_t MapRendererObjects::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererObjects::checksum(IMapRendererContext & context, const int3 & coordinates)
{
for(const auto & objectID : context.getObjects(coordinates))
{
@ -579,7 +587,7 @@ MapRendererDebug::MapRendererDebug()
}
void MapRendererDebug::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererDebug::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
if(context.showGrid())
target.draw(imageGrid, Point(0,0));
@ -607,7 +615,7 @@ void MapRendererDebug::renderTile(const IMapRendererContext & context, Canvas &
}
}
uint8_t MapRendererDebug::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererDebug::checksum(IMapRendererContext & context, const int3 & coordinates)
{
return 0;
}
@ -665,7 +673,7 @@ size_t MapRendererPath::selectImageArrow(bool reachableToday, const int3 & curr,
return selectImageReachability(reachableToday, imageIndex);
}
void MapRendererPath::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRendererPath::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
size_t imageID = selectImage(context, coordinates);
@ -673,7 +681,7 @@ void MapRendererPath::renderTile(const IMapRendererContext & context, Canvas & t
target.draw(pathNodes->getImage(imageID), Point(0,0));
}
size_t MapRendererPath::selectImage(const IMapRendererContext & context, const int3 & coordinates)
size_t MapRendererPath::selectImage(IMapRendererContext & context, const int3 & coordinates)
{
const auto & functor = [&](const CGPathNode & node)
{
@ -709,12 +717,12 @@ size_t MapRendererPath::selectImage(const IMapRendererContext & context, const i
return selectImageCross(reachableToday, iter->coord);
}
uint8_t MapRendererPath::checksum(const IMapRendererContext & context, const int3 & coordinates)
uint8_t MapRendererPath::checksum(IMapRendererContext & context, const int3 & coordinates)
{
return selectImage(context, coordinates) & 0xff;
}
MapRenderer::TileChecksum MapRenderer::getTileChecksum(const IMapRendererContext & context, const int3 & coordinates)
MapRenderer::TileChecksum MapRenderer::getTileChecksum(IMapRendererContext & context, const int3 & coordinates)
{
// computes basic checksum to determine whether tile needs an update
// if any component gives different value, tile will be updated
@ -736,7 +744,9 @@ MapRenderer::TileChecksum MapRenderer::getTileChecksum(const IMapRendererContext
else
{
result[1] = rendererTerrain.checksum(context, coordinates);
if (context.showRivers())
result[2] = rendererRiver.checksum(context, coordinates);
if (context.showRoads())
result[3] = rendererRoad.checksum(context, coordinates);
result[4] = rendererObjects.checksum(context, coordinates);
result[5] = rendererPath.checksum(context, coordinates);
@ -748,7 +758,7 @@ MapRenderer::TileChecksum MapRenderer::getTileChecksum(const IMapRendererContext
return result;
}
void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
void MapRenderer::renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
if(!context.isInMap(coordinates))
{
@ -765,8 +775,13 @@ void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & targe
else
{
rendererTerrain.renderTile(context, target, coordinates);
if (context.showRivers())
rendererRiver.renderTile(context, target, coordinates);
if (context.showRoads())
rendererRoad.renderTile(context, target, coordinates);
rendererObjects.renderTile(context, target, coordinates);
rendererPath.renderTile(context, target, coordinates);
rendererDebug.renderTile(context, target, coordinates);

View File

@ -41,8 +41,8 @@ class MapRendererTerrain
public:
MapRendererTerrain();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererRiver
@ -52,8 +52,8 @@ class MapRendererRiver
public:
MapRendererRiver();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererRoad
@ -63,8 +63,8 @@ class MapRendererRoad
public:
MapRendererRoad();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererObjects
@ -77,27 +77,28 @@ class MapRendererObjects
std::shared_ptr<CAnimation> getAnimation(const std::string & filename, bool generateMovementGroups);
std::shared_ptr<IImage> getImage(const IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation> & animation) const;
std::shared_ptr<IImage> getImage(IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation> & animation) const;
void renderImage(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage> & image);
void renderObject(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * obj);
void renderImage(IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage> & image);
void renderObject(IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * obj);
public:
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererBorder
{
std::unique_ptr<CAnimation> animation;
std::unique_ptr<Canvas> emptyFill;
size_t getIndexForTile(const IMapRendererContext & context, const int3 & coordinates);
size_t getIndexForTile(IMapRendererContext & context, const int3 & coordinates);
public:
MapRendererBorder();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererFow
@ -108,8 +109,8 @@ class MapRendererFow
public:
MapRendererFow();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererPath
@ -119,13 +120,13 @@ class MapRendererPath
size_t selectImageReachability(bool reachableToday, size_t imageIndex);
size_t selectImageCross(bool reachableToday, const int3 & curr);
size_t selectImageArrow(bool reachableToday, const int3 & curr, const int3 & prev, const int3 & next);
size_t selectImage(const IMapRendererContext & context, const int3 & coordinates);
size_t selectImage(IMapRendererContext & context, const int3 & coordinates);
public:
MapRendererPath();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererDebug
@ -136,8 +137,8 @@ class MapRendererDebug
public:
MapRendererDebug();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererOverlay
@ -146,8 +147,8 @@ class MapRendererOverlay
public:
MapRendererOverlay();
uint8_t checksum(const IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
uint8_t checksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRenderer
@ -164,7 +165,7 @@ class MapRenderer
public:
using TileChecksum = std::array<uint8_t, 8>;
TileChecksum getTileChecksum(const IMapRendererContext & context, const int3 & coordinates);
TileChecksum getTileChecksum(IMapRendererContext & context, const int3 & coordinates);
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
void renderTile(IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};

View File

@ -21,7 +21,7 @@
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapping/CMap.h"
MapObjectsSorter::MapObjectsSorter(const IMapRendererContext & context)
MapObjectsSorter::MapObjectsSorter(IMapRendererContext & context)
: context(context)
{
}
@ -66,6 +66,9 @@ bool MapRendererContext::isVisible(const int3 & coordinates) const
const CGPath * MapRendererContext::currentPath() const
{
if (worldViewModeActive)
return nullptr;
const auto * hero = adventureInt->curHero();
if(!hero)
@ -86,6 +89,9 @@ size_t MapRendererContext::objectImageIndex(ObjectInstanceID objectID, size_t gr
if (!settingsAdventureObjectAnimation)
return 0;
if (worldViewModeActive)
return 0;
// H3 timing for adventure map objects animation is 180 ms
// Terrain animations also use identical interval, however those are only present in HotA and/or HD Mod
size_t baseFrameTime = 180;
@ -105,6 +111,9 @@ size_t MapRendererContext::terrainImageIndex(size_t groupSize) const
if (!settingsAdventureTerrainAnimation)
return 0;
if (worldViewModeActive)
return 0;
size_t baseFrameTime = 180;
size_t frameCounter = animationTime / baseFrameTime;
size_t frameIndex = frameCounter % groupSize;
@ -144,7 +153,22 @@ bool MapRendererContext::tileAnimated(const int3 & coordinates) const
bool MapRendererContext::filterGrayscale() const
{
return false;//true;
return false;
}
bool MapRendererContext::showRoads() const
{
return true;
}
bool MapRendererContext::showRivers() const
{
return true;
}
bool MapRendererContext::showBorder() const
{
return !worldViewModeActive;
}
bool MapRendererContext::showOverlay() const

View File

@ -20,10 +20,10 @@ VCMI_LIB_NAMESPACE_END
class MapObjectsSorter
{
const IMapRendererContext & context;
IMapRendererContext & context;
public:
explicit MapObjectsSorter(const IMapRendererContext & context);
explicit MapObjectsSorter(IMapRendererContext & context);
bool operator()(const ObjectInstanceID & left, const ObjectInstanceID & right) const;
bool operator()(const CGObjectInstance * left, const CGObjectInstance * right) const;
@ -122,6 +122,9 @@ public:
size_t overlayImageIndex(const int3 & coordinates) const override;
bool filterGrayscale() const override;
bool showRoads() const override;
bool showRivers() const override;
bool showBorder() const override;
bool showOverlay() const override;
bool showGrid() const override;
bool showVisitable() const override;

View File

@ -11,14 +11,15 @@
#include "StdInc.h"
#include "MapView.h"
#include "MapViewModel.h"
#include "MapViewActions.h"
#include "MapViewCache.h"
#include "MapViewController.h"
#include "MapViewModel.h"
#include "mapHandler.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../gui/CGuiHandler.h"
#include "../render/CAnimation.h"
#include "../render/Canvas.h"
@ -49,17 +50,21 @@ MapView::MapView(const Point & offset, const Point & dimensions)
: model(createModel(dimensions))
, controller(new MapViewController(model))
, tilesCache(new MapViewCache(model))
, isSwiping(false)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos += offset;
pos.w = dimensions.x;
pos.h = dimensions.y;
actions = std::make_shared<MapViewActions>(*this, model);
actions->setContext(controller->getContext());
}
void MapView::render(Canvas & target, bool fullUpdate)
{
Canvas targetClipped(target, pos);
controller->update(GH.mainFPSmng->getElapsedMilliseconds());
tilesCache->update(controller->getContext());
tilesCache->render(controller->getContext(), targetClipped, fullUpdate);
@ -79,12 +84,59 @@ void MapView::showAll(SDL_Surface * to)
render(target, true);
}
std::shared_ptr<const MapViewModel> MapView::getModel() const
void MapView::onMapLevelSwitched()
{
return model;
if(LOCPLINT->cb->getMapSize().z > 1)
{
if(model->getLevel() == 0)
controller->setViewCenter(model->getMapViewCenter(), 1);
else
controller->setViewCenter(model->getMapViewCenter(), 0);
}
}
std::shared_ptr<MapViewController> MapView::getController()
void MapView::onMapScrolled(const Point & distance)
{
return controller;
if(!isSwiping)
controller->setViewCenter(model->getMapViewCenter() + distance, model->getLevel());
}
void MapView::onMapSwiped(const Point & viewPosition)
{
isSwiping = true;
controller->setViewCenter(viewPosition, model->getLevel());
}
void MapView::onMapSwipeEnded()
{
isSwiping = true;
}
void MapView::onCenteredTile(const int3 & tile)
{
controller->setViewCenter(tile);
}
void MapView::onCenteredObject(const CGObjectInstance * target)
{
controller->setViewCenter(target->getSightCenter());
}
void MapView::onViewSpellActivated(uint32_t tileSize, const std::vector<ObjectPosInfo> & objectPositions, bool showTerrain)
{
controller->setTileSize(Point(tileSize, tileSize));
controller->setOverlayVisibility(objectPositions);
controller->setTerrainVisibility(showTerrain);
}
void MapView::onViewWorldActivated(uint32_t tileSize)
{
controller->setTileSize(Point(tileSize, tileSize));
}
void MapView::onViewMapActivated()
{
controller->setTileSize(Point(32, 32));
controller->setOverlayVisibility({});
controller->setTerrainVisibility(false);
}

View File

@ -11,28 +11,64 @@
#include "../gui/CIntObject.h"
VCMI_LIB_NAMESPACE_BEGIN
struct ObjectPosInfo;
VCMI_LIB_NAMESPACE_END
class Canvas;
class MapViewActions;
class MapViewController;
class MapViewModel;
class MapViewCache;
/// Main map rendering class that mostly acts as container for component classes
/// Main class that represents visible section of adventure map
/// Contains all public interface of view and translates calls to internal model
class MapView : public CIntObject
{
std::shared_ptr<MapViewModel> model;
std::unique_ptr<MapViewCache> tilesCache;
std::shared_ptr<MapViewCache> tilesCache;
std::shared_ptr<MapViewController> controller;
std::shared_ptr<MapViewActions> actions;
bool isSwiping;
std::shared_ptr<MapViewModel> createModel(const Point & dimensions) const;
void render(Canvas & target, bool fullUpdate);
public:
std::shared_ptr<const MapViewModel> getModel() const;
std::shared_ptr<MapViewController> getController();
public:
MapView(const Point & offset, const Point & dimensions);
~MapView() override;
/// Moves current view to another level, preserving position
void onMapLevelSwitched();
/// Moves current view by specified distance in pixels
void onMapScrolled(const Point & distance);
/// Moves current view to specified position, in pixels
void onMapSwiped(const Point & viewPosition);
/// Ends swiping mode and allows normal map scrolling once again
void onMapSwipeEnded();
/// Moves current view to specified tile
void onCenteredTile(const int3 & tile);
/// Centers view on object and starts "tracking" it
/// Whenever object changes position, so will the object
/// Tracking will be disabled on any call that moves view
void onCenteredObject(const CGObjectInstance * target);
/// Switches view to "View Earth" / "View Air" mode, displaying downscaled map with overlay
void onViewSpellActivated( uint32_t tileSize, const std::vector<ObjectPosInfo>& objectPositions, bool showTerrain);
/// Switches view to downscaled View World
void onViewWorldActivated( uint32_t tileSize);
/// Switches view from View World mode back to standard view
void onViewMapActivated();
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
};

View File

@ -0,0 +1,172 @@
/*
* MapViewActions.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "MapViewActions.h"
#include "IMapRendererContext.h"
#include "MapViewModel.h"
#include "MapView.h"
#include "../CGameInfo.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../../lib/CConfigHandler.h"
MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel>& model)
: model(model)
, owner(owner)
, curHoveredTile(-1, -1, -1)
, isSwiping(false)
#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
, swipeEnabled(settings["general"]["swipe"].Bool())
#else
, swipeEnabled(settings["general"]["swipeDesktop"].Bool())
#endif
{
pos.w = model->getPixelsVisibleDimensions().x;
pos.h = model->getPixelsVisibleDimensions().y;
addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE);
}
void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & context)
{
this->context = context;
}
void MapViewActions::activate()
{
CIntObject::activate();
}
void MapViewActions::deactivate()
{
CIntObject::deactivate();
curHoveredTile = int3(-1,-1,-1); //we lost info about hovered tile when disabling
}
void MapViewActions::clickLeft(tribool down, bool previousState)
{
if(indeterminate(down))
return;
if(swipeEnabled)
{
if(handleSwipeStateChange(static_cast<bool>(down)))
{
return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
}
}
else
{
if(down == false)
return;
}
int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
if (context->isInMap(tile))
adventureInt->onTileLeftClicked(tile);
}
void MapViewActions::clickRight(tribool down, bool previousState)
{
if(isSwiping)
return;
int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
if (down && context->isInMap(tile))
adventureInt->onTileRightClicked(tile);
}
void MapViewActions::clickMiddle(tribool down, bool previousState)
{
handleSwipeStateChange(static_cast<bool>(down));
}
void MapViewActions::mouseMoved(const Point & cursorPosition)
{
handleHover(cursorPosition);
handleSwipeMove(cursorPosition);
}
void MapViewActions::handleSwipeMove(const Point & cursorPosition)
{
// unless swipe is enabled, swipe move only works with middle mouse button
if(!swipeEnabled && !GH.isMouseButtonPressed(MouseButton::MIDDLE))
return;
// on mobile platforms with enabled swipe any button is enough
if(swipeEnabled && (!GH.isMouseButtonPressed() || GH.multifinger))
return;
if(!isSwiping)
{
static constexpr int touchSwipeSlop = 16;
Point distance = (cursorPosition - swipeInitialRealPos);
// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
if( std::abs(distance.x) + std::abs(distance.y) > touchSwipeSlop)
isSwiping = true;
}
if(isSwiping)
{
Point swipeTargetPosition = swipeInitialViewPos + swipeInitialRealPos - cursorPosition;
owner.onMapSwiped(swipeTargetPosition);
}
}
bool MapViewActions::handleSwipeStateChange(bool btnPressed)
{
if(btnPressed)
{
swipeInitialRealPos = GH.getCursorPosition();
swipeInitialViewPos = model->getMapViewCenter();
return true;
}
if(isSwiping) // only accept this touch if it wasn't a swipe
{
owner.onMapSwipeEnded();
isSwiping = false;
return true;
}
return false;
}
void MapViewActions::handleHover(const Point & cursorPosition)
{
int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
if(!context->isInMap(tile))
{
CCS->curh->set(Cursor::Map::POINTER);
return;
}
if (tile != curHoveredTile)
{
curHoveredTile = tile;
adventureInt->onTileHovered(tile);
}
}
void MapViewActions::hover(bool on)
{
if (!on)
{
GH.statusbar->clear();
CCS->curh->set(Cursor::Map::POINTER);
}
}

View File

@ -0,0 +1,49 @@
/*
* MapViewActions.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../gui/CIntObject.h"
#include "../../lib/int3.h"
class IMapRendererContext;
class MapViewModel;
class MapView;
class MapViewActions : public CIntObject
{
bool swipeEnabled;
bool isSwiping;
Point swipeInitialViewPos;
Point swipeInitialRealPos;
int3 curHoveredTile;
MapView & owner;
std::shared_ptr<MapViewModel> model;
std::shared_ptr<IMapRendererContext> context;
void handleHover(const Point & cursorPosition);
void handleSwipeMove(const Point & cursorPosition);
bool handleSwipeStateChange(bool btnPressed);
public:
MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel>& model);
void setContext(const std::shared_ptr<IMapRendererContext> & context);
void activate() override;
void deactivate() override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void clickMiddle(tribool down, bool previousState) override;
void hover(bool on) override;
void mouseMoved (const Point & cursorPosition) override;
};

View File

@ -45,7 +45,7 @@ Canvas MapViewCache::getTile(const int3 & coordinates)
return Canvas(*terrain, model->getCacheTileArea(coordinates));
}
std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_ptr<const IMapRendererContext> & context, const int3 & coordinates)
std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_ptr<IMapRendererContext> & context, const int3 & coordinates)
{
size_t imageIndex = context->overlayImageIndex(coordinates);
@ -54,7 +54,7 @@ std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_p
return nullptr;
}
void MapViewCache::updateTile(const std::shared_ptr<const IMapRendererContext> & context, const int3 & coordinates)
void MapViewCache::updateTile(const std::shared_ptr<IMapRendererContext> & context, const int3 & coordinates)
{
int cacheX = (terrainChecksum.shape()[0] + coordinates.x) % terrainChecksum.shape()[0];
int cacheY = (terrainChecksum.shape()[1] + coordinates.y) % terrainChecksum.shape()[1];
@ -67,14 +67,7 @@ void MapViewCache::updateTile(const std::shared_ptr<const IMapRendererContext> &
newCacheEntry.checksum = mapRenderer->getTileChecksum(*context, coordinates);
if(cachedLevel == coordinates.z && oldCacheEntry == newCacheEntry && !context->tileAnimated(coordinates))
{
// debug code to check caching - cached tiles will slowly fade to black
//static const auto overlay = IImage::createFromFile("debug/cached");
//Canvas target = getTile(coordinates);
//target.draw(overlay, Point(0,0));
return;
}
Canvas target = getTile(coordinates);
@ -95,7 +88,7 @@ void MapViewCache::updateTile(const std::shared_ptr<const IMapRendererContext> &
tilesUpToDate[cacheX][cacheY] = false;
}
void MapViewCache::update(const std::shared_ptr<const IMapRendererContext> & context)
void MapViewCache::update(const std::shared_ptr<IMapRendererContext> & context)
{
Rect dimensions = model->getTilesTotalRect();
@ -103,7 +96,16 @@ void MapViewCache::update(const std::shared_ptr<const IMapRendererContext> & con
{
boost::multi_array<TileChecksum, 2> newCache;
newCache.resize(boost::extents[dimensions.w][dimensions.h]);
std::swap(newCache, terrainChecksum);
terrainChecksum.resize(boost::extents[dimensions.w][dimensions.h]);
terrainChecksum = newCache;
}
if(dimensions.w != tilesUpToDate.shape()[0] || dimensions.h != tilesUpToDate.shape()[1])
{
boost::multi_array<bool, 2> newCache;
newCache.resize(boost::extents[dimensions.w][dimensions.h]);
tilesUpToDate.resize(boost::extents[dimensions.w][dimensions.h]);
tilesUpToDate = newCache;
}
for(int y = dimensions.top(); y < dimensions.bottom(); ++y)
@ -113,20 +115,13 @@ void MapViewCache::update(const std::shared_ptr<const IMapRendererContext> & con
cachedLevel = model->getLevel();
}
void MapViewCache::render(const std::shared_ptr<const IMapRendererContext> & context, Canvas & target, bool fullRedraw)
void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context, Canvas & target, bool fullRedraw)
{
bool mapMoved = (cachedPosition != model->getMapViewCenter());
bool lazyUpdate = !mapMoved && !fullRedraw;
Rect dimensions = model->getTilesTotalRect();
if(dimensions.w != tilesUpToDate.shape()[0] || dimensions.h != tilesUpToDate.shape()[1])
{
boost::multi_array<bool, 2> newCache;
newCache.resize(boost::extents[dimensions.w][dimensions.h]);
std::swap(newCache, tilesUpToDate);
}
for(int y = dimensions.top(); y < dimensions.bottom(); ++y)
{
for(int x = dimensions.left(); x < dimensions.right(); ++x)

View File

@ -50,16 +50,16 @@ class MapViewCache
std::unique_ptr<CAnimation> iconsStorage;
Canvas getTile(const int3 & coordinates);
void updateTile(const std::shared_ptr<const IMapRendererContext> & context, const int3 & coordinates);
void updateTile(const std::shared_ptr<IMapRendererContext> & context, const int3 & coordinates);
std::shared_ptr<IImage> getOverlayImageForTile(const std::shared_ptr<const IMapRendererContext> & context, const int3 & coordinates);
std::shared_ptr<IImage> getOverlayImageForTile(const std::shared_ptr<IMapRendererContext> & context, const int3 & coordinates);
public:
explicit MapViewCache(const std::shared_ptr<MapViewModel> & model);
~MapViewCache();
/// updates internal terrain cache according to provided time delta
void update(const std::shared_ptr<const IMapRendererContext> & context);
void update(const std::shared_ptr<IMapRendererContext> & context);
/// renders updated terrain cache onto provided canvas
void render(const std::shared_ptr<const IMapRendererContext> &context, Canvas & target, bool fullRedraw);
void render(const std::shared_ptr<IMapRendererContext> &context, Canvas & target, bool fullRedraw);
};

View File

@ -24,23 +24,54 @@
void MapViewController::setViewCenter(const int3 & position)
{
assert(context->isInMap(position));
setViewCenter(Point(position) * model->getSingleTileSize(), position.z);
setViewCenter(Point(position) * model->getSingleTileSize() + model->getSingleTileSize() / 2, position.z);
}
void MapViewController::setViewCenter(const Point & position, int level)
{
Point upperLimit = Point(context->getMapSize()) * model->getSingleTileSize() + model->getSingleTileSize();
Point lowerLimit = Point(0,0);
if (context->worldViewModeActive)
{
Point area = model->getPixelsVisibleDimensions();
Point mapCenter = upperLimit / 2;
Point desiredLowerLimit = lowerLimit + area / 2;
Point desiredUpperLimit = upperLimit - area / 2;
Point actualLowerLimit {
std::min(desiredLowerLimit.x, mapCenter.x),
std::min(desiredLowerLimit.y, mapCenter.y)
};
Point actualUpperLimit {
std::max(desiredUpperLimit.x, mapCenter.x),
std::max(desiredUpperLimit.y, mapCenter.y)
};
upperLimit = actualUpperLimit;
lowerLimit = actualLowerLimit;
}
Point betterPosition = {
vstd::clamp(position.x, 0, context->getMapSize().x * model->getSingleTileSize().x),
vstd::clamp(position.y, 0, context->getMapSize().y * model->getSingleTileSize().y)
vstd::clamp(position.x, lowerLimit.x, upperLimit.x),
vstd::clamp(position.y, lowerLimit.y, upperLimit.y)
};
model->setViewCenter(betterPosition);
model->setLevel(vstd::clamp(level, 0, context->getMapSize().z));
if (adventureInt) // may be called before adventureInt is initialized
adventureInt->onMapViewMoved(model->getTilesTotalRect(), model->getLevel());
}
void MapViewController::setTileSize(const Point & tileSize)
{
model->setTileSize(tileSize);
// force update of view center since changing tile size may invalidated it
setViewCenter(model->getMapViewCenter(), model->getLevel());
}
MapViewController::MapViewController(std::shared_ptr<MapViewModel> model)
@ -49,7 +80,7 @@ MapViewController::MapViewController(std::shared_ptr<MapViewModel> model)
{
}
std::shared_ptr<const IMapRendererContext> MapViewController::getContext() const
std::shared_ptr<IMapRendererContext> MapViewController::getContext() const
{
return context;
}
@ -92,13 +123,11 @@ void MapViewController::update(uint32_t timeDelta)
context->movementAnimation->progress += timeDelta / heroMoveTime;
Point positionFrom = Point(hero->convertToVisitablePos(context->movementAnimation->tileFrom)) * model->getSingleTileSize();
Point positionDest = Point(hero->convertToVisitablePos(context->movementAnimation->tileDest)) * model->getSingleTileSize();
Point positionFrom = Point(hero->convertToVisitablePos(context->movementAnimation->tileFrom)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
Point positionDest = Point(hero->convertToVisitablePos(context->movementAnimation->tileDest)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
Point positionCurr = vstd::lerp(positionFrom, positionDest, context->movementAnimation->progress);
setViewCenter(positionCurr, context->movementAnimation->tileDest.z);
if(context->movementAnimation->progress >= 1.0)
{
setViewCenter(hero->getSightCenter());
@ -107,6 +136,10 @@ void MapViewController::update(uint32_t timeDelta)
context->addObject(context->getObject(context->movementAnimation->target));
context->movementAnimation.reset();
}
else
{
setViewCenter(positionCurr, context->movementAnimation->tileDest.z);
}
}
if(context->teleportAnimation)

View File

@ -42,7 +42,7 @@ private:
public:
explicit MapViewController(std::shared_ptr<MapViewModel> model);
std::shared_ptr<const IMapRendererContext> getContext() const;
std::shared_ptr<IMapRendererContext> getContext() const;
void setViewCenter(const int3 & position);
void setViewCenter(const Point & position, int level);

View File

@ -118,7 +118,7 @@ typedef void (*TColorPutterAlpha)(uint8_t *&ptr, const uint8_t & R, const uint8_
void setDefaultColorKeyPresize(SDL_Surface * surface);
/// helper that will safely set and un-set ClipRect for SDL_Surface
class CClipRectGuard
class CClipRectGuard : boost::noncopyable
{
SDL_Surface * surf;
Rect oldRect;

View File

@ -84,7 +84,7 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
Point offset = tileToPixels(tile);
setLevel(tile.z);
onMapViewMoved(Rect(), tile.z);
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, offset.x, offset.y);
@ -104,7 +104,7 @@ void CQuestMinimap::update()
void CQuestMinimap::iconClicked()
{
if(currentQuest->obj)
adventureInt->centerOn (currentQuest->obj->pos);
adventureInt->centerOnTile(currentQuest->obj->pos);
//moveAdvMapSelection();
}

View File

@ -22,7 +22,6 @@
#include "../battle/BattleInterface.h"
#include "../battle/BattleInterfaceClasses.h"
#include "../adventureMap/CAdvMapInt.h"
#include "../adventureMap/CTerrainRect.h"
#include "../windows/CMessage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../gui/CursorHandler.h"

View File

@ -132,6 +132,11 @@ public:
return *this;
}
bool operator == (const Rect & other)
{
return x == other.x && y == other.y && w == other.w && h == other.h;
}
/// returns true if this rect intersects with another rect
DLL_LINKAGE bool intersectionTest(const Rect & other) const;