作者:游蓝海
1.前言
我喜欢编程,但并不是任何时刻都喜欢,一个月中总有那么些天很懒很堕落,不喜欢出去散心,也无法静下心来学习,这也是为什么入行这么久了,还未成为大牛。我想,每个大牛们都有过这种经历吧,经过若干的心理斗争,终于战胜了懒惰,开始敲键盘,然后就一发不可收拾。好了, 废话不多说,开始今天的主题吧。
这里所说的ui编辑器,是指mygui中的布局编辑器(LayoutEditor)。mygui的ui编辑器也并非那么强大,存在一些不足,后面会相继提到。
2.概览
如下图所示,左侧是画布,用于显示ui布局,通过鼠标滚轮来缩放,可以通过菜单->设置来调整画布大小;右侧是功能分页,属性(properties)、窗体组件(widgets)、工程(project)。ui编辑器本来比较简单,我也不浪费自己和大家时间来介绍怎么用了,后面只介绍一些注意事项。
3.创建控件
在右侧widgets分页中选择一个类型(类型可以在properties中修改),在左侧画布中拖拽,会拉出目标界面。如果是一级界面,需要在properties中指定一个层(Layer),否则在游戏中将无法看到此界面;如果是子控件,一定要在第一次点击的时候点中父控件,否则你得撤销这次操作重新来一遍,mygui中并没有提供方法来修改一个控件的父控件。
mygui提供了一个菜单选项Widgets,用于显示当前画布上所有控件的树形关系,可以在这里选中那些无法用鼠标选中的控件。让我觉得遗憾的是,这个树形结构功能太简单了,至少得增加一个调整父子关系的功能。
4.关于相对布局
mygui的相对布局简直是垃圾。它的相对排版参考系是当前画布的尺寸,如果你的游戏窗口跟画布大小不一样,那么布局加载到游戏之后,显示的位置必定不是你想要的。虽然它的坐标可以选择百分比模式,但是在百分比模式下,界面的尺寸也是百分比的,会随着窗口尺寸变化一起变化,这明显也不是我们想要的。
我的解决办法是,在mygui中维护一个变量mDesignSize,记录画布大小,当加载布局的时候,将画布大小作为旧尺寸,layer尺寸作为新尺寸,重新调整布局。Widget* Gui::baseCreateWidget:
if (!_layer.empty())
{
LayerManager::getInstance().attachToLayerNode(_layer, widget);
if (widget->getLayer())
{
widget->_setAlign(mDesignSize, widget->getLayer()->getSize());
}
}
前几天,在网上看到其他的解决办法,将每个一级界面都设置成相对坐标(%:0 0 100 100),这样一级界面就可以自动根据窗口拉伸了。要做的界面都从二级界面开始。这个办法好处是不需要修改mygui代码,但我总觉的还是不爽,每个布局都会多出这么一个中间界面。
5.关于模板(皮肤)
在属性页面上,有一个skin选项,可以为控件选择皮肤,其实这里的皮肤有两个含义:一是指由皮肤编辑器生成的皮肤,二是指模板(template)。模板其实就是layout数据,即一个控件可以复用另外一个控件的布局数据,这与c++模板有着同样的原理——数据复用。个人觉得,这是mygui最强大的设计之一。
要生成模板很容易,之前没找到方法,以为必须要手写
。后来注意到编辑器上有一个project菜单,可以新建project,一个project其实是若干个layout的集合,project中的每个layout都可以当做模板使用。将project存储成*.xml文件,这个xml文件就是我们需要的模板文件。然后在MyGUI_Core.xml中加入project的xml文件,重启编辑器,就可以在使用自己建的模板(皮肤)了。
需要注意,要作为模板的控件,其名称必须为Root,并且勾选Template属性为true。
图 project菜单
图 project中的模板
6.其他
mygui的ui编辑器除了上文提到的bug外,还缺少很多易用的功能,下面是我所能想到的:
* 复制控件;
* 批量选中,然后删除、对齐、复制;
* 调整控件父子关系。
其他的暂时还没想到,后面想到再加上。