在cocos2d中的模态层上使用glScissor

时间:2012-08-07 10:58:31

标签: opengl cocos2d-iphone modal-dialog cclayer ccscrolllayer

我正在编码cocos2d中的模态层,我想使用OpenGL glScissor API调用来裁剪我正在使用的CCScrollLayer的内部,

基本上,

  1. 介绍某种Modal精灵
  2. 将带有资产的CCScrollLayer放在模态精灵上
  3. 我想裁剪CCScrollLayer,使其不会溢出精灵。
  4. 似乎很简单。

    我遇到的问题是visit函数似乎永远不会受到影响,因此glScissor永远不会被实现。

    我不确定我做错了什么。

    我做模态的方法是使用块来处理是和否条件/状态。

    // This appears in my "Pick City scene"
    -(id) init
    {
    
        if ((self = [super init])) 
        {
            NSLog(@"City list");
    
            for (City *cityObj in listOfCities) 
            {
                citySpriteOff = [CCSprite spriteWithSpriteFrameName:@"city.png"];
                citySpriteOn = [CCSprite spriteWithSpriteFrameName:@"city_on.png"];
    
                int x = [cityObj.x intValue];
                int y = [cityObj.y intValue];
    
                CCMenuItemSprite *mapMenuItem = [CCMenuItemSprite itemFromNormalSprite:citySpriteOff selectedSprite:citySpriteOn target:self selector:@selector(btnCity:)];
                [mapMenuItem setTag:i];
                [mapMenuItem setIsRelativeAnchorPoint:YES];
                [mapMenuItem setAnchorPoint:CGPointMake(0, 0)];
                [mapMenuItem setPosition:CGPointMake(x, y)];
                [mapMenuItem setIsEnabled:YES];
    
                [mapMenu addChild:mapMenuItem];
                i++;
            } // next
    
            [self addChild:mapMenu z:2];
        }
    }
    
    
    -(void) btnCity:(id)sender
    {
        NSLog(@"clicked a city button");
        int tag = [sender tag];
    
        City *cityObj = [listOfCities objectAtIndex:tag];
        NSLog(@"You clicked on city: %@", cityObj.name);
    
        [self lockLayers];
    
        CCLayer *layer = [CCLayer node];
        [self addChild:layer z:100];
    
        [MapModalLayer ConfirmCity:cityObj onLayer:layer yesBlock:^{[self btnConfirmedCity:cityObj];} noBlock:^{[self unlockLayers];}];
    
    }
    
    
    
    -(void) btnConfirmedCity:(City *)cityObj
    {
        NSLog(@"confirmed city: %@", cityObj.name);
    }
    
    
    
    
    #pragma mark - Lock/Unlock layers
    
    -(void) lockLayers
    {
        [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;
                    }
                }
            }
            else
                [self MenuStatus:_enable Node:result];
        } // next
    }
    

    实际的模态代码出现在这里,

    @implementation MapModalLayer
    
    - (id)init {
        self = [super init];
        if (self) {
            // This method never seems to be called
            NSLog(@"MapModalLayer init");
        }
        return self;
    }
    
    // This method never seems to be called
    - (void) visit {
        NSLog(@"Visit");
        if (!self.visible)
            return;
    
        glPushMatrix(); 
        glEnable(GL_SCISSOR_TEST);  
        glScissor(50, 50, 100 , 150);
    
        [super visit];
    
        glDisable(GL_SCISSOR_TEST);
        glPopMatrix();
    }
    
    
    + (void) CloseAlert: (CCSprite*) alertDialog onCoverLayer: (CCLayer*) coverLayer executingBlock: (void(^)())block {
        // shrink dialog box
        [alertDialog runAction:[CCScaleTo actionWithDuration:kAnimationTime scale:0]];
    
    
        // in parallel, fadeout and remove cover layer and execute block 
        // (note: you can't use CCFadeOut since we don't start at opacity 1!)
        [coverLayer runAction:[CCSequence actions:
                               [CCFadeTo actionWithDuration:0.2f opacity:0], 
                               [CCCallBlock actionWithBlock:^{
                                    [coverLayer removeFromParentAndCleanup:YES];
                                    if (block) block();
                                }],
                               nil]];
    }
    
    
    +(void) ConfirmCity:(City *)cityObj onLayer:(CCLayer *)layer yesBlock :(void (^)())yesBlock noBlock:(void (^)())noBlock
    {
    
        CCLayerColor *coverLayer = [CoverLayer new];
        [layer addChild:coverLayer z:INT_MAX]; // put to the very top to block application touches
        [coverLayer runAction:[CCFadeTo actionWithDuration:kAnimationTime opacity:80]]; // smooth fade-in to dim with semi-transparency
    
        CGSize winSize = [[CCDirector sharedDirector] winSize];
    
        CCSprite *dialog = [CCSprite spriteWithSpriteFrameName:@"modal.png"];
        [dialog setPosition:CGPointMake(winSize.width/2,winSize.height/2)];
        [dialog setTag:kDialogTag]; 
    
        //
        // We put our CCScrollLayer *scroller  content here... it doesn't matter what it is right now
        //
    
        //
        // Finally we put our accept/reject buttons
        //
    
        // Tick/Cross buttons    
        CCSprite *closeButtonOn = [CCSprite spriteWithSpriteFrameName:@"btn_close.png"];
        CCSprite *tickButtonOn  = [CCSprite spriteWithSpriteFrameName:@"btn_accept.png"];
    
    
    
        // add one or two buttons, as needed 
        CCMenuItemSprite *opt1Button = [CCMenuItemSprite itemFromNormalSprite:closeButtonOn
                                                               selectedSprite:nil
                                                                        block:^(id sender){ 
                                                                            // close alert and call opt1block when first button is pressed
                                                                            [self CloseAlert:dialog onCoverLayer: coverLayer executingBlock:noBlock];
                                                                        } ];
    
        [opt1Button setPosition:CGPointMake(-200, -120)];
    
        // create second button, if requested
        CCMenuItemSprite *opt2Button = [CCMenuItemSprite itemFromNormalSprite:tickButtonOn
                                                 selectedSprite:nil
                                                          block:^(id sender){ 
                                                              // close alert and call opt2block when second button is pressed
                                                              [self CloseAlert:dialog onCoverLayer: coverLayer executingBlock:yesBlock];
                                                          } ];
    
    
    
        [opt2Button setPosition:CGPointMake(40, -120)];
    
        CCMenu *menu = [CCMenu menuWithItems:opt1Button, opt2Button, nil];
        [menu setContentSize:dialog.contentSize];
        [dialog addChild:menu z:2];
    
    
        [coverLayer addChild:dialog];
    
    }  
    
    
    @end
    

    我认为是因为我只使用MapModalLayer的私有方法。

    但我不确定。

    有没有办法让我在如上所述的模态中使用glScissor

    我尝试将glScissor代码移动到模态的显示中,但它似乎从未做过任何事情。

    为了确认它是否有效,我将glScissor代码移到了父代,它似乎工作正常。

    因此,如何使模态层使用/使用glScissor

1 个答案:

答案 0 :(得分:1)

我已经解决了这个问题。

我使用了来自http://pastebin.com/tWsEbxvJ

的视口

我这样做的方式是:

  CoverLayer *coverLayer = [CoverLayer new];
    [layer addChild:coverLayer z:INT_MAX]; // put to the very top to block application touches
    [coverLayer runAction:[CCFadeTo actionWithDuration:kAnimationTime opacity:80]]; // smooth fade-in to dim with semi-transparency

    // ------------------------------

    CGSize winSize = [[CCDirector sharedDirector] winSize];

    CCSprite *dialog = [CCSprite spriteWithSpriteFrameName:@"modal.png"];
    [dialog setPosition:CGPointMake(winSize.width/2,winSize.height/2)];
    [dialog setTag:kDialogTag]; 

.. // Build your pagesArray here for ScrollLayer...



    // Now create the scroller and pass-in the pages (set widthOffset to 0 for fullscreen pages)
    CCScrollLayer *scroller = [[CCScrollLayer alloc] initWithLayers:pagesArray widthOffset: 350];
    [scroller setShowPagesIndicator:NO]; 

    // finally add the scroller to your scene
    //[dialog addChild:scroller];


    Viewport *cn = [[Viewport alloc] initWithRect:CGRectMake(3, 0, dialog.contentSize.width-12, dialog.contentSize.height-5)];
    [cn addChild:scroller];

    [scroller release];



    [coverLayer addChild:dialog z:1];

这允许我在一个图层上放置一个模态,放一个CCScrollLayer并确保内容不会溢出我所做的模态精灵的内部(这就是为什么宽度配置看起来有点奇怪)。 / p>

感谢。