热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CEGUI学习笔记如何扩展CEGUI控件库

本文是扩展CEGUI控件库的第2部分,对FalButton.CPP文件的分析记录。目的是探究下如何去控制Renderer,从而彻底实现一个CEGUI没有

本文是扩展CEGUI控件库的第2部分,对FalButton.CPP文件的分析记录。
目的是探究下如何去控制 Renderer,从而彻底实现一个CEGUI没有的控件类型。

但是分析未完成,希望这些半成品能对大家有用。

PS:由于公司的网络限制,所以Blog很长时间未更新。家里还没电脑,上班偷偷写的....
下次将整理下单独编译CEGUI,并给出CEGUI与Ogre结合的详细步骤。



//=====================================================================================================================
// 2008.4.18
//=====================================================================================================================
本来打算今天探究下如何去控制 Renderer,从而彻底实现一个CEGUI没有的控件类型。

首先从FalButton开始切入,但是发现问题远没有想象中那么简单。
在先前对Falagard的翻译中得知,如果要绘制一个控件,需要定义规定的StateImagery。
所以我期望在FalButton中看到这些状态的集合,否则手册里规定的状态从哪来呢?
实际上我看到的是 "Pushed" : "PushedOff"; "Disabled" "Hover"之类的 魔字符串!
现在知道这些状态是哪来的了:在CEGUIfalagardWRBase项目里相关文件里这样定义的!这可真要命,太不可接受了。

OK,既然已经知道如何定义需要实现哪些状态,再找找和显示相关的代码,在这个对象中,只有一句跟这个相关:
wlf.getStateImagery(actualStateName(state)).render(*w);
1、wlf是WidgetLookFeel,
2、getStateImagery返回StateImagery,
获取WidgetLookFeel的唯一对象,然后得到一个叫actualStateName(state)的StateImagery,并调用它的render()方法来进行绘制。
以w为参数。w是什么?
w是d_window,继续查找这个成员变量,发现是WindowRenderer类的成员变量,回头看H文件的定义,FalButton继承自WindowRenderer。
跟WindowRenderer类似的还有很多***Renderer的文件,所以推测Button,Frame等简单控件类型的绘制都继承这个WindowRenderer。
而List等复合控件类型需要另外特别的***Renderer来实现绘制。

***Renderer里实现绘制,确实是这样的吗?如果是这样的话,为什么要调用StateImagery对象的render()方法。
如果要绘制什么东西,一定需要绘制它的参数信息,包括数据和规则,既然***Renderer是作为参数传递给StateImagery的render(),
那么***Renderer要么给出了绘制方法,要么给出数据,要么给出规则。现在虽然不能确定,但是应该是提供规则的可能性大一些。
[后面将证明是错误的,它提供的不是规则而是数据。]
现在又有2条路了:
1、WindowRenderer是什么东西。
2、StateImagery的render()到底做了什么事。

先查看WindowRenderer类的介绍:
// Base-class for the assignable WindowRenderer object
这是什么,可支持的窗口渲染器对象的基类?显然不太好对付。
从类视图中可以看到它的派生类,找个复合控件,EditboxWindowRenderer类的介绍:
// Base class for the EditboxWindowRenderer class
OK,现在知道如果不看***Renderer的代码的话,是不知道这个类做什么用的了。
所以还是顺着render()看。
有2个版本,但结构差不多,所以只盯着一个看先。
先看这个函数的介绍,没什么很详细的信息....这说明如果我们了解整个设计目的的话,这个函数是理所当然的。
没什么好说的,RTFS。
void StateImagery::render(Window& srcWindow, const ColourRect* modcols, const Rect* clipper) const    
{
 float base_z;

 // render all layers defined for this state
 for(LayersList::const_iterator curr = d_layers.begin(); curr != d_layers.end(); ++curr)
 {
  // TODO: Magic number removal
  base_z = -0.0000001f * static_cast((*curr).getLayerPriority());
  (*curr).render(srcWindow, base_z, modcols, clipper, d_clipToDisplay);
 }
}

又冒出很多新鲜玩意出来了,就知道!
LayersList?估计就是 XML里的Layer关键字定义的那段东西,在CPP文件里的对应对象,暂时不管它的细节。
getLayerPriority?优先权?为什么要和-0.0000001f相乘?请教老大之后得知,这个Z值是给3D渲染器用的。因为
getLayerPriority返回的是整数,而3D渲染器的Z值是0到1,所以才需要这么乘一下。
再看看 *cuur.render() 接受的参数:1个窗口的引用,1个Z值,1个顶点颜色矩形,一个裁减矩形,还有一个d_clipToDisplay?

bool d_clipToDisplay; //!如果为true,就是相对于显示器进行裁减,而不是窗口(实际上没裁减)?
构造函数里的初始化为d_clipToDisplay(false),搜索操作这个变量的方法,发现跟XMLHelper扯上关系,
而整个CEGUI里没有调用这个方法来设置这个变量,看来是放出去给外部进行设置的,那就不管了先,等以后在某个例子里发现的时候再回头看。

好吧,现在继续LayersList的render()。
 // render all sections in this layer
 for(SectionList::const_iterator curr = d_sections.begin(); curr != d_sections.end(); ++curr)
  (*curr).render(srcWindow, base_z, modcols, clipper, clipToDisplay);
又是个遍历,不过这次遍历的是SectionList。

再次回忆上次LookNFeel里的定义:
StateImagery
 layer
  section = ImagerySection

而ImagerySection的层次是:
ImagerySection
 ImageryComponent
  Area
  Image
  VertFormat

那在这里预测,如果查找(*curr).render(),一定是遍历一个ComponentList,然后调用 (*xx).render()。

不过找到的是获取ImagerySection的代码:
const ImagerySection* sect =
  &WidgetLookManager::getSingleton().getWidgetLook(d_owner).getImagerySection(d_sectionName);
然后sect->render(...);

结果与预测的不太一样,在这个地方已经开始使用try和catch,说明已经开始实际的绘制操作,马上就可以知道WindowRenderer提供
的到底是数据信息,还是规则信息了!
与预测不一样的地方有2个:
1、获取的不是Component,而是ImagerySection,为什么?
2、没有遍历,为什么?
回头查看SectionList,
typedef std::vector SectionList;
说明Layer里可以有很多section,而section再来指出是哪个ImagerySection。所以应该先获取ImagerySection。
而section和ImagerySection是1对1的关系,所以没有遍历。

继续看ImagerySection的render(...),在里面发现了3个遍历:
FrameList:   FrameComponent   的render()
ImageryList: ImageryComponent 的render()
TextList:    TextComponent    的render()
FrameComponent   的render()里进行了一大堆的计算,然后分别绘制了Frame的4个角、4条边、1个背景。
虽然没看,但估计其他2个差不多。这就是实际的绘制工作了!

现在回头看看,Button有Frame吗?之前写Button的时候,只写了ImageryComponent。而我从FalButton开始切入,最后却看到了
FrameComponent的绘制,这说明了什么?

再从更大范围上整理一下:
我在XML文件里定义 Button的渲染器 FalButton,
FalButton里(通过d_window)判断当前按钮的状态(现在对于***Renderer到底是个什么还不清楚,等整理完就去看。),
再通过这个状态来(通过WidgetLookFeel对象)得到对应的StateImagery对象。
然后调用StateImagery对象的render()方法,以*w为参数。

然而现在来看,从调用StateImagery对象的render()方法开始,已经跟Button没关系了,一切都是按照规定好的流程在进行。
这说明如果我们要使用CEGUI的话,从这里开始就是不变的东西,如果要改变的话,要做的事情就比较多了。

在这之前,我们能控制的(自由度)就是(添加或减少一个)控件状态的定义。
但是在之前我写Button1的时候,没实现Hover状态下的代码,然后当我鼠标移到Button1的时候,就没图片显示出来。
如果按这个流程的话,得不到StateImagery对象,就不会调用render,所以就没图片显示出来,这就说的通了。

今天就到这里,下周顺着WindowRenderer开始查。


推荐阅读
  • 人脸检测 pyqt+opencv+dlib
    一、实验目标绘制PyQT界面,调用摄像头显示人脸信息。在界面中,用户通过点击不同的按键可以实现多种功能:打开和关闭摄像头, ... [详细]
  • 第一步:PyQt4Designer设计程序界面该部分设计类同VisvalStudio内的设计,改下各部件的objectName!设计 ... [详细]
  • 当我在doWork方法中运行代码时,通过单击button1,进度条按预期工作.但是,当我从其他方法(即btn2,btn3)将列表传递给doWork方法时,进度条在启动后会跳转到10 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • JavaScript和HTML之间的交互是经由过程事宜完成的。事宜:文档或浏览器窗口中发作的一些特定的交互霎时。能够运用侦听器(或处置惩罚递次来预订事宜),以便事宜发作时实行相应的 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • [翻译]PyCairo指南裁剪和masking
    裁剪和masking在PyCairo指南的这个部分,我么将讨论裁剪和masking操作。裁剪裁剪就是将图形的绘制限定在一定的区域内。这样做有一些效率的因素࿰ ... [详细]
  • 四、连接屏幕流各位读者好!我们已经到了应用开发的一个重要阶段——连接屏幕。如您所知,我们在上一章 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 在一对一直播源码使用过程中,有时会出现软键盘切换闪屏问题,就是当切换表情的时候屏幕会跳动,因此要对一对一直播源码表情面板无缝切换进行优化。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有