随笔-379  评论-37  文章-0  trackbacks-0

转:http://www.cppblog.com/yuanyajie/archive/2006/11/01/14485.html

使用 cegui 来制作界面 , 不论在何种平台下 , 有基本的三大步骤要做 :
1, 创建一个 CEGUI::Render 实例
2, 创建 CEGUI::System 对象
3, 调用各种方法来渲染用户界面
第一步 , 在我使用的 ogre 环境下使用以下代码来创建 CEGUI::Render 实例
Ogre3D
CEGUI::OgreCEGUIRenderer* myRenderer =
       new CEGUI::OgreCEGUIRenderer(myRenderWindow);
第二步相当简单 , 可使用
new CEGUI::System(myRenderer);
第三步,基本上来讲,大部分平台下,如 direct3D, OpenGL, 我们在渲染循环的尾部调用
CEGUI::System::renderGUI 来开始界面的渲染。如果我们使用 ogre3d 引擎,这一步不需要
我们显示的执行。因为 ogre 引擎已经考虑了。
除了这三大步之外,我们还有一些工作要做,首先,我们需要加载数据文件,并且完成初始化工作。
CEGUI 使用了许多类型的文件。 CEGUI 使用一个称为 ResourceProvider 的帮助对象,用它来做为核心 CEGUI 库与外部文件加载系统的接口。通过实现一个特定的 ResourceProvider 对象, cegui 的渲染模块就可以与外部系统的资源管理器、文件加载子系统无缝地集成。 CEGUI 需要的数据文件便可以通过外部系统提供的功能来进行加载。 CEGUI 中的大部分文件是以 XML 的文件格式来保存的。缺省情况下, CEGUI 在内部使用 Xerces-C++ 库来分析 XML 文件,使用 schema 来对 xml 进行校验, schema 文件以标准的 .xsd 扩展名来保存 . 许多文件本质上都是 XML 格式的文件,但是根据其意义不同,分别使用了不同的文件扩展名。
.Imageset 文件可将一幅图像看做若干小图像的集合。换名话说,就是将一幅图像的某个区域看做一幅独立的图片来使用。
.Font 定义了在 CEGUI 中所使用的字体类型。
.scheme  可以将许多数据组合在一起使用,它也是装载与注册 widget 最方便的方法。在一个 .scheme 文件中可以包括下列几种数据:
Imagest,font, window Set, window Alias
window set 指定了装载模块( .dll 等)的名称,和一组可以注册到系统中的 widget.
window alias 提供了别名的功能,实现已经注册的 window/widget 的形式上的隐藏。
.Layout  包含了窗口布局的 xml 表示。每个嵌套的 'window' 元素定义了被创建的 window 或是 widget."Property" 元素定义了窗口的设置与属性值。
.config 是可供选择的配置文件,他可指定一些缺省的属性。
我们使用 CEGUI 来制作图形界面,至少要使用以下三种文件:
.imageset, .Font . Scheme;
当然,我们知道在一个 Scheme 中是可以包括 imageset 与 Font 的。
CEGUI::SchemeManager::getSingleton().loadScheme(“../datafiles/schemes/TaharezLook.scheme”);
// load in a font.  The first font loaded automatically becomes the default font.
CEGUI::FontManager::getSingleton().createFont(“../datafiles/fonts/Commonwealth-10.font”);
对于 ogre 的使用者来讲,应该在 resources.cfg 将这些资源所在的目录加进去。
我们可用下面的语句来指定 cegui 所需要的缺省的 font 与 cursor 资源。
在 cegui 的概念里,每个 widget 都是一个 window, 从编程的角度来讲,每个 widget 类都是从同一个相同的 window 基类继承而来的 . 因此, widget 与 window 有着基本相同的行为。
窗体的许多属性与设置在窗口层树上是可以遗传的。高一级窗口的属性与行为会影响到下一级窗口的属性与行为。例如附着在某个 window 上的 window 与 widget 会被父 window 影响。当父窗口被 destroy 时,它所附属的所有的子窗口与 widget 也都将被 destroy.
创建 CEGUI 窗口,我们可以使用两种形式,一是 C ++代码,二是编辑 XML layout 文件。
注意:在 CEGUI 中,所有的 window 都是由 WindowManager singleton object 来统一创建的。我们首先得到这个对象:
using namespace CEGUI;
WindowManager& wmgr = WindowManager::getSingleton();
一般来讲,我们总是创建一个 DefaultWindow 来做为我们将使用的窗口的 Root, 在这种方式下,我们会有比较好的灵活性。
Window* myRoot = wmgr.createWindow(“DefaultWindow”, “root”);
System::getSingleton().setGUISheet(myRoot);
createwindows() 函数所使用的第一个参数,指明了将要创建的窗口类型,它一般是在我们使用的 .scheme 文件中所注册过的,当然还有一些系统定义的,总是有效的窗口类型如上面所提到的 DefaultWindow.DefualtWindow 是不可见的,它只是做为所有窗口的 root 来使用。
一般我们总是要创建一个 Framewindow, 它可以包括其他窗口与 widget ,本身也是可视的。
FrameWindow* fWnd = (FrameWindow*)wmgr.createWindow(“TaharezLook/FrameWindow”, “testWindow”);
之后,我们将创建的窗口挂到 root 上,形成一个层次关系。
myRoot->addChildWindow(fWnd);
编辑 xml layout 文件,可使用专门提供的制作工具。具体的使用方法可以参阅相关文档,这里说一下如何使用制作好的 xml layout 文件。
using namespace CEGUI;
Window* myRoot = WindowManager::getSingleton().loadWindowLayout(“test.layout”);
System::getSingleton().setGUISheet(myRoot);
首先,将 layout 文件装载进来,再指定根结点。
CEGUI 本身侦测用户输入,这些不是 CEGUI 的责任,而是程序的员的责任。当有用户外部输入时,我
们可以选择将这些消息告知 CEGUI ,这样 CEGUI 才会响应。
在 ceguir::System 类中定义了一组函数,它作为我们进行消息传递的接口。
bool injectMouseMove(float delta_x, float delta_y);
bool injectMousePosition(float x_pos, float y_pos);
bool injectMouseLeaves(void);
bool injectMouseButtonDown(MouseButton button);
bool injectMouseButtonUp(MouseButton button);
bool injectKeyDown(uint key_code);
bool injectKeyUp(uint key_code);
bool injectChar(utf32 code_point);
bool injectMouseWheelChange(float delta);
bool injectTimePulse(float timeElapsed);
这些函数的返回值说明了 CEGUI 是否已经将传入的消息 consume 掉了。
CEGUI 使用回调机制来进行消息处理。可以为某个窗体的特定事件注册一个函数,当窗体事件发生时, CEGUI 会自动调用所注册的函数。
bool TutorialApplication::handlePopMenu(constCEGUI::EventArgs& e)

// 。。。。。进行事件响应

void setupEventHandlers(void)
    {
       CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
       wmgr .getWindow((CEGUI::utf8*)"MyButton")->subscribeEvent(
       CEGUI ::PushButton::EventClicked, CEGUI::Event::Subscriber(&TutorialApplication::handlePopMenu, this));
   }

EventClicked :: 系统预定义的事件 . subscribeEvent:: 注册函数,它事件与响应函数联接在一起。
在 ogre 程序中,当侦听器收到键盘,鼠标消息时,首先经过适当的转换( CEGUI 可以识别)再传递给 CEGUI 。下面这个函数执行鼠标键标识转换。
CEGUI::MouseButton convertOgreButtonToCegui(int buttonID)
{
       switch (buttonID)
       {
       case MouseEvent::BUTTON0_MASK:
              return CEGUI::LeftButton;
       case MouseEvent::BUTTON1_MASK:
              return CEGUI::RightButton;
       case MouseEvent::BUTTON2_MASK:
              return CEGUI::MiddleButton;
       case MouseEvent::BUTTON3_MASK:
              return CEGUI::X1Button;
       default:
              return CEGUI::LeftButton;
       }
}

将 CEGUI 需要知道的键盘,鼠标消息告知它。即在 OGRE 处理这些消息时通知 CEGUI 。以下这函数说明了用法。
       void mouseMoved (MouseEvent *e)// 鼠标移动
       {
              CEGUI::System::getSingleton().injectMouseMove(
                   e->getRelX() * mGUIRenderer->getWidth(),
                   e->getRelY() * mGUIRenderer->getHeight());
                   e->consume();
       }

       void mousePressed (MouseEvent *e)// 鼠标按下
       {
              CEGUI::System::getSingleton().injectMouseButtonDown(
               convertOgreButtonToCegui(e->getButtonID()));
             e->consume();
       }
       void mouseReleased (MouseEvent *e)// 鼠标弹起
       {
              CEGUI::System::getSingleton().injectMouseButtonUp(
              convertOgreButtonToCegui(e->getButtonID()));
              e->consume();
       }

       void keyPressed(KeyEvent* e)// 键按下
       {
              CEGUI::System::getSingleton().injectKeyDown(e->getKey());
              CEGUI::System::getSingleton().injectChar(e->getKeyChar());
              e->consume();
       }
       void keyReleased(KeyEvent* e)// 键弹起
       {
             CEGUI::System::getSingleton().injectKeyUp(e->getKey());
             e->consume();

       }
在 CEGUI 中使用中文的问题:   现在总结了一下在 CEGUI 中显示中文需要注意的事项 :
    1 、将 simhei.ttf copy to \ogrenew\Samples\Media\gui
    2 、将 simhei-12.font  拷到上目录内容为
<?xml version="1.0"  ?>
<Font Name="SimHei-12" Filename="simhei.ttf" Type="Dynamic" Size="12" NativeHorzRes="800" NativeVertRes="600" 
AutoScaled="true">
<GlyphSet Glyphs=" 你好世界退出演示渲染到新材质建编辑窗口 " /> ( <---- 自己要用到的汉字)
</Font>
注意大小写!! GlyphSet Glyphs 是在程序中要用到的汉字,它是让 cegui 预生成一个字符图像集用的(想当然的 :-P )如果修改了这个文件,注意要用 Unicode ( UTF-8 )的编码来保存,在 vc7.1 中:文件 -> 高级保存选项   的   编码   栏中选择。
    3 、在 TaharezLook.scheme 中
     <Font Name="Tahoma-12" Filename="tahoma-12.font" /> 后加入
     <Font Name="SimHei-12" Filename="simhei-12.font" />  注意大小写
     以上是一些准备工作
    4 、在自己的应用中设置默认字体
    mGUISystem->setDefaultFont((CEGUI::utf8*)"Tahoma-12"); 改为
    mGUISystem->setDefaultFont((CEGUI::utf8*)"SimHei-12");
    5 、在自己的应用程序中就可以把相关的 Text 属性该为中文了,如:
    item = new CEGUI::ListboxTextItem((CEGUI::utf8*)" 退出 ", 6);
    同样要注意的是要保存为 Unicode ( UTF-8 )的编码。同时这些字要是在 simhei-12.font 中定义过的字,当然也可以象那个 CEGUIChieseDemo
那样用动态生成如:
    gfont->defineFontGlyphs(gfont->getAvailableGlyphs() + (utf8*)" 当前最佳坏平均的框架率三角 ");
    编译自己的程序,应该就可以看到中文了,罗嗦一下,记住只要有汉字出现的文件就保存为 Unicode ( UTF-8 )编码的!!!

posted on 2009-11-27 03:09 小王 阅读(974) 评论(0)  编辑 收藏 引用 所属分类: 游戏引擎

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理