1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Moved path rendering to new map renderer

This commit is contained in:
Ivan Savenko 2023-02-15 14:09:27 +02:00
parent 600054e001
commit 21a48e4f0d
5 changed files with 138 additions and 7 deletions

View File

@ -26,6 +26,7 @@
#include "../../lib/TerrainHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/CPathfinder.h"
struct NeighborTilesInfo
{
@ -534,10 +535,98 @@ void MapRendererDebugGrid::renderTile(const IMapRendererContext & context, Canva
}
}
MapRendererPath::MapRendererPath()
: pathNodes(new CAnimation("ADAG"))
{
pathNodes->preload();
}
void MapRendererPath::renderImage(Canvas & target, bool reachableToday, size_t imageIndex)
{
const static size_t unreachableTodayOffset = 25;
if(reachableToday)
target.draw(pathNodes->getImage(imageIndex), Point(0, 0));
else
target.draw(pathNodes->getImage(imageIndex + unreachableTodayOffset), Point(0, 0));
}
void MapRendererPath::renderImageCross(Canvas & target, bool reachableToday, const int3 & curr)
{
renderImage(target, reachableToday, 0);
}
void MapRendererPath::renderImageArrow(Canvas & target, bool reachableToday, const int3 & curr, const int3 & prev, const int3 & next)
{
// Vector directions
// 0 1 2
// |
// 3 - 4 - 5
// |
// 6 7 8
//For example:
// |
// +->
// is (directionToArrowIndex[7][5])
//
const static size_t directionToArrowIndex[9][9] = {
{16, 17, 18, 7, 0, 19, 6, 5, 0 },
{8, 9, 18, 7, 0, 19, 6, 0, 20},
{8, 1, 10, 7, 0, 19, 0, 21, 20},
{24, 17, 18, 15, 0, 0, 6, 5, 4 },
{0, 0, 0, 0, 0, 0, 0, 0, 0 },
{8, 1, 2, 0, 0, 11, 22, 21, 20},
{24, 17, 0, 23, 0, 3, 14, 5, 4 },
{24, 0, 2, 23, 0, 3, 22, 13, 4 },
{0, 1, 2, 23, 0, 3, 22, 21, 12}
};
size_t enterDirection = (curr.x - next.x + 1) + 3 * (curr.y - next.y + 1);
size_t leaveDirection = (prev.x - curr.x + 1) + 3 * (prev.y - curr.y + 1);
size_t imageIndex = directionToArrowIndex[enterDirection][leaveDirection];
renderImage(target, reachableToday, imageIndex);
}
void MapRendererPath::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
{
const auto & functor = [&](const CGPathNode & node)
{
return node.coord == coordinates;
};
const auto * path = context.currentPath();
if(!path)
return;
const auto & iter = boost::range::find_if(path->nodes, functor);
if(iter == path->nodes.end())
return;
bool reachableToday = iter->turns == 0;
if(iter == path->nodes.begin())
renderImageCross(target, reachableToday, iter->coord);
auto next = iter + 1;
auto prev = iter - 1;
// start of path - currentl hero location
if(next == path->nodes.end())
return;
bool pathContinuous = iter->coord.areNeighbours(next->coord) && iter->coord.areNeighbours(prev->coord);
bool embarking = iter->action == CGPathNode::EMBARK || iter->action == CGPathNode::DISEMBARK;
if(pathContinuous && !embarking)
renderImageArrow(target, reachableToday, iter->coord, prev->coord, next->coord);
else
renderImageCross(target, reachableToday, iter->coord);
}
MapRenderer::MapRenderer(const IMapRendererContext & context)
: rendererObjects(context)
{
}
void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
@ -560,6 +649,7 @@ void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & targe
rendererRiver.renderTile(context, target, coordinates);
rendererRoad.renderTile(context, target, coordinates);
rendererObjects.renderTile(context, target, coordinates);
rendererPath.renderTile(context, target, coordinates);
if (!context.isVisible(coordinates))
rendererFow.renderTile(context, target, coordinates);

View File

@ -113,6 +113,19 @@ public:
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererPath
{
std::unique_ptr<CAnimation> pathNodes;
void renderImage(Canvas & target, bool reachableToday, size_t imageIndex);
void renderImageCross(Canvas & target, bool reachableToday, const int3 & curr);
void renderImageArrow(Canvas & target, bool reachableToday, const int3 & curr, const int3 & prev, const int3 & next);
public:
MapRendererPath();
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererDebugGrid
{
public:
@ -127,6 +140,7 @@ class MapRenderer
MapRendererBorder rendererBorder;
MapRendererFow rendererFow;
MapRendererObjects rendererObjects;
MapRendererPath rendererPath;
MapRendererDebugGrid rendererDebugGrid;
public:

View File

@ -18,6 +18,7 @@ class Point;
class ObjectInstanceID;
class CGObjectInstance;
struct TerrainTile;
struct CGPath;
VCMI_LIB_NAMESPACE_END
@ -26,22 +27,38 @@ class IMapRendererContext
public:
virtual ~IMapRendererContext() = default;
using VisibilityMap = std::shared_ptr<const boost::multi_array<ui8, 3>>;
using ObjectsVector = std::vector< ConstTransitivePtr<CGObjectInstance> >;
/// returns dimensions of current map
virtual int3 getMapSize() const = 0;
/// returns true if chosen coordinates exist on map
virtual bool isInMap(const int3 & coordinates) const = 0;
/// returns tile by selected coordinates. Coordinates MUST be valid
virtual const TerrainTile & getMapTile(const int3 & coordinates) const = 0;
/// returns vector of all objects present on current map
virtual ObjectsVector getAllObjects() const = 0;
/// returns specific object by ID, or nullptr if not found
virtual const CGObjectInstance * getObject( ObjectInstanceID objectID ) const = 0;
virtual bool isVisible(const int3 & coordinates) const = 0;
virtual VisibilityMap getVisibilityMap() const = 0;
/// returns path of currently active hero, or nullptr if none
virtual const CGPath * currentPath() const = 0;
/// returns true if specified tile is visible in current context
virtual bool isVisible(const int3 & coordinates) const = 0;
/// returns how long should each frame of animation be visible, in milliseconds
virtual uint32_t getAnimationPeriod() const = 0;
/// returns total animation time since creation of this context
virtual uint32_t getAnimationTime() const = 0;
/// returns size of ouput tile, in pixels. 32x32 for "standard" map, may be smaller for world view mode
virtual Point tileSize() const = 0;
/// if true, map grid should be visible on map
virtual bool showGrid() const = 0;
};

View File

@ -13,6 +13,7 @@
#include "MapRenderer.h"
#include "mapHandler.h"
#include "CAdvMapInt.h"
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
@ -266,9 +267,17 @@ bool MapRendererContext::isVisible(const int3 & coordinates) const
return LOCPLINT->cb->isVisible(coordinates) || settings["session"]["spectate"].Bool();
}
MapRendererContext::VisibilityMap MapRendererContext::getVisibilityMap() const
const CGPath * MapRendererContext::currentPath() const
{
return LOCPLINT->cb->getVisibilityMap();
const auto * hero = adventureInt->curHero();
if(!hero)
return nullptr;
if(!LOCPLINT->paths.hasPath(hero))
return nullptr;
return &LOCPLINT->paths.getPath(hero);
}
uint32_t MapRendererContext::getAnimationPeriod() const

View File

@ -30,8 +30,9 @@ public:
ObjectsVector getAllObjects() const override;
const CGObjectInstance * getObject(ObjectInstanceID objectID) const override;
const CGPath * currentPath() const override;
bool isVisible(const int3 & coordinates) const override;
VisibilityMap getVisibilityMap() const override;
uint32_t getAnimationPeriod() const override;
uint32_t getAnimationTime() const override;