Ogre 编辑器一(MyGUI+Ogre整合与主界面)
在查看Ogre例子时,想看材质要里的纹理,着色器代码都需要每个去查找,非常麻烦.也想看更新每个Ogre里的对象后有什么效果.然后看到Compositor组件与粒子组件时,想到能实时编辑着色器代码实时更新渲染.
开始想着C++做界面麻烦,用C#的winForm做,后面发现首先结合层比较麻烦,然后C#与C++一起调试也会比较麻烦,还有一些比较奇怪的异常也会麻烦.好吧,不如全用C++做,在学习能用在Ogre中的UI时,主要了解了包括Ogre自己的Overlay, CEGUI, MyGUI等等,最终选择MyGUI,因为他小,功能全,代码容易理解,这样拓展起来也方便.因此最终选定Ogre1.9 + MyGUI3.2.2.这二个项目还都是跨平台的,如果有机会,后面可以尝试移值.开发平台暂时选用VS2013.
首先整合MyGUI到Ogre中,这部分主要是加载MyGUI的资源文件与初始化MyGUI的环境.其中初始化整个函数如下.
void initRoot()
{
String pluginsPath = fsLayer->getConfigFilePath("plugins.cfg");
String logPath = fsLayer->getWritablePath("ogre.log");
root = new Root(pluginsPath, fsLayer->getWritablePath("ogre.cfg"), "ogre.log");
//root->showConfigDialog();
bool foundit = false;
for (auto rs : root->getAvailableRenderers())
{
root->setRenderSystem(rs);
String rname = root->getRenderSystem()->getName();
if (rname == "OpenGL Rendering Subsystem")//"OpenGL Rendering Subsystem"
{
foundit = true;
break;
}
}
if (!foundit)
return; //we didn't find it... Raise exception?
//we found it, we might as well use it!
root->getRenderSystem()->setConfigOption("Full Screen", "No");
root->getRenderSystem()->setConfigOption("Video Mode", "1024 x 768 @ 32-bit colour");
window = root->initialise(true, "Ogre3DX");
Ogre::TextureManager::getSingleton().setDefaultNumMipmaps();
allResListener = new AllResourceListener(); this->loadUIResources();
this->loadResources();
this->createSceneManager();
this->createView();
this->createGui();
this->createSceneRoot();
}
InitRoot
先初始化Root,选择渲染系统,初始化渲染窗口,加载UI资源等.我们单独把UI部分的资源拿出来,这样可以先加快界面出现过程,然后在界面里用进度条等显示加载游戏资源,这是大头部分,后面也会修改成这种,如下是UI资源部分代码.
void loadUIResources()
{
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Core", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/OgreData", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Show", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Show/Main", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Show/Panel", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Show/Other", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Show/PanelView", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Show/PropertyField", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/Themes", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().addResourceLocation("../../Media/GUI/TreeControl", "FileSystem", "MyGUI");
ResourceGroupManager::getSingleton().initialiseResourceGroup("MyGUI");
}
Load UI
其中GUI/Core里放的就是MyGUI中的Media/MyGUI_Media这个目录,这个是必需的,MyGUI下另外的几个文件夹都是非必要的.不过在这里,我设定的是黑色风格,MyGUI_Media默认提供的不是这种,所以把原MyGUI下的Media/Tools/LayoutEditor/Themes放入我们的资源文件GUI/Themes下,另外一些文件夹后面遇到再说.
在生成viewport与camera后,我们开始加载MyGUI,如下是初始MyGUI环境代码.
void createGui()
{
ogrePlatform = new OgrePlatform();
ogrePlatform->initialise(window, sceneMgr, "MyGUI");
gui = new Gui();
gui->initialise(); std::ostringstream handleStr;
long handle = ;
window->getCustomAttribute("WINDOW", &handle); inputMgr = new OgreViewUI::InputManager();
inputMgr->createInput(handle);
pointMgr = new OgreViewUI::PointerManager();
pointMgr->createPointerManager(handle);
pointMgr->loadPointerResources(); MyGUI::ResourceManager::getInstance().load("FrameworkFonts.xml");
MyGUI::ResourceManager::getInstance().load("MyGUI_DarkSkin.xml");
MyGUI::ResourceManager::getInstance().load("MyGUI_DarkTemplate.xml");
MyGUI::ResourceManager::getInstance().load("TreeControlSkin.xml");
MyGUI::ResourceManager::getInstance().load("TreeControlTemplate.xml");
MyGUI::ResourceManager::getInstance().load("AutoComplete.xml"); MyGUI::FactoryManager& factory = MyGUI::FactoryManager::getInstance();
std::string widgetCategory = MyGUI::WidgetManager::getInstance().getCategoryName();
factory.registerFactory<MyGUI::TreeControl>(widgetCategory);
factory.registerFactory<MyGUI::TreeControlItem>(widgetCategory);
factory.registerFactory<MyGUI::AutoComplete>(widgetCategory);
}
MyGUI Initialise
OgrePlatform的初始化就是把对应MyGUI的RenderManager关联在Ogre的渲染过程中,详细说明请看我上一篇 MyGUI 解析 里有详细介绍这个过程.而gui对象的初始化就是对内部的单例管理类初始化,初始化的过程大部分都在解析上面所说MyGUI中的Media/MyGUI_Media 中的文件.
然后我们初始化InputManager与PointerManager这二个类,这二个类会在MyGUI下的Common/Input中提供,一个截获鼠标与键盘事件,一个是管理鼠标显示状态.
前面所说,Media/MyGUI_Media下文件名都是固定的,MyGUI初始化时自动会去加载对应的固定名,而非那个文件夹下的文件,我们需要自己用MyGUI提供的ResourceManger进行load,前面我们用Ogre去load,但是Ogre不能处理这些文件,但是会记录对应文件路径,这样读出对应的文件流给MyGUI去处理.然后我们注册我们自定义的一些UI组件,上面的是树型控件和自动完成控件.
这样Ogre与MyGUI就整合在一起了.然后就是主界面大致设定,如下图所示.
暂时大致分成五个部分,上面是菜单区,左边是管理区,大致分成场景,资源等,中间上面是显示区域,中间下面暂时空出,右边部分是属性区.
在这里,我们要先定义一个主界面的Layout文件与菜单的Layout文件如下:
注意Align,在这,我们想让主界面占满整个窗口,则定义为Stretch,相当于winForm中的Fill,注意这也是第一层控件,我们需要定义他的name固定为Root或是_Main,因为MyGUI给我们提供的一个基本管理Layout文件类BaseLayout有字段mMainWidget,在初始化时,检测名为Root或_Main的Widget赋给mMainWidget,找不到则给出异常,这样有个好处,mMainWidget能代表当前Layout的大小,如果我们调整大小,修改这个就好,并且根据子Widget的Align来调整子Widget的大小,还有Layer,前文说过,同一层的UI定义的Layer最好在同一层,不然层之间会遮挡.
在主界面的Layout中定义划二个Widget控件在上面,一个name为MainMenuControl,Align为Top.一个name为MainControl,Align为Stretch.而在菜单界面对应的Layout中放入的是MenuBar控件在上面.
对于菜单界面,我们直接使用Layout editor生成的代码,如下代码.
ATTRIBUTE_CLASS_LAYOUT(MainMenu, "MainMenuControl.layout");
class MainMenu :
public wraps::BaseLayout
{
public:
MainMenu(MyGUI::Widget* _parent = nullptr);
virtual ~MainMenu(); private:
void mouseClick(MyGUI::Widget* sender);
private:
//%LE Widget_Declaration list start
ATTRIBUTE_FIELD_WIDGET_NAME(MainMenu, mMenuMenuBar, "Menu");
MyGUI::MenuBar* mMenuMenuBar;
ATTRIBUTE_FIELD_WIDGET_NAME(MainMenu, mLoadMenuItem, "load");
MyGUI::MenuItem* mLoadMenuItem;
//%LE Widget_Declaration list end
}; MainMenu::MainMenu(MyGUI::Widget* _parent)
{
initialiseByAttributes(this, _parent);
mLoadMenuItem->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::mouseClick);
} MainMenu::~MainMenu()
{
} void MainMenu::mouseClick(MyGUI::Widget* sender)
{ }
MainMenu
每个类名前面一个宏,控件字段上带一个宏,这样在初始化,调用initialiseByAttributes时,其实就是分析相应宏设置,类宏提供对应的Layout文件(需要注意放入Ogre加载的文件夹下,否则找不到), 控件字段提供控件对象与Layout中的子Widget对应.其实我们不要上面的宏,在初始化调用如下语句,是一个意思.
MainMenu::MainMenu(MyGUI::Widget* _parent)
{
initialise("MainPane.layout");
assignWidget(mMenuMenuBar, "Menu");
assignWidget(mLoadMenuItem, "load"); //initialiseByAttributes(this, _parent);
mLoadMenuItem->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::mouseClick);
}
MainMenu
我们还记的主控件里放入的是二个Widget,并没有实际对应某种控件,一般控件里放入Widget,表示实际对应是另一个我们自己定义的Layout,如这里,上面的Widget明显对应的是我们上面所说的MainMenu.我们看下,如下把这二者关联起来.
class MainPane :
public wraps::BaseLayout
{
public:
MainPane(MyGUI::Widget* _parent = nullptr);
virtual ~MainPane();
private:
MainMenu* mMainMenuControl = nullptr; tools::PropertiesPanelView* properyPanel2 = nullptr;
}; MainPane::MainPane(MyGUI::Widget* _parent)
{
initialise("MainPane.layout");
assignBase(mMainMenuControl, "MainMenuControl");
assignBase(properyPanel2 , "MainControl");
}
MainPane
在MainPane里,我们自己来写,没用生成的代码,我们也就不用那些宏了,自己来初始化,和前面一样,先initialise对应的layout文件,然后把layout对应控件名给某控件,和前面用assignWidget不同,这里我们用的是assignBase.assignWidget一般用于指定layout的template控件(也就是系统内定的控件),而assignBase一般用于把layout中的Type为Widget的控件定义成我们自定义的Layout对应类.
MyGUI说大了,再复杂的界面都是于assignWidget与assignBase来构成,对于其内部具体实现,请看相关代码与于我前篇 MyGUI 解析 .
Ogre 编辑器一(MyGUI+Ogre整合与主界面)的更多相关文章
- Ogre 编辑器二(用Ogre的地形组件加载天龙八部地形)
主界面如上文设计完成后,场景刚开始添加了是Ogre例子里的,发现场景里实物太少,于是想到直接把天龙的场景拿下来,天龙网上有源码,参考了下,把天龙的地形用Ogre的地形组件完成了下,如下是效果图: 因为 ...
- Ogre 编辑器三(自动生成与更新Ogre对象编辑界面)
最开始设计这个编辑器时,其中一个要求就是能在运行过程中,通过UI来更新各对象,这样我们就能明确每个Ogre对象更新其属性影响的渲染效果.比如点光源,方向光源,聚光灯各属性与效果,深度测试开启与关闭,深 ...
- Winform开发主界面菜单的动态树形列表展示
我在之前很多文章里面,介绍过Winform主界面的开发,基本上都是标准的界面,在顶部放置工具栏,中间区域则放置多文档的内容,但是在顶部菜单比较多的时候,就需要把菜单分为几级处理,如可以在顶部菜单放置一 ...
- Winform开发框架主界面设计展示
做了好多年Winform的程序的开发,主窗口的界面设计一般都要求做的更好一些,可以根据不同的系统功能模块进行归类整合,能使客户迅速寻找到相关功能的同时,也能感觉到整体性的美观大方,因此主窗口的界面设计 ...
- android布局实践——模仿微信主界面
这是目前微信6.0版本的主界面 先来分析一波: 1.(top.xml)界面头部有一个微信(6)消息提醒 一个搜索图标 一个更多的的图标+,中间还有一段空白,我们可以弄两个textView(其 ...
- 使用DotNetBar制作漂亮的WinFrom界面,自定义AgileEAS.NET SOA平台WinClient主界面
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
- delphi 一个线程和主界面的交互的演示代码
求一个线程和主界面的交互的演示代码求一个线程和主界面的交互的演示代码.线程和主界面处于两个Unit.线程中的user中不能引用主窗口.我只是想学习一下,线程和主界面交互的方法.去网上查了好几天资料,能 ...
- 安卓开发_慕课网_Fragment实现Tab(App主界面)
学习内容来自“慕课网” 这里用Fragment来实现APP主界面 思路: 底部横向排列4个LinearLayout,每个LinearLayout包含一个图片按钮和一个文字 1.默认显示第一个功能(微信 ...
- 关于VS打包程序无法弹出主界面的问题
代码中的程序很正常,VS打包之后,无法弹出主界面的问题. 这种问题,一般是缺少程序加载所必须的东西,包括dll,配置文件等. (1)程序主界面使用的是DevExpress,DevExpress的相关类 ...
随机推荐
- [svc]linux启动过程及级别
Unix目录结构的来历 Linux 的启动流程 Linux 引导过程内幕 嵌入式系统 Boot Loader 技术内幕 centos6使用chkconfig治理服务和其原理 centos7的服务治理- ...
- 转:Git: git stash 用法小结
一.应用场景 综合下网上的介绍和资料, git stash (git储藏)可用于以下情形: 发现有一个类是多余的,想删掉它又担心以后需要查看它的代码,想保存它但又不想增加一个脏的提交.这时就可以考虑 ...
- [Windows Azure] Guidelines for Connecting to Windows Azure SQL Database
Guidelines for Connecting to Windows Azure SQL Database 6 out of 12 rated this helpful - Rate this t ...
- C++11 强枚举类型
在标准C++11之前的枚举是继承C的,枚举类型不是类型安全的.枚举类型被视为整数,这使得两种不同的枚举类型之间可以进行比较. 一.C中enum类型的局限语法: enum type1{a, b, c}; ...
- Zend Studio 12 windows 无限期试用
安装: 1.下载最新版本Zend Studio:http://downloads.zend.com/studio-eclipse/12.0.0/ZendStudio-12.0.0-win32.win3 ...
- (原) windows下autohotkey的快捷键脚本编写
autohotkey 脚本很强大,可以接受传参.能各种程序逻辑控制.还可以把脚本转换成独立执行的EXE.(安装完后程序目录下有个小程序:Convert .ahk to .exe,直接UI上转换.)总之 ...
- IIS6 301重定向和IIS7 301重定向
IIS6 301重定向 1.先在IIS里把网站正常发布,例如域名为(www.114390.com) 2.再硬盘上建一个空文件夹 3.再到IIS里建一个网站,例如域名为(114390.com),指向这个 ...
- jsdoc注释规范工具(使用 JSDoc 3 自动生成 JavaScript API 文档)
安装和使用规范见:http://moodpo.com/archives/jsdoc3-tutorial.html 实例: /** * 模块调用方法 * * * @param {string} modu ...
- 【转载】一个Sqrt函数引发的血案
转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 源码下载地址:http://diducoder ...
- Spring高级装配(一) profile
Spring高级装配要学习的内容包括: Spring profile 条件化的bean声明 自动装配与歧义性 bean的作用域 Spring表达式语言 以上属于高级一点的bean装配技术,如果你没有啥 ...