1

so i am trying to cut holes (a lot if them) into a tabletop and i am trying to use a script which cuts each hole one by one, because blender cant handle doing the boolean for this many objects at once.

So i have implemented a loop which calls the following function:

def boolean_difference(obj, subtract_obj):
bool_mod = obj.modifiers.new(name="Boolean", type='BOOLEAN')
bool_mod.operation = 'DIFFERENCE'
bool_mod.use_self = True
bool_mod.object = subtract_obj    
bpy.ops.object.modifier_apply(modifier="Boolean")

obj is the table and subtract_obj is a cylinder which i want to cut out of it. In the main loop i then do this:

if main_obj and subtract_obj:
for axis in move_axes:
    for i in range(num_iterations[axis]):
        boolean_difference(main_obj, subtract_obj)
    copied_obj = subtract_obj.copy()
    bpy.context.collection.objects.link(copied_obj)

    if axis == 'X':
        copied_obj.location.x += move_amounts[axis]
    elif axis == 'Y':
        copied_obj.location.y += move_amounts[axis]
    elif axis == 'Z':
        copied_obj.location.z += move_amounts[axis]

    # Delete the original subtracted object
    bpy.data.objects.remove(subtract_obj)

    # Update the subtracted object for the next iteration
    subtract_obj = copied_obj

I debugged it and i noticed that i get an error for incorrerct context on only the second iteration. This is the error:

RuntimeError: Operator bpy.ops.object.modifier_apply.poll() failed, context is incorrect

So i am thinking that i do not properly copy the object or have to set something regarding the context of the object, but i unfortunately dont know what and so far i was not successfull in my search for an answer.

If you have any questions i will provide more info. thank you in advance!

Temeos
  • 43
  • 4

2 Answers2

3

bpy.ops.object.modifier_apply() work on an active object,

use context.view_layer.objects.active = obj before modifier_apply()

def boolean_difference(obj, subtract_obj):
    bool_mod = obj.modifiers.new(name="Boolean", type='BOOLEAN')
    bool_mod.operation = 'DIFFERENCE'
    bool_mod.use_self = True
    bool_mod.object = subtract_obj    
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.modifier_apply(modifier="Boolean")
Karan
  • 1,984
  • 5
  • 21
3

You can use a context override so you don't have to mess with selection state :

def boolean_difference(obj, subtract_obj):
    bool_mod = obj.modifiers.new(name="Boolean", type='BOOLEAN')
    bool_mod.operation = 'DIFFERENCE'
    bool_mod.use_self = True
    bool_mod.object = subtract_obj    
    with bpy.context.temp_override(object=obj):
        bpy.ops.object.modifier_apply(modifier="Boolean")
Gorgious
  • 30,723
  • 2
  • 44
  • 101