Torque2D MIT 学习笔记(21) ---- 名称空间和脚本函数入口的用法

前言

  如果你选择了Torque,那么TorqueScript对于你来说就变得非常重要,因为为了直接跨平台和与最新版本同步,你就要尽量少的修改源代码,多多的用脚本开发.

  使用脚本,不是光有一些变量支持,语法支持就行的,它最重要的作用是与引擎通信,通过接口调用和事件的捕获来完成各种各样的任务,而对于接口调用这里不再多说,你只要搜索工程(Console*****)就会看到.

  我在这里分享一下脚本中对象方法的创建,引擎事件的捕获以及内部原理.

举例

  举个例子先:

function Test()
{
   %set = new SimSet() { class="SetClass"; };
   Game.ActiveStage.add( %set );
   
   %set.onCall( "test set namespace entry :)" );
}

function SetClass::onCall( %this, %data )
{
   echo( "setclass received call:" @ %data );
}

 上面的代码有三个重要点:

  1. 创建SimSet: 继承自SimObject

  2. 设置"class": SimObject的域名

  3. 声明"SetClass::onCall": 自定义回调

问题

  引擎是如何调用到SetClass::onCall的? 举一反三,引擎内部的一些事件抛出到脚本也是一样的原理,只不过消息名不一样,我们要如何做才能捕获到他们?

Namespace and Entry

  在Torque中,链表被大量的使用,Namesapce也是其中之一,他很重要,可以理解为是引擎和脚本的桥梁,它管理了所有的通信接口和脚本数据,方法.

  一个Namspace就可以看做是一个方法类,或者功能包.

  Entry是具体某个子功能的封装结构,比如OnCall这个方法在引擎内部就是一个Entry,而SetClass就是一个namespace.两者是一对多的关系.

  在SimObject的域初始化方法中有:

void SimObject::initPersistFields()
{
	.....
	// Namespace Linking.
	addGroup("Namespace Linking");
	addProtectedField("superclass", TypeString, Offset(mSuperClassName, SimObject), &setSuperClass, &defaultProtectedGetFn, &writeSuperclass, "Script Class of object.");
	addProtectedField("class",      TypeString, Offset(mClassName,      SimObject), &setClass,      &defaultProtectedGetFn, &writeClass, "Script SuperClass of object.");
	endGroup("Namespace Linking");
}

   有两个域和名称空间有关系,而他们的具体实现方法:

void SimObject::setClassNamespace( const char *classNamespace )
{
	mClassName = StringTable->insert( classNamespace );
	linkNamespaces();
}

void SimObject::setSuperClassNamespace( const char *superClassNamespace )
{  
	mSuperClassName = StringTable->insert( superClassNamespace );
	linkNamespaces();
}

   linkNamespaces中,会对superclas,class两个域进行判定,如果存在则会链接到namspace的链表中,在引擎调用脚本对象方法的时候,能够找到.

bool linkNamespaces(const char *parent, const char *child)
{
   Namespace *pns = lookupNamespace(parent);
   Namespace *cns = lookupNamespace(child);
   if(pns && cns)
      return cns->classLinkTo(pns);
   return false;
}

Namespace *Namespace::find(StringTableEntry name, StringTableEntry package)
{
   for(Namespace *walk = mNamespaceList; walk; walk = walk->mNext)
      if(walk->mName == name && walk->mPackage == package)
         return walk;

   Namespace *ret = (Namespace *) mAllocator.alloc(sizeof(Namespace));
   constructInPlace(ret);
   ret->mPackage = package;
   ret->mName = name;
   ret->mNext = mNamespaceList;
   mNamespaceList = ret;
   return ret;
}

   再结合编译过程中的一段代码:

         case OP_FUNC_DECL:
            if(!noCalls)
            {
               fnName       = U32toSTE(code[ip]);
               fnNamespace  = U32toSTE(code[ip+1]);
               fnPackage    = U32toSTE(code[ip+2]);
               bool hasBody = bool(code[ip+3]);
               
               Namespace::unlinkPackages();
               ns = Namespace::find(fnNamespace, fnPackage);
               ns->addFunction(fnName, this, hasBody ? ip : 0, curFNDocBlock ? dStrdup( curFNDocBlock ) : NULL );// if no body, set the IP to 0
               if( curNSDocBlock )
               {
                  if( fnNamespace == StringTable->lookup( nsDocBlockClass ) )
                  {
                     char *usageStr = dStrdup( curNSDocBlock );
                     usageStr[dStrlen(usageStr)] = '\0';
                     ns->mUsage = usageStr;
                     ns->mCleanUpUsage = true;
                     curNSDocBlock = NULL;
                  }
               }
               Namespace::relinkPackages();

               // If we had a docblock, it's definitely not valid anymore, so clear it out.
               curFNDocBlock = NULL;

               //Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip);
            }
            ip = code[ip + 4];
            break;

   我们可以看出,Namspace的名字不能够重复,在脚本编译阶段,如果遇到ClassName::Function这样的字段,编译器会自动寻找ClassName的名称空间,找不到直接创建个新的,然后加入一个Function的Entry,对象创建时的class设置于class本身的方法定义没有强制性的先后关系.

总结

  Torque提供了很多的脚本对象事件,如果你有工程,那么直接搜executef就可以看到大部分,结合上面的方法可以在脚本中捕获,处理. :)

posted on 2013-03-23 13:12  Kevin Game  阅读(968)  评论(0编辑  收藏  举报