使用 Lua 控制 GUI
使用 Lua 控制 GUI
在本教程中我們將介紹以下操作的基本知識:
- 創(chuàng)建一個 GUI 環(huán)境并將它激活
- 創(chuàng)建一個對話框?qū)嵗?/li>
- 通過編輯 XML 來配置對話框
- 關聯(lián)到按鈕事件
本教程中我們會學習如何在 Vision 使用 Lua 來創(chuàng)建和顯示 GUI。 我們將學習如何定義布局以及如何加載 XML 并通過修改它們來顯示自定義菜單和對話框。 然后我們會在對話框中添加一個勾選框,由它來控制場景中一個光源的可見性。
本課程基于“Scripting Basics”教程。 如果你還不了解 Vision 和 vForge 中的腳本功能,請先學習基本腳本教程。因為在本教程將專注于 GUI 腳本而跳過關于 vForge 腳本功能的基本講解。
基本概念:
Vision 的 GUI 系統(tǒng)基于引擎的底層 2D 渲染功能。 GUI 的類會被編譯成 VisionEnginePlugin,因此在插件被加載的時候它們會被正確地初始化。 它支持對話框,事件以及很多不同種類的控件。 所需的資源和對話框布局都在 XML 資源文件中定義。
所有的GUI 資源,比如對話框布局、游標、字體等等都通過專有的 GUI 管理器處理。 該管理器維護一個列表,管理所有使用 GUI 資源的 GUI 環(huán)境。 一個 GUI 環(huán)境的實例定義了一個獨立于其它 GUI 環(huán)境的具體的狀態(tài)(例如,如果場景中有很多控制臺模型的實例,這些控制臺顯示帶有門禁密碼的用戶界面,每一個控制臺都可以處于不同的狀態(tài),鎖定/解鎖)。
創(chuàng)建你的第一個對話框:
我們會從一個已經(jīng)準備好的場景開始。 我們將添加 GUI 資源以及 Lua 腳本。 你可以通過加載教程中的工程,然后打開 Scenes/GUI_LUA/GUI_LUA.scene 來使用該場景。
首先我們要添加一段初始化對話框的腳本。 為此,選擇場景的 Main Layer 然后來到 Properties 面板。 在面板中選擇 SceneScriptFile 屬性,然后在下拉菜單中選擇“New”。 新建一個名為“initGUI.lua”的腳本。
然后我們來拼接該腳本的內(nèi)容。 轉(zhuǎn)到 Script 面板并打開新新建的腳本。
我們需要兩個回調(diào)函數(shù):
- OnAfterSceneLoaded
- OnBeforeSceneUnloaded
OnAfterSceneLoaded 會在場景初始化后被調(diào)用。 在回調(diào)函數(shù)中,我們需要初始化 GUI 系統(tǒng)并加載所需的資源:
function OnAfterSceneLoaded(self)
GUI:LoadResourceFile("Dialogs/MenuSystem.xml") –-load resources
G.myDialog = GUI:ShowDialog("Dialogs/MainMenuLUA.xml") –-show GUI
GUI:SetCursorVisible(true) –-make the mouse cursor visible
end
Dialogs/MenuSystem.xml 和 Dialogs/MainMenuLUA.xml 已經(jīng)包含在了我們的樣例中。 MenuSystem.xml 定義了用于對話框的字體和游標的貼圖。 MainMenuLUA.xml 定義了具體的對話框布局。 稍后我們會仔細分析這個文件并添加新的按鈕。
在我們運行場景前還需要確保對話框在場景停止運行的時候會再次隱藏。 為此,我們在 OnBeforeSceneUnloaded 中添加下列代碼
function OnBeforeSceneUnloaded()
local mode = Application:GetEditorMode()
if mode == Vision.EDITOR_PLAY or mode == Vision.EDITOR_RUN then
GUI:SetCursorVisible(false)
GUI:CloseDialog( G.myDialog )
end
end
首先我們檢查當前的編輯模式。 因為我們只想在 vForge 中運行場景之后關閉對話框。 當我們通過導出再運行場景時不應該做這些,因為(那種情況下)對話框會在 OnBeforeSceneUnloaded 被觸發(fā)前就被清理干凈。
你最終的腳本應該是這樣的:
現(xiàn)在我們準備好啟動 Play-The-Game in vForge(在 vForge 中執(zhí)行游戲) 模式,你會看到如下對話框:
恭喜!
你已經(jīng)成功地在 Vision 中創(chuàng)建了一個 GUI 對話框!
修改 XML 布局:
現(xiàn)在我們有了一個可以運行的 GUI,再來看看布局是如何定義的。 對話框布局文件以 XML 形式存儲。 對話框的類名以及所有關于控件的信息都儲存在 XML 文件中。 一個典型的對話框資源 XML 是這樣的:
<root>
<DIALOG class="VDialog" name="MainMenu" fullscreen="FALSE" size="300,140" startPosition="ScreenCenter">
<control class="..." .../>
<control class="..." .../>
<control class="..." .../>
</DIALOG>
</root>
- 打開“Dialogs”文件夾中的 MainMenuLUA.xml。
- 如你所見,該 XML 定義了有三種控件的對話框布局:
- 一個顯示 Anarchy 徽標的圖片控件。
- 一個黃顏色的文本標簽顯示“Control Menu”。
- 一個標為“Close”的按鈕。
來理解一下用到的語法。 有許多種類的控件:文本框、列表、檢索圖、滑塊等等。 可以在這里找到關于 XML 控件的完整參考說明:
- 我們?yōu)椤癈lose”按鈕添加一個背景圖。 把下列 XML 代碼添加到 VPushButton 控件上:
<control class="VPushButton" ID="QUIT" ... >
...
<image texture="Button.tga" valign="CENTER" halign="CENTER">
<statemodifier state="mouseOver" texture="ButtonMouseOver.tga" cursor="HighMouse"/>
<statemodifier state="selected" texture="ButtonClicked.tga" cursor="HighMouse"/>
<statemodifier state="disabled" texture="ButtonDisabled.tga"/>
</image>
</control>
按鈕擁有不同的狀態(tài)(mouseOver、selected、disabled)。 你可以為每種狀態(tài)設置不同的圖片。 你還能改變與按鈕互動時的游標圖片。
- 保存文件并重啟 Play-The-Game 模式。 “Quit”按鈕現(xiàn)在看起來像這樣:
如果你將鼠標移到按鈕上,你會看到按鈕和鼠標的外觀都發(fā)生了改變。 在你點擊它的時候同樣會變化。
- 現(xiàn)在你可以嘗試在 XML 改變或添加控件。
恭喜!
你已經(jīng)成功地在 Vision 中修改了 GUI 布局!
為關閉按鈕添加功能
現(xiàn)在我們想為新按鈕添加一些功能。 如果用戶點擊了它,我們希望關閉對話框。
首先我們創(chuàng)建一個新的腳本文件來控制對話框。 來到 vForge 中的 Script 面板并在“Dialogs”文件夾中創(chuàng)建一個新的腳本,命名為“MainMenu.lua”。 添加下列代碼:
function OnItemClicked(self, item, buttons, x, y)
if (item:GetID() == GUI:GetID("QUIT")) then
self:SetVisible(false)
GUI:SetCursorVisible(false)
end
end
這個回調(diào)函數(shù)會在你每次點擊對話框中的按鈕時被調(diào)用。 Item::GetID 會返回按鈕在 MainMenuLUA.xml 中定義的參數(shù) ID。 所以當我們的按鈕被點擊時,我們將對話框隱藏。這里上下文中的“self”即代表對話框。 我們也同時隱藏游標。
最后我們需要將對話框 xml 和新建的腳本關聯(lián)。 為此,請
- 打開“Dialogs”文件夾中的 MainMenuLUA.xml。
- 在對話框標記里加入如下 xml 代碼
<DIALOG class="VDialog" name="MainMenu" fullscreen="FALSE" size="300,140" startPosition="ScreenCenter">
<script filename="MainMenu.lua" />
如果你現(xiàn)在運行 Play-The-Game 模式,你能夠通過點擊“Clost”按鈕關閉對話框。
通過 GUI 控制場景元素
最后這章我們會演示如何通過勾選框來控制一個場景元素。 我們希望在清除選擇框的時候關閉一個光源。 所以首先在 MainMenuLUA.xml 中添加一個勾選框:
<root>
<DIALOG class="VDialog" name="MainMenu" fullscreen="FALSE" size="300,140" startPosition="ScreenCenter">
<script filename="MainMenu.lua" />
<control class="..." .../>
…
<control class="VCheckBox" pos="30,350" size="150,25" ID="CHECKBOX1" checked="true">
<image texture="checkbox.tga">
<statemodifier state="selected" texture="checkboxMarked.tga"/>
</image>
<text text="Light enabled" font="MenuFont" color="255,255,255,255" valign="CENTER" ofs="30,0"/>
</control>
…
</DIALOG>
</root>
在你運行 Play-The-Game 模式后會看到這樣的對話框:
然后我們在場景中添加一個動態(tài)光源用來開關。
來到 Shapes Creator 面板,將 “Lights (Dynamic - Omni Light)”圖形拖拽到場景中。
將光源移到一個你可以看到的地方。 然后到新光源的屬性處修改顏色,比如綠色。之后在 ObjectKey 屬性處輸入字符串“switchlight”。 我們稍后會在 Lua 腳本中使用 ObjectKey 來獲得光源。
最后,讓我們在 vForge 腳本面板中擴展“MainMenu.lua”腳本。
function OnItemClicked(self, item, buttons, x, y)
if (item:GetID() == GUI:GetID("QUIT")) then
self:SetVisible(false)
GUI:SetCursorVisible(false)
elseif (item:GetID() == GUI:GetID("CHECKBOX1")) then
local switchlight = Game:GetLight("switchlight")
if switchlight:IsVisible() then
switchlight:SetVisible(false)
else
switchlight:SetVisible(true)
end
end
end
如你所見,現(xiàn)在我們檢查 ID 為“CHECKBOX1”的勾選框按鈕是否被按下。 如果是,那么我們通過函數(shù) Game:GetLight("switchlight") 獲得光源存放在一個本地變量上。 “switchlight”是先前我們賦給動態(tài)光的 ObjectKey。 如果我們的光源可見,那么將其隱藏。 如果隱藏了,那么將其設為可見。
現(xiàn)在開始 Play-The-Game 模式。 你可以通過對話框中的勾選框來開關光源。
總結(jié):
你已經(jīng)成功完成了通過 Lua 控制 GUI 的教程。 但是請牢記,如果你需要諸如添加動態(tài)文字等高級 GUI 功能的話,應該使用 C++ 來創(chuàng)建 UI。 如果你對此感興趣,請閱讀 C++ GUI 課程。