@@ -1676,6 +1676,93 @@ def execute(self, context):
16761676
16771677 return {'FINISHED' }
16781678
1679+ # Copy each modifier from the source - copies references and links modifiers - not working
1680+ def copy_mask_modifiers (layer , source_mask , target_mask ):
1681+ for mod in source_mask .modifiers :
1682+ new_mod = target_mask .modifiers .add ()
1683+ for attr in dir (mod ):
1684+ if attr .startswith ("_" ) or callable (getattr (mod , attr )):
1685+ continue
1686+ try :
1687+ setattr (new_mod , attr , getattr (mod , attr ))
1688+ except Exception :
1689+ pass
1690+
1691+ class YDuplicateLayerMask (bpy .types .Operator ):
1692+ bl_idname = "wm.y_duplicate_layer_mask"
1693+ bl_label = "Duplicate Layer Mask"
1694+ bl_description = "Duplicate the selected layer mask"
1695+ bl_options = {'REGISTER' , 'UNDO' }
1696+
1697+ @classmethod
1698+ def poll (cls , context ):
1699+ return hasattr (context , 'mask' ) and hasattr (context , 'layer' )
1700+
1701+ def execute (self , context ):
1702+ layer = context .layer
1703+ mask = context .mask
1704+ obj = context .object
1705+
1706+ tree = get_tree (layer )
1707+ source_node = tree .nodes .get (mask .source ) if hasattr (mask , 'source' ) else None
1708+ image = source_node .image if source_node and hasattr (source_node , 'image' ) else None
1709+
1710+ new_name = mask .name + "_Copy"
1711+
1712+ try :
1713+ new_mask = add_new_mask (
1714+ layer = layer ,
1715+ name = new_name ,
1716+ mask_type = mask .type ,
1717+ texcoord_type = mask .texcoord_type ,
1718+ uv_name = mask .uv_name ,
1719+ image = image ,
1720+ vcol = getattr (mask , 'vcol_name' , None ),
1721+ segment = getattr (mask , 'segment_name' , None ),
1722+ object_index = mask .object_index ,
1723+ blend_type = mask .blend_type ,
1724+ hemi_space = mask .hemi_space ,
1725+ hemi_use_prev_normal = mask .hemi_use_prev_normal ,
1726+ color_id = mask .color_id ,
1727+ source_input = mask .source_input ,
1728+ edge_detect_radius = mask .edge_detect_radius ,
1729+ modifier_type = getattr (mask , 'modifier_type' , 'INVERT' ),
1730+ interpolation = getattr (source_node , 'interpolation' , 'Linear' ) if source_node else 'Linear' ,
1731+ ao_distance = mask .ao_distance
1732+ )
1733+
1734+ # Copy extra float/vector properties
1735+ new_mask .intensity_value = mask .intensity_value
1736+
1737+ # Transform
1738+ new_mask .translation = mask .translation [:]
1739+ new_mask .rotation = mask .rotation [:]
1740+ new_mask .scale = mask .scale [:]
1741+
1742+ #update?
1743+ update_mask_transform (new_mask , context )
1744+
1745+ # Blur vector settings
1746+ new_mask .enable_blur_vector = mask .enable_blur_vector
1747+ new_mask .blur_vector_factor = mask .blur_vector_factor
1748+
1749+ # Decal projection distance
1750+ new_mask .decal_distance_value = mask .decal_distance_value
1751+
1752+ # Copy channel enable states
1753+ for i , ch in enumerate (mask .channels ):
1754+ if i < len (new_mask .channels ):
1755+ new_mask .channels [i ].enable = ch .enable
1756+
1757+ #copy_mask_modifiers(layer, mask, new_mask)
1758+
1759+ #self.report({'INFO'}, f"ucupaint addon: Duplicated mask '{mask.name}' as '{new_mask.name}'")
1760+ return {'FINISHED' }
1761+
1762+ except Exception as e :
1763+ self .report ({'ERROR' }, f"ucupaint addon: Failed to duplicate mask: { e } " )
1764+ return {'CANCELLED' }
1765+
16791766class YRemoveLayerMask (bpy .types .Operator ):
16801767 bl_idname = "wm.y_remove_layer_mask"
16811768 bl_label = "Remove Layer Mask"
@@ -2648,6 +2735,7 @@ def register():
26482735 bpy .utils .register_class (YOpenImageAsMask )
26492736 bpy .utils .register_class (YOpenAvailableDataAsMask )
26502737 bpy .utils .register_class (YMoveLayerMask )
2738+ bpy .utils .register_class (YDuplicateLayerMask )
26512739 bpy .utils .register_class (YRemoveLayerMask )
26522740 bpy .utils .register_class (YReplaceMaskType )
26532741 bpy .utils .register_class (YFixEdgeDetectAO )
@@ -2659,6 +2747,7 @@ def unregister():
26592747 bpy .utils .unregister_class (YOpenImageAsMask )
26602748 bpy .utils .unregister_class (YOpenAvailableDataAsMask )
26612749 bpy .utils .unregister_class (YMoveLayerMask )
2750+ bpy .utils .unregister_class (YDuplicateLayerMask )
26622751 bpy .utils .unregister_class (YRemoveLayerMask )
26632752 bpy .utils .unregister_class (YReplaceMaskType )
26642753 bpy .utils .unregister_class (YFixEdgeDetectAO )
0 commit comments