diff --git a/bin/assets/atlases/bnb.eta b/bin/assets/atlases/bnb.eta index 49f1f7951..5a3915aea 100644 Binary files a/bin/assets/atlases/bnb.eta and b/bin/assets/atlases/bnb.eta differ diff --git a/bin/assets/atlases/bnb.png b/bin/assets/atlases/bnb.png index 6b75bc5e7..a93d649b9 100644 Binary files a/bin/assets/atlases/bnb.png and b/bin/assets/atlases/bnb.png differ diff --git a/include/eepp/graphics/pixeldensity.hpp b/include/eepp/graphics/pixeldensity.hpp index 3b73522a5..535d7a4be 100644 --- a/include/eepp/graphics/pixeldensity.hpp +++ b/include/eepp/graphics/pixeldensity.hpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace EE::Math; @@ -37,6 +38,20 @@ class EE_API PixelDensity { return toFloat( (EE_PIXEL_DENSITY)pd ); } + static EE_PIXEL_DENSITY fromString( std::string str ) { + String::toLowerInPlace( str ); + if ( "mdpi" == str ) return PD_MDPI; + else if ( "hdpi" == str ) return PD_HDPI; + else if ( "xhdpi" == str ) return PD_XHDPI; + else if ( "xxhdpi" == str ) return PD_XXHDPI; + else if ( "xxxhdpi" == str ) return PD_XXXHDPI; + return PD_MDPI; + } + + static EE_PIXEL_DENSITY fromString( String str ) { + return fromString( str.toUtf8() ); + } + static const Float& getPixelDensity(); static void setPixelDensity( const Float& pixelDensity ); diff --git a/include/eepp/graphics/texturepacker.hpp b/include/eepp/graphics/texturepacker.hpp index d129c552e..794f255df 100644 --- a/include/eepp/graphics/texturepacker.hpp +++ b/include/eepp/graphics/texturepacker.hpp @@ -113,11 +113,11 @@ class EE_API TexturePacker { std::list mTextures; - Int32 mLongestEdge; Int32 mTotalArea; TexturePackerNode * mFreeList; Int32 mWidth; Int32 mHeight; + Sizei mMaxSize; bool mPacked; bool mAllowFlipping; TexturePacker * mChild; @@ -169,6 +169,8 @@ class EE_API TexturePacker { void createChild(); bool addPackerTex( TexturePackerTex * TPack ); + + void reset(); }; }} diff --git a/src/eepp/graphics/texturepacker.cpp b/src/eepp/graphics/texturepacker.cpp index 0a86abf10..27ad93572 100644 --- a/src/eepp/graphics/texturepacker.cpp +++ b/src/eepp/graphics/texturepacker.cpp @@ -9,11 +9,10 @@ namespace EE { namespace Graphics { TexturePacker::TexturePacker( const Uint32& MaxWidth, const Uint32& MaxHeight, const EE_PIXEL_DENSITY& PixelDensity, const bool& ForcePowOfTwo, const Uint32& PixelBorder, const bool& AllowFlipping ) : - mLongestEdge(0), mTotalArea(0), mFreeList(NULL), - mWidth(0), - mHeight(0), + mWidth(128), + mHeight(128), mPacked(false), mAllowFlipping(false), mChild(NULL), @@ -28,11 +27,11 @@ TexturePacker::TexturePacker( const Uint32& MaxWidth, const Uint32& MaxHeight, c } TexturePacker::TexturePacker() : - mLongestEdge(0), mTotalArea(0), mFreeList(NULL), - mWidth(1024), - mHeight(1024), + mWidth(128), + mHeight(128), + mMaxSize(mWidth, mHeight), mPacked(false), mAllowFlipping(false), mChild(NULL), @@ -51,8 +50,7 @@ TexturePacker::~TexturePacker() } void TexturePacker::close() { - mLongestEdge = 0; - mTotalArea = 0; + reset(); std::list::iterator it; @@ -61,6 +59,19 @@ void TexturePacker::close() { } mTextures.clear(); +} + +void TexturePacker::reset() { + mStrategy = PackBig; + mCount = mTextures.size(); + + TexturePackerTex * t = NULL; + std::list::iterator it; + + for ( it = mTextures.begin(); it != mTextures.end(); it++ ) { + t = (*it); + t->placed( false ); + } if ( NULL != mFreeList ) { TexturePackerNode * next = mFreeList; @@ -73,6 +84,8 @@ void TexturePacker::close() { eeSAFE_DELETE( kill ); } + + mFreeList = NULL; } eeSAFE_DELETE( mChild ); @@ -80,14 +93,14 @@ void TexturePacker::close() { void TexturePacker::setOptions( const Uint32& MaxWidth, const Uint32& MaxHeight, const EE_PIXEL_DENSITY& PixelDensity, const bool& ForcePowOfTwo, const Uint32& PixelBorder, const bool& AllowFlipping ) { if ( !mTextures.size() ) { // only can change the dimensions before adding any texture - mWidth = MaxWidth; - mHeight = MaxHeight; + mMaxSize.x = MaxWidth; + mMaxSize.y = MaxHeight; - if ( ForcePowOfTwo && !Math::isPow2( mWidth ) ) - mWidth = Math::nextPowOfTwo( mWidth ); + if ( ForcePowOfTwo && !Math::isPow2( mMaxSize.x ) ) + mMaxSize.x = Math::nextPowOfTwo( mMaxSize.x ); - if ( ForcePowOfTwo && !Math::isPow2( mHeight ) ) - mHeight = Math::nextPowOfTwo( mHeight ); + if ( ForcePowOfTwo && !Math::isPow2( mMaxSize.y ) ) + mMaxSize.y = Math::nextPowOfTwo( mMaxSize.y ); mForcePowOfTwo = ForcePowOfTwo; mAllowFlipping = AllowFlipping; @@ -192,8 +205,6 @@ void TexturePacker::addBorderToTextures( const Int32& BorderSize ) { t->width ( t->width() + BorderSize ); t->height ( t->height() + BorderSize ); } - - mLongestEdge += BorderSize; } } @@ -376,10 +387,9 @@ void TexturePacker::createChild() { bool TexturePacker::addTexturesPath( std::string TexturesPath ) { if ( FileSystem::isDirectory( TexturesPath ) ) { - FileSystem::dirPathAddSlashAtEnd( TexturesPath ); - std::vector files = FileSystem::filesGetInPath( TexturesPath ); + std::vector files = FileSystem::filesGetInPath( TexturesPath ); std::sort( files.begin(), files.end() ); for ( Uint32 i = 0; i < files.size(); i++ ) { @@ -397,8 +407,8 @@ bool TexturePacker::addTexturesPath( std::string TexturesPath ) { bool TexturePacker::addPackerTex( TexturePackerTex * TPack ) { if ( TPack->loadedInfo() ) { // Only add the texture if can fit inside the atlas, otherwise it will ignore it - if ( ( TPack->width() + mPixelBorder <= mWidth && TPack->height() + mPixelBorder <= mHeight ) || - ( mAllowFlipping && ( TPack->width() + mPixelBorder <= mHeight && TPack->height() + mPixelBorder <= mWidth ) ) + if ( ( TPack->width() + mPixelBorder <= mMaxSize.getWidth() && TPack->height() + mPixelBorder <= mMaxSize.getHeight() ) || + ( mAllowFlipping && ( TPack->width() + mPixelBorder <= mMaxSize.getHeight() && TPack->height() + mPixelBorder <= mMaxSize.getWidth() ) ) ) { mTotalArea += TPack->area(); @@ -442,9 +452,6 @@ bool TexturePacker::addTexture( const std::string& TexturePath ) { } Int32 TexturePacker::packTextures() { // pack the textures, the return code is the amount of wasted/unused area. - if ( mWidth <= 0 || mHeight <= 0 ) - return 0; - TexturePackerTex * t = NULL; addBorderToTextures( (Int32)mPixelBorder ); @@ -476,7 +483,7 @@ Int32 TexturePacker::packTextures() { // pack the textures, the return code is t eePRINTL( "Chaging Strategy to Tiny. %s faults.", t->name().c_str() ); } else if ( PackTiny == mStrategy ) { mStrategy = PackFail; - eePRINTL( "Strategy fail, must create a new image. %s faults.", t->name().c_str() ); + eePRINTL( "Strategy fail, must expand image or create a new one. %s faults.", t->name().c_str() ); } } else { insertTexture( t, bestFit, edgeCount, previousBestFit ); @@ -484,8 +491,28 @@ Int32 TexturePacker::packTextures() { // pack the textures, the return code is t } if ( PackFail == mStrategy ) { - eePRINTL( "Creating a new image as a child." ); - createChild(); + if ( mWidth < mMaxSize.getWidth() || mHeight < mMaxSize.getHeight() ) { + reset(); + addBorderToTextures( -( (Int32)mPixelBorder ) ); + + if ( mWidth <= mHeight ) { + mWidth *= 2; + + if ( mWidth > mMaxSize.getWidth() ) + mWidth = mMaxSize.getWidth(); + } else { + mHeight *= 2; + + if ( mHeight > mMaxSize.getHeight() ) + mHeight = mMaxSize.getHeight(); + } + + return packTextures(); + } else { + eePRINTL( "Creating a new image as a child." ); + createChild(); + } + break; } } diff --git a/src/eepp/graphics/texturepackertex.hpp b/src/eepp/graphics/texturepackertex.hpp index 849a21f26..8fd3d027c 100644 --- a/src/eepp/graphics/texturepackertex.hpp +++ b/src/eepp/graphics/texturepackertex.hpp @@ -43,6 +43,8 @@ class TexturePackerTex { inline const bool& placed() const { return mPlaced; } + inline void placed( bool placed ) { mPlaced = placed; } + inline const bool& flipped() const { return mFlipped; } inline const Int32& longestEdge() const { return mLongestEdge; } diff --git a/src/eepp/ui/tools/textureatlasnew.cpp b/src/eepp/ui/tools/textureatlasnew.cpp index a353f1833..8ce18abe5 100644 --- a/src/eepp/ui/tools/textureatlasnew.cpp +++ b/src/eepp/ui/tools/textureatlasnew.cpp @@ -17,7 +17,7 @@ TextureAtlasNew::TextureAtlasNew( TGCreateCb NewTGCb ) : return; mUIWindow = UIWindow::New(); - mUIWindow->setSizeWithDecoration( 378, 244 )->setWinFlags( UI_WIN_CLOSE_BUTTON | UI_WIN_USE_DEFAULT_BUTTONS_ACTIONS | UI_WIN_SHARE_ALPHA_WITH_CHILDS | UI_WIN_MODAL )->setMinWindowSize( 378, 244 ); + mUIWindow->setSizeWithDecoration( 378, 244 )->setWinFlags( UI_WIN_CLOSE_BUTTON | UI_WIN_USE_DEFAULT_BUTTONS_ACTIONS | UI_WIN_SHARE_ALPHA_WITH_CHILDS | UI_WIN_MODAL )->setMinWindowSize( 378, 260 ); mUIWindow->addEventListener( UIEvent::EventOnWindowClose, cb::Make1( this, &TextureAtlasNew::windowClose ) ); mUIWindow->setTitle( "New Texture Atlas" ); @@ -33,6 +33,7 @@ TextureAtlasNew::TextureAtlasNew( TGCreateCb NewTGCb ) : FileTypes.push_back( "BMP" ); FileTypes.push_back( "PNG" ); FileTypes.push_back( "DDS" ); + FileTypes.push_back( "JPG" ); mSaveFileType->getListBox()->addListBoxItems( FileTypes ); mSaveFileType->getListBox()->setSelected( "PNG" ); @@ -57,7 +58,7 @@ TextureAtlasNew::TextureAtlasNew( TGCreateCb NewTGCb ) : std::vector Sizes; - for ( Uint32 i = 6; i < 14; i++ ) { + for ( Uint32 i = 8; i < 15; i++ ) { Sizes.push_back( String::toStr( 1 << i ) ); } @@ -65,20 +66,34 @@ TextureAtlasNew::TextureAtlasNew( TGCreateCb NewTGCb ) : mComboHeight->getListBox()->addListBoxItems( Sizes ); mComboWidth->getInputTextBuffer()->setAllowOnlyNumbers( true ); mComboHeight->getInputTextBuffer()->setAllowOnlyNumbers( true ); - mComboWidth->getListBox()->setSelected( "512" ); - mComboHeight->getListBox()->setSelected( "512" ); + mComboWidth->getListBox()->setSelected( "2048" ); + mComboHeight->getListBox()->setSelected( "2048" ); createTxtBox( Vector2i( 10, 110 ), "Space between sub textures (pixels):" ); mPixelSpace = UISpinBox::New(); mPixelSpace->setParent( mUIWindow->getContainer() )->setSize( 100, 0 )->setPosition( PosX, 110 )->setVisible( true )->setEnabled( true ); - createTxtBox( Vector2i( 10, 140 ), "Texture Atlas Folder Path:" ); + createTxtBox( Vector2i( 10, 140 ), "Pixel Density:" ); + mPixelDensity = UIDropDownList::New(); + mPixelDensity->setParent( mUIWindow->getContainer() )->setSize( 100, 0 )->setPosition( PosX, 140 ); + + std::vector PixelDensities; + PixelDensities.push_back( "MDPI" ); + PixelDensities.push_back( "HDPI" ); + PixelDensities.push_back( "XHDPI" ); + PixelDensities.push_back( "XXHDPI" ); + PixelDensities.push_back( "XXXHDPI" ); + + mPixelDensity->getListBox()->addListBoxItems( PixelDensities ); + mPixelDensity->getListBox()->setSelected( "MDPI" ); + + createTxtBox( Vector2i( 10, 170 ), "Texture Atlas Folder Path:" ); mTGPath = UITextInput::New()->setMaxLength( 512 ); - mTGPath->setParent( mUIWindow->getContainer() )->setSize( mUIWindow->getContainer()->getSize().getWidth() - 60, 0 )->setPosition( 10, 160 ); + mTGPath->setParent( mUIWindow->getContainer() )->setSize( mUIWindow->getContainer()->getSize().getWidth() - 60, 0 )->setPosition( 10, 190 ); mTGPath->setAllowEditing( false ); mSetPathButton = UIPushButton::New(); - mSetPathButton->setParent( mUIWindow->getContainer() )->setSize( 32, 22 )->setPosition( mUIWindow->getContainer()->getSize().getWidth() - 10 - 32, 160 ); + mSetPathButton->setParent( mUIWindow->getContainer() )->setSize( 32, mTGPath->getSize().getHeight() )->setPosition( mUIWindow->getContainer()->getSize().getWidth() - 10 - 32, 190 ); mSetPathButton->setText( "..." ); mSetPathButton->addEventListener( UIEvent::EventMouseClick, cb::Make1( this, &TextureAtlasNew::onDialogFolderSelect ) ); @@ -143,7 +158,7 @@ void TextureAtlasNew::windowClose( const UIEvent * Event ) { } static bool isValidExtension( const std::string& ext ) { - return ext == "png" || ext == "bmp" || ext == "dds" || ext == "tga"; + return ext == "png" || ext == "bmp" || ext == "dds" || ext == "tga" || ext == "jpg"; } void TextureAtlasNew::textureAtlasSave( const UIEvent * Event ) { @@ -157,7 +172,7 @@ void TextureAtlasNew::textureAtlasSave( const UIEvent * Event ) { b = static_cast( mPixelSpace->getValue() ); if ( Res1 && Res2 ) { - Graphics::TexturePacker * TexturePacker = eeNew( Graphics::TexturePacker, ( w, h, PD_MDPI, false, b ) ); + Graphics::TexturePacker * TexturePacker = eeNew( Graphics::TexturePacker, ( w, h, PixelDensity::fromString( mPixelDensity->getText() ), false, b ) ); TexturePacker->addTexturesPath( mTGPath->getText() ); diff --git a/src/eepp/ui/tools/textureatlasnew.hpp b/src/eepp/ui/tools/textureatlasnew.hpp index 4d889d47f..1ba713193 100644 --- a/src/eepp/ui/tools/textureatlasnew.hpp +++ b/src/eepp/ui/tools/textureatlasnew.hpp @@ -23,10 +23,11 @@ class EE_API TextureAtlasNew { TGCreateCb mNewTGCb; UIComboBox * mComboWidth; UIComboBox * mComboHeight; - UISpinBox * mPixelSpace; + UISpinBox * mPixelSpace; UITextInput * mTGPath; UIPushButton * mSetPathButton; UIDropDownList * mSaveFileType; + UIDropDownList * mPixelDensity; void windowClose( const UIEvent * Event ); diff --git a/src/test/eetest.cpp b/src/test/eetest.cpp index 55e9e327f..320219cef 100644 --- a/src/test/eetest.cpp +++ b/src/test/eetest.cpp @@ -1046,7 +1046,7 @@ void EETest::onTextureLoaded( ResourceLoader * ResLoaded ) { void EETest::loadTextures() { if ( !FileSystem::fileExists( MyPath + "atlases/bnb.eta" ) ) { - TexturePacker tp( 512, 512, PD_MDPI, true, 0 ); + TexturePacker tp( 1024, 512, PD_MDPI, true, 1 ); tp.addTexturesPath( MyPath + "atlases/bnb/" ); tp.save( MyPath + "atlases/bnb.png" ); }