1. 程式人生 > >FairyGUI筆記:Component(九)

FairyGUI筆記:Component(九)

  • Component

自定義資料 可以設定一個自定義的資料,這個資料FairyGUI不做解析,按原樣釋出到最後的描述檔案中。開發者可以在執行時獲取。獲取方式根據SDK版本有所不同,如果是支援XML包格式的SDK,獲取方式為:

//Unity/Cry
aComponent.packageItem.componentData.GetAttribute("customData");
//Cocos2dx/Vision
aComponent->getPackageItem()->componentData->RootElement()->Attribute("customData");
//LayaAir
aComponent.packageItem.componentData.getAttribute("customData");
//Egret
aComponent.packageItem.componentData.attributes.customData;
//AS3/Starling
[email protected]
;

如果是支援二進位制包格式的SDK,獲取方式為:

//Unity/Cry/Laya/Egret
aComponent.baseUserData;
//Cocos2dx/Vision
aComponent->getBaseUserData();

穿透

//true表示不可穿透,false表示可穿透。
aComponent.opaque = false;

注意:圖片和普通文字是不接受點選的,如果一個只含有圖片或普通文字的元件,設定了點選穿透,那麼整個元件就是完全穿透了,不會攔截到任何點選。

  • 畫素點選測試

有些特殊需求,需要用到不規則區域的點選測試。首先你要準備一張包含不規則區域的圖片,圖片裡不透明的畫素代表接受點選的區域,透明的畫素代表點選穿透的區域,元件裡超出圖片範圍的也是可穿透的區域。

把這張圖片拖入舞臺,然後在元件的“畫素點選測試”屬性裡,選擇這張圖片。

  • 遮罩

矩形遮罩

將元件的“溢位處理”設定為“隱藏”或者“滾動”,那麼元件就帶了矩形遮罩。超出元件(矩形區域-邊緣留空)的區域都不可見。無論在什麼平臺,這種遮罩的效率是最高的。

自定義遮罩

可以設定元件內一個圖片或者圖形作為元件的遮罩。這種遮罩一般都是使用模板測試(Stencil Op)技術。各個平臺支援的力度不同:

  • AS3/Starling/Egret/Laya 使用圖形(Graph)作為遮罩時,有圖形的區域內容可見,例如,一個圓形,則圓形區域內可見,其他區域不可見。

    不能使用圖片(Image)作為遮罩,因為使用圖片作為遮罩也是取其矩形區域而已,用一個矩形(Graph)的圖形效果是一樣的。

    Starling版本要使用自定義遮罩必須在應用程式描述檔案里加上:

     

    <initialWindow>

    <depthAndStencil>true</depthAndStencil>

    </initialWindow>

  • Unity 使用圖形(Graph)作為遮罩時,有圖形的區域內容可見,例如,一個圓形,則圓形區域內可見,其他區域不可見。

    使用圖片(Image)作為遮罩時,圖片內透明度為0的畫素對應區域的內容不可見,反之可見。超出圖片區域的內容不可見

反向遮罩(挖洞)

效果和正常遮罩相反,也就是可見的區域變不可見,不可見的區域變可見。目前僅Unity平臺支援,例如:

使用圖形(Graph)作為遮罩時,有圖形的區域內容不可見,例如,一個圓形,則圓形區域內不可見,其他區域可見。

使用圖片(Image)作為遮罩時,圖片內透明度為0的畫素對應區域的內容可見,反之不可見。超出圖片區域的內容可見

注意:

  1. 當遮罩發生時,點選測試也同樣會發生變化,只有顯示出來的內容才接受點選檢測,被遮住的內容不接受點選檢測。
  2. 對於正在編輯的元件,遮罩只有在預覽時才能看到效果。
  3. 定義了遮罩的元件,其內部的元件永遠無法和外部的元件合併Draw Call,因為他們有不同的材質屬性。
  • 擴充套件

從提示可以看到,FairyGUI中“擴充套件”的定義方式是以”名稱約定“為基礎的。一個按鈕,可以帶有標題和圖示,這個標題(一般是一個文字)和圖示(一般是一個裝載器)需要你自己放置到元件中,並把他們名字設定為title和icon,就像這樣:

然後我們測試一下這個剛製作好的元件。把按鈕元件拖到另一個元件中,並設定一下“標題”和“圖示”,如下圖

效果出來了。這說明標題文字被自動設定到了名稱為“title”的文字元件上,圖示被自動設定到了名稱為“icon”的裝載器元件上。

如果按鈕元件裡沒有放置名稱為icon的裝載器控制元件呢?那麼設定圖示就沒有效果,僅此而已。其他約定的處理方式也相同。不會有任何報錯。

  • GComponent

元件支援動態建立,例如:

GComponent gcom = new GComponent();
gcom.SetSize(100,100);
GRoot.inst.AddChild(gcom);

動態建立的元件是空元件,可以作為其他元件的容器。一個常見的用途,如果你要建立一個多層的UI管理系統,那麼空元件就是一個合適的層級容器選擇。動態建立的元件預設是點選穿透的,也就是說如果直接new一個空元件作為接收點選用途,你還得這樣設定:

//設定元件點選不穿透。
gcom.opaque = true;

如果要建立UI庫裡的元件,應該使用這樣的方式:

GComponent gcom = UIPackage.CreateObject("包名","元件名").asCom;
GRoot.inst.AddChild(gcom);

FairyGUI和Flash/Cocos類似,採用樹狀的結構組織顯示物件。容器可以包含一個或多個基礎顯示物件,也可以包含容器。這個樹狀結構稱為顯示列表。FairyGUI提供了API管理顯示列表。

  • 顯示列表管理

  • numChildren 獲得容器內孩子元件的數量。

  • AddChild AddChildAt 向容器內新增元件。前者將元件新增到顯示列表的隊尾;後者可以指定一個索引控制元件的插入位置。

  • RemoveChild RemoveChildAt RemoveCihldren 從容器內刪除元件。當元件從顯示物件中移出時,將不再佔用顯示資源。但元件從顯示列表移出後,只是不顯示,並沒有銷燬,如果你沒有儲存這個物件的引用留待後續使用,或者沒有呼叫物件的Dispose方法銷燬物件,那麼會產生記憶體洩露。

  • GetChild GetChildAt 通過索引或名稱獲得元件引用。元件的名字是允許重複的,在這種情況下,GetChild返回第一個匹配名稱的物件。

  • GetChildIndex 獲得指定元件在顯示列表中的索引。

  • SetChildIndex SwapChildren SwapChildrenAt 設定元件在顯示列表中的索引。

  • 渲染順序

在FairyGUI中,顯示列表是以樹形組織的,下面說的渲染順序均指在同一個父元件下安排的順序,不同父元件的元件是不可能互相交錯的,這是前提,請注意。

顯示物件的渲染順序取決於它的顯示列表中的順序,順序大的後渲染,即顯示在較前面。一般來說,我們都是使用AddChild或SetChildIndex調整渲染順序。例如如果要一個元件顯示在容器的最前面,那呼叫AddChild(元件)就可以了,AddChild是可以重複呼叫的。也可以呼叫SetChildIndex設定物件在顯示列表中的具體位置,例如SetChildIndex(元件,0)就可以將元件置於最底層。

還有另外一個因子可以影響渲染循序,它就是GObject.sortingOrder。這個屬性只用於特定的用途,不作常規的使用。它一般用於類似固定置頂的功能,另外,永遠不要將sortingOrder用在列表中。sortingOrder越大,則渲染順序越後,即顯示到更前面的位置。一般情況下,sortingOrder為0,這時渲染順序由顯示物件在顯示列表中的順序決定。sortingOrder可以令你更靈活的控制渲染循序。例如,如果希望一個元件始終保持在其他元件上方,可以設定其sortingOrder一個較大的整數值,這樣無論容器使用AddChild添加了多少元件,這個元件依然顯示在最前面。(sortingOrder的效率較差,勿做頻繁呼叫的用途)

上面提到的都是調整物件在顯示列表中的順序,如果不想調整這個順序的同時,又要調整渲染順序,元件還提供了另一種方式。

//升序,這是預設值,按照物件在顯示列表中的順序,從小到大依次渲染,效果就是序號大的顯示在較前面。
aComponent.childrenRenderOrder = ChildrenRenderOrder.Ascent;
//降序,按照物件在顯示列表中的順序,從大到小依次渲染,效果就是序號小的顯示在較前面。
aComponent.childrenRenderOrder = ChildrenRenderOrder.Descent;
//拱形,需要指定一個頂峰的索引,從兩端向這個索引位置依次渲染,效果就是這個位置的物件顯示在最前面,兩邊的物件依次顯示在後面。
aComponent.childrenRenderOrder = ChildrenRenderOrder.Arch;
aComponent.apexIndex = 3; //索引為3的物件顯示在最前面。
  • 繫結擴充套件類

可以繫結一個類為元件的擴充套件類。首先,編寫一個擴充套件類:

public class MyComponent : GComponent
{
    GObject msgObj;
    //如果你有需要訪問容器內容的初始化工作,必須在這個方法裡,而不是在建構函式裡。各個SDK的函式原型的引數可能略有差別,請以程式碼提示為準。
    override protected void ConstructFromXML(XML xml)
    {
        base.ConstructFromXML(xml);
        
        //在這裡繼續你的初始化
        msgObj = GetChild("msg");
    }
    public void ShowMessage(string msg)
    {
        msgObj.text = msg;
    }
}

然後註冊你的擴充套件類。注意,必須在元件構建前註冊,如果你使用的是UIPanel,那麼在Start裡註冊是不夠早的,必須在Awake裡,總之,如果註冊不成功,90%可能都是註冊晚於建立,10%可能是URL錯誤,這可以通過列印URL排查。

UIObjectFactory.SetPackageItemExtension("ui://包名/元件A”, typeof(MyComponent));

這樣就為元件A綁定了一個實現類MyComponent 。以後所有元件A創建出來的物件(包括在編輯器裡使用的元件A)都是MyComponent型別。然後我們就可以為MyComponent新增API,用更加面向物件的方式操作元件A。例如:

MyComponent gcom = (MyComponent)UIPackage.CreateObject(“包名“, ”元件A”);
gcom.ShowMessage("Hello world");

注意:如果元件A只是一個普通的元件,沒有定義“擴充套件”,那麼基類是GComponent,如上例所示;如果元件A的擴充套件是按鈕,那麼MyComponent的基類應該為GButton,如果擴充套件是進度條,那麼基類應該為GProgressBar,等等。這個千萬不能弄錯,否則會出現報錯。