• Torque2D MIT 学习笔记(8) TAML的高级使用


    TAML 编译

    当你要将一个对象写入到TAML时,并不意味着之写入单一的对象,写入操作同样将作用于他的子对象.

    在写入的时候会遵循若干个步骤:

    1. 查找所有静态和动态的属性Field进行写入,保存.
    2. 查找所有的子对象进行写入,保存.
    3. 查找所有自定义状态进行写入,保存.

    静态和动态属性的编译

    这个过程实际上是由两部分组成,首先是遍历所有的静态属性域,并检测他们是否应该被写入文件.要注意的是这个检测操作只在没有前置调用WriteDefaults的情况下执行.

    在引擎的属性域系统中预先指定了每个属性的相关接口,有设置,获取,写入方法,如下:

    addProtectedField("Angle", TypeF32, NULL, &setAngle, &getAngle, &writeAngle, "");
    

    比如WriteAngle方法,如果谁想知道这个Angle域是否能被写入都可以进行调用来询问,用代码说明:

    // 添加image属性域
    addProtectedField("image", TypeImageAssetPtr, Offset(mImageAsset, ImageFont), &setImage, &getImage, &writeImage, "");
    
    // writeImage的实现
    static bool writeImage( void* obj, StringTableEntry pFieldName )  
    { 
        // 检测资源是不是为空(空为默认,证明没有改变过)
        return static_cast<ImageFont*>(obj)->mImageAsset.notNull(); 
    }
    

    TAML快速遍历所有的静态属性域并检测他们,形成一张需要写入的静态属性域列表.

    接下来,TAML快速遍历所有的动态属性域,并直接将他们加入写入列表.因为动态属性是在脚本中创建的,没有相关的检测接口,所以无法决定是否需要写入.

    子对象编译

    TAML先对写入对象进行检测是不是继承于TamlChildren,如果是则会查询包含多少子对象.

    参照代码可见:

    // 直接继承于TamlChild的类有三个(也有二次继承的,这里省略)
    class ParticleAsset : public AssetBase, public TamlChildren
    class SimSet: public SimObject, public TamlChildren
    class Scene : public BehaviorComponent,
    public TamlChildren,
    public PhysicsProxy,
    public b2ContactListener,
    public b2DestructionListener, public virtual Tickable
    // 编译代码中 void Taml::compileChildren( TamlWriteNode* pTamlWriteNode ) { ..... // 编译对象 SimObject* pSimObject = pTamlWriteNode->mpSimObject; // 类型转换为TamlChildren. TamlChildren* pChildren = dynamic_cast<TamlChildren*>( pSimObject ); // 这里要判断是不是转换成功以及有没有子对象 if ( pChildren == NULL || pChildren->getTamlChildCount() == 0 ) return; }

    如果存在子对象,TAML将遍历所有的子对象,并递归的进行它们属性域,自定义状态,子对象的写入.

    如上所示,SimSet继承于TamlChildren,可以包含很多的SimObject,同样适用于包含多个SceneObject的Scene,如下代码:

    %list = new SimSet();
    
    // Add some objects.
    %list.add( new ScriptObject() );
    %list.add( new ScriptObject() );
    %list.add( new ScriptObject() );
    
    // Write out the list.
    TamlWrite( %list, "list.taml" );
    

     写入的内容:

    <SimSet>
         <ScriptObject/>
         <ScriptObject/>
         <ScriptObject/>
      </SimSet>
    

    XML 格式

    与XML格式相比,想要阅读或者编辑二进制格式的文件是很困难的,而XML格式在开发和编辑过程中容易使用.

    下面是一个比较具体的脚本例子:

    // 创建一个SimSet对象实例
    %bookList = new SimSet()
    {
        Title="My Book List"; // 增加动态域Titile
    };
    
    // 创建几个Script对象,并设置相关的动态域
    %book1 = new ScriptObject()
    {
        Title="Torque 3D Game Development Cookbook";
        Author="Dave Wyand";
    };
    
    %book2 = new ScriptObject()
    {
        Title="Graphics Programming Black Book (Special Edition)";
        Author="Michael Abrash";
    };
    
    %book3 = new ScriptObject()
    {
        Title="Programming with Graphics";
        Author="Garry Marshall";
    };
    
    // 加入simSet
    %bookList.add( %book1 );
    %bookList.add( %book2 );
    %bookList.add( %book3 );
    
    // 写入TAML文件
    TamlWrite( %bookList, "booklist.taml" );
    

    文件结果如下:

    <SimSet
    	Title="My Book List">
    	<ScriptObject
    		Title="Torque 3D Game Development Cookbook"
    		Author="Dave Wyand"/>
    	<ScriptObject
    		Title="Graphics Programming Black Book (Special Edition)"
    		Author="Michael Abrash"/>				
    	<ScriptObject
    		Title="Programming with Graphics"
    		Author="Garry Marshall"/>				
      </SimSet>
    

    XML的布局方式非常的简洁.

    每一个XMl节点代表着一种能够被引擎认可并创建的类型.

    每一个XMl属性都是一个属性域.这个属性域可以是静态或者动态属性域名.

    TAML支持同一个对象在同一个TAML文件中多处存在,比如: 

    %list = new SimSet();
    
    %obj = new ScriptObject();
    %list.add( %obj );
    %list.add( %obj );
    %list.add( %obj );
    
    TamlWrite( %list, "list.taml" );
    

     产生的结果是:

    <SimSet>
    	<ScriptObject TamlId="1"/>
    	<ScriptObject TamlRefId="1"/>
    	<ScriptObject TamlRefId="1"/>
    </SimSet>
    

    命名对象

    TAML支持Torque对象的命名,不过要特别注意的是相同名字重复而产生的丢失问题.

    所以使用全局唯一的对象名是必要的,尤其是GUI文件.使用方法如下:

    TamlWrite( new ScriptObject(Fred), "test.taml" );
    // 输出
    <ScriptObject Name="Fred"/>
    

    TAML事件回调

      TAML提供了一个TamlCallbacks的监听器来执行对象的读写通告,SimObject继承了这个监听器,因此每一个对象都可以处理TAML的事件回调.具体回调如下:

    • onTamlPreWrite() - 对象写入前调用.
    • onTamlPostWrite() - 对象写入后调用.
    • onTamlPreRead() - 对象状态读取前调用.
    • onTamlPostRead() - 对象状态读取后调用.
    • onTamlAddParent() - onTamlPostRead()调用后并添加到父对象后调用.
    • onTamlCustomWrite() - 对象自定义属性写入期间调用.
    • onTamlCustomRead() - 对象自定义属性读取期间调用.
  • 相关阅读:
    vue视图刷新失效
    vue移动端框架搭建
    猜单词--莫妮卡的新游戏
    快速上手python的坑
    江西育华学校初三下月考英语试卷 2020.3
    Title
    什么是vuex? 什么场景下适用vuex?
    左右模块滑动
    vue-router的几种实例方法以及参数传递
    完整的 vue-router 导航解析流程
  • 原文地址:https://www.cnblogs.com/KevinYuen/p/2940493.html
Copyright © 2020-2023  润新知