用WPF和D3D开发游戏编辑器简介(3)

原创 2012年03月31日 00:53:13

下面简单介绍一下重新设计过的编辑器结构,从功能和层次上分主要是这样的:


App, MainWindow: 入口和主界面
Controls:使用的各种控件和自定义界面
Data:数据层,填充控件的数据信息,这里主要是魔兽世界的物品和npc等信息
Services:服务层,编辑器用到的功能由每个模块作为服务提供,比如场景服务维护编辑器中的场景结点等
Commands:命令,响应编辑器的各种命令,独立于界面
Resources:资源,包括主题,图像资源和程序中统一的界面元素,如上面程序的各种颜色边框

Application定义了程序的资源,主题,也是程序的入口,通常在启动主窗口之前,也是设置和获取使用的配置信息的地方,启动代码如下:

 protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            window = new MainWindow();

            // Restore the window size when the values are valid.
            if (Settings.Default.Left >= 0 && Settings.Default.Top >= 0 && Settings.Default.Width > 0 && Settings.Default.Height > 0
                && Settings.Default.Left + Settings.Default.Width <= SystemParameters.VirtualScreenWidth
                && Settings.Default.Top + Settings.Default.Height <= SystemParameters.VirtualScreenHeight)
            {
                window.Left = Settings.Default.Left;
                window.Top = Settings.Default.Top;
                window.Height = Settings.Default.Height;
                window.Width = Settings.Default.Width;
            }
            window.IsMaximized = Settings.Default.IsMaximized;
            Resources["EdgeBorderBrush"] = new SolidColorBrush(Settings.Default.EdgeBorderColor);

            //init
            new ShellService(window);
            new EngineService();
            new SceneService();
            new EditorService();

            //run
            window.Show();
        }

 

首先创建主窗口,通常在主窗口创建时完成引擎的初始化工作,然后读取配置信息,比如上次程序窗口的大小等信息,然后初始化各种服务,显示。

主窗口的设计界面如下图:

 

如图所示,窗口的界面主要分为菜单栏和左右底三个DockContent,这里需要控件AvalonDock,界面的主要代码如下:

 <DockPanel LastChildFill="true" >
        <!-- menu -->
        <control:MenuControl DockPanel.Dock="Top"/>

        <!--  docking manager  -->
        <ad:DockingManager x:Name="_dockManager" IsAnimationEnabled="True">
            <ad:ResizingPanel FocusManager.IsFocusScope="True" Orientation="Horizontal">
                <ad:DockablePane x:Name="_leftDockablePane" ad:ResizingPanel.ResizeWidth="0">
                    <v:MapContent x:Name="_mapContent"/>
                    <v:SpellVisualEffectContent x:Name="_spellVisualEffectContent" />
                    <v:NpcContent x:Name="_npcContent"/>
                    <v:CharacterContent x:Name="_characterContent"/> 
                </ad:DockablePane>

                <ad:ResizingPanel FocusManager.IsFocusScope="True" Orientation="Vertical">
                    <!--  Main Content  -->
                    <ad:DocumentPane Name="_documentPane" ShowHeader="False">
                        <ad:DocumentContent IsCloseable="false">
                            <Border Name="_controlHostElement" />
                        </ad:DocumentContent>
                    </ad:DocumentPane>

                    <ad:DockablePane x:Name="_bottomDockablePane" ad:ResizingPanel.ResizeHeight="0">
                        <v:AnimationContent x:Name="_animationContent"/>   
                    </ad:DockablePane>
                </ad:ResizingPanel>

                <ad:DockablePane x:Name="_rightDockablePane" ad:ResizingPanel.ResizeWidth="0">
                    <v:ClothesContent x:Name="_clothesContent"/>
                    <v:WeaponContent x:Name="_weaponContent"/>
                    <v:SetContent x:Name="_setContent"/>
                    </ad:DockablePane>
            </ad:ResizingPanel>

        </ad:DockingManager>
    </DockPanel>

WPF的界面部分非常简单,在设计阶段可以直接写几个简单的元素占位。

下面是比较复杂的初始化部分,流程大致是这样的:

1. 初始化引擎,把引擎窗口放到主界面中间,借助HwndHost。并设置resize和mouse消息处理。

2. 读取需要的数据表。

3. 读取命令绑定,初始化界面控件大小,激活窗口,启动timer准备渲染。

这三个步骤可以用一个Splash窗口来提示进度,总的代码如下:

 

private readonly DispatcherTimer timer;
        private readonly WindowHost windowhost;
        private bool isKeyFocus;

        public MainWindow()
        {
            InitializeComponent();

            Loaded += new RoutedEventHandler(MainWindow_Loaded);
            Closing += new CancelEventHandler(MainWindow_Closing);
            StateChanged += new EventHandler(MainWindow_StateChanged);
            this.LostKeyboardFocus += delegate { isKeyFocus = false; };

            windowhost = new WindowHost();
            timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle, windowhost.Dispatcher);
            timer.Interval = new System.TimeSpan(0, 0, 0, 0, 1);
            timer.Tick += new EventHandler(timer_Tick);
        }

 

  private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            this.Loaded -= MainWindow_Loaded;

            SplashWindow _splash = new SplashWindow();
            _splash.Show();
            this.IsEnabled = false;

            MessageListener.Instance.StartWork("第1/3步: 初始化引擎...", new DispatcherOperationCallback(InitStage0));
            Thread.Sleep(1);

            MessageListener.Instance.StartWork("第2/3步: 读取数据...", new DispatcherOperationCallback(InitStage1));
            Thread.Sleep(1);

            MessageListener.Instance.StartWork("第3/3步: 准备界面...", new DispatcherOperationCallback(InitStage2));
            Thread.Sleep(1);

            this.IsEnabled = true;
            _splash.Close();
        }

 

   private object InitStage0(object frame)
        {
            windowhost.HwndHost = EngineService.Instance.InitilalizeEngine();
            SceneService.Instance.Initialize();

            windowhost.WmResize += new ResizeEventHandler(windowHost_WmResize);
            windowhost.WmMouse += new MouseMessageHandler(windowHost_WmMouse);

            ((DispatcherFrame)frame).Continue = false;
            return null;
        }

 

        private object InitStage1(object frame)
        {
            EngineService.Instance.RetrieveWowData();

            ((DispatcherFrame)frame).Continue = false;
            return null;
        }

        private object InitStage2(object frame)
        {
            InitCommandBindings();

            _characterContent.Initialize();
            _npcContent.Initialize();
            _spellVisualEffectContent.Initialize();
            _mapContent.Initialize();

            _clothesContent.Initialize();
            _weaponContent.Initialize();
            _setContent.Initialize();

            _animationContent.Initialize();

            if (windowhost.HwndHost != IntPtr.Zero)
            {
                _controlHostElement.Child = windowhost;
            }

            _leftDockablePane.SetValue(ResizingPanel.ResizeWidthProperty, new GridLength(180));
            _rightDockablePane.SetValue(ResizingPanel.ResizeWidthProperty, new GridLength(180));
            _bottomDockablePane.SetValue(ResizingPanel.ResizeHeightProperty, new GridLength(150));

            this.Activate();

            timer.Start();

            ((DispatcherFrame)frame).Continue = false;
            return null;
        }

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

用WPF和D3D开发游戏编辑器简介(2)

距第一篇已经过去很长时间了,编辑器和引擎的开发并没有停止,每周都陆续有新的功能添加进去。在这几个月的时间里,wpf界面重新进行了自定义,风格更为简洁统一,编辑器代码也进行了重写,减少了不必要的更新操作...

3D游戏开发大全和简介

  • 2010-05-11 15:52
  • 1.07MB
  • 下载

unity3D游戏开发二之unity编辑器一

通过官网我们可以下载最新的unity版本,这里我们是基于Mac OS系统的,安装步骤很简单,这里就略过了。安装完成后,打开unity, 主界面如下: 下面我们来看看它的界面布局,Unity...

Unity3D游戏开发之编辑器扩展程序开发实例

各位朋友大家好,欢迎关注我的博客,我的博客地址是http://www.qinyuanpei.com。今天我们来说说如何在Unity3D中为编辑器开发扩展程序。提到扩展程序,相信大家都不会陌生了。不管是...

unity引擎简介——(1)Unity3D游戏开发流程与规范

http://martinchoice.blog.163.com/blog/static/21021818520152160181190/

unity3d游戏开发学习之使用3dmax创建导弹模型

在着手研究Unity3D的游戏开发时,3D模型可以考虑从unity的assets store去获取,也可以从网上搜索下载,同时咱们也可以尝试下自己动手去做一些简单的模型。 这里就根据unity3d坦克...

游戏开发行业那些事 -- 3.天堂向左,3D向右 (转)

天堂向左,3D向右    2002年的夏天,我背着一个书包孤身一人来到北京,书包里面,只有一条发白的长裤和汗衫。那时候正值2002年世界杯,天气炎热而清新。    当时的北京中关村大街海龙大厦上,曾经...

自学Unity3D游戏开发(3)刚体和碰撞

上一章讲到为物体粘贴图片,如果有同学运行下会发现物体会悬在空中不动,那是因为还没有添加物理规律,没有重力当然不会下落。 这里有一个名词叫做“刚体”,既Rigidbody,我们要把这个东西添加在物体上面...

使用Multiplayer Networking做一个简单的多人游戏例子-1/3(Unity3D开发之二十五)

本文主要讲述了如何使用Multiplayer Networking开发多人游戏,文中实例、代码来源于Unity官方教程。 原文:INTRODUCTION TO A SIMPLE MULTIPLAY...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)