Permalink
Browse files

Cleaned up, improved stack code, added fill animation support.

  • Loading branch information...
1 parent 3373361 commit d4ad6e8a94445262b533a5c669f726879d3ab5da @iNinja committed Apr 10, 2012
@@ -17,6 +17,23 @@ typedef struct _ccRange
int Y;
} ccRange;
+typedef struct _ccRangeStack
+{
+ ccRange * base;
+ ccRange * top;
+ ccRange * stack;
+ NSUInteger count;
+
+} ccRangeStack;
+
+void initStack(ccRangeStack * stack, NSUInteger count);
+void freeStack(ccRangeStack * stack);
+BOOL checkStack(ccRangeStack stack);
+void resetStack(ccRangeStack * stack);
+void pushRange(ccRangeStack * stack, ccRange range);
+ccRange popRange(ccRangeStack * stack);
+
+
static inline ccRange
ccr(const int start, const int end, const int y)
{
@@ -27,21 +44,33 @@ ccr(const int start, const int end, const int y)
@interface CCSpriteFloodFill : CCSprite {
CCTexture2DMutable * mutableTexture;
- // CCArray * PixelQueue;
+
BOOL pixelsChecked[1024][768];
ccColor4B targetColor;
ccColor4B startingColor;
+
+ ccRangeStack stack;
+
+ BOOL animated;
+ BOOL animating;
+
}
+// Number of steps per animation frame. Only used when ANIMATED is set to YES
+@property (nonatomic, assign) NSUInteger stepsPerFrame;
+
+ (id)spriteWithImage:(UIImage *)image;
++ (id)spriteWithImage:(UIImage *)image animated:(BOOL)anim;
- (id)initWithImage:(UIImage *)image;
+- (id)initWithImage:(UIImage *)image animated:(BOOL)anim;
+- (void)fillFromPoint:(CGPoint)pos withColor:(ccColor4B)col;
+
+// Internal use
-(void)linearFillFromX:(NSInteger)startX andY:(NSInteger)startY;
-(void)prepareFill;
-(void)floodFillTexture :(CGPoint) UvTxtCoord;
-- (void)fillFromPoint:(CGPoint)pos withColor:(ccColor4B)col;
-
@end
View
@@ -8,64 +8,160 @@
#import "CCSpriteFloodFill.h"
-BOOL checkPixel(ccColor4B pixel, ccColor4B color);
-BOOL checkStack(void);
-void pushRange(ccRange range);
-ccRange popRange(void);
-
-ccRange *tos, *p1, stack[786432];
-
BOOL checkPixel(ccColor4B pixel, ccColor4B color)
{
return pixel.r == color.r && pixel.g == color.g && pixel.b == color.b;
}
-BOOL checkStack(void)
+void initStack(ccRangeStack * stack, NSUInteger count)
+{
+ stack->stack = malloc(sizeof(ccRange *) * count);
+ memset(stack->stack, 0, sizeof(ccRange *) * count);
+ stack->base = stack->top = stack->stack;
+}
+
+void freeStack(ccRangeStack * stack)
+{
+ free(stack->stack);
+ stack->base = stack->top = stack->stack = NULL;
+}
+
+BOOL checkStack(ccRangeStack stack)
{
- return p1 == tos;
+ return stack.top == stack.base;
}
-void resetStack(void)
+void resetStack(ccRangeStack * stack)
{
- tos = p1 = stack;
+ stack->base = stack->top = stack->stack;
}
-void pushRange(ccRange range)
+void pushRange(ccRangeStack * stack, ccRange range)
{
- p1++;
+ stack->top++;
- assert(p1 != (tos + 786432) );
+ assert(stack->top != (stack->base + stack->count) );
- *p1 = range;
+ *(stack->top) = range;
}
-ccRange popRange(void)
+ccRange popRange(ccRangeStack * stack)
{
- assert(p1 != tos);
+ assert(stack->top != stack->base);
- p1--;
- return *(p1+1);
+ stack->top--;
+ return *(stack->top+1);
}
@implementation CCSpriteFloodFill
+@synthesize stepsPerFrame;
+
+ (id)spriteWithImage:(UIImage *)image
{
- return [[[CCSpriteFloodFill alloc] initWithImage:image] autorelease];
+ return [CCSpriteFloodFill spriteWithImage:image animated:NO];
+}
+
++ (id)spriteWithImage:(UIImage *)image animated:(BOOL)anim
+{
+ return [[[CCSpriteFloodFill alloc] initWithImage:image animated:anim] autorelease];
}
- (id)initWithImage:(UIImage *)image
+{
+ return [self initWithImage:image animated:NO];
+}
+
+- (id)initWithImage:(UIImage *)image animated:(BOOL)anim
{
CCTexture2DMutable * texture = [[[CCTexture2DMutable alloc] initWithImage:image] autorelease];
if (self = [super initWithTexture:texture]) {
+
+ animated = anim;
+
mutableTexture = texture;
- tos = stack;
- p1 = stack;
+ initStack(&stack, image.size.width * image.size.height);
+
+ self.stepsPerFrame = 30;
}
return self;
}
+- (void)dealloc
+{
+ freeStack(&stack);
+
+ [super dealloc];
+}
+
+- (void)onEnter
+{
+ [super onEnter];
+
+ if (animated) {
+ [self scheduleUpdate];
+ }
+}
+
+- (void)onExit
+{
+ [super onExit];
+
+ if (animated) {
+ [self unscheduleUpdate];
+ }
+}
+
+- (void)update:(ccTime)dt
+{
+ if( checkStack(stack) )
+ {
+ animating = NO;
+ return;
+ }
+
+ NSUInteger count = 0;
+
+ while (!checkStack(stack) && count < self.stepsPerFrame) {
+ ccRange range = popRange(&stack);
+
+ int upY = range.Y - 1;
+ int downY = range.Y +1;
+ for( int i = range.Start; i<= range.End; ++i )
+ {
+
+ if( range.Y > 0 && !pixelsChecked[i][upY])
+ {
+ ccColor4B pixel = [mutableTexture pixelAt:ccp(i,upY)];
+ if( checkPixel(pixel, startingColor) )
+ {
+ [self linearFillFromX:i andY:upY];
+ }
+ }
+
+ if( range.Y < [self contentSize].height-1 && !pixelsChecked[i][downY])
+ {
+ ccColor4B pixel = [mutableTexture pixelAt:ccp(i,downY)];
+ if( checkPixel(pixel, startingColor) )
+ {
+ [self linearFillFromX:i andY: downY];
+
+ }
+ }
+ }
+
+ ++count;
+ }
+
+ if (count > 0) {
+ [mutableTexture apply];
+ self.dirty = YES;
+ }
+
+}
+
+
- (void) linearFillFromX:(NSInteger)startX andY:(NSInteger)startY
{
//**********************************************************************
@@ -129,7 +225,7 @@ - (void) linearFillFromX:(NSInteger)startX andY:(NSInteger)startY
//add range to stack
ccRange range = ccr( lFillLoc, rFillLoc, startY);
- pushRange(range);
+ pushRange(&stack, range);
}
-(void)floodFillTexture :(CGPoint) UvTxtCoord
@@ -153,7 +249,7 @@ -(void)floodFillTexture :(CGPoint) UvTxtCoord
-(void)prepareFill
{
- resetStack();
+ resetStack(&stack);
int mw = [self contentSize].width;
int mh = [self contentSize].height;
@@ -164,6 +260,10 @@ -(void)prepareFill
- (void)fillFromPoint:(CGPoint)pos withColor:(ccColor4B)col {
+ if (animating) {
+ return;
+ }
+
CGPoint WolrdLoc = [self convertToNodeSpace:pos];
int pixelX = 0;
@@ -195,7 +295,7 @@ - (void)fillFromPoint:(CGPoint)pos withColor:(ccColor4B)col {
pixelY = (int)((float)ny/(float)self.scaleY);
}
- if( checkStack() )
+ if( checkStack(stack) )
{
targetColor = col;
if( targetColor.r <= 15 && targetColor.g <= 15 && targetColor.b <= 15 )
@@ -207,39 +307,45 @@ - (void)fillFromPoint:(CGPoint)pos withColor:(ccColor4B)col {
}
}
- while( ! checkStack() )
- {
- ccRange range = popRange();
-
- int upY = range.Y - 1;
- int downY = range.Y +1;
- for( int i = range.Start; i<= range.End; ++i )
+ if (animated) {
+ animating = YES;
+ }
+ else {
+ while( ! checkStack(stack) )
{
+ ccRange range = popRange(&stack);
- if( range.Y > 0 && !pixelsChecked[i][upY])
+ int upY = range.Y - 1;
+ int downY = range.Y +1;
+ for( int i = range.Start; i<= range.End; ++i )
{
- ccColor4B pixel = [mutableTexture pixelAt:ccp(i,upY)];
- if( checkPixel(pixel, startingColor) )
+
+ if( range.Y > 0 && !pixelsChecked[i][upY])
{
- [self linearFillFromX:i andY:upY];
+ ccColor4B pixel = [mutableTexture pixelAt:ccp(i,upY)];
+ if( checkPixel(pixel, startingColor) )
+ {
+ [self linearFillFromX:i andY:upY];
+ }
}
- }
-
- if( range.Y < [self contentSize].height-1 && !pixelsChecked[i][downY])
- {
- ccColor4B pixel = [mutableTexture pixelAt:ccp(i,downY)];
- if( checkPixel(pixel, startingColor) )
+
+ if( range.Y < [self contentSize].height-1 && !pixelsChecked[i][downY])
{
- [self linearFillFromX:i andY: downY];
-
+ ccColor4B pixel = [mutableTexture pixelAt:ccp(i,downY)];
+ if( checkPixel(pixel, startingColor) )
+ {
+ [self linearFillFromX:i andY: downY];
+
+ }
}
}
}
+
+ [mutableTexture apply];
+ self.dirty = YES;
+
}
-
- [mutableTexture apply];
- self.dirty = YES;
-
+
}
@@ -123,7 +123,6 @@
BC1D33F315250DC3005A0EAB /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1D33F215250DC3005A0EAB /* RootViewController.m */; };
BC1D33F615250DC3005A0EAB /* HelloWorldLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1D33F515250DC3005A0EAB /* HelloWorldLayer.m */; };
BC1D33FF15250E81005A0EAB /* CCTexture2DMutable.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1D33FE15250E81005A0EAB /* CCTexture2DMutable.m */; };
- BC1D340115251237005A0EAB /* Conejo.png in Resources */ = {isa = PBXBuildFile; fileRef = BC1D340015251237005A0EAB /* Conejo.png */; };
BC1D340315251958005A0EAB /* Btncolor.png in Resources */ = {isa = PBXBuildFile; fileRef = BC1D340215251958005A0EAB /* Btncolor.png */; };
BC57ECCD15261F6800857B22 /* CCSpriteFloodFill.m in Sources */ = {isa = PBXBuildFile; fileRef = BC57ECCC15261F6800857B22 /* CCSpriteFloodFill.m */; };
/* End PBXBuildFile section */
@@ -366,7 +365,6 @@
BC1D33F715250DC3005A0EAB /* GameConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameConfig.h; sourceTree = "<group>"; };
BC1D33FD15250E81005A0EAB /* CCTexture2DMutable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTexture2DMutable.h; sourceTree = "<group>"; };
BC1D33FE15250E81005A0EAB /* CCTexture2DMutable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTexture2DMutable.m; sourceTree = "<group>"; };
- BC1D340015251237005A0EAB /* Conejo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Conejo.png; path = Resources/Conejo.png; sourceTree = "<group>"; };
BC1D340215251958005A0EAB /* Btncolor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Btncolor.png; path = Resources/Btncolor.png; sourceTree = "<group>"; };
BC57ECCB15261F6800857B22 /* CCSpriteFloodFill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSpriteFloodFill.h; sourceTree = "<group>"; };
BC57ECCC15261F6800857B22 /* CCSpriteFloodFill.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSpriteFloodFill.m; sourceTree = "<group>"; };
@@ -448,7 +446,6 @@
isa = PBXGroup;
children = (
BC1D340215251958005A0EAB /* Btncolor.png */,
- BC1D340015251237005A0EAB /* Conejo.png */,
BC1D329E15250DBF005A0EAB /* Default.png */,
BC1D32A015250DBF005A0EAB /* fps_images.png */,
BC1D32A215250DBF005A0EAB /* Icon-72.png */,
@@ -833,7 +830,6 @@
BC1D32AB15250DBF005A0EAB /* Icon.png in Resources */,
BC1D32AD15250DBF005A0EAB /* Icon@2x.png in Resources */,
BC1D32B015250DBF005A0EAB /* iTunesArtwork in Resources */,
- BC1D340115251237005A0EAB /* Conejo.png in Resources */,
BC1D340315251958005A0EAB /* Btncolor.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Oops, something went wrong.

0 comments on commit d4ad6e8

Please sign in to comment.