CCScrollLayer или другой способ сделать просмотр галереи вертикально прокручиваемым
Я пытаюсь создать прокручиваемую галерею в своем приложении с использованием cocos2d 2.0, что-то вроде представления коллекции в ios6, но это мой третий день, когда я пытаюсь понять, как прокручивать что-либо по вертикали. Я начал с CCScrollLayer, и я использую его как прокручиваемое меню по горизонтали. Я потратил некоторое время, пытаясь найти версию, совместимую с cocos2d 2.0, потому что оригинальный CCScrollLayer имеет некоторый устаревший метод и необъявленный идентификатор.
Все говорят, просто измените x на y, и он будет прокручиваться вертикально, но я просто не могу это сделать. Потом я начал смотреть на CCMenuAdvanced, но это слишком запутанно для меня, я не могу заставить его работать вообще. Я хотел бы просто добавить элементы CCMenuItemImage к слоям, потому что элементам меню не требуется дополнительная функция обнаружения касания, чтобы быть кодом, я могу поместить некоторый код в блоки для каждого элемента, и он уже отображает изображения.
Я также нашел измененный CCScrollLayer, в котором есть возможность прокрутки по горизонтали и вертикали, и я не могу заставить его работать, потому что он не совместим с cocos2d. Может ли кто-нибудь умнее меня внести корректные изменения в этот код? Извините, но я не могу найти исходную ссылку и не помню имя / ник автора.
//
// CCScrollLayer.h
//
// Copyright 2010 DK101
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/
//
// Copyright 2010 Giv Parvaneh.
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/
//
// Copyright 2011 Stepan Generalov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED
/*
It is a very clean and elegant subclass of CCLayer that lets you pass-in an array
of layers and it will then create a smooth scroller.
Complete with the "snapping" effect. You can create screens with anything that can be added to a CCLayer.
Additions since Giv Parvaneh version:
1. Added ability to swipe above targetedTouchDelegates.
2. Added touches lengths & screens properties.
3. Added factory class method.
4. Code cleanup.
5. Added current page number indicator (iOS Style Dots).
Limitations:
1. Mac OS X not supported. (Note #ifndef wrappers ;) )
2. Standard Touch Delegates will still receive touch events after layer starts sliding.
*/
@interface CCScrollLayer : CCLayer {
// Holds the current distance of the screen substracting offset.
CGFloat scrollDistance_;
// Holds the current page being displayed.
int currentScreen_;
// A count of the total screens available.
int totalScreens_;
// The x coord of initial point the user starts their swipe.
CGFloat startSwipe_;
// For what distance user must slide finger to start scrolling menu.
CGFloat minimumTouchLengthToSlide_;
// For what distance user must slide finger to change the page.
CGFloat minimumTouchLengthToChangePage_;
// Whenever show or not gray/white dots under scrolling content.
BOOL showPagesIndicator_;
// Internal state of scrollLayer (scrolling or idle).
int state_;
// is horizontal, else is vertical.
BOOL isHorizontal_;
}
@property(readwrite, assign) CGFloat minimumTouchLengthToSlide;
@property(readwrite, assign) CGFloat minimumTouchLengthToChangePage;
@property(readwrite, assign) BOOL showPagesIndicator;
@property(readonly) int totalScreens;
@property(readonly) int currentScreen;
@property(readonly) BOOL isHorizontal;
// Horizontal scrolling
+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset;
-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset;
// Vertical scrolling
+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset;
-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset;
@end
#endif
//
// CCScrollLayer.m
//
// Copyright 2010 DK101
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/
//
// Copyright 2010 Giv Parvaneh.
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/
//
// Copyright 2011 Stepan Generalov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED
#import "CCScrollLayer.h"
#import "CCGL.h"
enum
{
kCCScrollLayerStateIdle,
kCCScrollLayerStateSliding,
};
@interface CCTouchDispatcher (targetedHandlersGetter)
- (NSMutableArray *) targetedHandlers;
@end
@implementation CCTouchDispatcher (targetedHandlersGetter)
- (NSMutableArray *) targetedHandlers
{
return targetedHandlers;
}
@end
@implementation CCScrollLayer
@synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_;
@synthesize minimumTouchLengthToChangePage = minimumTouchLengthToChangePage_;
@synthesize totalScreens = totalScreens_;
@synthesize currentScreen = currentScreen_;
@synthesize showPagesIndicator = showPagesIndicator_;
@synthesize isHorizontal = isHorizontal_;
+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset
{
return [[[self alloc] initWithLayers: layers widthOffset:offset] autorelease];
}
-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset
{
if ( (self = [super init]) )
{
NSAssert([layers count], @"CCScrollLayer#initWithLayers:widthOffset: you must provide at least one layer!");
// Enable touches.
self.isTouchEnabled = YES;
// Set default minimum touch length to scroll.
self.minimumTouchLengthToSlide = 30.0f;
self.minimumTouchLengthToChangePage = 100.0f;
// Show indicator by default.
self.showPagesIndicator = YES;
// Set up the starting variables
currentScreen_ = 1;
// offset added to show preview of next/previous screens
scrollDistance_ = [[CCDirector sharedDirector] winSize].width - offset;
// Loop through the array and add the screens
int i = 0;
for (CCLayer *l in layers)
{
l.anchorPoint = ccp(0,0);
l.position = ccp((i*scrollDistance_),0);
[self addChild:l];
i++;
}
// Setup a count of the available screens
totalScreens_ = [layers count];
}
return self;
}
+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset
{
return [[[self alloc] initWithLayers: layers heightOffset:offset] autorelease];
}
-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset
{
if ( (self = [super init]) )
{
NSAssert([layers count], @"CCScrollLayer#initWithLayers:heightOffset: you must provide at least one layer!");
// Enable touches.
self.isTouchEnabled = YES;
// Set default minimum touch length to scroll.
self.minimumTouchLengthToSlide = 30.0f;
self.minimumTouchLengthToChangePage = 100.0f;
// Show indicator by default.
self.showPagesIndicator = YES;
// Set up the starting variables
currentScreen_ = 1;
// offset added to show preview of next/previous screens
scrollDistance_ = [[CCDirector sharedDirector] winSize].height - offset;
// Loop through the array and add the screens
int i = 0;
for (CCLayer *l in layers)
{
l.anchorPoint = ccp(0,0);
l.position = ccp(0,-(i*scrollDistance_));
[self addChild:l];
i++;
}
// Setup a count of the available screens
totalScreens_ = [layers count];
}
return self;
}
#pragma mark CCLayer Methods ReImpl
// Register with more priority than CCMenu's but don't swallow touches
-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:kCCMenuTouchPriority - 1 swallowsTouches:NO];
}
- (void) visit
{
[super visit];//< Will draw after glPopScene.
if (self.showPagesIndicator)
{
// Prepare Points Array
CGFloat n = (CGFloat)totalScreens_; //< Total points count in CGFloat.
CGFloat d = 16.0f; //< Distance between points.
CGPoint points[totalScreens_];
if (isHorizontal_ == YES) {
CGFloat pY = ceilf ( self.contentSize.height / 8.0f ); //< Points y-coord in parent coord sys.
for (int i=0; i < totalScreens_; ++i)
{
CGFloat pX = 0.5f * self.contentSize.width + d * ( (CGFloat)i - 0.5f*(n-1.0f) );
points[i] = ccp (pX, pY);
}
} else {
CGFloat pX = self.contentSize.width - ceilf ( self.contentSize.width / 8.0f ); //< Points x-coord in parent coord sys.
for (int i=0; i < totalScreens_; ++i)
{
CGFloat pY = 0.5f * self.contentSize.height - d * ( (CGFloat)i - 0.5f*(n-1.0f) );
points[i] = ccp (pX, pY);
}
}
// Set GL Values
glEnable(GL_POINT_SMOOTH);
GLboolean blendWasEnabled = glIsEnabled( GL_BLEND );
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glPointSize( 6.0 * CC_CONTENT_SCALE_FACTOR() );
// Draw Gray Points
glColor4ub(0x96,0x96,0x96,0xFF);
ccDrawPoints( points, totalScreens_ );
// Draw White Point for Selected Page
glColor4ub(0xFF,0xFF,0xFF,0xFF);
ccDrawPoint(points[currentScreen_ - 1]);
// Restore GL Values
glPointSize(1.0f);
glDisable(GL_POINT_SMOOTH);
if (! blendWasEnabled)
glDisable(GL_BLEND);
}
}
#pragma mark Pages Control
-(void) moveToPage:(int)page
{
int changeX = 0;
int changeY = 0;
if (isHorizontal_ == YES) {
changeX = -((page-1)*scrollDistance_);
} else {
changeY = ((page-1)*scrollDistance_);
}
id changePage = [CCMoveTo actionWithDuration:0.3 position:ccp(changeX,changeY)];
[self runAction:changePage];
currentScreen_ = page;
}
#pragma mark Hackish Stuff
- (void) claimTouch: (UITouch *) aTouch
{
// Enumerate through all targeted handlers.
for ( CCTargetedTouchHandler *handler in [[CCTouchDispatcher sharedDispatcher] targetedHandlers] )
{
// Only our handler should claim the touch.
if (handler.delegate == self)
{
if (![handler.claimedTouches containsObject: aTouch])
{
[handler.claimedTouches addObject: aTouch];
}
else
{
CCLOGERROR(@"CCScrollLayer#claimTouch: %@ is already claimed!", aTouch);
}
return;
}
}
}
- (void) cancelAndStoleTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
// Throw Cancel message for everybody in TouchDispatcher.
[[CCTouchDispatcher sharedDispatcher] touchesCancelled: [NSSet setWithObject: touch] withEvent:event];
//< after doing this touch is already removed from all targeted handlers
// Squirrel away the touch
[self claimTouch: touch];
}
#pragma mark Touches
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
if (isHorizontal_ == YES) {
startSwipe_ = touchPoint.x;
} else {
startSwipe_ = touchPoint.y;
}
state_ = kCCScrollLayerStateIdle;
return YES;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
int moveDistance = 0;
if (isHorizontal_ == YES) {
moveDistance = touchPoint.x-startSwipe_;
} else {
moveDistance = touchPoint.y-startSwipe_;
}
// If finger is dragged for more distance then minimum - start sliding and cancel pressed buttons.
// Of course only if we not already in sliding mode
if ( (state_ != kCCScrollLayerStateSliding)
&& (fabsf(moveDistance) >= self.minimumTouchLengthToSlide) )
{
state_ = kCCScrollLayerStateSliding;
// Avoid jerk after state change.
if (isHorizontal_ == YES) {
startSwipe_ = touchPoint.x;
} else {
startSwipe_ = touchPoint.y;
}
[self cancelAndStoleTouch: touch withEvent: event];
}
if (state_ == kCCScrollLayerStateSliding) {
int pointX = 0;
int pointY = 0;
if (isHorizontal_ == YES) {
pointX = (-(currentScreen_-1)*scrollDistance_)+(touchPoint.x-startSwipe_);
} else {
pointY = ((currentScreen_-1)*scrollDistance_)+(touchPoint.y-startSwipe_);
}
self.position = ccp(pointX,pointY);
}
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
int offsetLoc = 0;
if (isHorizontal_ == YES) {
offsetLoc = (touchPoint.x - startSwipe_);
} else {
offsetLoc = -(touchPoint.y - startSwipe_);
}
if ( offsetLoc < -self.minimumTouchLengthToChangePage && (currentScreen_+1) <= totalScreens_ )
{
[self moveToPage: currentScreen_+1];
}
else if ( offsetLoc > self.minimumTouchLengthToChangePage && (currentScreen_-1) > 0 )
{
[self moveToPage: currentScreen_-1];
}
else
{
[self moveToPage:currentScreen_];
}
}
@end
#endif
1 ответ
РЕДАКТИРОВАТЬ: мне наконец удалось заставить его работать с cocos2d 2.x. Вот код, отлично работает, как задумано, по горизонтали и вертикали, возможно, он вам понадобится.
//
// CCScrollLayer.h
//
// Copyright 2010 DK101
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/
//
// Copyright 2010 Giv Parvaneh.
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/
//
// Copyright 2011 Stepan Generalov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED
@interface CCScrollLayerVerticalHorizontal : CCLayer {
// Holds the current distance of the screen substracting offset.
CGFloat scrollDistance_;
// Holds the current page being displayed.
int currentScreen_;
// A count of the total screens available.
int totalScreens_;
// The x coord of initial point the user starts their swipe.
CGFloat startSwipe_;
// For what distance user must slide finger to start scrolling menu.
CGFloat minimumTouchLengthToSlide_;
// For what distance user must slide finger to change the page.
CGFloat minimumTouchLengthToChangePage_;
// Whenever show or not gray/white dots under scrolling content.
BOOL showPagesIndicator_;
ccColor4B pagesIndicatorSelectedColor_;
ccColor4B pagesIndicatorNormalColor_;
// Internal state of scrollLayer (scrolling or idle).
int state_;
// is horizontal, else is vertical.
BOOL isHorizontal_;
}
@property(readwrite, assign) CGFloat minimumTouchLengthToSlide;
@property(readwrite, assign) CGFloat minimumTouchLengthToChangePage;
@property(readwrite, assign) BOOL showPagesIndicator;
@property(readonly) int totalScreens;
@property(readonly) int currentScreen;
@property(readonly) BOOL isHorizontal;
// Horizontal scrolling
+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset;
-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset;
// Vertical scrolling
+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset;
-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset;
@end
#endif
//
// CCScrollLayer.m
//
// Copyright 2010 DK101
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/
//
// Copyright 2010 Giv Parvaneh.
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/
//
// Copyright 2011 Stepan Generalov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED
#import "CCScrollLayerVerticalHorizontal.h"
#import "CCGL.h"
enum
{
kCCScrollLayerStateIdle,
kCCScrollLayerStateSliding,
};
@interface CCTouchDispatcher (targetedHandlersGetter)
- (NSMutableArray *) targetedHandlers;
@end
@implementation CCTouchDispatcher (targetedHandlersGetter)
- (NSMutableArray *) targetedHandlers
{
return targetedHandlers;
}
@end
@implementation CCScrollLayerVerticalHorizontal
@synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_;
@synthesize minimumTouchLengthToChangePage = minimumTouchLengthToChangePage_;
@synthesize totalScreens = totalScreens_;
@synthesize currentScreen = currentScreen_;
@synthesize showPagesIndicator = showPagesIndicator_;
@synthesize isHorizontal = isHorizontal_;
+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset
{
return [[[self alloc] initWithLayers: layers widthOffset:offset] autorelease];
}
-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset
{
if ( (self = [super init]) )
{
NSAssert([layers count], @"CCScrollLayer#initWithLayers:widthOffset: you must provide at least one layer!");
// Horizontal
isHorizontal_ = YES;
// Enable touches.
self.isTouchEnabled = YES;
// Set default minimum touch length to scroll.
self.minimumTouchLengthToSlide = 30.0f;
self.minimumTouchLengthToChangePage = 100.0f;
// Show indicator by default.
self.showPagesIndicator = YES;
// Set up the starting variables
currentScreen_ = 1;
// offset added to show preview of next/previous screens
scrollDistance_ = [[CCDirector sharedDirector] winSize].width - offset;
// Loop through the array and add the screens
int i = 0;
for (CCLayer *l in layers)
{
l.anchorPoint = ccp(0,0);
l.position = ccp((i*scrollDistance_),0);
[self addChild:l];
i++;
}
// Setup a count of the available screens
totalScreens_ = [layers count];
}
return self;
}
+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset
{
return [[[self alloc] initWithLayers: layers heightOffset:offset] autorelease];
}
-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset
{
if ( (self = [super init]) )
{
NSAssert([layers count], @"CCScrollLayer#initWithLayers:heightOffset: you must provide at least one layer!");
// Horizontal
isHorizontal_ = NO;
// Enable touches.
self.isTouchEnabled = YES;
// Set default minimum touch length to scroll.
self.minimumTouchLengthToSlide = 30.0f;
self.minimumTouchLengthToChangePage = 100.0f;
// Show indicator by default.
self.showPagesIndicator = YES;
// Set up the starting variables
currentScreen_ = 1;
// offset added to show preview of next/previous screens
scrollDistance_ = [[CCDirector sharedDirector] winSize].height - offset;
// Loop through the array and add the screens
int i = 0;
for (CCLayer *l in layers)
{
l.anchorPoint = ccp(0,0);
l.position = ccp(0,-(i*scrollDistance_));
[self addChild:l];
i++;
}
// Setup a count of the available screens
totalScreens_ = [layers count];
}
return self;
}
#pragma mark CCLayer Methods ReImpl
// Register with more priority than CCMenu's but don't swallow touches
-(void) registerWithTouchDispatcher
{
[[[CCDirector sharedDirector]touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO];
}
- (void) visit
{
[super visit];//< Will draw after glPopScene.
if (self.showPagesIndicator)
{
// Prepare Points Array
CGFloat n = (CGFloat)totalScreens_; //< Total points count in CGFloat.
CGFloat d = 16.0f; //< Distance between points.
CGPoint points[totalScreens_];
if (isHorizontal_ == YES) {
CGFloat pY = ceilf ( self.contentSize.height / 8.0f ); //< Points y-coord in parent coord sys.
for (int i=0; i < totalScreens_; ++i)
{
CGFloat pX = 0.5f * self.contentSize.width + d * ( (CGFloat)i - 0.5f*(n-1.0f) );
points[i] = ccp (pX, pY);
}
} else {
CGFloat pX = self.contentSize.width - ceilf ( self.contentSize.width / 8.0f ); //< Points x-coord in parent coord sys.
for (int i=0; i < totalScreens_; ++i)
{
CGFloat pY = 0.5f * self.contentSize.height - d * ( (CGFloat)i - 0.5f*(n-1.0f) );
points[i] = ccp (pX, pY);
}
}
// Set GL Values
#if COCOS2D_VERSION >= 0x00020000
// ccGLEnable(CC_GL_BLEND); //Guru
ccPointSize( 6.0 * CC_CONTENT_SCALE_FACTOR() );
#define DRAW_4B_FUNC ccDrawColor4B
#else
glEnable(GL_POINT_SMOOTH);
GLboolean blendWasEnabled = glIsEnabled( GL_BLEND );
glEnable(GL_BLEND);
// save the old blending functions
int blend_src = 0;
int blend_dst = 0;
glGetIntegerv( GL_BLEND_SRC, &blend_src );
glGetIntegerv( GL_BLEND_DST, &blend_dst );
glPointSize( 6.0 * CC_CONTENT_SCALE_FACTOR() );
#define DRAW_4B_FUNC glColor4ub
#endif
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
// Draw Gray Points
DRAW_4B_FUNC(pagesIndicatorNormalColor_.r,
pagesIndicatorNormalColor_.g,
pagesIndicatorNormalColor_.b,
pagesIndicatorNormalColor_.a);
ccDrawPoints( points, totalScreens_ );
// Draw White Point for Selected Page
DRAW_4B_FUNC(pagesIndicatorSelectedColor_.r,
pagesIndicatorSelectedColor_.g,
pagesIndicatorSelectedColor_.b,
pagesIndicatorSelectedColor_.a);
ccDrawPoint(points[currentScreen_]);
// Restore GL Values
#if COCOS2D_VERSION >= 0x00020000
ccPointSize(1.0f);
#else
glPointSize(1.0f);
glDisable(GL_POINT_SMOOTH);
if (! blendWasEnabled)
glDisable(GL_BLEND);
// always restore the blending functions too
glBlendFunc( blend_src, blend_dst );
#endif
}
}
#pragma mark Pages Control
-(void) moveToPage:(int)page
{
int changeX = 0;
int changeY = 0;
if (isHorizontal_ == YES) {
changeX = -((page-1)*scrollDistance_);
} else {
changeY = ((page-1)*scrollDistance_);
}
id changePage = [CCMoveTo actionWithDuration:0.3 position:ccp(changeX,changeY)];
[self runAction:changePage];
currentScreen_ = page;
}
#pragma mark Hackish Stuff
- (void) claimTouch: (UITouch *) aTouch
{
#if COCOS2D_VERSION >= 0x00020000
CCTouchDispatcher *dispatcher = [[CCDirector sharedDirector] touchDispatcher];
#else
CCTouchDispatcher *dispatcher = [CCTouchDispatcher sharedDispatcher];
#endif
// Enumerate through all targeted handlers.
for ( CCTargetedTouchHandler *handler in [dispatcher targetedHandlers] )
{
// Only our handler should claim the touch.
if (handler.delegate == self)
{
if (![handler.claimedTouches containsObject: aTouch])
{
[handler.claimedTouches addObject: aTouch];
}
}
else
{
// Steal touch from other targeted delegates, if they claimed it.
if ([handler.claimedTouches containsObject: aTouch])
{
if ([handler.delegate respondsToSelector:@selector(ccTouchCancelled:withEvent:)])
{
[handler.delegate ccTouchCancelled: aTouch withEvent: nil];
}
[handler.claimedTouches removeObject: aTouch];
}
}
}
}
- (void) cancelAndStoleTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
// Throw Cancel message for everybody in TouchDispatcher.
[[CCDirector sharedDirector] touchesCancelled: [NSSet setWithObject: touch] withEvent:event];
//< after doing this touch is already removed from all targeted handlers
// Squirrel away the touch
[self claimTouch: touch];
}
#pragma mark Touches
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
if (isHorizontal_ == YES) {
startSwipe_ = touchPoint.x;
} else {
startSwipe_ = touchPoint.y;
}
state_ = kCCScrollLayerStateIdle;
return YES;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
int moveDistance = 0;
if (isHorizontal_ == YES) {
moveDistance = touchPoint.x-startSwipe_;
} else {
moveDistance = touchPoint.y-startSwipe_;
}
// If finger is dragged for more distance then minimum - start sliding and cancel pressed buttons.
// Of course only if we not already in sliding mode
if ( (state_ != kCCScrollLayerStateSliding)
&& (fabsf(moveDistance) >= self.minimumTouchLengthToSlide) )
{
state_ = kCCScrollLayerStateSliding;
// Avoid jerk after state change.
if (isHorizontal_ == YES) {
startSwipe_ = touchPoint.x;
} else {
startSwipe_ = touchPoint.y;
}
[self cancelAndStoleTouch: touch withEvent: event];
}
if (state_ == kCCScrollLayerStateSliding) {
int pointX = 0;
int pointY = 0;
if (isHorizontal_ == YES) {
pointX = (-(currentScreen_-1)*scrollDistance_)+(touchPoint.x-startSwipe_);
} else {
pointY = ((currentScreen_-1)*scrollDistance_)+(touchPoint.y-startSwipe_);
}
self.position = ccp(pointX,pointY);
}
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint];
int offsetLoc = 0;
if (isHorizontal_ == YES) {
offsetLoc = (touchPoint.x - startSwipe_);
} else {
offsetLoc = -(touchPoint.y - startSwipe_);
}
if ( offsetLoc < -self.minimumTouchLengthToChangePage && (currentScreen_+1) <= totalScreens_ )
{
[self moveToPage: currentScreen_+1];
}
else if ( offsetLoc > self.minimumTouchLengthToChangePage && (currentScreen_-1) > 0 )
{
[self moveToPage: currentScreen_-1];
}
else
{
[self moveToPage:currentScreen_];
}
}
@end
#endif