Skip to content

Instantly share code, notes, and snippets.

@sambler
Created July 12, 2017 10:36
Show Gist options
  • Save sambler/19729b3381f036832683ace3d712611c to your computer and use it in GitHub Desktop.
Save sambler/19729b3381f036832683ace3d712611c to your computer and use it in GitHub Desktop.
Show image usage and provide way to clear it.
# made for https://blender.stackexchange.com/q/84328/935
# show places in blender where an image is in use.
# also provide a way to clear the usage of the images.
import bpy
bl_info = {
"name": "Find image users",
"author": "sambler",
"version": (1, 0),
"blender": (2, 75, 0),
"location": "blender",
"description": "Find users of an image.",
"warning": "Only testing",
"category": "Test",
}
import bpy
class ClearAllBackgroundImages(bpy.types.Operator):
bl_idname = 'image.clear_all_background_images'
bl_label = 'Clear the use of all 3DView background images'
def execute(self, context):
for scr in bpy.data.screens:
for a in scr.areas:
for sp in a.spaces:
if sp.type == 'VIEW_3D':
for bi in sp.background_images:
bi.image = None
return {'FINISHED'}
class ClearAllBrushImages(bpy.types.Operator):
bl_idname = 'image.clear_all_brush_images'
bl_label = 'Clear the use of all images by brushes'
def execute(self, context):
for b in bpy.data.brushes:
b.texture.image = None
return {'FINISHED'}
class ClearAllEmptyImages(bpy.types.Operator):
bl_idname = 'image.clear_all_empty_images'
bl_label = 'Clear the use of all empties displaying images'
def execute(self, context):
for o in bpy.data.objects:
if o.type == 'EMPTY':
o.data = None
return {'FINISHED'}
class ClearAllImageEditorImages(bpy.types.Operator):
bl_idname = 'image.clear_all_image_editor_images'
bl_label = 'Clear active images in UV/Image editors'
def execute(self, context):
for scr in bpy.data.screens:
for a in scr.areas:
for sp in a.spaces:
if sp.type == 'IMAGE_EDITOR':
sp.image = None
return {'FINISHED'}
class ClearAllCompositorNodeImages(bpy.types.Operator):
bl_idname = 'image.clear_all_compositor_images'
bl_label = 'Clear images used in the compositor'
def execute(self, context):
for scn in bpy.data.scenes:
if scn.use_nodes:
for n in scn.node_tree.nodes:
if n.type == 'IMAGE':
n.image = None
return {'FINISHED'}
class ClearAllCyclesMaterialImages(bpy.types.Operator):
bl_idname = 'image.clear_all_cycles_material_images'
bl_label = 'Clear images used in cycles materials'
def execute(self, context):
for m in bpy.data.materials:
if m.use_nodes:
for n in m.node_tree.nodes:
if n.type == 'TEX_IMAGE':
n.image = None
return {'FINISHED'}
class ClearAllTextureImages(bpy.types.Operator):
bl_idname = 'image.clear_all_texture_images'
bl_label = 'Clear the use of all images by textures'
def execute(self, context):
for t in bpy.data.textures:
t.image = None
return {'FINISHED'}
def show_background_use(layout, img):
in_use = False
for scr in bpy.data.screens:
for a in scr.areas:
for sp in a.spaces:
if sp.type == 'VIEW_3D':
for bi in sp.background_images:
if bi.image == img:
in_use = True
row = layout.row()
row.label(text='{} -- View {}'.format(
scr.name, bi.view_axis))
if not in_use:
row = layout.row()
row.label(text='None')
return in_use
def show_compositor_use(layout, img):
in_use = False
for scn in bpy.data.scenes:
if scn.use_nodes:
for n in scn.node_tree.nodes:
if n.type == 'IMAGE' and n.image == img:
in_use = True
row = layout.row()
row.label(text='Compositor '+n.name)
if not in_use:
row = layout.row()
row.label(text='None')
return in_use
def show_cycles_material_use(layout, img):
in_use = False
for m in bpy.data.materials:
if m.use_nodes:
for n in m.node_tree.nodes:
if n.type == 'TEX_IMAGE' and n.image == img:
in_use = True
row = layout.row()
row.label(text=m.name)
if not in_use:
row = layout.row()
row.label(text='None')
return in_use
def show_uvimage_editor_use(layout, img):
in_use = False
for scr in bpy.data.screens:
for a in scr.areas:
for sp in a.spaces:
if sp.type == 'IMAGE_EDITOR':
if sp.image == img:
in_use = True
row = layout.row()
row.label(text=scr.name)
if not in_use:
row = layout.row()
row.label(text='None')
return in_use
class ShowImageUsers(bpy.types.Panel):
bl_idname = 'IMAGE_PT_show_users'
bl_label = 'Image Users'
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
def draw(self, context):
layout = self.layout
img = context.space_data.image
if img == None:
box = layout.box()
box.label(text='No image active!')
return
if img.type != 'RENDER_RESULT' and img.type != 'COMPOSITING':
box = layout.box()
box.label(text='3DView backgrounds')
if show_background_use(layout, img):
box.operator(ClearAllBackgroundImages.bl_idname, text='Clear All')
box = layout.box()
box.label(text='Empties with image')
in_use = False
for o in bpy.data.objects:
if o.type == 'EMPTY' and o.data == img:
in_use = True
row = layout.row()
row.label(text=o.name)
if not in_use:
row = layout.row()
row.label(text='None')
else:
box.operator(ClearAllEmptyImages.bl_idname, text='Clear All')
box = layout.box()
box.label(text='Textures with image')
in_use = False
for t in bpy.data.textures:
if t.image == img:
in_use = True
row = layout.row()
row.label(text=t.name)
if not in_use:
row = layout.row()
row.label(text='None')
else:
box.operator(ClearAllTextureImages.bl_idname, text='Clear All')
box = layout.box()
box.label(text='Cycles Materials with image')
if show_cycles_material_use(layout, img):
box.operator(ClearAllCyclesMaterialImages.bl_idname, text='Clear All')
box = layout.box()
box.label(text='Compositor image nodes')
if show_compositor_use(layout, img):
box.operator(ClearAllCompositorNodeImages.bl_idname, text='Clear All')
box = layout.box()
box.label(text='UV/Image Editors')
if show_uvimage_editor_use(layout, img):
box.operator(ClearAllImageEditorImages.bl_idname, text='Clear All')
def register():
bpy.utils.register_class(ClearAllBackgroundImages)
bpy.utils.register_class(ClearAllBrushImages)
bpy.utils.register_class(ClearAllCompositorNodeImages)
bpy.utils.register_class(ClearAllCyclesMaterialImages)
bpy.utils.register_class(ClearAllEmptyImages)
bpy.utils.register_class(ClearAllImageEditorImages)
bpy.utils.register_class(ClearAllTextureImages)
bpy.utils.register_class(ShowImageUsers)
def unregister():
bpy.utils.unregister_class(ShowImageUsers)
bpy.utils.unregister_class(ClearAllBackgroundImages)
bpy.utils.unregister_class(ClearAllBrushImages)
bpy.utils.unregister_class(ClearAllCompositorNodeImages)
bpy.utils.unregister_class(ClearAllCyclesMaterialImages)
bpy.utils.unregister_class(ClearAllEmptyImages)
bpy.utils.unregister_class(ClearAllImageEditorImages)
bpy.utils.unregister_class(ClearAllTextureImages)
if __name__ == "__main__":
register()
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
@Azraelushka
Copy link

Azraelushka commented Sep 17, 2018

Hi! Can you kindly explain how to use it? I've installed it as an add-on, but can't find any interface. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment