Is there a way to batch add objects/materials to the asset browser? I have a fair number of various assets that I'd love to add to take advantage of the new browser, but they're all individual blend files. At the moment, I'm having to open each one individually, mark as asset, close, repeat. It's very tedious and would appreciate a way to speed up this process. Any tips or workarounds?
1 Answer
Goody it just so happens that I have just finished coding such tool yesterday :)
How to use :
OR
Then,
Go to File > Import > Batch generate asset previews
Navigate to a folder containing your blend files. Validate. It will automatically scan all the child folders recursively and mark all the objects as assets, and generate custom previews for them. Be warned that it will take something like 2 seconds per file to generate the assets and previews. It is because the previews are not instantly generated, and the thread generating them must finish before closing the file.
Here's the code that you can run as a script or install as an add-on :
bl_info = {
"name": "Batch Generate Asset Browser Previews ",
"author": "Gorgious",
"description": "Batch generate default previews for the Asset Browser from selected folder",
"blender": (3, 0, 0),
"version": (0, 0, 2),
"location": "",
"warning": "",
"category": "Import-Export",
}
from pathlib import Path
import bpy
import functools
from bpy_extras.io_utils import ImportHelper
from bpy.props import StringProperty
from bpy.types import Operator
INTERVAL = 1.0
class ASSET_OT_batch_generate_previews(Operator, ImportHelper):
bl_idname = "asset.batch_generate_previews"
bl_label = "Batch Generate Asset Previews"
filter_glob: StringProperty(
default="",
options={"HIDDEN"},
maxlen=255, # Max internal buffer length, longer would be clamped.
)
recursive: bpy.props.BoolProperty(
default=True,
name="Recursive",
description="Operate on blend files located in sub folders recursively\nIf unchecked it will only treat files in this folder",
)
def execute(self, context):
folder = Path(self.filepath)
if not folder.is_dir():
folder = folder.parent
if self.recursive:
blends = [fp for fp in folder.glob("**/*.blend") if fp.is_file()]
else:
blends = [fp for fp in folder.glob("*.blend") if fp.is_file()]
do_blends(blends)
return {"FINISHED"}
def do_blends(blends, save=None):
if save is not None:
bpy.ops.wm.save_as_mainfile(filepath=str(save))
if not blends:
print("Batch conversion completed")
return
print(f"{len(blends)} files left")
blend = blends.pop(0)
bpy.ops.wm.open_mainfile(filepath=str(blend))
bpy.app.timers.register(functools.partial(do_objs, blends, blend, [o for o in bpy.data.objects]))
def do_objs(blends, blend, objs):
if objs:
obj = objs.pop(0)
obj.asset_mark()
bpy.ops.ed.lib_id_generate_preview({"id": obj})
return INTERVAL
do_blends(blends, blend)
return None
def menu_func_import(self, context):
self.layout.operator(ASSET_OT_batch_generate_previews.bl_idname, text=ASSET_OT_batch_generate_previews.bl_label)
def register():
bpy.utils.register_class(ASSET_OT_batch_generate_previews)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
def unregister():
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
bpy.utils.unregister_class(ASSET_OT_batch_generate_previews)
if __name__ == "__main__":
register()
If you want to know how it works, when you validate it scans the selected folder and all subfolders recursively, then iterates over them and marks all objects as assets and generates their previews.
I suggest opening the console beforehand with Window > Toggle System Console because the script will print out the current state and how many files have been treated in the console but Blender will be unresponsive for the time being.
You can find the script and a readme on my github page.
-
-
$\begingroup$ You could do it differently. make a Path from self.filepath and then use Path's parent method to get the dirname:
p = Path(self.filepath).parent
$\endgroup$ Dec 10, 2021 at 16:03 -
$\begingroup$ This is great! Thank you so much for this! $\endgroup$ Dec 12, 2021 at 16:03
-
1$\begingroup$ @MartyFouts thanks, updated the script. It actually wasn't working for files with multiple objects so I changed it up a bit. Cheers $\endgroup$– GorgiousDec 13, 2021 at 9:11