diff --git a/ee.linux.cbp b/ee.linux.cbp index 706f500b7..a865d5a8b 100644 --- a/ee.linux.cbp +++ b/ee.linux.cbp @@ -120,13 +120,22 @@ + + + + + + + + + diff --git a/src/audio/caudiodevice.hpp b/src/audio/caudiodevice.hpp index 3ad5f0d1e..849a1fc28 100755 --- a/src/audio/caudiodevice.hpp +++ b/src/audio/caudiodevice.hpp @@ -5,7 +5,7 @@ namespace EE { namespace Audio { -class cAudioDevice { +class EE_API cAudioDevice { public : static cAudioDevice * instance(); diff --git a/src/audio/csoundfile.hpp b/src/audio/csoundfile.hpp index 8b99a2aad..1ab4e0141 100755 --- a/src/audio/csoundfile.hpp +++ b/src/audio/csoundfile.hpp @@ -5,7 +5,7 @@ namespace EE { namespace Audio { -class cSoundFile { +class EE_API cSoundFile { public: static cSoundFile* CreateRead(const std::string& Filename); static cSoundFile* CreateRead(const char* Data, std::size_t SizeInBytes); diff --git a/src/audio/csoundfiledefault.hpp b/src/audio/csoundfiledefault.hpp index c62ed3608..6af270bc2 100755 --- a/src/audio/csoundfiledefault.hpp +++ b/src/audio/csoundfiledefault.hpp @@ -9,7 +9,7 @@ namespace EE { namespace Audio { -class cSoundFileDefault : public cSoundFile { +class EE_API cSoundFileDefault : public cSoundFile { public : cSoundFileDefault(); ~cSoundFileDefault(); diff --git a/src/audio/csoundfileogg.hpp b/src/audio/csoundfileogg.hpp index b01fca769..5a5bc26a2 100755 --- a/src/audio/csoundfileogg.hpp +++ b/src/audio/csoundfileogg.hpp @@ -7,7 +7,7 @@ namespace EE { namespace Audio { -class cSoundFileOgg : public cSoundFile { +class EE_API cSoundFileOgg : public cSoundFile { public: cSoundFileOgg(); ~cSoundFileOgg(); diff --git a/src/base.hpp b/src/base.hpp index 23d53e194..21b410d7c 100644 --- a/src/base.hpp +++ b/src/base.hpp @@ -88,8 +88,6 @@ #endif namespace EE { - #define EE_CLOCKS_PER_SEC 1000000l - #define eeARRAY_SIZE(__array) ( sizeof(__array) / sizeof(__array[0]) ) #define eeSAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } #define eeSAFE_FREE(p) { if(p) { free ( (void*)p );(p)=NULL; } } diff --git a/src/ee.h b/src/ee.h index 58ab61e89..c7ae5d8dc 100755 --- a/src/ee.h +++ b/src/ee.h @@ -91,9 +91,11 @@ // Graphics #include "graphics/renders.hpp" + #include "graphics/cimage.hpp" #include "graphics/ctexture.hpp" #include "graphics/ctextureloader.hpp" #include "graphics/ctexturefactory.hpp" + #include "graphics/ctexturepacker.hpp" #include "graphics/cshape.hpp" #include "graphics/cshapegroup.hpp" #include "graphics/cglobalshapegroup.hpp" @@ -117,6 +119,7 @@ #include "graphics/cshader.hpp" #include "graphics/cshaderprogram.hpp" #include "graphics/cshaderprogrammanager.hpp" + #include "graphics/ctexturegrouploader.hpp" using namespace EE::Graphics; // Gaming diff --git a/src/graphics/cbatchrenderer.hpp b/src/graphics/cbatchrenderer.hpp index eeb7950bb..97e57d8e9 100755 --- a/src/graphics/cbatchrenderer.hpp +++ b/src/graphics/cbatchrenderer.hpp @@ -18,7 +18,7 @@ typedef struct { } eeVertex; /** @brief A batch rendering class. */ -class cBatchRenderer { +class EE_API cBatchRenderer { public: cBatchRenderer(); ~cBatchRenderer(); diff --git a/src/graphics/cfontmanager.hpp b/src/graphics/cfontmanager.hpp index 0974cbc64..c39edef6c 100644 --- a/src/graphics/cfontmanager.hpp +++ b/src/graphics/cfontmanager.hpp @@ -6,7 +6,7 @@ namespace EE { namespace Graphics { -class cFontManager : public tResourceManager, public cSingleton { +class EE_API cFontManager : public tResourceManager, public cSingleton { friend class cSingleton; public: cFontManager(); diff --git a/src/graphics/cglobalbatchrenderer.hpp b/src/graphics/cglobalbatchrenderer.hpp index 7e9a13a45..a19237988 100755 --- a/src/graphics/cglobalbatchrenderer.hpp +++ b/src/graphics/cglobalbatchrenderer.hpp @@ -7,7 +7,7 @@ namespace EE { namespace Graphics { /** @brief The global Batch Renderer class. This class will be used by the engine for the rendering. */ -class cGlobalBatchRenderer : public cSingleton, public cBatchRenderer { +class EE_API cGlobalBatchRenderer : public cSingleton, public cBatchRenderer { friend class cSingleton; public: cGlobalBatchRenderer(); diff --git a/src/graphics/cimage.cpp b/src/graphics/cimage.cpp index 5194cfd46..e06c7abc8 100644 --- a/src/graphics/cimage.cpp +++ b/src/graphics/cimage.cpp @@ -1,4 +1,5 @@ #include "cimage.hpp" +#include "../helper/SOIL/image_helper.h" namespace EE { namespace Graphics { @@ -7,7 +8,8 @@ cImage::cImage() : mWidth(0), mHeight(0), mChannels(0), - mSize(0) + mSize(0), + mAvoidFree(false) { } @@ -16,7 +18,8 @@ cImage::cImage( const Uint8* data, const eeUint& Width, const eeUint& Height, co mWidth(Width), mHeight(Height), mChannels(Channels), - mSize(0) + mSize(0), + mAvoidFree(false) { SetPixels( data ); } @@ -26,13 +29,35 @@ cImage::cImage( const Uint32& Width, const Uint32& Height, const Uint32& Channel mWidth(Width), mHeight(Height), mChannels(Channels), - mSize(0) + mSize(0), + mAvoidFree(false) { Create( Width, Height, Channels ); } +cImage::cImage( Uint8* data, const eeUint& Width, const eeUint& Height, const eeUint& Channels ) : + mPixels( data ), + mWidth(Width), + mHeight(Height), + mChannels(Channels), + mSize(Width*Height*Channels), + mAvoidFree(false) +{ +} + cImage::~cImage() { - ClearCache(); + if ( !mAvoidFree ) + ClearCache(); +} + +void cImage::SetPixels( const Uint8* data ) { + if ( data != NULL ) { + eeUint size = (eeUint)mWidth * (eeUint)mHeight * mChannels; + + Allocate( size ); + + memcpy( reinterpret_cast( &mPixels[0] ), reinterpret_cast ( data ), size ); + } } const Uint8* cImage::GetPixelsPtr() { @@ -77,16 +102,6 @@ void cImage::Create( const Uint32& Width, const Uint32& Height, const Uint32& Ch Allocate( mWidth * mHeight * mChannels ); } -void cImage::SetPixels( const Uint8* data ) { - if ( data != NULL ) { - eeUint size = (eeUint)mWidth * (eeUint)mHeight * mChannels; - - Allocate( size ); - - memcpy( reinterpret_cast( &mPixels[0] ), reinterpret_cast ( data ), size ); - } -} - Uint8* cImage::GetPixels() const { return mPixels; } @@ -140,4 +155,129 @@ bool cImage::SaveToFile( const std::string& filepath, const EE_SAVETYPE& Format return Res; } +void cImage::ReplaceColor( const eeColorA& ColorKey, const eeColorA& NewColor ) { + eeUint Pos = 0; + + if ( NULL == mPixels ) + return; + + for ( eeUint i = 0; i < mWidth * mHeight; i++ ) { + Pos = i * mChannels; + + if ( 4 == mChannels ) { + if ( mPixels[ Pos ] == ColorKey.R() && mPixels[ Pos + 1 ] == ColorKey.G() && mPixels[ Pos + 2 ] == ColorKey.B() && mPixels[ Pos + 3 ] == ColorKey.A() ) { + mPixels[ Pos ] = NewColor.R(); + mPixels[ Pos + 1 ] = NewColor.G(); + mPixels[ Pos + 2 ] = NewColor.B(); + mPixels[ Pos + 3 ] = NewColor.A(); + } + } else if ( 3 == mChannels ) { + if ( mPixels[ Pos ] == ColorKey.R() && mPixels[ Pos + 1 ] == ColorKey.G() && mPixels[ Pos + 2 ] == ColorKey.B() ) { + mPixels[ Pos ] = NewColor.R(); + mPixels[ Pos + 1 ] = NewColor.G(); + mPixels[ Pos + 2 ] = NewColor.B(); + } + } else if ( 2 == mChannels ) { + if ( mPixels[ Pos ] == ColorKey.R() && mPixels[ Pos + 1 ] == ColorKey.G() ) { + mPixels[ Pos ] = NewColor.R(); + mPixels[ Pos + 1 ] = NewColor.G(); + } + } else if ( 1 == mChannels ) { + if ( mPixels[ Pos ] == ColorKey.R() ) { + mPixels[ Pos ] = NewColor.R(); + } + } + } +} + +void cImage::CreateMaskFromColor( const eeColorA& ColorKey, Uint8 Alpha ) { + ReplaceColor( ColorKey, eeColorA( ColorKey.R(), ColorKey.G(), ColorKey.B(), Alpha ) ); +} + +void cImage::CreateMaskFromColor( const eeColor& ColorKey, Uint8 Alpha ) { + CreateMaskFromColor( eeColorA( ColorKey.R(), ColorKey.G(), ColorKey.B(), 255 ), Alpha ); +} + +void cImage::FillWithColor( const eeColorA& Color ) { + if ( NULL == mPixels ) + return; + + eeUint z; + + for ( eeUint i = 0; i < mWidth * mHeight; i += mChannels ) { + for ( z = 0; z < mChannels; z++ ) { + if ( 0 == z ) + mPixels[ i + z ] = Color.R(); + else if ( 1 == z ) + mPixels[ i + z ] = Color.G(); + else if ( 2 == z ) + mPixels[ i + z ] = Color.B(); + else if ( 3 == z ) + mPixels[ i + z ] = Color.A(); + } + } +} + +void cImage::CopyImage( cImage * Img, const eeUint& x, const eeUint& y ) { + if ( NULL != mPixels && NULL != Img->GetPixels() && mWidth >= x + Img->Width() && mHeight >= y + Img->Height() ) { + eeUint dWidth = Img->Width(); + eeUint dHeight = Img->Height(); + + for ( eeUint ty = 0; ty < dHeight; ty++ ) { + for ( eeUint tx = 0; tx < dWidth; tx++ ) { + SetPixel( x + tx, y + ty, Img->GetPixel( tx, ty ) ); + } + } + } +} + +void cImage::Resize( const eeUint& new_width, const eeUint& new_height ) { + if ( NULL != mPixels && mWidth != new_width && mHeight != new_height ) { + unsigned char * resampled = new unsigned char[ mChannels * new_width * new_height ]; + + int res = up_scale_image( reinterpret_cast ( mPixels ), mWidth, mHeight, mChannels, resampled, new_width, new_height ); + + if ( res ) { + ClearCache(); + + mPixels = resampled; + mWidth = new_width; + mHeight = new_height; + } else + eeSAFE_DELETE_ARRAY( resampled ); + } +} + +void cImage::Scale( const eeFloat& scale ) { + if ( 1.f == scale ) + return; + + Int32 new_width = (Int32)( (eeFloat)mWidth * scale ); + Int32 new_height = (Int32)( (eeFloat)mHeight * scale ); + + Resize( new_width, new_height ); +} + +cImage * cImage::Thumbnail( const eeUint& max_width, const eeUint& max_height ) { + if ( NULL != mPixels && mWidth > max_width && mHeight > max_height ) { + eeFloat iScaleX = ( (eeFloat)max_width / (eeFloat)mWidth ); + eeFloat iScaleY = ( (eeFloat)max_height / (eeFloat)mHeight ); + eeFloat iScale = ( iScaleY < iScaleX ) ? iScaleY : iScaleX; + Int32 new_width = (Int32)( (eeFloat)mWidth * iScale ); + Int32 new_height = (Int32)( (eeFloat)mHeight * iScale ); + + unsigned char * resampled = new unsigned char[ mChannels * new_width * new_height ]; + + int res = up_scale_image( reinterpret_cast ( mPixels ), mWidth, mHeight, mChannels, resampled, new_width, new_height ); + + if ( res ) { + return new cImage( (Uint8*)resampled, new_width, new_height, mChannels ); + } else { + eeSAFE_DELETE_ARRAY( resampled ); + } + } + + return NULL; +} + }} diff --git a/src/graphics/cimage.hpp b/src/graphics/cimage.hpp index 24b449908..899b5d319 100644 --- a/src/graphics/cimage.hpp +++ b/src/graphics/cimage.hpp @@ -5,10 +5,13 @@ namespace EE { namespace Graphics { -class cImage { +class EE_API cImage { public: cImage(); + /** Use an existing image */ + cImage( Uint8* data, const eeUint& Width, const eeUint& Height, const eeUint& Channels ); + /** Copy a image data to create the image */ cImage( const Uint8* data, const eeUint& Width, const eeUint& Height, const eeUint& Channels ); @@ -61,12 +64,40 @@ class cImage { /** Save the Image to a new File in a specific format */ virtual bool SaveToFile( const std::string& filepath, const EE_SAVETYPE& Format ); + + /** Create an Alpha mask from a Color */ + virtual void CreateMaskFromColor( const eeColorA& ColorKey, Uint8 Alpha ); + + /** Create an Alpha mask from a Color */ + void CreateMaskFromColor( const eeColor& ColorKey, Uint8 Alpha ); + + /** Replace a color on the image */ + virtual void ReplaceColor( const eeColorA& ColorKey, const eeColorA& NewColor ); + + /** Fill the image with a color */ + virtual void FillWithColor( const eeColorA& Color ); + + /** Copy the image to this image data, starting from the position x,y */ + virtual void CopyImage( cImage * Img, const eeUint& x, const eeUint& y ); + + /** Scale the image */ + virtual void Scale( const eeFloat& scale ); + + /** Resize the image */ + virtual void Resize( const eeUint& new_width, const eeUint& new_height ); + + /** Create a thumnail of the image */ + cImage * Thumbnail( const eeUint& max_width, const eeUint& max_height ); + + /** Set as true if you dont want to free the image data ( false as default ). */ + void AvoidFreeImage( const bool& AvoidFree ) { mAvoidFree = AvoidFree; } protected: Uint8 * mPixels; eeUint mWidth; eeUint mHeight; eeUint mChannels; Uint32 mSize; + bool mAvoidFree; void Allocate( const Uint32& size ); }; diff --git a/src/graphics/cshape.hpp b/src/graphics/cshape.hpp index ec013d006..357496279 100644 --- a/src/graphics/cshape.hpp +++ b/src/graphics/cshape.hpp @@ -53,7 +53,7 @@ class EE_API cShape { void Draw( const eeFloat& X, const eeFloat& Y, const eeRGBA& Color = eeRGBA(), const eeFloat& Angle = 0.f, const eeFloat& Scale = 1.f, const EE_RENDERALPHAS& Blend = ALPHA_NORMAL, const EE_RENDERTYPE& Effect = RN_NORMAL, const bool& ScaleRendered = true ); - void Draw( const eeFloat& X, const eeFloat& Y, const eeFloat& Angle = 0.f, const eeFloat& Scale = 1.f, const eeRGBA& Color0 = eeRGBA(), const eeRGBA& Color1 = eeRGBA(), const eeRGBA& Color2 = eeRGBA(), const eeRGBA& Color3 = eeRGBA(), const EE_RENDERALPHAS& Blend = ALPHA_NORMAL, const EE_RENDERTYPE& Effect = RN_NORMAL, const bool& ScaleRendered = true ); + void Draw( const eeFloat& X, const eeFloat& Y, const eeFloat& Angle, const eeFloat& Scale, const eeRGBA& Color0 = eeRGBA(), const eeRGBA& Color1 = eeRGBA(), const eeRGBA& Color2 = eeRGBA(), const eeRGBA& Color3 = eeRGBA(), const EE_RENDERALPHAS& Blend = ALPHA_NORMAL, const EE_RENDERTYPE& Effect = RN_NORMAL, const bool& ScaleRendered = true ); cTexture * GetTexture(); diff --git a/src/graphics/ctextcache.hpp b/src/graphics/ctextcache.hpp index 553a1be6f..3e7a969b4 100644 --- a/src/graphics/ctextcache.hpp +++ b/src/graphics/ctextcache.hpp @@ -9,7 +9,7 @@ namespace EE { namespace Graphics { class cFont; /** @brief Cached text for a fast font rendering. */ -class cTextCache { +class EE_API cTextCache { public: cTextCache( cFont * font, const std::wstring& text = L"", eeColorA FontColor = eeColorA(0xFFFFFFFF), eeColorA ShadowColor = eeColorA(0xFF000000) ); diff --git a/src/graphics/ctexture.cpp b/src/graphics/ctexture.cpp index 0f2e812e8..0a16e5896 100755 --- a/src/graphics/ctexture.cpp +++ b/src/graphics/ctexture.cpp @@ -251,31 +251,44 @@ void cTexture::SetTextureFilter(const EE_TEX_FILTER& filter) { } } -void cTexture::ReplaceColor(eeColorA ColorKey, eeColorA NewColor) { +void cTexture::ReplaceColor( const eeColorA& ColorKey, const eeColorA& NewColor ) { + Lock(); + + cImage::ReplaceColor( ColorKey, NewColor ); + + Unlock( false, true ); +} + +void cTexture::CreateMaskFromColor( const eeColorA& ColorKey, Uint8 Alpha ) { Lock( true ); - eeUint Pos = 0; + cImage::ReplaceColor( ColorKey, eeColorA( ColorKey.R(), ColorKey.G(), ColorKey.B(), Alpha ) ); - for ( eeUint i = 0; i < mWidth * mHeight; i++ ) { - Pos = i * mChannels; - - if ( mPixels[ Pos ] == ColorKey.R() && mPixels[ Pos + 1 ] == ColorKey.G() && mPixels[ Pos + 2 ] == ColorKey.B() && mPixels[ Pos + 3 ] == ColorKey.A() ) { - mPixels[ Pos ] = NewColor.R(); - mPixels[ Pos + 1 ] = NewColor.G(); - mPixels[ Pos + 2 ] = NewColor.B(); - mPixels[ Pos + 3 ] = NewColor.A(); - } - } - - Unlock(false, true); + Unlock( false, true ); } -void cTexture::CreateMaskFromColor(eeColorA ColorKey, Uint8 Alpha) { - ReplaceColor( ColorKey, eeColorA( ColorKey.R(), ColorKey.G(), ColorKey.B(), Alpha ) ); +void cTexture::FillWithColor( const eeColorA& Color ) { + Lock(); + + cImage::FillWithColor( Color ); + + Unlock( false, true ); } -void cTexture::CreateMaskFromColor(eeColor ColorKey, Uint8 Alpha) { - CreateMaskFromColor( eeColorA( ColorKey.R(), ColorKey.G(), ColorKey.B(), 255 ), Alpha ); +void cTexture::Resize( const eeUint& new_width, const eeUint& new_height ) { + Lock(); + + cImage::Resize( new_width, new_height ); + + Unlock( false, true ); +} + +void cTexture::CopyImage( cImage * Img, const eeUint& x, const eeUint& y ) { + Lock(); + + cImage::CopyImage( Img, x, y ); + + Unlock( false, true ); } bool cTexture::LocalCopy() { diff --git a/src/graphics/ctexture.hpp b/src/graphics/ctexture.hpp index 1b708a932..a43933c10 100755 --- a/src/graphics/ctexture.hpp +++ b/src/graphics/ctexture.hpp @@ -94,14 +94,20 @@ class EE_API cTexture : public cImage { /** Save the Texture to a new File */ bool SaveToFile( const std::string& filepath, const EE_SAVETYPE& Format ); - /** Create an Alpha mask from a Color */ - void CreateMaskFromColor(eeColorA ColorKey, Uint8 Alpha); - - /** Create an Alpha mask from a Color */ - void CreateMaskFromColor(eeColor ColorKey, Uint8 Alpha); - /** Replace a color on the texture */ - void ReplaceColor(eeColorA ColorKey, eeColorA NewColor); + void ReplaceColor( const eeColorA& ColorKey, const eeColorA& NewColor); + + /** Create an Alpha mask from a Color */ + void CreateMaskFromColor( const eeColorA& ColorKey, Uint8 Alpha ); + + /** Fill a texture with a color */ + void FillWithColor( const eeColorA& Color ); + + /** Resize the texture */ + void Resize( const eeUint& new_width, const eeUint& new_height ); + + /** Copy an image inside the texture */ + void CopyImage( cImage * Img, const eeUint& x, const eeUint& y ); /** @return If the Texture has a copy on the local memory */ bool LocalCopy(); diff --git a/src/graphics/ctexturegrouploader.cpp b/src/graphics/ctexturegrouploader.cpp new file mode 100644 index 000000000..787612fdd --- /dev/null +++ b/src/graphics/ctexturegrouploader.cpp @@ -0,0 +1,129 @@ +#include "ctexturegrouploader.hpp" +#include "cshapegroup.hpp" +#include "cshapegroupmanager.hpp" + +namespace EE { namespace Graphics { + +cTextureGroupLoader::cTextureGroupLoader() : + mThreaded(false), + mLoaded(false), + mAppPath( AppPath() ) +{ +} + +cTextureGroupLoader::cTextureGroupLoader( const std::string& TextureGroupPath, const bool& Threaded ) : + mTextureGroupPath( TextureGroupPath ), + mThreaded( Threaded ), + mLoaded(false), + mAppPath( AppPath() ) +{ + Load(); +} + +cTextureGroupLoader::~cTextureGroupLoader() +{ +} + +void cTextureGroupLoader::Update() { + mRL.Update(); + + if ( mRL.IsLoaded() && !mLoaded ) + CreateShapes(); +} + +void cTextureGroupLoader::Load( const std::string& TextureGroupPath ) { + mRL.Threaded( mThreaded ); + + if ( TextureGroupPath.size() ) + mTextureGroupPath = TextureGroupPath; + + sTextureGroupHdr TexGrHdr; + + std::fstream fs ( mTextureGroupPath.c_str() , std::ios::in | std::ios::binary ); + + if ( fs.is_open() ) { + fs.read( reinterpret_cast (&TexGrHdr), sizeof(sTextureGroupHdr) ); + + if ( TexGrHdr.Magic == ( ( 'E' << 0 ) | ( 'E' << 8 ) | ( 'T' << 16 ) | ( 'G' << 24 ) ) ) { + for ( Uint32 i = 0; i < TexGrHdr.TextureCount; i++ ) { + sTextureHdr tTextureHdr; + sTempTexGroup tTexGroup; + + fs.read( reinterpret_cast (&tTextureHdr), sizeof(sTextureHdr) ); + + tTexGroup.Texture = tTextureHdr; + tTexGroup.Shapes.resize( tTextureHdr.ShapeCount ); + + std::string name( &tTextureHdr.Name[0] ); + std::string path( FileRemoveFileName( mTextureGroupPath ) + name ); + + mRL.Add( new cTextureLoader( path ) ); + + fs.read( reinterpret_cast (&tTexGroup.Shapes[0]), sizeof(sShapeHdr) * tTextureHdr.ShapeCount ); + + mTempGroups.push_back( tTexGroup ); + } + } + + mRL.Load(); + + if ( !mThreaded ) + CreateShapes(); + } +} + +void cTextureGroupLoader::CreateShapes() { + cShapeGroup * tSG = NULL; + + for ( Uint32 z = 0; z < mTempGroups.size(); z++ ) { + sTempTexGroup * tTexGroup = &mTempGroups[z]; + sTextureHdr * tTexHdr = &tTexGroup->Texture; + + std::string name( &tTexHdr->Name[0] ); + std::string path( FileRemoveFileName( mTextureGroupPath ) + name ); + + Int32 pos = StrStartsWith( mAppPath, path ); + + if ( -1 != pos && (Uint32)(pos + 1) < path.size() ) + path = path.substr( pos + 1 ); + + cTexture * tTex = cTextureFactory::instance()->GetByName( path ); + + // Create the Shape Group with the name of the real texture, not the Childs ( example load 1.png and not 1_ch1.png ) + if ( 0 == z ) { + tSG = new cShapeGroup( name ); + cShapeGroupManager::instance()->Add( tSG ); + } + + if ( NULL != tTex ) { + for ( Int32 i = 0; i < tTexHdr->ShapeCount; i++ ) { + sShapeHdr * tSh = &tTexGroup->Shapes[i]; + + std::string ShapeName( &tSh->Name[0] ); + eeRecti tRect( tSh->X, tSh->Y, tSh->X + tSh->Width, tSh->Y + tSh->Height ); + + tSG->Add( new cShape( tTex->TexId(), tRect, tSh->DestWidth, tSh->DestHeight, tSh->OffsetX, tSh->OffsetY, ShapeName ) ); + } + } else { + /** @TODO: Error Report */ + return; + } + } + + mLoaded = true; +} + +bool cTextureGroupLoader::Threaded() const { + return mThreaded; +} + +void cTextureGroupLoader::Threaded( const bool& threaded ) { + mThreaded = threaded; +} + +const bool& cTextureGroupLoader::IsLoaded() const { + return mLoaded; +} + +}} + diff --git a/src/graphics/ctexturegrouploader.hpp b/src/graphics/ctexturegrouploader.hpp new file mode 100644 index 000000000..2359b1b06 --- /dev/null +++ b/src/graphics/ctexturegrouploader.hpp @@ -0,0 +1,50 @@ +#ifndef EE_GRAPHICSCTEXTUREGROUPLOADER_HPP +#define EE_GRAPHICSCTEXTUREGROUPLOADER_HPP + +#include "base.hpp" +#include "packerhelper.hpp" +#include "ctextureloader.hpp" +#include "ctexturefactory.hpp" +#include "../system/cresourceloader.hpp" + +namespace EE { namespace Graphics { + +using namespace Private; + +class EE_API cTextureGroupLoader { + public: + cTextureGroupLoader(); + + cTextureGroupLoader( const std::string& TextureGroupPath, const bool& Threaded = false ); + + ~cTextureGroupLoader(); + + void Update(); + + void Load( const std::string& TextureGroupPath = "" ); + + bool Threaded() const; + + void Threaded( const bool& threaded ); + + const bool& IsLoaded() const; + protected: + cResourceLoader mRL; + std::string mTextureGroupPath; + bool mThreaded; + bool mLoaded; + std::string mAppPath; + + typedef struct sTempTexGroupS { + sTextureHdr Texture; + std::vector Shapes; + } sTempTexGroup; + + std::vector mTempGroups; + + void CreateShapes(); +}; + +}} + +#endif diff --git a/src/graphics/ctextureloader.cpp b/src/graphics/ctextureloader.cpp index 2c7175d23..5ad63dce9 100644 --- a/src/graphics/ctextureloader.cpp +++ b/src/graphics/ctextureloader.cpp @@ -1,5 +1,6 @@ #include "ctextureloader.hpp" #include "ctexturefactory.hpp" +#define STBI_TYPE_SPECIFIC_FUNCTIONS #include "../helper/SOIL/stb_image.h" #include "../helper/SOIL/SOIL.h" diff --git a/src/graphics/ctexturepacker.cpp b/src/graphics/ctexturepacker.cpp new file mode 100644 index 000000000..7561dda5f --- /dev/null +++ b/src/graphics/ctexturepacker.cpp @@ -0,0 +1,670 @@ +#include "ctexturepacker.hpp" +#include "cimage.hpp" +#include "../helper/SOIL/SOIL.h" + +namespace EE { namespace Graphics { + +cTexturePacker::cTexturePacker() : + mLongestEdge(0), + mTotalArea(0), + mFreeList(NULL), + mWidth(0), + mHeight(0), + mPacked(false), + mAllowFlipping(false), + mChild(NULL), + mStrategy(PackBig), + mCount(0), + mParent(NULL), + mPlacedCount(0) +{ +} + +cTexturePacker::~cTexturePacker() +{ + Close(); +} + +void cTexturePacker::Close() { + mLongestEdge = 0; + mTotalArea = 0; + mTextures.clear(); + + if ( NULL != mFreeList ) { + cTexturePackerNode * next = mFreeList; + cTexturePackerNode * kill = NULL; + + while ( NULL != next ) { + kill = next; + + next = next->GetNext(); + + eeSAFE_DELETE( kill ); + } + } + + eeSAFE_DELETE( mChild ); +} + +void cTexturePacker::NewFree( Int32 x, Int32 y, Int32 width, Int32 height ) { + cTexturePackerNode * node = new cTexturePackerNode( x, y, width, height ); + node->SetNext( mFreeList ); + mFreeList = node; +} + +bool cTexturePacker::MergeNodes() { + cTexturePackerNode *f = mFreeList; + + while ( f ) { + cTexturePackerNode * prev = 0; + cTexturePackerNode * c = mFreeList; + + while ( c ) { + if ( f != c ) { + if ( f->Merge( *c ) ) { + assert( prev ); + + prev->SetNext( c->GetNext() ); + + eeSAFE_DELETE( c ); + + return true; + } + } + + prev = c; + c = c->GetNext(); + } + + f = f->GetNext(); + } + + return false; +} + +void cTexturePacker::Validate() { +#ifdef EE_DEBUG + cTexturePackerNode * f = mFreeList; + while ( f ) { + cTexturePackerNode * c = mFreeList; + + while ( c ) { + if ( f != c ) + f->Validate(c); + + c = c->GetNext(); + } + + f = f->GetNext(); + } +#endif +} + +cTexturePackerTex * cTexturePacker::GetLonguestEdge() { + cTexturePackerTex * t = NULL; + std::list::iterator it; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + if ( !(*it).Placed() ) { + t = &(*it); + break; + } + } + + return t; +} + +cTexturePackerTex * cTexturePacker::GetShortestEdge() { + cTexturePackerTex * t = NULL; + std::list::reverse_iterator it; + + for ( it = mTextures.rbegin(); it != mTextures.rend(); it++ ) { + if ( !(*it).Placed() ) { + t = &(*it); + break; + } + } + + return t; +} + +void cTexturePacker::AddBorderToTextures( const Int32& BorderSize ) { + cTexturePackerTex * t; + + if ( 0 != BorderSize ) { + std::list::iterator it; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + t = &(*it); + + t->Width ( t->Width() + BorderSize ); + t->Height ( t->Height() + BorderSize ); + } + + mLongestEdge += BorderSize; + } +} + +cTexturePackerNode * cTexturePacker::GetBestFit( cTexturePackerTex * t, cTexturePackerNode ** prevBestFit, Int32 * EdgeCount ) { + Int32 leastY = 0x7FFFFFFF; + Int32 leastX = 0x7FFFFFFF; + cTexturePackerNode * previousBestFit = NULL; + cTexturePackerNode * bestFit = NULL; + cTexturePackerNode * previous = NULL; + cTexturePackerNode * search = mFreeList; + Int32 edgeCount = 0; + + // Walk the singly linked list of free nodes + // see if it will fit into any currently free space + while ( search ) { + Int32 ec; + + // see if the texture will fit into this slot, and if so how many edges does it share. + if ( search->Fits( t->Width(), t->Height(), ec, mAllowFlipping ) ) { + + if ( ec == 2 ) { + previousBestFit = previous; // record the pointer previous to this one (used to patch the linked list) + bestFit = search; // record the best fit. + edgeCount = ec; + + break; + } + + if ( search->Y() < leastY ) { + leastY = search->Y(); + leastX = search->X(); + previousBestFit = previous; + bestFit = search; + edgeCount = ec; + } else if ( search->Y() == leastY && search->X() < leastX ) { + leastX = search->X(); + previousBestFit = previous; + bestFit = search; + edgeCount = ec; + } + } + + previous = search; + search = search->GetNext(); + } + + *EdgeCount = edgeCount; + *prevBestFit = previousBestFit; + + return bestFit; +} + +void cTexturePacker::InsertTexture( cTexturePackerTex * t, cTexturePackerNode * bestFit, Int32 edgeCount, cTexturePackerNode * previousBestFit ) { + if ( NULL != bestFit ) { + Validate(); + + switch ( edgeCount ) { + case 0: + { + bool flipped = false; + int w = t->Width(); + int h = t->Height(); + + if ( mAllowFlipping ) { + if ( t->LongestEdge() <= bestFit->Width() ) { + if ( h > w ) { + w = t->Height(); + h = t->Width(); + flipped = true; + } + } else { + assert( t->LongestEdge() <= bestFit->Height() ); + + if ( h < w ) { + w = t->Height(); + h = t->Width(); + flipped = true; + } + } + } + + t->Place( bestFit->X(), bestFit->Y(), flipped ); // place it. + + NewFree( bestFit->X(), bestFit->Y() + h, bestFit->Width(), bestFit->Height() - h ); + + bestFit->X ( bestFit->X() + w ); + bestFit->Width ( bestFit->Width() - w ); + bestFit->Height ( h ); + + Validate(); + } + break; + case 1: + { + if ( t->Width() == bestFit->Width() ) { + t->Place( bestFit->X(), bestFit->Y(), false ); + + bestFit->Y ( bestFit->Y() + t->Height() ); + bestFit->Height ( bestFit->Height() - t->Height() ); + + Validate(); + } else if ( t->Height() == bestFit->Height() ) { + t->Place( bestFit->X(), bestFit->Y(), false ); + + bestFit->X ( bestFit->X() + t->Width() ); + bestFit->Width ( bestFit->Width() - t->Width() ); + + Validate(); + } else if ( mAllowFlipping && t->Width() == bestFit->Height() ) { + t->Place( bestFit->X(), bestFit->Y(), true ); + + bestFit->X ( bestFit->X() + t->Height() ); + bestFit->Width ( bestFit->Width() - t->Height() ); + + Validate(); + } else if ( mAllowFlipping && t->Height() == bestFit->Width() ) { + t->Place( bestFit->X(), bestFit->Y(), true ); + + bestFit->Y ( bestFit->Y() + t->Width() ); + bestFit->Height ( bestFit->Height() - t->Width() ); + + Validate(); + } + } + break; + case 2: + { + bool flipped = t->Width() != bestFit->Width() || t->Height() != bestFit->Height(); + + t->Place( bestFit->X(), bestFit->Y(), flipped ); + + if ( previousBestFit ) + previousBestFit->SetNext( bestFit->GetNext() ); + else + mFreeList = bestFit->GetNext(); + + eeSAFE_DELETE( bestFit ); + + Validate(); + } + break; + } + + while ( MergeNodes() ); // keep merging nodes as much as we can... + } +} + +void cTexturePacker::CreateChild( const Uint32& MaxWidth, const Uint32& MaxHeight, const bool& ForcePowOfTwo, const Uint32& PixelBorder, const bool& AllowFlipping ) { + mChild = new cTexturePacker(); + + std::list::iterator it; + cTexturePackerTex * t = NULL; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + t = &(*it); + + if ( !t->Placed() ) { + mChild->AddTexture( t->Name() ); + mChild->mParent = this; + + t->Disabled( true ); + + mCount--; + } + } + + mChild->PackTextures( MaxWidth, MaxHeight, ForcePowOfTwo, PixelBorder, AllowFlipping ); +} + +bool cTexturePacker::AddTexturesPath( std::string TexturesPath ) { + if ( IsDirectory( TexturesPath ) ) { + + if ( TexturesPath[ TexturesPath.size() - 1 ] != '/' && TexturesPath[ TexturesPath.size() - 1 ] != '\\' ) + TexturesPath += "/"; + + std::vector files = FilesGetInPath( TexturesPath ); + std::sort( files.begin(), files.end() ); + + for ( Uint32 i = 0; i < files.size(); i++ ) { + std::string path( TexturesPath + files[i] ); + if ( !IsDirectory( path ) ) + AddTexture( path ); + } + + return true; + } + + return false; +} + +bool cTexturePacker::AddTexture( const std::string& TexturePath ) { + if ( FileExists( TexturePath ) ) { + cTexturePackerTex TPack( TexturePath ); + + if ( TPack.LoadedInfo() ) { + if ( TPack.Width() > mLongestEdge ) + mLongestEdge = TPack.Width(); + + if ( TPack.Height() > mLongestEdge ) + mLongestEdge = TPack.Height(); + + mTotalArea += TPack.Area(); + + // Insert ordered + std::list::iterator it; + + bool Added = false; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + if ( (*it).Area() < TPack.Area() ) { + mTextures.insert( it, TPack ); + Added = true; + break; + } + } + + if ( !Added ) { + mTextures.push_back( TPack ); + + return true; + } + } + } + + return false; +} + +Int32 cTexturePacker::PackTextures( const Uint32& MaxWidth, const Uint32& MaxHeight, const bool& ForcePowOfTwo, const Uint32& PixelBorder, const bool& AllowFlipping ) { // pack the textures, the return code is the amount of wasted/unused area. + mAllowFlipping = AllowFlipping; + Int32 Width = MaxWidth; + Int32 Height = MaxHeight; + cTexturePackerTex * t = NULL; + + AddBorderToTextures( (Int32)PixelBorder ); + + if ( ForcePowOfTwo && !IsPow2( Width ) ) + Width = NextPowOfTwo( Width ); + + if ( ForcePowOfTwo && !IsPow2( Height ) ) + Height = NextPowOfTwo( Height ); + + NewFree( 0, 0, Width, Height ); + + mCount = mTextures.size(); + + // We must place each texture + std::list::iterator it; + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + // For the texture with the longest edge we place it according to this criteria. + // (1) If it is a perfect match, we always accept it as it causes the least amount of fragmentation. + // (2) A match of one edge with the minimum area left over after the split. + // (3) No edges match, so look for the node which leaves the least amount of area left over after the split. + + if ( PackBig == mStrategy ) + t = GetLonguestEdge(); + else if ( PackTiny == mStrategy ) + t = GetShortestEdge(); + + cTexturePackerNode * previousBestFit = NULL; + Int32 edgeCount = 0; + cTexturePackerNode * bestFit = GetBestFit( t, &previousBestFit, &edgeCount ); + + if ( NULL == bestFit ) { + if ( PackBig == mStrategy ) { + mStrategy = PackTiny; + #ifdef EE_DEBUG + printf( "Chaging Strategy to Tiny. %s faults.\n", t->Name().c_str() ); + #endif + } else if ( PackTiny == mStrategy ) { + mStrategy = PackFail; + #ifdef EE_DEBUG + printf( "Strategy fail, must create a new image. %s faults.\n", t->Name().c_str() ); + #endif + } + } else { + InsertTexture( t, bestFit, edgeCount, previousBestFit ); + mCount--; + } + + if ( PackFail == mStrategy ) { + #ifdef EE_DEBUG + printf( "Creating a new image as a child.\n" ); + #endif + CreateChild( MaxWidth, MaxHeight, ForcePowOfTwo, PixelBorder, AllowFlipping ); + break; + } + } + + if ( mCount > 0 ) { + #ifdef EE_DEBUG + printf( "Creating a new image as a child. Some textures couldn't get it: %d\n", mCount ); + #endif + CreateChild( MaxWidth, MaxHeight, ForcePowOfTwo, PixelBorder, AllowFlipping ); + } + + AddBorderToTextures( -( (Int32)PixelBorder ) ); + + if ( ForcePowOfTwo ) + Height = NextPowOfTwo( Height ); + + mWidth = Width; + mHeight = Height; + mPacked = true; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + if ( !(*it).Placed() ) + mTotalArea -= (*it).Area(); + } + + #ifdef EE_DEBUG + printf( "Total Area Used: %d. This represents the %4.2f percent \n", mTotalArea, ( (eeDouble)mTotalArea / (eeDouble)( mWidth * mHeight ) ) * 100.0 ); + #endif + + return ( Width * Height ) - mTotalArea; +} + +void cTexturePacker::Save( const std::string& Filepath, const EE_SAVETYPE& Format ) { + mFilepath = Filepath; + + cImage Img( (Uint32)mWidth, (Uint32)mHeight, (Uint32)4 ); + + Img.FillWithColor( eeColorA(0,0,0,0) ); + + cTexturePackerTex * t = NULL; + int w, h, c; + std::list::iterator it; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + t = &(*it); + + if ( t->Placed() ) { + Uint8 * data = SOIL_load_image( t->Name().c_str(), &w, &h, &c, 0 ); + + if ( NULL != data && t->Width() == w && t->Height() == h ) { + cImage * ImgCopy = new cImage( data, w, h, c ); + + Img.CopyImage( ImgCopy, t->X(), t->Y() ); + + ImgCopy->AvoidFreeImage( true ); + + eeSAFE_DELETE( ImgCopy ); + + SOIL_free_image_data( data ); + + mPlacedCount++; + } + } + } + + Img.SaveToFile( Filepath, Format ); + + ChildSave( Format ); + + SaveShapes(); +} + +Int32 cTexturePacker::GetChildCount() { + cTexturePacker * Child = mChild; + Int32 ChildCount = 0; + + while ( NULL != Child ) { + ChildCount++; + Child = Child->GetChild(); + } + + return ChildCount; +} + +void cTexturePacker::SaveShapes() { + if ( NULL != mParent ) + return; + + sTextureGroupHdr TexGrHdr; + + TexGrHdr.Magic = ( ( 'E' << 0 ) | ( 'E' << 8 ) | ( 'T' << 16 ) | ( 'G' << 24 ) ); + TexGrHdr.TextureCount = 1 + GetChildCount(); + + sTextureHdr TexHdr[ TexGrHdr.TextureCount ]; + + TexHdr[ 0 ] = CreateTextureHdr( this ); + + Int32 HdrPos = 1; + cTexturePacker * Child = mChild; + + while ( NULL != Child ) { + TexHdr[ HdrPos ] = CreateTextureHdr( Child ); + Child = Child->GetChild(); + HdrPos++; + } + + std::vector tShapesHdr; + + std::string path = FileRemoveExtension( mFilepath ) + ".etg"; + std::fstream fs ( path.c_str() , std::ios::out | std::ios::binary ); + + if ( fs.is_open() ) { + fs.write( reinterpret_cast (&TexGrHdr), sizeof(sTextureGroupHdr) ); + + fs.write( reinterpret_cast (&TexHdr[ 0 ]), sizeof(sTextureHdr) ); + + CreateShapesHdr( this, tShapesHdr, &fs ); + + if ( tShapesHdr.size() ) + fs.write( reinterpret_cast (&tShapesHdr[ 0 ]), sizeof(sShapeHdr) * tShapesHdr.size() ); + + Int32 HdrPos = 1; + cTexturePacker * Child = mChild; + + while ( NULL != Child ) { + fs.write( reinterpret_cast (&TexHdr[ HdrPos ]), sizeof(sTextureHdr) ); + + CreateShapesHdr( Child, tShapesHdr, &fs ); + + if ( tShapesHdr.size() ) + fs.write( reinterpret_cast (&tShapesHdr[ 0 ]), sizeof(sShapeHdr) * tShapesHdr.size() ); + + Child = Child->GetChild(); + + HdrPos++; + } + + fs.close(); + } +} + +void cTexturePacker::CreateShapesHdr( cTexturePacker * Packer, std::vector& Shapes, std::fstream * fs ) { + Shapes.clear(); + + sShapeHdr tShapeHdr; + + std::list tTextures = *(Packer->GetTexturePackPtr()); + std::list::iterator it; + cTexturePackerTex * tTex; + + for ( it = tTextures.begin(); it != tTextures.end(); it++ ) { + tTex = &(*it); + + if ( tTex->Placed() ) { + std::string name = FileNameFromPath(tTex->Name() ); + + memset( tShapeHdr.Name, 0, HDR_NAME_SIZE ); + StrCopy( tShapeHdr.Name, name.c_str(), HDR_NAME_SIZE ); + + tShapeHdr.ResourceID = MakeHash( name ); + tShapeHdr.Width = tTex->Width(); + tShapeHdr.Height = tTex->Height(); + tShapeHdr.DestWidth = tTex->Width(); + tShapeHdr.DestHeight = tTex->Height(); + tShapeHdr.OffsetX = 0; + tShapeHdr.OffsetY = 0; + tShapeHdr.X = tTex->X(); + tShapeHdr.Y = tTex->Y(); + tShapeHdr.Date = FileGetModificationDate( tTex->Name() ); + + fs->write( reinterpret_cast (&tShapeHdr), sizeof(sShapeHdr) ); + } + } +} + +sTextureHdr cTexturePacker::CreateTextureHdr( cTexturePacker * Packer ) { + sTextureHdr TexHdr; + + std::string name( FileNameFromPath( Packer->GetFilepath() ) ); + + memset( TexHdr.Name, 0, HDR_NAME_SIZE ); + StrCopy( TexHdr.Name, name.c_str(), HDR_NAME_SIZE ); + + TexHdr.ResourceID = MakeHash( name ); + TexHdr.Size = FileSize( Packer->GetFilepath() ); + TexHdr.Width = Packer->GetWidth(); + TexHdr.Height = Packer->GetHeight(); + TexHdr.ShapeCount = Packer->GetPlacedCount(); + + return TexHdr; +} + +void cTexturePacker::ChildSave( const EE_SAVETYPE& Format ) { + if ( NULL != mChild ) { + cTexturePacker * Parent = mChild->GetParent(); + cTexturePacker * LastParent = NULL; + Int32 ParentCount = 0; + + // Find the grand parent + while ( NULL != Parent ) { + ParentCount++; + LastParent = Parent; + Parent = Parent->GetParent(); + } + + std::string fFpath = FileRemoveExtension( LastParent->GetFilepath() ); + std::string fExt = FileExtension( LastParent->GetFilepath() ); + std::string fName = fFpath + "_ch" + toStr( ParentCount ) + "." + fExt; + + mChild->Save( fName, Format ); + } +} + +cTexturePacker * cTexturePacker::GetChild() const { + return mChild; +} + +cTexturePacker * cTexturePacker::GetParent() const { + return mParent; +} + +std::list * cTexturePacker::GetTexturePackPtr() { + return &mTextures; +} + +const std::string& cTexturePacker::GetFilepath() const { + return mFilepath; +} + +const Int32& cTexturePacker::GetWidth() const { + return mWidth; +} + +const Int32& cTexturePacker::GetHeight() const { + return mHeight; +} + +const Int32& cTexturePacker::GetPlacedCount() const { + return mPlacedCount; +} + +}} diff --git a/src/graphics/ctexturepacker.hpp b/src/graphics/ctexturepacker.hpp new file mode 100644 index 000000000..eef272135 --- /dev/null +++ b/src/graphics/ctexturepacker.hpp @@ -0,0 +1,130 @@ +#ifndef EE_GRAPHICSCTEXTUREATLAS +#define EE_GRAPHICSCTEXTUREATLAS + +/*! +** +** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliffscarab@gmail.com +** +** The MIT license: +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is furnished +** to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in all +** copies or substantial portions of the Software. + +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +/*! NOTE by Martin Lucas Golini +** This implementation is based on the John W. Ratcliff texture atlas implementation. +** Implementation differ from the original, but i use the base texture atlas algorithm. +*/ + +#include "base.hpp" +#include "packerhelper.hpp" +#include "ctexturepackernode.hpp" +#include "ctexturepackertex.hpp" + +namespace EE { namespace Graphics { + +using namespace Private; + +class EE_API cTexturePacker { + public: + cTexturePacker(); + + ~cTexturePacker(); + + bool AddTexture( const std::string& TexturePath ); + + bool AddTexturesPath( std::string TexturesPath ); + + Int32 PackTextures( const Uint32& MaxWidth, const Uint32& MaxHeight, const bool& ForcePowOfTwo = true, const Uint32& PixelBorder = 0, const bool& AllowFlipping = false ); + + void Save( const std::string& Filepath, const EE_SAVETYPE& Format = EE_SAVE_TYPE_DDS ); + + void Close(); + + inline const Int32& Width() const { return mWidth; } + + inline const Int32& Height() const { return mHeight; } + protected: + enum PackStrategy { + PackBig, + PackTiny, + PackFail + }; + + std::list mTextures; + + Int32 mLongestEdge; + Int32 mTotalArea; + cTexturePackerNode * mFreeList; + Int32 mWidth; + Int32 mHeight; + bool mPacked; + bool mAllowFlipping; + cTexturePacker * mChild; + Int32 mStrategy; + Int32 mCount; + cTexturePacker * mParent; + std::string mFilepath; + Int32 mPlacedCount; + + cTexturePacker * GetChild() const; + + cTexturePacker * GetParent() const; + + std::list * GetTexturePackPtr(); + + const std::string& GetFilepath() const; + + void ChildSave( const EE_SAVETYPE& Format ); + + void SaveShapes(); + + void NewFree( Int32 x, Int32 y, Int32 width, Int32 height ); + + bool MergeNodes(); + + void Validate(); + + cTexturePackerTex * GetLonguestEdge(); + + cTexturePackerTex * GetShortestEdge(); + + Int32 GetChildCount(); + + const Int32& GetWidth() const; + + const Int32& GetHeight() const; + + const Int32& GetPlacedCount() const; + + sTextureHdr CreateTextureHdr( cTexturePacker * Packer ); + + void CreateShapesHdr( cTexturePacker * Packer, std::vector& Shapes, std::fstream * fs ); + + cTexturePackerNode * GetBestFit( cTexturePackerTex * t, cTexturePackerNode ** prevBestFit, Int32 * EdgeCount ); + + void InsertTexture( cTexturePackerTex * t, cTexturePackerNode * bestFit, Int32 edgeCount, cTexturePackerNode * previousBestFit ); + + void AddBorderToTextures( const Int32& BorderSize ); + + void CreateChild( const Uint32& MaxWidth, const Uint32& MaxHeight, const bool& ForcePowOfTwo, const Uint32& PixelBorder, const bool& AllowFlipping ); +}; + +}} + +#endif diff --git a/src/graphics/ctexturepackernode.cpp b/src/graphics/ctexturepackernode.cpp new file mode 100644 index 000000000..14a97c6e6 --- /dev/null +++ b/src/graphics/ctexturepackernode.cpp @@ -0,0 +1,100 @@ +#include "ctexturepackernode.hpp" + +namespace EE { namespace Graphics { namespace Private { + +cTexturePackerNode::cTexturePackerNode( Int32 x, Int32 y, Int32 width, Int32 height ) { + mX = x; + mY = y; + mWidth = width; + mHeight = height; + mNext = NULL; +} + +cTexturePackerNode * cTexturePackerNode::GetNext() const { + return mNext; +} + +bool cTexturePackerNode::Fits( Int32 width, Int32 height, Int32 &edgeCount, const bool& AllowFlipping ) const { + bool ret = false; + + edgeCount = 0; + + if ( width == mWidth || height == mHeight || width == mHeight || height == mWidth ) { + if ( width == mWidth ) { + edgeCount++; + if ( height == mHeight ) edgeCount++; + } + else if ( AllowFlipping && width == mHeight ) { + edgeCount++; + if ( height == mWidth ) edgeCount++; + } + else if ( AllowFlipping && height == mWidth ) { + edgeCount++; + } + else if ( height == mHeight ) { + edgeCount++; + } + } + + if ( width <= mWidth && height <= mHeight ) { + ret = true; + } else if ( AllowFlipping && height <= mWidth && width <= mHeight ) { + ret = true; + } + + return ret; +} + +void cTexturePackerNode::GetRect( eeRecti &r ) const { + r = eeRecti( mX, mY, mX + mWidth - 1, mY + mHeight - 1 ); +} + +void cTexturePackerNode::Validate( cTexturePackerNode * n ) { + eeRecti r1; + eeRecti r2; + GetRect( r1 ); + n->GetRect( r2 ); + assert( !r1.Intersect(r2) ); +} + +bool cTexturePackerNode::Merge( const cTexturePackerNode& n ) { + bool ret = false; + + eeRecti r1; + eeRecti r2; + + GetRect( r1 ); + n.GetRect( r2 ); + + r1.Right++; + r1.Bottom++; + r2.Right++; + r2.Bottom++; + + if ( r1.Left == r2.Left && r1.Right == r2.Right && r1.Top == r2.Bottom ) // if we share the top edge then.. + { + mY = n.Y(); + mHeight += n.Height(); + ret = true; + } + else if ( r1.Left == r2.Left && r1.Right == r2.Right && r1.Bottom == r2.Top ) // if we share the bottom edge + { + mHeight += n.Height(); + ret = true; + } + else if ( r1.Top == r2.Top && r1.Bottom == r2.Top && r1.Left == r2.Right ) // if we share the left edge + { + mX = n.X(); + mWidth += n.Width(); + ret = true; + } + else if ( r1.Top == r2.Top && r1.Bottom == r2.Top && r1.Right == r2.Left ) // if we share the left edge + { + mWidth += n.Width(); + ret = true; + } + + return ret; +} + +}}} diff --git a/src/graphics/ctexturepackernode.hpp b/src/graphics/ctexturepackernode.hpp new file mode 100644 index 000000000..a6e393718 --- /dev/null +++ b/src/graphics/ctexturepackernode.hpp @@ -0,0 +1,49 @@ +#ifndef EE_GRAPHICSPRIVATECTEXTUREPACKERNODE +#define EE_GRAPHICSPRIVATECTEXTUREPACKERNODE + +#include "base.hpp" + +namespace EE { namespace Graphics { namespace Private { + +class cTexturePackerNode { + public: + cTexturePackerNode( Int32 x, Int32 y, Int32 width, Int32 height ); + + bool Fits( Int32 wid, Int32 hit, Int32 &edgeCount, const bool& AllowFlipping = false ) const; + + void GetRect( eeRecti &r ) const; + + void Validate( cTexturePackerNode * n ); + + bool Merge( const cTexturePackerNode &n ); + + cTexturePackerNode * GetNext() const; + + inline void SetNext( cTexturePackerNode * Next ) { mNext = Next; } + + inline const Int32& X() const { return mX; } + + inline const Int32& Y() const { return mY; } + + inline void X( const Int32& x ) { mX = x; } + + inline void Y( const Int32& y ) { mY = y; } + + inline const Int32& Width() const { return mWidth; } + + inline const Int32& Height() const { return mHeight; } + + inline void Width( const Int32& W ) { mWidth = W; } + + inline void Height( const Int32& H ) { mHeight = H; } + protected: + cTexturePackerNode * mNext; + Int32 mX; + Int32 mY; + Int32 mWidth; + Int32 mHeight; +}; + +}}} + +#endif diff --git a/src/graphics/ctexturepackertex.cpp b/src/graphics/ctexturepackertex.cpp new file mode 100644 index 000000000..67a4be16f --- /dev/null +++ b/src/graphics/ctexturepackertex.cpp @@ -0,0 +1,38 @@ +#include "ctexturepackertex.hpp" +#include "../helper/SOIL/stb_image.h" + +namespace EE { namespace Graphics { namespace Private { + +cTexturePackerTex::cTexturePackerTex( const std::string& Name ) : + mName(Name), + mWidth(0), + mHeight(0), + mX(0), + mY(0), + mLongestEdge(0), + mArea(0), + mFlipped(false), + mPlaced(false), + mLoadedInfo(false), + mDisabled(false) +{ + Int32 c; + + if ( stbi_info( Name.c_str(), &mWidth, &mHeight, &c ) ) { + mArea = mWidth * mHeight; + mLongestEdge = ( mWidth >= mHeight ) ? mWidth : mHeight; + mLoadedInfo = true; + } +} + +void cTexturePackerTex::Place( Int32 x, Int32 y, bool flipped ) { + if ( !mPlaced ) { + mX = x; + mY = y; + mFlipped = flipped; + mPlaced = true; + } +} + +}}} + diff --git a/src/graphics/ctexturepackertex.hpp b/src/graphics/ctexturepackertex.hpp new file mode 100644 index 000000000..8510aff28 --- /dev/null +++ b/src/graphics/ctexturepackertex.hpp @@ -0,0 +1,61 @@ +#ifndef EE_GRAPHICSPRIVATECTEXTUREPACKERTEX +#define EE_GRAPHICSPRIVATECTEXTUREPACKERTEX + +#include "base.hpp" + +namespace EE { namespace Graphics { namespace Private { + +class cTexturePackerTex { + public: + cTexturePackerTex( const std::string& Name ); + + void Place( Int32 x, Int32 y, bool flipped ); + + inline const std::string& Name() const { return mName; } + + inline const Int32& X() const { return mX; } + + inline const Int32& Y() const { return mY; } + + inline void X( const Int32& x ) { mX = x; } + + inline void Y( const Int32& y ) { mY = y; } + + inline const Int32& Width() const { return mWidth; } + + inline const Int32& Height() const { return mHeight; } + + inline void Width( const Int32& W ) { mWidth = W; } + + inline void Height( const Int32& H ) { mHeight = H; } + + inline const bool& LoadedInfo() const { return mLoadedInfo; } + + inline const Int32& Area() const { return mArea; } + + inline const bool& Placed() const { return mPlaced; } + + inline const bool& Flipped() const { return mFlipped; } + + inline const Int32& LongestEdge() const { return mLongestEdge; } + + inline const bool& Disabled() const { return mDisabled; } + + inline void Disabled( const bool& d ) { mDisabled = d; } + protected: + std::string mName; + Int32 mWidth; + Int32 mHeight; + Int32 mX; + Int32 mY; + Int32 mLongestEdge; + Int32 mArea; + bool mFlipped; + bool mPlaced; + bool mLoadedInfo; + bool mDisabled; +}; + +}}} + +#endif diff --git a/src/graphics/packerhelper.hpp b/src/graphics/packerhelper.hpp new file mode 100644 index 000000000..6376c2140 --- /dev/null +++ b/src/graphics/packerhelper.hpp @@ -0,0 +1,40 @@ +#ifndef EE_PACKER_HELPER +#define EE_PACKER_HELPER + +#include "base.hpp" + +namespace EE { namespace Graphics { namespace Private { + +#define HDR_NAME_SIZE 64 + +typedef struct sShapeHdrS { + char Name[ HDR_NAME_SIZE ]; + Uint32 Date; + Int32 X; + Int32 Y; + Int32 Width; + Int32 Height; + Uint32 ResourceID; + Int32 OffsetX; + Int32 OffsetY; + Int32 DestWidth; + Int32 DestHeight; +} sShapeHdr; + +typedef struct sTextureHdrS { + char Name[ HDR_NAME_SIZE ]; + Uint32 ResourceID; + Uint32 Size; + Int32 Width; + Int32 Height; + Int32 ShapeCount; +} sTextureHdr; + +typedef struct sTextureGroupHdrS { + Uint32 Magic; + Uint32 TextureCount; +} sTextureGroupHdr; + +}}} + +#endif diff --git a/src/helper/SOIL/stb_image.c b/src/helper/SOIL/stb_image.c index 6907820a2..0c5d96ea9 100644 --- a/src/helper/SOIL/stb_image.c +++ b/src/helper/SOIL/stb_image.c @@ -1,4 +1,4 @@ -/* stbi-1.28 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c +/* stbi-1.29 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c when you control the images you're loading no warranty implied; use at your own risk @@ -20,7 +20,9 @@ - decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code) - supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) - Latest revisions: + Latest revisions: + 1.30 (2010-08-18) added stbi_info support for BMP,PSD,HDR,PIC by Martin Golini + 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) 1.27 (2010-08-01) cast-to-uint8 to fix warnings (Laurent Gomila) allow trailing 0s at end of image data (Laurent Gomila) @@ -42,7 +44,6 @@ See end of file for full revision history. TODO: - stbi_info support for BMP,PSD,HDR,PIC rewrite stbi_info and load_file variations to share file handling code (current system allows individual functions to be called directly, since each does all the work, but I doubt anyone uses this in practice) @@ -62,6 +63,8 @@ Extensions, features Janez Zemva Jetro Lauha (stbi_info) Jonathan Blow James "moose2000" Brown (iPhone PNG) Laurent Gomila + Aruelien Pocheville + Martin Golini If your name should be here but isn't, let Sean know. @@ -108,10 +111,6 @@ typedef unsigned char validate_uint32[sizeof(uint32)==4 ? 1 : -1]; #define STBI_NO_WRITE #endif -#ifndef STBI_NO_DDS -#include "stbi_DDS.h" -#endif - #define STBI_NOTUSED(v) v=v #ifdef _MSC_VER @@ -162,10 +161,15 @@ extern int stbi_png_info_from_file (FILE *f, int *x, int extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_bmp_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_bmp_test_file (FILE *f); -extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_bmp_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_bmp_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a tga? @@ -182,30 +186,45 @@ extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int extern int stbi_psd_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_psd_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_psd_test_file (FILE *f); -extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_psd_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_psd_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it an hdr? extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len); extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_hdr_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_hdr_test_file (FILE *f); -extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_hdr_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_hdr_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a pic? extern int stbi_pic_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_pic_load (char const *filename, int *x, int *y, int *comp, int req_comp); -extern stbi_uc *stbi_pic_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_pic_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_pic_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_pic_test_file (FILE *f); -extern stbi_uc *stbi_pic_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +extern stbi_uc *stbi_pic_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_pic_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_pic_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a gif? @@ -221,7 +240,10 @@ extern stbi_uc *stbi_gif_load_from_file (FILE *f, int *x, int extern int stbi_gif_info (char const *filename, int *x, int *y, int *comp); extern int stbi_gif_info_from_file (FILE *f, int *x, int *y, int *comp); #endif - + +#ifndef STBI_NO_DDS +#include "stbi_DDS.h" +#endif // this is not threadsafe static const char *failure_reason; @@ -400,6 +422,8 @@ int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) #ifndef STBI_NO_HDR return stbi_hdr_test_memory(buffer, len); #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); return 0; #endif } @@ -489,7 +513,7 @@ static void start_mem(stbi *s, uint8 const *buffer, int len) #ifndef STBI_NO_STDIO static void refill_buffer(stbi *s) { - int n = (int)fread(s->buffer_start, 1, s->buflen, s->img_file); + int n = fread(s->buffer_start, 1, s->buflen, s->img_file); if (n == 0) { s->from_file = 0; s->img_buffer = s->img_buffer_end-1; @@ -536,7 +560,7 @@ static void skip(stbi *s, int n) { #ifndef STBI_NO_STDIO if (s->img_file) { - int blen = (int)( s->img_buffer_end - s->img_buffer ); + int blen = s->img_buffer_end - s->img_buffer; if (blen < n) { s->img_buffer = s->img_buffer_end; fseek(s->img_file, n - blen, SEEK_CUR); @@ -551,7 +575,7 @@ static int getn(stbi *s, stbi_uc *buffer, int n) { #ifndef STBI_NO_STDIO if (s->img_file) { - int blen = (int)( s->img_buffer_end - s->img_buffer ); + int blen = s->img_buffer_end - s->img_buffer; if (blen < n) { int res; memcpy(buffer, s->img_buffer, blen); @@ -741,7 +765,7 @@ typedef struct typedef struct { - #if STBI_SIMD + #ifdef STBI_SIMD unsigned short dequant2[4][64]; #endif stbi s; @@ -1020,7 +1044,7 @@ __forceinline static uint8 clamp(int x) t1 += p2+p4; \ t0 += p1+p3; -#if STBI_SIMD +#ifdef STBI_SIMD typedef unsigned short stbi_dequantize_t; #else typedef uint8 stbi_dequantize_t; @@ -1135,7 +1159,7 @@ static int parse_entropy_coded_data(jpeg *z) reset(z); if (z->scan_n == 1) { int i,j; - #if STBI_SIMD + #ifdef STBI_SIMD __declspec(align(16)) #endif short data[64]; @@ -1149,7 +1173,7 @@ static int parse_entropy_coded_data(jpeg *z) for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; - #if STBI_SIMD + #ifdef STBI_SIMD stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); #else idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); @@ -1179,7 +1203,7 @@ static int parse_entropy_coded_data(jpeg *z) int x2 = (i*z->img_comp[n].h + x)*8; int y2 = (j*z->img_comp[n].v + y)*8; if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; - #if STBI_SIMD + #ifdef STBI_SIMD stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); #else idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); @@ -1227,7 +1251,7 @@ static int process_marker(jpeg *z, int m) if (t > 3) return e("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) z->dequant[t][dezigzag[i]] = get8u(&z->s); - #if STBI_SIMD + #ifdef STBI_SIMD for (i=0; i < 64; ++i) z->dequant2[t][i] = z->dequant[t][i]; #endif @@ -1547,7 +1571,7 @@ static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const } } -#if STBI_SIMD +#ifdef STBI_SIMD static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) @@ -1656,7 +1680,7 @@ static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int re if (n >= 3) { uint8 *y = coutput[0]; if (z->s.img_n == 3) { - #if STBI_SIMD + #ifdef STBI_SIMD stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); #else YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s.img_x, n); @@ -1704,9 +1728,18 @@ unsigned char *stbi_jpeg_load(char const *filename, int *x, int *y, int *comp, i unsigned char *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { + #ifdef STBI_SMALL_STACK + unsigned char *result; + jpeg *j = (jpeg *) malloc(sizeof(*j)); + start_mem(&j->s, buffer, len); + result = load_jpeg_image(j,x,y,comp,req_comp); + free(j); + return result; + #else jpeg j; start_mem(&j.s, buffer,len); return load_jpeg_image(&j, x,y,comp,req_comp); + #endif } static int stbi_jpeg_info_raw(jpeg *j, int *x, int *y, int *comp) @@ -3061,7 +3094,7 @@ stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int stbi s; start_mem(&s, buffer, len); return bmp_load(&s, x,y,comp,req_comp); -} +} // Targa Truevision - TGA // by Jonathan Dummer @@ -3075,12 +3108,9 @@ static int tga_info(stbi *s, int *x, int *y, int *comp) if( sz > 1 ) return 0; // only RGB or indexed allowed sz = get8u(s); // image type // only RGB or grey allowed, +/- RLE - if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; - get16le(s); // discard palette start - get16le(s); // discard palette length - get8(s); // discard bits per palette color entry - get16le(s); // discard x origin - get16le(s); // discard y origin + if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; + skip(s,9); + tga_w = get16le(s); if( tga_w < 1 ) return 0; // test width tga_h = get16le(s); @@ -3095,6 +3125,7 @@ static int tga_info(stbi *s, int *x, int *y, int *comp) return 1; // seems to have passed everything } +#ifndef STBI_NO_STDIO int stbi_tga_info_from_file(FILE *f, int *x, int *y, int *comp) { stbi s; @@ -3105,6 +3136,7 @@ int stbi_tga_info_from_file(FILE *f, int *x, int *y, int *comp) fseek(f, n, SEEK_SET); return r; } +#endif int stbi_tga_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) { @@ -4500,11 +4532,20 @@ int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) if (stbi_png_info_from_file(f, x, y, comp)) return 1; if (stbi_gif_info_from_file(f, x, y, comp)) + return 1; + if (stbi_bmp_info_from_file(f, x, y, comp)) + return 1; + if (stbi_psd_info_from_file(f, x, y, comp)) + return 1; + if (stbi_pic_info_from_file(f, x, y, comp)) return 1; - // @TODO: stbi_bmp_info_from_file - // @TODO: stbi_psd_info_from_file + #ifndef STBI_NO_DDS + if (stbi_dds_info_from_file(f, x, y, comp, NULL)) + return 1; + #endif #ifndef STBI_NO_HDR - // @TODO: stbi_hdr_info_from_file + if (stbi_hdr_info_from_file(f, x, y, comp)) + return 1; #endif // test tga last because it's a crappy test! if (stbi_tga_info_from_file(f, x, y, comp)) @@ -4520,11 +4561,20 @@ int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *c if (stbi_png_info_from_memory(buffer, len, x, y, comp)) return 1; if (stbi_gif_info_from_memory(buffer, len, x, y, comp)) + return 1; + if(stbi_bmp_info_from_memory(buffer, len, x, y, comp)) return 1; - // @TODO: stbi_bmp_info_from_memory - // @TODO: stbi_psd_info_from_memory + if(stbi_psd_info_from_memory(buffer, len, x, y, comp)) + return 1; + if(stbi_pic_info_from_memory(buffer, len, x, y, comp)) + return 1; + #ifndef STBI_NO_DDS + if (stbi_dds_info_from_memory(buffer, len, x, y, comp, NULL)) + return 1; + #endif #ifndef STBI_NO_HDR - // @TODO: stbi_hdr_info_from_memory + if(stbi_hdr_info_from_memory(buffer, len, x, y, comp)) + return 1; #endif // test tga last because it's a crappy test! if (stbi_tga_info_from_memory(buffer, len, x, y, comp)) @@ -4535,12 +4585,233 @@ int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *c // add in my DDS loading support #ifndef STBI_NO_DDS #include "stbi_DDS_c.h" -#endif +#endif + +static int bmp_info(stbi *s, int *x, int *y, int *comp) { + int hsz; + if (get8(s) != 'B' || get8(s) != 'M') return 0; + skip(s,12); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return 0; + if (hsz == 12) { + *x = get16le(s); + *y = get16le(s); + } else { + *x = get32le(s); + *y = get32le(s); + } + if (get16le(s) != 1) return 0; + *comp = get16le(s) / 8; + return 1; +} + +int stbi_bmp_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi s; + start_mem(&s,buffer, len); + return bmp_info( &s, x, y, comp ); +} + +#ifndef STBI_NO_STDIO +int stbi_bmp_info(char const *filename, int *x, int *y, int *comp) +{ + int res; + FILE *f = fopen(filename, "rb"); + if (!f) return 0; + res = stbi_bmp_info_from_file( f, x, y, comp ); + fclose(f); + return res; +} + +int stbi_bmp_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + stbi s; + int res; + long n = ftell(f); + start_file(&s, f); + res = bmp_info(&s, x, y, comp); + fseek(f, n, SEEK_SET); + return res; +} +#endif + +static int psd_info(stbi *s, int *x, int *y, int *comp) +{ + int channelCount; + if (get32(s) != 0x38425053) return 0; + if (get16(s) != 1) return 0; + skip(s, 6); + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) return 0; + *y = get32(s); + *x = get32(s); + if (get16(s) != 8) return 0; + if (get16(s) != 3) return 0; + *comp = 4; + return 1; +} + +int stbi_psd_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi s; + start_mem(&s,buffer, len); + return psd_info( &s, x, y, comp ); +} + +#ifndef STBI_NO_STDIO +int stbi_psd_info(char const *filename, int *x, int *y, int *comp) +{ + int res; + FILE *f = fopen(filename, "rb"); + if (!f) return 0; + res = stbi_psd_info_from_file( f, x, y, comp ); + fclose(f); + return res; +} + +int stbi_psd_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + stbi s; + int res; + long n = ftell(f); + start_file(&s, f); + res = psd_info(&s, x, y, comp); + fseek(f, n, SEEK_SET); + return res; +} +#endif + +static int pic_info(stbi *s, int *x, int *y, int *comp) +{ + skip(s, 92); + + *x = get16(s); + *y = get16(s); + if (at_eof(s)) return 0; + if ((1 << 28) / (*x) < (*y)) return 0; + + skip(s, 8); + + int act_comp=0,num_packets=0,chained; + pic_packet_t packets[10]; + + do { + pic_packet_t *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = get8(s); + packet->size = get8u(s); + packet->type = get8u(s); + packet->channel = get8u(s); + act_comp |= packet->channel; + + if (at_eof(s)) return 0; + if (packet->size != 8) return 0; + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} + +int stbi_pic_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi s; + start_mem(&s,buffer, len); + return pic_info( &s, x, y, comp ); +} + +#ifndef STBI_NO_STDIO +int stbi_pic_info(char const *filename, int *x, int *y, int *comp) +{ + int res; + FILE *f = fopen(filename, "rb"); + if (!f) return 0; + res = stbi_pic_info_from_file( f, x, y, comp ); + fclose(f); + return res; +} + +int stbi_pic_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + stbi s; + int res; + long n = ftell(f); + start_file(&s, f); + res = pic_info(&s, x, y, comp); + fseek(f, n, SEEK_SET); + return res; +} +#endif + +#ifndef STBI_NO_HDR +static int hdr_info(stbi *s, int *x, int *y, int *comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) return 0; + + for(;;) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return 0; + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return 0; + token += 3; + *y = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return 0; + token += 3; + *x = strtol(token, NULL, 10); + *comp = 3; + return 1; +} + +int stbi_hdr_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi s; + start_mem(&s,buffer, len); + return hdr_info( &s, x, y, comp ); +} + +#ifndef STBI_NO_STDIO +int stbi_hdr_info(char const *filename, int *x, int *y, int *comp) +{ + int res; + FILE *f = fopen(filename, "rb"); + if (!f) return 0; + res = stbi_hdr_info_from_file( f, x, y, comp ); + fclose(f); + return res; +} + +int stbi_hdr_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + stbi s; + int res; + long n = ftell(f); + start_file(&s, f); + res = hdr_info(&s, x, y, comp); + fseek(f, n, SEEK_SET); + return res; +} +#endif +#endif #endif // STBI_HEADER_FILE_ONLY /* - revision history: + revision history: + 1.30 (2010-08-18) added stbi_info support for BMP,PSD,HDR,PIC by Martin Golini + 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) 1.27 (2010-08-01) cast-to-uint8 to fix warnings diff --git a/src/helper/SOIL/stb_image.h b/src/helper/SOIL/stb_image.h index 85a22d292..6bd8b725a 100644 --- a/src/helper/SOIL/stb_image.h +++ b/src/helper/SOIL/stb_image.h @@ -210,7 +210,7 @@ typedef struct extern int stbi_register_loader(stbi_loader *loader); // define faster low-level operations (typically SIMD support) -#if STBI_SIMD +#ifdef STBI_SIMD typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize); // compute an integer IDCT on "input" // input[x] = data[x] * dequantize[x] @@ -232,7 +232,6 @@ extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); // TYPE-SPECIFIC ACCESS - #ifdef STBI_TYPE_SPECIFIC_FUNCTIONS // is it a jpeg? @@ -267,9 +266,14 @@ extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp); extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_bmp_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_bmp_test_file (FILE *f); extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_bmp_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_bmp_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a tga? @@ -277,9 +281,14 @@ extern int stbi_tga_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp); extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_tga_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_tga_test_file (FILE *f); extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_tga_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_tga_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a psd? @@ -287,9 +296,14 @@ extern int stbi_psd_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp); extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_psd_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_psd_test_file (FILE *f); extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_psd_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_psd_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it an hdr? @@ -297,9 +311,14 @@ extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len); extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp); extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_hdr_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_hdr_test_file (FILE *f); extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_hdr_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_hdr_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a pic? @@ -307,9 +326,14 @@ extern int stbi_pic_test_memory (stbi_uc const *buffer, int len); extern stbi_uc *stbi_pic_load (char const *filename, int *x, int *y, int *comp, int req_comp); extern stbi_uc *stbi_pic_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); +extern int stbi_pic_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp); + #ifndef STBI_NO_STDIO extern int stbi_pic_test_file (FILE *f); extern stbi_uc *stbi_pic_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + +extern int stbi_pic_info (char const *filename, int *x, int *y, int *comp); +extern int stbi_pic_info_from_file (FILE *f, int *x, int *y, int *comp); #endif // is it a gif? @@ -326,12 +350,12 @@ extern int stbi_gif_info (char const *filename, int *x, int extern int stbi_gif_info_from_file (FILE *f, int *x, int *y, int *comp); #endif -#endif//STBI_TYPE_SPECIFIC_FUNCTIONS - -#ifndef STBI_NO_DDS -#include "stbi_DDS.h" +#ifndef STBI_NO_DDS +#include "stbi_DDS.h" #endif +#endif//STBI_TYPE_SPECIFIC_FUNCTIONS + #ifdef __cplusplus } #endif @@ -340,3 +364,4 @@ extern int stbi_gif_info_from_file (FILE *f, int *x, int // //// end header file ///////////////////////////////////////////////////// #endif // STBI_INCLUDE_STB_IMAGE_H + diff --git a/src/helper/SOIL/stbi_DDS_c.h b/src/helper/SOIL/stbi_DDS_c.h index bf2f18d1e..eefbef451 100755 --- a/src/helper/SOIL/stbi_DDS_c.h +++ b/src/helper/SOIL/stbi_DDS_c.h @@ -338,9 +338,13 @@ int stbi_dds_info(char const *filename, int *x, int *y, int *comp, int *isco int stbi_dds_info_from_file(FILE *f, int *x, int *y, int *comp, int *iscompressed) { - stbi s; - start_file(&s, f); - return dds_get_info( &s, x, y, comp, iscompressed ); + stbi s; + int res; + long n = ftell(f); + start_file(&s, f); + res = dds_get_info(&s, x, y, comp, iscompressed); + fseek(f, n, SEEK_SET); + return res; } #endif diff --git a/src/helper/haikuttf/sophist.h b/src/helper/haikuttf/sophist.h index 0e8ac5933..3818b6b8e 100644 --- a/src/helper/haikuttf/sophist.h +++ b/src/helper/haikuttf/sophist.h @@ -1,4 +1,4 @@ -/* sophist.h - 0.2 - public domain - Sean Barrett 2010 +/* sophist.h - 0.3 - public domain - Sean Barrett 2010 ** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net ** Sophist provides portable types; you typedef/#define them to your own names ** @@ -47,38 +47,40 @@ typedef unsigned short SOPHIST_uint16; typedef unsigned int SOPHIST_uint32; #endif -#if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \ - || (defined(__alpha) && defined(__DECC)) +#ifndef SOPHIST_NO_64 + #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \ + || (defined(__alpha) && defined(__DECC)) - typedef signed __int64 SOPHIST_int64; - typedef unsigned __int64 SOPHIST_uint64; - #define SOPHIST_has_64 1 - #define SOPHIST_int64_constant(x) (x##i64) - #define SOPHIST_uint64_constant(x) (x##ui64) - #define SOPHIST_printf_format64 "I64" + typedef signed __int64 SOPHIST_int64; + typedef unsigned __int64 SOPHIST_uint64; + #define SOPHIST_has_64 1 + #define SOPHIST_int64_constant(x) (x##i64) + #define SOPHIST_uint64_constant(x) (x##ui64) + #define SOPHIST_printf_format64 "I64" -#elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64) + #elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64) - typedef signed long SOPHIST_int64; - typedef unsigned long SOPHIST_uint64; + typedef signed long SOPHIST_int64; + typedef unsigned long SOPHIST_uint64; - #define SOPHIST_has_64 1 - #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x) - #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x) - #define SOPHIST_printf_format64 "l" + #define SOPHIST_has_64 1 + #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x) + #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x) + #define SOPHIST_printf_format64 "l" -#elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ - || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \ - || defined(sgi) || defined (__sgi) || defined(__sgi__) \ - || defined(_CRAYC) + #elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ + || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \ + || defined(sgi) || defined (__sgi) || defined(__sgi__) \ + || defined(_CRAYC) - typedef signed long long SOPHIST_int64; - typedef unsigned long long SOPHIST_uint64; + typedef signed long long SOPHIST_int64; + typedef unsigned long long SOPHIST_uint64; - #define SOPHIST_has_64 1 - #define SOPHIST_int64_constant(x) (x##LL) - #define SOPHIST_uint64_constant(x) (x##ULL) - #define SOPHIST_printf_format64 "ll" + #define SOPHIST_has_64 1 + #define SOPHIST_int64_constant(x) (x##LL) + #define SOPHIST_uint64_constant(x) (x##ULL) + #define SOPHIST_printf_format64 "ll" + #endif #endif #ifndef SOPHIST_has_64 @@ -142,7 +144,7 @@ SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *)); #define SOPHIST_endian SOPHIST_big_endian #endif -#endif // __INCLUDE_SOPHIST_H__ +#endif /* __INCLUDE_SOPHIST_H__ */ #ifdef SOPHIST_selftest #include @@ -154,6 +156,7 @@ int main(int argc, char **argv) SOPHIST_uint8 bytes[4]; SOPHIST_uint32 num; } x; + #if SOPHIST_has_64 char buffer[32]; sprintf(buffer, "%016" SOPHIST_printf_format64 "x", @@ -175,6 +178,10 @@ int main(int argc, char **argv) } fputs(fail ? "Failed.\n" : "Passed.\n", stdout); + + argc = argc; /* attempt to suppress unused variable warnings */ + argv = argv; + return 0; } #endif diff --git a/src/math/cmtrand.hpp b/src/math/cmtrand.hpp index 8e7411e17..ae48758b8 100755 --- a/src/math/cmtrand.hpp +++ b/src/math/cmtrand.hpp @@ -65,7 +65,7 @@ namespace EE { namespace Math { -class MTRand { +class EE_API MTRand { public: static const Uint32 M = 397; static const Int32 N = 624; diff --git a/src/math/math.hpp b/src/math/math.hpp index c6ce72273..d5fbc5b97 100755 --- a/src/math/math.hpp +++ b/src/math/math.hpp @@ -39,10 +39,17 @@ eeFloat EE_API Degrees( const eeFloat& Radians ); template T NextPowOfTwo( T Size ) { - T PowerOfTwo = 1; - while (PowerOfTwo < Size) - PowerOfTwo *= 2; - return PowerOfTwo; + T p = 1; + + while ( p < Size ) + p <<= 1; + + return p; +} + +template +T IsPow2( T v ) { + return ( ( v & ( v - 1 ) ) == 0 ); } template diff --git a/src/system/cobjectloader.hpp b/src/system/cobjectloader.hpp index b754bb2e1..98a91d03a 100644 --- a/src/system/cobjectloader.hpp +++ b/src/system/cobjectloader.hpp @@ -6,7 +6,7 @@ namespace EE { namespace System { -class cObjectLoader : cThread { +class EE_API cObjectLoader : cThread { public: typedef boost::function1 ObjLoadCallback; diff --git a/src/system/crc4.hpp b/src/system/crc4.hpp index ac7d32e5a..3814dc3d9 100755 --- a/src/system/crc4.hpp +++ b/src/system/crc4.hpp @@ -6,7 +6,7 @@ namespace EE { namespace System { /** @brief RC4 Encryption Class. For more information check Wikipedia: http://en.wikipedia.org/wiki/RC4. \n All the Decrypting functions call the Encrypting functions, there are there only for clarity, not really usefull. Use them as you wish. */ -class cRC4 { +class EE_API cRC4 { public: cRC4(); ~cRC4(); diff --git a/src/system/cresourceloader.cpp b/src/system/cresourceloader.cpp index 3575bc125..112945b80 100644 --- a/src/system/cresourceloader.cpp +++ b/src/system/cresourceloader.cpp @@ -145,5 +145,9 @@ void cResourceLoader::SetLoaded() { } } +eeFloat cResourceLoader::Progress() { + return ( (eeFloat)mObjsLoaded.size() / (eeFloat)( mObjs.size() + mObjsLoaded.size() ) ) * 100.f; +} + }} diff --git a/src/system/cresourceloader.hpp b/src/system/cresourceloader.hpp index 82bb74372..5e8fa04d4 100644 --- a/src/system/cresourceloader.hpp +++ b/src/system/cresourceloader.hpp @@ -8,7 +8,7 @@ namespace EE { namespace System { #define THREADS_AUTO (0xFFFFFFFF) -class cResourceLoader { +class EE_API cResourceLoader { public: typedef boost::function1 ResLoadCallback; @@ -32,6 +32,8 @@ class cResourceLoader { void Threaded( const bool& threaded ); bool Clear( const bool& ClearObjectsLoaded = true ); + + eeFloat Progress(); protected: bool mLoaded; bool mLoading; diff --git a/src/system/ctimeelapsed.cpp b/src/system/ctimeelapsed.cpp index 4a7ffa98c..c54ff440c 100755 --- a/src/system/ctimeelapsed.cpp +++ b/src/system/ctimeelapsed.cpp @@ -2,7 +2,7 @@ namespace EE { namespace System { -cTimeElapsed::cTimeElapsed() : mFirstCheck( getMicroseconds() ), mLastCheck( getMicroseconds() ), mElapsed(0) +cTimeElapsed::cTimeElapsed() : mFirstCheck( getMicroseconds() ), mLastCheck( getMicroseconds() ), mElapsed(0) { } @@ -11,14 +11,14 @@ cTimeElapsed::~cTimeElapsed() } eeDouble cTimeElapsed::Elapsed() { - mElapsed = ( getMicroseconds() - mLastCheck ) / (eeDouble)EE_CLOCKS_PER_SEC * 1000; - mLastCheck = getMicroseconds(); - + mElapsed = (eeDouble)( getMicroseconds() - mLastCheck ) / 1000.0; + mLastCheck = getMicroseconds(); + return mElapsed; } eeDouble cTimeElapsed::ElapsedSinceStart() { - return ( getMicroseconds() - mFirstCheck ) / (eeDouble)EE_CLOCKS_PER_SEC * 1000; + return (eeDouble)( getMicroseconds() - mFirstCheck ) / 1000.0; } void cTimeElapsed::Reset() { diff --git a/src/system/ctimeelapsed.hpp b/src/system/ctimeelapsed.hpp index 744c8691b..dec1be77f 100755 --- a/src/system/ctimeelapsed.hpp +++ b/src/system/ctimeelapsed.hpp @@ -13,17 +13,17 @@ class EE_API cTimeElapsed : private cTimer { ~cTimeElapsed(); /** Time elapsed between this call and the last call to Elapsed() */ - eeDouble Elapsed(); + eeDouble Elapsed(); /** Time elapsed between the last Reset ( First Reset is when the class is instantiated ) */ - eeDouble ElapsedSinceStart(); + eeDouble ElapsedSinceStart(); /** Restart the initial counter. ( set it as now ) */ - void Reset(); + void Reset(); protected: - eeUint mFirstCheck; - eeUint mLastCheck; - eeDouble mElapsed; + eeUint mFirstCheck; + eeUint mLastCheck; + eeDouble mElapsed; }; }} diff --git a/src/system/ctimer.cpp b/src/system/ctimer.cpp index e02330542..0ea228ea0 100755 --- a/src/system/ctimer.cpp +++ b/src/system/ctimer.cpp @@ -21,7 +21,7 @@ bool cTimer::setOption( const std::string key, const void * val ) { // Get the current process core mask DWORD procMask; DWORD sysMask; - + #if _MSC_VER >= 1400 && defined (_M_X64) GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask); #else @@ -45,7 +45,7 @@ void cTimer::reset() { // Get the current process core mask DWORD procMask; DWORD sysMask; - + #if _MSC_VER >= 1400 && defined (_M_X64) GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask); #else @@ -80,7 +80,7 @@ void cTimer::reset() { mLastTime = 0; mZeroClock = clock(); #else - zeroClock = clock(); + mZeroClock = clock(); gettimeofday(&start, NULL); #endif } @@ -177,20 +177,12 @@ unsigned long cTimer::getMicroseconds() { unsigned long cTimer::getMillisecondsCPU() { clock_t newClock = clock(); - #if EE_PLATFORM == EE_PLATFORM_WIN32 - return (unsigned long)( (eeFloat)( newClock - mZeroClock ) / ( (eeFloat)CLOCKS_PER_SEC / 1000.0 ) ); - #else - return (unsigned long)( (eeFloat)( newClock - zeroClock ) / ( (eeFloat)EE_CLOCKS_PER_SEC / 1000.0) ); - #endif + return (unsigned long)( (eeDouble)( newClock - mZeroClock ) / ( (eeDouble)CLOCKS_PER_SEC / 1000.0 ) ); } unsigned long cTimer::getMicrosecondsCPU() { clock_t newClock = clock(); - #if EE_PLATFORM == EE_PLATFORM_WIN32 - return (unsigned long)( (eeFloat)( newClock - mZeroClock ) / ( (eeFloat)CLOCKS_PER_SEC / 1000000.0 ) ); - #else - return (unsigned long)( (eeFloat)( newClock - zeroClock ) / ((eeFloat)EE_CLOCKS_PER_SEC / 1000000.0) ); - #endif + return (unsigned long)( (eeDouble)( newClock - mZeroClock ) / ( (eeDouble)CLOCKS_PER_SEC / 1000000.0 ) ); } }} diff --git a/src/system/ctimer.hpp b/src/system/ctimer.hpp index 2ac1868bf..6c707dc04 100644 --- a/src/system/ctimer.hpp +++ b/src/system/ctimer.hpp @@ -27,9 +27,8 @@ namespace EE { namespace System { class EE_API cTimer { private: + clock_t mZeroClock; #if EE_PLATFORM == EE_PLATFORM_WIN32 - clock_t mZeroClock; - unsigned long mStartTick; LONGLONG mLastTime; LARGE_INTEGER mStartTime; @@ -42,7 +41,6 @@ class EE_API cTimer { } #else struct timeval start; - clock_t zeroClock; #endif public: /** Timer constructor. MUST be called on same thread that calls getMilliseconds() */ diff --git a/src/test/ee.cpp b/src/test/ee.cpp index 299b9ec14..aac6c8932 100644 --- a/src/test/ee.cpp +++ b/src/test/ee.cpp @@ -1,11 +1,12 @@ #include "../ee.h" /** +@TODO Load Animated Sprites from Shape Groups. +@TODO Create a texture packer tool ( texture atlas ). @TODO Create a Vertex Buffer Object class ( with and without GL_ARB_vertex_buffer_object ). @TODO Add support for Frame Buffer Object and to switch rendering to FBO and Screen. @TODO Create a basic UI system ( add basic controls, add skinning support ). @TODO Support multitexturing. -@TODO Create a texture packer tool ( pack various textures into one texture ). @TODO Encapsulate SDL and OpenGL ( and remove unnecessary dependencies ). @TODO Add some Surface Grid class, to create special effects ( waved texture, and stuff like that ). @TODO Support color cursors ( not only black and white cursors, that really sucks ) - Imposible with SDL 1.2 @@ -190,6 +191,8 @@ class cEETest : private cThread { eeFloat mAxisY; Uint32 mFace; + + cTextureGroupLoader * mTGL; }; @@ -254,6 +257,8 @@ void cEETest::Init() { Scenes[1] = boost::bind( &cEETest::Screen2, this ); Scenes[2] = boost::bind( &cEETest::Screen3, this ); + mTGL = new cTextureGroupLoader( MyPath + "res/1.etg", true ); + InBuf.Start(); SetRandomSeed(); @@ -408,11 +413,11 @@ void cEETest::CmdSetPartsNum ( const std::vector < std::wstring >& params ) { if ( params.size() >= 2 ) { try { Int32 tInt = boost::lexical_cast( wstringTostring( params[1] ) ); - if ( tInt >= 0 && tInt <= 10000 ) { + if ( tInt >= 0 && tInt <= 100000 ) { PS[2].Create(WormHole, tInt, TN[5], EE->GetWidth() * 0.5f, EE->GetHeight() * 0.5f, 32, true); Con.PushText( L"Wormhole Particles Number Changed to: " + toWStr(tInt) ); } else - Con.PushText( L"Valid parameters are between 0 and 10000 (0 = no limit)." ); + Con.PushText( L"Valid parameters are between 0 and 100000 (0 = no limit)." ); } catch (boost::bad_lexical_cast&) { Con.PushText( L"Invalid Parameter. Expected int value from '" + params[1] + L"'." ); } @@ -1088,6 +1093,19 @@ void cEETest::Process() { else mFontLoader.Update(); + if ( !mTGL->IsLoaded() ) + mTGL->Update(); + else { + cShapeGroup * tSG = cShapeGroupManager::instance()->GetByName( "1.png" ); + + if ( NULL != tSG ) { + cShape * tS = tSG->GetByName( "rn01.png" ); + + if ( NULL != tS ) + tS->Draw( 320, 0 ); + } + } + if ( KM->IsKeyUp(KEY_F12) ) EE->TakeScreenshot( MyPath + "data/screenshots/" ); //After render and before Display EE->Display(); @@ -1108,6 +1126,8 @@ void cEETest::End() { cLog::instance()->Save(); + delete mTGL; + cEngine::DestroySingleton(); } @@ -1146,6 +1166,19 @@ void cEETest::Particles() { int main (int argc, char * argv []) { cEETest Test; Test.Process(); +/* + cTexturePacker tp; + std::string Path = "/home/downloads/files/temp/bnb/allin/"; + + if ( argc > 1 ) + Path = std::string( argv[1] ); + + tp.AddTexturesPath( Path ); + + tp.PackTextures( 256, 256 ); + + tp.Save( AppPath() + "res/1.png", EE_SAVE_TYPE_PNG ); +*/ return 0; } diff --git a/src/ui/cuibackground.hpp b/src/ui/cuibackground.hpp index 0f7c2e1aa..fbb3a3393 100644 --- a/src/ui/cuibackground.hpp +++ b/src/ui/cuibackground.hpp @@ -5,7 +5,7 @@ namespace EE { namespace UI { -class cUIBackground { +class EE_API cUIBackground { public: cUIBackground(); cUIBackground( const eeColorA& Color, const eeUint& Corners = 0, const EE_RENDERALPHAS& BlendMode = ALPHA_NORMAL ); diff --git a/src/ui/cuiborder.hpp b/src/ui/cuiborder.hpp index 477725f16..9019ef68d 100644 --- a/src/ui/cuiborder.hpp +++ b/src/ui/cuiborder.hpp @@ -5,7 +5,7 @@ namespace EE { namespace UI { -class cUIBorder { +class EE_API cUIBorder { public: cUIBorder(); cUIBorder( const cUIBorder& border ); diff --git a/src/utils/cinterpolation.hpp b/src/utils/cinterpolation.hpp index d0cb11265..2aa428fbd 100644 --- a/src/utils/cinterpolation.hpp +++ b/src/utils/cinterpolation.hpp @@ -17,7 +17,7 @@ class Point1d { typedef Point1d cPoint1df; /** @brief A interpolation movement manager, used for movement interpolations. */ -class cInterpolation { +class EE_API cInterpolation { public: cInterpolation(); diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index bc9a696a2..24aec9dce 100755 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -16,9 +16,8 @@ #if EE_PLATFORM == EE_PLATFORM_WIN32 #include -#else - #include #endif +#include #if EE_PLATFORM == EE_PLATFORM_WIN32 #include @@ -32,14 +31,9 @@ namespace EE { namespace Utils { -bool FileExists(const std::string& filepath) { - std::fstream fs; - fs.open( filepath.c_str(), std::ios::in ); - if( fs.is_open() ) { - fs.close(); - return true; - } - return false; +bool FileExists( const std::string& Filepath ) { + struct stat st; + return ( stat( Filepath.c_str(), &st ) == 0 ); } Uint32 eeGetTicks() { @@ -197,13 +191,13 @@ std::vector FilesGetInPath( const std::string& path ) { } Uint32 FileSize( const std::string& Filepath ) { - std::ifstream f; - f.open(Filepath.c_str(), std::ios_base::binary | std::ios_base::in); - if (!f.good() || f.eof() || !f.is_open()) { return 0; } - f.seekg(0, std::ios_base::beg); - std::ifstream::pos_type begin_pos = f.tellg(); - f.seekg(0, std::ios_base::end); - return static_cast(f.tellg() - begin_pos); + struct stat st; + int res = stat( Filepath.c_str(), &st ); + + if ( 0 == res ) + return st.st_size; + + return 0; } eeDouble GetSystemTime() { @@ -337,6 +331,18 @@ std::string FileExtension( const std::string& filepath, const bool& lowerExt ) { return tstr; } +std::string FileRemoveExtension( const std::string& filepath ) { + return filepath.substr( 0, filepath.find_last_of(".") ); +} + +std::string FileNameFromPath( const std::string& filepath ) { + return filepath.substr( filepath.find_last_of("/\\") + 1 ); +} + +std::string FileRemoveFileName( const std::string& filepath ) { + return filepath.substr( 0, filepath.find_last_of("/\\") + 1 ); +} + eeInt GetNumCPUs() { eeInt nprocs = -1; @@ -389,4 +395,14 @@ bool FileWrite( const std::string& filepath, const std::vector& data ) { return FileWrite( filepath, reinterpret_cast ( &data[0] ), (Uint32)data.size() ); } +Uint32 FileGetModificationDate( const std::string& Filepath ) { + struct stat st; + int res = stat( Filepath.c_str(), &st ); + + if ( 0 == res ) + return st.st_mtime; + + return 0; +} + }} diff --git a/src/utils/utils.hpp b/src/utils/utils.hpp index 631b1d64b..56279e178 100755 --- a/src/utils/utils.hpp +++ b/src/utils/utils.hpp @@ -5,7 +5,7 @@ namespace EE { namespace Utils { /** @return True if the file exists */ - bool EE_API FileExists(const std::string& filepath); + bool EE_API FileExists( const std::string& Filepath ); /** @return The number of milliseconds since the EE++ library initialization. Note that this value wraps if the program runs for more than ~49 days. */ Uint32 EE_API eeGetTicks(); @@ -63,6 +63,15 @@ namespace EE { namespace Utils { */ std::string FileExtension( const std::string& filepath, const bool& lowerExt = true ); + /** @return The file name of a file path */ + std::string FileNameFromPath( const std::string& filepath ); + + /** @return Removes the file name from a path, and return the path. */ + std::string FileRemoveFileName( const std::string& filepath ); + + /** @return Removes the extension of a filepath */ + std::string FileRemoveExtension( const std::string& filepath ); + /** Write a file in binary mode and close it. */ bool FileWrite( const std::string& filepath, const Uint8* data, const Uint32& dataSize ); @@ -71,6 +80,9 @@ namespace EE { namespace Utils { /** @return The Number of CPUs of the system. */ eeInt GetNumCPUs(); + + /** @return The modification date of the file */ + Uint32 FileGetModificationDate( const std::string& Filepath ); } }