Ogitor代码分析

引擎状态监听(观察者)

底层变化时, 需要高层UI做出反应. 这个有一个原则, 就是下层逻辑不能依赖上层逻辑, 所以通过一个接口进行消息的派发. 如果是.net的话, 可以用delegate/event实现. C++的话, 可以自己用模板写个delegate用, 效率比用接口高…

实体抽象(工厂方法)

扩展性是很强, 但是…类太多了-_-. 这里有种基于DLL的插件模型可以学习. 工厂方法需要知道具体的工厂对象, 这里要求初始化工厂的对象(OgitorRoot)要知道具体的工厂定义(C++的#include做得太失败了, 导致编译效率低下…). 但是做成DLL插件的话, 就可以利用DLL的导出函数反向调用OgitorRoot进行注册. 不过, 对于内部使用, 进行二进制分离有意义吗?

Undo/Redo(命令模式)

这机制实现的前提是, 所有CBaseEditor对象都可以用一系列的”属性”来进行初始化/设置. 所以每一个Command都是针对属性的修改. 对于Create/Destory来说, 可以看成对所有属性的修改外加对象的创建/删除. 属性的变量类型并没有进行抽象, 而是转换成了字符串, 需要时再转换回来. 如果是.net的话, 就方便许多, 直接可以获得PropertyInfo[], 而且能跟PropertyGrid控件进行属性的自动绑定. 不过这属于语言的”反射”应用, 标准C++不具备这个特性(@_@).

  1. BaseEditor^ object = root->FindObject(objName);  
  2. if (nullptr == object)  
  3. return;  
  4. Dictionary<String^, Object^> properties = undoCmd->Properties;  
  5. for each(KeyValuePair<String^, Object^> pair in properties)  
  6. {  
  7.     PropertyInfo^ info = object->GetType()->GetProperty(pair->Key);  
  8. if (nullptr != info)  
  9.         info->SetValue(object, pair->Value, nullptr);  
  10. }  

鼠标编辑

就是移动, 旋转, 缩放对象的操作响应还有可视化表示. 操作时的选中轴是所有编辑对象统一使用一套, 自定义的表示, 如下图中的spot light, 是通过派生CVisualHelper来进行定制绘制的.

多选处理

这里到是没用什么有用的模式, 不过对于OgitorsRoot::VolumeSelect()的算法到是很感兴趣.

在viewport上的矩形选框, 可以对应3D空间一个5个平面组成的包围体(远面不包含), 以这个包围体到场景树去遍历查询所有实体, 就能得到选中的实体列表. 所有选中对象组合成一个CMultiSelEditor进行移动/旋转/缩放.

属性编辑

把SetXXX全部定义到一个函数指针数组, 根据类型(ID)进行索引, 避免了一堆if-else. 无论是UI到引擎, 还是引擎到UI的通知, 都是以这个ID来进行查找的. PropertyGrid的Item绑定的数据, 也是这个ID, 而不是实际的对象. 但是, 这样也带来另一个问题: 每扩充一个属性就会去改动这个类型定义的头文件, 那DLL中定义的特殊属性怎么办?

  1. /// The definition for any SETXXX function
  2. /// BIND_ID: is the BINDING ID between the PropertyGrid and the Actual Functions
  3. ////param val     : Since the actual variable types change, PropertyGrid passes
  4. ///                 Its values as String and refresh
  5. ////param refresh : Since those functions can be called by any object other than PropertyGrid
  6. ///                 this parameter defines if the value at PropertyGrid should be refreshed
  7. ///                 used as "false" from PropertyGrid
  8. typedef void (THISCALL CBaseEditor::* BINDINGSETFUNC)(int BIND_ID,Ogre::String val,bool refresh);  
  9. static BINDINGSETFUNC   m_SetFunctions[MAXIMUM_BINDING_FUNCTIONS]; ///< List of BINDING FUNCTIONS

序列化

这里有能体现出属性进行抽象的好处了, 所有对象直接写进XML格式的工程文件. 用XML的好处就是, 增删属性不用改文件序列化的代码, 缺点是解析速度慢, 占用空间大. 而二进制就比较郁闷, 格式一改动就要进行代码变更, 通常还要兼容几个版本的文件. 地形方面由于是插件的原因, 文件是独立的. 不过不管什么场景, 地形独立出来其实没什么不好的, 因为地形的格式比较稳定, 不会经常变动, 独立出来更方便做版本管理.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

编写快速安全Bash脚本的建议

作者:oschina 来源:https://www.oschina.net/translate/bash-scripting-quirks-safety-tip...

2918
来自专栏喔家ArchiSelf

全栈必备JavaScript基础

1995年,诞生了JavaScript语言,那一年,我刚刚从大学毕业。在今年RedMonk 推出的2017 年第一季度编程语言排行榜中,JavaScript 排...

1274
来自专栏程序员阿凯

JDK10 揭秘

1535
来自专栏高性能服务器开发

服务器开发通信协议设计介绍

由于我们的即时通讯软件的用户存在用户状态问题,即用户登录成功以后可以在他的好友列表中看到哪些好友在线,所以客户端和服务器需要保持长连接状态。另外即时通讯软件一般...

1972
来自专栏互联网杂技

Web前端面试题目汇总

以下是收集一些面试中经常会遇到的经典面试题以及自己面试过程中无法解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识,如有错误或更好的答案,欢...

3414
来自专栏一“技”之长

iOS中CoreData数据管理系列一——初识CoreData

    CoreData是一个专门用来管理数据的框架,其在性能与书写方便上都有很大的优势,在数据库管理方面,apple强烈推荐开发者使用CoreData框架,在...

603
来自专栏GopherCoder

『Go 语言学习专栏』-- 第九期

1171
来自专栏卡少编程之旅

js线程机制的介绍和练习

33413
来自专栏顶级程序员

分享史上Java最牛逼,最简短的代码

转自:最代码 确实是12306的最核心代码呀 <script> alert("当前访问用户过多,请稍后重试!"); </script> 确实牛 pub...

3517
来自专栏编程

正则表达式游戏的答案

两天过去了,我们才送出了四个番茄钟(其中一个还是作为礼物送给了鲁鸿驹先生,感谢鲁鸿驹的现场莅临指导 ,鲁总是VIM的fans,多年不编程的他还记得是删除一行的指...

2268

扫码关注云+社区

领取腾讯云代金券