Skip to content

Commit

Permalink
Minor updates. Also reverted the Lissajous example back to using CADi…
Browse files Browse the repository at this point in the history
…splayLink because of flickering problems
  • Loading branch information
Brian Coyner committed Mar 24, 2012
1 parent 590dc01 commit 3442c07
Show file tree
Hide file tree
Showing 17 changed files with 152 additions and 124 deletions.
3 changes: 2 additions & 1 deletion .gitignore
@@ -1,6 +1,7 @@
.DS_Store
profile

.idea
build

*.mode1
*.mode1v3
Expand Down
18 changes: 18 additions & 0 deletions CoreAnimationFunHouse.xcodeproj/project.pbxproj
Expand Up @@ -390,6 +390,8 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_OBJCPP_ARC_ABI = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
Expand All @@ -401,9 +403,16 @@
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
Expand All @@ -418,13 +427,22 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_OBJCPP_ARC_ABI = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
Expand Down
4 changes: 2 additions & 2 deletions CoreAnimationFunHouse/BTSAnchorPointLayer.m
Expand Up @@ -42,10 +42,10 @@ - (void)drawInContext:(CGContextRef)context
CGRect bounds = [self bounds];
CGPoint center = {CGRectGetMidX(bounds), CGRectGetMidY(bounds)};

int strokeWidth = 2;
CGFloat strokeWidth = 2.0;

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, center.x, center.y, bounds.size.width / 2 - strokeWidth, 0.0, M_PI * 2, 0);
CGPathAddArc(path, NULL, center.x, center.y, bounds.size.width / 2 - strokeWidth, 0.0, (CGFloat) (M_PI * 2.0), 0);

CGContextAddPath(context, path);
CGContextSetFillColorWithColor(context, [[UIColor redColor] colorWithAlphaComponent:0.5].CGColor);
Expand Down
14 changes: 5 additions & 9 deletions CoreAnimationFunHouse/BTSBasicLayerPropertiesViewController.m
Expand Up @@ -9,9 +9,7 @@
#import "BTSBasicLayerPropertiesViewController.h"
#import "BTSAnchorPointLayer.h"

#import <QuartzCore/QuartzCore.h>

// This view controller shows how various Core Animation CALayer properties implicitly animate.
// This view controller shows how various Core Animation CALayer properties implicitly animate.
// - position, corner radius, border, color, size, etc.

@interface BTSBasicLayerPropertiesViewController() {
Expand All @@ -23,8 +21,6 @@ @interface BTSBasicLayerPropertiesViewController() {
}

@property (strong, nonatomic) IBOutlet UILabel *animationDurationLabel;

- (IBAction)animationDurationChanged:(id)sender;

@end

Expand Down Expand Up @@ -53,7 +49,7 @@ - (void)viewDidLoad
_layer = [CALayer layer];
[_layer setContentsScale:[[UIScreen mainScreen] scale]];
[_layer setBackgroundColor:[UIColor blueColor].CGColor];
[_layer setBounds:CGRectMake(0, 0, 200, 200)];
[_layer setBounds:CGRectMake(0.0, 0.0, 200.0, 200.0)];

CGPoint anchorPoint = {0.5, 0.0};
[_layer setAnchorPoint:anchorPoint];
Expand All @@ -69,10 +65,10 @@ - (void)viewDidLoad

// Because the CALayer anchor point is {0.5,0.0}, we can simply set X to the center of the width.
// This centers the layer on the X axis.
CGFloat x = frame.size.width / 2;
CGFloat x = frame.size.width / 2.0;

// Position the layer 10 points from the top of the view.
CGFloat y = 10;
CGFloat y = 10.0;
[_layer setPosition:CGPointMake(x, y)];

[[[self view] layer] addSublayer:_layer];
Expand Down Expand Up @@ -135,7 +131,7 @@ - (IBAction)toggleSize:(id)sender
[CATransaction setAnimationDuration:_animationDuration];

CGRect layerBounds = _layer.bounds;
layerBounds.size.width = (layerBounds.size.width == layerBounds.size.height) ? 250 : 200;
layerBounds.size.width = (layerBounds.size.width == layerBounds.size.height) ? 250.0 : 200.0;
[_layer setBounds:layerBounds];

BTSAnchorPointLayer *anchorPointLayer = [[_layer sublayers] objectAtIndex:0];
Expand Down
6 changes: 2 additions & 4 deletions CoreAnimationFunHouse/BTSBezierPathViewController.m
Expand Up @@ -20,8 +20,6 @@ @interface BTSBezierPathViewController() {
CALayer *_layer;
}

- (void)updateAnimationForPath:(CGPathRef)path;

@end

@implementation BTSBezierPathViewController
Expand All @@ -35,8 +33,8 @@ - (void)viewDidLoad
// This is the layer that will animate along the path when the user presses the "animateButton".
_layer = [CALayer layer];
[_layer setContentsScale:[[UIScreen mainScreen] scale]];
[_layer setContents:(id)[UIImage imageNamed:@"american-flag.png"].CGImage];
[_layer setBounds:CGRectMake(0, 0, 60, 60)];
[_layer setContents:(__bridge id)[UIImage imageNamed:@"american-flag.png"].CGImage];
[_layer setBounds:CGRectMake(0.0, 0.0, 60.0, 60.0)];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
Expand Down
2 changes: 2 additions & 0 deletions CoreAnimationFunHouse/BTSCoreGraphics.h
Expand Up @@ -2,6 +2,8 @@
// Copyright (c) 2011 Brian Coyner. All rights reserved.
//

#import <CoreGraphics/CoreGraphics.h>
#import <stdio.h>
#import "BTSCoreGraphics.h"

static void BTSPrintCurrentCTM(CGContextRef context)
Expand Down
40 changes: 21 additions & 19 deletions CoreAnimationFunHouse/BTSCubicBezierPathView.m
Expand Up @@ -46,8 +46,6 @@ @interface BTSCubicBezierPathView() {

CGPathRef BTSPathCreateForCurrentControlPointPositions(CALayer *beginPointLayer, CALayer *endPointLayer, CALayer *beginPointControlPointLayer, CALayer *endPointControlPointLayer);

- (void)initLayers;

@end

@implementation BTSCubicBezierPathView
Expand Down Expand Up @@ -100,7 +98,7 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
// to pick up and move a control point layer.
CGRect hitTestRect = [layer convertRect:[layer bounds] toLayer:[layer superlayer]];

CGRect hitBounds = CGRectInset(hitTestRect, -20, -20);
CGRect hitBounds = CGRectInset(hitTestRect, -20.0, -20.0);
if (CGRectContainsPoint(hitBounds, touchLocationInView)) {
CFDictionarySetValue(_touchesToLayers, (__bridge CFTypeRef)touch, (__bridge CFTypeRef)layer);

Expand Down Expand Up @@ -132,7 +130,12 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
CGPoint locationInView = [currentTouch locationInView:self];

CGPoint offsetFromCenter = [(NSValue *)[layerToMove valueForKey:kBTSCubicBezierPathLocationOffset] CGPointValue];
CGPoint newPosition = CGPointMake(MIN(width, MAX(0, locationInView.x + offsetFromCenter.x)), MIN(height, MAX(0, locationInView.y + offsetFromCenter.y)));
CGFloat x = MAX(0, locationInView.x + offsetFromCenter.x);
x = MIN(width, x);

CGFloat y = MAX(0, locationInView.y + offsetFromCenter.y);
y = MIN(height, y);
CGPoint newPosition = CGPointMake(x, y);

[layerToMove setPosition:newPosition];
}
Expand Down Expand Up @@ -170,16 +173,16 @@ - (void)initLayers
CGFloat midY = CGRectGetMidY([self bounds]);

_beginPointLayer = [BTSEndPointLayer layer];
[_beginPointLayer setPosition:CGPointMake(midX, 40)];
[_beginPointLayer setPosition:CGPointMake(midX, 40.0)];

_endPointLayer = [BTSEndPointLayer layer];
[_endPointLayer setPosition:CGPointMake(midX, [self bounds].size.height - 40)];
[_endPointLayer setPosition:CGPointMake(midX, [self bounds].size.height - 40.0)];

_beginPointControlPointLayer = [BTSControlPointLayer layer];
[_beginPointControlPointLayer setPosition:CGPointMake(40, midY)];
[_beginPointControlPointLayer setPosition:CGPointMake(40.0, midY)];

_endPointControlPointLayer = [BTSControlPointLayer layer];
[_endPointControlPointLayer setPosition:CGPointMake([self bounds].size.width - 40, midY)];
[_endPointControlPointLayer setPosition:CGPointMake([self bounds].size.width - 40.0, midY)];

// create the initial path
CGPathRef path = BTSPathCreateForCurrentControlPointPositions(_beginPointLayer, _endPointLayer, _beginPointControlPointLayer, _endPointControlPointLayer);
Expand Down Expand Up @@ -208,7 +211,6 @@ CGPathRef BTSPathCreateForCurrentControlPointPositions(CALayer *beginPointLayer,
CGPathMoveToPoint(path, NULL, [beginPointLayer position].x, [beginPointLayer position].y);
CGPathAddCurveToPoint(path, NULL, [beginPointControlPointLayer position].x, [beginPointControlPointLayer position].y, [endPointControlPointLayer position].x, [endPointControlPointLayer position].y, [endPointLayer position].x, [endPointLayer position].y);
return path;

}
@end

Expand All @@ -222,7 +224,7 @@ - (id)init
{
self = [super init];
if (self) {
[self setBounds:CGRectMake(0, 0, 20, 20)];
[self setBounds:CGRectMake(0.0, 0.0, 20.0, 20.0)];
[self setContentsScale:[[UIScreen mainScreen] scale]];
[self setNeedsDisplay];
}
Expand All @@ -237,14 +239,14 @@ - (void)drawInContext:(CGContextRef)context

CGFloat centerX = CGRectGetMidX([self bounds]);
CGFloat centerY = CGRectGetMidY([self bounds]);
CGFloat radius = MIN(CGRectGetWidth([self bounds]) / 2, CGRectGetHeight([self bounds]) / 2) - 2;
CGFloat radius = MIN(CGRectGetWidth([self bounds]) / 2.0, CGRectGetHeight([self bounds]) / 2.0) - 2.0;

CGContextAddArc(context, centerX, centerY, radius, 0.0, M_PI * 2, 0);
CGContextAddArc(context, centerX, centerY, radius, 0.0, (CGFloat) (M_PI * 2.0), 0);
CGContextFillPath(context);

CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextAddArc(context, centerX, centerY, radius, 0.0, M_PI * 2, 0);
CGContextSetLineWidth(context, 2);
CGContextAddArc(context, centerX, centerY, radius, 0.0, (CGFloat) (M_PI * 2.0), 0);
CGContextSetLineWidth(context, 2.0);
CGContextStrokePath(context);
}

Expand All @@ -256,7 +258,7 @@ - (id)init
{
self = [super init];
if (self) {
[self setBounds:CGRectMake(0, 0, 30, 20)];
[self setBounds:CGRectMake(0.0, 0.0, 30.0, 20.0)];
[self setContentsScale:[[UIScreen mainScreen] scale]];
[self setNeedsDisplay];
}
Expand All @@ -271,14 +273,14 @@ - (void)drawInContext:(CGContextRef)context

CGFloat centerX = CGRectGetMidX([self bounds]);
CGFloat centerY = CGRectGetMidY([self bounds]);
CGFloat radius = MIN(CGRectGetWidth([self bounds]) / 2, CGRectGetHeight([self bounds]) / 2) - 2;
CGFloat radius = MIN(CGRectGetWidth([self bounds]) / 2.0, CGRectGetHeight([self bounds]) / 2.0) - 2.0;

CGContextAddArc(context, centerX, centerY, radius, 0.0, M_PI * 2, 0);
CGContextAddArc(context, centerX, centerY, radius, 0.0, (CGFloat) (M_PI * 2.0), 0);
CGContextFillPath(context);

CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextAddArc(context, centerX, centerY, radius, 0.0, M_PI * 2, 0);
CGContextSetLineWidth(context, 2);
CGContextAddArc(context, centerX, centerY, radius, 0.0, (CGFloat) (M_PI * 2.0), 0);
CGContextSetLineWidth(context, 2.0);
CGContextStrokePath(context);
}

Expand Down
54 changes: 44 additions & 10 deletions CoreAnimationFunHouse/BTSLissajousLayer.m
Expand Up @@ -8,16 +8,18 @@

#import "BTSLissajousLayer.h"

#import <QuartzCore/QuartzCore.h>

static NSString* const kBTSLissajouseLayerAmplitude = @"amplitude";
static NSString* const kBTSLissajouseLayerA = @"a";
static NSString* const kBTSLissajouseLayerB = @"b";
static NSString* const kBTSLissajouseLayerDelta = @"delta";

static const CGFloat TWO_PI = M_PI * 2.0f;
static const CGFloat TWO_PI = (CGFloat) (M_PI * 2.0f);

// NOTE: Sometimes the 'needsDisplayForKey:' (as described in 'BTSSineWaveLayer.m') can produce undesired 'flickering' effects.
// I have yet to see any undesired 'flickering' effects using the CADisplayLink approach.

@interface BTSLissajousLayer() {
CADisplayLink *_displayLink;
NSMutableArray *_currentAnimations;
}
@end
Expand All @@ -29,7 +31,7 @@ @implementation BTSLissajousLayer
@dynamic b;
@dynamic delta;

+ (NSSet *)keyPathsForCustomDisplayDrawing
+ (NSSet *)keyPathsForDynamicProperties
{
static NSSet *keys = nil;
if (keys == nil) {
Expand All @@ -38,11 +40,6 @@ + (NSSet *)keyPathsForCustomDisplayDrawing
return keys;
}

+ (BOOL)needsDisplayForKey:(NSString *)key
{
return [[self keyPathsForCustomDisplayDrawing] containsObject:key];
}

#pragma mark - Layer Drawing

- (id)init {
Expand Down Expand Up @@ -101,7 +98,7 @@ - (void)drawInContext:(CGContextRef)context
{
// Called when a property changes.

if ([[BTSLissajousLayer keyPathsForCustomDisplayDrawing] member:event]) {
if ([[BTSLissajousLayer keyPathsForDynamicProperties] member:event]) {

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
NSValue *valueForKey = [[self presentationLayer] valueForKey:event];
Expand All @@ -117,4 +114,41 @@ - (void)drawInContext:(CGContextRef)context
}
}

#pragma mark - Animation Delegate Callbacks

- (void)animationDidStart:(CAAnimation *)anim
{
if ([anim isKindOfClass:[CAPropertyAnimation class]]) {
NSSet *internalKeys = [BTSLissajousLayer keyPathsForDynamicProperties];
if ([internalKeys member:[(CAPropertyAnimation *)anim keyPath]]) {

[_currentAnimations addObject:anim];
if (_displayLink == nil) {
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animationTimerFired:)];
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
}
}
}

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
[_currentAnimations removeObject:animation];
if ([_currentAnimations count] == 0) {
[_displayLink invalidate];
_displayLink = nil;

// hmmm... the use of CADisplayLink seems to miss the final set of interpolated values... let's force a final paint.
// note... this was not necessary when using an explicit NSTimer (need to investigate more).
[self setNeedsDisplay];
}
}

#pragma mark - Timer Callback

- (void)animationTimerFired:(CADisplayLink *)displayLink
{
[self setNeedsDisplay];
}

@end

0 comments on commit 3442c07

Please sign in to comment.