Commit 064ae5bc authored by Gerhard Stein's avatar Gerhard Stein

Support for 2-fold sprite bitmaps

parent 313bea2a
......@@ -32,7 +32,7 @@ string(REGEX REPLACE "[\r\n]" "" CG_VERSION "${CG_VERSION}")
# Since shell script get_version is not processed properly on windows, we have to define manually here.
# TODO: Better system for defining the version
IF(WIN32)
set(CG_VERSION "2.2.2")
set(CG_VERSION "2.2.3")
endif()
# Generate the README file with the correct version string
......
......@@ -42,6 +42,11 @@ void GsGraphics::createEmptySprites(const size_t numVar,
mSprite.assign(numVar, spriteVec);
}
void GsGraphics::appendSpriteVec(const std::vector<GsSprite> &spriteVec)
{
mSprite.push_back(spriteVec);
}
void GsGraphics::dumpSprites()
{
for(size_t i = 0; i < mSprite[0].size(); i++)
......
......@@ -40,6 +40,8 @@ public:
void createEmptySprites(const size_t numVar,
const size_t num_sprites);
void appendSpriteVec(const std::vector<GsSprite> &spriteVec);
void createEmptyBitmaps(Uint16 num_bmps);
void createEmptyMaskedBitmaps(Uint16 num_bmps);
void createEmptyMisGsBitmaps(Uint16 num_bmps);
......
......@@ -108,7 +108,7 @@ GsSprite::exportBitmap()
const GsWeakSurface weak = GsWeakSurface(mSurface);
GsBitmap bmp(weak);
bmp.trimWidth(bmp.width()/3);
bmp.trimWidth(bmp.width()/mFold);
return bmp;
}
......@@ -201,7 +201,47 @@ void GsSprite::generateSprite( const int points )
m_bboxY2=getHeight();
}
void GsSprite::detectFoldness()
{
// The foldness can be detected looking at the picture
// searching for the start of the bounding box color.
mFold = 3;
mSurface.lock();
auto *srcSfc = mSurface.getSDLSurface();
auto *pixPtr = (Uint8*)(srcSfc->pixels);
for( Uint8 x=0 ; x<srcSfc->w ; x++ )
{
Uint32 color = 0x0;
memcpy( &color, pixPtr, srcSfc->format->BytesPerPixel );
Uint8 r, g, b, a;
SDL_GetRGBA( color, srcSfc->format, &r, &g, &b, &a );
// Now test it
if( g == 0x55 && b == 0x55)
{
if(r == 0x55 || r == 0xff)
{
// Odd it this happens
if(x == 0) return;
// Found it!
if(srcSfc->w/x == 2)
mFold = 2;
return;
}
}
pixPtr += srcSfc->format->BytesPerPixel;
}
mSurface.unlock();
}
bool GsSprite::loadHQSprite( const std::string& filename )
{
......@@ -222,7 +262,9 @@ bool GsSprite::loadHQSprite( const std::string& filename )
mSurface.createCopy(bmpSfc);
mMaskSurface.createCopy(bmpSfc);
m_xsize = bmpSfc.width()/3;
detectFoldness();
m_xsize = bmpSfc.width()/mFold;
m_ysize = bmpSfc.height();
readMask(bmpSfc.getSDLSurface());
......@@ -233,21 +275,84 @@ bool GsSprite::loadHQSprite( const std::string& filename )
return true;
}
/**
* \brief Reads the mask of a created modkeen style bitmap und converts that mask to 8-bit
* so it can be applied to the others. This is for HQ Sprites, the other ones have an internal algorithm
*/
void GsSprite::readMask(SDL_Surface *srcSfc)
void GsSprite::readMask2Fold(SDL_Surface *srcSfc)
{
assert(srcSfc);
Uint8 *maskpx, *pixel;
Uint32 color = 0;
Uint8 mask = 0;
Uint8 r,g,b,a;
Uint8 *maskpx, *pixel;
Uint32 color = 0;
Uint8 mask = 0;
Uint8 r,g,b,a;
// We have three fragments in one bitmap. The second fragment is the mask
Uint16 w = (srcSfc->w)/mFold;
assert(w>0);
if(SDL_MUSTLOCK(srcSfc))
{
SDL_LockSurface(srcSfc);
}
mMaskSurface.lock();
auto maskSfc = mMaskSurface.getSDLSurface();
// In same occasions the dimensions are not exact. In that case, apply the minimum
const auto minW = std::min(Uint16(srcSfc->w/mFold), mMaskSurface.width());
const auto minH = std::min(Uint16(srcSfc->h), mMaskSurface.height());
Uint8* srcLinePtr = static_cast<Uint8*>(srcSfc->pixels);
Uint8* maskLinePtr = static_cast<Uint8*>(maskSfc->pixels);
for( Uint8 y=0 ; y<minH ; y++ )
{
pixel = srcLinePtr;
maskpx = maskLinePtr;
for( Uint8 x=0 ; x<minW ; x++ )
{
memcpy( &color, pixel, srcSfc->format->BytesPerPixel );
SDL_GetRGBA( color, srcSfc->format, &r, &g, &b, &a );
if(r == 0xcc && g == 0xff && b == 0xcc)
{
mask = 0;
}
else
{
mask = 16;
}
memcpy( maskpx, &mask, srcSfc->format->BytesPerPixel );
pixel += srcSfc->format->BytesPerPixel;
maskpx += maskSfc->format->BytesPerPixel;
}
srcLinePtr += srcSfc->w * srcSfc->format->BytesPerPixel;
maskLinePtr += maskSfc->w * maskSfc->format->BytesPerPixel;
}
mMaskSurface.unlock();
if(SDL_MUSTLOCK(srcSfc))
{
SDL_UnlockSurface(srcSfc);
}
}
void GsSprite::readMask3Fold(SDL_Surface *srcSfc)
{
assert(srcSfc);
Uint8 *maskpx, *pixel;
Uint32 color = 0;
Uint8 mask = 0;
Uint8 r,g,b,a;
// We have three fragments in one bitmap. The second fragment is the mask
Uint16 w = (srcSfc->w)/3;
Uint16 w = (srcSfc->w)/mFold;
assert(w>0);
......@@ -261,35 +366,35 @@ void GsSprite::readMask(SDL_Surface *srcSfc)
auto maskSfc = mMaskSurface.getSDLSurface();
// In same occasions the dimensions are not exact. In that case, apply the minimum
const auto minW = std::min(Uint16(srcSfc->w/3), mMaskSurface.width());
const auto minW = std::min(Uint16(srcSfc->w/mFold), mMaskSurface.width());
const auto minH = std::min(Uint16(srcSfc->h), mMaskSurface.height());
Uint8* srcLinePtr = static_cast<Uint8*>(srcSfc->pixels) + minW*srcSfc->format->BytesPerPixel;
Uint8* maskLinePtr = static_cast<Uint8*>(maskSfc->pixels);
for( Uint8 y=0 ; y<minH ; y++ )
{
{
pixel = srcLinePtr;
maskpx = maskLinePtr;
for( Uint8 x=0 ; x<minW ; x++ )
{
{
memcpy( &color, pixel, srcSfc->format->BytesPerPixel );
SDL_GetRGBA( color, srcSfc->format, &r, &g, &b, &a );
Uint32 mask32 = (r+g+b)/(3*16);
mask = 15-mask32;
Uint32 mask32 = (r+g+b)/(3*16);
mask = 15-mask32;
memcpy( maskpx, &mask, srcSfc->format->BytesPerPixel );
pixel += srcSfc->format->BytesPerPixel;
maskpx += maskSfc->format->BytesPerPixel;
}
}
srcLinePtr += srcSfc->w * srcSfc->format->BytesPerPixel;
maskLinePtr += maskSfc->w * maskSfc->format->BytesPerPixel;
}
}
mMaskSurface.unlock();
......@@ -299,6 +404,15 @@ void GsSprite::readMask(SDL_Surface *srcSfc)
}
}
void GsSprite::readMask(SDL_Surface *srcSfc)
{
if(mFold == 2)
readMask2Fold(srcSfc);
else
readMask3Fold(srcSfc);
}
/**
* \brief Reads the bounding box of a created modkeen style bitmap and assigns new coordinates
*/
......@@ -307,13 +421,60 @@ void GsSprite::readBBox(SDL_Surface *displaysurface)
// TODO: That code need to be implemented
}
void GsSprite::applyTransparency()
void GsSprite::applyTransparency2Fold()
{
if( mSurface.empty() || mMaskSurface.empty() ) return;
mSurface.lock();
mMaskSurface.lock();
const auto bpp = mSurface.getSDLSurface()->format->BytesPerPixel;
const auto maskBpp = mMaskSurface.getSDLSurface()->format->BytesPerPixel;
// In same occasions the dimensions are not exact. In that case, apply the minimum
const auto minW = std::min(Uint16(mSurface.width()), mMaskSurface.width());
const auto minH = std::min(Uint16(mSurface.height()), mMaskSurface.height());
for( int y=0 ; y<minH ; y++ )
{
Uint8 *pixel = mSurface.PixelPtr() + y*mSurface.getSDLSurface()->pitch;
Uint8 *maskpx = mMaskSurface.PixelPtr() + y*mMaskSurface.getSDLSurface()->pitch;
for( int x=0 ; x<minW ; x++ )
{
Uint32 colour;
Uint8 r,g,b,a;
memcpy( &colour, pixel, bpp );
mSurface.getRGBA(colour, r, g, b, a);
const Uint8 maskCol = *maskpx;
if(maskCol<16)
{
a = (255*maskCol)/15;
}
else
{
a = 255;
}
colour = mSurface.mapRGBA(r, g, b, a);
memcpy( pixel, &colour, bpp );
pixel += bpp;
maskpx += maskBpp;
}
}
mMaskSurface.unlock();
mSurface.unlock();
}
void GsSprite::applyTransparency3Fold()
{
mSurface.lock();
mMaskSurface.lock();
const auto bpp = mSurface.getSDLSurface()->format->BytesPerPixel;
const auto maskBpp = mMaskSurface.getSDLSurface()->format->BytesPerPixel;
......@@ -322,16 +483,16 @@ void GsSprite::applyTransparency()
const auto minH = std::min(Uint16(mSurface.height()), mMaskSurface.height());
for( int y=0 ; y<minH ; y++ )
{
{
Uint8 *pixel = mSurface.PixelPtr() + y*mSurface.getSDLSurface()->pitch;
Uint8 *maskpx = mMaskSurface.PixelPtr() + y*mMaskSurface.getSDLSurface()->pitch;
for( int x=0 ; x<minW ; x++ )
{
{
Uint32 colour;
Uint8 r,g,b,a;
memcpy( &colour, pixel, bpp );
mSurface.getRGBA(colour, r, g, b, a);
const Uint8 maskCol = *maskpx;
......@@ -348,16 +509,27 @@ void GsSprite::applyTransparency()
colour = mSurface.mapRGBA(r, g, b, a);
memcpy( pixel, &colour, bpp );
pixel += bpp;
maskpx += maskBpp;
}
}
}
}
mMaskSurface.unlock();
mSurface.unlock();
}
void GsSprite::applyTransparency()
{
if( mSurface.empty() || mMaskSurface.empty() ) return;
if(mFold == 2)
applyTransparency2Fold();
else
applyTransparency3Fold();
}
void GsSprite::applyTranslucency(Uint8 value)
{
Uint32 colour = 0;
......
......@@ -55,9 +55,18 @@ public:
*/
bool empty();
void readMask2Fold(SDL_Surface *srcSfc);
void readMask3Fold(SDL_Surface *srcSfc);
/**
* \brief Reads the mask of a created modkeen style bitmap und converts that mask to 8-bit
* so it can be applied to the others. This is for HQ Sprites, the other ones have an internal algorithm
*/
void readMask(SDL_Surface *displaysurface);
void readBBox(SDL_Surface *displaysurface);
void applyTransparency2Fold();
void applyTransparency3Fold();
void applyTransparency();
void applyTranslucency(Uint8 value);
void copy( GsSprite &Destination, SDL_Color *Palette );
......@@ -65,6 +74,8 @@ public:
void exchangeSpriteColor(const Uint16 find1, const Uint16 find2, const Uint16 miny );
void generateSprite( const int points );
void detectFoldness();
bool loadHQSprite( const std::string& filename );
void setSize(Uint8 w, Uint8 h) { m_xsize = w; m_ysize = h; }
......@@ -126,7 +137,11 @@ private:
Uint8 m_xsize = 0;
Uint8 m_ysize = 0;
Sint16 m_xoffset, m_yoffset;
Uint8 m_alpha = 255;
Uint8 m_alpha = 255;
// Some pictures for sprites have three sections,
// but there have been arising some which only use two and the mask is a special odd color
int mFold = 3;
};
#endif /* GsSprite_H_ */
v2.2.3:
-------
- Video/Display change fixes
- Virtual Pad improvements
- Tilting screen finally works as intended
v2.2.2:
-------
- More settings in the Launcher finally working!
......
......@@ -37,8 +37,8 @@ CPlayerSpriteVarSelection(const GsControl::Style style) :
mBmpBox = new CGUIBitmap(mpPlayerBmpVec[0]);
mpMenuDialog->addControl( mBmpBox,
GsRect<float>(0.07f, 0.41f,
0.15f, 0.2f));
GsRect<float>(0.17f, 0.21f,
0.24f, 0.32f));
}
......@@ -47,7 +47,7 @@ CPlayerSpriteVarSelection(const GsControl::Style style) :
style);
mpMenuDialog->addControl( mpGameButton,
GsRect<float>(0.07f, 0.71f,
GsRect<float>(0.17f, 0.71f,
0.8f, 0.1f));
mpChangeButton = new GameButton( "Change",
......@@ -55,7 +55,7 @@ CPlayerSpriteVarSelection(const GsControl::Style style) :
style);
mpMenuDialog->addControl( mpChangeButton,
GsRect<float>(0.07f, 0.81f,
GsRect<float>(0.17f, 0.81f,
0.8f, 0.1f));
......
......@@ -1506,11 +1506,25 @@ bool CEGAGraphicsGalaxy::readSprites( const size_t numSprites,
GetFileList(playersList, fileListAdder,
playersPathList, false, FM_DIR);
// If there are more players than preallocated, enlarge the rooster
if(gGraphics.spriteVecVec().size() < playersList.size())
{
auto curNumSpriteVecs = gGraphics.spriteVecVec().size();
gLogging << "More player to load. Enlarging sprite buffer...";
// Copy the sprites
for( unsigned int i=curNumSpriteVecs ; i< playersList.size() ; i++ )
{
gGraphics.appendSpriteVec(SpriteOrigVec);
}
}
// For a list of players try to load the sprites
int numSpriteVar = 0;
for(const auto &player : playersList)
{
{
auto &SpriteVecPlayer = gGraphics.getSpriteVec(numSpriteVar);
const std::string curPlayerPath = JoinPaths(playersPathList, player);
......
#ifndef CG_VERSION_H
#define CG_VERSION_H
#define CGVERSION "2.2.2-Release"
#define CGVERSION "2.2.3-Release"
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment