CEGUI 0.7.7版的一些bug

小明 2012-12-25 2,921 views

围绕cegui的bug的工作前后加起来应该有几天了,为了防止我本人再犯,同时提醒还在关注本博客的博友们注意,现把问题及解决办法汇总一下。

1.窗口重绘

官方给出的解决方法是CEGUI::System::signalRedraw方法,这个函数会把guisheet的重绘状态置位,正常应该是guisheet下面的所有子窗口得到重绘。但该方法从来没有成果过。

解决:CEGUI::System::getGUISheet()通过该函数拿到guisheet指针,然后执行invalidate(true)方法,该方法会把所有子窗口设为无效,然后清空窗口rt,再进行重绘。

2.窗口大小改变

官方给出的方法是CEGUI::System::notifyDisplaySizeChanged方法。如果ogre和cegui使用的是ios库处理键盘鼠标消息应该没问题。但如果自己写的windows消息,通常会进入下面的流程: 有消息->响应 没有消息->渲染。如果是后一种就要注意了。如果你得到WM_SIZE消息是调用上面的notifyDisplaySizeChanged方法就会出错,现象是扩大窗口时ui控件变得很大,缩小窗口时ui控件变得很小。因为它会去查询ui绑定的ogre::RenderWindow的大小,然后根据这个大小计算一个比值缩放控件和计算渲染区域,通常这个RenderWindow就是窗口,但是它的大小要在帧更新后才会改变,此时你在处理WM_SIZE消息,等你处理完才会交给ogre渲染,所以这个RenderWindow还是原有的大小,但是CEGUI把它当成是改变后的窗口。

解决:处理完WM_SIZE消息后的下一帧调用notifyDisplaySizeChanged,给ogre时间更新相关对象。

3.设备丢失

官方给的例子里面并没有相关处理,你肯能参照1去解决该问题,对于所有课件窗口,参照1是对的,只需要添加一个ogre的rendersystem下面的监听器,接收eventOccurred回调,它会通知你DeviceRestored,此时调用问题1的解决方案即可。但是对于现在隐藏的窗口这个解决方法并不起作用,当隐藏窗口需要再次显示的时候又是花屏。原因是因为虽然调用了invalidate方法,但是对于隐藏属性的窗口,它为了所谓的效率,并不去更新窗口的rt,不会去清除rt,于是虽然走了一遍渲染流程,但是rt没有更新,下次显示的时候还是乱起八糟的纹理被画到backbuffer上去了。

解决:修改CEGUIRenderingWindow.cpp的void RenderingWindow::invalidate()方法,把里面的if (!d_invalidated)这句注释掉,d_invalidated这个变量只在draw里面会被置false,但是隐藏的窗口显然是不会被draw的,坑爹吧。


    欢迎拍砖!