Windows Phone 7: Touch-based Gestures API in XNA Game Studio 4.0
Check out this great sample available in the XNA community site.
It includes code that uses the Gestures API to enable hold, drag, tap, flick, pinch gestures.
Check out this great sample available in the XNA community site.
It includes code that uses the Gestures API to enable hold, drag, tap, flick, pinch gestures.
I’ve just finished some experiments using the Windows Phone 7 emulator and the “Microsoft Surface Manipulations and Inertia Sample for Microsoft Silverlight” in order to enable Multi-Touch gestures using Blend Behaviors:
This new implementation, now available for download in the Expression Gallery, permits to enable Multi-Touch gestures (the usual translation, rotation, zoom and inertia) on separate User Controls available in the same container.
In this way you can apply distinct Multi-Touch manipulations (inertia included) to single elements using a single code in xaml:
<Grid x:Name="ContentPanel" Grid.Row="1">
<Canvas>
<Image Source="Images/Desert.jpg" x:Name="image1">
<interactivity:Interaction.Behaviors>
<WP7:MultiTouchManipulationBehavior IsInertiaEnabled="True" IsRotateEnabled="True" IsTranslateEnabled="True" IsScaleEnabled="True" MinimumScaleRadius="1" MaximumScaleRadius="720"/>
</interactivity:Interaction.Behaviors>
</Image>
<Image Source="Images/Jellyfish.jpg" x:Name="image2">
<interactivity:Interaction.Behaviors>
<WP7:MultiTouchManipulationBehavior IsInertiaEnabled="True" IsRotateEnabled="True" IsTranslateEnabled="True" IsScaleEnabled="True" MinimumScaleRadius="60" MaximumScaleRadius="360"/>
</interactivity:Interaction.Behaviors>
</Image>
</Canvas>
</Grid>
Alternatively you can use Blend inserting a reference to the project MultiTouch.Behaviors.Silverlight.WP7 and then dragging the MultiTouchManipulationBehavior from the Assets section to the control to be touch-enabled:
Considerations
This one has been an interesting exercise in porting code written for Silverlight to Windows Phone: I had only to create a Windows Phone 7 project and add to it the code already available for the Silverlight version and all worked well quite quickly.
Limitations
At this time the behavior works only in the fixed Portrait orientation of Windows Phone: if you change to Landscape the manipulation doesn’t work well. I’ll have to investigate further and currently I don’t have a physical device to test (I’d really love to have a device to try it
).
Happy Silverlighting!
Some time ago I’ve started a Codeplex project dedicated to multi-touch, available on Codeplex at http://multitouch.codeplex.com.
The goal of this project is to provide an unified interface for Silverlight, WPF and Windows Phone 7 in order to provide multi-touch support using a visual approach via the concept of Behavior available in Expression Blend.
Recently I had the honor to welcome in the project a pillar of the Silverlight community, Laurent Bugnion, who is working on the Windows Phone 7 version of the Behavior:
Laurent has just published on his blog two awesome videos to get started with this new Behavior, and has created a specific section on his site http://www.galasoft.ch/touch to announce updates and publish content.
A special thanks to Pete Blois of the Expression Blend team for his help and contributions.
Stay tuned as we’ll be posting updates very soon
Happy Silverlighting!
I’ve already blogged about adding multi-touch support to Silverlight applications using Blend behaviors (you can also read my italian language article).
This is a powerful and simple approach which is now available in WPF using Expression Blend 4 RC and the TranslateZoomRotateBehavior.
Let’s try to build a simple example:
1 – Open Expression Blend and create a new WPF project:
2 – Drag a Rectangle in the MainWindows.xaml:
3 – Let’s add multi-touch gestures and inertia effects to the rectangle selecting the Assets->Behavior tab and dragging the TranslateZoomRotateBehavior inside the rectangle:
4 – Let’s examine the Properties:
It’s possible to set the supported gestures (All, None, TranslateX, TranslateY, Rotate, Scale), the constrainToParentBounds modality, the Minimum, Maximum Scale and the Rotational and Translate Friction associated to the inertia.
Let’s select the constrainToParentBounds check box and run the project using the Project->Run Project menu:
Cool, Multi-touch and inertia effects are now enabled for the rectangle without writing a line of code!
And this is the generated xaml:
<Window xmlns="http://schemas.microsoft.com/winfx/ 2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/ 2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/ 2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/ 2010/interactions" x:Class="WpfApplication1.MainWindow" x:Name="Window" Title="MainWindow" UseLayoutRounding="True" Width="640" Height="480"> <Grid x:Name="LayoutRoot"> <Rectangle Margin="149,106,133,191" Stroke="Black"> <i:Interaction.Behaviors> <ei:TranslateZoomRotateBehavior ConstrainToParentBounds="True"/> </i:Interaction.Behaviors> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="Black" Offset="0"/> <GradientStop Color="#FF8F98CA" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> </Window>
The source code of the project is available for download here.
“The Microsoft Surface Toolkit for Windows Touch Beta is a set of controls, APIs, templates, sample applications and documentation currently available for Surface developers.
With the .NET Framework 4.0, Windows Presentation Framework 4.0 (WPF), and this toolkit, Windows Touch developers can quickly and consistently create advanced multitouch applications for Windows Touch PCs.
This toolkit also provides a jump-start for Surface application developers to prepare for the next version of Microsoft Surface. Use it to take advantage of the innovative Surface technology and user interface to develop your own rich and intuitive multitouch experiences for a variety of Windows Touch devices.”
Links:
Enjoy!
I’ve just updated the project on CodePlex http://multitouch.codeplex.com to Silverlight 4 RC and added a new sample of multi-touch using Windows Phone 7 manipulation capabilities starting from this how-to available in MSDN – “How to: Handle Manipulation Events” - http://msdn.microsoft.com/en-us/library/ff426933(VS.96).aspx.
The modified sample uses an Image to illustrate the possibility to move and scale objects in the Windows Phone emulator using the “ManipulationDelta” event:
These are the steps to follow in order to enable Scale and Translation gestures in a Windows Phone application:
<Canvas x:Name="ContentCanvas" Grid.Row="1">
<Image Source="Images/Desert.jpg" Canvas.Left="99" Canvas.Top="100"
x:Name="image1" Stretch="Fill" Width="300">
</Image>
</Canvas>
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
ManipulationDelta += image1_ManipulationDelta;
_compositeTransform=new CompositeTransform();
image1.RenderTransform = _compositeTransform;
}
private CompositeTransform _compositeTransform;
void image1_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// Scale
if (e.DeltaManipulation.Scale.X!=0)
_compositeTransform.ScaleX *= e.DeltaManipulation.Scale.X;
if (e.DeltaManipulation.Scale.Y!=0)
_compositeTransform.ScaleY *= e.DeltaManipulation.Scale.Y;
// Translation
_compositeTransform.TranslateX += e.DeltaManipulation.Translation.X;
_compositeTransform.TranslateY += e.DeltaManipulation.Translation.Y;
}
The source code is available for download from CodePlex: http://multitouch.codeplex.com
Happy Silverlighting!
I have already blogged about using Blend behaviors to add Multi-Touch gestures and inertia effects to a generic Silverlight user control, so I wanted to use the same approach to add the same behaviors to the CodePlex project Simon.
I think that inserting multi-touch manipulation effects to a Silverlight application using Blend behaviors is an elegant way which makes the code very clear and readable.
To start you need to download the Multi-touch manipulation and inertia behavior (wow, more than 7000 downloads, great feedback!
), which I already published on the Expression site.
This behavior is based on the code available in the Microsoft Surface Manipulations and Inertia Sample for Microsoft Silverlight, in my opinion the best example available for using multi-touch in Silverlight at this time.
The solution available contains a project named “MultiTouch.behaviors.Silverlight” which must be included in your application to enable the multi-touch functionalities.
To make the Silverlight/Blend Behavior work with Simon I’ve modified some code relative to the Zoom gesture in order to use a ScaleTransform (check out the source code on CodePlex: http://simon.codeplex.com).
To use the Behavior in XAML just add a reference to the “MultiTouch.Behaviors.Silverlight” project and use the following code:
<UserControl x:Class="SimonSilverlight.MainPage"
....
xmlns:interactivity="clr-namespace:System.Windows.Interactivity; assembly=System.Windows.Interactivity"
xmlns:multitouch="clr-namespace:MultiTouch.Behaviors.Silverlight; assembly=MultiTouch.Behaviors.Silverlight">
....
<Canvas>
<uc:Simon x:Name="Says">
<interactivity:Interaction.Behaviors>
<multitouch:MultiTouchManipulationBehavior InertiaEnabled="True" TouchRotateEnabled="True"
TouchScaleEnabled="True" TouchTranslateEnabled="True"/>
</interactivity:Interaction.Behaviors>
</uc:Simon>
</Canvas>
Since we are using a Blend Behavior, we can also open the solution in Expression Blend, select the “MultiTouchManipulationBehavior” from the “Assets” section and drag it over the Simon control:
Happy Silverlighting!
I’ve updated the behavior available in the Expression Community gallery adding Multi-Touch manipulation (translation, rotation and zoom) and inertia effects using code from the Surface Manipulations and Inertia Sample for Microsoft Silverlight.
To enable Multi-Touch in your code simply download the behavior from here, add the project “MultiTouch.Behaviors.Silverlight” to a Visual Studio solution and then enable the gestures in XAML:
<UserControl x:Class="SilverlightMultiTouch.MainPage"
...
xmlns:interactivity="clr-namespace:System.Windows.Interactivity; assembly=System.Windows.Interactivity"
xmlns:behaviors="clr-namespace:MultiTouch.Behaviors.Silverlight; assembly=MultiTouch.Behaviors.Silverlight"
...
>
<Canvas>
<Image Source="Images/Desert.jpg">
<interactivity:Interaction.Behaviors>
<behaviors:MultiTouchManipulationBehavior InertiaEnabled="True" TouchRotateEnabled="True" TouchTranslateEnabled="True" TouchScaleEnabled="True"/>
</interactivity:Interaction.Behaviors>
</Image>
<Image Source="Images/Jellyfish.jpg">
<interactivity:Interaction.Behaviors>
<behaviors:MultiTouchManipulationBehavior InertiaEnabled="True" TouchRotateEnabled="True" TouchTranslateEnabled="True" TouchScaleEnabled="True"/>
</interactivity:Interaction.Behaviors>
</Image>
</Canvas>
The MultiTouchManipulationBehavior also contains some dependency properties (TouchRotateEnabled, TouchTranslateEnabled, TouchScaleEnabled and InertiaEnabled) to enable the corresponding gestures.
The example contains Multi-Touch manipulations applied to some Image controls and a Smooth streaming player of the Silverlight Media Framework.
I’ve also posted to CodePlex a sample using WPF 4 based on the article “Introduction to WPF 4 Multitouch“ by Jaime Rodriguez.
Hope this helps and Happy Silverlighting!
I’ve published in the Expression gallery the Multi-Touch behaviors featuring Drag and Zoom gestures already posted on CodePlex.
The original article is available here.
I should insert new features in the next weeks, feel free to ping me for any suggestion
Update: A Silverlight / Expression Blend behavior to add Multi-Touch Manipulation and Inertia
In the previous post, I’ve described a basic example of WPF custom control for reusing multi-touch functionalities across applications. The same task can be achieved in Silverlight 3 using the new touch apis (check out this great article by Tim Heuer to get started), in addition we can use the new behaviors in order to write and simply reuse the code (a quick note: at this stage Silverlight 3 only supports basic touch events, gesture messages are not available).
To start I’ve added two simple behaviors named TouchDrag and TouchZoom to the Multi-Touch Codeplex project.
These new objects can be used in xaml by inserting the following code (the System.Windows.Interactivity namespace can be imported from the Expression Blend 3 SDK, already available if Blend 3 is installed):
<UserControl x:Class="SilverlightMultiTouch.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/ presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d= "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/ markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" Width="1280" Height="800"
xmlns:myControls="clr-namespace:MultiTouch.Controls.Silverlight; assembly=MultiTouch.Controls.Silverlight"
xmlns:behaviors="clr-namespace: MultiTouch.Controls.Silverlight.Behaviors; assembly=MultiTouch.Controls.Silverlight"
xmlns:interactivity="clr-namespace: System.Windows.Interactivity; assembly=System.Windows.Interactivity"
>
<Canvas Background="Black">
<!-- Example using Behaviors -->
<Canvas>
<interactivity:Interaction.Behaviors>
<behaviors:TouchDrag TouchDragEnabled="True"/>
<behaviors:TouchZoom TouchZoomEnabled="True"/>
</interactivity:Interaction.Behaviors>
<Image Source="Images/image.png" Height="597" Width="448" Canvas.Left="404" Canvas.Top="96"/>
</Canvas>
</Canvas>
</UserControl>
Have you seen the previous lines of code? The touch features are simply associated to the Image object using this xaml:
<interactivity:Interaction.Behaviors>
<behaviors:TouchDrag TouchDragEnabled="True"/>
<behaviors:TouchZoom TouchZoomEnabled="True"/>
</interactivity:Interaction.Behaviors>
The TouchDrag and TouchZoom behaviors can be defined in code-behind in this way:
TouchDrag.cs
public class TouchDrag : Behavior<FrameworkElement>
{
//Dependency property for enabling the TouchDrag
public static readonly DependencyProperty TouchDragEnabledProperty =
DependencyProperty.Register("TouchDragEnabled", typeof(bool), typeof(TouchDrag), new PropertyMetadata(false));
[Category("Target Properties")]
public bool TouchDragEnabled { get; set; }
//Occurs when the primary point is touched down
private bool _touchDown = false;
//Origin point
private Point _ptOrigin;
//Translate Transform
TranslateTransform _translateTransform;
/// Initialize the behavior
protected override void OnAttached()
{
base.OnAttached();
Touch.FrameReported += AssociatedObjectTouchFrameReported;
}
/// Occurs when detaching the behavior
protected override void OnDetaching()
{
base.OnDetaching();
Touch.FrameReported -= AssociatedObjectTouchFrameReported;
}
/// Touch Frame Handler
private void AssociatedObjectTouchFrameReported(object sender, TouchFrameEventArgs e)
{
//Handler for the Touch events
if (this.TouchDragEnabled)
{
if (e.GetPrimaryTouchPoint(AssociatedObject) != null)
{
switch (e.GetPrimaryTouchPoint( AssociatedObject).Action)
{
case TouchAction.Up:
this.AssociatedObjectTouchUp(sender, e);
break;
case TouchAction.Move:
this.AssociatedObjectTouchMove(sender, e);
break;
case TouchAction.Down:
this.AssociatedObjectTouchDown(sender, e);
break;
}
}
}
}
/// Touch Down Handler
private void AssociatedObjectTouchDown(object sender, TouchFrameEventArgs e)
{
this._touchDown = true;
this.AssociatedObject.Opacity = .75;
this._ptOrigin = e.GetPrimaryTouchPoint(AssociatedObject).Position;
//Initialize the Translate transform and the TransformGroup
if (this._translateTransform == null)
{
this._translateTransform = new TranslateTransform();
if ((this.AssociatedObject.RenderTransform == null) || !(this.AssociatedObject.RenderTransform is TransformGroup))
this.AssociatedObject.RenderTransform = new TransformGroup();
if (this.AssociatedObject.RenderTransform is TransformGroup)
(this.AssociatedObject.RenderTransform as TransformGroup).Children.Add( this._translateTransform);
}
//Suspend Mouse promotion
e.SuspendMousePromotionUntilTouchUp();
}
/// Handle the Touch movement
private void AssociatedObjectTouchMove(object sender, TouchFrameEventArgs e)
{
if (this._touchDown)
{
//Find the new position
Point newPosition = e.GetPrimaryTouchPoint(AssociatedObject.Parent as FrameworkElement).Position;
//Drag the Control using the TranslateTransform
this._translateTransform.X = (newPosition.X - _ptOrigin.X); this._translateTransform.Y = (newPosition.Y - _ptOrigin.Y);
}
}
/// Touch Up Handler
private void AssociatedObjectTouchUp(object sender, TouchFrameEventArgs e)
{
// turn off drag
this._touchDown = false;
AssociatedObject.Opacity = 1;
}
}
TouchZoom.cs:
public class TouchZoom : Behavior<FrameworkElement>
{
//Dependency property for enabling the TouchZoom
public static readonly DependencyProperty TouchDragEnabledProperty =
DependencyProperty.Register("TouchZoomEnabled", typeof(bool), typeof(TouchZoom), new PropertyMetadata(false));
[Category("Target Properties")]
public bool TouchZoomEnabled { get; set; }
//Occurs when the primary point is touched down
private bool _touchDown = false;
//Origin points
private TouchPointCollection _tpInitialPoints;
//ScaleTransform
ScaleTransform _scaleTransform;
/// Calculate the distance between two points
private double Distance(Point point1, Point point2)
{
try
{
return Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) + (point1.Y - point2.Y) * (point1.Y - point2.Y));
}
catch { return double.NaN; }
}
/// Calculate the MidPoint
private Point MidPoint(Point point1, Point point2)
{
return new Point((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
}
/// Initialize the behavior
protected override void OnAttached()
{
base.OnAttached();
Touch.FrameReported += AssociatedObjectTouchFrameReported;
}
/// Occurs when detaching the behavior
protected override void OnDetaching()
{
base.OnDetaching();
Touch.FrameReported -= AssociatedObjectTouchFrameReported;
}
/// Touch Frame Handler
private void AssociatedObjectTouchFrameReported(object sender, TouchFrameEventArgs e)
{
if (this.TouchZoomEnabled)
{
TouchPointCollection tpCollection = e.GetTouchPoints(this.AssociatedObject);
tpCollection.ToList().ForEach(tp =>
{
switch (tp.Action)
{
case TouchAction.Up:
this.AssociatedObjectTouchUp(sender, e);
break;
case TouchAction.Move:
this.AssociatedObjectTouchMove(sender, e);
break;
case TouchAction.Down:
this.AssociatedObjectTouchDown(sender, e);
break;
}
});
}
}
/// Touch Down Handler
private void AssociatedObjectTouchDown(object sender, TouchFrameEventArgs e)
{
//Initialize the parameters
this._touchDown = true;
this.AssociatedObject.Opacity = .75;
this._tpInitialPoints = e.GetTouchPoints(this.AssociatedObject);
//Initialize the Scale transform
if (this._scaleTransform == null)
{
this._scaleTransform = new ScaleTransform();
if ((this.AssociatedObject.RenderTransform == null) || !(this.AssociatedObject.RenderTransform is TransformGroup))
this.AssociatedObject.RenderTransform = new TransformGroup();
if (this.AssociatedObject.RenderTransform is TransformGroup)
(this.AssociatedObject.RenderTransform as TransformGroup).Children.Add( this._scaleTransform);
}
//TODO: e.SuspendMousePromotionUntilTouchUp();
}
/// Handle the Touch movement
private void AssociatedObjectTouchMove(object sender, TouchFrameEventArgs e)
{
if (this._touchDown)
{
//Find the new points
TouchPointCollection newPoints = e.GetTouchPoints(AssociatedObject.Parent as FrameworkElement);
if (newPoints!=null && this._tpInitialPoints!=null)
if (this._tpInitialPoints.Count == 2 && newPoints.Count == 2)
{
//Zoom the Control using the ScaleTransform
double ratio = this.Distance( newPoints.First().Position, newPoints.Last().Position) /
this.Distance( this._tpInitialPoints.First().Position, this._tpInitialPoints.Last().Position);
if (ratio != double.NaN)
{
Point midPoint = this.MidPoint( newPoints.First().Position, newPoints.Last().Position);
this._scaleTransform.CenterX = midPoint.X; this._scaleTransform.CenterY = midPoint.Y;
this._scaleTransform.ScaleX = ratio; this._scaleTransform.ScaleY = ratio;
}
}
}
}
/// Touch Up Handler
private void AssociatedObjectTouchUp(object sender, TouchFrameEventArgs e)
{
// turn off Zoom mode
this._touchDown = false;
this.AssociatedObject.Opacity = 1;
}
}
The behavior approach is very powerful, in this way you can share functionalities between Visual Studio and Expression Blend 3 in a simple way, making the code maintainable and simply reusable in different projects.
The source code is available for download on http://multitouch.codeplex.com.
If you have a multi-touch enabled devices, the demo application is available on-line here, featuring Drag and Zoom gestures.
Hope this helps and… happy Silverlighting!