123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- # This sample script demonstrates a dynamic EnumProperty with custom icons.
- # The EnumProperty is populated dynamically with thumbnails of the contents of
- # a chosen directory in 'enum_previews_from_directory_items'.
- # Then, the same enum is displayed with different interfaces. Note that the
- # generated icon previews do not have Blender IDs, which means that they can
- # not be used with UILayout templates that require IDs,
- # such as template_list and template_ID_preview.
- #
- # Other use cases:
- # - make a fixed list of enum_items instead of calculating them in a function
- # - generate isolated thumbnails to use as custom icons in buttons
- # and menu items
- #
- # For custom icons, see the template "ui_previews_custom_icon.py".
- #
- # For distributable scripts, it is recommended to place the icons inside the
- # script directory and access it relative to the py script file for portability:
- #
- # os.path.join(os.path.dirname(__file__), "images")
- import os
- import bpy
- def enum_previews_from_directory_items(self, context):
- """EnumProperty callback"""
- enum_items = []
- if context is None:
- return enum_items
- wm = context.window_manager
- directory = wm.my_previews_dir
- # Get the preview collection (defined in register func).
- pcoll = preview_collections["main"]
- if directory == pcoll.my_previews_dir:
- return pcoll.my_previews
- print("Scanning directory: %s" % directory)
- if directory and os.path.exists(directory):
- # Scan the directory for png files
- image_paths = []
- for fn in os.listdir(directory):
- if fn.lower().endswith(".png"):
- image_paths.append(fn)
- for i, name in enumerate(image_paths):
- # generates a thumbnail preview for a file.
- filepath = os.path.join(directory, name)
- icon = pcoll.get(name)
- if not icon:
- thumb = pcoll.load(name, filepath, 'IMAGE')
- else:
- thumb = pcoll[name]
- enum_items.append((name, name, "", thumb.icon_id, i))
- pcoll.my_previews = enum_items
- pcoll.my_previews_dir = directory
- return pcoll.my_previews
- class PreviewsExamplePanel(bpy.types.Panel):
- """Creates a Panel in the Object properties window"""
- bl_label = "Previews Example Panel"
- bl_idname = "OBJECT_PT_previews"
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "object"
- def draw(self, context):
- layout = self.layout
- wm = context.window_manager
- row = layout.row()
- row.prop(wm, "my_previews_dir")
- row = layout.row()
- row.template_icon_view(wm, "my_previews")
- row = layout.row()
- row.prop(wm, "my_previews")
- # We can store multiple preview collections here,
- # however in this example we only store "main"
- preview_collections = {}
- def register():
- from bpy.types import WindowManager
- from bpy.props import (
- StringProperty,
- EnumProperty,
- )
- WindowManager.my_previews_dir = StringProperty(
- name="Folder Path",
- subtype='DIR_PATH',
- default=""
- )
- WindowManager.my_previews = EnumProperty(
- items=enum_previews_from_directory_items,
- )
- # Note that preview collections returned by bpy.utils.previews
- # are regular Python objects - you can use them to store custom data.
- #
- # This is especially useful here, since:
- # - It avoids us regenerating the whole enum over and over.
- # - It can store enum_items' strings
- # (remember you have to keep those strings somewhere in py,
- # else they get freed and Blender references invalid memory!).
- import bpy.utils.previews
- pcoll = bpy.utils.previews.new()
- pcoll.my_previews_dir = ""
- pcoll.my_previews = ()
- preview_collections["main"] = pcoll
- bpy.utils.register_class(PreviewsExamplePanel)
- def unregister():
- from bpy.types import WindowManager
- del WindowManager.my_previews
- for pcoll in preview_collections.values():
- bpy.utils.previews.remove(pcoll)
- preview_collections.clear()
- bpy.utils.unregister_class(PreviewsExamplePanel)
- if __name__ == "__main__":
- register()
|