Set EnumProperties inside a function

by Alejandro Torres   Last Updated July 18, 2018 00:15 AM

I want to regenerated a Preview Collection based on the Category and Subcategory selected. Right now I was able to update the Subcategory EnumProperty based on the Category EnumProperty, however, when I try to implement the same technique to the Preview Enum Property it doesn't work.

enter image description here

import bpy
from bpy.types import Panel, EnumProperty, WindowManager
from bpy.props import *
import bpy.utils.previews

import os
import json

props_list = []

with open(os.path.join(os.path.dirname(__file__), "props_list.json")) as json_file:
    data = json.load(json_file)
    props_list = data["Models"]

# UI
class PropsPreviewsPanel(bpy.types.Panel):
    bl_label = "Props Library"
    bl_idname = "OBJECT_PT_previews"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Props Library"

    def draw(self, context):
        layout = self.layout
        wm = context.window_manager
        # This tells Blender to draw the my_previews window manager object
        # (Which is our preview)
        row = layout.row()
        row.template_icon_view(context.scene, "props_thumbnails", show_labels=True)

        row = layout.row()
        row.prop(context.scene, 'PropEnum')

        row = layout.row()
        row.prop(context.scene, 'PropEnumSec')

        # Just a way to access which one is selected
        row = layout.row()
        row.label(text="You selected: " + bpy.context.scene.PropEnum)

        row = layout.row()
        row.operator(
            Props_Import.bl_idname,
            text = "Import",
            icon='APPEND_BLEND')

preview_collections = {}

class Props_Import(bpy.types.Operator):
    bl_idname = "object.props_imp"
    bl_label = "Import"
    bl_options = {'REGISTER', 'UNDO'}

def execute_import(self, context):

    dirpath = os.path.join(os.path.dirname(__file__),    "blends/retro.blend/Object/")

    bpy.ops.wm.append(filename="Stop", directory=dirpath)

    return {'FINISHED'}

def generate_previews():
    # We are accessing all of the information that we generated in the register function below
    pcoll = preview_collections["thumbnail_previews"]
    image_location = pcoll.images_location
    VALID_EXTENSIONS = ('.png', '.jpg', '.jpeg')

    enum_items = []
    i = 0

    # Generate the thumbnails
    for prop, category, subcategory, prop_image in props_list:
        filepath = os.path.join(image_location, prop_image)
        thumb = pcoll.load(filepath, filepath, 'IMAGE')
        enum_items.append((prop, prop, "", thumb.icon_id, i))
        i += 1

    return enum_items

def update_func(self, context):

    for pcoll in preview_collections.values():
        bpy.utils.previews.remove(pcoll)
    preview_collections.clear()

    pcoll = bpy.utils.previews.new()
    preview_collections["thumbnail_previews"] = pcoll
    pcoll.images_location = os.path.join(os.path.dirname(__file__), "images")

    bpy.types.Scene.my_thumbnails = EnumProperty(
        items=generate_previews()
        )

    return None

def generate_subcategories(self, context):

    enum_subcat = []

    if self.PropEnum == 'Kitchen & Food':
        enum_subcat.append(('Glassware', 'Glassware', ''))
        enum_subcat.append(('subcat2', 'Subcategory 2', ''))
        enum_subcat.append(('subcat3', 'Subcategory 3', ''))
        enum_subcat.append(('subcat4', 'Subcategory 4', ''))
        enum_subcat.append(('subcat5', 'Subcategory 5', ''))
        enum_subcat.append(('subcat6', 'Subcategory 6', ''))

    elif self.PropEnum == 'cat2':
        enum_subcat.append(('subcat1', 'Subcategory 1', ''))
        enum_subcat.append(('subcat2', 'Subcategory 2', ''))
        enum_subcat.append(('subcat3', 'Subcategory 3', ''))
        enum_subcat.append(('subcat4', 'Subcategory 4', ''))

    else: enum_subcat = []

    return enum_subcat


def register():
    from bpy.types import Scene
    from bpy.props import StringProperty, EnumProperty

    # Create a new preview collection (only upon register)
    pcoll = bpy.utils.previews.new()

    # This line needs to be uncommented if you install as an addon
    pcoll.images_location = os.path.join(os.path.dirname(__file__), "images")

    # This line is for running as a script. Make sure images are in a folder called images in the same
    # location as the Blender file. Comment out if you install as an addon
    #pcoll.images_location = bpy.path.abspath('//images')

    # Enable access to our preview collection outside of this function
    preview_collections["thumbnail_previews"] = pcoll

    # This is an EnumProperty to hold all of the images
    # You really can save it anywhere in bpy.types.*  Just make sure the location makes sense
    bpy.types.Scene.props_thumbnails = EnumProperty(
        items = generate_previews()
        )

    bpy.types.Scene.PropEnum = EnumProperty(
    items = [('Kitchen & Food', 'Kitchen & Food', ''),
             ('cat2', 'Category 2', ''),
             ('cat3', 'Category 3', ''),
             ('cat4', 'Category 4', ''),
             ('cat5', 'Category 5', ''),
             ('cat6', 'Category 6', '')],
    name = "Category",
    update = update_func
    )

    bpy.types.Scene.PropEnumSec = EnumProperty(
    name = "Subcategory",
    items = generate_subcategories
    )

def unregister():
    from bpy.types import WindowManager
    for pcoll in preview_collections.values():
        bpy.utils.previews.remove(pcoll)
    preview_collections.clear()

    del bpy.types.Scene.props_thumbnails

if __name__ == "__main__":
    register()

The add-on works collecting the images from a JSON file with the information of the models

{
  "Models": [
    [
      "Burgundy",
      "Kitchen & Food",
      "Glassware",
      "F_Burgundy.png"
    ],
    [
      "Chardonnay",
      "Kitchen & Food",
      "Glassware",
      "F_Chardonnay.png"
    ],
    [
      "Cabernet",
      "Kitchen & Food",
      "Glassware",
      "F_Cabernet.png"
    ],
    [
      "Champagne",
      "Kitchen & Food",
      "Glassware",
      "F_Champagne.png"
    ],
    [
      "Fries",
      "Kitchen & Food",
      "Fast Food",
      "Fastfood.JPG"
    ]
  ]
}


Related Questions


How to redefine an Float Property after create it?

Updated April 28, 2015 23:06 PM

Getting a Reference to an Object in a Panel

Updated June 16, 2016 08:06 AM

Add a custom curve mapping property for an add-on?

Updated August 28, 2016 08:06 AM

custom layout (via scripting)

Updated June 05, 2015 23:06 PM

Blender Python - Modes, If obj.type particles?

Updated October 05, 2016 09:06 AM