Touch Priority, Touches going through layers

Hi All,

Cocos2d-x 2.1.4 on OSX, building an iOS target.

I have a CCLayer and the user taps and brings up a HUD that is also a CCLayer that contains a CCMenu. The Menu items work, except if I touch the HUDLayer someplace in black space the CCLayer behind it accepts the touch.

Imaging tapping on the same place that brought up the HUD, now it is open twice and I have to click my close button twice to close them all.

So I thought this was layer~~>setPriority but this doesn’t seem to be working.
I know I should be able to set the priority I have tried setting the HUD to:
hudLayer~~>setTouchPriority(129);
hudLayer
>setTouchPriority(128);
hudLayer
>setTouchPriority(128);

But the layer behind is accepting touches if I touch someplace that isn’t a CCMenu item.

See this method http://www.cocos2d-x.org/reference/native-cpp/d9/d66/classcocos2d_1_1_c_c_layer.html#a78ea96ded4dd36c8a92d38acdbbd2d89 in CCLayer also read about CCTouchDelegate http://www.cocos2d-x.org/reference/native-cpp/d0/d38/classcocos2d_1_1_c_c_touch_delegate.html

When you return true in ccTouchBegan you “consume” touch or not if you register it in such way at method registerWithTouchDispatcher

So probably your problem is that your HUD layer don’t consume touches and those touches are passed to next CCTouchDelegate by priority.

I have a similar problem. I have some CCControlSlider and buttons on top of a CCScrollView.

I want that when I am dragging inside the CCControlSlider it shouldn’t drag the CCScrollView also.

CCControlSlider::ccTouchBegan returns true (which means it should swallow/consume the touch) but it still drags the scrollview under it (both part of same layer). I tried placing them both of different layers but it has same behavior.

How do I place my Nodes so that touch isn’t sent to next object?

Update:

I tried playing with setTouchPriority and the order in which CCScrollView and CCControlSlider are added to the layer (and also if they are separate layer, the order in which layers are added to the scene).

Regardless of the orders, the CCScrollView always gets the touch event first. How do I make CCControlSlider get the touch event before CCScrollView? Will that solve my problem?

Hi Dawid,

Can you explain a little bit about when one overrides the “touch” versus the “touches” methods? Maybe I am doing something wrong here

I see one can override, as example:

ccTouchesBegan(cocos2d::CCSet pTouches, cocos2d::CCEventpEvent)

but also there is:

ccTouchBegan(cocos2d::CCTouch pTouch, cocos2d::CCEventpEvent)

Is one due to inheriting a class from CCTargetedTouchDelegate? versus just using setTouchEnabled(true);

I think I need to rework my layers a bit and review your advice above in terms of what I am overriding for methods.

Would you create a class that inherits from CCLayer and CCTargetedTouchDelegate or would you create a plain class that has a CCLayer as a private member variable? (This is a personal opinion I am asking for)

Check this out, This should help you understand all you need.

Would you create a class that inherits from CCLayer and CCTargetedTouchDelegate or would you create a plain class that has a CCLayer as a private member variable? (This is a personal opinion I am asking for)

Of cours composition is better than inheritance but it depends sometimes it is much simper to make inheritance so if you are making GUI i suggest make inheritance because you will need all API from CCLayer.

CCLayer already inherits from CCTouchDelegate so you don’t have to inherit it again.

Hi Dawid,

OK, things are a lot better for me. I was able to get my HUDLayer responding to events and the events not passing through to layers behind it.

However, what has happened is the CCMenu I add to the HUD Layer, it shows, but I cannot click on any of the menu items. When I click the HUDLayer touchbegin and touchend events respond…

Example of the code, a snippet of the menu just in case:

 pMenuItem = cocos2d::CCMenuItemImage::create(BROCCOLI::plantMenuFileName.c_str(),
                                                             BROCCOLI::plantMenuFileName.c_str(), this,
                                                             (cocos2d::SEL_MenuHandler) &PlantingHUD::plantBroccoli);

pHUDMenuItems->addObject(pMenuItem);

pHUDMenu = cocos2d::CCMenu::createWithArray(pHUDMenuItems);

        CC_BREAK_IF(!pHUDMenu);

        bRet = true;
    } while (0);

    addChild(pHUDMenu, 2);

Any thoughts on how to make it respond again. It was working before.

This must be happening because your HudLayer has higher priority than the menu added to the hud.

What you could do is check if the touch location is inside any of the menu item’s bounding boxes and let it pass through. Something like this…

@

bool ccTouchBegan(CCTouch pTouch, CCEventpEvent){
CCPoint p = pTouch~~>getLocation;
//find out if any of the children are covering the up the point, if not let it go.
CCArray arr = getChildren;
for; i++)
{
CCNode
ptr = dynamic_cast<CCNode*>);
CCRect rect = ptr~~>boundingBox();
//return true to indicate that we have consumed it.
if(rect.containsPoint§){
return true;
}
}
return false;
}
@

Instead of all the children just loop over the children in menu.

Thanks for the idea, I will try it.

I did try to set my Menu to a higher priority than the layer but it didn’t work

 pHUDMenu->setTouchPriority(INT_MIN+1);

So you are saying instead of:

CCArray *arr = getChildren();

use the array that I build up before populating the CCMenu with

createWithArray()

pHUDMenu = cocos2d::CCMenu::createWithArray(pHUDMenuItems);