Skip to content

Instantly share code, notes, and snippets.

@rolandoam
Created November 4, 2010 18:42
Show Gist options
  • Save rolandoam/662931 to your computer and use it in GitHub Desktop.
Save rolandoam/662931 to your computer and use it in GitHub Desktop.
SectionalMenu.h
SectionalButton *it1 = [SectionalButton buttonWithFile:@"Images/home/classic.png" target:self];
SectionalButton *it2 = [SectionalButton buttonWithFile:@"Images/home/gad.png" target:self];
[it1 addSelector:@selector(help1) section:CGRectMake(0, 0, it1.contentSize.width, it1.contentSize.height/3)];
[it1 addSelector:@selector(play1) section:CGRectMake(0, it1.contentSize.height/3, it1.contentSize.width, 2*it1.contentSize.height/3)];
[it2 addSelector:@selector(help2) section:CGRectMake(0, 0, it2.contentSize.width, it2.contentSize.height/3)];
[it2 addSelector:@selector(play2) section:CGRectMake(0, it2.contentSize.height/3, it2.contentSize.width, 2*it2.contentSize.height/3)];
// create a section with data, and disable that section
int selIdx = [it2 addSelector:@selector(selectSomethingWithData:)
withData:someObj
section:CGRectMake(0, 70+(101*j), 71, 101)];
[it2 enableSection:selIdx enabled:NO];
it1.rotation = -20.0f; // target: 20
it2.rotation = -55.0f; // target: -15
SectionalMenu *menu = [SectionalMenu node];
[menu addChild:it1 z:0 tag:kItem1Tag];
[menu addChild:it2 z:0 tag:kItem2Tag];
[self addChild:menu z:1 tag:kMenuTag];
...
- (void)selectSomethingWithData:(id)data {
// do something with data here
}
#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface SectionalButton : CCSprite
{
id target_;
CCArray *selectors_;
CCArray *sections_;
CCArray *sectionsEnabled_;
CCArray *sectionsData_;
BOOL enabled_;
}
@property (nonatomic,readwrite,assign) BOOL enabled;
@property (nonatomic,readonly) CCArray *sections;
+ (SectionalButton *)buttonWithFile:(NSString *)file target:(id)target;
- (id)initWithFile:(NSString *)file target:(id)target;
/*
* binds a selector to a section
*/
- (int)addSelector:(SEL)selector section:(CGRect)section;
/*
* binds a selector to a section. `data` will be passed to the selector, so
* you have to make sure `selector` receives only one argument of type id.
* Also, `data` will be retained.
*/
- (int)addSelector:(SEL)selector withData:(id)data section:(CGRect)section;
- (void)enableSection:(int)section enabled:(BOOL)sectionEnabled;
- (BOOL)sectionEnabled:(int)section;
- (void)selectSection:(int)section;
@end
@interface SectionalMenu : CCLayer {
BOOL enabled_;
GLubyte opacity_;
NSInteger selectedSection_;
SectionalButton *selectedButton_;
}
@property (nonatomic,readwrite,assign) BOOL enabled;
- (SectionalButton *)itemForTouch:(UITouch *)touch section:(NSInteger *)section;
- (void)setOpacity:(GLubyte)opac;
- (GLubyte)opacity;
@end
#import "SectionalMenu.h"
@implementation SectionalButton
@synthesize enabled=enabled_, sections=sections_;
+ (SectionalButton *)buttonWithFile:(NSString *)file target:(id)target {
return [[[SectionalButton alloc] initWithFile:file target:target] autorelease];
}
- (id)initWithFile:(NSString *)file target:(id)target {
if ((self = [super initWithFile:file])) {
target_ = target;
enabled_ = YES;
selectors_ = [[CCArray arrayWithCapacity:5] retain];
sections_ = [[CCArray arrayWithCapacity:5] retain];
sectionsEnabled_ = [[CCArray arrayWithCapacity:5] retain];
sectionsData_ = [[CCArray arrayWithCapacity:5] retain];
}
return self;
}
- (int)addSelector:(SEL)selector section:(CGRect)section {
return [self addSelector:selector withData:nil section:section];
}
- (int)addSelector:(SEL)selector withData:(id)data section:(CGRect)section {
// selector and section are just structs
// we can safely append them to the array
[selectors_ addObject:[NSValue valueWithBytes:&selector objCType:@encode(SEL)]];
[sections_ addObject:[NSValue valueWithCGRect:section]];
// section enabled by default
[sectionsEnabled_ addObject:[NSNumber numberWithBool:YES]];
// add data
[sectionsData_ addObject:data];
// return the index of the section
return ([sections_ count]-1);
}
- (void)enableSection:(int)section enabled:(BOOL)sectionEnabled {
NSAssert(section >= 0 && section < [selectors_ count], @"Invalid section");
[sectionsEnabled_ removeObjectAtIndex:section];
[sectionsEnabled_ insertObject:[NSNumber numberWithBool:sectionEnabled] atIndex:section];
}
- (BOOL)sectionEnabled:(int)section {
NSAssert(section >= 0 && section < [selectors_ count], @"Invalid section");
return [[sectionsEnabled_ objectAtIndex:section] boolValue];
}
- (void)selectSection:(int)section {
if (target_) {
NSAssert(section >= 0 && section < [selectors_ count], @"Invalid section selected");
BOOL sectionEnabled = [[sectionsEnabled_ objectAtIndex:section] boolValue];
if (sectionEnabled) {
SEL selector;
id data = [sectionsData_ objectAtIndex:section];
[[selectors_ objectAtIndex:section] getValue:&selector];
if (data) {
[target_ performSelector:selector withObject:data];
} else {
[target_ performSelector:selector];
}
}
}
}
- (void)dealloc {
[selectors_ release];
[sections_ release];
[sectionsEnabled_ release];
[sectionsData_ release];
[super dealloc];
}
#if COCOS2D_DEBUG
// debug draw the sections
- (void)draw {
[super draw];
NSValue *v;
int idx = 0;
CCARRAY_FOREACH(sections_, v) {
BOOL sectionEnabled = [[sectionsEnabled_ objectAtIndex:idx] boolValue];
// violet if enabled, white if disabled
if (sectionEnabled)
glColor4ub(0xff, 0x0, 0xff, 0xff);
else
glColor4ub(0xff, 0xff, 0xff, 0xff);
CGRect r = [v CGRectValue];
CGPoint verts[] = {
ccp(r.origin.x , r.origin.y + r.size.height),
ccp(r.origin.x + r.size.width, r.origin.y + r.size.height),
ccp(r.origin.x + r.size.width, r.origin.y),
ccp(r.origin.x , r.origin.y),
};
ccDrawPoly(verts, 4, YES);
idx ++;
}
}
#endif
@end
@implementation SectionalMenu
@synthesize enabled=enabled_;
- (id)init {
if ((self = [super init])) {
self.isTouchEnabled = YES;
enabled_ = YES;
opacity_ = 1.0f;
selectedButton_ = nil;
selectedSection_ = -1;
}
return self;
}
- (void)setOpacity:(GLubyte)opac {
SectionalButton *item;
opacity_ = opac;
CCARRAY_FOREACH(children_, item) {
[item setOpacity:opac];
}
}
- (GLubyte)opacity {
return opacity_;
}
- (void)addChild:(CCMenuItem*)child z:(int)z tag:(int)aTag {
NSAssert([child isKindOfClass:[SectionalButton class]], @"SectionalMenu only supports SectionalButton objects as children");
[super addChild:child z:z tag:aTag];
}
- (void)registerWithTouchDispatcher {
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:INT_MIN+1 swallowsTouches:YES];
}
- (SectionalButton *)itemForTouch:(UITouch *)touch section:(NSInteger *)section {
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
SectionalButton* item;
CCARRAY_FOREACH(children_, item){
if ([item visible] && [item enabled]) {
CGPoint local = [item convertToNodeSpace:touchLocation];
NSValue *v;
NSInteger i=0;
// invalidate section
*section = -1;
CCARRAY_FOREACH(item.sections, v) {
CGRect r = [v CGRectValue];
if (CGRectContainsPoint(r, local) && [item sectionEnabled:i]) {
*section = i;
return item;
}
i++;
}
}
}
return nil;
}
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
if (!visible_ || !enabled_)
return NO;
selectedButton_ = [self itemForTouch:touch section:&selectedSection_];
if (selectedButton_) {
return YES;
}
return NO;
}
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
NSInteger s;
SectionalButton *b = [self itemForTouch:touch section:&s];
if (b == selectedButton_ && s == selectedSection_)
[b selectSection:s];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment