import bpy from bpy.props import StringProperty from bpy.types import PropertyGroup, UIList, Panel class FMT_PT_Panel(Panel): """Find missing texture panel""" bl_label = "Find missing textures" bl_idname = "FMT_PT_Panel" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" bl_category = "FMT" bl_icon = "OUTLINER_OB_HAIR" def invoke(self, context, event): bpy.context.scene.fmt_search_bars.add() def draw(self, context): scene = context.scene layout = self.layout row = layout.row() row.label(text=f"Bad images list: ({len(scene.fmt_list)} images)", icon ="LIBRARY_DATA_BROKEN") row = layout.row() row.template_list("List_View", "", scene, "fmt_list", scene, "fmt_list_index") row = layout.row() row.prop(bpy.context.scene, "fmt_select_bad_obj", text = "Select objects with bad textures") row = layout.row() row.scale_x = .3 row.operator("texture.remove_image", text = 'Delete selected image', icon ="TRASH") row.scale_x = .7 row.operator("texture.find_missing_textures", icon ="FILE_REFRESH") row = layout.row() if len(bpy.context.scene.fmt_list) > 0 and len(scene.fmt_search_bars) > 0: row.prop(bpy.context.scene, "fmt_extension_replace", text = "Search for images with different extension") row = layout.row() for bar_index in range (len(scene.fmt_search_bars)): row = layout.row() row.prop(scene.fmt_search_bars[bar_index], "bars", text ="Search path") row.operator("texture.bars", text = "", icon ="REMOVE").add = 'F'+ str(bar_index) row.operator("texture.bars", text = "", icon ="ADD").add = 'T' row = layout.row() row.operator("texture.folder_find", text = "Find textures in this folders", icon ="VIEWZOOM") class List_View(UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): custom_icon = 'OBJECT_DATAMODE' if self.layout_type in {'DEFAULT', 'COMPACT'}: path_scale = 0.7 layout.scale_x = 1 - path_scale layout.label(text=item.img_name) layout.scale_x = path_scale if not bpy.data.images[item.img_name].has_data: layout.prop(bpy.data.images[item.img_name], "filepath", text = "",icon="LIBRARY_DATA_BROKEN") else: layout.prop(bpy.data.images[item.img_name], "filepath", text = "",icon="IMAGE_DATA") elif self.layout_type in {'GRID'}: layout.alignment = 'CENTER' layout.label(text="", icon = custom_icon) class ListItem(PropertyGroup): """Group of properties representing an item in the list.""" img_name: StringProperty( name="Name", description="Name of the image", default="Non") class SearchBars(PropertyGroup): bars: StringProperty( name="Searching folder", subtype="DIR_PATH", description="Searching path for the images (folder and sub folders)", default="//")