1
$\begingroup$

I want to add a few options to this python template which I found inside Blender-ui_previews_dynamic_enum.py Here is the code:

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()

This code will scan and use the png files from the directory and create the thumbnails of that.

Is there a way to specify the items before, with thumbnails, and on choosing a certain option from that menu, a change in the code takes place.....

$\endgroup$

1 Answer 1

1
$\begingroup$

Try using update methods. Changing the dir would be the time to populate the list, changing the enum ... run some other code. A lot of the code in the items callback can then be removed.

import os
import bpy

preview_collections = {}

def enum_previews_from_directory_items(self, context):
    pcoll = preview_collections.get("main")
    if not pcoll:
        return []

    if self.my_previews_dir == "": # use better default
        # put some code in here to populate default list
        print("MAKE A NEW THUMB LIST HERE")
        newlist = []
        '''
        # a list of items with name, filepath to image, and unique i

        thumb = pcoll.load(filepath, filepath, 'IMAGE')
        item = (name, name, "", thumb.icon_id, i) 
        newlist.append(item)
        '''       
        return newlist

    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"


def preview_dir_update(wm, context):
    print("wm.my_previews_dir = %s" % wm.my_previews_dir)

    """EnumProperty callback"""
    enum_items = []

    wm = context.window_manager
    directory = wm.my_previews_dir

    # Get the preview collection (defined in register func).
    pcoll = preview_collections["main"]

    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 None

def preview_enum_update(wm, context):
    print("wm.my_previews = %s" % wm.my_previews)
    return None

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="",
            update=preview_dir_update,
            )

    WindowManager.my_previews = EnumProperty(
            items=enum_previews_from_directory_items,
            update=preview_enum_update,
                )

    # 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

    pcol = preview_collections.setdefault("main", bpy.utils.previews.new())

    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()

You can get fancy with the update methods using the methods outlined here https://blender.stackexchange.com/a/39624/15543

$\endgroup$
4
  • $\begingroup$ Well, I actually want there to be different options. And, I don't know how to specify those items or options in the enum_previews_from_directory_items(). Each item should have a different thumbnail $\endgroup$ Dec 2, 2015 at 9:48
  • $\begingroup$ Ok, I get it, but how will I check which option is selected by the user..... $\endgroup$ Dec 2, 2015 at 10:33
  • $\begingroup$ preview_enum_update is called when user changes selection. $\endgroup$
    – batFINGER
    Dec 2, 2015 at 10:44
  • $\begingroup$ Thanks for help, I was thinking if it was possible to remove the StringProperty from the Interface, and assign it a specific default value which will never update.... :) $\endgroup$ Dec 2, 2015 at 11:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .