Start a new topic

texture index reset

I am working on a script that checks a polygons for a texture ,then the name, if it has a material, if not creates it and applies it to the polygon.

so this worked fine on the flt file I made and created the script with, but say the next file has a texture in it that has an index already (say 256) 

can the texture index in the texture palette be reset to 0 before the rest of the script is run?

Im actually kinda proud of myself that I got this thing working and boom, next file, no workie.....

I was told it could take days to weeks to get the file to this box and post here. I will have to type it out.

typing it out now while waiting for some input here.

Hi John,

I'm confused as to what you are trying to do. Are you just applying materials to polygons that have texture? If so, is the material special?  Is it extended material perhaps and you are applying the texture to the material?

I'm just confused as to why you would want to change a texture's index in the texture palette. 

the overall goal of this script was to create an extended material, add it to the polygon with the same name and index. 

what I want to do later with this is to maybe copy the texture palette, name textures with ###_spec...###_bump and apply them to the matching texture layers. So I could atleast have the _spec..._bump in the txt folder to work on at a later date. 

we dont have alot of unity work at the moment but I do try to attach a unity build to some deliveries and hope someone comes across it. However alot of the stuff i doing with scripts is getting ready for future work...

to save some typing time, I only listed the first two extended materials(mat0, mat1) the script goes to 9(total of 10 textures)

for one, i didnt want to use the mgGetTextureSaveName since we save our paths  relative to database. but it got me a shorter filename for when i create the material and name it the texture name. i get rid or the rgb, with the split(kinda stumbled across that and went with it.) id prefer to figure out how to just use the GetTextureName and delte all the path info and the file extension, leaving the texture name only.

db = mgGetCurrentDb()

def makeExMat(db,rec,parent,userData):

        b,index,name = mgGetTexture(db)

        mat0,matIndex = mgNewMaterial(db,"mat0")

        savenamea = mgGetTextureSaveName(db,0)

        savename = savenamea.split ('.') [0]

        b,index1,name1 = mgGetTexture(db)

        mat1,matIndex = mgNewMaterial(db,"mat1")

        savenameb = mgGetTextureSaveName(db,1)

        savename1= savenameb.split ('.') [0]

        mgSetAttList (mat0, fltMatType, 1, fltMatShadeModel, 1, fltMatName, savename)

        mgSetAttList (mat1, fltMatType, 1, fltMatShadeModel, 1, fltMatName, savename1)

        mgSetNormColor( mat0, fltDiffuseExColor, 1.0, 1.0, 1.0)

        mgSetTextureLayer( mat0, fltDiffuseEx, index, 0)

        mgSetNormColor( mat1, fltDiffuseExColor, 1.0, 1.0, 1.0)

        mgSetTextureLayer( mat1, fltDiffuseEx, index1, 1)

mgWalk (db, makeExtMat, None, None, MWALK_NONESTED)

##Tex and mat list###

def MatchNodeType(db,parent,rec,userData):

        if (mgGetCode (rec) == userData):

                return MG_TRUE

        return MG_TRUE

def texIndexList(db,rec,parent,userData):

        usedTexturesList [ ]

        code = fltPolygon

        polyTXNodes = mgFind ( db, MatchNodeType, code, 0)

        numPoly = mgGetRecListCOunt (polyTXNodes)

        for i in range (0, numPoly):

                rec, matrix = mgGetNextRecInList (polyTXNodes)

                nodeName = mgGetName(rec)

                numAttr, texIndexCode, texIndex = mgGetAttList(rec, fltPolyTexture)

                usedTexturesList.append (texIndex)

                numAttrs, matIndexCode, matIndex = mgGetAttList(rec, fltPolyMaterial)

                if matIndex != texIndex:

                        applymat = mgSetAttList(rec, fltPolyMaterial, texIndex)

mgWalk (db, texIndexList, None , None, MWALK_NONESTED)

didnt see an edit button.

i have the above script working in the file that was made for it, but when i go to a different file, and the texture palette does has random numbers instead of starting from 0. The script was made for this to be the case. Again, im suprised it worked at all. Im learning little by little

hrmm, just stumbled across make surface maps.. pretty much what im going after

thinking about it, the script should work no matter what the texture index is...

i cant even get it to work on the same file setup that i built it off of

Hey John,

You did quite good for a first attempt! I notice some odd things that need to be fixed. The first one is the use of the function mgGetTexture()

This isn't actually a function in the API. We allow you to get a texture if you know the index. We also allow you to get the first texture in the db and then loop through all the textures. I think if you modified that first function to check the texture index on the rec (after making sure it was a polygon) then getting the texture at that index, you would have better results. Probably more changes needed after that.  In any case, I wrote a script a while back to convert from standard material and texture on layers into an extended material. Check it out below and see if it is useful.


db = mgGetCurrentDb()

#Set the following values to the polygon texture layers to find the data
#Use -1 to turn off a feature
#Diffuse and Ambient are always set
AlphaLayer      = 0
SpecularLayer   = 3
LightMapLayer   = 7
BumpLayer       = -1
EmissiveLayer   = -1
ShadowMapLayer  = -1

def GetTextureLayerCode (layer):
   if layer == 0:
      return fltPolyTexture
   if layer == 1:
      return fltLayerTexture1
   if layer == 2:
      return fltLayerTexture2
   if layer == 3:
      return fltLayerTexture3
   if layer == 4:
      return fltLayerTexture4
   if layer == 5:
      return fltLayerTexture5
   if layer == 6:
      return fltLayerTexture6
   if layer == 7:
      return fltLayerTexture7
   return -1
processedMaterials = {} # define an empty dictionary to hold our texturename to material mapping

def ReplaceExtension (filename, newextension):
   index = filename.rfind('.')
   newstr = filename[:index] + newextension
   return newstr

# A way to detect if a texture exists on disk without using os.path
def TextureExists (name):
   status, type, width, height = mgReadImageHeader (name)
   if (width != None):
      return True
   return False

# converts a diffuse texture name into the material texture name using our convention
# looks to see if the material texture name is already loaded into our palette
# if it does not find the material texture name in the palette, it checks to see if it exists on disk
# if it exists on disk, it will load the texture and return the index
# else it will return -1
def FindPhysicalMaterialIndex (diffuseTexName):
   materialname = ReplaceExtension (diffuseTexName, "_mat.tif")
   mattexidx = mgGetTextureIndex (db, materialname)
   if (mattexidx < 0 and TextureExists(materialname)):
      mattexidx = mgInsertTexture (db, materialname)
   return mattexidx
# for each polygon, we check to see if there is an extended material applied
# if an extended material is applied, then we check to see if the base layer diffuse texture has
# a physical material texture. if it does, then we write it to the correct techniqe
# if there is no extended material, we check to see if the base laye rtexture has already been processed
# if we already processed that texture, we simply assign the extended material we created for that texture
# if it has not been processed, we check to see if the diffuse texture has an physical material map on disk
# if it does, then we create a new extended materail and set it up with the diffuse and physical material map
# then store the resulting material we created in our processed dictionary
def ProcessNode (db, parent, rec, i):
   global processedMaterials
   if (mgGetCode (rec) == fltPolygon):      
      ok, code, matidx = mgGetAttList (rec, fltPolyMaterial)
      matrec = mgGetMaterial (db, matidx)
      ok, code, isExtended = mgGetAttList (matrec, fltMatType)
      if (isExtended):
         # make sure this material contains our physical material data
         ok, diffusetexidx, diffusetexlayer = mgGetMatTextureLayer (matrec, fltDiffuseExLayer1)
         if (diffusetexidx > -1):
            ok, ambientidx, ambienttexlayer = mgGetMatTextureLayer (matrec, fltAmbientExLayer1)
            if(ambientidx == -1):
               mgSetMatTextureLayer(matrec, fltAmbientExLayer1, diffusetexidx, 0)
            name = mgGetTextureName (db, diffusetexidx)
            mattexidx = FindPhysicalMaterialIndex (name)
            if (mattexidx > -1):
               mgSetMatTextureLayer (matrec, fltPhysicalMaterialMapExTexture, mattexidx, diffusetexlayer)
         #not extended, so check to see if we created a material for this polygon's texture yet
         ok, code, diffusetexidx = mgGetAttList (rec, fltPolyTexture)
         if (diffusetexidx > -1):
            name = mgGetTextureName (db, diffusetexidx)
            destmatidx = -1
            if (diffusetexidx in processedMaterials.keys()):
               destmatidx = processedMaterials[diffusetexidx]
               newmat, destmatidx = mgNewMaterial (db, "")
               mgSetNormColor (newmat, fltAmbient, 0.71875,0.71875,0.71875)
               mgSetNormColor (newmat, fltDiffuse, 0.9140625,0.9140625,0.9140625)
               processedMaterials[diffusetexidx] = destmatidx
               mgSetAttList (newmat, fltMatType, 1) # sets type to extended material
               mgSetAttList (newmat, fltMatShadeModel, 1) # sets Shade Model to Per Vertex Phong 
               mgSetNormColor (newmat, fltAmbientExColor, 0.71875,0.71875,0.71875)
               mgSetNormColor (newmat, fltDiffuseExColor, 0.9140625,0.9140625,0.9140625)
               mgSetMatTextureLayer(newmat, fltDiffuseExLayer1, diffusetexidx, 0)
               mgSetMatTextureLayer(newmat, fltAmbientExLayer1, diffusetexidx, 0)
               if AlphaLayer >= 0:
                  ok, code, alphatexidx = mgGetAttList (rec, GetTextureLayerCode(AlphaLayer))
                  mgSetMatTextureLayer(newmat, fltAlphaExLayer1, alphatexidx, AlphaLayer)
               if BumpLayer >= 0:
                  ok, code, texidx = mgGetAttList (rec, GetTextureLayerCode(BumpLayer))
                  mgSetMatTextureLayer(newmat, fltBumpMapExTexture, texidx, BumpLayer)

               if SpecularLayer >= 0:
                  ok, code, texidx = mgGetAttList (rec, GetTextureLayerCode(SpecularLayer))
                  mgSetMatTextureLayer(newmat, fltSpecularExLayer1, texidx, SpecularLayer)
               if EmissiveLayer >= 0:
                  ok, code, texidx = mgGetAttList (rec, GetTextureLayerCode(EmissiveLayer))
                  mgSetMatTextureLayer(newmat, fltEmissiveExLayer1, texidx, EmissiveLayer)
               if LightMapLayer >= 0:
                  ok, code, texidx = mgGetAttList (rec, GetTextureLayerCode(LightMapLayer))
                  mgSetMatTextureLayer(newmat, fltLightMapExTexture, texidx, LightMapLayer)
               if ShadowMapLayer >= 0:
                  ok, code, texidx = mgGetAttList (rec, GetTextureLayerCode(ShadowMapLayer))
                  mgSetMatTextureLayer(newmat, fltShadowMapExTexture, texidx, ShadowMapLayer)
            mgSetAttList (rec, fltPolyMaterial, destmatidx)
   return MG_TRUE

# use the line below instead of the one below it to enable the script to work only on visible polygons 
# mgWalk (db, ProcessNode, None, None, MWALK_ON)
mgWalk (db, ProcessNode, None, None, 0)


thank you. i find it weird that my script wont work on anything but the file I was using while testing it. Another file, no go. Same file, replacing 1 or two textures with something else, no go. But put back the original textures, boom it works.

can the api access the make surface maps under edit in the texture palette?

i will see what I can come up with using tex index searches instead of get texture

looking at your reply, i was wondering what you were talking about with mgGetTexture. i did finally notice that i didnt type the line correctly in the post but it was mgGetFirstTexture in my script.

"can the api access make surface maps"

Unfortunately no. That tool must be run with Creator's UI

"i find it weird that my script wont work on anything but the file I was using while testing it"

Yes that is very strange. I have no idea why that would be

"i was wondering what you were talking about with mgGetTexture"

I thought the whole script would never do anything because of the mgGetTexture typo, but if you were using mgGetFirstTexture that would do something. What I was suggesting is instead of just getting the first texture, get the texture index from the rec, then get the texture it uses. This prevents the need to modify what index a texture is stored at in the palette, so it would make things much more simple.

'I thought the whole script would never do anything because of the mgGetTexture typo'

yeah it runs through fine and creates the materials with the texture name, assigns it to the polygons. It was a holy shit moment when it just ran and did everything I wanted it to....then it didnt. i see its definitely an index issue.


just for clarity, im having a hard time understanding outs[]...

does outs[0] mean rec

polyHidden = outs[2] . does this mean it has two options, like off/on? 0/1

and I really dont understand if numAttr == 1

def chkHiddenFace(rec):

        nodeName = mgGetName(rec)

        outs = mgGetAttList(rec, fltPolyHidden)

        numAttr = outs[0]

        polyHidden = outs[2]

        if (numAttr ==1):

                if (polyHidden == 1):


this is a Python thing. Basically functions in python can return multiple variables. When calling a function, you can collect all the returns into a list:

outs = mgGetAttList(rec, fltPolyHidden)

numAttr = outs[0]

fltCodeAskedFor = outs[1]

polyHidden = outs[2]

or you can assign them directly to variables

numAttr, fltCodeAskedFor, hidenState = mgGetAttList(rec, fltPolyHidden)

Both of these are identical, but the first one allows you to be a little more safe. for instance, if you were asking for a texture index and you were asking for it from a group node, the first one would return a 0 in outs[0]. You can use this to make your code not crash. The second one would fail and produce an error saying unable to unpack or something like that.

The fact that outs[1] contains the code you passed in might seem a little strange. This is there because you can ask for any number of codes in the same call.

outs = mgGetAttList (rec, fltPolyTexture, fltPolyHidden, ...)

If you ask for 4 attributes, outs[0] will be 4. You can use this to check to make sure everything is working properly. If you asked for 4 codes, and only 3 were returned, then you need the outs[2] to know what data is contained in outs[3]

thank you for the explanation. i think i understand

Login to post a comment