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 解析的更多相关文章

  1. Ogre 编辑器一(MyGUI+Ogre整合与主界面)

    在查看Ogre例子时,想看材质要里的纹理,着色器代码都需要每个去查找,非常麻烦.也想看更新每个Ogre里的对象后有什么效果.然后看到Compositor组件与粒子组件时,想到能实时编辑着色器代码实时更 ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  3. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  4. Html Agility Pack 解析Html

    Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面  用Fir ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  6. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  7. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  8. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  9. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

随机推荐

  1. WebClient请求帮助类

    /// <summary> /// 通过JSON方式发送POST请求 /// 将返回结果按JSON方式解析 /// </summary> public static class ...

  2. C语言发展历程及其保留字(关键字)——附:C语言标准文档

    引言         抽时间对C语言发展历程和C语言的标准库文件及其保留字/关键字做了个梳理,后面附C语言各版本国际标准. C语言发展历程及其标准库 C语言关键字/保留字 C语言国际标准       ...

  3. lua -- io.pathinfo

    io.pathinfo 拆分一个路径字符串,返回组成路径的各个部分. 格式: parts = io.pathinfo(路径) 使用示例: local pathinfo = io.pathinfo(&q ...

  4. elastic search internal

    Realtime Search with Lucene http://2010.berlinbuzzwords.de/sites/2010.berlinbuzzwords.de/files/busch ...

  5. Swift中Notification.Name这么难用怎么办

    Swift中Notification.Name这么难用怎么办 以前的发送通知的参数就是一个简单的字符串: NSNotificationCenter.defaultCenter().post(" ...

  6. DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端

    最近头脑里面一直在想怎么样让能让大家基于DIOCP上写出稳定的服务端程序.很多朋友问我,你DIOCP稳定吗,我可以用他来做三层服务器吗? 当时我是这样回答的,我只能保证DIOCP底层通信的稳定. 说实 ...

  7. XnView查看图片实际大小

    找了很多软件,只有它可以显示尺寸大小. 各位如有别的发现,可留言推荐,谢谢

  8. 【转载】关于Java String, StringBuilder, StringBuffer, Hashtable, HashMap的面试题

    REF: http://blog.csdn.net/fightforyourdream/article/details/15333405 题目是一道简单的小程序,像下面这样:[java] view p ...

  9. YII登陆错误 mcrypt_create_iv()

    使用php框架YII进行开发的时候,虽然很快,性能很好,但是也有一些小问题,现在记录下来. 1.在使用gii的自动代码生成后,登陆系统,就会报错 mcrypt_create_iv() [<a h ...

  10. kali Rolling 安装QQ和虚拟机

    环境: kali Rolling   64位 WPS 官网linux版下载链接:http://community.wps.cn/download/ 使用dpkg命令安装,遇到依赖问题,用apt-get ...