Я пытаюсь создать простую коробку преобразования. Я начал добавлять изменение размера (в настоящее время только расширение ширины справа), но когда я изменяю ширину, а затем поворачиваюсь, перевод Y портится. Я полагаю, что перевод Y должен меняться в зависимости от поворота, чтобы манипуляции выглядели согласованно, но по какой-то причине я не могу понять, как это учитывать. 1004 *
(следующий UserControl является дочерним элементом элемента управления Canvas)
.xaml
<UserControl
x:Class="TransformBox"
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"
PointerPressed="UserControl_PointerPressed"
PointerMoved="UserControl_PointerMoved"
PointerReleased="UserControl_PointerReleased"
Width="200" Height="150">
<UserControl.Resources>
<Style x:Key="ScaleEllipseStyle" TargetType="Ellipse">
<Setter Property="Width" Value="12"/>
<Setter Property="Height" Value="12"/>
<Setter Property="Fill" Value="{StaticResource SystemAccentColor}"/>
</Style>
</UserControl.Resources>
<Grid>
<Rectangle x:Name="RotateRegion" Stroke="Purple" StrokeThickness="20" Margin="-20"/>
<Rectangle x:Name="TranslateRegion" Fill="Transparent" StrokeThickness="2"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="-6,-6,0,0"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,-6,0,0"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,-6,-6,0"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="-6,0,0,0"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,-6,0"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="-6,0,0,-6"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,-6"/>
<Ellipse Style="{StaticResource ScaleEllipseStyle}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,-6,-6"/>
<Ellipse x:Name="OriginRegion" Width="12" Height="12" Fill="Transparent" Stroke="{StaticResource SystemAccentColor}" StrokeThickness="2"/>
</Grid>
</UserControl>
.xaml.cs
public sealed partial class TransformBox : UserControl
{
private bool isDragging;
private Point prevPosition;
private Point _clickPosition;
private TransformType action;
private double _prevRot = 0;
public float SetWidth = 200;
public float SetHeight = 150;
public Point Origin = new Point(0.5, 0.5);
public float X = 0;
public float Y = 0;
public new float Rotation = 0;
public TransformBox()
{
this.InitializeComponent();
Width = SetWidth;
Height = SetHeight;
}
private void UserControl_PointerPressed(object sender, PointerRoutedEventArgs e)
{
isDragging = true;
_clickPosition = prevPosition = e.GetCurrentPoint(Parent as UIElement).Position;
this.CapturePointer(e.Pointer);
if (e.OriginalSource == TranslateRegion) {
action = TransformType.Translate;
}
else if (e.OriginalSource == RotateRegion)
{
action = TransformType.Rotate;
_prevRot = Math.Atan2(_clickPosition.Y - (Y + Height / 2), _clickPosition.X - (X + Width / 2));
}
else if (e.OriginalSource == OriginRegion)
{
action = TransformType.TransformOrigin;
}
else
{
action = TransformType.Scale;
}
}
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
{
if (isDragging)
{
Point mousePos = e.GetCurrentPoint(Parent as UIElement).Position;
switch (action)
{
case TransformType.Translate:
X += (float) (mousePos.X - prevPosition.X);
Y += (float) (mousePos.Y - prevPosition.Y);
prevPosition = mousePos;
break;
case TransformType.Rotate:
double curRot = Math.Atan2(mousePos.Y - (Y + Height / 2), mousePos.X - (X + Width / 2));
Rotation += (float) (curRot - _prevRot);
_prevRot = curRot;
break;
case TransformType.Scale:
double dist = Math.Sqrt(Math.Pow(mousePos.X - _clickPosition.X, 2) + Math.Pow(mousePos.Y - _clickPosition.Y, 2) * 1.0);
double mouseRot = Math.Atan2(mousePos.Y - _clickPosition.Y, mousePos.X - _clickPosition.X);
double proj = dist * Math.Cos(0 - mouseRot);
Width = SetWidth + proj;
break;
}
Matrix4x4 translate = Matrix4x4.CreateTranslation(new Vector3(X, Y, 0f));
Matrix4x4 rotate = Matrix4x4.CreateRotationZ(Rotation, new Vector3(X + (float) SetWidth / 2, Y + (float) SetHeight / 2, 0f));
TransformMatrix = Matrix4x4.Multiply(translate, rotate);
}
}
private void UserControl_PointerReleased(object sender, PointerRoutedEventArgs e)
{
isDragging = false;
SetWidth = (float) Width;
SetHeight = (float) Height;
this.ReleasePointerCapture(e.Pointer);
}
enum TransformType
{
Translate,
Rotate,
Scale,
TransformOrigin
}
}