mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
- New animation system:
-- New files: hch/CAnimation.h/cpp -- Class CAnimation capable to load file partially and/or keep data in compressed state -- Buttons now use CAnimation instead of CDefHandler - build system regenerated to include new files - fixed several gcc warnings - updated README.linux
This commit is contained in:
parent
6cadd47f0d
commit
c10dac929d
14
README.linux
14
README.linux
@ -13,16 +13,20 @@ And then regenerate the build system with
|
||||
|
||||
To compile, at least the following packages (and their development counterparts) are needed to build:
|
||||
* libstdc++ devel
|
||||
* boost c++ libraries v1.36+ (1.35 will not work) (www.boost.org)
|
||||
* SDL and SDL-devel
|
||||
* SDL_mixer and SDL_mixer-devel
|
||||
* SDL_image and SDL_image-devel
|
||||
* SDL_ttf and SDL_ttf-devel
|
||||
* zlib and zlib-devel
|
||||
* the ffmpeg libraries (libavformat and libswscale). Their name could be libavformat-devel and libswscale-devel, or ffmpeg-libs-devel or similar names.
|
||||
* boost c++ libraries v1.36+ (1.35 will not work) (www.boost.org):
|
||||
- filesystem
|
||||
- iostreams
|
||||
- system
|
||||
- thread
|
||||
|
||||
On Ubuntu 9.04, run:
|
||||
sudo apt-get install g++ libsdl1.2debian-all libsdl-image1.2-dev libsdl-ttf2.0-dev libsdl-mixer1.2-dev zlib1g-dev libavformat-dev libswscale-dev libboost1.37-dev
|
||||
On Ubuntu 9.04 or later, run:
|
||||
sudo apt-get install g++ libsdl1.2debian-all libsdl-image1.2-dev libsdl-ttf2.0-dev libsdl-mixer1.2-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-iostreams-dev libboost-system-dev libboost-thread-dev
|
||||
|
||||
Create a directory /YOUR_INSTALL_PATH/vcmi (such as
|
||||
/usr/local/share/games/vcmi) that will contain the game data files. The /vcmi at the end is necessary.
|
||||
@ -47,7 +51,7 @@ That will generate vcmiclient, vcmiserver as well as 3 .so libraries.
|
||||
II. Installing Heroes of Might and Magic 3
|
||||
|
||||
VCMI needs an installed version of Heroes III as well as WoG on top of
|
||||
it. The version of Heroes needed is (I think!) either Shadow of Death
|
||||
it. The version of Heroes needed is either Shadow of Death
|
||||
or Complete.
|
||||
|
||||
Wog can be downloaded from: http://www.maps4heroes.com/heroes3/files/allinone_358f.zip
|
||||
@ -61,7 +65,7 @@ Install Heroes 3 and Wog. Then move all the installed files into
|
||||
Once both programs are installed, you can install VCMI.
|
||||
|
||||
Download the windows VCMI release (at time of writing:
|
||||
http://vcmi.antypika.aplus.pl/forum/dload.php?action=download&id=14)
|
||||
http://forum.vcmi.eu/dload.php?action=download&id=18)
|
||||
and extract it in a private directory. Populate /YOUR_INSTALL_PATH/vcmi:
|
||||
|
||||
mv sprites /YOUR_INSTALL_PATH/vcmi/Sprites
|
||||
|
4
aclocal.m4
vendored
4
aclocal.m4
vendored
@ -13,8 +13,8 @@
|
||||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],,
|
||||
[m4_warning([this file was generated for autoconf 2.65.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
|
||||
[m4_warning([this file was generated for autoconf 2.67.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically `autoreconf'.])])
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "AdventureMapButton.h"
|
||||
#include "../hch/CAnimation.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "SDL_Extensions.h"
|
||||
#include "../hch/CDefHandler.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "../hch/CLodHandler.h"
|
||||
#include "../hch/CGeneralTextHandler.h"
|
||||
@ -14,7 +14,7 @@
|
||||
#include "CMessage.h"
|
||||
|
||||
/*
|
||||
* AdevntureMapButton.cpp, part of VCMI engine
|
||||
* AdventureMapButton.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
@ -41,19 +41,19 @@ CButtonBase::~CButtonBase()
|
||||
delete text;
|
||||
if(notFreeButton)
|
||||
return;
|
||||
for(int i =0; i<imgs.size();i++)
|
||||
for(int j=0;j<imgs[i].size();j++)
|
||||
SDL_FreeSurface(imgs[i][j]);
|
||||
for (size_t i = 0; i<imgs.size(); i++)
|
||||
delete imgs[i];
|
||||
imgs.clear();
|
||||
}
|
||||
|
||||
void CButtonBase::show(SDL_Surface * to)
|
||||
{
|
||||
int img = std::min(state+bitmapOffset,int(imgs[curimg].size()-1));
|
||||
int img = std::min(state+bitmapOffset,int(imgs[curimg]->size()-1));
|
||||
img = std::max(0, img);
|
||||
|
||||
if (abs)
|
||||
{
|
||||
blitAt(imgs[curimg][img],pos.x,pos.y,to);
|
||||
blitAt(imgs[curimg]->image(img),pos.x,pos.y,to);
|
||||
if(text)
|
||||
{//using "state" instead of "state == 1" screwed up hoverable buttons with text
|
||||
CSDL_Ext::printAt(text->text, text->x + pos.x + (state == 1), text->y + pos.y + (state == 1), text->font, text->color, to);
|
||||
@ -61,7 +61,7 @@ void CButtonBase::show(SDL_Surface * to)
|
||||
}
|
||||
else
|
||||
{
|
||||
blitAt(imgs[curimg][img],pos.x+ourObj->pos.x,pos.y+ourObj->pos.y,to);
|
||||
blitAt(imgs[curimg]->image(img),pos.x+ourObj->pos.x,pos.y+ourObj->pos.y,to);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,28 +221,15 @@ void AdventureMapButton::init(const CFunctionList<void()> &Callback, const std::
|
||||
setDef(defName, playerColoredButton);
|
||||
|
||||
if (add && add->size())
|
||||
{
|
||||
imgs.resize(imgs.size()+add->size());
|
||||
for (size_t i=0; i<add->size();i++)
|
||||
{
|
||||
CDefHandler *temp = CDefHandler::giveDef((*add)[i]);
|
||||
temp->notFreeImgs = true;
|
||||
for (size_t j=0;j<temp->ourImages.size();j++)
|
||||
{
|
||||
imgs[i+1].push_back(temp->ourImages[j].bitmap);
|
||||
if(playerColoredButton)
|
||||
{
|
||||
graphics->blueToPlayersAdv(imgs[1+i][j],LOCPLINT->playerID);
|
||||
}
|
||||
}
|
||||
delete temp;
|
||||
}
|
||||
//delete add;
|
||||
}
|
||||
setDef((*add)[i], playerColoredButton);
|
||||
if (playerColoredButton)
|
||||
setPlayerColor(LOCPLINT->playerID);
|
||||
|
||||
pos.x += x;
|
||||
pos.y += y;
|
||||
pos.w = imgs[curimg][0]->w;
|
||||
pos.h = imgs[curimg][0]->h -1;
|
||||
pos.w = imgs[curimg]->image(0)->w;
|
||||
pos.h = imgs[curimg]->image(0)->h -1;
|
||||
}
|
||||
|
||||
void AdventureMapButton::block( ui8 on )
|
||||
@ -257,30 +244,22 @@ void AdventureMapButton::setDef(const std::string & defName, bool playerColoredB
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
for (size_t i=0;i<imgs[0].size();i++)
|
||||
SDL_FreeSurface(imgs[0][i]);
|
||||
imgs[0].clear();
|
||||
for (size_t i=0; i<imgs.size(); i++)
|
||||
delete imgs[i];
|
||||
imgs.clear();
|
||||
}
|
||||
|
||||
CDefHandler * temp = CDefHandler::giveDef(defName);
|
||||
temp->notFreeImgs = true;
|
||||
for (size_t i=0;i<temp->ourImages.size();i++)
|
||||
{
|
||||
imgs.resize(1);
|
||||
imgs[0].push_back(temp->ourImages[i].bitmap);
|
||||
if(playerColoredButton)
|
||||
{
|
||||
graphics->blueToPlayersAdv(imgs[curimg][i],LOCPLINT->playerID);
|
||||
}
|
||||
}
|
||||
delete temp;
|
||||
imgs.push_back(new CAnimation(defName));
|
||||
imgs.back()->load();
|
||||
}
|
||||
|
||||
void AdventureMapButton::setPlayerColor(int player)
|
||||
{
|
||||
for(int i =0; i<imgs.size();i++)
|
||||
for(int j=0;j<imgs[i].size();j++)
|
||||
graphics->blueToPlayersAdv(imgs[i][j],player);
|
||||
for(size_t i =0; i<imgs.size();i++)
|
||||
for(size_t j=0;j<imgs[i]->size();j++)
|
||||
{
|
||||
graphics->blueToPlayersAdv(imgs[i]->image(j),player);
|
||||
}
|
||||
}
|
||||
|
||||
void CHighlightableButton::select(bool on)
|
||||
@ -364,7 +343,7 @@ void CHighlightableButtonsGroup::addButton(const std::map<int,std::string> &tool
|
||||
}
|
||||
|
||||
CHighlightableButtonsGroup::CHighlightableButtonsGroup(const CFunctionList2<void(int)> &OnChange, bool musicLikeButtons)
|
||||
: musicLike(musicLikeButtons), onChange(OnChange)
|
||||
: onChange(OnChange), musicLike(musicLikeButtons)
|
||||
{}
|
||||
|
||||
CHighlightableButtonsGroup::~CHighlightableButtonsGroup()
|
||||
@ -559,7 +538,7 @@ void CSlider::clickLeft(tribool down, bool previousState)
|
||||
|
||||
CSlider::~CSlider()
|
||||
{
|
||||
delete imgs;
|
||||
|
||||
}
|
||||
|
||||
CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, int style)
|
||||
@ -609,19 +588,23 @@ CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int
|
||||
|
||||
if(style == 0)
|
||||
{
|
||||
if (horizontal)
|
||||
imgs = CDefHandler::giveDefEss("IGPCRDIV.DEF");
|
||||
else
|
||||
imgs = CDefHandler::giveDefEss("OVBUTN2.DEF");
|
||||
left->imgs.resize(1); right->imgs.resize(1); slider->imgs.resize(1);
|
||||
left->imgs[0].push_back(imgs->ourImages[0].bitmap); left->imgs[0].push_back(imgs->ourImages[1].bitmap);
|
||||
right->imgs[0].push_back(imgs->ourImages[2].bitmap); right->imgs[0].push_back(imgs->ourImages[3].bitmap);
|
||||
slider->imgs[0].push_back(imgs->ourImages[4].bitmap);
|
||||
left->notFreeButton = right->notFreeButton = slider->notFreeButton = true;
|
||||
CAnimation * pics = new CAnimation(horizontal?"IGPCRDIV.DEF":"OVBUTN2.DEF");
|
||||
pics->load();
|
||||
|
||||
left->imgs.push_back(new CAnimation());
|
||||
right->imgs.push_back(new CAnimation());
|
||||
slider->imgs.push_back(new CAnimation());
|
||||
|
||||
left->imgs.back()->add(pics->image(0), true);
|
||||
left->imgs.back()->add(pics->image(1), true);
|
||||
right->imgs.back()->add(pics->image(2), true);
|
||||
right->imgs.back()->add(pics->image(3), true);
|
||||
slider->imgs.back()->add(pics->image(4), true);
|
||||
|
||||
delete pics;
|
||||
}
|
||||
else
|
||||
{
|
||||
imgs = NULL;
|
||||
left->setDef(horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", false);
|
||||
right->setDef(horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", false);
|
||||
slider->setDef("SCNRBSL.DEF", false);
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern SDL_Color tytulowy, tlo, zwykly ;
|
||||
|
||||
class CDefEssential;
|
||||
class CAnimation;
|
||||
|
||||
namespace config{struct ButtonInfo;}
|
||||
|
||||
@ -41,7 +41,7 @@ public:
|
||||
bool notFreeButton; //TODO: comment me
|
||||
CIntObject * ourObj; // "owner"
|
||||
int state; //TODO: comment me
|
||||
std::vector< std::vector<SDL_Surface*> > imgs; //images for this button
|
||||
std::vector< CAnimation * > imgs; //images for this button
|
||||
int curimg; //curently displayed image from imgs
|
||||
virtual void show(SDL_Surface * to);
|
||||
virtual void showAll(SDL_Surface * to);
|
||||
@ -129,8 +129,6 @@ public:
|
||||
bool wheelScrolling;
|
||||
bool keyScrolling;
|
||||
|
||||
CDefEssential *imgs ;
|
||||
|
||||
boost::function<void(int)> moved;
|
||||
|
||||
void redrawSlider();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "SDL_Extensions.h"
|
||||
#include "CAdvmapInterface.h"
|
||||
#include "AdventureMapButton.h"
|
||||
#include "../hch/CAnimation.h"
|
||||
#include "../hch/CObjectHandler.h"
|
||||
#include "../hch/CHeroHandler.h"
|
||||
#include "../hch/CDefHandler.h"
|
||||
@ -3914,9 +3915,9 @@ CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInt
|
||||
animSpeeds->onChange = boost::bind(&CBattleInterface::setAnimSpeed, owner, _1);
|
||||
|
||||
setToDefault = new AdventureMapButton (CGI->generaltexth->zelp[392].first, CGI->generaltexth->zelp[392].second, boost::bind(&CBattleOptionsWindow::bDefaultf,this), 405, 443, "codefaul.def");
|
||||
std::swap(setToDefault->imgs[0][0], setToDefault->imgs[0][1]);
|
||||
setToDefault->imgs[0]->fixButtonPos();
|
||||
exit = new AdventureMapButton (CGI->generaltexth->zelp[393].first, CGI->generaltexth->zelp[393].second, boost::bind(&CBattleOptionsWindow::bExitf,this), 516, 443, "soretrn.def",SDLK_RETURN);
|
||||
std::swap(exit->imgs[0][0], exit->imgs[0][1]);
|
||||
exit->imgs[0]->fixButtonPos();
|
||||
|
||||
//printing texts to background
|
||||
CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[392], 242, 32, FONT_BIG, tytulowy, background); //window title
|
||||
|
@ -1138,9 +1138,8 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
|
||||
if(down)
|
||||
{
|
||||
CCastleInterface * ci=LOCPLINT->castleInt;
|
||||
const CGTownInstance * town = ci->town;
|
||||
std::set<si32> bld = ci->town->builtBuildings;
|
||||
int summ=0, cnt=0;
|
||||
int summ=0;
|
||||
std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number
|
||||
boost::algorithm::replace_first(descr,"%s",CGI->creh->creatures[crid]->nameSing);
|
||||
boost::algorithm::replace_first(descr,"%d", boost::lexical_cast<std::string>(ci->town->creatureGrowth(level)));
|
||||
@ -1174,7 +1173,7 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
|
||||
summ+=AddToString(CGI->buildh->buildings[ci->town->subID][24]->Name()+" %+d",descr,
|
||||
CGI->creh->creatures[crid]->hordeGrowth);
|
||||
|
||||
cnt = 0;
|
||||
int cnt = 0;
|
||||
|
||||
std::vector< const CGDwelling * > myDwellings = LOCPLINT->cb->getMyDwellings();
|
||||
for (std::vector<const CGDwelling*>::const_iterator it = myDwellings.begin(); it != myDwellings.end(); ++it)
|
||||
|
@ -2,14 +2,18 @@
|
||||
#include "CConfigHandler.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#if BOOST_VERSION >= 103800
|
||||
#include <boost/spirit/include/classic.hpp>
|
||||
#else
|
||||
#include <boost/spirit.hpp>
|
||||
#endif
|
||||
#include <boost/version.hpp>
|
||||
#include <fstream>
|
||||
using namespace config;
|
||||
|
||||
#if BOOST_VERSION >= 103800
|
||||
#include <boost/spirit/include/classic.hpp>
|
||||
using namespace boost::spirit::classic;
|
||||
#else
|
||||
#include <boost/spirit.hpp>
|
||||
using namespace boost::spirit;
|
||||
#endif
|
||||
|
||||
using namespace phoenix;
|
||||
|
||||
/*
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "CMessage.h"
|
||||
#include "SDL_ttf.h"
|
||||
#include "../hch/CDefHandler.h"
|
||||
#include "../hch/CAnimation.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "SDL_Extensions.h"
|
||||
#include "../hch/CLodHandler.h"
|
||||
@ -427,7 +428,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player)
|
||||
// Compute total width of buttons
|
||||
bw = 20*(ret->buttons.size()-1); // space between all buttons
|
||||
for(size_t i=0; i<ret->buttons.size(); i++) //and add buttons width
|
||||
bw+=ret->buttons[i]->imgs[0][0]->w;
|
||||
bw+=ret->buttons[i]->imgs[0]->image(0)->w;
|
||||
winSize.second += 20 + //before button
|
||||
ok->ourImages[0].bitmap->h; //button
|
||||
}
|
||||
@ -464,13 +465,13 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player)
|
||||
{
|
||||
// Position the buttons at the bottom of the window
|
||||
bw = (ret->bitmap->w/2) - (bw/2);
|
||||
curh = ret->bitmap->h - SIDE_MARGIN - ret->buttons[0]->imgs[0][0]->h;
|
||||
curh = ret->bitmap->h - SIDE_MARGIN - ret->buttons[0]->imgs[0]->image(0)->h;
|
||||
|
||||
for(size_t i=0; i<ret->buttons.size(); i++)
|
||||
{
|
||||
ret->buttons[i]->pos.x = bw + ret->pos.x;
|
||||
ret->buttons[i]->pos.y = curh + ret->pos.y;
|
||||
bw += ret->buttons[i]->imgs[0][0]->w + 20;
|
||||
bw += ret->buttons[i]->imgs[0]->image(0)->w + 20;
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<ret->components.size(); i++)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "SDL_Extensions.h"
|
||||
#include "CGameInfo.h"
|
||||
#include "CCursorHandler.h"
|
||||
#include "../hch/CAnimation.h"
|
||||
#include "../hch/CDefHandler.h"
|
||||
#include "../hch/CDefObjInfoHandler.h"
|
||||
#include "../hch/CGeneralTextHandler.h"
|
||||
@ -798,7 +799,7 @@ void SelectionTab::parseCampaigns( std::vector<FileInfo> & files )
|
||||
}
|
||||
|
||||
SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(CMapInfo *)> &OnSelect, bool MultiPlayer)
|
||||
:onSelect(OnSelect), bg(NULL)
|
||||
:bg(NULL), onSelect(OnSelect)
|
||||
{
|
||||
OBJ_CONSTRUCTION;
|
||||
selectionPos = 0;
|
||||
@ -1239,7 +1240,7 @@ CChatBox::CChatBox(const Rect &rect)
|
||||
}
|
||||
|
||||
InfoCard::InfoCard( CMenuScreen::EState Type, bool network )
|
||||
: difficulty(NULL), sizes(NULL), sFlags(NULL), bg(NULL), chatOn(false), chat(NULL)
|
||||
: bg(NULL), chatOn(false), chat(NULL), difficulty(NULL), sizes(NULL), sFlags(NULL)
|
||||
{
|
||||
OBJ_CONSTRUCTION;
|
||||
pos.x += 393;
|
||||
@ -2333,8 +2334,8 @@ void CHotSeatPlayers::enterSelectionScreen()
|
||||
}
|
||||
|
||||
CBonusSelection::CBonusSelection( CCampaignState * _ourCampaign )
|
||||
: ourCampaign(_ourCampaign), highlightedRegion(NULL), ourHeader(NULL), bonuses(NULL),
|
||||
diffLb(NULL), diffRb(NULL)
|
||||
: highlightedRegion(NULL), ourCampaign(_ourCampaign), ourHeader(NULL),
|
||||
diffLb(NULL), diffRb(NULL), bonuses(NULL)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
static const std::string bgNames [] = {"E1_BG.BMP", "G2_BG.BMP", "E2_BG.BMP", "G1_BG.BMP", "G3_BG.BMP", "N1_BG.BMP",
|
||||
@ -2765,9 +2766,9 @@ void CBonusSelection::updateBonusSelection()
|
||||
blitAt(twcp->ourImages[1].bitmap, 0, 0, selected);
|
||||
|
||||
//moving surfaces into button
|
||||
bonuses->buttons.back()->imgs[0].clear();
|
||||
bonuses->buttons.back()->imgs[0].push_back(notSelected);
|
||||
bonuses->buttons.back()->imgs[0].push_back(selected);
|
||||
bonuses->buttons.back()->imgs[0]->unload();
|
||||
bonuses->buttons.back()->imgs[0]->add(notSelected);
|
||||
bonuses->buttons.back()->imgs[0]->add(selected);
|
||||
|
||||
//cleaning
|
||||
delete de;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "CConfigHandler.h"
|
||||
#include "CCreatureAnimation.h"
|
||||
#include "Graphics.h"
|
||||
#include "../hch/CAnimation.h"
|
||||
#include "../hch/CArtHandler.h"
|
||||
#include "../hch/CBuildingHandler.h"
|
||||
#include "../hch/CGeneralTextHandler.h"
|
||||
@ -3868,19 +3869,19 @@ CSystemOptionsWindow::CSystemOptionsWindow(const SDL_Rect &pos, CPlayerInterface
|
||||
// std::swap(save->imgs[0][0], load->imgs[0][1]);
|
||||
|
||||
save = new AdventureMapButton (CGI->generaltexth->zelp[322].first, CGI->generaltexth->zelp[322].second, boost::bind(&CSystemOptionsWindow::bsavef, this), pos.x+357, pos.y+298, "SOSAVE.DEF", SDLK_s);
|
||||
std::swap(save->imgs[0][0], save->imgs[0][1]);
|
||||
save->imgs[0]->fixButtonPos();
|
||||
|
||||
// restart = new AdventureMapButton (CGI->generaltexth->zelp[323].first, CGI->generaltexth->zelp[323].second, boost::bind(&CSystemOptionsWindow::bmainmenuf, this), pos.x+346, pos.y+357, "SORSTRT", SDLK_r);
|
||||
// std::swap(save->imgs[0][0], restart->imgs[0][1]);
|
||||
|
||||
mainMenu = new AdventureMapButton (CGI->generaltexth->zelp[320].first, CGI->generaltexth->zelp[320].second, boost::bind(&CSystemOptionsWindow::bmainmenuf, this), pos.x+357, pos.y+357, "SOMAIN.DEF", SDLK_m);
|
||||
std::swap(mainMenu->imgs[0][0], mainMenu->imgs[0][1]);
|
||||
mainMenu->imgs[0]->fixButtonPos();
|
||||
|
||||
quitGame = new AdventureMapButton (CGI->generaltexth->zelp[324].first, CGI->generaltexth->zelp[324].second, boost::bind(&CSystemOptionsWindow::bquitf, this), pos.x+246, pos.y+415, "soquit.def", SDLK_q);
|
||||
std::swap(quitGame->imgs[0][0], quitGame->imgs[0][1]);
|
||||
quitGame->imgs[0]->fixButtonPos();
|
||||
|
||||
backToMap = new AdventureMapButton (CGI->generaltexth->zelp[325].first, CGI->generaltexth->zelp[325].second, boost::bind(&CSystemOptionsWindow::breturnf, this), pos.x+357, pos.y+415, "soretrn.def", SDLK_RETURN);
|
||||
std::swap(backToMap->imgs[0][0], backToMap->imgs[0][1]);
|
||||
backToMap->imgs[0]->fixButtonPos();
|
||||
backToMap->assignedKeys.insert(SDLK_ESCAPE);
|
||||
|
||||
heroMoveSpeed = new CHighlightableButtonsGroup(0);
|
||||
|
@ -13,7 +13,8 @@ vcmiclient_SOURCES = \
|
||||
../CThreadHelper.h \
|
||||
../StartInfo.h \
|
||||
../global.h \
|
||||
../hch/CAmbarCendamo.h \
|
||||
../hch/CAnimation.h \
|
||||
../hch/CAnimation.cpp \
|
||||
../hch/CBuildingHandler.h \
|
||||
../hch/CDefHandler.cpp \
|
||||
../hch/CDefHandler.h \
|
||||
|
@ -59,6 +59,7 @@ PROGRAMS = $(bin_PROGRAMS)
|
||||
am_vcmiclient_OBJECTS = vcmiclient-CCallback.$(OBJEXT) \
|
||||
vcmiclient-CGameInterface.$(OBJEXT) \
|
||||
vcmiclient-CThreadHelper.$(OBJEXT) \
|
||||
vcmiclient-CAnimation.$(OBJEXT) \
|
||||
vcmiclient-CDefHandler.$(OBJEXT) \
|
||||
vcmiclient-CMusicHandler.$(OBJEXT) \
|
||||
vcmiclient-CSndHandler.$(OBJEXT) \
|
||||
@ -280,7 +281,8 @@ vcmiclient_SOURCES = \
|
||||
../CThreadHelper.h \
|
||||
../StartInfo.h \
|
||||
../global.h \
|
||||
../hch/CAmbarCendamo.h \
|
||||
../hch/CAnimation.h \
|
||||
../hch/CAnimation.cpp \
|
||||
../hch/CBuildingHandler.h \
|
||||
../hch/CDefHandler.cpp \
|
||||
../hch/CDefHandler.h \
|
||||
@ -437,6 +439,7 @@ distclean-compile:
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-AdventureMapButton.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CAdvmapInterface.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CAnimation.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CBattleInterface.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CBitmapHandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcmiclient-CCallback.Po@am__quote@
|
||||
@ -539,6 +542,22 @@ vcmiclient-CThreadHelper.obj: ../CThreadHelper.cpp
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -c -o vcmiclient-CThreadHelper.obj `if test -f '../CThreadHelper.cpp'; then $(CYGPATH_W) '../CThreadHelper.cpp'; else $(CYGPATH_W) '$(srcdir)/../CThreadHelper.cpp'; fi`
|
||||
|
||||
vcmiclient-CAnimation.o: ../hch/CAnimation.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -MT vcmiclient-CAnimation.o -MD -MP -MF $(DEPDIR)/vcmiclient-CAnimation.Tpo -c -o vcmiclient-CAnimation.o `test -f '../hch/CAnimation.cpp' || echo '$(srcdir)/'`../hch/CAnimation.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vcmiclient-CAnimation.Tpo $(DEPDIR)/vcmiclient-CAnimation.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../hch/CAnimation.cpp' object='vcmiclient-CAnimation.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -c -o vcmiclient-CAnimation.o `test -f '../hch/CAnimation.cpp' || echo '$(srcdir)/'`../hch/CAnimation.cpp
|
||||
|
||||
vcmiclient-CAnimation.obj: ../hch/CAnimation.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -MT vcmiclient-CAnimation.obj -MD -MP -MF $(DEPDIR)/vcmiclient-CAnimation.Tpo -c -o vcmiclient-CAnimation.obj `if test -f '../hch/CAnimation.cpp'; then $(CYGPATH_W) '../hch/CAnimation.cpp'; else $(CYGPATH_W) '$(srcdir)/../hch/CAnimation.cpp'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vcmiclient-CAnimation.Tpo $(DEPDIR)/vcmiclient-CAnimation.Po
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../hch/CAnimation.cpp' object='vcmiclient-CAnimation.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -c -o vcmiclient-CAnimation.obj `if test -f '../hch/CAnimation.cpp'; then $(CYGPATH_W) '../hch/CAnimation.cpp'; else $(CYGPATH_W) '$(srcdir)/../hch/CAnimation.cpp'; fi`
|
||||
|
||||
vcmiclient-CDefHandler.o: ../hch/CDefHandler.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vcmiclient_CXXFLAGS) $(CXXFLAGS) -MT vcmiclient-CDefHandler.o -MD -MP -MF $(DEPDIR)/vcmiclient-CDefHandler.Tpo -c -o vcmiclient-CDefHandler.o `test -f '../hch/CDefHandler.cpp' || echo '$(srcdir)/'`../hch/CDefHandler.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vcmiclient-CDefHandler.Tpo $(DEPDIR)/vcmiclient-CDefHandler.Po
|
||||
|
@ -61,9 +61,9 @@ STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&p
|
||||
template<int bpp, int incrementPtr>
|
||||
STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
|
||||
{
|
||||
PutColor(ptr, (((Uint32)ptr[2]-(Uint32)R)*(Uint32)A) >> 8 + (Uint32)R,
|
||||
(((Uint32)ptr[1]-(Uint32)G)*(Uint32)A) >> 8 + (Uint32)G,
|
||||
(((Uint32)ptr[0]-(Uint32)B)*(Uint32)A) >> 8 + (Uint32)B);
|
||||
PutColor(ptr, (((Uint32)ptr[2]-(Uint32)R)*(Uint32)A) >> (8 + (Uint32)R),
|
||||
(((Uint32)ptr[1]-(Uint32)G)*(Uint32)A) >> (8 + (Uint32)G),
|
||||
(((Uint32)ptr[0]-(Uint32)B)*(Uint32)A) >> (8 + (Uint32)B));
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ if test "x$GXX" = "xyes" -a "x$enable_debug" = "xyes" ; then
|
||||
fi
|
||||
|
||||
if test "x$GXX" = "xyes" ; then
|
||||
CXXFLAGS="$CXXFLAGS -Wall -Wno-switch-enum -Wno-sign-compare -Wcast-align -Wpointer-arith"
|
||||
CXXFLAGS="$CXXFLAGS -Wall -Wno-switch -Wno-sign-compare -Wcast-align -Wpointer-arith"
|
||||
fi
|
||||
|
||||
CXXFLAGS="$CXXFLAGS -DDATA_DIR=\\\"\$(pkgdatadir)\\\" -DBIN_DIR=\\\"\$(bindir)\\\" -DLIB_DIR=\\\"\$(pkglibdir)\\\""
|
||||
|
689
hch/CAnimation.cpp
Normal file
689
hch/CAnimation.cpp
Normal file
@ -0,0 +1,689 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
#include "../client/CBitmapHandler.h"
|
||||
#include "CAnimation.h"
|
||||
#include "CLodHandler.h"
|
||||
|
||||
/*
|
||||
* CAnimation.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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
extern DLL_EXPORT CLodHandler *spriteh;
|
||||
|
||||
/*************************************************************************
|
||||
* DefFile, class used for def loading *
|
||||
*************************************************************************/
|
||||
|
||||
bool CDefFile::haveFrame(size_t frame, size_t group) const
|
||||
{
|
||||
if (offset.size() > group)
|
||||
if (offset[group].size() > frame)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_Surface * CDefFile::loadFrame(size_t frame, size_t group) const
|
||||
{
|
||||
if (haveFrame(frame, group))
|
||||
return loadFrame(( unsigned char * )data+offset[group][frame], colors);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_Surface * CDefFile::loadFrame (const unsigned char * FDef, const BMPPalette * palette)
|
||||
{
|
||||
SDL_Surface * ret=NULL;
|
||||
|
||||
unsigned int BaseOffset,
|
||||
SpriteWidth, SpriteHeight, //format of sprite
|
||||
TotalRowLength, // length of read segment
|
||||
add, FullHeight,FullWidth,
|
||||
RowAdd,
|
||||
prSize,
|
||||
defType2;
|
||||
int LeftMargin, RightMargin, TopMargin, BottomMargin;
|
||||
|
||||
|
||||
unsigned char SegmentType;
|
||||
|
||||
BaseOffset = 0;
|
||||
SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef + BaseOffset);
|
||||
|
||||
prSize = SDL_SwapLE32(sd.prSize);
|
||||
defType2 = SDL_SwapLE32(sd.defType2);
|
||||
FullWidth = SDL_SwapLE32(sd.FullWidth);
|
||||
FullHeight = SDL_SwapLE32(sd.FullHeight);
|
||||
SpriteWidth = SDL_SwapLE32(sd.SpriteWidth);
|
||||
SpriteHeight = SDL_SwapLE32(sd.SpriteHeight);
|
||||
LeftMargin = SDL_SwapLE32(sd.LeftMargin);
|
||||
TopMargin = SDL_SwapLE32(sd.TopMargin);
|
||||
RightMargin = FullWidth - SpriteWidth - LeftMargin;
|
||||
BottomMargin = FullHeight - SpriteHeight - TopMargin;
|
||||
|
||||
//if(LeftMargin + RightMargin < 0)
|
||||
// SpriteWidth += LeftMargin + RightMargin; //ugly construction... TODO: check how to do it nicer
|
||||
if (LeftMargin<0)
|
||||
SpriteWidth+=LeftMargin;
|
||||
if (RightMargin<0)
|
||||
SpriteWidth+=RightMargin;
|
||||
|
||||
// Note: this looks bogus because we allocate only FullWidth, not FullWidth+add
|
||||
add = 4 - FullWidth%4;
|
||||
if (add==4)
|
||||
add=0;
|
||||
|
||||
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, FullWidth, FullHeight, 8, 0, 0, 0, 0);
|
||||
//int tempee2 = readNormalNr(0,4,((unsigned char *)tempee.c_str()));
|
||||
|
||||
BaseOffset += sizeof(SSpriteDef);
|
||||
int BaseOffsetor = BaseOffset;
|
||||
|
||||
for (int i=0; i<256; ++i)
|
||||
{
|
||||
SDL_Color pr;
|
||||
pr.r = palette[i].R;
|
||||
pr.g = palette[i].G;
|
||||
pr.b = palette[i].B;
|
||||
pr.unused = palette[i].F;
|
||||
(*(ret->format->palette->colors+i))=pr;
|
||||
}
|
||||
|
||||
int ftcp=0;
|
||||
|
||||
// If there's a margin anywhere, just blank out the whole surface.
|
||||
if (TopMargin > 0 || BottomMargin > 0 || LeftMargin > 0 || RightMargin > 0)
|
||||
{
|
||||
memset( reinterpret_cast<char*>(ret->pixels), 0, FullHeight*FullWidth);
|
||||
}
|
||||
|
||||
// Skip top margin
|
||||
if (TopMargin > 0)
|
||||
ftcp += TopMargin*(FullWidth+add);
|
||||
|
||||
switch (defType2)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
for (unsigned int i=0; i<SpriteHeight; i++)
|
||||
{
|
||||
if (LeftMargin>0)
|
||||
ftcp += LeftMargin;
|
||||
|
||||
memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth);
|
||||
ftcp += SpriteWidth;
|
||||
BaseOffset += SpriteWidth;
|
||||
|
||||
if (RightMargin>0)
|
||||
ftcp += RightMargin;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
const unsigned int * RWEntriesLoc = reinterpret_cast<const unsigned int *>(FDef+BaseOffset);
|
||||
BaseOffset += sizeof(int) * SpriteHeight;
|
||||
for (unsigned int i=0; i<SpriteHeight; i++)
|
||||
{
|
||||
BaseOffset=BaseOffsetor + SDL_SwapLE32(read_unaligned_u32(RWEntriesLoc + i));
|
||||
if (LeftMargin>0)
|
||||
ftcp += LeftMargin;
|
||||
|
||||
TotalRowLength=0;
|
||||
do
|
||||
{
|
||||
unsigned int SegmentLength;
|
||||
|
||||
SegmentType=FDef[BaseOffset++];
|
||||
SegmentLength=FDef[BaseOffset++] + 1;
|
||||
|
||||
if (SegmentType==0xFF)
|
||||
{
|
||||
memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, FDef + BaseOffset, SegmentLength);
|
||||
BaseOffset+=SegmentLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(reinterpret_cast<char*>(ret->pixels)+ftcp, SegmentType, SegmentLength);
|
||||
}
|
||||
ftcp += SegmentLength;
|
||||
TotalRowLength += SegmentLength;
|
||||
}
|
||||
while (TotalRowLength<SpriteWidth);
|
||||
|
||||
RowAdd=SpriteWidth-TotalRowLength;
|
||||
|
||||
if (RightMargin>0)
|
||||
ftcp += RightMargin;
|
||||
|
||||
if (add>0)
|
||||
ftcp += add+RowAdd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
BaseOffset = BaseOffsetor + SDL_SwapLE16(read_unaligned_u16(FDef + BaseOffsetor));
|
||||
|
||||
for (unsigned int i=0; i<SpriteHeight; i++)
|
||||
{
|
||||
//BaseOffset = BaseOffsetor+RWEntries[i];
|
||||
if (LeftMargin>0)
|
||||
ftcp += LeftMargin;
|
||||
|
||||
TotalRowLength=0;
|
||||
|
||||
do
|
||||
{
|
||||
SegmentType=FDef[BaseOffset++];
|
||||
unsigned char code = SegmentType / 32;
|
||||
unsigned char value = (SegmentType & 31) + 1;
|
||||
if (code==7)
|
||||
{
|
||||
memcpy(reinterpret_cast<char*>(ret->pixels)+ftcp, &FDef[BaseOffset], value);
|
||||
ftcp += value;
|
||||
BaseOffset += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(reinterpret_cast<char*>(ret->pixels)+ftcp, code, value);
|
||||
ftcp += value;
|
||||
}
|
||||
TotalRowLength+=value;
|
||||
}
|
||||
while (TotalRowLength<SpriteWidth);
|
||||
|
||||
if (RightMargin>0)
|
||||
ftcp += RightMargin;
|
||||
|
||||
RowAdd=SpriteWidth-TotalRowLength;
|
||||
|
||||
if (add>0)
|
||||
ftcp += add+RowAdd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
for (unsigned int i=0; i<SpriteHeight; i++)
|
||||
{
|
||||
BaseOffset = BaseOffsetor + SDL_SwapLE16(read_unaligned_u16(FDef + BaseOffsetor+i*2*(SpriteWidth/32)));
|
||||
if (LeftMargin>0)
|
||||
ftcp += LeftMargin;
|
||||
|
||||
TotalRowLength=0;
|
||||
|
||||
do
|
||||
{
|
||||
SegmentType=FDef[BaseOffset++];
|
||||
unsigned char code = SegmentType / 32;
|
||||
unsigned char value = (SegmentType & 31) + 1;
|
||||
|
||||
int len = std::min<unsigned int>(value, SpriteWidth - TotalRowLength) - std::max(0, -LeftMargin);
|
||||
amax(len, 0);
|
||||
|
||||
if (code==7)
|
||||
{
|
||||
memcpy((ui8*)ret->pixels + ftcp, FDef + BaseOffset, len);
|
||||
ftcp += len;
|
||||
BaseOffset += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset((ui8*)ret->pixels + ftcp, code, len);
|
||||
ftcp += len;
|
||||
}
|
||||
TotalRowLength+=( LeftMargin>=0 ? value : value+LeftMargin );
|
||||
}
|
||||
while (TotalRowLength<SpriteWidth);
|
||||
|
||||
if (RightMargin>0)
|
||||
ftcp += RightMargin;
|
||||
|
||||
RowAdd=SpriteWidth-TotalRowLength;
|
||||
|
||||
if (add>0)
|
||||
ftcp += add+RowAdd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::string("Unknown sprite format.");
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_Color ttcol = ret->format->palette->colors[0];
|
||||
Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.unused);
|
||||
SDL_SetColorKey(ret, SDL_SRCCOLORKEY, keycol);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BMPPalette * CDefFile::getPalette()
|
||||
{
|
||||
BMPPalette * ret = new BMPPalette[256];
|
||||
memcpy(ret, colors, sizeof(BMPPalette)*256);
|
||||
return ret;
|
||||
}
|
||||
|
||||
CDefFile::CDefFile(std::string Name):data(NULL),colors(NULL)
|
||||
{
|
||||
data = spriteh->giveFile(Name, &datasize);
|
||||
if (!data)
|
||||
{
|
||||
tlog0<<"Error: file "<< Name <<" not found\n";
|
||||
return;
|
||||
}
|
||||
|
||||
colors = new BMPPalette[256];
|
||||
int it = 0;
|
||||
|
||||
//int type = readNormalNr(data, it); it+=4;
|
||||
//int width = readNormalNr(data, it); it+=4;//not used
|
||||
//int height = readNormalNr(data, it); it+=4;
|
||||
it+=12;
|
||||
unsigned int totalBlocks = readNormalNr(data, it);
|
||||
it+=4;
|
||||
|
||||
for (unsigned int i=0; i<256; i++)
|
||||
{
|
||||
colors[i].R = data[it++];
|
||||
colors[i].G = data[it++];
|
||||
colors[i].B = data[it++];
|
||||
colors[i].F = 0;
|
||||
}
|
||||
|
||||
offset.resize(totalBlocks);
|
||||
offList.insert(datasize);
|
||||
|
||||
for (unsigned int i=0; i<totalBlocks; i++)
|
||||
{
|
||||
it+=4;
|
||||
unsigned int totalEntries = readNormalNr(data, it);
|
||||
it+=12;
|
||||
|
||||
//13 bytes for name of every frame in this block - not used, skipping
|
||||
it+= 13 * totalEntries;
|
||||
|
||||
for (unsigned int j=0; j<totalEntries; j++)
|
||||
{
|
||||
size_t currOffset = readNormalNr(data, it);
|
||||
offset[i].push_back(currOffset);
|
||||
offList.insert(currOffset);
|
||||
it += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned char * CDefFile::getFrame(size_t frame, size_t group) const
|
||||
{
|
||||
if (offset.size() > group)
|
||||
{
|
||||
if (offset[group].size() > frame)
|
||||
{
|
||||
size_t offs = offset[group][frame];
|
||||
|
||||
std::set<size_t>::iterator it = offList.find(offs);
|
||||
|
||||
if (it == offList.end() || ++it == offList.end())
|
||||
tlog0<<"Error: offset not found!\n";
|
||||
|
||||
size_t size = *it - offs;
|
||||
|
||||
unsigned char * ret = new unsigned char[size];
|
||||
memcpy(ret, data+offs, size);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CDefFile::~CDefFile()
|
||||
{
|
||||
delete[] data;
|
||||
delete[] colors;
|
||||
}
|
||||
|
||||
bool CDefFile::loaded() const
|
||||
{
|
||||
return data != NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* CAnimation for animations handling, can load part of file if needed *
|
||||
*************************************************************************/
|
||||
|
||||
CAnimation::AnimEntry::AnimEntry():
|
||||
surf(NULL),
|
||||
source(0),
|
||||
refCount(0),
|
||||
data(NULL),
|
||||
dataSize(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool CAnimation::loadFrame(CDefFile * file, size_t frame, size_t group)
|
||||
{
|
||||
if (groupSize(group) <= frame)
|
||||
return false;
|
||||
AnimEntry &e = entries[group][frame];
|
||||
|
||||
if (e.surf || e.data)
|
||||
{
|
||||
e.refCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e.source & 6)//load frame with SDL_Image
|
||||
{
|
||||
int size;
|
||||
unsigned char * pic = NULL;
|
||||
|
||||
std::ostringstream str;
|
||||
if ( e.source & 2 )
|
||||
str << name << '#' << (group+1) << '#' << (frame+1); // file#12#34.*
|
||||
else
|
||||
str << name << '#' << (frame+1);//file#34.*
|
||||
|
||||
pic = spriteh->giveFile(str.str(), &size);
|
||||
if (pic)
|
||||
{
|
||||
if (compressed)
|
||||
{
|
||||
e.data = pic;
|
||||
e.dataSize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
e.surf = IMG_Load_RW( SDL_RWFromMem((void*)pic, size), 1);
|
||||
delete pic;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (file && e.source & 1)//try to get image from def
|
||||
{
|
||||
if (compressed)
|
||||
e.data = file->getFrame(frame, group);
|
||||
else
|
||||
e.surf = file->loadFrame(frame, group);
|
||||
}
|
||||
|
||||
if (!(e.surf || e.data))
|
||||
return false;//failed to load
|
||||
|
||||
e.refCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAnimation::unloadFrame(size_t frame, size_t group)
|
||||
{
|
||||
if (groupSize(group) > frame && entries[group][frame].refCount)
|
||||
{
|
||||
AnimEntry &e = entries[group][frame];
|
||||
if (--e.refCount)//not last ref
|
||||
return true;
|
||||
|
||||
SDL_FreeSurface(e.surf);
|
||||
delete e.data;
|
||||
|
||||
e.surf = NULL;
|
||||
e.data = NULL;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CAnimation::decompress(AnimEntry &entry)
|
||||
{
|
||||
if (entry.source & 6)//load frame with SDL_Image
|
||||
entry.surf = IMG_Load_RW( SDL_RWFromMem((void*)entry.data, entry.dataSize), 1);
|
||||
|
||||
else if (entry.source & 1)
|
||||
entry.surf = CDefFile::loadFrame(entry.data, defPalette);
|
||||
}
|
||||
|
||||
void CAnimation::init(CDefFile * file)
|
||||
{
|
||||
if (compressed)
|
||||
defPalette = file->getPalette();
|
||||
|
||||
for (size_t group = 0; ; group++)
|
||||
{
|
||||
std::vector<AnimEntry> toAdd;
|
||||
|
||||
for (size_t frame = 0; ; frame++)
|
||||
{
|
||||
unsigned char res=0;
|
||||
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << name << '#' << (group+1) << '#' << (frame+1); // format: file#12#34.*
|
||||
if (spriteh->haveFile(str.str()))
|
||||
res |= 2;
|
||||
}
|
||||
|
||||
if (group == 0)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << name << '#' << (frame+1);// format: file#34.*
|
||||
if ( spriteh->haveFile(str.str()))
|
||||
res |=4;
|
||||
}
|
||||
|
||||
if (file)//we have def too. try to get image from def
|
||||
{
|
||||
if (file->haveFrame(frame, group))
|
||||
res |=1;
|
||||
}
|
||||
|
||||
if (res)
|
||||
{
|
||||
toAdd.push_back(AnimEntry());
|
||||
toAdd.back().source = res;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!toAdd.empty())
|
||||
{
|
||||
entries.push_back(toAdd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CDefFile * CAnimation::getFile() const
|
||||
{
|
||||
CDefFile * file = new CDefFile(name);
|
||||
if (!file->loaded())
|
||||
{
|
||||
delete file;
|
||||
return NULL;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
void CAnimation::printError(size_t frame, size_t group, std::string type) const
|
||||
{
|
||||
tlog0 << type <<" error: Request for frame not present in CAnimation!\n"
|
||||
<<"\tFile name: "<<name<<" Group: "<<group<<" Frame: "<<frame<<"\n";
|
||||
}
|
||||
|
||||
CAnimation::CAnimation(std::string Name, bool Compressed):
|
||||
name(Name),
|
||||
compressed(Compressed),
|
||||
defPalette(NULL)
|
||||
{
|
||||
std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))toupper);
|
||||
int dotPos = name.find_last_of('.');
|
||||
if ( dotPos != -1 )
|
||||
name.erase(dotPos);
|
||||
|
||||
CDefFile * file = getFile();
|
||||
init(file);
|
||||
delete file;
|
||||
}
|
||||
|
||||
CAnimation::CAnimation():
|
||||
name(""),
|
||||
compressed(false),
|
||||
defPalette(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CAnimation::~CAnimation()
|
||||
{
|
||||
delete defPalette;
|
||||
|
||||
for (size_t i = 0; i < entries.size(); i++)
|
||||
for (size_t j = 0; j < entries.at(i).size(); j++)
|
||||
{
|
||||
delete entries[i][j].data;
|
||||
if (entries[i][j].surf)
|
||||
SDL_FreeSurface(entries[i][j].surf);
|
||||
}
|
||||
}
|
||||
|
||||
void CAnimation::add(SDL_Surface * surf, bool shared, size_t group)
|
||||
{
|
||||
if (!surf)
|
||||
return;
|
||||
|
||||
if (entries.size() <= group)
|
||||
entries.resize(group+1);
|
||||
|
||||
if (shared)
|
||||
surf->refcount++;
|
||||
|
||||
entries[group].push_back(AnimEntry());
|
||||
entries[group].back().refCount = 1;
|
||||
entries[group].back().surf = surf;
|
||||
}
|
||||
|
||||
void CAnimation::purgeCompressed()
|
||||
{
|
||||
for (size_t group; group < entries.size(); group++)
|
||||
for (size_t frame; frame < entries[group].size(); frame++)
|
||||
if (entries[group][frame].surf)
|
||||
SDL_FreeSurface(entries[group][frame].surf);
|
||||
}
|
||||
|
||||
SDL_Surface * CAnimation::image(size_t frame)
|
||||
{
|
||||
size_t group=0;
|
||||
for (; group<entries.size() && frame > entries[group].size(); group++)
|
||||
frame -= entries[group].size();
|
||||
|
||||
return image(frame, group);
|
||||
}
|
||||
|
||||
SDL_Surface * CAnimation::image(size_t frame, size_t group)
|
||||
{
|
||||
if ( groupSize(group) > frame )
|
||||
{
|
||||
AnimEntry &e = entries[group][frame];
|
||||
if (!e.surf && e.data)
|
||||
decompress(e);
|
||||
return e.surf;
|
||||
}
|
||||
|
||||
printError(frame, group, "GetImage");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CAnimation::load()
|
||||
{
|
||||
CDefFile * file = getFile();
|
||||
|
||||
for (size_t group = 0; group<entries.size(); group++)
|
||||
for (size_t frame = 0; frame<entries[group].size(); frame++)
|
||||
loadFrame(file, frame, group);
|
||||
|
||||
delete file;
|
||||
}
|
||||
|
||||
void CAnimation::unload()
|
||||
{
|
||||
for (size_t group = 0; group<entries.size(); group++)
|
||||
for (size_t frame = 0; frame<entries[group].size(); frame++)
|
||||
unloadFrame(frame, group);
|
||||
}
|
||||
|
||||
void CAnimation::loadGroup(size_t group)
|
||||
{
|
||||
CDefFile * file = getFile();
|
||||
|
||||
for (size_t frame = 0; frame<entries[group].size(); frame++)
|
||||
loadFrame(file, frame, group);
|
||||
}
|
||||
|
||||
void CAnimation::unloadGroup(size_t group)
|
||||
{
|
||||
for (size_t frame = 0; frame<entries[group].size(); frame++)
|
||||
unloadFrame(frame, group);
|
||||
}
|
||||
|
||||
void CAnimation::load(size_t frame, size_t group)
|
||||
{
|
||||
CDefFile * file = getFile();
|
||||
loadFrame(file, frame, group);
|
||||
delete file;
|
||||
}
|
||||
|
||||
void CAnimation::unload(size_t frame, size_t group)
|
||||
{
|
||||
unloadFrame(frame, group);
|
||||
}
|
||||
|
||||
void CAnimation::load(std::vector <std::pair <size_t, size_t> > frames)
|
||||
{
|
||||
CDefFile * file = getFile();
|
||||
for (size_t i=0; i<frames.size(); i++)
|
||||
loadFrame(file, frames[i].second, frames[i].first);
|
||||
delete file;
|
||||
}
|
||||
|
||||
void CAnimation::unload(std::vector <std::pair <size_t, size_t> > frames)
|
||||
{
|
||||
for (size_t i=0; i<frames.size(); i++)
|
||||
unloadFrame(frames[i].second, frames[i].first);
|
||||
}
|
||||
|
||||
void CAnimation::fixButtonPos()
|
||||
{
|
||||
if ( groupSize(0) > 1 )
|
||||
std::swap(entries[0][1].surf, entries[0][0].surf);
|
||||
}
|
||||
|
||||
size_t CAnimation::groupSize(size_t group) const
|
||||
{
|
||||
if (entries.size() > group)
|
||||
return entries[group].size();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t CAnimation::size() const
|
||||
{
|
||||
size_t ret=0;
|
||||
for (size_t i=0; i<entries.size(); i++)
|
||||
{
|
||||
ret += entries[i].size();
|
||||
}
|
||||
return ret;
|
||||
}
|
177
hch/CAnimation.h
Normal file
177
hch/CAnimation.h
Normal file
@ -0,0 +1,177 @@
|
||||
#ifndef __CANIMATION_H__
|
||||
#define __CANIMATION_H__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "../global.h"
|
||||
|
||||
/*
|
||||
* CAnimation.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
|
||||
*
|
||||
*/
|
||||
|
||||
struct SDL_Surface;
|
||||
struct BMPPalette;
|
||||
|
||||
//class for def loading, methods are based on CDefHandler
|
||||
//after loading will store general info (palette and frame offsets) and pointer to file itself
|
||||
class CDefFile
|
||||
{
|
||||
private:
|
||||
|
||||
struct SSpriteDef
|
||||
{
|
||||
ui32 prSize;
|
||||
ui32 defType2;
|
||||
ui32 FullWidth;
|
||||
ui32 FullHeight;
|
||||
ui32 SpriteWidth;
|
||||
ui32 SpriteHeight;
|
||||
ui32 LeftMargin;
|
||||
ui32 TopMargin;
|
||||
};
|
||||
|
||||
unsigned char * data;
|
||||
int datasize;
|
||||
BMPPalette * colors;
|
||||
|
||||
//offset[group][frame] - offset of frame data in file
|
||||
std::vector< std::vector <size_t> > offset;
|
||||
|
||||
//sorted list of offsets used to determine size
|
||||
std::set <size_t> offList;
|
||||
|
||||
|
||||
public:
|
||||
CDefFile(std::string Name);
|
||||
~CDefFile();
|
||||
|
||||
//true if file was opened correctly
|
||||
bool loaded() const;
|
||||
|
||||
//get copy of palette to unpack compressed animation
|
||||
BMPPalette * getPalette();
|
||||
|
||||
//true if frame is present in it
|
||||
bool haveFrame(size_t frame, size_t group) const;
|
||||
|
||||
//get copy of binary data
|
||||
unsigned char * getFrame(size_t frame, size_t group) const;
|
||||
|
||||
//load frame as SDL_Surface
|
||||
SDL_Surface * loadFrame(size_t frame, size_t group) const ;
|
||||
|
||||
//static version of previous one for calling from compressed anim
|
||||
static SDL_Surface * loadFrame(const unsigned char * FDef, const BMPPalette * palette);
|
||||
};
|
||||
|
||||
// Class for handling animation.
|
||||
class CAnimation
|
||||
{
|
||||
private:
|
||||
|
||||
//internal structure to hold all data of specific frame
|
||||
struct AnimEntry
|
||||
{
|
||||
//surface for this entry
|
||||
SDL_Surface * surf;
|
||||
|
||||
//bitfield, location of image data: 1 - def, 2 - file#9.*, 4 - file#9#2.*
|
||||
unsigned char source;
|
||||
|
||||
//reference count, changed by loadFrame \ unloadFrame
|
||||
size_t refCount;
|
||||
|
||||
//data for CompressedAnim
|
||||
unsigned char * data;
|
||||
|
||||
//size of compressed data, unused for def files
|
||||
size_t dataSize;
|
||||
|
||||
AnimEntry();
|
||||
};
|
||||
|
||||
//animation file name
|
||||
std::string name;
|
||||
|
||||
//if true all frames will be stored in compressed state
|
||||
const bool compressed;
|
||||
|
||||
//palette from def file, used only for compressed anim
|
||||
BMPPalette * defPalette;
|
||||
|
||||
//entries[group][position], store all info regarding frames
|
||||
std::vector< std::vector <AnimEntry> > entries;
|
||||
|
||||
//loader, will be called by load(), require opened def file for loading from it. Returns true if image is loaded
|
||||
bool loadFrame(CDefFile * file, size_t frame, size_t group);
|
||||
|
||||
//unloadFrame, returns true if image has been unloaded ( either deleted or decreased refCount)
|
||||
bool unloadFrame(size_t frame, size_t group);
|
||||
|
||||
//decompress entry data
|
||||
void decompress(AnimEntry &entry);
|
||||
|
||||
//initialize animation from file
|
||||
void init(CDefFile * file);
|
||||
|
||||
//try to open def file
|
||||
CDefFile * getFile() const;
|
||||
|
||||
//to get rid of copy-pasting error message :]
|
||||
void printError(size_t frame, size_t group, std::string type) const;
|
||||
|
||||
public:
|
||||
|
||||
CAnimation(std::string Name, bool Compressed = false);
|
||||
CAnimation();
|
||||
~CAnimation();
|
||||
|
||||
//add custom surface to the end of specific group. If shared==true surface needs to be deleted
|
||||
//somewhere outside of CAnim as well (SDL_Surface::refcount will be increased)
|
||||
void add(SDL_Surface * surf, bool shared=false, size_t group=0);
|
||||
|
||||
//removes all surfaces which have compressed data
|
||||
void purgeCompressed();
|
||||
|
||||
//get pointer to surface, this function ignores groups (like ourImages in DefHandler)
|
||||
SDL_Surface * image (size_t frame);
|
||||
|
||||
//get pointer to surface, from specific group
|
||||
SDL_Surface * image(size_t frame, size_t group);
|
||||
|
||||
//all available frames
|
||||
void load ();
|
||||
void unload();
|
||||
|
||||
//all frames from group
|
||||
void loadGroup (size_t group);
|
||||
void unloadGroup(size_t group);
|
||||
|
||||
//single image
|
||||
void load (size_t frame, size_t group=0);
|
||||
void unload(size_t frame, size_t group=0);
|
||||
|
||||
//list of frames (first = group ID, second = frame ID)
|
||||
void load (std::vector <std::pair <size_t, size_t> > frames);
|
||||
void unload(std::vector <std::pair <size_t, size_t> > frames);
|
||||
|
||||
//helper to fix frame order on some buttons
|
||||
void fixButtonPos();
|
||||
|
||||
//size of specific group, 0 if not present
|
||||
size_t groupSize(size_t group) const;
|
||||
|
||||
//total count of frames in whole anim
|
||||
size_t size() const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // __CANIMATIONHANDLER_H__
|
@ -119,6 +119,17 @@ unsigned char * CLodHandler::giveFile(std::string defName, int * length)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CLodHandler::haveFile(std::string name)
|
||||
{
|
||||
std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))toupper);
|
||||
int dotPos = name.find_last_of('.');
|
||||
if ( dotPos != -1 )
|
||||
name.erase(dotPos);
|
||||
|
||||
Entry * ourEntry = entries.znajdz(Entry(name));
|
||||
return ourEntry != NULL;
|
||||
}
|
||||
|
||||
DLL_EXPORT int CLodHandler::infs2(unsigned char * in, int size, int realSize, unsigned char *& out, int wBits)
|
||||
{
|
||||
int ret;
|
||||
@ -232,12 +243,15 @@ void CLodHandler::init(std::string lodFile, std::string dirName)
|
||||
std::transform(entry.nameStr.begin(), entry.nameStr.end(),
|
||||
entry.nameStr.begin(), toupper);
|
||||
|
||||
int dotPos = entry.nameStr.find_last_of('.');
|
||||
std::string ext = entry.nameStr.substr(dotPos);
|
||||
if (ext == ".MSK" || ext == ".MSG")
|
||||
entry.nameStr[dotPos] = '#';//this files have same name as def - rename to defName#msk
|
||||
else
|
||||
entry.nameStr.erase(dotPos);//filename.ext becomes filename
|
||||
size_t dotPos = entry.nameStr.find_last_of('.');
|
||||
if ( dotPos < entry.nameStr.size() )
|
||||
{
|
||||
std::string ext = entry.nameStr.substr(dotPos);
|
||||
if (ext == ".MSK" || ext == ".MSG")
|
||||
entry.nameStr[dotPos] = '#';//this files have same name as def - rename to defName#msk
|
||||
else
|
||||
entry.nameStr.erase(dotPos);//filename.ext becomes filename
|
||||
}
|
||||
|
||||
entry.offset= SDL_SwapLE32(lodEntries[i].offset);
|
||||
entry.realSize = SDL_SwapLE32(lodEntries[i].uncompressedSize);
|
||||
@ -259,12 +273,15 @@ void CLodHandler::init(std::string lodFile, std::string dirName)
|
||||
std::string realname = name;
|
||||
std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))toupper);
|
||||
|
||||
int dotPos = name.find_last_of('.');
|
||||
std::string ext = name.substr(dotPos);
|
||||
if (ext == ".MSK" || ext == ".MSG")
|
||||
name[dotPos] = '#';//this files have same name as def - rename to defName#msk
|
||||
else
|
||||
name.erase(dotPos);//filename.ext becomes filename
|
||||
size_t dotPos = name.find_last_of('.');
|
||||
if ( dotPos < name.size() )
|
||||
{
|
||||
std::string ext = name.substr(dotPos);
|
||||
if (ext == ".MSK" || ext == ".MSG")
|
||||
name[dotPos] = '#';//this files have same name as def - rename to defName#msk
|
||||
else
|
||||
name.erase(dotPos);//filename.ext becomes filename
|
||||
}
|
||||
|
||||
Entry * e = entries.znajdz(name);
|
||||
if(e) //file present in .lod - overwrite its entry
|
||||
|
@ -77,6 +77,7 @@ public:
|
||||
~CLodHandler();
|
||||
int infs2(unsigned char * in, int size, int realSize, unsigned char*& out, int wBits=15); //zlib fast handler
|
||||
unsigned char * giveFile(std::string defName, int * length=NULL); //returns pointer to the decompressed data - it must be deleted when no longer needed!
|
||||
bool haveFile(std::string name);//check if file is present in lod
|
||||
std::string getTextFile(std::string name); //extracts one file
|
||||
void extractFile(std::string FName, std::string name); //extracts a specific file
|
||||
void init(std::string lodFile, std::string dirName);
|
||||
|
@ -283,10 +283,10 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* getVectorItemFromId(const VectorisedObjectInfo<T> &oInfo, si32 id) const
|
||||
T* getVectorItemFromId(const VectorisedObjectInfo<T> &oInfo, ui32 id) const
|
||||
{
|
||||
if(id < 0)
|
||||
return NULL;
|
||||
/* if(id < 0)
|
||||
return NULL;*/
|
||||
|
||||
assert(oInfo.vector);
|
||||
assert(oInfo.vector->size() > id);
|
||||
@ -673,14 +673,14 @@ public:
|
||||
typedef typename VectorisedTypeFor<TObjectType>::type VType; //eg: CGHeroInstance -> CGobjectInstance
|
||||
if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
|
||||
{
|
||||
si32 id;
|
||||
ui32 id;
|
||||
*this >> id;
|
||||
data = static_cast<T>(getVectorItemFromId(*info, id));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ui32 pid = -1; //pointer id (or maybe rather pointee id)
|
||||
ui32 pid = 0xffffffff; //pointer id (or maybe rather pointee id)
|
||||
if(smartPointerSerialization)
|
||||
{
|
||||
*this >> pid; //get the id
|
||||
@ -721,7 +721,7 @@ public:
|
||||
template <typename T>
|
||||
void ptrAllocated(const T *ptr, ui32 pid)
|
||||
{
|
||||
if(smartPointerSerialization && pid != -1)
|
||||
if(smartPointerSerialization && pid != 0xffffffff)
|
||||
loadedPointers[pid] = (void*)ptr; //add loaded pointer to our lookup map; cast is to avoid errors with const T* pt
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user