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:
parent
58aa5c0427
commit
165f6a0944
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user