wpf3d游戏引擎TransformView实现

发布于:2025-06-24 ⋅ 阅读:(20) ⋅ 点赞:(0)

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);


            }

        }


    }
}
 


网站公告

今日签到

点亮在社区的每一天
去签到