-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodifier.py
218 lines (158 loc) · 6.01 KB
/
modifier.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import bpy
from math import radians
import os
from . registration import get_prefs
from . append import append_nodetree
from .. items import mirror_props
from . nodes import get_nodegroup_input_identifier
from bpy.app.translations import pgettext as _
def add_triangulate(obj):
mod = obj.modifiers.new(name="Triangulate", type="TRIANGULATE")
mod.keep_custom_normals = True
mod.quad_method = 'FIXED'
mod.show_expanded = True
return mod
def add_shrinkwrap(obj, target):
mod = obj.modifiers.new(name="Shrinkwrap", type="SHRINKWRAP")
mod.target = target
mod.show_on_cage = True
mod.show_expanded = False
return mod
def add_surface_slide(obj, target):
mod = add_shrinkwrap(obj, target)
mod.name = _('Surface Slide')
return mod
def add_mods_from_dict(obj, modsdict):
for name, props in modsdict.items():
mod = obj.modifiers.new(name=name, type=props['type'])
for pname, pvalue in props.items():
if pname != 'type':
setattr(mod, pname, pvalue)
def add_bevel(obj, method='WEIGHT'):
mod = obj.modifiers.new(name='Bevel', type='BEVEL')
mod.limit_method = method
mod.show_expanded = False
return mod
def add_boolean(obj, operator, method='DIFFERENCE', solver='FAST'):
boolean = obj.modifiers.new(name=method.title(), type="BOOLEAN")
boolean.object = operator
boolean.operation = 'DIFFERENCE' if method == 'SPLIT' else method
boolean.show_in_editmode = True
if method == 'SPLIT':
boolean.show_viewport = False
boolean.solver = solver
return boolean
def add_auto_smooth(obj, angle=20):
smooth_by_angles = [tree for tree in bpy.data.node_groups if tree.name.startswith('Smooth by Angle')]
if smooth_by_angles:
ng = smooth_by_angles[0]
else:
path = os.path.join(bpy.utils.system_resource('DATAFILES'), 'assets', 'geometry_nodes', 'smooth_by_angle.blend')
ng = append_nodetree(path, 'Smooth by Angle')
if not ng:
print("WARNING: Could not import Smooth by Angle node group from ESSENTIALS! This should never happen")
return
mod = obj.modifiers.new(name="Auto Smooth", type="NODES")
mod.node_group = ng
mod.show_expanded = get_prefs().auto_smooth_show_expanded
set_mod_input(mod, 'Angle', radians(angle))
mod.id_data.update_tag()
return mod
def get_auto_smooth(obj):
if (mod := obj.modifiers.get('Auto Smooth', None)) and mod.type == 'NODES':
return mod
elif (mod := obj.modifiers.get('Smooth by Angle', None)) and mod.type == 'NODES':
return mod
else:
mods = [mod for mod in obj.modifiers if mod.type == 'NODES' and (ng := mod.node_group) and ng.name.startswith('Smooth by Angle')]
if mods:
return mods[0]
def get_surface_slide(obj):
mods = [mod for mod in obj.modifiers if mod.type == 'SHRINKWRAP' and 'SurfaceSlide' in mod.name]
if mods:
return mods[0]
def remove_mod(mod):
obj = mod.id_data
if isinstance(mod, bpy.types.Modifier):
obj.modifiers.remove(mod)
elif isinstance(mod, bpy.types.GpencilModifier):
obj.grease_pencil_modifiers.remove(mod)
else:
print(f"WARNING: Could not remove modiifer {mod.name} of type {mod.type}")
def remove_triangulate(obj):
lastmod = obj.modifiers[-1] if obj.modifiers else None
if lastmod and lastmod.type == 'TRIANGULATE':
obj.modifiers.remove(lastmod)
return True
def get_mod_as_dict(mod, skip_show_expanded=False):
d = {}
if mod.type == 'MIRROR':
for prop in mirror_props:
if skip_show_expanded and prop == 'show_expanded':
continue
if prop in ['use_axis', 'use_bisect_axis', 'use_bisect_flip_axis']:
d[prop] = tuple(getattr(mod, prop))
else:
d[prop] = getattr(mod, prop)
return d
def get_mods_as_dict(obj, types=[], skip_show_expanded=False):
mods = []
for mod in obj.modifiers:
if types:
if mod.type in types:
mods.append(mod)
else:
mods.append(mod)
modsdict = {}
for mod in mods:
modsdict[mod.name] = get_mod_as_dict(mod, skip_show_expanded=skip_show_expanded)
return modsdict
def apply_mod(modname):
bpy.ops.object.modifier_apply(modifier=modname)
def get_mod_obj(mod):
if mod.type in ['BOOLEAN', 'HOOK', 'LATTICE', 'DATA_TRANSFER', 'GP_MIRROR']:
return mod.object
elif mod.type == 'MIRROR':
return mod.mirror_object
elif mod.type == 'ARRAY':
return mod.offset_object
def move_mod(mod, index=0):
obj = mod.id_data
current_index = list(obj.modifiers).index(mod)
if current_index != index:
obj.modifiers.move(current_index, index)
def sort_mod(mod):
def is_mirror(mod):
return mod.type == 'MIRROR'
def is_array(mod):
return mod.type == 'ARRAY'
def is_auto_smooth(mod):
return mod.type == 'NODES' and mod.node_group and 'Smooth by Angle' in mod.node_group.name
def should_preceed(mod, prev_mod):
if is_auto_smooth(mod):
return any([is_mirror(prev_mod), is_array(prev_mod)])
if is_auto_smooth(mod):
obj = mod.id_data
mods = list(obj.modifiers)
if len(mods) > 1:
move_mod(mod, len(mods) - 1)
index = len(mods) - 1
while index:
index -= 1
prev_mod = obj.modifiers[index]
if should_preceed(mod, prev_mod):
if index == 0:
move_mod(mod, index)
continue
else:
move_mod(mod, index + 1)
break
def get_mod_input(mod, name):
if ng := mod.node_group:
identifier, socket_type = get_nodegroup_input_identifier(ng, name)
if identifier:
return mod[identifier]
def set_mod_input(mod, name, value):
if ng := mod.node_group:
identifier, socket_type = get_nodegroup_input_identifier(ng, name)
mod[identifier] = value