How to update UI Panel based on selection of multiple objects?

Hello,

I would like to view materials of multiple selected objects simultaneously in a custom UI Panel (with an ability to change their name).
I already tried to edit ‘UI Panel Simple’ template to achieve this, sadly my py skills are not good enough.
How can I achieve this?

Mokup:
Objects are not selected:
image

Objects are selected:
image

Thank you,
ikakupa

I didn’t dig too much about being able to change the names from that panel, but here is a start to see the materials of the selected objects.

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

        boxframe = layout.box()
        col = boxframe.column(align=True)
        for ob in bpy.context.selected_objects:
            for slot in ob.material_slots:
                col.label (text = slot.name)
1 Like

Thank you @Ryxx,

This function lists all the selected materials, now I have this one part working:


I think renaming them in this Panel is not an easy task.


So after week of trying it myself, I found almost a readymade script from Blender Stackexchange:
python - How to compile template_list with some object in scene 2.8 - Blender Stack Exchange!

Changed from this:

def get_scene_materials(self):
    return set(s.material for o in self.objects
               for s in o.material_slots if s.material)

to this:

def get_scene_materials(self):
    c = bpy.context
    return set(s.material for o in c.selected_objects
               for s in o.material_slots if s.material)

Full Addon:

    bl_info = {
    "name": "Selected Materials",
    "author": "batFINGER, (edited by Iraki Kupunia)",
    "version": (1, 0),
    "blender": (2, 92, 0),
    "location": "View3D > UI > Item",
    "description": "List selected Materials",
    "warning": "",
    "doc_url": "https://blender.stackexchange.com/a/141207/15543",
    "category": "Materials",
}

import bpy
from bpy.types import PropertyGroup
from bpy.props import (
    CollectionProperty,
    IntProperty,
    BoolProperty,
    StringProperty,
    PointerProperty,
)

def get_update_materials(self):

    update = set(s.material for s in self.material_slots).symmetric_difference(self.materials)
    if update:
        set_update_materials(self, True)
    return False


def set_update_materials(self, value):
    if value:
        self.material_slots.clear() # update (or get) instead?
        for m in self.materials:
            s = self.material_slots.add()
            s.name = m.name
            s.material = m


def get_scene_materials(self):
    c = bpy.context
    return set(s.material for o in c.selected_objects  #only selected
               for s in o.material_slots if s.material)


class SceneMaterialSlot(PropertyGroup):
    def get_name(self):
        return getattr(self.material, "name", "")
    material: PointerProperty(type=bpy.types.Material)
    #name : StringProperty(get=get_name)


class MATERIAL_UL_extreme_matslot(bpy.types.UIList):

    def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
        ob = data
        slot = item
        ma = slot.material

        if self.layout_type in {'DEFAULT', 'COMPACT'}:
            if ma:
                layout.prop(ma, "name", text="", emboss=False, icon_value=layout.icon(ma))


class SceneMaterialsPanel(bpy.types.Panel):

    bl_label = "Selected Materials"#bl_info["name"]
    bl_idname = "SCENE_PT_materials"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Item"

    def draw(self, context):

        scn = context.scene
        layout = self.layout
        col = layout.column()
        if scn.update_materials:
            col.prop(scn, "update_materials", toggle=True, icon='FILE_REFRESH')
        col.template_list(
            "MATERIAL_UL_extreme_matslot",
            "",
            scn,
            "material_slots",
            scn,
            "active_material_index")


classes = (SceneMaterialSlot,
           MATERIAL_UL_extreme_matslot,
           SceneMaterialsPanel)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.materials = property(get_scene_materials)
    bpy.types.Scene.update_materials = BoolProperty(
        get=get_update_materials,
        set=set_update_materials,
        name="Update Scene Materials")
    bpy.types.Scene.active_material_index = IntProperty()
    bpy.types.Scene.material_slots = CollectionProperty(
        type=SceneMaterialSlot)


def unregister():
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)

    del bpy.types.Scene.active_material_index
    del bpy.types.Scene.material_slots


if __name__ == "__main__":
    register()
1 Like