In my cocos2d game, I have a Settings button that launches the modal layer and is designed to lock everything under it. To do this, I use a combination of a menu state method that blocks all CCMenuItems, and I use coverlayer; both of which are below in code.
The problem is that no solution seems to work in CCScrollLayers. When I click the button (launches the modal), CCScrollLayer can still scroll, which is not what I want.
I would like to:
- Click the button disabled ALL touch and disable all items including CCScrollLayers
- Run modal (allow touch only for modal)
I tried:
- Using Touch to swallow all touches using
CCTargetedTouchDelegate
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
self.isTouchEnabled = NO on the layer starting the modal
- I tried to adapt the
MenuStatus method MenuStatus that it works for CCScrollLayers, but it does not work.
I'm not sure what I'm doing wrong. Now my code.
// My main layer which launches the Settings Modal Layer #pragma mark - Lock/Unlock layers -(void) doSettings { [self lockLayers]; SettingsModalLayer *sml = [[[SettingsModalLayer alloc] init] autorelease]; [sml showSettingsOnLayer:self closeBlock:^{[self unlockLayers];}]; } -(void) lockLayers { [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES]; [self MenuStatus:NO Node:self]; } -(void) unlockLayers { [self MenuStatus:YES Node:self]; } // Disabled/Enable layers -(void) MenuStatus:(BOOL)_enable Node:(id)_node { for (id result in ((CCNode *)_node).children) { if ([result isKindOfClass:[CCMenu class]]) { for (id result1 in ((CCMenu *)result).children) { if ([result1 isKindOfClass:[CCMenuItem class]]) { ((CCMenuItem *)result1).isEnabled = _enable; } } // next } } // next } -(void) registerWithTouchDispatcher { [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES]; } - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"Event: %@", event); for( UITouch *touch in touches ) { CGPoint location = [touch locationInView: [touch view]]; location = [[CCDirector sharedDirector] convertToGL: location]; CCLayer *gl = (CCLayer *)[self getChildByTag:4]; [gl setIsTouchEnabled:NO]; } } -(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event { } -(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { [self removeFromParentAndCleanup:YES]; } -(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { return YES; } // Settings Modal Layer -(void) showSettingsOnLayer:(CCLayer *)layer closeBlock:(void (^)())noBlock { CoverLayer *coverLayer = [[CoverLayer alloc] init]; [layer addChild:coverLayer z:1000]; [coverLayer runAction:[CCFadeTo actionWithDuration:kAnimationTime opacity:155]]; // smooth fade-in to dim with semi-transparency ... // Other stuff goes here } // CoverLayer // This is meant to stop all touches, but it doesn't really work on CCScrollLayer #define kDialogTag 1234 #import "CoverLayer.h" // class that implements a black colored layer that will cover the whole screen // and eats all touches except within the dialog box child @implementation CoverLayer - (id)init { self = [super init]; if (self) { [self initWithColor:ccc4(0,0,0,0) width:[CCDirector sharedDirector].winSize.width height:[CCDirector sharedDirector].winSize.height]; self.isTouchEnabled = YES; } return self; } - (void)dealloc { [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; [super dealloc]; } - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint touchLocation = [self convertTouchToNodeSpace: touch]; CCNode *dialogBox = [self getChildByTag: kDialogTag]; // eat all touches outside of dialog box return !CGRectContainsPoint(dialogBox.boundingBox, touchLocation); }
source share