|
@@ -23,143 +23,10 @@
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
-class SDLImageLoader;
|
|
|
-class CompImageLoader;
|
|
|
-
|
|
|
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
|
|
|
-/// After loading will store general info (palette and frame offsets) and pointer to file itself
|
|
|
-class CDefFile
|
|
|
-{
|
|
|
-private:
|
|
|
-
|
|
|
- struct SSpriteDef
|
|
|
- {
|
|
|
- ui32 size;
|
|
|
- ui32 format; /// format in which pixel data is stored
|
|
|
- ui32 fullWidth; /// full width and height of frame, including borders
|
|
|
- ui32 fullHeight;
|
|
|
- ui32 width; /// width and height of pixel data, borders excluded
|
|
|
- ui32 height;
|
|
|
- si32 leftMargin;
|
|
|
- si32 topMargin;
|
|
|
- } PACKED_STRUCT;
|
|
|
- //offset[group][frame] - offset of frame data in file
|
|
|
- std::map<size_t, std::vector <size_t> > offset;
|
|
|
-
|
|
|
- std::unique_ptr<ui8[]> data;
|
|
|
- std::unique_ptr<SDL_Color[]> palette;
|
|
|
-
|
|
|
-public:
|
|
|
- CDefFile(std::string Name);
|
|
|
- ~CDefFile();
|
|
|
-
|
|
|
- //load frame as SDL_Surface
|
|
|
- template<class ImageLoader>
|
|
|
- void loadFrame(size_t frame, size_t group, ImageLoader &loader) const;
|
|
|
-
|
|
|
- const std::map<size_t, size_t> getEntries() const;
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
- * Wrapper around SDL_Surface
|
|
|
- */
|
|
|
-class SDLImage : public IImage
|
|
|
-{
|
|
|
-public:
|
|
|
- //Surface without empty borders
|
|
|
- SDL_Surface * surf;
|
|
|
- //size of left and top borders
|
|
|
- Point margins;
|
|
|
- //total size including borders
|
|
|
- Point fullSize;
|
|
|
-
|
|
|
-public:
|
|
|
- //Load image from def file
|
|
|
- SDLImage(CDefFile *data, size_t frame, size_t group=0, bool compressed=false);
|
|
|
- //Load from bitmap file
|
|
|
- SDLImage(std::string filename, bool compressed=false);
|
|
|
- //Create using existing surface, extraRef will increase refcount on SDL_Surface
|
|
|
- SDLImage(SDL_Surface * from, bool extraRef);
|
|
|
- ~SDLImage();
|
|
|
-
|
|
|
- void draw(SDL_Surface * where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
|
|
- void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
|
|
|
- SDL_Surface * scaleFast(float scale) const override;
|
|
|
-
|
|
|
- void playerColored(PlayerColor player) override;
|
|
|
- void setFlagColor(PlayerColor player) override;
|
|
|
- int width() const override;
|
|
|
- int height() const override;
|
|
|
-
|
|
|
- void horizontalFlip() override;
|
|
|
- void verticalFlip() override;
|
|
|
-
|
|
|
- void shiftPalette(int from, int howMany) override;
|
|
|
-
|
|
|
- friend class SDLImageLoader;
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * RLE-compressed image data for 8-bit images with alpha-channel, currently far from finished
|
|
|
- * primary purpose is not high compression ratio but fast drawing.
|
|
|
- * Consist of repeatable segments with format similar to H3 def compression:
|
|
|
- * 1st byte:
|
|
|
- * if (byte == 0xff)
|
|
|
- * raw data, opaque and semi-transparent data always in separate blocks
|
|
|
- * else
|
|
|
- * RLE-compressed image data with this color
|
|
|
- * 2nd byte = size of segment
|
|
|
- * raw data (if any)
|
|
|
- */
|
|
|
-class CompImage : public IImage
|
|
|
-{
|
|
|
- //x,y - margins, w,h - sprite size
|
|
|
- Rect sprite;
|
|
|
- //total size including borders
|
|
|
- Point fullSize;
|
|
|
-
|
|
|
- //RLE-d data
|
|
|
- ui8 * surf;
|
|
|
- //array of offsets for each line
|
|
|
- ui32 * line;
|
|
|
- //palette
|
|
|
- SDL_Color *palette;
|
|
|
-
|
|
|
- //Used internally to blit one block of data
|
|
|
- template<int bpp, int dir>
|
|
|
- void BlitBlock(ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha) const;
|
|
|
- void BlitBlockWithBpp(ui8 bpp, ui8 type, ui8 size, ui8 *&data, ui8 *&dest, ui8 alpha, bool rotated) const;
|
|
|
-
|
|
|
-public:
|
|
|
- //Load image from def file
|
|
|
- CompImage(const CDefFile *data, size_t frame, size_t group=0);
|
|
|
- //TODO: load image from SDL_Surface
|
|
|
- CompImage(SDL_Surface * surf);
|
|
|
- ~CompImage();
|
|
|
-
|
|
|
- void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
|
|
- void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
|
|
|
-
|
|
|
- SDL_Surface * scaleFast(float scale) const override;
|
|
|
-
|
|
|
- void playerColored(PlayerColor player) override;
|
|
|
- void setFlagColor(PlayerColor player) override;
|
|
|
- int width() const override;
|
|
|
- int height() const override;
|
|
|
-
|
|
|
- void horizontalFlip() override;
|
|
|
- void verticalFlip() override;
|
|
|
-
|
|
|
- void shiftPalette(int from, int howMany) override;
|
|
|
-
|
|
|
- friend class CompImageLoader;
|
|
|
-};
|
|
|
-
|
|
|
class SDLImageLoader
|
|
|
{
|
|
|
SDLImage * image;
|
|
@@ -347,7 +214,7 @@ void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const
|
|
|
//pixel data is not compressed, copy data to surface
|
|
|
for (ui32 i=0; i<sprite.height; i++)
|
|
|
{
|
|
|
- loader.Load(sprite.width, FDef + currentOffset);
|
|
|
+ loader.Load(sprite.width, FDef[currentOffset]);
|
|
|
currentOffset += sprite.width;
|
|
|
loader.EndLine();
|
|
|
}
|
|
@@ -769,69 +636,30 @@ void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha
|
|
|
if (!surf)
|
|
|
return;
|
|
|
|
|
|
- Rect destRect(posX, posY, surf->w, surf->h);
|
|
|
-
|
|
|
- draw(where, &destRect, src);
|
|
|
-}
|
|
|
-
|
|
|
-void SDLImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha) const
|
|
|
-{
|
|
|
- if (!surf)
|
|
|
- return;
|
|
|
-
|
|
|
- Rect sourceRect(0, 0, surf->w, surf->h);
|
|
|
-
|
|
|
- Point destShift(0,0);
|
|
|
-
|
|
|
- if(src)
|
|
|
- {
|
|
|
- if(src->x < margins.x)
|
|
|
- destShift.x += margins.x - src->x;
|
|
|
-
|
|
|
- if(src->y < margins.y)
|
|
|
- destShift.y += margins.y - src->y;
|
|
|
-
|
|
|
- sourceRect = Rect(*src) & Rect(margins.x, margins.y, surf->w, surf->h);
|
|
|
-
|
|
|
- sourceRect -= margins;
|
|
|
- }
|
|
|
- else
|
|
|
- destShift = margins;
|
|
|
-
|
|
|
- Rect destRect(margins.x, margins.y, surf->w, surf->h);
|
|
|
-
|
|
|
- if(dest)
|
|
|
+ Rect sourceRect(margins.x, margins.y, surf->w, surf->h);
|
|
|
+ //TODO: rotation and scaling
|
|
|
+ if (src)
|
|
|
{
|
|
|
- destRect = *dest;
|
|
|
-
|
|
|
- destRect = destRect & Rect(destRect.x, destRect.y, sourceRect.w, sourceRect.h);
|
|
|
-
|
|
|
- destRect += destShift;
|
|
|
+ sourceRect = sourceRect & *src;
|
|
|
}
|
|
|
+ Rect destRect(posX, posY, surf->w, surf->h);
|
|
|
+ destRect += sourceRect.topLeft();
|
|
|
+ sourceRect -= margins;
|
|
|
|
|
|
if(surf->format->BitsPerPixel == 8)
|
|
|
{
|
|
|
CSDL_Ext::blit8bppAlphaTo24bpp(surf, &sourceRect, where, &destRect);
|
|
|
}
|
|
|
- else
|
|
|
+ else if(surf->format->Amask == 0)
|
|
|
{
|
|
|
- SDL_UpperBlit(surf, &sourceRect, where, &destRect);
|
|
|
+ SDL_BlitSurface(surf, &sourceRect, where, &destRect);
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-SDL_Surface * SDLImage::scaleFast(float scale) const
|
|
|
-{
|
|
|
- //todo: margins
|
|
|
- auto scaled = CSDL_Ext::scaleSurfaceFast(surf, surf->w * scale, surf->h * scale);
|
|
|
-
|
|
|
- if (scaled->format && scaled->format->palette) // fix color keying, because SDL loses it at this point
|
|
|
- CSDL_Ext::setColorKey(scaled, scaled->format->palette->colors[0]);
|
|
|
- else if(scaled->format && scaled->format->Amask)
|
|
|
- SDL_SetSurfaceBlendMode(scaled, SDL_BLENDMODE_BLEND);//just in case
|
|
|
else
|
|
|
- CSDL_Ext::setDefaultColorKey(scaled);//just in case
|
|
|
-
|
|
|
- return scaled;
|
|
|
+ {
|
|
|
+ SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_BLEND);
|
|
|
+ SDL_BlitSurface(surf, &sourceRect, where, &destRect);
|
|
|
+ SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void SDLImage::playerColored(PlayerColor player)
|
|
@@ -839,12 +667,6 @@ void SDLImage::playerColored(PlayerColor player)
|
|
|
graphics->blueToPlayersAdv(surf, player);
|
|
|
}
|
|
|
|
|
|
-void SDLImage::setFlagColor(PlayerColor player)
|
|
|
-{
|
|
|
- if(player < PlayerColor::PLAYER_LIMIT || player==PlayerColor::NEUTRAL)
|
|
|
- CSDL_Ext::setPlayerColor(surf, player);
|
|
|
-}
|
|
|
-
|
|
|
int SDLImage::width() const
|
|
|
{
|
|
|
return fullSize.x;
|
|
@@ -855,45 +677,6 @@ int SDLImage::height() const
|
|
|
return fullSize.y;
|
|
|
}
|
|
|
|
|
|
-void SDLImage::horizontalFlip()
|
|
|
-{
|
|
|
- SDL_Surface * flipped = CSDL_Ext::horizontalFlip(surf);
|
|
|
-
|
|
|
- SDL_FreeSurface(surf);
|
|
|
-
|
|
|
- surf = flipped;
|
|
|
-
|
|
|
- margins.y = fullSize.y - surf->h - margins.y;
|
|
|
-}
|
|
|
-
|
|
|
-void SDLImage::verticalFlip()
|
|
|
-{
|
|
|
- SDL_Surface * flipped = CSDL_Ext::verticalFlip(surf);
|
|
|
-
|
|
|
- SDL_FreeSurface(surf);
|
|
|
-
|
|
|
- surf = flipped;
|
|
|
-
|
|
|
- margins.x = fullSize.x - surf->w - margins.x;
|
|
|
-}
|
|
|
-
|
|
|
-void SDLImage::shiftPalette(int from, int howMany)
|
|
|
-{
|
|
|
- //works with at most 16 colors, if needed more -> increase values
|
|
|
- assert(howMany < 16);
|
|
|
-
|
|
|
- if(surf->format->palette)
|
|
|
- {
|
|
|
- SDL_Color palette[16];
|
|
|
-
|
|
|
- for(int i=0; i<howMany; ++i)
|
|
|
- {
|
|
|
- palette[(i+1)%howMany] = surf->format->palette->colors[from + i];
|
|
|
- }
|
|
|
- SDL_SetColors(surf, palette, from, howMany);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
SDLImage::~SDLImage()
|
|
|
{
|
|
|
SDL_FreeSurface(surf);
|
|
@@ -916,12 +699,6 @@ CompImage::CompImage(SDL_Surface * surf)
|
|
|
}
|
|
|
|
|
|
void CompImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 alpha) const
|
|
|
-{
|
|
|
- Rect dest(posX,posY, width(), height());
|
|
|
- draw(where, &dest, src, alpha);
|
|
|
-}
|
|
|
-
|
|
|
-void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alpha) const
|
|
|
{
|
|
|
int rotation = 0; //TODO
|
|
|
//rotation & 2 = horizontal rotation
|
|
@@ -936,18 +713,11 @@ void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alph
|
|
|
sourceRect = sourceRect & Rect(0, 0, where->w, where->h);
|
|
|
|
|
|
//Starting point on SDL surface
|
|
|
- Point dst(sourceRect.x,sourceRect.y);
|
|
|
-
|
|
|
- if (dest)
|
|
|
- {
|
|
|
- dst.x += dest->x;
|
|
|
- dst.y += dest->y;
|
|
|
- }
|
|
|
-
|
|
|
+ Point dest(posX+sourceRect.x, posY+sourceRect.y);
|
|
|
if (rotation & 2)
|
|
|
- dst.y += sourceRect.h;
|
|
|
+ dest.y += sourceRect.h;
|
|
|
if (rotation & 4)
|
|
|
- dst.x += sourceRect.w;
|
|
|
+ dest.x += sourceRect.w;
|
|
|
|
|
|
sourceRect -= sprite.topLeft();
|
|
|
|
|
@@ -978,10 +748,10 @@ void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alph
|
|
|
//Calculate position for blitting: pixels + Y + X
|
|
|
ui8* blitPos = (ui8*) where->pixels;
|
|
|
if (rotation & 4)
|
|
|
- blitPos += (dst.y - currY) * where->pitch;
|
|
|
+ blitPos += (dest.y - currY) * where->pitch;
|
|
|
else
|
|
|
- blitPos += (dst.y + currY) * where->pitch;
|
|
|
- blitPos += dst.x * bpp;
|
|
|
+ blitPos += (dest.y + currY) * where->pitch;
|
|
|
+ blitPos += dest.x * bpp;
|
|
|
|
|
|
//Blit blocks that must be fully visible
|
|
|
while (currX + size < sourceRect.w)
|
|
@@ -999,16 +769,6 @@ void CompImage::draw(SDL_Surface* where, SDL_Rect* dest, SDL_Rect* src, ui8 alph
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-SDL_Surface * CompImage::scaleFast(float scale) const
|
|
|
-{
|
|
|
- //todo: CompImage::scaleFast
|
|
|
-
|
|
|
- logAnim->error("CompImage::scaleFast is not implemented");
|
|
|
-
|
|
|
- return CSDL_Ext::newSurface(width() * scale, height() * scale);
|
|
|
-}
|
|
|
-
|
|
|
#define CASEBPP(x,y) case x: BlitBlock<x,y>(type, size, data, dest, alpha); break
|
|
|
|
|
|
//FIXME: better way to get blitter
|
|
@@ -1123,11 +883,6 @@ void CompImage::playerColored(PlayerColor player)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CompImage::setFlagColor(PlayerColor player)
|
|
|
-{
|
|
|
- logAnim->error("CompImage::setFlagColor is not implemented");
|
|
|
-}
|
|
|
-
|
|
|
int CompImage::width() const
|
|
|
{
|
|
|
return fullSize.x;
|
|
@@ -1145,22 +900,6 @@ CompImage::~CompImage()
|
|
|
delete [] palette;
|
|
|
}
|
|
|
|
|
|
-void CompImage::horizontalFlip()
|
|
|
-{
|
|
|
- logAnim->error("CompImage::horizontalFlip is not implemented");
|
|
|
-}
|
|
|
-
|
|
|
-void CompImage::verticalFlip()
|
|
|
-{
|
|
|
- logAnim->error("CompImage::verticalFlip is not implemented");
|
|
|
-}
|
|
|
-
|
|
|
-void CompImage::shiftPalette(int from, int howMany)
|
|
|
-{
|
|
|
- logAnim->error("CompImage::shiftPalette is not implemented");
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/*************************************************************************
|
|
|
* CAnimation for animations handling, can load part of file if needed *
|
|
|
*************************************************************************/
|
|
@@ -1177,7 +916,6 @@ IImage * CAnimation::getFromExtraDef(std::string filename)
|
|
|
pos = filename.find(':', pos);
|
|
|
if (pos != -1)
|
|
|
{
|
|
|
- pos++;
|
|
|
group = frame;
|
|
|
frame = atoi(filename.c_str()+pos);
|
|
|
}
|
|
@@ -1225,7 +963,7 @@ bool CAnimation::loadFrame(CDefFile * file, size_t frame, size_t group)
|
|
|
}
|
|
|
else //load from separate file
|
|
|
{
|
|
|
- std::string filename = source[group][frame]["file"].String();
|
|
|
+ std::string filename = source[group][frame].Struct().find("file")->second.String();
|
|
|
|
|
|
IImage * img = getFromExtraDef(filename);
|
|
|
if (!img)
|
|
@@ -1367,25 +1105,6 @@ CAnimation::~CAnimation()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup)
|
|
|
-{
|
|
|
- //todo: clone actual loaded Image object
|
|
|
- JsonNode clone(source[sourceGroup][sourceFrame]);
|
|
|
-
|
|
|
- if(clone.getType() == JsonNode::DATA_NULL)
|
|
|
- {
|
|
|
- std::string temp = name+":"+boost::lexical_cast<std::string>(sourceGroup)+":"+boost::lexical_cast<std::string>(sourceFrame);
|
|
|
- clone["file"].String() = temp;
|
|
|
- }
|
|
|
-
|
|
|
- source[targetGroup].push_back(clone);
|
|
|
-
|
|
|
- size_t index = source[targetGroup].size() - 1;
|
|
|
-
|
|
|
- if(preloaded)
|
|
|
- load(index, targetGroup);
|
|
|
-}
|
|
|
-
|
|
|
void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
|
|
|
{
|
|
|
if (source[group].size() <= frame)
|
|
@@ -1429,11 +1148,8 @@ void CAnimation::unload()
|
|
|
|
|
|
void CAnimation::preload()
|
|
|
{
|
|
|
- if(!preloaded)
|
|
|
- {
|
|
|
- preloaded = true;
|
|
|
- load();
|
|
|
- }
|
|
|
+ preloaded = true;
|
|
|
+ load();
|
|
|
}
|
|
|
|
|
|
void CAnimation::loadGroup(size_t group)
|