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