Search code examples
cocos2d-iphoneclippingccnode

Rotated Clipping Node in Cocos2d


I'm using the clipping node here: http://www.learn-cocos2d.com/2011/01/cocos2d-gem-clippingnode

ClippingNode.h

#import "cocos2d.h"
@interface ClippingNode : CCNode {
    CGRect clippingRegionInNodeCoordinates;
    CGRect clippingRegion;
}
@property (nonatomic) CGRect clippingRegion;
@end

ClippingNode.m

#import "ClippingNode.h"

@interface ClippingNode (PrivateMethods)
-(void) deviceOrientationChanged:(NSNotification*)notification;
@end

@implementation ClippingNode
-(CGRect) clippingRegion {
    return clippingRegionInNodeCoordinates;
}

-(void) setClippingRegion:(CGRect)region {

    // keep the original region coordinates in case the user wants them back unchanged
    clippingRegionInNodeCoordinates = region;
    self.position = clippingRegionInNodeCoordinates.origin;
    self.contentSize = clippingRegionInNodeCoordinates.size;

    // convert to retina coordinates if needed
    region = CC_RECT_POINTS_TO_PIXELS(region);

    // respect scaling
    clippingRegion = CGRectMake(region.origin.x * scaleX_, region.origin.y * scaleY_,
                            region.size.width * scaleX_, region.size.height * scaleY_);
}

-(void) setScale:(float)newScale {
    [super setScale:newScale];
    // re-adjust the clipping region according to the current scale factor
    [self setClippingRegion:clippingRegionInNodeCoordinates];
}

-(void) deviceOrientationChanged:(NSNotification*)notification {
    // re-adjust the clipping region according to the current orientation
    [self setClippingRegion:clippingRegionInNodeCoordinates];
}

-(void) visit {

    glEnable(GL_SCISSOR_TEST);
    CGPoint worldPosition = [self convertToWorldSpace:CGPointZero];
    const CGFloat s = [[CCDirector sharedDirector] contentScaleFactor];
    glScissor((clippingRegion.origin.x) + (worldPosition.x*s), (clippingRegion.origin.y) + (worldPosition.y*s),
          (clippingRegion.size.width), (clippingRegion.size.height));

    [super visit];

    glDisable(GL_SCISSOR_TEST);

}
@end

However, I need to clip a rotated CCNode. Any idea on how I could accomplish such a task?


Solution

  • It only needs CCRenderTexture to finish the job. Any suggestion will be greatly appreciated.

    ClippingNode.h

    #import "cocos2d.h"
    @interface ClippingNode : CCNode
    @property (nonatomic, assign) CGSize clippingSize;
    @end
    

    ClippingNode.m

    #import "ClippingNode.h"
    @interface ClippingNode()
    @property (nonatomic, strong) CCRenderTexture * renderTexture;
    @property (nonatomic, strong) CCSprite * clippedSprite;
    @end
    
    
    @implementation ClippingNode
    @synthesize renderTexture;
    @synthesize clippedSprite;
    @synthesize clippingSize;
    
    - (void) setClippingSize:(CGSize)newClippingSize {
    
        //assignment
        clippingSize = newClippingSize;
    
        //set contentSize
        self.contentSize = clippingSize;
    
        //configure renderTexture
        self.renderTexture = [CCRenderTexture renderTextureWithWidth:clippingSize.width height:clippingSize.height];
        renderTexture.contentSize = CGSizeMake(clippingSize.width, clippingSize.height);
    
        //configure the renderTexture sprite
        self.clippedSprite = [CCSprite spriteWithTexture:renderTexture.sprite.texture];
        clippedSprite.position = self.position;
        clippedSprite.rotation = rotation_;
        clippedSprite.scaleY = -1;
    }
    
    - (void)visit {
        [renderTexture beginWithClear:0 g:0 b:0 a:1];
        [super visit];
        [renderTexture end];
    
        [clippedSprite visit];
    }
    
    @end
    

    Usage:

    CCSprite * spriteImage = ...;
    spriteImage.position = ccp(0,0);
    spriteImage.anchorPoint = ccp(0.5,0.5);
    
    //configure clipping Node
    self.clippingNode = [ClippingNode node];
    clippingNode.position = ccp(size.width * 0.5f, size.height * 0.5f);
    clippingNode.anchorPoint = ccp(0.5f, 0.5f);
    clippingNode.rotation = -10.0f;
    
    //configure clipping region
    [clippingNode setClippingSize:CGSizeMult(spriteImage.boundingBox.size, 1.5f)];
    
    //add content to the clipping node
    [clippingNode addChild:spriteImage]