138 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# 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)
 | 
						|
            thumb = pcoll.load(filepath, filepath, 'IMAGE')
 | 
						|
            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()
 |