Files
blender-portable-repo/scripts/addons/easy_weight/utils.py
T
2026-03-17 14:58:51 -06:00

135 lines
4.4 KiB
Python

# SPDX-FileCopyrightText: 2025 Blender Studio Tools Authors
#
# SPDX-License-Identifier: GPL-3.0-or-later
import bpy
from bpy.types import PoseBone, Object, VertexGroup, Bone, EditBone
from . import __package__ as base_package
def get_addon_prefs(context=None):
if not context:
context = bpy.context
if base_package.startswith('bl_ext'):
# 4.2
return context.preferences.addons[base_package].preferences
else:
return context.preferences.addons[base_package.split(".")[0]].preferences
def poll_deformed_mesh_with_vgroups(operator, context, must_deform=True) -> bool:
obj = context.active_object
if not obj or obj.type != 'MESH':
operator.poll_message_set("No active mesh object.")
return False
if must_deform and ('ARMATURE' not in [m.type for m in obj.modifiers]):
operator.poll_message_set("This mesh is not deformed by an Armature modifier.")
return False
if not obj.vertex_groups:
operator.poll_message_set("This mesh has no vertex groups yet.")
return False
return True
def delete_vgroups(mesh_ob, vgroups: list[VertexGroup]):
for vgroup in vgroups:
mesh_ob.vertex_groups.remove(vgroup)
def get_deforming_vgroups(mesh_ob: Object, arm_ob: Object = None) -> list[VertexGroup]:
"""Get the vertex groups of a mesh object that correspond to a deform bone in the given armature."""
if not arm_ob:
arm_ob = get_deforming_armature(mesh_ob)
if not arm_ob:
return []
deforming_vgroups = []
for bone in arm_ob.data.bones:
if bone.name in mesh_ob.vertex_groups and bone.use_deform:
deforming_vgroups.append(mesh_ob.vertex_groups[bone.name])
return deforming_vgroups
def get_deforming_armature(mesh_ob: Object) -> Object | None:
"""Return first Armature modifier's target object."""
for mod in mesh_ob.modifiers:
if mod.type == 'ARMATURE':
return mod.object
def poll_weight_paint_mode(operator, context, with_rig=False, with_groups=False):
"""Function used for operator poll functions, ie. to determine whether
operators should be available or not."""
obj = context.active_object
if context.mode != 'PAINT_WEIGHT':
operator.poll_message_set("Must be in Weight Paint mode.")
return False
if with_rig:
if not 'ARMATURE' in (m.type for m in obj.modifiers):
operator.poll_message_set("This mesh is not deformed by an Armature modifier.")
return False
if not context.pose_object or context.pose_object != get_deforming_armature(obj):
operator.poll_message_set(
"Couldn't find deforming armature, or it is not in pose mode."
)
return False
if with_groups and not obj.vertex_groups:
operator.poll_message_set("This mesh object has no vertex groups yet.")
return False
return True
def reveal_bone(bone: Bone or EditBone or PoseBone, select=True):
"""Reveall and optionally select a bone, regardless of current
selection or visibility states.
"""
if type(bone) == PoseBone:
bone = bone.bone
armature = bone.id_data
if hasattr(armature, 'layers'):
# Blender 3.6 and below: Bone Layers.
enabled_layers = [i for i in range(32) if armature.layers[i]]
# If none of this bone's layers are enabled, enable the first one.
bone_layers = [i for i in range(32) if bone.layers[i]]
if not any([i in enabled_layers for i in bone_layers]):
armature.layers[bone_layers[0]] = True
else:
# Blender 4.0 and above: Bone Collections.
ensure_visible_bone_collection(bone)
bone.hide = False
if select:
bone.select = True
def ensure_visible_bone_collection(bone: Bone or EditBone or PoseBone):
"""If target bone not in any enabled collections, enable first one."""
# NOTE: This function was lifted from CloudRig.
if type(bone) == PoseBone:
bone = bone.bone
armature = bone.id_data
collections = armature.collections
if len(bone.collections) == 0:
return
if not any([coll.is_visible_effectively for coll in bone.collections]):
coll = bone.collections[0]
while coll:
if collections.is_solo_active:
coll.is_solo = True
else:
coll.is_visible = True
coll = coll.parent