怎样开发编辑器:使用C++和DirectX开发GUI - 资源编辑器及其它



  欢迎回到“使用C和DX开发GUI”第 4部分接着我们主题(我是如何为我未来游戏开发GUI — Quaternion)本文将关注所有有关游戏GUI细节问题

4.1、保存窗口
   窗口序列化(存储和载入窗口)对你工程而言或许不重要如果你游戏GUI很简单你可以全靠在游戏中实现窗口但如果你GUI相对复杂或者随着开发过程经常会改变那么你会想写以把个窗口(和所有它子窗口)存到文件里然后再装载它对初学者而言窗口序列化代码允许你改变游戏GUI而不用重新编译而且它对于多人协调工作也是有益
   我计划是从主对话窗口开始然后遍历它所有子窗口把每个存到磁盘上如果我用C语言写我告诉自己句话是“好如果我必须保存这些窗口我需要每个窗口有个字节来告诉我它是什么样窗口以使我能正确载入它比如1是按钮2是列表框3是图表等等
   这种问题是CRTTI(运行期类型识别)关心RTTI提供了两个东东type_info类和typeid两者允许我查询个对象所属类名称例如gui_windowgui_button等等我没有使用枚举和ID而是简单地为每个将要保存窗口typid并“写下”窗口类名称
   我注意到使用RTTI对象识别来帮助保存窗口两个小缺点RTTI ID是串而不是整型这意味着它们将占用磁盘上更多空间(按照Pascal方式存储字串将是前4个字节代表字串长度接下来是字串本身数据)第 2如果你改变个窗口类名字你会破坏已经存好所有窗口文件
   由于这些原因你可能不会这样使用RTTI毕竟并不是有技术就定要使用它然而我发现RTTI对我代码而言却是救生员要获得更多有关RTTI和这两个信息请在你联机帮助文档里查找
   另外如果你决定在VC里使用RTTI确保你在工程属性C/C栏和C语言选项中打开它

4.2、载入窗口
   载入窗口比存储他们要难点儿这主要是你必须新建()每个窗口载入并当它不再需要时候删除
   这是个递归用PDL表达话如下所示:

  =ColorCode>void gui_window:load( filehandle)
   {

     =ColorCatchword>// read window properties (colors, etc.)
     // read total number of children for this window
     // for each child?
       // read window ID from disk
       // a gui_window derivative based _disibledevent=>}

   换句话说你得像你所想得那样从磁盘载入窗口要处理基类窗口:读取他属性然后读取基类窗口所有子窗口数目对每个子窗口读取ID字节根据ID新建个窗口然后让新窗口载入自己(低轨到它)当所有字窗口载入完毕时就结束了
   当然文件结构致也非常重要确保你存储代码以你想要载入顺序存储信息

4.3、资源编辑器
   要想真正使你GUI大放光彩你必须有个资源编辑器当然你不需要做个象开发环境提供资源编辑器那样华丽和强大但是你起码得有个基本来完成加入编辑删除排列免除你为对话框每个Control控件计算虚拟坐标位置麻烦事儿
   写个功能完善所见即所得(=English>WYSIWYG)资源编辑器超出了本文范围但是我能给你些小提示来帮助你完成这个壮举:
  • 共享你代码特别地让你资源编辑器和你游戏起分享同样渲染代码这样你就得到了所见即所得支持并且免除了开发两套GUI代码麻烦我向你保证调整你DirectX代码以使它渲染个GDI表面而不是个双缓冲系统将比重新开发整套新绘制代码简单记住过段时间的后你GUI系统可能会改变你不会想要经常在两个区别地方改写代码

  • 不要试图模仿开发环境外表和感觉换句话说不要费时间模仿开发环境细节(例如属性页和预览窗口)如果你编辑器相对而言比较难看不要沮丧;小组效率是和他使用工具效能成直接正比关系但是同时小组的外人是不可能使用你资源编辑器你也不会用它去开发个完整GUI;你不过只是做几个对话框而已你不需要环境文本帮助(=English>context sensitive help)你不需要环境文本菜单(=English>context menus)除非你觉得这会简化个特定繁复操作如果你资源编辑器不那么漂亮也无所谓只要它能完成工作就行了

  • 强调数据完整而不是速度资源编辑器是个数据整合者而不是个高性能没有什么比你花了个小时来设计东西由于而丢失而更让人恼火事儿了当写你GUI时候保存数据是你最高目标花些时间来做自动存储释放缓冲区(=English>autosaves, undo buffers)等等别把优化看得那么重要
4.4、生成子类(=English>sub)
   那些熟悉Win32处理窗口人们可能已经知道“sub”这个术语含义了如果不知道当你“sub个窗口时候你就“衍生(=English>derive)”个新窗口类型然后把新窗口类型嵌入到旧窗口要使用地方
   让我做更详细地解释比如我们需要个超级列表框我们已经有个普通列表框类但是某种原因它不适合;我们游戏需要超级列表框所以我们从普通列表框类中衍生出个超级列表框类就是这样
   但是我们如何在我们游戏对话框中放置这个超级列表框呢?由于超级列表框是为我们特制我们不能为我们资源编辑器增加来支持它但同时我们怎样通知GUI系统为这个特殊例子(我们游戏)让所有列表框都是超级列表框呢?这就是生成子类(=English>sub)要做事情这不是个精确技术定义但是表达了足够信息
   这里我要讲述思路方法称作“载入过程生成子类(=English>subing at load time)”要理解它让我们从上节所述基本载入代码开始我们有个载入它第归地完成创建载入增加窗口这里我们用PDL表述如下:



  =ColorCatchword>// read total number of children for this window
   // for each child...
     // read window ID from disk
     // a gui_window derivative based _disibledevent=>  要完成生成子类我让我窗口载入“给个创建这类型窗口机会“像这样:

   =ColorCatchword>// read total number of children for this window
   // for each child...
     // read window ID from disk
     // give application a chance to create a window of this type
     // the application didn\'t create a window,
       // then a gui_window derivative based _disibledevent=>

   我通过指针给这个机会如果需要为个窗口生成子类就在指针里填上自己地址当窗口载入过程中这个,传入想要创建窗口ID如果想要根据ID为个窗口生成子类新建个适当对象并把新指针返回给窗口如果不需要这个ID则返回NULL窗口根据返回值创建恰当默认对象这种思路方法允许“预先过滤”引入窗口ID信息并为特定窗口类型重载默认太完美了(译者:这段我翻译得实在不能说是完美相反是简直不知所云这里把原文贴出来请您自己斟酌吧)
   =English>Specically, I give the application this chance by way of a function poer. If the application needs to sub a window, it fills in the function poer with the address of its own function. When the windows are loading, they call this application function, passing in the ID of the window they want to create. If the application wants to sub a window from this ID, it s up the appropriate object and s the poer back to the window. If the app doesn\'t want to do anything special for this ID, it s NULL, and the window function senses this and s up the appropriate default object. This method allows the app to \"pre-filter\" the incoming window ID s, and to override the default behavior for certain window types. Perfect!

   用这种思路方法在创建自定Control控件时候给了我很大自由我为我资源编辑器增加代码以使我能为每个存储窗口改变ID然后当我需要自定控间时候我只需用资源编辑器改变保存这个窗口ID字节在磁盘上保存是ID和所有为自定Control控件其他基类属性
   很快吧?还有其他思路方法来做同样这是在模仿STL需要创建对象时使用思路方法STL使用特定“allocator(分配符)”类这有点儿像“类厂”(=English>factories)它们按照客户告诉他们需要来创建类你可以使用这种思路方法来创建窗口
   这种思路方法工作原理如下:创建个类并把它叫做“gui_window_allocator”个虚拟叫做CreateWindowOfType它接受个给定窗口ID并传出个新指针给窗口现在你就得到了个简单分配符类窗口载入代码将使用它来新建需要窗口
   现在当你需要为窗口重载“”操作符衍生个新相关gui_window_allocator类并告诉你窗口载入代码来使用这个分配符而不是默认那个这种思路方法就象提供指针只用了点儿C

4.5、加速GUI渲染
   还有个能帮助你加速GUI渲染小提示
   关键概念是就象其它绘制优化不要画你不需要东西默认方式GUI花很多时间绘制没有变化部分然而你能通过告诉GUI绘制改变窗口(=English>windows that are dirty)作些优化当窗口外观需要改变时候窗口设定它们dirty标志在绘制时候清除它们dirty标志
   由于我们GUIControl控件可能是透明个Control控件被标记为dirty父窗口必须也被标记为dirty这样当它被绘制时候背景没有改变父窗口也刚刚被重绘

4.6、整理总结:相逢在XGDC
   呼好长4篇文章然而我们还是遗漏了很多
   我准备在即将来临Armageddon XGDC(eXtreme Game Developer\'s Conference)上讲述GUI我将尽力让我发言有用现在你已经看了所有文章如果你有什么需要扩展问题或是我有什么遗漏请给我写信让我了解祝各位做游戏愉快



   作者介绍:
   Mason McCuskey先生是Spin Studio(个正在制作名为Quaternion伟大游戏制作小组)领导者.他盼望着你建议和评论电子邮件是([email protected])

   译者手记:
   终于结束了漫长翻译过程这是Rick翻译过最长也是难度最大技术文章了其中定有不少和遗漏如果您发现了这些问题请来信告诉我([email protected])谢谢您支持

Tags:  怎样开发图形编辑器 开发svg编辑器 eclipse开发编辑器 怎样开发编辑器

延伸阅读

最新评论

发表评论