HowTo/Reskin an Asset using an alias

From TrainzOnline
Jump to: navigation, search

Contents

Introduction

The usual method of reskinning an asset is to copy the whole asset and change the images. This process is relatively simple, but creates issues of copyright, so that if the reskinned asset is to be distributed to the community the permission of the creator of the original asset is required. In some cases it is not possible to obtain permission, or perhaps it is not clear that the original content creator has the right to approve distribution. In these cases it is possible to reskin an asset without copying it first by creating a new asset but referring to the mesh in the original asset using the alias facility.

Note that this method has some drawbacks:

1. The procedure for using the asset in game is not as efficient - it requires changing the mesh textures after the mesh is loaded and processed.

2. The original asset becomes a dependency of the reskin - anyone using the reskin must have both the reskin and the original asset installed on their system.

3. Udates to the original asset might affect the reskin.

Despite these issues, reskinning using an alias has been used for a large number of assets.

This Howto describes the procedure for reskinning an asset using the aliasing feature as of build 3.5.

How To Reskin an Asset using an alias - A step-by-step guide

From build 3.5 the procedure for reskinning an asset using an alias has changed. 'Alias' is no longer available as a top-level tag in config.sys. Instead, the aliasing is accomplished through a process that involves nominating an aliased mesh (not just the asset) and then specifying texture replacement rules for each aliased mesh. Scripting is then used to do the texture replacement.

1. Select the asset to use as the source for the reskinning. This example is the simplest possible case - one texture, no attachments and no existing scripting.

Config.txt:

 kuid                                    <kuid:12345:1000>
 username                                "Alias Sample - Original"
 kind                                    "scenery"
 trainz-build                            3.5
 mesh-table {
   default {
     mesh                                "alias_sample.im"
     auto-create                         1
   }
 }
 category-class                          "BS"
 category-era                            "2000s"
 category-region                         "00"
 thumbnails {
   0 { 
     image                               "$screenshot$.jpg"
     width                               240
     height                              180
   }
 }
 kuid-table { }

Files:

 $screenshot$.jpg
 alias_sample.im
 config.txt
 top.texture.txt
 top.tga

Note that nothing in particular is required in the original asset to support the rekinning - all the reskin information is in the reskin asset. The important items to note from the original are the kuid, the mesh-table container name ("default"), the mesh name ("alias_sample") and the image name ("top.texture").

2. Create the reskin version config.txt:

 kuid                                      <kuid:12345:1001>
 username                                  "Alias Sample - Reskinned"
 kind                                      "scenery"
 trainz-build                              3.5
 script                                    "reskin"
 class                                     "reskin"
 mesh-table {
   default {
     mesh-asset                            <kuid:12345:1000>
     mesh                                  "alias_sample.im"
     effects {
       main {
         kind                              "texture-replacement"
         texture                           "top.texture"
       }
     }
     auto-create                           1
   }
 }
 category-class                            "BS"
 category-era                              "2000s"
 category-region                           "00"
 thumbnails {
   0 {
     image                                 "$screenshot$.jpg"
     width                                 240
     height                                180
   }
 }
 kuid-table {
   0                                       <kuid:12345:1000>
 }

Files:

 $screenshot$.jpg
 config.txt
 new.texture.txt
 new.tga

'new.texture.txt' references 'new.tga', as for a typical texture file. There is no '.im' file for the reskin asset. The mesh-table container in the config file is where the texturing is defined.

 1	mesh-table {
 2	  default {
 3	    mesh-asset                            <kuid:12345:1000>
 4	    mesh                                  "alias_sample.im"
 5	    effects {
 6	      main {
 7	        kind                              "texture-replacement"
 8	        texture                           "top.texture"
 9	      }
 10	    }
 11	    auto-create                           1
 12	  }

2. The subcontainer name(s) should match the names used in the original.

3. The mesh-asset is the KUID of the asset where the mesh to be reskinned is located.

4. The mesh is the '.im' file from the original asset.

5. The effects subcontainer is used to control the reskinning.

6. The effect subcontainer name is an arbitrary name used by the script to identify the texture.

7. The kind for the effect is always "texture-replacement".

8. The texture to be replaced is the texture used in the original asset.

This arrangment sets out the details for the reskinning, but it does not actually do anything. That happens in the script that needs to be attached to the reskin asset - in this case "reskin". From config:

 1	script                                    "reskin"
 2	class                                     "reskin"

1. This is the name of the script as it exists in the reskin asset. The name is arbitrary, but the script tag value must match the file name exactly. The file must have a .gs extension.

2. This is the script class, as defined within the script. This name is arbitrary, but the tag must match the name used in the script 'class' statement. See script details below.

reskin.gs

 include "MapObject.gs"
  // Script:	reskin
  // Function:	reskin aliased asset
  // Author:	
  // Revision:	0.1	July 2015
  //
  // Comments
  //  For assets at build 3.5 and higher, 'alias' is no longer available as a tag.
  //  It is replaced by the 'mesh-asset' tag in the mesh table.  However, for
  //  reskining using an alias, the mesh-asset tag must be supported by a texture replacement 
  //  script so that the replacement texture is applied to the aliased mesh.
  class reskin isclass MapObject  {
	public void Init(void)
	//The Init function is called when the object is created
	{
	// call the parent
               inherited();
	//  ! This will change the texture name that have to be replaced on the effects mesh.
	//  WARNING: This will typically cause Trainz to freeze for a short period when called
	//  and/or when the mesh in question first becomes visible.
	//
	// Param:  effectName	the name of the effect that we want to apply the texture to
	// Param:  textureName	the name of the texture that we want to apply
	//                       
	//   Sets the specified texture onto the named effect.
              SetFXTextureReplacementTexture("main", "new.texture");
	}
  };

MapObject.gs must be included to enable access to the mesh object that is to be reskinned.

Any line starting with // is a comment and can be changed or deleted as required.

"class reskin isclass MapObject" defines the class for the script (this must match the class tag in config) and defines the object to be skinned as a MapObject.

The init procedure and the inherited method create the object to be reskinned.

The "SetFXTextureReplacementTexture" function does the replacing. The texture-replacement container name ("main" in this example) must match the effect name from the config, and the texture name ("new.texture") must match the texture file name (without the .txt extension).

If there are multiple textures to be reskinned for this mesh, repeat the effects subcontainer using appropriate names, and repeat the SetFXTextureReplacementTexture statements with the required effects subcontainer name and the matching replacement texture.

If there are multiple meshes to be reskinned for the asset, repeat the mesh-table subcontainer using the correct name, insert the required effects containers with unique subcontainer names, and repeat the SetFXTextureReplacementTexture statements with those additional names.

Notes

1. If the mesh and texture in the original asset are located in a subfolder, the full path must be specified for the mesh, but the textures will be located relative to that mesh. For instance, for a locomotive it is common to put the main mesh and textures in a 'body' folder - the mesh requires the folder name in the path, but the textures do not. Also, there might be more than one texture.

     mesh-asset                        <kuid:12345:1000>
     mesh                              "body/alias_sample.im"
     effects {
     reskin1      {
       kind                            "texture-replacement"
       texture                         "map1.texture"
     }
     reskin2      {
       kind                            "texture-replacement"
       texture                         "map2.texture"
     }
   }

The texture replacement line in the script will be repeated accordingly.

2. The example above is a simple scenery object. For other types of assets it might be necessary to use the script class specific to that asset. In that case, the MeshObject script must be included in order to provide access to the replacement function. For instance, an engine is type Locomotive, so the script file include statements are

 include "Locomotive.gs"
 include "MeshObject.gs"

and the class definition is

 alias_reskin isclass Locomotive

Similar considerations may apply to other kinds of assets.

3. Numbering of locomotives. If the original asset supports running numbers then the skin asset can also be set up to support it. The skin asset does not require the digit_xx texture files that were previously required (when the 'alias' tag was used) in order to suppress error message about missing textures. The number images that are used are from the skin asset, not the original, but obviously they must match for size. Note that if the reskinning has overridden the running number feature with the running numbers embedded in the texture, then the running number for the loco should be left blank.

4. If upgrading an asset that previously used the 'alias' tag, those textures and their image file that are not changed from the original should be removed from the skin asset and should not be included in the texture replacement.

Reskinning using an alias and scripted assets

If the existing script is accessible, the texture replacement script lines can be added to that script.

If the exiting script is not accessible, and must be retained, then two changes are needed to the reskin script.

1. The existing asset script must listed as an 'include' script. For instance, for a traincar:

include "Vehicle.gs"
include "MeshObject.gs"
include "assetscript.gs"

2. The reskin script must be identified as inheriting from the existing asset script. This means that the existing script init function will be called when the reskin script calls its parent. To change this, the class of the reskin script is changed to the class of the asset script (which is typically the same name as the script). For instance:

 class reskin isclass assetscript  {
   public void Init(void)
   //The Init function is called when the object is created
   {
   // call the parent
     inherited();

The config.txt tags (script and class) are changed to the 'reskin' script file name and 'reskin' as the asset primary class.

Reskinning an asset that uses Level of Detail (LOD)

If an asset to be reskinned uses the same texture for all LOD meshes then no special action is required. But if that asset uses different textures for LOD meshes then a texture replacement is usually required for each texture.

1. An example of a reskin mesh-table referencing a mesh asset that uses the LM.TXT LOD method:

  mesh-table {
    default {
      mesh-asset             <kuid:12345:1000>
      mesh                   "body/alias_sample.lm"
      effects {
        reskin-lod0 {
          kind               "texture-replacement"
          texture            "lod0-map.texture"
        }
        reskin-lod1 {
          kind               "texture-replacement"
          texture            "lod1-map.texture"
        }
     }
    ...
  }

2. The reskin script must call all the LOD texture replacements in the Init() method. For instance:

 class reskin isclass Locomotive  {
   public void Init(void) {
     inherited();
           
     //   Set the specified textures onto the named effects.
     SetFXTextureReplacementTexture("reskin-lod0", "lod0-map.texture");
     SetFXTextureReplacementTexture("reskin-lod1", "lod1-map.texture");
     ...
   }


Related Links

Personal tools