一、几个重要类的分析
enum TrayLocation //类,枚举widget窗口在Tray中摆放的位置。
enum ButtonState //类,枚举鼠标动作。
class SdkTrayListener //类,监听Tray中事件的接口。
class Widget// 类,是Tray中所以GUI控件的子类。
{
protected:
Ogre::OverlayElement* mElement; //用于显示的OverlayElement对象
TrayLocation mTrayLoc; //用于记录放置位置
SdkTrayListener* mListener; //用于相应鼠标动作,不同状态下显示GUI控件
//其它的大多是一些static的通用函数。
// callbacks 回调函数,SdkTrayManager 类出发鼠标消息时将调用下列函数
virtual void _cursorPressed(const Ogre::Vector2& cursorPos) {}
virtual void _cursorReleased(const Ogre::Vector2& cursorPos) {}
virtual void _cursorMoved(const Ogre::Vector2& cursorPos) {}
virtual void _focusLost() {}
}
class SdkTrayManager //类,是Tray系统的GUI控件管理工具
{
//本来,SdkTrayManager 类没有这么麻烦,但是它把ogre的实例显示的界面也在这里实现了,所以就很大。
//其实这些我们都是用不到的。比如:这个类实现了SdkTrayListener接口,就用不到。
Ogre::OverlayContainer* mTrays[10]; // widget trays 用于存放所有GUI控件的OverlayContainer
WidgetList mWidgets[10]; // widgets 分出不同位置存放GUI控件
WidgetList mWidgetDeathRow; // widget queue for deletion 用于存放待删除的GUI控件
//下列函数,用于从RenderWindow中获得鼠标信息,向Tray中注入鼠标消息
bool injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
bool injectMouseUp(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
bool injectMouseMove(const OIS::MouseEvent& evt);
}
二、以OgreBites::SelectMenu类为例,介绍Tray系统GUI的应用
1、创建菜单:
调用 SdkTrayManager::createLongSelectMenu()函数创建菜单。
(函数createThickSelectMenu()等函数可以创建菜单,略)
创建出来的菜单对象指针存放在WidgetList mWidgets[10]; 中对应的WidgetList对象里面。
菜单的Ogre::OverlayContainer*存放在Ogre::OverlayContainer* mTrays[10]; 里面。
2、添加菜单项:
应用SelectMenu::addItem()和SelectMenu::setItems()函数
{
OgreBites::SelectMenu* menu = mTrayMgr->createLongSelectMenu(OgreBites::TL_TOPRIGHT,
"MainMenu",Ogre::DisplayString(L""), 120,112,10);
Ogre::StringVector itemNames;
itemNames.push_back("menuItem1");
itemNames.push_back("menuItem2");
menu->setItems(itemNames);
menu->show();
}
现在显示菜单不相应任何动作。
3、将鼠标注入Tray
(1)SdkTrayManager::SdkTrayManager()中需要OIS::Mouse*做参数。
由于我使用的是MFC做界面,在生成一个OIS::Mouse*还要更新挺麻烦的。
查看代码发现mMouse只在SdkTrayManager::refreshCursor函数中被使用过。我不要Tray显示鼠标,所以
注释掉函数内容。
生成SdkTrayManager代码如下:
mTrayMgr = new OgreBites::SdkTrayManager("TrayGui", m_Window, 0,this);
(2)在鼠标消息的相应函数中,new 一个OIS::Mouse,填写对应信息,将MFC的鼠标消息转换成OIS::Mouse。将改OIS::Mouse对象注入Tray中。
//下列函数,用于从RenderWindow中获得鼠标信息,向Tray中注入鼠标消息
bool injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
bool injectMouseUp(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
bool injectMouseMove(const OIS::MouseEvent& evt);
调用后,SdkTrayManager类的机制就会调用Widget类的回调函数,是GUI控件在鼠标悬停、按下等状态显示不同的界面。
class Widget
{
// callbacks 回调函数,SdkTrayManager 类出发鼠标消息时将调用下列函数
virtual void _cursorPressed(const Ogre::Vector2& cursorPos) {}
virtual void _cursorReleased(const Ogre::Vector2& cursorPos) {}
virtual void _cursorMoved(const Ogre::Vector2& cursorPos) {}
virtual void _focusLost() {}
}
(3)实现class SdkTrayListener 类,监听Tray中事件的接口。
让监听类继承class SdkTrayListener 类。
另:由于我在创建SdkTrayManager类时没有给鼠标mMouse赋值,所以光标不会移动。
但是,SdkTrayListener 类中的鼠标位置点不是取从injectMouseDown()等函数的参数的值。是去光标显示的位置值。
修改如下:(其它注入函数类似)
bool injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
……
Ogre::Vector2 cursorPos(evt.state.X.abs,evt.state.Y.abs);
//Ogre::Vector2 cursorPos(mCursor->getLeft(), mCursor->getTop());
……
}
这时,编译生成,运行。可以看到鼠标悬停、按下、离开时OgreBites::SelectMenu类显示的变化。
但是,菜单不能实现任何功能,只是一个显示的界面。
(4)实现菜单功能
在 class SdkTrayListener 类的子类中重新函数void itemSelected()
void CMfcWin::itemSelected(OgreBites::SelectMenu* menu)
{
Ogre::String menuSelected = menu->getSelectedItem();
if (menuSelected=="menuItem1")
{
//menuItem1的实现功能
}else if (menuSelected=="menuItem2")
{
//menuItem2的实现功能
}
}
4、编译生成、运行。Ok。
三、深入OgreBites::SelectMenu类
由于我用的是OgreBites::SelectMenu类,所以了解比较多,记录一下,省的忘记。
下面为OgreBites::SelectMenu类各个成员变量具体功能。
其中,“下拉菜单”我的意思是,点击菜单头时候弹各个菜单项的那个显示面板。
Ogre::BorderPanelOverlayElement* mSmallBox; //菜单条目的小外框mSmallBox
Ogre::BorderPanelOverlayElement* mExpandedBox; //下拉菜单面板
Ogre::TextAreaOverlayElement* mTextArea; //MenuCaption
Ogre::TextAreaOverlayElement* mSmallTextArea; //菜单条目的字体显示mSmallTextArea
Ogre::BorderPanelOverlayElement* mScrollTrack; //下拉菜单右边的滚动条
Ogre::PanelOverlayElement* mScrollHandle; //下拉菜单右边的滚动条 小滑块
std::vector<Ogre::BorderPanelOverlayElement*> mItemElements;//下拉菜单条目列表
bool mCursorOver;//鼠标是否在菜单上
bool mExpanded;//是否在显示下拉菜单列表
DisplayVector mItems; //菜单条目的文字信息记录vector