Skip to content

Instantly share code, notes, and snippets.

@p2or
Last active February 8, 2024 14:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save p2or/37ec841fa315481836c2655ebc4b1b42 to your computer and use it in GitHub Desktop.
Save p2or/37ec841fa315481836c2655ebc4b1b42 to your computer and use it in GitHub Desktop.
Blend file list based on: https://blender.stackexchange.com/q/30444/ #Blender
import bpy
from bpy.props import IntProperty, CollectionProperty, StringProperty, EnumProperty
from bpy.types import Panel, UIList, PropertyGroup, Operator
from bpy_extras.io_utils import ImportHelper
import os
class CUSTOM_OT_actionsUIList(Operator):
bl_idname = "custom.list_action"
bl_label = "List Action"
action: EnumProperty(
items=(
('UP', "Up", ""),
('DOWN', "Down", ""),
('REMOVE', "Remove", ""),
('ADD', "Add", ""),
)
)
def invoke(self, context, event):
scn = context.scene
idx = scn.custom_index
try:
item = scn.custom[idx]
except IndexError:
pass
else:
if self.action == 'DOWN' and idx < len(scn.custom) - 1:
item_next = scn.custom[idx+1].name
scn.custom_index += 1
info = 'Item %d selected' % (scn.custom_index + 1)
self.report({'INFO'}, info)
elif self.action == 'UP' and idx >= 1:
item_prev = scn.custom[idx-1].name
scn.custom_index -= 1
info = 'Item %d selected' % (scn.custom_index + 1)
self.report({'INFO'}, info)
elif self.action == 'REMOVE':
info = 'Item %s removed from list' % (scn.custom[scn.custom_index].name)
scn.custom_index -= 1
self.report({'INFO'}, info)
scn.custom.remove(idx)
if self.action == 'ADD':
bpy.ops.custom.blend_select('INVOKE_DEFAULT')
scn.custom_index = (len(scn.custom)) # (len(scn.custom)-1)
return {"FINISHED"}
class CUSTOM_OT_blendSelect(bpy.types.Operator, ImportHelper):
"""This appears in the tooltip of the operator and in the generated docs"""
bl_idname = "custom.blend_select"
bl_label = "Blend Selector"
bl_options = {'PRESET', 'UNDO'}
# ImportHelper mixin class uses this
filename_ext = ".blend"
filter_glob: StringProperty(
default="*.blend",
options={'HIDDEN'},
)
# Selected files
files: CollectionProperty(type=PropertyGroup)
def execute(self, context):
scn = context.scene
# get the folder
folder = (os.path.dirname(self.filepath))
# iterate through the selected files
for i in self.files:
# generate full path to file
path_to_file = (os.path.join(folder, i.name))
item = scn.custom.add()
item.id = len(scn.custom)
item.name = i.name # assign name of selected object
item.path = path_to_file
self.report({'INFO'}, "Files Added")
return {'FINISHED'}
class CUSTOM_UL_items(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
split = layout.split(factor=0.7)
split.prop(item, "name", text="", emboss=False, translate=False, icon='FILE_BLEND')
split.label(text="Index: %d" % (index))
def invoke(self, context, event):
pass
class CUSTOM_PT_blendFiles(Panel):
"""Creates a Panel in the Object properties window"""
bl_idname = 'OBJECT_PT_my_panel'
bl_space_type = "TEXT_EDITOR"
bl_region_type = "UI"
bl_label = "Custom Blend File List"
def draw(self, context):
layout = self.layout
scn = bpy.context.scene
try:
current_item = (scn.custom[scn.custom_index].name)
except IndexError:
current_item = ""
rows = 2
row = layout.row()
row.template_list("CUSTOM_UL_items", "", scn, "custom", scn, "custom_index", rows=rows)
col = row.column(align=True)
col.operator(CUSTOM_OT_actionsUIList.bl_idname, icon='TRIA_UP', text="").action = 'UP'
col.operator(CUSTOM_OT_actionsUIList.bl_idname, icon='TRIA_DOWN', text="").action = 'DOWN'
row = layout.row()
col = layout.column(align=True)
rowsub = col.row(align=True)
rowsub.operator(CUSTOM_OT_actionsUIList.bl_idname, icon='ZOOM_IN', text="Add Files to List").action = 'ADD'
rowsub.operator(CUSTOM_OT_actionsUIList.bl_idname, icon='ZOOM_OUT', text="Remove File").action = 'REMOVE'
row = layout.row()
col = row.column(align=True)
col.operator("custom.active_item", icon="CONSOLE")
col.operator("custom.print_list", icon="WORDWRAP_ON")
col.operator("custom.clear_list", icon="X")
row = layout.row(align=True)
row.label(text="Active Item is: {}".format(current_item))
class CUSTOM_OT_clearListItems(bpy.types.Operator):
bl_idname = "custom.clear_list"
bl_label = "Clear List"
bl_description = "Clear all items in the list"
def execute(self, context):
scn = context.scene
lst = scn.custom
current_index = scn.custom_index
if len(lst) > 0:
# reverse range to remove last item first
for i in range(len(lst)-1,-1,-1):
scn.custom.remove(i)
self.report({'INFO'}, "All items removed")
else:
self.report({'INFO'}, "Nothing to remove")
return{'FINISHED'}
# print button
class CUSTOM_OT_printListItems(Operator):
bl_idname = "custom.print_list"
bl_label = "Print Name, ID and Path to Console"
bl_description = "Print all items to the Console"
def execute(self, context):
scn = context.scene
for i in scn.custom:
print ("Blend-File:", i.name, "ID:", i.id, "Path:", i.path)
return{'FINISHED'}
# select button
class CUSTOM_OT_selectAllItems(Operator):
bl_idname = "custom.active_item"
bl_label = "Print Active Item to Console"
bl_description = "Print Active Selection"
def execute(self, context):
scn = context.scene
print (scn.custom[scn.custom_index].name)
return{'FINISHED'}
# Create custom property group
class CUSTOM_PG_items(PropertyGroup):
# name: StringProperty() - instantiated by default
id: IntProperty()
path: StringProperty()
# -------------------------------------------------------------------
# Registration
# -------------------------------------------------------------------
classes = (
CUSTOM_OT_actionsUIList,
CUSTOM_OT_blendSelect,
CUSTOM_UL_items,
CUSTOM_PT_blendFiles,
CUSTOM_OT_clearListItems,
CUSTOM_OT_printListItems,
CUSTOM_OT_selectAllItems,
CUSTOM_PG_items
)
def register():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
bpy.types.Scene.custom = CollectionProperty(type=CUSTOM_PG_items)
bpy.types.Scene.custom_index = IntProperty()
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
del bpy.types.Scene.custom
del bpy.types.Scene.custom_index
if __name__ == "__main__":
register()
@dt192
Copy link

dt192 commented Jul 5, 2021

I've updated it to work with Blender 2.9.3, as they broke stuff. Check the fork.

@p2or
Copy link
Author

p2or commented Jul 9, 2021

Hi @dt192, updated the gist. You forgot to replace the assignment operators in the item group and to change the class names according to the current requirements in your fork hence the warnings in the console. Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment