Getting the texture path for the active material

How to get the texture path from each material into a string?


For example, Material 1 is assigned 1 texture, which is red, Material 2 is assigned 2 textures, etc.


You can get the path from 1 texture.
изображение

impb = bpy.data.images[“1.png”].filepath
I assign this to a variable.

imp = context.object.imp = impb
I output it through the string property.

For 2nd material it won’t be the same.

A material can’t be assigned a texture. A material node tree can contain, zero, one or more image texture nodes, which can have a texture assigned. But textures are never directly assigned to the material. If you want to list all of the textures inside a material node tree, you can iterate over all nodes and test their type. Something like that

from collections import defaultdict
import bpy

material_textures = defaultdict(list)

for material in bpy.data.materials:
    if not material.use_nodes:
        continue
    for node in material.node_tree.nodes:
        if not(isinstance(node, bpy.types.ShaderNodeTexImage)):
            continue
        if not node.image:
            continue
        material_textures[material.name].append(node.image.filepath)

# This will print a dictionary with material names as a key and texture filepaths as values
print(material_textures)

BTW you can code however you want for yourself. However if you plan on sharing your code or asking for help, I suggest you follow the PEP-8 python guidelines for coding in python. It will make potential helpers more eager to contribute, and you’ll have a better time extending your script. In your case I would suggest you to name your variables consistently, and avoid chaining equal statements, they are confusing with non-trivial assignments.

Cheers

2 Likes


Thank you. Everything works now.
It makes a copy of the file that is assigned to the material in the specified folder when you click on the button.
I corrected the names of the variables to make them more readable.

As I understand it, he does the enter correctly after the conditions or cycles?


I kind of understood how it was built. This is where we access through this code.

Exactly, here are some API links you might find useful

https://docs.blender.org/api/current/bpy.types.Material.html

https://docs.blender.org/api/current/bpy.types.NodeTree.html

https://docs.blender.org/api/current/bpy.types.Nodes.html

https://docs.blender.org/api/current/bpy.types.ShaderNodeTexImage.html

In human language, you check every material in the file, if they have a node tree, you check every node of their node tree, if the node is a texture image node, you check if they have a texture assigned, and if they do, you add the texture image filepath to the dictionary to map it to the material it belongs to.


please tell me how to raise the list in the console? I don’t see the list above.

What are you looking for ? This is a list of panel classes definitions


I’m trying to understand the logic behind how this all works.
For example, here he tells me that this is class.

If I register bpy.types.UILayout.
I see base class methods.
How can I see everything that is specified in the API?

  1. Please explain this point to me again.
    Why the code doesn’t work.
import gr
gr.myfunction

Where gr is the name of gr.py in the addon folder.
This is essentially a function file. There is such an option in the Python instructions.

if "bpy" in locals():
    import importlib
    if "import_fbx" in locals():
        importlib.reload(import_fbx)
    if "export_fbx_bin" in locals():
        importlib.reload(export_fbx_bin)
    if "export_fbx" in locals():
        importlib.reload(export_fbx)

I saw how it was done in the standard. For example in fbx.
I found this code.
This part is required.

from . import export_fbx_bin

Now the most incomprehensible part. Why does it only work with a period after from?
I did the same but replaced the name with my gr and then everything works.

from  import export_fbx_bin

Why can’t I do this?

I suggest you familiarize yourself a bit more with the python import system. ‘import module’ imports a top level module, ‘from . import module’ will import a module relatively to the file that is currently executed. ‘from . . import module’ will go to the parent directory to fetch the module. Every dot you add will go one level higher in the hierarchy

import win32gui

They write about this module on the forums. It helps manage the system interface or windows.
How to connect it to a blender?
win32gui-221.6-cp36-cp36m-win_amd64.whl (3.1 MB)

Found some file where to paste it?

Again, I kindly suggest you to try to get your hand on a crash course about python, this should be covered in the import section. You need to install win32gui in your local Blender environment. You can do it by running this in a text editor

import subprocess
import sys
from pathlib import Path

py_exec = str(sys.executable)
# Get lib directory
lib = Path(py_exec).parent.parent / "lib"
# Ensure pip is installed
subprocess.call([py_exec, "-m", "ensurepip", "--user" ])
# Update pip (not mandatory)
subprocess.call([py_exec, "-m", "pip", "install", "--upgrade", "pip" ])
# Install packages
subprocess.call([py_exec,"-m", "pip", "install", f"--target={str(lib)}", "win32gui"])

Source

https://blender.stackexchange.com/questions/5287/using-3rd-party-python-modules

1 Like

Thanks a lot. At the same time, I’m also reading about working in Python itself. And I’m already practicing getting something into the blender. I also make notes on parts of the code and keywords or algorithms.
Parts of the code can be thrown into templates and then quickly retrieved from there. This is what I did with the package installation code.

To be honest, I only don’t like 2 things.
1 these code blocks are not separated by brackets like in Java or C++, etc.
2 There is a real lack of auto-substitution in the editor in blender itself.
At least the blender API.
This can be done in visual studio code.
Point 2 is not convenient for me because you can get used to point 1 and accept it as a feature of the language.

This is such a useful thing.

1 Like
def materiallist(self,context):
    mat_items = []
    for mat in bpy.data.materials:
         mat_items.append((mat.name, mat.name, "", 1))
    return  mat_items

Why can I only select 1 material from the list?
I want every material to be selected.