1
$\begingroup$

How would I go about making a property box that contained all the materials in a scene (in a Toolshelf (T) panel for example) and is able to pass the material in the list to another operator that assigned the material that was selected in the property box?

$\endgroup$
1

2 Answers 2

1
$\begingroup$

Here is an example of how this can be achieved:

import bpy

def mat_update(self, context):
    ob = context.active_object
    mats = bpy.data.materials
    selected_mat = context.scene.mymats
    if selected_mat != 'None':
        if ob.data.materials:
            ob.data.materials[0] = mats[selected_mat]
        else:
            ob.data.materials.append(mats[selected_mat])

class MyListPanelExample(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_example"
    bl_space_type = 'VIEW_3D'
    bl_region_type = "TOOLS"
    bl_category = 'My Panel'

    @classmethod
    def poll(cls, context):
        return context.active_object is not None 

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

        obj = context.object
        row = layout.row()
        row.prop(context.scene, "mymats")

def register():
    def getsets(self, context):
        sets = []
        mats = bpy.data.materials
        for mat in mats:
            sets.append((mat.name, mat.name, mat.name))
        if not sets:
            sets = [('None', 'None', 'None')]
        return sets

    bpy.utils.register_module(__name__)
    bpy.types.Scene.mymats = bpy.props.EnumProperty(items=getsets, update=mat_update)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()
$\endgroup$
1
  • 1
    $\begingroup$ Rewrote the code because I read the question wrong. $\endgroup$
    – cmomoney
    Jan 29, 2017 at 21:11
4
$\begingroup$

Use pointers.

EDIT, having a property to keep the name, and use in a property search has IMO been superseded by assigning a pointer property with a poll in later (circa late 2.79 and beyond).

Example, select from and assign a property to a material of all non grease pencil materials in blend :

Custom search data to UILayout.prop_search


Finding only the materials in the scene would be doable (make a set of all materials of all objects in scene) but is probably not necessary, instead suggest using bpy.data.materials the list of all materials in the file.

EDIT: However have done this here How to populate UIList with all material slot in scene? 2.8

A UILayout.prop_search can be used as a UI to assign a material's name to a string property.

import bpy
from bpy.props import StringProperty

class LayoutDemoPanel(bpy.types.Panel):
    bl_label = "Set Active Material"
    bl_idname = "OBJECT_PT_example"
    bl_space_type = 'VIEW_3D'
    bl_region_type = "TOOLS"
    bl_category = 'Materials'

    @classmethod
    def poll(cls, context):
        return len(bpy.data.materials) > 0

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

        scene = context.scene

        layout.prop_search(scene,
                           "selected_mat",
                           bpy.data,
                           "materials")

def register():
    bpy.types.Scene.selected_mat = StringProperty(default="None")    
    bpy.utils.register_class(LayoutDemoPanel)


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


if __name__ == "__main__":
    register()

enter image description here

In an operator can use the property like so.

scene = context.scene
material = bpy.data.materials.get(scene.selected_mat)
if material is None:
    # no material has it been renamed?
    return {'CANCELLED'}
# do something with material
$\endgroup$

You must log in to answer this question.

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