2015-05-11 16:29:12 +02:00
|
|
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License
|
|
|
|
# as published by the Free Software Foundation; either version 2
|
|
|
|
# of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software Foundation,
|
|
|
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
#
|
|
|
|
# ##### END GPL LICENSE BLOCK #####
|
|
|
|
|
|
|
|
# <pep8 compliant>
|
|
|
|
|
|
|
|
"""
|
|
|
|
This module contains utility functions to handle custom previews.
|
|
|
|
|
|
|
|
It behaves as a high-level 'cached' previews manager.
|
|
|
|
|
2015-05-12 18:06:31 +10:00
|
|
|
This allows scripts to generate their own previews, and use them as icons in UI widgets
|
|
|
|
('icon_value' for UILayout functions).
|
|
|
|
|
|
|
|
|
|
|
|
Custom Icon Example
|
|
|
|
-------------------
|
|
|
|
|
2016-06-12 11:20:13 +10:00
|
|
|
.. literalinclude:: __/__/__/release/scripts/templates_py/ui_previews_custom_icon.py
|
2015-05-11 16:29:12 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
__all__ = (
|
|
|
|
"new",
|
|
|
|
"remove",
|
2015-05-12 18:06:31 +10:00
|
|
|
"ImagePreviewCollection",
|
2018-06-30 09:23:07 +02:00
|
|
|
)
|
2015-05-11 16:29:12 +02:00
|
|
|
|
|
|
|
import _bpy
|
|
|
|
_utils_previews = _bpy._utils_previews
|
|
|
|
del _bpy
|
|
|
|
|
|
|
|
|
|
|
|
_uuid_open = set()
|
|
|
|
|
|
|
|
|
|
|
|
# High-level previews manager.
|
|
|
|
# not accessed directly
|
2015-05-12 18:06:31 +10:00
|
|
|
class ImagePreviewCollection(dict):
|
2015-05-11 16:29:12 +02:00
|
|
|
"""
|
2015-05-12 18:06:31 +10:00
|
|
|
Dictionary-like class of previews.
|
|
|
|
|
|
|
|
This is a subclass of Python's built-in dict type,
|
|
|
|
used to store multiple image previews.
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
- instance with :mod:`bpy.utils.previews.new`
|
|
|
|
- keys must be ``str`` type.
|
|
|
|
- values will be :class:`bpy.types.ImagePreview`
|
2015-05-11 16:29:12 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
# Internal notes:
|
|
|
|
# - Blender's internal 'PreviewImage' struct uses 'self._uuid' prefix.
|
2020-09-17 12:42:07 +10:00
|
|
|
# - Blender's preview.new/load return the data if it exists,
|
|
|
|
# don't do this for the Python API as it allows accidental re-use of names,
|
|
|
|
# anyone who wants to reuse names can use dict.get() to check if it exists.
|
|
|
|
# We could use this for the C API too (would need some investigation).
|
2015-05-11 16:29:12 +02:00
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super().__init__()
|
|
|
|
self._uuid = hex(id(self))
|
|
|
|
_uuid_open.add(self._uuid)
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
if self._uuid not in _uuid_open:
|
|
|
|
return
|
|
|
|
|
|
|
|
raise ResourceWarning(
|
2020-06-26 12:30:03 +10:00
|
|
|
"%r: left open, remove with 'bpy.utils.previews.remove()'" % self
|
2018-06-30 09:23:07 +02:00
|
|
|
)
|
2015-05-11 16:29:12 +02:00
|
|
|
self.close()
|
|
|
|
|
|
|
|
def _gen_key(self, name):
|
|
|
|
return ":".join((self._uuid, name))
|
|
|
|
|
|
|
|
def new(self, name):
|
|
|
|
if name in self:
|
2020-07-16 23:50:33 +10:00
|
|
|
raise KeyError("key %r already exists" % name)
|
2015-05-11 16:29:12 +02:00
|
|
|
p = self[name] = _utils_previews.new(
|
2018-06-30 09:23:07 +02:00
|
|
|
self._gen_key(name))
|
2015-05-11 16:29:12 +02:00
|
|
|
return p
|
|
|
|
new.__doc__ = _utils_previews.new.__doc__
|
|
|
|
|
|
|
|
def load(self, name, path, path_type, force_reload=False):
|
|
|
|
if name in self:
|
2020-07-16 23:50:33 +10:00
|
|
|
raise KeyError("key %r already exists" % name)
|
2015-05-11 16:29:12 +02:00
|
|
|
p = self[name] = _utils_previews.load(
|
2018-06-30 09:23:07 +02:00
|
|
|
self._gen_key(name), path, path_type, force_reload)
|
2015-05-11 16:29:12 +02:00
|
|
|
return p
|
|
|
|
load.__doc__ = _utils_previews.load.__doc__
|
|
|
|
|
|
|
|
def clear(self):
|
2015-05-12 18:06:31 +10:00
|
|
|
"""Clear all previews."""
|
2015-05-11 16:29:12 +02:00
|
|
|
for name in self.keys():
|
|
|
|
_utils_previews.release(self._gen_key(name))
|
|
|
|
super().clear()
|
|
|
|
|
|
|
|
def close(self):
|
2015-05-12 18:06:31 +10:00
|
|
|
"""Close the collection and clear all previews."""
|
2015-05-11 16:29:12 +02:00
|
|
|
self.clear()
|
|
|
|
_uuid_open.remove(self._uuid)
|
|
|
|
|
|
|
|
def __delitem__(self, key):
|
2015-05-17 17:17:02 +10:00
|
|
|
_utils_previews.release(self._gen_key(key))
|
2015-05-12 18:43:30 +10:00
|
|
|
super().__delitem__(key)
|
2015-05-11 16:29:12 +02:00
|
|
|
|
|
|
|
def __repr__(self):
|
2020-06-26 12:30:03 +10:00
|
|
|
return "<%s id=%s[%d], %r>" % (
|
|
|
|
self.__class__.__name__, self._uuid, len(self), super()
|
|
|
|
)
|
2015-05-11 16:29:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
def new():
|
|
|
|
"""
|
2015-05-12 18:06:31 +10:00
|
|
|
:return: a new preview collection.
|
|
|
|
:rtype: :class:`ImagePreviewCollection`
|
2015-05-11 16:29:12 +02:00
|
|
|
"""
|
|
|
|
|
2015-05-12 18:06:31 +10:00
|
|
|
return ImagePreviewCollection()
|
2015-05-11 16:29:12 +02:00
|
|
|
|
|
|
|
|
2015-05-12 18:06:31 +10:00
|
|
|
def remove(pcoll):
|
2015-05-11 16:29:12 +02:00
|
|
|
"""
|
|
|
|
Remove the specified previews collection.
|
2015-05-12 18:06:31 +10:00
|
|
|
|
|
|
|
:arg pcoll: Preview collection to close.
|
|
|
|
:type pcoll: :class:`ImagePreviewCollection`
|
2015-05-11 16:29:12 +02:00
|
|
|
"""
|
2015-05-12 18:06:31 +10:00
|
|
|
pcoll.close()
|
2015-05-11 16:29:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
# don't complain about resources on exit (only unregister)
|
|
|
|
import atexit
|
|
|
|
|
2015-05-17 17:17:02 +10:00
|
|
|
|
2015-05-11 16:29:12 +02:00
|
|
|
def exit_clear_warning():
|
2015-05-12 18:06:31 +10:00
|
|
|
del ImagePreviewCollection.__del__
|
2015-05-11 16:29:12 +02:00
|
|
|
|
2018-06-30 09:23:07 +02:00
|
|
|
|
2015-05-11 16:29:12 +02:00
|
|
|
atexit.register(exit_clear_warning)
|
|
|
|
del atexit, exit_clear_warning
|