<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cocoa Is My Girlfriend &#187; Core Animation</title>
	<atom:link href="http://www.cimgf.com/category/core-animation/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cimgf.com</link>
	<description>Taglines are for Windows programmers</description>
	<lastBuildDate>Thu, 15 Jul 2010 21:20:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Fun With UIButtons and Core Animation Layers</title>
		<link>http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/</link>
		<comments>http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 06:53:03 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPod Touch]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=861</guid>
		<description><![CDATA[Upon first glance, the UIButton class doesn&#8217;t seem to provide what you might expect in terms of customization. This often causes developers to resort to creating buttons in an image editor and then specifying that in the Background field in Interface Builder. This is a fine solution and will likely give you what you need, [...]]]></description>
			<content:encoded><![CDATA[<p>Upon first glance, the UIButton class doesn&#8217;t seem to provide what you might expect in terms of customization. This often causes developers to resort to creating buttons in an image editor and then specifying that in the Background field in Interface Builder. This is a fine solution and will likely give you what you need, but with Core Animation layers there is a simpler way to achieve the look you want without having to create an image. This post will demonstrate how.
<span id="more-861"></span></p>

<h2>Setting a Background Color</h2>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/01/solidcolorbuttons.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/01/solidcolorbuttons.png" alt="Solid Background Buttons" title="Solid Background Buttons" width="291" height="93" class="alignleft size-full wp-image-866" /></a></p>

<p>In Interface Builder, you can specify a background color for your button if you are using the &#8216;Custom&#8217; button setting, but when you run the application, the button will display as a block with no rounded corners. This is because custom buttons don&#8217;t really have any default attributes defined. It&#8217;s completely up to you to define them. Core Animation layers can help.</p>

<blockquote><strong>Note:</strong> Before I get into the source code, I want to remind you that you&#8217;ll need to add the QuartzCore framework to your project and #import &lt;QuartzCore/QuartzCore.h&gt; into one of your header files to have Core Animation layer support. I normally add this import statement to my precompiled header (.pch) file.</blockquote>

<p>What Interface Builder doesn&#8217;t give you, you can still take advantage of by writing a little bit of code. For example, if you want your custom button to have a red background color with rounded corners and a border, you need to define an outlet in your view controller where the button will be referenced and set the following attributes on the UIButton&#8217;s <em>layer</em>.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>button layer<span style="color: #002200;">&#93;</span> setCornerRadius<span style="color: #002200;">:</span>8.0f<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>button layer<span style="color: #002200;">&#93;</span> setMasksToBounds<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>button layer<span style="color: #002200;">&#93;</span> setBorderWidth<span style="color: #002200;">:</span>1.0f<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<p>With this code the layer gets a corner radius of 8.0 and the -setMasksToBounds: tells the button&#8217;s layer to mask any layer content that comes below it in the layer tree. This is necessary in order for the layer to mask off the rounded corners.</p>

<p>Finally, set the border width to 1.0 to display an outline around the button. The default color for this border is black. You can change it to anything you like using -setBorderColor: on the layer passing it a CGColorRef (e.g. [[UIColor greenColor] CGColor] would give you a green border).</p>

<blockquote><strong>iPhone Development Protip:</strong> Rounding corners is possible on any UIView based view. All UIViews have a root layer. You simply call  <strong>-setCornerRadius:</strong> and <strong>-setMasksToBounds:</strong> on the view&#8217;s layer and your corners will be rounded. It is <em>that</em> simple.</blockquote>

<p>You can set the background color in Interface Builder or in code&#8211;whichever you prefer. There are two ways to do this in code. One using the layer and one using the UIView call to -setBackgroundColor:.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Core Animation way</span>
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>button layer<span style="color: #002200;">&#93;</span> setBackgroundColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIColor redColor<span style="color: #002200;">&#93;</span> CGColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #11740a; font-style: italic;">// UIView way</span>
<span style="color: #002200;">&#91;</span>button setBackgroundColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor redColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<p>The main difference between the two is that the layer works with a CGColorRef while the UIView works with a UIColor. It&#8217;s a subtle difference, but one that you should know.</p>

<h2>Gradient Buttons Rule</h2>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/01/colorfulbuttonsapp1.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/01/colorfulbuttonsapp1-156x300.png" alt="Colorful Buttons App" title="Colorful Buttons App" width="156" height="300" class="alignleft size-medium wp-image-872" /></a></p>

<p>The demo app uses some ultra-bright gaudy looking color gradients just for effect. I suggest you don&#8217;t use something so loud and obnoxious. A more subtle difference between colors will look better. Of course this is subjective, so do what you like.</p>

<p>To achieve this gradient look, I use a <a href="http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CAGradientLayer_class/Reference/Reference.html">CAGradientLayer</a> and add it to the root of the button&#8217;s layer tree. In fact, for the demo application, I created a UIButton derived class that encapsulates the gradient layer creation and drawing. Here is its implementation:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;ColorfulButton.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> ColorfulButton
&nbsp;
<span style="color: #a61390;">@synthesize</span> _highColor;
<span style="color: #a61390;">@synthesize</span> _lowColor;
<span style="color: #a61390;">@synthesize</span> gradientLayer;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Initialize the gradient layer</span>
    gradientLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>CAGradientLayer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Set its bounds to be the same of its parent</span>
    <span style="color: #002200;">&#91;</span>gradientLayer setBounds<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self bounds<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Center the layer inside the parent layer</span>
    <span style="color: #002200;">&#91;</span>gradientLayer setPosition<span style="color: #002200;">:</span>
                CGPointMake<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self bounds<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">/</span><span style="color: #2400d9;">2</span>,
                       <span style="color: #002200;">&#91;</span>self bounds<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">/</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Insert the layer at position zero to make sure the </span>
    <span style="color: #11740a; font-style: italic;">// text of the button is not obscured</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self layer<span style="color: #002200;">&#93;</span> insertSublayer<span style="color: #002200;">:</span>gradientLayer atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Set the layer's corner radius</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self layer<span style="color: #002200;">&#93;</span> setCornerRadius<span style="color: #002200;">:</span>8.0f<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Turn on masking</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self layer<span style="color: #002200;">&#93;</span> setMasksToBounds<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Display a border around the button </span>
    <span style="color: #11740a; font-style: italic;">// with a 1.0 pixel width</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self layer<span style="color: #002200;">&#93;</span> setBorderWidth<span style="color: #002200;">:</span>1.0f<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>rect;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>_highColor <span style="color: #002200;">&amp;&amp;</span> _lowColor<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Set the colors for the gradient to the </span>
        <span style="color: #11740a; font-style: italic;">// two colors specified for high and low</span>
        <span style="color: #002200;">&#91;</span>gradientLayer setColors<span style="color: #002200;">:</span>
                     <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span>
                            <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>_highColor CGColor<span style="color: #002200;">&#93;</span>, 
                            <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>_lowColor CGColor<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #002200;">&#91;</span>super drawRect<span style="color: #002200;">:</span>rect<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setHighColor<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIColor<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>color;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Set the high color and repaint</span>
    <span style="color: #002200;">&#91;</span>self set_highColor<span style="color: #002200;">:</span>color<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self layer<span style="color: #002200;">&#93;</span> setNeedsDisplay<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setLowColor<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIColor<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>color;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Set the low color and repaint</span>
    <span style="color: #002200;">&#91;</span>self set_lowColor<span style="color: #002200;">:</span>color<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self layer<span style="color: #002200;">&#93;</span> setNeedsDisplay<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Release our gradient layer</span>
    <span style="color: #002200;">&#91;</span>gradientLayer release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>Now, when I&#8217;m creating a button in Interface Builder, I can make it of class <em>ColorfulButton</em> and then set an outlet for it in my view controller.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2010/01/colorfulbuttonclass.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2010/01/colorfulbuttonclass-300x184.png" alt="" title="Colorful Button Class Attribute" width="300" height="184" class="alignleft size-medium wp-image-881" /></a></p>

<p>If I don&#8217;t set colors for a gradient, it will just render the button using the background color I specify for it in Interface Builder. If, however, I want to take advantage of the gradient capability, I set the gradient colors in my view controller as shown in the following code snippet:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>button1 setHighColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor redColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>button1 setLowColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor orangeColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>button2 setHighColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor blueColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>button2 setLowColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor lightGrayColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>button3 setHighColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor yellowColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>button3 setLowColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor purpleColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>button4 setHighColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor cyanColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>button4 setLowColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>UIColor magentaColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>These are the first four buttons you see in the demo app screenshot above. The buttons are declared in the view controller header as show in the following snippet:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;UIKit/UIKit.h&gt;</span>
<span style="color: #6e371a;">#import &quot;ColorfulButton.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> ColorfulButtonsViewController <span style="color: #002200;">:</span> UIViewController <span style="color: #002200;">&#123;</span>
    IBOutlet ColorfulButton <span style="color: #002200;">*</span>button1;
    IBOutlet ColorfulButton <span style="color: #002200;">*</span>button2;
    IBOutlet ColorfulButton <span style="color: #002200;">*</span>button3;
    IBOutlet ColorfulButton <span style="color: #002200;">*</span>button4;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>The <strong>CAGradientLayer</strong> supports adding an array of colors and will automatically render them linearly with equal distribution. It will also allow you to specify the distribution pattern, however, to keep it simple here I just use two colors represented by the upper color called <em>highColor</em> and the lower color called <em>lowColor</em>. If you want to add more complex gradients, you could modify my <em>ColorfulButton</em> class to take an array of colors as well. I leave this as an exercise for the reader.</p>

<h2>Conclusion</h2>

<p>Next time you need to customize a button, consider using Core Animation layers first. You may be surprised at what all you can achieve without having to resort to creating images to use as the button background. I have included the source code for this blog post below. Let me know if you have any thoughts or questions about it in the comments section. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2010/01/ColorfulButtons.zip'>Colorful Buttons Demo Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Marching Ants With Core Animation</title>
		<link>http://www.cimgf.com/2009/10/20/marching-ants-with-core-animation/</link>
		<comments>http://www.cimgf.com/2009/10/20/marching-ants-with-core-animation/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 21:13:38 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=789</guid>
		<description><![CDATA[Our Core Animation book should be available by the end of the year. Go ahead and pre-order it now at Amazon if you would like ;-). When we started writing for Addison-Wesley back in September of 2008, I had no idea how long to expect it to take to finish a technical book as this [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cimgf.com/wp-content/uploads/2009/10/marchingants1.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2009/10/marchingants1.png" alt="Marching Ants" title="Marching Ants" class="alignleft size-full wp-image-796" width="137" align="left" /></a>Our Core Animation book should be available by the end of the year. Go ahead and <a href="http://www.amazon.com/Core-Animation-Simplified-Techniques-Development/dp/0321617754/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1255981650&#038;sr=8-2">pre-order it now at Amazon</a> if you would like ;-). When we started writing for Addison-Wesley back in September of 2008, I had no idea how long to expect it to take to finish a technical book as this was my first. One thing I discovered though, is that it is when you are about ready to go to production you start to realize all of the things that you probably should have added to the book, but didn&#8217;t think of in time. This blog post will cover one such item as a way to make up for not thinking of it in time. I may include this in a second edition if there is one, but consider this one a freebie.<span id="more-789"></span></p>

<p>One of the Core Animation layers available as of Snow Leopard and iPhone OS 3.0, CAShapeLayer provides some interesting attributes that are animatable. The CAShapeLayer enables you to create a layer that renders any arbitrary shape you specify using a path, a CGPathRef. It also enables you to specify a stroke pattern for the stroke that outlines the shape. A stroke is optional, but if you do specify one you may also determine the pattern for it. I do point this part out in the book in Chapter 10, by the way. You use the method, -setLineDashPattern which takes an NSArray of integers. These integers specify painted segments verses unpainted segments. What this means is that if you specify 10, 5 in your array, for example, you will see 10 units of painted segment and 5 units unpainted. Notice I use the term <em>units</em> as opposed to <em>pixels</em>. This is due to the fact that we are to start getting used to the idea of resolution independence. Pixels don&#8217;t matter in the same way any more.</p>

<p>The pattern example I used is very simple. You could easily specify something much more complex, say 10, 72, 55, 2, 146, etc. for example. This would mean 10 painted units, followed by 72 unpainted units, followed by 55 painted units, followed by 2 unpainted units, followed by 146 painted units&#8211;on and on. You get the picture.</p>

<p>Now for the part I didn&#8217;t mention in the book. You can animate this stroke pattern. If you&#8217;ve ever used any drawing program you realize that when a rectangular area of the image is in a seleted mode, a dashed pattern stroke outlines that area and the pattern will move like marching ants. To achieve this effect manually actually takes quite a bit of effort, but is quite trivial when done with Core Animation.</p>

<p>What makes it so is another little property of the CAShaperLayer called <strong>lineDashPhase</strong>. This property specifies the phase of the stroke pattern. The default is zero. Animate this property to see the marching ants effect. If you want the animation to loop perfectly, set the <strong>toValue</strong> in the animation to the sum of all of the values specified in the lineDashPattern array. The code to animate the lineDashPhase should look something like the following:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>toggleMarching<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>shapeLayer animationForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;linePhase&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#91;</span>shapeLayer removeAnimationForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;linePhase&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
        CABasicAnimation <span style="color: #002200;">*</span>dashAnimation;
        dashAnimation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CABasicAnimation 
                         animationWithKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;lineDashPhase&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span>dashAnimation setFromValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span>0.0f<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>dashAnimation setToValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span>15.0f<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>dashAnimation setDuration<span style="color: #002200;">:</span>0.75f<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>dashAnimation setRepeatCount<span style="color: #002200;">:</span><span style="color: #2400d9;">10000</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span>shapeLayer addAnimation<span style="color: #002200;">:</span>dashAnimation forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;linePhase&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>This is the code we would use to animate a stroke pattern of 10, 5. Notice the sum of those two is 15, which is what the call to setToValue takes in the sample code for the animation. This is important. If the phase doesn&#8217;t match the stroke pattern, the animation will jerk back to the starting position. We want the animation to be smooth and seamless.</p>

<p>We set up our CAShaperLayer using the following code:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>viewDidLoad <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super viewDidLoad<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create the shape layer</span>
    shapeLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CAShapeLayer layer<span style="color: #002200;">&#93;</span>;
    CGRect shapeRect <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span>0.0f, 0.0f, 200.0f, 100.0f<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setBounds<span style="color: #002200;">:</span>shapeRect<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setPosition<span style="color: #002200;">:</span>CGPointMake<span style="color: #002200;">&#40;</span>160.0f, 140.0f<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setFillColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIColor clearColor<span style="color: #002200;">&#93;</span> CGColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setStrokeColor<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIColor blackColor<span style="color: #002200;">&#93;</span> CGColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setLineWidth<span style="color: #002200;">:</span>1.0f<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setLineJoin<span style="color: #002200;">:</span>kCALineJoinRound<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setLineDashPattern<span style="color: #002200;">:</span>
     <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">10</span><span style="color: #002200;">&#93;</span>, 
      <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">5</span><span style="color: #002200;">&#93;</span>, 
      <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Setup the path</span>
    CGMutablePathRef path <span style="color: #002200;">=</span> CGPathCreateMutable<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    CGPathAddRect<span style="color: #002200;">&#40;</span>path, <span style="color: #a61390;">NULL</span>, shapeRect<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>shapeLayer setPath<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;
    CGPathRelease<span style="color: #002200;">&#40;</span>path<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Set the layer's contents</span>
    <span style="color: #002200;">&#91;</span>shapeLayer setContents<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIImage imageNamed<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;balloon.jpg&quot;</span><span style="color: #002200;">&#93;</span> CGImage<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self view<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>shapeLayer<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Set the fill color to clear color so we can see through the shape. Set the line width to 1.0. Set the line join to be rounded. Then create the lineDashPattern. Next we create a path that matches the rectangle of our layer as to outline it correctly.</p>

<p>Finally we set the contents of the shape layer to a CGImageRef of the image we load from the bundle called balloon.jpg.</p>

<p>Once we connect the button in Interface Builder to the action called -toggleMarching, we can start and stop the marching ants animation.</p>

<h2>Conclusion</h2>

<p>The marching ants effect has limited use, but this example code demonstrates once again how Core Animation really simplifies a lot of visual tasks that would have at one time taken a lot more code to achieve. If there is anything I&#8217;ve learned while researching and writing the book it&#8217;s that Core Animation should be the go-to technology for a vast majority of visualizations on OS X and the iPhone. I find many questions related to the visual aspects of programming for both platforms on Stack Overflow have a very elegant answer in Core Animation. Other solutions exist, but they are often much more cumbersome. Until next time.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2009/10/MarchingAnts.zip">Marching Ants Demo Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2009/10/20/marching-ants-with-core-animation/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Record Your Core Animation Animation</title>
		<link>http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/</link>
		<comments>http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 05:38:37 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[QTKit]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=437</guid>
		<description><![CDATA[Every once in a while I find a way to combine multiple technologies that, while they don&#8217;t produce anything terribly useful, are very interesting when combined. In this post I will be taking a look at combining Core Animation and QuickTime. As you may or may not be aware, you can draw in a graphics [...]]]></description>
			<content:encoded><![CDATA[<p>Every once in a while I find a way to combine multiple technologies that, while they don&#8217;t produce anything terribly useful, are very interesting when combined. In this post I will be taking a look at combining Core Animation and QuickTime. As you may or may not be aware, you can draw in a graphics context while your Core Animation animation is running and add each image created to a QTMovie object from QTKit. This enables you to create a QuickTime movie of your Core Animation animation. Here&#8217;s how.
<span id="more-437"></span></p>

<p>The basic process flow goes like this. Clicking the &#8216;Capture&#8217; button on the user interface calls an IBAction called <em>-saveAnimation</em>. It prompts the user to select an output file for the movie. When the user has selected the file, the animations are created and added to the layer. Next we create a timer that is going to call a function that will grab the current frame and place it into the QTMovie object using <em>-addImage</em> at a specified interval. We set our AppDelegate to also be the delegate for the animation group so that when the animation completes we get notified and can then write our QTMovie object data to disk.</p>

<h2>Use An Interesting Animation</h2>

<p>First you are going to need an animation that is worth recording. Of course any old animation will do, but we&#8217;ll keep it interesting by adding multiple animations to a single layer. I have created four different keyframe animations that we will add to an animation group. The keypaths are &#8220;backgroundColor&#8221;, &#8220;borderWidth&#8221;, &#8220;position&#8221;, and &#8220;bounds&#8221;. Check the sample code to see how these animations are constructed.</p>

<p>We set the duration for all of the animations to five seconds. We also need to make sure that we set the duration for the group itself, otherwise it will override the five second duration we set for the animations themselves and run in the default 0.25 seconds. The code below shows how the animations are added to the layer.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>loadAnimations;
<span style="color: #002200;">&#123;</span>
  CAAnimationGroup <span style="color: #002200;">*</span>group <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CAAnimationGroup animation<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>group setAnimations<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObjects<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self backgroundColorAnimation<span style="color: #002200;">&#93;</span>,
                          <span style="color: #002200;">&#91;</span>self borderWidthAnimation<span style="color: #002200;">&#93;</span>,
                          <span style="color: #002200;">&#91;</span>self positionAnimation<span style="color: #002200;">&#93;</span>,
                          <span style="color: #002200;">&#91;</span>self boundsAnimation<span style="color: #002200;">&#93;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>group setValue<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mainGroup&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>group setDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">5.0</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>group setAutoreverses<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>group setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>layer addAnimation<span style="color: #002200;">:</span>group forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;group&quot;</span><span style="color: #002200;">&#93;</span>;  
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice that we have used KVC here to set a name for the animation group. We will use this as a tag later to make sure the animation that triggers our <em>-animationDidStop:finished</em> animation delegate is the correct one. More on that later.</p>

<h2>Get Our Movie Ready</h2>

<p>Prior to loading the animations, we prompt the user to select a file to write the movie file to. After loading the animations, we start our timer.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>saveAnimation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSSavePanel</span> <span style="color: #002200;">*</span>savePanel;
&nbsp;
  savePanel <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSSavePanel</span> savePanel<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>savePanel setExtensionHidden<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>savePanel setCanSelectHiddenExtension<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>savePanel setTreatsFilePackagesAsDirectories<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>savePanel runModal<span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> NSOKButton <span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>
    movie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>QTMovie alloc<span style="color: #002200;">&#93;</span> initToWritableFile<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>savePanel filename<span style="color: #002200;">&#93;</span> error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;    
  <span style="color: #002200;">&#125;</span>
&nbsp;
  <span style="color: #002200;">&#91;</span>self loadAnimations<span style="color: #002200;">&#93;</span>;
&nbsp;
  timer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSTimer</span> scheduledTimerWithTimeInterval<span style="color: #002200;">:</span><span style="color: #2400d9;">1.0</span><span style="color: #002200;">/</span><span style="color: #002200;">&#40;</span>NSTimeInterval<span style="color: #002200;">&#41;</span><span style="color: #2400d9;">10.0</span>
                                           target<span style="color: #002200;">:</span>self
                                         selector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>updateTime<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                         userInfo<span style="color: #002200;">:</span><span style="color: #a61390;">NULL</span>
                                          repeats<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;    
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Our <em>-updateTime</em> selector will get called every 1/10th of a second and will grab the current frame to save it to the QTMoive object. Here is the <em>-updateTime</em> code.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>updateTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSTimer</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>theTimer;
<span style="color: #002200;">&#123;</span>
  <span style="color: #400080;">NSBitmapImageRep</span> <span style="color: #002200;">*</span>image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getCurrentFrame<span style="color: #002200;">&#93;</span>;
&nbsp;
  QTTime <span style="color: #a61390;">time</span> <span style="color: #002200;">=</span> QTMakeTime<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1</span>, <span style="color: #2400d9;">10</span><span style="color: #002200;">&#41;</span>;
  <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>attrs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;png &quot;</span> forKey<span style="color: #002200;">:</span>QTAddImageCodecType<span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSImage</span> <span style="color: #002200;">*</span>img <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSImage</span> alloc<span style="color: #002200;">&#93;</span> initWithData<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>image TIFFRepresentation<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>movie addImage<span style="color: #002200;">:</span>img forDuration<span style="color: #002200;">:</span><span style="color: #a61390;">time</span> withAttributes<span style="color: #002200;">:</span>attrs<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>image release<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Obtaining the Current Frame</h2>

<p>The code to obtain the current frame is somewhat lengthy, but the concepts are pretty simple. We need to create a graphics context that we can draw into and then draw into it using the presentationLayer of the contenView&#8217;s root layer. If you&#8217;re not familiar, the presentationLayer provides the current state of the animated fields while &#8220;in-flight&#8221;.</p>

<p>Core Animation doesn&#8217;t provide any callbacks for when a frame is ready to be displayed which is why we are using a timer. This means that we may be capturing more frames than we need to, so getting the right frame rate takes a bit of trial and error, which I have to confess I wasn&#8217;t able to get nailed down completely. I&#8217;m still working on it and will update here when I get that part figured out. Meanwhile, here is the code for <em>-getCurrentFrame</em></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSBitmapImageRep</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>getCurrentFrame;
<span style="color: #002200;">&#123;</span>
  CGContextRef    context <span style="color: #002200;">=</span> <span style="color: #a61390;">NULL</span>;
  CGColorSpaceRef colorSpace;
  <span style="color: #a61390;">int</span> bitmapByteCount;
  <span style="color: #a61390;">int</span> bitmapBytesPerRow;
&nbsp;
  <span style="color: #a61390;">int</span> pixelsHigh <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> bounds<span style="color: #002200;">&#93;</span>.size.height;
  <span style="color: #a61390;">int</span> pixelsWide <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> bounds<span style="color: #002200;">&#93;</span>.size.width;
&nbsp;
  bitmapBytesPerRow   <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>pixelsWide <span style="color: #002200;">*</span> <span style="color: #2400d9;">4</span><span style="color: #002200;">&#41;</span>;
  bitmapByteCount     <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>bitmapBytesPerRow <span style="color: #002200;">*</span> pixelsHigh<span style="color: #002200;">&#41;</span>;
&nbsp;
  colorSpace <span style="color: #002200;">=</span> CGColorSpaceCreateWithName<span style="color: #002200;">&#40;</span>kCGColorSpaceGenericRGB<span style="color: #002200;">&#41;</span>;
&nbsp;
  context <span style="color: #002200;">=</span> CGBitmapContextCreate <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>,
                                   pixelsWide,
                                   pixelsHigh,
                                   <span style="color: #2400d9;">8</span>,
                                   bitmapBytesPerRow,
                                   colorSpace,
                                   kCGImageAlphaPremultipliedLast<span style="color: #002200;">&#41;</span>;
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>context<span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Failed to create context.&quot;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
  <span style="color: #002200;">&#125;</span>
&nbsp;
  CGColorSpaceRelease<span style="color: #002200;">&#40;</span> colorSpace <span style="color: #002200;">&#41;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> presentationLayer<span style="color: #002200;">&#93;</span> renderInContext<span style="color: #002200;">:</span>context<span style="color: #002200;">&#93;</span>;
&nbsp;
  CGImageRef img <span style="color: #002200;">=</span> CGBitmapContextCreateImage<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
  <span style="color: #400080;">NSBitmapImageRep</span> <span style="color: #002200;">*</span>bitmap <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBitmapImageRep</span> alloc<span style="color: #002200;">&#93;</span> initWithCGImage<span style="color: #002200;">:</span>img<span style="color: #002200;">&#93;</span>;
  CFRelease<span style="color: #002200;">&#40;</span>img<span style="color: #002200;">&#41;</span>;
&nbsp;
  <span style="color: #a61390;">return</span> bitmap;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice that we are calling <em>-renderInContext</em> on the presentationLayer of the window&#8217;s contentView&#8217;s root layer. If we were only to render our animated layer, we wouldn&#8217;t be able to see the animation as it will only render the containing rectangle of the animating layer.</p>

<h2>Finishing Up</h2>

<p>Finally we need to write the movie data out to disk. The QTMovie object provides a single call to do so, but we need a way to know when the animation has finished so we can make this call. When we created our animation group, we set its delegate to our AppDelegate which will cause the delegate method <em>-animationDidStop:finished</em> to get called. Remember that setting the delegate for each of the individual animations gets ignored when you are using an animation group. We implement the <em>-animationDidStop:finished</em> delegate as shown below.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>animationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CAAnimation <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>theAnimation finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>flag;
<span style="color: #002200;">&#123;</span>
  NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Animation stopped: %@&quot;</span>, theAnimation<span style="color: #002200;">&#41;</span>;
&nbsp;
  <span style="color: #a61390;">id</span> name <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>theAnimation valueForKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;name&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> name <span style="color: #002200;">&#41;</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>name isEqualToString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;mainGroup&quot;</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>movie updateMovieFile<span style="color: #002200;">&#93;</span>;
      <span style="color: #002200;">&#91;</span>timer invalidate<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The first thing we do is check the animation tag we set when creating the animation group. This really isn&#8217;t necessary in this code example since there is only one animation that is going to use it, but this code shows you how to differentiate if you were to use multiple animations or groups and wanted to know when each of them finished animating.</p>

<p>The call to <em>-updateMovieFile</em> writes the data to disk and we now have a QuickTime movie that will play our animation. Open the resulting file in QuickTime or just invoke QuickLook to see the result.</p>

<h2>Conclusion</h2>

<p>Maybe you can think of a use for this kind of thing. I haven&#8217;t yet&#8211;other than for writing a blog post of course. Shoot me your thoughts and comments in the comments section. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2009/02/caanimationcapture.zip'>CA Animation Capture Demo Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Interrupting Animation Progress</title>
		<link>http://www.cimgf.com/2008/11/05/core-animation-tutorial-interrupting-animation-progress/</link>
		<comments>http://www.cimgf.com/2008/11/05/core-animation-tutorial-interrupting-animation-progress/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 00:10:46 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=317</guid>
		<description><![CDATA[Starting and stopping animations in Core Animation is as simple as adding and removing your animation from the layer upon which is being run. In this post I am going to talk about how to interrupt animation progress and how to determine whether an animation completed its full run or was interrupted. This is accomplished [...]]]></description>
			<content:encoded><![CDATA[<p>Starting and stopping animations in Core Animation is as simple as adding and removing your animation from the layer upon which is being run. In this post I am going to talk about how to interrupt animation progress and how to determine whether an animation completed its full run or was interrupted. This is accomplished with the animation delegate <em>-animationDidStop:finished</em>.
<span id="more-317"></span></p>

<h2>Differentiating Keypath From Key</h2>

<p>Each core animation layer contains a dictionary that enables you to add and remove animations based on a key that you define. I created a layer-backed view that receives mouse clicks and animates the position of the layer toward that mouse click.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>mouseDown<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSEvent</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event;
<span style="color: #002200;">&#123;</span>
    CABasicAnimation <span style="color: #002200;">*</span>animation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CABasicAnimation animationWithKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;position&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>animation setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>animation setFromValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSValue</span> valueWithPoint<span style="color: #002200;">:</span>previousValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    previousValue <span style="color: #002200;">=</span> NSMakePoint<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>event locationInWindow<span style="color: #002200;">&#93;</span>.x, <span style="color: #002200;">&#91;</span>event locationInWindow<span style="color: #002200;">&#93;</span>.y<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#91;</span>animation setToValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSValue</span> valueWithPoint<span style="color: #002200;">:</span>previousValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>animation setDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">2.0</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>objectLayer addAnimation<span style="color: #002200;">:</span>animation forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;follow&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice that when I create the animation, I am creating it with a keypath&#8211;in this case <em>position</em>. The keypath is different from the key by which we store the animation in the animations dictionary contained by the layer. In the sample code I add the animation to the dictionary using a key called &#8220;follow&#8221;. This could be any string that is meaningful to keep track of the animation in question. Consider it a tag.</p>

<p>I only make this distinction because I&#8217;ve seen some confusion about the difference between the two. To summarize, the keypath <em>specifies which layer property you want to animate</em> while the key is <em>the key by which you will store, recall, and delete an animation from the animation dictionary contained by the layer</em>.</p>

<h2>Adding The Animation, Again</h2>

<p>In the code above, you&#8217;ll also notice that we are adding the animation to the layer for the same key each time we receive a <em>-mouseDown</em>. If we are setting a new object in the dictionary each time, then how are we able to keep track of whether or not the animation finished?</p>

<p>By setting a delegate for the animation, we can be notified when animation has been removed from the animations dictionary. We implement the <em>-animationDidStop:finished</em> delegate.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>animationDidStop<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CAAnimation <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>theAnimation finished<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>flag
<span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Animation interrupted: %@&quot;</span>, <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>flag<span style="color: #002200;">&#41;</span>?<span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Yes&quot;</span> <span style="color: #002200;">:</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;No&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>There are several things going on here. When we call <em>[objectLayer addAnimation:animation forKey:@"follow"];</em> in our <em>-mouseDown</em> code, the animation that was there previously, if there was one, is replaced by the new one. If the user clicked on the screen before the animation completed, the animation is removed and the delegate <em>-animationDidStop</em> gets called. If instead of clicking the mouse again before the current animation is finished, you just let it finish, the animation is also removed from the dictionary because this is the default behavior for an animation. If you don&#8217;t specify <em>[animation setRemovedOnCompletion:NO]</em> explicitly, the animation will be removed.</p>

<h2>Changing Direction While In Flight</h2>

<p>When the view receives a click the basic animation is re-created and added to the layer for the key &#8220;follow&#8221; again. The fromValue field needs set again, but if you click another spot on the view before the animation finishes, what value do you set it to? If you set it to the previous value, it will simply animate from the previous location which won&#8217;t look right. You want it to change direction rather than starting from the previous start location.</p>

<p>If instead of using a basic animation in our example code we had simply opted to use the animator proxy, calling <em>-setPosition</em> on the layer would do this for us. The problem is that we want to be able to demonstrate the <em>-animationDidStop</em> delegate which we can&#8217;t do with the animator proxy. So how do we provide this functionality of changing direction in flight?</p>

<p>Look no further than the <em>presentationLayer</em> which is accessible through our layer object. We can obtain the last location of our &#8220;position&#8221; parameter by first getting the presentationLayer and getting the position from it instead. We&#8217;ve modified our <em>-mouseDown</em> event to reflect this change.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>mouseDown<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSEvent</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>event;
<span style="color: #002200;">&#123;</span>
  CABasicAnimation <span style="color: #002200;">*</span>animation <span style="color: #002200;">=</span> 
          <span style="color: #002200;">&#91;</span>CABasicAnimation animationWithKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;position&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>animation setDelegate<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #11740a; font-style: italic;">// Get the presentationLayer</span>
  CALayer <span style="color: #002200;">*</span>p <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>CALayer<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>objectLayer presentationLayer<span style="color: #002200;">&#93;</span>;
  CGPoint position <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>p position<span style="color: #002200;">&#93;</span>;
  <span style="color: #400080;">NSValue</span> <span style="color: #002200;">*</span>prevVal <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSValue</span> valueWithPoint<span style="color: #002200;">:</span>
                      NSPointFromCGPoint<span style="color: #002200;">&#40;</span>position<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>animation setFromValue<span style="color: #002200;">:</span>prevVal<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>animation setToValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSValue</span> valueWithPoint<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>event locationInWindow<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>animation setDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">2.0</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>animation setRemovedOnCompletion<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>objectLayer addAnimation<span style="color: #002200;">:</span>animation forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;follow&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Now, when we click in our view, the animation changes directions from its current location in the animation. The <em>presentationLayer</em> provides you with current values of whatever field you are currently animating. If a value is not being animated, you will get the same value as what is in the main layer.</p>

<h2>Conclusion</h2>

<p>It&#8217;s very handy to have a way to know when an animation is completed. You simply set your app delegate to be your animation&#8217;s delegate and when the animation completes, <em>-animationDidStop:finished</em> gets called conveying through the <em>finished</em> flag whether the animation was interrupted or not. To get our in flight values when the animation hasn&#8217;t completed, we simply look at the <em>presentationLayer</em>. These features of Core Animation are very powerful. Given the choice I would like to see the <em>presentationLayer</em> values become KVO compliant as this would let you monitor changes in real time, but being able to read the current value at any given time is a great capability in its own right. It&#8217;s very cool technology. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/11/followme.zip'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="64"/><br />Follow Me Demo Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/11/05/core-animation-tutorial-interrupting-animation-progress/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Slider Based Layer Rotation</title>
		<link>http://www.cimgf.com/2008/10/25/core-animation-tutorial-slider-based-layer-rotation/</link>
		<comments>http://www.cimgf.com/2008/10/25/core-animation-tutorial-slider-based-layer-rotation/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 00:15:50 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=322</guid>
		<description><![CDATA[It is often helpful to create a custom control for you application that will display a value as a level like a gas gauge shows how full your tank is. In this post I will demonstrate how to create a three layer tree that will show the current rotation of a circular layer as the [...]]]></description>
			<content:encoded><![CDATA[<p>It is often helpful to create a custom control for you application that will display a value as a level like a gas gauge shows how full your tank is. In this post I will demonstrate how to create a three layer tree that will show the current rotation of a circular layer as the value from a slider (NSSlider) is updated in real time. The layers include the root layer, the rotation layer, and a text layer that will display the current rotation in degrees.
<span id="more-322"></span></p>

<h2>The Slider Value</h2>

<p>We connect a slider to an IBAction in xcode that will get called continuously as we have checked the checkbox called &#8216;Continuous&#8217; in Interface Builder. We can read the slider value and apply it to our animation that we use to rotate the layer. In interface builder, we have specified a minimum value of -180, a maximum value of 180 and a current value (our starting value) of 0 on the slide control. When the slider is moved, the rotation updates as does the value of our text layer.</p>

<p>While it is coincidental that the demo application sort of looks like a pumpkin, it seems appropriate considering the time of year.</p>

<div id="attachment_325" class="wp-caption alignleft" style="width: 283px"><a href="http://www.cimgf.com/wp-content/uploads/2008/10/layerrotate.png" rel="lightbox"><img src="http://www.cimgf.com/wp-content/uploads/2008/10/layerrotate-273x300.png" alt="Layer Rotate" title="Layer Rotate" width="273" height="300" class="size-medium wp-image-325" /></a><p class="wp-caption-text">Layer Rotate</p></div>

<h2>Rotation Animation</h2>

<p>Rotating a layer is very simple. You just need to create an animation with &#8220;transform.rotation.z&#8221; as your keypath and then you can set from and to values that the animation will rotate between. We simply keep track of the last value we rotated (<em>previousValue</em> in the code) to and use this as our from value in the next change to the slider.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CAAnimation<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>rotateAnimation;
<span style="color: #002200;">&#123;</span>
  CABasicAnimation <span style="color: #002200;">*</span> animation;
  animation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CABasicAnimation 
               animationWithKeyPath<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;transform.rotation.z&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>animation setFromValue<span style="color: #002200;">:</span>DegreesToNumber<span style="color: #002200;">&#40;</span>previousValue<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>animation setToValue<span style="color: #002200;">:</span>DegreesToNumber<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>slider floatValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>animation setRemovedOnCompletion<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>animation setFillMode<span style="color: #002200;">:</span>kCAFillModeForwards<span style="color: #002200;">&#93;</span>;
&nbsp;
  previousValue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>slider floatValue<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #a61390;">return</span> animation;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>When our -sliderChange function gets called when the user moves the slider, we add the animation to the layer again using the key &#8220;rotate&#8221;. This is done first in our -awakeFromNib call and then in the -sliderChange call.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>sliderChange<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span>degreesTextLayer setString<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%f&quot;</span>, <span style="color: #002200;">&#91;</span>slider floatValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>needleLayer addAnimation<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self rotateAnimation<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;rotate&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>needleLayer setNeedsDisplay<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>You will notice that we call -setNeedsDisplay on the layer. This is necessary as we have implemented the delegate method -drawLayer:inContext. We use this method to draw the vertical and horizontal black lines that intersect in the center of the circle layer.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawLayer<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CALayer <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>layer inContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGContextRef<span style="color: #002200;">&#41;</span>context;
<span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> layer <span style="color: #002200;">==</span> needleLayer <span style="color: #002200;">&#41;</span>
  <span style="color: #002200;">&#123;</span>
      CGMutablePathRef path <span style="color: #002200;">=</span> CGPathCreateMutable<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
      CGPathMoveToPoint<span style="color: #002200;">&#40;</span>path,<span style="color: #a61390;">NULL</span>, <span style="color: #002200;">&#91;</span>view bounds<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">/</span><span style="color: #2400d9;">2.0</span>, <span style="color: #2400d9;">0.0</span><span style="color: #002200;">&#41;</span>;
      CGPathAddLineToPoint<span style="color: #002200;">&#40;</span>path, <span style="color: #a61390;">NULL</span>, <span style="color: #002200;">&#91;</span>view bounds<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">/</span><span style="color: #2400d9;">2.0</span>, <span style="color: #002200;">&#91;</span>view bounds<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">&#41;</span>;
&nbsp;
      CGPathMoveToPoint<span style="color: #002200;">&#40;</span>path,<span style="color: #a61390;">NULL</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #002200;">&#91;</span>view bounds<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">/</span><span style="color: #2400d9;">2.0</span><span style="color: #002200;">&#41;</span>;
      CGPathAddLineToPoint<span style="color: #002200;">&#40;</span>path, <span style="color: #a61390;">NULL</span>, <span style="color: #002200;">&#91;</span>view bounds<span style="color: #002200;">&#93;</span>.size.width, <span style="color: #002200;">&#91;</span>view bounds<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">/</span><span style="color: #2400d9;">2.0</span><span style="color: #002200;">&#41;</span>;
&nbsp;
      CGColorRef black <span style="color: #002200;">=</span>
              CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#41;</span>;
      CGContextSetStrokeColorWithColor<span style="color: #002200;">&#40;</span>context, black<span style="color: #002200;">&#41;</span>;
      CFRelease<span style="color: #002200;">&#40;</span>black<span style="color: #002200;">&#41;</span>;
&nbsp;
      CGContextBeginPath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
      CGContextAddPath<span style="color: #002200;">&#40;</span>context, path<span style="color: #002200;">&#41;</span>;
&nbsp;
      CGContextSetLineWidth<span style="color: #002200;">&#40;</span>context, <span style="color: #2400d9;">3.0</span><span style="color: #002200;">&#41;</span>;
&nbsp;
      CGContextStrokePath<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;
&nbsp;
      CFRelease<span style="color: #002200;">&#40;</span>path<span style="color: #002200;">&#41;</span>;
&nbsp;
  <span style="color: #002200;">&#125;</span>  
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Retaining The Rotation Position</h2>

<p>There are two parameters of an animation that must be set otherwise the layer transform will just revert back to the original rotation. These two lines of code in our animation creation code ensure that what you see remains <em>sticky</em> when the value is changed.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span>animation setRemovedOnCompletion<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>animation setFillMode<span style="color: #002200;">:</span>kCAFillModeForwards<span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>Now, when the slider moves, the vertical and horizontal lines will stay in the correct rotation position. If you comment those two lines of code out in the demo project, you will see that while the rotation layer animates, it jumps right back to its original rotation as soon as the animation completes.</p>

<h2>Conclusion</h2>

<p>You will likely find many uses for this type of control. You could of course control the rotation based upon some other value or control other than a slider, but this code demonstrates how simple it is to rotate a layer based upon user input. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/10/layerrotate.zip'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="64"/><br />Layer Rotate Demo Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/10/25/core-animation-tutorial-slider-based-layer-rotation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Core Animation And Quartz Composer (QCCompositionLayer)</title>
		<link>http://www.cimgf.com/2008/09/24/core-animation-tutorial-core-animation-and-quartz-composer-qccompositionlayer/</link>
		<comments>http://www.cimgf.com/2008/09/24/core-animation-tutorial-core-animation-and-quartz-composer-qccompositionlayer/#comments</comments>
		<pubDate>Wed, 24 Sep 2008 16:18:16 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=289</guid>
		<description><![CDATA[Last night at NSCoder night, Fraser Hess was asking question about being able to draw in a Quartz Composer View (QCView) about which none of the rest of us had any knowledge or experience. As I&#8217;ve been doing a lot with Core Animation lately, I asked him if it was possible to just make the [...]]]></description>
			<content:encoded><![CDATA[<p>Last night at NSCoder night, Fraser Hess was asking question about being able to draw in a Quartz Composer View (QCView) about which none of the rest of us had any knowledge or experience. As I&#8217;ve been doing a lot with Core Animation lately, I asked him if it was possible to just make the view layer backed and start adding layers to it. Fraser hasn&#8217;t worked with Core Animation much yet, so he was unsure. The other three of us set to looking at docs and making demo apps. The race was on&#8230; Oh. It&#8217;s not a race? Sorry about that. I thought we were practicing for Iron Coder&#8230;
<span id="more-289"></span>
My first attempt to get a QCView working succeeded. I was able to display a Quartz Composition in a window, but then I decided to try to make the QCView layer-backed like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> setWantsLayer<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>qcView setWantsLayer<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
CATextLayer <span style="color: #002200;">*</span>text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CATextLayer layer<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>text setString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;hello World&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>text setFrame<span style="color: #002200;">:</span>NSRectToCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>qcView frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>qcView layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>text<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<p>This code would allow the text layer to show up, however, the Quartz Composition was gone and all I got was a gray window with the &#8220;hello World&#8221; text on it.</p>

<h2>Two Heads Better Than One</h2>

<p>This is what I love about NSCoder Night. You get some Cocoa geeks together and the collective wisdom starts this synergy where we can bounce things off each other and a solution emerges.</p>

<p>Chad, in the mean time, had been searching the web for some examples and at about the time I started to wonder if there was a Core Animation specific layer for Quartz Compositions, he said, &#8220;QCCompositionLayer&#8221;. Marcus and I were both at that point thinking, &#8220;ah, I should have thought of that since there are Core Animation layers to do everything else media related.&#8221;</p>

<p>I then went to town slinging some code and here is what I came up with:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib;
<span style="color: #002200;">&#123;</span>
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> setWantsLayer<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  QCCompositionLayer <span style="color: #002200;">*</span>layer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>QCCompositionLayer alloc<span style="color: #002200;">&#93;</span> 
            initWithFile<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/Developer/Examples/Quartz Composer/Plugins/OpticalFlow/Teapotii.qtz&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span>layer setFrame<span style="color: #002200;">:</span>NSRectToCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
  CATextLayer <span style="color: #002200;">*</span>text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CATextLayer layer<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>text setString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;hello World&quot;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>text setFrame<span style="color: #002200;">:</span>NSRectToCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#91;</span>ayer addSublayer<span style="color: #002200;">:</span>text<span style="color: #002200;">&#93;</span>;
&nbsp;
  <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>layer<span style="color: #002200;">&#93;</span>;    
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>I got rid of the QCView altogether and just added the Quartz Composer layer to the sublayers of the window&#8217;s content view. The Quartz Composition in a QCCompositionLayer begins to play automatically, so really this code is all there is to it. And notice that the text overlay works as well. You could really add anything you wanted in a Core Animation layer at this point.</p>

<h2>Your Own Composition</h2>

<p>If you&#8217;re anything like me this will whet your appetite for playing with some very cool technology. I decided to create my own Quartz Composition and include that in the demo project. The demo composition takes the vide input of your iSight camera and applies the image to each side of a cube. It then rotates the cube. Creating the composition was pretty easy with a cursory reading of Apple&#8217;s <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/QuartzComposerUserGuide/qc_intro/chapter_1_section_1.html">Quartz Composer User Guide</a>. It&#8217;s quite helpful.</p>

<p>You can take a look at the Quartz Composition in Quartz Composer. The <a href='http://www.cimgf.com/wp-content/uploads/2008/09/caquartzcomposition.zip'>demo application</a> has two .qtz files in it. You can just double click either of those from the Finder to see what I did. The one I&#8217;m using in the demo app is the one called &#8220;VideoCub.qtz&#8221;. You can switch it in the code to see the other one as well, which is a quad of four iSight inputs.</p>

<div id="attachment_294" class="wp-caption alignleft" style="width: 160px"><a href="http://www.cimgf.com/wp-content/uploads/2008/09/vidcubeeditor.jpg" rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/09/vidcubeeditor-150x150.jpg" alt="VideoCube QC Editor" title="VideoCube QC Editor" width="150" height="150" class="size-thumbnail wp-image-294" /></a><p class="wp-caption-text">VideoCube QC Editor</p></div>

<div id="attachment_297" class="wp-caption alignleft" style="width: 310px"><a href="http://www.cimgf.com/wp-content/uploads/2008/09/qclayer.jpg" rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/09/qclayer-300x237.jpg" alt="Quartz Composer Layer" title="Quartz Composer Layer" width="300" height="237" class="size-medium wp-image-297" /></a><p class="wp-caption-text">Quartz Composer Layer</p></div>

<p>You can see I added a CATextLayer to the QCCompositionLayer which displays the words, &#8220;hello World&#8221;. I also applied a Gaussian blur filter to the whole thing so you can see how easy it is to add filters as well. Here is <em>all</em> of the code needed to make this work.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib;
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> setWantsLayer<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>path <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBundle</span> mainBundle<span style="color: #002200;">&#93;</span> 
                      pathForResource<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;VideoCube&quot;</span> 
                      ofType<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;qtz&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    QCCompositionLayer <span style="color: #002200;">*</span>layer <span style="color: #002200;">=</span> 
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>QCCompositionLayer alloc<span style="color: #002200;">&#93;</span> initWithFile<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>layer setFrame<span style="color: #002200;">:</span>NSRectToCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    CATextLayer <span style="color: #002200;">*</span>text <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CATextLayer layer<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>text setString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;hello World&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>text setFrame<span style="color: #002200;">:</span>NSRectToCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>layer addSublayer<span style="color: #002200;">:</span>text<span style="color: #002200;">&#93;</span>;
&nbsp;
    CIFilter <span style="color: #002200;">*</span>blurFilter <span style="color: #002200;">=</span> 
    <span style="color: #002200;">&#91;</span>CIFilter filterWithName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;CIGaussianBlur&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>blurFilter setDefaults<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>blurFilter setValue<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #2400d9;">2.0</span><span style="color: #002200;">&#93;</span> 
                  forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;inputRadius&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>blurFilter setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;blur&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>layer setFilters<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSArray</span> arrayWithObject<span style="color: #002200;">:</span>blurFilter<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>layer<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>What&#8217;s even more exciting to me is that if you know a bit of OpenGL, you can do all kinds of other manipulations of the image since QCCompositionLayer inherits from CAOpenGLLayer. Take a close look at -drawInCGLContext in the CAOpenGLLayer API docs. There is a ton of great potential there.</p>

<h2>Conclusion</h2>

<p>The conclusion is that Quartz Compositions are very cool and they are now even cooler since you can work with them in Core Animation. Take a look a the Quartz Composer guide and start building your own compositions that you can easily incorporate into your Core Animation based applications. Until next time.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/09/caquartzcomposition.zip'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="xcode.png" border="0" width="64"/><br />Quartz Composition Layer Demo Project</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/09/24/core-animation-tutorial-core-animation-and-quartz-composer-qccompositionlayer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Rendering QuickTime Movies In A CAOpenGLLayer</title>
		<link>http://www.cimgf.com/2008/09/10/core-animation-tutorial-rendering-quicktime-movies-in-a-caopengllayer/</link>
		<comments>http://www.cimgf.com/2008/09/10/core-animation-tutorial-rendering-quicktime-movies-in-a-caopengllayer/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 15:20:38 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Core Video]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[QTKit]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=219</guid>
		<description><![CDATA[I&#8217;ve been experimenting a great deal lately with OpenGL and QuickTime trying to see how the two technologies work together. It&#8217;s been a bit challenging, but fortunately Apple provides two really great resources&#8211;number one, sample code. I&#8217;ve been able to learn a lot just from the samples they provide in the development tools examples as [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been experimenting a great deal lately with OpenGL and QuickTime trying to see how the two technologies work together. It&#8217;s been a bit challenging, but fortunately Apple provides two really great resources&#8211;number one, sample code. I&#8217;ve been able to learn a lot just from the samples they provide in the development tools examples as well as online. And second, the cocoa-dev and quicktime-api lists are great. Lot&#8217;s of brilliant people there who are willing to share their knowledge. It&#8217;s very helpful, prohibition to discuss the iPhone SDK notwithstanding.</p>

<p>Getting two technologies to work together can be a challenge especially when the bridges between the two are not necessarily clearly laid out in documentation. As I pointed out Apple provides some excellent sample code to help you along, but there is no hand-holding approach to any of it. I actually appreciate that having come from the Windows world as it seems that there all you get sometimes is hand-holding where Microsoft doesn&#8217;t trust you, the developer to figure things out and really own what you&#8217;re doing. But I digress (wouldn&#8217;t be a CIMGF post if I didn&#8217;t dig on MS a bit).
<span id="more-219"></span></p>

<p>Like peanut butter and chocolate, what you get when you put together QuickTime and OpenGL is something greater than either of them left on their own (ok, this is subjective. Not everyone likes peanut butter and chocolate together, but again, I digress).</p>

<p>If you read the <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/CoreVideo/CVProg_Intro/chapter_1_section_1.html">Core Video Programming Guide</a> from Apple, you see they provide the reasons for using Core Video:</p>

<blockquote>
CoreVideo is necessary only if you want to manipulate individual video frames. For example, the following types of video processing would require CoreVideo:
<ul>
<li>Color correction or other filtering, such as provided by Core Image filters 
<li>Physical transforms of the video images (such as warping, or mapping on to a surface) 
<li>Adding video to an OpenGL scene 
<li>Adding additional information to frames, such as a visible timecode 
<li>Compositing multiple video streams 
</ul>
</blockquote>

<p>If all you need to do is display a movie, you should simply use either a QTMovieView or, if you want to stick with the Core Animation route, use a QTMovieLayer. They both function similarly, however, the view provides a lot of features that you won&#8217;t have to implement in the UI yourself such as a scrubber or play/pause buttons. Plus the view is very fast and efficient. I&#8217;m in the process of exploring performance differences between the two, but I will save my comments about that for another post.</p>

<p>For our example code we are most interested in the third point above&#8211;<strong>adding video to an OpenGL scene</strong>. It seems that new QuickTime developers often want to know how to manipulate movie images before displaying them. Often this leads them to pursue adding sub-views to the movie view which can become a big mess. Because we are using OpenGL, doing other drawing on the scene is very fast. I won&#8217;t kid you. OpenGL is a pain. I don&#8217;t know anybody who loves it, but everybody respects it because of its raw speed.</p>

<p>Point number five above&#8211;<strong>compositing multiple video streams</strong>&#8211;is also interesting. While I won&#8217;t be covering it in this post, I will say that it makes a world of difference performance wise if you composite the movies into a OpenGL scene. If you&#8217;ve ever tried to run multiple videos simultaneously in two different views or layers, it can get pretty herky jerky. You can see why it is necessary to use OpenGL instead.</p>

<h2>The OpenGL QuickTime Two Step</h2>

<p>Ok, it actually will take more than two steps, however, when you are working with Core Animation layers things get a whole lot easier than they are for rendering a movie in an NSOpenGLView. Here is what you get for free, as the kids say.</p>

<ul>
<li>You don&#8217;t have to set up the OpenGL context. It is already available for you to send your OpenGL calls to.
<li>The viewport for display is already configured
<li>You don&#8217;t need to set up a display link callback
</ul>

<p>What took over 400 lines of code when rendering a QuickTime movie with no filters to an NSOpengGLView now only takes around 150 lines. Any time you can reduce code to something simpler, it makes life easier. It also makes it much easier to grok, in my opinion.</p>

<p>There really are two primary steps you take when using a CAOpenGLLayer. First you check to see if you should draw. Then, depending upon the answer, drawInCGLContext gets called or doesn&#8217;t. Really thats it. Determining whether or not you should draw depends upon what you are trying to do. In our case, we only want to draw if all of the following are true:</p>

<ul>
<li>The movie is actually playing back
<li>The visual context for the movie has been initialized
<li>The visual context has a new image ready to be rendered
</ul>

<p>If all of these are true, then our call to canDrawInCGLContext returns YES. Here is the code I use to check these contraints in canDrawInCGLContext:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>canDrawInCGLContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLContextObj<span style="color: #002200;">&#41;</span>glContext 
                pixelFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLPixelFormatObj<span style="color: #002200;">&#41;</span>pixelFormat 
               forLayerTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CFTimeInterval<span style="color: #002200;">&#41;</span>timeInterval 
                displayTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> CVTimeStamp <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>timeStamp
<span style="color: #002200;">&#123;</span> 
    <span style="color: #11740a; font-style: italic;">// There is no point in trying to draw anything if our</span>
    <span style="color: #11740a; font-style: italic;">// movie is not playing.</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span>movie rate<span style="color: #002200;">&#93;</span> &lt;<span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span> <span style="color: #002200;">&#41;</span>
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
&nbsp;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>qtVisualContext <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// If our visual context for our QTMovie has not been set up</span>
        <span style="color: #11740a; font-style: italic;">// we initialize it now</span>
        <span style="color: #002200;">&#91;</span>self setupVisualContext<span style="color: #002200;">:</span>glContext withPixelFormat<span style="color: #002200;">:</span>pixelFormat<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Check to see if a new frame (image) is ready to be draw at</span>
    <span style="color: #11740a; font-style: italic;">// the time specified.</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>QTVisualContextIsNewImageAvailable<span style="color: #002200;">&#40;</span>qtVisualContext,timeStamp<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Release the previous frame</span>
        CVOpenGLTextureRelease<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Copy the current frame into our image buffer</span>
        QTVisualContextCopyImageForTime<span style="color: #002200;">&#40;</span>qtVisualContext,
                                        <span style="color: #a61390;">NULL</span>,
                                        timeStamp,
                                        <span style="color: #002200;">&amp;</span>currentFrame<span style="color: #002200;">&#41;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// Returns the texture coordinates for the part of the image that should be displayed</span>
        CVOpenGLTextureGetCleanTexCoords<span style="color: #002200;">&#40;</span>
                            currentFrame, 
                            lowerLeft, 
                            lowerRight, 
                            upperRight, upperLeft<span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #a61390;">return</span> <span style="color: #a61390;">NO</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The call to setup the visual context is where we are associating the QuickTime movie itself with a QTVisualContextRef object which is what OpenGL needs to draw the current frame. We will then use this object to load image data into a CVImageBufferRef which can be used for rendering with OpenGL. Here is the code to set up the visual context.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setupVisualContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLContextObj<span style="color: #002200;">&#41;</span>glContext 
           withPixelFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLPixelFormatObj<span style="color: #002200;">&#41;</span>pixelFormat;
<span style="color: #002200;">&#123;</span>
    OSStatus			    error;
&nbsp;
    <span style="color: #400080;">NSDictionary</span>	    <span style="color: #002200;">*</span>attributes <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    attributes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                  <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">&#93;</span>,
                   kQTVisualContextTargetDimensions_WidthKey,
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">&#93;</span>,
                   kQTVisualContextTargetDimensions_HeightKey, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>, 
                  kQTVisualContextTargetDimensionsKey, 
                  <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.width<span style="color: #002200;">&#93;</span>, 
                   kCVPixelBufferWidthKey, 
                   <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>.size.height<span style="color: #002200;">&#93;</span>, 
                   kCVPixelBufferHeightKey, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>, 
                  kQTVisualContextPixelBufferAttributesKey,
                  <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create our quicktimee visual context</span>
    error <span style="color: #002200;">=</span> QTOpenGLTextureContextCreate<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>,
                                         glContext,
                                         pixelFormat,
                                         <span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>attributes,
                                         <span style="color: #002200;">&amp;</span>qtVisualContext<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Associate it with our movie.</span>
    SetMovieVisualContext<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>movie quickTimeMovie<span style="color: #002200;">&#93;</span>,qtVisualContext<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Next we check to see if there is an image ready using:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>QTVisualContextIsNewImageAvailable<span style="color: #002200;">&#40;</span>qtVisualContext,timeStamp<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span></pre></td></tr></table></div>


<p>And then we copy the image to our CVImageBufferRef with:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Copy the current frame into our image buffer</span>
QTVisualContextCopyImageForTime<span style="color: #002200;">&#40;</span>qtVisualContext,
                                <span style="color: #a61390;">NULL</span>,
                                timeStamp,
                                <span style="color: #002200;">&amp;</span>currentFrame<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>Now it&#8217;s all a matter of rendering the frame for the current time stamp.</p>

<h2>But Wait! What TimeStamp?</h2>

<p>If you asked this question, then you are a very astute reader. In order to obtain the next image, we simply passed the CVTimeStamp parameter, <em>timeStamp</em> to our call to QTVisualContextCopyImageForTime. But how do we even have a timestamp? Isn&#8217;t that something we need to get from a display link? If you&#8217;re asking what is a display link at this point, take a look at the <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/CoreVideo/CVProg_Concepts/chapter_2_section_3.html">Core Video Programming Guide</a> which states:</p>

<blockquote>
To simplify synchronization of video with a displayâ€™s refresh rate, Core Video provides a special timer called a display link. The display link runs as a separate high priority thread, which is not affected by interactions within your application process.

In the past, synchronizing your video frames with the displayâ€™s refresh rate was often a problem, especially if you also had audio. You could only make simple guesses for when to output a frame (by using a timer, for example), which didnâ€™t take into account possible latency from user interactions, CPU loading, window compositing and so on. The Core Video display link can make intelligent estimates for when a frame needs to be output, based on display type and latencies.
</blockquote>

<p>I will provide a more complete answer to the question in the future as I am still studying it myself, however, I will mention that a display link callback is unnecessary in this context as the CAOpenGLLayer is providing this for us. The timestamp field is all we need in order to get the current frame assuming that the movie is playing back.</p>

<h2>Drawing The Frame</h2>

<p>There is a special group of people who really get OpenGL. I salute all of you to whom this applies. You are amazing. I, however, only write as much of it as necessary and you&#8217;ll see that most of the code I have here is simply a copy and paste from sample code I got from Apple. I am starting to understand it more and more, however, it makes my brain hurt. Here is my drawing code for when a frame is ready to be rendered.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>drawInCGLContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLContextObj<span style="color: #002200;">&#41;</span>glContext 
             pixelFormat<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGLPixelFormatObj<span style="color: #002200;">&#41;</span>pixelFormat 
            forLayerTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CFTimeInterval<span style="color: #002200;">&#41;</span>interval 
             displayTime<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">const</span> CVTimeStamp <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>timeStamp
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">NSRect</span>    bounds <span style="color: #002200;">=</span> NSRectFromCGRect<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>self bounds<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    GLfloat 	minX, minY, maxX, maxY;        
&nbsp;
    minX <span style="color: #002200;">=</span> NSMinX<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
    minY <span style="color: #002200;">=</span> NSMinY<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
    maxX <span style="color: #002200;">=</span> NSMaxX<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
    maxY <span style="color: #002200;">=</span> NSMaxY<span style="color: #002200;">&#40;</span>bounds<span style="color: #002200;">&#41;</span>;
&nbsp;
    glMatrixMode<span style="color: #002200;">&#40;</span>GL_MODELVIEW<span style="color: #002200;">&#41;</span>;
    glLoadIdentity<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    glMatrixMode<span style="color: #002200;">&#40;</span>GL_PROJECTION<span style="color: #002200;">&#41;</span>;
    glLoadIdentity<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    glOrtho<span style="color: #002200;">&#40;</span> minX, maxX, minY, maxY, <span style="color: #002200;">-</span><span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    glClearColor<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span>, <span style="color: #2400d9;">0.0</span><span style="color: #002200;">&#41;</span>;	     
    glClear<span style="color: #002200;">&#40;</span>GL_COLOR_BUFFER_BIT<span style="color: #002200;">&#41;</span>;
&nbsp;
    CGRect imageRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self frame<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Enable target for the current frame</span>
    glEnable<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #11740a; font-style: italic;">// Bind to the current frame</span>
    <span style="color: #11740a; font-style: italic;">// This tells OpenGL which texture we are wanting </span>
    <span style="color: #11740a; font-style: italic;">// to draw so that when we make our glTexCord and </span>
    <span style="color: #11740a; font-style: italic;">// glVertex calls, our current frame gets drawn</span>
    <span style="color: #11740a; font-style: italic;">// to the context.</span>
    glBindTexture<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span>, 
                  CVOpenGLTextureGetName<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    glMatrixMode<span style="color: #002200;">&#40;</span>GL_TEXTURE<span style="color: #002200;">&#41;</span>;
    glLoadIdentity<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    glColor4f<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span>, <span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#41;</span>;
    glBegin<span style="color: #002200;">&#40;</span>GL_QUADS<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Draw the quads</span>
    glTexCoord2f<span style="color: #002200;">&#40;</span>upperLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, upperLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x, 
                 imageRect.origin.y <span style="color: #002200;">+</span> imageRect.size.height<span style="color: #002200;">&#41;</span>;
    glTexCoord2f<span style="color: #002200;">&#40;</span>upperRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, upperRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x <span style="color: #002200;">+</span> imageRect.size.width, 
                 imageRect.origin.y <span style="color: #002200;">+</span> imageRect.size.height<span style="color: #002200;">&#41;</span>;
    glTexCoord2f<span style="color: #002200;">&#40;</span>lowerRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, lowerRight<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x <span style="color: #002200;">+</span> imageRect.size.width, 
                 imageRect.origin.y<span style="color: #002200;">&#41;</span>;
    glTexCoord2f<span style="color: #002200;">&#40;</span>lowerLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>, lowerLeft<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">1</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
    glVertex2f  <span style="color: #002200;">&#40;</span>imageRect.origin.x, imageRect.origin.y<span style="color: #002200;">&#41;</span>;
&nbsp;
    glEnd<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// This CAOpenGLLayer is responsible to flush</span>
    <span style="color: #11740a; font-style: italic;">// the OpenGL context so we call super</span>
    <span style="color: #002200;">&#91;</span>super drawInCGLContext<span style="color: #002200;">:</span>glContext 
                pixelFormat<span style="color: #002200;">:</span>pixelFormat 
               forLayerTime<span style="color: #002200;">:</span>interval 
                displayTime<span style="color: #002200;">:</span>timeStamp<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Task the context</span>
    QTVisualContextTask<span style="color: #002200;">&#40;</span>qtVisualContext<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>If you&#8217;re not familiar with OpenGL it would help you to know that it&#8217;s all about the current state. What does this mean? Well, simply put, it means that the call you are making right now, applies to whatever state the context is in. These two calls are what are the most important for our purposes.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">glEnable<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
glBindTexture<span style="color: #002200;">&#40;</span>CVOpenGLTextureGetTarget<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span>, 
                  CVOpenGLTextureGetName<span style="color: #002200;">&#40;</span>currentFrame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>With these two calls we have told OpenGL which texture to use. Now, every subsequent call applies to this texture until the state is changed to something else. So now, when we set a color or draw a quad, it applies to the texture that has been set here.</p>

<h2>Conclusion</h2>

<p>I love both of these technologies, QuickTime and OpenGL. They are so powerful. It&#8217;s harnessing the power that&#8217;s the trick. I&#8217;ve got some other ideas for some related posts that I plan to cover in the weeks to come, but this was a real breakthrough for me. With the help of John Clayton, Jean-Daniel Dupas, and David Duncan on the cocoa-dev list, I was able to get the sample code put together for this post. Feel free to ask questions in the comments. I will do my best to answer, but I&#8217;m still pretty new to these technologies. Write some code yourself and have fun. This is really exciting stuff. Until next time.</p>

<h2>About The Demo Code</h2>

<p><strike>John Clayton has some issues getting the code to work on his Mac Pro. I successfully ran it on  my MacBook Pro, and the family iMac without any issues. Anyhow, we&#8217;re not sure what the problem is, so if you do run into trouble, let me know. Maybe we can figure it out. Meanwhile we&#8217;re investigating it as we have time.</strike></p>

<p><strong>Update:</strong> John Clayton figured it out. Apparently the visual context needs to be reset because the pixel format is not correct on the first run. We just reset the visual context now in the call to -copyCGLContextForPixelFormat and everything seems happy. The demo code has been updated to reflect the change.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/09/qtglcalayerdemo.zip'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/xcode.png" alt="Quicktime CAOpenGLLayer Demo" title="Quicktime CAOpenGLLayer Demo" width="64" class="aligncenter size-medium wp-image-49" /><br />Quicktime CAOpenGLLayer Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/09/10/core-animation-tutorial-rendering-quicktime-movies-in-a-caopengllayer/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Dashboard Effect</title>
		<link>http://www.cimgf.com/2008/03/15/core-animation-tutorial-dashboard-effect/</link>
		<comments>http://www.cimgf.com/2008/03/15/core-animation-tutorial-dashboard-effect/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 14:07:11 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[dasboard]]></category>
		<category><![CDATA[effect]]></category>
		<category><![CDATA[fade]]></category>
		<category><![CDATA[fading]]></category>
		<category><![CDATA[scale]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/03/15/core-animation-tutorial-dashboard-effect/</guid>
		<description><![CDATA[In our continued efforts to demonstrate different ways to use Core Animation, we have noticed different effects you see in OS X itself that present an interesting challenge to duplicate. In a previous post, we demonstrated how to shake a login window similar to the way that OS X shakes the login window when the [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.cimgf.com/wp-content/uploads/2008/03/dashboardeffect.jpg' title='Dashboard Effect' rel='lightbox'><img src='http://www.cimgf.com/wp-content/uploads/2008/03/dashboardeffect.thumbnail.jpg' alt='Dashboard Effect' align='left' style='margin:5px;' /></a>In our continued efforts to demonstrate different ways to use Core Animation, we have noticed different effects you see in OS X itself that present an interesting challenge to duplicate. In a previous post, we <a href="http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/">demonstrated how to shake a login window</a> similar to the way that OS X shakes the login window when the user enters the wrong password. This time, we&#8217;re going to demonstrate how to do what we&#8217;ve dubbed the Dashboard Effect.</p>

<p>I&#8217;m not sure this is the best name for it as some people may think we mean the ripple effect you see when you drop a new Dashboard widget on the screen, but what we mean is the way in which the Dashboard widgets that are already employed in Dashboard fly in and out of view when you enable and disable Dashboard. Enable Dashboard now and watch your widgets fly in from offscreen. Then disable it and watch the widgets fly out again. This is what we mean by the Dashboard effect and this is what we set out to duplicate.
<span id="more-44"></span></p>

<p>Download the demo project from here: <a href='http://www.cimgf.com/wp-content/uploads/2008/03/dashboardeffect.zip' title='Dashboard Effect Sample Project'>Dashboard Effect Sample Project</a>. When you build and run it, press Command-N to add additional layers to the screen and then press Command-E to see the effect. Press Shift-Command-E to see the effect in slow motion.</p>

<h2>Scaling Sublayers Is Automatic In Core Animation</h2>

<p>When you create a Core Animation layer tree, your layer transformation cascades the tree automatically, so we really only have to create sublayers and add them to a top level layer upon which we perform the scaling transformation. Before we do that, though, go ahead and enable Dashboard in Mac OS X so you can see the effect that we&#8217;re going for. Hold the shift key while you enable/disable Dashboard and you&#8217;ll see it animate slowly. In my demo project I&#8217;ve simply created a BOOL variable to keep track of whether we are scaling up or down and set that on each invocation of the scaling function. Here is what the function looks like:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>doItIn<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">float</span><span style="color: #002200;">&#41;</span>duration
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Set the animation duration.</span>
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAnimationContext</span> currentContext<span style="color: #002200;">&#93;</span> setDuration<span style="color: #002200;">:</span>duration<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> scaleUp <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Scale everything (x, y, and z) by a factor of factor (static variable) and reduce the opacity</span>
        CATransform3D transform <span style="color: #002200;">=</span> CATransform3DMakeScale<span style="color: #002200;">&#40;</span>factor, factor, factor<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#91;</span>mainLayer setTransform<span style="color: #002200;">:</span>transform<span style="color: #002200;">&#93;</span>;
        mainLayer.opacity <span style="color: #002200;">=</span> 0.0f;
        scaleUp <span style="color: #002200;">=</span> <span style="color: #a61390;">NO</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">else</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// Scale the rect back down to the orignal and bring up the opacity</span>
        CATransform3D transform <span style="color: #002200;">=</span> CATransform3DMakeScale<span style="color: #002200;">&#40;</span>1.0f, 1.0f, 1.0f<span style="color: #002200;">&#41;</span>;
        <span style="color: #002200;">&#91;</span>mainLayer setTransform<span style="color: #002200;">:</span>transform<span style="color: #002200;">&#93;</span>;
        mainLayer.opacity <span style="color: #002200;">=</span> 1.0f;
        scaleUp <span style="color: #002200;">=</span> <span style="color: #a61390;">YES</span>;
    <span style="color: #002200;">&#125;</span> 
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In this function we pass in the duration we want to use. This is predicated on whether or not the user was holding the shift key as we want to try to duplicate the effect of Dashboard as close as possible. Take a look at the two IBAction(s) we&#8217;ve declared in <strong>AppDelegate.h</strong> in the sample project to see it getting called.</p>

<h2>Adding Random Layers</h2>

<p>I&#8217;ve added another menu action as well as keyboard shortcut (Command-N) that will allow you to add new layers at random points with random sizes and colors onto the screen. Just press Command-N several times and then press Command-E again to see the effect. Notice that I&#8217;ve also dimmed the background behind the front layers (which are our representation of Dashboard widgets). That dimmed backing layer is actually the only layer we animate as you see in the previous code example. Here is how the layers (widgets) get created:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>addNewLayer<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
&nbsp;
    CALayer <span style="color: #002200;">*</span>layer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CALayer layer<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Set some random colors, and the border width</span>
    <span style="color: #a61390;">float</span> r <span style="color: #002200;">=</span> SSRandomFloatBetween<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1.00</span>, <span style="color: #2400d9;">0.00</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">float</span> g <span style="color: #002200;">=</span> SSRandomFloatBetween<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1.00</span>, <span style="color: #2400d9;">0.00</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">float</span> b <span style="color: #002200;">=</span> SSRandomFloatBetween<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">1.00</span>, <span style="color: #2400d9;">0.00</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    layer.backgroundColor <span style="color: #002200;">=</span> CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span>r,g,b,1.0f<span style="color: #002200;">&#41;</span>;
    layer.borderColor<span style="color: #002200;">=</span>CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span>b,r,g,1.0f<span style="color: #002200;">&#41;</span>;
    layer.borderWidth<span style="color: #002200;">=</span><span style="color: #2400d9;">4.0</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create a random rectangle with a size between 300 and 200 pixels.</span>
    <span style="color: #a61390;">NSRect</span> rect <span style="color: #002200;">=</span> NSZeroRect;
    rect.size <span style="color: #002200;">=</span> NSMakeSize<span style="color: #002200;">&#40;</span> SSRandomFloatBetween<span style="color: #002200;">&#40;</span> <span style="color: #2400d9;">300.0</span>, <span style="color: #2400d9;">200.0</span> <span style="color: #002200;">&#41;</span>, SSRandomFloatBetween<span style="color: #002200;">&#40;</span> <span style="color: #2400d9;">300.0</span>, <span style="color: #2400d9;">200.0</span> <span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Calculate random origin point</span>
    rect.origin <span style="color: #002200;">=</span> SSRandomPointForSizeWithinRect<span style="color: #002200;">&#40;</span> rect.size, <span style="color: #002200;">&#91;</span>window frame<span style="color: #002200;">&#93;</span> <span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Set the layer frame to our random rectangle.</span>
    layer.frame <span style="color: #002200;">=</span> NSRectToCGRect<span style="color: #002200;">&#40;</span>rect<span style="color: #002200;">&#41;</span>;
    layer.cornerRadius <span style="color: #002200;">=</span> rect.size.height<span style="color: #002200;">/</span><span style="color: #2400d9;">5</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Create a text layer to add so we can see text scale too.</span>
    CATextLayer <span style="color: #002200;">*</span>textLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CATextLayer layer<span style="color: #002200;">&#93;</span>;
    textLayer.<span style="color: #a61390;">string</span> <span style="color: #002200;">=</span> <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Hello World!&quot;</span>;
    CGFontRef font <span style="color: #002200;">=</span> CGFontCreateWithFontName<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFStringRef<span style="color: #002200;">&#41;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Helvetica&quot;</span><span style="color: #002200;">&#41;</span>;
    textLayer.font <span style="color: #002200;">=</span> font;
    textLayer.frame <span style="color: #002200;">=</span> CGRectMake<span style="color: #002200;">&#40;</span><span style="color: #2400d9;">10.0</span>, <span style="color: #2400d9;">100.0</span>, <span style="color: #2400d9;">195.0</span>, <span style="color: #2400d9;">35.0</span><span style="color: #002200;">&#41;</span>;
    CGFontRelease<span style="color: #002200;">&#40;</span>font<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Use the same color for the text that we used for the border.</span>
    textLayer.foregroundColor <span style="color: #002200;">=</span> layer.borderColor;
    <span style="color: #11740a; font-style: italic;">// Add the text layer</span>
    <span style="color: #002200;">&#91;</span>layer addSublayer<span style="color: #002200;">:</span>textLayer<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Insert the layer into the root layer</span>
    <span style="color: #002200;">&#91;</span>mainLayer addSublayer<span style="color: #002200;">:</span>layer<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<blockquote>
<strong>Note:</strong> I grabbed these convenience functions, <strong>SSRandomFloatBetween</strong> and <strong> SSRandomPointForSizeWithinRect</strong>from the <span style="color:red;">&lt;ScreenSaver/ScreenSaver.h&gt;</span> library. They provide a simple way to get random points and rectangles for placing new layers on the screen. You&#8217;ll need to <em>#import &lt;ScreenSaver/ScreenSaver.h&gt;</em> to use them in your projects. 
</blockquote>

<h2>Trans-Parent</h2>

<p>The parent window in our application, is a borderless window with a transparent background color. You&#8217;ll see the window class we&#8217;ve created called <em>BorderlessWindow</em> in the project. This simply removes the borders and makes the backing window transparent so all we see are Core Animation layers. I used a similar technique in <a href="http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/">my last post</a>. Again, I haven&#8217;t taken the time to see if there is a way to click through the window. As it stands, you can see through the window, but when you try to click what&#8217;s behind it, no dice.</p>

<h2>Conclusion</h2>

<p>Well, that&#8217;s about it for this one. It&#8217;s pretty simple thanks to Core Animation. Marcus and I started down a path where we were trying to figure out all of the math ourselves in order to scale and move each of the CALayer frames individually. As it turns out, all of the hard work is done for us where all we had to do was specify the scaleX, scaleY, and scaleZ to the <em> CATransform3DMakeScale</em> function and voila, instant layer scaling with cascading. I&#8217;m continually impressed by all Apple has provided to developers to use in Core Animation. It&#8217;s a great library.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/03/15/core-animation-tutorial-dashboard-effect/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: QTMovieLayer and Image Animation</title>
		<link>http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/</link>
		<comments>http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 19:33:26 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[NSOperation]]></category>
		<category><![CDATA[QTKit]]></category>
		<category><![CDATA[calayer]]></category>
		<category><![CDATA[convert nsimage to cgimageref]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[qtmovielayer]]></category>
		<category><![CDATA[sample code]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/</guid>
		<description><![CDATA[In my first post I wrote about using NSOperation to grab an image of the current frame of a QuickTime movie while it was playing and save it out to the filesystem. Considering the excitement that is surrounding Core Animation these days, I thought it might be interesting to take that project and change it [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.cimgf.com/wp-content/uploads/2008/03/qtmovielayer_desktop.jpg' title='QTMovieLayer App Desktop'  rel='lightbox'><img src='http://www.cimgf.com/wp-content/uploads/2008/03/qtmovielayer_desktop.thumbnail.jpg' alt='QTMovieLayer App Desktop' align="left" style="margin:5px;" /></a>In my <a href="http://www.cimgf.com/2008/02/23/nsoperation-example/">first post</a> I wrote about using NSOperation to grab an image of the current frame of a QuickTime movie while it was playing and save it out to the filesystem. Considering the excitement that is surrounding Core Animation these days, I thought it might be interesting to take that project and change it to instead grab the current frame and animate it across the screen using a Core Animation layer (CALayer). I had to employ a few tricks to get it to work, but the end result, while completely useless, is quite excellent.
<br /><br /><br /><br />
&nbsp;
<br /><br /><br /><br />
<span id="more-38"></span></p>

<h2>Getting Ready For The Image</h2>

<p>The focus of this tutorial is Core Animation and specifically how to use a QTMovieLayer as well as animating an image across the screen using a CALayer. I, therefore, will not spend any time addressing NSOperation and I think we&#8217;ve covered this adequately on this site. I would suggest, however, that you familiarize yourself with <a href="http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/">Marcus&#8217; post on NSOperation</a> as he discusses calling back into the main thread once the NSOperation has completed. I employ Marcus&#8217; technique in this project so that I can be notified when the image I&#8217;m wanting to animate is ready.</p>

<blockquote>
You can download the demo project for this post from here: <a href='http://www.cimgf.com/wp-content/uploads/2008/03/movieimageflick.zip' title='Movie Image Flick Demo Project'>Movie Image Flick Demo Project</a>
</blockquote>

<p>Download the project and run it. It will prompt you to select a QuickTime movie to play. Once the movie starts playing, tap your spacebar and watch the images pop off of the movie and animate to random places on the screen. Tap the spacebar quickly to see the effect work in rapid succession.</p>

<p>As in my NSOperation post, I want the video playback to be completely flicker free. I achieve this by obtaining a reference to a copy of the QTMovie object from which I obtain the image at the given time. If you take a look at my <em>main:</em> function in my NSOperation derived class, you&#8217;ll see how I am notifying the main thread that it may now do something with the image I&#8217;ve obtained.</p>

<p><strong>ImageGrabber.m:main</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> movie <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span> image;
        image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>movie frameImageAtTime<span style="color: #002200;">:</span><span style="color: #a61390;">time</span> 
                      withAttributes<span style="color: #002200;">:</span>imageAttrs error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>image retain<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>AppDelegate shared<span style="color: #002200;">&#93;</span> performSelectorOnMainThread<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>imageReady<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                               withObject<span style="color: #002200;">:</span>image
                                            waitUntilDone<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>image release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In the second last line of the function, notice I am calling back into my main thread and letting the app delegate know that the image is ready. I am also handing the image to the <em>imageReady:</em> function. This is very convenient for what we need to do next. But first, let&#8217;s discuss drawing the layers with no backing view or window.</p>

<h2>Drawing Layers In Thin Air</h2>

<p>This project employs a trick that makes it appear as if the layers are being drawn without a backing view. This is, of course, not really possible, so instead we do a little trick. I achieved this effect by creating a borderless window with a transparent background. As usual, I want to give credit where credit is due. Lucas Newman answered a question <a href="http://theocacao.com/document.page/551">I posted on Scott Stevenson&#8217;s blog</a> to find out how Lucas did this in his demo project a the Silicon Valley CocoaHeads meeting on Core Animation. You simply create your own NSWindow derived class and override the initWithContentRect: method. Here is the resulting initialization code I came up with from his suggestion.</p>

<p><strong>BorderlessWindow.m:initWithContentRect</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithContentRect<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRect</span><span style="color: #002200;">&#41;</span> contentRect
                 styleMask<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> aStyle
                   backing<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>NSBackingStoreType<span style="color: #002200;">&#41;</span> bufferingType
                     defer<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> flag
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>super initWithContentRect<span style="color: #002200;">:</span> contentRect 
                 styleMask<span style="color: #002200;">:</span> NSBorderlessWindowMask 
                   backing<span style="color: #002200;">:</span> bufferingType 
                   defer<span style="color: #002200;">:</span> flag<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#91;</span>self setBackgroundColor<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSColor</span> clearColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self setOpaque<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The only issue with using a transparent backing window/view is that you cannot click through it even though it looks like you ought to be able to. There is probably a way to pass the click on to the next front most window, but I haven&#8217;t yet researched this. I&#8217;ll let you know when I find the answer, or if you know the answer, post it in the comments.</p>

<h2>Rapid Fire Image Animation</h2>

<p>I created a method to initialize my NSOperation derived objects and hand them off to the NSOperationQueue. I hooked it up to the spacebar and can then tap the spacebar as quickly as possible and watch the images just pop off the playing movie. Here is my <em>flickIt:</em> function.</p>

<p><strong>AppDelegate.m:flickIt</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>flickIt<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    ImageGrabber <span style="color: #002200;">*</span>grabber <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ImageGrabber alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>grabber setTime<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>movie currentTime<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Hand off the background movie to the NSOperation derived</span>
    <span style="color: #11740a; font-style: italic;">// object</span>
    <span style="color: #002200;">&#91;</span>grabber setMovie<span style="color: #002200;">:</span>movieBak<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Add the oepration to the queue. It will be run immediately.</span>
    <span style="color: #002200;">&#91;</span>queue addOperation<span style="color: #002200;">:</span>grabber<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>This function creates the NSOpeartion derived objects and passes a reference to the current time in the playing movie as well as a reference to the background movie that I use to pull the image data from. Remember that this object is copied from the original QTMovie object and is used to keep from needing to pull the image data from the QTMovie object that is actually playing in the QTMovieLayer. Pulling the image from the QTMovie object that is being used for playback would cause the playback to stutter.</p>

<p>As stated earlier, when my image is ready, the NSOperation derived object, ImageGrabber, calls back into the main thread calling the function called <em>imageReady:</em>. Here is its implementation.</p>

<p><strong>AppDelegate.m:imageReady</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>imageReady<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image;
<span style="color: #002200;">&#123;</span>    
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAnimationContext</span> currentContext<span style="color: #002200;">&#93;</span> setDuration<span style="color: #002200;">:</span>1.5f<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Save off the rectangle of the ready layer before</span>
    <span style="color: #11740a; font-style: italic;">// it gets animated. We will use this to reset the</span>
    <span style="color: #11740a; font-style: italic;">// ready layer.</span>
    CGRect prevRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>readyLayer frame<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Convert the NSImage to a CGImageRef</span>
    CGImageRef imageRef <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self nsImageToCGImageRef<span style="color: #002200;">:</span>image<span style="color: #002200;">&#93;</span>;
    CFRetain<span style="color: #002200;">&#40;</span>imageRef<span style="color: #002200;">&#41;</span>;
    readyLayer.contents <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>imageRef;
    readyLayer.backgroundColor <span style="color: #002200;">=</span> CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span>0.0f,0.0f,0.0f,1.0f<span style="color: #002200;">&#41;</span>;
    readyLayer.borderColor <span style="color: #002200;">=</span> CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span>0.45f,0.45f,0.45f,1.0f<span style="color: #002200;">&#41;</span>;
    readyLayer.borderWidth <span style="color: #002200;">=</span> 4.0f;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Grab a random rectangle on the screen where our image</span>
    <span style="color: #11740a; font-style: italic;">// layer will animate to.</span>
    CGRect randRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getRandomRect<span style="color: #002200;">:</span>prevRect<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>readyLayer setFrame<span style="color: #002200;">:</span>randRect<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>readyLayer setOpacity<span style="color: #002200;">:</span>1.0f<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Reset the ready layer so that it is ready for the next image</span>
    readyLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>CALayer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> retain<span style="color: #002200;">&#93;</span>;
    readyLayer.frame <span style="color: #002200;">=</span> prevRect;
    readyLayer.opacity <span style="color: #002200;">=</span> 0.01f;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>readyLayer<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice that we are converting the <em>NSImage</em> that gets passed to this function into a <em>CGImageRef</em> which is what our Core Animation layer requires to set it contents. Here is the code to convert an <em>NSImage</em> to a <em>CGImageRef</em>.</p>

<p><strong>AppDelegate.m:nsImageToCGImageRef</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGImageRef<span style="color: #002200;">&#41;</span>nsImageToCGImageRef<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span> imageData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image TIFFRepresentation<span style="color: #002200;">&#93;</span>;
    CGImageRef imageRef;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>imageData<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        CGImageSourceRef imageSource <span style="color: #002200;">=</span> 
                     CGImageSourceCreateWithData<span style="color: #002200;">&#40;</span>
                           <span style="color: #002200;">&#40;</span>CFDataRef<span style="color: #002200;">&#41;</span>imageData,  <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        imageRef <span style="color: #002200;">=</span> CGImageSourceCreateImageAtIndex<span style="color: #002200;">&#40;</span>
                          imageSource, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> imageRef;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Preloading A Layer to Animate</h2>

<p>Instead of creating the layer, setting its contents, and then animating it all at once, I instead set an empty layer with a near zero opacity to overlay the QTMovieLayer when the movie first loads. Then, when the user taps the spacebar, I populate that invisible layer&#8217;s contents with the image data and then animate it. This keeps me from having to create a more complicated animation to get the desired effect.</p>

<p>Once the image layer has it&#8217;s new frame set, I re-initialize the ready layer. You see the ready layer get reset with this code from the <em>imageReady:</em> function.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Reset the ready layer so that it is ready for the next image</span>
readyLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>CALayer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> retain<span style="color: #002200;">&#93;</span>;
readyLayer.frame <span style="color: #002200;">=</span> prevRect;
readyLayer.opacity <span style="color: #002200;">=</span> 0.01f;
&nbsp;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>readyLayer<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<blockquote>
<br />
<strong>Note:</strong> I set the opacity to near zero as when it is set to zero it won&#8217;t animate the opacity change properly. I&#8217;m looking into why this is and will update this post with what I find when I find it.
<br /><br />

&nbsp;
</blockquote>

<h2>Random Points</h2>

<p>When I animate the layers, I simply grab a random point and the screen and then scale the image down to 35% of the original. When I call <em>setFrame:</em> the magic ensues and my screen gets really cluttered with lots of images. As I said before, not very useful, but excellent. Here is the random rectangle calculation function, <em>getRandomRect:</em>.</p>

<p><strong>AppDelegate.m:getRandomRect</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>getRandomRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>startRect;
<span style="color: #002200;">&#123;</span>    
    CGPoint point <span style="color: #002200;">=</span> CGPointMake<span style="color: #002200;">&#40;</span>random<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">%</span> 
                          <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>NSWidth<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>window frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>, 
                          random<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">%</span> 
                           <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>NSHeight<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>window frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> CGRectMake<span style="color: #002200;">&#40;</span>point.x, point.y, 
                 startRect.size.width <span style="color: #002200;">*</span> 0.35f, startRect.size.height <span style="color: #002200;">*</span> 0.35f<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Conclusion</h2>

<p>The nuances of Core Animation are quite interesting and provide a fun challenge when trying to solve problems. In other words, the devil is in the details. There is probably a better way to achieve the animation code, but I felt that the solution I came up with here works pretty well. There are details about Core Animation that I am still learning, but this type of effect demonstrates exactly the kinds of interesting things that are possible.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Wizard Dialog with Transitions</title>
		<link>http://www.cimgf.com/2008/03/03/core-animation-tutorial-wizard-dialog-with-transitions/</link>
		<comments>http://www.cimgf.com/2008/03/03/core-animation-tutorial-wizard-dialog-with-transitions/#comments</comments>
		<pubDate>Mon, 03 Mar 2008 18:27:25 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[dialog]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[wizard]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/03/03/core-animation-tutorial-wizard-dialog-with-transitions/</guid>
		<description><![CDATA[A question that I have seen pop up a few times is how to build a Wizard in Cocoa. Having thought about that question a bit I realized that a better answer to it is &#8212; how to build a wizard in Cocoa using Core Animation. The basic concept behind this project is to present [...]]]></description>
			<content:encoded><![CDATA[<p>A question that I have seen pop up a few times is how to build a Wizard in Cocoa.  Having thought about that question a bit I realized that a better answer to it is &#8212; how to build a wizard in Cocoa using Core Animation.</p>

<p>The basic concept behind this project is to present a window to the user that will walk them through a list of options.  To accomplish this task, I created a number of NSViews that will be presented to the user in order so that they can make the decisions needed.  To make this a little easier, I have extended NSView to create MSZLinkedView.  The added functionality in this subclass is that the view has a reference to the previous and next views in the wizard.  These references are set in interface builder directly so that I do not have to worry about them in code.</p>

<p><span id="more-42"></span></p>

<p>You can download the sample project from here: <a href='http://www.cimgf.com/wp-content/uploads/2008/03/coreanimationwizard.zip' title='Core Animation Wizard Tutorial Project'>Core Animation Wizard Tutorial Project</a>.
</p>

<p><b>MSZLinkedView.h</b></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> MSZLinkedView <span style="color: #002200;">:</span> <span style="color: #400080;">NSView</span> <span style="color: #002200;">&#123;</span>
    IBOutlet MSZLinkedView <span style="color: #002200;">*</span>previousView;
    IBOutlet MSZLinkedView <span style="color: #002200;">*</span>nextView;
&nbsp;
    IBOutlet <span style="color: #400080;">NSButton</span> <span style="color: #002200;">*</span>nextButton;
    IBOutlet <span style="color: #400080;">NSButton</span> <span style="color: #002200;">*</span>previousButton;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span><span style="color: #002200;">&#40;</span>retain<span style="color: #002200;">&#41;</span>MSZLinkedView <span style="color: #002200;">*</span>previousView, <span style="color: #002200;">*</span>nextView;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p><b>MSZLinkedView.m</b></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@implementation</span> MSZLinkedView
&nbsp;
<span style="color: #a61390;">@synthesize</span>  previousView, nextView;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self setWantsLayer<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>previousButton setEnabled<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>previousView <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>nextButton setEnabled<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>nextView <span style="color: #002200;">!=</span> <span style="color: #a61390;">nil</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>There is not much to this class.  The primary purpose is to keep a reference to its place in the linked list.  But since I have the subclass I have added the core animation setWantsLayer: call into the awakeFromNib and it also checks to see if it has a previous and/or next view to disable the appropriate buttons.  This NSView subclass will be used to build the different &#8220;pages&#8221; of the wizard.</p>

<h2>Building the XIB/NIB</h2>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/03/mainmenu.nib.png' rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/mainmenu.nib.png" alt="MainMenu.nib.png" border="0" width="200" style='float:right;'/></a>The next step in building the wizard is to lay out the views in Interface Builder.  In the sample project, I have created three views: first, second and third.  Each of these views has a next button, previous button and a custom box with a different color.  If you build and run the project you can flip through these three and the appropriate button will be disabled.</p>

<p>Each view links to the next view, the previous view, and its own next and previous button.  All of these links will occur before the awakeFromNib is called on each view so that the buttons will be disabled as appropriate.<a href='http://www.cimgf.com/wp-content/uploads/2008/03/firstview.png' rel='lightbox'><img src="http://www.cimgf.com/wp-content/uploads/2008/03/firstview.png" alt="FirstView.png" border="0" width="200" style='float:right;'/></a>  In an actual application I would have put in text fields, radio buttons, pictures, etc on each &#8220;slide&#8221; but in this case I only put in a simple box with a custom design.  This will allow the user to see the slides clearly.</p>

<p>The application delegate in this example holds a reference to the main window and <i>only the first selected view.</i>  Because the views are in a linked list, the AppDelegate does not care about the other views at all.  That is responsibility of the list.  There is one little catch though.  When the nib is being loaded, the current view will be referenced before the awakeFromNib is called.  To get the view added as a subview I need to add it in the awakeFromNib.  This will set the stage for the wizard.</p>

<p><b>AppDelegate.h</b></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> AppDelegate <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span> <span style="color: #002200;">&#123;</span>
    IBOutlet <span style="color: #400080;">NSWindow</span> <span style="color: #002200;">*</span>window;
    IBOutlet MSZLinkedView <span style="color: #002200;">*</span>currentView;
&nbsp;
    CATransition <span style="color: #002200;">*</span>transition;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span><span style="color: #002200;">&#40;</span>retain<span style="color: #002200;">&#41;</span><span style="color: #400080;">NSWindow</span> <span style="color: #002200;">*</span>window;
<span style="color: #a61390;">@property</span><span style="color: #002200;">&#40;</span>retain<span style="color: #002200;">&#41;</span>MSZLinkedView <span style="color: #002200;">*</span>currentView;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>nextView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>previousView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<h2>Method breakdown of the AppDelegate</h2>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSView</span> <span style="color: #002200;">*</span>contentView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self window<span style="color: #002200;">&#93;</span> contentView<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>contentView setWantsLayer<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>contentView addSubview<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self currentView<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    transition <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CATransition animation<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>transition setType<span style="color: #002200;">:</span>kCATransitionPush<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>transition setSubtype<span style="color: #002200;">:</span>kCATransitionFromLeft<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>ani <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObject<span style="color: #002200;">:</span>transition 
                                                    forKey<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;subviews&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>contentView setAnimations<span style="color: #002200;">:</span>ani<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h3>awakeFromNib</h3>

<p>The awakeFromNib first turns on Core Animation for the content view of the window.  It then adds the currently referenced &#8220;currentView&#8221; as a subview of the contentView.  Since we have already set up the &#8220;currentView&#8221; to have a frameOrigin of 0,0 I do not need to worry about setting the subview&#8217;s location.</p>

<p>&lt;</p>

<p>p>Next I build a CATransition animation.  Note that I have kept a reference to this animation as an ivar in the AppDelegate.  The reason for that will become apparent later.  Once the animation is built, I add it as the transition animation for the key &#8220;subviews&#8221; in the content view.  This transition animation will trigger whenever a subview is added, removed or replaced.</p>

<p>&lt;</p>

<p>p></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setCurrentView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>MSZLinkedView<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>newView
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>currentView<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        currentView <span style="color: #002200;">=</span> newView;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #400080;">NSView</span> <span style="color: #002200;">*</span>contentView <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self window<span style="color: #002200;">&#93;</span> contentView<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>contentView animator<span style="color: #002200;">&#93;</span> replaceSubview<span style="color: #002200;">:</span>currentView with<span style="color: #002200;">:</span>newView<span style="color: #002200;">&#93;</span>;
    currentView <span style="color: #002200;">=</span> newView;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h3>setCurrentView:(MSZLinkedView*)view</h3>

<p>The reason that I overrode this setter method is a matter of convenience.  Since I only ever wanted one view showing at any time, I can comfortably swap out the views whenever the setter for &#8220;currentView&#8221; is called.  I could do this in other places to the same effect but since I want to keep track of the current view it is ideal to handle both at the same time.  Therefore, whenever I want to switch the subviews I can pass the new view into the setCurrentView method and be done with it.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>nextView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self currentView<span style="color: #002200;">&#93;</span> nextView<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#91;</span>transition setSubtype<span style="color: #002200;">:</span>kCATransitionFromRight<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self setCurrentView<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self currentView<span style="color: #002200;">&#93;</span> nextView<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>previousView<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self currentView<span style="color: #002200;">&#93;</span> previousView<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#91;</span>transition setSubtype<span style="color: #002200;">:</span>kCATransitionFromLeft<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self setCurrentView<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self currentView<span style="color: #002200;">&#93;</span> previousView<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h3>nextView:(id)sender previousView:(id)sender</h3>

<p>Both of these methods perform the same function.  In each method I grab a reference to the current view and check that its previous/next is not nil.  This is only protective since each view should have already disabled the buttons that don&#8217;t have a link.</p>

<p>Once that check is complete, I simply call setCurrentView: passing it the appropriate view &#8212; either the next or previous based on the method called.  The setCurrentView: discussed above takes care of the rest.  Just before I change the view, however, I change the subtype for the transition.  This is the reason I keep a reference to the transition around.  I do this so that visually the transitions make sense.  The previous view comes in from the left and the next view comes in from the right.  While this step is not necessary, it does give a nicer spacial feel to the animation.</p>

<h2>Conclusion</h2>

<p>So where is the magic?  What makes the Core Animation transition happen?  All of that is in the AppDelegate&#8217;s awakeFromNib.  Simply setting the CATransition on the content view of the window takes care of all the animation.  The rest of the code is just to handle all of the switching of the subview.  You can play with the transitions very easily by change the type and subtype being set in the awakeFromNib of the AppDelegate.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/03/03/core-animation-tutorial-wizard-dialog-with-transitions/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: Window Shake Effect</title>
		<link>http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/</link>
		<comments>http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 18:06:52 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[animate window]]></category>
		<category><![CDATA[Login]]></category>
		<category><![CDATA[shake window]]></category>
		<category><![CDATA[vibrate]]></category>
		<category><![CDATA[vibrate window]]></category>
		<category><![CDATA[Window shake effect]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/</guid>
		<description><![CDATA[Core Animation is really the buzz among Cocoa developers these days and we are no different from the rest. Learning to do simple fades and frame movement is trivial, but figuring out the more complex effects is quite a challenge. We decided to venture out and try to create some really concise examples of effects [...]]]></description>
			<content:encoded><![CDATA[<p>Core Animation is really the buzz among Cocoa developers these days and we are no different from the rest. Learning to do simple fades and frame movement is trivial, but figuring out the more complex effects is quite a challenge. We decided to venture out and try to create some really concise examples of effects you might find used in Leopard. And while these effects may not be done with Core Animation where they are found in the OS, we&#8217;ve set out to duplicate them in Core Animation regardless. Our first challenge? Shaking a login window.</p>

<div align="center">
<img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-1.png' alt='Just Say No Window' title='Just Say No Window' />
</div>

<p><span id="more-28"></span></p>

<h2>Shaking To Say No</h2>

<p>If you have your system set up to auto-login, you&#8217;ve probably never seen this effect before. Simply put, when you enter your password in the login window when doing a manual login, if you fat-finger it, it will shake you off&#8211;which is to say it will shake side to side several times in succession. It&#8217;s really quite a clever and intuitive response to what is normally responded to with a dialog.</p>

<div align="center">
<img src='http://www.cimgf.com/wp-content/uploads/2008/02/login.jpg' alt='OS X Login' title='OS X Login' style="align: center;" />
</div>

<p>After a fair bit of research and tweaking some code we found in a <a href="http://www.cocoabuilder.com/archive/message/cocoa/2007/11/7/192496">CocoaBuilder post</a> written by <a href="http://bill.dudney.net/roller/objc/">Bill Dudney</a>, author of the upcoming <a href="http://www.pragprog.com/titles/bdcora">Core Animation for OS X: Creating Dynamic Compelling User Interfaces</a>, we came up with a very elegant and tight solution. We have provided an <a href='http://www.cimgf.com/wp-content/uploads/2008/02/justsayno.zip' title='Just Say No Demo Project'>example project you can download</a>, but here is the frame animation code.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CAKeyframeAnimation <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>shakeAnimation<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRect</span><span style="color: #002200;">&#41;</span>frame
<span style="color: #002200;">&#123;</span>
    CAKeyframeAnimation <span style="color: #002200;">*</span>shakeAnimation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>CAKeyframeAnimation animation<span style="color: #002200;">&#93;</span>;
&nbsp;
    CGMutablePathRef shakePath <span style="color: #002200;">=</span> CGPathCreateMutable<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
    CGPathMoveToPoint<span style="color: #002200;">&#40;</span>shakePath, <span style="color: #a61390;">NULL</span>, NSMinX<span style="color: #002200;">&#40;</span>frame<span style="color: #002200;">&#41;</span>, NSMinY<span style="color: #002200;">&#40;</span>frame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">int</span> index;
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>index <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>; index &lt; numberOfShakes; <span style="color: #002200;">++</span>index<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        CGPathAddLineToPoint<span style="color: #002200;">&#40;</span>shakePath, <span style="color: #a61390;">NULL</span>, NSMinX<span style="color: #002200;">&#40;</span>frame<span style="color: #002200;">&#41;</span> <span style="color: #002200;">-</span> frame.size.width <span style="color: #002200;">*</span> vigourOfShake, NSMinY<span style="color: #002200;">&#40;</span>frame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
        CGPathAddLineToPoint<span style="color: #002200;">&#40;</span>shakePath, <span style="color: #a61390;">NULL</span>, NSMinX<span style="color: #002200;">&#40;</span>frame<span style="color: #002200;">&#41;</span> <span style="color: #002200;">+</span> frame.size.width <span style="color: #002200;">*</span> vigourOfShake, NSMinY<span style="color: #002200;">&#40;</span>frame<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    CGPathCloseSubpath<span style="color: #002200;">&#40;</span>shakePath<span style="color: #002200;">&#41;</span>;
    shakeAnimation.path <span style="color: #002200;">=</span> shakePath;
    shakeAnimation.duration <span style="color: #002200;">=</span> durationOfShake;
    <span style="color: #a61390;">return</span> shakeAnimation;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>That&#8217;s really all there is to it. We&#8217;ve set some static variables in the <a href='http://www.cimgf.com/wp-content/uploads/2008/02/justsayno.zip' title='Just Say No Demo Project'>demo project</a> that are used to determine how many times to shake the window, how vigorously to shake it and how long the shake effect should take to complete. Play with these variables yourself to see a variation of this same shaking effect you find in the OS X login window.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
