游戏人生

不积跬步,无以至千里;不积小流,无以成江海。

导航

引擎设计跟踪(三)

一直忙着写编辑器的UI部分.大至框架终于搭好了.
简单说说思路,UI作为引擎的一个插件,不包含编辑的逻辑.因为要作为插件,又要封装.目前是简单的把菜单和工具栏,以及主窗口做了抽象.

因为目前实现部分是用的MFC,所以MFC的主窗口在DLL中创建,同时有回调接口可以在主循环调用MFCAPP的OnIdle和PreTranslateMsg(这两个函数在DLL模式下不会自动执行),这样保证了MFC框架的正常运行.之前没有加OnIdle的时候,toolbar会出现问题,比如双击一个工具栏之后,如果上面的DockBar空了,仍然不消失,等等还有很多问题.考虑到扩展性,窗口系统使用的MDI.

UI部分抽象的接口有 IMenu 和IMenuManager, IEditorUI(主窗口), IToolbox, 还有一个IIconManager,用来加载图片的.目前所有的图标都是单个动态载入的png格式,包括主窗口的图标.这些接口是编辑框架预定义的回调接口,UI插件只需要实现就可以了.
还有一个IHotkeyManager,是编辑器框架内部封装的,不需要UI来实现(没有用MFC的Accelerator)这是为了使功能尽量脱离(不依赖)UI的实现.

我怀疑是不是有点过度抽象了,因为如果用跨平台的UI库,比如Qt,就可以直接拿来用了.现在是UI的实现细节,根本不可见,只有接口.不过想想,就算使用Qt,如果直接依赖的话,如果要换UI比如WxWidgets,就悲剧了.所以感觉这样可能会灵活一点儿吧.还是依赖于接口,而不依赖于具体的类,这样比较好,如果换UI了,那么编辑器的逻辑代码不需要任何修改.如果是直接依赖,那么换UI模块,编辑逻辑也不会改,但起码要改一下对UI调用的地方吧..

菜单和工具栏都是可以动态创建的,这样编辑器的插件就可以自己加载图片,并添加菜单和工具栏了.

编辑工具的抽象刚有一个雏形,目前只简单写了选择(Select)工具,因为没有实现mesh,所以Rotate和Translate工具先不写,因为不好调试.下一步准备写地形高度画刷(Terrain Deform).

为了实现Select工具,简单写了场景射线查询和AABB渲染.AABB渲染用的hardware Instancing,遇到的问题是,如果不使用index,渲染不正确.DX doc上面说,如果不用index,则需要有多个instance的vertex copy放在vertexbuffer里面,但是我用一个AABB实例测试,用PIX调试发现后面的顶点在渲染时instance数据为空.但是改为index模式就好了,这个仍有疑问.不过DX doc上说没有index的instancing是没有硬件加速的,所以也没有深入debug了.

另外从CodeProject上面下了CSizingToolbar的代码,简单改改直接用了,还有ownerdraw tabcontrol,下载下来简单改了改.懒得自己写了,菜单的OWNERDRAW是自己写的,因为CodeProject上面的菜单都太复杂了,不想用.也简单写了下左边带tab的dockbar.

编辑器框架的接口,主要用IEditorFile,IEditorTool.这两个接口主要用于插件扩展,因为框架主要提供机制,除了内置的菜单(比如文件菜单),还有内置的工具(比如选择工具),没有内置文件格式.都是通过插件来扩展的.

这两个接口,也可被UI模块访问,来处理一些基本的逻辑判断.

贴一段编辑器框架初始化内置菜单的代码:

		IMenu* menu_file = IMenuManager::getSingleton().addRootMenu( BTString("File"),TEXT('F') );
		IMenu* menu_edit = IMenuManager::getSingleton().addRootMenu( BTString("Edit"),TEXT('E') );
		IMenu* menu_tool = IMenuManager::getSingleton().addRootMenu( BTString("Tool"),TEXT('T') );
		IMenu* menu_view = IMenuManager::getSingleton().addRootMenu( BTString("View"),TEXT('V') );

		menu_file->addSubItem(BTString("New"),EdUICmd.getEditorCommand(UIC_NEW),true,TEXT('N'),HOTKEY(KC_N) );
		menu_file->addSubItem(BTString("Open"),EdUICmd.getEditorCommand(UIC_OPEN),true,TEXT('O'),HOTKEY(KC_O) );
		menu_file->addSeparator();
		menu_file->addSubItem(BTString("Save"),EdUICmd.getEditorCommand(UIC_SAVE),false,TEXT('S'),HOTKEY(KC_S) );
		menu_file->addSubItem(BTString("Save All"),EdUICmd.getEditorCommand(UIC_SAVE_ALL),false,TEXT('A'),HOTKEY(KC_S,KC_CTRL,KC_SHIFT) );
		menu_file->addSeparator();
		menu_file->addSubItem(BTString("Exit"),EdUICmd.getEditorCommand(UIC_EXIT),false,TEXT('E'),HOTKEY(KC_X) );

上面是效果图.目前连雏形都不算吧..工作量太大了,一定要坚持学习下去.

posted on 2011-05-23 23:34  crazii  阅读(700)  评论(0编辑  收藏  举报