properties_physics_cloth.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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. # <pep8 compliant>
  19. from bpy.types import (
  20. Panel,
  21. )
  22. from bl_ui.utils import PresetPanel
  23. from bl_ui.properties_physics_common import (
  24. point_cache_ui,
  25. effector_weights_ui,
  26. )
  27. def cloth_panel_enabled(md):
  28. return md.point_cache.is_baked is False
  29. class CLOTH_PT_presets(PresetPanel, Panel):
  30. bl_label = "Cloth Presets"
  31. preset_subdir = "cloth"
  32. preset_operator = "script.execute_preset"
  33. preset_add_operator = "cloth.preset_add"
  34. class PhysicButtonsPanel:
  35. bl_space_type = 'PROPERTIES'
  36. bl_region_type = 'WINDOW'
  37. bl_context = "physics"
  38. @classmethod
  39. def poll(cls, context):
  40. ob = context.object
  41. return (ob and ob.type == 'MESH') and (context.engine in cls.COMPAT_ENGINES) and (context.cloth)
  42. class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
  43. bl_label = "Cloth"
  44. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  45. def draw_header_preset(self, _context):
  46. CLOTH_PT_presets.draw_panel_header(self.layout)
  47. def draw(self, context):
  48. layout = self.layout
  49. layout.use_property_split = True
  50. md = context.cloth
  51. cloth = md.settings
  52. layout.active = cloth_panel_enabled(md)
  53. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  54. col = flow.column()
  55. col.prop(cloth, "quality", text="Quality Steps")
  56. col = flow.column()
  57. col.prop(cloth, "time_scale", text="Speed Multiplier")
  58. class PHYSICS_PT_cloth_physical_properties(PhysicButtonsPanel, Panel):
  59. bl_label = "Physical Properties"
  60. bl_parent_id = 'PHYSICS_PT_cloth'
  61. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  62. def draw(self, context):
  63. layout = self.layout
  64. layout.use_property_split = True
  65. md = context.cloth
  66. cloth = md.settings
  67. layout.active = cloth_panel_enabled(md)
  68. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  69. col = flow.column()
  70. col.prop(cloth, "mass", text="Mass")
  71. col = flow.column()
  72. col.prop(cloth, "air_damping", text="Air Viscosity")
  73. col = flow.column()
  74. col.prop(cloth, "bending_model")
  75. class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
  76. bl_label = "Stiffness"
  77. bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
  78. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  79. def draw(self, context):
  80. layout = self.layout
  81. layout.use_property_split = True
  82. md = context.cloth
  83. cloth = md.settings
  84. layout.active = cloth_panel_enabled(md)
  85. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  86. col = flow.column()
  87. if cloth.bending_model == 'ANGULAR':
  88. col.prop(cloth, "tension_stiffness", text="Tension")
  89. col = flow.column()
  90. col.prop(cloth, "compression_stiffness", text="Compression")
  91. else:
  92. col.prop(cloth, "tension_stiffness", text="Structural")
  93. col = flow.column()
  94. col.prop(cloth, "shear_stiffness", text="Shear")
  95. col = flow.column()
  96. col.prop(cloth, "bending_stiffness", text="Bending")
  97. class PHYSICS_PT_cloth_damping(PhysicButtonsPanel, Panel):
  98. bl_label = "Damping"
  99. bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
  100. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  101. def draw(self, context):
  102. layout = self.layout
  103. layout.use_property_split = True
  104. md = context.cloth
  105. cloth = md.settings
  106. layout.active = cloth_panel_enabled(md)
  107. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  108. col = flow.column()
  109. if cloth.bending_model == 'ANGULAR':
  110. col.prop(cloth, "tension_damping", text="Tension")
  111. col = flow.column()
  112. col.prop(cloth, "compression_damping", text="Compression")
  113. else:
  114. col.prop(cloth, "tension_damping", text="Structural")
  115. col = flow.column()
  116. col.prop(cloth, "shear_damping", text="Shear")
  117. col = flow.column()
  118. col.prop(cloth, "bending_damping", text="Bending")
  119. class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
  120. bl_label = "Cache"
  121. bl_parent_id = 'PHYSICS_PT_cloth'
  122. bl_options = {'DEFAULT_CLOSED'}
  123. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  124. def draw(self, context):
  125. md = context.cloth
  126. point_cache_ui(self, md.point_cache, cloth_panel_enabled(md), 'CLOTH')
  127. class PHYSICS_PT_cloth_shape(PhysicButtonsPanel, Panel):
  128. bl_label = "Shape"
  129. bl_parent_id = 'PHYSICS_PT_cloth'
  130. bl_options = {'DEFAULT_CLOSED'}
  131. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  132. def draw(self, context):
  133. layout = self.layout
  134. layout.use_property_split = True
  135. md = context.cloth
  136. ob = context.object
  137. cloth = md.settings
  138. layout.active = cloth_panel_enabled(md)
  139. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  140. col = flow.column(align=True)
  141. col.prop_search(cloth, "vertex_group_mass", ob, "vertex_groups", text="Pin Group")
  142. sub = col.column(align=True)
  143. sub.active = cloth.vertex_group_mass != ""
  144. sub.prop(cloth, "pin_stiffness", text="Stiffness")
  145. col.separator()
  146. col = flow.column(align=True)
  147. col.prop(cloth, "use_sewing_springs", text="Sewing")
  148. sub = col.column(align=True)
  149. sub.active = cloth.use_sewing_springs
  150. sub.prop(cloth, "sewing_force_max", text="Max Sewing Force")
  151. col.separator()
  152. col = flow.column()
  153. col.prop(cloth, "shrink_min", text="Shrinking Factor")
  154. col = flow.column()
  155. col.prop(cloth, "use_dynamic_mesh", text="Dynamic Mesh")
  156. key = ob.data.shape_keys
  157. if key:
  158. col = flow.column()
  159. col.active = not cloth.use_dynamic_mesh
  160. col.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="Rest Shape Key")
  161. class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
  162. bl_label = "Collisions"
  163. bl_parent_id = 'PHYSICS_PT_cloth'
  164. bl_options = {'DEFAULT_CLOSED'}
  165. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  166. def draw(self, context):
  167. layout = self.layout
  168. layout.use_property_split = True
  169. cloth = context.cloth.collision_settings
  170. md = context.cloth
  171. layout.active = (cloth.use_collision or cloth.use_self_collision) and cloth_panel_enabled(md)
  172. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  173. col = flow.column()
  174. col.prop(cloth, "collision_quality", text="Quality")
  175. class PHYSICS_PT_cloth_object_collision(PhysicButtonsPanel, Panel):
  176. bl_label = "Object Collisions"
  177. bl_parent_id = 'PHYSICS_PT_cloth_collision'
  178. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  179. def draw_header(self, context):
  180. cloth = context.cloth.collision_settings
  181. self.layout.active = cloth_panel_enabled(context.cloth)
  182. self.layout.prop(cloth, "use_collision", text="")
  183. def draw(self, context):
  184. layout = self.layout
  185. layout.use_property_split = True
  186. cloth = context.cloth.collision_settings
  187. md = context.cloth
  188. layout.active = cloth.use_collision and cloth_panel_enabled(md)
  189. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  190. col = flow.column()
  191. col.prop(cloth, "distance_min", slider=True, text="Distance")
  192. col = flow.column()
  193. col.prop(cloth, "impulse_clamp")
  194. col = flow.column()
  195. col.prop(cloth, "collection")
  196. class PHYSICS_PT_cloth_self_collision(PhysicButtonsPanel, Panel):
  197. bl_label = "Self Collisions"
  198. bl_parent_id = 'PHYSICS_PT_cloth_collision'
  199. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  200. def draw_header(self, context):
  201. cloth = context.cloth.collision_settings
  202. self.layout.active = cloth_panel_enabled(context.cloth)
  203. self.layout.prop(cloth, "use_self_collision", text="")
  204. def draw(self, context):
  205. layout = self.layout
  206. layout.use_property_split = True
  207. cloth = context.cloth.collision_settings
  208. md = context.cloth
  209. ob = context.object
  210. layout.active = cloth.use_self_collision and cloth_panel_enabled(md)
  211. flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
  212. col = flow.column()
  213. col.prop(cloth, "self_friction", text="Friction")
  214. col = flow.column()
  215. col.prop(cloth, "self_distance_min", slider=True, text="Distance")
  216. col = flow.column()
  217. col.prop(cloth, "self_impulse_clamp")
  218. col = flow.column()
  219. col.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="Vertex Group")
  220. class PHYSICS_PT_cloth_property_weights(PhysicButtonsPanel, Panel):
  221. bl_label = "Property Weights"
  222. bl_parent_id = 'PHYSICS_PT_cloth'
  223. bl_options = {'DEFAULT_CLOSED'}
  224. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  225. def draw(self, context):
  226. layout = self.layout
  227. layout.use_property_split = True
  228. md = context.cloth
  229. ob = context.object
  230. cloth = context.cloth.settings
  231. layout.active = cloth_panel_enabled(md)
  232. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
  233. col = flow.column()
  234. col.prop_search(
  235. cloth, "vertex_group_structural_stiffness", ob, "vertex_groups",
  236. text="Structural Group",
  237. )
  238. col.prop(cloth, "tension_stiffness_max", text="Max Tension")
  239. col.prop(cloth, "compression_stiffness_max", text="Max Compression")
  240. col.separator()
  241. col = flow.column()
  242. col.prop_search(
  243. cloth, "vertex_group_shear_stiffness", ob, "vertex_groups",
  244. text="Shear Group",
  245. )
  246. col.prop(cloth, "shear_stiffness_max", text="Max Shearing")
  247. col.separator()
  248. col = flow.column()
  249. col.prop_search(
  250. cloth, "vertex_group_bending", ob, "vertex_groups",
  251. text="Bending Group"
  252. )
  253. col.prop(cloth, "bending_stiffness_max", text="Max Bending")
  254. col.separator()
  255. col = flow.column()
  256. col.prop_search(
  257. cloth, "vertex_group_shrink", ob, "vertex_groups",
  258. text="Shrinking Group"
  259. )
  260. col.prop(cloth, "shrink_max", text="Max Shrinking")
  261. class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
  262. bl_label = "Field Weights"
  263. bl_parent_id = 'PHYSICS_PT_cloth'
  264. bl_options = {'DEFAULT_CLOSED'}
  265. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  266. def draw(self, context):
  267. cloth = context.cloth.settings
  268. effector_weights_ui(self, cloth.effector_weights, 'CLOTH')
  269. classes = (
  270. CLOTH_PT_presets,
  271. PHYSICS_PT_cloth,
  272. PHYSICS_PT_cloth_physical_properties,
  273. PHYSICS_PT_cloth_stiffness,
  274. PHYSICS_PT_cloth_damping,
  275. PHYSICS_PT_cloth_cache,
  276. PHYSICS_PT_cloth_shape,
  277. PHYSICS_PT_cloth_collision,
  278. PHYSICS_PT_cloth_object_collision,
  279. PHYSICS_PT_cloth_self_collision,
  280. PHYSICS_PT_cloth_property_weights,
  281. PHYSICS_PT_cloth_field_weights,
  282. )
  283. if __name__ == "__main__": # only for live edit.
  284. from bpy.utils import register_class
  285. for cls in classes:
  286. register_class(cls)