MyGUI 解析
MyGUI源码还是比较简单的,我们在这里只是简单分析相应控件如何生成,如何渲染。
我们分成三个部分来说明,分别是资源类型,控件生成,控件渲染。
资源类型:
ResourceSkin:用于记录各个控件状态的纹理坐标位置,关联的图片,如何划分SubSkin及文本。

- SubSkin有主要有几种Type,主要是SubSkin, MainSkin, EditText, SimpleText, RoatingSkin, PolygonalSkin, TileRect. 分别对应ISubWidget里的几种子类实现。
- ResourceSkin用来生成上面所说的各种ISubWidget.
ResourceLayout:用于记录控件结构,用于表示Widget的树成分,Widget与子Widget类型,大小,属性等。

ILayer:表示层的概念,和Ogre中的Overlay比较类似,一般我用把在某些时间一起显示的控件放入同一层中,如刚进游戏界面和进入游戏后的界面UI应该用不同的Larer.
- MyGUI默认给我们分配一些Layer,请看文件MyGUI_Layers.xml,如Overlapped,Main,Popup等是我们比较常用的。
- MyGUI注册了二种类型的Layer,分别是SharedLayer与OverlappedLayer,其中SharedLayer层上控件如果不重叠可以用这个,否则用OverlappedLayer,原因见后面.
控件生成:
ISubWidget:前面说ResourceSkin有提到,他的子类实现主要有EditText, MainSkin, SubSkin, TileRect, PolygonalSkin, RotationSkin ,SimpleText这些,ISubWidget负责最后的渲染,就是说控件到最后都是组合成ISubWidget来进行渲染.
- 上面所说的子类实现,主要是从二种ISubWidget的子类继承,一种是ISubWidgetRect,一种是ISubWidgetText.简单来说,一种没有文本,只有位置,颜色信号,一种包含文本信息,如字体名,字体大小等.上面说的EditText与SimpleText是从ISubWidgetText继承,别的ISubWidget都是从ISubWidgetRect继承.
LayerItem:一种树型结构,叶子节点为ISubWidget,非叶子节点为LayerItem,能绑定到Layer和LayerNode上,也能解绑.
SkinItem: LayerItem的子类.提供根据资源ResourceSkin文件生成ISubWidget列表功能,并提取一个ISubWidgetRect到字段mMainSkin,一个ISubWidgetText到mText上,没有则为空.
Widget:MyGUI中控件的父类,这个类就相当于winForm中的Control,本身是树型结构(Widget包含子Widget列表).可以对照上面的ResourceLayout的图.
- 继承多个类,其中继承SkinItem类能根据ResourceSkin生成子ISubWidget列表,继承WidgetInput 提供与键盘和鼠标事件的交互,继承IcroppedRectangle提供大小,绝对位置或相对父位置信息.
- Widget可以由ResourceLayout资源序列化得到,其中每个节点Widget属性上的Type指点对应生成子类控件(Button/EditBox等),而对应的Skin则指明对应的ResourceSkin,生成SkinItem信息.
Button/EditBox等:这些基本控件MyGUI中的WidgetManager注册,并且由MyGUI本身提供的基本Templates文件提供的ResoureceLayout生成Widget.
控件渲染:
IVertexBuffer:一块缓冲区数据,数据块格式P3fT2fC1i,就是每个顶点用三个float数据表示顶点,二个float表示纹理坐标,一个uint数据表示颜色,根据不同的平台来实现这个子类.
IRenderTarget:渲染目标,一般是当前窗口.
RenderItem:简单来说,把多个SubWidget组合在一起渲染,前面我们可以看到,同一类型的Skin一般都是用一张图,那么只要记录各顶点的纹理坐标位置就可以合成一个Pass渲染完成.MyGUI效率高从这个类可以看到原因.
LayerNode:管理Layer中的RenderItem,当把Widget加入Layer中,实际是把Widget中的顶层ISubWidget添加到对应的LayerNode中的RenderItem中,这样ISubWidget,RenderItem,LayerNode三者就联系在一起了.
- 对应上面的Layer, 一个OverlappedLayer包含多个LayerNode,而一个SharedLayer只有一个共用的SharedLayerNode.后面LayerNode是一个接一个渲染的,那么如果各顶层ISubWidget有覆盖,然后又添加到SharedLayerNode,他并不能保证覆盖渲染正确.
- 并不是所有的Widget都能加入到LayerNode, CroppedParent为空或是没有父Widget的Widget才会生成并添加到LayerNode中,其中没有父Widget的Widget一般是那种窗口,而CroppedParent为空一般是Popup类型(如PopupMenu).
加载控件与渲染流程
1.LayoutManager::loadLayout 加载layoutName 得到ResoureceLayout.
2.ResourceLayout::createLayout 根据ResoureceLayout中的WidgetInfo(对应ResoureceLayout资源文件中的Widget节点)创建Widget.
3.ResourceLayout::createWidget 根据控件是否是模版控件(对应的LayoutResourece file是否是模版文件,默认的Button /EditBox 等都在一个模板LayoutResource 文件里).分别调用不同的方法生成Widget.
4.LayerManager::attachToLayerNode 在上面创建Widget后,会把对应的Widget添加到他所属于的Layer层中.(注意前面说过,CroppedParent为空或是没有父Widget的Widget才会添加到Layer中的LayerNode中.这样,只有顶层Widget才会添加到LayerNode中.)其中OverlappedLayer每个顶层Widget生成一个对应的LayerNode,而SharedLayer只会生成一个SharedLayerNode,所有顶层Widget同享这个SharedLayerNode.这样前面说的控件如果不重叠可以用SharedLayerNode就有了解释,因为同层LayerNode中的RenderItem的渲染顺序我们控制不了,但是不同LayerNode我们可以控制渲染顺序,如二个部分重合的窗口,我激活那个,我就让那个RenderItem后渲染.这样激活的那个就显示在后面了.
5.LayerNode::attachLayerItem 把顶层Widget附加到LayerNode中.
6.LayerItem::attachToLayerItemNode 编历LayerItem(前面有说过)中的树层次,把所有叶子节点的ISubWidget放入一个列表.
7.ISubWidget::createDrawItem(注意,ISubWidget没有这方法,但是其最后的实体子类都实现了这个方法).在这里根据上面的LayerItem叶子节点中的ISubWidget列表,我们来创建对应LayerNode中的RenderItem.
8.LayerNode::addToRenderItem 根据ISubWidget中的图片决定是否生成新的RenderItem.并把ISubWidget添加到RenderItem中.
- 其中ISubWidgetText的子类添加到LayerNode的第二通道上,而ISubWidgetRect添加到LayerNode的第一通道上.
- 在这里并不是一个ISubWidget创建一个RenderItem,如果多个ISubWidget都用的相同图片,则只生成一个RenderItem.
如上这些,是在初始化Layout资源文件发生的过程,那么渲染是如何进行的.
在MyGUI.OgrePlatform中,Ogre渲染平台实现了MyGUI中的RenderManager实现类OgreRenderManager.其中OgreRenderManager 实现了监听类Ogre::RenderQueueListener,这个监听类具体方法以及作用请看Ogre 监听类与渲染流程.
当我们调用OgrePlatform::initialise时,把OgreRenderManager注册到SceneManager中的RenderQueueListener中.这样Ogre开始渲染通道时,进入到OgreRenderManager::renderQueueStarted中,然后交给RenderManager::onRenderToTarget.
1.RenderManager::onRenderToTarget MyGUI开始渲染.
2.ILayer::renderToTarget MyGUI中的每个层开始渲染.
3.LayerNode::renderToTarget 每层中的每个LayerNode开始渲染.
4.RenderItem::renderToTarget 渲染二个通道里的每个RenderItem.(RenderItem如何来的,请看前面.)
5.ISubWidget::doRender 渲染RenderItem里的ISubWidget列表.根据当前ISubWidget计算位置,大小,颜色,纹理坐标等等,整合所有ISubWidget成一个IVertexBuffe与一个ITexture.
6.OgreRenderManager::doRender 调用Ogre渲染上面的IVertexBuffe与ITexture.
如上一个渲染结束,大致总结下,MyGUI最后就是ISubWidget在更新渲染的数据,而ISubWidget根据资源文件ResourceSkin生成.一个窗口里的控件如果用的是同一样式,同一字体,那么一般二次渲染就行了.
ResourceSkin如果上面说的不是很清楚,可以看下面TabHeaderButtonSkin在Skin editor中的显示.




如下是上面ComboBox中的Layout文件在Layout editor中的界面显示.

写完,睡觉.
MyGUI 解析的更多相关文章
- Ogre 编辑器一(MyGUI+Ogre整合与主界面)
在查看Ogre例子时,想看材质要里的纹理,着色器代码都需要每个去查找,非常麻烦.也想看更新每个Ogre里的对象后有什么效果.然后看到Compositor组件与粒子组件时,想到能实时编辑着色器代码实时更 ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- .NET Core中的认证管理解析
.NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...
- Html Agility Pack 解析Html
Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面 用Fir ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- Asp.Net WebApi核心对象解析(下篇)
在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...
- 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye
一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...
随机推荐
- [sql]mysql参数(配置)手册
my-innodb-heavy-4G.cnf配置文件注解 [client] #客户端 port = 3306 #mysql客户端连接时的默认端口号 socket = /application/mysq ...
- (转)Unity3d使用心得(2):Unity3d 动态下载动画资源——AnimationClip 的使用 - 斯玛特琦
引言: 在使用 Unity3d 开发微端.或者网页游戏的时候常常须要将资源打包成 AssetBundle ,然后通过 www 的方式动态的下载资源.今天要分享的是我再动态下载 Animation 骨骼 ...
- CAS无锁实现原理以及ABA问题
CAS(比较与交换,Compare and swap) 是一种有名的无锁算法.无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(N ...
- Vue.js使用-http请求
Vue.js使用-ajax使用 1.为什么要使用ajax 前面的例子,使用的是本地模拟数据,通过ajax请求服务器数据. 2.使用jquery的ajax库示例 new Vue({ el: '#app' ...
- 每日英语:U.S. Media Firms Stymied in China
China's recent clampdown on foreign media is crimping the expansion plans of Western news organizati ...
- 旧的flex
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- QQ通信原理及QQ是怎么穿透内网进行通信的?
http://blog.csdn.net/frank_good/article/details/51160027 ******************************************* ...
- webpack打包调试react并使用babel编译jsx配置方法
http://lxj8749.iteye.com/blog/2287074 ********************************************** 安装webpack npm i ...
- 9个绚丽多彩的HTML5进度条动画赏析
进度条在网页应用中越来越广泛了,特别是现在的页面异步局部刷新时代,进度条可以让用户更好的等待操作结果.本文要分享9款绚丽多彩的HTML5进度条动画,有很多还是挺实用的,效果也非常不错. 1.CSS3发 ...
- 【Python】京东商品价格监控
import requests,json,re,winsound,time class Stock(object): def __init__(self): self.province_dict={v ...