From e5952ad44018c768ff7fabdd518cf7e971481702 Mon Sep 17 00:00:00 2001 From: Wenhai Lin Date: Wed, 16 Dec 2015 11:53:59 +0800 Subject: [PATCH 1/2] Improved robustness in release mode --- cocos/2d/CCProgressTimer.cpp | 13 ++--- cocos/2d/CCSprite.cpp | 99 +++++++++++++++++++++++----------- cocos/2d/CCSpriteBatchNode.cpp | 38 ++++++++----- cocos/ui/UIScale9Sprite.cpp | 68 ++++++++++++++--------- 4 files changed, 141 insertions(+), 77 deletions(-) diff --git a/cocos/2d/CCProgressTimer.cpp b/cocos/2d/CCProgressTimer.cpp index cb6a0787f3..c31a4b706c 100644 --- a/cocos/2d/CCProgressTimer.cpp +++ b/cocos/2d/CCProgressTimer.cpp @@ -54,17 +54,14 @@ ProgressTimer::ProgressTimer() ProgressTimer* ProgressTimer::create(Sprite* sp) { ProgressTimer *progressTimer = new (std::nothrow) ProgressTimer(); - if (progressTimer->initWithSprite(sp)) + if (progressTimer && progressTimer->initWithSprite(sp)) { progressTimer->autorelease(); + return progressTimer; } - else - { - delete progressTimer; - progressTimer = nullptr; - } - - return progressTimer; + + delete progressTimer; + return nullptr; } bool ProgressTimer::initWithSprite(Sprite* sp) diff --git a/cocos/2d/CCSprite.cpp b/cocos/2d/CCSprite.cpp index e401be8d6b..8851f9996a 100644 --- a/cocos/2d/CCSprite.cpp +++ b/cocos/2d/CCSprite.cpp @@ -142,9 +142,11 @@ Sprite* Sprite::create() return nullptr; } -bool Sprite::init(void) +bool Sprite::init() { - return initWithTexture(nullptr, Rect::ZERO ); + initWithTexture(nullptr, Rect::ZERO); + + return true; } bool Sprite::initWithTexture(Texture2D *texture) @@ -152,9 +154,11 @@ bool Sprite::initWithTexture(Texture2D *texture) CCASSERT(texture != nullptr, "Invalid texture for sprite"); Rect rect = Rect::ZERO; - rect.size = texture->getContentSize(); + if (texture) { + rect.size = texture->getContentSize(); + } - return initWithTexture(texture, rect); + return initWithTexture(texture, rect, false); } bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect) @@ -173,7 +177,7 @@ bool Sprite::initWithFile(const std::string& filename) _fileName = filename; _fileType = 0; - Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename); + Texture2D *texture = _director->getTextureCache()->addImage(filename); if (texture) { Rect rect = Rect::ZERO; @@ -189,12 +193,16 @@ bool Sprite::initWithFile(const std::string& filename) bool Sprite::initWithFile(const std::string &filename, const Rect& rect) { - CCASSERT(filename.size()>0, "Invalid filename"); - + CCASSERT(!filename.empty(), "Invalid filename"); + if (filename.empty()) + { + return false; + } + _fileName = filename; _fileType = 0; - Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename); + Texture2D *texture = _director->getTextureCache()->addImage(filename); if (texture) { return initWithTexture(texture, rect); @@ -208,8 +216,12 @@ bool Sprite::initWithFile(const std::string &filename, const Rect& rect) bool Sprite::initWithSpriteFrameName(const std::string& spriteFrameName) { - CCASSERT(spriteFrameName.size() > 0, "Invalid spriteFrameName"); - + CCASSERT(!spriteFrameName.empty(), "Invalid spriteFrameName"); + if (spriteFrameName.empty()) + { + return false; + } + _fileName = spriteFrameName; _fileType = 1; @@ -220,7 +232,11 @@ bool Sprite::initWithSpriteFrameName(const std::string& spriteFrameName) bool Sprite::initWithSpriteFrame(SpriteFrame *spriteFrame) { CCASSERT(spriteFrame != nullptr, "spriteFrame can't be nullptr!"); - + if (spriteFrame == nullptr) + { + return false; + } + bool bRet = initWithTexture(spriteFrame->getTexture(), spriteFrame->getRect()); setSpriteFrame(spriteFrame); @@ -229,21 +245,23 @@ bool Sprite::initWithSpriteFrame(SpriteFrame *spriteFrame) bool Sprite::initWithPolygon(const cocos2d::PolygonInfo &info) { - Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(info.filename); - bool res = false; - if(initWithTexture(texture)) + bool ret = false; + + Texture2D *texture = _director->getTextureCache()->addImage(info.filename); + if(texture && initWithTexture(texture)) { _polyInfo = info; - setContentSize(_polyInfo.rect.size/Director::getInstance()->getContentScaleFactor()); - res = true; + setContentSize(_polyInfo.rect.size / _director->getContentScaleFactor()); + ret = true; } - return res; + + return ret; } // designated initializer bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect, bool rotated) { - bool result; + bool result = false; if (Node::init()) { _batchNode = nullptr; @@ -284,12 +302,10 @@ bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect, bool rotated) setBatchNode(nullptr); result = true; } - else - { - result = false; - } + _recursiveDirty = true; setDirty(true); + return result; } @@ -359,7 +375,7 @@ void Sprite::setTexture(Texture2D *texture) if (texture == nullptr) { // Gets the texture by key firstly. - texture = Director::getInstance()->getTextureCache()->getTextureForKey(CC_2x2_WHITE_IMAGE_KEY); + texture = _director->getTextureCache()->getTextureForKey(CC_2x2_WHITE_IMAGE_KEY); // If texture wasn't in cache, create it from RAW data. if (texture == nullptr) @@ -369,7 +385,7 @@ void Sprite::setTexture(Texture2D *texture) CC_UNUSED_PARAM(isOK); CCASSERT(isOK, "The 2x2 empty texture was created unsuccessfully."); - texture = Director::getInstance()->getTextureCache()->addImage(image, CC_2x2_WHITE_IMAGE_KEY); + texture = _director->getTextureCache()->addImage(image, CC_2x2_WHITE_IMAGE_KEY); CC_SAFE_RELEASE(image); } } @@ -451,13 +467,13 @@ void Sprite::setVertexRect(const Rect& rect) void Sprite::setTextureCoords(Rect rect) { - rect = CC_RECT_POINTS_TO_PIXELS(rect); - Texture2D *tex = _batchNode ? _textureAtlas->getTexture() : _texture; - if (! tex) + if (tex == nullptr) { return; } + + rect = CC_RECT_POINTS_TO_PIXELS(rect); float atlasWidth = (float)tex->getPixelsWide(); float atlasHeight = (float)tex->getPixelsHigh(); @@ -637,6 +653,11 @@ void Sprite::updateTransform(void) void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) { + if (_texture == nullptr) + { + return; + } + #if CC_USE_CULLING // Don't do calculate the culling if the transform was not updated auto visitingCamera = Camera::getVisitingCamera(); @@ -684,7 +705,11 @@ void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) void Sprite::addChild(Node *child, int zOrder, int tag) { CCASSERT(child != nullptr, "Argument must be non-nullptr"); - + if (child == nullptr) + { + return; + } + if (_batchNode) { Sprite* childSprite = dynamic_cast(child); @@ -705,6 +730,10 @@ void Sprite::addChild(Node *child, int zOrder, int tag) void Sprite::addChild(Node *child, int zOrder, const std::string &name) { CCASSERT(child != nullptr, "Argument must be non-nullptr"); + if (child == nullptr) + { + return; + } if (_batchNode) { @@ -1012,6 +1041,12 @@ bool Sprite::isOpacityModifyRGB(void) const void Sprite::setSpriteFrame(const std::string &spriteFrameName) { + CCASSERT(!spriteFrameName.empty(), "spriteFrameName must not be empty"); + if (spriteFrameName.empty()) + { + return; + } + SpriteFrameCache *cache = SpriteFrameCache::getInstance(); SpriteFrame *spriteFrame = cache->getSpriteFrameByName(spriteFrameName); @@ -1051,8 +1086,12 @@ void Sprite::setSpriteFrame(SpriteFrame *spriteFrame) void Sprite::setDisplayFrameWithAnimationName(const std::string& animationName, ssize_t frameIndex) { - CCASSERT(animationName.size()>0, "CCSprite#setDisplayFrameWithAnimationName. animationName must not be nullptr"); - + CCASSERT(!animationName.empty(), "CCSprite#setDisplayFrameWithAnimationName. animationName must not be nullptr"); + if (animationName.empty()) + { + return; + } + Animation *a = AnimationCache::getInstance()->getAnimation(animationName); CCASSERT(a, "CCSprite#setDisplayFrameWithAnimationName: Frame not found"); diff --git a/cocos/2d/CCSpriteBatchNode.cpp b/cocos/2d/CCSpriteBatchNode.cpp index 96a78e6d83..c2b5f0e71d 100644 --- a/cocos/2d/CCSpriteBatchNode.cpp +++ b/cocos/2d/CCSpriteBatchNode.cpp @@ -45,10 +45,14 @@ NS_CC_BEGIN SpriteBatchNode* SpriteBatchNode::createWithTexture(Texture2D* tex, ssize_t capacity/* = DEFAULT_CAPACITY*/) { SpriteBatchNode *batchNode = new (std::nothrow) SpriteBatchNode(); - batchNode->initWithTexture(tex, capacity); - batchNode->autorelease(); - - return batchNode; + if(batchNode && batchNode->initWithTexture(tex, capacity)) + { + batchNode->autorelease(); + return batchNode; + } + + delete batchNode; + return nullptr; } /* @@ -58,10 +62,14 @@ SpriteBatchNode* SpriteBatchNode::createWithTexture(Texture2D* tex, ssize_t capa SpriteBatchNode* SpriteBatchNode::create(const std::string& fileImage, ssize_t capacity/* = DEFAULT_CAPACITY*/) { SpriteBatchNode *batchNode = new (std::nothrow) SpriteBatchNode(); - batchNode->initWithFile(fileImage, capacity); - batchNode->autorelease(); - - return batchNode; + if(batchNode && batchNode->initWithFile(fileImage, capacity)) + { + batchNode->autorelease(); + return batchNode; + } + + delete batchNode; + return nullptr; } /* @@ -69,6 +77,11 @@ SpriteBatchNode* SpriteBatchNode::create(const std::string& fileImage, ssize_t c */ bool SpriteBatchNode::initWithTexture(Texture2D *tex, ssize_t capacity/* = DEFAULT_CAPACITY*/) { + if(tex == nullptr) + { + return false; + } + CCASSERT(capacity>=0, "Capacity must be >= 0"); _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; @@ -78,7 +91,7 @@ bool SpriteBatchNode::initWithTexture(Texture2D *tex, ssize_t capacity/* = DEFAU } _textureAtlas = new (std::nothrow) TextureAtlas(); - if (capacity == 0) + if (capacity <= 0) { capacity = DEFAULT_CAPACITY; } @@ -148,13 +161,12 @@ void SpriteBatchNode::visit(Renderer *renderer, const Mat4 &parentTransform, uin // IMPORTANT: // To ease the migration to v3.0, we still support the Mat4 stack, // but it is deprecated and your code should not rely on it - Director* director = Director::getInstance(); - director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); - director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform); + _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); + _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform); draw(renderer, _modelViewTransform, flags); - director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); + _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); // FIX ME: Why need to set _orderOfArrival to 0?? // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 // setOrderOfArrival(0); diff --git a/cocos/ui/UIScale9Sprite.cpp b/cocos/ui/UIScale9Sprite.cpp index 91454b8058..501bee49c6 100644 --- a/cocos/ui/UIScale9Sprite.cpp +++ b/cocos/ui/UIScale9Sprite.cpp @@ -84,17 +84,25 @@ namespace ui { bool Scale9Sprite::initWithSpriteFrame(SpriteFrame* spriteFrame, const Rect& capInsets) { - Texture2D* texture = spriteFrame->getTexture(); - CCASSERT(texture != NULL, "CCTexture must be not nil"); - Sprite *sprite = Sprite::createWithSpriteFrame(spriteFrame); - CCASSERT(sprite != NULL, "sprite must be not nil"); - bool pReturn = this->init(sprite, - spriteFrame->getRect(), - spriteFrame->isRotated(), - spriteFrame->getOffset(), - spriteFrame->getOriginalSize(), - capInsets); - return pReturn; + bool ret = false; + do { + Texture2D* texture = spriteFrame->getTexture(); + CCASSERT(texture != NULL, "CCTexture must be not nil"); + if(texture == nullptr) break; + + Sprite *sprite = Sprite::createWithSpriteFrame(spriteFrame); + CCASSERT(sprite != NULL, "sprite must be not nil"); + if(sprite == nullptr) break; + + ret = this->init(sprite, + spriteFrame->getRect(), + spriteFrame->isRotated(), + spriteFrame->getOffset(), + spriteFrame->getOriginalSize(), + capInsets); + } while (false); + + return ret; } bool Scale9Sprite::initWithSpriteFrame(SpriteFrame* spriteFrame) { @@ -105,15 +113,20 @@ namespace ui { bool Scale9Sprite::initWithSpriteFrameName(const std::string& spriteFrameName, const Rect& capInsets) { - CCASSERT((SpriteFrameCache::getInstance()) != NULL, - "SpriteFrameCache::getInstance() must be non-NULL"); - - SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName); - CCASSERT(frame != NULL, "CCSpriteFrame must be non-NULL"); - - if (NULL == frame) return false; - bool pReturn = this->initWithSpriteFrame(frame, capInsets); - return pReturn; + bool ret = false; + do { + auto spriteFrameCache = SpriteFrameCache::getInstance(); + CCASSERT(spriteFrameCache != nullptr, + "SpriteFrameCache::getInstance() must be non-NULL"); + + SpriteFrame *frame = spriteFrameCache->getSpriteFrameByName(spriteFrameName); + CCASSERT(frame != nullptr, "CCSpriteFrame must be non-NULL"); + if (frame == nullptr) return false; + + ret = initWithSpriteFrame(frame, capInsets); + } while (false); + + return ret; } bool Scale9Sprite::initWithSpriteFrameName(const std::string& spriteFrameName) { @@ -198,16 +211,19 @@ namespace ui { const Rect& rect, const Rect& capInsets) { - Sprite *sprite = nullptr; - sprite = Sprite::create(file); - bool pReturn = this->init(sprite, rect, capInsets); - return pReturn; + CCASSERT(!file.empty(), "file must not be empty string!"); + if(file.empty()) + { + return false; + } + + auto sprite = Sprite::create(file); + return init(sprite, rect, capInsets); } bool Scale9Sprite::initWithFile(const std::string& file, const Rect& rect) { - bool pReturn = this->initWithFile(file, rect, Rect::ZERO); - return pReturn; + return initWithFile(file, rect, Rect::ZERO); } Scale9Sprite* Scale9Sprite::create() From dfdc202171a64c49b507f0ceb468cf2179a8312b Mon Sep 17 00:00:00 2001 From: Wenhai Lin Date: Wed, 16 Dec 2015 15:08:48 +0800 Subject: [PATCH 2/2] refine --- cocos/ui/UIScale9Sprite.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos/ui/UIScale9Sprite.cpp b/cocos/ui/UIScale9Sprite.cpp index 501bee49c6..6b61355cb5 100644 --- a/cocos/ui/UIScale9Sprite.cpp +++ b/cocos/ui/UIScale9Sprite.cpp @@ -118,10 +118,11 @@ namespace ui { auto spriteFrameCache = SpriteFrameCache::getInstance(); CCASSERT(spriteFrameCache != nullptr, "SpriteFrameCache::getInstance() must be non-NULL"); + if(spriteFrameCache == nullptr) break; SpriteFrame *frame = spriteFrameCache->getSpriteFrameByName(spriteFrameName); CCASSERT(frame != nullptr, "CCSpriteFrame must be non-NULL"); - if (frame == nullptr) return false; + if (frame == nullptr) break; ret = initWithSpriteFrame(frame, capInsets); } while (false);