Skip to content

Commit

Permalink
Handlers and randomization
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelomer committed Feb 15, 2020
1 parent 77d93fa commit 224a06a
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 41 deletions.
18 changes: 17 additions & 1 deletion Goose/MGGooseView.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
#import <UIKit/UIKit.h>

@class MGGooseView;

typedef NS_ENUM(NSInteger, MGGooseFrameState) {
MGGooseWillStartDrawing = 0b10000000,
MGGooseDidFinishDrawing = 0,
#define e(name, val) MGGooseDidDraw##name = val, MGGooseWillDraw##name = (val | 0b10000000)
e(Shadow, 1),
e(Feet, 2),
e(Body, 3),
e(Neck, 4),
e(Eyes, 5),
e(Beak, 6)
#undef e
};
typedef void(^MGGooseFrameHandler)(MGGooseView *, MGGooseFrameState);

// Do you think I'm using the wrong terms in variable names? If so,
// feel free to make a pull request that fixes it.

Expand All @@ -24,6 +40,6 @@
completionHandler:(void(^)(MGGooseView *))completion;
- (void)setFacingTo:(CGFloat)degress
animationCompletion:(void(^)(MGGooseView *))completion;
- (NSUInteger)addFrameHandler:(void(^)(MGGooseView *))handler;
- (NSUInteger)addFrameHandler:(MGGooseFrameHandler)handler;
- (void)removeFrameHandlerAtIndex:(NSUInteger)index;
@end
62 changes: 48 additions & 14 deletions Goose/MGGooseView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,37 @@ - (CGSize)sizeThatFits:(CGSize)size {
return CGSizeMake(80, 80);
}

- (void)notifyFrameHandlers:(MGGooseFrameState)state {
for (NSUInteger i=0; i<_frameHandlers.count; i++) {
MGGooseFrameHandler handler = (MGGooseFrameHandler)[_frameHandlers pointerAtIndex:i];
if (handler) handler(self, state);
}
}

- (void)advanceDrawingState:(int *)state {
if (!state) return;
static const int stateOrder[] = { -1, 1, 2, 3, 4, 6, 5, -1 };
if (stateOrder[*state] >= 0) {
// Did draw
[self notifyFrameHandlers:stateOrder[*state]];
}
(*state)++;
if (stateOrder[*state] >= 0) {
// Will draw
[self notifyFrameHandlers:(stateOrder[*state] | 0b10000000)];
}
}

- (void)drawRect:(CGRect)rect {
int state = 0;
[self notifyFrameHandlers:MGGooseWillStartDrawing];

CGFloat facingToDegrees = (_facingTo + -[[self._viewControllerForAncestor valueForKey:@"lastDegrees"] doubleValue]);
CGFloat facingToRadians = facingToDegrees * M_PI / 180.0;

// Shadow
[shadowColor setFill];
[self advanceDrawingState:&state];
CGRect shadowBounds = CGRectMake(20, 30, 30, 30);
@autoreleasepool {
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:shadowBounds];
Expand All @@ -44,6 +69,7 @@ - (void)drawRect:(CGRect)rect {

// Feet
[[UIColor orangeColor] setFill];
[self advanceDrawingState:&state];
@autoreleasepool {
CGFloat change = (_walkMultiplier / 2.6);
switch (_walkingState) {
Expand Down Expand Up @@ -100,6 +126,7 @@ - (void)drawRect:(CGRect)rect {

// Body
[[UIColor whiteColor] setFill];
[self advanceDrawingState:&state];
@autoreleasepool {
CGRect oval1Rect = CGRectMake(25, 20, 20, 20);
UIBezierPath *oval1 = [UIBezierPath bezierPathWithOvalInRect:oval1Rect];
Expand All @@ -114,6 +141,8 @@ - (void)drawRect:(CGRect)rect {
}

// Neck
[[UIColor whiteColor] setFill];
[self advanceDrawingState:&state];
@autoreleasepool {
// Create a rect without the correct position
const CGFloat neckHeight = 10;
Expand All @@ -139,6 +168,8 @@ - (void)drawRect:(CGRect)rect {
}

// Face
[[UIColor orangeColor] setFill];
[self advanceDrawingState:&state];
@autoreleasepool {
// Create a rect without the correct position
const CGFloat beakSize = 8.0;
Expand All @@ -149,31 +180,30 @@ - (void)drawRect:(CGRect)rect {
rect.origin.x += 21.0 + (beakRadius * cos(facingToRadians));
rect.origin.y += 4.5 + (beakRadius * sin(facingToRadians));

[[UIColor orangeColor] setFill];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
[path fill];

[[UIColor blackColor] setFill];
[self advanceDrawingState:&state];

const CGFloat eyeSize = beakSize * 0.6;
const CGFloat eyeRadius = beakRadius - 3.0;
rect.size.height = rect.size.width = eyeSize;
[[UIColor blackColor] setFill];
for (int8_t i=0, offset=15; i<2; i+=1.0) {
rect.origin.x = 32.5 + (eyeRadius * cos(DEG_TO_RAD(facingToDegrees + offset)));
rect.origin.y = 24.5 + (eyeRadius * sin(DEG_TO_RAD(facingToDegrees + offset)));
path = [UIBezierPath bezierPathWithOvalInRect:rect];
[path fill];
offset = -offset;
}
[self advanceDrawingState:&state];
}
if (_remainingFramesUntilCompletion == 0) _walkingState = 0;
if (_remainingFramesUntilCompletion >= 0) _remainingFramesUntilCompletion--;
for (NSUInteger i=0; i<_frameHandlers.count; i++) {
void(^handler)(MGGooseView *) = (typeof(handler))[_frameHandlers pointerAtIndex:i];
if (handler) handler(self);
}
[self notifyFrameHandlers:MGGooseDidFinishDrawing];
}

- (NSUInteger)addFrameHandler:(void(^)(MGGooseView *))handler {
- (NSUInteger)addFrameHandler:(MGGooseFrameHandler)handler {
for (NSUInteger i=0; i<_frameHandlers.count; i++) {
if (![_frameHandlers pointerAtIndex:i]) {
[_frameHandlers replacePointerAtIndex:i withPointer:(__bridge void *)handler];
Expand All @@ -184,6 +214,16 @@ - (NSUInteger)addFrameHandler:(void(^)(MGGooseView *))handler {
return _frameHandlers.count - 1;
}

- (BOOL)isFrameAtEdge:(CGRect)frame {
CGRect screenBounds = self._viewControllerForAncestor.view.bounds;
return (
((frame.origin.x + frame.size.width) >= (screenBounds.size.width - 1)) ||
((frame.origin.y + frame.size.height) >= (screenBounds.size.height - 1)) ||
(frame.origin.x <= 1) ||
(frame.origin.y <= 1)
);
}

- (void)removeFrameHandlerAtIndex:(NSUInteger)index {
[_frameHandlers replacePointerAtIndex:index withPointer:NULL];
}
Expand Down Expand Up @@ -228,13 +268,7 @@ - (void)timer:(id)unused {
CGRect frame = self.frame;
frame.origin.x += cos(DEG_TO_RAD(_facingTo)) * _walkMultiplier;
frame.origin.y += sin(DEG_TO_RAD(_facingTo)) * _walkMultiplier;
CGRect screenBounds = self._viewControllerForAncestor.view.bounds;
if (_stopsAtEdge &&
(((frame.origin.x + frame.size.width) >= (screenBounds.size.width - 1)) ||
((frame.origin.y + frame.size.height) >= (screenBounds.size.height - 1)) ||
(frame.origin.x <= 1) ||
(frame.origin.y <= 1))
) {
if (_stopsAtEdge && [self isFrameAtEdge:frame]) {
_remainingFramesUntilCompletion = -1;
_walkingState = 0;
}
Expand Down
65 changes: 39 additions & 26 deletions Tweak.xm
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ static void(^animation2Handler)(MGGooseView *);
static void(^showMeme)(MGGooseView *);
static void(^walkHandler)(MGGooseView *);
static void(^findMeme)(MGGooseView *);
static void(^gotoMemeFrameHandler)(MGGooseView *);
static void(^gotoMemeFrameHandler)(MGGooseView *, MGGooseFrameState state);
static void(^turnToMemeHandler)(MGGooseView *);
static void(^pullMemeFrameHandler)(MGGooseView *);
static void(^pullMemeFrameHandler)(MGGooseView *, MGGooseFrameState state);
static void(^finishMemeAnimation)(MGGooseView *);
static void(^turnToUserAnimation)(MGGooseView *);
static void(^loadMeme)(void);
static __kindof MGContainerView *imageContainer;
static NSInteger frameHandlerIndex;
static NSArray *honks;
static NSPointerArray *containers;
static MGViewController *viewController;

%subclass MGWindow : UIWindow
Expand Down Expand Up @@ -112,27 +113,34 @@ static MGViewController *viewController;
});
}
};
pullMemeFrameHandler = ^(MGGooseView *sender){
CGPoint center = imageContainer.center;
center.x += sender.positionChange.x;
imageContainer.center = center;
pullMemeFrameHandler = ^(MGGooseView *sender, MGGooseFrameState state){
if (state == MGGooseDidFinishDrawing) {
CGPoint center = imageContainer.center;
center.x += sender.positionChange.x;
imageContainer.center = center;
}
};
gotoMemeFrameHandler = ^(MGGooseView *sender){
if (sender.frame.origin.x <= -15.0) {
[sender removeFrameHandlerAtIndex:frameHandlerIndex];
frameHandlerIndex = [sender addFrameHandler:pullMemeFrameHandler];
CGPoint point = CGPointMake(-(imageContainer.frame.size.width/2.0), sender.center.y);
CGFloat min = (imageContainer.frame.size.height / 2.0);
CGFloat max = (gooseWindow.frame.size.height - min);
if (point.y < min) point.y = min;
else if (point.y > max) point.y = max;
imageContainer.center = point;
imageContainer.hidden = NO;
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
loadMeme
);
[sender walkForDuration:3.0 speed:-2.0 completionHandler:finishMemeAnimation];
gotoMemeFrameHandler = ^(MGGooseView *sender, MGGooseFrameState state){
if (state == MGGooseDidFinishDrawing) {
if (/* (cond) ? */
(sender.frame.origin.x <= -15.0)/* :
(sender.frame.origin.x >= (gooseWindow.frame.size.width - sender.frame.size.width + 15.0))
*/) {
[sender removeFrameHandlerAtIndex:frameHandlerIndex];
frameHandlerIndex = [sender addFrameHandler:pullMemeFrameHandler];
CGPoint point = CGPointMake(-(imageContainer.frame.size.width/2.0), sender.center.y);
CGFloat min = (imageContainer.frame.size.height / 2.0);
CGFloat max = (gooseWindow.frame.size.height - min);
if (point.y < min) point.y = min;
else if (point.y > max) point.y = max;
imageContainer.center = point;
imageContainer.hidden = NO;
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
loadMeme
);
[sender walkForDuration:(3.0 + ((NSTimeInterval)arc4random_uniform(25) / 10.0)) speed:-2.0 completionHandler:finishMemeAnimation];
}
}
};
turnToMemeHandler = ^(MGGooseView *sender){
Expand All @@ -148,20 +156,24 @@ static MGViewController *viewController;
dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * ((double)arc4random_uniform(50) / 10.0)),
dispatch_get_main_queue(),
^{
uint8_t randomValue = arc4random_uniform(5);
uint8_t randomValue;
[containers compact];
if (containers.count >= 5) randomValue = 0;
else randomValue = arc4random_uniform(100);
Class cls = nil;
switch (randomValue) {
case 3:
case 40 ... 44:
cls = [MGImageContainerView class];
break;
case 4:
case 45 ... 49:
cls = [MGTextContainerView class];
break;
default:
walkHandler(sender);
return;
}
imageContainer = [[cls alloc] initWithFrame:CGRectMake(0,0,125,125)];
[containers addPointer:(__bridge void *)imageContainer];
imageContainer.transform = transform;
imageContainer.hidden = YES;
[gooseWindow.rootViewController.view
Expand All @@ -186,6 +198,7 @@ static MGViewController *viewController;
speed:2.6
completionHandler:turnToUserAnimation];
};
containers = [NSPointerArray weakObjectsPointerArray];
NSMutableArray *mHonks = [NSMutableArray new];
const NSInteger gooseCount = 1;
for (NSInteger i=0; i<gooseCount; i++) {
Expand All @@ -197,7 +210,7 @@ static MGViewController *viewController;
arc4random_uniform(gooseWindow.frame.size.height - frame.size.height)
);
honk.frame = frame;
[gooseWindow.rootViewController.view insertSubview:honk atIndex:1];
[gooseWindow.rootViewController.view insertSubview:honk atIndex:NSIntegerMax];
[mHonks addObject:honk];
honk.facingTo = 0.0;
animationHandler(honk);
Expand Down

0 comments on commit 224a06a

Please sign in to comment.