页面构成
在FairyGUI编译器中,游戏界面是由被多个包(Package)构成, 包是有多个组件(Component)组成,而组件的基本元素就是元件(Object)。
在编译器中,每次创建包后,在asserts目录下,会生成你命名的文件夹也就是包名,文件夹内包含都会包含一个package.xml。
创建了一个Basic的包,包含了一个导出和未导出的组件。asserts/Basic目录下的package.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<packageDescription id="gdlp271k">
<resources>
<component id="fjgj0" name="MainView.xml" path="/" exported="true"/>
<component id="vx0u1" name="widget_item.xml" path="/"/>
</resources>
<publish name="" maxAtlasIndex="15"/>
</packageDescription>
- packageDescription: id指的就是pkgId
- resources: exported表示是导出,id就是指的resId, 唯一标识符
- publish: maxAtlasIndex指的是纹理集设置的最大数目(0开始),通过包设置, 纹理集定义可进行查看
接下来看下,关于MainView.xml的配置文件:
<?xml version="1.0" encoding="utf-8"?>
<component size="960,640">
<displayList>
<graph id="n1_vx0u" name="graph_bg1" xy="0,0" size="960,640" type="rect" fillColor="#ffcccccc">
<relation target="" sidePair="width-width,height-height"/>
</graph>
<graph id="n2_vx0u" name="graph_bg2" xy="0,0" size="960,100" type="rect" fillColor="#ff006699">
<relation target="" sidePair="width-width,top-top"/>
</graph>
<component id="n3_vx0u" name="closeBtn" src="vx0u3s" fileName="btn/normal_btn_close1.xml" pkg="a0imyaf1" xy="890,28" scale="2,2">
<relation target="" sidePair="right-right,top-top"/>
</component>
<list id="n6_vx0u" name="list" xy="233,137" size="494,412" overflow="scroll" lineGap="6" defaultItem="ui://gdlp271kvx0u1" align="center" autoClearItems="true">
<relation target="" sidePair="center-center"/>
<item/>
<item/>
</list>
</displayList>
</component>
- component: 组件相关,size为设定的组件大小
- displayList: 显示元件(object) 元素集合相关, 针对于元素支持组件内嵌套组件的
- graph/list: 元件类型相关, 稍后将详述
- id: 元件资源id, 是唯一标识符
- name: 元件资源名,同层级下的元件不可重名
- xy/size:位置,大小相关
- list内的item表示列表item,一般情况下会通过代码动态创建,发布为空就是这个样式
- sidePair: 元件关联相关,UI适配相关
- defaultItem: list列表下使用item组件,其实质就是: widget_item.xml文件
URL地址
通过defaultItem的属性值,我们简要说明下: ui://gdlp271kvx0u1
。参考:包
打开UI编译器,分别选择MainView, widget_item 右键选择: 复制URL
MainView: ui://gdlp271kfjgj0
widget_item: ui://gdlp271kvx0u1
其构成实质就是: ui:// + pkgId + resId
,它是从包中获取组件的核心。C++中实现的逻辑如下:
PackageItem* UIPackage::getItemByURL(const string& url)
{
if (url.size() == 0)
return nullptr;
ssize_t pos1 = url.find('/');
if (pos1 == -1)
return nullptr;
ssize_t pos2 = url.find('/', pos1 + 2);
if (pos2 == -1)
{
if (url.size() > 13)
{
// 获取pkgId,根据pkgId获取指定pkg包
string pkgId = url.substr(5, 8);
UIPackage* pkg = getById(pkgId);
if (pkg != nullptr)
{
// 获取resId,根据resId获取指定包内的Item,也就是组件
string srcId = url.substr(13);
return pkg->getItem(srcId);
}
}
}
else
{
// 获取包名,根据包名获取指定的pkg包
string pkgName = url.substr(pos1 + 2, pos2 - pos1 - 2);
UIPackage* pkg = getByName(pkgName);
if (pkg != nullptr)
{
// 获取组件名,根据组件名获取指定的item
string srcName = url.substr(pos2 + 1);
return pkg->getItemByName(srcName);
}
}
return nullptr;
}
在C++的实现逻辑中,可以发现有两种方式:
- 通过pkgId, resId来获取指定的packageItem
- 通过pkgName, resName来获取指定的packageItem
看下Lua的示例:
fairygui.UIPackage:addPackage("fgui/Basic")
-- 方式1
local itemUrl = "ui://gdlp271kfjgj0"
local packageItem = fairygui.UIPackage:getItemByURL(itemUrl)
print("packageItem name:", packageItem.name) -- MainView
print("packageItem id:", packageItem.id) -- fjgj0
-- 方式2
local itemUrl = "ui://Basic/MainView"
local packageItem = fairygui.UIPackage:getItemByURL(itemUrl)
print("packageItem name:", packageItem.name) -- MainView
print("packageItem id:", packageItem.id) -- fjgj0
两者比较的话,前者通过id相关实现阅读会困难,后者可读性较高。
后者的编写规则就如官网上所说: ui://包名/资源名
, 理解这个有助于更好的理解GLoader关于setURL的使用。
程序结构
参考:元件
元件的构成
基础元件: 图片、图形、动画、装载器、文本、富文本、组、组件。
组合型元件:标签、按钮、下拉框、滚动条、滑动条、进度条。
特殊元件:列表
其他:
针对于元件的动态构建,使用create即可,但是推荐使用FairyGUI创建的工厂类:UIObjectFactory
// 创建元件GObject*
GObject* UIObjectFactory::newObject(ObjectType type)
{
switch (type)
{
case ObjectType::IMAGE:
return GImage::create();
case ObjectType::MOVIECLIP:
return GMovieClip::create();
case ObjectType::COMPONENT:
return GComponent::create();
case ObjectType::TEXT:
return GBasicTextField::create();
case ObjectType::RICHTEXT:
return GRichTextField::create();
case ObjectType::INPUTTEXT:
return GTextInput::create();
// ...
}
}
Lua示例
-- 创建Loader
local objectType = fairygui.ObjectType.LOADER
local object = fairygui.UIObjectFactory:newObject(objectType)
print(tolua.isnull(object), tolua.type(object)) -- false fairygui.GLoader
上一篇:cocos2d-Lua FairyGUI注意项(二)
下一篇: cocos2dx-Lua FairyGUI 之装载器(四)