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$
3
  • $\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$ Jan 7, 2016 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$ Jan 7, 2016 at 16:16
  • $\begingroup$ This seems to be a duplicate of this, at the very least they are related. $\endgroup$
    – Carel
    Jan 16, 2016 at 22:20

3 Answers 3

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$
3
  • $\begingroup$ .difference is like remove/minus? inside "selected = set(selection).difference(set([active]))" $\endgroup$ Jan 7, 2016 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, 2016 at 18:30
  • $\begingroup$ great this also helped me to figure out how to do a mirror modifier along a specific axis $\endgroup$ Jan 28, 2016 at 18:05
3
$\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$
1
  • $\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$ Jan 7, 2016 at 19:02
1
$\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$
0

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.