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",
"version": (0, 4, 0),
"blender": (2, 80, 0),
"description": "Bool Tool Hotkey: Ctrl Shift B",
import bpy
from bpy.types import (
AddonPreferences,
Operator,
Panel,
Menu,
)
BoolProperty,
StringProperty,
)
# ------------------- Bool Tool FUNCTIONS -------------------------
# Utils:
# Hide boolean objects
def update_BoolHide(self, context):
objs = [i.object for i in ao.modifiers if i.type == "BOOLEAN"]
hide_state = context.scene.BoolHide
for o in objs:
def isCanvas(_obj):
try:
if _obj["BoolToolRoot"]:
return True
except:
return False
# Object is a Brush Tool Bool
def isBrush(_obj):
try:
if _obj["BoolToolBrush"]:
return True
except:
return False
# Object is a Poly Brush Tool Bool collection
def isPolyBrush(_obj):
try:
if _obj["BoolToolPolyBrush"]:
return True
except:
return False
def BT_ObjectByName(obj):
if isCanvas(ob) or isBrush(ob):
if ob.name == obj:
return ob
def FindCanvas(obj):
if isCanvas(ob):
for mod in ob.modifiers:
if "BTool_" in mod.name:
if obj.name in mod.name:
return ob
def isFTransf():
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
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
cyclesVis = selObj.cycles_visibility
selObj.display_type = "WIRE"
selObj.display_type = "BOUNDS"
cyclesVis.camera = False
cyclesVis.diffuse = False
cyclesVis.glossy = False
cyclesVis.shadow = False
cyclesVis.transmission = False
if _operation == "SLICE":
# copies instance_collection property(empty), but group property is empty (users_group = None)
clone = actObj.copy()
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 Obejcts 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):
# if it's the brush object
if obj.name == _thisObj_name:
cyclesVis = obj.cycles_visibility
obj.display_type = "TEXTURED"
del obj["BoolToolBrush"]
del obj["BoolTool_FTransform"]
cyclesVis.camera = True
cyclesVis.diffuse = True
cyclesVis.glossy = True
cyclesVis.shadow = True
cyclesVis.transmission = 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)
if Prop == "THIS":
RemoveThis(thisObj_name)
# If the remove was called from the Properties:
else:
# Remove the Brush Property
if Prop == "BRUSH":
Canvas = FindCanvas(actObj)
if "BTool_" in mod.name:
if actObj.name in mod.name:
Canvas.modifiers.remove(mod)
cyclesVis = actObj.cycles_visibility
actObj.display_type = "TEXTURED"
del actObj["BoolToolBrush"]
del actObj["BoolTool_FTransform"]
cyclesVis.camera = True
cyclesVis.diffuse = True
cyclesVis.glossy = True
cyclesVis.shadow = True
cyclesVis.transmission = True
if Prop == "CANVAS":
for mod in actObj.modifiers:
RemoveThis(mod.object.name)
# Toggle the Enable the Brush Object Property
def EnableBrush(context, objList, canvas):
for obj in objList:
for mod in canvas.modifiers:
if "BTool_" in mod.name and mod.object.name == obj:
mod.show_viewport = False
mod.show_render = False
else:
mod.show_viewport = True
mod.show_render = True
# Find the Canvas and Enable this Brush
def EnableThisBrush(context, set):
canvas = None
if obj != bpy.context.active_object:
if isCanvas(obj):
for mod in obj.modifiers:
if mod.object == bpy.context.active_object:
canvas = obj
for mod in canvas.modifiers:
if mod.object == bpy.context.active_object:
if set == "None":
mod.show_viewport = False
mod.show_render = False
else:
mod.show_viewport = True
mod.show_render = True
else:
mod.show_viewport = True
else:
mod.show_viewport = False
return
# Toggle the Fast Transform Property of the Active Brush
def EnableFTransf(context):
actObj = bpy.context.active_object
if actObj["BoolTool_FTransform"] == "True":
actObj["BoolTool_FTransform"] = "False"
else:
actObj["BoolTool_FTransform"] = "True"
return
# Apply All Brushes to the Canvas
def ApplyAll(context, list):
objDeleteList = []
for selObj in list:
if isCanvas(selObj) and selObj == context.active_object:
for mod in selObj.modifiers:
objDeleteList.append(mod.object)
try:
bpy.ops.object.modifier_apply(modifier=mod.name)
except: # if fails the means it is multiuser data
context.active_object.data = context.active_object.data.copy() # so just make data unique
bpy.ops.object.modifier_apply(modifier=mod.name)
for obj in context.scene.objects:
if isCanvas(obj):
for mod in obj.modifiers:
# do not delete brush that is used by another canvas
if mod.type == "BOOLEAN" and mod.object in objDeleteList:
objDeleteList.remove(mod.object) # remove it from deletion
bpy.ops.object.select_all(action="DESELECT")
# Apply This Brush to the Canvas
def ApplyThisBrush(context, brush):
for obj in context.scene.objects:
if isCanvas(obj):
for mod in obj.modifiers:
if "BTool_" + brush.name in mod.name:
try:
bpy.ops.object.modifier_apply(modifier=mod.name)
except: # if fails the means it is multiuser data
context.active_object.data = context.active_object.data.copy() # so just make data unique
bpy.ops.object.modifier_apply(modifier=mod.name)
bpy.ops.object.select_all(action="TOGGLE")
bpy.ops.object.select_all(action="DESELECT")
# Garbage Collector
# bpy.ops.object.delete()
# ------------------ Bool Tool OPERATORS --------------------------------------
class BTool_DrawPolyBrush(Operator):
bl_idname = "btool.draw_polybrush"
bl_label = "Draw Poly Brush"
bl_description = (
"Draw Polygonal Mask, can be applied to Canvas > Brush or Directly\n"
"Note: ESC to Cancel, Enter to Apply, Right Click to erase the Lines"
)
store_cont_draw = False
@classmethod
def poll(cls, context):
return context.active_object is not None
def set_cont_draw(self, context, start=False):
# store / restore GP continuous drawing (see T52321)
scene = context.scene
tool_settings = scene.tool_settings
continuous = tool_settings.use_gpencil_continuous_drawing
if start:
self.store_cont_draw = continuous
tool_settings.use_gpencil_continuous_drawing = True
else:
tool_settings.use_gpencil_continuous_drawing = self.store_cont_draw
def modal(self, context, event):
self.count += 1
actObj = bpy.context.active_object
if self.count == 1:
bpy.ops.gpencil.draw("INVOKE_DEFAULT", mode="DRAW_POLY")
if event.type == "RIGHTMOUSE":
# use this to pass to the Grease Pencil eraser (see T52321)
pass
if event.type in {"RET", "NUMPAD_ENTER"}:
bpy.ops.gpencil.convert(type="POLY")
self.set_cont_draw(context)
for obj in context.selected_objects:
if obj.type == "CURVE":
obj.name = "PolyDraw"
bpy.context.view_layer.objects.active = obj
bpy.ops.object.select_all(action="DESELECT")
bpy.ops.object.convert(target="MESH")
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="SELECT")
bpy.ops.mesh.edge_face_add()
bpy.ops.mesh.flip_normals()
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.origin_set(type="ORIGIN_CENTER_OF_MASS")
bpy.ops.object.modifier_add(type="SOLIDIFY")
for mod in obj.modifiers:
if mod.name == "Solidify":
mod.name = "BTool_PolyBrush"
mod.thickness = 1
mod.offset = 0
obj["BoolToolPolyBrush"] = True
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = actObj
bpy.context.view_layer.update()
actObj.select_set(state=True)
obj.select_set(state=True)
bpy.context.view_layer.grease_pencil.clear()
bpy.ops.gpencil.data_unlink()
if event.type == "ESC":
bpy.ops.ed.undo() # remove o Grease Pencil
self.set_cont_draw(context)
self.report({"INFO"}, "Draw Poly Brush: Operation Cancelled by User")
return {"CANCELLED"}
def invoke(self, context, event):
if context.object:
self.set_cont_draw(context, start=True)
context.window_manager.modal_handler_add(self)
self.report({"WARNING"}, "No active object, could not finish")
return {"CANCELLED"}
# Fast Transform
class BTool_FastTransform(Operator):
bl_idname = "btool.fast_transform"
bl_label = "Fast Transform"
bl_description = "Enable Fast Transform"
count = 0
def modal(self, context, event):
self.count += 1
actObj = bpy.context.active_object
useWire = bpy.context.preferences.addons[__name__].preferences.use_wire
if self.count == 1:
if isBrush(actObj) and actObj["BoolTool_FTransform"] == "True":
EnableThisBrush(bpy.context, "False")
if useWire:
actObj.display_type = "WIRE"
actObj.display_type = "BOUNDS"
if self.operator == "Translate":
bpy.ops.transform.translate("INVOKE_DEFAULT")
if self.operator == "Rotate":
bpy.ops.transform.rotate("INVOKE_DEFAULT")
if self.operator == "Scale":
bpy.ops.transform.resize("INVOKE_DEFAULT")
if event.type == "LEFTMOUSE":
if isBrush(actObj):
EnableThisBrush(bpy.context, "True")
actObj.display_type = "WIRE"
if event.type in {"RIGHTMOUSE", "ESC"}:
if isBrush(actObj):
EnableThisBrush(bpy.context, "True")
actObj.display_type = "WIRE"
def invoke(self, context, event):
if context.object:
context.window_manager.modal_handler_add(self)
self.report({"WARNING"}, "No active object, could not finish")
return {"CANCELLED"}
# ------------------- Bool Tool OPERATOR CLASSES --------------------------------------------------------
# Brush Operators --------------------------------------------
# Boolean Union Operator
class BTool_Union(Operator):
bl_idname = "btool.boolean_union"
bl_label = "Brush Union"
bl_description = "This operator add a union brush to a canvas"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
Operation(context, "UNION")
# Boolean Intersection Operator
class BTool_Inters(Operator):
bl_idname = "btool.boolean_inters"
bl_label = "Brush Intersection"
bl_description = "This operator add a intersect brush to a canvas"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
Operation(context, "INTERSECT")
# Boolean Difference Operator
class BTool_Diff(Operator):
bl_idname = "btool.boolean_diff"
bl_label = "Brush Difference"
bl_description = "This operator add a difference brush to a canvas"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
Operation(context, "DIFFERENCE")
class BTool_Slice(Operator):
bl_idname = "btool.boolean_slice"
bl_label = "Brush Slice"
bl_description = "This operator add a intersect brush to a canvas"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
Operation(context, "SLICE")
# --------------------------------------------------------------------------------------
class Auto_Boolean:
for ob in bpy.context.selected_objects:
Mikhail Rachinskiy
committed
bpy.ops.object.make_single_user(object=True, obdata=True)
bpy.ops.object.convert(target="MESH")
def mesh_selection(self, ob, select_action):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action=select_action)
bpy.ops.object.mode_set(mode="OBJECT")
bpy.context.view_layer.objects.active = obj
self.mesh_selection(obj, "DESELECT")
self.mesh_selection(ob, "SELECT")
self.boolean_mod(obj, ob, self.mode)
def boolean_mod(self, obj, ob, mode, ob_delete=True):
md = obj.modifiers.new("Auto Boolean", "BOOLEAN")
md.show_viewport = False
md.operation = mode
md.object = ob
bpy.ops.object.modifier_apply(modifier="Auto Boolean")
if not ob_delete:
return
bpy.data.objects.remove(ob)
class OBJECT_OT_BoolTool_Auto_Union(Operator, Auto_Boolean):
bl_idname = "object.booltool_auto_union"
bl_label = "Bool Tool Union"
bl_description = "Combine selected objects"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
class OBJECT_OT_BoolTool_Auto_Difference(Operator, Auto_Boolean):
bl_idname = "object.booltool_auto_difference"
bl_label = "Bool Tool Difference"
bl_description = "Subtract selected objects from active object"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
class OBJECT_OT_BoolTool_Auto_Intersect(Operator, Auto_Boolean):
bl_idname = "object.booltool_auto_intersect"
bl_label = "Bool Tool Intersect"
bl_description = "Keep only intersecting geometry"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
class OBJECT_OT_BoolTool_Auto_Slice(Operator, Auto_Boolean):
bl_idname = "object.booltool_auto_slice"
bl_label = "Bool Tool Slice"
bl_description = "Slice active object along the selected object"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
obj = context.active_object
ob = context.selected_objects[0]
self.mesh_selection(obj, "DESELECT")
self.mesh_selection(ob, "SELECT")
obj_copy = obj.copy()
obj_copy.data = obj.data.copy()
space_data = context.space_data
is_local_view = bool(space_data.local_view)
if is_local_view:
obj_copy.local_view_set(space_data, True)
self.boolean_mod(obj, ob, "DIFFERENCE", ob_delete=False)
context.view_layer.objects.active = obj_copy
self.boolean_mod(obj_copy, ob, "INTERSECT")
# Utils Class ---------------------------------------------------------------
# Find the Brush Selected in Three View
class BTool_FindBrush(Operator):
bl_idname = "btool.find_brush"
bl_label = ""
bl_description = "Find the selected brush"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
if ob.name == self.obj:
bpy.ops.object.select_all(action="TOGGLE")
bpy.ops.object.select_all(action="DESELECT")
bpy.context.view_layer.objects.active = ob
ob.set_select(state=True)
# Move The Modifier in The Stack Up or Down
class BTool_MoveStack(Operator):
bl_idname = "btool.move_stack"
bl_label = ""
bl_description = "Move this Brush Up/Down in the Stack"
modif: StringProperty("")
direction: StringProperty("")
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
bpy.ops.object.modifier_move_up(modifier=self.modif)
bpy.ops.object.modifier_move_down(modifier=self.modif)
# Enable or Disable a Brush in the Three View
class BTool_EnableBrush(Operator):
bl_idname = "btool.enable_brush"
bl_label = ""
bl_description = "Removes all BoolTool config assigned to it"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
# in this case is just one object but the function accept more than one at once
EnableBrush(context, [self.thisObj], context.active_object)
# Enable or Disable a Brush Directly
class BTool_EnableThisBrush(Operator):
bl_idname = "btool.enable_this_brush"
bl_label = ""
bl_description = "Toggles this brush"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
EnableThisBrush(context, "None")
# Enable or Disable a Brush Directly
class BTool_EnableFTransform(Operator):
bl_idname = "btool.enable_ftransf"
bl_label = ""
bl_description = "Use Fast Transformations to improve speed"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
EnableFTransf(context)
# Other Operations -------------------------------------------------------
# Remove a Brush or a Canvas
class BTool_Remove(Operator):
bl_idname = "btool.remove"
bl_description = "Removes all BoolTool config assigned to it"
thisObj: StringProperty("")
Prop: StringProperty("")
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
Remove(context, self.thisObj, self.Prop)
# Apply All to Canvas
class BTool_AllBrushToMesh(Operator):
bl_idname = "btool.to_mesh"
bl_label = "Apply All Canvas"
bl_description = "Apply all brushes of this canvas"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
lists = bpy.context.selected_objects
ApplyAll(context, lists)
# Apply This Brush to the Canvas
class BTool_BrushToMesh(Operator):
bl_idname = "btool.brush_to_mesh"
bl_label = "Apply this Brush to Canvas"
bl_description = "Apply this brush to the canvas"
@classmethod
def poll(cls, context):
if isBrush(context.active_object):
return True
else:
return False
def execute(self, context):
ApplyThisBrush(context, bpy.context.active_object)
# TODO
# Apply This Brush To Mesh
# ------------------- MENU CLASSES ------------------------------
class VIEW3D_MT_booltool_menu(Menu):
bl_label = "BoolTool Operators"
bl_idname = "VIEW3D_MT_booltool_menu"
def draw(self, context):
layout = self.layout
layout.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text="Difference", icon="PIVOT_ACTIVE")
layout.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text="Union", icon="PIVOT_INDIVIDUAL")
layout.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text="Intersect", icon="PIVOT_MEDIAN")
layout.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text="Slice", icon="PIVOT_MEDIAN")
layout.separator()
layout.operator(BTool_Diff.bl_idname, icon="PIVOT_ACTIVE")
layout.operator(BTool_Union.bl_idname, icon="PIVOT_INDIVIDUAL")
layout.operator(BTool_Inters.bl_idname, icon="PIVOT_MEDIAN")
layout.operator(BTool_Slice.bl_idname, icon="PIVOT_MEDIAN")
if isCanvas(context.active_object):
layout.separator()
layout.operator(BTool_AllBrushToMesh.bl_idname, icon="MOD_LATTICE", text="Apply All")
Rem = layout.operator(BTool_Remove.bl_idname, icon="CANCEL", text="Remove All")
Rem.thisObj = ""
Rem.Prop = "CANVAS"
if isBrush(context.active_object):
layout.separator()
layout.operator(BTool_BrushToMesh.bl_idname, icon="MOD_LATTICE", text="Apply Brush")
Rem = layout.operator(BTool_Remove.bl_idname, icon="CANCEL", text="Remove Brush")
Rem.thisObj = ""
Rem.Prop = "BRUSH"
def VIEW3D_BoolTool_Menu(self, context):
self.layout.menu(VIEW3D_MT_booltool_menu.bl_idname)
# ---------------- Toolshelf: Tools ---------------------
class VIEW3D_PT_booltool_tools(Panel):
bl_label = "Bool Tool"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_context = "objectmode"
@classmethod
def poll(cls, context):
return context.active_object is not None
def draw(self, context):
layout = self.layout
obj = context.active_object
obs_len = len(context.selected_objects)
row = layout.row()
row.alignment = "RIGHT"
row.scale_x = 1.5
row.operator("wm.booltool_help", text="", icon="QUESTION")
main.enabled = obj.type == "MESH" and obs_len > 0
col = main.column(align=True)
col.enabled = obs_len > 1
col.label(text="Auto Boolean", icon="MODIFIER")
col.operator(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, text="Difference", icon="PIVOT_ACTIVE")
col.operator(OBJECT_OT_BoolTool_Auto_Union.bl_idname, text="Union", icon="PIVOT_INDIVIDUAL")
col.operator(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, text="Intersect", icon="PIVOT_MEDIAN")
sub = col.column(align=True)
sub.enabled = obs_len == 2
sub.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text="Slice", icon="PIVOT_MEDIAN")
col = main.column(align=True)
col.enabled = obs_len > 1
col.label(text="Brush Boolean", icon="MODIFIER")
col.operator(BTool_Diff.bl_idname, text="Difference", icon="PIVOT_ACTIVE")
col.operator(BTool_Union.bl_idname, text="Union", icon="PIVOT_INDIVIDUAL")
col.operator(BTool_Inters.bl_idname, text="Intersect", icon="PIVOT_MEDIAN")
col.operator(BTool_Slice.bl_idname, text="Slice", icon="PIVOT_MEDIAN")
# col = main.column(align=True)
# col.label(text="Draw:", icon="MESH_CUBE")
# col.separator()
# col.operator(BTool_DrawPolyBrush.bl_idname, icon="LINE_DATA")
# ---------- Toolshelf: Properties --------------------------------------------------------
class VIEW3D_PT_booltool_config(Panel):
bl_label = "Properties"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_context = "objectmode"
@classmethod
def poll(cls, context):
result = False
actObj = bpy.context.active_object
if isCanvas(actObj) or isBrush(actObj) or isPolyBrush(actObj):
result = True
return result
def draw(self, context):
actObj = bpy.context.active_object
icon = ""
layout = self.layout
# CANVAS ---------------------------------------------------
if isCanvas(actObj):
row.prop(context.scene, "BoolHide", text="Hide Bool objects")
row.operator(BTool_AllBrushToMesh.bl_idname, icon="MOD_LATTICE", text="Apply All")
Rem = row.operator(BTool_Remove.bl_idname, icon="CANCEL", text="Remove All")
Rem.thisObj = ""
Rem.Prop = "CANVAS"
if isBrush(actObj):
layout.separator()
# BRUSH ------------------------------------------------------
if isBrush(actObj):
if actObj["BoolToolBrush"] == "UNION":
if actObj["BoolToolBrush"] == "DIFFERENCE":
if actObj["BoolToolBrush"] == "INTERSECT":
if actObj["BoolToolBrush"] == "SLICE":
row = layout.row(align=True)
row.label(text="BRUSH", icon=icon)
icon = ""
if actObj["BoolTool_FTransform"] == "True":
icon = "PMARKER_ACT"
else:
icon = "PMARKER"
if isFTransf():
pass
if isFTransf():
row.operator(BTool_EnableFTransform.bl_idname, text="Fast Vis", icon=icon)
row.operator(BTool_EnableThisBrush.bl_idname, text="Enable", icon="HIDE_OFF")
row.operator(BTool_EnableThisBrush.bl_idname, icon="HIDE_OFF")