Recreating my GSoC branch.
[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.prop(softbody, "new_aero", text="Aero")
190         sub = col.column()
191         sub.enabled = softbody.new_aero
192         sub.prop(softbody, "aero", text="Factor")
193
194         col.label(text="Collision:")
195         col.prop(softbody, "edge_collision", text="Edge")
196         col.prop(softbody, "face_collision", text="Face")
197
198
199 class PHYSICS_PT_softbody_collision(PhysicButtonsPanel):
200     bl_label = "Soft Body Self Collision"
201     bl_default_closed = True
202
203     def poll(self, context):
204         return context.soft_body
205
206     def draw_header(self, context):
207         softbody = context.soft_body.settings
208
209         self.layout.active = softbody_panel_enabled(context.soft_body)
210         self.layout.prop(softbody, "self_collision", text="")
211
212     def draw(self, context):
213         layout = self.layout
214
215         md = context.soft_body
216         softbody = md.settings
217         wide_ui = context.region.width > narrowui
218
219         layout.active = softbody.self_collision and softbody_panel_enabled(md)
220
221         layout.label(text="Collision Ball Size Calculation:")
222         if wide_ui:
223             layout.prop(softbody, "collision_type", expand=True)
224         else:
225             layout.prop(softbody, "collision_type", text="")
226
227         col = layout.column(align=True)
228         col.label(text="Ball:")
229         col.prop(softbody, "ball_size", text="Size")
230         col.prop(softbody, "ball_stiff", text="Stiffness")
231         col.prop(softbody, "ball_damp", text="Dampening")
232
233
234 class PHYSICS_PT_softbody_solver(PhysicButtonsPanel):
235     bl_label = "Soft Body Solver"
236     bl_default_closed = True
237
238     def poll(self, context):
239         return context.soft_body
240
241     def draw(self, context):
242         layout = self.layout
243
244         md = context.soft_body
245         softbody = md.settings
246         wide_ui = context.region.width > narrowui
247
248         layout.active = softbody_panel_enabled(md)
249
250         # Solver
251         split = layout.split()
252
253         col = split.column(align=True)
254         col.label(text="Step Size:")
255         col.prop(softbody, "minstep")
256         col.prop(softbody, "maxstep")
257         col.prop(softbody, "auto_step", text="Auto-Step")
258
259         if wide_ui:
260             col = split.column()
261         col.prop(softbody, "error_limit")
262         col.label(text="Helpers:")
263         col.prop(softbody, "choke")
264         col.prop(softbody, "fuzzy")
265
266         layout.label(text="Diagnostics:")
267         layout.prop(softbody, "diagnose")
268         layout.prop(softbody, "estimate_matrix")
269
270
271 class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel):
272     bl_label = "Soft Body Field Weights"
273     bl_default_closed = True
274
275     def poll(self, context):
276         return (context.soft_body)
277
278     def draw(self, context):
279         md = context.soft_body
280         softbody = md.settings
281
282         effector_weights_ui(self, context, softbody.effector_weights)
283
284
285 classes = [
286     PHYSICS_PT_softbody,
287     PHYSICS_PT_softbody_cache,
288     PHYSICS_PT_softbody_goal,
289     PHYSICS_PT_softbody_edge,
290     PHYSICS_PT_softbody_collision,
291     PHYSICS_PT_softbody_solver,
292     PHYSICS_PT_softbody_field_weights]
293
294
295 def register():
296     register = bpy.types.register
297     for cls in classes:
298         register(cls)
299
300
301 def unregister():
302     unregister = bpy.types.unregister
303     for cls in classes:
304         unregister(cls)
305
306 if __name__ == "__main__":
307     register()