zar*_*don 5 modal-dialog event-handling cocos2d-iphone ccmenuitem
在我的 cocos2d 游戏中,我有一个“设置”按钮,它启动一个模态层,旨在锁定其下的所有内容。为此,我使用了锁定所有 CCMenuItem 的菜单状态方法的组合,并使用了覆盖层;两者都在代码下面。
问题是这两种解决方案似乎都不适用于 CCScrollLayers。当我单击按钮(启动模态)时,CCScrollLayer 仍然可以滚动,这不是我想要的。
我想:
我试过了:
CCTargetedTouchDelegate[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
self.isTouchEnabled = NO 在启动模态的层上
MenuStatus方法以使其适用于 CCScrollLayers,但它似乎不起作用。我不确定我做错了什么。我的代码现在如下。
// 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);
}
Run Code Online (Sandbox Code Playgroud)
您只需要了解CCTouchDispatcher 的优先级如何工作即可。具有最小优先级值的层将首先接收触摸事件。现在您只需相应地调整优先级即可。
创建一个阻塞层类,并在注册 CCTouchDispatcher 时将其优先级设置为最低,并覆盖 ccTouchBegan 并在其中返回 YES。
如果您查看 CCMenu 类,您会发现默认优先级是 kCCMenuTouchPriority = -128,这就是菜单项具有更高触摸优先级的原因。