Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dt192/975cfdcb17b12ce2dee62de65b728a2d to your computer and use it in GitHub Desktop.
Save dt192/975cfdcb17b12ce2dee62de65b728a2d to your computer and use it in GitHub Desktop.
blender-blend-file-uiist example updated for Blender 2.9.3
import bpy
from bpy.props import IntProperty, CollectionProperty, StringProperty
from bpy.types import Panel, UIList
from bpy_extras.io_utils import ImportHelper
import os
# ui list item actions
class Uilist_actions(bpy.types.Operator):
bl_idname = "custom.list_action"
bl_label = "List Action"
action : bpy.props.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 BlendSelectOperator(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=bpy.types.PropertyGroup)
def execute(self, context):
scn = context.scene
# get the folder
folder = (os.path.dirname(self.filepath))
# iterate through the selected files
for j, i in enumerate(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'}
# -------------------------------------------------------------------
# draw
# -------------------------------------------------------------------
# custom list
class 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
# draw the panel
class UIListPanelExample(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 = ""
#row.operator("custom.list_action", icon='ZOOMIN', text="Add Files").action = 'ADD'
#row.operator("custom.list_action", icon='ZOOMOUT', text="").action = 'REMOVE'
#split = row.split(align=True, percentage=0.6)
rows = 2
row = layout.row()
row.template_list("UL_items", "", scn, "custom", scn, "custom_index", rows=rows)
col = row.column(align=True)
#col.operator("custom.list_action", icon='ZOOMIN', text="").action = 'ADD'
#col.operator("custom.list_action", icon='ZOOMOUT', text="").action = 'REMOVE'
#col.separator()
col.operator("custom.list_action", icon='TRIA_UP', text="").action = 'UP'
col.operator("custom.list_action", icon='TRIA_DOWN', text="").action = 'DOWN'
row = layout.row()
col = layout.column(align=True)
rowsub = col.row(align=True)
rowsub.operator("custom.list_action", icon='ZOOM_IN', text="Add Files to List").action = 'ADD'
rowsub.operator("custom.list_action", 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))
# clear button
class Uilist_clearAllItems(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 Uilist_printAllItems(bpy.types.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 Uilist_selectAllItems(bpy.types.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 CustomProps(bpy.types.PropertyGroup):
id = IntProperty()
name = StringProperty()
path = StringProperty()
# -------------------------------------------------------------------
# register
# -------------------------------------------------------------------
classes = (
Uilist_actions,
UL_items,
BlendSelectOperator,
UIListPanelExample,
Uilist_clearAllItems,
Uilist_printAllItems,
Uilist_selectAllItems,
CustomProps,
)
def register():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
bpy.types.Scene.custom = CollectionProperty(type=CustomProps)
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment