Solved Get all texture tags & show texture paths,but reflection channel throw error? :(

Hello guys,
It's been a while guys hope y'all okay.

I working on a small script, on getting all texture tags on object & show texture paths by printing out to the c4d console.
But the reflection channel throw error when I enable the code to run, It's like it don't want me to get the texture path.

CODE:

    import c4d, os, shutil
    from c4d import plugins, gui, bitmaps, documents, storage
    from os import path as p
    
    #Welcome to the world of Python
    
    def CopyPath_To_Path(path, tex_path, pastefolder):
        if ":\\" not in path:
           # Is in tex.
           Tex_path = tex_path + "\\tex\\" + path
           shutil.copy2(Tex_path, pastefolder)
           print Tex_path  
        else:
            # Not in tex.
            shutil.copy2(path, pastefolder)
            print path          
        return True
    
    def main():
        
        desk_folder = storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP)
        folder = os.path.join(desk_folder, "CopyTextures")
        if not p.exists(folder):
            os.mkdir(folder)
        
        doc = c4d.documents.GetActiveDocument()
        if doc == None:
            return False
        
        # Get Objects form the Object Manager     
        list_objs = doc.GetActiveObjects(1)
        if not list_objs:
            gui.MessageDialog("Select an Object!")
            return
        for E in list_objs:
            
            doc = c4d.documents.GetActiveDocument()
            
            ProjectTexPath = doc.GetDocumentPath()
    
            object_Tags = E.GetTags()
    
            for each_c4d_tag  in object_Tags:
                
                if each_c4d_tag.CheckType(c4d.Ttexture):
                    
                    get_t = each_c4d_tag[c4d.TEXTURETAG_MATERIAL]
                    makstr = str(get_t)
                    
                    # Get string by spliting a long string up.
                    str_1 = makstr.split("'")[1]
                    finalstr = str_1.split('/')[0]
                    
                    # Material Name
                    MatName = finalstr
                    
                    # Find Material
                    GetMat = doc.SearchMaterial(MatName)
                    
                    # Get Material
                    userMat = doc.GetActiveMaterial()
                    
                    # Get Material Shaders Texture Paths.
                    m_color = userMat[c4d.MATERIAL_COLOR_SHADER]
                    show_loc_path_Diff = m_color[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_Diff, tex_path=ProjectTexPath, pastefolder=folder)
                    
                    m_alpha = userMat[c4d.MATERIAL_ALPHA_SHADER]
                    show_loc_path_Alpha = m_alpha[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_Alpha, tex_path=ProjectTexPath, pastefolder=folder)
    
                    m_diffusion = userMat[c4d.MATERIAL_DIFFUSION_SHADER]
                    show_loc_path_diff = m_diffusion[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_diff, tex_path=ProjectTexPath, pastefolder=folder)
                    
                    m_lum = userMat[c4d.MATERIAL_LUMINANCE_SHADER]
                    show_loc_path_LM = m_lum[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_LM, tex_path=ProjectTexPath, pastefolder=folder)
    
                    m_nor = userMat[c4d.MATERIAL_NORMAL_SHADER]
                    show_loc_path_Nor = m_nor[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_Nor, tex_path=ProjectTexPath, pastefolder=folder)
                    
                    m_trans = userMat[c4d.MATERIAL_TRANSPARENCY_SHADER]
                    show_loc_path_Trans = m_trans[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_Trans, tex_path=ProjectTexPath, pastefolder=folder)
                    
                    m_enviro = userMat[c4d.MATERIAL_ENVIRONMENT_SHADER]
                    show_loc_path_enviro = m_enviro[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_enviro, tex_path=ProjectTexPath, pastefolder=folder)
                    
                    m_bump = userMat[c4d.MATERIAL_BUMP_SHADER]
                    show_loc_path_bump = m_bump[c4d.BITMAPSHADER_FILENAME]
                    CopyPath_To_Path(path=show_loc_path_bump, tex_path=ProjectTexPath, pastefolder=folder)
                    
                    #----------------------------------------------------------------#
                    # THE PROBLEM HERE WHEN I ENABLE IT.
                    #m_spec = userMat[c4d.MATERIAL_REFLECTION_SHADER]
                    #show_loc_path_Spec = m_spec[c4d.BITMAPSHADER_FILENAME]
                    #print show_loc_path_Spec
                    #----------------------------------------------------------------#
    
        c4d.EventAdd()       
                    
    if __name__=='__main__':
        main()

Error in the Console:
alt text

TypeError: 'NoneType' object has no attribute 'getitem'

tips on this would be great.
cheers,
Ashton:white_frowning_face:

Hi @Ashton_FCS_PluginDev, we are glad to see you back in the new plugincafe community!
No worries at all since it's your first post here, but please make sure to read and apply the rules defined on the following topics:

Regarding your issue, you read m_spec, but you never check if there is a bitmashader in it or not. And in your case, there is no, so m_spec is set to None, and you are then trying to access value.
So please always check for None.
Then since you directly read the BITMAPSHADER_FILENAME parameter from this shader, please also consider to check the shader type you retrieve, maybe a user used a noise and not a bitmap.

m_spec = userMat[c4d.MATERIAL_REFLECTION_SHADER]
if not m_spec or m_spec.CheckType(c4d.Xbitmap):
    continue

Finally, as you may already be aware, reflection gets multiple layers. You get some information in this thread, how to deal with it.

If you have any others question, please let me know!
Cheers,
Maxime.

Hi @Ashton_FCS_PluginDev, we are glad to see you back in the new plugincafe community!
No worries at all since it's your first post here, but please make sure to read and apply the rules defined on the following topics:

Regarding your issue, you read m_spec, but you never check if there is a bitmashader in it or not. And in your case, there is no, so m_spec is set to None, and you are then trying to access value.
So please always check for None.
Then since you directly read the BITMAPSHADER_FILENAME parameter from this shader, please also consider to check the shader type you retrieve, maybe a user used a noise and not a bitmap.

m_spec = userMat[c4d.MATERIAL_REFLECTION_SHADER]
if not m_spec or m_spec.CheckType(c4d.Xbitmap):
    continue

Finally, as you may already be aware, reflection gets multiple layers. You get some information in this thread, how to deal with it.

If you have any others question, please let me know!
Cheers,
Maxime.

Thank you m_adam! And for the advice. :relaxed:
Everything works fine, and no error.
But Maxon needs to add some of the C++ api sdk to the python api sdk. Cause I had to research for the (REFLECTION_LAYER types ) and they was in c++ sdk so I hope maxon think about this, cause it a lot of up and down lol.

The fix and working code:

            # Get Reflection or Spec map texture from the Reflectance Channel.
            m_spec = userMat.GetReflectionLayerCount()
            for each_layer in xrange(0, m_spec):  
                getlayer = userMat.GetReflectionLayerIndex(each_layer)
                get_spec = userMat[getlayer.GetDataID() + c4d.REFLECTION_LAYER_COLOR_TEXTURE]
                if not get_spec or get_spec.CheckType(c4d.Xbitmap):
                    print " No bitmap apply in this channel. "
                    pass
                else:
                    show_loc_path_Spec = get_spec[c4d.BITMAPSHADER_FILENAME]
                    print show_loc_path_Spec

For anyone who would like to use or learn from the script. You can download full script from github. ( Get And Copy Textures From Texture Tags )

Thanks again and Cheers,
Ashton,
Love new plugincafe forum!

For anyone who would like to use or learn from the script. You can download full script from github. ( Get And Copy Textures From Texture Tags )