4
$\begingroup$

Similar to Python : Get selected objects in outliner

How can one access the assets that are currently selected in the asset browser editor using the python API ?

I assume it should be available on a per-editor basis since, contrary to the outliner where selection state is shared between all editors, different asset browser editors can have different asset selection states :

enter image description here

$\endgroup$
8
  • $\begingroup$ i cannot even find the "right" area type 😱 TypeError: bpy_struct: item.attr = val: enum "ASSET_BROWSER" not found in ('EMPTY', 'VIEW_3D', 'IMAGE_EDITOR', 'NODE_EDITOR', 'SEQUENCE_EDITOR', 'CLIP_EDITOR', 'DOPESHEET_EDITOR', 'GRAPH_EDITOR', 'NLA_EDITOR', 'TEXT_EDITOR', 'CONSOLE', 'INFO', 'TOPBAR', 'STATUSBAR', 'OUTLINER', 'PROPERTIES', 'FILE_BROWSER', 'SPREADSHEET', 'PREFERENCES') $\endgroup$ Commented Jan 11, 2022 at 16:38
  • $\begingroup$ have a look at startup/bl_operators/assets.py. It looks like you need something like active_asset = SpaceAssetInfo.get_active_asset(context) There only seems to be the concept of active and not selected? $\endgroup$ Commented Jan 11, 2022 at 16:50
  • $\begingroup$ @Chris Yeah it's not .type it's .ui_type... was fooled by it too ! $\endgroup$ Commented Jan 11, 2022 at 18:53
  • 1
    $\begingroup$ The quote from the docs: "Avoid using this, it will be replaced..." made my day :D $\endgroup$ Commented Feb 3, 2022 at 11:36
  • 1
    $\begingroup$ @brockmann Fast forward in 5 years when this quote is still there in the docs... xD $\endgroup$ Commented Feb 3, 2022 at 13:00

2 Answers 2

8
$\begingroup$

Blender 4.0+

Blender 4.0 introduces bpy.types.AssetRepresentation, bpy.context.selected_assets, bpy.context.asset we can use to our advantage.

import bpy class PrintSelectedAssets(bpy.types.Operator): bl_idname = "asset.print_selected_assets" bl_label = "Print Selected Assets" @classmethod def poll(cls, context): return context.selected_assets def execute(self, context): for asset_representation in context.selected_assets: print(f"{asset_representation.full_path=}") print(f"{asset_representation.full_library_path=}") print(f"{asset_representation.id_type=}") print(f"{asset_representation.name=}") # This will be None if the asset is not located in current file : print(f"{asset_representation.local_id=}") print(context.asset) # Active asset return {"FINISHED"} def display_button(self, context): self.layout.operator(PrintSelectedAssets.bl_idname) def register(): bpy.utils.register_class(PrintSelectedAssets) bpy.types.ASSETBROWSER_MT_editor_menus.append(display_button) def unregister(): bpy.types.ASSETBROWSER_MT_editor_menus.remove(display_button) bpy.utils.unregister_class(PrintSelectedAssets) if __name__ == "__main__": register() 

Blender 3.6

I found the answer while researching another answer.

It's actually an attribute of File context which unless I'm mistaken does require the piece of code to be executed inside the context of the asset browser.

Here's the slightly altered script that adds a button in the Asset Browser header that, when clicked, outputs some information about the selected assets in the console :

import bpy from pathlib import Path class PrintSelectedAssets(bpy.types.Operator): bl_idname = "asset.print_selected_assets" bl_label = "Print Selected Assets" @classmethod def poll(cls, context): return context.selected_asset_files def execute(self, context): current_library_name = context.area.spaces.active.params.asset_library_ref if current_library_name != "LOCAL": # NOT Current file library_path = Path(context.preferences.filepaths.asset_libraries.get(current_library_name).path) for asset_file in context.selected_asset_files: if current_library_name == "LOCAL": print(f"{asset_file.local_id.name} is selected in the asset browser. (Local File)") else: asset_fullpath = library_path / asset_file.relative_path print(f"{asset_fullpath} is selected in the asset browser.") print(f"It is located in a user library named '{current_library_name}'") return {"FINISHED"} def display_button(self, context): self.layout.operator(PrintSelectedAssets.bl_idname) def register(): bpy.utils.register_class(PrintSelectedAssets) bpy.types.ASSETBROWSER_MT_editor_menus.append(display_button) def unregister(): bpy.types.ASSETBROWSER_MT_editor_menus.remove(display_button) bpy.utils.unregister_class(PrintSelectedAssets) if __name__ == "__main__": register() 
$\endgroup$
2
  • $\begingroup$ context should be the context of the asset browser? context.selected_assets won't work out of that context I think $\endgroup$ Commented Mar 10, 2024 at 12:14
  • 1
    $\begingroup$ @NoobCat well, yes, because you can have multiple asset browsers open at the same time with different selection states $\endgroup$ Commented Mar 11, 2024 at 9:35
4
$\begingroup$

How to get it from the window area

>>> bpy.context.screen.areas[3].spaces.active.params.filename 'geometry_nodes\\procedural_hair_node_assets.blend\\NodeTree\\Braid Hair Curves' 

enter image description here

If the asset browser area on the window has been identified, it is useful to learn the information from the console.

In the example, it is "bpy.context.screen.areas[3]".

but the number will vary depending on the environment.

The area can be identified

by https://github.com/Pullusb/devTools

which is an add-on that provides a convenient button on the console.

enter image description here

Acquire information via operator

We already have the code for the answer, but some of the context data accesses have "mechanisms that can only be accessed via the operator".

For example, the following access is only accessible on the operator and not in the area

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

Therefore, it is necessary to set up an access button in the area from which to obtain the divestment. Of course, if you place this button anywhere other than on the asset browser, it will not work.

import bpy from pathlib import Path # breakpoint = bpy.types.BP_PT_bp.bp class PrintSelectedAssets(bpy.types.Operator): bl_idname = "asset.print_selected_assets" bl_label = "Print Selected Assets" @classmethod def poll(cls, context): return context.selected_asset_files def execute(self, context): for asset in context.selected_asset_files: asset_re_path=asset.relative_path print("### asset path :",asset_re_path) return {"FINISHED"} def display_button(self, context): self.layout.operator(PrintSelectedAssets.bl_idname) def register(): bpy.utils.register_class(PrintSelectedAssets) bpy.types.ASSETBROWSER_MT_editor_menus.append(display_button) def unregister(): bpy.utils.unregister_class(PrintSelectedAssets) bpy.types.ASSETBROWSER_MT_editor_menus.remove(display_button) if __name__ == "__main__": register() 

enter image description here

enter image description here


For blender4.0

There seems to have been a change in the API. The following are the changes

From selected_asset_files

To selected_assets

https://docs.blender.org/api/current/bpy.context.html#bpy.context.selected_assets

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

import bpy from pathlib import Path class PrintSelectedAssets(bpy.types.Operator): bl_idname = "asset.print_selected_assets" bl_label = "Print Selected Assets" @classmethod def poll(cls, context): return context.selected_assets def execute(self, context): for asset in context.selected_assets: asset_path=asset.full_path print("### asset :",asset_path) return {"FINISHED"} def display_button(self, context): self.layout.operator(PrintSelectedAssets.bl_idname) def register(): bpy.utils.register_class(PrintSelectedAssets) bpy.types.ASSETBROWSER_MT_editor_menus.append(display_button) def unregister(): for f in bpy.types.ASSETBROWSER_MT_editor_menus._dyn_ui_initialize(): if f.__name__ == display_button.__name__: bpy.types.ASSETBROWSER_MT_editor_menus.remove(f) return if __name__ == "__main__": unregister() register() 
$\endgroup$
2
  • $\begingroup$ It works, but how to get all selected assets? It return only one (the last)... $\endgroup$ Commented Dec 27, 2023 at 13:44
  • 1
    $\begingroup$ @Bicukow I have made an addition to my answer. Please check it. $\endgroup$ Commented Dec 28, 2023 at 22:00

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.