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?
-
2Does this answer help? – sambler Jan 29 '17 at 18:53
2 Answers
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()
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
- 84,216
- 10
- 108
- 233
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()
- 2,660
- 12
- 17
