4

I have this script, but its not working as expected

import bpy

for img in bpy.data.images:
    print("%s" % img.name)
    if( ".0" in img.name):
        img.name=img.name[:-4]
        print("%s" % img.name)

I want to have one texture on different materials, now i have something like this enter image description here

Edit: Solved.

for mat in bpy.data.materials:
    if mat.node_tree:
        for n in mat.node_tree.nodes:
            if n.type == 'TEX_IMAGE':
                if n.image is none:
                    print(mat.name,'has an image node with no image')
                elif n.image.name[-3:].isdigit():
                    n.image = bpy.data.images[n.image.name[:-4]]

for imgs in bpy.data.images:
    if imgs.name[-3:].isdigit():
        print(imgs.name)
        imgs.user_clear()

Thanks to all who helped. ok!

r3aktormk
  • 83
  • 6
  • 1
    what are expecting ? you are just renaming the images ( they won't have the same name blender will add the numbers back ) – Chebhou Jan 31 '16 at 21:44
  • I'm fairly new to python, but you should probably not try to rename the textures but to reload Tex.Generic_Spec.png if Image Texture File has a number in the materials. – maegmaeg Jan 31 '16 at 21:52
  • 1
    PProbably this related topic gives you some idea how to do it: http://blender.stackexchange.com/questions/38052/how-can-i-make-a-script-to-make-cycles-load-a-new-texture-each-frame – maegmaeg Jan 31 '16 at 22:06

2 Answers2

6

img.name=img.name[:-4] is renaming the image to match the original image name, as this name already exists a numeric suffix is added to the other image with that name, which just undoes the change.

You need to go through your material nodes and get each image node to use the same image.

for mat in bpy.data.materials:
    if mat.node_tree:
        for n in mat.node_tree.nodes:
            if n.type == 'TEX_IMAGE':
                if n.image is None:
                    print(mat.name,'has an image node with no image')
                elif n.image.name[-3:].isdigit():
                    n.image = bpy.data.images[n.image.name[:-4]]

Note that the last line doesn't just change the name used, it changes the image data block that the image node is linked to.

Once you have removed the users of the duplicate images they will be removed after you save and re-open the file.

batFINGER
  • 84,216
  • 10
  • 108
  • 233
sambler
  • 55,387
  • 3
  • 59
  • 192
  • 1
    Is 'if n.type == 'TEX_IMAGE' and '.0' in n.image.name:' sufficent to find only the image textures mentioned? – maegmaeg Feb 01 '16 at 11:52
  • 1
    That will find all image texture nodes that use an image with '.0' in the name, using the same example test from your code. if n.type == 'TEX_IMAGE' and n.image.name[-3:].isdigit() should be a more accurate test. It does assume that bpy.data.images[n.image.name[:-4]] actually exists. – sambler Feb 01 '16 at 12:21
  • It works! on the test scene i had, but not on my real scene, n.image.name[-3:] returns "NoneType" – r3aktormk Feb 02 '16 at 02:52
  • 1
    if n.image.name[-3:] returns NoneType then you don't have an image on that node. – sambler Feb 02 '16 at 04:08
  • Suggest adding a filepath test too, for the same image filename, different folder side case. (and for generated images?). Making a lookup / replacement table from bpy.data.images to start with could be the go. – batFINGER Jul 24 '18 at 17:31
0

The solution posted above bugs out in several situations. always have to check if data exists before pulling it, also if the original image has digits then remove it.

# for material check for texture nodes
# if it has a digit check if the original exists
# if original has also digits remove

for mat in bpy.data.materials: if mat.node_tree: for n in mat.node_tree.nodes: if n.type == 'TEX_IMAGE': if n.image is None: print(mat.name,'has an image node with no image') elif n.image.name[-3:].isdigit(): name = n.image.name[:-4] exists = False for img in bpy.data.images: if img.name in name: exists = True if exists: n.image = bpy.data.images[name] else: n.image.name = name