8
$\begingroup$

I want to know how to create a menu with previews for an add-on. Until now I know that this is related with the bpy.utils.preview. I'm making an add-on that appends objects from a .blend file, I know how to append objects but what I want to do is to create a menu with previews of the objects /(similar to the matcaps menu - see below), select them and then press an "import button" to append the object.

Here's some documentation about the module: https://docs.blender.org/api/current/bpy.utils.previews.html https://developer.blender.org/diffusion/B/browse/master/release/scripts/templates_py/ui_previews_dynamic_enum.py

matcap menu

Also, as this is an add-on I don't know if I should have a def register() and a def unregister() inside this .py file as well as in the __init__.py file.

$\endgroup$
6
  • 1
    $\begingroup$ Yes sure. Sorry this is my first question on this site :/ $\endgroup$ Commented Feb 23, 2016 at 2:54
  • 1
    $\begingroup$ Thanks! I will take a look and see if I can help. Do you already have images for the previews, or do you need the script to render for you.. $\endgroup$
    – doomslug
    Commented Feb 24, 2016 at 17:07
  • 1
    $\begingroup$ I already have them, I just want a way to load each image with an specific id that I can write and track for future functions $\endgroup$ Commented Feb 24, 2016 at 17:50
  • 1
    $\begingroup$ Sorry that it took so long! I got it working! (finally) :) $\endgroup$
    – doomslug
    Commented Mar 1, 2016 at 22:47
  • 1
    $\begingroup$ you mentioned possibly using a script to render previews of objects. That is something I would love to see. $\endgroup$
    – patmo141
    Commented Mar 2, 2016 at 2:19

1 Answer 1

16
$\begingroup$

By analyzing the two provided scripts, as well as the free version of Pro Lighting: Skies I was able to understand how to create a previews menu.

Here is my script that I commented in if you want to study it. If you run it in Blender's text editor, it will create a panel at the bottom of the Object properties area.

The key parts of what you want to do are:

Create a property collection

This happens in the register function so only one is created. Because you want the the images folder to be predefined, we hard-code the location inside of the script. You also set a globally defined preview_collections variable to hold the collection. Then you create an EnumProperty to hold the images. This has a function to generate the images from the folder.

pcoll = bpy.utils.previews.new()
pcoll.images_location = bpy.path.abspath('//images')
preview_collections["thumbnail_previews"] = pcoll
bpy.types.Scene.my_thumbnails = EnumProperty(
    items=generate_previews(),
    )

Generate Previews

In the generate_previews function, we create a pcoll object that references the one we created in the register function.

def generate_previews():
    pcoll = preview_collections["thumbnail_previews"]
    image_location = pcoll.images_location
    VALID_EXTENSIONS = ('.png', '.jpg', '.jpeg')

    enum_items = []

    # Generate the thumbnails
    for i, image in enumerate(os.listdir(image_location)):
        if image.endswith(VALID_EXTENSIONS):
            filepath = os.path.join(image_location, image)
            thumb = pcoll.load(filepath, filepath, 'IMAGE')
            enum_items.append((image, image, "", thumb.icon_id, i))

    return enum_items

Access the values

We can then access this preview collection in any Blender UI Panel with

row=layout.row()
row.template_icon_view(context.scene, "my_thumbnails")

Or however else you named it. Then you can use bpy.context.Scene.my_thumbnails to access the currently selected image name. From there you can create an append button to append from a file based on the image name.


Using in an Addon

To use this method in an addon, you need to change a line in the Previews.py file. Instead of getting the location of the images folder based on the current .blend file, you need to get it based on the location of the addon. So change

pcoll.images_location = bpy.path.abspath('//images')

to

pcoll.images_location = os.path.join(os.path.dirname(__file__), "images")

In the __init__.py file, the register and unregister functions need to call the Previews.py's register and unregister functions.

def register(): 
    bpy.utils.register_module(__name__)
    Previews.register()


def unregister():
    bpy.utils.unregister_module(__name__)
    Previews.unregister()

And finally, because you use bpy.utils.register_module(__name__) you need to remove the register_class call in the Previews.py file to register the UI class, or it will be called twice.

# Delete this, as well as the one in the unregister function from Previews.py
bpy.utils.register_class(PreviewsExamplePanel)

I have updated the Gist on GitHub with the changes.

$\endgroup$
8
  • $\begingroup$ Is your addon in a folder? $\endgroup$
    – doomslug
    Commented Mar 2, 2016 at 19:38
  • $\begingroup$ Yes. it's in a folder inside the script folder, I think it is related with the 'init.py' file I leave you here the links with the source code pasteall.org/65655/python pasteall.org/65653/python $\endgroup$ Commented Mar 2, 2016 at 19:50
  • $\begingroup$ Sorry for delete and write comments over and over, the site doesn't allow me to edit them $\endgroup$ Commented Mar 2, 2016 at 19:51
  • $\begingroup$ I will take a look! $\endgroup$
    – doomslug
    Commented Mar 2, 2016 at 21:37
  • $\begingroup$ @AlejandroTorres I got it to work! Check out the edited answer. $\endgroup$
    – doomslug
    Commented Mar 3, 2016 at 17:23

You must log in to answer this question.

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