1
$\begingroup$

I'd like to replicate copying (CTRL+C) and pasting (CTRL+V) an object using Python, i.e. the copy should be identical, yet completely independent of the original (i.e., if I change something about the original, the copy should not be affected). While this is easy to achieve for some properties, by copying the object data or calling bpy.ops.object.make_single_user(type='SELECTED_OBJECTS', object=True, obdata=True, material=True, animation=True, obdata_animation=True), I did not find a way yet to do this for modifiers, such as geometry nodes. Is there an easy way to achieve this?

Thanks.

$\endgroup$
5
  • $\begingroup$ Nice question! I think it should be reported, if it's not. $\endgroup$
    – Crantisz
    Feb 1, 2022 at 9:06
  • $\begingroup$ Thanks for the comment. What exactly would you like to have reported? $\endgroup$
    – Nos
    Feb 1, 2022 at 9:14
  • 1
    $\begingroup$ try bpy.ops.node.copy_geometry_node_group_assign() $\endgroup$
    – relaxed
    Feb 1, 2022 at 10:03
  • $\begingroup$ @relaxed Thanks for the hint! Would you mind elaborating a little? The documentation of bpy.ops.node.copy_geometry_node_group_assign is a little sparse, as of now. $\endgroup$
    – Nos
    Feb 1, 2022 at 12:56
  • $\begingroup$ I don't have much more either. It´s is the same operator as in the middle of the header of Geometry Node Editor (files icon) where you can copy the active geometry node group and assign it to the active modifier in one step to make it a separate node group. Similar to the "New/Add" button in most data block menus. [docs.blender.org/manual/en/latest/interface/controls/templates/… $\endgroup$
    – relaxed
    Feb 1, 2022 at 15:37

1 Answer 1

2
$\begingroup$

Thanks to @relaxed, I found a solution that works for me, for the moment. However, be aware that there might be other data blocks (apart from node setups, particle settings and textures) that need to be copied as well.

def create_duplicate(object_: bpy.types.Object, 
                     duplicate_name: str, 
                     target_collection: bpy.types.Collection) -> bpy.types.Object:
    duplicate = object_.copy()
    duplicate.data = object_.data.copy()
    duplicate.name = duplicate_name
    
    target_collection.objects.link(duplicate)
    
    bpy.ops.object.select_all(action="DESELECT")
    bpy.context.view_layer.objects.active = duplicate
    duplicate.select_set(True)

    bpy.ops.object.make_single_user(object=True, 
                                    obdata=True, 
                                    material=True, 
                                    animation=True, 
                                    obdata_animation=True)
    
    for particle_system in duplicate.particle_systems:
        particle_system.settings = particle_system.settings.copy()

    for modifier in duplicate.modifiers:
        bpy.ops.object.modifier_set_active(modifier=modifier.name)
        
        if modifier.type == "NODES":
            bpy.ops.node.copy_geometry_node_group_assign()
        elif hasattr(modifier, "texture"):
            modifier.texture = modifier.texture.copy()
            
    return duplicate
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .