Ajout du Drag de plusieurs image

master
cldupland 6 years ago
parent 6b249a7b42
commit e30805be57

@ -1,11 +1,11 @@
#pragma warning disable 1591 #pragma warning disable 1591
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Ce code a été généré par un outil. // This code was generated by a tool.
// Version du runtime :4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si // Changes to this file may cause incorrect behavior and will be lost if
// le code est régénéré. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

@ -71,10 +71,12 @@
<None Include="Entitlements.plist" /> <None Include="Entitlements.plist" />
<None Include="Info.plist" /> <None Include="Info.plist" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<None Include="Resources\Apple.png" />
<BundleResource Include="Resources\FontStyle\IndieFlower.ttf" /> <BundleResource Include="Resources\FontStyle\IndieFlower.ttf" />
<BundleResource Include="Resources\FontStyle\ENSOTYPE License &amp; FAQ - DO READ THIS!.pdf" /> <BundleResource Include="Resources\FontStyle\ENSOTYPE License &amp; FAQ - DO READ THIS!.pdf" />
<BundleResource Include="Resources\FontStyle\Ruhaniyat DEMO.otf" /> <BundleResource Include="Resources\FontStyle\Ruhaniyat DEMO.otf" />
<BundleResource Include="Resources\Apple.png">
<LogicalName>TheGameExtreme.iOS.Resources.Apple.png</LogicalName>
</BundleResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<InterfaceDefinition Include="Resources\LaunchScreen.storyboard" /> <InterfaceDefinition Include="Resources\LaunchScreen.storyboard" />

@ -21,7 +21,6 @@
<Folder Include="model\gameActions\extreme\" /> <Folder Include="model\gameActions\extreme\" />
<Folder Include="model\gameActions\classic\" /> <Folder Include="model\gameActions\classic\" />
<Folder Include="Media\" /> <Folder Include="Media\" />
<Folder Include="view\Image\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="model\effect\StopColm.cs" /> <Compile Remove="model\effect\StopColm.cs" />

@ -7,15 +7,20 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms" xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
xmlns:tt="clr-namespace:TouchTracking.Forms;assembly=TouchTracking.Forms" xmlns:tt="clr-namespace:TouchTracking.Forms;assembly=TouchTracking.Forms"
xmlns:local="clr-namespace:TheGameExtreme.view"
mc:Ignorable="d" mc:Ignorable="d"
x:Class="TheGameExtreme.view.MainPage"> x:Class="TheGameExtreme.view.MainPage">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition> <RowDefinition Height="10*"/>
<RowDefinition Height="*"></RowDefinition> <RowDefinition Height="90*"/>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="70*"/>
<ColumnDefinition Width="15*"/>
</Grid.ColumnDefinitions>
<Grid.Effects> <Grid.Effects>
<tt:TouchEffect <tt:TouchEffect
@ -27,42 +32,127 @@
<StackLayout
<Label Grid.Row="0"
x:Name="pseudo" Grid.Column="1">
Text="Pseudo" <Label
HorizontalTextAlignment="Center" x:Name="pseudo"
VerticalTextAlignment="Start" Text="Pseudo"
TextColor="{DynamicResource WhiteColor}" HorizontalTextAlignment="Center"
Margin="30" VerticalTextAlignment="Center"
FontSize="28" Grid.Row="0"/> TextColor="{DynamicResource WhiteColor}"
FontSize="28"/>
<ImageButton <Picker Title="Touch Mode"
Source="HomeIcon.png" Grid.Row="0"
HorizontalOptions="Start" SelectedIndexChanged="OnTouchModePickerSelectedIndexChanged">
VerticalOptions="Start" <Picker.ItemsSource>
WidthRequest="45" <x:Array Type="{x:Type local:TouchManipulationMode}">
Margin="20,20,0,0" <x:Static Member="local:TouchManipulationMode.None" />
HeightRequest="45" <x:Static Member="local:TouchManipulationMode.PanOnly" />
BackgroundColor="{DynamicResource BlackColor}" <x:Static Member="local:TouchManipulationMode.IsotropicScale" />
<x:Static Member="local:TouchManipulationMode.AnisotropicScale" />
<x:Static Member="local:TouchManipulationMode.ScaleRotate" />
<x:Static Member="local:TouchManipulationMode.ScaleDualRotate" />
</x:Array>
</Picker.ItemsSource>
<Picker.SelectedIndex>
4
</Picker.SelectedIndex>
</Picker>
</StackLayout>
<StackLayout
Grid.Row="0"
Grid.Column="0">
<ImageButton
Source="HomeIcon.png"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="45"
HeightRequest="45"
BackgroundColor="{DynamicResource BlackColor}"
Clicked="PlayToHome"/>
</StackLayout>
<StackLayout
Grid.Row="0" Grid.Row="0"
Clicked="PlayToHome"/> Grid.Column="2">
<Button
<Button Text="End Turn"
Text="End Turn" HorizontalOptions="End"
HorizontalOptions="End" VerticalOptions="Start"
VerticalOptions="Start" BackgroundColor="{DynamicResource SkyBlueColor}"
BackgroundColor="{DynamicResource SkyBlueColor}" HeightRequest="35"/>
HeightRequest="35" </StackLayout>
Margin="0,30,20,0"
Grid.Row="0"/>
<!--<Grid
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
</Grid.ColumnDefinitions>
<StackLayout
Grid.Column="0">
<Image
x:Name="pile1"
Source="UsersExiticon.png"
HeightRequest="45"
WidthRequest="45"/>
</StackLayout>
<StackLayout
Grid.Column="1">
<Image
x:Name="pile2"
Source="UsersExiticon.png"
HeightRequest="45"
WidthRequest="45"/>
</StackLayout>
<StackLayout
Grid.Column="2">
<Image
x:Name="pioche"
Source="UsersExiticon.png"
HeightRequest="45"
WidthRequest="45"/>
</StackLayout>
<StackLayout
Grid.Column="3">
<Image
x:Name="pile4"
Source="UsersExiticon.png"
HeightRequest="45"
WidthRequest="45"/>
</StackLayout>
<StackLayout
Grid.Column="4">
<Image
x:Name="pile5"
Source="UsersExiticon.png"
HeightRequest="45"
WidthRequest="45"/>
</StackLayout>
</Grid>-->
<skia:SKCanvasView <skia:SKCanvasView
x:Name="canvasView" x:Name="canvasView"
PaintSurface="OnCanvasViewPaintSurface" PaintSurface="OnCanvasViewPaintSurface"
Grid.Row="0" Grid.Row="0"
Grid.RowSpan="3"/> Grid.RowSpan="2"
Grid.Column="0"
Grid.ColumnSpan="3"/>

@ -19,17 +19,14 @@ namespace TheGameExtreme.view
{ {
private bool isFirst = true; private bool isFirst = true;
private Main viewmodel; private Main viewmodel;
private List<CheckBox> stacks = new List<CheckBox>(); private List<SKRect> stacks = new List<SKRect>();
Button button = new Button(); Button button = new Button();
List<string> playersNames; List<string> playersNames;
SKBitmap bitmap; TouchManipulationBitmap bitmap;
SKBitmap bitmap2; List<TouchManipulationBitmap> bitmapCollection = new List<TouchManipulationBitmap>();
SKMatrix matrix = SKMatrix.MakeIdentity(); Dictionary<long, TouchManipulationBitmap> bitmapDictionary = new Dictionary<long, TouchManipulationBitmap>();
// Touch information
long touchId = -1;
SKPoint previousPoint;
public MainPage(List<string> playersNames) public MainPage(List<string> playersNames)
@ -39,17 +36,29 @@ namespace TheGameExtreme.view
InitializeComponent(); InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false); NavigationPage.SetHasNavigationBar(this, false);
string resourceID = "TheGameExtreme.Media.thegame.jpg";
string resourceID2 = "TheGameExtreme.Media.moon.jpg";
Assembly assembly = GetType().GetTypeInfo().Assembly; Assembly assembly = GetType().GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(resourceID); string[] resourceIDs = assembly.GetManifestResourceNames();
bitmap = SKBitmap.Decode(stream);
Stream stream2 = assembly.GetManifestResourceStream(resourceID2); SKPoint position = new SKPoint();
bitmap2 = SKBitmap.Decode(stream2);
foreach (string resourceID in resourceIDs)
{
if (resourceID.EndsWith(".png") ||
resourceID.EndsWith(".jpg"))
{
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
SKBitmap bitmap = SKBitmap.Decode(stream);
bitmapCollection.Add(new TouchManipulationBitmap(bitmap)
{
Matrix = SKMatrix.MakeTranslation(position.X, position.Y),
});
position.X += 100;
position.Y += 100;
}
}
}
//stacks.Add(checkbox0); //stacks.Add(checkbox0);
@ -75,60 +84,76 @@ namespace TheGameExtreme.view
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) // Faire plusieurs canvas void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) // Faire plusieurs canvas
{ {
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
SKCanvas canvas = args.Surface.Canvas;
canvas.Clear(); canvas.Clear();
// Display the bitmap foreach (TouchManipulationBitmap bitmap in bitmapCollection)
canvas.SetMatrix(matrix); {
canvas.DrawBitmap(bitmap, new SKPoint()); bitmap.Paint(canvas);
//canvas.DrawBitmap(bitmap2, new SKPoint(500, 500)); }
} }
void OnTouchEffectAction(object sender, TouchActionEventArgs args) void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{ {
// Convert Xamarin.Forms point to pixels // Convert Xamarin.Forms point to pixels
TouchTrackingPoint pt = args.Location; TouchTrackingPoint pt = args.Location;
SKPoint point = SKPoint point =
new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width), new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
(float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height)); (float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
switch (args.Type) switch (args.Type)
{ {
case TouchActionType.Pressed: case TouchActionType.Pressed:
// Find transformed bitmap rectangle for (int i = bitmapCollection.Count - 1; i >= 0; i--)
SKRect rect = new SKRect(0, 0, bitmap.Width, bitmap.Height); {
rect = matrix.MapRect(rect); TouchManipulationBitmap bitmap = bitmapCollection[i];
// Determine if the touch was within that rectangle if (bitmap.HitTest(point))
if (rect.Contains(point))
{ {
touchId = args.Id; // Move bitmap to end of collection
previousPoint = point; bitmapCollection.Remove(bitmap);
} bitmapCollection.Add(bitmap);
break;
case TouchActionType.Moved: // Do the touch processing
if (touchId == args.Id) bitmapDictionary.Add(args.Id, bitmap);
{ bitmap.ProcessTouchEvent(args.Id, args.Type, point);
// Adjust the matrix for the new position
matrix.TransX += point.X - previousPoint.X;
matrix.TransY += point.Y - previousPoint.Y;
previousPoint = point;
canvasView.InvalidateSurface(); canvasView.InvalidateSurface();
break;
} }
break; }
break;
case TouchActionType.Released: case TouchActionType.Moved:
case TouchActionType.Cancelled: if (bitmapDictionary.ContainsKey(args.Id))
touchId = -1; {
break; TouchManipulationBitmap bitmap = bitmapDictionary[args.Id];
} bitmap.ProcessTouchEvent(args.Id, args.Type, point);
canvasView.InvalidateSurface();
}
break;
case TouchActionType.Released:
case TouchActionType.Cancelled:
if (bitmapDictionary.ContainsKey(args.Id))
{
TouchManipulationBitmap bitmap = bitmapDictionary[args.Id];
bitmap.ProcessTouchEvent(args.Id, args.Type, point);
bitmapDictionary.Remove(args.Id);
canvasView.InvalidateSurface();
}
break;
}
}
void OnTouchModePickerSelectedIndexChanged(object sender, EventArgs args)
{
if (bitmap != null)
{
Picker picker = (Picker)sender;
bitmap.TouchManager.Mode = (TouchManipulationMode)picker.SelectedItem;
} }
}

@ -0,0 +1,103 @@
using System;
using SkiaSharp;
namespace TheGameExtreme.view
{
public class MatrixDisplay
{
public SKPaint MatrixPaint { set; get; } = new SKPaint
{
Color = SKColors.Black,
TextSize = 48,
StrokeWidth = 2
};
public string PerspectiveFormat { set; get; } = "F0";
public SKSize Measure(SKMatrix matrix)
{
return MeasureAndPaint(null, matrix, new SKPoint(), false);
}
public void Paint(SKCanvas canvas, SKMatrix matrix, SKPoint location)
{
MeasureAndPaint(canvas, matrix, location, true);
}
SKSize MeasureAndPaint(SKCanvas canvas, SKMatrix matrix, SKPoint location, bool doPaint)
{
float[] values = matrix.Values;
string[] texts = new string[9];
SKRect[] bounds = new SKRect[9];
float[] widths = new float[3];
for (int i = 0; i < 9; i++)
{
int row = i % 3;
int col = i / 3;
// Format string differently based on row
texts[i] = values[i].ToString(row == 2 ? "F0" : (col == 2 ? PerspectiveFormat : "F2"));
// Measure string with a '-' even if one is not present
bool isNegative = texts[i][0] == '-';
string text = (isNegative ? "" : "-") + texts[i];
MatrixPaint.MeasureText(text, ref bounds[i]);
// Get maximum width for each column
widths[col] = Math.Max(widths[col], bounds[i].Width);
// Measure the text again without the '-' in front
MatrixPaint.MeasureText(texts[i], ref bounds[i]);
}
// Some formatting constants
float horzGap = MatrixPaint.TextSize;
float horzMarg = MatrixPaint.TextSize;
float vertMarg = MatrixPaint.FontSpacing / 4;
// Calculate the total width and height of the matrix display
float totalWidth = widths[0] + widths[1] + widths[2] + 2 * horzGap + 2 * horzMarg;
float totalHeight = 3 * MatrixPaint.FontSpacing + 2 * vertMarg;
if (doPaint)
{
SKPaintStyle saveStyle = MatrixPaint.Style;
for (int i = 0; i < 9; i++)
{
int row = i % 3;
int col = i / 3;
// Find x, y of upper-left corner of text
float x = location.X + horzMarg;
for (int c = 0; c < col; c++)
{
x += widths[c] + horzGap;
}
float y = location.Y + vertMarg + row * MatrixPaint.FontSpacing;
// Adjust for right-justified text
x += widths[col] - bounds[i].Width;
y += (MatrixPaint.FontSpacing - bounds[i].Height) / 2 - bounds[i].Top;
// Draw the text
MatrixPaint.Style = SKPaintStyle.Fill;
canvas.DrawText(texts[i], x, y, MatrixPaint);
}
// Display vertical lines at the sides of the matrix
MatrixPaint.Style = SKPaintStyle.Stroke;
canvas.DrawLine(location.X + horzMarg / 2, location.Y + vertMarg,
location.X + horzMarg / 2, location.Y + totalHeight - vertMarg, MatrixPaint);
canvas.DrawLine(location.X + totalWidth - horzMarg / 2, location.Y + vertMarg,
location.X + totalWidth - horzMarg / 2, location.Y + totalHeight - vertMarg, MatrixPaint);
MatrixPaint.Style = saveStyle;
}
return new SKSize(totalWidth, totalHeight);
}
}
}

@ -6,84 +6,111 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TheGameExtreme.view.Settings"> x:Class="TheGameExtreme.view.Settings">
<Grid> <Grid
Margin="20,20,20,20">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*"/> <RowDefinition Height="15*"/>
<RowDefinition Height="*"/> <RowDefinition Height="28*"/>
<RowDefinition Height="*"/> <RowDefinition Height="28*"/>
<RowDefinition Height="*"/> <RowDefinition Height="28*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ImageButton Source="ArrowSettingsBack.png" <StackLayout
Grid.Row="0" Grid.Column="0" Grid.Row="0">
<ImageButton Source="ArrowSettingsBack.png"
VerticalOptions="Start" VerticalOptions="Start"
HorizontalOptions="StartAndExpand" HorizontalOptions="StartAndExpand"
HeightRequest="40" HeightRequest="40"
WidthRequest="50" WidthRequest="50"
Clicked="SettingToHomePage" Clicked="SettingToHomePage"
BackgroundColor="{DynamicResource BlackColor}" BackgroundColor="{DynamicResource BlackColor}"
Margin="10,10,0,0"/> Margin="10,10,0,0"/>
</StackLayout>
<Label HorizontalTextAlignment="Start"
Text ="Langage" Grid.Column="0"
Grid.Row="0" FontSize="25"
TextColor="{DynamicResource WhiteColor}"
Margin="40,58,0,0"/>
<Label Text="English"
Grid.Column="1" Grid.Row="0"
FontSize="25"
TextColor="{DynamicResource WhiteColor}"
Margin="80,58,0,0"/>
<CheckBox IsChecked="False" <Grid
Grid.Column="1" Grid.Row="0" Grid.Row="1">
x:Name="CBBr" <Grid.ColumnDefinitions>
CheckedChanged="CBBr_CheckedChanged" <ColumnDefinition Width="33*"/>
Color="{DynamicResource SkyBlueColor}" <ColumnDefinition Width="33*"/>
Margin="40,63,0,0"/> <ColumnDefinition Width="33*"/>
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
HorizontalTextAlignment="Start"
Text ="Langage"
FontSize="25"
TextColor="{DynamicResource WhiteColor}"
VerticalTextAlignment="Center"/>
<StackLayout
Grid.Column="1"
Orientation="Horizontal">
<Label
Text="English"
FontSize="25"
TextColor="{DynamicResource WhiteColor}"
VerticalTextAlignment="Center"/>
<Label Text="Français" <CheckBox
Grid.Column="2" Grid.Row="0" IsChecked="False"
FontSize="25" x:Name="CBBr"
TextColor="{DynamicResource WhiteColor}" CheckedChanged="CBBr_CheckedChanged"
Margin="80,58,0,0"/> Color="{DynamicResource SkyBlueColor}"
/>
</StackLayout>
<StackLayout
Grid.Column="2"
Orientation="Horizontal">
<Label
Text="Français"
FontSize="25"
TextColor="{DynamicResource WhiteColor}"
VerticalTextAlignment="Center"/>
<CheckBox IsChecked="True" <CheckBox
Grid.Column="2" Grid.Row="0" IsChecked="True"
x:Name="CBFr" x:Name="CBFr"
CheckedChanged="CBFr_CheckedChanged" CheckedChanged="CBFr_CheckedChanged"/>
Color="{DynamicResource SkyBlueColor}" </StackLayout>
Margin="40,63,0,0"/>
</Grid>
<StackLayout
Grid.Row="2"
Orientation="Horizontal">
<Label HorizontalTextAlignment="Start" <Label
Text="Mode Extreme" Grid.Column="0" HorizontalTextAlignment="Start"
Grid.Row="2" FontSize="25" Text="Mode Extreme"
TextColor="{DynamicResource WhiteColor}" FontSize="25"
Margin="40,25,0,0"/> TextColor="{DynamicResource WhiteColor}"/>
<Switch <Switch
Grid.Column="1" Grid.Row="2"
OnColor="{DynamicResource SkyBlueColor}" OnColor="{DynamicResource SkyBlueColor}"
ThumbColor="WhiteSmoke"/> ThumbColor="WhiteSmoke"/>
<Label Text="Thème Clair" </StackLayout>
Grid.Column="0" Grid.Row="3"
FontSize="25" <StackLayout
TextColor="{DynamicResource WhiteColor}" Grid.Row="3"
Margin="40,25,0,0"/> Orientation="Horizontal">
<Label
Text="Thème Clair"
FontSize="25"
TextColor="{DynamicResource WhiteColor}"/>
<Switch <Switch
Grid.Column="1" Grid.Row="3" Toggled="Switch_Toggled_Theme"
Toggled="Switch_Toggled_Theme" x:Name="swTheme" x:Name="swTheme"
OnColor="{DynamicResource SkyBlueColor}" ThumbColor="WhiteSmoke"/> OnColor="{DynamicResource SkyBlueColor}"
ThumbColor="WhiteSmoke"/>
</StackLayout>
</Grid> </Grid>
</ContentPage> </ContentPage>

@ -0,0 +1,113 @@
using System.Collections.Generic;
using SkiaSharp;
using TouchTracking;
namespace TheGameExtreme.view
{
public class TouchManipulationBitmap
{
SKBitmap bitmap;
Dictionary<long, TouchManipulationInfo> touchDictionary = new Dictionary<long, TouchManipulationInfo>();
public TouchManipulationBitmap(SKBitmap bitmap)
{
this.bitmap = bitmap;
Matrix = SKMatrix.MakeIdentity();
TouchManager = new TouchManipulationManager
{
Mode = TouchManipulationMode.ScaleRotate
};
}
public TouchManipulationManager TouchManager { set; get; }
public SKMatrix Matrix { set; get; }
public void Paint(SKCanvas canvas)
{
canvas.Save();
SKMatrix matrix = Matrix;
canvas.Concat(ref matrix);
canvas.DrawBitmap(bitmap, 0, 0);
canvas.Restore();
}
public bool HitTest(SKPoint location)
{
// Invert the matrix
SKMatrix inverseMatrix;
if (Matrix.TryInvert(out inverseMatrix))
{
// Transform the point using the inverted matrix
SKPoint transformedPoint = inverseMatrix.MapPoint(location);
// Check if it's in the untransformed bitmap rectangle
SKRect rect = new SKRect(0, 0, bitmap.Width, bitmap.Height);
return rect.Contains(transformedPoint);
}
return false;
}
public void ProcessTouchEvent(long id, TouchActionType type, SKPoint location)
{
switch (type)
{
case TouchActionType.Pressed:
touchDictionary.Add(id, new TouchManipulationInfo
{
PreviousPoint = location,
NewPoint = location
});
break;
case TouchActionType.Moved:
TouchManipulationInfo info = touchDictionary[id];
info.NewPoint = location;
Manipulate();
info.PreviousPoint = info.NewPoint;
break;
case TouchActionType.Released:
touchDictionary[id].NewPoint = location;
Manipulate();
touchDictionary.Remove(id);
break;
case TouchActionType.Cancelled:
touchDictionary.Remove(id);
break;
}
}
void Manipulate()
{
TouchManipulationInfo[] infos = new TouchManipulationInfo[touchDictionary.Count];
touchDictionary.Values.CopyTo(infos, 0);
SKMatrix touchMatrix = SKMatrix.MakeIdentity();
if (infos.Length == 1)
{
SKPoint prevPoint = infos[0].PreviousPoint;
SKPoint newPoint = infos[0].NewPoint;
SKPoint pivotPoint = Matrix.MapPoint(bitmap.Width / 2, bitmap.Height / 2);
touchMatrix = TouchManager.OneFingerManipulate(prevPoint, newPoint, pivotPoint);
}
else if (infos.Length >= 2)
{
int pivotIndex = infos[0].NewPoint == infos[0].PreviousPoint ? 0 : 1;
SKPoint pivotPoint = infos[pivotIndex].NewPoint;
SKPoint newPoint = infos[1 - pivotIndex].NewPoint;
SKPoint prevPoint = infos[1 - pivotIndex].PreviousPoint;
touchMatrix = TouchManager.TwoFingerManipulate(prevPoint, newPoint, pivotPoint);
}
SKMatrix matrix = Matrix;
SKMatrix.PostConcat(ref matrix, touchMatrix);
Matrix = matrix;
}
}
}

@ -0,0 +1,12 @@
using System;
using SkiaSharp;
namespace TheGameExtreme.view
{
public class TouchManipulationInfo
{
public SKPoint PreviousPoint { set; get; }
public SKPoint NewPoint { set; get; }
}
}

@ -0,0 +1,107 @@
using System;
using SkiaSharp;
namespace TheGameExtreme.view
{
public class TouchManipulationManager
{
public TouchManipulationMode Mode { set; get; }
float Magnitude(SKPoint point)
{
return (float)Math.Sqrt(Math.Pow(point.X, 2) + Math.Pow(point.Y, 2));
}
public SKMatrix OneFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint)
{
if (Mode == TouchManipulationMode.None)
{
return SKMatrix.MakeIdentity();
}
SKMatrix touchMatrix = SKMatrix.MakeIdentity();
SKPoint delta = newPoint - prevPoint;
if (Mode == TouchManipulationMode.ScaleDualRotate) // One-finger rotation
{
SKPoint oldVector = prevPoint - pivotPoint;
SKPoint newVector = newPoint - pivotPoint;
// Avoid rotation if fingers are too close to center
if (Magnitude(newVector) > 25 && Magnitude(oldVector) > 25)
{
float prevAngle = (float)Math.Atan2(oldVector.Y, oldVector.X);
float newAngle = (float)Math.Atan2(newVector.Y, newVector.X);
// Calculate rotation matrix
float angle = newAngle - prevAngle;
touchMatrix = SKMatrix.MakeRotation(angle, pivotPoint.X, pivotPoint.Y);
// Effectively rotate the old vector
float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector);
oldVector.X = magnitudeRatio * newVector.X;
oldVector.Y = magnitudeRatio * newVector.Y;
// Recalculate delta
delta = newVector - oldVector;
}
}
// Multiply the rotation matrix by a translation matrix
SKMatrix.PostConcat(ref touchMatrix, SKMatrix.MakeTranslation(delta.X, delta.Y));
return touchMatrix;
}
public SKMatrix TwoFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint)
{
SKMatrix touchMatrix = SKMatrix.MakeIdentity();
SKPoint oldVector = prevPoint - pivotPoint;
SKPoint newVector = newPoint - pivotPoint;
if (Mode == TouchManipulationMode.ScaleRotate ||
Mode == TouchManipulationMode.ScaleDualRotate)
{
// Find angles from pivot point to touch points
float oldAngle = (float)Math.Atan2(oldVector.Y, oldVector.X);
float newAngle = (float)Math.Atan2(newVector.Y, newVector.X);
// Calculate rotation matrix
float angle = newAngle - oldAngle;
touchMatrix = SKMatrix.MakeRotation(angle, pivotPoint.X, pivotPoint.Y);
// Effectively rotate the old vector
float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector);
oldVector.X = magnitudeRatio * newVector.X;
oldVector.Y = magnitudeRatio * newVector.Y;
}
float scaleX = 1;
float scaleY = 1;
if (Mode == TouchManipulationMode.AnisotropicScale)
{
scaleX = newVector.X / oldVector.X;
scaleY = newVector.Y / oldVector.Y;
}
else if (Mode == TouchManipulationMode.IsotropicScale ||
Mode == TouchManipulationMode.ScaleRotate ||
Mode == TouchManipulationMode.ScaleDualRotate)
{
scaleX = scaleY = Magnitude(newVector) / Magnitude(oldVector);
}
if (!float.IsNaN(scaleX) && !float.IsInfinity(scaleX) &&
!float.IsNaN(scaleY) && !float.IsInfinity(scaleY))
{
SKMatrix.PostConcat(ref touchMatrix,
SKMatrix.MakeScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y));
}
return touchMatrix;
}
}
}

@ -0,0 +1,13 @@
using System;
namespace TheGameExtreme.view
{
public enum TouchManipulationMode
{
None,
PanOnly,
IsotropicScale, // includes panning
AnisotropicScale, // includes panning
ScaleRotate, // implies isotropic scaling
ScaleDualRotate // adds one-finger rotation
}
}
Loading…
Cancel
Save