本节在上节画矩形框的基础上添加了一个鼠标箭头,以更形象展示鼠标位置。显示鼠标我们可以用CEGUI之类的组件,但对于我的实验程序来说过于庞大,我只需要鼠标来显示点击位置即可。所以我利用OGRE中的Overlay面板和PanelOverlayElement组件来实现鼠标效果。下面简单介绍一下Overlay。
基本概念
Overlay是那些将在主场景被渲染之后才渲染的可视组件(2D和3D)的容器。这些可视组件将构成HUD(Heads-Up-Display)、菜单或其它在主场景内容之上的任何东西。Overlay将被渲染在“普通”场景内容之上的层。一个Overlay总是占满整个Viewport,即使它包含的组件并没有那么大。Overlay只是可视组件的容器,本身并不代表任何可视组件。Overlay可以通过调用OverlayManager::Create函数来创建,或者将其定义在特定的脚本文件(.overlay文件)。你可以定义无限多的Overlay;Overlay被创建后是隐藏的,即你必须调用“show”函数才能看到它。这样你可以预先定义很多Overlay(如菜单),仅在需要它们的时候才将它们显示出来。在同一时刻可以存在和显示多个Overlay,Overlay的“zorder”参数决定了谁在上谁在下。缺省情况下,Overlay会被渲染到全部的Viewport。当你只有一个全屏Overlay的时候这非常好用,但当你在程序中用几个Viewport构成“画中画”的时候,你可能就不想让它显示在小画面中了。你可以通过调用Viewport::setDisplayOverlays方法将某些Viewport的Overlay关闭。
PanelOverlayElement表示一个平面,单一材质(或透明)的面板,它可以包含其他元素。与其他类一样,如果它隐藏,它包含的内容也跟着隐藏,如果移动了它包含的内容也跟着移动等等。这个面板本身是一个2D矩形,它要么完全透明,要么用单一材质渲染。面板上的纹理可以根据你的需要平铺(tile)。这个组件适合作为背景及将其他元素分组。注意,因为它只有单一重复的材质,它的边界不能是离散的(除非纹理只有一个且只铺了一次)。
动手实践
因为我们使用了材质,故需要修改resources_d.cfg,在其后添加FileSystem=../../media,将其指向我们放材质和纹理的文件夹。../表示上级目录。新建一个txt文件,将其命名为Cursor,并将其后缀名改为material,即Cursor.material。添加如下代码:
material Cursor/default { technique { pass { scene_blend alpha_blend texture_unit { texture cursor.png tex_address_mode clamp } } } }
其中cursor.png即为我们所需要的鼠标纹理文件,如下所示:
在程序中,我们需要定义Overlay容器和PanelOverlayElement组件。
//Cursor Overlay* OverCursor; PanelOverlayElement* mCursor;
并将其初始化
//create cursor void createCursor(String name, String material, RenderWindow* win) { OverCursor = OverlayManager::getSingleton().create(name); mCursor = new PanelOverlayElement(name); mCursor->initialise(); mCursor->setMaterialName(material); MaterialPtr m = MaterialManager::getSingleton().getByName(material); m->getTechnique(0)->getPass(0)->setAlphaRejectValue(150); mCursor->setDimensions(32.0/win->getWidth(), 32.0/win->getHeight()); OverCursor->add2D(mCursor); OverCursor->show(); mCursor->show(); }
这样做以后鼠标会显示在窗口的左上角,但不会动。我们需要在mouseMoved事件中添加相应的语句,以使鼠标在窗口范围内移动。如下所示:
bool mouseMoved (const OIS::MouseEvent& e) { const Real clickX = static_cast <Real> (e.state.X.abs) / mWindow->getWidth(); const Real clickY = static_cast <Real> (e.state.Y.abs) / mWindow->getHeight(); mCursor->setLeft(clickX); mCursor->setTop (clickY); return true; }
这样我们就可以看到活动的鼠标了。完整的代码可以从如下网址下载(我是用VS2008编译的)。
Author : Zhu Xiaoyang ([email protected])
Creation Date : May 10 2011