从零开始做3d地图编辑器基于qt与ogre_第1页
从零开始做3d地图编辑器基于qt与ogre_第2页
从零开始做3d地图编辑器基于qt与ogre_第3页
从零开始做3d地图编辑器基于qt与ogre_第4页
从零开始做3d地图编辑器基于qt与ogre_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第一章 基础知识注:文章里面有不少个人见解,欢迎大家一起互相讨论。希望高人能给予相应理解与意见建议。在实际3D游戏开发中,编辑器是极其重要的一个部分,一个优秀健壮的编辑器,可以使项目事半功倍,而相反,一款BUG超多(随时会挂)又不注重操作习惯(完全基于快捷键,又没有详细的使用说明)的编辑器,不仅会使项目事倍功半,而且会削弱开发人员的积极性,甚至让开发人员对项目产生排斥情绪。编辑器在游戏里面应用很广泛,一般都有地图编辑器(关卡、世界)、粒子编辑器、动画编辑器、字体编辑器(单机里面较多)、UI编辑器、材质编辑器、脚本编辑器等等,编辑器设计制作方法也大致可分为两个趋势,一种是倾向于做大而全的世界编辑

2、器,一种是做小而精的功能编辑器,在这里我不想讨论这两者的利与弊,我只能说,只要这个解决方案可以解决我们当前的问题,那么它就是一个适合现阶段的解决方案,但并不一定是最好的解决方案。一、工具现在制作编辑器,流行以下几种方式:1、 使用C#制作基于WinForm的编辑器。2、 制作基于MFC的编辑器。3、 制作基于WxWidgets的编辑器。4、 制作基于QT的编辑器。基于C#来制作编辑器,在制作一些小工具上面很有利,比如说打包工具,加密器等等和图形关系不大的工具,它的优势在于它的简单易用,但是当你涉及到图形这一块的时候,如果引擎支持不C#,那么使用XNA、Manage DX 都不是很好的一种解决方

3、案(除非你的游戏就是基于两者),导入动态链接库的方法又会比较麻烦,C#和C+之间还是有不小的区别。基于MFC做编辑器,在以前基本是首选,它的优势在于文档应用特别多,你遇到问题的时候,基本上网络上都能找到解决方案,但是它相对门槛高,一个初学者经常会被它折磨得兴趣殆尽,应用也很麻烦,特别是在多窗口应用上面,所以以前我用MFC做编辑器都是基于Dialog来做。WxWidgets和QT都是跨平台的GUI 库,目前来说还算主流,我个人倾向于QT,WxWidgets了解不多,QT目前由诺基亚负责,有自己的IDE、设计工具、详细的例子、比较充实的文档、与VS的结合还算完美,还有一些第三方的库支持,网络上的资

4、料也还多,是个发展潜力不错的GUI库。因为我将要做一个3D地图编辑器,在图形这一块也有不少选择,OGRE与Irrlicht等,我选择使用OGRE,当然你也可以选择自己的引擎。OGRE是一个开源的图形渲染引擎,它的材质脚本还是很强大的,简单易用、目的性明确,让你的Shader容易应用与修改。早期的版本在地形这一块做得不够,所以早期做OGRE的地形编辑时一般会选择ETM,PLSM等库,新的1.7版本对地形这一块增强不少,而我也会在编辑器里面应用它地形编辑的功能。二、工具安装指南1、OGRE下载与编译OGRE官方网站:下载最高版本的OGRE(1.7.1),有两种方式:第一种方式是直接下载SDK,下载

5、的SDK可以直接使用,但是由于编译环境不同,可能会缺少一些DX的DLL,你得在网络下另外下载缺少的DLL,下载方法是从网站左侧的DownLoad里面选择SDK,然后选择相应VS的版本,我们推荐使用VS2008,因为QT针对2008做了一个AddIn。第二种方式是下载源代码进行编译。个人觉得使用OGRE应该使用自己编译的库,毕竟有什么需要的时候还可以自己修改,自己编译需要注意几点:1、除了OGRE源码外,你需要额外下载Microsoft Visual C+ Dependencies Package,并把它解压到OGRE目录(你自己的OGRE目录)后编译。 2、你需要下载CMAKE,官方网站是。下

6、载一个最新版本就行。3、你机器需要安装DX的SDK,不然OIS和DX的渲染系统插件无法编译。4、使用Cmake生成Ogre VS解决方案的时候要记得指定Dependencies目录(在Cmake提醒你的时候指定)。此过程可以参考用VS打开生成的解决方案,然后直接编译就可以获得dll和lib.2、QT下载QT官方网站:下载QT也有两种方式,一种是纯SDK(Qt SDK for Windows* (287 MB)),另外一种是针对VS2008的库(Qt libraries 4.6.2 for Windows (VS 2008, 194 MB)),这两者有一定的区别,前者带有更多的工具(IDE等)。

7、我推荐下载针对VS2008的库,下载安装完之后,还需要下载一个Addin,这个Addin比较难找,在Other downloads里面下载Visual Studio Add-in (44 MB)。安装完Add-In之后,打开VS2008应该就可以找到QT的模板了。QT4 projects下面有一些选项,选择新建一个QT Application。新建完编译通过,运行发现这是一个基本窗口。如果编译OIS没有成功,请在项目属性里面填入DX的include和lib路径。三、开始之前的配置我看到过很多同志在做项目时,直接新建项目后立马就直接开始编程,使用的是VS默认目录,结果在Debug的时候老是找不到

8、dll,找不到资源,然后又花了一堆的时间去查找问题,白白地浪费了不少时间,更有甚者就在此时便失去了继续向下的动力,觉得这个东西太难理解了(一遇挫折就跑)。所以我觉得在每次开始项目前都应该好好地把解决方案配置一下。我做项目的时候喜欢这种方式,项目目录下面存在以下几个目录。Bin目录不难理解,里面放的是生成的可执行文件,下面又分了Debug、Release、Data(Media)等目录,Debug、Release里面放的是执行文件和dll,命名的时候Debug要命名为_d.exe.因为资源文件是共用的,所以资源不应该放在Debug或Release下面,直接放Bin下面就行了。Docs目录里面放的是

9、相关文档。Objs目录里面存放编译过程中的中间文件,临时文件。Scripts目录里面存放解决方案,Sln或其他格式。SDKS 目录存放第三方库,比如OGRE,Boost,Lua等。Tools目录存放着制作时的一些工具。剩下那个目录一般改名为Src或source.为什么目录要这样分?Bin文件夹分出来有利于你程序的发布,调试。把Objs从source分出来,有利于你的源代码版本控制,备份。把解决方案单独拿出来,有利于你的跨平台或换IDE,SDKS拿出来很重要,因为有可能两年后你的引擎或者底层更新或者大改动过,但是你又需要把两年前的游戏重新编译,如果没有备份好,结果自然不难想像。同样,工具也是这样

10、,比如说加密器算法经常改动,你不备份好你的东西以后都没有办法修改了。接下来要调整VS来适应这一套目录结构。第一件事,用文本工具打开修改sln,把它指向source目录里面的工程文件。# Visual Studio 2008Project(8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942) = Test, .SourceTest.vcproj, 83E01383-8BC1-404F-9C25-A9AFFCDBB210EndProject像上面那样修改为你的工程名.之后用新的解决方案打开项目,在VS里项目名上右键打开属性。之后的第一件事情就是修改工作目录,很多同志就是因为没

11、有设定这个目录导致找不到DLL,它在配置属性中调试一栏里面,修改成你当前的Bin所在目录,最好设置为相对目录,Debug模式下是./Bin/Debug,对应的Release下面是./Bin/Release。接着在常规里面修改中间目录和输出目录,我们都修改成./Objs/Debug和./Objs/Release。之后在链接器常规里面修改输出文件,修改成.binDebug$(ProjectName)_d.exe和./Bin/Release/$(ProjectName).exe。然后在C/C+常规中把你要的include添加进去,在链接器附加库中把你要的lib目录添加进去。完成这些我们就配置完了。附

12、:Ogre1.7.1的配置要注意:由于Ogre使用了boost,所以一定要把Ogre自带的Boost目录放进SDKs中,如果要使用OIS,还得包含OIS的头文件路径,库文件和OGRE放在一起,所以不用再设置。另:如果是在IDE中新建QT Application,QT头文件与库的相关配置会自动帮你设置好。你只需要在它的基础上把其他库添加好就行了。四、QT基本知识回到QT,先在VS中新建一个QT Application,项目里面有几个目录:1、 Form Files目录,它里面放的是使用QT designer制作的基于XML的布局文件,双击它就会自动进入QT designer。2、 Generat

13、ed Files目录,它里面放的是一些临时生成的文件,这些文件用来处理QT的信号和槽等机制。3、 Resource Files目录,它里面放的是基于XML的资源文件,你可以在窗体里面使用它们。4、 Header Files和Source Files这两个和VS默认是一样的。理解了目录结构之后,先来试着写一个Hello World,先把除了main.cpp之外的所有文件移除(使用QT designer会提高制作效率,但是会让QT入门门槛变高)!打开main.cpp,仅保留以下代码:view plaincopy to clipboardprint?#include int main(int arg

14、c, char *argv) QApplication a(argc, argv); return a.exec();#include int main(int argc, char *argv) QApplication a(argc, argv); return a.exec();编译通过。运行没有任何反应,因为还没有往里面增加任何东西。在代码中,Main函数是C语言的入口,之后申请的QApplication用来管理控制流和主要设置,这是核心,一定要保留。按钮是GUI中最基本的一个控件,先看看怎么增加一个按钮。使用按钮控件必须先包含头文件:view plaincopy to clipboa

15、rdprint?#include #include 然后在QApplication a(argc, argv);与return a.exec();中间插入下面代码:view plaincopy to clipboardprint?QPushButton button(HELLO); button.setGeometry(100,100,300,300); button.show();QPushButton button(HELLO); button.setGeometry(100,100,300,300); button.show();代码第一行是申请一个按钮,并把按钮的Caption标题设为

16、HELLO,第二行表示这个按钮出现在屏幕坐标(100,100)的位置,宽高为(300,300),最后一行是显示这个按钮,你可以尝试把它去掉看看效果(官方助手里有QPushButton的更多资料,请自行查看)。编译出来,发现屏幕上出现一个框,框里面有一个按钮,按钮可以点击,但是没有任何反应,因为还没有为这个按钮增加任何的槽(Slot)。在MFC对控件的处理一般是通过事件机制,而在QT中是使用信号(Signal)和槽(Slot)机制,其实你也可以把它理解为事件机制。简单理解信号其实就是输入,而槽就是输出,拿按钮打比方,在一次点击中,这个点击,就是一个信号,而点击后的反馈,就是槽。每一个控件都拥有一

17、些默认的Signal和Slot,这些都可以在官方提供的助手中查看。绑定Signal和slot是使用静态函数connect。函数原型是:view plaincopy to clipboardprint?Bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt:ConnectionType type = Qt:AutoConnection )Bool connect ( const QObject * sender, const char

18、 * signal, const QObject * receiver, const char * method, Qt:ConnectionType type = Qt:AutoConnection )其中sender是发送者,而receiver是接收者,signal是信号,而method就是slot,type里面提供了几种绑定方式,可以详细查看助手。 先看一个例子,在上面代码中加入点击按钮后关闭应用程序的效果。很简单,只需要在view plaincopy to clipboardprint?button. setGeometry(100,100,300,300);button. setGe

19、ometry(100,100,300,300);后面加入view plaincopy to clipboardprint?QObject:connect(&button, SIGNAL(clicked(), &a, SLOT(quit();QObject:connect(&button, SIGNAL(clicked(), &a, SLOT(quit();编译运行,点击后窗体关闭。这是使用默认槽的例子,有时候需要点击按钮之后执行自定义的效果,那么就需要使用自定义槽了。 下面是一个使用自定义Slot的例子,鼠标点击按钮之后,文本框文字会改变。先加入一个QLabel控件,你先加入头文件:view

20、plaincopy to clipboardprint?#include #include 然后在connect前加入view plaincopy to clipboardprint?QLabel label(World); label.setGeometry(50,50,300,300);QLabel label(World); label.setGeometry(50,50,300,300);先尝试编译一下,结果label没有出现在窗体里面!它当然不会出现在窗体里面,因为我们只是对Button使用了Show()函数,尝试加入label.show(),结果出现了两个窗体,一个里面有按钮,另一

21、个里面有一个label。那么怎么把它们放在一起呢? 通过上面的测试发现,调用一次show就会产生一个窗口,那么是不是只调用一次show就行了?把函数里面代码改为:view plaincopy to clipboardprint?QApplication a(argc, argv); QWidget window; QPushButton button(HELLO); button.setGeometry(100,100,300,300); QLabel label(World); label.setGeometry(50,50,300,300); QHBoxLayout layout; Lay

22、out.addWidget(&button); Layout.addWidget(&label); QObject:connect(&button, SIGNAL(clicked(), &window, SLOT(close(); window.setLayout(&layout); window.show(); return a.exec();QApplication a(argc, argv); QWidget window; QPushButton button(HELLO); button.setGeometry(100,100,300,300); QLabel label(World

23、); label.setGeometry(50,50,300,300); QHBoxLayout layout; Layout.addWidget(&button); Layout.addWidget(&label); QObject:connect(&button, SIGNAL(clicked(), &window, SLOT(close(); window.setLayout(&layout); window.show(); return a.exec();附上此时的头文件列表:view plaincopy to clipboardprint?#include #include #inc

24、lude #include #include #include #include #include #include #include 一开始,我就申请了一个QWidget,QWidget类是QT中所有用户界面对象的基类,它本身并没有什么实际意义,在这里你可以把它看成一个窗体容器,然后又添加了一个QHBoxLayout layout; QHBoxLayout这是个可以对子widget进行特定布局的控件,通过它可以把按钮和label并排,之后把窗体的layout设为指定的layout,然后调用show()。调试运行,终于两个控件都出现了。回到之前的话题,自定义槽。在QT中所有自定义槽都需要先编译

25、成moc,才可以被使用。不过你放心,这个过程由QT自动完成,当然你也可以手动进行编译,QT的Bin目录里面有moc.exe,参照说明进行使用。你应该可以看到我已经偷偷把按钮的点击信号转向了窗体的close槽。为什么要这样做呢,因为我们需要把自定义槽函数定义放在头文件里。第一步,先把window封装起来,我新建一个MainWidget类,继承自QWidget类,类的头文件如下:view plaincopy to clipboardprint?#ifndef _MAIN_WIDGET_H_#define _MAIN_WIDGET_H_#include #include #include #incl

26、ude class MainWidget: public QWidgetpublic: MainWidget(); MainWidget();protected:private: QLabel* m_pLabel; QPushButton* m_pButton; QHBoxLayout* m_pLayout;#endifCPP如下:#include MainWidget.hMainWidget:MainWidget() m_pLabel = new QLabel(World); m_pLabel -setGeometry(50,50,300,300); m_pButton = new QPus

27、hButton (HELLO); m_pButton -setGeometry(100,100,300,300); m_pLayout = new QHBoxLayout(); m_pLayout - addWidget(m_pButton); m_pLayout - addWidget(m_pLabel); connect(m_pButton, SIGNAL(clicked(), this, SLOT(close(); setLayout(m_pLayout);MainWidget:MainWidget()#ifndef _MAIN_WIDGET_H_#define _MAIN_WIDGET

28、_H_#include #include #include #include class MainWidget: public QWidgetpublic: MainWidget(); MainWidget();protected:private: QLabel* m_pLabel; QPushButton* m_pButton; QHBoxLayout* m_pLayout;#endifCPP如下:#include MainWidget.hMainWidget:MainWidget() m_pLabel = new QLabel(World); m_pLabel -setGeometry(5

29、0,50,300,300); m_pButton = new QPushButton (HELLO); m_pButton -setGeometry(100,100,300,300); m_pLayout = new QHBoxLayout(); m_pLayout - addWidget(m_pButton); m_pLayout - addWidget(m_pLabel); connect(m_pButton, SIGNAL(clicked(), this, SLOT(close(); setLayout(m_pLayout);MainWidget:MainWidget()Main.cpp

30、改为:view plaincopy to clipboardprint?#include #include MainWidget.hint main(int argc, char *argv) QApplication a(argc, argv); MainWidget window; window.show(); return a.exec();#include #include MainWidget.hint main(int argc, char *argv) QApplication a(argc, argv); MainWidget window; window.show(); re

31、turn a.exec();编译运行,结果和上次一样。接下来申请一个自定义Slot,首先在头文件public:前加入宏Q_OBJECT;只有加入了Q_OBJECT,你才能使用QT中的signal和slot机制。这点很重要,不然你编译的时候会报“找不到slot”的错误。然后在protected: 前加入:view plaincopy to clipboardprint?private slots: void SetText ();private slots: void SetText ();slot同样也分private、public、protected,意义和c+一样。CPP中加入相应执行:v

32、iew plaincopy to clipboardprint?void MainWidget: SetText () m_pLabel - setText(Test);void MainWidget: SetText () m_pLabel - setText(Test);把connect改成:view plaincopy to clipboardprint?connect(m_pButton, SIGNAL(clicked(), this, SLOT(SetText ();connect(m_pButton, SIGNAL(clicked(), this, SLOT(SetText ();

33、编译运行,这时点击按钮就会改变文字了。就这么简单。信号也可以自定义,不过信号自定义相对来说用武之地稍微小一点,定义的方式和slot定义差不多,都得在头文件中定义,举个例子:点击按钮后文本改变,触发一个新信号,这个信号会把文字又变回来。在头文件中加入:view plaincopy to clipboardprint?signals: void TextChanged ();signals: void TextChanged ();再增加一个Slot用来对这个信号进行反馈。在private slots:后加入view plaincopy to clipboardprint?void Recover

34、Text ();void RecoverText ();CPP中加入执行:view plaincopy to clipboardprint?void MainWidget:RecoverText() m_pLabel - setText(Hello);void MainWidget:RecoverText() m_pLabel - setText(Hello);注意信号是不需要加执行代码。然后修改SetText()函数加入触发新信号的代码:view plaincopy to clipboardprint?emit TextChanged();emit TextChanged();最后加入新的c

35、onnect:view plaincopy to clipboardprint?connect(this, SIGNAL(TextChanged(), this, SLOT(RecoverText();connect(this, SIGNAL(TextChanged(), this, SLOT(RecoverText();编译运行,结果和我们想要的一样。注:信号和槽都是可以有参数的。有关QT的基础知识就介绍到这里,具体控件的使用方法,请自行参考助手。五、OGRE基础知识友善提醒:如果你对OGRE比较了解,请自觉跳过此节。本节并不打算提供详细的入门教程,只是对OGRE的简单介绍,如果需要OGRE

36、的详细资料,请自行使用网络功能。1、OGRE是什么 Ogre是一款开源的图形渲染引擎,它的全名叫(Object-oriented Graphics Rendering Engine),目前在开源图形渲染引擎这一块排名第一,由于它功能齐全(跨平台,支持DX和OPENGL)、知名度高,而且不断更新,所以国内学习资料也比较多,在网络游戏在一块已有不少游戏公司已经使用过或者正在使用OGRE(天龙八部、成吉思汗等),部分公司招聘要求里面也明确表示熟悉OGRE者优先,所以说学习OGRE是前景可观的。2、OGRE可以做什么 首先OGRE只是一个图形渲染引擎,连输入输出都使用第三方的OIS,目前大部分应用都在

37、游戏、VR。但是如果你需要用它来做网络游戏,你还需要网络库、UI库、音频音效库等。3、如何学习OGRE OGRE自1.7以来,抛弃了它的ExampleApplication的框架,开始使用SampleBrower加dll的方式来表示例子,我个人认为虽然看起来更专业了,但是对于新人入门来说,难度比 ExampleApplication还高,尽管ExampleApplication就已经让新人晕头转向了! 那么怎么去学习OGRE呢,有一本书是必备的,名字叫PRO OGRE 3D PROGRAMMING(现在已经有爱好者翻译的中文版了),这本书是OGRE入门的圣典,推荐方法是先仔细地看一遍,然后再重

38、头开始码例子,为什么推荐这样做,因为我发现有些人在学习Opengl的时候,看完glbegin,glend就不看了,甚至还动手写引擎,人家红宝书后面明确地表明尽量不要使用glbegin,glend! 官方手册也是必看的,里面对一些模块进行了详细的讲解,材质脚本说得挺细。 个人推荐OGRE入门掌握顺序:A、 渲染窗体管理(初级:初始化,销毁)B、 OIS输入输出(初级:两种模式(回调、缓冲)、按键处理) C、场景管理(初级:管理器选择,节点管理、实体管理) D、材质(初级:材质使用、材质脚本) E、资源管理(初级:资源组、资源) D、动画(初级:骨骼动画) E、面片相关(初级:表层、公告板、粒子)

39、 基本掌握这些就可以做些简单的游戏了,然后在这基础之上再慢慢探索OGRE的庞大的世界。几个学习的地方:1、OGRE官方网站:、官方论坛、Addon论坛、wiki是学习OGRE的好地方。 2、中文社区:也聚集了不少OGRE的爱好者。 3、游戏资源网也是一个学习游戏开发的不错的网站。请充分利用你手头上面的搜索工具,百度适合搜索国内中文资料,google适合搜索英文资料。第二章 编辑器的基本框架一、几个问题前面说了很多编辑器之外的东西,真正要动手做编辑器了,也不能一股脑地就开始了,这之前必须要问自己几个问题:1、这个地图编辑器有什么基本功能?2、导入导出文件格式?A、3D地图编辑器的基本功能正如开篇

40、所说,编辑器制作有两种趋势,其中一种是大而全的世界编辑器,这种方式可以带给极大的成就感,正合很多新人的意,但是我觉得一开始给自己(特别是新人)设定一个庞大的计划是件空洞而不现实的事情,一个编辑器越是大而全它的应用方向就越窄,越不利用拓展,使用就越费劲,问题BUG也就越集中,维护成本也就越高。其实可以从小做起,先来分析基本需求:所谓地图编辑器,地图编辑是其基础功能,一般地图都是在地形(平面)上面放置演员(把它叫作演员是不希望和OGRE的实体概念冲突),那么我们就确定了我们两个需求:地形编辑、演员管理。 那么这两个需求又引申出新的需求,地形不能是光模吧,演员不能永远是编辑器预设的几个模型吧,所以我

41、们又需要实体、纹理加载与删除的功能。加载之后的纹理和实体总应该有个地方可以浏览吧,不然怎么选择使用? 好了,因为我们的目标暂时是做一个基本框架。所以我们暂时确定以下基本需求:1、 添加删除浏览实体、纹理2、 地形编辑3、 演员管理除了基本需求外,我们还有另外一些编辑器本身的一些需求:1、 菜单、工具栏、状态栏。2、 日志管理。日志管理是一个很重要的东西,它得支持两种方式,一种是导成文本,另一种是在编辑器里面实时看到,为什么要提供这两种东西呢,如果没有文本,有时候挂的时候你看不到为什么挂,如果没有实时地看到每次去看文本又很麻烦。B、文件格式导入导出文件格式是一个很纠结的问题,现在一般流行几种方式

42、:1、 纯二进制数据,优点是读取速度非常快,几乎无浪费数据,缺点是不易被修改,如果没有工具基本上几乎不可能被改动(当然你要约定某些字符串也是可以的),这种方法还有不少应用。2、 自定义格式,类似于INI,优点是终于可能手动修改了,缺点是得花不少时间去写解析模块,应该是一种过渡解决方案,这种方案和上面那种有模糊的界定,区别在于这个拥有一个解析器。3、 XML,现在应该是主流,优点是编辑修改很方式,手改也行,工具也很多,还不用写解析器,TinyXML,RapidXML等都是不错的解析器,缺点是效率低,在特定环境下会出现偶尔读不出文件的情况(可能是解析器的问题)。现在不少游戏使用两种1和3两种方式结

43、合的方法,在编辑时使用XML,结果用工具导成纯二进制加密文件,我也打算使用这种方法:编辑器配置文件(需要对窗体的开关状态进行存储)和生成的地图使用XML。导入纹理、实体使用OGRE默认支持的格式。二、基本框架布局 根据上一节的一些基本需求,做出一个简单的布局如下图:窗体大小:1024*768,太大了有点显示器放不下!支持最大化,最小化,关闭按钮,支持手动拖大拖小。拥有菜单项(支持快捷键,图标):File : New, Open, Save, Save As, ExitEdit: Undo, Redo,Copy, Paste(这个功能暂时保留)Window:Entity List, Textur

44、e List ,Node List, property,Log,(支持图标check)Help:About工具栏拥有按钮:New, Open, Save, Save As, Undo, Redo,Copy, Paste, Entity List, Texture List , Scene, property,Log,(部分支持check)Dock窗口(支持自由拖动,重新排列,叠加,关闭,打开):EntityList, Texture List, Node List, property,(这四个都可以是左右两侧),log窗口(只能在下侧)视口:OGRE的显示窗口,大小可以改变。我们这里暂时只提供

45、一个窗口,通过状态机加多个摄影机来管理浏览。各个Dock窗口都拥有自己的小工具栏,Entity ListTexture ListNode list都是树型结构,栏目里面拥有相应添加删除的子功能。属性栏使用了QT的第三方库,这个库得另行下载,后面会有详细介绍。日志栏使用QListWidget,提供SystemLog方法,添加日志后自动跳转到最新。状态栏显示鼠标移上控件时的一些详细说明。三、窗体、菜单栏、工具栏、状态栏A、创建窗体 我还是按照QT基础那节的内容创建一个窗体类,不同的是这个窗体类现在继承于QMainWindow,它会使得封装中央部件、菜单条和工具条以及窗口状态变得更容易。接下去,设置

46、标题和窗口大小:view plaincopy to clipboardprint?setWindowTitle(Editor); /设置窗口标题 resize( WINDOW_WIDTH, WINDOW_HEIGHT);/ 设置窗口大小setWindowTitle(Editor); /设置窗口标题 resize( WINDOW_WIDTH, WINDOW_HEIGHT);/ 设置窗口大小其中WINDOW_WIDTH和WINDOW_HEIGHT被定义在头文件中:view plaincopy to clipboardprint?static const int WINDOW_WIDTH = 102

47、4; static const int WINDOW_HEIGHT = 768;static const int WINDOW_WIDTH = 1024; static const int WINDOW_HEIGHT = 768;在C+里尽量减少使用宏。设置中央部件: view plaincopy to clipboardprint?setCentralWidget(m_pButton);/暂时把按钮设置为中央部件setCentralWidget(m_pButton);/暂时把按钮设置为中央部件为什么要设置中央部件呢?因为接下去我要使用Dock Widget,如果没有中央部件,左侧,右侧,下部

48、就没有参照,也没意义了。 针对我们的基本框架,目前也仅仅需要这些简单的功能。B、创建菜单栏和工具栏在QT创建菜单、工具栏前,必须先创建QAction,然后把这个QAction添加给菜单或者工具栏。QAction是什么,它是用户的UI动作,在一列菜单中,比如说File下面的new 就是一个QAction,这个QAction包括包括图标,名字,快捷方式,状态栏信息等。我通过以下方法来设置QAction:头文件中加入:view plaincopy to clipboardprint?QAction* m_p;QAction* m_p;因为工具栏和菜单都共用一个QAction,所以我把它用为类成员放在头文件中。Cpp中加入:view plaincopy to clipboardprint?m_p = new QAction(QIcon(:/images/new.png), tr(&New), this); m_p - setShortcu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论