mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-29 21:56:54 +02:00
commit
d01ecbba90
@ -29,12 +29,9 @@ static long long pow(long long a, int b)
|
||||
|
||||
CDefHandler::CDefHandler()
|
||||
{
|
||||
notFreeImgs = false;
|
||||
}
|
||||
CDefHandler::~CDefHandler()
|
||||
{
|
||||
if (notFreeImgs)
|
||||
return;
|
||||
for (auto & elem : ourImages)
|
||||
{
|
||||
if (elem.bitmap)
|
||||
@ -44,11 +41,6 @@ CDefHandler::~CDefHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
CDefEssential::~CDefEssential()
|
||||
{
|
||||
for(auto & elem : ourImages)
|
||||
SDL_FreeSurface(elem.bitmap);
|
||||
}
|
||||
|
||||
void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
|
||||
{
|
||||
@ -350,14 +342,6 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Co
|
||||
return ret;
|
||||
}
|
||||
|
||||
CDefEssential * CDefHandler::essentialize()
|
||||
{
|
||||
auto ret = new CDefEssential();
|
||||
ret->ourImages = ourImages;
|
||||
notFreeImgs = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CDefHandler * CDefHandler::giveDef(const std::string & defName)
|
||||
{
|
||||
ResourceID resID(std::string("SPRITES/") + defName, EResType::ANIMATION);
|
||||
@ -369,12 +353,4 @@ CDefHandler * CDefHandler::giveDef(const std::string & defName)
|
||||
nh->openFromMemory(data.get(), defName);
|
||||
return nh;
|
||||
}
|
||||
CDefEssential * CDefHandler::giveDefEss(const std::string & defName)
|
||||
{
|
||||
CDefEssential * ret;
|
||||
CDefHandler * temp = giveDef(defName);
|
||||
ret = temp->essentialize();
|
||||
delete temp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -66,12 +66,6 @@ struct SSpriteDef
|
||||
ui32 TopMargin;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
class CDefEssential //DefHandler with images only
|
||||
{
|
||||
public:
|
||||
std::vector<Cimage> ourImages;
|
||||
~CDefEssential();
|
||||
};
|
||||
|
||||
class CDefHandler
|
||||
{
|
||||
@ -84,20 +78,17 @@ private:
|
||||
int group;
|
||||
} ;
|
||||
std::vector<SEntry> SEntries ;
|
||||
|
||||
void openFromMemory(ui8 * table, const std::string & name);
|
||||
|
||||
void openFromMemory(ui8 * table, const std::string & name);
|
||||
SDL_Surface * getSprite (int SIndex, const ui8 * FDef, const SDL_Color * palette) const;
|
||||
public:
|
||||
int width, height; //width and height
|
||||
std::string defName;
|
||||
std::vector<Cimage> ourImages;
|
||||
bool notFreeImgs;
|
||||
|
||||
CDefHandler();
|
||||
~CDefHandler();
|
||||
|
||||
CDefEssential * essentialize();
|
||||
|
||||
|
||||
static CDefHandler * giveDef(const std::string & defName);
|
||||
static CDefEssential * giveDefEss(const std::string & defName);
|
||||
};
|
||||
|
@ -232,16 +232,10 @@ std::shared_ptr<CAnimation> Graphics::loadHeroFlagAnimation(const std::string &
|
||||
|
||||
for(const auto & rotation : rotations)
|
||||
{
|
||||
const int sourceGroup = rotation.first;
|
||||
const int targetGroup = rotation.second;
|
||||
const int sourceGroup = rotation.first;
|
||||
const int targetGroup = rotation.second;
|
||||
|
||||
for(size_t frame = 0; frame < anim->size(sourceGroup); ++frame)
|
||||
{
|
||||
anim->duplicateImage(sourceGroup, frame, targetGroup);
|
||||
|
||||
IImage * image = anim->getImage(frame, targetGroup);
|
||||
image->verticalFlip();
|
||||
}
|
||||
anim->createFlippedGroup(sourceGroup, targetGroup);
|
||||
}
|
||||
|
||||
return anim;
|
||||
@ -262,15 +256,10 @@ std::shared_ptr<CAnimation> Graphics::loadHeroAnimation(const std::string &name)
|
||||
|
||||
for(const auto & rotation : rotations)
|
||||
{
|
||||
const int sourceGroup = rotation.first;
|
||||
const int targetGroup = rotation.second;
|
||||
const int sourceGroup = rotation.first;
|
||||
const int targetGroup = rotation.second;
|
||||
|
||||
for(size_t frame = 0; frame < anim->size(sourceGroup); ++frame)
|
||||
{
|
||||
anim->duplicateImage(sourceGroup, frame, targetGroup);
|
||||
IImage * image = anim->getImage(frame, targetGroup);
|
||||
image->verticalFlip();
|
||||
}
|
||||
anim->createFlippedGroup(sourceGroup, targetGroup);
|
||||
}
|
||||
|
||||
return anim;
|
||||
|
@ -16,11 +16,11 @@
|
||||
#include "CBattleInterface.h"
|
||||
#include "CCreatureAnimation.h"
|
||||
|
||||
#include "../CDefHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
@ -58,13 +58,13 @@ bool CBattleAnimation::isEarliest(bool perStackConcurrency)
|
||||
{
|
||||
int lowestMoveID = owner->animIDhelper + 5;
|
||||
CBattleStackAnimation * thAnim = dynamic_cast<CBattleStackAnimation *>(this);
|
||||
CSpellEffectAnimation * thSen = dynamic_cast<CSpellEffectAnimation *>(this);
|
||||
CEffectAnimation * thSen = dynamic_cast<CEffectAnimation *>(this);
|
||||
|
||||
for(auto & elem : owner->pendingAnims)
|
||||
{
|
||||
|
||||
CBattleStackAnimation * stAnim = dynamic_cast<CBattleStackAnimation *>(elem.first);
|
||||
CSpellEffectAnimation * sen = dynamic_cast<CSpellEffectAnimation *>(elem.first);
|
||||
CEffectAnimation * sen = dynamic_cast<CEffectAnimation *>(elem.first);
|
||||
if(perStackConcurrency && stAnim && thAnim && stAnim->stack->ID != thAnim->stack->ID)
|
||||
continue;
|
||||
|
||||
@ -171,7 +171,7 @@ bool CDefenceAnimation::init()
|
||||
if(attAnim && attAnim->stack->ID != stack->ID)
|
||||
continue;
|
||||
|
||||
CSpellEffectAnimation * sen = dynamic_cast<CSpellEffectAnimation *>(elem.first);
|
||||
CEffectAnimation * sen = dynamic_cast<CEffectAnimation *>(elem.first);
|
||||
if (sen)
|
||||
continue;
|
||||
|
||||
@ -243,7 +243,7 @@ CCreatureAnim::EAnimType CDefenceAnimation::getMyAnimType()
|
||||
if(killed)
|
||||
return CCreatureAnim::DEATH;
|
||||
|
||||
if (vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||
if(vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||
return CCreatureAnim::DEFENCE;
|
||||
|
||||
return CCreatureAnim::HITTED;
|
||||
@ -270,10 +270,15 @@ void CDefenceAnimation::nextFrame()
|
||||
|
||||
void CDefenceAnimation::endAnim()
|
||||
{
|
||||
if (killed)
|
||||
if(killed)
|
||||
{
|
||||
myAnim->setType(CCreatureAnim::DEAD);
|
||||
}
|
||||
else
|
||||
{
|
||||
myAnim->setType(CCreatureAnim::HOLDING);
|
||||
}
|
||||
|
||||
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
@ -785,13 +790,13 @@ bool CShootingAnimation::init()
|
||||
spi.dx = animSpeed;
|
||||
spi.dy = 0;
|
||||
|
||||
SDL_Surface * img = owner->idToProjectile[spi.creID]->ourImages[0].bitmap;
|
||||
IImage * img = owner->idToProjectile[spi.creID]->getImage(0);
|
||||
|
||||
// Add explosion anim
|
||||
Point animPos(destPos.x - 126 + img->w / 2,
|
||||
destPos.y - 105 + img->h / 2);
|
||||
Point animPos(destPos.x - 126 + img->width() / 2,
|
||||
destPos.y - 105 + img->height() / 2);
|
||||
|
||||
owner->addNewAnim( new CSpellEffectAnimation(owner, catapultDamage ? "SGEXPL.DEF" : "CSGRCK.DEF", animPos.x, animPos.y));
|
||||
owner->addNewAnim( new CEffectAnimation(owner, catapultDamage ? "SGEXPL.DEF" : "CSGRCK.DEF", animPos.x, animPos.y));
|
||||
}
|
||||
|
||||
auto & angles = shooterInfo->animation.missleFrameAngles;
|
||||
@ -801,7 +806,7 @@ bool CShootingAnimation::init()
|
||||
owner->initStackProjectile(shooter);
|
||||
|
||||
// only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used
|
||||
size_t maxFrame = std::min<size_t>(angles.size(), owner->idToProjectile.at(spi.creID)->ourImages.size());
|
||||
size_t maxFrame = std::min<size_t>(angles.size(), owner->idToProjectile.at(spi.creID)->size(0));
|
||||
|
||||
assert(maxFrame > 0);
|
||||
|
||||
@ -872,35 +877,40 @@ void CShootingAnimation::endAnim()
|
||||
delete this;
|
||||
}
|
||||
|
||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx, int _dy, bool _Vflip, bool _alignToBottom)
|
||||
:CBattleAnimation(_owner), effect(_effect), destTile(_destTile), customAnim(""), x(-1), y(-1), dx(_dx), dy(_dy), Vflip(_Vflip), alignToBottom(_alignToBottom)
|
||||
CEffectAnimation::CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip, bool _alignToBottom)
|
||||
: CBattleAnimation(_owner),
|
||||
destTile(BattleHex::INVALID),
|
||||
customAnim(_customAnim),
|
||||
x(_x),
|
||||
y(_y),
|
||||
dx(_dx),
|
||||
dy(_dy),
|
||||
Vflip(_Vflip),
|
||||
alignToBottom(_alignToBottom)
|
||||
{
|
||||
logAnim->debug("Created spell anim for effect #%d", effect);
|
||||
logAnim->debug("Created effect animation %s", customAnim);
|
||||
}
|
||||
|
||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip, bool _alignToBottom)
|
||||
:CBattleAnimation(_owner), effect(-1), destTile(BattleHex::INVALID), customAnim(_customAnim), x(_x), y(_y), dx(_dx), dy(_dy), Vflip(_Vflip), alignToBottom(_alignToBottom)
|
||||
CEffectAnimation::CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip, bool _alignToBottom)
|
||||
: CBattleAnimation(_owner),
|
||||
destTile(_destTile),
|
||||
customAnim(_customAnim),
|
||||
x(-1),
|
||||
y(-1),
|
||||
dx(0),
|
||||
dy(0),
|
||||
Vflip(_Vflip),
|
||||
alignToBottom(_alignToBottom)
|
||||
{
|
||||
logAnim->debug("Created spell anim for %s", customAnim);
|
||||
}
|
||||
|
||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip, bool _alignToBottom)
|
||||
:CBattleAnimation(_owner), effect(-1), destTile(_destTile), customAnim(_customAnim), x(-1), y(-1), dx(0), dy(0), Vflip(_Vflip), alignToBottom(_alignToBottom)
|
||||
{
|
||||
logAnim->debug("Created spell anim for %s", customAnim);
|
||||
logAnim->debug("Created effect animation %s", customAnim);
|
||||
}
|
||||
|
||||
|
||||
bool CSpellEffectAnimation::init()
|
||||
bool CEffectAnimation::init()
|
||||
{
|
||||
if(!isEarliest(true))
|
||||
return false;
|
||||
|
||||
if(customAnim.empty() && effect != ui32(-1) && !graphics->battleACToDef[effect].empty())
|
||||
{
|
||||
customAnim = graphics->battleACToDef[effect][0];
|
||||
}
|
||||
|
||||
if(customAnim.empty())
|
||||
{
|
||||
endAnim();
|
||||
@ -909,97 +919,88 @@ bool CSpellEffectAnimation::init()
|
||||
|
||||
const bool areaEffect = (!destTile.isValid() && x == -1 && y == -1);
|
||||
|
||||
std::shared_ptr<CAnimation> animation = std::make_shared<CAnimation>(customAnim);
|
||||
|
||||
animation->preload();
|
||||
if(Vflip)
|
||||
animation->verticalFlip();
|
||||
|
||||
IImage * first = animation->getImage(0, 0, true);
|
||||
if(!first)
|
||||
{
|
||||
endAnim();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(areaEffect) //f.e. armageddon
|
||||
{
|
||||
CDefHandler * anim = CDefHandler::giveDef(customAnim);
|
||||
|
||||
for(int i=0; i * anim->width < owner->pos.w ; ++i)
|
||||
for(int i=0; i * first->width() < owner->pos.w ; ++i)
|
||||
{
|
||||
for(int j=0; j * anim->height < owner->pos.h ; ++j)
|
||||
for(int j=0; j * first->height() < owner->pos.h ; ++j)
|
||||
{
|
||||
BattleEffect be;
|
||||
be.effectID = ID;
|
||||
be.anim = CDefHandler::giveDef(customAnim);
|
||||
if (Vflip)
|
||||
{
|
||||
for (auto & elem : be.anim->ourImages)
|
||||
{
|
||||
CSDL_Ext::VflipSurf(elem.bitmap);
|
||||
}
|
||||
}
|
||||
be.animation = animation;
|
||||
be.currentFrame = 0;
|
||||
be.maxFrame = be.anim->ourImages.size();
|
||||
be.x = i * anim->width + owner->pos.x;
|
||||
be.y = j * anim->height + owner->pos.y;
|
||||
|
||||
be.x = i * first->width() + owner->pos.x;
|
||||
be.y = j * first->height() + owner->pos.y;
|
||||
be.position = BattleHex::INVALID;
|
||||
|
||||
owner->battleEffects.push_back(be);
|
||||
}
|
||||
}
|
||||
|
||||
delete anim;
|
||||
}
|
||||
else // Effects targeted at a specific creature/hex.
|
||||
{
|
||||
const CStack * destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(destTile, false);
|
||||
Rect & tilePos = owner->bfield[destTile]->pos;
|
||||
BattleEffect be;
|
||||
be.effectID = ID;
|
||||
be.animation = animation;
|
||||
be.currentFrame = 0;
|
||||
|
||||
const CStack* destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(destTile, false);
|
||||
Rect & tilePos = owner->bfield[destTile]->pos;
|
||||
BattleEffect be;
|
||||
be.effectID = ID;
|
||||
be.anim = CDefHandler::giveDef(customAnim);
|
||||
|
||||
if (Vflip)
|
||||
{
|
||||
for (auto & elem : be.anim->ourImages)
|
||||
{
|
||||
CSDL_Ext::VflipSurf(elem.bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
be.currentFrame = 0;
|
||||
be.maxFrame = be.anim->ourImages.size();
|
||||
|
||||
//todo: lightning anim frame count override
|
||||
//todo: lightning anim frame count override
|
||||
|
||||
// if(effect == 1)
|
||||
// be.maxFrame = 3;
|
||||
|
||||
if(x == -1)
|
||||
{
|
||||
be.x = tilePos.x + tilePos.w/2 - be.anim->width/2;
|
||||
}
|
||||
if(x == -1)
|
||||
{
|
||||
be.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
be.x = x;
|
||||
}
|
||||
|
||||
if(y == -1)
|
||||
{
|
||||
if(alignToBottom)
|
||||
be.y = tilePos.y + tilePos.h - first->height();
|
||||
else
|
||||
{
|
||||
be.x = x;
|
||||
}
|
||||
be.y = tilePos.y - first->height()/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
be.y = y;
|
||||
}
|
||||
|
||||
if(y == -1)
|
||||
{
|
||||
if(alignToBottom)
|
||||
be.y = tilePos.y + tilePos.h - be.anim->height;
|
||||
else
|
||||
be.y = tilePos.y - be.anim->height/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
be.y = y;
|
||||
}
|
||||
// Correction for 2-hex creatures.
|
||||
if(destStack != nullptr && destStack->doubleWide())
|
||||
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||
|
||||
// Correction for 2-hex creatures.
|
||||
if (destStack != nullptr && destStack->doubleWide())
|
||||
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||
|
||||
//Indicate if effect should be drawn on top of everything or just on top of the hex
|
||||
be.position = destTile;
|
||||
|
||||
owner->battleEffects.push_back(be);
|
||||
//Indicate if effect should be drawn on top of everything or just on top of the hex
|
||||
be.position = destTile;
|
||||
|
||||
owner->battleEffects.push_back(be);
|
||||
}
|
||||
//battleEffects
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSpellEffectAnimation::nextFrame()
|
||||
void CEffectAnimation::nextFrame()
|
||||
{
|
||||
//notice: there may be more than one effect in owner->battleEffects correcponding to this animation (ie. armageddon)
|
||||
for(auto & elem : owner->battleEffects)
|
||||
@ -1008,7 +1009,7 @@ void CSpellEffectAnimation::nextFrame()
|
||||
{
|
||||
elem.currentFrame += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000;
|
||||
|
||||
if(elem.currentFrame >= elem.maxFrame)
|
||||
if(elem.currentFrame >= elem.animation->size())
|
||||
{
|
||||
endAnim();
|
||||
break;
|
||||
@ -1022,7 +1023,7 @@ void CSpellEffectAnimation::nextFrame()
|
||||
}
|
||||
}
|
||||
|
||||
void CSpellEffectAnimation::endAnim()
|
||||
void CEffectAnimation::endAnim()
|
||||
{
|
||||
CBattleAnimation::endAnim();
|
||||
|
||||
@ -1038,7 +1039,6 @@ void CSpellEffectAnimation::endAnim()
|
||||
|
||||
for(auto & elem : toDel)
|
||||
{
|
||||
delete elem->anim;
|
||||
owner->battleEffects.erase(elem);
|
||||
}
|
||||
|
||||
|
@ -208,16 +208,15 @@ public:
|
||||
void endAnim() override;
|
||||
|
||||
//last two params only for catapult attacks
|
||||
CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest,
|
||||
const CStack * _attacked, bool _catapult = false, int _catapultDmg = 0);
|
||||
CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest,
|
||||
const CStack * _attacked, bool _catapult = false, int _catapultDmg = 0);
|
||||
virtual ~CShootingAnimation(){};
|
||||
};
|
||||
|
||||
/// This class manages a spell effect animation
|
||||
class CSpellEffectAnimation : public CBattleAnimation
|
||||
/// This class manages effect animation
|
||||
class CEffectAnimation : public CBattleAnimation
|
||||
{
|
||||
private:
|
||||
ui32 effect;
|
||||
BattleHex destTile;
|
||||
std::string customAnim;
|
||||
int x, y, dx, dy;
|
||||
@ -228,8 +227,7 @@ public:
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip = false, bool _alignToBottom = false);
|
||||
virtual ~CSpellEffectAnimation(){};
|
||||
CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip = false, bool _alignToBottom = false);
|
||||
virtual ~CEffectAnimation(){};
|
||||
};
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
@ -263,7 +264,10 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
battleImage = hero1->type->heroClass->imageBattleMale;
|
||||
|
||||
attackingHero = new CBattleHero(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this);
|
||||
attackingHero->pos = genRect(attackingHero->dh->ourImages[0].bitmap->h, attackingHero->dh->ourImages[0].bitmap->w, pos.x - 43, pos.y - 19);
|
||||
|
||||
IImage * img = attackingHero->animation->getImage(0, 0, true);
|
||||
if(img)
|
||||
attackingHero->pos = genRect(img->height(), img->width(), pos.x - 43, pos.y - 19);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -278,7 +282,10 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
||||
battleImage = hero2->type->heroClass->imageBattleMale;
|
||||
|
||||
defendingHero = new CBattleHero(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this);
|
||||
defendingHero->pos = genRect(defendingHero->dh->ourImages[0].bitmap->h, defendingHero->dh->ourImages[0].bitmap->w, pos.x + 693, pos.y - 19);
|
||||
|
||||
IImage * img = defendingHero->animation->getImage(0, 0, true);
|
||||
if(img)
|
||||
defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -425,9 +432,6 @@ CBattleInterface::~CBattleInterface()
|
||||
for (auto & elem : creAnims)
|
||||
delete elem.second;
|
||||
|
||||
for (auto & elem : idToProjectile)
|
||||
delete elem.second;
|
||||
|
||||
for (auto & elem : idToObstacle)
|
||||
delete elem.second;
|
||||
|
||||
@ -999,20 +1003,21 @@ void CBattleInterface::newStack(const CStack *stack)
|
||||
|
||||
void CBattleInterface::initStackProjectile(const CStack * stack)
|
||||
{
|
||||
CDefHandler *&projectile = idToProjectile[stack->getCreature()->idNumber];
|
||||
|
||||
const CCreature *creature;//creature whose shots should be loaded
|
||||
if (stack->getCreature()->idNumber == CreatureID::ARROW_TOWERS)
|
||||
const CCreature * creature;//creature whose shots should be loaded
|
||||
if(stack->getCreature()->idNumber == CreatureID::ARROW_TOWERS)
|
||||
creature = CGI->creh->creatures[siegeH->town->town->clientInfo.siegeShooter];
|
||||
else
|
||||
creature = stack->getCreature();
|
||||
|
||||
projectile = CDefHandler::giveDef(creature->animation.projectileImageName);
|
||||
std::shared_ptr<CAnimation> projectile = std::make_shared<CAnimation>(creature->animation.projectileImageName);
|
||||
projectile->preload();
|
||||
|
||||
for (auto & elem : projectile->ourImages) //alpha transforming
|
||||
{
|
||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
||||
}
|
||||
if(projectile->size(1) != 0)
|
||||
logAnim->error("Expected empty group 1 in stack projectile");
|
||||
else
|
||||
projectile->createFlippedGroup(0, 1);
|
||||
|
||||
idToProjectile[stack->getCreature()->idNumber] = projectile;
|
||||
}
|
||||
|
||||
void CBattleInterface::stackRemoved(int stackID)
|
||||
@ -1216,7 +1221,7 @@ void CBattleInterface::stackIsCatapulting(const CatapultAttack & ca)
|
||||
{
|
||||
Point destPos = CClickableHex::getXYUnitAnim(attackInfo.destinationTile, nullptr, this) + Point(99, 120);
|
||||
|
||||
addNewAnim(new CSpellEffectAnimation(this, "SGEXPL.DEF", destPos.x, destPos.y));
|
||||
addNewAnim(new CEffectAnimation(this, "SGEXPL.DEF", destPos.x, destPos.y));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1304,20 +1309,23 @@ void CBattleInterface::spellCast(const BattleSpellCast *sc)
|
||||
|
||||
std::string animToDisplay = spell.animationInfo.selectProjectile(angle);
|
||||
|
||||
if (!animToDisplay.empty())
|
||||
if(!animToDisplay.empty())
|
||||
{
|
||||
//TODO: calculate inside CEffectAnimation
|
||||
std::shared_ptr<CAnimation> tmp = std::make_shared<CAnimation>(animToDisplay);
|
||||
tmp->load(0, 0);
|
||||
IImage * first = tmp->getImage(0, 0);
|
||||
|
||||
//displaying animation
|
||||
CDefEssential *animDef = CDefHandler::giveDefEss(animToDisplay);
|
||||
double diffX = (destcoord.x - srccoord.x)*(destcoord.x - srccoord.x);
|
||||
double diffY = (destcoord.y - srccoord.y)*(destcoord.y - srccoord.y);
|
||||
double distance = sqrt(diffX + diffY);
|
||||
|
||||
int steps = distance / AnimationControls::getSpellEffectSpeed() + 1;
|
||||
int dx = (destcoord.x - srccoord.x - animDef->ourImages[0].bitmap->w)/steps;
|
||||
int dy = (destcoord.y - srccoord.y - animDef->ourImages[0].bitmap->h)/steps;
|
||||
int dx = (destcoord.x - srccoord.x - first->width())/steps;
|
||||
int dy = (destcoord.y - srccoord.y - first->height())/steps;
|
||||
|
||||
delete animDef;
|
||||
addNewAnim(new CSpellEffectAnimation(this, animToDisplay, srccoord.x, srccoord.y, dx, dy, Vflip));
|
||||
addNewAnim(new CEffectAnimation(this, animToDisplay, srccoord.x, srccoord.y, dx, dy, Vflip));
|
||||
}
|
||||
}
|
||||
waitForAnims();
|
||||
@ -1349,8 +1357,8 @@ void CBattleInterface::spellCast(const BattleSpellCast *sc)
|
||||
{
|
||||
Point leftHero = Point(15, 30) + pos;
|
||||
Point rightHero = Point(755, 30) + pos;
|
||||
addNewAnim(new CSpellEffectAnimation(this, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero.x, leftHero.y, 0, 0, false));
|
||||
addNewAnim(new CSpellEffectAnimation(this, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero.x, rightHero.y, 0, 0, false));
|
||||
addNewAnim(new CEffectAnimation(this, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero.x, leftHero.y, 0, 0, false));
|
||||
addNewAnim(new CEffectAnimation(this, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero.x, rightHero.y, 0, 0, false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1413,9 +1421,11 @@ void CBattleInterface::castThisSpell(SpellID spellID)
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::displayEffect(ui32 effect, int destTile)
|
||||
void CBattleInterface::displayEffect(ui32 effect, BattleHex destTile)
|
||||
{
|
||||
addNewAnim(new CSpellEffectAnimation(this, effect, destTile, 0, 0, false));
|
||||
std::string customAnim = graphics->battleACToDef[effect][0];
|
||||
|
||||
addNewAnim(new CEffectAnimation(this, customAnim, destTile));
|
||||
}
|
||||
|
||||
void CBattleInterface::displaySpellAnimation(const CSpell::TAnimation & animation, BattleHex destinationTile)
|
||||
@ -1426,7 +1436,7 @@ void CBattleInterface::displaySpellAnimation(const CSpell::TAnimation & animatio
|
||||
}
|
||||
else
|
||||
{
|
||||
addNewAnim(new CSpellEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||
addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2732,7 +2742,7 @@ void CBattleInterface::obstaclePlaced(const CObstacleInstance & oi)
|
||||
//we assume here that effect graphics have the same size as the usual obstacle image
|
||||
// -> if we know how to blit obstacle, let's blit the effect in the same place
|
||||
Point whereTo = getObstaclePosition(getObstacleImage(oi), oi);
|
||||
addNewAnim(new CSpellEffectAnimation(this, defname, whereTo.x, whereTo.y));
|
||||
addNewAnim(new CEffectAnimation(this, defname, whereTo.x, whereTo.y));
|
||||
|
||||
//TODO we need to wait after playing sound till it's finished, otherwise it overlaps and sounds really bad
|
||||
//CCS->soundh->playSound(sound);
|
||||
@ -3166,23 +3176,18 @@ void CBattleInterface::showProjectiles(SDL_Surface *to)
|
||||
continue; // wait...
|
||||
}
|
||||
|
||||
SDL_Surface *image = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap;
|
||||
size_t group = it->reverse ? 1 : 0;
|
||||
IImage * image = idToProjectile[it->creID]->getImage(it->frameNum, group, true);
|
||||
|
||||
SDL_Rect dst;
|
||||
dst.h = image->h;
|
||||
dst.w = image->w;
|
||||
dst.x = it->x - dst.w / 2;
|
||||
dst.y = it->y - dst.h / 2;
|
||||
if(image)
|
||||
{
|
||||
SDL_Rect dst;
|
||||
dst.h = image->height();
|
||||
dst.w = image->width();
|
||||
dst.x = it->x - dst.w / 2;
|
||||
dst.y = it->y - dst.h / 2;
|
||||
|
||||
if (it->reverse)
|
||||
{
|
||||
SDL_Surface *rev = CSDL_Ext::verticalFlip(image);
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(rev, nullptr, to, &dst);
|
||||
SDL_FreeSurface(rev);
|
||||
}
|
||||
else
|
||||
{
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(image, nullptr, to, &dst);
|
||||
image->draw(to, &dst, nullptr);
|
||||
}
|
||||
|
||||
// Update projectile
|
||||
@ -3200,7 +3205,7 @@ void CBattleInterface::showProjectiles(SDL_Surface *to)
|
||||
it->y = it->catapultInfo->calculateY(it->x);
|
||||
|
||||
++(it->frameNum);
|
||||
it->frameNum %= idToProjectile[it->creID]->ourImages.size();
|
||||
it->frameNum %= idToProjectile[it->creID]->size(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3368,11 +3373,13 @@ void CBattleInterface::showBattleEffects(SDL_Surface *to, const std::vector<cons
|
||||
for (auto & elem : battleEffects)
|
||||
{
|
||||
int currentFrame = floor(elem->currentFrame);
|
||||
currentFrame %= elem->anim->ourImages.size();
|
||||
currentFrame %= elem->animation->size();
|
||||
|
||||
SDL_Surface *bitmapToBlit = elem->anim->ourImages[currentFrame].bitmap;
|
||||
SDL_Rect temp_rect = genRect(bitmapToBlit->h, bitmapToBlit->w, elem->x, elem->y);
|
||||
SDL_BlitSurface(bitmapToBlit, nullptr, to, &temp_rect);
|
||||
IImage * img = elem->animation->getImage(currentFrame);
|
||||
|
||||
SDL_Rect temp_rect = genRect(img->height(), img->width(), elem->x, elem->y);
|
||||
|
||||
img->draw(to, &temp_rect, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ struct BattleHex;
|
||||
struct InfoAboutHero;
|
||||
struct BattleAction;
|
||||
class CBattleGameInterface;
|
||||
class CAnimation;
|
||||
|
||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||
struct StackAttackedInfo
|
||||
@ -67,8 +68,7 @@ struct BattleEffect
|
||||
{
|
||||
int x, y; //position on the screen
|
||||
float currentFrame;
|
||||
int maxFrame;
|
||||
CDefHandler *anim; //animation to display
|
||||
std::shared_ptr<CAnimation> animation;
|
||||
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
||||
BattleHex position; //Indicates if effect which hex the effect is drawn on
|
||||
};
|
||||
@ -120,6 +120,7 @@ class CBattleInterface : public CIntObject
|
||||
};
|
||||
private:
|
||||
SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes;
|
||||
|
||||
CButton *bOptions, *bSurrender, *bFlee, *bAutofight, *bSpell,
|
||||
* bWait, *bDefence, *bConsoleUp, *bConsoleDown, *btactNext, *btactEnd;
|
||||
CBattleConsole *console;
|
||||
@ -128,7 +129,9 @@ private:
|
||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
||||
std::map<int, CCreatureAnimation *> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||
std::map<int, CDefHandler *> idToProjectile; //projectiles of creatures (creatureID, defhandler)
|
||||
|
||||
std::map<int, std::shared_ptr<CAnimation>> idToProjectile;
|
||||
|
||||
std::map<int, CDefHandler *> idToObstacle; //obstacles located on the battlefield
|
||||
std::map<int, SDL_Surface *> idToAbsoluteObstacle; //obstacles located on the battlefield
|
||||
|
||||
@ -340,7 +343,7 @@ public:
|
||||
void spellCast(const BattleSpellCast *sc); //called when a hero casts a spell
|
||||
void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
|
||||
void castThisSpell(SpellID spellID); //called when player has chosen a spell from spellbook
|
||||
void displayEffect(ui32 effect, int destTile); //displays custom effect on the battlefield
|
||||
void displayEffect(ui32 effect, BattleHex destTile); //displays custom effect on the battlefield
|
||||
|
||||
void displaySpellCast(SpellID spellID, BattleHex destinationTile); //displays spell`s cast animation
|
||||
void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
||||
@ -376,7 +379,7 @@ public:
|
||||
|
||||
friend class CBattleResultWindow;
|
||||
friend class CBattleHero;
|
||||
friend class CSpellEffectAnimation;
|
||||
friend class CEffectAnimation;
|
||||
friend class CBattleStackAnimation;
|
||||
friend class CReverseAnimation;
|
||||
friend class CDefenceAnimation;
|
||||
|
@ -13,13 +13,13 @@
|
||||
#include "CBattleInterface.h"
|
||||
|
||||
#include "../CBitmapHandler.h"
|
||||
#include "../CDefHandler.h"
|
||||
#include "../CGameInfo.h"
|
||||
#include "../CMessage.h"
|
||||
#include "../CMusicHandler.h"
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../CVideoHandler.h"
|
||||
#include "../Graphics.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../gui/CCursorHandler.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
@ -129,13 +129,18 @@ CBattleConsole::CBattleConsole() : lastShown(-1), alterTxt(""), whoSetAlter(0)
|
||||
|
||||
void CBattleHero::show(SDL_Surface * to)
|
||||
{
|
||||
IImage * flagFrame = flagAnimation->getImage(flagAnim, 0, true);
|
||||
|
||||
if(!flagFrame)
|
||||
return;
|
||||
|
||||
//animation of flag
|
||||
SDL_Rect temp_rect;
|
||||
if(flip)
|
||||
{
|
||||
temp_rect = genRect(
|
||||
flag->ourImages[flagAnim].bitmap->h,
|
||||
flag->ourImages[flagAnim].bitmap->w,
|
||||
flagFrame->height(),
|
||||
flagFrame->width(),
|
||||
pos.x + 61,
|
||||
pos.y + 39);
|
||||
|
||||
@ -143,28 +148,30 @@ void CBattleHero::show(SDL_Surface * to)
|
||||
else
|
||||
{
|
||||
temp_rect = genRect(
|
||||
flag->ourImages[flagAnim].bitmap->h,
|
||||
flag->ourImages[flagAnim].bitmap->w,
|
||||
flagFrame->height(),
|
||||
flagFrame->width(),
|
||||
pos.x + 72,
|
||||
pos.y + 39);
|
||||
}
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(
|
||||
flag->ourImages[flagAnim].bitmap,
|
||||
nullptr,
|
||||
screen,
|
||||
&temp_rect);
|
||||
|
||||
flagFrame->draw(screen, &temp_rect, nullptr); //FIXME: why screen?
|
||||
|
||||
//animation of hero
|
||||
SDL_Rect rect = pos;
|
||||
CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[currentFrame].bitmap, nullptr, to, &rect);
|
||||
|
||||
if ( ++animCount == 4 )
|
||||
IImage * heroFrame = animation->getImage(currentFrame, phase, true);
|
||||
if(!heroFrame)
|
||||
return;
|
||||
|
||||
heroFrame->draw(to, &rect, nullptr);
|
||||
|
||||
if(++animCount >= 4)
|
||||
{
|
||||
animCount = 0;
|
||||
if ( ++flagAnim >= flag->ourImages.size())
|
||||
if(++flagAnim >= flagAnimation->size(0))
|
||||
flagAnim = 0;
|
||||
|
||||
if ( ++currentFrame >= lastFrame)
|
||||
if(++currentFrame >= lastFrame)
|
||||
switchToNextPhase();
|
||||
}
|
||||
}
|
||||
@ -190,7 +197,13 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
|
||||
if(myOwner->spellDestSelectMode) //we are casting a spell
|
||||
return;
|
||||
|
||||
if(myHero != nullptr && !down && myOwner->myTurn && myOwner->getCurrentPlayerInterface()->cb->battleCanCastSpell(myHero, ECastingMode::HERO_CASTING) == ESpellCastProblem::OK) //check conditions
|
||||
if(boost::logic::indeterminate(down))
|
||||
return;
|
||||
|
||||
if(!myHero || down || !myOwner->myTurn)
|
||||
return;
|
||||
|
||||
if(myOwner->getCurrentPlayerInterface()->cb->battleCanCastSpell(myHero, ECastingMode::HERO_CASTING) == ESpellCastProblem::OK) //check conditions
|
||||
{
|
||||
for(int it=0; it<GameConstants::BFIELD_SIZE; ++it) //do nothing when any hex is hovered - hero's animation overlaps battlefield
|
||||
{
|
||||
@ -205,6 +218,9 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
|
||||
|
||||
void CBattleHero::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(boost::logic::indeterminate(down))
|
||||
return;
|
||||
|
||||
Point windowPosition;
|
||||
windowPosition.x = (!flip) ? myOwner->pos.topLeft().x + 1 : myOwner->pos.topRight().x - 79;
|
||||
windowPosition.y = myOwner->pos.y + 135;
|
||||
@ -220,24 +236,19 @@ void CBattleHero::clickRight(tribool down, bool previousState)
|
||||
|
||||
void CBattleHero::switchToNextPhase()
|
||||
{
|
||||
if (phase != nextPhase)
|
||||
if(phase != nextPhase)
|
||||
{
|
||||
phase = nextPhase;
|
||||
|
||||
//find first and last frames of our animation
|
||||
for (firstFrame = 0;
|
||||
firstFrame < dh->ourImages.size() && dh->ourImages[firstFrame].groupNumber != phase;
|
||||
firstFrame++);
|
||||
firstFrame = 0;
|
||||
|
||||
for (lastFrame = firstFrame;
|
||||
lastFrame < dh->ourImages.size() && dh->ourImages[lastFrame].groupNumber == phase;
|
||||
lastFrame++);
|
||||
lastFrame = animation->size(phase);
|
||||
}
|
||||
|
||||
currentFrame = firstFrame;
|
||||
}
|
||||
|
||||
CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor player, const CGHeroInstance * hero, const CBattleInterface * owner):
|
||||
CBattleHero::CBattleHero(const std::string & animationPath, bool flipG, PlayerColor player, const CGHeroInstance * hero, const CBattleInterface * owner):
|
||||
flip(flipG),
|
||||
myHero(hero),
|
||||
myOwner(owner),
|
||||
@ -246,39 +257,25 @@ CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor pl
|
||||
flagAnim(0),
|
||||
animCount(0)
|
||||
{
|
||||
dh = CDefHandler::giveDef( defName );
|
||||
for(auto & elem : dh->ourImages) //transforming images
|
||||
{
|
||||
if(flip)
|
||||
{
|
||||
SDL_Surface * hlp = CSDL_Ext::verticalFlip(elem.bitmap);
|
||||
SDL_FreeSurface(elem.bitmap);
|
||||
elem.bitmap = hlp;
|
||||
}
|
||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
||||
}
|
||||
animation = std::make_shared<CAnimation>(animationPath);
|
||||
animation->preload();
|
||||
if(flipG)
|
||||
animation->verticalFlip();
|
||||
|
||||
if(flip)
|
||||
flag = CDefHandler::giveDef("CMFLAGR.DEF");
|
||||
flagAnimation = std::make_shared<CAnimation>("CMFLAGR");
|
||||
else
|
||||
flag = CDefHandler::giveDef("CMFLAGL.DEF");
|
||||
flagAnimation = std::make_shared<CAnimation>("CMFLAGL");
|
||||
|
||||
flagAnimation->preload();
|
||||
flagAnimation->playerColored(player);
|
||||
|
||||
//coloring flag and adding transparency
|
||||
for(auto & elem : flag->ourImages)
|
||||
{
|
||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
||||
graphics->blueToPlayersAdv(elem.bitmap, player);
|
||||
}
|
||||
addUsedEvents(LCLICK | RCLICK | HOVER);
|
||||
|
||||
switchToNextPhase();
|
||||
}
|
||||
|
||||
CBattleHero::~CBattleHero()
|
||||
{
|
||||
delete dh;
|
||||
delete flag;
|
||||
}
|
||||
CBattleHero::~CBattleHero() = default;
|
||||
|
||||
CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner)
|
||||
{
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "../windows/CWindowObject.h"
|
||||
|
||||
struct SDL_Surface;
|
||||
class CDefHandler;
|
||||
class CGHeroInstance;
|
||||
class CBattleInterface;
|
||||
class CPicture;
|
||||
@ -53,19 +52,24 @@ class CBattleHero : public CIntObject
|
||||
void switchToNextPhase();
|
||||
public:
|
||||
bool flip; //false if it's attacking hero, true otherwise
|
||||
CDefHandler *dh, *flag; //animation and flag
|
||||
|
||||
std::shared_ptr<CAnimation> animation;
|
||||
std::shared_ptr<CAnimation> flagAnimation;
|
||||
|
||||
const CGHeroInstance * myHero; //this animation's hero instance
|
||||
const CBattleInterface * myOwner; //battle interface to which this animation is assigned
|
||||
int phase; //stage of animation
|
||||
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
||||
int currentFrame, firstFrame, lastFrame; //frame of animation
|
||||
ui8 flagAnim, animCount; //for flag animation
|
||||
|
||||
size_t flagAnim;
|
||||
ui8 animCount; //for flag animation
|
||||
void show(SDL_Surface * to) override; //prints next frame of animation to to
|
||||
void setPhase(int newPhase); //sets phase of hero animation
|
||||
void hover(bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override; //call-in
|
||||
void clickRight(tribool down, bool previousState) override; //call-in
|
||||
CBattleHero(const std::string &defName, bool filpG, PlayerColor player, const CGHeroInstance *hero, const CBattleInterface *owner);
|
||||
CBattleHero(const std::string & animationPath, bool filpG, PlayerColor player, const CGHeroInstance * hero, const CBattleInterface * owner);
|
||||
~CBattleHero();
|
||||
};
|
||||
|
||||
|
@ -10,14 +10,10 @@
|
||||
#include "StdInc.h"
|
||||
#include "CCreatureAnimation.h"
|
||||
|
||||
#include "../../lib/vcmi_endian.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/filesystem/CBinaryReader.h"
|
||||
#include "../../lib/filesystem/CMemoryStream.h"
|
||||
|
||||
#include "../gui/SDL_Pixels.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
|
||||
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };
|
||||
static const SDL_Color creatureGoldBorder = { 255, 255, 0, 255 };
|
||||
@ -142,60 +138,43 @@ void CCreatureAnimation::setType(CCreatureAnim::EAnimType type)
|
||||
play();
|
||||
}
|
||||
|
||||
CCreatureAnimation::CCreatureAnimation(std::string name, TSpeedController controller)
|
||||
: defName(name),
|
||||
speed(0.1),
|
||||
currentFrame(0),
|
||||
elapsedTime(0),
|
||||
CCreatureAnimation::CCreatureAnimation(const std::string & name_, TSpeedController controller)
|
||||
: name(name_),
|
||||
speed(0.1),
|
||||
currentFrame(0),
|
||||
elapsedTime(0),
|
||||
type(CCreatureAnim::HOLDING),
|
||||
border(CSDL_Ext::makeColor(0, 0, 0, 0)),
|
||||
speedController(controller),
|
||||
once(false)
|
||||
speedController(controller),
|
||||
once(false)
|
||||
{
|
||||
// separate block to avoid accidental use of "data" after it was moved into "pixelData"
|
||||
{
|
||||
ResourceID resID(std::string("SPRITES/") + name, EResType::ANIMATION);
|
||||
forward = std::make_shared<CAnimation>(name_);
|
||||
reverse = std::make_shared<CAnimation>(name_);
|
||||
|
||||
auto data = CResourceHandler::get()->load(resID)->readAll();
|
||||
|
||||
pixelData = std::move(data.first);
|
||||
pixelDataSize = data.second;
|
||||
}
|
||||
|
||||
CMemoryStream stm(pixelData.get(), pixelDataSize);
|
||||
|
||||
CBinaryReader reader(&stm);
|
||||
|
||||
reader.readInt32(); // def type, unused
|
||||
|
||||
fullWidth = reader.readInt32();
|
||||
fullHeight = reader.readInt32();
|
||||
|
||||
int totalBlocks = reader.readInt32();
|
||||
|
||||
for (auto & elem : palette)
|
||||
{
|
||||
elem.r = reader.readUInt8();
|
||||
elem.g = reader.readUInt8();
|
||||
elem.b = reader.readUInt8();
|
||||
elem.a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
|
||||
for (int i=0; i<totalBlocks; i++)
|
||||
{
|
||||
int groupID = reader.readInt32();
|
||||
|
||||
int totalInBlock = reader.readInt32();
|
||||
|
||||
reader.skip(4 + 4 + 13 * totalInBlock); // some unused data
|
||||
|
||||
for (int j=0; j<totalInBlock; j++)
|
||||
dataOffsets[groupID].push_back(reader.readUInt32());
|
||||
}
|
||||
//todo: optimize
|
||||
forward->preload();
|
||||
reverse->preload();
|
||||
|
||||
// if necessary, add one frame into vcmi-only group DEAD
|
||||
if (dataOffsets.count(CCreatureAnim::DEAD) == 0)
|
||||
dataOffsets[CCreatureAnim::DEAD].push_back(dataOffsets[CCreatureAnim::DEATH].back());
|
||||
if(forward->size(CCreatureAnim::DEAD) == 0)
|
||||
{
|
||||
forward->duplicateImage(CCreatureAnim::DEATH, forward->size(CCreatureAnim::DEATH)-1, CCreatureAnim::DEAD);
|
||||
reverse->duplicateImage(CCreatureAnim::DEATH, reverse->size(CCreatureAnim::DEATH)-1, CCreatureAnim::DEAD);
|
||||
}
|
||||
|
||||
//TODO: get dimensions form CAnimation
|
||||
IImage * first = forward->getImage(0, type, true);
|
||||
|
||||
if(!first)
|
||||
{
|
||||
fullWidth = 0;
|
||||
fullHeight = 0;
|
||||
return;
|
||||
}
|
||||
fullWidth = first->width();
|
||||
fullHeight = first->height();
|
||||
|
||||
reverse->verticalFlip();
|
||||
|
||||
play();
|
||||
}
|
||||
@ -285,142 +264,35 @@ static SDL_Color addColors(const SDL_Color & base, const SDL_Color & over)
|
||||
);
|
||||
}
|
||||
|
||||
std::array<SDL_Color, 8> CCreatureAnimation::genSpecialPalette()
|
||||
void CCreatureAnimation::genBorderPalette(IImage::BorderPallete & target)
|
||||
{
|
||||
std::array<SDL_Color, 8> ret;
|
||||
|
||||
ret[0] = genShadow(0);
|
||||
ret[1] = genShadow(64);
|
||||
ret[2] = genShadow(128);//unused
|
||||
ret[3] = genShadow(128);//unused
|
||||
ret[4] = genShadow(128);
|
||||
ret[5] = genBorderColor(getBorderStrength(elapsedTime), border);
|
||||
ret[6] = addColors(genShadow(128), genBorderColor(getBorderStrength(elapsedTime), border));
|
||||
ret[7] = addColors(genShadow(64), genBorderColor(getBorderStrength(elapsedTime), border));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<int bpp>
|
||||
void CCreatureAnimation::nextFrameT(SDL_Surface * dest, bool rotate)
|
||||
{
|
||||
assert(dataOffsets.count(type) && dataOffsets.at(type).size() > size_t(currentFrame));
|
||||
|
||||
ui32 offset = dataOffsets.at(type).at(floor(currentFrame));
|
||||
|
||||
CMemoryStream stm(pixelData.get(), pixelDataSize);
|
||||
|
||||
CBinaryReader reader(&stm);
|
||||
|
||||
reader.getStream()->seek(offset);
|
||||
|
||||
reader.readUInt32(); // unused, size of pixel data for this frame
|
||||
const ui32 defType2 = reader.readUInt32();
|
||||
const ui32 fullWidth = reader.readUInt32();
|
||||
/*const ui32 fullHeight =*/ reader.readUInt32();
|
||||
const ui32 spriteWidth = reader.readUInt32();
|
||||
const ui32 spriteHeight = reader.readUInt32();
|
||||
const int leftMargin = reader.readInt32();
|
||||
const int topMargin = reader.readInt32();
|
||||
|
||||
const int rightMargin = fullWidth - spriteWidth - leftMargin;
|
||||
//const int bottomMargin = fullHeight - spriteHeight - topMargin;
|
||||
|
||||
const size_t baseOffset = reader.getStream()->tell();
|
||||
|
||||
assert(defType2 == 1);
|
||||
UNUSED(defType2);
|
||||
|
||||
auto specialPalette = genSpecialPalette();
|
||||
|
||||
for (ui32 i=0; i<spriteHeight; i++)
|
||||
{
|
||||
//NOTE: if this loop will be optimized to skip empty lines - recheck this read access
|
||||
ui8 * lineData = pixelData.get() + baseOffset + reader.readUInt32();
|
||||
|
||||
size_t destX = pos.x;
|
||||
if (rotate)
|
||||
destX += rightMargin + spriteWidth - 1;
|
||||
else
|
||||
destX += leftMargin;
|
||||
|
||||
size_t destY = pos.y + topMargin + i;
|
||||
size_t currentOffset = 0;
|
||||
size_t totalRowLength = 0;
|
||||
|
||||
while (totalRowLength < spriteWidth)
|
||||
{
|
||||
ui8 type = lineData[currentOffset++];
|
||||
ui32 length = lineData[currentOffset++] + 1;
|
||||
|
||||
if (type==0xFF)//Raw data
|
||||
{
|
||||
for (size_t j=0; j<length; j++)
|
||||
putPixelAt<bpp>(dest, destX + (rotate?(-j):(j)), destY, lineData[currentOffset + j], specialPalette);
|
||||
|
||||
currentOffset += length;
|
||||
}
|
||||
else// RLE
|
||||
{
|
||||
if (type != 0) // transparency row, handle it here for speed
|
||||
{
|
||||
for (size_t j=0; j<length; j++)
|
||||
putPixelAt<bpp>(dest, destX + (rotate?(-j):(j)), destY, type, specialPalette);
|
||||
}
|
||||
}
|
||||
|
||||
destX += rotate ? (-length) : (length);
|
||||
totalRowLength += length;
|
||||
}
|
||||
}
|
||||
target[0] = genBorderColor(getBorderStrength(elapsedTime), border);
|
||||
target[1] = addColors(genShadow(128), genBorderColor(getBorderStrength(elapsedTime), border));
|
||||
target[2] = addColors(genShadow(64), genBorderColor(getBorderStrength(elapsedTime), border));
|
||||
}
|
||||
|
||||
void CCreatureAnimation::nextFrame(SDL_Surface *dest, bool attacker)
|
||||
{
|
||||
// Note: please notice that attacker value is inversed when passed further.
|
||||
// This is intended behavior because "attacker" actually does not needs rotation
|
||||
switch(dest->format->BytesPerPixel)
|
||||
{
|
||||
case 2: return nextFrameT<2>(dest, !attacker);
|
||||
case 3: return nextFrameT<3>(dest, !attacker);
|
||||
case 4: return nextFrameT<4>(dest, !attacker);
|
||||
default:
|
||||
logGlobal->error("%d bpp is not supported!", (int)dest->format->BitsPerPixel);
|
||||
}
|
||||
size_t frame = floor(currentFrame);
|
||||
|
||||
IImage * image = nullptr;
|
||||
|
||||
if(attacker)
|
||||
image = forward->getImage(frame, type);
|
||||
else
|
||||
image = reverse->getImage(frame, type);
|
||||
|
||||
IImage::BorderPallete borderPallete;
|
||||
genBorderPalette(borderPallete);
|
||||
|
||||
image->setBorderPallete(borderPallete);
|
||||
|
||||
image->draw(dest, pos.x, pos.y);
|
||||
}
|
||||
|
||||
int CCreatureAnimation::framesInGroup(CCreatureAnim::EAnimType group) const
|
||||
{
|
||||
if(dataOffsets.count(group) == 0)
|
||||
return 0;
|
||||
|
||||
return dataOffsets.at(group).size();
|
||||
}
|
||||
|
||||
ui8 * CCreatureAnimation::getPixelAddr(SDL_Surface * dest, int X, int Y) const
|
||||
{
|
||||
return (ui8*)dest->pixels + X * dest->format->BytesPerPixel + Y * dest->pitch;
|
||||
}
|
||||
|
||||
template<int bpp>
|
||||
inline void CCreatureAnimation::putPixelAt(SDL_Surface * dest, int X, int Y, size_t index, const std::array<SDL_Color, 8> & special) const
|
||||
{
|
||||
if ( X < pos.x + pos.w && Y < pos.y + pos.h && X >= 0 && Y >= 0)
|
||||
putPixel<bpp>(getPixelAddr(dest, X, Y), palette[index], index, special);
|
||||
}
|
||||
|
||||
template<int bpp>
|
||||
inline void CCreatureAnimation::putPixel(ui8 * dest, const SDL_Color & color, size_t index, const std::array<SDL_Color, 8> & special) const
|
||||
{
|
||||
if((index <= 1) || (index >=4 && index < 8))
|
||||
{
|
||||
const SDL_Color & pal = special[index];
|
||||
ColorPutter<bpp, 0>::PutColor(dest, pal.r, pal.g, pal.b, pal.a);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorPutter<bpp, 0>::PutColor(dest, color.r, color.g, color.b);
|
||||
}
|
||||
return forward->size(group);
|
||||
}
|
||||
|
||||
bool CCreatureAnimation::isDead() const
|
||||
@ -456,7 +328,8 @@ void CCreatureAnimation::pause()
|
||||
|
||||
void CCreatureAnimation::play()
|
||||
{
|
||||
//logAnim->trace("Play %s group %d at %d:%d", name, static_cast<int>(getType()), pos.x, pos.y);
|
||||
speed = 0;
|
||||
if (speedController(this, type) != 0)
|
||||
if(speedController(this, type) != 0)
|
||||
speed = 1 / speedController(this, type);
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../lib/FunctionList.h"
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
|
||||
class CIntObject;
|
||||
class CCreatureAnimation;
|
||||
@ -52,21 +52,12 @@ public:
|
||||
typedef std::function<float(CCreatureAnimation *, size_t)> TSpeedController;
|
||||
|
||||
private:
|
||||
std::string defName;
|
||||
std::string name;
|
||||
std::shared_ptr<CAnimation> forward;
|
||||
std::shared_ptr<CAnimation> reverse;
|
||||
|
||||
int fullWidth, fullHeight;
|
||||
|
||||
// palette, as read from def file
|
||||
std::array<SDL_Color, 256> palette;
|
||||
|
||||
//key = id of group (note that some groups may be missing)
|
||||
//value = offset of pixel data for each frame, vector size = number of frames in group
|
||||
std::map<int, std::vector<unsigned int>> dataOffsets;
|
||||
|
||||
//animation raw data
|
||||
//TODO: use vector instead?
|
||||
std::unique_ptr<ui8[]> pixelData;
|
||||
size_t pixelDataSize;
|
||||
int fullWidth;
|
||||
int fullHeight;
|
||||
|
||||
// speed of animation, measure in frames per second
|
||||
float speed;
|
||||
@ -85,21 +76,10 @@ private:
|
||||
|
||||
bool once; // animation will be played once and the reset to idling
|
||||
|
||||
ui8 * getPixelAddr(SDL_Surface * dest, int ftcpX, int ftcpY) const;
|
||||
|
||||
template<int bpp>
|
||||
void putPixelAt(SDL_Surface * dest, int X, int Y, size_t index, const std::array<SDL_Color, 8> & special) const;
|
||||
|
||||
template<int bpp>
|
||||
void putPixel( ui8 * dest, const SDL_Color & color, size_t index, const std::array<SDL_Color, 8> & special) const;
|
||||
|
||||
template<int bpp>
|
||||
void nextFrameT(SDL_Surface * dest, bool rotate);
|
||||
|
||||
void endAnimation();
|
||||
|
||||
/// creates 8 special colors for current frame
|
||||
std::array<SDL_Color, 8> genSpecialPalette();
|
||||
|
||||
void genBorderPalette(IImage::BorderPallete & target);
|
||||
public:
|
||||
|
||||
// function(s) that will be called when animation ends, after reset to 1st frame
|
||||
@ -113,12 +93,12 @@ public:
|
||||
/// name - path to .def file, relative to SPRITES/ directory
|
||||
/// controller - function that will return for how long *each* frame
|
||||
/// in specified group of animation should be played, measured in seconds
|
||||
CCreatureAnimation(std::string name, TSpeedController speedController);
|
||||
CCreatureAnimation(const std::string & name_, TSpeedController speedController);
|
||||
|
||||
void setType(CCreatureAnim::EAnimType type); //sets type of animation and cleares framecount
|
||||
CCreatureAnim::EAnimType getType() const; //returns type of animation
|
||||
|
||||
void nextFrame(SDL_Surface * dest, bool rotate);
|
||||
void nextFrame(SDL_Surface * dest, bool attacker);
|
||||
|
||||
// should be called every frame, return true when animation was reset to beginning
|
||||
bool incrementFrame(float timePassed);
|
||||
|
@ -29,7 +29,7 @@ typedef std::map <size_t, std::vector <JsonNode> > source_map;
|
||||
typedef std::map<size_t, IImage* > image_map;
|
||||
typedef std::map<size_t, image_map > group_map;
|
||||
|
||||
/// Class for def loading, methods are based on CDefHandler
|
||||
/// Class for def loading
|
||||
/// After loading will store general info (palette and frame offsets) and pointer to file itself
|
||||
class CDefFile
|
||||
{
|
||||
@ -100,6 +100,8 @@ public:
|
||||
|
||||
void shiftPalette(int from, int howMany) override;
|
||||
|
||||
void setBorderPallete(const BorderPallete & borderPallete) override;
|
||||
|
||||
friend class SDLImageLoader;
|
||||
};
|
||||
|
||||
@ -157,6 +159,7 @@ public:
|
||||
void verticalFlip() override;
|
||||
|
||||
void shiftPalette(int from, int howMany) override;
|
||||
void setBorderPallete(const BorderPallete & borderPallete) override;
|
||||
|
||||
friend class CompImageLoader;
|
||||
};
|
||||
@ -985,6 +988,15 @@ void SDLImage::shiftPalette(int from, int howMany)
|
||||
}
|
||||
}
|
||||
|
||||
void SDLImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
||||
{
|
||||
if(surf->format->palette)
|
||||
{
|
||||
SDL_SetColors(surf, const_cast<SDL_Color *>(borderPallete.data()), 5, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SDLImage::~SDLImage()
|
||||
{
|
||||
SDL_FreeSurface(surf);
|
||||
@ -1238,22 +1250,27 @@ CompImage::~CompImage()
|
||||
|
||||
void CompImage::horizontalFlip()
|
||||
{
|
||||
logAnim->error("CompImage::horizontalFlip is not implemented");
|
||||
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
void CompImage::verticalFlip()
|
||||
{
|
||||
logAnim->error("CompImage::verticalFlip is not implemented");
|
||||
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
void CompImage::shiftPalette(int from, int howMany)
|
||||
{
|
||||
logAnim->error("CompImage::shiftPalette is not implemented");
|
||||
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
void CompImage::exportBitmap(const boost::filesystem::path& path) const
|
||||
void CompImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
||||
{
|
||||
logAnim->error("CompImage::exportBitmap is not implemented");
|
||||
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
void CompImage::exportBitmap(const boost::filesystem::path & path) const
|
||||
{
|
||||
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
|
||||
@ -1605,6 +1622,38 @@ size_t CAnimation::size(size_t group) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CAnimation::horizontalFlip()
|
||||
{
|
||||
for(auto & group : images)
|
||||
for(auto & image : group.second)
|
||||
image.second->horizontalFlip();
|
||||
}
|
||||
|
||||
void CAnimation::verticalFlip()
|
||||
{
|
||||
for(auto & group : images)
|
||||
for(auto & image : group.second)
|
||||
image.second->verticalFlip();
|
||||
}
|
||||
|
||||
void CAnimation::playerColored(PlayerColor player)
|
||||
{
|
||||
for(auto & group : images)
|
||||
for(auto & image : group.second)
|
||||
image.second->playerColored(player);
|
||||
}
|
||||
|
||||
void CAnimation::createFlippedGroup(const size_t sourceGroup, const size_t targetGroup)
|
||||
{
|
||||
for(size_t frame = 0; frame < size(sourceGroup); ++frame)
|
||||
{
|
||||
duplicateImage(sourceGroup, frame, targetGroup);
|
||||
|
||||
IImage * image = getImage(frame, targetGroup);
|
||||
image->verticalFlip();
|
||||
}
|
||||
}
|
||||
|
||||
float CFadeAnimation::initialCounter() const
|
||||
{
|
||||
if (fadingMode == EMode::OUT)
|
||||
|
@ -24,6 +24,7 @@ class IImage
|
||||
{
|
||||
int refCount;
|
||||
public:
|
||||
using BorderPallete = std::array<SDL_Color, 3>;
|
||||
|
||||
//draws image on surface "where" at position
|
||||
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, Rect * src = nullptr, ui8 alpha = 255) const=0;
|
||||
@ -49,6 +50,9 @@ public:
|
||||
//only indexed bitmaps, 16 colors maximum
|
||||
virtual void shiftPalette(int from, int howMany) = 0;
|
||||
|
||||
//only indexed bitmaps, colors 5,6,7 must be special
|
||||
virtual void setBorderPallete(const BorderPallete & borderPallete) = 0;
|
||||
|
||||
virtual void horizontalFlip() = 0;
|
||||
virtual void verticalFlip() = 0;
|
||||
|
||||
@ -127,6 +131,12 @@ public:
|
||||
|
||||
//total count of frames in group (including not loaded)
|
||||
size_t size(size_t group=0) const;
|
||||
|
||||
void horizontalFlip();
|
||||
void verticalFlip();
|
||||
void playerColored(PlayerColor player);
|
||||
|
||||
void createFlippedGroup(const size_t sourceGroup, const size_t targetGroup);
|
||||
};
|
||||
|
||||
const float DEFAULT_DELTA = 0.05f;
|
||||
|
@ -23,11 +23,20 @@ void CCursorHandler::initCursor()
|
||||
xpos = ypos = 0;
|
||||
type = ECursor::DEFAULT;
|
||||
dndObject = nullptr;
|
||||
currentCursor = nullptr;
|
||||
|
||||
cursors =
|
||||
{
|
||||
make_unique<CAnimImage>("CRADVNTR", 0),
|
||||
make_unique<CAnimImage>("CRCOMBAT", 0),
|
||||
make_unique<CAnimImage>("CRDEFLT", 0),
|
||||
make_unique<CAnimImage>("CRSPELL", 0)
|
||||
};
|
||||
|
||||
currentCursor = cursors.at(int(ECursor::DEFAULT)).get();
|
||||
|
||||
help = CSDL_Ext::newSurface(40,40);
|
||||
//No blending. Ensure, that we are copying pixels during "screen restore draw"
|
||||
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
|
||||
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
changeGraphic(ECursor::ADVENTURE, 0);
|
||||
@ -35,32 +44,23 @@ void CCursorHandler::initCursor()
|
||||
|
||||
void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
|
||||
{
|
||||
std::string cursorDefs[4] = { "CRADVNTR.DEF", "CRCOMBAT.DEF", "CRDEFLT.DEF", "CRSPELL.DEF" };
|
||||
|
||||
if (type != this->type)
|
||||
if(type != this->type)
|
||||
{
|
||||
BLOCK_CAPTURING; // not used here
|
||||
|
||||
this->type = type;
|
||||
this->frame = index;
|
||||
|
||||
delete currentCursor;
|
||||
currentCursor = new CAnimImage(cursorDefs[int(type)], index);
|
||||
currentCursor = cursors.at(int(type)).get();
|
||||
currentCursor->setFrame(index);
|
||||
}
|
||||
|
||||
if (frame != index)
|
||||
else if(index != this->frame)
|
||||
{
|
||||
frame = index;
|
||||
this->frame = index;
|
||||
currentCursor->setFrame(index);
|
||||
}
|
||||
}
|
||||
|
||||
void CCursorHandler::dragAndDropCursor(CAnimImage * object)
|
||||
void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
|
||||
{
|
||||
if (dndObject)
|
||||
delete dndObject;
|
||||
|
||||
dndObject = object;
|
||||
dndObject = std::move(object);
|
||||
}
|
||||
|
||||
void CCursorHandler::cursorMove(const int & x, const int & y)
|
||||
@ -101,13 +101,6 @@ void CCursorHandler::drawRestored()
|
||||
|
||||
SDL_Rect temp_rect = genRect(40, 40, x, y);
|
||||
SDL_BlitSurface(help, nullptr, screen, &temp_rect);
|
||||
//blitAt(help,x,y);
|
||||
}
|
||||
|
||||
void CCursorHandler::draw(SDL_Surface *to)
|
||||
{
|
||||
currentCursor->moveTo(Point(xpos, ypos));
|
||||
currentCursor->showAll(screen);
|
||||
}
|
||||
|
||||
void CCursorHandler::shiftPos( int &x, int &y )
|
||||
@ -233,12 +226,10 @@ void CCursorHandler::render()
|
||||
drawRestored();
|
||||
}
|
||||
|
||||
CCursorHandler::CCursorHandler() = default;
|
||||
|
||||
CCursorHandler::~CCursorHandler()
|
||||
{
|
||||
if(help)
|
||||
SDL_FreeSurface(help);
|
||||
|
||||
delete currentCursor;
|
||||
delete dndObject;
|
||||
}
|
||||
|
@ -17,27 +17,28 @@ namespace ECursor
|
||||
enum ECursorTypes { ADVENTURE, COMBAT, DEFAULT, SPELLBOOK };
|
||||
|
||||
enum EBattleCursors { COMBAT_BLOCKED, COMBAT_MOVE, COMBAT_FLY, COMBAT_SHOOT,
|
||||
COMBAT_HERO, COMBAT_QUERY, COMBAT_POINTER,
|
||||
COMBAT_HERO, COMBAT_QUERY, COMBAT_POINTER,
|
||||
//various attack frames
|
||||
COMBAT_SHOOT_PENALTY = 15, COMBAT_SHOOT_CATAPULT, COMBAT_HEAL,
|
||||
COMBAT_SACRIFICE, COMBAT_TELEPORT};
|
||||
}
|
||||
|
||||
/// handles mouse cursor
|
||||
class CCursorHandler
|
||||
class CCursorHandler final
|
||||
{
|
||||
SDL_Surface * help;
|
||||
CAnimImage * currentCursor;
|
||||
CAnimImage * dndObject; //if set, overrides currentCursor
|
||||
|
||||
std::unique_ptr<CAnimImage> dndObject; //if set, overrides currentCursor
|
||||
|
||||
std::array<std::unique_ptr<CAnimImage>, 4> cursors;
|
||||
|
||||
bool showing;
|
||||
|
||||
/// Draw cursor preserving original image below cursor
|
||||
void drawWithScreenRestore();
|
||||
/// Restore original image below cursor
|
||||
void drawRestored();
|
||||
/// Simple draw cursor
|
||||
void draw(SDL_Surface *to);
|
||||
|
||||
public:
|
||||
/// position of cursor
|
||||
int xpos, ypos;
|
||||
@ -58,8 +59,8 @@ public:
|
||||
* @param image Image to replace cursor with or nullptr to use the normal
|
||||
* cursor. CursorHandler takes ownership of object
|
||||
*/
|
||||
void dragAndDropCursor (CAnimImage * image);
|
||||
|
||||
void dragAndDropCursor (std::unique_ptr<CAnimImage> image);
|
||||
|
||||
void render();
|
||||
|
||||
void shiftPos( int &x, int &y );
|
||||
@ -71,5 +72,6 @@ public:
|
||||
/// Move cursor to screen center
|
||||
void centerCursor();
|
||||
|
||||
CCursorHandler();
|
||||
~CCursorHandler();
|
||||
};
|
||||
|
@ -459,8 +459,7 @@ void CGuiHandler::renderFrame()
|
||||
// draw the mouse cursor and update the screen
|
||||
CCS->curh->render();
|
||||
|
||||
if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
|
||||
logGlobal->error("%s SDL_RenderCopy %s", __FUNCTION__, SDL_GetError());
|
||||
SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr);
|
||||
|
||||
SDL_RenderPresent(mainRenderer);
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ void CHeroArtPlace::select ()
|
||||
}
|
||||
}
|
||||
|
||||
CCS->curh->dragAndDropCursor(new CAnimImage("artifact", ourArt->artType->iconIndex));
|
||||
CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", ourArt->artType->iconIndex));
|
||||
ourOwner->commonInfo->src.setTo(this, false);
|
||||
ourOwner->markPossibleSlots(ourArt);
|
||||
|
||||
@ -766,7 +766,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
|
||||
commonInfo->src.art = dst.getArt();
|
||||
commonInfo->src.slotID = dst.slot;
|
||||
assert(commonInfo->src.AOH);
|
||||
CCS->curh->dragAndDropCursor(new CAnimImage("artifact", dst.getArt()->artType->iconIndex));
|
||||
CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", dst.getArt()->artType->iconIndex));
|
||||
markPossibleSlots(dst.getArt());
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "../gui/SDL_Extensions.h"
|
||||
#include "../gui/CGuiHandler.h"
|
||||
#include "../gui/CAnimation.h"
|
||||
#include "../widgets/MiscWidgets.h"
|
||||
#include "../widgets/CComponent.h"
|
||||
|
||||
@ -107,7 +108,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
|
||||
quitButton = new CButton(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [&](){ close(); }, SDLK_RETURN);
|
||||
quitButton->assignedKeys.insert(SDLK_ESCAPE);
|
||||
dismissButton = new CButton(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [&](){ dismissCurrent(); }, SDLK_d);
|
||||
questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [&](){ questlog(); }, SDLK_q);
|
||||
questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q);
|
||||
|
||||
formations = new CToggleGroup(0);
|
||||
formations->addToggle(0, new CToggleButton(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t));
|
||||
@ -144,11 +145,12 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
|
||||
luck = new MoraleLuckBox(false, Rect(233,179,53,45));
|
||||
spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
|
||||
|
||||
auto secSkills = std::make_shared<CAnimation>("SECSKILL");
|
||||
for(int i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
|
||||
{
|
||||
Rect r = Rect(i%2 == 0 ? 18 : 162, 276 + 48 * (i/2), 136, 42);
|
||||
secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill));
|
||||
secSkillImages.push_back(new CAnimImage("SECSKILL", 0, 0, r.x, r.y));
|
||||
secSkillImages.push_back(new CAnimImage(secSkills, 0, 0, r.x, r.y));
|
||||
}
|
||||
|
||||
//dismiss / quest log
|
||||
@ -158,12 +160,14 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
|
||||
//////////////////////////////////////////////////////////////////////////???????????????
|
||||
|
||||
//primary skills & exp and mana
|
||||
new CAnimImage("PSKIL42", 0, 0, 32, 111, false);
|
||||
new CAnimImage("PSKIL42", 1, 0, 102, 111, false);
|
||||
new CAnimImage("PSKIL42", 2, 0, 172, 111, false);
|
||||
new CAnimImage("PSKIL42", 3, 0, 162, 230, false);
|
||||
new CAnimImage("PSKIL42", 4, 0, 20, 230, false);
|
||||
new CAnimImage("PSKIL42", 5, 0, 242, 111, false);
|
||||
auto primSkills = std::make_shared<CAnimation>("PSKIL42");
|
||||
primSkills->preload();
|
||||
new CAnimImage(primSkills, 0, 0, 32, 111);
|
||||
new CAnimImage(primSkills, 1, 0, 102, 111);
|
||||
new CAnimImage(primSkills, 2, 0, 172, 111);
|
||||
new CAnimImage(primSkills, 3, 0, 162, 230);
|
||||
new CAnimImage(primSkills, 4, 0, 20, 230);
|
||||
new CAnimImage(primSkills, 5, 0, 242, 111);
|
||||
|
||||
// various texts
|
||||
new CLabel( 52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1]);
|
||||
@ -306,11 +310,6 @@ void CHeroWindow::dismissCurrent()
|
||||
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, 0, false);
|
||||
}
|
||||
|
||||
void CHeroWindow::questlog()
|
||||
{
|
||||
LOCPLINT->showQuestLog();
|
||||
}
|
||||
|
||||
void CHeroWindow::commanderWindow()
|
||||
{
|
||||
//TODO: allow equipping commander artifacts by drag / drop
|
||||
|
@ -86,7 +86,6 @@ public:
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
|
||||
void questlog(); //show quest log in hero window
|
||||
void commanderWindow();
|
||||
void switchHero(); //changes displayed hero
|
||||
virtual void updateGarrisons() override; //updates the morale widget and calls the parent
|
||||
|
@ -187,7 +187,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
|
||||
aw->arts->markPossibleSlots(art);
|
||||
|
||||
//aw->arts->commonInfo->dst.AOH = aw->arts;
|
||||
CCS->curh->dragAndDropCursor(new CAnimImage("artifact", art->artType->iconIndex));
|
||||
CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", art->artType->iconIndex));
|
||||
|
||||
aw->arts->artifactsOnAltar.erase(art);
|
||||
setID(-1);
|
||||
|
@ -37,7 +37,6 @@ class CGObjectInstance;
|
||||
class CCreature;
|
||||
class CMap;
|
||||
struct StartInfo;
|
||||
struct SDL_Surface;
|
||||
class CMapHandler;
|
||||
struct SetObjectProperty;
|
||||
struct MetaString;
|
||||
|
Loading…
x
Reference in New Issue
Block a user