<?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>MultiTouchup.com &#187; Tutorials</title>
	<atom:link href="http://multitouchup.com/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://multitouchup.com</link>
	<description>Explore Multitouch on the Flash platform.  Video tutorials and related content presented by Matt LeGrand</description>
	<lastBuildDate>Thu, 15 Mar 2012 21:56:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Building a Multitouch Paint Canvas (Video Tutorial)</title>
		<link>http://multitouchup.com/building-a-multitouch-paint-canvas-video-tutorial/</link>
		<comments>http://multitouchup.com/building-a-multitouch-paint-canvas-video-tutorial/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 11:45:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=720</guid>
		<description><![CDATA[<a href="http://multitouchup.com/building-a-multitouch-paint-canvas-video-tutorial/"><img src="http://multitouchup.com/wp-content/uploads/2010/03/drawing-1-300x205.jpg" style="border: medium groove white;" alt="drawing-1" title="drawing-1" width="300" height="205" class="alignright size-medium wp-image-732" /></a>Take off the horn-rim glasses and put your hair into a ponytail because we are building a multitouch paint canvas that may turn the artistic world upside down.  Ok,  maybe it's not that exciting, but in this tutorial we build a multitouch paintable canvas as well as a large color picker component.

Thanks for checking it out]]></description>
			<content:encoded><![CDATA[<p>Take off the horn-rim glasses and put your hair into a ponytail because we are building a multitouch paint canvas that may turn the artistic world upside down.  Ok,  maybe it&#8217;s not that exciting, but in this tutorial we build a multitouch paintable canvas as well as a large color picker component.</p>
<p>Thanks for checking it out:</p>
<p style="text-align: center;">
<a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/drawing.flv"><img class="size-medium wp-image-137 aligncenter" title="mapping" src="http://multitouchup.com/wp-content/uploads/2010/03/drawing-1.jpg" alt="drawing-1" title="drawing-1" width="589" height="404" style="border: medium groove white;" class="aligncenter size-full wp-image-732" /></a>
</p>
<p>Here is a link to a similar drawing application that James Ward did <a href="http://www.jamesward.com/2010/03/22/flex-paint-updated-to-flex-4/">on his blog</a>.  Thanks for keeping it real James.</p>
<p>And here is a <a href="http://multitouchup.com/project_files/Drawable.zip">zip file</a> of the entire application.</p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/building-a-multitouch-paint-canvas-video-tutorial/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Intro to Multitouch Presentation (Video Screencast)</title>
		<link>http://multitouchup.com/intro-to-multitouch-presentation-video-screencast/</link>
		<comments>http://multitouchup.com/intro-to-multitouch-presentation-video-screencast/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 12:12:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=447</guid>
		<description><![CDATA[<a href="http://multitouchup.com/?p=447"><img style="border:medium groove white;" class="alignright size-medium wp-image-448" title="MultiTouchPresentation" src="http://multitouchup.com/wp-content/uploads/2010/03/MultiTouchPresentation-300x200.jpg" alt="MultiTouchPresentation" width="300" height="200" /></a>Hey guys,  I'd like to post this presentation that I worked on recently.  I think it'll be a great jumping off point for people that aren't familiar with the new multitouch capabilities in Flash.]]></description>
			<content:encoded><![CDATA[<p>Hey guys,  I&#8217;d like to post this presentation that I worked on recently.  I think it&#8217;ll be a great jumping off point for people that aren&#8217;t familiar with the new multitouch capabilities in Flash.</p>
<p>It&#8217;s mostly just me talking through my slides but the presentation uses an Adobe Air application that I cooked up.  The application uses multitouch by connecting to my iPhone over a UDP socket connection.  Fun stuff.</p>
<p><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/mtPresentation.flv"><img class="aligncenter size-full wp-image-395" style="border: medium groove white;" title="Preso" src="http://multitouchup.com/wp-content/uploads/2010/03/MultiTouchPresentation.jpg" alt="Preso" width="500" height="333" /></a></p>
<p>I&#8217;d also recommend people go back and check out some of the first multitouch tutorials I did where we trace out some of the new touch events as well as the new transform gesture events.  </p>
<p>Here&#8217;s a link to demos and the actual presentation on <a href="http://github.com/mlegrand/360-Flex-Presentation-Material-">github</a></p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/intro-to-multitouch-presentation-video-screencast/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://multitouchup.com/flvs/mtPresentation.flv" length="277978194" type="video/x-flv" />
		</item>
		<item>
		<title>SimTouch &#8211; Multitouch Simulator (Screencast)</title>
		<link>http://multitouchup.com/simtouch-multitouch-simulator-screencast/</link>
		<comments>http://multitouchup.com/simtouch-multitouch-simulator-screencast/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 07:53:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=404</guid>
		<description><![CDATA[<a href="http://multitouchup.com/?p=404"><img style="border:medium groove white;" class="alignright size-full wp-image-395" title="SimTouch" src="http://multitouchup.com/wp-content/uploads/2010/02/simTouch.jpg" alt="SimTouch" width="300" height="167" /></a>I'm currently working on a second version of SimTouch. SimTouch is a multitouch simulator that sits over on top of the application that your working on to simulate multiple touch events. If you don't have multitouch capable hardware, SimTouch is a great tool to allow you to develop multitouch software. However, more commonly, developers with capable hardware prefer to use a simulator for quick and dirty testing while they progressively develop their applications.]]></description>
			<content:encoded><![CDATA[<p><a href="http://multitouchup.com/wp-content/uploads/2010/02/sim_touch_logo_128.png"><img class="alignright size-full wp-image-423" title="sim_touch_logo_128" src="http://multitouchup.com/wp-content/uploads/2010/02/sim_touch_logo_128.png" alt="sim_touch_logo_128" width="128" height="128" /></a>I&#8217;m currently working on a second version of SimTouch.  SimTouch is a multitouch simulator that sits on top of the application that your working on to simulate multiple touch events.  If you don&#8217;t have multitouch capable hardware, SimTouch is a great tool to allow you to develop multitouch software.  However, more commonly, developers with capable hardware prefer to use a simulator for quick and dirty testing while they progressively develop their applications.</p>
<p>The current version of <a href="http://code.google.com/p/simtouch/">SimTouch</a> requires an additional socket server and communicates via the <a href="http://tuio.org/">TUIO</a> protocol.  The newest version will contain it&#8217;s own socket server (thank you Air 2) and be able to dispatch native Flash touch events.  I&#8217;m expecting to wrap up some sort of working version by March 1st.</p>
<p>Here is a quick screencast of some of the features:</p>
<p><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/SimTouch.flv"><img class="aligncenter size-full wp-image-395" title="SimTouch" src="http://multitouchup.com/wp-content/uploads/2010/02/simTouch.jpg" alt="SimTouch" width="501" height="278" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/simtouch-multitouch-simulator-screencast/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rotatable Scalable (Part 2)</title>
		<link>http://multitouchup.com/rotatable-scalable-part-2/</link>
		<comments>http://multitouchup.com/rotatable-scalable-part-2/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 03:20:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=391</guid>
		<description><![CDATA[<a href="http://multitouchup.com/?p=391"><img class="alignright size-full wp-image-395" title="RotatableScalable2" src="http://multitouchup.com/wp-content/uploads/2010/02/RotatableScalable2.jpg" alt="RotatableScalable2" width="300" height="168" /></a>In this video screencast we suffer through the lengthy addition of adding TouchEvents to our RotatableScalable class for multitouch use with action script display objects. We are largely copying and pasting code over from the orginal <a href="http://touchlib.googlecode.com/svn/trunk/AS3/int/app/core/action/RotatableScalable.as">RotatableScalable</a> class which you can find on the TouchLib open source project <a href="http://code.google.com/p/touchlib/">home</a>.   Our finished class is still far from perfect, but you can copy the current version which after the fold.  ]]></description>
			<content:encoded><![CDATA[<p>In this video screencast we suffer through the lengthy addition of adding TouchEvents to our RotatableScalable class for multitouch use with action script display objects. We are largely copying and pasting code over from the orginal <a href="http://touchlib.googlecode.com/svn/trunk/AS3/int/app/core/action/RotatableScalable.as">RotatableScalable</a> class which you can find at the TouchLib open source project <a href="http://code.google.com/p/touchlib/">home</a>.  Our finished class is still far from perfect, but you can copy the current version which is following the video.</p>
<p><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/RS2.flv"><img class="aligncenter size-full wp-image-395" title="RotatableScalable2" src="http://multitouchup.com/wp-content/uploads/2010/02/RotatableScalable2.jpg" alt="RotatableScalable2" width="500" height="279" /></a></p>
<p>RotatableScalable:</p>
<pre lang="”ACTIONSCRIPT”" colla="+">

package com.mlegrand
{
 import flash.display.DisplayObject;
 import flash.events.Event;
 import flash.events.TouchEvent;
 import flash.events.TransformGestureEvent;
 import flash.geom.Matrix;
 import flash.geom.Point;

 ///////////////////////////////////////////////////////////////////////////////////////
 //
 //  Original class can be found at :
 //  http://touchlib.googlecode.com/svn/trunk/AS3/int/app/core/action/RotatableScalable.as
 //
 //////////////////////////////////////////////////////////////////////////////////////

 public class RotatableScalable
 {
 //States
 protected static const NONE:String = 'none';
 protected static const DRAGGING:String = 'dragging';
 protected static const ROTATE_SCALE:String = 'rotateScale';

 //
 protected static const GRAD_PI:Number = 180/3.14159;
 protected static const HALF:Number = 0.5;

 protected var displayO:DisplayObject;

 protected var blobs : Array = [];
 protected var blob1 : Object;
 protected var blob2 : Object;
 protected var pointMap : Object = {};

 protected var state:String;
 protected var curScale:Number;
 protected var curAngle:Number;
 protected var curPosition:Point = new Point(0,0);

 protected var point1:Object;
 protected var point2:Object;

 protected var dX:Number;
 protected var dY:Number;
 protected var dAng:Number;

 protected var _rp:Point = new Point();

 //
 // Properties
 //
 public var draggable:Boolean;

 public function RotatableScalable(displayObject:DisplayObject)
 {
 displayO = displayObject;
 state = NONE;
 blobs = new Array();
 dX = 0;
 dY = 0;
 dAng = 0;
 addGestureEventListeners();
 addTouchEventListeners();
 }

 //
 //  Event Listeners
 //

 protected function addGestureEventListeners():void
 {
 displayO.addEventListener(TransformGestureEvent.GESTURE_ROTATE,
 onGestureRotate);
 displayO.addEventListener(TransformGestureEvent.GESTURE_ZOOM,
 onGesturePinch);
 }

 protected function addTouchEventListeners():void
 {
 displayO.addEventListener( TouchEvent.TOUCH_BEGIN, onTouchBegin );
 displayO.addEventListener( TouchEvent.TOUCH_END, onTouchEnd );
 displayO.addEventListener( TouchEvent.TOUCH_MOVE, onTouchMove );
 displayO.addEventListener( Event.ENTER_FRAME, update );

 displayO.addEventListener(TransformGestureEvent.GESTURE_ROTATE,
 onGestureRotate);
 displayO.addEventListener(TransformGestureEvent.GESTURE_ZOOM,
 onGesturePinch);
 }

 //
 //  Gesture Event Handlers
 //

 private function onGesturePinch(pinchEvent:TransformGestureEvent):void{

 pinchEvent.stopImmediatePropagation()
 var pinchMatrix:Matrix = displayO.transform.matrix;
 var pinchPoint:Point =
 pinchMatrix.transformPoint(
 new Point((displayO.width/2), (displayO.height/2)));
 pinchMatrix.translate(-pinchPoint.x, -pinchPoint.y);
 pinchMatrix.scale(pinchEvent.scaleX, pinchEvent.scaleY);
 pinchMatrix.translate(pinchPoint.x, pinchPoint.y);
 displayO.transform.matrix = pinchMatrix;
 }

 private function onGestureRotate(rotateEvent:TransformGestureEvent):void
 {
 rotateEvent.stopImmediatePropagation()
 var rotateMatrix:Matrix = displayO.transform.matrix;
 var rotatePoint:Point =
 rotateMatrix.transformPoint(
 new Point((displayO.width/2), (displayO.height/2)));
 rotateMatrix.translate(-rotatePoint.x, -rotatePoint.y);
 rotateMatrix.rotate(rotateEvent.rotation*(Math.PI/180));
 rotateMatrix.translate(rotatePoint.x, rotatePoint.y);
 displayO.transform.matrix = rotateMatrix ;
 }

 //
 //  Touch Event Handlers
 //

 private function onTouchBegin( event : TouchEvent ) : void
 {
 var p:Point;
 if(event.stageX == 0 &amp;&amp; event.stageY == 0)
 {
 p = new Point(event.localX, event.localY);
 }
 else
 {
 p = new Point(event.stageX, event.stageY);
 }
 event.stopImmediatePropagation();
 pointMap[ event.touchPointID.toString() ] = p;
 addBlob( event.touchPointID, p.x, p.y );
 }

 private function onTouchEnd( event : TouchEvent ) : void
 {
 event.stopImmediatePropagation()
 removeBlob( event.touchPointID );
 delete pointMap[ event.touchPointID.toString() ];
 }

 private function onTouchMove( event : TouchEvent ) : void
 {
 event.stopImmediatePropagation()
 var p:Point;
 if(event.stageX == 0 &amp;&amp; event.stageY == 0)
 {
 p = new Point(event.localX, event.localY);
 }
 else
 {
 p = new Point(event.stageX, event.stageY);
 }

 if ( pointMap[ event.touchPointID.toString() ] )
 {
 pointMap[ event.touchPointID.toString() ].x = p.x;
 pointMap[ event.touchPointID.toString() ].y = p.y;
 }
 update(null)
 }

 private function addBlob(id:Number, origX:Number, origY:Number):void
 {
 for(var i:int=0; i&lt;blobs.length; i++)
 {
 if(blobs[i].id == id)
 return;
 }

 blobs.push( {id: id, origX: origX, origY: origY, myOrigX: displayO.x, myOrigY:displayO.y} );

 if(blobs.length == 1)
 {                
 state = DRAGGING;
 curScale = displayO.scaleX;
 curAngle = displayO.rotation;                    
 curPosition.x = displayO.x;
 curPosition.y = displayO.y;                
 blob1 = blobs[0];
 }
 else if(blobs.length == 2)
 {
 state = ROTATE_SCALE;
 curScale = displayO.scaleX;
 curAngle = displayO.rotation;                    
 curPosition.x = displayO.x;
 curPosition.y = displayO.y;        

 blob1 = blobs[0];                                
 blob2 = blobs[1];        

 var tuioobj1 : Object = pointMap[ blob1.id ];
 var tuioobj2 : Object = pointMap[ blob2.id ];

 var midPoint:Point = Point.interpolate(displayO.globalToLocal(new Point(tuioobj1.x, tuioobj1.y)),displayO.globalToLocal(new Point(tuioobj2.x, tuioobj2.y)),0.5);

 setRegistration(midPoint.x,midPoint.y);

 // if not found, then it must have died..
 if(tuioobj1)
 {
 var curPt1:Point = displayO.parent.globalToLocal(new Point(tuioobj1.x, tuioobj1.y));                                    
 blob1.origX = curPt1.x;
 blob1.origY = curPt1.y;
 }                

 }

 }

 private function removeBlob(id:Number):void
 {
 for(var i:int=0; i&lt;blobs.length; i++)
 {
 if(blobs[i].id == id)
 {
 blobs.splice(i, 1);

 if(blobs.length == 0)
 state = NONE;
 if(blobs.length == 1)
 {
 state = DRAGGING;                    

 curScale = displayO.scaleX;
 curAngle = displayO.rotation;                    
 curPosition.x = displayO.x;
 curPosition.y = displayO.y;                    

 blob1 = blobs[0];        

 var tuioobj1 : Object = pointMap[ blob1.id ];

 if(tuioobj1)
 {                        
 var curPt1:Point = displayO.parent.globalToLocal(new Point(tuioobj1.x, tuioobj1.y));

 blob1.origX = curPt1.x;
 blob1.origY = curPt1.y;
 }

 }
 if(blobs.length &gt;= 2) {
 state = ROTATE_SCALE;

 curScale = displayO.scaleX;
 curAngle = displayO.rotation;                    
 curPosition.x = displayO.x;
 curPosition.y = displayO.y;                

 blob1 = blobs[0];                                
 blob2 = blobs[1];        

 tuioobj1 = pointMap[ blob1.id ];

 if(tuioobj1)
 {
 curPt1 = displayO.parent.globalToLocal(new Point(tuioobj1.x, tuioobj1.y));                        
 blob1.origX = curPt1.x;
 blob1.origY = curPt1.y;
 }                                    
 }
 return;                    
 }
 }            
 }

 private function getAngleTrig(X:Number, Y:Number): Number
 {
 if (X == 0.0)
 {
 if(Y &lt; 0.0)
 return 270;
 else
 return 90;
 } else if (Y == 0)
 {
 if(X &lt; 0)
 return 180;
 else
 return 0;
 }

 if ( Y &gt; 0.0)
 if (X &gt; 0.0)
 return Math.atan(Y/X) * GRAD_PI;
 else
 return 180.0-Math.atan(Y/-X) * GRAD_PI;
 else
 if (X &gt; 0.0)
 return 360.0-Math.atan(-Y/X) * GRAD_PI;
 else
 return 180.0+Math.atan(-Y/-X) * GRAD_PI;
 }         

 private function update(e:Event):void
 {

 if(state == DRAGGING)
 {
 var tuioobj:Object = pointMap[ blob1.id ];

 if(!tuioobj)
 {
 removeBlob(blob1.id);
 return;
 }

 var curPt:Point = displayO.parent.globalToLocal(new Point(tuioobj.x, tuioobj.y));  

 var oldX:Number, oldY:Number;
 oldX = displayO.x;
 oldY = displayO.y;

 displayO.x = (curPosition.x + (curPt.x - (blob1.origX )) &gt; 0)? curPosition.x + (curPt.x - (blob1.origX ))  : 0 ;        
 displayO.y = (curPosition.y + (curPt.y - (blob1.origY )) &gt; 0)? curPosition.y + (curPt.y - (blob1.origY ))  : 0;

 dX *= HALF;
 dY *= HALF;                        
 dAng *= HALF;
 dX += displayO.x - oldX;
 dY += displayO.y - oldY;        

 }
 else if(state == ROTATE_SCALE)
 {

 var tuioobj1 : Object = pointMap[ blob1.id ];

 if(!tuioobj1)
 {
 removeBlob(blob1.id);
 return;
 }                

 var curPt1:Point = displayO.parent.globalToLocal(new Point(tuioobj1.x, tuioobj1.y));                                

 var tuioobj2 : Object = pointMap[ blob2.id ];
 // if not found, then it must have died..
 if(!tuioobj2)
 {
 removeBlob(blob2.id);
 return;
 }                                

 var curPt2:Point = displayO.parent.globalToLocal(new Point(tuioobj2.x, tuioobj2.y));                
 var curCenter:Point = Point.interpolate(curPt1, curPt2, 0.5);    

 var origPt1:Point = new Point(blob1.origX, blob1.origY);
 var origPt2:Point = new Point(blob2.origX, blob2.origY);
 var centerOrig:Point = Point.interpolate(origPt1, origPt2, 0.5);
 var offs:Point = curCenter.subtract(centerOrig);

 var len1:Number = Point.distance(origPt1, origPt2);
 var len2:Number = Point.distance(curPt1, curPt2);                    
 var len3:Number = Point.distance(origPt1, new Point(0,0));

 var newscale:Number = curScale * len2 / len1;

 if(newscale&lt;4)
 {

 setProperty2('scaleX', newscale);
 setProperty2('scaleY', newscale);
 }
 var origLine:Point = origPt1;
 origLine = origLine.subtract(origPt2);

 var ang1:Number = getAngleTrig(origLine.x, origLine.y);

 var curLine:Point = curPt1;
 curLine = curLine.subtract(curPt2);

 var ang2:int = getAngleTrig(curLine.x, curLine.y);
 var oldAngle:int = displayO.rotation;

 setProperty2("rotation", curAngle + (ang2 - ang1));    

 oldX = displayO.x;
 oldY = displayO.y;

 dX *= HALF;
 dY *= HALF;        
 dAng *= HALF;                

 dX += displayO.x - oldX;
 dY += displayO.y - oldY;

 dAng += displayO.rotation - oldAngle;

 } else {
 if(dX != 0 || dY != 0)
 {
 //this.released(dX, dY, dAng);
 dX = 0;
 dY = 0;
 dAng = 0;
 }
 }

 }    

 public function setRegistration(x:Number=0, y:Number=0):void{
 _rp = new Point(x, y);
 }

 public function setProperty2(prop:String, n:Number):void{
 var a:Point = new Point();
 var b:Point = new Point();
 if(displayO.parent != null){
 a = displayO.parent.globalToLocal(displayO.localToGlobal(_rp));
 displayO[prop] = n;
 b = displayO.parent.globalToLocal(displayO.localToGlobal(_rp));
 }else{
 a = displayO.localToGlobal(_rp);
 displayO[prop] = n;
 b = displayO.localToGlobal(_rp);
 }
 displayO.x -= b.x - a.x;
 displayO.y -= b.y - a.y;
 }
 }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/rotatable-scalable-part-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Making Flex DisplayObjects Zoom and Rotate (Multitouch Screencast)</title>
		<link>http://multitouchup.com/making-flex-displayobjects-zoom-and-rotate-multitouch-screencast/</link>
		<comments>http://multitouchup.com/making-flex-displayobjects-zoom-and-rotate-multitouch-screencast/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 12:50:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=357</guid>
		<description><![CDATA[<a href="http://multitouchup.com/?p=357"><img class="alignright size-full wp-image-358" title="RotatableScalable.mov" src="http://multitouchup.com/wp-content/uploads/2010/02/RotatableScalable.mov.jpg" alt="RotatableScalable.mov" width="300" height="220" /></a>I have a friend who once said that the image rotate and zoom application is the 'hello world' of multitouch.  I thought that was a pretty astute observation.  

In this video tutorial, we'll take a look at how to make any Flex component Rotatable and Scalable.  This class can be applied to images for the classic 'hello world' effect, but it can also be added to videos, data grids and containers making for a fun and engaging user experience.  

Video and code after the jump.]]></description>
			<content:encoded><![CDATA[<p>I have a friend who once said that the image rotate and zoom application is the &#8216;hello world&#8217; of multitouch.  I thought that was a pretty astute observation.  In part one (of two) in this video tutorial, we&#8217;ll take a look at how to make any Flex component Rotatable and Scalable.  This class can be applied to images for the classic &#8216;hello world&#8217; effect, but it can also be added to videos, data grids and containers making for a fun and engaging user experience.</p>
<p><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/RS.flv"><img class="aligncenter size-full wp-image-358" title="RotatableScalable.mov" src="http://multitouchup.com/wp-content/uploads/2010/02/RotatableScalable.mov.jpg" alt="RotatableScalable.mov" width="500" height="366" /></a></p>
<p>Here is the class that drives most of the application:</p>
<p>RotatableScalable:</p>
<pre lang=”ACTIONSCRIPT”  colla=”+”>

package com.mlegrand
{
	import flash.display.DisplayObject;
	import flash.events.TransformGestureEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;

	public class RotatableScalable
	{

		protected var disO:DisplayObject

		public function RotatableScalable(displayObject:DisplayObject)
		{
			disO = displayObject;
			if(Multitouch.supportsGestureEvents)
			{
				Multitouch.inputMode = MultitouchInputMode.GESTURE;
				addGestureEventListeners()
			}

		}

		protected function addGestureEventListeners():void
		{
			disO.addEventListener(TransformGestureEvent.GESTURE_ROTATE, gestureRotateHandler);
			disO.addEventListener(TransformGestureEvent.GESTURE_ZOOM, gestureZoomHandler);
		}

		protected function gestureRotateHandler(event:TransformGestureEvent) : void
		{
			event.stopImmediatePropagation();
			var m:Matrix = disO.transform.matrix;
			var p:Point = m.transformPoint(new Point(disO.width/2, disO.height/2));
			m.translate(-p.x, -p.y);
			m.rotate(event.rotation*(Math.PI/180));
			m.translate(p.x, p.y);
			disO.transform.matrix = m;
		}

		protected function gestureZoomHandler(event:TransformGestureEvent):void
		{
			event.stopImmediatePropagation();
			var m:Matrix = disO.transform.matrix;
			var p:Point = m.transformPoint(new Point(disO.width/2, disO.height/2));
			m.translate(-p.x, -p.y);
			m.scale(event.scaleX, event.scaleY);
			m.translate(p.x, p.y);
			disO.transform.matrix = m;
		}

	}
}
</pre>
<p>Other notes:</p>
<p>I noticed the matrix transform over at <a href="http://justinimhoff.com/flash-multitouch-gesture-example/">Justin Imhoff&#8217;s blog</a>.  I highly recommend that you add his blog to your feed reader.  I also mentioned the <a href="http://justinimhoff.com/flash-multitouch-gesture-example/">Natural User Interface Group</a>.  Their <a href="http://nuigroup.com/forums">forums</a> are very active and may have helpful ideas for anyone interested in multitouch development.</p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/making-flex-displayobjects-zoom-and-rotate-multitouch-screencast/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Multitouch Ripple Effect (Screencast)</title>
		<link>http://multitouchup.com/multitouch-ripple-effect-screencast/</link>
		<comments>http://multitouchup.com/multitouch-ripple-effect-screencast/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 17:58:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=193</guid>
		<description><![CDATA[This is short screencast showing how to build a multitouch water ripple effect using David Lenaerts's Shallow Water Container and pixel bender shadder classes.
<p/>
<a href="http://multitouchup.com/?p=193"><img class="aligncenter size-full wp-image-194" title="rippleEffect" src="http://multitouchup.com/wp-content/uploads/2010/01/rippleEffect.png" alt="rippleEffect" width="670" height="422" /></a>

Links and full code after the jump
]]></description>
			<content:encoded><![CDATA[<p>This is a short screencast showing how to build a multitouch water ripple effect using <a href="http://www.derschmale.com/">David Lenaerts&#8217;s</a> Shallow Water Container and pixel bender shadder classes.</p>
<p style="text-align: center;"><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/rippleEffect.flv"><img class="aligncenter size-full wp-image-194" title="rippleEffect" src="http://multitouchup.com/wp-content/uploads/2010/01/rippleEffect.png" alt="rippleEffect" width="670" height="422" /></a></p>
<p style="text-align: left;">
<p style="text-align: left;">Here&#8217;s David&#8217;s <a href="http://www.derschmale.com/2009/04/23/return-of-the-ripples-shallow-water-simulation-with-pixel-bender/">Blog post</a> and the <a href="http://www.derschmale.com/demo/rippler-v2/srcview/">source</a> for his flash app.</p>
<p style="text-align: left;">Here&#8217;s the code that we came up with for the screencast:</p>
<p style="text-align: center;">
<p style="text-align: left;">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;utf-8&#8243;?&gt;<br />
&lt;s:WindowedApplication xmlns:fx=&#8221;http://ns.adobe.com/mxml/2009&#8243;<br />
xmlns:s=&#8221;library://ns.adobe.com/flex/spark&#8221;<br />
xmlns:mx=&#8221;library://ns.adobe.com/flex/halo&#8221;<br />
width=&#8221;1010&#8243; height=&#8221;670&#8243; creationComplete=&#8221;windowedapplication1_creationCompleteHandler(event)&#8221;&gt;<br />
&lt;fx:Script&gt;<br />
&lt;![CDATA[<br />
import com.derschmale.fluids.ShallowWaterContainer;</p>
<p>import flash.events.TouchEvent;<br />
import flash.ui.Multitouch;<br />
import flash.ui.MultitouchInputMode;</p>
<p>import mx.events.FlexEvent;</p>
<p>protected var ripple:ShallowWaterContainer;</p>
<p>[Embed (source='CloudyWaves.jpg')]<br />
protected var CloudyWave:Class;</p>
<p>protected var touchMap : Array  = [];</p>
<p>protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void<br />
{<br />
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;<br />
addRipple();<br />
}</p>
<p>protected function addRipple() : void<br />
{<br />
ripple = new ShallowWaterContainer(1000,650, 200, 200);<br />
ui.addChild(ripple);<br />
ripple.timeStep = 1;<br />
ripple.viscosity =0.2;<br />
ripple.relaxation = 0.15;<br />
ripple.relaxationSteps = 2;</p>
<p>ripple.addChild(new CloudyWave());</p>
<p>this.addEventListener(TouchEvent.TOUCH_BEGIN, touchBeginHandler);<br />
this.addEventListener(TouchEvent.TOUCH_END, touchEndHandler);<br />
this.addEventListener(TouchEvent.TOUCH_MOVE, touchMoveHandler);<br />
}</p>
<p>protected function touchBeginHandler(event:TouchEvent):void<br />
{<br />
var key : String = event.touchPointID.toString();<br />
var touchPoint:Object = {};<br />
touchPoint.x = event.localX;<br />
touchPoint.y = event.localY;<br />
touchPoint.sizeX = event.sizeX;<br />
touchPoint.sizeY = event.sizeY;<br />
touchMap[ key ] = touchPoint;<br />
}</p>
<p>protected function touchEndHandler(event:TouchEvent):void<br />
{<br />
var key : String = event.touchPointID.toString();<br />
delete touchMap [ key ];<br />
}</p>
<p>protected function touchMoveHandler(event:TouchEvent):void<br />
{<br />
var key : String = event.touchPointID.toString();<br />
if(touchMap [ key ])<br />
{<br />
ripple.addVelocity( event.localX, event.localY,<br />
(event.localX &#8211; touchMap[key].x),<br />
(event.localY -  touchMap [ key ].y), 5, 1);<br />
ripple.addPressure(event.localX, event.localY, 7, 1);</p>
<p>// update touchpoint in map</p>
<p>touchMap[key].x = event.localX;<br />
touchMap[key].y = event.localY;<br />
touchMap[key].sizeX = event.sizeX;<br />
touchMap[key].sizeY = event.sizeY;<br />
}<br />
}<br />
]]&gt;<br />
&lt;/fx:Script&gt;<br />
&lt;fx:Declarations&gt;<br />
&lt;!&#8211; Place non-visual elements (e.g., services, value objects) here &#8211;&gt;<br />
&lt;/fx:Declarations&gt;</p>
<p>&lt;mx:UIComponent id=&#8221;ui&#8221; width=&#8221;100%&#8221; height=&#8221;100%&#8221; /&gt;</p>
<p>&lt;/s:WindowedApplication&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/multitouch-ripple-effect-screencast/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Multi-touch Mapping (Screencast)</title>
		<link>http://multitouchup.com/multi-touch-mapping-screencast/</link>
		<comments>http://multitouchup.com/multi-touch-mapping-screencast/#comments</comments>
		<pubDate>Sun, 13 Dec 2009 03:40:42 +0000</pubDate>
		<dc:creator>mlegrand</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=136</guid>
		<description><![CDATA[<a href="http://www.cynergysystems.com/blogs/page/andrewtrice?entry=max_recap_multi_touch_development">Andrew Trice</a> gave a presentation at the Adobe Max conference talking about Multi-touch.
<p style="text-align: center;">
<a rel="shadowbox;height=720;width=1280" href="flvs/mapping.flv"><img class="size-medium wp-image-137 aligncenter" title="mapping" src="http://multitouchup.com/wp-content/uploads/2009/12/mapping-300x208.jpg" alt="mapping" width="300" height="208" /></a>
</p>
One of the presentations he gave was on using the new gesture events and the <a href="http://modestmaps.com/">Modest Maps</a> api to create a quick mapping application.

In this tutorial we take a closer look at some of that code.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cynergysystems.com/blogs/page/andrewtrice?entry=max_recap_multi_touch_development">Andrew Trice</a> gave a presentation at the Adobe Max conference talking about Multi-touch.</p>
<p style="text-align: center;">
<a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/mapping.flv"><img class="size-medium wp-image-137 aligncenter" title="mapping" src="http://multitouchup.com/wp-content/uploads/2009/12/mapping-300x208.jpg" alt="mapping" width="300" height="208" /></a>
</p>
<p>One of the presentations he gave was on using the new gesture events and the <a href="http://modestmaps.com/">Modest Maps</a> api to create a quick mapping application.</p>
<p>In this tutorial we take a closer look at some of that code.</p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/multi-touch-mapping-screencast/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Multi-Touch Eye Candy &#8211; Fire (Screencast)</title>
		<link>http://multitouchup.com/multi-touch-eye-candy-fire-screencast/</link>
		<comments>http://multitouchup.com/multi-touch-eye-candy-fire-screencast/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 17:05:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=115</guid>
		<description><![CDATA[<p>Howdy ladies and gentlemen,  </p>
<p>So in this tutorial we&#8217;re going to use a few blurs and color transforms to put together a fun multi-touch visual effect called Fire.  </p>
<p><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/PlayingWithFire.flv"><img src="http://multitouchup.com/wp-content/uploads/2009/12/PlayingWithFireH264.mov.png" alt="PlayingWithFire(H264).mov" title="PlayingWithFire(H264).mov" width="632" height="398" class="aligncenter size-full wp-image-116" /></a></p>
<p>Here&#8217;s&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>Howdy ladies and gentlemen,  </p>
<p>So in this tutorial we&#8217;re going to use a few blurs and color transforms to put together a fun multi-touch visual effect called Fire.  </p>
<p><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/PlayingWithFire.flv"><img src="http://multitouchup.com/wp-content/uploads/2009/12/PlayingWithFireH264.mov.png" alt="PlayingWithFire(H264).mov" title="PlayingWithFire(H264).mov" width="632" height="398" class="aligncenter size-full wp-image-116" /></a></p>
<p>Here&#8217;s the code for the fire class:</p>
<pre lang="actionscript" num="n" >
package fire
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.StageAlign;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TouchEvent;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.Capabilities;
	import flash.system.TouchscreenType;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;

	import mx.core.UIComponent;

	public class Fire extends UIComponent
	{
		protected var canvas:BitmapData;
		protected var canvasBitmap:Bitmap;

		protected var p1:Point;
		protected var p2:Point;
		protected var p3:Point;

		protected var r:Rectangle;
		protected var blobRect:Rectangle;

		protected var bf:BlurFilter;
		protected var ct:ColorTransform;
		protected var ct2:ColorTransform;

		protected var m:Matrix;
		protected var starterCanvasSize:Number = 400;

		protected var noise:BitmapData;

		public function Fire()
		{
			super();
			addEventListeners();
		}

		override protected function createChildren() : void
		{
			super.createChildren();
			canvas = new BitmapData(starterCanvasSize, starterCanvasSize, false, 0);
			canvasBitmap = new Bitmap(canvas);
			addChild(canvasBitmap);

			p1 = new Point();
			p2 = new Point();
			p3 = new Point();

			r = new Rectangle(0,0, canvas.width, 2);

			blobRect = new Rectangle();

			bf = new BlurFilter(6, 6, 1);

			ct = new ColorTransform(1.05, 1.03, 1.00, 1,-1, -1, -1, 0);
			ct2 = new ColorTransform(1, 1.25, 2.5);

			m = new Matrix();
			m.translate(0, -1);

			noise = new BitmapData(canvas.width, canvas.height);
			noise.perlinNoise(6, 6, 3, 7, false, false, 1|2|4, true);
		}

		protected function addEventListeners():void
		{
			if(stage)
			{
				addedToStage(null);
			}
			else
			{
				addEventListener(Event.ADDED_TO_STAGE, addedToStage);
			}

			addEventListener(MouseEvent.MOUSE_MOVE, updateFireOnMouseMove, false, 0, true);
			addEventListener(Event.ENTER_FRAME, updateFire, false, 0, true);

			if(Capabilities.touchscreenType == TouchscreenType.FINGER)
			{
				Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
				addEventListener(TouchEvent.TOUCH_BEGIN, touchEventHandler, false, 0, true);
				addEventListener(TouchEvent.TOUCH_END, touchEventHandler, false, 0, true);
				addEventListener(TouchEvent.TOUCH_MOVE, touchEventHandler, false, 0, true);
			}
		}

		protected function updateFireOnMouseMove(event:MouseEvent):void
		{
			r.y = (r.y+1) % noise.height;
			if(stage)
			{
				drawBlob( 1, event.stageX, event.stageY);
			}
			//blur
			canvas.applyFilter(canvas, canvas.rect, p1, bf);
			canvas.draw(canvas, m, ct);
		}

		protected function touchEventHandler(event:TouchEvent):void
		{
			r.y = (r.y+1) % noise.height;
			if(stage)
			{
				drawBlob(event.touchPointID, event.stageX, event.stageY);
			}
			//blur
			canvas.applyFilter(canvas, canvas.rect, p1, bf);
			canvas.draw(canvas, m, ct);
		}

		protected function addedToStage(event:Event):void
		{
			stage.addEventListener(Event.RESIZE, stageResized, false, 0, true);
			removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
			stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
		}

		protected function stageResized(event:Event):void
		{
			stage.align = StageAlign.TOP_LEFT;
			canvasBitmap.width = stage.width;
			canvasBitmap.height = stage.height;
		}

		protected function drawBlob(id:int, mx:Number, my:Number) : void
		{
			p3.x = int(mx * starterCanvasSize/stage.stageWidth) - 4;
			p3.y = int(my* starterCanvasSize/stage.stageHeight) - 4;
			blobRect.left = p3.x;
			blobRect.top = p3.y;
			blobRect.bottom = p3.y + 8;
			blobRect.right = p3.x + 8;
			var m2:Matrix = new Matrix();
			m2.translate(p3.x, p3.y);
			canvas.draw(noise, m2, ct2, BlendMode.ADD, blobRect);
		}

		protected function updateFire(event:Event):void
		{
			r.y = (r.y+1) % noise.height;
			canvas.applyFilter(canvas, canvas.rect, p1, bf);
			canvas.draw(canvas, m, ct);
		}
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/multi-touch-eye-candy-fire-screencast/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Check Out Two New Multi-Touch Events in Air 2 (Screencast)</title>
		<link>http://multitouchup.com/check-out-two-new-multi-touch-events-in-air-2-screencast/</link>
		<comments>http://multitouchup.com/check-out-two-new-multi-touch-events-in-air-2-screencast/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 02:49:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://multitouchup.com/?p=108</guid>
		<description><![CDATA[<p>In this tutorial we take a quick look into our users multi-touch capabilities and also display some of the new events for multi-touch in the brand new Air 2.</p>
<p style="text-align: center;"><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/TouchTrace.flv"><img class="size-full wp-image-110 aligncenter" title="Check Out Two New Multi-Touch Events in Air 2 (Screencast) « MultiTouchup.com" src="http://multitouchup.com/wp-content/uploads/2009/11/Check-Out-Two-New-Multi-Touch-Events-in-Air-2-Screencast-«-MultiTouchup.com.png" alt="Check Out Two New Multi-Touch Events in Air 2 (Screencast) « MultiTouchup.com" width="643" height="380" /></a></p>
&#8230;]]></description>
			<content:encoded><![CDATA[<p>In this tutorial we take a quick look into our users multi-touch capabilities and also display some of the new events for multi-touch in the brand new Air 2.</p>
<p style="text-align: center;"><a rel="shadowbox;height=720;width=1280" href="http://multitouchup.com/flvs/TouchTrace.flv"><img class="size-full wp-image-110 aligncenter" title="Check Out Two New Multi-Touch Events in Air 2 (Screencast) « MultiTouchup.com" src="http://multitouchup.com/wp-content/uploads/2009/11/Check-Out-Two-New-Multi-Touch-Events-in-Air-2-Screencast-«-MultiTouchup.com.png" alt="Check Out Two New Multi-Touch Events in Air 2 (Screencast) « MultiTouchup.com" width="643" height="380" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://multitouchup.com/check-out-two-new-multi-touch-events-in-air-2-screencast/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

