mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Implemented terrain transition animation
This commit is contained in:
@@ -67,6 +67,8 @@ public:
|
|||||||
/// returns animation frame for terrain
|
/// returns animation frame for terrain
|
||||||
virtual size_t terrainImageIndex(size_t groupSize) const = 0;
|
virtual size_t terrainImageIndex(size_t groupSize) const = 0;
|
||||||
|
|
||||||
|
virtual double viewTransitionProgress() const = 0;
|
||||||
|
|
||||||
/// if true, rendered images will be converted to grayscale
|
/// if true, rendered images will be converted to grayscale
|
||||||
virtual bool filterGrayscale() const = 0;
|
virtual bool filterGrayscale() const = 0;
|
||||||
|
|
||||||
|
@@ -139,6 +139,11 @@ size_t MapRendererBaseContext::overlayImageIndex(const int3 & coordinates) const
|
|||||||
return std::numeric_limits<size_t>::max();
|
return std::numeric_limits<size_t>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double MapRendererBaseContext::viewTransitionProgress() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool MapRendererBaseContext::filterGrayscale() const
|
bool MapRendererBaseContext::filterGrayscale() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -246,6 +251,16 @@ bool MapRendererAdventureContext::showBlockable() const
|
|||||||
return settingShowBlockable;
|
return settingShowBlockable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapRendererAdventureTransitionContext::MapRendererAdventureTransitionContext(const MapRendererContextState & viewState)
|
||||||
|
: MapRendererAdventureContext(viewState)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double MapRendererAdventureTransitionContext::viewTransitionProgress() const
|
||||||
|
{
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
MapRendererAdventureFadingContext::MapRendererAdventureFadingContext(const MapRendererContextState & viewState)
|
MapRendererAdventureFadingContext::MapRendererAdventureFadingContext(const MapRendererContextState & viewState)
|
||||||
: MapRendererAdventureContext(viewState)
|
: MapRendererAdventureContext(viewState)
|
||||||
{
|
{
|
||||||
|
@@ -47,6 +47,7 @@ public:
|
|||||||
size_t terrainImageIndex(size_t groupSize) const override;
|
size_t terrainImageIndex(size_t groupSize) const override;
|
||||||
size_t overlayImageIndex(const int3 & coordinates) const override;
|
size_t overlayImageIndex(const int3 & coordinates) const override;
|
||||||
|
|
||||||
|
double viewTransitionProgress() const override;
|
||||||
bool filterGrayscale() const override;
|
bool filterGrayscale() const override;
|
||||||
bool showRoads() const override;
|
bool showRoads() const override;
|
||||||
bool showRivers() const override;
|
bool showRivers() const override;
|
||||||
@@ -79,6 +80,16 @@ public:
|
|||||||
bool showBlockable() const override;
|
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
|
class MapRendererAdventureFadingContext : public MapRendererAdventureContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -30,6 +30,7 @@ MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
|
|||||||
, iconsStorage(new CAnimation("VwSymbol"))
|
, iconsStorage(new CAnimation("VwSymbol"))
|
||||||
, intermediate(new Canvas(Point(32, 32)))
|
, intermediate(new Canvas(Point(32, 32)))
|
||||||
, terrain(new Canvas(model->getCacheDimensionsPixels()))
|
, terrain(new Canvas(model->getCacheDimensionsPixels()))
|
||||||
|
, terrainTransition(new Canvas(model->getPixelsVisibleDimensions()))
|
||||||
{
|
{
|
||||||
iconsStorage->preload();
|
iconsStorage->preload();
|
||||||
for(size_t i = 0; i < iconsStorage->size(); ++i)
|
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;
|
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)
|
void MapViewCache::invalidate(const std::shared_ptr<IMapRendererContext> & context, const ObjectInstanceID & object)
|
||||||
{
|
{
|
||||||
for(size_t cacheY = 0; cacheY < terrainChecksum.shape()[1]; ++cacheY)
|
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)
|
void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context, Canvas & target, bool fullRedraw)
|
||||||
{
|
{
|
||||||
bool mapMoved = (cachedPosition != model->getMapViewCenter());
|
bool mapMoved = (cachedPosition != model->getMapViewCenter());
|
||||||
bool lazyUpdate = !mapMoved && !fullRedraw;
|
bool lazyUpdate = !mapMoved && !fullRedraw && context->viewTransitionProgress() == 0;
|
||||||
|
|
||||||
Rect dimensions = model->getTilesTotalRect();
|
Rect dimensions = model->getTilesTotalRect();
|
||||||
|
|
||||||
@@ -164,6 +154,7 @@ void MapViewCache::render(const std::shared_ptr<IMapRendererContext> & context,
|
|||||||
Rect targetRect = model->getTargetTileArea(tile);
|
Rect targetRect = model->getTargetTileArea(tile);
|
||||||
target.draw(source, targetRect.topLeft());
|
target.draw(source, targetRect.topLeft());
|
||||||
|
|
||||||
|
if (!fullRedraw)
|
||||||
tilesUpToDate[cacheX][cacheY] = true;
|
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();
|
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);
|
explicit MapViewCache(const std::shared_ptr<MapViewModel> & model);
|
||||||
~MapViewCache();
|
~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);
|
void invalidate(const std::shared_ptr<IMapRendererContext> & context, const ObjectInstanceID & object);
|
||||||
|
|
||||||
/// updates internal terrain cache according to provided time delta
|
/// updates internal terrain cache according to provided time delta
|
||||||
@@ -70,4 +70,8 @@ public:
|
|||||||
|
|
||||||
/// renders updated terrain cache onto provided canvas
|
/// renders updated terrain cache onto provided canvas
|
||||||
void render(const std::shared_ptr<IMapRendererContext> & context, Canvas & target, bool fullRedraw);
|
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)
|
// - teleporting ( 250 ms)
|
||||||
static const double fadeOutDuration = 500;
|
static const double fadeOutDuration = 500;
|
||||||
static const double fadeInDuration = 500;
|
static const double fadeInDuration = 500;
|
||||||
//static const double heroTeleportDuration = 250;
|
static const double heroTeleportDuration = 250;
|
||||||
|
|
||||||
//FIXME: remove code duplication?
|
//FIXME: remove code duplication?
|
||||||
|
|
||||||
@@ -140,13 +140,14 @@ void MapViewController::update(uint32_t timeDelta)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(teleportContext)
|
if(teleportContext)
|
||||||
//{
|
{
|
||||||
// teleportContext->progress += timeDelta / heroTeleportDuration;
|
teleportContext->progress += timeDelta / heroTeleportDuration;
|
||||||
// moveFocusToSelection();
|
if(teleportContext->progress >= 1.0)
|
||||||
// if(teleportContext->progress >= 1.0)
|
{
|
||||||
// teleportContext.reset();
|
activateAdventureContext(teleportContext->animationTime);
|
||||||
//}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(fadingOutContext)
|
if(fadingOutContext)
|
||||||
{
|
{
|
||||||
@@ -316,9 +317,8 @@ void MapViewController::onBeforeHeroTeleported(const CGHeroInstance * obj, const
|
|||||||
|
|
||||||
if(isEventVisible(obj, from, dest))
|
if(isEventVisible(obj, from, dest))
|
||||||
{
|
{
|
||||||
// TODO: generate view with old state
|
|
||||||
setViewCenter(obj->getSightCenter());
|
setViewCenter(obj->getSightCenter());
|
||||||
removeObject(obj);
|
view->createTransitionSnapshot(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,16 +326,16 @@ void MapViewController::onAfterHeroTeleported(const CGHeroInstance * obj, const
|
|||||||
{
|
{
|
||||||
assert(!hasOngoingAnimations());
|
assert(!hasOngoingAnimations());
|
||||||
|
|
||||||
if(isEventVisible(obj, from, dest))
|
|
||||||
{
|
|
||||||
// TODO: animation
|
|
||||||
setViewCenter(obj->getSightCenter());
|
|
||||||
addObject(obj);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
removeObject(obj);
|
removeObject(obj);
|
||||||
addObject(obj);
|
addObject(obj);
|
||||||
|
|
||||||
|
if(isEventVisible(obj, from, dest))
|
||||||
|
{
|
||||||
|
teleportContext = std::make_shared<MapRendererAdventureTransitionContext>(*state);
|
||||||
|
teleportContext->animationTime = adventureContext->animationTime;
|
||||||
|
adventureContext = teleportContext;
|
||||||
|
context = teleportContext;
|
||||||
|
setViewCenter(obj->getSightCenter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,6 +395,9 @@ bool MapViewController::hasOngoingAnimations()
|
|||||||
if(fadingInContext)
|
if(fadingInContext)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (teleportContext)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +461,7 @@ void MapViewController::resetContext()
|
|||||||
movementContext.reset();
|
movementContext.reset();
|
||||||
fadingOutContext.reset();
|
fadingOutContext.reset();
|
||||||
fadingInContext.reset();
|
fadingInContext.reset();
|
||||||
|
teleportContext.reset();
|
||||||
worldViewContext.reset();
|
worldViewContext.reset();
|
||||||
spellViewContext.reset();
|
spellViewContext.reset();
|
||||||
puzzleMapContext.reset();
|
puzzleMapContext.reset();
|
||||||
|
@@ -24,6 +24,7 @@ class IMapRendererContext;
|
|||||||
class MapRendererAdventureContext;
|
class MapRendererAdventureContext;
|
||||||
class MapRendererAdventureFadingContext;
|
class MapRendererAdventureFadingContext;
|
||||||
class MapRendererAdventureMovingContext;
|
class MapRendererAdventureMovingContext;
|
||||||
|
class MapRendererAdventureTransitionContext;
|
||||||
class MapRendererWorldViewContext;
|
class MapRendererWorldViewContext;
|
||||||
class MapRendererSpellViewContext;
|
class MapRendererSpellViewContext;
|
||||||
class MapRendererPuzzleMapContext;
|
class MapRendererPuzzleMapContext;
|
||||||
@@ -41,7 +42,7 @@ class MapViewController : public IMapObjectObserver
|
|||||||
// only some are present at any given moment, rest are nullptr's
|
// only some are present at any given moment, rest are nullptr's
|
||||||
std::shared_ptr<MapRendererAdventureContext> adventureContext;
|
std::shared_ptr<MapRendererAdventureContext> adventureContext;
|
||||||
std::shared_ptr<MapRendererAdventureMovingContext> movementContext;
|
std::shared_ptr<MapRendererAdventureMovingContext> movementContext;
|
||||||
//std::shared_ptr<IMapRendererContext> teleportContext;
|
std::shared_ptr<MapRendererAdventureTransitionContext> teleportContext;
|
||||||
std::shared_ptr<MapRendererAdventureFadingContext> fadingOutContext;
|
std::shared_ptr<MapRendererAdventureFadingContext> fadingOutContext;
|
||||||
std::shared_ptr<MapRendererAdventureFadingContext> fadingInContext;
|
std::shared_ptr<MapRendererAdventureFadingContext> fadingInContext;
|
||||||
std::shared_ptr<MapRendererWorldViewContext> worldViewContext;
|
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)
|
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);
|
SDL_SetSurfaceAlphaMod(image.surface, 255 * transparency);
|
||||||
CSDL_Ext::blitSurface(image.surface, image.renderArea, surface, renderArea.topLeft() + pos);
|
CSDL_Ext::blitSurface(image.surface, image.renderArea, surface, renderArea.topLeft() + pos);
|
||||||
SDL_SetSurfaceAlphaMod(image.surface, 255);
|
SDL_SetSurfaceAlphaMod(image.surface, 255);
|
||||||
|
SDL_SetSurfaceBlendMode(image.surface, oldMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::drawScaled(const Canvas & image, const Point & pos, const Point & targetSize)
|
void Canvas::drawScaled(const Canvas & image, const Point & pos, const Point & targetSize)
|
||||||
|
Reference in New Issue
Block a user