diff --git a/object_boolean_tools.py b/object_boolean_tools.py index 42e99eae15ce3943a68c50dccb4c73020d2e795e..e56880854375d705997ec2ac35e24489abf168b8 100644 --- a/object_boolean_tools.py +++ b/object_boolean_tools.py @@ -26,19 +26,19 @@ bl_info = { "location": "View3D > Sidebar", "description": "Bool Tool Hotkey: Ctrl Shift B", "category": "Object", - } +} import bpy from bpy.types import ( - AddonPreferences, - Operator, - Panel, - Menu, - ) + AddonPreferences, + Operator, + Panel, + Menu, +) from bpy.props import ( - BoolProperty, - StringProperty, - ) + BoolProperty, + StringProperty, +) # ------------------- Bool Tool FUNCTIONS ------------------------- @@ -47,7 +47,7 @@ from bpy.props import ( # 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'] + objs = [i.object for i in ao.modifiers if i.type == "BOOLEAN"] hide_state = context.scene.BoolHide for o in objs: @@ -92,8 +92,8 @@ 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): + if "BTool_" in mod.name: + if obj.name in mod.name: return ob @@ -116,12 +116,14 @@ def ConvertToMesh(obj): # Do the Union, Difference and Intersection Operations with a Brush def Operation(context, _operation): - prefs = bpy.context.preferences.addons[__name__].preferences useWire = prefs.use_wire for selObj in bpy.context.selected_objects: - if selObj != context.active_object and (selObj.type == "MESH" or selObj.type == "CURVE"): + if ( + selObj != context.active_object and + (selObj.type == "MESH" or selObj.type == "CURVE") + ): if selObj.type == "CURVE": ConvertToMesh(selObj) actObj = context.active_object @@ -181,8 +183,8 @@ def Remove(context, thisObj_name, Prop): # Remove it from the Canvas for mod in actObj.modifiers: - if ("BTool_" in mod.name): - if (_thisObj_name in mod.name): + if "BTool_" in mod.name: + if _thisObj_name in mod.name: actObj.modifiers.remove(mod) if Prop == "THIS": @@ -195,8 +197,8 @@ def Remove(context, thisObj_name, Prop): Canvas = FindCanvas(actObj) if Canvas: for mod in Canvas.modifiers: - if ("BTool_" in mod.name): - if (actObj.name in mod.name): + if "BTool_" in mod.name: + if actObj.name in mod.name: Canvas.modifiers.remove(mod) cyclesVis = actObj.cycles_visibility actObj.display_type = "TEXTURED" @@ -210,7 +212,7 @@ def Remove(context, thisObj_name, Prop): if Prop == "CANVAS": for mod in actObj.modifiers: - if ("BTool_" in mod.name): + if "BTool_" in mod.name: RemoveThis(mod.object.name) @@ -218,9 +220,9 @@ def Remove(context, thisObj_name, Prop): def EnableBrush(context, objList, canvas): for obj in objList: for mod in canvas.modifiers: - if ("BTool_" in mod.name and mod.object.name == obj): + if "BTool_" in mod.name and mod.object.name == obj: - if (mod.show_viewport): + if mod.show_viewport: mod.show_viewport = False mod.show_render = False else: @@ -235,22 +237,22 @@ def EnableThisBrush(context, set): if obj != bpy.context.active_object: if isCanvas(obj): for mod in obj.modifiers: - if ("BTool_" in mod.name): + if "BTool_" in mod.name: if mod.object == bpy.context.active_object: canvas = obj for mod in canvas.modifiers: - if ("BTool_" in mod.name): + if "BTool_" in mod.name: if mod.object == bpy.context.active_object: if set == "None": - if (mod.show_viewport): + if mod.show_viewport: mod.show_viewport = False mod.show_render = False else: mod.show_viewport = True mod.show_render = True else: - if (set == "True"): + if set == "True": mod.show_viewport = True else: mod.show_viewport = False @@ -274,23 +276,23 @@ def ApplyAll(context, list): for selObj in list: if isCanvas(selObj) and selObj == context.active_object: for mod in selObj.modifiers: - if ("BTool_" in mod.name): + if "BTool_" in mod.name: 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) - del selObj['BoolToolRoot'] + del selObj["BoolToolRoot"] for obj in context.scene.objects: if isCanvas(obj): for mod in obj.modifiers: - if mod.type == 'BOOLEAN': - if mod.object in objDeleteList: # do not delete brush that is used by another canvas - objDeleteList.remove(mod.object) # remove it from deletion + # 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') + bpy.ops.object.select_all(action="DESELECT") for obj in objDeleteList: obj.select_set(state=True) bpy.ops.object.delete() @@ -301,8 +303,7 @@ 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): - + if "BTool_" + brush.name in mod.name: # Apply This Brush context.view_layer.objects.active = obj try: @@ -310,20 +311,24 @@ def ApplyThisBrush(context, brush): 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') + bpy.ops.object.select_all(action="TOGGLE") + bpy.ops.object.select_all(action="DESELECT") # Garbage Collector brush.select_set(state=True) # 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") + 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" + ) count = 0 store_cont_draw = False @@ -348,30 +353,30 @@ class BTool_DrawPolyBrush(Operator): actObj = bpy.context.active_object if self.count == 1: actObj.select_set(state=True) - bpy.ops.gpencil.draw('INVOKE_DEFAULT', mode="DRAW_POLY") + bpy.ops.gpencil.draw("INVOKE_DEFAULT", mode="DRAW_POLY") - if event.type in {'RIGHTMOUSE'}: + if event.type in {"RIGHTMOUSE"}: # use this to pass to the Grease Pencil eraser (see T52321) pass - if event.type in {'RET', 'NUMPAD_ENTER'}: + if event.type in {"RET", "NUMPAD_ENTER"}: - bpy.ops.gpencil.convert(type='POLY') + 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.select_all(action="DESELECT") obj.select_set(state=True) bpy.ops.object.convert(target="MESH") - bpy.ops.object.mode_set(mode='EDIT') - bpy.ops.mesh.select_all(action='SELECT') + 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.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": @@ -380,7 +385,7 @@ class BTool_DrawPolyBrush(Operator): mod.offset = 0 obj["BoolToolPolyBrush"] = True - bpy.ops.object.select_all(action='DESELECT') + bpy.ops.object.select_all(action="DESELECT") bpy.context.view_layer.objects.active = actObj bpy.context.view_layer.update() actObj.select_set(state=True) @@ -389,26 +394,25 @@ class BTool_DrawPolyBrush(Operator): bpy.context.view_layer.grease_pencil.clear() bpy.ops.gpencil.data_unlink() - return {'FINISHED'} + return {"FINISHED"} - if event.type in {'ESC'}: + if event.type in {"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'} + self.report({"INFO"}, "Draw Poly Brush: Operation Cancelled by User") + return {"CANCELLED"} - return {'RUNNING_MODAL'} + return {"RUNNING_MODAL"} def invoke(self, context, event): if context.object: self.set_cont_draw(context, start=True) context.window_manager.modal_handler_add(self) - return {'RUNNING_MODAL'} + return {"RUNNING_MODAL"} else: - self.report({'WARNING'}, "No active object, could not finish") - return {'CANCELLED'} + self.report({"WARNING"}, "No active object, could not finish") + return {"CANCELLED"} # Fast Transform @@ -417,7 +421,7 @@ class BTool_FastTransform(Operator): bl_label = "Fast Transform" bl_description = "Enable Fast Transform" - operator : StringProperty("") + operator: StringProperty("") count = 0 @@ -435,33 +439,33 @@ class BTool_FastTransform(Operator): actObj.display_type = "BOUNDS" if self.operator == "Translate": - bpy.ops.transform.translate('INVOKE_DEFAULT') + bpy.ops.transform.translate("INVOKE_DEFAULT") if self.operator == "Rotate": - bpy.ops.transform.rotate('INVOKE_DEFAULT') + bpy.ops.transform.rotate("INVOKE_DEFAULT") if self.operator == "Scale": - bpy.ops.transform.resize('INVOKE_DEFAULT') + bpy.ops.transform.resize("INVOKE_DEFAULT") - if event.type == 'LEFTMOUSE': + if event.type == "LEFTMOUSE": if isBrush(actObj): EnableThisBrush(bpy.context, "True") actObj.display_type = "WIRE" - return {'FINISHED'} + return {"FINISHED"} - if event.type in {'RIGHTMOUSE', 'ESC'}: + if event.type in {"RIGHTMOUSE", "ESC"}: if isBrush(actObj): EnableThisBrush(bpy.context, "True") actObj.display_type = "WIRE" - return {'CANCELLED'} + return {"CANCELLED"} - return {'RUNNING_MODAL'} + return {"RUNNING_MODAL"} def invoke(self, context, event): if context.object: context.window_manager.modal_handler_add(self) - return {'RUNNING_MODAL'} + return {"RUNNING_MODAL"} else: - self.report({'WARNING'}, "No active object, could not finish") - return {'CANCELLED'} + self.report({"WARNING"}, "No active object, could not finish") + return {"CANCELLED"} # ------------------- Bool Tool OPERATOR CLASSES -------------------------------------------------------- @@ -480,7 +484,7 @@ class BTool_Union(Operator): def execute(self, context): Operation(context, "UNION") - return {'FINISHED'} + return {"FINISHED"} # Boolean Intersection Operator @@ -495,7 +499,7 @@ class BTool_Inters(Operator): def execute(self, context): Operation(context, "INTERSECT") - return {'FINISHED'} + return {"FINISHED"} # Boolean Difference Operator @@ -510,7 +514,7 @@ class BTool_Diff(Operator): def execute(self, context): Operation(context, "DIFFERENCE") - return {'FINISHED'} + return {"FINISHED"} # Boolean Slices Operator @@ -525,7 +529,7 @@ class BTool_Slice(Operator): def execute(self, context): Operation(context, "SLICE") - return {'FINISHED'} + return {"FINISHED"} # Auto Boolean operators @@ -533,24 +537,23 @@ class BTool_Slice(Operator): class Auto_Boolean: - def objects_prepare(self): for ob in bpy.context.selected_objects: - if ob.type != 'MESH': + if ob.type != "MESH": ob.select_set(state=False) bpy.ops.object.make_single_user(object=True, obdata=True) - bpy.ops.object.convert(target='MESH') + bpy.ops.object.convert(target="MESH") def mesh_selection(self, ob, select_action): obj = bpy.context.active_object bpy.context.view_layer.objects.active = ob - bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.object.mode_set(mode="EDIT") bpy.ops.mesh.reveal() bpy.ops.mesh.select_all(action=select_action) - bpy.ops.object.mode_set(mode='OBJECT') + bpy.ops.object.mode_set(mode="OBJECT") bpy.context.view_layer.objects.active = obj def boolean_operation(self): @@ -558,14 +561,14 @@ class Auto_Boolean: obj.select_set(state=False) obs = bpy.context.selected_objects - self.mesh_selection(obj, 'DESELECT') + self.mesh_selection(obj, "DESELECT") for ob in obs: - self.mesh_selection(ob, 'SELECT') + self.mesh_selection(ob, "SELECT") self.boolean_mod(obj, ob, self.mode) obj.select_set(state=True) def boolean_mod(self, obj, ob, mode, ob_delete=True): - md = obj.modifiers.new("Auto Boolean", 'BOOLEAN') + md = obj.modifiers.new("Auto Boolean", "BOOLEAN") md.show_viewport = False md.operation = mode md.object = ob @@ -580,49 +583,49 @@ 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'} + bl_options = {"REGISTER", "UNDO"} - mode = 'UNION' + mode = "UNION" def execute(self, context): self.objects_prepare() self.boolean_operation() - return {'FINISHED'} + return {"FINISHED"} 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'} + bl_options = {"REGISTER", "UNDO"} - mode = 'DIFFERENCE' + mode = "DIFFERENCE" def execute(self, context): self.objects_prepare() self.boolean_operation() - return {'FINISHED'} + return {"FINISHED"} 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'} + bl_options = {"REGISTER", "UNDO"} - mode = 'INTERSECT' + mode = "INTERSECT" def execute(self, context): self.objects_prepare() self.boolean_operation() - return {'FINISHED'} + return {"FINISHED"} 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'} + bl_options = {"REGISTER", "UNDO"} def execute(self, context): self.objects_prepare() @@ -631,19 +634,19 @@ class OBJECT_OT_BoolTool_Auto_Slice(Operator, Auto_Boolean): obj.select_set(state=False) ob = context.selected_objects[0] - self.mesh_selection(obj, 'DESELECT') - self.mesh_selection(ob, 'SELECT') + self.mesh_selection(obj, "DESELECT") + self.mesh_selection(ob, "SELECT") obj_copy = obj.copy() obj_copy.data = obj.data.copy() context.collection.objects.link(obj_copy) - self.boolean_mod(obj, ob, 'DIFFERENCE', ob_delete=False) + self.boolean_mod(obj, ob, "DIFFERENCE", ob_delete=False) bpy.context.view_layer.objects.active = obj_copy - self.boolean_mod(obj_copy, ob, 'INTERSECT') + self.boolean_mod(obj_copy, ob, "INTERSECT") obj_copy.select_set(state=True) - return {'FINISHED'} + return {"FINISHED"} # Utils Class --------------------------------------------------------------- @@ -654,7 +657,7 @@ class BTool_FindBrush(Operator): bl_label = "" bl_description = "Find the selected brush" - obj : StringProperty("") + obj: StringProperty("") @classmethod def poll(cls, context): @@ -662,12 +665,12 @@ class BTool_FindBrush(Operator): def execute(self, context): for ob in bpy.context.view_layer.objects: - if (ob.name == self.obj): - bpy.ops.object.select_all(action='TOGGLE') - bpy.ops.object.select_all(action='DESELECT') + 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) - return {'FINISHED'} + return {"FINISHED"} # Move The Modifier in The Stack Up or Down @@ -676,19 +679,19 @@ class BTool_MoveStack(Operator): bl_label = "" bl_description = "Move this Brush Up/Down in the Stack" - modif : StringProperty("") - direction : StringProperty("") + modif: StringProperty("") + direction: StringProperty("") @classmethod def poll(cls, context): return context.active_object is not None def execute(self, context): - if (self.direction == "UP"): + if self.direction == "UP": bpy.ops.object.modifier_move_up(modifier=self.modif) - if (self.direction == "DOWN"): + if self.direction == "DOWN": bpy.ops.object.modifier_move_down(modifier=self.modif) - return {'FINISHED'} + return {"FINISHED"} # Enable or Disable a Brush in the Three View @@ -697,7 +700,7 @@ class BTool_EnableBrush(Operator): bl_label = "" bl_description = "Removes all BoolTool config assigned to it" - thisObj : StringProperty("") + thisObj: StringProperty("") @classmethod def poll(cls, context): @@ -706,7 +709,7 @@ class BTool_EnableBrush(Operator): 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) - return {'FINISHED'} + return {"FINISHED"} # Enable or Disable a Brush Directly @@ -721,7 +724,7 @@ class BTool_EnableThisBrush(Operator): def execute(self, context): EnableThisBrush(context, "None") - return {'FINISHED'} + return {"FINISHED"} # Enable or Disable a Brush Directly @@ -736,7 +739,7 @@ class BTool_EnableFTransform(Operator): def execute(self, context): EnableFTransf(context) - return {'FINISHED'} + return {"FINISHED"} # Other Operations ------------------------------------------------------- @@ -746,10 +749,10 @@ class BTool_Remove(Operator): bl_idname = "btool.remove" bl_label = "" bl_description = "Removes all BoolTool config assigned to it" - bl_options = {'UNDO'} + bl_options = {"UNDO"} - thisObj : StringProperty("") - Prop : StringProperty("") + thisObj: StringProperty("") + Prop: StringProperty("") @classmethod def poll(cls, context): @@ -757,7 +760,7 @@ class BTool_Remove(Operator): def execute(self, context): Remove(context, self.thisObj, self.Prop) - return {'FINISHED'} + return {"FINISHED"} # Apply All to Canvas @@ -765,7 +768,7 @@ class BTool_AllBrushToMesh(Operator): bl_idname = "btool.to_mesh" bl_label = "Apply All Canvas" bl_description = "Apply all brushes of this canvas" - bl_options = {'UNDO'} + bl_options = {"UNDO"} @classmethod def poll(cls, context): @@ -774,7 +777,7 @@ class BTool_AllBrushToMesh(Operator): def execute(self, context): lists = bpy.context.selected_objects ApplyAll(context, lists) - return {'FINISHED'} + return {"FINISHED"} # Apply This Brush to the Canvas @@ -782,7 +785,7 @@ 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" - bl_options = {'UNDO'} + bl_options = {"UNDO"} @classmethod def poll(cls, context): @@ -794,7 +797,7 @@ class BTool_BrushToMesh(Operator): def execute(self, context): ApplyThisBrush(context, bpy.context.active_object) - return {'FINISHED'} + return {"FINISHED"} # TODO @@ -812,27 +815,27 @@ class VIEW3D_MT_booltool_menu(Menu): layout = self.layout layout.label(text="Auto Boolean") - 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.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.label(text="Brush Boolean") - 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') + 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)): + 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)): + 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") @@ -846,12 +849,13 @@ def VIEW3D_BoolTool_Menu(self, context): # ---------------- Toolshelf: Tools --------------------- + class VIEW3D_PT_booltool_tools(Panel): - bl_category = 'objectmode' + bl_category = "objectmode" bl_label = "Bool Tool" - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_context = 'objectmode' + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + bl_context = "objectmode" @classmethod def poll(cls, context): @@ -868,18 +872,18 @@ class VIEW3D_PT_booltool_tools(Panel): row.operator("wm.booltool_help", text="", icon="QUESTION") main = layout.column(align=True) - main.enabled = obj.type == 'MESH' and obs_len > 0 + 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.separator() - 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') + 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') + sub.operator(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, text="Slice", icon="PIVOT_MEDIAN") main.separator() @@ -887,10 +891,10 @@ class VIEW3D_PT_booltool_tools(Panel): col.enabled = obs_len > 1 col.label(text="Brush Boolean", icon="MODIFIER") col.separator() - 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.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") # TODO Draw Poly Brush # main.separator() @@ -903,19 +907,20 @@ class VIEW3D_PT_booltool_tools(Panel): # ---------- Toolshelf: Properties -------------------------------------------------------- + class VIEW3D_PT_booltool_config(Panel): - bl_category = 'objectmode' + bl_category = "objectmode" bl_label = "Properties" - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_context = 'objectmode' + 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)): + if isCanvas(actObj) or isBrush(actObj) or isPolyBrush(actObj): result = True return result @@ -930,7 +935,7 @@ class VIEW3D_PT_booltool_config(Panel): if isCanvas(actObj): row.label(text="CANVAS", icon="MESH_GRID") row = layout.row() - row.prop(context.scene, 'BoolHide', text="Hide Bool objects") + row.prop(context.scene, "BoolHide", text="Hide Bool objects") row = layout.row(align=True) row.operator(BTool_AllBrushToMesh.bl_idname, icon="MOD_LATTICE", text="Apply All") @@ -945,13 +950,13 @@ class VIEW3D_PT_booltool_config(Panel): # BRUSH ------------------------------------------------------ if isBrush(actObj): - if (actObj["BoolToolBrush"] == "UNION"): + if actObj["BoolToolBrush"] == "UNION": icon = "PIVOT_INDIVIDUAL" - if (actObj["BoolToolBrush"] == "DIFFERENCE"): + if actObj["BoolToolBrush"] == "DIFFERENCE": icon = "PIVOT_MEDIAN" - if (actObj["BoolToolBrush"] == "INTERSECT"): + if actObj["BoolToolBrush"] == "INTERSECT": icon = "PIVOT_ACTIVE" - if (actObj["BoolToolBrush"] == "SLICE"): + if actObj["BoolToolBrush"] == "SLICE": icon = "PIVOT_MEDIAN" row = layout.row(align=True) @@ -995,12 +1000,13 @@ class VIEW3D_PT_booltool_config(Panel): # ---------- Toolshelf: Brush Viewer ------------------------------------------------------- + class VIEW3D_PT_booltool_bviewer(Panel): - bl_category = 'objectmode' + bl_category = "objectmode" bl_label = "Brush Viewer" - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_context = 'objectmode' + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + bl_context = "objectmode" @classmethod def poll(cls, context): @@ -1022,21 +1028,21 @@ class VIEW3D_PT_booltool_bviewer(Panel): container = self.layout.box() row = container.row(align=True) icon = "" - if ("BTool_" in mod.name): - if (mod.operation == "UNION"): + if "BTool_" in mod.name: + if mod.operation == "UNION": icon = "PIVOT_INDIVIDUAL" - if (mod.operation == "DIFFERENCE"): + if mod.operation == "DIFFERENCE": icon = "PIVOT_MEDIAN" - if (mod.operation == "INTERSECT"): + if mod.operation == "INTERSECT": icon = "PIVOT_ACTIVE" - if (mod.operation == "SLICE"): + if mod.operation == "SLICE": icon = "PIVOT_MEDIAN" objSelect = row.operator("btool.find_brush", text=mod.object.name, icon=icon, emboss=False) objSelect.obj = mod.object.name EnableIcon = "RESTRICT_VIEW_ON" - if (mod.show_viewport): + if mod.show_viewport: EnableIcon = "RESTRICT_VIEW_OFF" Enable = row.operator(BTool_EnableBrush.bl_idname, icon=EnableIcon, emboss=False) Enable.thisObj = mod.object.name @@ -1072,10 +1078,11 @@ class VIEW3D_PT_booltool_bviewer(Panel): class WM_OT_BoolTool_Help(Operator): bl_idname = "wm.booltool_help" bl_label = "Bool Tool Help" - bl_description = "Tool Help - click to read some basic information" + bl_description = "Help - click to read basic information" def draw(self, context): layout = self.layout + layout.label(text="To use:") layout.label(text="Select two or more objects,") layout.label(text="choose one option from the panel") @@ -1083,16 +1090,16 @@ class WM_OT_BoolTool_Help(Operator): layout.separator() - layout.label(text="Auto Boolean") + layout.label(text="Auto Boolean:") layout.label(text="Apply Boolean operation directly.") layout.separator() - layout.label(text="Brush Boolean") + layout.label(text="Brush Boolean:") layout.label(text="Create a Boolean brush setup.") def execute(self, context): - return {'FINISHED'} + return {"FINISHED"} def invoke(self, context, event): return context.window_manager.invoke_popup(self, width=220) @@ -1115,7 +1122,7 @@ panels = ( VIEW3D_PT_booltool_tools, VIEW3D_PT_booltool_config, VIEW3D_PT_booltool_bviewer, - ) +) def update_panels(self, context): @@ -1125,7 +1132,9 @@ def update_panels(self, context): bpy.utils.unregister_class(panel) for panel in panels: - panel.bl_category = context.preferences.addons[__name__].preferences.category + panel.bl_category = context.preferences.addons[ + __name__ + ].preferences.category bpy.utils.register_class(panel) except Exception as e: @@ -1136,39 +1145,37 @@ def update_panels(self, context): class PREFS_BoolTool_Props(AddonPreferences): bl_idname = __name__ - fast_transform : BoolProperty( - name="Fast Transformations", - default=False, - update=UpdateBoolTool_Pref, - description="Replace the Transform HotKeys (G,R,S)\n" - "for a custom version that can optimize the visualization of Brushes", - ) - make_vertex_groups : BoolProperty( - name="Make Vertex Groups", - default=False, - description="When Applying a Brush to the Object it will create\n" - "a new vertex group for the new faces", - ) - make_boundary : BoolProperty( - name="Make Boundary", - default=False, - description="When Apply a Brush to the Object it will create a\n" - "new vertex group of the boundary boolean area", - ) - use_wire : BoolProperty( - name="Use Bmesh", - default=False, - description="Use The Wireframe Instead of Bounding Box for visualization", - ) - category : StringProperty( - name="Tab Category", - description="Choose a name for the category of the panel", - default="Tools", - update=update_panels, - ) - Enable_Tab_01 : BoolProperty( - default=False - ) + fast_transform: BoolProperty( + name="Fast Transformations", + default=False, + update=UpdateBoolTool_Pref, + description="Replace the Transform HotKeys (G,R,S)\n" + "for a custom version that can optimize the visualization of Brushes", + ) + make_vertex_groups: BoolProperty( + name="Make Vertex Groups", + default=False, + description="When Applying a Brush to the Object it will create\n" + "a new vertex group for the new faces", + ) + make_boundary: BoolProperty( + name="Make Boundary", + default=False, + description="When Apply a Brush to the Object it will create a\n" + "new vertex group of the boundary boolean area", + ) + use_wire: BoolProperty( + name="Use Bmesh", + default=False, + description="Use The Wireframe Instead of Bounding Box for visualization", + ) + category: StringProperty( + name="Tab Category", + description="Choose a name for the category of the panel", + default="Tools", + update=update_panels, + ) + Enable_Tab_01: BoolProperty(default=False) def draw(self, context): layout = self.layout @@ -1220,17 +1227,14 @@ class PREFS_BoolTool_Props(AddonPreferences): classes = ( PREFS_BoolTool_Props, - VIEW3D_MT_booltool_menu, VIEW3D_PT_booltool_tools, VIEW3D_PT_booltool_config, VIEW3D_PT_booltool_bviewer, - OBJECT_OT_BoolTool_Auto_Union, OBJECT_OT_BoolTool_Auto_Difference, OBJECT_OT_BoolTool_Auto_Intersect, OBJECT_OT_BoolTool_Auto_Slice, - BTool_Union, BTool_Diff, BTool_Inters, @@ -1246,9 +1250,8 @@ classes = ( BTool_EnableThisBrush, BTool_EnableFTransform, BTool_FastTransform, - WM_OT_BoolTool_Help, - ) +) # ------------------- REGISTER ------------------------------------------------ @@ -1260,17 +1263,17 @@ addon_keymapsFastT = [] # Fast Transform HotKeys Register def RegisterFastT(): wm = bpy.context.window_manager - km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY') + km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY") - kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, 'G', 'PRESS') + kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, "G", "PRESS") kmi.properties.operator = "Translate" addon_keymapsFastT.append((km, kmi)) - kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, 'R', 'PRESS') + kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, "R", "PRESS") kmi.properties.operator = "Rotate" addon_keymapsFastT.append((km, kmi)) - kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, 'S', 'PRESS') + kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, "S", "PRESS") kmi.properties.operator = "Scale" addon_keymapsFastT.append((km, kmi)) @@ -1293,10 +1296,10 @@ def register(): # Scene variables bpy.types.Scene.BoolHide = BoolProperty( - default=False, - description="Hide boolean objects", - update=update_BoolHide, - ) + default=False, + description="Hide boolean objects", + update=update_BoolHide, + ) bpy.types.VIEW3D_MT_object.append(VIEW3D_BoolTool_Menu) try: @@ -1307,38 +1310,64 @@ def register(): wm = bpy.context.window_manager # create the boolean menu hotkey - km = wm.keyconfigs.addon.keymaps.new(name='Object Mode') + km = wm.keyconfigs.addon.keymaps.new(name="Object Mode") - kmi = km.keymap_items.new('wm.call_menu', 'B', 'PRESS', ctrl=True, shift=True) - kmi.properties.name = 'VIEW3D_MT_booltool_menu' + kmi = km.keymap_items.new("wm.call_menu", "B", "PRESS", ctrl=True, shift=True) + kmi.properties.name = "VIEW3D_MT_booltool_menu" addon_keymaps.append((km, kmi)) # Brush Operators - kmi = km.keymap_items.new(BTool_Union.bl_idname, 'NUMPAD_PLUS', 'PRESS', ctrl=True) + kmi = km.keymap_items.new(BTool_Union.bl_idname, "NUMPAD_PLUS", "PRESS", ctrl=True) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(BTool_Diff.bl_idname, 'NUMPAD_MINUS', 'PRESS', ctrl=True) + kmi = km.keymap_items.new(BTool_Diff.bl_idname, "NUMPAD_MINUS", "PRESS", ctrl=True) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(BTool_Inters.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', ctrl=True) + kmi = km.keymap_items.new(BTool_Inters.bl_idname, "NUMPAD_ASTERIX", "PRESS", ctrl=True) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(BTool_Slice.bl_idname, 'NUMPAD_SLASH', 'PRESS', ctrl=True) + kmi = km.keymap_items.new(BTool_Slice.bl_idname, "NUMPAD_SLASH", "PRESS", ctrl=True) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(BTool_BrushToMesh.bl_idname, 'NUMPAD_ENTER', 'PRESS', ctrl=True) + kmi = km.keymap_items.new(BTool_BrushToMesh.bl_idname, "NUMPAD_ENTER", "PRESS", ctrl=True) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(BTool_AllBrushToMesh.bl_idname, 'NUMPAD_ENTER', 'PRESS', ctrl=True, shift=True) + kmi = km.keymap_items.new( + BTool_AllBrushToMesh.bl_idname, + "NUMPAD_ENTER", + "PRESS", + ctrl=True, + shift=True, + ) addon_keymaps.append((km, kmi)) # Auto Operators - kmi = km.keymap_items.new(OBJECT_OT_BoolTool_Auto_Union.bl_idname, - 'NUMPAD_PLUS', 'PRESS', ctrl=True, shift=True) + kmi = km.keymap_items.new( + OBJECT_OT_BoolTool_Auto_Union.bl_idname, + "NUMPAD_PLUS", + "PRESS", + ctrl=True, + shift=True, + ) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(OBJECT_OT_BoolTool_Auto_Difference.bl_idname, - 'NUMPAD_MINUS', 'PRESS', ctrl=True, shift=True) + kmi = km.keymap_items.new( + OBJECT_OT_BoolTool_Auto_Difference.bl_idname, + "NUMPAD_MINUS", + "PRESS", + ctrl=True, + shift=True, + ) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, - 'NUMPAD_ASTERIX', 'PRESS', ctrl=True, shift=True) + kmi = km.keymap_items.new( + OBJECT_OT_BoolTool_Auto_Intersect.bl_idname, + "NUMPAD_ASTERIX", + "PRESS", + ctrl=True, + shift=True, + ) addon_keymaps.append((km, kmi)) - kmi = km.keymap_items.new(OBJECT_OT_BoolTool_Auto_Slice.bl_idname, - 'NUMPAD_SLASH', 'PRESS', ctrl=True, shift=True) + kmi = km.keymap_items.new( + OBJECT_OT_BoolTool_Auto_Slice.bl_idname, + "NUMPAD_SLASH", + "PRESS", + ctrl=True, + shift=True, + ) addon_keymaps.append((km, kmi)) @@ -1367,4 +1396,4 @@ def unregister(): if __name__ == "__main__": - register() \ No newline at end of file + register()