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