Skip to content
Snippets Groups Projects
object_boolean_tools.py 46.5 KiB
Newer Older
  • Learn to ignore specific revisions
  •         sub.enabled = len(context.selected_objects) == 2
            sub.operator(Direct_Slice.bl_idname, icon="ROTATECENTER")
            sub.operator(Direct_Subtract.bl_idname, icon="ROTACTIVE")
    
    
            layout.separator()
            row = layout.row(True)
            col = row.column(True)
            col.label("Brush Boolean:", icon="MODIFIER")
            col.separator()
            col.operator(BTool_Diff.bl_idname, text="Difference", icon="ROTACTIVE")
            col.operator(BTool_Union.bl_idname, text="Union", icon="ROTATECOLLECTION")
            col.operator(BTool_Inters.bl_idname, text="Intersect", icon="ROTATECENTER")
            col.operator(BTool_Slice.bl_idname, text="Slice", icon="ROTATECENTER")
    
            layout.separator()
            row = layout.row(True)
            col = row.column(True)
            col.label("Draw:", icon="MESH_CUBE")
            col.separator()
            col.operator(BTool_DrawPolyBrush.bl_idname, icon="LINE_DATA")
            col.separator()
    
    
    # ---------- Properties --------------------------------------------------------
    class BoolTool_Config(Panel):
        bl_label = "Properties"
        bl_idname = "BoolTool_BConfig"
        bl_space_type = "VIEW_3D"
        bl_region_type = "TOOLS"
        bl_category = "Bool Tool"
        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
            row = layout.row(True)
    
            # CANVAS ---------------------------------------------------
            if isCanvas(actObj):
                row.label("CANVAS", icon="MESH_GRID")
                row = layout.row()
                row.prop(context.scene, 'BoolHide', text="Hide Bool objects")
                row = layout.row(True)
                row.operator(BTool_AllBrushToMesh.bl_idname, icon="MOD_LATTICE", text="Apply All")
    
                row = layout.row(True)
                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"):
                    icon = "ROTATECOLLECTION"
                if (actObj["BoolToolBrush"] == "DIFFERENCE"):
                    icon = "ROTATECENTER"
                if (actObj["BoolToolBrush"] == "INTERSECT"):
                    icon = "ROTACTIVE"
                if (actObj["BoolToolBrush"] == "SLICE"):
                    icon = "ROTATECENTER"
    
                row = layout.row(True)
                row.label("BRUSH", icon=icon)
                # layout.separator()
    
                icon = ""
                if actObj["BoolTool_FTransform"] == "True":
                    icon = "PMARKER_ACT"
                else:
                    icon = "PMARKER"
                if isFTransf():
                    pass
    
                if isFTransf():
                    row = layout.row(True)
                    row.operator(BTool_EnableFTransform.bl_idname, text="Fast Vis", icon=icon)
                    row.operator(BTool_EnableThisBrush.bl_idname, text="Enable", icon="VISIBLE_IPO_ON")
                    row = layout.row(True)
                else:
                    row.operator(BTool_EnableThisBrush.bl_idname, icon="VISIBLE_IPO_ON")
                    row = layout.row(True)
    
            if isPolyBrush(actObj):
                row = layout.row(False)
                row.label("POLY BRUSH", icon="LINE_DATA")
                mod = actObj.modifiers["BTool_PolyBrush"]
                row = layout.row(False)
                row.prop(mod, "thickness", text="Size")
                layout.separator()
    
            if isBrush(actObj):
                row = layout.row(True)
                row.operator(BTool_BrushToMesh.bl_idname, icon="MOD_LATTICE", text="Apply Brush")
                row = layout.row(True)
                Rem = row.operator(BTool_Remove.bl_idname, icon="CANCEL", text="Remove Brush")
                Rem.thisObj = ""
                Rem.Prop = "BRUSH"
    
            layout.separator()
    
    
    # ---------- Tree Viewer-------------------------------------------------------
    class BoolTool_BViwer(Panel):
        bl_label = "Brush Viewer"
        bl_idname = "BoolTool_BViwer"
        bl_space_type = "VIEW_3D"
        bl_region_type = "TOOLS"
        bl_category = "Bool Tool"
        bl_context = "objectmode"
    
        @classmethod
        def poll(cls, context):
            actObj = bpy.context.active_object
    
            if isCanvas(actObj):
                return True
            else:
                return False
    
        def draw(self, context):
    
            actObj = bpy.context.active_object
            icon = ""
    
            if isCanvas(actObj):
    
                for mod in actObj.modifiers:
                    container = self.layout.box()
                    row = container.row(True)
                    icon = ""
                    if ("BTool_" in mod.name):
                        if (mod.operation == "UNION"):
                            icon = "ROTATECOLLECTION"
                        if (mod.operation == "DIFFERENCE"):
                            icon = "ROTATECENTER"
                        if (mod.operation == "INTERSECT"):
                            icon = "ROTACTIVE"
                        if (mod.operation == "SLICE"):
                            icon = "ROTATECENTER"
    
                        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):
                            EnableIcon = "RESTRICT_VIEW_OFF"
                        Enable = row.operator(BTool_EnableBrush.bl_idname, icon=EnableIcon, emboss=False)
                        Enable.thisObj = mod.object.name
    
                        Remove = row.operator("btool.remove", icon="CANCEL", emboss=False)
                        Remove.thisObj = mod.object.name
                        Remove.Prop = "THIS"
    
                        # Stack Changer
                        Up = row.operator("btool.move_stack", icon="TRIA_UP", emboss=False)
                        Up.modif = mod.name
                        Up.direction = "UP"
    
                        Dw = row.operator("btool.move_stack", icon="TRIA_DOWN", emboss=False)
                        Dw.modif = mod.name
                        Dw.direction = "DOWN"
    
                    else:
                        row.label(mod.name)
                        # Stack Changer
                        Up = row.operator("btool.move_stack", icon="TRIA_UP", emboss=False)
                        Up.modif = mod.name
                        Up.direction = "UP"
    
                        Dw = row.operator("btool.move_stack", icon="TRIA_DOWN", emboss=False)
                        Dw.modif = mod.name
                        Dw.direction = "DOWN"
    
    
    # ------------------ BOOL TOOL ADD-ON PREFERENCES ----------------------------
    
    def UpdateBoolTool_Pref(self, context):
        if self.fast_transform:
            RegisterFastT()
        else:
            UnRegisterFastT()
    
    ## Addons Preferences Update Panel
    def update_panel(self, context):
        try:
            bpy.utils.unregister_class(BoolTool_Tools)
            bpy.utils.unregister_class(BoolTool_Config)
            bpy.utils.unregister_class(BoolTool_BViwer)
        except:
            pass
        BoolTool_Tools.bl_category = context.user_preferences.addons[__name__].preferences.category
        bpy.utils.register_class(BoolTool_Tools)
        BoolTool_Config.bl_category = context.user_preferences.addons[__name__].preferences.category
        bpy.utils.register_class(BoolTool_Config)
        BoolTool_BViwer.bl_category = context.user_preferences.addons[__name__].preferences.category
        bpy.utils.register_class(BoolTool_BViwer)
    
    
    
    class BoolTool_Pref(AddonPreferences):
    
        fast_transform = BoolProperty(
    
                name="Fast Transformations",
                default=False,
                update=UpdateBoolTool_Pref,
                description=("Replace the Transform HotKeys (G,R,S) "
    
                             "for a custom version that can optimize the visualization of Brushes")
                )
    
        make_vertex_groups = BoolProperty(
    
                name="Make Vertex Groups",
                default=False,
                description="When Apply a Brush to de Object it will create a new vertex group of the new faces"
                )
    
        make_boundary = BoolProperty(
    
                name="Make Boundary",
                default=False,
                description="When Apply a Brush to de Object it will create a new vertex group of the bondary boolean area"
                )
    
        use_wire = BoolProperty(
    
                name="Use Bmesh",
                default=False,
                description="Use The Wireframe Instead Of Boolean"
                )
    
        category = StringProperty(
    
                name="Tab Category",
                description="Choose a name for the category of the panel",
                default="Bool Tools",
                update=update_panel
                )
    
        solver = EnumProperty(
    
                name='Boolean Solver',
                items=(('BMESH', 'BMesh', ''),
                       ('CARVE', 'Carve', '')),
                default='BMESH',
                description='Specify solver for boolean operations'
                )
    
        bpy.types.Scene.Enable_Tab_01 = bpy.props.BoolProperty(default=False)
    
        def draw(self, context):
    
            split_percent = 0.3
    
            split = layout.split(percentage=split_percent)
            col = split.column()
    
            col.label(text="Tab Category:")
    
            col = split.column()
            colrow = col.row()
            colrow.alignment = 'LEFT'
            colrow.prop(self, "category", text="")
    
            split = layout.split(percentage=split_percent)
            col = split.column()
    
            col.label('Boolean Solver:')
    
            colrow = col.row()
    
            colrow.alignment = 'LEFT'
    
            colrow.prop(self, 'solver', text='')
    
            col.label("Experimental Features:")
            col.prop(self, "fast_transform")
            col.prop(self, "use_wire", text="Use Wire Instead Of Bbox")
    
            col.prop(self, "make_vertex_groups")
            col.prop(self, "make_boundary")
    
            layout.prop(context.scene, "Enable_Tab_01", text="Hot Keys", icon="KEYINGSET")
            if scene.Enable_Tab_01:
                row = layout.row()
    
                col = row.column()
                col.label("Hotkey List:")
                col.label("Menu: Ctrl Shift B")
    
                row = layout.row()
                col = row.column()
                col.label("Brush Operators:")
                col.label("Union: Ctrl Num +")
                col.label("Diff: Ctrl Num -")
                col.label("Intersect: Ctrl Num *")
                col.label("Slice: Ctrl Num /")
    
                row = layout.row()
                col = row.column()
                col.label("Direct Operators:")
                col.label("Direct Union: Ctrl Shift Num +")
                col.label("Direct Difference: Ctrl Shift Num -")
                col.label("Direct Intersect: Ctrl Shift Num *")
                col.label("Direct Slice: Ctrl Shift Num /")
                col.label("BTool Brush To Mesh: Ctrl Num Enter")
                col.label("BTool All Brush To Mesh: Ctrl Shift Num Enter")
    
    
    # ------------------- Class List ------------------------------------------------
    
        BoolTool_Menu,
        BoolTool_Tools,
        BoolTool_Config,
        BoolTool_BViwer,
    
        # Booltron
        Direct_Union,
        Direct_Difference,
        Direct_Intersect,
        Direct_Slice,
        Direct_Subtract,
        # Bool Tools
        BTool_Union,
        BTool_Diff,
        BTool_Inters,
        BTool_Slice,
        BTool_DrawPolyBrush,
        BTool_Remove,
        BTool_AllBrushToMesh,
        BTool_BrushToMesh,
        BTool_FindBrush,
        BTool_MoveStack,
        BTool_EnableBrush,
        BTool_EnableThisBrush,
        BTool_EnableFTransform,
        BTool_FastTransform,
    
    
    # ------------------- REGISTER ------------------------------------------------
    addon_keymaps = []
    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')
    
        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.properties.operator = "Rotate"
        addon_keymapsFastT.append((km, kmi))
    
        kmi = km.keymap_items.new(BTool_FastTransform.bl_idname, 'S', 'PRESS')
        kmi.properties.operator = "Scale"
        addon_keymapsFastT.append((km, kmi))
    
    
    # Fast Transform HotKeys UnRegister
    def UnRegisterFastT():
        wm = bpy.context.window_manager
        km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
    
        for km, kmi in addon_keymapsFastT:
            km.keymap_items.remove(kmi)
        addon_keymapsFastT.clear()
    
    
    def register():
        for cls in classes:
            bpy.utils.register_class(cls)
    
        wm = bpy.context.window_manager
        # Scene variables
    
        bpy.types.Scene.BoolHide = BoolProperty(
    
                default=False,
                description='Hide boolean objects',
                update=update_BoolHide,
                )
        # Handlers
        bpy.app.handlers.scene_update_post.append(HandleScene)
    
        bpy.types.VIEW3D_MT_object.append(VIEW3D_BoolTool_Menu)
    
        # create the boolean menu hotkey
        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 = 'OBJECT_MT_BoolTool_Menu'
    
        # Brush Operators
        kmi = km.keymap_items.new(BTool_Union.bl_idname, 'NUMPAD_PLUS', 'PRESS', ctrl=True)
        kmi = km.keymap_items.new(BTool_Diff.bl_idname, 'NUMPAD_MINUS', 'PRESS', ctrl=True)
        kmi = km.keymap_items.new(BTool_Inters.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', ctrl=True)
        kmi = km.keymap_items.new(BTool_Slice.bl_idname, 'NUMPAD_SLASH', 'PRESS', ctrl=True)
    
        # Direct Operators
        kmi = km.keymap_items.new(Direct_Union.bl_idname, 'NUMPAD_PLUS', 'PRESS', ctrl=True, shift=True)
        kmi = km.keymap_items.new(Direct_Difference.bl_idname, 'NUMPAD_MINUS', 'PRESS', ctrl=True, shift=True)
        kmi = km.keymap_items.new(Direct_Intersect.bl_idname, 'NUMPAD_ASTERIX', 'PRESS', ctrl=True, shift=True)
        kmi = km.keymap_items.new(Direct_Slice.bl_idname, 'NUMPAD_SLASH', 'PRESS', ctrl=True, shift=True)
        kmi = km.keymap_items.new(BTool_BrushToMesh.bl_idname, 'NUMPAD_ENTER', 'PRESS', ctrl=True)
        kmi = km.keymap_items.new(BTool_AllBrushToMesh.bl_idname, 'NUMPAD_ENTER', 'PRESS', ctrl=True, shift=True)
    
        addon_keymaps.append(km)
    
    
    def unregister():
    
        # Keymapping
        # remove keymaps when add-on is deactivated
        wm = bpy.context.window_manager
        for km in addon_keymaps:
            wm.keyconfigs.addon.keymaps.remove(km)
        del addon_keymaps[:]
    
        bpy.types.VIEW3D_MT_object.remove(VIEW3D_BoolTool_Menu)
    
        del bpy.types.Scene.BoolHide
    
        for cls in classes:
            bpy.utils.unregister_class(cls)
    
    if __name__ == "__main__":
        register()