0
votes

I want to zoom in out a CCNode by pinching and panning the screen. The node has a background which is very large but the portionof it shown on the screen. That node also contains other sprites.

What I have done by now is that first I register UIPinchGestureRecognizer

UIPinchGestureRecognizer * pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchFrom:)]; [[[CCDirector sharedDirector] view] addGestureRecognizer: pinchRecognizer];

-(void)handlePinchFrom:(UIPinchGestureRecognizer *) pinch
{
    if(pinch.state == UIGestureRecognizerStateEnded) {
        prevScale = 1;
    }
    else {
        CGFloat dscale = [self scale] - prevScale + pinch.scale;
        if(dscale > 0)
        {
            deltaScale = dscale;
        }
        CGAffineTransform transform = CGAffineTransformScale(pinch.view.transform, deltaScale, deltaScale);
        [pinch.view setTransform: transform];

//        [_contentNode setScale:deltaScale];

        prevScale = pinch.scale;
    }
}

The problem is that it scalw whole UIView not the CCNode. I have also tried to by setting the scale of my _contentNode.

**EDIT

I ave also tried this

- (void)handlePinchGesture:(UIPinchGestureRecognizer*)aPinchGestureRecognizer
{

if (pinch.state == UIGestureRecognizerStateBegan || pinch.state == UIGestureRecognizerStateChanged) {
    CGPoint midpoint = [pinch locationInView:[CCDirector sharedDirector].view];
    CGSize winSize = [CCDirector sharedDirector].viewSize;
    float x = midpoint.x/winSize.width;
    float y = midpoint.y/winSize.height;
    _contentNode.anchorPoint = CGPointMake(x, y);
    float scale = [pinch scale];
    _contentNode.scale *= scale;
    pinch.scale = 1;
}
}

But it zoom from the bottom left of the screen.

1
why don't you try setting the node position, instead of its anchorPoint? I cannot say if this will solve your issue, because it is not clear what kind of effect your are aiming at. btw, the first approach will not work to scale just the node...sergio
Thanks alot for the response. I have tried second one with position as well, but the problem is still that it scale from the bottom left not from the centre of the pinching. The node i want to scale has anchor point of is 0.5,0.5Nauman Afzaal

1 Answers

0
votes

I had the same problem. I use CCScrollView, that contains CCNode that larger than device screen. I want scroll and zoom it, but node shouldnt scroll out of screen, and scale smaller than screen. So, i create my subclass of CCScrollView, where i handle pinch. It has some strange glitches, but it works fine at all.

When pinch began i set anchor point of my node to pinch center on node space. Then i need change position of my node proportional to shift of anchor point, so moving anchor point doesn't change nodes location on view:

   - (void)handlePinch:(UIPinchGestureRecognizer*)recognizer
{
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        _previousScale = self.contentNode.scale;
    }
    else if (recognizer.state == UIGestureRecognizerStateBegan) {
        float X = [recognizer locationInNode:self.contentNode].x / self.contentNode.contentSize.width;
        float Y = [recognizer locationInNode:self.contentNode].y / self.contentNode.contentSize.height;

        float positionX = self.contentNode.position.x + self.contentNode.boundingBox.size.width * (X - self.contentNode.anchorPoint.x);
        float positionY = self.contentNode.position.y + self.contentNode.boundingBox.size.height * (Y - self.contentNode.anchorPoint.y);

        self.contentNode.anchorPoint = ccp(X, Y);
        self.contentNode.position = ccp(positionX, positionY);
    }
    else {
        CGFloat scale = _previousScale * recognizer.scale;

        if (scale >= maxScale) {
            self.contentNode.scale = maxScale;
        }
        else if (scale <= [self minScale]) {
            self.contentNode.scale = [self minScale];
        }
        else {
            self.contentNode.scale = scale;
        }
    }
}

Also i need change CCScrollView min and max scroll, so my node never scroll out of view. Default anchor point is (0,1), so i need shift min and max scroll proportional to the new anchor point.

- (float) maxScrollX
{
    if (!self.contentNode) return 0;

    float maxScroll = self.contentNode.boundingBox.size.width - self.contentSizeInPoints.width;
    if (maxScroll < 0) maxScroll = 0;

    return maxScroll - self.contentNode.boundingBox.size.width * self.contentNode.anchorPoint.x;
}

- (float) maxScrollY
{
    if (!self.contentNode) return 0;

    float maxScroll = self.contentNode.boundingBox.size.height - self.contentSizeInPoints.height;
    if (maxScroll < 0) maxScroll = 0;

    return maxScroll - self.contentNode.boundingBox.size.height * (1 - self.contentNode.anchorPoint.y);
}

- (float) minScrollX
{
    float minScroll = [super minScrollX];

    return minScroll - self.contentNode.boundingBox.size.width * self.contentNode.anchorPoint.x;
}

- (float) minScrollY
{
    float minScroll = [super minScrollY];
    return minScroll - self.contentNode.boundingBox.size.height * (1 - self.contentNode.anchorPoint.y);
}

UIGestureRecognizerStateEnded doesn't have locationInNode: method, so i added it by category. It just return touch location on node space:

#import "UIGestureRecognizer+locationInNode.h"

@implementation UIGestureRecognizer (locationInNode)

- (CGPoint) locationInNode:(CCNode*) node
{
    CCDirector* dir = [CCDirector sharedDirector];

    CGPoint touchLocation = [self locationInView: [self view]];
    touchLocation = [dir convertToGL: touchLocation];
    return [node convertToNodeSpace:touchLocation];
}

- (CGPoint) locationInWorld
{
    CCDirector* dir = [CCDirector sharedDirector];

    CGPoint touchLocation = [self locationInView: [self view]];
    return [dir convertToGL: touchLocation];
}

@end