Sharing a Preview Collection across a multiple file add-on

Hello! I have a multi-file Add-on. Following this example from the Blender documentation, I’m able to create custom icons.

import os
import bpy


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
        pcoll = preview_collections["main"]

        row = layout.row()
        my_icon = pcoll["my_icon"]
        row.operator("render.render", icon_value=my_icon.icon_id)

        # my_icon.icon_id can be used in any UI function that accepts
        # icon_value # try also setting text=""
        # to get an icon only operator button


# We can store multiple preview collections here,
# however in this example we only store "main"
preview_collections = {}


def register():

    # Note that preview collections returned by bpy.utils.previews
    # are regular py objects - you can use them to store custom data.
    import bpy.utils.previews
    pcoll = bpy.utils.previews.new()

    # path to the folder where the icon is
    # the path is calculated relative to this py file inside the addon folder
    my_icons_dir = os.path.join(os.path.dirname(__file__), "icons")

    # load a preview thumbnail of a file and store in the previews collection
    pcoll.load("my_icon", os.path.join(my_icons_dir, "icon-image.png"), 'IMAGE')

    preview_collections["main"] = pcoll

    bpy.utils.register_class(PreviewsExamplePanel)


def unregister():

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

    bpy.utils.unregister_class(PreviewsExamplePanel)


if __name__ == "__main__":
    register()

My issue is that I’d like to load these images once for my add-on rather than in every separate file. Is it possible to load and access these once for my Add-on package?

Can I store the ImagePreviewCollection in the Scene somehow? In the example, they’re creating a dictionary preview_collection and I’m not sure how I’d share this across files.

Thank you!

storing them in a module’s global scope is the way to go imo. even if it were possible to store on the scene you wouldn’t want to do that since scene data is stored when you save a file, and preview data is not transient so you’d have a bunch of null pointers when you loaded the scene again.

quick example of how to use multiple modules to do what you want to do. say you have three files in the following hierarchy:

__init__.py
/operators/coolstuff.py
/interface/icons.py

now imagine your global preview_collections is in /interface/icons.py

from here you have a couple of options on how you want to import (this is basic python stuff, so if you already know it just skip to whatever is relevant to you):

to access it from init, if you want to import the entire icons modules (including the preview global)
you could use from . interface import icons, which would allow you to call the module using its namespace (for lack of a better/more relevant python term): icons.preview_collections.

you could also just import the preview_collections global by itself with from . interface.icons import preview_collections

if you need to access the global from the a module in the /operators/ path you’d need to adjust your import to be relative to the current module’s location:
from .. interface import icons
from .. interface.icons import preview_collections

.. moves up one directory. if you need to import something relative to the root you could use ...

1 Like

Thank you so much for taking the time to answer.