d7b222523e371ee4e4cc264d3c4928039b2e6e3e
[blender.git] / release / scripts / startup / bl_ui / properties_physics_softbody.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 import bpy
22 from bpy.types import (
23     Panel,
24 )
25 from .properties_physics_common import (
26     point_cache_ui,
27     effector_weights_ui,
28 )
29
30 COMPAT_OB_TYPES = {'MESH', 'LATTICE', 'CURVE', 'SURFACE', 'FONT'}
31
32
33 def softbody_panel_enabled(md):
34     return (md.point_cache.is_baked is False)
35
36
37 class PhysicButtonsPanel:
38     bl_space_type = 'PROPERTIES'
39     bl_region_type = 'WINDOW'
40     bl_context = "physics"
41
42     @classmethod
43     def poll(cls, context):
44         ob = context.object
45         return ob and ob.type in COMPAT_OB_TYPES and context.engine in cls.COMPAT_ENGINES and context.soft_body
46
47
48 class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
49     bl_label = "Soft Body"
50     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
51
52     def draw(self, context):
53         layout = self.layout
54         layout.use_property_split = True
55
56         md = context.soft_body
57         softbody = md.settings
58
59         layout.prop(softbody, "collision_collection")
60
61
62 class PHYSICS_PT_softbody_object(PhysicButtonsPanel, Panel):
63     bl_label = "Object"
64     bl_parent_id = 'PHYSICS_PT_softbody'
65     bl_options = {'DEFAULT_CLOSED'}
66     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
67
68     def draw(self, context):
69         layout = self.layout
70         layout.use_property_split = True
71
72         md = context.soft_body
73         softbody = md.settings
74         ob = context.object
75
76         layout.enabled = softbody_panel_enabled(md)
77         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
78
79         col = flow.column()
80         col.prop(softbody, "friction")
81
82         col.separator()
83
84         col = flow.column()
85         col.prop(softbody, "mass")
86
87         col.prop_search(softbody, "vertex_group_mass", ob, "vertex_groups", text="Control Point")
88
89
90 class PHYSICS_PT_softbody_simulation(PhysicButtonsPanel, Panel):
91     bl_label = "Simulation"
92     bl_parent_id = 'PHYSICS_PT_softbody'
93     bl_options = {'DEFAULT_CLOSED'}
94     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
95
96     def draw(self, context):
97         layout = self.layout
98         layout.use_property_split = True
99
100         md = context.soft_body
101         softbody = md.settings
102
103         layout.enabled = softbody_panel_enabled(md)
104
105         layout.prop(softbody, "speed")
106
107
108 class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
109     bl_label = "Cache"
110     bl_parent_id = 'PHYSICS_PT_softbody'
111     bl_options = {'DEFAULT_CLOSED'}
112     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
113
114     def draw(self, context):
115         md = context.soft_body
116         point_cache_ui(self, context, md.point_cache, softbody_panel_enabled(md), 'SOFTBODY')
117
118
119 class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
120     bl_label = "Goal"
121     bl_parent_id = 'PHYSICS_PT_softbody'
122     bl_options = {'DEFAULT_CLOSED'}
123     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
124
125     def draw_header(self, context):
126         softbody = context.soft_body.settings
127
128         self.layout.active = softbody_panel_enabled(context.soft_body)
129         self.layout.prop(softbody, "use_goal", text="")
130
131     def draw(self, context):
132         layout = self.layout
133         layout.use_property_split = True
134
135         md = context.soft_body
136         softbody = md.settings
137         ob = context.object
138
139         layout.active = softbody.use_goal and softbody_panel_enabled(md)
140
141         layout.prop_search(softbody, "vertex_group_goal", ob, "vertex_groups", text="Vertex Group")
142
143
144 class PHYSICS_PT_softbody_goal_strengths(PhysicButtonsPanel, Panel):
145     bl_label = "Strengths"
146     bl_parent_id = 'PHYSICS_PT_softbody_goal'
147     bl_options = {'DEFAULT_CLOSED'}
148     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
149
150     def draw(self, context):
151         layout = self.layout
152         layout.use_property_split = True
153
154         md = context.soft_body
155         softbody = md.settings
156
157         layout.active = softbody.use_goal and softbody_panel_enabled(md)
158         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
159
160         col = flow.column()
161         col.prop(softbody, "goal_default", text="Default")
162
163         col.separator()
164
165         col = flow.column(align=True)
166         col.prop(softbody, "goal_min", text="Min")
167         col.prop(softbody, "goal_max", text="Max")
168
169
170 class PHYSICS_PT_softbody_goal_settings(PhysicButtonsPanel, Panel):
171     bl_label = "Settings"
172     bl_parent_id = 'PHYSICS_PT_softbody_goal'
173     bl_options = {'DEFAULT_CLOSED'}
174     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
175
176     def draw(self, context):
177         layout = self.layout
178         layout.use_property_split = True
179
180         md = context.soft_body
181         softbody = md.settings
182
183         layout.active = softbody.use_goal and softbody_panel_enabled(md)
184         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
185
186         col = flow.column()
187         col.prop(softbody, "goal_spring", text="Stiffness")
188
189         col = flow.column()
190         col.prop(softbody, "goal_friction", text="Damping")
191
192
193 class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel):
194     bl_label = "Edges"
195     bl_parent_id = 'PHYSICS_PT_softbody'
196     bl_options = {'DEFAULT_CLOSED'}
197     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
198
199     def draw_header(self, context):
200         softbody = context.soft_body.settings
201
202         self.layout.active = softbody_panel_enabled(context.soft_body)
203         self.layout.prop(softbody, "use_edges", text="")
204
205     def draw(self, context):
206         layout = self.layout
207         layout.use_property_split = True
208
209         md = context.soft_body
210         softbody = md.settings
211         ob = context.object
212
213         layout.active = softbody.use_edges and softbody_panel_enabled(md)
214         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
215
216         col = flow.column()
217
218         col.prop_search(softbody, "vertex_group_spring", ob, "vertex_groups", text="Springs")
219
220         col.separator()
221
222         col.prop(softbody, "pull")
223         col.prop(softbody, "push")
224
225         col.separator()
226
227         col = flow.column()
228         col.prop(softbody, "damping")
229         col.prop(softbody, "plastic")
230         col.prop(softbody, "bend")
231
232         col.separator()
233
234         col = flow.column()
235         col.prop(softbody, "spring_length", text="Length")
236         col.prop(softbody, "use_edge_collision", text="Collision Edge")
237         col.prop(softbody, "use_face_collision", text="Face")
238
239
240 class PHYSICS_PT_softbody_edge_aerodynamics(PhysicButtonsPanel, Panel):
241     bl_label = "Aerodynamics"
242     bl_parent_id = 'PHYSICS_PT_softbody_edge'
243     bl_options = {'DEFAULT_CLOSED'}
244     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
245
246     def draw(self, context):
247         layout = self.layout
248         layout.use_property_split = True
249         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
250
251         md = context.soft_body
252         softbody = md.settings
253
254         flow.active = softbody.use_edges and softbody_panel_enabled(md)
255
256         col = flow.column()
257         col.prop(softbody, "aerodynamics_type", text="Type")
258
259         col = flow.column()
260         col.prop(softbody, "aero", text="Factor")
261
262
263 class PHYSICS_PT_softbody_edge_stiffness(PhysicButtonsPanel, Panel):
264     bl_label = "Stiffness"
265     bl_parent_id = 'PHYSICS_PT_softbody_edge'
266     bl_options = {'DEFAULT_CLOSED'}
267     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
268
269     def draw_header(self, context):
270         softbody = context.soft_body.settings
271
272         self.layout.active = softbody_panel_enabled(context.soft_body)
273         self.layout.prop(softbody, "use_stiff_quads", text="")
274
275     def draw(self, context):
276         layout = self.layout
277         layout.use_property_split = True
278
279         md = context.soft_body
280         softbody = md.settings
281
282         layout.active = softbody.use_edges and softbody.use_stiff_quads and softbody_panel_enabled(md)
283
284         layout.prop(softbody, "shear")
285
286
287 class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
288     bl_label = "Self Collision"
289     bl_parent_id = 'PHYSICS_PT_softbody'
290     bl_options = {'DEFAULT_CLOSED'}
291     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
292
293     def draw_header(self, context):
294         softbody = context.soft_body.settings
295
296         self.layout.active = softbody_panel_enabled(context.soft_body)
297         self.layout.prop(softbody, "use_self_collision", text="")
298
299     def draw(self, context):
300         layout = self.layout
301         layout.use_property_split = True
302
303         md = context.soft_body
304         softbody = md.settings
305
306         layout.active = softbody.use_self_collision and softbody_panel_enabled(md)
307
308         layout.prop(softbody, "collision_type", text="Calculation Type")
309
310         layout.separator()
311
312         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
313
314         col = flow.column()
315         col.prop(softbody, "ball_size", text="Ball Size")
316
317         col = flow.column()
318         col.prop(softbody, "ball_stiff", text="Stiffness")
319         col.prop(softbody, "ball_damp", text="Dampening")
320
321
322 class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel):
323     bl_label = "Solver"
324     bl_parent_id = 'PHYSICS_PT_softbody'
325     bl_options = {'DEFAULT_CLOSED'}
326     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
327
328     def draw(self, context):
329         layout = self.layout
330         layout.use_property_split = True
331
332         md = context.soft_body
333         softbody = md.settings
334
335         layout.active = softbody_panel_enabled(md)
336         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
337
338         col = flow.column(align=True)
339         col.prop(softbody, "step_min", text="Step Size Min")
340         col.prop(softbody, "step_max", text="Max")
341
342         col = flow.column()
343         col.prop(softbody, "use_auto_step", text="Auto-Step")
344         col.prop(softbody, "error_threshold")
345
346
347 class PHYSICS_PT_softbody_solver_diagnostics(PhysicButtonsPanel, Panel):
348     bl_label = "Diagnostics"
349     bl_parent_id = 'PHYSICS_PT_softbody_solver'
350     bl_options = {'DEFAULT_CLOSED'}
351     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
352
353     def draw(self, context):
354         layout = self.layout
355         layout.use_property_split = True
356
357         md = context.soft_body
358         softbody = md.settings
359
360         layout.active = softbody_panel_enabled(md)
361
362         layout.prop(softbody, "use_diagnose")
363         layout.prop(softbody, "use_estimate_matrix")
364
365
366 class PHYSICS_PT_softbody_solver_helpers(PhysicButtonsPanel, Panel):
367     bl_label = "Helpers"
368     bl_parent_id = 'PHYSICS_PT_softbody_solver'
369     bl_options = {'DEFAULT_CLOSED'}
370     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
371
372     def draw(self, context):
373         layout = self.layout
374         layout.use_property_split = True
375
376         md = context.soft_body
377         softbody = md.settings
378
379         layout.active = softbody_panel_enabled(md)
380         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
381
382         col = flow.column()
383         col.prop(softbody, "choke")
384
385         col = flow.column()
386         col.prop(softbody, "fuzzy")
387
388
389 class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
390     bl_label = "Field Weights"
391     bl_parent_id = 'PHYSICS_PT_softbody'
392     bl_options = {'DEFAULT_CLOSED'}
393     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
394
395     def draw(self, context):
396         md = context.soft_body
397         softbody = md.settings
398
399         effector_weights_ui(self, context, softbody.effector_weights, 'SOFTBODY')
400
401
402 classes = (
403     PHYSICS_PT_softbody,
404     PHYSICS_PT_softbody_object,
405     PHYSICS_PT_softbody_simulation,
406     PHYSICS_PT_softbody_cache,
407     PHYSICS_PT_softbody_goal,
408     PHYSICS_PT_softbody_goal_settings,
409     PHYSICS_PT_softbody_goal_strengths,
410     PHYSICS_PT_softbody_edge,
411     PHYSICS_PT_softbody_edge_aerodynamics,
412     PHYSICS_PT_softbody_edge_stiffness,
413     PHYSICS_PT_softbody_collision,
414     PHYSICS_PT_softbody_solver,
415     PHYSICS_PT_softbody_solver_diagnostics,
416     PHYSICS_PT_softbody_solver_helpers,
417     PHYSICS_PT_softbody_field_weights,
418 )
419
420
421 if __name__ == "__main__":  # only for live edit.
422     from bpy.utils import register_class
423     for cls in classes:
424         register_class(cls)