Last active
December 23, 2015 04:08
-
-
Save Shilo/6577834 to your computer and use it in GitHub Desktop.
An extension for Sparrow that allows alpha handing of texture-based objects. (Sparrow 2.X)
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
// | |
// 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 |
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
// | |
// 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" | |
@interface SHAlphaTexture () | |
- (float)alphaOfPixelWithX:(float)x y:(float)y; | |
@end | |
@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 { | |
return [self initWithTexture:[SHAlphaTexture textureWithWidth:width height:height draw:NULL]]; | |
} | |
+ (SHAlphaImage *)imageWithTexture:(SPTexture*)texture { | |
return [[self alloc] initWithTexture:texture]; | |
} | |
+ (SHAlphaImage *)imageWithContentsOfFile:(NSString*)path { | |
return [[self alloc] initWithContentsOfFile:path]; | |
} | |
- (SPDisplayObject *)hitTestPoint:(SPPoint *)localPoint { | |
if (mAllowTouchOnAlpha <= 0) return [super hitTestPoint:localPoint]; | |
SHAlphaTexture *texture = (SHAlphaTexture *)self.texture; | |
if (![texture isKindOfClass:[SHAlphaTexture class]] && ![texture isKindOfClass:[SHAlphaSubTexture class]] && ![texture isKindOfClass:[SHGLAlphaTexture class]]) { | |
return [super hitTestPoint:localPoint]; | |
} | |
if ((!self.visible || !self.touchable) || ![super hitTestPoint:localPoint]) | |
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 isKindOfClass:[SHAlphaTexture class]] && ![texture isKindOfClass:[SHAlphaSubTexture class]] && ![texture isKindOfClass:[SHGLAlphaTexture class]]) { | |
return 0; | |
} else { | |
return [texture alphaOfPixelWithX:x y:y]; | |
} | |
} | |
@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
// | |
// 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, strong) 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; | |
- (float)alphaOfPixelWithX:(float)x y:(float)y; | |
@end | |
@interface SHAlphaSubTexture : SPSubTexture { | |
NSData *mAlphaData; | |
float mAlphaWidth; | |
float mAlphaScale; | |
} | |
@property (nonatomic, strong) NSData *alphaData; | |
@property (nonatomic, assign) float alphaWidth; | |
@property (nonatomic, assign) float alphaScale; | |
- (float)alphaOfPixelWithX:(float)x y:(float)y; | |
@end | |
@interface SHGLAlphaTexture : SPGLTexture { | |
NSData *mAlphaData; | |
float mAlphaWidth; | |
float mAlphaScale; | |
} | |
@property (nonatomic, strong) NSData *alphaData; | |
@property (nonatomic, assign) float alphaWidth; | |
@property (nonatomic, assign) float alphaScale; | |
- (float)alphaOfPixelWithX:(float)x y:(float)y; | |
@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
// | |
// 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 | |
@interface SPTexture () | |
+ (NSDictionary *)optionsForPath:(NSString *)path mipmaps:(BOOL)mipmaps pma:(BOOL)pma; | |
+ (BOOL)isCompressedFile:(NSString *)path; | |
@end | |
@implementation SHAlphaTexture | |
- (id)initWithContentsOfFile:(NSString *)path generateMipmaps:(BOOL)mipmaps | |
premultipliedAlpha:(BOOL)pma | |
{ | |
NSString *fullPath = [SPUtils absolutePathToFile:path]; | |
if (!fullPath) | |
[NSException raise:SP_EXC_FILE_NOT_FOUND format:@"File '%@' not found", path]; | |
UIImage *image = [UIImage imageWithContentsOfFile:fullPath]; | |
SHAlphaTexture *texture = [self initWithContentsOfImage:image generateMipmaps:mipmaps]; | |
NSData *alphaData = [SHAlphaTexture alphaDataOfCGImage:image.CGImage]; | |
texture.alphaScale = [fullPath contentScaleFactor]; | |
texture.alphaData = alphaData; | |
texture.alphaWidth = texture.width; | |
return texture; | |
} | |
+ (void)loadFromFile:(NSString *)path generateMipmaps:(BOOL)mipmaps premultipliedAlpha:(BOOL)pma | |
onComplete:(SPTextureLoadingBlock)callback; | |
{ | |
NSString *fullPath = [SPUtils absolutePathToFile:path]; | |
float actualScaleFactor = [fullPath contentScaleFactor]; | |
if ([self isCompressedFile:path]) | |
[NSException raise:SP_EXC_INVALID_OPERATION | |
format:@"Async loading of gzip-compressed files is not supported"]; | |
if (!fullPath) | |
[NSException raise:SP_EXC_FILE_NOT_FOUND format:@"File '%@' not found", path]; | |
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:fullPath]] queue:[NSOperationQueue mainQueue] | |
completionHandler:^(NSURLResponse *response, NSData *data, NSError *outError) | |
{ | |
SHAlphaTexture *texture = nil; | |
if (!outError) { | |
UIImage *image = [UIImage imageWithData:data scale:actualScaleFactor]; | |
texture = [[SHAlphaTexture alloc] initWithContentsOfImage:image generateMipmaps:mipmaps]; | |
NSData *alphaData = [SHAlphaTexture alphaDataOfCGImage:image.CGImage]; | |
texture.alphaScale = [fullPath contentScaleFactor]; | |
texture.alphaData = alphaData; | |
texture.alphaWidth = texture.width; | |
} | |
callback(texture, outError); | |
}]; | |
} | |
- (id)initWithContentsOfImage:(UIImage *)image generateMipmaps:(BOOL)mipmaps | |
{ | |
NSData *alphaData = [SHAlphaTexture alphaDataOfCGImage:image.CGImage]; | |
SHAlphaTexture *texture = [self initWithWidth:image.size.width height:image.size.height generateMipmaps:mipmaps | |
scale:image.scale draw:^(CGContextRef context) | |
{ | |
[image drawAtPoint:CGPointMake(0, 0)]; | |
}]; | |
texture.alphaScale = image.scale; | |
texture.alphaData = alphaData; | |
texture.alphaWidth = image.size.width; | |
return texture; | |
} | |
- (id)initWithWidth:(float)width height:(float)height generateMipmaps:(BOOL)mipmaps | |
scale:(float)scale draw:(SPTextureDrawingBlock)drawingBlock | |
{ | |
// only textures with sidelengths that are powers of 2 support all OpenGL ES features. | |
int legalWidth = [SPUtils nextPowerOfTwo:width * scale]; | |
int legalHeight = [SPUtils nextPowerOfTwo:height * scale]; | |
CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB(); | |
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast; | |
BOOL premultipliedAlpha = YES; | |
int bytesPerPixel = 4; | |
void *imageData = calloc(legalWidth * legalHeight * bytesPerPixel, 1); | |
CGContextRef context = CGBitmapContextCreate(imageData, legalWidth, legalHeight, 8, | |
bytesPerPixel * legalWidth, cgColorSpace, | |
bitmapInfo); | |
CGColorSpaceRelease(cgColorSpace); | |
// UIKit referential is upside down - we flip it and apply the scale factor | |
CGContextTranslateCTM(context, 0.0f, legalHeight); | |
CGContextScaleCTM(context, scale, -scale); | |
if (drawingBlock) | |
{ | |
UIGraphicsPushContext(context); | |
drawingBlock(context); | |
UIGraphicsPopContext(); | |
} | |
SHGLAlphaTexture *glTexture = [[SHGLAlphaTexture alloc] initWithData:imageData | |
width:legalWidth | |
height:legalHeight | |
generateMipmaps:mipmaps | |
scale:scale | |
premultipliedAlpha:premultipliedAlpha]; | |
CGContextRelease(context); | |
free(imageData); | |
SPRectangle *region = [SPRectangle rectangleWithX:0 y:0 width:width height:height]; | |
return [[SHAlphaTexture alloc] initWithRegion:region ofTexture:glTexture]; | |
} | |
- (id)initWithRegion:(SPRectangle*)region frame:(SPRectangle *)frame ofTexture:(SHAlphaTexture*)texture | |
{ | |
if (frame || region.x != 0.0f || region.width != texture.width | |
|| region.y != 0.0f || region.height != texture.height) | |
{ | |
return (SHAlphaTexture *)[[SHAlphaSubTexture alloc] initWithRegion:region frame:frame ofTexture:texture]; | |
} | |
else | |
{ | |
return texture; | |
} | |
} | |
+ (id)emptyTexture { | |
return [[SHGLAlphaTexture alloc] init]; | |
} | |
+ (id)textureWithContentsOfFile:(NSString *)path { | |
return [[SHAlphaTexture alloc] initWithContentsOfFile:path]; | |
} | |
+ (id)textureWithRegion:(SPRectangle *)region ofTexture:(SPTexture *)texture { | |
return [[SHAlphaTexture alloc] initWithRegion:region ofTexture:texture]; | |
} | |
+ (id)textureWithWidth:(float)width height:(float)height draw:(SPTextureDrawingBlock)drawingBlock { | |
return [[SHAlphaTexture alloc] initWithWidth:width height:height draw:drawingBlock]; | |
} | |
+ (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, (CGBitmapInfo)kCGImageAlphaOnly); | |
if (context == NULL) { | |
free(bitmapData); | |
fprintf(stderr, "Context not created!"); | |
} | |
return context; | |
} | |
- (float)alphaOfPixelWithX:(float)x y:(float)y { return 0.0f; } | |
- (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; | |
- (float)alphaOfPixelWithX:(float)x y:(float)y { | |
x = floorf(x); | |
y = floorf(y); | |
if (x < 0 || x >= self.width || y < 0 || y >= self.height) return 0; | |
NSUInteger index = x + (y * self.alphaWidth); | |
char *rawDataBytes = (char *)[self.alphaData bytes]; | |
UInt8 alpha = rawDataBytes[index] & 0x000000ff; | |
return ((float)alpha/255.0f); | |
} | |
@end | |
@implementation SHGLAlphaTexture | |
@synthesize alphaData = mAlphaData; | |
@synthesize alphaWidth = mAlphaWidth; | |
@synthesize alphaScale = mAlphaScale; | |
- (float)alphaOfPixelWithX:(float)x y:(float)y { | |
x = floorf(x); | |
y = floorf(y); | |
if (x < 0 || x >= self.width || y < 0 || y >= self.height) return 0; | |
NSUInteger index = x + (y * self.alphaWidth); | |
char *rawDataBytes = (char *)[self.alphaData bytes]; | |
UInt8 alpha = rawDataBytes[index] & 0x000000ff; | |
return ((float)alpha/255.0f); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment