原文地址https://www.iddevnet.com/quake4/GUIEditor
Quake4的gui跟doom3的關卡編輯器基本上一模一樣,我覺得
反正都是doom3的引擎代碼,挖過來,看一看id 的代碼結構到底是什麼樣子的。對於理解Doom3的代碼有所幫助
本文檔概述了在Quake 4中創建GUI的基礎知識。遊戲中存在兩種類型的GUI:整體UI GUI,如菜單系統和HUD,以及遊戲中的電梯,電腦屏幕和其他交互式GUI等世界GUI。本文檔涵蓋這兩種類型,但往往強調菜單GUI,因爲它們比世界GUI複雜得多。但是,該信息適用於兩種GUI類型。
Quake 4中的所有* .gui文件可以由GUI編輯器或文本編輯器查看。瞭解GUI腳本的最佳方法是查看Quake 4中使用的GUI文件。要查看GUI,請提取pak001.pk4文件的內容並瀏覽到../q4base/GUIs文件夾。
基礎
GUI編輯器可以通過editguis命令從控制檯啓動。您還可以通過添加+ editguis參數通過命令行啓動它。
GUI編輯器包含四個主要區域:GUI顯示,導航器,變壓器和屬性窗口。
該GUI顯示 爲編輯器的主要工作區域。該區域顯示GUI中包含桌面的所有* Def元素。可以在“ 視圖”>“選項”下修改此區域的基本顯示屬性。* Def元素作爲藍色框架顯示在顯示屏上,手柄控制在側面和角落。
WindowDef(rect,visible等)的屬性顯示在“ 屬性”窗口中。單擊屬性對話框可以通過點擊Alt + Enter或雙擊該元素來提高。屬性對話框包含三個選項卡:常規,圖像和文本。所有這些都包含元素的基本屬性,將在後續章節中單獨討論該元素。也可以在“屬性”窗口中更改元素的屬性,方法是單擊所需的空間以更改值,或單擊空白處添加新屬性。
的導航 顯示GUI的* def組件樹。元素是分層和嵌套的,使得在樹下方的元素比先前的元素更高級,並且嵌套在其他元素中的元素在其父元素之下縮進。可以通過單擊導航器中左側顯示的箭頭摺疊和展開父元素。對於要完整顯示的元素,其父窗口的大小必須大於或小於子元素。可以在導航器中更改元素及其父子關係的順序 - 請參閱“ 使用元素”部分。
與windowDef相關聯的腳本顯示在單獨的編輯區域中,可以通過點擊ctrl + Enter或右鍵單擊顯示區域或導航器中的元素並選擇“腳本”來啓動。有關腳本的更多信息,請參閱腳本操作和動畫。
基本的GUI結構和桌面
在此文檔中,windowDef 用於引用任何* Def元素,因爲它們共享幾乎所有相同的屬性。如果有所不同,那就會被注意到。
GUI由單個元素組成,其中大部分是windowDef。還有choiceDefs,editDefs和其他* Defs,如下所述。所有windowDef包含在桌面,它是主GUI父元素。當windowDef創建時,它嵌套在桌面下。WindowDefs可以嵌套在其他windowDef中,創建一個父子關係。
windowDef包含標誌和腳本。標誌是確定windowDef的基本屬性(如大小,可見性,顏色等)的值。腳本嵌套在windowDef的大括號內,並根據具體情況執行。
該桌面還包含浮動,vec4s和namedEvents的所有定義(參見第6節)。
如果您使用GUI編輯器,則通常不會手動編寫一個windowDef(儘管您可以打開純文本文件並以這種方式手動編寫GUI)。但是,要知道什麼是基本的windowDef腳本看起來像您必須進入腳本文本本身並操縱的東西是有用的。以下示例是GUI中幾個簡單的windowDef的腳本看起來如何:
windowDef元素1 { rect 0,0,640,480 可見1 backcolor 1,1,0,1 } windowDef element2 { 正零0,300,300 可見1 backcolor 1,1,0,0.5 文字“這是一些文字” textscale 0.5 forecolor 1,1,1,1 }
以下示例將是一個windowDef,它還包含一些執行操作的腳本:
windowDef元素1 { rect 0,0,640,480 可見1 backcolor 1,1,0,1 OnMouseEnter在 { 設置“backcolor”“1,1,1,1”; } onMouseExit { 設置“backcolor”“1,1,1,0.5”; } }
請參閱windowDef的每個可能標誌的定義。
在Quake 4 GUI系統中可以創建兩種GUI:菜單和HUD GUI和世界GUI。菜單和HUD GUI用作基本遊戲UI,而世界GUI是玩家可以走上游戲並在遊戲中使用以屏蔽世界的謎題,獲取信息或移動的屏幕(即,使電梯GUI玩家選擇一個樓層移動到)。
使用元素
要移動* Def元素圍繞顯示區域,只需單擊並拖動元素並移動。要調整大小,只需點擊並拖動一個* Def元素的控件句柄。元素的位置和大小也可以通過“屬性”對話框進行控制。
要創建另一個元素的子元素,首先選擇所需的父元素。然後按住CTRL,選擇所需的子元素。然後右鍵單擊並選擇排列>製作小孩或按CTRL + \。要反轉此操作,請使用桌面重複此過程作爲所需的父元素。當選擇元素時,選擇的第一個元素將始終爲採用操作時的父元素。首先選擇父元素後,可以通過選擇多個元素來創建多個子元素。
元素的層次順序可以在導航器中更改。爲此,選擇一個元素,然後右鍵單擊並選擇排列 ,然後選擇移動到前,後或前進或後退。這也可以通過右鍵菜單中顯示的鍵盤快捷鍵來完成。
GUI編輯器還允許您通過使用另一個元素作爲參考點來調整大小或移動元素。要使兩個元素的大小相同,請選擇要用作參考點的第一個元素,然後按住CTRL選擇要調整大小的第二個元素。右鍵單擊並選擇“對齊”>“設置相同大小”。選擇寬度,高度或兩者以調整大小。可以選擇多個元素; 所選擇的第一個元素將始終作爲參考點,並且所有其他所選元素將相應調整大小。該對齊選項還允許您對齊沿主元素的左側多個元素,右側,頂部,底部或中心。與其他行動一樣,
使用紋理
元素參考材料與背景屬性。GUI中使用的所有材料的大小必須大於2。材質可以是簡單的紋理,也可以是.mtr文件中定義的着色器。如果所使用的路徑不是着色器路徑,而是直接映射到圖像的路徑,則將使用默認着色器。該默認着色器將是一個32位alpha混合圖像着色器。即使引用直接圖像,最好在路徑末尾離開.tga。
使用瀏覽器
點擊CTRL + T 將顯示GUI Viewer。這個窗口顯示了加載的GUI,就像在遊戲中顯示一樣,允許您測試GUI的功能。
編輯器選項
“ 視圖 ”選項卡下有幾個顯示選項。放大和縮小是不言自明的。隱藏/顯示將隱藏或顯示所選元素,或將隱藏所有元素。顯示輪廓將顯示GUI中所有元素的輪廓。顯示網格將顯示網格,這可以在視圖>選項下自定義。捕捉到網格將會將元素的位置捕捉到網格。顯示安全區域 僅用於爲控制檯開發的GUI,並顯示哪些元素必須保留在內部的區域,以便不會被電視屏幕潛在地削減。
“ 工具”菜單選項下有兩個選項。Viewer已經被討論過了。重新加載材料(CTRL + M)將重新加載GUI中使用的紋理。如果您更改了紋理並希望快速刷新GUI以查看更改,這將非常有用。
在本地化當前GUI 選項會在GUI中的所有文本字符串,並保存他們,如同* .lang文件中引用“#str_xxxxxx”的價值觀。這用於確保其他語言的GUI本地化容易。
- 使用通用動畫在GUI中執行基本的,可重複的功能。例如,如果您在菜單中使用彈出窗口,請創建單個動畫或命名事件,將通用彈出圖形提升,然後設置將在if語句中檢查的桌面浮動,以確定要在頂部顯示的消息的。
-
組織GUI,並使用嵌套windowDefs的父子關係來保持組織。例如,如果您有幾個動畫windowDef,請將它們全部放在標有“p_anims”的父窗口標記或類似的東西下。
-
如果您打算調整windowDefs通過轉換頻繁,它有助於創造一種無形的windowDef大小被確定爲新的大小,然後使用這個windowDef因此在過渡命令,其中“window1_newsize”是無形的windowDef:
轉換“window1 :: rect”“$ window1 :: rect”“$ window1_newsize :: rect”“250”;
-
如果您的菜單變大,創建一些重定義動畫或命名事件,將特定的windowDef組中的所有內容設置爲默認值是有用的。例如,您可能需要將按鈕的屏幕重置爲未高亮的默認狀態。
- GUI系統中的腳本中的語句被同時執行。如果您希望某些步驟發生在其他人之前,您必須使用動畫。
- 避免在動畫中調用命名事件或使用設置的“cmd”或consoleCmd語句。如果一個幀被丟棄,並且你的命令或命名事件調用在該幀中,它將不會被執行,並且會破壞GUI。
-
如果您 嘗試加載GUI時您的GUIEditor崩潰,那可能是因爲您的腳本錯誤。最常見的罪魁禍首是大括號錯誤或不好的聲明。由於GUIEditor 缺少錯誤反饋系統,最好保存不同版本的gui文件,以防萬一損壞。嘗試記住您正在工作的區域,如果可能,請使用高級編輯器(如Ultra Edit),以便您可以將文件彼此進行比較,以發現可能導致崩潰/損壞的差異。
-
可以在桌面標題和元素屬性中使用數學語句來實現某些效果,例如動態放置。舉個例子,看一下scoreboard.gui和mpmain.gui。不過要小心!該GUIEditor 如果您打開編輯器中的桌面腳本窗口已經知道,在他們的數學陳述腐敗桌面頭。如果發生這種情況,保存要複製和粘貼的桌面標題的副本通常是有幫助的。
例如,桌面頭腳本如下:
windowDef桌面 { rect 0,0,640,480 可見1 nocursor 1 menugui 1 float“igOffset”282 - ((32 *“gui :: ig_awards”)/ 2) float“aim_fade_time”10000 - “gui :: main_notice_duration”
將會變成這樣:(注意被剝離的引號,這將打破這些腳本參數)
windowDef桌面 { rect 0,0,640,480 可見1 nocursor 1 menugui 1 float“igOffset”282 - ((32 * gui :: ig_awards)/ 2) float“aim_fade_time”10000-gui :: main_notice_duration
-
桌面是一個windowDef ,就像其他的一樣,它的屬性可以這樣修改。例如,如果要打開半透明的疊加層,請將GUI的桌面設置爲0,0,0,0.5的背景顏色。
-
GUI中的所有元素必須具有唯一的名稱。當複製元素或創建新元素時,GUIEditor有時 會爲其提供唯一的名稱,但有時不會。如果您的元素沒有唯一的名稱,則GUI的功能可能會被破壞。如果您保存並關閉具有相同名稱的多個窗口的gui,則可以手動編輯gui來修復此問題。但是,如果您保存並關閉GUIEditor,您的工作可能會丟失。
- 必須將GUI變量顯式發送到引用它們的每個GUI。如果您的GUI變量不起作用,請嘗試檢查代碼以確保將其發送到正確的GUI。
腳本操作和動畫
在GUI中有兩個基本的事情:
1.用戶單擊導致操作的元素
2.動作發送命令,執行單獨的腳本或啓動動畫
爲了實現這一點,windowDefs必須包含腳本。要添加腳本到windowDef在GUI編輯器,選擇windowDefs和命中Ctrl + Enter。然後在彈出的窗口中輸入腳本。可以在窗口中輸入多個腳本函數,因此腳本窗口可能包含腳本,例如onMouseEnter,onMouseExit和onAction(有關特定腳本函數的更多信息,請參見下文)。
腳本元素的語法如下所示:
OnScriptElementName { 命令“windowname :: parameter”“value”; }
常用腳本命令
設置和轉換
兩個最常見的腳本命令是設置和轉換。兩者都用於設置或更改windowDef標誌的值。腳本可以更改包含腳本或其他windowDef 的windowDef的標誌。如果腳本正在更改自己的windowDef的標誌,則可以刪除“windowname :: flag”語法,並且只需要該標誌(參見下面的示例)。
以下是“set”命令語法的一些示例。
-
設置“可見”“0”;
這將關閉包含腳本的windowDef的可見性。
-
設置“foo :: visible”“1”;
-
設置“cmd”“close”
這將發送關閉GUI的命令。
可以像用戶在控制檯中鍵入命令一樣發送命令:
-
consolecmd“si_map mp / q4dm1”;
該特定命令將服務器映射設置爲mp / q4dm1
轉換用於隨着時間的推移將一個標誌值更改爲另一個。這通常用於鼠標懸停顏色更改和windowDef 大小更改,但也可用於其他情況。轉換命令需要兩個值在一個時間之間進行轉換,以執行以毫秒爲單位的轉換。以下是“轉換”命令語法的一些示例。
-
轉換“matcolor”“1,1,1,1”“1,1,0,1”“100”;
這將在windowDef中將圖像的顏色從白色轉換爲黃色超過100毫秒。以下功能執行相同的功能,但只能轉換windowDef的 alpha顏色:
-
轉換“matcolor_w”“1”“0”“100”;
下列轉換的大小windowDef從640×480到300×300超過500毫秒。
-
過渡“直角”“0,0,640,480”“0,0,300,300”“500”;
的setFocus
setFocus主要用於控制檯菜單。此命令用於設置特定windowDef的鼠標焦點。語法如下:
-
setFocus“windowname”;
Stoptransitions
該stoptransitions命令來暫停動畫或過渡。這與設置notime標誌類似,但主要區別在於設置不變,將允許動畫完成所有的onTime步驟,而stoptransitions將完全脫離onTime或轉換語句。以下示例說明了其上下文:
windowDef按鈕1 { 直線0,0,100,100 可見1 OnMouseEnter在 { //突出顯示按鈕 轉換“matcolor_w”“0.5”“1”“150”; } onMouseExit { // unhighlight the button 轉換“matcolor_w”“1”“0.5”“150”; } 的OnAction { //播放器選擇按鈕時停止所有動畫和轉場 按鈕1“; } }
非交互
非交互命令用於使整個GUI非交互式,直到該標誌設置爲0,使其再次進行交互:
-
非交互式“1”;
腳本功能
OnMouseEnter在
-
指定當玩家移到windowDef上時發生的動作。
onMouseExit
-
指定當玩家從windowDef中移出時發生的動作。
的OnAction
onESC
-
通常在桌面中定義(對於控制檯菜單,這也在其他windowDefs中定義)。定義當玩家擊中ESC鍵時要執行的操作。(對於在WindowDefs中使用的氙菜單,它定義了當玩家擊中B按鈕時發生的操作。)
onNamedEvent
- 定義調用命名事件時要執行的操作。命名事件可以在桌面中定義,也可以是由GUI調用的代碼中的命名事件。
OnJoyUp,onJoyDown,onJoyRight,onJoyLeft
- 用於Xbox 360 GUI。定義當玩家使用D-pad時發生的動作。
onJoyButton1,onJoyButton2,onJoyRShoulder,onJoyShoulder
- 用於Xbox 360 GUI。定義當玩家分別按下X按鈕,Y按鈕,右肩和左肩按鈕時發生的動作。
onJoyBack
- 用於控制檯GUI。這是一個更通用的onESC腳本版本,當播放器按下控制器上的B按鈕時,它將被執行。
腳本函數語法
下面的例子顯示腳本窗口可能是什麼樣子的windowDef當玩家將鼠標移動到它,遠離它,並按下它,將執行的操作,導致兩個命令來執行:
windowDef按鈕1 { 正在0,0200,100 可見1 backcolor 1,1,0,1 文字“按鈕1” textscale 0.26 字體“字體/低像素” OnMouseEnter在 { 轉換“button1 :: backcolor”“1,1,0,1”“1,1,1,1”“100”; } onMouseExit { 轉換“button1 :: backcolor”“1,1,1,1”“1,1,0,1”“100”; } 的OnAction { 設置“cmd”“play guisound_beep2; runscript map_hangar1 :: fire”; } }
onTime和動畫
GUI通常使用動畫來在屏幕之間轉換或使背景元素動畫化,在Quake 4 GUI系統中,onTime用於定義將在指定的時間步長中發生的動畫。準時使用就像在一個任何其它腳本元素windowDef:
windowDef foo { rect 0,0,1,1 可見0 不過0 onTime 0 { //這裏要執行的語句 } }
注意:windowDefs不需要爲其onTime腳本可見才能運行。在具有設置爲0,0,1,1的rect 屬性的小windowDef中放置動畫是常見的,使其不可見,然後使用resettime命令使其運行(請參見下面的resettime)。
語法可以用兩種方法之一寫成。以下兩個例子都做同樣的事情:它們導致“foo”的背景顏色從白色與完整的阿爾法變爲白色與零阿爾法,然後回到完整的阿爾法,然後回到零阿爾法,最後回到完整的阿爾法。
實施例1
onTime 0 { 轉換“foo :: backcolor_w”“1”“0”“100”; } onTime 100 { 轉換“foo :: backcolor_w”“0”“1”“100”; } onTime 200 { 轉換“foo :: backcolor_w”“1”“0”“100”; } onTime 300 { 轉換“foo :: backcolor_w”“0”“1”“100”; }
實施例2
OnTime 0 { 轉換“foo :: backcolor_w”“1”“0”“100”; } onTime +100 { 轉換“foo :: backcolor_w”“0”“1”“100”; } onTime +100 { 轉換“foo :: backcolor_w”“1”“0”“100”; } onTime +100 { 轉換“foo :: backcolor_w”“0”“1”“100”; }
在第一個例子中,時間在腳本中是很難定義的。在第二個例子中,每個onTime 在先前定義的動作之後+ X秒執行下一個動作。決定要使用的語法取決於您要完成的任務。第二種語法通常更容易用於非常大的動畫,您可能需要調整各個時間步長,並且調整onTime腳本中的所有時間都是不方便的。
動畫可以通過resettime命令循環。的重新設定時間 命令可以在一個工作時間腳本的末尾使用,或者它可以從另一個腳本就像組命令被髮送。當在動畫循環本身之外使用時,例如從另一個windowDef,resettime命令將從頭開始一個動畫。
以下是使用resettime命令循環的“白色帶有零alpha”的白色完整阿爾法到動畫的示例:
onTime 0 { 過渡“windowname :: backcolor”“1,1,1,1”“1,1,10”“100”; } onTime 100 { 過渡“windowname :: backcolor”“1,1,1,0”“1,1,1,1”“100”; } onTime 200 { 復位時間“0”; }
以下示例將從另一個windowDef的onAction腳本中重置名爲“foo” 的windowDef中的動畫時間:
的OnAction { 復位時間“foo”“0”; }
循環動畫也可以用notime標誌來停止。如果您希望在玩家在GUI中某個地方點擊windowDef時停止播放動畫,則語法將如下所示:
的OnAction { 設置“windowname :: notime”“1”; }
不過也可以將其設置爲windowDef的標誌,以保持動畫不會運行,直到resettime命令發出:
windowDef animation_alpha { rect 0,0,1,1 可見0 不時1 onTime 0 { 轉換“foo :: matcolor_w”“1”“0”“100”; } }
如果聲明
if和else if 語句可以在GUI系統中使用。他們的語法是基本的 以下示例使用if語句來檢查桌面浮點數,然後根據該值執行命令:
if(“desktop :: float1”== 0){ 設置“foo :: backcolor”“1,0,0,1”; } else if(“desktop :: float1”== 1){ 設置“foo :: backcolor”“1,1,1,1”; } else { 設置“foo :: backcolor”“1,1,0,1”; }
如果語句可以更高級,並檢查值的範圍。您可以檢查大於,小於或大於/小於或 ==的值。您也可以檢查Not值。大於或等於由> =表示,而不等於由!=表示高級值檢查的示例。
if(“desktop :: float1”> = 5){ 設置“foo :: backcolor”“1,0,0,1”; } else if(“desktop :: float1”<= 2){ 設置“foo :: backcolor”“1,1,1,1”; } else if(“desktop :: float1”!= 8){ 設置“foo :: backcolor”“1,0,1,1”; } else { 設置“foo :: backcolor”“1,1,0,1”; }
它們也可以用來檢查和案件或者案件。而且案件都是通過集合分隔檢查&&同時或者案件由分隔||
if(“desktop :: float1”== 0 &&“desktop :: float2”== 0){ 設置“foo :: backcolor”“1,0,0,1”; } else if(“desktop :: float1”== 2 ||“desktop :: float2”== 2 ||“desktop :: float3”== 2){ 設置“foo :: backcolor”“1,1,1,1”; } else { 設置“foo :: backcolor”“1,1,0,1”; }