1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Added basic overlay support for World View mode

This commit is contained in:
Ivan Savenko 2023-02-20 19:56:35 +02:00
parent def1e35836
commit 1c144637c1
5 changed files with 85 additions and 107 deletions

View File

@ -136,6 +136,15 @@ public:
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRendererOverlay
{
std::unique_ptr<CAnimation> iconsStorage;
public:
MapRendererOverlay();
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
};
class MapRenderer
{
MapRendererTerrain rendererTerrain;

View File

@ -67,6 +67,9 @@ public:
// /// returns size of ouput tile, in pixels. 32x32 for "standard" map, may be smaller for world view mode
// virtual Point getTileSize() const = 0;
/// if true, world view overlay will be shown
virtual bool showOverlay() const = 0;
/// if true, map grid should be visible on map
virtual bool showGrid() const = 0;
virtual bool showVisitable() const = 0;

View File

@ -20,6 +20,7 @@
#include "../gui/CGuiHandler.h"
#include "../render/CAnimation.h"
#include "../render/Canvas.h"
#include "../render/IImage.h"
#include "../renderSDL/SDL_Extensions.h"
#include "../../CCallback.h"
@ -33,9 +34,14 @@ MapViewCache::~MapViewCache() = default;
MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
: model(model)
, mapRenderer(new MapRenderer())
, iconsStorage(new CAnimation("VwSymbol"))
, intermediate(new Canvas(Point(32,32)))
, terrain(new Canvas(model->getCacheDimensionsPixels()))
{
iconsStorage->preload();
for (size_t i = 0; i < iconsStorage->size(); ++i)
iconsStorage->getImage(i)->setBlitMode(EImageBlitMode::COLORKEY);
}
Canvas MapViewCache::getTile(const int3 & coordinates)
@ -43,6 +49,45 @@ Canvas MapViewCache::getTile(const int3 & coordinates)
return Canvas(*terrain, model->getCacheTileArea(coordinates));
}
std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates)
{
if (!context->isVisible(coordinates))
return nullptr;
for(const auto & objectID : context->getObjects(coordinates))
{
const auto * object = context->getObject(objectID);
if (!object->visitableAt(coordinates.x, coordinates.y))
continue;
size_t ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * static_cast<size_t>(EWorldViewIcon::ICONS_PER_PLAYER);
if (object->tempOwner.isValidPlayer())
ownerIndex = object->tempOwner.getNum() * static_cast<size_t>(EWorldViewIcon::ICONS_PER_PLAYER);
switch (object->ID)
{
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
case Obj::MONOLITH_ONE_WAY_EXIT:
case Obj::MONOLITH_TWO_WAY:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::TELEPORT));
case Obj::SUBTERRANEAN_GATE:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::GATE));
case Obj::ARTIFACT:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::ARTIFACT));
case Obj::TOWN:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::TOWN));
case Obj::HERO:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::HERO));
case Obj::MINE:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::MINE_WOOD) + object->subID);
case Obj::RESOURCE:
return iconsStorage->getImage(ownerIndex + static_cast<size_t>(EWorldViewIcon::RES_WOOD) + object->subID);
}
}
return nullptr;
}
void MapViewCache::updateTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates)
{
Canvas target = getTile(coordinates);
@ -67,7 +112,7 @@ void MapViewCache::update(const std::shared_ptr<MapRendererContext> & context)
updateTile(context, {x, y, model->getLevel()});
}
void MapViewCache::render(Canvas & target)
void MapViewCache::render(const std::shared_ptr<MapRendererContext> & context, Canvas & target)
{
Rect dimensions = model->getTilesTotalRect();
@ -79,6 +124,17 @@ void MapViewCache::render(Canvas & target)
Canvas source = getTile(tile);
Rect targetRect = model->getTargetTileArea(tile);
target.draw(source, targetRect.topLeft());
if (context->showOverlay())
{
auto overlay = getOverlayImageForTile(context, tile);
if (overlay)
{
Point position = targetRect.center() - overlay->dimensions() / 2;
target.draw(overlay, position);
}
}
}
}
}
@ -115,7 +171,7 @@ void MapView::show(SDL_Surface * to)
controller->update(GH.mainFPSmng->getElapsedMilliseconds());
tilesCache->update(context);
tilesCache->render(targetClipped);
tilesCache->render(context, targetClipped);
}
void MapView::showAll(SDL_Surface * to)
@ -194,6 +250,11 @@ size_t MapRendererContext::terrainImageIndex(size_t groupSize) const
// return Point(32, 32);
//}
bool MapRendererContext::showOverlay() const
{
return worldViewModeActive;
}
bool MapRendererContext::showGrid() const
{
return settings["gameTweaks"]["showGrid"].Bool();
@ -550,7 +611,8 @@ void MapViewController::update(uint32_t timeDelta)
}
context->animationTime += timeDelta;
context->tileSize = Point(32,32); //model->getSingleTileSize();
//context->tileSize = Point(32,32); //model->getSingleTileSize();
context->worldViewModeActive = model->getSingleTileSize() != Point(32,32);
}
void MapViewController::onObjectFadeIn(const CGObjectInstance * obj)

View File

@ -38,7 +38,7 @@ class MapRendererContext : public IMapRendererContext
boost::multi_array<MapObjectsList, 3> objects;
Point tileSize = Point(32, 32);
//Point tileSize = Point(32, 32);
uint32_t animationTime = 0;
boost::optional<HeroAnimationState> movementAnimation;
@ -47,6 +47,8 @@ class MapRendererContext : public IMapRendererContext
boost::optional<FadingAnimationState> fadeOutAnimation;
boost::optional<FadingAnimationState> fadeInAnimation;
bool worldViewModeActive = false;
public:
MapRendererContext();
@ -69,6 +71,8 @@ public:
size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const override;
size_t terrainImageIndex(size_t groupSize) const override;
// Point getTileSize() const override;
bool showOverlay() const override;
bool showGrid() const override;
bool showVisitable() const override;
bool showBlockable() const override;
@ -130,10 +134,12 @@ class MapViewCache
std::unique_ptr<Canvas> intermediate;
std::unique_ptr<MapRenderer> mapRenderer;
std::unique_ptr<CAnimation> iconsStorage;
Canvas getTile(const int3 & coordinates);
void updateTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates);
std::shared_ptr<IImage> getOverlayImageForTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates);
public:
explicit MapViewCache(const std::shared_ptr<MapViewModel> & model);
~MapViewCache();
@ -142,7 +148,7 @@ public:
void update(const std::shared_ptr<MapRendererContext> & context);
/// renders updated terrain cache onto provided canvas
void render(Canvas & target);
void render(const std::shared_ptr<MapRendererContext> &context, Canvas & target);
};
/// Class responsible for updating view state,

View File

@ -22,108 +22,6 @@
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/TerrainHandler.h"
/*
std::shared_ptr<IImage> CMapWorldViewBlitter::objectToIcon(Obj id, si32 subId, PlayerColor owner) const
{
int ownerIndex = 0;
if(owner < PlayerColor::PLAYER_LIMIT)
{
ownerIndex = owner.getNum() * 19;
}
else if (owner == PlayerColor::NEUTRAL)
{
ownerIndex = PlayerColor::PLAYER_LIMIT.getNum() * 19;
}
switch(id)
{
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
case Obj::MONOLITH_ONE_WAY_EXIT:
case Obj::MONOLITH_TWO_WAY:
return info->icons->getImage((int)EWorldViewIcon::TELEPORT);
case Obj::SUBTERRANEAN_GATE:
return info->icons->getImage((int)EWorldViewIcon::GATE);
case Obj::ARTIFACT:
return info->icons->getImage((int)EWorldViewIcon::ARTIFACT);
case Obj::TOWN:
return info->icons->getImage((int)EWorldViewIcon::TOWN + ownerIndex);
case Obj::HERO:
return info->icons->getImage((int)EWorldViewIcon::HERO + ownerIndex);
case Obj::MINE:
return info->icons->getImage((int)EWorldViewIcon::MINE_WOOD + subId + ownerIndex);
case Obj::RESOURCE:
return info->icons->getImage((int)EWorldViewIcon::RES_WOOD + subId + ownerIndex);
}
return std::shared_ptr<IImage>();
}
*/
/*
void CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
{
auto drawIcon = [this,targetSurf](Obj id, si32 subId, PlayerColor owner)
{
auto wvIcon = this->objectToIcon(id, subId, owner);
if(nullptr != wvIcon)
{
// centering icon on the object
Point dest(realPos.x + tileSize / 2 - wvIcon->width() / 2, realPos.y + tileSize / 2 - wvIcon->height() / 2);
wvIcon->draw(targetSurf, dest.x, dest.y);
}
};
auto & objects = tile.objects;
for(auto & object : objects)
{
const CGObjectInstance * obj = object.obj;
if(!obj)
continue;
const bool sameLevel = obj->pos.z == pos.z;
//FIXME: Don't read options in a loop :v
const bool isVisible = settings["session"]["spectate"].Bool() ? true : (*info->visibilityMap)[pos.z][pos.x][pos.y];
const bool isVisitable = obj->visitableAt(pos.x, pos.y);
if(sameLevel && isVisible && isVisitable)
drawIcon(obj->ID, obj->subID, obj->tempOwner);
}
}
*/
/*
void CMapWorldViewBlitter::drawOverlayEx(SDL_Surface * targetSurf)
{
if(nullptr == info->additionalIcons)
return;
const int3 bottomRight = pos + tileCount;
for(const ObjectPosInfo & iconInfo : *(info->additionalIcons))
{
if( iconInfo.pos.z != pos.z)
continue;
if((iconInfo.pos.x < topTile.x) || (iconInfo.pos.y < topTile.y))
continue;
if((iconInfo.pos.x > bottomRight.x) || (iconInfo.pos.y > bottomRight.y))
continue;
realPos.x = initPos.x + (iconInfo.pos.x - topTile.x) * tileSize;
realPos.y = initPos.y + (iconInfo.pos.y - topTile.y) * tileSize;
auto wvIcon = this->objectToIcon(iconInfo.id, iconInfo.subId, iconInfo.owner);
if(nullptr != wvIcon)
{
// centering icon on the object
Point dest(realPos.x + tileSize / 2 - wvIcon->width() / 2, realPos.y + tileSize / 2 - wvIcon->height() / 2);
wvIcon->draw(targetSurf, dest.x, dest.y);
}
}
}
*/
/*
void CMapPuzzleViewBlitter::drawObjects(SDL_Surface * targetSurf, const TerrainTile2 & tile) const
{