MyGUI 学习笔记(1)

  蛋疼的MyGUI,虽然很好用,但是没有文档,网上几乎没有资源,依赖ogre的MyGUI我依然没能编译运行,一运行demo就崩溃,不知道是不是ogre版本的问题,我用ogre3.0.1+ogre1.7.3,知道为什么的,请告诉我谢谢。

以下都是基于directx渲染的MyGUI的学习,其实ogre渲染的也差不多。

MyGUI资源来源:

MyGUI 官网

Ogre 官网wiki

Baidu/google

资料太少,唯有自己边学边做笔记,如有错的地方,请指导:

GUI初始化

1.GUI实现过程:

先来看下demo的baseManager,通过baseManager观察整个MyGUI的初始化过程:

BaseManager实质是简单了封装了MyGUI和调用d3d初始化的过程。

1.1来看下create的代码:

View Code
bool BaseManager::create()

{

//创建窗口

WNDCLASS wc = {0, (WNDPROC)DXWndProc, 0, 0, GetModuleHandle(NULL), LoadIcon(NULL, IDI_APPLICATION),LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), NULL, TEXT(WND_CLASS_NAME),};

RegisterClass(&wc);

hWnd = CreateWindow(wc.lpszClassName, TEXT("Direct3D9 Render Window"), WS_POPUP,0, 0, 0, 0, GetDesktopWindow(), NULL, wc.hInstance, this);

if (!hWnd)

{

//OutException("fatal error!", "failed create window");

return false;

}

hInstance = wc.hInstance;

const unsigned int width = 1024;

const unsigned int height = 768;

bool windowed = true;

// createRender封装了d3d的初始化过程

createRender(width, height, windowed);

windowAdjustSettings(hWnd, width, height, !mD3dpp.Windowed);

//封装了OIS

createInput((size_t)hWnd);

_windowResized();

//重点代码:

createGui();

createPointerManager((size_t)hWnd);

createScene();

return true;

}

CreateGUI:

void BaseManager::createGui()

{

mPlatform = new MyGUI::DirectXPlatform();

mPlatform->initialise(mDevice);

//重点代码:

setupResources();

mGUI = new MyGUI::Gui();

mGUI->initialise(mResourceFileName);

mInfo = new diagnostic::StatisticInfo();

}

void BaseManager::setupResources()

{

MyGUI::xml::Document doc;

if (!doc.open(std::string("resources.xml")))

doc.getLastError();

MyGUI::xml::ElementPtr root = doc.getRoot();

if (root == nullptr || root->getName() != "Paths")

return;

MyGUI::xml::ElementEnumerator node = root->getElementEnumerator();

while (node.next())

{

if (node->getName() == "Path")

{

bool root = false;

if (node->findAttribute("root") != "")

{

root = MyGUI::utility::parseBool(node->findAttribute("root"));

if (root) mRootMedia = node->getContent();

}

addResourceLocation(node->getContent(), false);

}

}

}


而各个demo就会继承baseManager从而实现具体的skins和layout的载入和显示,实现各种UI界面。

如第一个demo:

 

View Code
void DemoKeeper::createScene()

{

getGUI()->load("Wallpaper0.layout");//载入layout文件其实这是一张背景图

MyGUI::VectorWidgetPtr& root = MyGUI::LayoutManager::getInstance().load("BackHelp.layout");

//root是一个vector<Widget *>,下面是在BackHelp.layout里面找到Text这个widget。

root.at(0)->findWidget("Text")->setCaption("Sample colour picker implementation. Select text in Edit and then select colour to colour selected part of text.");

//加载皮肤文件

MyGUI::Gui::getInstance().load("colour_slider_skin.xml");

//加载两个面板

//里面加载了各自的layout

mColourPanel = new
ColourPanel();

mEditPanel = new
EditPanel();

//注册事件

mColourPanel->eventColourAccept = MyGUI::newDelegate(this, &DemoKeeper::nColourAccept);

}


 

1.2初始化流程大概就是:
View Code
mPlatform = new MyGUI::DirectXPlatform();

mPlatform->initialise(mDevice);

//加载资源:环境

mPlatform->getDataManagerPtr()->addResourceLocation(_name, _recursive);

mGUI = new MyGUI::Gui();

mGUI->initialise(mResourceFileName);

1.3加载layout,skins文件

 

1.3.1资源加载分析:

先调用BaseManager::setupResources

View Code
void
BaseManager::setupResources()

{

MyGUI::xml::Document
doc;

if (!doc.open(std::string("resources.xml")))

doc.getLastError();

MyGUI::xml::ElementPtr
root = doc.getRoot();

if (root == nullptr || root->getName() != "Paths")

return;

MyGUI::xml::ElementEnumerator
node = root->getElementEnumerator();

while (node.next())

{

if (node->getName() == "Path")

{

bool
root = false;

if (node->findAttribute("root") != "")

{

root = MyGUI::utility::parseBool(node->findAttribute("root"));

if (root) mRootMedia = node->getContent();

}

addResourceLocation(node->getContent(), false);

}

}

}

这个函数操作resources.xml

resources.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Paths>
<Path root="true">http://www.cnblogs.com/../Media</Path>
<Path>http://www.cnblogs.com/../Media/MyGUI_Media</Path>
</Paths>


可以看到resources.xml里面指定了资源目录和资源路径。

看到:在第一个demo就在继承basemanager的setupResources里加载了本身的资源目录:

void DemoKeeper::setupResources()

{

base::BaseManager::setupResources();

addResourceLocation(getRootMedia() + "/Demos/Demo_Colour");

addResourceLocation(getRootMedia() + "/Common/Wallpapers");

}

1.4加載Layout

 

getGUI()->load("Wallpaper0.layout");



1.5找到widget

mMouseMoveSpeedScroll =MyGUI::Gui::getInstancePtr()->findWidget<MyGUI::HScroll>("MouseMoveSpeedScroll");

mEffectSoundCheck = MyGUI::Gui::getInstancePtr()->findWidget<MyGUI::Button>("EffectSoundCheck");

1.6實現委託、綁定事件:

 

mEffectSoundCheck->eventMouseButtonClick=MyGUI::newDelegate(this,&VSGuiOptionPanel::notifyEffectSoundCheck);

1.7實現函數notifyEffectSoundCheck

Void notifyEffectSoundCheck()

{

//....

}

 

1.8 MyGUI的Hello World:

View Code
void
CTest::createScene()

{
MyGUI::LayoutManager::getInstancePtr()->loadLayout("test.layout");

MyGUI::Gui * m_pGUI = getGUI();

m_btn = m_pGUI->findWidget<MyGUI::Button>("testBtn");

m_btn->eventMouseButtonPressed = MyGUI::newDelegate(this,&CTest::notifyMouseClick);

}

void
CTest::notifyMouseClick(MyGUI::Widget* _sender, int
_left, int
_top, MyGUI::MouseButton
_id)

{

if(_id == MyGUI::MouseButton::Left)

{

MyGUI::Window *m_pWIn = getGUI()->findWidget<MyGUI::Window>("win");

m_pWIn->setCaption(L"hello world");

}

}


 

 

Skin和layout

 

 

2.1Layout 文件的分析:

<?xml version="1.0" encoding="UTF-8"?>

<MyGUI type="Layout">

<Widget type="Widget" skin="testa1" position="10 10 120 120" align="Default" layer="Main" name="testWidget"/>

<Widget type="Button" skin="testa1" position ="230 230 50 50" align="Default" layer="Main" name="testBtn"/>

</MyGUI>

可以看到layout也是一个xml。而且widget 里面有各种各样的参数,比如:

在按钮上写字:

<Widget type="Button" skin="Button" position="14 22 160 26" name="New">

<Property key="Widget_Caption" value="New"/>

</Widget>


要查这些参数,在MyGUI_widgetName.h 里面查找setProperty这个函数。可以看到各种各样的property。

比如:

void StaticText::setProperty(const
std::string& _key, const
std::string& _value)

{

if (_key == "Text_TextColour") setTextColour(utility::parseValue<Colour>(_value));

else
if (_key == "Text_TextAlign") setTextAlign(utility::parseValue<Align>(_value));

else
if (_key == "Text_FontName") setFontName(_value);

else
if (_key == "Text_FontHeight") setFontHeight(utility::parseValue<int>(_value));

else
if (_key == "Text_AutoReturn") setAutoReturn(utility::parseValue<bool>(_value));

else

{

Base::setProperty(_key, _value);

return;

}

eventChangeProperty(this, _key, _value);

}


2.2 Skin:

Skin文件的描述(来自ogre 官网):

View Code
<?xml version="1.0" encoding="UTF-8"?>

<MyGUI type="Resource" version="1.1">

<Resource type="ResourceSkin" name = "__Skin_name__" size = "__width height__" texture = "__Texture_file_name__" >

<!- size 属性是默认的widget size,subskins 和子widget 的对齐都依赖于这个size-->

<Property key="__Property_name__" value = "__Property_value__" />

<!- 一些widget类型有指定的属性,你可以在skins文件中设置,而不是在layout或在代码中设置-->

<Child type="__Widget_type__" skin="__Some_skin_name__" offset = "__left top width height__" align = "__Some_align__" name = "__Child_widget_name__">

<!- Offset 和 align 是儿子widget的皮肤属性 -->

<Property key="__Property_name__" value = "__Property_value__" />

<!- 子widget也有一些指定的属性-->

</Child>

<!- 如同窗口有按钮,按钮就是子widget,所以皮肤也有子widget-->

<BasisSkin type="__SubSkin_type__" offset = "__left top width height__" align = "__Some_align__">

<!- 和子widget一样的偏移和对齐方式-->

<State name="__state_name__" offset = "__left top width height__"/>

<!- Here is defined part of texture for different widget states. ''Offset''指在纹理上的偏移部分,这部分将被渲染显示-->

</BasisSkin>

<!-- ''BasisSkin'' with type ''MainSkin'' or ''SubSkin'' is an actual part of texture that will be rendered.

Usually skins contain one part (part of texture stretched over whole widget) - SubSkin_type should be ''MainSkin'',

three parts (left part, stretched central part and right part) - SubSkin_type should be ''SubSkin''

or nine parts (one in center and 8 around) - SubSkin_type should be SubSkin.

You may have any amount of ''BasisSkin'' elements one for each texture part.

-->

<BasisSkin type="SimpleText" offset = "__left top width height__" align = "__Some_align__">

<!- Offset and align here works same way as for child widgets -->

<State name="__state_name__" colour="__R G B or #RRGGBB (hex)__"/>

<!- ''SimpleText'' may contain state description, it is optional. If it contain node - default colour will be used for all states. -->

</BasisSkin>

<!- ''SimpleText'' is place where widget text is placed. Also if this text should be selectable or editable you should use ''EditText'' type instead. >

</Resource>

<!- Lots of other skins here ... -->

</MyGUI>

<!-- ''BasisSkin'' with type ''MainSkin'' or ''SubSkin'' is an actual part of texture that will be rendered.

Usually skins contain one part (part of texture stretched over whole widget) - SubSkin_type should be ''MainSkin'',

three parts (left part, stretched central part and right part) - SubSkin_type should be ''SubSkin''

or nine parts (one in center and 8 around) - SubSkin_type should be SubSkin.

You may have any amount of ''BasisSkin'' elements one for each texture part.

-->


本人翻译水平太差了,杯具

2.3注意:

要在这张UI纹理图中获取比如一个框:

<Resource type="ResourceSkin" name = "testa1" size = "233 158" texture="uiShopGroup.png">

<BasisSkin type="MainSkin" offset="0 0 233 183",align="Stretch">

<State name="normal" offset="0 0 50 50"/>

</BasisSkin>

</Resource>


我们就要在state里指定left top width height。注意是在state里面。

第2点:对于某些widget来说,会有不同的state,比如按钮,有按下,悬停等状态,如下;

<State name="disabled" offset = "0 0 64 64"/>
<State name="normal" offset = "0 64 64 64"/>
<State name="highlighted" offset = "0 128 64 64"/>
<State name="normal_checked" offset = "0 192 64 64"/>
<State name="pushed" offset = "0 252 64 64"/>


第3点:默认情况下,skin是放在core_skin.xml 里面

第4点:相同的skin可以由不同的layout加载,从而实现skin重用,实现的效果也不一样。

第5点:就是这段话:

Usually skins contain one part (part of texture stretched over whole widget) - SubSkin_type should be ''MainSkin'',

three parts (left part, stretched central part and right part) - SubSkin_type should be ''SubSkin''

or nine parts (one in center and 8 around) - SubSkin_type should be SubSkin.

这段话的意思是指,有些skin的纹理可以整张拉大,延伸。比如图中的一些按钮。这些一般是MainSkin,

有些skin是分3部分,中间延伸,两边固定的,比如血条之类的。

有些skin是纹理分9份(九宫格),其中四个角固定,其他四块延伸。比如一些窗口。

以上三种都可以通过skin的align来指定。

例如9宫格的panel(代码来源于http://hi.baidu.com/sysnoah/home):

View Code
<Resource type="ResourceSkin" name="NFSkin_Panel9" size="11 11" texture="ItemIcon1.png">

<BasisSkin type="SubSkin" offset="0 0 3 3" align="Left Top">

<State name="normal" offset="429 70 3 3"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="3 0 3 3" align="HStretch Top">

<State name="normal" offset="435 70 3 3"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="6 0 5 3" align="Right Top">

<State name="normal" offset="447 70 5 3"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="0 3 3 3" align="Left VStretch">

<State name="normal" offset="429 76 3 3"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="3 3 3 3" align="Stretch">

<State name="normal" offset="432 5 65 57"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="6 3 5 3" align="Right VStretch">

<State name="normal" offset="447 76 5 3"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="0 6 3 5" align="Left Bottom">

<State name="normal" offset="429 87 3 5"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="3 6 3 5" align="HStretch Bottom">

<State name="normal" offset="435 87 3 5"/>

</BasisSkin>

<BasisSkin type="SubSkin" offset="6 6 5 5" align="Right Bottom">

<State name="normal" offset="447 87 5 5"/>

</BasisSkin>

</Resource>


2.4皮肤文件的属性:

假设要自己实现控件,要继承widget,往往还要实现这个函数,这个函数就是包含widget的皮肤属性,你也可以加上你要的皮肤属性。

View Code
void
Widget :: initialiseWidgetSkin (ResourceSkin * _info, const
IntSize & _size)

{

/*............省略...............................*/

Widget :: setState ("normal") ;//*/ /*/ FIXME - explicit call

/// / Parse properties

const
MapString & properties = _info-> getProperties ();

if (! properties.empty ())

{

MapString :: const_iterator
iter = properties.end ();

if ((iter = properties.find ("NeedKey"))! = properties.end ()) setNeedKeyFocus (utility :: parseBool (iter-> second));

if ((iter = properties.find ("NeedMouse"))! = properties.end ()) setNeedMouseFocus (utility :: parseBool (iter-> second));

if ((iter = properties.find ("Pointer"))! = properties.end ()) mPointer = iter-> second;

if ((iter = properties.find ("Visible"))! = properties.end ()) {setVisible (utility :: parseBool (iter-> second));}

// / / OBSOLETE

if ((iter = properties.find ("AlignText"))! = properties.end ()) _setTextAlign (Align :: parse (iter-> second));

if ((iter = properties.find ("Colour"))! = properties.end ()) _setTextColour (Colour :: parse (iter-> second));

if ((iter = properties.find ("Show"))! = properties.end ()) {setVisible (utility :: parseBool (iter-> second));}

if ((iter = properties.find ("TextAlign"))! = properties.end ()) _setTextAlign (Align :: parse (iter-> second));

if ((iter = properties.find ("TextColour"))! = properties.end ()) _setTextColour (Colour :: parse (iter-> second));

if ((iter = properties.find ("FontName"))! = properties.end ()) _setFontName (iter-> second);

if ((iter = properties.find ("FontHeight"))! = properties.end ()) _setFontHeight (utility :: parseInt (iter-> second));

}

/*............省略...............................*/

}






 

 

中文显示

3.1(非常简单,请参考网上文章)


常用的Widget

 

各个事件的原型:

View Code
//Delegates to the event widget

typedef
delegates::CDelegate1<Widget*> EventHandle_WidgetVoid;

typedef
delegates::CDelegate2<Widget*, Widget*> EventHandle_WidgetWidget;

typedef
delegates::CDelegate2<Widget*, bool> EventHandle_WidgetBool;

typedef
delegates::CDelegate2<Widget*, int> EventHandle_WidgetInt;

typedef
delegates::CDelegate2<Widget*, size_t> EventHandle_WidgetSizeT;

typedef
delegates::CDelegate3<Widget*, int, int> EventHandle_WidgetIntInt;

typedef
delegates::CDelegate4<Widget*, int, int, MouseButton> EventHandle_WidgetIntIntButton;

typedef
delegates::CDelegate2<Widget*, KeyCode> EventHandle_WidgetKeyCode;

typedef
delegates::CDelegate3<Widget*, KeyCode, Char> EventHandle_WidgetKeyCodeChar;

typedef
delegates::CDelegate3<Widget*, const
std::string&, const
std::string&> EventHandle_WidgetStringString;

typedef
delegates::CDelegate3<Widget*, Widget*&, size_t &> EventHandle_WidgetRefWidgetRefSizeT;

typedef
delegates::CDelegate2<Widget*, const
ToolTipInfo& > EventHandle_WidgetToolTip;

/** Event : Widget lost mouse focus.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::Widget* _new)\n

@param _sender widget that called this event

@param _new widget with mouse focus or nullptr

*/

EventHandle_WidgetWidget
eventMouseLostFocus;

/** Event : Widget got mouse focus.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::Widget* _old)\n

@param _sender widget that called this event

@param _old widget with mouse focus or nullptr

*/

EventHandle_WidgetWidget
eventMouseSetFocus;

/** Event : Widget mouse move with captured widget.\n

signature : void method(MyGUI::Widget* _sender, int _left, int _top)\n

@param _sender widget that called this event

@param _left - pointer position

@param _top - pointer position

*/

EventHandle_WidgetIntInt
eventMouseDrag;

/** Event : Mouse move over widget.\n

signature : void method(MyGUI::Widget* _sender, int _left, int _top)\n

@param _sender widget that called this event

@param _left - pointer position

@param _top - pointer position

*/

EventHandle_WidgetIntInt
eventMouseMove;

/** Event : Mouse wheel over widget.\n

signature : void method(MyGUI::Widget* _sender, int _rel)\n

@param _sender widget that called this event

@param _rel relative wheel position

*/

EventHandle_WidgetInt
eventMouseWheel;

/** Event : Mouse button pressed.\n

signature : void method(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)\n

@param _sender widget that called this event

@param _left - pointer position

@param _top - pointer position

@param _id Mouse button id

*/

EventHandle_WidgetIntIntButton
eventMouseButtonPressed;

/** Event : Mouse button released.\n

signature : void method(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)\n

@param _sender widget that called this event

@param _left - pointer position

@param _top - pointer position

@param _id Mouse button id

*/

EventHandle_WidgetIntIntButton
eventMouseButtonReleased;

/** Event : Mouse button pressed and released.\n

signature : void method(MyGUI::Widget* _sender)

@param _sender widget that called this event

*/

EventHandle_WidgetVoid
eventMouseButtonClick;

/** Event : Mouse button double click.\n

signature : void method(MyGUI::Widget* _sender)

@param _sender widget that called this event

*/

EventHandle_WidgetVoid
eventMouseButtonDoubleClick;

/** Event : Widget lost keyboard focus.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::Widget* _new)\n

@param _sender widget that called this event

@param _new widget with keyboard focus or nullptr

*/

EventHandle_WidgetWidget
eventKeyLostFocus;

/** Event : Widget got keyboard focus.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::Widget* _old)\n

@param _sender widget that called this event

@param _old widget with keyboard focus or nullptr

*/

EventHandle_WidgetWidget
eventKeySetFocus;

/** Event : Key pressed.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::KeyCode _key, MyGUI::Char _char)\n

@param _sender widget that called this event

@param _key code

@param _char of pressed symbol (for multilanguage applications)

*/

EventHandle_WidgetKeyCodeChar
eventKeyButtonPressed;

/** Event : Key released.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::KeyCode _key)\n

@param _sender widget that called this event

@param _key code

*/

EventHandle_WidgetKeyCode
eventKeyButtonReleased;

/** Event : Root widget changed mouse focus.\n

info : this event sends only to root widget\n

signature : void method(MyGUI::Widget* _sender, bool _focus);

@param _sender widget that called this event

@param _focus Is widget got mouse focus.

*/

EventHandle_WidgetBool
eventRootMouseChangeFocus;

/** Event : Root widget changed keyboard focus.\n

info : this event sends only to root widget\n

signature : void method(MyGUI::Widget* _sender, bool _focus);

@param _sender widget that called this event

@param _focus Is widget got keyboard focus.

*/

EventHandle_WidgetBool
eventRootKeyChangeFocus;

/** Event : Event about changing tooltip state.\n

signature : void method(MyGUI::Widget* _sender, const MyGUI::ToolTipInfo& _info);

@param _sender widget that called this event

@param _info about tooltip

*/

EventHandle_WidgetToolTip
eventToolTip;

/** Event : Extendeble event for special cases or plugins.\n

signature : void method(MyGUI::Widget* _sender, const std::string& _key, const std::string& _value);

@param _sender widget that called this event

@param _key

@param _value

*/

EventHandle_WidgetStringString
eventActionInfo;

/** Event : Internal request for parent and item index, used for any widget.\n

signature : void method(MyGUI::Widget* _sender, MyGUI::Widget*& _container, size_t& _index);

@param _sender widget that called this event

@param _container parent

@param _index of container

*/

EventHandle_WidgetRefWidgetRefSizeT
_requestGetContainer;

/** Event : Widget property changed through setProperty (in code, or from layout)\n

signature : void method(MyGUI::Widget* _sender, const std::string& _key, const std::string& _value);

@param _sender widget that called this event

@param _key

@param _value

*/


posted @ 2012-03-21 12:48  xfate  阅读(1975)  评论(1编辑  收藏  举报