1
$\begingroup$

The following script adds a boolean modifier to the active object. This works great for one cutting and one target object.

Imagine you have one cube and 4 spheres and you would like to end up with the cube having 4 boolean modifiers and each modifier uses one of the four spheres.

Would it be possible via python to collect / sort all the non-active objects and one by one add a modifier to the cube and then add a sphere?

    target_obj = context.object
    cutter_obj = bpy.data.objects['Sphere']

    bool_mod = target_obj.modifiers.new('cutter', 'BOOLEAN')
    bool_mod.operation = 'DIFFERENCE'

    bool_mod.object = cutter_obj
$\endgroup$
  • $\begingroup$ No, one cutter object per one boolean modifier. But you can join the cutter meshes into one object and cut with that within one modifier. Or just use multiple boolean modifiers like you suggested. $\endgroup$ – Jaroslav Jerryno Novotny Jan 7 '16 at 16:10
  • $\begingroup$ I think you misunderstood me. I know that one boolean can only use one object. I am asking about adding as many boolean modifiers as there are objects to add automatically so you do not have to do this manually. I rewrote my question to make this more clear. $\endgroup$ – Claas Kuhnen Jan 7 '16 at 16:16
  • $\begingroup$ This seems to be a duplicate of this, at the very least they are related. $\endgroup$ – Carel Jan 16 '16 at 22:20
3
$\begingroup$

Why not add Boolean modifiers based on selected vs active states. If you have 5 selected objects, the last one selected is active.

The concept

import bpy

def get_active_and_selected(context):

    active = context.active_object
    selection = context.selected_objects
    selected = set(selection).difference(set([active]))
    print('active:', active.name)
    print('selected (not active):', [o.name for o in selected])

get_active_and_selected(bpy.context)

If the cube is selected last it will print:

active: Cube
selected (not active): ['Sphere.004', 'Sphere.002', 'Sphere.001', 'Sphere.003']

The function

Adding multiple modifiers to the active object

import bpy

def add_selected_to_active(context):

    active = context.active_object
    selection = context.selected_objects
    selected = set(selection).difference(set([active]))

    if not (active and selected):
        return

    for idx, cutter in enumerate(selected):
        bool_mod = active.modifiers.new('cutter_' + str(idx), 'BOOLEAN')
        bool_mod.operation = 'DIFFERENCE'
        bool_mod.object = cutter
        cutter.hide = True

add_selected_to_active(bpy.context)

enter image description here

The operator

This could be easily turned into an Operator and employ error checking to avoid doing anything until all necessary conditions are OK.

At this point it's worth your time to read up on operators. How to make them, register them and call them from UI. It's just a bit of boilerplate which is similar for all add-ons. Blender's TextEditor has a few Operator templates, most notably: TextEditor > Templates > Python > Operator (Simple)

$\endgroup$
  • $\begingroup$ .difference is like remove/minus? inside "selected = set(selection).difference(set([active]))" $\endgroup$ – Claas Kuhnen Jan 7 '16 at 18:25
  • $\begingroup$ technically it is just: return the items in set(selection) that are not in set([active]) and call the result (also a set) selected, using Boolean math. like Venn diagrams. $\endgroup$ – zeffii Jan 7 '16 at 18:30
  • $\begingroup$ great this also helped me to figure out how to do a mirror modifier along a specific axis $\endgroup$ – Claas Kuhnen Jan 28 '16 at 18:05
2
$\begingroup$

I see, lets get the target_obj = active object (last selected), and all the cutter objects (selected but not active) and then you add a modifier for every cutter object with your code snipped in a loop:

import bpy

target_obj = bpy.context.active_object
cutter_objs = [obj for obj in bpy.context.selected_objects if obj != target_obj]

for obj in cutter_objs:
    bool_mod = target_obj.modifiers.new(obj.name+'_cutter', 'BOOLEAN')
    bool_mod.operation = 'DIFFERENCE'
    bool_mod.object = obj
$\endgroup$
  • $\begingroup$ This works as well great. Adding "obj.draw_type = "BOUNDS"" will make call cutters to BOUNDS. This script also works with only two objects selected. Any idea why this is different to zeffii's script? $\endgroup$ – Claas Kuhnen Jan 7 '16 at 19:02
0
$\begingroup$

The answers here didn't really work for me using Blender 2.79, so I thought I'd paste the script I currently use here:

def applyBoolean(operation, name, a, b):
    """For operation use either UNION, DIFFERENCE, or INTERSECT"""
    modifier = a.modifiers.new(type="BOOLEAN", name=name)
    modifier.object = b
    modifier.operation = operation
    bpy.ops.object.modifier_apply(modifier=name, apply_as="DATA")

    bpy.data.objects.remove(b)

Usage:

    bpy.ops.mesh.primitive_cylinder_add(
        radius=3,
        location=(0, 0, 0)
    )

    base = bpy.context.object
    base.name = "Base"

    bpy.ops.mesh.primitive_cylinder_add(
        radius=2,
        depth=7,
        location=(0, 0, 0)
    )

    torso = bpy.context.object
    torso.name = "Torso"

    applyBoolean("DIFFERENCE", "diff_base_torso", torso, base)

This will create a modifier to remove the base object from the torso object. It will also the delete the base object so the end-result in your editor is what you would expect if you have used other tools. :)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.