diff --git a/cocos2dx/CCDirector.cpp b/cocos2dx/CCDirector.cpp index a4fd396b5a..376d01f084 100644 --- a/cocos2dx/CCDirector.cpp +++ b/cocos2dx/CCDirector.cpp @@ -578,33 +578,44 @@ void CCDirector::popScene(void) } void CCDirector::popToRootScene(void) +{ + popToSceneStackLevel(1); +} + +void CCDirector::popToSceneStackLevel(int level) { CCAssert(m_pRunningScene != NULL, "A running Scene is needed"); unsigned int c = m_pobScenesStack->count(); - if (c == 1) + // level 0? -> end + if (level == 0) { - m_pobScenesStack->removeLastObject(); - this->end(); - } - else - { - while (c > 1) - { - CCScene *current = (CCScene*)m_pobScenesStack->lastObject(); - if( current->isRunning() ) - { - current->onExitTransitionDidStart(); - current->onExit(); - } - current->cleanup(); - - m_pobScenesStack->removeLastObject(); - c--; - } - m_pNextScene = (CCScene*)m_pobScenesStack->lastObject(); - m_bSendCleanupToScene = false; + end(); + return; } + + // current level or lower -> nothing + if (level >= c) + return; + + // pop stack until reaching desired level + while (c > level) + { + CCScene *current = (CCScene*)m_pobScenesStack->lastObject(); + + if (current->isRunning()) + { + current->onExitTransitionDidStart(); + current->onExit(); + } + + current->cleanup(); + m_pobScenesStack->removeLastObject(); + c--; + } + + m_pNextScene = (CCScene*)m_pobScenesStack->lastObject(); + m_bSendCleanupToScene = false; } void CCDirector::end() diff --git a/cocos2dx/CCDirector.h b/cocos2dx/CCDirector.h index 8e19e33b37..fd16376414 100644 --- a/cocos2dx/CCDirector.h +++ b/cocos2dx/CCDirector.h @@ -204,7 +204,7 @@ public: // Scene Management - /**Enters the Director's main loop with the given Scene. + /** Enters the Director's main loop with the given Scene. * Call it to run only your FIRST scene. * Don't call it if there is already a running scene. * @@ -212,27 +212,33 @@ public: */ void runWithScene(CCScene *pScene); - /**Suspends the execution of the running scene, pushing it on the stack of suspended scenes. + /** Suspends the execution of the running scene, pushing it on the stack of suspended scenes. * The new scene will be executed. * Try to avoid big stacks of pushed scenes to reduce memory allocation. * ONLY call it if there is a running scene. */ void pushScene(CCScene *pScene); - /**Pops out a scene from the queue. + /** Pops out a scene from the queue. * This scene will replace the running one. * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated. * ONLY call it if there is a running scene. */ void popScene(void); - /**Pops out all scenes from the queue until the root scene in the queue. + /** Pops out all scenes from the queue until the root scene in the queue. * This scene will replace the running one. - * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated. - * ONLY call it if there is a running scene. + * Internally it will call `popToSceneStackLevel(1)` */ void popToRootScene(void); + /** Pops out all scenes from the queue until it reaches `level`. + If level is 0, it will end the director. + If level is 1, it will pop all scenes until it reaches to root scene. + If level is <= than the current stack level, it won't do anything. + */ + void popToSceneStackLevel(int level); + /** Replaces the running scene with a new one. The running scene is terminated. * ONLY call it if there is a running scene. */ diff --git a/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.cpp b/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.cpp index 6bc248cdcf..9f0b1bb3e1 100644 --- a/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.cpp +++ b/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.cpp @@ -171,13 +171,13 @@ bool SceneTestLayer3::init() { CCSize s = CCDirector::sharedDirector()->getWinSize(); - CCMenuItemFont *item0 = CCMenuItemFont::create("Touch to pushScene (self)", this, menu_selector(SceneTestLayer3::item0Clicked)); - CCMenuItemFont *item1 = CCMenuItemFont::create("Touch to popScene", this, menu_selector(SceneTestLayer3::item1Clicked)); - CCMenuItemFont *item2 = CCMenuItemFont::create("Touch to popToRootScene", this, menu_selector(SceneTestLayer3::item2Clicked)); - - - CCMenu *menu = CCMenu::create(item0, item1, item2, NULL); - this->addChild(menu); + CCMenuItemFont *item0 = CCMenuItemFont::create("Touch to pushScene (self)", this, menu_selector(SceneTestLayer3::item0Clicked)); + CCMenuItemFont *item1 = CCMenuItemFont::create("Touch to popScene", this, menu_selector(SceneTestLayer3::item1Clicked)); + CCMenuItemFont *item2 = CCMenuItemFont::create("Touch to popToRootScene", this, menu_selector(SceneTestLayer3::item2Clicked)); + CCMenuItemFont *item3 = CCMenuItemFont::create("Touch to popToSceneStackLevel(2)", this, menu_selector(SceneTestLayer3::item3Clicked)); + + CCMenu *menu = CCMenu::create(item0, item1, item2, item3, NULL); + this->addChild(menu); menu->alignItemsVertically(); this->schedule(schedule_selector(SceneTestLayer3::testDealloc)); @@ -215,6 +215,11 @@ void SceneTestLayer3::item2Clicked(CCObject* pSender) CCDirector::sharedDirector()->popToRootScene(); } +void SceneTestLayer3::item3Clicked(CCObject* pSender) +{ + CCDirector::sharedDirector()->popToSceneStackLevel(2); +} + void SceneTestScene::runThisTest() { CCLayer* pLayer = new SceneTestLayer1(); diff --git a/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.h b/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.h index d4b9bb86c0..c9c9c0bfb5 100644 --- a/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.h +++ b/samples/Cpp/TestCpp/Classes/SceneTest/SceneTest.h @@ -44,6 +44,7 @@ public: void item0Clicked(CCObject* pSender); void item1Clicked(CCObject* pSender); void item2Clicked(CCObject* pSender); + void item3Clicked(CCObject* pSender); CREATE_FUNC(SceneTestLayer3) } ;