Skip to content

Instantly share code, notes, and snippets.

@Shilo
Created March 13, 2012 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Shilo/2027039 to your computer and use it in GitHub Desktop.
Save Shilo/2027039 to your computer and use it in GitHub Desktop.
An extension for Sparrow that allows alpha handing of texture-based objects. (Sparrow 1.X)
//
// SHAlphaButton.h
// Sparrow
//
// Created by Shilo White on 8/13/11.
// Copyright 2011 Shilocity Productions. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPButton.h"
@interface SHAlphaButton : SPButton {
float mAllowTouchOnAlpha;
}
@property (nonatomic, assign) float allowTouchOnAlpha;
+ (id)buttonWithUpState:(SPTexture *)upState downState:(SPTexture *)downState;
+ (id)buttonWithUpState:(SPTexture *)upState text:(NSString *)text;
+ (id)buttonWithUpState:(SPTexture *)upState;
@end
//
// SHAlphaButton.m
// Sparrow
//
// Created by Shilo White on 8/13/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SHAlphaButton.h"
#import "SHAlphaTexture.h"
@implementation SHAlphaButton
+ (id)buttonWithUpState:(SPTexture *)upState downState:(SPTexture *)downState {
return [[[self alloc] initWithUpState:upState downState:downState] autorelease];
}
+ (id)buttonWithUpState:(SPTexture *)upState text:(NSString *)text {
return [[[self alloc] initWithUpState:upState text:text] autorelease];
}
+ (id)buttonWithUpState:(SPTexture *)upState {
return [[[self alloc] initWithUpState:upState] autorelease];
}
- (SPDisplayObject *)hitTestPoint:(SPPoint *)localPoint forTouch:(BOOL)isTouch {
SHAlphaTexture *upState = (SHAlphaTexture *)self.upState;
if (![upState isMemberOfClass:[SHAlphaTexture class]] && ![upState isMemberOfClass:[SHAlphaSubTexture class]] && ![upState isMemberOfClass:[SHGLAlphaTexture class]]) {
return [super hitTestPoint:localPoint forTouch:isTouch];
}
if ((isTouch && (!self.visible || !self.touchable)) || ![super hitTestPoint:localPoint forTouch:isTouch])
return nil;
float scale = upState.alphaScale;
NSUInteger index = round(localPoint.x*scale) + (round(localPoint.y*scale) * (upState.alphaWidth*scale));
char *rawDataBytes = (char *)[upState.alphaData bytes];
//return (rawDataBytes[index] == 0) ? nil : self;
return (rawDataBytes[index] == -1) ? self : nil;
}
@end
//
// SHAlphaImage.h
// Sparrow
//
// Created by Shilo White on 3/12/12.
// Copyright (c) 2012 Shilocity Productions. All rights reserved.
//
#import "SPImage.h"
@interface SHAlphaImage : SPImage {
float mAllowTouchOnAlpha;
}
@property (nonatomic, assign) float allowTouchOnAlpha;
+ (SHAlphaImage *)imageWithTexture:(SPTexture*)texture;
+ (SHAlphaImage *)imageWithContentsOfFile:(NSString*)path;
- (float)alphaOfPixelWithX:(float)x y:(float)y;
@end
//
// SHAlphaImage.m
// Sparrow
//
// Created by Shilo White on 3/12/12.
// Copyright (c) 2012 Shilocity Productions. All rights reserved.
//
#import "SHAlphaImage.h"
#import "SHAlphaTexture.h"
@implementation SHAlphaImage
@synthesize allowTouchOnAlpha = mAllowTouchOnAlpha;
- (id)initWithTexture:(SPTexture*)texture {
if ((self = [super initWithTexture:texture])) {
mAllowTouchOnAlpha = 1.0f;
}
return self;
}
- (id)initWithContentsOfFile:(NSString*)path {
return [self initWithTexture:[SHAlphaTexture textureWithContentsOfFile:path]];
}
- (id)initWithWidth:(float)width height:(float)height {
SPTextureProperties properties = { .width = width, .height = height };
return [self initWithTexture:[SHGLAlphaTexture textureWithData:NULL properties:properties]];
}
+ (SHAlphaImage *)imageWithTexture:(SPTexture*)texture {
return [[[self alloc] initWithTexture:texture] autorelease];
}
+ (SHAlphaImage *)imageWithContentsOfFile:(NSString*)path {
return [[[self alloc] initWithContentsOfFile:path] autorelease];
}
- (SPDisplayObject *)hitTestPoint:(SPPoint *)localPoint forTouch:(BOOL)isTouch {
if (isTouch && mAllowTouchOnAlpha <= 0) return [super hitTestPoint:localPoint forTouch:isTouch];
SHAlphaTexture *texture = (SHAlphaTexture *)self.texture;
if (![texture isMemberOfClass:[SHAlphaTexture class]] && ![texture isMemberOfClass:[SHAlphaSubTexture class]] && ![texture isMemberOfClass:[SHGLAlphaTexture class]]) {
return [super hitTestPoint:localPoint forTouch:isTouch];
}
if ((isTouch && (!self.visible || !self.touchable)) || ![super hitTestPoint:localPoint forTouch:isTouch])
return nil;
//NSUInteger index = round(localPoint.x) + (round(localPoint.y) * upState.alphaWidth);
//char *rawDataBytes = (char *)[upState.alphaData bytes];
//return (rawDataBytes[index] == 0) ? nil : self;
//return (rawDataBytes[index] < 0) ? self : nil;
//return (rawDataBytes[index] == -1) ? self : nil;
return ([texture alphaOfPixelWithX:localPoint.x y:localPoint.y] >= mAllowTouchOnAlpha) ? self : nil;
}
- (float)alphaOfPixelWithX:(float)x y:(float)y {
SHAlphaTexture *texture = (SHAlphaTexture *)self.texture;
if (![texture isMemberOfClass:[SHAlphaTexture class]] && ![texture isMemberOfClass:[SHAlphaSubTexture class]] && ![texture isMemberOfClass:[SHGLAlphaTexture class]]) {
return 0;
} else {
return [texture alphaOfPixelWithX:x y:y];
}
}
@end
//
// SPAlphaTexture.h
// Sparrow
//
// Created by Shilo White on 8/13/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPTexture.h"
#import "SPSubTexture.h"
#import "SPGLTexture.h"
@interface SHAlphaTexture : SPTexture
@property (nonatomic, retain) NSData *alphaData;
@property (nonatomic, assign) float alphaWidth;
@property (nonatomic, assign) float alphaScale;
+ (id)textureWithContentsOfFile:(NSString*)path;
+ (id)textureWithRegion:(SPRectangle *)region ofTexture:(SPTexture *)texture;
+ (id)textureWithWidth:(float)width height:(float)height draw:(SPTextureDrawingBlock)drawingBlock;
+ (id)emptyTexture;
@end
@interface SHAlphaSubTexture : SPSubTexture {
NSData *mAlphaData;
float mAlphaWidth;
float mAlphaScale;
}
@property (nonatomic, retain) NSData *alphaData;
@property (nonatomic, assign) float alphaWidth;
@property (nonatomic, assign) float alphaScale;
@end
@interface SHGLAlphaTexture : SPGLTexture {
NSData *mAlphaData;
float mAlphaWidth;
float mAlphaScale;
}
@property (nonatomic, retain) NSData *alphaData;
@property (nonatomic, assign) float alphaWidth;
@property (nonatomic, assign) float alphaScale;
@end
//
// SPAlphaTexture.m
// Sparrow
//
// Created by Shilo White on 8/13/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SHAlphaTexture.h"
#import <CoreGraphics/CoreGraphics.h>
@interface SHAlphaTexture ()
- (NSData *)alphaDataOfCGImage:(CGImageRef)image;
CGContextRef CreateAlphaBitmapContext(CGImageRef image);
@end
@implementation SHAlphaTexture
- (id)initWithContentsOfImage:(UIImage *)image {
float scale = [image respondsToSelector:@selector(scale)] ? [image scale] : 1.0f;
NSData *alphaData = [self alphaDataOfCGImage:image.CGImage];
SHAlphaTexture *texture = [self initWithWidth:image.size.width height:image.size.height
scale:scale colorSpace:SPColorSpaceRGBA draw:^(CGContextRef context)
{
[image drawAtPoint:CGPointMake(0, 0)];
}];
texture.alphaScale = scale;
texture.alphaData = alphaData;
texture.alphaWidth = image.size.width;
return texture;
}
- (id)initWithWidth:(float)width height:(float)height scale:(float)scale colorSpace:(SPColorSpace)colorSpace draw:(SPTextureDrawingBlock)drawingBlock {
[self release];
int legalWidth = [SPUtils nextPowerOfTwo:width * scale];
int legalHeight = [SPUtils nextPowerOfTwo:height * scale];
SPTextureFormat textureFormat;
CGColorSpaceRef cgColorSpace;
CGBitmapInfo bitmapInfo;
BOOL premultipliedAlpha;
int bytesPerPixel;
if (colorSpace == SPColorSpaceRGBA) {
bytesPerPixel = 4;
textureFormat = SPTextureFormatRGBA;
cgColorSpace = CGColorSpaceCreateDeviceRGB();
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
premultipliedAlpha = YES;
} else {
bytesPerPixel = 1;
textureFormat = SPTextureFormatAlpha;
cgColorSpace = CGColorSpaceCreateDeviceGray();
bitmapInfo = kCGImageAlphaNone;
premultipliedAlpha = NO;
}
void *imageData = calloc(legalWidth * legalHeight * bytesPerPixel, 1);
CGContextRef context = CGBitmapContextCreate(imageData, legalWidth, legalHeight, 8,
bytesPerPixel * legalWidth, cgColorSpace,
bitmapInfo);
CGColorSpaceRelease(cgColorSpace);
CGContextTranslateCTM(context, 0.0f, legalHeight);
CGContextScaleCTM(context, scale, -scale);
if (drawingBlock) {
UIGraphicsPushContext(context);
drawingBlock(context);
UIGraphicsPopContext();
}
SPTextureProperties properties = {
.format = textureFormat,
.width = legalWidth,
.height = legalHeight,
.generateMipmaps = YES,
.premultipliedAlpha = premultipliedAlpha
};
SHGLAlphaTexture *glTexture = [[SHGLAlphaTexture alloc] initWithData:imageData properties:properties];
glTexture.scale = scale;
CGContextRelease(context);
free(imageData);
SPRectangle *region = [SPRectangle rectangleWithX:0 y:0 width:width height:height];
SHAlphaTexture *subTexture = [[SHAlphaTexture alloc] initWithRegion:region ofTexture:glTexture];
[glTexture release];
return subTexture;
}
- (id)initWithRegion:(SPRectangle *)region ofTexture:(SPTexture *)texture {
[self release];
if (region.x == 0.0f && region.y == 0.0f && region.width == texture.width && region.height == texture.height) {
return (id)[texture retain];
} else {
return (id)[[SHAlphaSubTexture alloc] initWithRegion:region ofTexture:texture];
}
}
+ (id)emptyTexture {
return [[[SHGLAlphaTexture alloc] init] autorelease];
}
+ (id)textureWithContentsOfFile:(NSString *)path {
return [[[SHAlphaTexture alloc] initWithContentsOfFile:path] autorelease];
}
+ (id)textureWithRegion:(SPRectangle *)region ofTexture:(SPTexture *)texture {
return [[[SHAlphaTexture alloc] initWithRegion:region ofTexture:texture] autorelease];
}
+ (id)textureWithWidth:(float)width height:(float)height draw:(SPTextureDrawingBlock)drawingBlock {
return [[[SHAlphaTexture alloc] initWithWidth:width height:height draw:drawingBlock] autorelease];
}
- (NSData *)alphaDataOfCGImage:(CGImageRef)image {
CGContextRef context = CreateAlphaBitmapContext(image);
if (context == NULL)
return nil;
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
CGRect rect = CGRectMake(0, 0, width, height);
CGContextDrawImage(context, rect, image);
void *data = CGBitmapContextGetData(context);
CGContextRelease(context);
if (!data)
return nil;
size_t dataSize = width * height;
return [NSData dataWithBytes:data length:dataSize];
}
CGContextRef CreateAlphaBitmapContext(CGImageRef image) {
CGContextRef context = NULL;
void *bitmapData;
int bitmapByteCount;
size_t pixelsWide = CGImageGetWidth(image);
size_t pixelsHigh = CGImageGetHeight(image);
bitmapByteCount = pixelsWide * pixelsHigh;
bitmapData = malloc(bitmapByteCount);
if (bitmapData == NULL)
return nil;
context = CGBitmapContextCreate(bitmapData, pixelsWide, pixelsHigh, 8, pixelsWide, NULL, kCGImageAlphaOnly);
if (context == NULL) {
free(bitmapData);
fprintf(stderr, "Context not created!");
}
return context;
}
- (void)setAlphaData:(NSData *)alphaData { return; }
- (NSData *)alphaData { return nil; }
- (void)setAlphaWidth:(float)alphaWidth { return; }
- (float)alphaWidth { return 0; }
@end
@implementation SHAlphaSubTexture
@synthesize alphaData = mAlphaData;
@synthesize alphaWidth = mAlphaWidth;
@synthesize alphaScale = mAlphaScale;
- (void)dealloc {
[mAlphaData release];
[super dealloc];
}
@end
@implementation SHGLAlphaTexture
@synthesize alphaData = mAlphaData;
@synthesize alphaWidth = mAlphaWidth;
@synthesize alphaScale = mAlphaScale;
- (void)dealloc {
[mAlphaData release];
[super dealloc];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment