cegui 6
统一度量系统使用指南
注意:此教程仅适用于CEGUI >= 0.4.0
统一度量系统使得我们可以用相对部分和绝对部分共同来表示一个坐标或大小。这给窗口布局带来了极大的方便。比如:你可以用相对尺寸来表示高度,使用绝对大小表示宽度,或者混合使用。
统一度量系统共有三种形式
* UDim : 简单的一维
* UVector2 : 由两个UDim组成的二维向量
* URect : 用四个UDim表示一个矩形,依次为:左,上,右,下
UDim
UDim是最简单的了
1 格式为 :{scale, offset}
2 例如 :{1,0}
父窗口的值乘以“scale”然后加上offset就是最后的结果(单位都是像素)。例如:假如上面的例子是窗口的UnifiedWidth属性值,我们将得到和其父窗口一样宽的窗口。
另一个例子:
{0.5, 25}
这将使得到的窗口宽度为其父窗口的一半加上25像素。
使用单一UDim作为其值的属性有:
* UnifiedXPosition
* UnifiedYPosition
* UnifiedWidth
* UnifiedHeight
UVector2
UVector2是用来表示位置和大小的。
3 格式为 :{{x-scale, x-offset}, {y-scale, y-offset}}
4 例如 :{{1, 0}, {1, 0}}
UVector2中包含的两个UDim很像。还是用例子说明吧:假如上面的例子代表窗口的UnifiedSize属性,我们将得到和它的父窗口一样大小的窗口。
5 {{1,0},{0,100}}
上例将产生一个和其父窗口一样宽,但是高度固定为100像素的窗口。
使用Uvector2作为其值的属性有:
* UnifiedPosition
* UnifiedSize
* UnifiedMinSize
* UnifiedMaxSize
URect
最后的一种是URect。它有点特殊,它定义了左,上,右,下四个坐标,而不是大小或位置。由于参数很多,我将用“ls”代替“left-scale”,用“to”代替“top-offset”等等。
6 格式为 :{{ls,lo},{ts,to},{rs,ro},{bs,bo}}
7 例如 :{{0,0},{0,0},{1,0},{1,0}}
上述代码是DefaultWindow类型窗口的默认矩形。它将覆盖其父窗口的整个区域。只有一个属性使用URect值 ---- UnifiedAreaRect。
我们定义矩形区域而不是其大小的做法是很聪明的。比如:假如我们想使一个窗口覆盖它的父窗口,但要为父窗口的四边分别留出10像素的大小,代码可以这样写:
8 {{0,10},{0,10},{1,-10},{1,-10}}
此例可以看出,绝对部分可以取负数。
XML中的应用举例
9 <property name="UnifiedPosition" value="{{0.1,10},{1.0,-30}}">
10 </property>
X-position:父窗口宽度的10% + 10像素
Y-position:父窗口的高度 - 30像素
11 <property name="UnifiedSize" value="{{0.6,5},{0.3,20}}">
12 </property>
Width:父窗口宽度的60% + 5像素
Height:父窗口高度的30% + 20像素
13 <property name="UnifiedXPosition" value="{0.25,-5}">
14 </property>
X-position:父窗口宽度的25% - 5像素
15 <property name="UnifiedAreaRect" value="{{0.1,0},{0.1,0},{0.9,0},{0.9,0}}">
16 </property>
X-position:父窗口宽度的10%
Y-position:父窗口高度的10%
Width:父窗口宽度的80%
Height:父窗口高度的80%
cegui 7
在CEGUI中使用Lua脚本入门
CEGUI所使用的脚本是基于Lua5.0.2 和tolua++ 1.06pre2-1的.
界面的编写很大一部分可以通过脚本来实现.我们可以修改脚本而不必重新编译整个程序,
这就为我们省去了好多时间去设计界面.
目前的Lua脚本模块仍然处于初期的开发阶段。它支持绝大多数的内核系统、基层的窗口类,不过,对于某些特殊的控件目前只能通过属性系统(properties system)来设置。
Ok,我们开始吧!你需要有一定的CEGUI基础,比如初始化、创建窗口等,当然,还要有一定的Lua基础。
初始化
Lua脚本模块囊括了所有的管理类(manager classes),所以可以通过Lua脚本对CEGUI进行简单的初始化.例如:
#include "CEGUILua.h"
1 CEGUI::YourRendererOfChoice* renderer = new YourRendererOfChoice;
2 CEGUI::LuaScriptModule* script_module = new CEGUI::LuaScriptModule();
3
4 // 第二个参数设置xml解析器,0代表默认解析器
5 new CEGUI::System( renderer, 0, script_module );
现在CEGUI::System已经被创建,脚本模块也被指定了。此时,LuaScriptModule的构造函数自动为我们创建了一个lua_State。你也可以传递一个lua_State*到LuaScriptModule的构造函数中来使用自己的lua_State。
如果你在初始化脚本中用到自定义函数,你就需要这么做。代码如下:
6 ...
7 lua_State* s = your_lua_state;
8 CEGUI::LuaScriptModule* script_module = new CEGUI::LuaScriptModule(s);
9 ...
初始化/退出 脚本
CEGUI支持一个配置文件。它的文件名是CEGUI::System的构造函数的一个可选参数。默认为“cegui.config”。
通过设置此配置文件,你可以控制在系统创建和销毁的时候是否执行一个脚本。配置文件的内容类似这样:
10 <?xml version="1.0" ?>
11 <CEGUIConfig
12 InitScript="../datafiles/scripts/init_script.lua"
13 TerminateScript="../datafiles/scripts/exit_script.lua"
14 />
init_script.lua是在系统初始化时候将要被执行的Lua脚本文件。内容可以是这样:
15 -- 获取CEGUI singletons
16 local logger = CEGUI.Logger:getSingleton()
17 logger:logEvent( ">>> Init script says hello" )
18 --logger:setLoggingLevel( CEGUI.Informative )
19
20 -- 为我们要使用的singletons创建相应的局部变量(非必须)
21 local system = CEGUI.System:getSingleton()
22 local fontman = CEGUI.FontManager:getSingleton()
23 local schememan = CEGUI.SchemeManager:getSingleton()
24
25 -- 载入schemes
26 schememan:loadScheme( "../datafiles/schemes/TaharezLook.scheme" )
27 schememan:loadScheme( "../datafiles/schemes/WindowsLook.scheme" )
28
29 -- 载入默认字体
30 local font = fontman:createFont( "../datafiles/fonts/Commonwealth-10.font" )
31
32 -- 设置默认鼠标光标
33 system:setDefaultMouseCursor( "TaharezLook","MouseArrow" )
34
35 logger:logEvent( "<<< Init script says goodbye" )
并不一定要同时提供初始化和退出脚本,但是,假如你在初始化脚本中申请了全局使用的存储空间,那你就要在退出脚本中释放它(或者在其它合适的地方)。
现在,你学习了怎样用Lua脚本初始化CEGUI。后续教程将更深入的讲解。
cegui 8 Lua消息处理入门 收藏
cegui 8
Lua消息处理入门
把GUI的消息处理从代码中分离出来,并交给lua脚本处理,这样可以给你的界面带来很大的灵活性.GUI
的相关地东西可以在测试期间很轻松的修改.
Lua中的负责处理消息的东西其实只不过是普普通通的只带一个参数的Lua函数而已.若想用它作事件
处理函数,你必须先在系统中注册它.所以除非你在初始化脚本中载入他们,你必须在处理相应事件之前
载入相关脚本文件.
载入脚本文件
有2种载入脚本文件的方法:使用c++代码或者在初始化脚本中使用Lua代码,由于Lua函数和相应的c++
函数一一对应,这2种方法看起来很像.
CEGUI::System::executeScriptFile(const CEGUI::String &filename,const CEGUI::String& resourceGroup="");
显然这个函数有两个参数:文件名和资源组。大多数情况下,可以不用管最后一个参数。
通过CEGUI指定的Lua脚本模块调用此函数就可以执行指定的Lua脚本文件。这意味着:你的程序可以访问脚本中文件定义的函数等所有东西了,当然,被定义为局部范围的除外。
例如,用C++可以这么写:
1 CEGUI::System::getSingleton().executeScriptFile("../datafiles/scripts/guiscript.lua");
如果有错误产生,它会抛出一个异常。
用Lua可以这么写:
2 CEGUI.System:getSingleton():executeScriptFile("../datafiles/scripts/guiscript.lua")
脚本文件中的全局代码也将被执行,所以要注意对每次执行进行必要的处理(使用一个计数器fx)。
注册事件到Lua函数
既然我们已经载入了脚本文件,下一步就可以绑定事件到脚本处理函数上了.
绑定Lua函数的函数与绑定C++函数的函数名称不同。
3 Event::Connection subscribeScriptedEvent(const String& name,
4 const String& subscriber_name);
参数name是你要绑定的事件。参数subscriber_name为处理此事件的Lua函数的函数名。
调用完此函数后,指定的Lua函数就将成为那个事件的处理函数。而且它运行起来和C++版本的函数几乎一模一样(当然,不同的是:它是Lua脚本)。
如下是绑定PushButton单击事件到一个Lua函数上的代码片段:
5 CEGUI::PushButton* pb = (CEGUI::PushButton*)CEGUI::WindowManager::getSingleton().createWindow("TaharezLook/Button","lua_powered_button");
6 pb->setSize(CEGUI::Size(0.1f,0.1f));
7 pb->setPosition(CEGUI::Point(0.1f,0.1f));
8 pb->subscribeScriptedEvent("Clicked","luabtn_clicked");
9 CEGUI::System::getSingleton().getGUISheet()->addChildWindow(pb);
这段代码将创建一个简单的TaharezLook按钮,把它的Clicked事件绑定到Lua函数luabtn_clicked中,然后把它添加到当前的GUI。
现在,我们看一下那个Lua事件处理函数:
10 function luabtn_clicked(e)
11 local we = CEGUI.toWindowEventArgs(e)
12 we.window:setText("handled from Lua");
13 end
它使得当按钮被按下时,它的文本会变成“handled from Lua”。
我们使用了一个公用的函数:
14 CEGUI.toWindowEventArgs(e)
从它的名字可以看出:它把EventArgs参数转换为WindowEventArgs类型。其他的EventArgs类型也有类似的转换函数。
在Layout文件中注册Lua事件处理函数
在Layout文件中绑定用Lua写的事件处理函数是很简单的。看下这个例子吧:
15 <?xml version="1.0"?>
16 <GUILayout>
17 <Window Type="TaharezLook/Button" Name="lua_powered_button">
18 <Property Name="Width" Value="0.1" />
19 <Property Name="Height" Value="0.1" />
20 <Property Name="XPosition" Value="0.1" />
21 <Property Name="YPosition" Value="0.1" />
22 <Event Name="Clicked" Function="luabtn_clicked" />
23 </Window>
24 </GUILayout>
这个简单的layout文件所做的事和上面的C++代码是一样的。
cegui 9 编写CEGUI脚本入门
本教程所列的代码是Lua脚本,它用到了CEGUI自0.4版本起所绑定的CEGUILua模块。这些代码片段可能没有多少实际用途,但它们足以展示CEGUI和Lua结合起来使用的可能性。
更改记录级别
local logger = CEGUI.Logger:getSingleton()--获取logger
local lvl = logger.getLoggingLevel() --获取记录级别
if lvl < CEGUI.Insane then
logger:setLoggingLevel(lvl +1)
end
此代码:每次增加记录级别一个等级直到到达Insane级别.
载入一个Scheme
CEGUI.SchemeManager:getSingleton():loadScheme("../datafiles/scheme/TaharezLook.scheme")
此代码:载入了TaharezLook.scheme.
简单的界面
1 -- 创建GUI sheet
2 local sheet = CEGUI.WindowManager:getSingleton():createWindow(
3 "DefaultGUISheet","root");
4 CEGUI.System:getSingleton():setGUISheet(sheet) -- 然后,把它附着到系统中
5 -- 创建一个FrameWindow
6 local fw = CEGUI.WindowManager:getSingleton():createWindow(
7 "TaharezLook/FrameWindow","framewnd");
8 -- 把它附着到sheet上
9 sheet:addChildWindow(fw)
10
11 -- 设置它的大小和位置
12 local sz = CEGUI.Size(0.5,0.5)
13 local pos = CEGUI.Point(0.2,0.1)
14 fw:setSize(sz)
15 fw:setPosition(pos)
16 -- 禁止用户改变大小
17 fw:setProperty("SizingEnabled","False")
18
19 -- 使关闭按钮生效
20 fw:subscribeEvent("CloseClicked","fwCloseClicked")
21
22 -- CloseClicked事件的处理函数
23 function fwCloseClicked(eventArgs)
24 local we = CEGUI.toWindowEventArgs(eventArgs)
25 CEGUI.WindowManager:getSingleton():destroyWindow(we.window) -- 销毁frame窗口
26 end
此代码:创建一个GUISheet,把它附着到System上。然后,创建一个FrameWindow,设置它的大小和位置,禁用更改大小属性并为CloseClicked事件绑定了事件处理函数。
类型转换的另一种方法
27 -- CloseClicked事件的处理函数
28 function fwCloseClicked(eventArgs)
29 local we = tolua.cast(eventArgs,"CEGUI::WindowEventArgs")
30 CEGUI.WindowManager:getSingleton():destroyWindow(we.window) -- 销毁frame窗口
31 end
此代码:展示了把EventArgs对象转换成WindowEventArgs类型的另一种方法。
载入一个layout
32 local w = CEGUI.WindowManager:getSingleton():loadWindowLayout(
33 "../datafiles/layouts/test.layout")
34 CEGUI.System:getSingleton():getGUISheet():addChildWindow(w)
此代码:载入了一个layout并把返回的窗口添加到当前的GUISheet中。
弹出菜单
35 -- 我们将多次使用WindowManager对象
36 local wmgr = CEGUI.WindowManager:getSingleton()
37
38 -- 设置菜单
39 local bar = wmgr:createWindow("WindowsLook/Menubar","the_menu_bar")
40 bar:setSize(CEGUI.Size(1,0.1))
41 CEGUI.System:getSingleton():getGUISheet():addChildWindow(bar)
42
43 -- 添加一个菜单项
44 local item = wmgr:createWindow("WindowsLook/MenubarItem","the_menu_bar_item")
45 item:setText("Bar item")
46 bar:addChildWindow(item)
47
48 -- 添加一个弹出菜单到菜单项中
49 local pop = wmgr:createWindow("WindowsLook/PopupMenu","the_popup_menu")
50 item:addChildWindow(pop)
51
52 -- 添加一些菜单项到弹出菜单中
53 item = wmgr:createWindow("WindowsLook/PopupMenuItem","the_popup_menu_item_1")
54 item:setText("Popup item 1")
55 pop:addChildWindow(item)
56
57 item = wmgr:createWindow("WindowsLook/PopupMenuItem","the_popup_menu_item_2")
58 item:setText("Popup item 2")
59 pop:addChildWindow(item)
此代码:创建了一个简单的菜单,并添加了一个包含两个子菜单的弹出式菜单到它上面。