Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-12-31 13:52:48 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-12-31 13:52:48 +0400
commit92cda885fcad3a8b03f57051e8bc417d6662c59c (patch)
tree84fb4bae6e18d77c4d3a733012b37e40a9ef37e0 /space_view3d_materials_utils.py
parent537ad49d2866838acf690891d0414a3b0d429adf (diff)
- make pep8 compliant
- fix error when a mesh had a None material - no need to set the object as avtive when assigning materials
Diffstat (limited to 'space_view3d_materials_utils.py')
-rw-r--r--space_view3d_materials_utils.py429
1 files changed, 218 insertions, 211 deletions
diff --git a/space_view3d_materials_utils.py b/space_view3d_materials_utils.py
index c34b01d7..39813c7a 100644
--- a/space_view3d_materials_utils.py
+++ b/space_view3d_materials_utils.py
@@ -29,36 +29,44 @@ bl_info = {
"blender": (2, 5, 6),
"api": 35324,
"location": "View3D > Q key",
- "description": "Menu of material tools (assign, select by etc) in the 3D View",
+ "description": "Menu of material tools (assign, select..) in the 3D View",
"warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
- "Scripts/3D interaction/Materials Utils",
- "tracker_url": "https://projects.blender.org/tracker/index.php?"\
- "func=detail&aid=22140",
+ "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
+ "Scripts/3D interaction/Materials Utils",
+ "tracker_url": "https://projects.blender.org/tracker/index.php?"
+ "func=detail&aid=22140",
"category": "3D View"}
"""
This script has several functions and operators... grouped for convenience
* assign material:
- offers the user a list of ALL the materials in the blend file and an additional "new" entry
- the chosen material will be assigned to all the selected objects in object mode.
-
+ offers the user a list of ALL the materials in the blend file and an
+ additional "new" entry the chosen material will be assigned to all the
+ selected objects in object mode.
+
in edit mode the selected faces get the selected material applied.
- if the user chose "new" the new material can be renamed using the "last operator" section of the toolbox
- After assigning the material "clean material slots" and "material to texface" are auto run to keep things tidy (see description bellow)
+ if the user chose "new" the new material can be renamed using the
+ "last operator" section of the toolbox.
+ After assigning the material "clean material slots" and
+ "material to texface" are auto run to keep things tidy
+ (see description bellow)
* select by material
- in object mode this offers the user a menu of all materials in the blend file
- any objects using the selected material will become selected, any objects without the material will be removed from selection.
-
- in edit mode: the menu offers only the materials attached to the current object. It will select the faces that use the material and deselect those that do not.
+ in object mode this offers the user a menu of all materials in the blend
+ file any objects using the selected material will become selected, any
+ objects without the material will be removed from selection.
+
+ in edit mode: the menu offers only the materials attached to the current
+ object. It will select the faces that use the material and deselect those
+ that do not.
* clean material slots
- for all selected objects any empty material slots or material slots with materials that are not used by the mesh faces will be removed.
+ for all selected objects any empty material slots or material slots with
+ materials that are not used by the mesh faces will be removed.
-* Any un-used materials and slots will be removed
+* Any un-used materials and slots will be removed
"""
@@ -66,92 +74,92 @@ import bpy
from bpy.props import*
-def replace_material(m1 , m2, all_objects = False):
- #replace material named m1 with material named m2
- #m1 is the name of original material
- #m2 is the name of the material to replace it with
- #'all' will replace throughout the blend file
- try:
- matorg = bpy.data.materials[m1]
- matrep = bpy.data.materials[m2]
-
-
+def replace_material(m1, m2, all_objects=False):
+ # replace material named m1 with material named m2
+ # m1 is the name of original material
+ # m2 is the name of the material to replace it with
+ # 'all' will replace throughout the blend file
+
+ matorg = bpy.data.materials.get(m1)
+ matrep = bpy.data.materials.get(m2)
+
+ if matorg and matrep:
#store active object
scn = bpy.context.scene
ob_active = bpy.context.active_object
-
+
if all_objects:
objs = bpy.data.objects
-
+
else:
objs = bpy.context.selected_editable_objects
-
+
for ob in objs:
if ob.type == 'MESH':
scn.objects.active = ob
- print(ob.name)
- ms = ob.material_slots.values()
-
- for m in ms:
+
+ for m in ob.material_slots.values():
if m.material == matorg:
m.material = matrep
- #don't break the loop as the material can be
+ # don't break the loop as the material can be
# ref'd more than once
-
- #restore active object
- scn.objects.active = ob_active
- except:
+
+ else:
print('no match to replace')
-def select_material_by_name(find_mat):
- #in object mode selects all objects with material find_mat
- #in edit mode selects all faces with material find_mat
-
+
+def select_material_by_name(find_mat_name):
+ #in object mode selects all objects with material find_mat_name
+ #in edit mode selects all faces with material find_mat_name
+
+ find_mat = bpy.data.materials.get(find_mat_name)
+
+ if find_mat is None:
+ return
+
#check for editmode
editmode = False
scn = bpy.context.scene
-
+
#set selection mode to faces
- scn.tool_settings.mesh_select_mode =[False,False,True]
-
+ scn.tool_settings.mesh_select_mode = False, False, True
+
actob = bpy.context.active_object
if actob.mode == 'EDIT':
- editmode =True
+ editmode = True
bpy.ops.object.mode_set()
-
-
+
if not editmode:
- objs = bpy.data.objects
+ objs = bpy.data.objects
for ob in objs:
- typ = ['MESH','CURVE', 'SURFACE', 'FONT', 'META']
- if ob.type in typ:
+ if ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META'}:
ms = ob.material_slots.values()
for m in ms:
- if m.material.name == find_mat:
+ if m.material == find_mat:
ob.select = True
- #the active object may not have the mat!
- #set it to one that does!
+ # the active object may not have the mat!
+ # set it to one that does!
scn.objects.active = ob
break
else:
ob.select = False
-
- #deselect non-meshes
+
+ #deselect non-meshes
else:
ob.select = False
-
+
else:
#it's editmode, so select the faces
ob = actob
ms = ob.material_slots.values()
-
+
#same material can be on multiple slots
- slot_indeces =[]
+ slot_indeces = []
i = 0
# found = False # UNUSED
for m in ms:
- if m.material.name == find_mat:
+ if m.material == find_mat:
slot_indeces.append(i)
# found = True # UNUSED
i += 1
@@ -161,29 +169,30 @@ def select_material_by_name(find_mat):
f.select = True
else:
f.select = False
- me.update()
+ me.update()
if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
+
def mat_to_texface():
- #assigns the first image in each material to the faces in the active uvlayer
- #for all selected objects
-
+ # assigns the first image in each material to the faces in the active
+ # uvlayer for all selected objects
+
#check for editmode
editmode = False
-
+
actob = bpy.context.active_object
if actob.mode == 'EDIT':
- editmode =True
+ editmode = True
bpy.ops.object.mode_set()
-
+
for ob in bpy.context.selected_editable_objects:
if ob.type == 'MESH':
#get the materials from slots
ms = ob.material_slots.values()
-
+
#build a list of images, one per material
- images=[]
+ images = []
#get the textures from the mats
for m in ms:
gotimage = False
@@ -195,17 +204,16 @@ def mat_to_texface():
if tex.type == 'IMAGE':
img = tex.image
images.append(img)
- gotimage =True
+ gotimage = True
break
-
+
if not gotimage:
print('noimage on', m.name)
images.append(None)
-
- #now we have the images
- #applythem to the uvlayer
-
-
+
+ # now we have the images
+ # applythem to the uvlayer
+
me = ob.data
#got uvs?
if not me.uv_textures:
@@ -213,7 +221,7 @@ def mat_to_texface():
scn.objects.active = ob
bpy.ops.mesh.uv_texture_add()
scn.objects.active = actob
-
+
#get active uvlayer
for t in me.uv_textures:
if t.active:
@@ -224,14 +232,12 @@ def mat_to_texface():
uvtex[f.index].image = images[f.material_index]
else:
uvtex[f.index].image = None
-
+
me.update()
-
-
+
if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-
+ bpy.ops.object.mode_set(mode='EDIT')
+
def assignmatslots(ob, matlist):
#given an object and a list of material names
@@ -246,15 +252,14 @@ def assignmatslots(ob, matlist):
for s in ob.material_slots:
bpy.ops.object.material_slot_remove()
-
- #re-add them and assign material
+ # re-add them and assign material
i = 0
for m in matlist:
mat = bpy.data.materials[m]
ob.data.materials.append(mat)
i += 1
- #restore active object:
+ # restore active object:
scn.objects.active = ob_active
@@ -263,52 +268,49 @@ def cleanmatslots():
editmode = False
actob = bpy.context.active_object
if actob.mode == 'EDIT':
- editmode =True
+ editmode = True
bpy.ops.object.mode_set()
-
objs = bpy.context.selected_editable_objects
-
+
for ob in objs:
if ob.type == 'MESH':
mats = ob.material_slots.keys()
-
+
#check the faces on the mesh to build a list of used materials
- usedMatIndex =[] #we'll store used materials indices here
- faceMats =[]
+ usedMatIndex = [] # we'll store used materials indices here
+ faceMats = []
me = ob.data
for f in me.faces:
#get the material index for this face...
faceindex = f.material_index
-
+
#indices will be lost: Store face mat use by name
currentfacemat = mats[faceindex]
faceMats.append(currentfacemat)
-
-
- #check if index is already listed as used or not
+
+ # check if index is already listed as used or not
found = 0
for m in usedMatIndex:
if m == faceindex:
found = 1
#break
-
+
if found == 0:
- #add this index to the list
+ #add this index to the list
usedMatIndex.append(faceindex)
-
+
#re-assign the used mats to the mesh and leave out the unused
ml = []
mnames = []
for u in usedMatIndex:
- ml.append( mats[u] )
+ ml.append(mats[u])
#we'll need a list of names to get the face indices...
mnames.append(mats[u])
-
+
assignmatslots(ob, ml)
-
-
- #restore face indices:
+
+ # restore face indices:
i = 0
for f in me.faces:
matindex = mnames.index(faceMats[i])
@@ -316,81 +318,73 @@ def cleanmatslots():
i += 1
if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
-
-
-
+ bpy.ops.object.mode_set(mode='EDIT')
-def assign_mat(matname="Default"):
- #get active object so we can restore it later
+def assign_mat(matname="Default"):
+ # get active object so we can restore it later
actob = bpy.context.active_object
-
- #check if material exists, if it doesn't then create it
- mats =bpy.data.materials
+
+ # check if material exists, if it doesn't then create it
found = False
- for m in mats:
+ for m in bpy.data.materials:
if m.name == matname:
target = m
found = True
break
if not found:
target = bpy.data.materials.new(matname)
-
-
- #if objectmode then set all faces
+
+ # if objectmode then set all faces
editmode = False
allfaces = True
if actob.mode == 'EDIT':
- editmode =True
- allfaces = False
+ editmode = True
+ allfaces = False
bpy.ops.object.mode_set()
-
+
objs = bpy.context.selected_editable_objects
-
- for ob in objs:
- #set the active object to our object
+
+ for ob in objs:
+ # set the active object to our object
scn = bpy.context.scene
scn.objects.active = ob
-
-
- other = ['CURVE', 'SURFACE', 'FONT', 'META']
- if ob.type in other:
- found=False
+
+ if ob.type in {'CURVE', 'SURFACE', 'FONT', 'META'}:
+ found = False
i = 0
- mats = bpy.data.materials
- for m in mats:
+ for m in bpy.data.materials:
if m.name == matname:
- found =True
+ found = True
index = i
break
i += 1
if not found:
- index = i-1
- targetlist =[index]
+ index = i - 1
+ targetlist = [index]
assignmatslots(ob, targetlist)
-
- elif ob.type =='MESH':
- #check material slots for matname material
- found=False
+
+ elif ob.type == 'MESH':
+ # check material slots for matname material
+ found = False
i = 0
mats = ob.material_slots
for m in mats:
if m.name == matname:
- found =True
+ found = True
index = i
#make slot active
ob.active_material_index = i
break
i += 1
-
+
if not found:
- index=i
- #the material is not attached to the object
- ob.data.materials.append(target)
-
+ index = i
+ #the material is not attached to the object
+ ob.data.materials.append(target)
+
#now assign the material:
- me =ob.data
+ me = ob.data
if allfaces:
for f in me.faces:
f.material_index = index
@@ -399,17 +393,14 @@ def assign_mat(matname="Default"):
if f.select:
f.material_index = index
me.update()
-
-
#restore the active object
bpy.context.scene.objects.active = actob
if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
-
-def check_texture(img,mat):
+def check_texture(img, mat):
#finds a texture from an image
#makes a texture if needed
#adds it to the material if it isn't there already
@@ -434,11 +425,12 @@ def check_texture(img,mat):
mtex.texture_coords = 'UV'
mtex.use_map_color_diffuse = True
+
def texface_to_mat():
# editmode check here!
editmode = False
ob = bpy.context.object
- if ob.mode =='EDIT':
+ if ob.mode == 'EDIT':
editmode = True
bpy.ops.object.mode_set()
@@ -446,11 +438,11 @@ def texface_to_mat():
faceindex = []
unique_images = []
-
+
# get the texface images and store indices
if (ob.data.uv_textures):
for f in ob.data.uv_textures.active.data:
- if f.image:
+ if f.image:
img = f.image
#build list of unique images
if img not in unique_images:
@@ -459,30 +451,26 @@ def texface_to_mat():
else:
img = None
- faceindex.append(None)
-
-
+ faceindex.append(None)
- #check materials for images exist; create if needed
+ # check materials for images exist; create if needed
matlist = []
for i in unique_images:
if i:
- print(i.name)
try:
m = bpy.data.materials[i.name]
-
except:
- m = bpy.data.materials.new(name = i.name)
+ m = bpy.data.materials.new(name=i.name)
continue
finally:
matlist.append(m.name)
# add textures if needed
- check_texture(i,m)
+ check_texture(i, m)
- #set up the object material slots
+ # set up the object material slots
assignmatslots(ob, matlist)
-
+
#set texface indices to material slot indices..
me = ob.data
@@ -492,11 +480,11 @@ def texface_to_mat():
me.faces[i].material_index = f
i += 1
if editmode:
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
-#operator classes:
-#---------------------------------------------------------------------
+# -----------------------------------------------------------------------------
+# operator classes:
class VIEW3D_OT_texface_to_material(bpy.types.Operator):
''''''
@@ -513,19 +501,24 @@ class VIEW3D_OT_texface_to_material(bpy.types.Operator):
texface_to_mat()
return {'FINISHED'}
else:
- self.report({'WARNING'}, "No editable selected objects, could not finish")
+ self.report({'WARNING'},
+ "No editable selected objects, could not finish")
return {'CANCELLED'}
+
class VIEW3D_OT_assign_material(bpy.types.Operator):
'''assign a material to the selection'''
bl_idname = "view3d.assign_material"
bl_label = "MW Assign Material"
bl_options = {'REGISTER', 'UNDO'}
- matname = StringProperty(name = 'Material Name',
- description = 'Name of Material to Assign',
- default = "", maxlen = 21)
-
+ matname = StringProperty(
+ name='Material Name',
+ description='Name of Material to Assign',
+ default="",
+ maxlen=21,
+ )
+
@classmethod
def poll(cls, context):
return context.active_object != None
@@ -538,8 +531,9 @@ class VIEW3D_OT_assign_material(bpy.types.Operator):
mat_to_texface()
return {'FINISHED'}
+
class VIEW3D_OT_clean_material_slots(bpy.types.Operator):
- '''removes any material slots from the
+ '''removes any material slots from the
selected objects that are not used by the mesh'''
bl_idname = "view3d.clean_material_slots"
bl_label = "MW Clean Material Slots"
@@ -553,6 +547,7 @@ class VIEW3D_OT_clean_material_slots(bpy.types.Operator):
cleanmatslots()
return {'FINISHED'}
+
class VIEW3D_OT_material_to_texface(bpy.types.Operator):
''''''
bl_idname = "view3d.material_to_texface"
@@ -567,14 +562,17 @@ class VIEW3D_OT_material_to_texface(bpy.types.Operator):
mat_to_texface()
return {'FINISHED'}
+
class VIEW3D_OT_select_material_by_name(bpy.types.Operator):
''''''
bl_idname = "view3d.select_material_by_name"
bl_label = "MW Select Material By Name"
bl_options = {'REGISTER', 'UNDO'}
- matname = StringProperty(name = 'Material Name',
- description = 'Name of Material to Select',
- default = "", maxlen = 21)
+ matname = StringProperty(
+ name='Material Name',
+ description='Name of Material to Select',
+ maxlen=21,
+ )
@classmethod
def poll(cls, context):
@@ -592,18 +590,21 @@ class VIEW3D_OT_replace_material(bpy.types.Operator):
bl_label = "MW Replace Material"
bl_options = {'REGISTER', 'UNDO'}
- matorg = StringProperty(name = 'Material to Replace',
- description = 'Name of Material to Assign',
- default = "", maxlen = 21)
-
- matrep = StringProperty(name = 'Replacement material',
- description = 'Name of Material to Assign',
- default = "", maxlen = 21)
+ matorg = StringProperty(
+ name='Material to Replace',
+ description="Name of Material to Assign",
+ maxlen=21,
+ )
+ matrep = StringProperty(name="Replacement material",
+ description='Name of Material to Assign',
+ maxlen=21,
+ )
+ all_objects = BoolProperty(
+ name="all_objects",
+ description="replace for all objects in this blend file",
+ default=True,
+ )
- all_objects = BoolProperty(name ='all_objects',
- description="replace for all objects in this blend file",
- default = True)
-
@classmethod
def poll(cls, context):
return context.active_object != None
@@ -612,11 +613,13 @@ class VIEW3D_OT_replace_material(bpy.types.Operator):
m1 = self.matorg
m2 = self.matrep
all = self.all_objects
- replace_material(m1,m2,all)
+ replace_material(m1, m2, all)
return {'FINISHED'}
-#menu classes
-#-------------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# menu classes
+
class VIEW3D_MT_master_material(bpy.types.Menu):
bl_label = "Master Material Menu"
@@ -627,17 +630,20 @@ class VIEW3D_MT_master_material(bpy.types.Menu):
layout.menu("VIEW3D_MT_assign_material", icon='ZOOMIN')
layout.menu("VIEW3D_MT_select_material", icon='HAND')
layout.separator()
- layout.operator("view3d.clean_material_slots",
- text = 'Clean Material Slots', icon='CANCEL')
+ layout.operator("view3d.clean_material_slots",
+ text='Clean Material Slots',
+ icon='CANCEL')
layout.operator("view3d.material_to_texface",
- text = 'Material to Texface',icon='FACESEL_HLT')
+ text='Material to Texface',
+ icon='FACESEL_HLT')
layout.operator("view3d.texface_to_material",
- text = 'Texface to Material',icon='FACESEL_HLT')
+ text="Texface to Material",
+ icon='FACESEL_HLT')
layout.separator()
- layout.operator("view3d.replace_material",
- text = 'Replace Material', icon='ARROW_LEFTRIGHT')
-
+ layout.operator("view3d.replace_material",
+ text='Replace Material',
+ icon='ARROW_LEFTRIGHT')
class VIEW3D_MT_assign_material(bpy.types.Menu):
@@ -646,14 +652,15 @@ class VIEW3D_MT_assign_material(bpy.types.Menu):
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- for i in range (len(bpy.data.materials)):
-
+ for material_name in bpy.data.materials.keys():
layout.operator("view3d.assign_material",
- text=bpy.data.materials[i].name,
- icon='MATERIAL_DATA').matname = bpy.data.materials[i].name
+ text=material_name,
+ icon='MATERIAL_DATA').matname = material_name
+
+ layout.operator("view3d.assign_material",
+ text="Add New",
+ icon='ZOOMIN')
- layout.operator("view3d.assign_material",text="Add New",
- icon='ZOOMIN')
class VIEW3D_MT_select_material(bpy.types.Menu):
bl_label = "Select by Material"
@@ -666,30 +673,31 @@ class VIEW3D_MT_select_material(bpy.types.Menu):
layout.label
if ob.mode == 'OBJECT':
#show all used materials in entire blend file
- for i in range (len(bpy.data.materials)):
- if bpy.data.materials[i].users > 0:
+ for material_name, material in bpy.data.materials.items():
+ if material.users > 0:
layout.operator("view3d.select_material_by_name",
- text=bpy.data.materials[i].name,
- icon='MATERIAL_DATA').matname = bpy.data.materials[i].name
-
+ text=material_name,
+ icon='MATERIAL_DATA',
+ ).matname = material_name
elif ob.mode == 'EDIT':
#show only the materials on this object
mats = ob.material_slots.keys()
for m in mats:
layout.operator("view3d.select_material_by_name",
- text=m,
+ text=m,
icon='MATERIAL_DATA').matname = m
def register():
bpy.utils.register_module(__name__)
-
+
kc = bpy.context.window_manager.keyconfigs.addon
km = kc.keymaps.new(name="3D View", space_type="VIEW_3D")
kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS')
kmi.properties.name = "VIEW3D_MT_master_material"
+
def unregister():
bpy.utils.unregister_module(__name__)
@@ -697,10 +705,9 @@ def unregister():
km = kc.keymaps["3D View"]
for kmi in km.keymap_items:
if kmi.idname == 'wm.call_menu':
- if kmi.properties.name == "VIEW3D_MT_master_material":
+ if kmi.properties.name == "VIEW3D_MT_master_material":
km.keymap_items.remove(kmi)
break
if __name__ == "__main__":
register()
-