要使用sdkTray的界面,首先要创建一个OgreBites::SdkTrayManager对象;
OgreBites::SdkTrayManager* mTrayMgr;
//第二个参数是Ogre::RenderWindow*,第三个参数是OIS::Mouse* ,
//第四个参数是监听器:OgreBites::SdkTrayListener,
mTrayMgr = new OgreBites::SdkTrayManager("InterfaceName", mWindow, mMouse, this);
监听器的原始定义:
class SdkTrayListener
{
public:
virtual ~SdkTrayListener() {}
virtual void buttonHit(Button* button) {}
virtual void itemSelected(SelectMenu* menu) {}
virtual void labelHit(Label* label) {}
virtual void sliderMoved(Slider* slider) {}
virtual void checkBoxToggled(CheckBox* box) {}
virtual void okDialogClosed(const Ogre::DisplayString& message) {}
virtual void yesNoDialogClosed(const Ogre::DisplayString& question, bool yesHit) {}
};
一般由BaseApplication类继承这个监听器,并重写里面的虚函数:
注意一般需要在BaseApplication::frameRenderingQueued,显示的调用mTrayMgr->frameRenderingQueued(evt);
SdkTrayManager对象的frameRenderingQueued函数只是更新帧状态。
要使SdkTrayManager里面的控件能够响应各种鼠标键盘事件,需要在这些鼠标键盘事件发生时调用相应的SdkTrayManager函数:
其实主要是鼠标事件,键盘事件的话,就一个keyPressed事件,对于这个事件首先要判断:
if (mTrayMgr->isDialogVisible()) return true;//如果SdkTrayManager的对话框弹出来了,任何其他按键事件都不做处理了,看来
这是个模态对话框啊,哈哈。
对于各种鼠标事件,在事件处理函数的开头调用:
if (mTrayMgr->injectMouseMove(arg)) return true;
if (mTrayMgr->injectMouseDown(arg, id)) return true;
if (mTrayMgr->injectMouseUp(arg, id)) return true;
然后再做其他方面的处理。
再看一下其他的有用的SdkTrayManager函数:
showAll();//这个函数里面是这样的:{showBackdrop(),showTrays(),showCursor()}
hideAll();//因此,貌似sdkTray里面有三种东西:backdrop,trays,cursor,控件都是放在trays里面的。
有一个很有用的函数:Ogre::Ray getCursorRay(Ogre::Camera* cam)//获得屏幕光标处到场景的一条射线。
//根据控件的指针,将控件放在屏幕的某一个位置
void moveWidgetToTray(Widget* widget, TrayLocation trayLoc, int place = -1)
//根据名字
void moveWidgetToTray(const Ogre::String& name, TrayLocation trayLoc, unsigned int place = -1)
//将控件移出屏幕
void removeWidgetFromTray(Widget* widget)
void removeWidgetFromTray(const Ogre::String& name)
void removeWidgetFromTray(TrayLocation trayLoc, const Ogre::String& name)
//将某个位置的所有控件移出屏幕
void clearTray(TrayLocation trayLoc)
//将所有控件移出屏幕
void clearAllTrays()
//还有很多创建各种控件的函数,以及各种监听器的虚函数的重写。
有了管理器对象就可以做一些事情了:
1
mTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);//显示帧状态
mTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT); //显示ogre log
mTrayMgr->hideCursor(); //隐藏光标
//下面可以创建各种控件了,各种控件都继承Widget类
这个widget类有一些比较实用的函数:
//对一个字符串进行裁剪,使它可以显示在某个文本区域里面。
static void fitCaptionToArea(const Ogre::DisplayString& caption, Ogre::TextAreaOverlayElement* area, Ogre::Real maxWidth)
//获得文本overlayelement的标题的宽度
static Ogre::Real getCaptionWidth(const Ogre::DisplayString& caption, Ogre::TextAreaOverlayElement* area)
Ogre::OverlayElement* getOverlayElement()//获得overlayelement
static Ogre::Vector2 cursorOffset(Ogre::OverlayElement* element, const Ogre::Vector2& cursorPos)
static bool isCursorOver(Ogre::OverlayElement* element, const Ogre::Vector2& cursorPos, Ogre::Real voidBorder = 0)
static void nukeOverlayElement(Ogre::OverlayElement* element) //删除本widget里面的所有overlayelement
const Ogre::String& getName() //获得名字
TrayLocation getTrayLocation() //获得位置
hide(),show(),隐藏和显示
bool isVisible();
//这个类还有各种响应鼠标事件的虚函数,需要在各种控件里面重写,各种控件也都重写了这些虚函数
//鼠标移动,旋转,焦点丢失等等这些效果都不需要我们操心了。
Widget类里面有个SdkTrayListener* mListener,SdkTrayManager在创建Widget类对象的时候会将他自己的SdkTrayListener* mListener
传递给刚创建的Widget的mListener成员。
2创建参数面板:
Ogre::StringVector items;
items.push_back("cam.pX"); //第一个参数
items.push_back("cam.pY"); //第二个参数
items.push_back("cam.pZ");
mDetailsPanel = mTrayMgr->createParamsPanel(OgreBites::TL_NONE, "DetailsPanel", 200, items);//200是面板的宽度
mDetailsPanel->setParamValue(1, "Bilinear"); //通过索引设置某一项参数的值,有个函数可以通过参数名设置参数的值
mDetailsPanel->getParamValue(2); //通过索引来获得参数值,也可以通过参数名来获得值。
3创建菜单:
SelectMenu* selectMenu = mTrayMgr->createLongSelectMenu();
添加菜单项:
selectMenu->addItem(Ogre::String item);
菜单类class SelectMenu : public Widget
有各种函数,。。。。自己去看,可以获得当前选择的菜单项,设置各种等等。
他自己重写了Widget的各种响应鼠标事件的函数,因此鼠标在菜单上面的动作都能自动得到响应
不需要我们去处理了,我们只需要调用一个函数得到他当前选择的菜单项即可。
4创建按钮
OgreBites::Button* pBut = mTrayMgr->createButton(TL_TOPRIGHT, "名字", "标题", 像素宽度);
//在其他地方可以直接通过控件的名字得到控件
static_cast<OgreBites::Button*>(mTrayMgr->getWidget("PageButtonControl"))->setCaption(pageText);
Button类只有一些获取设置button标题的一些函数。button最重要的是button按下事件响应。
//控件按下之后总要改变一些东西吧,比如说改变某个变量的值等,这怎么实现呢?
//也就是有没有控件的事件响应函数呢?
我知道了,在他的_cursorReleased()函数里面调用了Widget类的mListener->buttonHit(this);
这个mListener是SdkTrayListener*类型。
这个mListener是谁给他赋值的呢,原来SdkTrayManager在创建各种Widget的时候,都会将自己的SdkTrayListener*成员赋值给
Widget的mListener,因此这个buttonhit实际上时调用了SdkTrayManager中的mListener->buttonhit。
而这个SdkTrayManager中的mListener是我们自己在创建SdkTrayManager对象时,将TutorialApplication指针传递了进去,
TutorialApplication继承了SdkTrayListener,并重新了其中的buttonHit();
所以现在可以知道了其实是TutorialApplication中重写的buttonHit()响应了按钮事件。
5创建CheckBox:
mTrayMgr->createCheckBox(TL_TOPLEFT, "SpinLightButton", "Spin Light", 175)->setChecked(true);
这个CheckBox最重要的也是check状态变化响应函数,重写监听器的checkBoxToggled(CheckBox* cb)函数
在里面获取cb的check状态,从而做出相应的反应。
const Ogre::DisplayString& getCaption()
void setCaption(const Ogre::DisplayString& caption)
bool isChecked()
void setChecked(bool checked, bool notifyListener = true)
void toggle(bool notifyListener = true)
就上面这些函数。
6创建滑动条Slider:
OgreBites::Slider* mslider = mTrayMgr->createThickSlider(......);
对于slider控件,SdkTrayListener里面也有个虚函数需要重载:virtual void sliderMoved(Slider* slider) {}
当然Slider类本身也有一些函数设置滑块的位置等。
setRange();
getValueCaption();
void setValueCaption(const Ogre::DisplayString& caption)
void setValue(Ogre::Real value, bool notifyListener = true);
Ogre::Real getValue();
const Ogre::DisplayString& getCaption()
void setCaption(const Ogre::DisplayString& caption)
就上面这些函数。