7

Part of my addon's functionality is to replace local materials with their counterparts in linked libraries / assets.

In order to check if a material of the same name as a local material is available as an asset in the asset browser, I need some way to iterate through all assets of a given UserAssetLibrary and check for matches.

Unfortunately, I've not been able to find a method to get all assets contained in a UserAssetLibrary so far. After browsing the Data API it also doesn't seem like those are stored anywhere in the current BLEND file in the first place.

I suspect that since the asset browser seems to be a version of the file browser, I need to instead look into methods of getting a list of all files listed in the file browser. What I've found there has mostly been about finding the selcted file(s) though, not all files.

see:

Part of the function where this would be used below. Currently it only checks for linked files, but assets in the browser do not show up as materials in bpy.data.materials, and as such I cannot check for matches.

        for slot in obj.material_slots:
            if slot.material is not None and slot.material.library is None:
                old_material = slot.material
                new_material = None
            for mtl in bpy.data.materials:
                # If an object is imported that has a material that already exists in the scene, it is numbered.
                # Thus checking the substring of the name is necessary to catch all of them.
                if mtl.library != None and ( mtl.name == old_material.name or mtl.name == old_material.name[:-4] ) and old_material.seut.overrideMatLib == False:
                    new_material = mtl
                    break                            

            if new_material != None:
                slot.material = new_material
                if old_material not in mtl_to_delete:
                    mtl_to_delete.append(old_material)

Gorgious
  • 30,723
  • 2
  • 44
  • 101
enenra
  • 71
  • 2

2 Answers2

2

The asset libraries are stored in the preferences filepaths. Preferences are accessed with the current context.

An User Asset Library object holds the name of the library and the path to its root directory.

You can load the contents with bpy.data.libraries.load and the argument assets_only=True to filter only assets. Thanks to viktor for pointing it out.

import bpy
from pathlib import Path

prefs = bpy.context.preferences filepaths = prefs.filepaths asset_libraries = filepaths.asset_libraries

for asset_library in asset_libraries: library_name = asset_library.name library_path = Path(asset_library.path) blend_files = [fp for fp in library_path.glob("*/.blend") if fp.is_file()] print(f"Checking the content of library '{library_name}' :") for blend_file in blend_files: with bpy.data.libraries.load(str(blend_file), assets_only=True) as (file_contents, _): # Note this will print out the names of the objects, # Not the actual objects print(file_contents.objects) print(file_contents.materials) print(file_contents.worlds) # etc.

Gorgious
  • 30,723
  • 2
  • 44
  • 101
2

When you are loading a library with bpy.data.libraries.load(str(blend_file)), you can use assets_only=True keyword in order to load only assets instead of all contents.

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187