properties_physics_dynamicpaint.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  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. UIList,
  22. )
  23. from bl_ui.properties_physics_common import (
  24. point_cache_ui,
  25. effector_weights_ui,
  26. )
  27. class PHYSICS_UL_dynapaint_surfaces(UIList):
  28. def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
  29. # assert(isinstance(item, bpy.types.DynamicPaintSurface)
  30. surf = item
  31. sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
  32. if self.layout_type in {'DEFAULT', 'COMPACT'}:
  33. row = layout.row(align=True)
  34. row.label(text="", icon_value=icon)
  35. row.prop(surf, "name", text="", emboss=False, icon_value=sticon)
  36. row = layout.row(align=True)
  37. row.prop(surf, "is_active", text="")
  38. elif self.layout_type == 'GRID':
  39. layout.alignment = 'CENTER'
  40. row = layout.row(align=True)
  41. row.label(text="", icon_value=icon)
  42. row.label(text="", icon_value=sticon)
  43. class PhysicButtonsPanel:
  44. bl_space_type = 'PROPERTIES'
  45. bl_region_type = 'WINDOW'
  46. bl_context = "physics"
  47. @staticmethod
  48. def poll_dyn_paint(context):
  49. ob = context.object
  50. return (ob and ob.type == 'MESH') and context.dynamic_paint
  51. @staticmethod
  52. def poll_dyn_canvas(context):
  53. if not PhysicButtonsPanel.poll_dyn_paint(context):
  54. return False
  55. md = context.dynamic_paint
  56. return (md and md.ui_type == 'CANVAS' and md.canvas_settings and md.canvas_settings.canvas_surfaces.active)
  57. @staticmethod
  58. def poll_dyn_canvas_paint(context):
  59. if not PhysicButtonsPanel.poll_dyn_canvas(context):
  60. return False
  61. surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
  62. return (surface.surface_type == 'PAINT')
  63. @staticmethod
  64. def poll_dyn_canvas_brush(context):
  65. if not PhysicButtonsPanel.poll_dyn_paint(context):
  66. return False
  67. md = context.dynamic_paint
  68. return (md and md.ui_type == 'BRUSH' and md.brush_settings)
  69. @staticmethod
  70. def poll_dyn_output(context):
  71. if not PhysicButtonsPanel.poll_dyn_canvas(context):
  72. return False
  73. surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
  74. return (not (surface.surface_format == 'VERTEX' and (surface.surface_type in {'DISPLACE', 'WAVE'})))
  75. @staticmethod
  76. def poll_dyn_output_maps(context):
  77. if not PhysicButtonsPanel.poll_dyn_output(context):
  78. return False
  79. surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
  80. return (surface.surface_format == 'IMAGE' and surface.surface_type == 'PAINT')
  81. class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
  82. bl_label = "Dynamic Paint"
  83. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  84. @classmethod
  85. def poll(cls, context):
  86. if not PhysicButtonsPanel.poll_dyn_paint(context):
  87. return False
  88. return (context.engine in cls.COMPAT_ENGINES)
  89. def draw(self, context):
  90. layout = self.layout
  91. layout.use_property_split = True
  92. md = context.dynamic_paint
  93. layout.prop(md, "ui_type")
  94. class PHYSICS_PT_dynamic_paint_settings(PhysicButtonsPanel, Panel):
  95. bl_label = "Settings"
  96. bl_parent_id = 'PHYSICS_PT_dynamic_paint'
  97. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  98. @classmethod
  99. def poll(cls, context):
  100. if not PhysicButtonsPanel.poll_dyn_paint(context):
  101. return False
  102. return (context.engine in cls.COMPAT_ENGINES)
  103. def draw(self, context):
  104. layout = self.layout
  105. md = context.dynamic_paint
  106. if md.ui_type == 'CANVAS':
  107. canvas = md.canvas_settings
  108. if canvas is None:
  109. layout.operator("dpaint.type_toggle", text="Add Canvas").type = 'CANVAS'
  110. return # do nothing.
  111. layout.operator("dpaint.type_toggle", text="Remove Canvas", icon='X').type = 'CANVAS'
  112. surface = canvas.canvas_surfaces.active
  113. row = layout.row()
  114. row.template_list(
  115. "PHYSICS_UL_dynapaint_surfaces", "", canvas, "canvas_surfaces",
  116. canvas.canvas_surfaces, "active_index", rows=1,
  117. )
  118. col = row.column(align=True)
  119. col.operator("dpaint.surface_slot_add", icon='ADD', text="")
  120. col.operator("dpaint.surface_slot_remove", icon='REMOVE', text="")
  121. layout.separator()
  122. layout.use_property_split = True
  123. if surface:
  124. flow = layout.grid_flow(
  125. row_major=True, columns=0, even_columns=True, even_rows=False, align=False,
  126. )
  127. col = flow.column()
  128. col.prop(surface, "surface_format")
  129. if surface.surface_format != 'VERTEX':
  130. col.prop(surface, "image_resolution")
  131. col.prop(surface, "use_antialiasing")
  132. col = flow.column(align=True)
  133. col.prop(surface, "frame_start", text="Frame Start")
  134. col.prop(surface, "frame_end", text="End")
  135. col.prop(surface, "frame_substeps")
  136. elif md.ui_type == 'BRUSH':
  137. brush = md.brush_settings
  138. if brush is None:
  139. layout.operator("dpaint.type_toggle", text="Add Brush").type = 'BRUSH'
  140. return # do nothing.
  141. layout.operator("dpaint.type_toggle", text="Remove Brush", icon='X').type = 'BRUSH'
  142. layout.use_property_split = True
  143. flow = layout.grid_flow(
  144. row_major=True, columns=0, even_columns=True, even_rows=False, align=False,
  145. )
  146. col = flow.column()
  147. col.prop(brush, "paint_color")
  148. col.prop(brush, "paint_alpha", text="Alpha", slider=True)
  149. col = flow.column()
  150. col.prop(brush, "paint_wetness", text="Wetness", slider=True)
  151. col.prop(brush, "use_absolute_alpha")
  152. col.prop(brush, "use_paint_erase")
  153. class PHYSICS_PT_dp_surface_canvas(PhysicButtonsPanel, Panel):
  154. bl_label = "Surface"
  155. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  156. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  157. @classmethod
  158. def poll(cls, context):
  159. if not PhysicButtonsPanel.poll_dyn_canvas(context):
  160. return False
  161. return (context.engine in cls.COMPAT_ENGINES)
  162. def draw(self, context):
  163. layout = self.layout
  164. layout.use_property_split = True
  165. canvas = context.dynamic_paint.canvas_settings
  166. surface = canvas.canvas_surfaces.active
  167. surface_type = surface.surface_type
  168. layout.prop(surface, "surface_type")
  169. layout.separator()
  170. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
  171. # per type settings
  172. if surface_type == 'DISPLACE':
  173. col = flow.column()
  174. if surface.surface_format == 'VERTEX':
  175. col.prop(surface, "depth_clamp")
  176. col.prop(surface, "displace_factor")
  177. col.prop(surface, "use_incremental_displace")
  178. col.separator()
  179. elif surface_type == 'WAVE':
  180. col = flow.column()
  181. col.prop(surface, "use_wave_open_border")
  182. col.prop(surface, "wave_timescale")
  183. col.prop(surface, "wave_speed")
  184. col.separator()
  185. col = flow.column()
  186. col.prop(surface, "wave_damping")
  187. col.prop(surface, "wave_spring")
  188. col.prop(surface, "wave_smoothness")
  189. col.separator()
  190. col = flow.column()
  191. col.prop(surface, "brush_collection")
  192. if surface_type not in {'DISPLACE', 'WAVE'}:
  193. col = flow.column() # flow the layout otherwise.
  194. col.prop(surface, "brush_influence_scale", text="Scale Influence")
  195. col.prop(surface, "brush_radius_scale", text="Radius")
  196. class PHYSICS_PT_dp_surface_canvas_paint_dry(PhysicButtonsPanel, Panel):
  197. bl_label = "Dry"
  198. bl_parent_id = "PHYSICS_PT_dp_surface_canvas"
  199. bl_options = {'DEFAULT_CLOSED'}
  200. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  201. @classmethod
  202. def poll(cls, context):
  203. if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
  204. return False
  205. return (context.engine in cls.COMPAT_ENGINES)
  206. def draw_header(self, context):
  207. canvas = context.dynamic_paint.canvas_settings
  208. surface = canvas.canvas_surfaces.active
  209. self.layout.prop(surface, "use_drying", text="")
  210. def draw(self, context):
  211. layout = self.layout
  212. layout.use_property_split = True
  213. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  214. canvas = context.dynamic_paint.canvas_settings
  215. surface = canvas.canvas_surfaces.active
  216. flow.active = surface.use_drying
  217. col = flow.column()
  218. col.prop(surface, "dry_speed", text="Time")
  219. col = flow.column()
  220. col.prop(surface, "color_dry_threshold", text="Color")
  221. col.prop(surface, "use_dry_log", text="Slow")
  222. class PHYSICS_PT_dp_surface_canvas_paint_dissolve(PhysicButtonsPanel, Panel):
  223. bl_label = "Dissolve"
  224. bl_parent_id = "PHYSICS_PT_dp_surface_canvas"
  225. bl_options = {'DEFAULT_CLOSED'}
  226. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  227. @classmethod
  228. def poll(cls, context):
  229. if not PhysicButtonsPanel.poll_dyn_canvas(context):
  230. return False
  231. surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
  232. return (surface.surface_type != 'WAVE' and context.engine in cls.COMPAT_ENGINES)
  233. def draw_header(self, context):
  234. canvas = context.dynamic_paint.canvas_settings
  235. surface = canvas.canvas_surfaces.active
  236. self.layout.prop(surface, "use_dissolve", text="")
  237. def draw(self, context):
  238. layout = self.layout
  239. layout.use_property_split = True
  240. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  241. canvas = context.dynamic_paint.canvas_settings
  242. surface = canvas.canvas_surfaces.active
  243. flow.active = surface.use_dissolve
  244. col = flow.column()
  245. col.prop(surface, "dissolve_speed", text="Time")
  246. col = flow.column()
  247. col.prop(surface, "use_dissolve_log", text="Slow")
  248. class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
  249. bl_label = "Output"
  250. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  251. bl_options = {'DEFAULT_CLOSED'}
  252. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  253. @classmethod
  254. def poll(cls, context):
  255. if not PhysicButtonsPanel.poll_dyn_output(context):
  256. return False
  257. return (context.engine in cls.COMPAT_ENGINES)
  258. def draw(self, context):
  259. layout = self.layout
  260. layout.use_property_split = True
  261. canvas = context.dynamic_paint.canvas_settings
  262. surface = canvas.canvas_surfaces.active
  263. ob = context.object
  264. surface_type = surface.surface_type
  265. # vertex format outputs.
  266. if surface.surface_format == 'VERTEX':
  267. if surface_type == 'PAINT':
  268. # paint-map output.
  269. row = layout.row()
  270. row.prop_search(surface, "output_name_a", ob.data, "vertex_colors", text="Paintmap Layer")
  271. icons = 'REMOVE' if surface.output_exists(object=ob, index=0) else 'ADD'
  272. row.operator("dpaint.output_toggle", icon=icons, text="").output = 'A'
  273. # wet-map output.
  274. row = layout.row()
  275. row.prop_search(surface, "output_name_b", ob.data, "vertex_colors", text="Wetmap Layer")
  276. icons = 'REMOVE' if surface.output_exists(object=ob, index=1) else 'ADD'
  277. row.operator("dpaint.output_toggle", icon=icons, text="").output = 'B'
  278. elif surface_type == 'WEIGHT':
  279. row = layout.row()
  280. row.prop_search(surface, "output_name_a", ob, "vertex_groups", text="Vertex Group")
  281. icons = 'REMOVE' if surface.output_exists(object=ob, index=0) else 'ADD'
  282. row.operator("dpaint.output_toggle", icon=icons, text="").output = 'A'
  283. # image format outputs.
  284. if surface.surface_format == 'IMAGE':
  285. layout.operator("dpaint.bake", text="Bake Image Sequence", icon='MOD_DYNAMICPAINT')
  286. layout.prop(surface, "image_output_path", text="Cache Path")
  287. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  288. col = flow.column()
  289. col.prop_search(surface, "uv_layer", ob.data, "uv_layers", text="UV Map")
  290. col = flow.column()
  291. col.prop(surface, "image_fileformat")
  292. col.prop(surface, "use_premultiply", text="Premultiply Alpha")
  293. if surface_type != 'PAINT':
  294. col = col.column()
  295. col.prop(surface, "output_name_a", text="Filename")
  296. if surface_type == 'DISPLACE':
  297. col.prop(surface, "displace_type", text="Displace Type")
  298. col.prop(surface, "depth_clamp")
  299. elif surface_type == 'WAVE':
  300. col.prop(surface, "depth_clamp", text="Wave Clamp")
  301. class PHYSICS_PT_dp_canvas_output_paintmaps(PhysicButtonsPanel, Panel):
  302. bl_label = "Paintmaps"
  303. bl_parent_id = "PHYSICS_PT_dp_canvas_output"
  304. bl_options = {'DEFAULT_CLOSED'}
  305. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  306. @classmethod
  307. def poll(cls, context):
  308. if not PhysicButtonsPanel.poll_dyn_output_maps(context):
  309. return False
  310. return (context.engine in cls.COMPAT_ENGINES)
  311. def draw_header(self, context):
  312. canvas = context.dynamic_paint.canvas_settings
  313. surface = canvas.canvas_surfaces.active
  314. self.layout.prop(surface, "use_output_a", text="")
  315. def draw(self, context):
  316. layout = self.layout
  317. layout.use_property_split = True
  318. canvas = context.dynamic_paint.canvas_settings
  319. surface = canvas.canvas_surfaces.active
  320. sub = layout.column()
  321. sub.active = surface.use_output_a
  322. sub.prop(surface, "output_name_a", text="Name")
  323. class PHYSICS_PT_dp_canvas_output_wetmaps(PhysicButtonsPanel, Panel):
  324. bl_label = "Wetmaps"
  325. bl_parent_id = "PHYSICS_PT_dp_canvas_output"
  326. bl_options = {'DEFAULT_CLOSED'}
  327. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  328. @classmethod
  329. def poll(cls, context):
  330. if not PhysicButtonsPanel.poll_dyn_output_maps(context):
  331. return False
  332. return (context.engine in cls.COMPAT_ENGINES)
  333. def draw_header(self, context):
  334. canvas = context.dynamic_paint.canvas_settings
  335. surface = canvas.canvas_surfaces.active
  336. self.layout.prop(surface, "use_output_b", text="")
  337. def draw(self, context):
  338. layout = self.layout
  339. layout.use_property_split = True
  340. canvas = context.dynamic_paint.canvas_settings
  341. surface = canvas.canvas_surfaces.active
  342. sub = layout.column()
  343. sub.active = surface.use_output_b
  344. sub.prop(surface, "output_name_b", text="Name")
  345. class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
  346. bl_label = "Initial Color"
  347. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  348. bl_options = {'DEFAULT_CLOSED'}
  349. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  350. @classmethod
  351. def poll(cls, context):
  352. if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
  353. return False
  354. return (context.engine in cls.COMPAT_ENGINES)
  355. def draw(self, context):
  356. layout = self.layout
  357. canvas = context.dynamic_paint.canvas_settings
  358. surface = canvas.canvas_surfaces.active
  359. ob = context.object
  360. layout.use_property_split = True
  361. col = layout.column()
  362. col.prop(surface, "init_color_type", text="Type", expand=False)
  363. if surface.init_color_type != 'NONE':
  364. col.separator()
  365. # dissolve
  366. if surface.init_color_type == 'COLOR':
  367. layout.prop(surface, "init_color")
  368. elif surface.init_color_type == 'TEXTURE':
  369. col.prop(surface, "init_texture")
  370. col.prop_search(surface, "init_layername", ob.data, "uv_layers", text="UV Map")
  371. elif surface.init_color_type == 'VERTEX_COLOR':
  372. col.prop_search(surface, "init_layername", ob.data, "vertex_colors", text="Color Layer")
  373. class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
  374. bl_label = "Effects"
  375. bl_parent_id = 'PHYSICS_PT_dynamic_paint'
  376. bl_options = {'DEFAULT_CLOSED'}
  377. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  378. @classmethod
  379. def poll(cls, context):
  380. if not PhysicButtonsPanel.poll_dyn_canvas_paint(context):
  381. return False
  382. return (context.engine in cls.COMPAT_ENGINES)
  383. def draw(self, _context):
  384. return # do nothing.
  385. class PHYSICS_PT_dp_effects_spread(PhysicButtonsPanel, Panel):
  386. bl_label = "Spread"
  387. bl_parent_id = "PHYSICS_PT_dp_effects"
  388. bl_options = {'DEFAULT_CLOSED'}
  389. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  390. @classmethod
  391. def poll(cls, context):
  392. if not PhysicButtonsPanel.poll_dyn_paint(context):
  393. return False
  394. return (context.engine in cls.COMPAT_ENGINES)
  395. def draw_header(self, context):
  396. canvas = context.dynamic_paint.canvas_settings
  397. surface = canvas.canvas_surfaces.active
  398. self.layout.prop(surface, "use_spread", text="")
  399. def draw(self, context):
  400. layout = self.layout
  401. layout.use_property_split = True
  402. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  403. canvas = context.dynamic_paint.canvas_settings
  404. surface = canvas.canvas_surfaces.active
  405. layout.active = surface.use_spread
  406. col = flow.column()
  407. col.prop(surface, "spread_speed", text="Speed")
  408. col = flow.column()
  409. col.prop(surface, "color_spread_speed", text="Color")
  410. class PHYSICS_PT_dp_effects_drip(PhysicButtonsPanel, Panel):
  411. bl_label = "Drip"
  412. bl_parent_id = "PHYSICS_PT_dp_effects"
  413. bl_options = {'DEFAULT_CLOSED'}
  414. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  415. @classmethod
  416. def poll(cls, context):
  417. if not PhysicButtonsPanel.poll_dyn_paint(context):
  418. return False
  419. return (context.engine in cls.COMPAT_ENGINES)
  420. def draw_header(self, context):
  421. canvas = context.dynamic_paint.canvas_settings
  422. surface = canvas.canvas_surfaces.active
  423. self.layout.prop(surface, "use_drip", text="")
  424. def draw(self, context):
  425. layout = self.layout
  426. layout.use_property_split = True
  427. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  428. canvas = context.dynamic_paint.canvas_settings
  429. surface = canvas.canvas_surfaces.active
  430. flow.active = surface.use_drip
  431. col = flow.column()
  432. col.prop(surface, "drip_velocity", slider=True)
  433. col = flow.column()
  434. col.prop(surface, "drip_acceleration", slider=True)
  435. class PHYSICS_PT_dp_effects_drip_weights(PhysicButtonsPanel, Panel):
  436. bl_label = "Weights"
  437. bl_parent_id = "PHYSICS_PT_dp_effects_drip"
  438. bl_options = {'DEFAULT_CLOSED'}
  439. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  440. @classmethod
  441. def poll(cls, context):
  442. if not PhysicButtonsPanel.poll_dyn_paint(context):
  443. return False
  444. return (context.engine in cls.COMPAT_ENGINES)
  445. def draw(self, context):
  446. layout = self.layout
  447. canvas = context.dynamic_paint.canvas_settings
  448. surface = canvas.canvas_surfaces.active
  449. layout.active = surface.use_drip
  450. effector_weights_ui(self, surface.effector_weights, 'DYNAMIC_PAINT')
  451. class PHYSICS_PT_dp_effects_shrink(PhysicButtonsPanel, Panel):
  452. bl_label = "Shrink"
  453. bl_parent_id = "PHYSICS_PT_dp_effects"
  454. bl_options = {'DEFAULT_CLOSED'}
  455. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  456. @classmethod
  457. def poll(cls, context):
  458. if not PhysicButtonsPanel.poll_dyn_paint(context):
  459. return False
  460. return (context.engine in cls.COMPAT_ENGINES)
  461. def draw_header(self, context):
  462. canvas = context.dynamic_paint.canvas_settings
  463. surface = canvas.canvas_surfaces.active
  464. self.layout.prop(surface, "use_shrink", text="")
  465. def draw(self, context):
  466. layout = self.layout
  467. layout.use_property_split = True
  468. canvas = context.dynamic_paint.canvas_settings
  469. surface = canvas.canvas_surfaces.active
  470. layout.active = surface.use_shrink
  471. layout.prop(surface, "shrink_speed", text="Speed")
  472. class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
  473. bl_label = "Cache"
  474. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  475. bl_options = {'DEFAULT_CLOSED'}
  476. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  477. @classmethod
  478. def poll(cls, context):
  479. if not PhysicButtonsPanel.poll_dyn_canvas(context):
  480. return False
  481. surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
  482. return (surface.is_cache_user and (context.engine in cls.COMPAT_ENGINES))
  483. def draw(self, context):
  484. surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
  485. cache = surface.point_cache
  486. point_cache_ui(self, cache, (cache.is_baked is False), 'DYNAMIC_PAINT')
  487. class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
  488. bl_label = "Source"
  489. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  490. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  491. @classmethod
  492. def poll(cls, context):
  493. if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
  494. return False
  495. return (context.engine in cls.COMPAT_ENGINES)
  496. def draw(self, context):
  497. layout = self.layout
  498. layout.use_property_split = True
  499. brush = context.dynamic_paint.brush_settings
  500. ob = context.object
  501. layout.prop(brush, "paint_source", text="Paint")
  502. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  503. if brush.paint_source == 'PARTICLE_SYSTEM':
  504. col = flow.column()
  505. col.separator()
  506. col.prop_search(brush, "particle_system", ob, "particle_systems")
  507. if brush.particle_system:
  508. col = flow.column()
  509. sub = col.column()
  510. sub.active = not brush.use_particle_radius
  511. sub.prop(brush, "solid_radius", text="Effect Solid Radius")
  512. col.prop(brush, "use_particle_radius", text="Use Particle's Radius")
  513. col.prop(brush, "smooth_radius", text="Smooth Radius")
  514. if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}:
  515. col = flow.column()
  516. col.separator()
  517. col.prop(brush, "paint_distance", text="Distance")
  518. col.prop(brush, "proximity_falloff")
  519. if brush.paint_source == 'VOLUME_DISTANCE':
  520. col.prop(brush, "invert_proximity")
  521. col = flow.column()
  522. col.prop(brush, "use_negative_volume")
  523. if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE'}:
  524. col = flow.column() if brush.paint_source != 'VOLUME_DISTANCE' else col.column()
  525. col.prop(brush, "use_proximity_project")
  526. sub = col.column()
  527. sub.active = brush.use_proximity_project
  528. sub.prop(brush, "ray_direction")
  529. class PHYSICS_PT_dp_brush_source_color_ramp(PhysicButtonsPanel, Panel):
  530. bl_label = "Falloff Ramp"
  531. bl_parent_id = "PHYSICS_PT_dp_brush_source"
  532. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  533. @classmethod
  534. def poll(cls, context):
  535. if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
  536. return False
  537. brush = context.dynamic_paint.brush_settings
  538. return ((brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'})
  539. and (brush.proximity_falloff == 'RAMP')
  540. and (context.engine in cls.COMPAT_ENGINES))
  541. def draw(self, context):
  542. layout = self.layout
  543. layout.use_property_split = True
  544. brush = context.dynamic_paint.brush_settings
  545. layout.prop(brush, "use_proximity_ramp_alpha", text="Only Use Alpha")
  546. layout.use_property_split = False
  547. layout.template_color_ramp(brush, "paint_ramp", expand=True)
  548. class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
  549. bl_label = "Velocity"
  550. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  551. bl_options = {'DEFAULT_CLOSED'}
  552. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  553. @classmethod
  554. def poll(cls, context):
  555. if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
  556. return False
  557. return (context.engine in cls.COMPAT_ENGINES)
  558. def draw(self, context):
  559. layout = self.layout
  560. layout.use_property_split = True
  561. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  562. brush = context.dynamic_paint.brush_settings
  563. col = flow.column()
  564. col.prop(brush, "use_velocity_alpha")
  565. col.prop(brush, "use_velocity_color")
  566. col = flow.column()
  567. col.prop(brush, "use_velocity_depth")
  568. sub = col.column()
  569. sub.active = (brush.use_velocity_alpha or brush.use_velocity_color or brush.use_velocity_depth)
  570. sub.prop(brush, "velocity_max")
  571. class PHYSICS_PT_dp_brush_velocity_color_ramp(PhysicButtonsPanel, Panel):
  572. bl_label = "Ramp"
  573. bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
  574. bl_options = {'DEFAULT_CLOSED'}
  575. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  576. @classmethod
  577. def poll(cls, context):
  578. if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
  579. return False
  580. return (context.engine in cls.COMPAT_ENGINES)
  581. def draw(self, context):
  582. layout = self.layout
  583. brush = context.dynamic_paint.brush_settings
  584. layout.template_color_ramp(brush, "velocity_ramp", expand=True)
  585. class PHYSICS_PT_dp_brush_velocity_smudge(PhysicButtonsPanel, Panel):
  586. bl_label = "Smudge"
  587. bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
  588. bl_options = {'DEFAULT_CLOSED'}
  589. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  590. @classmethod
  591. def poll(cls, context):
  592. if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
  593. return False
  594. return (context.engine in cls.COMPAT_ENGINES)
  595. def draw_header(self, context):
  596. brush = context.dynamic_paint.brush_settings
  597. self.layout.prop(brush, "use_smudge", text="")
  598. def draw(self, context):
  599. layout = self.layout
  600. layout.use_property_split = True
  601. brush = context.dynamic_paint.brush_settings
  602. layout.active = brush.use_smudge
  603. layout.prop(brush, "smudge_strength", text="Strength", slider=True)
  604. class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
  605. bl_label = "Waves"
  606. bl_parent_id = "PHYSICS_PT_dynamic_paint"
  607. bl_options = {'DEFAULT_CLOSED'}
  608. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  609. @classmethod
  610. def poll(cls, context):
  611. if not PhysicButtonsPanel.poll_dyn_canvas_brush(context):
  612. return False
  613. return (context.engine in cls.COMPAT_ENGINES)
  614. def draw(self, context):
  615. layout = self.layout
  616. layout.use_property_split = True
  617. brush = context.dynamic_paint.brush_settings
  618. layout.prop(brush, "wave_type", text="Type")
  619. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
  620. if brush.wave_type != 'REFLECT':
  621. col = flow.column()
  622. col.prop(brush, "wave_factor")
  623. col = flow.column()
  624. col.prop(brush, "wave_clamp")
  625. classes = (
  626. PHYSICS_UL_dynapaint_surfaces,
  627. PHYSICS_PT_dynamic_paint,
  628. PHYSICS_PT_dynamic_paint_settings,
  629. PHYSICS_PT_dp_surface_canvas,
  630. PHYSICS_PT_dp_surface_canvas_paint_dissolve,
  631. PHYSICS_PT_dp_surface_canvas_paint_dry,
  632. PHYSICS_PT_dp_cache,
  633. PHYSICS_PT_dp_effects,
  634. PHYSICS_PT_dp_effects_spread,
  635. PHYSICS_PT_dp_effects_drip,
  636. PHYSICS_PT_dp_effects_drip_weights,
  637. PHYSICS_PT_dp_effects_shrink,
  638. PHYSICS_PT_dp_canvas_initial_color,
  639. PHYSICS_PT_dp_brush_source,
  640. PHYSICS_PT_dp_brush_source_color_ramp,
  641. PHYSICS_PT_dp_brush_velocity,
  642. PHYSICS_PT_dp_brush_velocity_color_ramp,
  643. PHYSICS_PT_dp_brush_velocity_smudge,
  644. PHYSICS_PT_dp_brush_wave,
  645. PHYSICS_PT_dp_canvas_output,
  646. PHYSICS_PT_dp_canvas_output_paintmaps,
  647. PHYSICS_PT_dp_canvas_output_wetmaps,
  648. )
  649. if __name__ == "__main__": # only for live edit.
  650. from bpy.utils import register_class
  651. for cls in classes:
  652. register_class(cls)