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:
Diffstat (limited to 'mesh_extra_tools/mesh_extrude_and_reshape.py')
-rw-r--r--mesh_extra_tools/mesh_extrude_and_reshape.py133
1 files changed, 73 insertions, 60 deletions
diff --git a/mesh_extra_tools/mesh_extrude_and_reshape.py b/mesh_extra_tools/mesh_extrude_and_reshape.py
index 14d9d744..8716bfb1 100644
--- a/mesh_extra_tools/mesh_extrude_and_reshape.py
+++ b/mesh_extra_tools/mesh_extrude_and_reshape.py
@@ -1,4 +1,4 @@
-### BEGIN GPL LICENSE BLOCK #####
+# ##### 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
@@ -25,14 +25,17 @@ bl_info = {
"version": (0, 8, 1),
"blender": (2, 76, 5),
"location": "View3D > TOOLS > Tools > Mesh Tools > Add: > Extrude Menu (Alt + E)",
- "description": "Extrude face and merge edge intersections between the mesh and the new edges",
- "wiki_url" : "http://blenderartists.org/forum/showthread.php?376618-Addon-Push-Pull-Face",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
+ "description": "Extrude face and merge edge intersections "
+ "between the mesh and the new edges",
+ "wiki_url": "http://blenderartists.org/forum/"
+ "showthread.php?376618-Addon-Push-Pull-Face",
"category": "Mesh"}
-import bpy, bmesh
+import bpy
+import bmesh
from mathutils.geometry import intersect_line_line
-from bpy.props import FloatProperty
+from bpy.types import Operator
+
class BVHco():
i = 0
@@ -43,7 +46,8 @@ class BVHco():
c2y = 0.0
c2z = 0.0
-def edges_BVH_overlap(bm, edges, epsilon = 0.0001):
+
+def edges_BVH_overlap(bm, edges, epsilon=0.0001):
bco = set()
for e in edges:
bvh = BVHco()
@@ -113,19 +117,19 @@ def edges_BVH_overlap(bm, edges, epsilon = 0.0001):
overlap[e1] = oget(e1, set()).union({e2})
return overlap
-def intersect_edges_edges(overlap, precision = 4):
+
+def intersect_edges_edges(overlap, precision=4):
epsilon = .1**precision
fpre_min = -epsilon
- fpre_max = 1+epsilon
+ fpre_max = 1 + epsilon
splits = {}
sp_get = splits.get
new_edges1 = set()
new_edges2 = set()
targetmap = {}
for edg1 in overlap:
- #print("***", ed1.index, "***")
+ # print("***", ed1.index, "***")
for edg2 in overlap[edg1]:
- #print('loop', ed2.index)
a1 = edg1.verts[0]
a2 = edg1.verts[1]
b1 = edg2.verts[0]
@@ -133,7 +137,7 @@ def intersect_edges_edges(overlap, precision = 4):
# test if are linked
if a1 in {b1, b2} or a2 in {b1, b2}:
- #print('linked')
+ # print('linked')
continue
aco1, aco2 = a1.co, a2.co
@@ -141,23 +145,23 @@ def intersect_edges_edges(overlap, precision = 4):
tp = intersect_line_line(aco1, aco2, bco1, bco2)
if tp:
p1, p2 = tp
- if (p1 - p2).to_tuple(precision) == (0,0,0):
- v = aco2-aco1
+ if (p1 - p2).to_tuple(precision) == (0, 0, 0):
+ v = aco2 - aco1
f = p1 - aco1
- x,y,z = abs(v.x), abs(v.y), abs(v.z)
+ x, y, z = abs(v.x), abs(v.y), abs(v.z)
max1 = 0 if x >= y and x >= z else\
1 if y >= x and y >= z else 2
- fac1 = f[max1]/v[max1]
+ fac1 = f[max1] / v[max1]
- v = bco2-bco1
+ v = bco2 - bco1
f = p2 - bco1
- x,y,z = abs(v.x), abs(v.y), abs(v.z)
+ x, y, z = abs(v.x), abs(v.y), abs(v.z)
max2 = 0 if x >= y and x >= z else\
1 if y >= x and y >= z else 2
- fac2 = f[max2]/v[max2]
+ fac2 = f[max2] / v[max2]
if fpre_min <= fac1 <= fpre_max:
- #print(edg1.index, 'can intersect', edg2.index)
+ # print(edg1.index, 'can intersect', edg2.index)
ed1 = edg1
elif edg1 in splits:
@@ -168,21 +172,21 @@ def intersect_edges_edges(overlap, precision = 4):
vco1 = a1.co
vco2 = a2.co
- v = vco2-vco1
+ v = vco2 - vco1
f = p1 - vco1
- fac1 = f[max1]/v[max1]
+ fac1 = f[max1] / v[max1]
if fpre_min <= fac1 <= fpre_max:
- #print(e.index, 'can intersect', edg2.index)
+ # print(e.index, 'can intersect', edg2.index)
break
else:
- #print(edg1.index, 'really does not intersect', edg2.index)
+ # print(edg1.index, 'really does not intersect', edg2.index)
continue
else:
- #print(edg1.index, 'not intersect', edg2.index)
+ # print(edg1.index, 'not intersect', edg2.index)
continue
if fpre_min <= fac2 <= fpre_max:
- #print(ed1.index, 'actually intersect', edg2.index)
+ # print(ed1.index, 'actually intersect', edg2.index)
ed2 = edg2
elif edg2 in splits:
@@ -193,17 +197,17 @@ def intersect_edges_edges(overlap, precision = 4):
vco1 = b1.co
vco2 = b2.co
- v = vco2-vco1
+ v = vco2 - vco1
f = p2 - vco1
- fac2 = f[max2]/v[max2]
+ fac2 = f[max2] / v[max2]
if fpre_min <= fac2 <= fpre_max:
- #print(ed1.index, 'actually intersect', e.index)
+ # print(ed1.index, 'actually intersect', e.index)
break
else:
- #print(ed1.index, 'really does not intersect', ed2.index)
+ # print(ed1.index, 'really does not intersect', ed2.index)
continue
else:
- #print(ed1.index, 'not intersect', edg2.index)
+ # print(ed1.index, 'not intersect', edg2.index)
continue
new_edges1.add(ed1)
@@ -227,30 +231,28 @@ def intersect_edges_edges(overlap, precision = 4):
new_edges2.add(ne2)
splits[edg2] = sp_get(edg2, set()).union({ne2})
- if nv1 != nv2: #necessary?
+ if nv1 != nv2: # necessary?
targetmap[nv1] = nv2
- #else:
- #print('not coplanar')
- #else:
- #print("parallel or collinear")
+
return new_edges1, new_edges2, targetmap
-class Extrude_and_Reshape(bpy.types.Operator):
- """Push and pull face entities to sculpt 3d models"""
+
+class Extrude_and_Reshape(Operator):
bl_idname = "mesh.extrude_reshape"
bl_label = "Extrude and Reshape"
+ bl_description = "Push and pull face entities to sculpt 3d models"
bl_options = {'REGISTER', 'GRAB_CURSOR', 'BLOCKING'}
@classmethod
def poll(cls, context):
- return context.mode is not 'EDIT_MESH'
+ return context.mode is not 'EDIT_MESH'
def modal(self, context, event):
if self.confirm:
sface = self.bm.faces.active
if not sface:
for face in self.bm.faces:
- if face.select == True:
+ if face.select is True:
sface = face
break
else:
@@ -259,13 +261,13 @@ class Extrude_and_Reshape(bpy.types.Operator):
edges = set()
[[edges.add(ed) for ed in v.link_edges] for v in sface.verts]
- overlap = edges_BVH_overlap(self.bm, edges, epsilon = 0.0001)
- overlap = {k: v for k,v in overlap.items() if k not in edges} # remove repetition
-
- #print([e.index for e in edges])
- #for a, b in overlap.items():
- #print(a.index, [e.index for e in b])
-
+ overlap = edges_BVH_overlap(self.bm, edges, epsilon=0.0001)
+ overlap = {k: v for k, v in overlap.items() if k not in edges} # remove repetition
+ """
+ print([e.index for e in edges])
+ for a, b in overlap.items():
+ print(a.index, [e.index for e in b])
+ """
new_edges1, new_edges2, targetmap = intersect_edges_edges(overlap)
pos_weld = set()
for e in new_edges1:
@@ -274,9 +276,11 @@ class Extrude_and_Reshape(bpy.types.Operator):
pos_weld.add((targetmap[v1], targetmap[v2]))
if targetmap:
bmesh.ops.weld_verts(self.bm, targetmap=targetmap)
- #print([e.is_valid for e in new_edges1])
- #print([e.is_valid for e in new_edges2])
- #sp_faces1 = set()
+ """
+ print([e.is_valid for e in new_edges1])
+ print([e.is_valid for e in new_edges2])
+ sp_faces1 = set()
+ """
for e in pos_weld:
v1, v2 = e
lf1 = set(v1.link_faces)
@@ -285,11 +289,11 @@ class Extrude_and_Reshape(bpy.types.Operator):
for f in rlfe:
try:
nf = bmesh.utils.face_split(f, v1, v2)
- #sp_faces1.update({f, nf[0]})
+ # sp_faces1.update({f, nf[0]})
except:
pass
- #sp_faces2 = set()
+ # sp_faces2 = set()
for e in new_edges2:
lfe = set(e.link_faces)
v1, v2 = e.verts
@@ -298,7 +302,7 @@ class Extrude_and_Reshape(bpy.types.Operator):
rlfe = lf1.intersection(lf2)
for f in rlfe.difference(lfe):
nf = bmesh.utils.face_split(f, v1, v2)
- #sp_faces2.update({f, nf[0]})
+ # sp_faces2.update({f, nf[0]})
bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
return {'FINISHED'}
@@ -315,7 +319,7 @@ class Extrude_and_Reshape(bpy.types.Operator):
selection = self.bm.select_history[-1]
except:
for face in self.bm.faces:
- if face.select == True:
+ if face.select is True:
selection = face
break
else:
@@ -325,22 +329,27 @@ class Extrude_and_Reshape(bpy.types.Operator):
return {'FINISHED'}
else:
face = selection
- #face.select = False
+ # face.select = False
bpy.ops.mesh.select_all(action='DESELECT')
geom = []
for edge in face.edges:
- if abs(edge.calc_face_angle(0) - 1.5707963267948966) < 0.01: #self.angle_tolerance:
+ if abs(edge.calc_face_angle(0) - 1.5707963267948966) < 0.01: # self.angle_tolerance:
geom.append(edge)
- ret_dict = bmesh.ops.extrude_discrete_faces(self.bm, faces = [face])
+ ret_dict = bmesh.ops.extrude_discrete_faces(self.bm, faces=[face])
for face in ret_dict['faces']:
self.bm.faces.active = face
face.select = True
sface = face
- dfaces = bmesh.ops.dissolve_edges(self.bm, edges = geom, use_verts=True, use_face_split=False)
+ dfaces = bmesh.ops.dissolve_edges(
+ self.bm, edges=geom, use_verts=True, use_face_split=False
+ )
bmesh.update_edit_mesh(self.mesh, tessface=True, destructive=True)
- bpy.ops.transform.translate('INVOKE_DEFAULT', constraint_axis=(False, False, True), constraint_orientation='NORMAL', release_confirm=True)
+ bpy.ops.transform.translate(
+ 'INVOKE_DEFAULT', constraint_axis=(False, False, True),
+ constraint_orientation='NORMAL', release_confirm=True
+ )
context.window_manager.modal_handler_add(self)
@@ -348,18 +357,22 @@ class Extrude_and_Reshape(bpy.types.Operator):
self.confirm = False
return {'RUNNING_MODAL'}
-def operator_draw(self,context):
+
+def operator_draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.operator("mesh.extrude_reshape", text="Extrude and Reshape")
+
def register():
bpy.utils.register_class(Extrude_and_Reshape)
bpy.types.VIEW3D_MT_edit_mesh_extrude.append(operator_draw)
+
def unregister():
bpy.types.VIEW3D_MT_edit_mesh_extrude.remove(operator_draw)
bpy.utils.unregister_class(Extrude_and_Reshape)
+
if __name__ == "__main__":
register()