In the Geo-Scatter plugin, this is how we proceed, the method is FAR from ideal.
Collection type could be implemented that way as well, however, note that we rely on the context asset library being selected, the new "all" category for example render this method useless.
One of the constraints we are facing is the asset.relative_path
property, which is utterly useless, as we still lack the most important information, which is the context library directory
class AssetItem():
def __init__(self, asset=None, directory="",):
self.asset = asset
self.name = asset.name
self.type = asset.id_type
if (bool(directory)):
blend, inner = asset.relative_path.split(".blend") #this line won't work if the name is "dude.blend123.blend" for example
self.path = os.path.join(directory, f"{blend}.blend")
self.full_path = os.path.join(directory, asset.relative_path)
assert os.path.exists(self.path)
else:
self.path = "current_file"
self.full_path = "current_file"
def __repr__(self):
return f"<AssetItem {self.type} '{self.name}' at {self.full_path}>"
#globals needed for workaround
is_current_file = None
import_type = None
selected_asset_items = None
class SCATTER5_OT_get_browser_items(bpy.types.Operator):
"""workaround, use an operator context override to get the correct context. using areas[x].selected_asset_files simply refuses to work on blender 3.3LTS"""
bl_idname = "scatter5.get_browser_items"
bl_label = ""
bl_description = ""
def execute(self, context):
"""gather asset browset items from operator context"""
#import globals and reset
global is_current_file , import_type , selected_asset_items
is_current_file = import_type = selected_asset_items = None
#no headless support
if (not context.window):
print("SCATTER5_OT_get_browser_items->not context.window, using blender headlessly?")
return {'FINISHED'}
#set global context
window, area = None, None
#is context area already correct?
if (context.area.ui_type=="ASSETS"):
window, area = context.window, context.area
#else try to find AB area in context window first
if (area is None):
for a in context.window.screen.areas:
if (a.ui_type=="ASSETS"):
window, area = context.window, a
break
#else try other windows?
if (area is None):
for w in context.window_manager.windows:
for a in w.screen.areas:
if (a.ui_type=="ASSETS"):
window, area = w, a
break
#else raise error..
if (area is None):
print("SCATTER5_OT_get_browser_items->No match for windows/areas")
return {'FINISHED'}
#override if needed, to do so, will need to quit and relaunch this operator
if ((context.area!=area) or (context.window!=window)):
override = bpy.context.copy()
override.update(area=area)
override.update(window=window)
bpy.ops.scatter5.get_browser_items(override)
return {'FINISHED'}
space = area.spaces[0]
directory = space.params.directory.decode("utf-8")
#Better way to support assets? get main directory path easily from API? don't looks like it
#write globals
is_current_file = not bool(directory)
import_type = space.params.import_type
selected_asset_items = [ AssetItem(asset=ass, directory=directory) for ass in context.selected_asset_files ]
#TODO supports "COLLECTION", will need to import collection and do object instance ourself if cannot find collection instance object
selected_asset_items = [ Ass for Ass in selected_asset_items if (Ass.type=="OBJECT") ]
return {'FINISHED'}
def import_selected_assets(link=False, link_coll="Geo-Scatter Import",):
"""import selected object type assets from browser, link/append depends on technique"""
objects_found = []
bpy.ops.scatter5.get_browser_items()
global is_current_file , import_type , selected_asset_items
...
# proceed to the import code..
os.path
$\endgroup$