3
$\begingroup$

I'm struggling with implementing a custom icons into script. As my level of Python is low, I did try others suggestions but without any luck. Addon never show up in Blender, but it's installed in blender addon folder.

Always tested with zip file, as zip file contain a script Selection.py and folder "icons" with init.py script inside.

I always get error - ImportError: No module named 'icons'.

I believe that I never register a init.py script and Selection.py script can't see it. ?

Scripts

Selection.py script

import bpy
import bpy.utils.previews
from icons import get_icon_id
from bpy.types import (
        Panel,
        Menu,
        Operator,
        )
from bpy.props import IntProperty, FloatProperty

bl_info = {
    "name": "IPG",
    "author": "InvisibleParrot",
    "version": (0, 0, 1),
    "blender": (2, 77, 0),
    "location": "View3D > Edit Mode",
    "description": "IPG tools of trade",
    "warning": "",
    "wiki_url": "",
    "category": "IPG Tools"}


class SelectionPanel(bpy.types.Panel):
    """Selection"""
    bl_label = 'Selection'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = 'IPG Tools'

    def draw(self, context):
        layout = self.layout

        col = layout.column(align = True)

        col.operator("object.unwrapobject", text="Unwrap", icon_value=get_icon_id("C_Black"))


def register():
    bpy.utils.register_class(ColorSelectionPanel)

    bpy.utils.register_module(__name__)


def unregister():
    bpy.utils.unregister_class(ColorSelectionPanel)

    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()

and init.py script

import os
import bpy

icons_collection = None
icons_directory = os.path.dirname(__file__)

def get_icon_id(identifier):
    # The initialize_icons_collection function needs to be called first.
    return get_icon(identifier).icon_id

def get_icon(identifier):
    if identifier in icons_collection:
        return icons_collection[identifier]
    return icons_collection.load(identifier, os.path.join(icons_directory, identifier + ".png"), "IMAGE")

def initialize_icons_collection():
    global icons_collection
    icons_collection = bpy.utils.previews.new()

def unload_icons():
    bpy.utils.previews.remove(icons_collection)

class IconsMock:
    def get(self, identifier):
        return get_icon(identifier)

icons = IconsMock()
$\endgroup$
2
  • $\begingroup$ from . import icons or from .icons import get_icon_id or from your_package.icons import get_icon_id or look at the 'importlib' especially import_module(...) which lets you use string names, and can take advantage of __package__ and __name__ $\endgroup$
    – batFINGER
    Sep 4, 2016 at 5:48
  • $\begingroup$ Do you know the custom icon example in the python api? blender.org/api/blender_python_api_2_76_release/… $\endgroup$
    – Tiles
    Sep 4, 2016 at 7:34

1 Answer 1

1
$\begingroup$

Thanks for response.

Ok, now everything works..

Is there cleaner way for doing this or I need always register new icon ?

import os
import bpy

bl_info = {
    "name": "IPG Selection",
    "author": "InvisibleParrot",
    "version": (0, 0, 1),
    "blender": (2, 77, 0),
    "location": "View3D > Edit Mode",
    "description": "IPG tools of trade",
    "warning": "",
    "wiki_url": "",
    "category": "IPG Tools"}


preview_collections = {}


class PreviewsExamplePanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = 'Selection'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = 'IPG Tools'


    def draw(self, context):
        layout = self.layout

        col = layout.column(align = True)
        this_icon = preview_collections["custom_icons"]["custom_icon"].icon_id
        col.operator("render.render", text="Unwrap", icon_value=this_icon)
        this_icon = preview_collections["custom_icons"]["custom_icon2"].icon_id
        col.operator("render.render", text="Unwrap2", icon_value=this_icon)
        this_icon = preview_collections["custom_icons"]["custom_icon3"].icon_id
        col.operator("render.render", text="Unwrap3", icon_value=this_icon)
        this_icon = preview_collections["custom_icons"]["custom_icon4"].icon_id
        col.operator("render.render", text="Unwrap4", icon_value=this_icon)



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("custom_icon", os.path.join(my_icons_dir, "C_Black.png"), 'IMAGE')
    pcoll.load("custom_icon2", os.path.join(my_icons_dir, "C_Blue.png"), 'IMAGE')
    pcoll.load("custom_icon3", os.path.join(my_icons_dir, "C_Yellow.png"), 'IMAGE')
    pcoll.load("custom_icon4", os.path.join(my_icons_dir, "C_Red.png"), 'IMAGE')

    preview_collections["custom_icons"] = pcoll

    bpy.utils.register_class(PreviewsExamplePanel)

    bpy.utils.register_module(__name__)



def unregister():

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

    bpy.utils.unregister_class(PreviewsExamplePanel)

    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()
$\endgroup$
1
  • 2
    $\begingroup$ I preferred where you were going with this in the Q. You just needed to change how the previews were loaded and removed in icons.__init__.py and import it properly in Selection.py. (from . import icons) With this fixed you could simply call icons.initialize_icons_collection() in register, and unload in unregister. $\endgroup$
    – batFINGER
    Sep 4, 2016 at 11:51

You must log in to answer this question.

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