native(307) final iterator function TouchingActors( class<Actor> BaseClass, out Actor OutActor );迭代子宣告在一個原生UnrealScript類別裡,由C++實作,實際上是一個成員函式。要在UnrealScript中使用一個迭代子,需要透過foreach語法。下列程式碼示範如何使用一個迭代子:
function PrintTouchingActors()
{
local Actor TouchedActor;
foreach TouchingActors(class'Actor', TouchedActor)
{
`log(TouchedActor.Name);
}
}
範例
以下程式碼示範如何自訂一個可以取得所有類別的迭代子:
class MyIterator extends Object
native;
native iterator static function AllClasses( class BaseClass, out class OutClass );
static function PrintAllClasses( class BaseClass )
{
local class cls;
foreach AllClasses( BaseClass, cls )
{
`log( cls );
}
}
編譯過上列UnrealScript後會自動產生以下的C++類別定義:
class UMyIterator : public UObject
{
public:
DECLARE_FUNCTION(execAllClasses);
DECLARE_CLASS(UMyIterator,UObject,0,MyGame)
NO_DEFAULT_CONSTRUCTOR(UMyIterator)
};
其中的execAllClasses()函式正是對應到先前在UnrealScript宣告的迭代子。DECLARE_FUNCTION
巨集宣告的函式參數都一樣,第一個參數是執行UnrealScript用的堆疊,可由此取得運算元,第二個參數是存放傳回值位址的void指標。以下是該
函式的實作碼:
void UMyIterator::execAllClasses( FFrame& Stack, RESULT_DECL )
{
P_GET_OBJECT(UClass, BaseClass);
P_GET_OBJECT_REF(UClass, OutClass);
P_FINISH;
TObjectIterator<UClass> It;
PRE_ITERATOR
OutClass = NULL;
// Fetch a valid output.
while( It )
{
UClass* CurrentClass = *It;
++It;
if( CurrentClass->IsChildOf(BaseClass) )
{
OutClass = CurrentClass;
break;
}
}
// If there is no output, skip POST_ITERATOR and go to the end of the script block.
if(! OutClass)
{
Stack.Code = &Stack.Node->Script(wEndOffset + 1);
break;
}
POST_ITERATOR
}
其中的PRE_ITERATOR和POST_ITERATOR巨集其實是一個do while迴圈,必須在POST_ITERATOR前取得每次迭代的輸出物件並且指派到輸出參數(本例中是OutClass),POST_ITERATOR本身會執行一次迴圈內容然後前進到下一次迭代。所以當遇到終止條件時就要逕自跳離巨集所形成的迴圈,以避免執行POST_ITERATOR,並且利用如上面if區塊的程式碼跳離UnrealScript的foreach區塊。
沒有留言:
張貼留言