6
$\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://www.blender.org/api/blender_python_api_2_74_5/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$
  • $\begingroup$ Add some more details and I will be glad to help. I'm not quite sure what you mean by "menu with previews that executes a class when a preview is pressed". Maybe add pictures or expand your description so others can understand. $\endgroup$ – Nathan Craddock Feb 23 '16 at 1:45
  • $\begingroup$ Yes sure. Sorry this is my first question on this site :/ $\endgroup$ – Alejandro Torres Feb 23 '16 at 2:54
  • $\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$ – Nathan Craddock Feb 24 '16 at 17:07
  • $\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$ – Alejandro Torres Feb 24 '16 at 17:50
  • $\begingroup$ Sorry that it took so long! I got it working! (finally) :) $\endgroup$ – Nathan Craddock Mar 1 '16 at 22:47
9
$\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$
  • $\begingroup$ very nice. Tested, it works! $\endgroup$ – patmo141 Mar 2 '16 at 3:07
  • $\begingroup$ Is your addon in a folder? $\endgroup$ – Nathan Craddock Mar 2 '16 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$ – Alejandro Torres Mar 2 '16 at 19:50
  • $\begingroup$ Sorry for delete and write comments over and over, the site doesn't allow me to edit them $\endgroup$ – Alejandro Torres Mar 2 '16 at 19:51
  • $\begingroup$ I will take a look! $\endgroup$ – Nathan Craddock Mar 2 '16 at 21:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.