forked from BenjaminSauder/EdgeFlow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
op_set_edge_flow.py
122 lines (85 loc) · 3.46 KB
/
op_set_edge_flow.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import math
import bpy
from bpy.props import IntProperty, FloatProperty, EnumProperty
import bmesh
from . import util
class SetEdgeLoopBase():
def get_bm(self, obj):
bm = bmesh.new()
bm.from_mesh(obj.data)
bm.normal_update()
bm.verts.ensure_lookup_table()
return bm
def revert(self):
# print("reverting vertex positions")
for obj in self.objects:
if obj in self.vert_positions:
for vert, pos in self.vert_positions[obj].items():
# print("revert: %s -> %s" % (vert.index, pos))
vert.co = pos
@classmethod
def poll(cls, context):
return (
context.space_data.type == 'VIEW_3D'
and context.active_object is not None
and context.active_object.type == "MESH"
and context.active_object.mode == 'EDIT')
def invoke(self, context):
#sprint("base invoke")
self.objects = set(context.selected_editable_objects)
self.bm = {}
self.edgeloops = {}
self.vert_positions = {}
bpy.ops.object.mode_set(mode='OBJECT')
ignore = set()
for obj in self.objects:
self.bm[obj] = self.get_bm(obj)
edges = [e for e in self.bm[obj].edges if e.select]
if len(edges) == 0:
ignore.add(obj)
continue
#print("no edges selected")
#bpy.ops.object.mode_set(mode='EDIT')
#return {'CANCELLED'}
#self.edges = edges
self.vert_positions[obj] = {}
for e in edges:
for v in e.verts:
if v not in self.vert_positions[obj]:
# print("storing: %s " % v.co)
p = v.co.copy()
p = p.freeze()
self.vert_positions[obj][v] = p
self.edgeloops[obj] = util.get_edgeloops(self.bm[obj], edges)
self.objects = self.objects - ignore
return {'PASS_THROUGH'}
class SetEdgeFlowOP(bpy.types.Operator, SetEdgeLoopBase):
bl_idname = "mesh.set_edge_flow"
bl_label = "Set edge flow"
bl_options = {'REGISTER', 'UNDO'}
bl_description = "adjust edge loops to curvature"
tension : IntProperty(name="Tension", default=180, min=-500, max=500)
iterations : IntProperty(name="Iterations", default=1, min=1, max=32)
#bias = IntProperty(name="Bias", default=0, min=-100, max=100)
min_angle : IntProperty(name="Min Angle", default=0, min=0, max=180, subtype='FACTOR' )
def execute(self, context):
#print ("execute")
bpy.ops.object.mode_set(mode='OBJECT')
self.revert()
for obj in self.objects:
for i in range(self.iterations):
for edgeloop in self.edgeloops[obj]:
edgeloop.set_flow(self.tension / 100.0, math.radians(self.min_angle) )
self.bm[obj].to_mesh(obj.data)
bpy.ops.object.mode_set(mode='EDIT')
return {'FINISHED'}
def invoke(self, context, event):
#print("invoke")
self.tension = 180
self.iterations = 1
self.bias = 0
#self.min_angle = 0
result = super(SetEdgeFlowOP, self).invoke(context)
if "CANCELLED" in result:
return result
return self.execute(context)