Last active
August 29, 2015 14:05
-
-
Save sarah-j-smith/54e291e7d7c93de1ba23 to your computer and use it in GitHub Desktop.
Cocos2D CCLabelBMFont that can display two colours, by surrounding [highlighted] sections in [square brackets] for emphasis.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// TwoColorText.h | |
// SpaceBotAlpha | |
// | |
// Created by Sarah Smith on 26/08/2014. | |
// Copyright (c) 2014 Smithsoft Pty Ltd. All rights reserved. | |
// License: https://creativecommons.org/licenses/by-sa/3.0/au/ | |
// | |
// Implemented from ideas seen here: http://whitesponge.com/blog/dual-colored-labels-with-cocos2d/ | |
// but done so as to handle multiple sections of [highlighted] text [not just one]. | |
#import "CCLabelBMFont.h" | |
@interface TwoColorText : CCLabelBMFont | |
{ | |
NSString *_rawText; | |
NSString *_highlightColorHexString; | |
} | |
@property (nonatomic, strong) CCColor *highlightColor; | |
@property (nonatomic, strong) NSString *highlightColorHexString; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// TwoColorText.m | |
// SpaceBotAlpha | |
// | |
// Created by Sarah Smith on 26/08/2014. | |
// Copyright (c) 2014 Smithsoft Pty Ltd. All rights reserved. | |
// | |
#import "TwoColorText.h" | |
NSString *stripSquareBrackets(NSString *theString) | |
{ | |
NSMutableString *text = [theString mutableCopy]; | |
[text replaceOccurrencesOfString:@"[" withString:@"" options:NSCaseInsensitiveSearch | |
range:NSMakeRange(0, [text length])]; | |
[text replaceOccurrencesOfString:@"]" withString:@"" options:NSCaseInsensitiveSearch | |
range:NSMakeRange(0, [text length])]; | |
return [text copy]; | |
} | |
NSString *hexStringFromColor(CCColor *color) | |
{ | |
NSInteger r = [color red] * 255.0f; | |
NSInteger g = [color green] * 255.0f; | |
NSInteger b = [color blue] * 255.0f; | |
return [NSString stringWithFormat:@"#%02x%02x%02x", r, g, b]; | |
} | |
@implementation TwoColorText | |
{ | |
BOOL _dirty; | |
} | |
@synthesize highlightColor = _highlightColor; | |
@synthesize highlightColorHexString = _highlightColorHexString; | |
- (void)update:(CCTime)delta | |
{ | |
if (_dirty) | |
{ | |
[self updateHighlightedText]; | |
} | |
} | |
- (NSString *)description | |
{ | |
return [NSString stringWithFormat:@"%@ - %@ - %@", [super description], _rawText, [self highlightColorHexString]]; | |
} | |
-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment imageOffset:(CGPoint)offset | |
{ | |
self = [super initWithString:stripSquareBrackets(theString) fntFile:fntFile width:width alignment:alignment imageOffset:offset]; | |
if (self) | |
{ | |
_rawText = theString; | |
_cascadeColorEnabled = NO; | |
_highlightColor = [CCColor colorWithCcColor4b:ccc4(70, 117, 255, 255)]; | |
_highlightColorHexString = hexStringFromColor(_highlightColor); | |
[self updateHighlightedText]; | |
} | |
return self; | |
} | |
- (void)setColor:(CCColor *)color | |
{ | |
[super setColor:color]; | |
_dirty = YES; | |
} | |
- (void)setColorRGBA:(CCColor *)colorRGBA | |
{ | |
[super setColorRGBA:colorRGBA]; | |
_dirty = YES; | |
} | |
- (void)setHighlightColor:(CCColor *)highlightColor | |
{ | |
_highlightColor = highlightColor; | |
_highlightColorHexString = hexStringFromColor(_highlightColor); | |
_dirty = YES; | |
} | |
- (void)setHighlightColorHexString:(NSString *)highlightColorHexString | |
{ | |
_dirty = YES; | |
_highlightColorHexString = highlightColorHexString; | |
highlightColorHexString = [highlightColorHexString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; | |
NSUInteger len = [highlightColorHexString length]; | |
if (len == 0) | |
{ | |
// either nil or @"" | |
_highlightColor = [CCColor colorWithCcColor4b:ccc4(70, 117, 255, 255)]; | |
return; | |
} | |
_highlightColor = nil; | |
NSString *hx = @"^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"; | |
NSRegularExpression *hexColorString = [NSRegularExpression regularExpressionWithPattern:hx options:0 error:nil]; | |
NSArray *matches = [hexColorString matchesInString:highlightColorHexString options:0 range:NSMakeRange(0, [highlightColorHexString length])]; | |
if ([matches count] == 1) | |
{ | |
NSUInteger r = 0, g = 0, b = 0; | |
NSTextCheckingResult *result = [matches objectAtIndex:0]; | |
if ([result numberOfRanges] == 4) | |
{ | |
r = strtol([[highlightColorHexString substringWithRange:[result rangeAtIndex:1]] UTF8String], NULL, 16); | |
g = strtol([[highlightColorHexString substringWithRange:[result rangeAtIndex:2]] UTF8String], NULL, 16); | |
b = strtol([[highlightColorHexString substringWithRange:[result rangeAtIndex:3]] UTF8String], NULL, 16); | |
_highlightColor = [CCColor colorWithCcColor3b:ccc3(r, g, b)]; | |
} | |
} | |
if (_highlightColor == nil) | |
{ | |
NSLog(@"#### ERROR: bad color %@: expected \"#rrggbb\" where r, g & b are 0-9", highlightColorHexString); | |
} | |
} | |
- (void)updateHighlightedText | |
{ | |
_dirty = NO; | |
CCColor *white = [CCColor whiteColor]; | |
if (_rawText != nil && [_rawText rangeOfString:@"["].location != NSNotFound) | |
{ | |
_cascadeColorEnabled = NO; | |
NSUInteger rawLen = [_rawText length]; | |
NSMutableArray *markers = [NSMutableArray arrayWithCapacity:rawLen]; | |
for (NSUInteger i = 0; i < rawLen; ++i) | |
{ | |
[markers addObject:@" "]; | |
} | |
NSRange currentRange; | |
currentRange.length = rawLen; | |
currentRange.location = 0; | |
NSCharacterSet *nlcs = [NSCharacterSet newlineCharacterSet]; | |
while (true) | |
{ | |
NSUInteger linefeed = [_rawText rangeOfCharacterFromSet:nlcs options:0 range:currentRange].location; | |
if (linefeed == NSNotFound) break; | |
[markers setObject:@"N" atIndexedSubscript:linefeed]; | |
currentRange.location = linefeed+1; | |
currentRange.length = rawLen - currentRange.location; | |
} | |
currentRange.location = 0; | |
currentRange.length = rawLen; | |
while (true) | |
{ | |
NSUInteger startBracket = [_rawText rangeOfString:@"[" options:0 range:currentRange].location; | |
NSUInteger endBracket = [_rawText rangeOfString:@"]" options:0 range:currentRange].location; | |
if (startBracket == NSNotFound || endBracket == NSNotFound) { break; } | |
[markers setObject:@"[" atIndexedSubscript:startBracket]; | |
[markers setObject:@"]" atIndexedSubscript:endBracket]; | |
currentRange.location = endBracket + 1; | |
currentRange.length = rawLen - currentRange.location; | |
} | |
NSUInteger ix = 0; | |
BOOL inHighlight = NO; | |
CCColor *col = [self color]; | |
if (col == nil) | |
{ | |
col = white; | |
} | |
for (NSString *marker in markers) | |
{ | |
if ([marker isEqualToString:@"["]) | |
{ | |
inHighlight = YES; | |
} | |
else if ([marker isEqualToString:@"]"]) | |
{ | |
inHighlight = NO; | |
} | |
else if ([marker isEqualToString:@"N"]) | |
{ | |
// | |
} | |
else | |
{ | |
CCSprite *charSprite = (CCSprite *)[[self children] objectAtIndex:ix]; | |
[charSprite setColor:inHighlight ? [self highlightColor] : col]; | |
++ix; | |
} | |
} | |
} | |
else | |
{ | |
_cascadeColorEnabled = YES; | |
} | |
} | |
- (void)setString:(NSString *)label | |
{ | |
[super setString:stripSquareBrackets(label)]; | |
_rawText = [label copy]; | |
_dirty = YES; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment