Game Development Community

easier setSkinName

by Thomas Huehn · 05/15/2007 (11:40 am) · 2 comments

This resource replace the default behavior of setSkinName. I simply want a
function to replace the skin on my shapes. The existing setSkinName requires
to have the texture saved with a root prefix "base". So its only work if your
texture is exported with that syntax. That would also work but i want it a little
bit easier so setSkinName("nameofmytexture") replace the texture of the shape.

Example: You have a shape "cube.dts" with a texture called "red.png" and one called "blue.png".
All textures are in the same directory with the shape. The shape is created with the name "cube".
With the following modification you can simple switch the shapeskin with
cube.setSkinName("red") or back with cube.setSkinName("blue"). No need for special
texture names.

Ok lets start. Make a backup of the files engine/ts/tsShapeInstance.cc and engine/ts/tsShapeInstance.cc .

Open the engine/ts/tsShapeInstance.h and replace:
void reSkin(StringHandle& newBaseHandle);

with

void reSkin(StringHandle& newSkinHandle);

done with that file.

Now open the the file engine/ts/tsShapeInstance.cc and replace the whole

void TSShapeInstance::reSkin(StringHandle& newBaseHandle);
..
..

with

void TSShapeInstance::reSkin(StringHandle& newSkinHandle)
{
   #define NAME_BUFFER_LENGTH 256
   char pathName[NAME_BUFFER_LENGTH];
   const char* newSkinName;

   if (newSkinHandle.isValidString()) {
      newSkinName = newSkinHandle.getString();
      if (newSkinName == NULL) {
         return;
      }
   }

   // Make our own copy of the materials list from the resource
   // if necessary.
   if (ownMaterialList() == false) {
      cloneMaterialList();
   }

   const char* resourcePath = hShape.getFilePath();

   // Cycle through the materials.
   TSMaterialList* pMatList = getMaterialList();
   for (S32 j = 0; j < pMatList->mMaterialNames.size(); j++) {
      // Get the name of this material.
      const char* pName = pMatList->mMaterialNames[j];
      // Bail if no name.
      if (pName == NULL) {
         continue;
      }
      // Make a texture file pathname with the new root if this name
      // has the old root in it; otherwise just make a path with the
      // original name.

	  //XXTH Pname=oldskin
	  bool replacedSkin = newSkinHandle.isValidString() && dStrcmp(pName,newSkinName)!=0;

      dStrcpy(pathName,resourcePath);
      dStrcat(pathName, "/");

      if (!replacedSkin) {
         // If this wasn't in the desired format, set the material's
         // texture handle (since that wasn't copied over in the
         // cloning) and continue.
         dStrcat(pathName, pName);
         AssertFatal(dStrlen(pathName) < NAME_BUFFER_LENGTH, "reSkin: Error, pathname too long");
         pMatList->mMaterials[j] = TextureHandle(pathName, MeshTexture, false);
         continue;
      }

      dStrcat(pathName, newSkinName);
      AssertFatal(dStrlen(pathName) < NAME_BUFFER_LENGTH, "reSkin: Error, pathname too long");
      // OK, it is a skin texture.  Get the handle.
      TextureHandle skinHandle = TextureHandle(pathName, MeshTexture, false);
      // Do a sanity check; if it fails, use the original skin instead.
      if (skinHandle.getGLName() != 0) {
         pMatList->mMaterials[j] = skinHandle;
      }  else { //if (!replacedSkin)

         pMatList->mMaterials[j] = TextureHandle(pathName, MeshTexture, false);
      }
   }
}

You could also remove the function

static bool makeSkinPath(char* buffer, U32 bufferLength, const char* resourcePath,
                         const char* oldSkin, const char* oldRoot, const char* newRoot)
....

because its not longer needed with this modification.


Have fun ;)

#1
12/07/2007 (7:04 pm)
Excellent Resource - worked like a charm.
#2
12/09/2007 (8:11 am)
Bit confused by this resounce. It seems to break the existing behavior.
When I have a dts that uses two textures, e.g. a tank with base.turret.png and base.body.png, a call to the old setSkinName("green"); would use green.turret.png and green.body.png.
With this change the same call fails because it can't find a single texture "green.png".
What am I doing wrong? Thanks!