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

Implemented terrain transition animation

This commit is contained in:
Ivan Savenko 2023-03-01 19:25:51 +02:00
parent 58aa5c0427
commit 165f6a0944
8 changed files with 74 additions and 32 deletions

View File

@ -67,6 +67,8 @@ public:
/// returns animation frame for terrain
virtual size_t terrainImageIndex(size_t groupSize) const = 0;
virtual double viewTransitionProgress() const = 0;
/// if true, rendered images will be converted to grayscale
virtual bool filterGrayscale() const = 0;

View File

@ -139,6 +139,11 @@ size_t MapRendererBaseContext::overlayImageIndex(const int3 & coordinates) const
return std::numeric_limits<size_t>::max();
}
double MapRendererBaseContext::viewTransitionProgress() const
{
return 0;
}
bool MapRendererBaseContext::filterGrayscale() const
{
return false;
@ -246,6 +251,16 @@ bool MapRendererAdventureContext::showBlockable() const
return settingShowBlockable;
}
MapRendererAdventureTransitionContext::MapRendererAdventureTransitionContext(const MapRendererContextState & viewState)
: MapRendererAdventureContext(viewState)
{
}
double MapRendererAdventureTransitionContext::viewTransitionProgress() const
{
return progress;
}
MapRendererAdventureFadingContext::MapRendererAdventureFadingContext(const MapRendererContextState & viewState)
: MapRendererAdventureContext(viewState)
{

View File

@ -47,6 +47,7 @@ public:
size_t terrainImageIndex(size_t groupSize) const override;
size_t overlayImageIndex(const int3 & coordinates) const override;
double viewTransitionProgress() const override;
bool filterGrayscale() const override;
bool showRoads() const override;
bool showRivers() const override;
@ -79,6 +80,16 @@ public:
bool showBlockable() const override;
};
class MapRendererAdventureTransitionContext : public MapRendererAdventureContext
{
public:
double progress = 0;
explicit MapRendererAdventureTransitionContext(const MapRendererContextState & viewState);
double viewTransitionProgress() const override;
};
class MapRendererAdventureFadingContext : public MapRendererAdventureContext
{
public:

View File

@ -30,6 +30,7 @@ MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
, iconsStorage(new CAnimation("VwSymbol"))
, intermediate(new Canvas(Point(32, 32)))
, terrain(new Canvas(model->getCacheDimensionsPixels()))
, terrainTransition(new Canvas(model->getPixelsVisibleDimensions()))
{
iconsStorage->preload();
for(size_t i = 0; i < iconsStorage->size(); ++i)
@ -54,17 +55,6 @@ std::shared_ptr<IImage> MapViewCache::getOverlayImageForTile(const std::shared_p
return nullptr;
}
void MapViewCache::invalidate(const std::shared_ptr<IMapRendererContext> & context, const int3 & tile)
{
int cacheX = (terrainChecksum.shape()[0] + tile.x) % terrainChecksum.shape()[0];
int cacheY = (terrainChecksum.shape()[1] + tile.y) % terrainChecksum.shape()[1];
auto & entry = terrainChecksum[cacheX][cacheY];
if(entry.tileX == tile.x && entry.tileY == tile.y)
entry = TileChecksum{};
}
void MapViewCache::invalidate(const std::shared_ptr<IMapRendererContext> & context, const ObjectInstanceID & object)
{
for(size_t cacheY = 0; cacheY < terrainChecksum.shape()[1]; ++cacheY)
@ -145,7 +135,7 @@ void MapViewCache::update(const std::shared_ptr<IMapRendererContext> & context)
void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context, Canvas & target, bool fullRedraw)
{
bool mapMoved = (cachedPosition != model->getMapViewCenter());
bool lazyUpdate = !mapMoved && !fullRedraw;
bool lazyUpdate = !mapMoved && !fullRedraw && context->viewTransitionProgress() == 0;
Rect dimensions = model->getTilesTotalRect();
@ -164,7 +154,8 @@ void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context,
Rect targetRect = model->getTargetTileArea(tile);
target.draw(source, targetRect.topLeft());
tilesUpToDate[cacheX][cacheY] = true;
if (!fullRedraw)
tilesUpToDate[cacheX][cacheY] = true;
}
}
@ -187,5 +178,14 @@ void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context,
}
}
if (context->viewTransitionProgress() != 0)
target.drawTransparent(*terrainTransition, Point(0,0), 1.0 - context->viewTransitionProgress());
cachedPosition = model->getMapViewCenter();
}
void MapViewCache::createTransitionSnapshot(const std::shared_ptr<IMapRendererContext> & context)
{
update(context);
render(context, *terrainTransition, true);
}

View File

@ -62,7 +62,7 @@ public:
explicit MapViewCache(const std::shared_ptr<MapViewModel> & model);
~MapViewCache();
void invalidate(const std::shared_ptr<IMapRendererContext> & context, const int3 & tile);
/// invalidates cache of specified object
void invalidate(const std::shared_ptr<IMapRendererContext> & context, const ObjectInstanceID & object);
/// updates internal terrain cache according to provided time delta
@ -70,4 +70,8 @@ public:
/// renders updated terrain cache onto provided canvas
void render(const std::shared_ptr<IMapRendererContext> & context, Canvas & target, bool fullRedraw);
/// creates snapshot of current view and stores it into internal canvas
/// used for view transition, e.g. Dimension Door spell or teleporters (Subterra gates / Monolith)
void createTransitionSnapshot(const std::shared_ptr<IMapRendererContext> & context);
};

View File

@ -99,7 +99,7 @@ void MapViewController::update(uint32_t timeDelta)
// - teleporting ( 250 ms)
static const double fadeOutDuration = 500;
static const double fadeInDuration = 500;
//static const double heroTeleportDuration = 250;
static const double heroTeleportDuration = 250;
//FIXME: remove code duplication?
@ -140,13 +140,14 @@ void MapViewController::update(uint32_t timeDelta)
}
}
//if(teleportContext)
//{
// teleportContext->progress += timeDelta / heroTeleportDuration;
// moveFocusToSelection();
// if(teleportContext->progress >= 1.0)
// teleportContext.reset();
//}
if(teleportContext)
{
teleportContext->progress += timeDelta / heroTeleportDuration;
if(teleportContext->progress >= 1.0)
{
activateAdventureContext(teleportContext->animationTime);
}
}
if(fadingOutContext)
{
@ -316,9 +317,8 @@ void MapViewController::onBeforeHeroTeleported(const CGHeroInstance * obj, const
if(isEventVisible(obj, from, dest))
{
// TODO: generate view with old state
setViewCenter(obj->getSightCenter());
removeObject(obj);
view->createTransitionSnapshot(context);
}
}
@ -326,16 +326,16 @@ void MapViewController::onAfterHeroTeleported(const CGHeroInstance * obj, const
{
assert(!hasOngoingAnimations());
removeObject(obj);
addObject(obj);
if(isEventVisible(obj, from, dest))
{
// TODO: animation
teleportContext = std::make_shared<MapRendererAdventureTransitionContext>(*state);
teleportContext->animationTime = adventureContext->animationTime;
adventureContext = teleportContext;
context = teleportContext;
setViewCenter(obj->getSightCenter());
addObject(obj);
}
else
{
removeObject(obj);
addObject(obj);
}
}
@ -395,6 +395,9 @@ bool MapViewController::hasOngoingAnimations()
if(fadingInContext)
return true;
if (teleportContext)
return true;
return false;
}
@ -458,6 +461,7 @@ void MapViewController::resetContext()
movementContext.reset();
fadingOutContext.reset();
fadingInContext.reset();
teleportContext.reset();
worldViewContext.reset();
spellViewContext.reset();
puzzleMapContext.reset();

View File

@ -24,6 +24,7 @@ class IMapRendererContext;
class MapRendererAdventureContext;
class MapRendererAdventureFadingContext;
class MapRendererAdventureMovingContext;
class MapRendererAdventureTransitionContext;
class MapRendererWorldViewContext;
class MapRendererSpellViewContext;
class MapRendererPuzzleMapContext;
@ -41,7 +42,7 @@ class MapViewController : public IMapObjectObserver
// only some are present at any given moment, rest are nullptr's
std::shared_ptr<MapRendererAdventureContext> adventureContext;
std::shared_ptr<MapRendererAdventureMovingContext> movementContext;
//std::shared_ptr<IMapRendererContext> teleportContext;
std::shared_ptr<MapRendererAdventureTransitionContext> teleportContext;
std::shared_ptr<MapRendererAdventureFadingContext> fadingOutContext;
std::shared_ptr<MapRendererAdventureFadingContext> fadingInContext;
std::shared_ptr<MapRendererWorldViewContext> worldViewContext;

View File

@ -84,9 +84,14 @@ void Canvas::draw(const Canvas & image, const Point & pos)
void Canvas::drawTransparent(const Canvas & image, const Point & pos, double transparency)
{
SDL_BlendMode oldMode;
SDL_GetSurfaceBlendMode(image.surface, &oldMode);
SDL_SetSurfaceBlendMode(image.surface, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(image.surface, 255 * transparency);
CSDL_Ext::blitSurface(image.surface, image.renderArea, surface, renderArea.topLeft() + pos);
SDL_SetSurfaceAlphaMod(image.surface, 255);
SDL_SetSurfaceBlendMode(image.surface, oldMode);
}
void Canvas::drawScaled(const Canvas & image, const Point & pos, const Point & targetSize)