bool newIsTransition = dynamic_cast(_nextScene) != nullptr;
如果这个newIsTransition不是一个TransitionScene的话我们就调用_runningScene的onExit和onExiteTransitionDidStart2个函数,当前_runningScene退出了。
接下来_sendCleanupToScene这个变量实在PopScene和replaceScene时候被设置成ture的,所以当调用replasceScene时候会调用_runningScene->cleanup();这个cleanup是Node的方法。
下面说说cleanup方法:
for( const auto& child : _children ) child->cleanup();
他会递归的调用所有子节点的cleanup()方法。也就是当前层的所有子节点都会被cleanup一次。
cleanup开始时有个2个调用:下面2个方法都是Node成员方法
this->stopAllActions();
this->unscheduleAllCallbacks();
在调用stopAllactions时,由_actionManager->removeAllActionsFromTarget(this);
此时他会在Action中找到与当前this相关的Action,然后调用deleteHashElement方法。在deleteHashElement方法中会调用与此actionElement绑定的Node->release(),这个Node就是上面的this指针。然后free掉这个element。
到此可以说明个问题:那就是cocos2d中的Action是由自身执行这个action的Node对象自身管理的,在这个Node中有成员变量_actionManager它负责Action的管理。当切换场景的时候,由上面指出的只要这个Node在running中它就会被调用cleanup。
形如这样:auto node = Sprite::create(""); node->runAction( Action );时,node的refCount会+1,但是这个refCount在replaceScene时,会被自身的_actionManager查询到,并且会调用node->release()一次,所以动作引发的refCount++不用我们自己处理,引擎是通过刚才分析去使refCount--的。
继续说setNexScene下面做的事情:
接下来就是要处理新场景。
_runningScene = _nextScene;
_runningScene->retain();
_runningScene->onEnter();
_runningScene->onEnterTransitionDidFinish();
到此整个setNextScene解析完毕
总结:setNextScene方法中最重要的就是_sendCleanupToScene这个变量控制的cleanup了。由cleanup清理掉所有场景及场景所有子节点。重要的就是使得引擎内部维护的Node的refCount--工作。
网友评论