Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Rachinskiy <mikhail.rachinskiy@gmail.com>2016-09-01 01:13:57 +0300
committerMikhail Rachinskiy <mikhail.rachinskiy@gmail.com>2016-09-01 01:13:57 +0300
commit1d3abec502b6975d7d3bac4e6a985b7ee597b6de (patch)
tree60f86da9a5a47ea3483beded7bb4964512e33333
parentd744864e54836195f25ec53e075316505d9de540 (diff)
Bool Tool: Unify and simplify code for direct booleans
-rw-r--r--object_boolean_tools.py137
1 files changed, 60 insertions, 77 deletions
diff --git a/object_boolean_tools.py b/object_boolean_tools.py
index e71dc1ac..79b40100 100644
--- a/object_boolean_tools.py
+++ b/object_boolean_tools.py
@@ -622,51 +622,7 @@ class BTool_Slice(Operator):
return {'FINISHED'}
-# Booltron operators for direct booleans ---------------------------------------------------
-
-
-def prepare_objects():
- bpy.ops.object.make_single_user(object=True, obdata=True)
- bpy.ops.object.convert(target='MESH')
-
-
-def mesh_selection(ob, select_action):
- context = bpy.context
- scene = context.scene
- obj = context.active_object
- ops_me = bpy.ops.mesh
- ops_ob = bpy.ops.object
-
- def mesh_cleanup():
- ops_me.select_all(action='SELECT')
- ops_me.delete_loose()
- ops_me.select_all(action='SELECT')
- ops_me.remove_doubles(threshold=0.0001)
- ops_me.fill_holes(sides=0)
- ops_me.normals_make_consistent()
-
- scene.objects.active = ob
- ops_ob.mode_set(mode='EDIT')
-
- mesh_cleanup()
- ops_me.select_all(action=select_action)
-
- ops_ob.mode_set(mode='OBJECT')
- scene.objects.active = obj
-
-
-def get_objects(context):
- obj = context.active_object
-
- prepare_objects()
-
- obj.select = False
- ob = context.selected_objects[0]
-
- mesh_selection(obj, 'DESELECT')
- mesh_selection(ob, 'SELECT')
-
- return obj, ob
+# Direct booleans operators (maintainer Mikhail Rachinskiy) ---------------------------------------------------
class DirectBooleans:
@@ -674,8 +630,10 @@ class DirectBooleans:
solver = EnumProperty(
name='Boolean Solver',
- items=(('BMESH', 'BMesh', ''),
- ('CARVE', 'Carve', '')),
+ items=(('BMESH', 'BMesh', 'BMesh solver is faster, but less stable '
+ 'and cannot handle coplanar geometry'),
+ ('CARVE', 'Carve', 'Carve solver is slower, but more stable '
+ 'and can handle simple cases of coplanar geometry')),
description='Specify solver for boolean operation',
options={'SKIP_SAVE'}
)
@@ -683,35 +641,48 @@ class DirectBooleans:
def __init__(self):
self.context = bpy.context
self.solver = self.context.user_preferences.addons[__name__].preferences.solver
+ self.obs_prepare()
- def boolean_each(self, mode):
+ def boolean_op(self, mode):
obj = self.context.active_object
-
- prepare_objects()
-
obj.select = False
obs = self.context.selected_objects
- mesh_selection(obj, 'DESELECT')
+ self.mesh_selection(obj, 'DESELECT')
for ob in obs:
- mesh_selection(ob, 'SELECT')
+ self.mesh_selection(ob, 'SELECT')
self.boolean_mod(obj, ob, mode)
obj.select = True
- def boolean_mod(self, obj, ob, mode, terminate=True):
- md = obj.modifiers.new('Immediate apply', 'BOOLEAN')
+ def boolean_mod(self, obj, ob, mode, delete_ob=True):
+ md = obj.modifiers.new('Direct Boolean', 'BOOLEAN')
md.show_viewport = False
- md.show_render = False
md.operation = mode
md.solver = self.solver
md.object = ob
- bpy.ops.object.modifier_apply(modifier='Immediate apply')
- if not terminate:
+ bpy.ops.object.modifier_apply(modifier='Direct Boolean')
+ if not delete_ob:
return
self.context.scene.objects.unlink(ob)
bpy.data.objects.remove(ob)
+ def obs_prepare(self):
+ for ob in self.context.selected_objects:
+ if ob.type != 'MESH':
+ ob.select = False
+ bpy.ops.object.convert(target='MESH')
+
+ def mesh_selection(self, ob, select_action):
+ scene = self.context.scene
+ obj = self.context.active_object
+
+ scene.objects.active = ob
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action=select_action)
+ bpy.ops.object.mode_set(mode='OBJECT')
+ scene.objects.active = obj
+
class Direct_Union(DirectBooleans, Operator):
"""Combine selected objects"""
@@ -719,7 +690,7 @@ class Direct_Union(DirectBooleans, Operator):
bl_label = "Union"
def execute(self, context):
- self.boolean_each('UNION')
+ self.boolean_op('UNION')
return {'FINISHED'}
@@ -729,7 +700,7 @@ class Direct_Difference(DirectBooleans, Operator):
bl_label = "Difference"
def execute(self, context):
- self.boolean_each('DIFFERENCE')
+ self.boolean_op('DIFFERENCE')
return {'FINISHED'}
@@ -739,7 +710,7 @@ class Direct_Intersect(DirectBooleans, Operator):
bl_label = "Intersect"
def execute(self, context):
- self.boolean_each('INTERSECT')
+ self.boolean_op('INTERSECT')
return {'FINISHED'}
@@ -750,20 +721,22 @@ class Direct_Slice(DirectBooleans, Operator):
def execute(self, context):
scene = context.scene
- obj, ob = get_objects(context)
-
- def object_duplicate(ob):
- ops_ob = bpy.ops.object
- ops_ob.select_all(action="DESELECT")
- ops_ob.select_pattern(pattern=ob.name)
- ops_ob.duplicate()
- scene.objects.active = obj
- return context.selected_objects[0]
-
- obj_copy = object_duplicate(obj)
- self.boolean_mod(obj, ob, 'DIFFERENCE', terminate=False)
+ obj = context.active_object
+ obj.select = False
+ 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()
+ scene.objects.link(obj_copy)
+
+ self.boolean_mod(obj, ob, 'DIFFERENCE', delete_ob=False)
scene.objects.active = obj_copy
self.boolean_mod(obj_copy, ob, 'INTERSECT')
+ obj_copy.select = True
+
return {'FINISHED'}
@@ -774,8 +747,14 @@ class Direct_Subtract(DirectBooleans, Operator):
bl_label = "Subtract"
def execute(self, context):
- obj, ob = get_objects(context)
- self.boolean_mod(obj, ob, 'DIFFERENCE', terminate=False)
+ obj = context.active_object
+ obj.select = False
+ ob = context.selected_objects[0]
+
+ self.mesh_selection(obj, 'DESELECT')
+ self.mesh_selection(ob, 'SELECT')
+ self.boolean_mod(obj, ob, 'DIFFERENCE', delete_ob=False)
+
return {'FINISHED'}
@@ -1249,12 +1228,16 @@ class BoolTool_Pref(AddonPreferences):
solver = EnumProperty(
name='Boolean Solver',
- items=(('BMESH', 'BMesh', ''),
- ('CARVE', 'Carve', '')),
+ items=(('BMESH', 'BMesh', 'BMesh solver is faster, but less stable '
+ 'and cannot handle coplanar geometry'),
+ ('CARVE', 'Carve', 'Carve solver is slower, but more stable '
+ 'and can handle simple cases of coplanar geometry')),
default='BMESH',
description='Specify solver for boolean operations'
)
+
bpy.types.Scene.Enable_Tab_01 = bpy.props.BoolProperty(default=False)
+
def draw(self, context):
scene = context.scene
layout = self.layout