forked from BenjaminSauder/EdgeFlow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
op_set_edge_flow.py
121 lines (85 loc) · 3.56 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
import math
import bpy
from bpy.props import IntProperty, FloatProperty, EnumProperty
import bmesh
from . import util
class SetEdgeLoopBase():
def __init__(self):
self.is_invoked = False
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):
# print("base invoke")
self.is_invoked = True
self.objects = set(context.selected_editable_objects) if context.selected_editable_objects else set([context.object])
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
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
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, soft_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")
# print(f"Tension:{self.tension} Iterations:{self.iterations}")
if not self.is_invoked:
return self.invoke(context, None)
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")
if event:
self.tension = 180
self.iterations = 1
self.bias = 0
#self.min_angle = 0
super(SetEdgeFlowOP, self).invoke(context)
return self.execute(context)