mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Implemented basic hero movement animation & object fade-out
This commit is contained in:
parent
4501036a04
commit
7cf00ba87d
@ -53,7 +53,6 @@ set(client_SRCS
|
||||
render/CAnimation.cpp
|
||||
render/CBitmapHandler.cpp
|
||||
render/CDefFile.cpp
|
||||
render/CFadeAnimation.cpp
|
||||
render/Canvas.cpp
|
||||
render/ColorFilter.cpp
|
||||
render/Colors.cpp
|
||||
@ -169,7 +168,6 @@ set(client_HEADERS
|
||||
render/CAnimation.h
|
||||
render/CBitmapHandler.h
|
||||
render/CDefFile.h
|
||||
render/CFadeAnimation.h
|
||||
render/Canvas.h
|
||||
render/ColorFilter.h
|
||||
render/Colors.h
|
||||
|
@ -457,22 +457,10 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
return;
|
||||
}
|
||||
|
||||
adventureInt->centerOn(hero); //actualizing screen pos
|
||||
adventureInt->minimap->redraw();
|
||||
adventureInt->heroList->redraw();
|
||||
|
||||
auto waitFrame = [&]()
|
||||
{
|
||||
int frameNumber = GH.mainFPSmng->getFrameNumber();
|
||||
|
||||
auto unlockPim = vstd::makeUnlockGuard(*pim);
|
||||
while(frameNumber == GH.mainFPSmng->getFrameNumber())
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
||||
};
|
||||
|
||||
//main moving
|
||||
while (CGI->mh->hasActiveAnimations())
|
||||
waitFrame(); //for animation purposes
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
|
||||
//finishing move
|
||||
hero->isStanding = true;
|
||||
|
@ -344,6 +344,8 @@ void ApplyFirstClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
|
||||
CGObjectInstance *obj = gs.getObjInstance(pack.objid);
|
||||
if(CGI->mh)
|
||||
CGI->mh->onObjectFadeOut(obj);
|
||||
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
}
|
||||
void ApplyClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
|
||||
{
|
||||
@ -351,6 +353,7 @@ void ApplyClientNetPackVisitor::visitChangeObjPos(ChangeObjPos & pack)
|
||||
if(CGI->mh)
|
||||
CGI->mh->onObjectFadeIn(obj);
|
||||
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
cl.invalidatePaths();
|
||||
}
|
||||
|
||||
@ -426,6 +429,8 @@ void ApplyFirstClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
|
||||
if(gs.isVisible(o, i->first) || (!cl.getPlayerState(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first))
|
||||
i->second->objectRemoved(o);
|
||||
}
|
||||
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitRemoveObject(RemoveObject & pack)
|
||||
@ -938,7 +943,6 @@ void ApplyClientNetPackVisitor::visitOpenWindow(OpenWindow & pack)
|
||||
callInterfaceIfPresent(cl, obj1->tempOwner, &IGameEventsReceiver::showTavernWindow, obj2);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitCenterView(CenterView & pack)
|
||||
@ -959,6 +963,7 @@ void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack)
|
||||
if(gs.isVisible(obj, i->first))
|
||||
i->second->newObject(obj);
|
||||
}
|
||||
CGI->mh->waitForOngoingAnimations();
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitSetAvailableArtifacts(SetAvailableArtifacts & pack)
|
||||
|
@ -319,7 +319,7 @@ void CAdvMapInt::fsleepWake()
|
||||
void CAdvMapInt::fmoveHero()
|
||||
{
|
||||
const CGHeroInstance *h = curHero();
|
||||
if (!h || !LOCPLINT->paths.hasPath(h) || CGI->mh->hasActiveAnimations())
|
||||
if (!h || !LOCPLINT->paths.hasPath(h) || CGI->mh->hasOngoingAnimations())
|
||||
return;
|
||||
|
||||
LOCPLINT->moveHero(h, LOCPLINT->paths.getPath(h));
|
||||
@ -833,7 +833,7 @@ void CAdvMapInt::keyPressed(const SDL_Keycode & key)
|
||||
if(!h || !isActive())
|
||||
return;
|
||||
|
||||
if (CGI->mh->hasActiveAnimations())
|
||||
if (CGI->mh->hasOngoingAnimations())
|
||||
return;
|
||||
|
||||
if(*direction == Point(0,0))
|
||||
@ -1138,7 +1138,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
|
||||
if(LOCPLINT->paths.hasPath(currentHero) &&
|
||||
LOCPLINT->paths.getPath(currentHero).endPos() == mapPos)//we'll be moving
|
||||
{
|
||||
if(!CGI->mh->hasActiveAnimations())
|
||||
if(!CGI->mh->hasOngoingAnimations())
|
||||
LOCPLINT->moveHero(currentHero, LOCPLINT->paths.getPath(currentHero));
|
||||
return;
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/CFadeAnimation.h"
|
||||
#include "../render/IImage.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
#include "../widgets/TextControls.h"
|
||||
@ -35,9 +34,7 @@
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
|
||||
CTerrainRect::CTerrainRect()
|
||||
: fadeSurface(nullptr)
|
||||
, fadeAnim(std::make_shared<CFadeAnimation>())
|
||||
, curHoveredTile(-1, -1, -1)
|
||||
: curHoveredTile(-1, -1, -1)
|
||||
, isSwiping(false)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||
@ -51,20 +48,14 @@ CTerrainRect::CTerrainRect()
|
||||
renderer = std::make_shared<MapView>( Point(0,0), pos.dimensions() );
|
||||
}
|
||||
|
||||
CTerrainRect::~CTerrainRect()
|
||||
{
|
||||
if(fadeSurface)
|
||||
SDL_FreeSurface(fadeSurface);
|
||||
}
|
||||
|
||||
void CTerrainRect::setViewCenter(const int3 &coordinates)
|
||||
{
|
||||
renderer->setViewCenter(coordinates);
|
||||
renderer->getController()->setViewCenter(coordinates);
|
||||
}
|
||||
|
||||
void CTerrainRect::setViewCenter(const Point & position, int level)
|
||||
{
|
||||
renderer->setViewCenter(position, level);
|
||||
renderer->getController()->setViewCenter(position, level);
|
||||
}
|
||||
|
||||
void CTerrainRect::deactivate()
|
||||
@ -220,30 +211,17 @@ Rect CTerrainRect::visibleTilesArea()
|
||||
|
||||
void CTerrainRect::fadeFromCurrentView()
|
||||
{
|
||||
if (!ADVOPT.screenFading)
|
||||
return;
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
|
||||
if (!fadeSurface)
|
||||
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
|
||||
CSDL_Ext::blitSurface(screen, fadeSurface, Point(0,0));
|
||||
fadeAnim->init(CFadeAnimation::EMode::OUT, fadeSurface);
|
||||
assert(0);//TODO
|
||||
}
|
||||
|
||||
void CTerrainRect::setLevel(int level)
|
||||
{
|
||||
renderer->setViewCenter(renderer->getModel()->getMapViewCenter(), level);
|
||||
renderer->getController()->setViewCenter(renderer->getModel()->getMapViewCenter(), level);
|
||||
}
|
||||
|
||||
void CTerrainRect::moveViewBy(const Point & delta)
|
||||
{
|
||||
renderer->setViewCenter(renderer->getModel()->getMapViewCenter() + delta, getLevel());
|
||||
}
|
||||
|
||||
int3 CTerrainRect::getTileCenter()
|
||||
{
|
||||
return renderer->getModel()->getTileCenter();
|
||||
renderer->getController()->setViewCenter(renderer->getModel()->getMapViewCenter() + delta, getLevel());
|
||||
}
|
||||
|
||||
Point CTerrainRect::getViewCenter()
|
||||
@ -258,5 +236,5 @@ int CTerrainRect::getLevel()
|
||||
|
||||
void CTerrainRect::setTileSize(int sizePixels)
|
||||
{
|
||||
renderer->setTileSize(Point(sizePixels, sizePixels));
|
||||
renderer->getController()->setTileSize(Point(sizePixels, sizePixels));
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
struct CGPath;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class CFadeAnimation;
|
||||
class MapView;
|
||||
|
||||
/// Holds information about which tiles of the terrain are shown/not shown at the screen
|
||||
@ -24,9 +23,6 @@ class CTerrainRect : public CIntObject
|
||||
{
|
||||
std::shared_ptr<MapView> renderer;
|
||||
|
||||
SDL_Surface * fadeSurface;
|
||||
std::shared_ptr<CFadeAnimation> fadeAnim;
|
||||
|
||||
Point swipeInitialViewPos;
|
||||
Point swipeInitialRealPos;
|
||||
bool isSwiping;
|
||||
@ -48,7 +44,6 @@ class CTerrainRect : public CIntObject
|
||||
|
||||
public:
|
||||
CTerrainRect();
|
||||
~CTerrainRect();
|
||||
|
||||
void moveViewBy(const Point & delta);
|
||||
void setViewCenter(const int3 & coordinates);
|
||||
@ -56,7 +51,6 @@ public:
|
||||
void setLevel(int level);
|
||||
void setTileSize(int sizePixels);
|
||||
|
||||
int3 getTileCenter();
|
||||
Point getViewCenter();
|
||||
int getLevel();
|
||||
|
||||
|
@ -182,8 +182,8 @@ void MapRendererRiver::renderTile(const IMapRendererContext & context, Canvas &
|
||||
}
|
||||
}
|
||||
|
||||
MapRendererRoad::MapRendererRoad():
|
||||
storage(VLC->roadTypeHandler->objects.size())
|
||||
MapRendererRoad::MapRendererRoad()
|
||||
: storage(VLC->roadTypeHandler->objects.size())
|
||||
{
|
||||
for(const auto & road : VLC->roadTypeHandler->objects)
|
||||
storage.load(road->getIndex(), road->tilesFilename);
|
||||
@ -191,19 +191,19 @@ MapRendererRoad::MapRendererRoad():
|
||||
|
||||
void MapRendererRoad::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
|
||||
{
|
||||
const int3 coordinatesAbove = coordinates - int3(0,1,0);
|
||||
const int3 coordinatesAbove = coordinates - int3(0, 1, 0);
|
||||
|
||||
if (context.isInMap(coordinatesAbove))
|
||||
if(context.isInMap(coordinatesAbove))
|
||||
{
|
||||
const TerrainTile & mapTileAbove = context.getMapTile(coordinatesAbove);
|
||||
if (mapTileAbove.roadType->getId() != Road::NO_ROAD)
|
||||
if(mapTileAbove.roadType->getId() != Road::NO_ROAD)
|
||||
{
|
||||
int32_t terrainIndex = mapTileAbove.roadType->getIndex();
|
||||
int32_t imageIndex = mapTileAbove.roadDir;
|
||||
int32_t rotationIndex = (mapTileAbove.extTileFlags >> 4) % 4;
|
||||
|
||||
const auto & image = storage.find(terrainIndex, rotationIndex, imageIndex);
|
||||
target.draw(image, Point(0,0), Rect(0, 16, 32, 16));
|
||||
target.draw(image, Point(0, 0), Rect(0, 16, 32, 16));
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ void MapRendererRoad::renderTile(const IMapRendererContext & context, Canvas & t
|
||||
int32_t rotationIndex = (mapTile.extTileFlags >> 4) % 4;
|
||||
|
||||
const auto & image = storage.find(terrainIndex, rotationIndex, imageIndex);
|
||||
target.draw(image, Point(0,16), Rect(0, 0, 32, 16));
|
||||
target.draw(image, Point(0, 16), Rect(0, 0, 32, 16));
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,31 +231,31 @@ size_t MapRendererBorder::getIndexForTile(const IMapRendererContext & context, c
|
||||
|
||||
int3 size = context.getMapSize();
|
||||
|
||||
if (tile.x < -1 || tile.x > size.x || tile.y < -1 || tile.y > size.y)
|
||||
return std::abs(tile.x) % 4 + 4*(std::abs(tile.y) % 4);
|
||||
if(tile.x < -1 || tile.x > size.x || tile.y < -1 || tile.y > size.y)
|
||||
return std::abs(tile.x) % 4 + 4 * (std::abs(tile.y) % 4);
|
||||
|
||||
if (tile.x == -1 && tile.y == -1)
|
||||
if(tile.x == -1 && tile.y == -1)
|
||||
return 16;
|
||||
|
||||
if (tile.x == size.x && tile.y == -1)
|
||||
if(tile.x == size.x && tile.y == -1)
|
||||
return 17;
|
||||
|
||||
if (tile.x == size.x && tile.y == size.y)
|
||||
if(tile.x == size.x && tile.y == size.y)
|
||||
return 18;
|
||||
|
||||
if (tile.x == -1 && tile.y == size.y)
|
||||
if(tile.x == -1 && tile.y == size.y)
|
||||
return 19;
|
||||
|
||||
if (tile.y == -1)
|
||||
if(tile.y == -1)
|
||||
return 20 + (tile.x % 4);
|
||||
|
||||
if (tile.x == size.x)
|
||||
if(tile.x == size.x)
|
||||
return 24 + (tile.y % 4);
|
||||
|
||||
if (tile.y == size.y)
|
||||
if(tile.y == size.y)
|
||||
return 28 + (tile.x % 4);
|
||||
|
||||
if (tile.x == -1)
|
||||
if(tile.x == -1)
|
||||
return 32 + (tile.y % 4);
|
||||
|
||||
//else - visible area, no renderable border
|
||||
@ -266,7 +266,7 @@ size_t MapRendererBorder::getIndexForTile(const IMapRendererContext & context, c
|
||||
void MapRendererBorder::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
|
||||
{
|
||||
const auto & image = animation->getImage(getIndexForTile(context, coordinates));
|
||||
target.draw(image, Point(0,0));
|
||||
target.draw(image, Point(0, 0));
|
||||
}
|
||||
|
||||
MapRendererFow::MapRendererFow()
|
||||
@ -278,7 +278,7 @@ MapRendererFow::MapRendererFow()
|
||||
|
||||
static const std::vector<int> rotations = {22, 15, 2, 13, 12, 16, 28, 17, 20, 19, 7, 24, 26, 25, 30, 32, 27};
|
||||
|
||||
size_t size = fogOfWarPartialHide->size(0);//group size after next rotation
|
||||
size_t size = fogOfWarPartialHide->size(0); //group size after next rotation
|
||||
|
||||
for(const int rotation : rotations)
|
||||
{
|
||||
@ -295,8 +295,8 @@ void MapRendererFow::renderTile(const IMapRendererContext & context, Canvas & ta
|
||||
|
||||
const NeighborTilesInfo neighborInfo(context, coordinates);
|
||||
|
||||
int retBitmapID = neighborInfo.getBitmapID();// >=0 -> partial hide, <0 - full hide
|
||||
if (retBitmapID < 0)
|
||||
int retBitmapID = neighborInfo.getBitmapID(); // >=0 -> partial hide, <0 - full hide
|
||||
if(retBitmapID < 0)
|
||||
{
|
||||
// generate a number that is predefined for each tile,
|
||||
// but appears random to break visible pattern in large areas of fow
|
||||
@ -304,15 +304,15 @@ void MapRendererFow::renderTile(const IMapRendererContext & context, Canvas & ta
|
||||
size_t pseudorandomNumber = ((coordinates.x * 997) ^ (coordinates.y * 1009)) / 101;
|
||||
size_t imageIndex = pseudorandomNumber % fogOfWarFullHide->size();
|
||||
|
||||
target.draw(fogOfWarFullHide->getImage(imageIndex), Point(0,0));
|
||||
target.draw(fogOfWarFullHide->getImage(imageIndex), Point(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
target.draw(fogOfWarPartialHide->getImage(retBitmapID), Point(0,0));
|
||||
target.draw(fogOfWarPartialHide->getImage(retBitmapID), Point(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const CGObjectInstance* obj)
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const CGObjectInstance * obj)
|
||||
{
|
||||
const auto & info = obj->appearance;
|
||||
|
||||
@ -333,36 +333,26 @@ std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const CGObjectInsta
|
||||
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getAnimation(const std::string & filename, bool generateMovementGroups)
|
||||
{
|
||||
if (animations.count(filename))
|
||||
if(animations.count(filename))
|
||||
return animations[filename];
|
||||
|
||||
auto ret = std::make_shared<CAnimation>(filename);
|
||||
animations[filename] = ret;
|
||||
ret->preload();
|
||||
|
||||
if (generateMovementGroups)
|
||||
if(generateMovementGroups)
|
||||
{
|
||||
ret->createFlippedGroup(1,13);
|
||||
ret->createFlippedGroup(2,14);
|
||||
ret->createFlippedGroup(3,15);
|
||||
ret->createFlippedGroup(1, 13);
|
||||
ret->createFlippedGroup(2, 14);
|
||||
ret->createFlippedGroup(3, 15);
|
||||
|
||||
ret->createFlippedGroup(6,10);
|
||||
ret->createFlippedGroup(7,11);
|
||||
ret->createFlippedGroup(8,12);
|
||||
ret->createFlippedGroup(6, 10);
|
||||
ret->createFlippedGroup(7, 11);
|
||||
ret->createFlippedGroup(8, 12);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MapRendererObjects::MapRendererObjects(const IMapRendererContext & context)
|
||||
{
|
||||
auto mapSize = context.getMapSize();
|
||||
|
||||
objects.resize(boost::extents[mapSize.z][mapSize.x][mapSize.y]);
|
||||
|
||||
for(const auto & obj : context.getAllObjects())
|
||||
onObjectInstantAdd(context, obj);
|
||||
}
|
||||
|
||||
std::shared_ptr<CAnimation> MapRendererObjects::getFlagAnimation(const CGObjectInstance* obj)
|
||||
{
|
||||
//TODO: relocate to config file?
|
||||
@ -401,7 +391,7 @@ std::shared_ptr<IImage> MapRendererObjects::getImage(const IMapRendererContext &
|
||||
if(!animation)
|
||||
return nullptr;
|
||||
|
||||
size_t groupIndex = getAnimationGroup(context, obj);
|
||||
size_t groupIndex = context.objectGroupIndex(obj->id);
|
||||
|
||||
if(animation->size(groupIndex) == 0)
|
||||
return nullptr;
|
||||
@ -412,52 +402,37 @@ std::shared_ptr<IImage> MapRendererObjects::getImage(const IMapRendererContext &
|
||||
return animation->getImage(frameIndex, groupIndex);
|
||||
}
|
||||
|
||||
size_t MapRendererObjects::getAnimationGroup(const IMapRendererContext & context, const CGObjectInstance * obj) const
|
||||
{
|
||||
// TODO
|
||||
//static const std::vector<size_t> moveGroups = {99, 10, 5, 6, 7, 8, 9, 12, 11};
|
||||
static const std::vector<size_t> idleGroups = {99, 13, 0, 1, 2, 3, 4, 15, 14};
|
||||
|
||||
if(obj->ID == Obj::HERO)
|
||||
{
|
||||
const auto * hero = dynamic_cast<const CGHeroInstance *>(obj);
|
||||
return idleGroups[hero->moveDir];
|
||||
}
|
||||
|
||||
if(obj->ID == Obj::BOAT)
|
||||
{
|
||||
const auto * boat = dynamic_cast<const CGBoat *>(obj);
|
||||
return idleGroups[boat->direction];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MapRendererObjects::renderImage(Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage>& image)
|
||||
void MapRendererObjects::renderImage(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage>& image)
|
||||
{
|
||||
if(!image)
|
||||
return;
|
||||
|
||||
uint8_t transparency = static_cast<uint8_t>(std::round(255 * context.objectTransparency(object->id)));
|
||||
|
||||
if (transparency == 0)
|
||||
return;
|
||||
|
||||
image->setAlpha(transparency);
|
||||
image->setFlagColor(object->tempOwner);
|
||||
|
||||
int3 offsetTiles(object->getPosition() - coordinates);
|
||||
Point offsetPixels = context.objectImageOffset(object->id, coordinates);
|
||||
|
||||
Point offsetPixels(offsetTiles.x * 32, offsetTiles.y * 32);
|
||||
Point imagePos = image->dimensions() - offsetPixels - Point(32, 32);
|
||||
Point tileDimensions(32, 32);
|
||||
|
||||
target.draw(image, Point(0, 0), Rect(imagePos, tileDimensions));
|
||||
if ( offsetPixels.x < image->dimensions().x && offsetPixels.y < image->dimensions().y)
|
||||
{
|
||||
Point imagePos = image->dimensions() - offsetPixels - Point(32, 32);
|
||||
target.draw(image, Point(0, 0), Rect(imagePos, Point(32,32)));
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererObjects::renderObject(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance* instance)
|
||||
{
|
||||
renderImage(target, coordinates, instance, getImage(context, instance, getAnimation(instance)));
|
||||
renderImage(target, coordinates, instance, getImage(context, instance, getFlagAnimation(instance)));
|
||||
renderImage(context, target, coordinates, instance, getImage(context, instance, getAnimation(instance)));
|
||||
renderImage(context, target, coordinates, instance, getImage(context, instance, getFlagAnimation(instance)));
|
||||
}
|
||||
|
||||
void MapRendererObjects::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
|
||||
{
|
||||
for(const auto & objectID : objects[coordinates.z][coordinates.x][coordinates.y])
|
||||
for(const auto & objectID : context.getObjects(coordinates))
|
||||
{
|
||||
const auto * objectInstance = context.getObject(objectID);
|
||||
|
||||
@ -472,61 +447,6 @@ void MapRendererObjects::renderTile(const IMapRendererContext & context, Canvas
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererObjects::onObjectInstantAdd(const IMapRendererContext & context, const CGObjectInstance * obj)
|
||||
{
|
||||
if(!obj)
|
||||
return;
|
||||
|
||||
if(obj->ID == Obj::HERO && dynamic_cast<const CGHeroInstance *>(obj)->inTownGarrison)
|
||||
return;
|
||||
|
||||
if(obj->ID == Obj::BOAT && dynamic_cast<const CGBoat *>(obj)->hero)
|
||||
return;
|
||||
|
||||
std::shared_ptr<CAnimation> animation = getAnimation(obj);
|
||||
|
||||
//no animation at all, e.g. Event
|
||||
if(!animation)
|
||||
return;
|
||||
|
||||
//empty animation. Illegal?
|
||||
assert(animation->size(0) > 0);
|
||||
if(animation->size(0) == 0)
|
||||
return;
|
||||
|
||||
auto image = animation->getImage(0, 0);
|
||||
|
||||
int imageWidthTiles = (image->width() + 31) / 32;
|
||||
int imageHeightTiles = (image->height() + 31) / 32;
|
||||
|
||||
int objectWidth = std::min(obj->getWidth(), imageWidthTiles);
|
||||
int objectHeight = std::min(obj->getHeight(), imageHeightTiles);
|
||||
|
||||
for(int fx = 0; fx < objectWidth; ++fx)
|
||||
{
|
||||
for(int fy = 0; fy < objectHeight; ++fy)
|
||||
{
|
||||
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
|
||||
|
||||
if(context.isInMap(currTile) && obj->coveringAt(currTile.x, currTile.y))
|
||||
{
|
||||
auto & container = objects[currTile.z][currTile.x][currTile.y];
|
||||
|
||||
container.push_back(obj->id);
|
||||
boost::range::sort(container, MapObjectsSorter(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererObjects::onObjectInstantRemove(const IMapRendererContext & context, const CGObjectInstance * object)
|
||||
{
|
||||
for(int z = 0; z < context.getMapSize().z; z++)
|
||||
for(int x = 0; x < context.getMapSize().x; x++)
|
||||
for(int y = 0; y < context.getMapSize().y; y++)
|
||||
vstd::erase(objects[z][x][y], object->id);
|
||||
}
|
||||
|
||||
void MapRendererDebugGrid::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
|
||||
{
|
||||
if(context.showGrid())
|
||||
@ -625,14 +545,9 @@ void MapRendererPath::renderTile(const IMapRendererContext & context, Canvas & t
|
||||
renderImageCross(target, reachableToday, iter->coord);
|
||||
}
|
||||
|
||||
MapRenderer::MapRenderer(const IMapRendererContext & context)
|
||||
: rendererObjects(context)
|
||||
{
|
||||
}
|
||||
|
||||
void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates)
|
||||
{
|
||||
if (!context.isInMap(coordinates))
|
||||
if(!context.isInMap(coordinates))
|
||||
{
|
||||
rendererBorder.renderTile(context, target, coordinates);
|
||||
return;
|
||||
@ -640,7 +555,7 @@ void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & targe
|
||||
|
||||
const NeighborTilesInfo neighborInfo(context, coordinates);
|
||||
|
||||
if (neighborInfo.areAllHidden())
|
||||
if(neighborInfo.areAllHidden())
|
||||
{
|
||||
rendererFow.renderTile(context, target, coordinates);
|
||||
}
|
||||
@ -652,8 +567,8 @@ void MapRenderer::renderTile(const IMapRendererContext & context, Canvas & targe
|
||||
rendererObjects.renderTile(context, target, coordinates);
|
||||
rendererPath.renderTile(context, target, coordinates);
|
||||
|
||||
if (!context.isVisible(coordinates))
|
||||
if(!context.isVisible(coordinates))
|
||||
rendererFow.renderTile(context, target, coordinates);
|
||||
}
|
||||
rendererDebugGrid.renderTile(context, target,coordinates);
|
||||
rendererDebugGrid.renderTile(context, target, coordinates);
|
||||
}
|
||||
|
@ -72,12 +72,8 @@ public:
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
};
|
||||
|
||||
class MapRendererObjects : public IMapObjectObserver
|
||||
class MapRendererObjects
|
||||
{
|
||||
using MapObject = ObjectInstanceID;
|
||||
using MapTile = std::vector<MapObject>;
|
||||
|
||||
boost::multi_array<MapTile, 3> objects;
|
||||
std::map<std::string, std::shared_ptr<CAnimation>> animations;
|
||||
|
||||
std::shared_ptr<CAnimation> getFlagAnimation(const CGObjectInstance * obj);
|
||||
@ -85,17 +81,12 @@ class MapRendererObjects : public IMapObjectObserver
|
||||
std::shared_ptr<CAnimation> getAnimation(const std::string & filename, bool generateMovementGroups);
|
||||
|
||||
std::shared_ptr<IImage> getImage(const IMapRendererContext & context, const CGObjectInstance * obj, const std::shared_ptr<CAnimation> & animation) const;
|
||||
size_t getAnimationGroup(const IMapRendererContext & context, const CGObjectInstance * obj) const;
|
||||
|
||||
void renderImage(Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage> & image);
|
||||
void renderImage(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * object, const std::shared_ptr<IImage> & image);
|
||||
void renderObject(const IMapRendererContext & context, Canvas & target, const int3 & coordinates, const CGObjectInstance * obj);
|
||||
|
||||
public:
|
||||
explicit MapRendererObjects(const IMapRendererContext & context);
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
|
||||
void onObjectInstantAdd(const IMapRendererContext & context, const CGObjectInstance * object) final override;
|
||||
void onObjectInstantRemove(const IMapRendererContext & context, const CGObjectInstance * object) final override;
|
||||
};
|
||||
|
||||
class MapRendererBorder
|
||||
@ -150,7 +141,5 @@ class MapRenderer
|
||||
MapRendererDebugGrid rendererDebugGrid;
|
||||
|
||||
public:
|
||||
explicit MapRenderer(const IMapRendererContext & context);
|
||||
|
||||
void renderTile(const IMapRendererContext & context, Canvas & target, const int3 & coordinates);
|
||||
};
|
||||
|
@ -15,9 +15,9 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class int3;
|
||||
class Point;
|
||||
class ObjectInstanceID;
|
||||
class CGObjectInstance;
|
||||
class CGHeroInstance;
|
||||
class ObjectInstanceID;
|
||||
struct TerrainTile;
|
||||
struct CGPath;
|
||||
|
||||
@ -26,9 +26,10 @@ VCMI_LIB_NAMESPACE_END
|
||||
class IMapRendererContext
|
||||
{
|
||||
public:
|
||||
virtual ~IMapRendererContext() = default;
|
||||
using MapObject = ObjectInstanceID;
|
||||
using MapObjectsList = std::vector<MapObject>;
|
||||
|
||||
using ObjectsVector = std::vector<ConstTransitivePtr<CGObjectInstance>>;
|
||||
virtual ~IMapRendererContext() = default;
|
||||
|
||||
/// returns dimensions of current map
|
||||
virtual int3 getMapSize() const = 0;
|
||||
@ -39,8 +40,8 @@ public:
|
||||
/// returns tile by selected coordinates. Coordinates MUST be valid
|
||||
virtual const TerrainTile & getMapTile(const int3 & coordinates) const = 0;
|
||||
|
||||
/// returns vector of all objects present on current map
|
||||
virtual ObjectsVector getAllObjects() const = 0;
|
||||
/// returns all objects visible on specified tile
|
||||
virtual const MapObjectsList & getObjects(const int3 & coordinates) const = 0;
|
||||
|
||||
/// returns specific object by ID, or nullptr if not found
|
||||
virtual const CGObjectInstance * getObject(ObjectInstanceID objectID) const = 0;
|
||||
@ -51,6 +52,12 @@ public:
|
||||
/// returns true if specified tile is visible in current context
|
||||
virtual bool isVisible(const int3 & coordinates) const = 0;
|
||||
|
||||
virtual size_t objectGroupIndex(ObjectInstanceID objectID) const = 0;
|
||||
virtual Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const = 0;
|
||||
|
||||
/// returns object animation transparency. IF set to 0, object will not be visible
|
||||
virtual double objectTransparency(ObjectInstanceID objectID) const = 0;
|
||||
|
||||
/// returns how long should each frame of animation be visible, in milliseconds
|
||||
virtual uint32_t getAnimationPeriod() const = 0;
|
||||
|
||||
@ -70,24 +77,26 @@ public:
|
||||
IMapObjectObserver();
|
||||
virtual ~IMapObjectObserver();
|
||||
|
||||
virtual bool hasOngoingAnimations() = 0;
|
||||
|
||||
/// Plays fade-in animation and adds object to map
|
||||
virtual void onObjectFadeIn(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
virtual void onObjectFadeIn(const CGObjectInstance * obj) {}
|
||||
|
||||
/// Plays fade-out animation and removed object from map
|
||||
virtual void onObjectFadeOut(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
virtual void onObjectFadeOut(const CGObjectInstance * obj) {}
|
||||
|
||||
/// Adds object to map instantly, with no animation
|
||||
virtual void onObjectInstantAdd(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
virtual void onObjectInstantAdd(const CGObjectInstance * obj) {}
|
||||
|
||||
/// Removes object from map instantly, with no animation
|
||||
virtual void onObjectInstantRemove(const IMapRendererContext & context, const CGObjectInstance * obj) {}
|
||||
virtual void onObjectInstantRemove(const CGObjectInstance * obj) {}
|
||||
|
||||
/// Perform hero teleportation animation with terrain fade animation
|
||||
virtual void onHeroTeleported(const IMapRendererContext & context, const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
virtual void onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
|
||||
/// Perform hero movement animation, moving hero across terrain
|
||||
virtual void onHeroMoved(const IMapRendererContext & context, const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
virtual void onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
|
||||
/// Instantly rotates hero to face destination tile
|
||||
virtual void onHeroRotated(const IMapRendererContext & context, const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
virtual void onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest) {}
|
||||
};
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "StdInc.h"
|
||||
#include "MapView.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "MapRenderer.h"
|
||||
#include "mapHandler.h"
|
||||
#include "CAdvMapInt.h"
|
||||
@ -20,7 +22,6 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/CFadeAnimation.h"
|
||||
#include "../render/Canvas.h"
|
||||
#include "../render/Colors.h"
|
||||
#include "../render/Graphics.h"
|
||||
@ -41,51 +42,45 @@
|
||||
#include "../../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
|
||||
MapCache::~MapCache() = default;
|
||||
MapViewCache::~MapViewCache() = default;
|
||||
|
||||
MapCache::MapCache(const std::shared_ptr<MapViewModel> & model)
|
||||
MapViewCache::MapViewCache(const std::shared_ptr<MapViewModel> & model)
|
||||
: model(model)
|
||||
, context(new MapRendererContext())
|
||||
, mapRenderer(new MapRenderer(*context))
|
||||
, mapRenderer(new MapRenderer())
|
||||
, terrain(new Canvas(model->getCacheDimensionsPixels()))
|
||||
{
|
||||
terrain = std::make_unique<Canvas>(model->getCacheDimensionsPixels());
|
||||
}
|
||||
|
||||
Canvas MapCache::getTile(const int3 & coordinates)
|
||||
Canvas MapViewCache::getTile(const int3 & coordinates)
|
||||
{
|
||||
return Canvas(*terrain, model->getCacheTileArea(coordinates));
|
||||
}
|
||||
|
||||
void MapCache::updateTile(const int3 & coordinates)
|
||||
void MapViewCache::updateTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates)
|
||||
{
|
||||
Canvas target = getTile(coordinates);
|
||||
|
||||
mapRenderer->renderTile(*context, target, coordinates);
|
||||
}
|
||||
|
||||
void MapCache::update(uint32_t timeDelta)
|
||||
void MapViewCache::update(const std::shared_ptr<MapRendererContext> & context)
|
||||
{
|
||||
context->advanceAnimations(timeDelta);
|
||||
context->setTileSize(model->getSingleTileSize());
|
||||
|
||||
Rect dimensions = model->getTilesTotalRect();
|
||||
|
||||
for(int y = dimensions.top(); y < dimensions.bottom(); ++y)
|
||||
for(int x = dimensions.left(); x < dimensions.right(); ++x)
|
||||
updateTile({x, y, model->getLevel()});
|
||||
updateTile(context, {x, y, model->getLevel()});
|
||||
}
|
||||
|
||||
void MapCache::render(Canvas & target)
|
||||
void MapViewCache::render(Canvas & target)
|
||||
{
|
||||
update(GH.mainFPSmng->getElapsedMilliseconds());
|
||||
|
||||
Rect dimensions = model->getTilesTotalRect();
|
||||
|
||||
for(int y = dimensions.top(); y < dimensions.bottom(); ++y)
|
||||
{
|
||||
for(int x = dimensions.left(); x < dimensions.right(); ++x)
|
||||
{
|
||||
int3 tile( x,y,model->getLevel());
|
||||
int3 tile(x, y, model->getLevel());
|
||||
Canvas source = getTile(tile);
|
||||
Rect targetRect = model->getTargetTileArea(tile);
|
||||
target.draw(source, targetRect.topLeft());
|
||||
@ -98,8 +93,8 @@ std::shared_ptr<MapViewModel> MapView::createModel(const Point & dimensions) con
|
||||
auto result = std::make_shared<MapViewModel>();
|
||||
|
||||
result->setLevel(0);
|
||||
result->setTileSize(Point(32,32));
|
||||
result->setViewCenter(Point(0,0));
|
||||
result->setTileSize(Point(32, 32));
|
||||
result->setViewCenter(Point(0, 0));
|
||||
result->setViewDimensions(dimensions);
|
||||
|
||||
return result;
|
||||
@ -107,12 +102,13 @@ std::shared_ptr<MapViewModel> MapView::createModel(const Point & dimensions) con
|
||||
|
||||
MapView::MapView(const Point & offset, const Point & dimensions)
|
||||
: model(createModel(dimensions))
|
||||
, tilesCache(new MapCache(model))
|
||||
, context(new MapRendererContext())
|
||||
, controller(new MapViewController(context, model))
|
||||
, tilesCache(new MapViewCache(model))
|
||||
{
|
||||
pos += offset;
|
||||
pos.w = dimensions.x;
|
||||
pos.h = dimensions.y;
|
||||
|
||||
}
|
||||
|
||||
void MapView::show(SDL_Surface * to)
|
||||
@ -122,6 +118,8 @@ void MapView::show(SDL_Surface * to)
|
||||
|
||||
CSDL_Ext::CClipRectGuard guard(to, pos);
|
||||
|
||||
controller->update(GH.mainFPSmng->getElapsedMilliseconds());
|
||||
tilesCache->update(context);
|
||||
tilesCache->render(targetClipped);
|
||||
}
|
||||
|
||||
@ -130,11 +128,6 @@ void MapView::showAll(SDL_Surface * to)
|
||||
show(to);
|
||||
}
|
||||
|
||||
void MapRendererContext::advanceAnimations(uint32_t ms)
|
||||
{
|
||||
animationTime += ms;
|
||||
}
|
||||
|
||||
int3 MapRendererContext::getMapSize() const
|
||||
{
|
||||
return LOCPLINT->cb->getMapSize();
|
||||
@ -150,11 +143,6 @@ const TerrainTile & MapRendererContext::getMapTile(const int3 & coordinates) con
|
||||
return CGI->mh->getMap()->getTile(coordinates);
|
||||
}
|
||||
|
||||
MapRendererContext::ObjectsVector MapRendererContext::getAllObjects() const
|
||||
{
|
||||
return CGI->mh->getMap()->objects;
|
||||
}
|
||||
|
||||
const CGObjectInstance * MapRendererContext::getObject(ObjectInstanceID objectID) const
|
||||
{
|
||||
return CGI->mh->getMap()->objects.at(objectID.getNum());
|
||||
@ -165,11 +153,6 @@ bool MapRendererContext::isVisible(const int3 & coordinates) const
|
||||
return LOCPLINT->cb->isVisible(coordinates) || settings["session"]["spectate"].Bool();
|
||||
}
|
||||
|
||||
void MapRendererContext::setTileSize(const Point & dimensions)
|
||||
{
|
||||
tileSize = dimensions;
|
||||
}
|
||||
|
||||
const CGPath * MapRendererContext::currentPath() const
|
||||
{
|
||||
const auto * hero = adventureInt->curHero();
|
||||
@ -208,19 +191,19 @@ bool MapRendererContext::showGrid() const
|
||||
return true; // settings["session"]["showGrid"].Bool();
|
||||
}
|
||||
|
||||
void MapView::setViewCenter(const int3 & position)
|
||||
void MapViewController::setViewCenter(const int3 & position)
|
||||
{
|
||||
model->setViewCenter(Point(position.x, position.y) * model->getSingleTileSize());
|
||||
model->setLevel(position.z);
|
||||
}
|
||||
|
||||
void MapView::setViewCenter(const Point & position, int level)
|
||||
void MapViewController::setViewCenter(const Point & position, int level)
|
||||
{
|
||||
model->setViewCenter(position);
|
||||
model->setLevel(level);
|
||||
}
|
||||
|
||||
void MapView::setTileSize(const Point & tileSize)
|
||||
void MapViewController::setTileSize(const Point & tileSize)
|
||||
{
|
||||
model->setTileSize(tileSize);
|
||||
}
|
||||
@ -290,11 +273,6 @@ Rect MapViewModel::getTilesTotalRect() const
|
||||
);
|
||||
}
|
||||
|
||||
int3 MapViewModel::getTileCenter() const
|
||||
{
|
||||
return getTileAtPoint(getMapViewCenter());
|
||||
}
|
||||
|
||||
int3 MapViewModel::getTileAtPoint(const Point & position) const
|
||||
{
|
||||
Point topLeftOffset = getMapViewCenter() - getPixelsVisibleDimensions() / 2;
|
||||
@ -335,8 +313,259 @@ Rect MapViewModel::getTargetTileArea(const int3 & coordinates) const
|
||||
Point tilePosAbsolute = Point(coordinates) * tileSize;
|
||||
Point tilePosRelative = tilePosAbsolute - topLeftOffset;
|
||||
|
||||
return {
|
||||
tilePosRelative,
|
||||
tileSize
|
||||
};
|
||||
return Rect(tilePosRelative, tileSize);
|
||||
}
|
||||
|
||||
MapRendererContext::MapRendererContext()
|
||||
{
|
||||
auto mapSize = getMapSize();
|
||||
|
||||
objects.resize(boost::extents[mapSize.z][mapSize.x][mapSize.y]);
|
||||
|
||||
for(const auto & obj : CGI->mh->getMap()->objects)
|
||||
addObject(obj);
|
||||
}
|
||||
|
||||
void MapRendererContext::addObject(const CGObjectInstance * obj)
|
||||
{
|
||||
if(!obj)
|
||||
return;
|
||||
|
||||
for(int fx = 0; fx < obj->getWidth(); ++fx)
|
||||
{
|
||||
for(int fy = 0; fy < obj->getHeight(); ++fy)
|
||||
{
|
||||
int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
|
||||
|
||||
if(isInMap(currTile) && obj->coveringAt(currTile.x, currTile.y))
|
||||
{
|
||||
auto & container = objects[currTile.z][currTile.x][currTile.y];
|
||||
|
||||
container.push_back(obj->id);
|
||||
boost::range::sort(container, MapObjectsSorter(*this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererContext::addMovingObject(const CGObjectInstance * object, const int3 & tileFrom, const int3 & tileDest)
|
||||
{
|
||||
int xFrom = std::min(tileFrom.x, tileDest.x) - object->getWidth();
|
||||
int xDest = std::max(tileFrom.x, tileDest.x);
|
||||
int yFrom = std::min(tileFrom.y, tileDest.y) - object->getHeight();
|
||||
int yDest = std::max(tileFrom.y, tileDest.y);
|
||||
|
||||
for(int x = xFrom; x <= xDest; ++x)
|
||||
{
|
||||
for(int y = yFrom; y <= yDest; ++y)
|
||||
{
|
||||
int3 currTile(x, y, object->pos.z);
|
||||
|
||||
if(isInMap(currTile))
|
||||
{
|
||||
auto & container = objects[currTile.z][currTile.x][currTile.y];
|
||||
|
||||
container.push_back(object->id);
|
||||
boost::range::sort(container, MapObjectsSorter(*this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapRendererContext::removeObject(const CGObjectInstance * object)
|
||||
{
|
||||
for(int z = 0; z < getMapSize().z; z++)
|
||||
for(int x = 0; x < getMapSize().x; x++)
|
||||
for(int y = 0; y < getMapSize().y; y++)
|
||||
vstd::erase(objects[z][x][y], object->id);
|
||||
}
|
||||
|
||||
const MapRendererContext::MapObjectsList & MapRendererContext::getObjects(const int3 & coordinates) const
|
||||
{
|
||||
assert(isInMap(coordinates));
|
||||
return objects[coordinates.z][coordinates.x][coordinates.y];
|
||||
}
|
||||
|
||||
size_t MapRendererContext::objectGroupIndex(ObjectInstanceID objectID) const
|
||||
{
|
||||
const CGObjectInstance * obj = getObject(objectID);
|
||||
// TODO
|
||||
static const std::vector<size_t> moveGroups = {99, 10, 5, 6, 7, 8, 9, 12, 11};
|
||||
static const std::vector<size_t> idleGroups = {99, 13, 0, 1, 2, 3, 4, 15, 14};
|
||||
|
||||
if(obj->ID == Obj::HERO)
|
||||
{
|
||||
const auto * hero = dynamic_cast<const CGHeroInstance *>(obj);
|
||||
if (movementAnimation && movementAnimation->target == objectID)
|
||||
return moveGroups[hero->moveDir];
|
||||
return idleGroups[hero->moveDir];
|
||||
}
|
||||
|
||||
if(obj->ID == Obj::BOAT)
|
||||
{
|
||||
const auto * boat = dynamic_cast<const CGBoat *>(obj);
|
||||
if (movementAnimation && movementAnimation->target == objectID)
|
||||
return moveGroups[boat->direction];
|
||||
return idleGroups[boat->direction];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Point MapRendererContext::objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const
|
||||
{
|
||||
if (movementAnimation && movementAnimation->target == objectID)
|
||||
{
|
||||
int3 offsetTilesFrom = movementAnimation->tileFrom - coordinates;
|
||||
int3 offsetTilesDest = movementAnimation->tileDest - coordinates;
|
||||
|
||||
Point offsetPixelsFrom = Point(offsetTilesFrom) * Point(32,32);
|
||||
Point offsetPixelsDest = Point(offsetTilesDest) * Point(32,32);
|
||||
|
||||
Point result = vstd::lerp(offsetPixelsFrom, offsetPixelsDest, movementAnimation->progress);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const CGObjectInstance * object = getObject(objectID);
|
||||
int3 offsetTiles(object->getPosition() - coordinates);
|
||||
return Point(offsetTiles) * Point(32, 32);
|
||||
}
|
||||
|
||||
double MapRendererContext::objectTransparency(ObjectInstanceID objectID) const
|
||||
{
|
||||
if (fadeOutAnimation && objectID == fadeOutAnimation->target)
|
||||
return 1.0 - fadeOutAnimation->progress;
|
||||
|
||||
if (fadeInAnimation && objectID == fadeInAnimation->target)
|
||||
return fadeInAnimation->progress;
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
MapViewController::MapViewController(std::shared_ptr<MapRendererContext> context, std::shared_ptr<MapViewModel> model)
|
||||
: context(std::move(context))
|
||||
, model(std::move(model))
|
||||
{
|
||||
}
|
||||
|
||||
void MapViewController::update(uint32_t timeDelta)
|
||||
{
|
||||
static const double fadeOutDuration = 1.0;
|
||||
static const double fadeInDuration = 1.0;
|
||||
static const double heroMoveDuration = 1.0;
|
||||
static const double heroTeleportDuration = 1.0;
|
||||
|
||||
//FIXME: remove code duplication?
|
||||
|
||||
if (context->movementAnimation)
|
||||
{
|
||||
context->movementAnimation->progress += heroMoveDuration * timeDelta / 1000;
|
||||
|
||||
Point positionFrom = Point(context->movementAnimation->tileFrom) * model->getSingleTileSize();
|
||||
Point positionDest = Point(context->movementAnimation->tileDest) * model->getSingleTileSize();
|
||||
|
||||
Point positionCurr = vstd::lerp(positionFrom, positionDest, context->movementAnimation->progress);
|
||||
|
||||
setViewCenter(positionCurr, context->movementAnimation->tileDest.z);
|
||||
|
||||
if (context->movementAnimation->progress >= 1.0)
|
||||
{
|
||||
setViewCenter(context->movementAnimation->tileDest);
|
||||
|
||||
context->removeObject(context->getObject(context->movementAnimation->target));
|
||||
context->addObject(context->getObject(context->movementAnimation->target));
|
||||
context->movementAnimation.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (context->teleportAnimation)
|
||||
{
|
||||
context->teleportAnimation->progress += heroTeleportDuration * timeDelta / 1000;
|
||||
if (context->teleportAnimation->progress >= 1.0)
|
||||
context->teleportAnimation.reset();
|
||||
}
|
||||
|
||||
if (context->fadeOutAnimation)
|
||||
{
|
||||
context->fadeOutAnimation->progress += fadeOutDuration * timeDelta / 1000;
|
||||
if (context->fadeOutAnimation->progress >= 1.0)
|
||||
{
|
||||
context->removeObject(context->getObject(context->fadeOutAnimation->target));
|
||||
context->fadeOutAnimation.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (context->fadeInAnimation)
|
||||
{
|
||||
context->fadeInAnimation->progress += fadeInDuration * timeDelta / 1000;
|
||||
if (context->fadeInAnimation->progress >= 1.0)
|
||||
context->fadeInAnimation.reset();
|
||||
}
|
||||
|
||||
context->animationTime += timeDelta;
|
||||
context->tileSize =model->getSingleTileSize();
|
||||
}
|
||||
|
||||
void MapViewController::onObjectFadeIn(const CGObjectInstance * obj)
|
||||
{
|
||||
assert(!context->fadeInAnimation);
|
||||
context->fadeInAnimation = FadingAnimationState{obj->id, 0.0};
|
||||
context->addObject(obj);
|
||||
}
|
||||
|
||||
void MapViewController::onObjectFadeOut(const CGObjectInstance * obj)
|
||||
{
|
||||
assert(!context->fadeOutAnimation);
|
||||
context->fadeOutAnimation = FadingAnimationState{obj->id, 0.0};
|
||||
}
|
||||
|
||||
void MapViewController::onObjectInstantAdd(const CGObjectInstance * obj)
|
||||
{
|
||||
context->addObject(obj);
|
||||
};
|
||||
|
||||
void MapViewController::onObjectInstantRemove(const CGObjectInstance * obj)
|
||||
{
|
||||
context->removeObject(obj);
|
||||
};
|
||||
|
||||
void MapViewController::onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||
{
|
||||
assert(!context->teleportAnimation);
|
||||
context->teleportAnimation = HeroAnimationState{ obj->id, from, dest, 0.0 };
|
||||
}
|
||||
|
||||
void MapViewController::onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||
{
|
||||
assert(!context->movementAnimation);
|
||||
context->removeObject(obj);
|
||||
context->addMovingObject(obj, from, dest);
|
||||
context->movementAnimation = HeroAnimationState{ obj->id, from, dest, 0.0 };
|
||||
}
|
||||
|
||||
void MapViewController::onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
std::shared_ptr<MapViewController> MapView::getController()
|
||||
{
|
||||
return controller;
|
||||
}
|
||||
|
||||
bool MapViewController::hasOngoingAnimations()
|
||||
{
|
||||
if(context->movementAnimation)
|
||||
return true;
|
||||
|
||||
if(context->teleportAnimation)
|
||||
return true;
|
||||
|
||||
if(context->fadeOutAnimation)
|
||||
return true;
|
||||
|
||||
if(context->fadeInAnimation)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -9,37 +9,65 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../gui/CIntObject.h"
|
||||
|
||||
#include "MapRendererContext.h"
|
||||
#include "../gui/CIntObject.h"
|
||||
#include "../lib/int3.h"
|
||||
|
||||
class Canvas;
|
||||
class MapRenderer;
|
||||
class MapViewController;
|
||||
|
||||
struct HeroAnimationState
|
||||
{
|
||||
ObjectInstanceID target;
|
||||
int3 tileFrom;
|
||||
int3 tileDest;
|
||||
double progress;
|
||||
};
|
||||
|
||||
struct FadingAnimationState
|
||||
{
|
||||
ObjectInstanceID target;
|
||||
double progress;
|
||||
};
|
||||
|
||||
class MapRendererContext : public IMapRendererContext
|
||||
{
|
||||
friend class MapViewController;
|
||||
|
||||
boost::multi_array<MapObjectsList, 3> objects;
|
||||
|
||||
Point tileSize = Point(32, 32);
|
||||
uint32_t animationTime = 0;
|
||||
|
||||
boost::optional<HeroAnimationState> movementAnimation;
|
||||
boost::optional<HeroAnimationState> teleportAnimation;
|
||||
|
||||
boost::optional<FadingAnimationState> fadeOutAnimation;
|
||||
boost::optional<FadingAnimationState> fadeInAnimation;
|
||||
|
||||
public:
|
||||
void advanceAnimations(uint32_t ms);
|
||||
void setTileSize(const Point & dimensions);
|
||||
MapRendererContext();
|
||||
|
||||
int3 getMapSize() const override;
|
||||
bool isInMap(const int3 & coordinates) const override;
|
||||
const TerrainTile & getMapTile(const int3 & coordinates) const override;
|
||||
|
||||
ObjectsVector getAllObjects() const override;
|
||||
const CGObjectInstance * getObject(ObjectInstanceID objectID) const override;
|
||||
|
||||
const CGPath * currentPath() const override;
|
||||
void addObject(const CGObjectInstance * object);
|
||||
void addMovingObject(const CGObjectInstance * object, const int3 & tileFrom, const int3 & tileDest);
|
||||
void removeObject(const CGObjectInstance * object);
|
||||
|
||||
int3 getMapSize() const final;
|
||||
bool isInMap(const int3 & coordinates) const final;
|
||||
bool isVisible(const int3 & coordinates) const override;
|
||||
|
||||
const TerrainTile & getMapTile(const int3 & coordinates) const override;
|
||||
const MapObjectsList & getObjects(const int3 & coordinates) const override;
|
||||
const CGObjectInstance * getObject(ObjectInstanceID objectID) const override;
|
||||
const CGPath * currentPath() const override;
|
||||
|
||||
size_t objectGroupIndex(ObjectInstanceID objectID) const override;
|
||||
Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const override;
|
||||
double objectTransparency(ObjectInstanceID objectID) const override;
|
||||
uint32_t getAnimationPeriod() const override;
|
||||
uint32_t getAnimationTime() const override;
|
||||
Point getTileSize() const override;
|
||||
|
||||
bool showGrid() const override;
|
||||
};
|
||||
|
||||
@ -81,50 +109,79 @@ public:
|
||||
/// returns area covered by specified tile in target view
|
||||
Rect getTargetTileArea(const int3 & coordinates) const;
|
||||
|
||||
int getLevel() const;
|
||||
int3 getTileCenter() const;
|
||||
|
||||
/// returns tile under specified position in target view
|
||||
int3 getTileAtPoint(const Point & position) const;
|
||||
|
||||
/// returns currently visible map level
|
||||
int getLevel() const;
|
||||
};
|
||||
|
||||
class MapCache
|
||||
/// Class responsible for rendering of entire map view
|
||||
/// uses rendering parameters provided by owner class
|
||||
class MapViewCache
|
||||
{
|
||||
std::unique_ptr<Canvas> terrain;
|
||||
std::shared_ptr<MapViewModel> model;
|
||||
|
||||
std::unique_ptr<MapRendererContext> context;
|
||||
std::unique_ptr<Canvas> terrain;
|
||||
std::unique_ptr<MapRenderer> mapRenderer;
|
||||
|
||||
Canvas getTile(const int3 & coordinates);
|
||||
void updateTile(const int3 & coordinates);
|
||||
void updateTile(const std::shared_ptr<MapRendererContext> & context, const int3 & coordinates);
|
||||
|
||||
public:
|
||||
explicit MapCache(const std::shared_ptr<MapViewModel> & model);
|
||||
~MapCache();
|
||||
explicit MapViewCache(const std::shared_ptr<MapViewModel> & model);
|
||||
~MapViewCache();
|
||||
|
||||
void update(uint32_t timeDelta);
|
||||
/// updates internal terrain cache according to provided time delta
|
||||
void update(const std::shared_ptr<MapRendererContext> & context);
|
||||
|
||||
/// renders updated terrain cache onto provided canvas
|
||||
void render(Canvas & target);
|
||||
};
|
||||
|
||||
/// Class responsible for updating view state,
|
||||
/// such as its position and any animations
|
||||
class MapViewController : public IMapObjectObserver
|
||||
{
|
||||
std::shared_ptr<MapRendererContext> context;
|
||||
std::shared_ptr<MapViewModel> model;
|
||||
|
||||
private:
|
||||
// IMapObjectObserver impl
|
||||
bool hasOngoingAnimations() override;
|
||||
void onObjectFadeIn(const CGObjectInstance * obj) override;
|
||||
void onObjectFadeOut(const CGObjectInstance * obj) override;
|
||||
void onObjectInstantAdd(const CGObjectInstance * obj) override;
|
||||
void onObjectInstantRemove(const CGObjectInstance * obj) override;
|
||||
void onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
|
||||
void onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
|
||||
void onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest) override;
|
||||
|
||||
public:
|
||||
MapViewController(std::shared_ptr<MapRendererContext> context, std::shared_ptr<MapViewModel> model);
|
||||
|
||||
void setViewCenter(const int3 & position);
|
||||
void setViewCenter(const Point & position, int level);
|
||||
void setTileSize(const Point & tileSize);
|
||||
void update(uint32_t timeDelta);
|
||||
};
|
||||
|
||||
/// Main map rendering class that mostly acts as container for component classes
|
||||
class MapView : public CIntObject
|
||||
{
|
||||
std::shared_ptr<MapViewModel> model;
|
||||
std::unique_ptr<MapCache> tilesCache;
|
||||
std::shared_ptr<MapRendererContext> context;
|
||||
std::unique_ptr<MapViewCache> tilesCache;
|
||||
std::shared_ptr<MapViewController> controller;
|
||||
|
||||
std::shared_ptr<MapViewModel> createModel(const Point & dimensions) const;
|
||||
|
||||
public:
|
||||
std::shared_ptr<const MapViewModel> getModel() const;
|
||||
std::shared_ptr<MapViewController> getController();
|
||||
|
||||
MapView(const Point & offset, const Point & dimensions);
|
||||
|
||||
void setViewCenter(const int3 & position);
|
||||
void setViewCenter(const Point & position, int level);
|
||||
void setTileSize(const Point & tileSize);
|
||||
|
||||
void moveHero();
|
||||
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "MapView.h"
|
||||
|
||||
#include "../render/CAnimation.h"
|
||||
#include "../render/CFadeAnimation.h"
|
||||
#include "../render/Colors.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
@ -27,6 +26,7 @@
|
||||
|
||||
#include "../../CCallback.h"
|
||||
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
@ -476,10 +476,24 @@ bool CMapHandler::hideObject(const CGObjectInstance * obj, bool fadeout)
|
||||
}
|
||||
*/
|
||||
|
||||
bool CMapHandler::hasActiveAnimations()
|
||||
bool CMapHandler::hasOngoingAnimations()
|
||||
{
|
||||
return false; // !fadeAnims.empty(); // don't allow movement during fade animation
|
||||
for (auto * observer : observers)
|
||||
if (observer->hasOngoingAnimations())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CMapHandler::waitForOngoingAnimations()
|
||||
{
|
||||
while (CGI->mh->hasOngoingAnimations())
|
||||
{
|
||||
auto unlockPim = vstd::makeUnlockGuard(*CPlayerInterface::pim);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void CMapHandler::updateWater() //shift colors in palettes of water tiles
|
||||
{
|
||||
@ -600,26 +614,6 @@ bool CMapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObj
|
||||
return false;
|
||||
}
|
||||
|
||||
TerrainTileObject::TerrainTileObject(const CGObjectInstance * obj_, Rect rect_, bool visitablePos)
|
||||
: obj(obj_),
|
||||
rect(rect_),
|
||||
fadeAnimKey(-1)
|
||||
{
|
||||
// We store information about ambient sound is here because object might disappear while sound is updating
|
||||
if(obj->getAmbientSound())
|
||||
{
|
||||
// All tiles of static objects are sound sources. E.g Volcanos and special terrains
|
||||
// For visitable object only their visitable tile is sound source
|
||||
if(!CCS->soundh->ambientCheckVisitable() || !obj->isVisitable() || visitablePos)
|
||||
ambientSound = obj->getAmbientSound();
|
||||
}
|
||||
}
|
||||
|
||||
TerrainTileObject::~TerrainTileObject()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CMapHandler::CMapHandler(const CMap * map)
|
||||
: map(map)
|
||||
{
|
||||
@ -652,45 +646,47 @@ std::vector<std::string> CMapHandler::getAmbientSounds(const int3 & tile)
|
||||
|
||||
void CMapHandler::onObjectFadeIn(const CGObjectInstance * obj)
|
||||
{
|
||||
onObjectInstantAdd(obj);
|
||||
for (auto * observer : observers)
|
||||
observer->onObjectFadeIn(obj);
|
||||
}
|
||||
|
||||
void CMapHandler::onObjectFadeOut(const CGObjectInstance * obj)
|
||||
{
|
||||
onObjectInstantRemove(obj);
|
||||
for (auto * observer : observers)
|
||||
observer->onObjectFadeOut(obj);
|
||||
}
|
||||
|
||||
void CMapHandler::onObjectInstantAdd(const CGObjectInstance * obj)
|
||||
{
|
||||
MapRendererContext context;
|
||||
for (auto * observer : observers)
|
||||
observer->onObjectInstantAdd(context, obj);
|
||||
observer->onObjectInstantAdd(obj);
|
||||
}
|
||||
|
||||
void CMapHandler::onObjectInstantRemove(const CGObjectInstance * obj)
|
||||
{
|
||||
MapRendererContext context;
|
||||
for (auto * observer : observers)
|
||||
observer->onObjectInstantRemove(context, obj);
|
||||
observer->onObjectInstantRemove(obj);
|
||||
}
|
||||
|
||||
void CMapHandler::onHeroTeleported(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||
{
|
||||
assert(obj->pos == dest);
|
||||
onObjectInstantRemove(obj);
|
||||
onObjectInstantAdd(obj);
|
||||
for (auto * observer : observers)
|
||||
observer->onHeroTeleported(obj, from, dest);
|
||||
}
|
||||
|
||||
void CMapHandler::onHeroMoved(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||
{
|
||||
assert(obj->pos == dest);
|
||||
onObjectInstantRemove(obj);
|
||||
onObjectInstantAdd(obj);
|
||||
for (auto * observer : observers)
|
||||
observer->onHeroMoved(obj, from, dest);
|
||||
}
|
||||
|
||||
void CMapHandler::onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||
{
|
||||
//TODO
|
||||
assert(obj->pos == from);
|
||||
for (auto * observer : observers)
|
||||
observer->onHeroRotated(obj, from, dest);
|
||||
}
|
||||
|
||||
void CMapHandler::addMapObserver(IMapObjectObserver * object)
|
||||
|
@ -38,7 +38,6 @@ VCMI_LIB_NAMESPACE_END
|
||||
struct SDL_Surface;
|
||||
class CAnimation;
|
||||
class IImage;
|
||||
class CFadeAnimation;
|
||||
class CMapHandler;
|
||||
class IMapObjectObserver;
|
||||
|
||||
@ -63,30 +62,6 @@ enum class EWorldViewIcon
|
||||
RES_CRYSTAL,
|
||||
RES_GEM,
|
||||
RES_GOLD,
|
||||
|
||||
};
|
||||
|
||||
enum class EMapObjectFadingType
|
||||
{
|
||||
NONE,
|
||||
IN,
|
||||
OUT
|
||||
};
|
||||
|
||||
struct TerrainTileObject
|
||||
{
|
||||
const CGObjectInstance *obj;
|
||||
Rect rect;
|
||||
int fadeAnimKey;
|
||||
boost::optional<std::string> ambientSound;
|
||||
|
||||
TerrainTileObject(const CGObjectInstance *obj_, Rect rect_, bool visitablePos = false);
|
||||
~TerrainTileObject();
|
||||
};
|
||||
|
||||
struct TerrainTile2
|
||||
{
|
||||
std::vector<TerrainTileObject> objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
|
||||
};
|
||||
|
||||
class CMapHandler
|
||||
@ -125,7 +100,10 @@ public:
|
||||
bool hasObjectHole(const int3 & pos) const;
|
||||
|
||||
/// determines if the map is ready to handle new hero movement (not available during fading animations)
|
||||
bool hasActiveAnimations();
|
||||
bool hasOngoingAnimations();
|
||||
|
||||
/// blocking wait until all ongoing animatins are over
|
||||
void waitForOngoingAnimations();
|
||||
|
||||
static bool compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b);
|
||||
};
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* CFadeAnimation.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CFadeAnimation.h"
|
||||
|
||||
#include "../renderSDL/SDL_Extensions.h"
|
||||
|
||||
#include <SDL_surface.h>
|
||||
|
||||
float CFadeAnimation::initialCounter() const
|
||||
{
|
||||
if (fadingMode == EMode::OUT)
|
||||
return 1.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void CFadeAnimation::update()
|
||||
{
|
||||
if (!fading)
|
||||
return;
|
||||
|
||||
if (fadingMode == EMode::OUT)
|
||||
fadingCounter -= delta;
|
||||
else
|
||||
fadingCounter += delta;
|
||||
|
||||
if (isFinished())
|
||||
{
|
||||
fading = false;
|
||||
if (shouldFreeSurface)
|
||||
{
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
fadingSurface = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CFadeAnimation::isFinished() const
|
||||
{
|
||||
if (fadingMode == EMode::OUT)
|
||||
return fadingCounter <= 0.0f;
|
||||
return fadingCounter >= 1.0f;
|
||||
}
|
||||
|
||||
CFadeAnimation::CFadeAnimation()
|
||||
: delta(0), fadingSurface(nullptr), fading(false), fadingCounter(0), shouldFreeSurface(false),
|
||||
fadingMode(EMode::NONE)
|
||||
{
|
||||
}
|
||||
|
||||
CFadeAnimation::~CFadeAnimation()
|
||||
{
|
||||
if (fadingSurface && shouldFreeSurface)
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
|
||||
void CFadeAnimation::init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd, float animDelta)
|
||||
{
|
||||
if (fading)
|
||||
{
|
||||
// in that case, immediately finish the previous fade
|
||||
// (alternatively, we could just return here to ignore the new fade request until this one finished (but we'd need to free the passed bitmap to avoid leaks))
|
||||
logGlobal->warn("Tried to init fading animation that is already running.");
|
||||
if (fadingSurface && shouldFreeSurface)
|
||||
SDL_FreeSurface(fadingSurface);
|
||||
}
|
||||
if (animDelta <= 0.0f)
|
||||
{
|
||||
logGlobal->warn("Fade anim: delta should be positive; %f given.", animDelta);
|
||||
animDelta = DEFAULT_DELTA;
|
||||
}
|
||||
|
||||
if (sourceSurface)
|
||||
fadingSurface = sourceSurface;
|
||||
|
||||
delta = animDelta;
|
||||
fadingMode = mode;
|
||||
fadingCounter = initialCounter();
|
||||
fading = true;
|
||||
shouldFreeSurface = freeSurfaceAtEnd;
|
||||
}
|
||||
|
||||
void CFadeAnimation::draw(SDL_Surface * targetSurface, const Point &targetPoint)
|
||||
{
|
||||
if (!fading || !fadingSurface || fadingMode == EMode::NONE)
|
||||
{
|
||||
fading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
CSDL_Ext::setAlpha(fadingSurface, (int)(fadingCounter * 255));
|
||||
CSDL_Ext::blitSurface(fadingSurface, targetSurface, targetPoint); //FIXME
|
||||
CSDL_Ext::setAlpha(fadingSurface, 255);
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* CFadeAnimation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef IN
|
||||
#undef IN
|
||||
#endif
|
||||
|
||||
#ifdef OUT
|
||||
#undef OUT
|
||||
#endif
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
class Point;
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
struct SDL_Surface;
|
||||
|
||||
const float DEFAULT_DELTA = 0.05f;
|
||||
|
||||
class CFadeAnimation
|
||||
{
|
||||
public:
|
||||
enum class EMode
|
||||
{
|
||||
NONE, IN, OUT
|
||||
};
|
||||
private:
|
||||
float delta;
|
||||
SDL_Surface * fadingSurface;
|
||||
bool fading;
|
||||
float fadingCounter;
|
||||
bool shouldFreeSurface;
|
||||
|
||||
float initialCounter() const;
|
||||
bool isFinished() const;
|
||||
public:
|
||||
EMode fadingMode;
|
||||
|
||||
CFadeAnimation();
|
||||
~CFadeAnimation();
|
||||
void init(EMode mode, SDL_Surface * sourceSurface, bool freeSurfaceAtEnd = false, float animDelta = DEFAULT_DELTA);
|
||||
void update();
|
||||
void draw(SDL_Surface * targetSurface, const Point & targetPoint);
|
||||
bool isFading() const { return fading; }
|
||||
};
|
Loading…
Reference in New Issue
Block a user