1.TransformView.xaml
<UserControl x:Class="PrimalEditor.Editors.TransformView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PrimalEditor.Editors"
xmlns:vm="clr-namespace:PrimalEditor.Components"
xmlns:utl="clr-namespace:PrimalEditor.Utilities.Controls"
d:DataContext="{d:DesignInstance Type=vm:MSTransform, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource LightTextBlockStyle}"/>
</UserControl.Resources>
<local:ComponentView Header="Transform">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="78"/>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Position" Grid.Column="0" Grid.Row="0"/>
<utl:VectorBox X="{Binding PosX}" Y="{Binding PosY}" Z="{Binding PosZ}" Grid.Column="1" Grid.Row="0"
PreviewMouseLeftButtonDown="OnPosition_VectorBox_PreviewMouse_LBD"
PreviewMouseLeftButtonUp="OnPosition_VectorBox_PreviewMouse_LBU"
LostKeyboardFocus="OnPosition_VectorBox_LostKeyboardFocus"
/>
<TextBlock Text="Rotation" Grid.Column="0" Grid.Row="0"/>
<utl:VectorBox X="{Binding RotX}" Y="{Binding RotY}" Z="{Binding RotZ}" Grid.Column="1" Grid.Row="0"
PreviewMouseLeftButtonDown="OnRotation_VectorBox_PreviewMouse_LBD"
PreviewMouseLeftButtonUp="OnRotation_VectorBox_PreviewMouse_LBU"
LostKeyboardFocus="OnRotation_VectorBox_LostKeyboardFocus"
/>
<TextBlock Text="Scale" Grid.Column="0" Grid.Row="0"/>
<utl:VectorBox X="{Binding ScaleX}" Y="{Binding ScaleY}" Z="{Binding ScaleZ}" Grid.Column="1" Grid.Row="0"
PreviewMouseLeftButtonDown="OnScale_VectorBox_PreviewMouse_LBD"
PreviewMouseLeftButtonUp="OnScale_VectorBox_PreviewMouse_LBU"
LostKeyboardFocus="OnScale_VectorBox_LostKeyboardFocus"
/>
</Grid>
</local:ComponentView>
</UserControl>
2.TransformView.xaml.cs
using PrimalEditor.Components;
using PrimalEditor.GameProject;
using PrimalEditor.Utilities;
using System.Diagnostics;
using System.Numerics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace PrimalEditor.Editors
{
/// <summary>
/// TransformView.xaml 的交互逻辑
/// </summary>
public partial class TransformView : UserControl
{
private Action _undoAction = null;
private bool _propertyChanged = false;
public TransformView()
{
InitializeComponent();
Loaded += OnTransformViewLoaded;
}
private void OnTransformViewLoaded(object sender, RoutedEventArgs e)
{
Loaded -= OnTransformViewLoaded;
(DataContext as MSTransform).PropertyChanged += (s, e) => _propertyChanged = true;
}
private Action GetAction(Func<Transform, (Transform transform, Vector3)> selector,
Action<(Transform transform, Vector3)> forEachAction)
{
if (!(DataContext is MSTransform vm))
{
_undoAction = null;
_propertyChanged = false;
return null;
}
var selection = vm.SelectedComponents.Select(x => selector(x)).ToList();
return new Action(() =>
{
selection.ForEach(x => forEachAction(x));
(GameEntityView.Instance.DataContext as MSEntity)?.GetMSComponent<MSTransform>().Refresh();
});
}
private Action GetPositionAction() => GetAction((x) => (x, x.Position), (x) => x.transform.Position = x.Item2);
private Action GetRotationAction() => GetAction((x) => (x, x.Rotation), (x) => x.transform.Rotation = x.Item2);
private Action GetScaleAction() => GetAction((x) => (x, x.Scale), (x) => x.transform.Scale = x.Item2);
private void RecordActions(Action redoAction, string name)
{
if (_propertyChanged)
{
Debug.Assert(_undoAction != null);
_propertyChanged = false;
Project.UndoRedo.Add(new UndoRedoAction(_undoAction, redoAction, name));
}
}
private void OnPosition_VectorBox_PreviewMouse_LBD(object sender, MouseButtonEventArgs e)
{
_propertyChanged = false;
_undoAction = GetPositionAction();
}
private void OnPosition_VectorBox_PreviewMouse_LBU(object sender, MouseButtonEventArgs e)
{
RecordActions(GetPositionAction(), "Postion Changed");
}
private void OnRotation_VectorBox_PreviewMouse_LBD(object sender, MouseButtonEventArgs e)
{
_propertyChanged = false;
_undoAction = GetRotationAction();
}
private void OnRotation_VectorBox_PreviewMouse_LBU(object sender, MouseButtonEventArgs e)
{
RecordActions(GetPositionAction(), "Rotation Changed");
}
private void OnScale_VectorBox_PreviewMouse_LBD(object sender, MouseButtonEventArgs e)
{
_propertyChanged = false;
_undoAction = GetScaleAction();
}
private void OnScale_VectorBox_PreviewMouse_LBU(object sender, MouseButtonEventArgs e)
{
RecordActions(GetPositionAction(), "Scale Changed");
}
private void OnPosition_VectorBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (_propertyChanged && _undoAction != null)
{
OnPosition_VectorBox_PreviewMouse_LBU(sender, null);
}
}
private void OnRotation_VectorBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (_propertyChanged && _undoAction != null)
{
OnPosition_VectorBox_PreviewMouse_LBU(sender, null);
}
}
private void OnScale_VectorBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (_propertyChanged && _undoAction != null)
{
OnPosition_VectorBox_PreviewMouse_LBU(sender, null);
}
}
}
}