Skip to content
Snippets Groups Projects
object_boolean_tools.py 40.9 KiB
Newer Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

# <pep8 compliant>

bl_info = {
    "name": "Bool Tool",
    "author": "Vitor Balbio, Mikhail Rachinskiy, TynkaTopi, Meta-Androcto, Simon Appelt",
    "blender": (2, 80, 0),
meta-androcto's avatar
meta-androcto committed
    "location": "View3D > Sidebar > Edit Tab",
    "description": "Bool Tool Hotkey: Ctrl Shift B",
    "doc_url": "{BLENDER_MANUAL_URL}/addons/object/bool_tools.html",
    "category": "Object",

import bpy
from bpy.types import (
    AddonPreferences,
    Operator,
    Panel,
    Menu,
)
from bpy.props import (
    BoolProperty,
    StringProperty,
)
# -------------------  Bool Tool FUNCTIONS -------------------------
# Utils:

# Hide boolean objects
def update_BoolHide(self, context):
    ao = context.view_layer.objects.active
    objs = [i.object for i in ao.modifiers if i.type == "BOOLEAN"]
    hide_state = context.scene.BoolHide

    for o in objs:
        o.hide_viewport = hide_state


def isCanvas(_obj):
    try:
        if _obj["BoolToolRoot"]:
            return True
    except:
        return False


def isBrush(_obj):
    try:
        if _obj["BoolToolBrush"]:
            return True
    except:
        return False


# TODO
# def isPolyBrush(_obj):
#     try:
#         if _obj["BoolToolPolyBrush"]:
#             return True
#     except:
#         return False
def cycles_visibility_set(ob, value=False):
    if not hasattr(ob, "cycles_visibility"):
        return

    vis = ob.cycles_visibility

    vis.camera = value
    vis.diffuse = value
    vis.glossy = value
    vis.shadow = value
    vis.transmission = value
    vis.scatter = value


def BT_ObjectByName(obj):
    for ob in bpy.context.view_layer.objects:
        if isCanvas(ob) or isBrush(ob):
            if ob.name == obj:
                return ob


def FindCanvas(obj):
    for ob in bpy.context.view_layer.objects:
        if isCanvas(ob):
            for mod in ob.modifiers:
                if "BTool_" in mod.name:
                    if obj.name in mod.name:
    preferences = bpy.context.preferences
    addons = preferences.addons
    addon_prefs = addons[__name__].preferences
    if addon_prefs.fast_transform:
        return True
    else:
        return False


def ConvertToMesh(obj):
    act = bpy.context.view_layer.objects.active
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.convert(target="MESH")
    bpy.context.view_layer.objects.active = act


# Do the Union, Difference and Intersection Operations with a Brush
def Operation(context, _operation):
    prefs = context.preferences.addons[__name__].preferences
    useWire = prefs.use_wire
    for selObj in context.selected_objects:
        if (
            selObj != context.active_object and
            (selObj.type == "MESH" or selObj.type == "CURVE")
        ):
            if selObj.type == "CURVE":
                ConvertToMesh(selObj)
            actObj = context.active_object
            selObj.hide_render = True
                selObj.display_type = "WIRE"
                selObj.display_type = "BOUNDS"
            cycles_visibility_set(selObj, value=False)
            if _operation == "SLICE":
                # copies instance_collection property(empty), but group property is empty (users_group = None)
                context.collection.objects.link(clone)

                space_data = context.space_data
                is_local_view = bool(space_data.local_view)

                if is_local_view:
                    clone.local_view_set(space_data, True)

                sliceMod = clone.modifiers.new("BTool_" + selObj.name, "BOOLEAN")  # add mod to clone obj
                sliceMod.object = selObj
                sliceMod.operation = "DIFFERENCE"
                clone["BoolToolRoot"] = True
            newMod = actObj.modifiers.new("BTool_" + selObj.name, "BOOLEAN")
            newMod.object = selObj
            if _operation == "SLICE":
                newMod.operation = "INTERSECT"
            else:
                newMod.operation = _operation

            actObj["BoolToolRoot"] = True
            selObj["BoolToolBrush"] = _operation
            selObj["BoolTool_FTransform"] = "False"


# Remove Objects form the BoolTool System
def Remove(context, thisObj_name, Prop):
    # Find the Brush pointed in the Tree View and Restore it, active is the Canvas
    actObj = context.active_object

    # Restore the Brush
    def RemoveThis(_thisObj_name):
        for obj in bpy.context.view_layer.objects:
            # if it's the brush object
            if obj.name == _thisObj_name:
                obj.display_type = "TEXTURED"
                del obj["BoolToolBrush"]
                del obj["BoolTool_FTransform"]
                cycles_visibility_set(obj, value=True)

                # Remove it from the Canvas
                for mod in actObj.modifiers:
                    if "BTool_" in mod.name:
                        if _thisObj_name in mod.name:
                            actObj.modifiers.remove(mod)
Loading
Loading full blame...