2
$\begingroup$

How can I delete hierarchy of objects in code? When trying to delete the "parent_obj", it's written in the GUI tooltip:

bpy.ops.outliner.object_operation(type='DELETE_HIERARCHY')

I tried to select the "parent_obj" using this code:

context.scene.objects.active = bpy.data.objects['parent_obj']

But got this error:

File "~/blender-2.76-rc2-linux-glibc211-x86_64/2.76/scripts/modules/bpy/ops.py", line 189, in __call__
    ret = op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.outliner.object_operation.poll() failed, context is incorrect

Edit

Ok, I've found how to bypass this problem. Instead of using bpy.ops.outliner.object_operation(), I first select the objects hierarchy, and then used bpy.ops.object.delete():

bpy.data.objects[obj_name].select = True
for child in bpy.data.objects[obj_name].children:
    child.select = True
bpy.ops.object.delete()
$\endgroup$
1
  • 1
    $\begingroup$ Have you searched for "context is incorrect" on this site yet? $\endgroup$
    – zeffii
    Jan 10, 2016 at 13:31

3 Answers 3

5
$\begingroup$

One should deseleted all the objects, select and remove the animation data from all the objects in the hierarchy, and call bpy.ops.object.delete():

def delete_hierarchy(parent_obj_name):
    bpy.ops.object.select_all(action='DESELECT')
    obj = bpy.data.objects[parent_obj_name]
    obj.animation_data_clear()
    names = set()
    # Go over all the objects in the hierarchy like @zeffi suggested:
    def get_child_names(obj):
        for child in obj.children:
            names.add(child.name)
            if child.children:
                get_child_names(child)

    get_child_names(obj)

    print(names)
    objects = bpy.data.objects
    [setattr(objects[n], 'select', True) for n in names]
    # Remove the animation from the all the child objects
    for child_name in names:
        bpy.data.objects[child_name].animation_data_clear()

    result = bpy.ops.object.delete()
    if result == {'FINISHED'}:
        print ("Successfully deleted object")
    else:
        print ("Could not delete object")
$\endgroup$
4
  • $\begingroup$ [setattr(objects[n], 'select', True) for n in names] doesn't work in 2022, and the code can not delete the parent_obj right now. $\endgroup$
    – Tac
    Aug 22, 2022 at 11:26
  • $\begingroup$ @tac pls don't change the answer as this one works perfectly for the blender version 2.76 it was intended. consider adding another answer for what works in the newer versions. $\endgroup$ Aug 22, 2022 at 13:03
  • 1
    $\begingroup$ @HarryMcKenzie Thank you for your advice. I have post a new answer for what works in the newer versions. $\endgroup$
    – Tac
    Aug 23, 2022 at 8:08
  • $\begingroup$ @Tac cool thanks! :) $\endgroup$ Aug 23, 2022 at 8:38
3
$\begingroup$

Your own solution probably works fine in your case, but the general case where the hierarchy is a bit more nested (children of children) might still deserve a solution.

perhaps something recursive:

import bpy

def delete_hierarchy(obj):
    names = set([obj.name])

    # recursion
    def get_child_names(obj):
        for child in obj.children:
            names.add(child.name)
            if child.children:
                get_child_names(child)

    get_child_names(obj)

    print(names)
    objects = bpy.data.objects
    [setattr(objects[n], 'select', True) for n in names]

    bpy.ops.object.delete()

delete_hierarchy(bpy.context.active_object)

This function assumes no objects are currently selected, and accumulates the names of the hierarchy starting with the main object ( i used active_object, but you can pass any object reference there ). Then it selects all the found names, then runs the object_delete operator.

$\endgroup$
7
  • $\begingroup$ I found that bpy.ops.object.delete() doesn't delete a nested animation objects. I inserted keyframes to the parent objects, and they weren't been deleted. Any ideas? $\endgroup$
    – Noam Peled
    Jan 11, 2016 at 16:12
  • $\begingroup$ you want to remove all keyframes from each object in this hierarchy.? $\endgroup$
    – zeffii
    Jan 11, 2016 at 16:31
  • $\begingroup$ Yes. In my case, only the parent obj has keyframes. $\endgroup$
    – Noam Peled
    Jan 11, 2016 at 16:33
  • $\begingroup$ I dont have a file at hand with any complicated animation, perhaps share one on blend-exchange.giantcowfilms.com - can be a trivial one to show what you mean, before and after. $\endgroup$
    – zeffii
    Jan 11, 2016 at 16:34
  • 1
    $\begingroup$ If you've solved your own question. we encourage you to write your own answer and even accept it :) $\endgroup$
    – zeffii
    Jan 11, 2016 at 18:49
2
$\begingroup$

@p2or and @Noam Peled have given a good idea, but [setattr(objects[n], 'select', True) for n in names] doesn't work in 2022, and their code can't delete the parent_obj right now. So I modified their code to work with Blender 3.0 and higher.

def delete_hierarchy(parent_obj_name):
    bpy.ops.object.select_all(action='DESELECT')
    obj = bpy.data.objects[parent_obj_name]
    obj.animation_data_clear()
    names = set()
    # Go over all the objects in the hierarchy like @zeffi suggested:
    def get_child_names(obj):
        for child in obj.children:
            names.add(child.name)
            if child.children:
                get_child_names(child)

    get_child_names(obj)
    names.add(parent_obj_name)
    print(names)
    objects = bpy.data.objects
    
    # Remove the animation from the all the child objects
    if names:
        for child_name in names:
            bpy.data.objects[child_name].animation_data_clear()
            objects[child_name].select_set(state=True)
            bpy.data.objects.remove(objects[child_name])
        print ("Successfully deleted object")
    else:
        print ("Could not delete object")
$\endgroup$

You must log in to answer this question.

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