2012年6月9日 星期六

自訂UnrealScript運算子

UnrealScript提供自訂運算子的功能,可以不修改引擎原始碼而在自訂專案中添加新的運算子。運算子宣告在一個原生UnrealScript類別裡,由C++實作,實際上是一個成員函式。在Object.uc裡即可找到許多運算子的宣告,連最簡單的整數加法都有:
native(146) static final operator(20) int + ( int A, int B );
關鍵字native後面括弧裡面的數字是靜態查表索引,索引值不可重覆。靜態查表不限用於運算子,只要是原生函式都可使用。它的查詢速度比一般的動態查表快,通常是用在常用的函式。關鍵字operator用來宣告運算子,後面括弧裡面的數字代表運算優先權,用來建立先乘除後加減的規則。優先權越高的越先運算。

UnrealScript運算子只能使用固定組合的字符,以下列出其中幾個可用的字符以及它們在程式碼中的名稱:
+ Add
- Subtract
* Multiply
/ Divide
+= AddEqual
-= SubtractEqual
*= MultiplyEqual
/= DivideEqual
++ AddAdd
-- SubtractSubtract
== EqualEqual

若想要增加可用的字符,可以修改UnScrCom.cpp的FScriptCompiler::GetToken()函式。

運算子對應的C++函式名稱是固定的,為:
"exec" + 運算子名稱 + "_" + 第一個運算元型別 + 第二個運算元型別
例如一開始提到的整數加法,對應的函式名稱即execAdd_IntInt。

範例


以下程式碼示範如何自訂一個可以作Vector和Vector2D加法的運算子。為了不修改引擎原始碼,在此把運算子宣告在自訂的類別,所以只有該類別或子類別才可使用此運算子。
class MyOperator extends Object
    native;
  
native static final operator(20) Vector + ( Vector A, Vector2D B );

static function Test()
{
    local Vector A, B;
    local Vector2D C;

    B = vect(1, 2, 3);

    C.x = 1;
    C.y = 2;

    A = B + C;
}
編譯過上列UnrealScript後會自動產生以下的C++類別定義:
class UMyOperator : public UObject
{
public:

    DECLARE_FUNCTION(execAdd_VectorVector2D);    

    DECLARE_CLASS(UMyOperator, UObject, 0, MyGame)    

    NO_DEFAULT_CONSTRUCTOR(UMyOperator)    
};
其中的execAdd_VectorVector2D()函式正是對應到先前在UnrealScript宣告的運算子。DECLARE_FUNCTION巨集宣告的函式參數都一樣,第一個參數是執行UnrealScript用的堆疊,可由此取得運算元,第二個參數是存放傳回值位址的void指標。以下是該函式的實作碼:
void UMyOperator::execAdd_VectorVector2D( FFrame& Stack, RESULT_DECL )
{
    P_GET_VECTOR(A);
    P_GET_VECTOR2D(B);
    P_FINISH;
 
    FVector* R = (FVector*)Result;
    *R = A;

    R->X += B.X;
    R->Y += B.Y;   
}

沒有留言:

張貼留言