-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsubdivideplusOt.py
166 lines (137 loc) · 6.55 KB
/
subdivideplusOt.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# Name : Subdivide+
# Description : Subdivide+ and then select the newly created edges
# Author : iceythe (Kaio)
# Permission : Special thanks to iceythe for the creation of this script and permission to include it with the Neltulz - Bonus Utils add-on
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
import bpy
import bmesh
from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, FloatVectorProperty, EnumProperty, PointerProperty)
from bpy.types import (Panel, Operator, AddonPreferences, PropertyGroup)
class VIEW3D_OT_ntzbu_subdivide_plus(Operator):
bl_idname = 'view3d.ntzbu_subdivide_plus'
bl_description = 'Subdivide with additional features for automatically selecting newly added vertices and edgse, etc.'
bl_label = 'NTZBU : Subdivide+'
bl_options = {'REGISTER', 'UNDO'}
_falloffs = (('SMOOTH', 'Smooth', '', 0),
('SPHERE', 'Sphere', '', 1),
('ROOT', 'Root', '', 2),
('SHARP', 'Sharp', '', 3),
('LINEAR', 'Linear', '', 4),
('INVERSE_SQUARE', 'Inverse Square', '', 5))
_corner_type = (('STRAIGHT_CUT', 'Straight Cut', '', 0),
('INNER_VERT', 'Inner Vert', '', 1),
('PATH', 'Path', '', 2),
('FAN', 'Fan', '', 3))
_single_edge = None
flatten: BoolProperty(name='Flatten', default=True)
_flat_swap = False
_smooth_val = 0.0
cuts: IntProperty(name='Number Cuts', default=1,
min=1, max=500)
smooth: FloatProperty(name='Smoothness', default=0.0, min=-2.0)
falloff: EnumProperty(name='Smooth Falloff', default='SMOOTH',
items=_falloffs)
quad_corner: EnumProperty(name='Quad Corner Type',
default='INNER_VERT', items=_corner_type)
grid_fill: BoolProperty(name='Grid Fill', default=True)
single_edge: BoolProperty(name='Single Edge', default=False)
only_quads: BoolProperty(name='Only Quads', default=False)
sphere: BoolProperty(name='Spherize', default=False)
smooth_even: BoolProperty(name='Even Smoothing', default=False)
fractal: FloatProperty(name='Fractal Noise', default=0.0)
along_normal: FloatProperty(name='Along Normal', default=0.0)
seed: IntProperty(name='Seed', default=0)
edge_percents: FloatProperty(name='Edge Percent', default=0.5,
min=0.0, max=1.0)
@classmethod
def poll(cls, context):
return (context.mode == 'EDIT_MESH' and
context.object.data.total_edge_sel)
def is_individual(self, edges):
for edge in edges:
for v in edge.verts:
for e in v.link_edges:
if e.select and e is not edge:
return False
return True
def execute(self, context):
smooth_val = self._smooth_val
flat_swap = self._flat_swap
smooth = self.smooth
flatten = self.flatten
me = context.object.data
bm = bmesh.from_edit_mesh(me)
totface = me.total_face_sel
msm = context.tool_settings.path_resolve('mesh_select_mode', False)
edges_pre = set(bm.edges)
edges = [e for e in bm.edges if e.select]
individual = self.is_individual(edges)
if smooth != 0 and flatten and not flat_swap:
self.flatten = flatten = False
self._flat_swap = flat_swap = True
if smooth != 0 and flatten and flat_swap:
self._smooth_val = smooth_val = smooth
self.smooth = smooth = 0
self._flat_swap = flat_swap = False
elif smooth == 0 and not flatten and smooth_val is not None:
self.smooth = smooth_val
self._smooth_val = None
self._flat_swap = True
edge_percents = {}
if self.edge_percents != 0.5:
edge_percents = {e: self.edge_percents for e in edges}
ret = bmesh.ops.subdivide_edges(
bm, edges=edges, use_smooth_even=self.smooth_even,
smooth_falloff=self.falloff, fractal=self.fractal,
along_normal=self.along_normal, use_sphere=self.sphere,
quad_corner_type=self.quad_corner, seed=self.seed,
use_single_edge=self.single_edge, cuts=self.cuts,
use_only_quads=self.only_quads, smooth=self.smooth,
edge_percents=edge_percents, use_grid_fill=self.grid_fill)
geom_inner = ret['geom_inner']
inner = ret['geom_inner']
split = ret['geom_split']
if individual and len(edges) > 1:
# assume vert select mode
for elem in ret['geom']:
elem.select = False
bm.select_history.add(geom_inner[-1])
geom_inner[-1].select = True
for elem in geom_inner:
elem.select = True
elif msm[:] == (1, 0, 0):
for v in bm.verts:
v.select = False
for elem in ret['geom']:
if isinstance(elem, bmesh.types.BMVert):
elem.select = True
elif (len(edges) == 1 and len(geom_inner) == 1) or self._single_edge:
bm.select_mode = {'VERT'}
vert = geom_inner[0]
bm.select_history.add(vert)
msm[:] = 1, 0, 0
self._single_edge = True
for elem in geom_inner:
elem.select = True
elif msm[:] == (0, 1, 0) and not totface:
# print("edges mode, quad corner")
for elem in ret['geom']:
elem.select = False
edges_post = set(bm.edges).difference(edges_pre)
geom = set(j for i in ret.values() for j in i)
corner_geom = [e for e in edges_post if e not in geom]
for e in corner_geom:
if any([True for v in e.verts if v in split]):
e.select = True
continue
e.select = False
for e in inner:
if isinstance(e, bmesh.types.BMEdge):
e.select = True
else:
for elem in geom_inner:
elem.select = True
bm.select_flush_mode()
bmesh.update_edit_mesh(me)
return {'FINISHED'}