Skip to content

Instantly share code, notes, and snippets.

@eliemichel
Last active September 24, 2018 15:11
Show Gist options
  • Save eliemichel/a2d81db737b5a1e3eb297c4b5b90b5bb to your computer and use it in GitHub Desktop.
Save eliemichel/a2d81db737b5a1e3eb297c4b5b90b5bb to your computer and use it in GitHub Desktop.
"""
Transfer material data from active to selected objects.
If the active object is a group instance, recurse over its elements and match
destination by name (object selection is then ignored).
Copyright (c) 2018 -- Elie Michel
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the “Software”), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software is provided “as is”, without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose and noninfringement. In no event shall the
authors or copyright holders be liable for any claim, damages or other
liability, whether in an action of contract, tort or otherwise, arising from,
out of or in connection with the software or the use or other dealings in the
Software.
"""
bl_info = {
"name": "Transfer Material",
"author": "Elie Michel",
"version": (1, 0),
"blender": (2, 79, 0),
"location": "View3D > Object",
"description": "Transfer material data from active to selected objects",
"warning": "",
"wiki_url": "",
"category": "Object",
}
import bpy
from bpy.types import Operator
# -----------------------------------------------------------------------------
def transferMaterialsFromObject(context, from_obj, to_obj):
"""Transfer material data from active to selected object."""
if from_obj == to_obj:
return
context.scene.objects.active = to_obj
# Remove current materials from destination object
while len(to_obj.material_slots) > 0:
bpy.ops.object.material_slot_remove()
# Copy material slots
for i, slot in enumerate(from_obj.material_slots):
bpy.ops.object.material_slot_add()
to_obj.material_slots[i].material = slot.material
# Copy individual faces' material indices, assuming that the objects have
# the same topology
for from_poly, to_poly in zip(from_obj.data.polygons, to_obj.data.polygons):
to_poly.material_index = from_poly.material_index
def transferMaterialsFromGroup(context, from_group):
"""Recurse over its elements and match destination by name (object selection
is then ignored)."""
warnings = []
scene = context.scene
for from_obj in from_group.objects:
name = from_obj.name
if name not in scene.objects:
warnings.append("Object found in surf but not in rig: {}".format(name))
continue
to_obj = scene.objects[name]
transferMaterialsFromObject(context, from_obj, to_obj)
if warnings:
print("WARNINGS:\n" + "\n".join(warnings))
# -----------------------------------------------------------------------------
class TransferMaterialsOperator(Operator):
"""Transfer material data from active to selected object.
If the active object is a group instance, recurse over its elements and
match destination by name (object selection is then ignored)."""
bl_idname = "object.transfer_materials"
bl_label = "Transfer Materials"
@classmethod
def poll(cls, context):
return context.mode == 'OBJECT' and context.active_object is not None
def execute(self, context):
active = context.scene.objects.active
if active.type == 'EMPTY' and active.dupli_type == 'GROUP':
transferMaterialsFromGroup(context, active.dupli_group)
elif active.type == 'MESH':
for selected in context.selected_objects:
transferMaterialsFromObject(context, active, selected)
# Restore active object
context.scene.objects.active = active
return {'FINISHED'}
# -----------------------------------------------------------------------------
def register():
bpy.utils.register_class(TransferMaterialsOperator)
def unregister():
bpy.utils.unregister_class(TransferMaterialsOperator)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment