wpf主界面游戏引擎实现

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

2.GameEntityView.xaml

<UserControl x:Class="PrimalEditor.Editors.GameEntityView"
             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"
             mc:Ignorable="d" Background="{StaticResource Editor.Window.GrayBrush3}"
             
             d:DesignHeight="450" d:DesignWidth="800">

  


    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
        <ScrollViewer.Style>
            <Style TargetType="ScrollViewer">
                <Style.Triggers>
                    <Trigger Property="DataContext" Value="{x:Null}">
                        <Setter Property="Visibility" Value="Collapsed"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ScrollViewer.Style>
        <StackPanel>

        <Border Height="32">
            <ToggleButton x:Name="addComponent" VerticalAlignment="Center"
                          HorizontalAlignment="Left" Margin="5,0,0,0">
                <ToggleButton.Content>
                    <DockPanel>
                        <TextBlock Text="Add Component" Margin="5,0"/>
                        <Path Margin="3,0,2,0"
                          Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
                          HorizontalAlignment="Center" Fill="Black"
                           VerticalAlignment="Center"                          
                          />
                    </DockPanel>
                </ToggleButton.Content>

            </ToggleButton>

        </Border>

        <Grid>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="78"/>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            
            <TextBlock Text="Name" Grid.Column="0" Margin="5,0,0,0"/>
            <TextBox Text="{Binding Name}" Grid.Column="1"  Tag="{Binding RenameCommand}"/>
                <StackPanel Orientation="Horizontal" Grid.Column="2">
                <TextBlock Text="Enabled" Margin="5,0,0,0"/>
            <CheckBox IsChecked="{Binding IsEnabled}" Command="{Binding IsEnabledCommand}" 
                      CommandParameter="{Binding IsChecked,RelativeSource={RelativeSource Self}}"
                      Margin="5,0" VerticalAlignment="Center"/>
           </StackPanel>
        </Grid>
        
        <ItemsControl ItemsSource="{Binding Components}">
            <ItemsControl.ItemsPanel>

                <ItemsPanelTemplate>
                    <StackPanel/>

                </ItemsPanelTemplate>


            </ItemsControl.ItemsPanel>
        </ItemsControl>


    </StackPanel>

   </ScrollViewer>
</UserControl>
2.GameEntityView.xaml.cs


using PrimalEditor.Components;
using PrimalEditor.GameProject;
using PrimalEditor.Utilities;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;

namespace PrimalEditor.Editors
{

    public class NullableBoolToBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value is bool b && b == true;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value is bool b && b == true;
        }
    }


    /// <summary>
    /// GameEntityView.xaml 的交互逻辑
    /// </summary>
    public partial class GameEntityView : UserControl
    {

        private Action _undoAction;
        private string _propertyName;

        public static GameEntityView Instance { get; private set; }
        public GameEntityView()
        {
            InitializeComponent();
            DataContext = null;
            Instance = this;
            DataContextChanged += (_, __) =>
            {

                if (DataContext != null)
                {
                    (DataContext as MSEntity).PropertyChanged += (s, e) => _propertyName = e.PropertyName;

                }

            };

        }

        private Action GetRenameAction()
        {

            var vm = DataContext as MSEntity;
            var selection = vm.SelectedEntities.Select(entity => (entity, entity.Name)).ToList();

            return new Action(() =>
            {

                selection.ForEach(item => item.entity.Name = item.Name);
                (DataContext as MSEntity).Refresh();

            });

        }

        private Action GetIsEnabledAction()
        {

            var vm = DataContext as MSEntity;
            var selection = vm.SelectedEntities.Select(entity => (entity, entity.IsEnabled)).ToList();

            return new Action(() =>
            {

                selection.ForEach(item => item.entity.IsEnabled = item.IsEnabled);
                (DataContext as MSEntity).Refresh();

            });


        }

        private void OnName_TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            _propertyName = string.Empty;
            _undoAction = GetRenameAction();

        }

        private void OnName_TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {

            if (_propertyName == nameof(MSEntity.Name) && _undoAction != null)
            {

                var vm = DataContext as MSEntity;
                var selection = vm.SelectedEntities.Select(entity => (entity, entity.Name)).ToList();
                var redoAction = new Action(() =>
                {

                    selection.ForEach(item => item.entity.Name = item.Name);

                });

                Project.UndoRedo.Add(new UndoRedoAction(_undoAction, redoAction, "Rename game entity"));
                _propertyName = null;


            };


            _undoAction = null;


        }


        private void OnIsEnabled_CheckBox_Click(object sender, RoutedEventArgs e)
        {

            var undoAction = GetIsEnabledAction();
            var vm = DataContext as MSEntity;
            vm.IsEnabled = (sender as CheckBox).IsChecked == true;
            var redoAction = GetIsEnabledAction();

            Project.UndoRedo.Add(new UndoRedoAction(undoAction, redoAction,
                vm.IsEnabled == true ? "Enable game entity" : "Disable game entity"
                ));


        }

        private void OnAddComponent_Button_PreviewMouse_LBD(object sender, MouseButtonEventArgs e)
        {

            var menu = FindResource("addComponentMenu") as ContextMenu;
            var btn = sender as ToggleButton;
            btn.IsChecked = true;

            menu.Placement = PlacementMode.Bottom;
            menu.PlacementTarget = btn;
            menu.MinWidth = btn.ActualWidth;
            menu.IsOpen = true;
        }


        private void AddComponent(ComponentType componentType, object data)
        {


            var creationFunction = ComponentFactory.GetCreationFunction(componentType);
            var changedEntities = new List<(GameEntity entity, Component component)>();
            var vm = DataContext as MSEntity;
            foreach (var entity in vm.SelectedEntities)
            {
                var component = creationFunction(entity, data);
                if (entity.AddComponent(component))
                {


                    changedEntities.Add((entity, component));

                }


            }

            if (changedEntities.Any())
            {

                vm.Refresh();

                Project.UndoRedo.Add(new UndoRedoAction(

                      () =>
                      {
                          changedEntities.ForEach(x => x.entity.RemoveComponent(x.component));
                          (DataContext as MSEntity).Refresh();

                      },

                       () =>
                       {

                           changedEntities.ForEach(x => x.entity.AddComponent(x.component));
                           (DataContext as MSEntity).Refresh();

                       },
                       $"Add {componentType} component"

                    ));

            }

        }

        private void AddScriptComponent(object sender, RoutedEventArgs e)
        {


            AddComponent(ComponentType.Script, (sender as MenuItem).Header.ToString());


        }


    }
}
 


网站公告

今日签到

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