diff --git a/cocos2dx/menu_nodes/CCMenu.cpp b/cocos2dx/menu_nodes/CCMenu.cpp index b4c6c77cb3..9c4137eb73 100644 --- a/cocos2dx/menu_nodes/CCMenu.cpp +++ b/cocos2dx/menu_nodes/CCMenu.cpp @@ -179,14 +179,31 @@ void CCMenu::onExit() { if (m_eState == kCCMenuStateTrackingTouch) { - m_pSelectedItem->unselected(); + if (m_pSelectedItem) + { + m_pSelectedItem->unselected(); + m_pSelectedItem = NULL; + } + m_eState = kCCMenuStateWaiting; - m_pSelectedItem = NULL; } CCLayer::onExit(); } +void CCMenu::removeChild(CCNode* child, bool cleanup) +{ + CCMenuItem *pMenuItem = dynamic_cast(child); + CCAssert(pMenuItem != NULL, "Menu only supports MenuItem objects as children"); + + if (m_pSelectedItem == pMenuItem) + { + m_pSelectedItem = NULL; + } + + CCNode::removeChild(child, cleanup); +} + //Menu - Events void CCMenu::setHandlerPriority(int newPriority) diff --git a/cocos2dx/menu_nodes/CCMenu.h b/cocos2dx/menu_nodes/CCMenu.h index f74e37198a..bb9336b9b9 100644 --- a/cocos2dx/menu_nodes/CCMenu.h +++ b/cocos2dx/menu_nodes/CCMenu.h @@ -125,6 +125,7 @@ public: virtual void addChild(CCNode * child, int zOrder); virtual void addChild(CCNode * child, int zOrder, int tag); virtual void registerWithTouchDispatcher(); + virtual void removeChild(CCNode* child, bool cleanup); /** @brief For phone event handle functions diff --git a/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.cpp b/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.cpp index 3ed005aafd..c03afd4771 100644 --- a/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.cpp +++ b/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.cpp @@ -68,12 +68,15 @@ MenuLayerMainMenu::MenuLayerMainMenu() // Font Item CCMenuItemFont* item8 = CCMenuItemFont::create("Quit", this, menu_selector(MenuLayerMainMenu::onQuit)); + CCMenuItemFont* item9 = CCMenuItemFont::create("Remove menu item when moving", this, + menu_selector(MenuLayerMainMenu::menuMovingCallback)); + CCActionInterval* color_action = CCTintBy::create(0.5f, 0, -255, -255); CCActionInterval* color_back = color_action->reverse(); CCSequence* seq = CCSequence::create(color_action, color_back, NULL); item8->runAction(CCRepeatForever::create(seq)); - CCMenu* menu = CCMenu::create( item1, item2, item3, item4, item5, item6, item7, item8, NULL); + CCMenu* menu = CCMenu::create( item1, item2, item3, item4, item5, item6, item7, item8, item9, NULL); menu->alignItemsVertically(); @@ -185,6 +188,11 @@ void MenuLayerMainMenu::onQuit(CCObject* sender) //getCocosApp()->exit(); } +void MenuLayerMainMenu::menuMovingCallback(CCObject *pSender) +{ + ((CCLayerMultiplex*)m_pParent)->switchTo(6); +} + //------------------------------------------------------------------ // // MenuLayer2 @@ -571,6 +579,58 @@ void BugsTest::backMenuCallback(cocos2d::CCObject *pSender) ((CCLayerMultiplex*)m_pParent)->switchTo(0); } +RemoveMenuItemWhenMove::RemoveMenuItemWhenMove() +{ + CCSize s = CCDirector::sharedDirector()->getWinSize(); + + CCLabelTTF* label = CCLabelTTF::create("click item and move, should not crash", "Arial", 20); + label->setPosition(ccp(s.width/2, s.height - 30)); + addChild(label); + + item = CCMenuItemFont::create("item 1"); + item->retain(); + + CCMenuItemFont *back = CCMenuItemFont::create("go back", this, menu_selector(RemoveMenuItemWhenMove::goBack)); + + CCMenu *menu = CCMenu::create(item, back, NULL); + addChild(menu); + menu->alignItemsVertically(); + + menu->setPosition(ccp(s.width/2, s.height/2)); + + setTouchEnabled(true); +} + +void RemoveMenuItemWhenMove::goBack(CCObject *pSender) +{ + ((CCLayerMultiplex*)m_pParent)->switchTo(0); +} + +RemoveMenuItemWhenMove::~RemoveMenuItemWhenMove() +{ + CC_SAFE_RELEASE(item); +} + +void RemoveMenuItemWhenMove::registerWithTouchDispatcher(void) +{ + CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -129, false); +} + +bool RemoveMenuItemWhenMove::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) +{ + return true; +} + +void RemoveMenuItemWhenMove::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) +{ + if (item) + { + item->removeFromParentAndCleanup(true); + item->release(); + item = NULL; + } +} + void MenuTestScene::runThisTest() { CCLayer* pLayer1 = new MenuLayerMainMenu(); @@ -579,8 +639,9 @@ void MenuTestScene::runThisTest() CCLayer* pLayer4 = new MenuLayer4(); CCLayer* pLayer5 = new MenuLayerPriorityTest(); CCLayer* pLayer6 = new BugsTest(); + CCLayer* pLayer7 = new RemoveMenuItemWhenMove(); - CCLayerMultiplex* layer = CCLayerMultiplex::create(pLayer1, pLayer2, pLayer3, pLayer4, pLayer5, pLayer6, NULL); + CCLayerMultiplex* layer = CCLayerMultiplex::create(pLayer1, pLayer2, pLayer3, pLayer4, pLayer5, pLayer6, pLayer7, NULL); addChild(layer, 0); pLayer1->release(); @@ -589,6 +650,7 @@ void MenuTestScene::runThisTest() pLayer4->release(); pLayer5->release(); pLayer6->release(); + pLayer7->release(); CCDirector::sharedDirector()->replaceScene(this); } diff --git a/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.h b/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.h index ee39bfcf42..38833c86ca 100644 --- a/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.h +++ b/samples/Cpp/TestCpp/Classes/MenuTest/MenuTest.h @@ -28,6 +28,7 @@ public: void menuCallbackPriorityTest(CCObject* pSender); void menuCallbackBugsTest(CCObject *pSender); void onQuit(CCObject* pSender); + void menuMovingCallback(CCObject *pSender); //CREATE_NODE(MenuLayer1); }; @@ -109,6 +110,22 @@ public: void backMenuCallback(CCObject *pSender); }; +class RemoveMenuItemWhenMove : public CCLayer +{ +public: + RemoveMenuItemWhenMove(); + ~RemoveMenuItemWhenMove(); + + virtual void registerWithTouchDispatcher(void); + virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); + virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); + + void goBack(CCObject *pSender); + +private: + CCMenuItemFont *item; +}; + class MenuTestScene : public TestScene {