Fix for [#22667] Soft Body Aero on/off switch
[blender-staging.git] / release / scripts / 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 import bpy
21
22 narrowui = bpy.context.user_preferences.view.properties_width_check
23
24
25 from properties_physics_common import point_cache_ui
26 from properties_physics_common import effector_weights_ui
27
28
29 def softbody_panel_enabled(md):
30     return (md.point_cache.baked is False)
31
32
33 class PhysicButtonsPanel(bpy.types.Panel):
34     bl_space_type = 'PROPERTIES'
35     bl_region_type = 'WINDOW'
36     bl_context = "physics"
37
38     def poll(self, context):
39         ob = context.object
40         rd = context.scene.render
41 #        return (ob and ob.type == 'MESH') and (not rd.use_game_engine)
42 # i really hate touching things i do not understand completely .. but i think this should read (bjornmose)
43         return (ob and (ob.type == 'MESH' or ob.type == 'LATTICE'or ob.type == 'CURVE')) and (not rd.use_game_engine)
44
45
46 class PHYSICS_PT_softbody(PhysicButtonsPanel):
47     bl_label = "Soft Body"
48
49     def draw(self, context):
50         layout = self.layout
51
52         md = context.soft_body
53         ob = context.object
54         wide_ui = context.region.width > narrowui
55
56         split = layout.split()
57
58         if md:
59             # remove modifier + settings
60             split.set_context_pointer("modifier", md)
61             split.operator("object.modifier_remove", text="Remove")
62
63             row = split.row(align=True)
64             row.prop(md, "render", text="")
65             row.prop(md, "realtime", text="")
66         else:
67             # add modifier
68             split.operator("object.modifier_add", text="Add").type = 'SOFT_BODY'
69             if wide_ui:
70                 split.column()
71
72         if md:
73             softbody = md.settings
74
75             # General
76             split = layout.split()
77             split.enabled = softbody_panel_enabled(md)
78
79             col = split.column()
80             col.label(text="Object:")
81             col.prop(softbody, "friction")
82             col.prop(softbody, "mass")
83             col.prop_object(softbody, "mass_vertex_group", ob, "vertex_groups", text="Mass:")
84
85             if wide_ui:
86                 col = split.column()
87             col.label(text="Simulation:")
88             col.prop(softbody, "speed")
89
90
91 class PHYSICS_PT_softbody_cache(PhysicButtonsPanel):
92     bl_label = "Soft Body Cache"
93     bl_default_closed = True
94
95     def poll(self, context):
96         return context.soft_body
97
98     def draw(self, context):
99         md = context.soft_body
100         point_cache_ui(self, context, md.point_cache, softbody_panel_enabled(md), 'SOFTBODY')
101
102
103 class PHYSICS_PT_softbody_goal(PhysicButtonsPanel):
104     bl_label = "Soft Body Goal"
105     bl_default_closed = True
106
107     def poll(self, context):
108         return context.soft_body
109
110     def draw_header(self, context):
111         softbody = context.soft_body.settings
112
113         self.layout.active = softbody_panel_enabled(context.soft_body)
114         self.layout.prop(softbody, "use_goal", text="")
115
116     def draw(self, context):
117         layout = self.layout
118
119         md = context.soft_body
120         softbody = md.settings
121         ob = context.object
122         wide_ui = context.region.width > narrowui
123
124         layout.active = softbody.use_goal and softbody_panel_enabled(md)
125
126         split = layout.split()
127
128         # Goal
129         split = layout.split()
130
131         col = split.column()
132         col.label(text="Goal Strengths:")
133         col.prop(softbody, "goal_default", text="Default")
134         sub = col.column(align=True)
135         sub.prop(softbody, "goal_min", text="Minimum")
136         sub.prop(softbody, "goal_max", text="Maximum")
137
138         if wide_ui:
139             col = split.column()
140         col.label(text="Goal Settings:")
141         col.prop(softbody, "goal_spring", text="Stiffness")
142         col.prop(softbody, "goal_friction", text="Damping")
143
144         layout.prop_object(softbody, "goal_vertex_group", ob, "vertex_groups", text="Vertex Group")
145
146
147 class PHYSICS_PT_softbody_edge(PhysicButtonsPanel):
148     bl_label = "Soft Body Edges"
149     bl_default_closed = True
150
151     def poll(self, context):
152         return context.soft_body
153
154     def draw_header(self, context):
155         softbody = context.soft_body.settings
156
157         self.layout.active = softbody_panel_enabled(context.soft_body)
158         self.layout.prop(softbody, "use_edges", text="")
159
160     def draw(self, context):
161         layout = self.layout
162
163         md = context.soft_body
164         softbody = md.settings
165         ob = context.object
166         wide_ui = context.region.width > narrowui
167
168         layout.active = softbody.use_edges and softbody_panel_enabled(md)
169
170         split = layout.split()
171
172         col = split.column()
173         col.label(text="Springs:")
174         col.prop(softbody, "pull")
175         col.prop(softbody, "push")
176         col.prop(softbody, "damp")
177         col.prop(softbody, "plastic")
178         col.prop(softbody, "bending")
179         col.prop(softbody, "spring_length", text="Length")
180         col.prop_object(softbody, "spring_vertex_group", ob, "vertex_groups", text="Springs:")
181
182         if wide_ui:
183             col = split.column()
184         col.prop(softbody, "stiff_quads")
185         sub = col.column()
186         sub.active = softbody.stiff_quads
187         sub.prop(softbody, "shear")
188
189         col.label(text="Aerodynamics:")
190         col.row().prop(softbody, "aerodynamics_type", expand=True)
191         col.prop(softbody, "aero", text="Factor")
192         
193         #sub = col.column()
194         #sub.enabled = softbody.aero > 0
195         
196
197         col.label(text="Collision:")
198         col.prop(softbody, "edge_collision", text="Edge")
199         col.prop(softbody, "face_collision", text="Face")
200
201
202 class PHYSICS_PT_softbody_collision(PhysicButtonsPanel):
203     bl_label = "Soft Body Self Collision"
204     bl_default_closed = True
205
206     def poll(self, context):
207         return context.soft_body
208
209     def draw_header(self, context):
210         softbody = context.soft_body.settings
211
212         self.layout.active = softbody_panel_enabled(context.soft_body)
213         self.layout.prop(softbody, "self_collision", text="")
214
215     def draw(self, context):
216         layout = self.layout
217
218         md = context.soft_body
219         softbody = md.settings
220         wide_ui = context.region.width > narrowui
221
222         layout.active = softbody.self_collision and softbody_panel_enabled(md)
223
224         layout.label(text="Collision Ball Size Calculation:")
225         if wide_ui:
226             layout.prop(softbody, "collision_type", expand=True)
227         else:
228             layout.prop(softbody, "collision_type", text="")
229
230         col = layout.column(align=True)
231         col.label(text="Ball:")
232         col.prop(softbody, "ball_size", text="Size")
233         col.prop(softbody, "ball_stiff", text="Stiffness")
234         col.prop(softbody, "ball_damp", text="Dampening")
235
236
237 class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
238     bl_label = "Soft Body Solver"
239     bl_default_closed = True
240
241     def poll(self, context):
242         return context.soft_body
243
244     def draw(self, context):
245         layout = self.layout
246
247         md = context.soft_body
248         softbody = md.settings
249         wide_ui = context.region.width > narrowui
250
251         layout.active = softbody_panel_enabled(md)
252
253         # Solver
254         split = layout.split()
255
256         col = split.column(align=True)
257         col.label(text="Step Size:")
258         col.prop(softbody, "minstep")
259         col.prop(softbody, "maxstep")
260         col.prop(softbody, "auto_step", text="Auto-Step")
261
262         if wide_ui:
263             col = split.column()
264         col.prop(softbody, "error_limit")
265         col.label(text="Helpers:")
266         col.prop(softbody, "choke")
267         col.prop(softbody, "fuzzy")
268
269         layout.label(text="Diagnostics:")
270         layout.prop(softbody, "diagnose")
271         layout.prop(softbody, "estimate_matrix")
272
273
274 class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel):
275     bl_label = "Soft Body Field Weights"
276     bl_default_closed = True
277
278     def poll(self, context):
279         return (context.soft_body)
280
281     def draw(self, context):
282         md = context.soft_body
283         softbody = md.settings
284
285         effector_weights_ui(self, context, softbody.effector_weights)
286
287
288 classes = [
289     PHYSICS_PT_softbody,
290     PHYSICS_PT_softbody_cache,
291     PHYSICS_PT_softbody_goal,
292     PHYSICS_PT_softbody_edge,
293     PHYSICS_PT_softbody_collision,
294     PHYSICS_PT_softbody_solver,
295     PHYSICS_PT_softbody_field_weights]
296
297
298 def register():
299     register = bpy.types.register
300     for cls in classes:
301         register(cls)
302
303
304 def unregister():
305     unregister = bpy.types.unregister
306     for cls in classes:
307         unregister(cls)
308
309 if __name__ == "__main__":
310     register()