import bpy def popup_error(message: str): def _draw(self, context): self.layout.label(text=message) try: bpy.context.window_manager.popup_menu(_draw, title="HardHat", icon='ERROR') except Exception: print(f"ERROR: {message}") def selected_hair_meshes(): # Use stored scene targets if present (strict requirement per user preference) names = (bpy.context.scene.get('HH_HairTargets') or '').split(';') names = [n for n in names if n] if names: objs = [bpy.data.objects.get(n) for n in names] return [o for o in objs if o and o.type == 'MESH'] popup_error("No HardHat hair targets set. Click 'Set HardHat Hair Targets' first.") return [] def ensure_empty_vertex_group(obj, name): vg = obj.vertex_groups.get(name) if vg: # Clear existing by removing and recreating to guarantee emptiness obj.vertex_groups.remove(vg) return obj.vertex_groups.new(name=name) def ensure_full_vertex_group(obj, name): vg = obj.vertex_groups.get(name) if vg: obj.vertex_groups.remove(vg) vg = obj.vertex_groups.new(name=name) if obj.data.vertices: vg.add(range(len(obj.data.vertices)), 1.0, 'REPLACE') return vg def set_mask_modifiers(obj, main_name, hh_name): # Remove existing for m in list(obj.modifiers): if m.type == 'MASK' and m.name in {main_name, hh_name}: obj.modifiers.remove(m) m1 = obj.modifiers.new(name=main_name, type='MASK') m1.vertex_group = main_name m2 = obj.modifiers.new(name=hh_name, type='MASK') m2.vertex_group = hh_name return m1, m2 def run(): hair_objs = selected_hair_meshes() if not hair_objs: print("Error: Select hair mesh object(s) before running") return for obj in hair_objs: ensure_full_vertex_group(obj, 'MainMask') ensure_empty_vertex_group(obj, 'HHMask') set_mask_modifiers(obj, 'MainMask', 'HHMask') print(f"Prepared '{obj.name}': MainMask=all verts, HHMask=empty, mask modifiers created") print("hh_mask: Done. Assign weights to HHMask as needed.") run()