I am trying to watch changes in the depsgraph so that ever time I assign a material to a mesh, all its sibling meshes (those that share a parent) are assigned the same color.
The way I do that is in the script below.
However, when I update a material one of these things happen (randomly as far as I can tell):
- the material gets updated on the mesh and all its siblings, and Blender crashes with the next update
- the material changes on the mesh and all its siblings, but into a black non-reflective material (I havent't checked if the material name is correct, and it just doesn't render)
- Blender crashes immediately
import bpy
import time
from bpy.app.handlers import persistent
from inspect import currentframe, getframeinfo, stack
mats = dict()
for obj in bpy.data.objects:
mats[obj.name] = obj.material_slots[0].material if obj.material_slots else None
def lprint(*args):
frameinfo = getframeinfo(stack()[1][0])
print(frameinfo.filename, frameinfo.lineno, *args)
def depsgraph_handler_post(scene, depsgraph):
updates = [ u for u in depsgraph.updates if u.is_updated_shading and type(u.id).__name__ == "Object" ]
siblings = []
mat = None
bpy.app.handlers.depsgraph_update_post.remove(depsgraph_handler_post)
bpy.app.handlers.depsgraph_update_pre.remove(depsgraph_handler_pre)
for update in updates:
try:
obj = update.id
mat = obj.material_slots[0].material
lprint("Post", type(obj).__name__, obj.name, mats[obj.name].name, mat.name)
mats[obj.name] = mat if obj.material_slots else None
parent = obj.parent
siblings = [ o.name for o in bpy.data.objects if o.parent and o.parent.name == parent.name and not o.name == obj.name ]
except Exception as err:
lprint("Post", err)
for name in siblings:
print(name)
obj = bpy.data.objects[name]
if len(obj.material_slots) == 0:
obj.data.materials.append(mat)
else:
obj.material_slots[0].material = mat
bpy.app.handlers.depsgraph_update_post.append(depsgraph_handler_post)
bpy.app.handlers.depsgraph_update_pre.append(depsgraph_handler_pre)
scene.render.use_lock_interface = False
def depsgraph_handler_pre(scene):
scene.render.use_lock_interface = True
bpy.app.handlers.depsgraph_update_post.append(depsgraph_handler_post)
bpy.app.handlers.depsgraph_update_pre.append(depsgraph_handler_pre)
I have managed to work around the problem in a semi-satisfactory way, but I would like to know what's going on here.