Skip to content

Instantly share code, notes, and snippets.

@sarah-j-smith
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sarah-j-smith/54e291e7d7c93de1ba23 to your computer and use it in GitHub Desktop.
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.
//
// 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
//
// 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