From 565288f5876e0ad84b2651399d76a00cee6d57e7 Mon Sep 17 00:00:00 2001 From: BoydTang Date: Mon, 13 Jan 2014 22:54:26 +0800 Subject: [PATCH 01/13] =?UTF-8?q?-=20fix=20long=20string=20will=20be=20cut?= =?UTF-8?q?=20off=20by=20function=20=E2=80=9Ccc=5Futf8=5Fto=5Futf16?= =?UTF-8?q?=E2=80=9D=20(=20=E2=80=9Ccc=5Futf8=5Fstrlen=E2=80=9D=20returns?= =?UTF-8?q?=20long=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cocos/2d/ccUTF8.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/2d/ccUTF8.cpp b/cocos/2d/ccUTF8.cpp index 6e70a313d5..c4b9893a04 100644 --- a/cocos/2d/ccUTF8.cpp +++ b/cocos/2d/ccUTF8.cpp @@ -279,7 +279,7 @@ cc_utf8_get_char (const char * p) unsigned short* cc_utf8_to_utf16(const char* str_old, int length/* = -1 */, int* rUtf16Size/* = nullptr */) { - unsigned short len = cc_utf8_strlen(str_old, length); + long len = cc_utf8_strlen(str_old, length); if (rUtf16Size != nullptr) { *rUtf16Size = len; } From a765e5e7e1d54cc9f2557734693d6cf1f2d05ea2 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Thu, 16 Jan 2014 16:37:29 +0800 Subject: [PATCH 02/13] closed #3628:Integrate LabelAtlas with new Label --- cocos/2d/CCFont.cpp | 16 ++ cocos/2d/CCFont.h | 4 + cocos/2d/CCFontAtlasCache.cpp | 59 ++++++ cocos/2d/CCFontAtlasCache.h | 4 + cocos/2d/CCFontAtlasFactory.cpp | 42 +++++ cocos/2d/CCFontAtlasFactory.h | 4 + cocos/2d/CCFontCharMap.cpp | 171 ++++++++++++++++++ cocos/2d/CCFontCharMap.h | 69 +++++++ cocos/2d/CCLabel.cpp | 87 +++++++++ cocos/2d/CCLabel.h | 18 +- cocos/2d/cocos2d.vcxproj | 2 + cocos/2d/cocos2d.vcxproj.filters | 6 + .../Classes/LabelTest/LabelTestNew.cpp | 47 +++++ .../TestCpp/Classes/LabelTest/LabelTestNew.h | 16 ++ 14 files changed, 540 insertions(+), 5 deletions(-) create mode 100644 cocos/2d/CCFontCharMap.cpp create mode 100644 cocos/2d/CCFontCharMap.h diff --git a/cocos/2d/CCFont.cpp b/cocos/2d/CCFont.cpp index dc363cfe02..1c2d3bab86 100644 --- a/cocos/2d/CCFont.cpp +++ b/cocos/2d/CCFont.cpp @@ -28,6 +28,7 @@ #include "CCFontFNT.h" #include "CCFontFreeType.h" +#include "CCFontCharMap.h" #include "edtaa3func.h" NS_CC_BEGIN @@ -116,6 +117,21 @@ Font* Font::createWithFNT(const std::string& fntFilePath) return FontFNT::create(fntFilePath); } +Font* Font::createWithCharMap(const std::string& plistFile) +{ + return FontCharMap::create(plistFile); +} + +Font* Font::createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) +{ + return FontCharMap::create(texture,itemWidth,itemHeight,startCharMap); +} + +Font* Font::createWithCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) +{ + return FontCharMap::create(charMapFile,itemWidth,itemHeight,startCharMap); +} + unsigned char * Font::makeDistanceMap( unsigned char *img, unsigned int width, unsigned int height) { unsigned int pixelAmount = (width + 2 * DistanceMapSpread) * (height + 2 * DistanceMapSpread); diff --git a/cocos/2d/CCFont.h b/cocos/2d/CCFont.h index 440da0808b..abbbf0098d 100644 --- a/cocos/2d/CCFont.h +++ b/cocos/2d/CCFont.h @@ -45,6 +45,10 @@ public: // create the font static Font* createWithTTF(const std::string& fntName, int fontSize, GlyphCollection glyphs, const char *customGlyphs); static Font* createWithFNT(const std::string& fntFilePath); + + static Font * createWithCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); + static Font * createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); + static Font * createWithCharMap(const std::string& plistFile); static unsigned char * makeDistanceMap(unsigned char *img, unsigned int width, unsigned int height); void setDistanceFieldEnabled(bool distanceFieldEnabled); diff --git a/cocos/2d/CCFontAtlasCache.cpp b/cocos/2d/CCFontAtlasCache.cpp index ccea76b254..3850791f7d 100644 --- a/cocos/2d/CCFontAtlasCache.cpp +++ b/cocos/2d/CCFontAtlasCache.cpp @@ -69,6 +69,65 @@ FontAtlas * FontAtlasCache::getFontAtlasFNT(const std::string& fontFileName) return tempAtlas; } +FontAtlas * FontAtlasCache::getFontAtlasCharMap(const std::string& plistFile) +{ + std::string atlasName = generateFontName(plistFile, 0, GlyphCollection::CUSTOM,false); + FontAtlas *tempAtlas = _atlasMap[atlasName]; + + if ( !tempAtlas ) + { + tempAtlas = FontAtlasFactory::createAtlasFromCharMap(plistFile); + if (tempAtlas) + _atlasMap[atlasName] = tempAtlas; + } + else + { + tempAtlas->retain(); + } + + return tempAtlas; +} + +FontAtlas * FontAtlasCache::getFontAtlasCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) +{ + char tmp[30]; + sprintf_s(tmp,"name:%u_%d_%d_%d",texture->getName(),itemWidth,itemHeight,startCharMap); + std::string atlasName = generateFontName(tmp, 0, GlyphCollection::CUSTOM,false); + FontAtlas *tempAtlas = _atlasMap[atlasName]; + + if ( !tempAtlas ) + { + tempAtlas = FontAtlasFactory::createAtlasFromCharMap(texture,itemWidth,itemHeight,startCharMap); + if (tempAtlas) + _atlasMap[atlasName] = tempAtlas; + } + else + { + tempAtlas->retain(); + } + + return tempAtlas; +} + +FontAtlas * FontAtlasCache::getFontAtlasCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) +{ + std::string atlasName = generateFontName(charMapFile, 0, GlyphCollection::CUSTOM,false); + FontAtlas *tempAtlas = _atlasMap[atlasName]; + + if ( !tempAtlas ) + { + tempAtlas = FontAtlasFactory::createAtlasFromCharMap(charMapFile,itemWidth,itemHeight,startCharMap); + if (tempAtlas) + _atlasMap[atlasName] = tempAtlas; + } + else + { + tempAtlas->retain(); + } + + return tempAtlas; +} + std::string FontAtlasCache::generateFontName(const std::string& fontFileName, int size, GlyphCollection theGlyphs, bool useDistanceField) { std::string tempName(fontFileName); diff --git a/cocos/2d/CCFontAtlasCache.h b/cocos/2d/CCFontAtlasCache.h index bdc7dd24d1..f9e84ba904 100644 --- a/cocos/2d/CCFontAtlasCache.h +++ b/cocos/2d/CCFontAtlasCache.h @@ -41,6 +41,10 @@ public: static FontAtlas * getFontAtlasTTF(const std::string& fontFileName, int size, GlyphCollection glyphs, const char *customGlyphs = 0, bool useDistanceField = false); static FontAtlas * getFontAtlasFNT(const std::string& fontFileName); + + static FontAtlas * getFontAtlasCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); + static FontAtlas * getFontAtlasCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); + static FontAtlas * getFontAtlasCharMap(const std::string& plistFile); static bool releaseFontAtlas(FontAtlas *atlas); diff --git a/cocos/2d/CCFontAtlasFactory.cpp b/cocos/2d/CCFontAtlasFactory.cpp index c9d3ebbb3b..3b6d536223 100644 --- a/cocos/2d/CCFontAtlasFactory.cpp +++ b/cocos/2d/CCFontAtlasFactory.cpp @@ -60,4 +60,46 @@ FontAtlas * FontAtlasFactory::createAtlasFromFNT(const std::string& fntFilePath) } } +FontAtlas * FontAtlasFactory::createAtlasFromCharMap(const std::string& plistFile) +{ + Font *font = Font::createWithCharMap(plistFile); + + if(font) + { + return font->createFontAtlas(); + } + else + { + return nullptr; + } +} + +FontAtlas * FontAtlasFactory::createAtlasFromCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) +{ + Font *font = Font::createWithCharMap(texture,itemWidth,itemHeight,startCharMap); + + if(font) + { + return font->createFontAtlas(); + } + else + { + return nullptr; + } +} + +FontAtlas * FontAtlasFactory::createAtlasFromCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) +{ + Font *font = Font::createWithCharMap(charMapFile,itemWidth,itemHeight,startCharMap); + + if(font) + { + return font->createFontAtlas(); + } + else + { + return nullptr; + } +} + NS_CC_END diff --git a/cocos/2d/CCFontAtlasFactory.h b/cocos/2d/CCFontAtlasFactory.h index 2a10cc8d63..095ad134ec 100644 --- a/cocos/2d/CCFontAtlasFactory.h +++ b/cocos/2d/CCFontAtlasFactory.h @@ -39,6 +39,10 @@ public: static FontAtlas * createAtlasFromTTF(const std::string& fntFilePath, int fontSize, GlyphCollection glyphs, const char *customGlyphs = 0, bool useDistanceField = false); static FontAtlas * createAtlasFromFNT(const std::string& fntFilePath); + + static FontAtlas * createAtlasFromCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); + static FontAtlas * createAtlasFromCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); + static FontAtlas * createAtlasFromCharMap(const std::string& plistFile); private: }; diff --git a/cocos/2d/CCFontCharMap.cpp b/cocos/2d/CCFontCharMap.cpp new file mode 100644 index 0000000000..217312762b --- /dev/null +++ b/cocos/2d/CCFontCharMap.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** + Copyright (c) 2013 Zynga Inc. + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + 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. + ****************************************************************************/ + +#include "CCFontCharMap.h" +#include "CCFontAtlas.h" + +NS_CC_BEGIN + +FontCharMap * FontCharMap::create(const std::string& plistFile) +{ + std::string pathStr = FileUtils::getInstance()->fullPathForFilename(plistFile); + std::string relPathStr = pathStr.substr(0, pathStr.find_last_of("/"))+"/"; + + ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(pathStr.c_str()); + + CCASSERT(dict["version"].asInt() == 1, "Unsupported version. Upgrade cocos2d version"); + + std::string textureFilename = relPathStr + dict["textureFilename"].asString(); + + unsigned int width = dict["itemWidth"].asInt() / CC_CONTENT_SCALE_FACTOR(); + unsigned int height = dict["itemHeight"].asInt() / CC_CONTENT_SCALE_FACTOR(); + unsigned int startChar = dict["firstChar"].asInt(); + + Texture2D *tempTexture = Director::getInstance()->getTextureCache()->addImage(textureFilename); + if (!tempTexture) + { + return nullptr; + } + + FontCharMap *tempFont = new FontCharMap(tempTexture,width,height,startChar); + + if (!tempFont) + { + return nullptr; + } + tempFont->autorelease(); + return tempFont; +} + +FontCharMap* FontCharMap::create(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) +{ + Texture2D *tempTexture = Director::getInstance()->getTextureCache()->addImage(charMapFile); + + if (!tempTexture) + { + return nullptr; + } + + FontCharMap *tempFont = new FontCharMap(tempTexture,itemWidth,itemHeight,startCharMap); + + if (!tempFont) + { + return nullptr; + } + tempFont->autorelease(); + return tempFont; +} + +FontCharMap* FontCharMap::create(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) +{ + FontCharMap *tempFont = new FontCharMap(texture,itemWidth,itemHeight,startCharMap); + + if (!tempFont) + { + return nullptr; + } + tempFont->autorelease(); + return tempFont; +} + +FontCharMap::~FontCharMap() +{ + +} + +Size * FontCharMap::getAdvancesForTextUTF16(unsigned short *text, int &outNumLetters) const +{ + if (!text) + return 0; + + outNumLetters = cc_wcslen(text); + + if (!outNumLetters) + return 0; + + Size *sizes = new Size[outNumLetters]; + if (!sizes) + return 0; + + int advance = _itemWidth * CC_CONTENT_SCALE_FACTOR(); + for (int c = 0; c < outNumLetters; ++c) + { + sizes[c].width = advance; + } + + return sizes; +} + +Rect FontCharMap::getRectForChar(unsigned short theChar) const +{ + return _charRect; +} + +FontAtlas * FontCharMap::createFontAtlas() +{ + FontAtlas *tempAtlas = new FontAtlas(*this); + if (!tempAtlas) + return nullptr; + + Size s = _texture->getContentSize(); + + int itemsPerColumn = (int)(s.height / _itemHeight); + int itemsPerRow = (int)(s.width / _itemWidth); + + tempAtlas->setCommonLineHeight(_itemHeight); + + FontLetterDefinition tempDefinition; + tempDefinition.textureID = 0; + tempDefinition.anchorX = 0.5f; + tempDefinition.anchorY = 0.5f; + tempDefinition.offsetX = 0.0f; + tempDefinition.offsetY = 0.0f; + tempDefinition.validDefinition = true; + tempDefinition.width = _itemWidth; + tempDefinition.height = _itemHeight; + + int charId = _mapStartChar; + float itemWidthInPixels = _itemWidth * CC_CONTENT_SCALE_FACTOR(); + float itemHeightInPixels = _itemHeight * CC_CONTENT_SCALE_FACTOR(); + for (int row = 0; row < itemsPerColumn; ++row) + { + for (int col = 0; col < itemsPerRow; ++col) + { + tempDefinition.letteCharUTF16 = charId; + + tempDefinition.U = _itemWidth * col; + tempDefinition.V = _itemHeight * row; + + tempAtlas->addLetterDefinition(tempDefinition); + charId++; + } + } + + tempAtlas->addTexture(*_texture,0); + + return tempAtlas; +} + +NS_CC_END \ No newline at end of file diff --git a/cocos/2d/CCFontCharMap.h b/cocos/2d/CCFontCharMap.h new file mode 100644 index 0000000000..f77c855c08 --- /dev/null +++ b/cocos/2d/CCFontCharMap.h @@ -0,0 +1,69 @@ +/**************************************************************************** + Copyright (c) 2013 Zynga Inc. + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + 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. + ****************************************************************************/ + +#ifndef _CCFontCharMap_h_ +#define _CCFontCharMap_h_ + +#include "cocos2d.h" +#include "CCFont.h" + +NS_CC_BEGIN + +class FontCharMap : public Font +{ + +public: + + static FontCharMap * create(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); + static FontCharMap * create(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); + static FontCharMap * create(const std::string& plistFile); + + virtual Size* getAdvancesForTextUTF16(unsigned short *text, int &outNumLetters) const override; + virtual Rect getRectForChar(unsigned short theChar) const override; + virtual FontAtlas *createFontAtlas() override; + +protected: + + FontCharMap(Texture2D* texture,int itemWidth, int itemHeight, int startCharMap) : + _texture(texture),_itemWidth(itemWidth),_itemHeight(itemHeight),_mapStartChar(startCharMap),_charRect(0,0,itemWidth,itemHeight){} + /** + * @js NA + * @lua NA + */ + virtual ~FontCharMap(); + +private: + + Texture2D* _texture; + int _mapStartChar; + int _itemWidth; + int _itemHeight; + + Rect _charRect; +}; + +NS_CC_END + +#endif /* defined(_CCFontCharMap_h_) */ diff --git a/cocos/2d/CCLabel.cpp b/cocos/2d/CCLabel.cpp index a267a41938..1bd74756e8 100644 --- a/cocos/2d/CCLabel.cpp +++ b/cocos/2d/CCLabel.cpp @@ -92,6 +92,93 @@ Label* Label::createWithBMFont(const std::string& bmfontFilePath, const std::str } } +Label* Label::createWithCharMap(const std::string& plistFile) +{ + Label *ret = new Label(); + + if (!ret) + return nullptr; + + if (ret->setCharMap(plistFile)) + { + ret->autorelease(); + return ret; + } + else + { + delete ret; + return nullptr; + } +} + +Label* Label::createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) +{ + Label *ret = new Label(); + + if (!ret) + return nullptr; + + if (ret->setCharMap(texture,itemWidth,itemHeight,startCharMap)) + { + ret->autorelease(); + return ret; + } + else + { + delete ret; + return nullptr; + } +} + +Label* Label::createWithCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) +{ + Label *ret = new Label(); + + if (!ret) + return nullptr; + + if (ret->setCharMap(charMapFile,itemWidth,itemHeight,startCharMap)) + { + ret->autorelease(); + return ret; + } + else + { + delete ret; + return nullptr; + } +} + +bool Label::setCharMap(const std::string& plistFile) +{ + FontAtlas *newAtlas = FontAtlasCache::getFontAtlasCharMap(plistFile); + + if (!newAtlas) + return false; + + return initWithFontAtlas(newAtlas); +} + +bool Label::setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) +{ + FontAtlas *newAtlas = FontAtlasCache::getFontAtlasCharMap(texture,itemWidth,itemHeight,startCharMap); + + if (!newAtlas) + return false; + + return initWithFontAtlas(newAtlas); +} + +bool Label::setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap) +{ + FontAtlas *newAtlas = FontAtlasCache::getFontAtlasCharMap(charMapFile,itemWidth,itemHeight,startCharMap); + + if (!newAtlas) + return false; + + return initWithFontAtlas(newAtlas); +} + Label::Label(FontAtlas *atlas, TextHAlignment alignment, bool useDistanceField,bool useA8Shader) : _reusedLetter(nullptr) , _commonLineHeight(0.0f) diff --git a/cocos/2d/CCLabel.h b/cocos/2d/CCLabel.h index 26dcc89f9a..1e312d422d 100644 --- a/cocos/2d/CCLabel.h +++ b/cocos/2d/CCLabel.h @@ -62,12 +62,12 @@ typedef struct _ttfConfig const char *customGlyphs; bool distanceFieldEnabled; - _ttfConfig(const char* filePath,int fontSize = 36, const GlyphCollection& glyphs = GlyphCollection::NEHE, - const char *customGlyphs = nullptr,bool useDistanceField = false) + _ttfConfig(const char* filePath,int size = 36, const GlyphCollection& glyphCollection = GlyphCollection::NEHE, + const char *customGlyphCollection = nullptr,bool useDistanceField = false) :fontFilePath(filePath) - ,fontSize(fontSize) - ,glyphs(glyphs) - ,customGlyphs(customGlyphs) + ,fontSize(size) + ,glyphs(glyphCollection) + ,customGlyphs(customGlyphCollection) ,distanceFieldEnabled(useDistanceField) {} }TTFConfig; @@ -82,10 +82,18 @@ public: static Label* createWithBMFont(const std::string& bmfontFilePath, const std::string& text,const TextHAlignment& alignment = TextHAlignment::CENTER, int lineWidth = 0); + static Label * createWithCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); + static Label * createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); + static Label * createWithCharMap(const std::string& plistFile); + bool setTTFConfig(const TTFConfig& ttfConfig); bool setBMFontFilePath(const std::string& bmfontFilePath); + bool setCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); + bool setCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); + bool setCharMap(const std::string& plistFile); + bool setString(const std::string& text, const TextHAlignment& alignment = TextHAlignment::CENTER, float lineWidth = -1, bool lineBreakWithoutSpaces = false); //only support for TTF diff --git a/cocos/2d/cocos2d.vcxproj b/cocos/2d/cocos2d.vcxproj index 95f7f385fd..9c7bd8f40f 100644 --- a/cocos/2d/cocos2d.vcxproj +++ b/cocos/2d/cocos2d.vcxproj @@ -248,6 +248,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou + @@ -429,6 +430,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\win32-specific\gles\prebuilt\*.*" "$(Ou + diff --git a/cocos/2d/cocos2d.vcxproj.filters b/cocos/2d/cocos2d.vcxproj.filters index 6c887936b6..6a28597e2d 100644 --- a/cocos/2d/cocos2d.vcxproj.filters +++ b/cocos/2d/cocos2d.vcxproj.filters @@ -601,6 +601,9 @@ renderer + + label_nodes + @@ -1213,5 +1216,8 @@ renderer + + label_nodes + \ No newline at end of file diff --git a/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.cpp b/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.cpp index c28585dfbe..604ff0cb8b 100644 --- a/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.cpp +++ b/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.cpp @@ -67,6 +67,7 @@ static std::function createFunctions[] = CL(LabelBMFontTestNew), CL(LabelTTFDistanceField), CL(LabelTTFDistanceFieldEffect), + CL(LabelCharMapTest), CL(LabelCrashTest) }; @@ -1244,6 +1245,52 @@ std::string LabelTTFDistanceFieldEffect::subtitle() const return "Testing effect base on DistanceField"; } +LabelCharMapTest::LabelCharMapTest() +{ + _time = 0.0f; + + auto label1 = Label::createWithCharMap("fonts/tuffy_bold_italic-charmap.plist"); + addChild(label1, 0, kTagSprite1); + label1->setPosition( Point(10,100) ); + label1->setOpacity( 200 ); + + auto label2 = Label::createWithCharMap("fonts/tuffy_bold_italic-charmap.plist"); + addChild(label2, 0, kTagSprite2); + label2->setPosition( Point(10,160) ); + label2->setOpacity( 32 ); + + auto label3 = Label::createWithCharMap("fonts/tuffy_bold_italic-charmap.png", 48, 64, ' '); + label3->setString("123 Test"); + addChild(label3, 0, kTagSprite3); + label3->setPosition( Point(10,220) ); + + schedule(schedule_selector(LabelCharMapTest::step)); +} + +void LabelCharMapTest::step(float dt) +{ + _time += dt; + char string[12] = {0}; + sprintf(string, "%2.2f Test", _time); + + auto label1 = (Label*)getChildByTag(kTagSprite1); + label1->setString(string); + + auto label2 = (Label*)getChildByTag(kTagSprite2); + sprintf(string, "%d", (int)_time); + label2->setString(string); +} + +std::string LabelCharMapTest::title() const +{ + return "New Label + char map file"; +} + +std::string LabelCharMapTest::subtitle() const +{ + return "Updating label should be fast."; +} + LabelCrashTest::LabelCrashTest() { auto size = Director::getInstance()->getWinSize(); diff --git a/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.h b/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.h index b0b120b063..45d9374d4c 100644 --- a/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.h +++ b/samples/Cpp/TestCpp/Classes/LabelTest/LabelTestNew.h @@ -347,6 +347,22 @@ public: virtual std::string subtitle() const override; }; +class LabelCharMapTest : public AtlasDemoNew +{ +public: + CREATE_FUNC(LabelCharMapTest); + + LabelCharMapTest(); + + virtual std::string title() const override; + virtual std::string subtitle() const override; + + void step(float dt); + +private: + float _time; +}; + class LabelCrashTest : public AtlasDemoNew { public: From 671b008f3dd2db6c00d67e0b5a25eb18148202e9 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Thu, 16 Jan 2014 17:50:09 +0800 Subject: [PATCH 03/13] fix compiling error cause by sprintf_s. --- cocos/2d/CCFontAtlasCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/2d/CCFontAtlasCache.cpp b/cocos/2d/CCFontAtlasCache.cpp index 3850791f7d..673c15d38a 100644 --- a/cocos/2d/CCFontAtlasCache.cpp +++ b/cocos/2d/CCFontAtlasCache.cpp @@ -91,7 +91,7 @@ FontAtlas * FontAtlasCache::getFontAtlasCharMap(const std::string& plistFile) FontAtlas * FontAtlasCache::getFontAtlasCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) { char tmp[30]; - sprintf_s(tmp,"name:%u_%d_%d_%d",texture->getName(),itemWidth,itemHeight,startCharMap); + sprintf(tmp,"name:%u_%d_%d_%d",texture->getName(),itemWidth,itemHeight,startCharMap); std::string atlasName = generateFontName(tmp, 0, GlyphCollection::CUSTOM,false); FontAtlas *tempAtlas = _atlasMap[atlasName]; From 53be67c6530457dde0d6483ecded287daa75abda Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Thu, 16 Jan 2014 18:12:53 +0800 Subject: [PATCH 04/13] update project file. --- cocos/2d/Android.mk | 1 + cocos/2d/CMakeLists.txt | 1 + tools/project-creator/module/cocos_files.json.REMOVED.git-id | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos/2d/Android.mk b/cocos/2d/Android.mk index 9fca766934..2253bcd7d9 100644 --- a/cocos/2d/Android.mk +++ b/cocos/2d/Android.mk @@ -47,6 +47,7 @@ CCEventListenerTouch.cpp \ CCEventMouse.cpp \ CCEventTouch.cpp \ CCFont.cpp \ +CCFontCharMap.cpp \ CCFontAtlas.cpp \ CCFontAtlasCache.cpp \ CCFontAtlasFactory.cpp \ diff --git a/cocos/2d/CMakeLists.txt b/cocos/2d/CMakeLists.txt index 8340903c8b..886c2ebc21 100644 --- a/cocos/2d/CMakeLists.txt +++ b/cocos/2d/CMakeLists.txt @@ -71,6 +71,7 @@ set(COCOS2D_SRC CCFontDefinition.cpp CCFontFNT.cpp CCFontFreeType.cpp + CCFontCharMap.cpp CCLabel.cpp CCLabelAtlas.cpp CCLabelBMFont.cpp diff --git a/tools/project-creator/module/cocos_files.json.REMOVED.git-id b/tools/project-creator/module/cocos_files.json.REMOVED.git-id index 681e527955..0b8e553434 100644 --- a/tools/project-creator/module/cocos_files.json.REMOVED.git-id +++ b/tools/project-creator/module/cocos_files.json.REMOVED.git-id @@ -1 +1 @@ -5ae50c3f2080b46e18ba3f5aee4c5c686d54e13a \ No newline at end of file +f056b511a4fb5efc921792e46fe57597f669de83 \ No newline at end of file From f5afa09de10cd36927b166b03c722053238920e2 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Fri, 17 Jan 2014 09:46:59 +0800 Subject: [PATCH 05/13] remove unneeded empty line. --- cocos/2d/CCFontAtlasCache.h | 7 ++----- cocos/2d/CCFontCharMap.h | 8 ++------ cocos/2d/CCLabelTextFormatter.cpp | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/cocos/2d/CCFontAtlasCache.h b/cocos/2d/CCFontAtlasCache.h index f9e84ba904..31d785dc73 100644 --- a/cocos/2d/CCFontAtlasCache.h +++ b/cocos/2d/CCFontAtlasCache.h @@ -35,10 +35,8 @@ NS_CC_BEGIN class CC_DLL FontAtlasCache -{ - +{ public: - static FontAtlas * getFontAtlasTTF(const std::string& fontFileName, int size, GlyphCollection glyphs, const char *customGlyphs = 0, bool useDistanceField = false); static FontAtlas * getFontAtlasFNT(const std::string& fontFileName); @@ -48,8 +46,7 @@ public: static bool releaseFontAtlas(FontAtlas *atlas); -private: - +private: static std::string generateFontName(const std::string& fontFileName, int size, GlyphCollection theGlyphs, bool useDistanceField); static std::unordered_map _atlasMap; }; diff --git a/cocos/2d/CCFontCharMap.h b/cocos/2d/CCFontCharMap.h index f77c855c08..23caaeff22 100644 --- a/cocos/2d/CCFontCharMap.h +++ b/cocos/2d/CCFontCharMap.h @@ -32,10 +32,8 @@ NS_CC_BEGIN class FontCharMap : public Font -{ - +{ public: - static FontCharMap * create(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap); static FontCharMap * create(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); static FontCharMap * create(const std::string& plistFile); @@ -44,8 +42,7 @@ public: virtual Rect getRectForChar(unsigned short theChar) const override; virtual FontAtlas *createFontAtlas() override; -protected: - +protected: FontCharMap(Texture2D* texture,int itemWidth, int itemHeight, int startCharMap) : _texture(texture),_itemWidth(itemWidth),_itemHeight(itemHeight),_mapStartChar(startCharMap),_charRect(0,0,itemWidth,itemHeight){} /** @@ -55,7 +52,6 @@ protected: virtual ~FontCharMap(); private: - Texture2D* _texture; int _mapStartChar; int _itemWidth; diff --git a/cocos/2d/CCLabelTextFormatter.cpp b/cocos/2d/CCLabelTextFormatter.cpp index 550d017beb..69d6efaae8 100644 --- a/cocos/2d/CCLabelTextFormatter.cpp +++ b/cocos/2d/CCLabelTextFormatter.cpp @@ -353,7 +353,7 @@ bool LabelTextFormatter::createStringSprites(LabelTextFormatProtocol *theLabel) Point fontPos = Point((float)nextFontPositionX + charXOffset + charRect.size.width * 0.5f + kerningAmount, - (float)nextFontPositionY + yOffset - charRect.size.height * 0.5f); + (float)nextFontPositionY + yOffset - charRect.size.height * 0.5f); if( theLabel->recordLetterInfo(CC_POINT_PIXELS_TO_POINTS(fontPos),c,i) == false) { From 4302f3886d51cb67f1b68423fabee7f0200405ae Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 16 Jan 2014 10:19:52 +0800 Subject: [PATCH 06/13] issue #2789: Adds performance test for Vector and CCArray. --- .../project.pbxproj.REMOVED.git-id | 2 +- cocos/2d/ccCArray.cpp | 2 +- .../PerformanceContainerTest.cpp | 658 ++++++++++++++++++ .../PerformanceContainerTest.h | 96 +++ .../PerformanceTest/PerformanceTest.cpp | 2 + 5 files changed, 758 insertions(+), 2 deletions(-) create mode 100644 samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp create mode 100644 samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h diff --git a/build/cocos2d_samples.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_samples.xcodeproj/project.pbxproj.REMOVED.git-id index 2603132689..bb3a11cb54 100644 --- a/build/cocos2d_samples.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_samples.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -b6abaf935c97f8f1dc7a7179e54850928015b442 \ No newline at end of file +1fa58d8cba77ef923c83d2860d5511d28dad6c27 \ No newline at end of file diff --git a/cocos/2d/ccCArray.cpp b/cocos/2d/ccCArray.cpp index 9c43756ffd..b0827eed5c 100644 --- a/cocos/2d/ccCArray.cpp +++ b/cocos/2d/ccCArray.cpp @@ -73,7 +73,7 @@ void ccArrayEnsureExtraCapacity(ccArray *arr, ssize_t extra) { while (arr->max < arr->num + extra) { - CCLOG("cocos2d: ccCArray: resizing ccArray capacity from [%d] to [%d].", + CCLOGINFO("cocos2d: ccCArray: resizing ccArray capacity from [%d] to [%d].", static_cast(arr->max), static_cast(arr->max*2)); diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp new file mode 100644 index 0000000000..01ee5a2c7b --- /dev/null +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp @@ -0,0 +1,658 @@ +/* + * + */ +#include "PerformanceContainerTest.h" + +#include + +// Enable profiles for this file +#undef CC_PROFILER_DISPLAY_TIMERS +#define CC_PROFILER_DISPLAY_TIMERS() Profiler::getInstance()->displayTimers() +#undef CC_PROFILER_PURGE_ALL +#define CC_PROFILER_PURGE_ALL() Profiler::getInstance()->releaseAllTimers() + +#undef CC_PROFILER_START +#define CC_PROFILER_START(__name__) ProfilingBeginTimingBlock(__name__) +#undef CC_PROFILER_STOP +#define CC_PROFILER_STOP(__name__) ProfilingEndTimingBlock(__name__) +#undef CC_PROFILER_RESET +#define CC_PROFILER_RESET(__name__) ProfilingResetTimingBlock(__name__) + +#undef CC_PROFILER_START_CATEGORY +#define CC_PROFILER_START_CATEGORY(__cat__, __name__) do{ if(__cat__) ProfilingBeginTimingBlock(__name__); } while(0) +#undef CC_PROFILER_STOP_CATEGORY +#define CC_PROFILER_STOP_CATEGORY(__cat__, __name__) do{ if(__cat__) ProfilingEndTimingBlock(__name__); } while(0) +#undef CC_PROFILER_RESET_CATEGORY +#define CC_PROFILER_RESET_CATEGORY(__cat__, __name__) do{ if(__cat__) ProfilingResetTimingBlock(__name__); } while(0) + +#undef CC_PROFILER_START_INSTANCE +#define CC_PROFILER_START_INSTANCE(__id__, __name__) do{ ProfilingBeginTimingBlock( String::createWithFormat("%08X - %s", __id__, __name__)->getCString() ); } while(0) +#undef CC_PROFILER_STOP_INSTANCE +#define CC_PROFILER_STOP_INSTANCE(__id__, __name__) do{ ProfilingEndTimingBlock( String::createWithFormat("%08X - %s", __id__, __name__)->getCString() ); } while(0) +#undef CC_PROFILER_RESET_INSTANCE +#define CC_PROFILER_RESET_INSTANCE(__id__, __name__) do{ ProfilingResetTimingBlock( String::createWithFormat("%08X - %s", __id__, __name__)->getCString() ); } while(0) + +static std::function createFunctions[] = +{ + CL(TemplateVectorPerfTest), + CL(ArrayPerfTest) +}; + +#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) + +enum { + kTagInfoLayer = 1, + + kTagBase = 20000, +}; + +enum { + kMaxNodes = 15000, + kNodesIncrease = 500, +}; + +static int g_curCase = 0; + +//////////////////////////////////////////////////////// +// +// ContainerBasicLayer +// +//////////////////////////////////////////////////////// + +ContainerBasicLayer::ContainerBasicLayer(bool bControlMenuVisible, int nMaxCases, int nCurCase) +: PerformBasicLayer(bControlMenuVisible, nMaxCases, nCurCase) +{ +} + +void ContainerBasicLayer::showCurrentTest() +{ + int nodes = ((PerformanceContainerScene*)getParent())->getQuantityOfNodes(); + + auto scene = createFunctions[_curCase](); + + g_curCase = _curCase; + + if (scene) + { + scene->initWithQuantityOfNodes(nodes); + + Director::getInstance()->replaceScene(scene); + } +} + +//////////////////////////////////////////////////////// +// +// PerformanceContainerScene +// +//////////////////////////////////////////////////////// +void PerformanceContainerScene::initWithQuantityOfNodes(unsigned int nNodes) +{ + _type = 0; + //srand(time()); + auto s = Director::getInstance()->getWinSize(); + + // Title + auto label = LabelTTF::create(title().c_str(), "Arial", 40); + addChild(label, 1, TAG_TITLE); + label->setPosition(Point(s.width/2, s.height-32)); + label->setColor(Color3B(255,255,40)); + + // Subtitle + std::string strSubTitle = subtitle(); + if(strSubTitle.length()) + { + auto l = LabelTTF::create(strSubTitle.c_str(), "Thonburi", 16); + addChild(l, 1, TAG_SUBTITLE); + l->setPosition(Point(s.width/2, s.height-80)); + } + + lastRenderedCount = 0; + currentQuantityOfNodes = 0; + quantityOfNodes = nNodes; + + MenuItemFont::setFontSize(65); + auto decrease = MenuItemFont::create(" - ", [&](Object *sender) { + quantityOfNodes -= kNodesIncrease; + if( quantityOfNodes < 0 ) + quantityOfNodes = 0; + + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + CC_PROFILER_PURGE_ALL(); + srand(0); + }); + decrease->setColor(Color3B(0,200,20)); + _decrease = decrease; + + auto increase = MenuItemFont::create(" + ", [&](Object *sender) { + quantityOfNodes += kNodesIncrease; + if( quantityOfNodes > kMaxNodes ) + quantityOfNodes = kMaxNodes; + + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); + CC_PROFILER_PURGE_ALL(); + srand(0); + }); + increase->setColor(Color3B(0,200,20)); + _increase = increase; + + auto menu = Menu::create(decrease, increase, NULL); + menu->alignItemsHorizontally(); + menu->setPosition(Point(s.width/2, s.height/2+15)); + addChild(menu, 1); + + auto infoLabel = LabelTTF::create("0 nodes", "Marker Felt", 30); + infoLabel->setColor(Color3B(0,200,20)); + infoLabel->setPosition(Point(s.width/2, s.height/2-15)); + addChild(infoLabel, 1, kTagInfoLayer); + + auto menuLayer = new ContainerBasicLayer(true, MAX_LAYER, g_curCase); + addChild(menuLayer); + menuLayer->release(); + + printf("Size of Node: %lu\n", sizeof(Node)); + + int oldFontSize = MenuItemFont::getFontSize(); + MenuItemFont::setFontSize(24); + + Vector toggleItems; + + generateTestFunctions(); + + CCASSERT(!_testFunctions.empty(), "Should not be empty after generate test functions"); + + + for (const auto& f : _testFunctions) + { + toggleItems.pushBack(MenuItemFont::create(f.name)); + } + + auto toggle = MenuItemToggle::createWithCallback([this](Object* sender){ + auto toggle = static_cast(sender); + this->_type = toggle->getSelectedIndex(); + auto label = static_cast(this->getChildByTag(TAG_SUBTITLE)); + label->setString(StringUtils::format("Test '%s', See console", this->_testFunctions[this->_type].name)); + this->updateProfilerName(); + }, toggleItems); + + toggle->setAnchorPoint(Point::ANCHOR_MIDDLE_LEFT); + toggle->setPosition(VisibleRect::left()); + _toggle = toggle; + + auto start = MenuItemFont::create("start", [this](Object* sender){ + auto director = Director::getInstance(); + auto sched = director->getScheduler(); + + CC_PROFILER_PURGE_ALL(); + sched->scheduleSelector(schedule_selector(PerformanceContainerScene::dumpProfilerInfo), this, 2, false); + + this->unscheduleUpdate(); + this->scheduleUpdate(); + this->_startItem->setEnabled(false); + this->_stopItem->setEnabled(true); + this->_toggle->setEnabled(false); + this->_increase->setEnabled(false); + this->_decrease->setEnabled(false); + }); + start->setAnchorPoint(Point::ANCHOR_MIDDLE_RIGHT); + start->setPosition(VisibleRect::right() + Point(0, 40)); + _startItem = start; + + auto stop = MenuItemFont::create("stop", [this](Object* sender){ + auto director = Director::getInstance(); + auto sched = director->getScheduler(); + + sched->unscheduleSelector(schedule_selector(PerformanceContainerScene::dumpProfilerInfo), this); + + this->unscheduleUpdate(); + this->_startItem->setEnabled(true); + this->_stopItem->setEnabled(false); + this->_toggle->setEnabled(true); + this->_increase->setEnabled(true); + this->_decrease->setEnabled(true); + }); + + stop->setEnabled(false); + stop->setAnchorPoint(Point::ANCHOR_MIDDLE_RIGHT); + stop->setPosition(VisibleRect::right() + Point(0, -40)); + _stopItem = stop; + + auto menu2 = Menu::create(toggle, start, stop, NULL); + menu2->setPosition(Point::ZERO); + addChild(menu2); + + MenuItemFont::setFontSize(oldFontSize); + + updateQuantityLabel(); + updateQuantityOfNodes(); + updateProfilerName(); +} + +std::string PerformanceContainerScene::title() const +{ + return "No title"; +} + +std::string PerformanceContainerScene::subtitle() const +{ + return ""; +} + +void PerformanceContainerScene::updateQuantityLabel() +{ + if( quantityOfNodes != lastRenderedCount ) + { + auto infoLabel = static_cast( getChildByTag(kTagInfoLayer) ); + char str[20] = {0}; + sprintf(str, "%u nodes", quantityOfNodes); + infoLabel->setString(str); + + lastRenderedCount = quantityOfNodes; + } +} + +const char * PerformanceContainerScene::profilerName() +{ + return _profilerName; +} + +void PerformanceContainerScene::updateProfilerName() +{ + snprintf(_profilerName, sizeof(_profilerName)-1, "%s(%d)", testName(), quantityOfNodes); +} + +void PerformanceContainerScene::onExitTransitionDidStart() +{ + Scene::onExitTransitionDidStart(); + + auto director = Director::getInstance(); + auto sched = director->getScheduler(); + + sched->unscheduleSelector(schedule_selector(PerformanceContainerScene::dumpProfilerInfo), this); +} + +void PerformanceContainerScene::onEnterTransitionDidFinish() +{ + Scene::onEnterTransitionDidFinish(); + + auto director = Director::getInstance(); + auto sched = director->getScheduler(); + + CC_PROFILER_PURGE_ALL(); + sched->scheduleSelector(schedule_selector(PerformanceContainerScene::dumpProfilerInfo), this, 2, false); +} + +void PerformanceContainerScene::dumpProfilerInfo(float dt) +{ + CC_PROFILER_DISPLAY_TIMERS(); +} + +void PerformanceContainerScene::update(float dt) +{ + _testFunctions[_type].func(); +} + +void PerformanceContainerScene::updateQuantityOfNodes() +{ + currentQuantityOfNodes = quantityOfNodes; +} + +const char* PerformanceContainerScene::testName() +{ + return _testFunctions[_type].name; +} + +//////////////////////////////////////////////////////// +// +// TemplateVectorPerfTest +// +//////////////////////////////////////////////////////// + +void TemplateVectorPerfTest::generateTestFunctions() +{ + auto createVector = [this](){ + Vector ret; + + for( int i=0; isetTag(i); + ret.pushBack(node); + } + return ret; + }; + + TestFunction nameCBs[] = { + { "pushBack", [=](){ + Vector nodeVector; + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + { "insert", [=](){ + Vector nodeVector; + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + { "replace", [=](){ + Vector nodeVector = createVector(); + + srand(time(nullptr)); + ssize_t index = rand() % quantityOfNodes; + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + { "getIndex", [=](){ + + Vector nodeVector = createVector(); + Node* objToGet = nodeVector.at(quantityOfNodes/3); + ssize_t index = 0; + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + + log("index = %d", (int)index); + } } , + { "find", [=](){ + Vector nodeVector = createVector(); + Node* objToGet = nodeVector.at(quantityOfNodes/3); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + { "at", [=](){ + Vector nodeVector = createVector(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + { "contains", [=](){ + Vector nodeVector = createVector(); + Node* objToGet = nodeVector.at(quantityOfNodes/3); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + { "eraseObject", [=](){ + Vector nodeVector = createVector(); + Node** nodes = (Node**)malloc(sizeof(Node*) * quantityOfNodes); + + for (int i = 0; i < quantityOfNodes; ++i) + { + nodes[i] = nodeVector.at(i); + } + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + + CCASSERT(nodeVector.empty(), "nodeVector was not empty."); + + free(nodes); + } } , + { "erase", [=](){ + Vector nodeVector = createVector(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + + CCASSERT(nodeVector.empty(), "nodeVector was not empty."); + + } } , + { "clear", [=](){ + Vector nodeVector = createVector(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + + CCASSERT(nodeVector.empty(), "nodeVector was not empty."); + } } , + { "swap by index", [=](){ + Vector nodeVector = createVector(); + + int swapIndex1 = quantityOfNodes / 3; + int swapIndex2 = quantityOfNodes / 3 * 2; + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + + { "swap by object", [=](){ + Vector nodeVector = createVector(); + + Node* swapNode1 = nodeVector.at(quantityOfNodes / 3); + Node* swapNode2 = nodeVector.at(quantityOfNodes / 3 * 2); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + + { "reverse", [=](){ + Vector nodeVector = createVector(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iprofilerName()); + } } , + }; + + for (const auto& nameCB : nameCBs) + { + _testFunctions.push_back(nameCB); + } +} + + + +std::string TemplateVectorPerfTest::title() const +{ + return "Vector Perf test"; +} + +std::string TemplateVectorPerfTest::subtitle() const +{ + return "Test 'pushBack', See console"; +} + + + +//////////////////////////////////////////////////////// +// +// ArrayPerfTest +// +//////////////////////////////////////////////////////// + +std::string ArrayPerfTest::title() const +{ + return "Array Perf test"; +} + +std::string ArrayPerfTest::subtitle() const +{ + return "Test addObject, See console"; +} + +void ArrayPerfTest::generateTestFunctions() +{ + auto createArray = [this](){ + Array* ret = Array::create(); + + for( int i=0; isetTag(i); + ret->addObject(node); + } + return ret; + }; + + TestFunction nameCBs[] = { + { "addObject", [=](){ + Array* nodeVector = Array::create(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iaddObject(Node::create()); + CC_PROFILER_STOP(this->profilerName()); + } } , + { "insertObject", [=](){ + Array* nodeVector = Array::create(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iinsertObject(Node::create(), 0); + CC_PROFILER_STOP(this->profilerName()); + } } , + { "setObject", [=](){ + Array* nodeVector = createArray(); + + srand(time(nullptr)); + ssize_t index = rand() % quantityOfNodes; + + CC_PROFILER_START(this->profilerName()); + for( int i=0; isetObject(Node::create(), index); + CC_PROFILER_STOP(this->profilerName()); + } } , + { "getIndexOfObject", [=](){ + Array* nodeVector = createArray(); + Object* objToGet = nodeVector->getObjectAtIndex(quantityOfNodes/3); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; igetIndexOfObject(objToGet); + CC_PROFILER_STOP(this->profilerName()); + + } } , + { "getObjectAtIndex", [=](){ + Array* nodeVector = createArray(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; igetObjectAtIndex(quantityOfNodes/3); + CC_PROFILER_STOP(this->profilerName()); + } } , + { "containsObject", [=](){ + Array* nodeVector = createArray(); + Object* objToGet = nodeVector->getObjectAtIndex(quantityOfNodes/3); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; icontainsObject(objToGet); + CC_PROFILER_STOP(this->profilerName()); + } } , + { "removeObject", [=](){ + Array* nodeVector = createArray(); + Node** nodes = (Node**)malloc(sizeof(Node*) * quantityOfNodes); + + for (int i = 0; i < quantityOfNodes; ++i) + { + nodes[i] = static_cast(nodeVector->getObjectAtIndex(i)); + } + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iremoveObject(nodes[i]); + CC_PROFILER_STOP(this->profilerName()); + + CCASSERT(nodeVector->count() == 0, "nodeVector was not empty."); + + free(nodes); + } } , + { "removeObjectAtIndex", [=](){ + Array* nodeVector = createArray(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iremoveObjectAtIndex(0); + CC_PROFILER_STOP(this->profilerName()); + + CCASSERT(nodeVector->count() == 0, "nodeVector was not empty."); + + } } , + { "removeAllObjects", [=](){ + Array* nodeVector = createArray(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iremoveAllObjects(); + CC_PROFILER_STOP(this->profilerName()); + + CCASSERT(nodeVector->count() == 0, "nodeVector was not empty."); + } } , + { "swap by index", [=](){ + Array* nodeVector = createArray(); + + int swapIndex1 = quantityOfNodes / 3; + int swapIndex2 = quantityOfNodes / 3 * 2; + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iswap(swapIndex1, swapIndex2); + CC_PROFILER_STOP(this->profilerName()); + } } , + + { "swap by object", [=](){ + Array* nodeVector = createArray(); + + Object* swapNode1 = nodeVector->getObjectAtIndex(quantityOfNodes / 3); + Object* swapNode2 = nodeVector->getObjectAtIndex(quantityOfNodes / 3 * 2); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; iexchangeObject(swapNode1, swapNode2); + CC_PROFILER_STOP(this->profilerName()); + } } , + + { "reverseObjects", [=](){ + Array* nodeVector = createArray(); + + CC_PROFILER_START(this->profilerName()); + for( int i=0; ireverseObjects(); + CC_PROFILER_STOP(this->profilerName()); + } } , + }; + + for (const auto& nameCB : nameCBs) + { + _testFunctions.push_back(nameCB); + } +} + +///---------------------------------------- +void runContainerPerformanceTest() +{ + auto scene = createFunctions[g_curCase](); + scene->initWithQuantityOfNodes(kNodesIncrease); + + Director::getInstance()->replaceScene(scene); +} diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h new file mode 100644 index 0000000000..88c1bb3984 --- /dev/null +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h @@ -0,0 +1,96 @@ +/* + * + */ +#ifndef __PERFORMANCE_CONTAINER_TEST_H__ +#define __PERFORMANCE_CONTAINER_TEST_H__ + +#include "PerformanceTest.h" +#include "CCProfiling.h" + +class ContainerBasicLayer : public PerformBasicLayer +{ +public: + ContainerBasicLayer(bool bControlMenuVisible, int nMaxCases = 0, int nCurCase = 0); + + virtual void showCurrentTest(); +}; + +class PerformanceContainerScene : public Scene +{ +public: + + static const int TAG_TITLE = 100; + static const int TAG_SUBTITLE = 101; + + struct TestFunction + { + const char* name; + std::function func; + }; + + virtual void initWithQuantityOfNodes(unsigned int nNodes); + virtual void generateTestFunctions() = 0; + + virtual std::string title() const; + virtual std::string subtitle() const; + virtual void updateQuantityOfNodes(); + + const char* profilerName(); + void updateProfilerName(); + + // for the profiler + virtual const char* testName(); + + void updateQuantityLabel(); + + int getQuantityOfNodes() { return quantityOfNodes; } + + void dumpProfilerInfo(float dt); + + // overrides + virtual void onExitTransitionDidStart() override; + virtual void onEnterTransitionDidFinish() override; + virtual void update(float dt) override; + +protected: + char _profilerName[256]; + int lastRenderedCount; + int quantityOfNodes; + int currentQuantityOfNodes; + unsigned int _type; + std::vector _testFunctions; + + MenuItemFont* _increase; + MenuItemFont* _decrease; + MenuItemFont* _startItem; + MenuItemFont* _stopItem; + MenuItemToggle* _toggle; +}; + +class TemplateVectorPerfTest : public PerformanceContainerScene +{ +public: + CREATE_FUNC(TemplateVectorPerfTest); + + virtual void generateTestFunctions() override; + + + virtual std::string title() const override; + virtual std::string subtitle() const override; +}; + +class ArrayPerfTest : public PerformanceContainerScene +{ +public: + CREATE_FUNC(ArrayPerfTest); + + virtual void generateTestFunctions() override; + + virtual std::string title() const override; + virtual std::string subtitle() const override; +}; + + +void runContainerPerformanceTest(); + +#endif // __PERFORMANCE_CONTAINER_TEST_H__ diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceTest.cpp b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceTest.cpp index 9ef97602b6..7884aec8d3 100644 --- a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceTest.cpp @@ -8,6 +8,7 @@ #include "PerformanceAllocTest.h" #include "PerformanceLabelTest.h" #include "PerformanceRendererTest.h" +#include "PerformanceContainerTest.h" enum { @@ -28,6 +29,7 @@ struct { { "Touches Perf Test",[](Object*sender){runTouchesTest();} }, { "Label Perf Test",[](Object*sender){runLabelTest();} }, { "Renderer Perf Test",[](Object*sender){runRendererTest();} }, + { "Container Perf Test", [](Object* sender ) { runContainerPerformanceTest(); } } }; static const int g_testMax = sizeof(g_testsName)/sizeof(g_testsName[0]); From 811f55bb8daab12e487df97d85dbcd20bf9cae18 Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 16 Jan 2014 14:41:31 +0800 Subject: [PATCH 07/13] issue #2789: Avoids compiler to do optimization. --- .../PerformanceContainerTest.cpp | 48 +++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp index 01ee5a2c7b..9f61b4e4ee 100644 --- a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp @@ -363,33 +363,59 @@ void TemplateVectorPerfTest::generateTestFunctions() index = nodeVector.getIndex(objToGet); CC_PROFILER_STOP(this->profilerName()); - log("index = %d", (int)index); + // Uses `index` to avoids `getIndex` invoking was optimized in release mode + if (index == quantityOfNodes/3) + { + nodeVector.clear(); + } } } , { "find", [=](){ Vector nodeVector = createVector(); Node* objToGet = nodeVector.at(quantityOfNodes/3); + Vector::iterator iter; CC_PROFILER_START(this->profilerName()); for( int i=0; iprofilerName()); + + // Uses `iter` to avoids `find` invoking was optimized in release mode + if (*iter == objToGet) + { + nodeVector.clear(); + } + } } , { "at", [=](){ Vector nodeVector = createVector(); - + Node* objToGet = nullptr; CC_PROFILER_START(this->profilerName()); for( int i=0; iprofilerName()); + + // Uses `objToGet` to avoids `at` invoking was optimized in release mode + if (nodeVector.getIndex(objToGet) == quantityOfNodes/3) + { + nodeVector.clear(); + } } } , { "contains", [=](){ Vector nodeVector = createVector(); Node* objToGet = nodeVector.at(quantityOfNodes/3); + bool ret = false; + CC_PROFILER_START(this->profilerName()); for( int i=0; iprofilerName()); + + // Uses `ret` to avoids `contains` invoking was optimized in release mode + if (ret) + { + nodeVector.clear(); + } } } , { "eraseObject", [=](){ Vector nodeVector = createVector(); @@ -497,7 +523,7 @@ std::string ArrayPerfTest::title() const std::string ArrayPerfTest::subtitle() const { - return "Test addObject, See console"; + return "Test `addObject`, See console"; } void ArrayPerfTest::generateTestFunctions() @@ -545,12 +571,16 @@ void ArrayPerfTest::generateTestFunctions() { "getIndexOfObject", [=](){ Array* nodeVector = createArray(); Object* objToGet = nodeVector->getObjectAtIndex(quantityOfNodes/3); - + ssize_t index = 0; CC_PROFILER_START(this->profilerName()); for( int i=0; igetIndexOfObject(objToGet); + index = nodeVector->getIndexOfObject(objToGet); CC_PROFILER_STOP(this->profilerName()); - + // Uses `index` to avoids `getIndex` invoking was optimized in release mode + if (index == quantityOfNodes/3) + { + nodeVector->removeAllObjects(); + } } } , { "getObjectAtIndex", [=](){ Array* nodeVector = createArray(); From 83b459fcdb057b613216ad0ac481cb8893c0f3fa Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 16 Jan 2014 15:51:01 +0800 Subject: [PATCH 08/13] issue #2789: Adds loop test for Vector and Array. --- .../PerformanceContainerTest.cpp | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp index 9f61b4e4ee..75c8f31b44 100644 --- a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp @@ -488,6 +488,17 @@ void TemplateVectorPerfTest::generateTestFunctions() nodeVector.reverse(); CC_PROFILER_STOP(this->profilerName()); } } , + + { "c++11 Range Loop", [=](){ + Vector nodeVector = createVector(); + + CC_PROFILER_START(this->profilerName()); + for (const auto& e : nodeVector) + { + e->setTag(111); + } + CC_PROFILER_STOP(this->profilerName()); + } } , }; for (const auto& nameCB : nameCBs) @@ -670,6 +681,18 @@ void ArrayPerfTest::generateTestFunctions() nodeVector->reverseObjects(); CC_PROFILER_STOP(this->profilerName()); } } , + + { "CCARRAY_FOREACH", [=](){ + Array* nodeVector = createArray(); + Object* obj; + CC_PROFILER_START(this->profilerName()); + + CCARRAY_FOREACH(nodeVector, obj) + { + static_cast(obj)->setTag(111); + } + CC_PROFILER_STOP(this->profilerName()); + } } , }; for (const auto& nameCB : nameCBs) From b3e1319982f7389d2bd7a15700c412f398124563 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 17 Jan 2014 09:44:49 +0800 Subject: [PATCH 09/13] issue #2789: Updates Android.mk and CMakeLists.txt. --- samples/Cpp/TestCpp/Android.mk | 1 + samples/Cpp/TestCpp/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/Cpp/TestCpp/Android.mk b/samples/Cpp/TestCpp/Android.mk index 07d231cbf8..1d661d5aa1 100644 --- a/samples/Cpp/TestCpp/Android.mk +++ b/samples/Cpp/TestCpp/Android.mk @@ -122,6 +122,7 @@ Classes/PerformanceTest/PerformanceTextureTest.cpp \ Classes/PerformanceTest/PerformanceTouchesTest.cpp \ Classes/PerformanceTest/PerformanceLabelTest.cpp \ Classes/PerformanceTest/PerformanceRendererTest.cpp \ +Classes/PerformanceTest/PerformanceContainerTest.cpp \ Classes/PhysicsTest/PhysicsTest.cpp \ Classes/RenderTextureTest/RenderTextureTest.cpp \ Classes/RotateWorldTest/RotateWorldTest.cpp \ diff --git a/samples/Cpp/TestCpp/CMakeLists.txt b/samples/Cpp/TestCpp/CMakeLists.txt index 6c10336eb2..df0a738a87 100644 --- a/samples/Cpp/TestCpp/CMakeLists.txt +++ b/samples/Cpp/TestCpp/CMakeLists.txt @@ -117,6 +117,7 @@ set(SAMPLE_SRC Classes/PerformanceTest/PerformanceTouchesTest.cpp Classes/PerformanceTest/PerformanceLabelTest.cpp Classes/PerformanceTest/PerformanceRendererTest.cpp + Classes/PerformanceTest/PerformanceContainerTest.cpp Classes/PhysicsTest/PhysicsTest.cpp Classes/RenderTextureTest/RenderTextureTest.cpp Classes/RotateWorldTest/RotateWorldTest.cpp From 3af95f3e843272533a77eb120bde69cacd3ddf77 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 17 Jan 2014 10:05:26 +0800 Subject: [PATCH 10/13] issue #2789: Updates windows projects. --- samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj | 3 +++ samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj.filters | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj b/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj index 1e60324f40..056b3f6cff 100644 --- a/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj +++ b/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj @@ -186,6 +186,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\websockets\prebuilt\win32\*.*" "$ + @@ -332,6 +333,8 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\websockets\prebuilt\win32\*.*" "$ + + diff --git a/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj.filters b/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj.filters index 00e2567c95..5cfe11e6c9 100644 --- a/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj.filters +++ b/samples/Cpp/TestCpp/proj.win32/TestCpp.vcxproj.filters @@ -718,6 +718,9 @@ Classes\PerformanceTest + + Classes\PerformanceTest + @@ -1324,5 +1327,11 @@ Classes\PerformanceTest + + Classes\PerformanceTest + + + Classes\PerformanceTest + \ No newline at end of file From f48f42982539f5c686d570b2c34f227d0dc06fe6 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 17 Jan 2014 10:29:21 +0800 Subject: [PATCH 11/13] issue #2789: Removes unused empty lines and renames some variables. --- .../PerformanceTest/PerformanceContainerTest.cpp | 12 ++++++------ .../PerformanceTest/PerformanceContainerTest.h | 5 ----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp index 75c8f31b44..75efc640e5 100644 --- a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.cpp @@ -325,7 +325,7 @@ void TemplateVectorPerfTest::generateTestFunctions() return ret; }; - TestFunction nameCBs[] = { + TestFunction testFunctions[] = { { "pushBack", [=](){ Vector nodeVector; @@ -501,9 +501,9 @@ void TemplateVectorPerfTest::generateTestFunctions() } } , }; - for (const auto& nameCB : nameCBs) + for (const auto& func : testFunctions) { - _testFunctions.push_back(nameCB); + _testFunctions.push_back(func); } } @@ -551,7 +551,7 @@ void ArrayPerfTest::generateTestFunctions() return ret; }; - TestFunction nameCBs[] = { + TestFunction testFunctions[] = { { "addObject", [=](){ Array* nodeVector = Array::create(); @@ -695,9 +695,9 @@ void ArrayPerfTest::generateTestFunctions() } } , }; - for (const auto& nameCB : nameCBs) + for (const auto& func : testFunctions) { - _testFunctions.push_back(nameCB); + _testFunctions.push_back(func); } } diff --git a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h index 88c1bb3984..d99cac90ff 100644 --- a/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h +++ b/samples/Cpp/TestCpp/Classes/PerformanceTest/PerformanceContainerTest.h @@ -18,7 +18,6 @@ public: class PerformanceContainerScene : public Scene { public: - static const int TAG_TITLE = 100; static const int TAG_SUBTITLE = 101; @@ -40,11 +39,8 @@ public: // for the profiler virtual const char* testName(); - void updateQuantityLabel(); - int getQuantityOfNodes() { return quantityOfNodes; } - void dumpProfilerInfo(float dt); // overrides @@ -74,7 +70,6 @@ public: virtual void generateTestFunctions() override; - virtual std::string title() const override; virtual std::string subtitle() const override; }; From d309ae76d051076c433017c6175c44e778d397bb Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 17 Jan 2014 11:13:40 +0800 Subject: [PATCH 12/13] issue #3628: Adds missing files for iOS and Mac. --- build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id index e14906c550..b052741ae6 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -88c095bbe123ab56df3f7870692c6631f4464c8d \ No newline at end of file +e1e5a1169e92834330092c45165660c6cbd03609 \ No newline at end of file From 54d587153bbbcfc696db3f3d0a06a189a98ca570 Mon Sep 17 00:00:00 2001 From: James Chen Date: Fri, 17 Jan 2014 11:55:20 +0800 Subject: [PATCH 13/13] Update CHANGELOG [ci skip] --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index fe1e346007..c4a8ea7282 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ cocos2d-x-3.0final ?.? ? [NEW] Console: added the 'textures', 'fileutils dump' and 'config' commands [NEW] GLCache: glActiveTexture() is cached with GL::activeTexture(). All code MUST call the cached version in order to work correctly [NEW] Label: Uses a struct of TTF configuration for Label::createWithTTF to reduce parameters and make this interface more easily to use. + [NEW] Label: Integrates LabelAtlas into new Label. [NEW] Renderer: Added BatchCommand. This command is not "batchable" with other commands, but improves performance in about 10% [FIX] CocoStudio: TestColliderDetector in ArmatureTest can't work.