properties_scene.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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. import bpy
  20. from bpy.types import (
  21. Panel,
  22. UIList,
  23. )
  24. from rna_prop_ui import PropertyPanel
  25. from bl_ui.properties_physics_common import (
  26. point_cache_ui,
  27. effector_weights_ui,
  28. )
  29. class SCENE_UL_keying_set_paths(UIList):
  30. def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
  31. # assert(isinstance(item, bpy.types.KeyingSetPath)
  32. kspath = item
  33. icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
  34. if self.layout_type in {'DEFAULT', 'COMPACT'}:
  35. # Do not make this one editable in uiList for now...
  36. layout.label(text=kspath.data_path, translate=False, icon_value=icon)
  37. elif self.layout_type == 'GRID':
  38. layout.alignment = 'CENTER'
  39. layout.label(text="", icon_value=icon)
  40. class SceneButtonsPanel:
  41. bl_space_type = 'PROPERTIES'
  42. bl_region_type = 'WINDOW'
  43. bl_context = "scene"
  44. class SCENE_PT_scene(SceneButtonsPanel, Panel):
  45. bl_label = "Scene"
  46. def draw(self, context):
  47. layout = self.layout
  48. layout.use_property_split = True
  49. layout.use_property_decorate = False
  50. scene = context.scene
  51. layout.prop(scene, "camera")
  52. layout.prop(scene, "background_set")
  53. layout.prop(scene, "active_clip")
  54. class SCENE_PT_unit(SceneButtonsPanel, Panel):
  55. bl_label = "Units"
  56. bl_options = {'DEFAULT_CLOSED'}
  57. def draw(self, context):
  58. layout = self.layout
  59. unit = context.scene.unit_settings
  60. layout.use_property_split = True
  61. layout.use_property_decorate = False
  62. layout.prop(unit, "system")
  63. col = layout.column()
  64. col.enabled = unit.system != 'NONE'
  65. col.prop(unit, "scale_length")
  66. col.prop(unit, "use_separate")
  67. col = layout.column()
  68. col.prop(unit, "system_rotation", text="Rotation")
  69. subcol = col.column()
  70. subcol.enabled = unit.system != 'NONE'
  71. subcol.prop(unit, "length_unit", text="Length")
  72. subcol.prop(unit, "mass_unit", text="Mass")
  73. subcol.prop(unit, "time_unit", text="Time")
  74. class SceneKeyingSetsPanel:
  75. @staticmethod
  76. def draw_keyframing_settings(context, layout, ks, ksp):
  77. SceneKeyingSetsPanel._draw_keyframing_setting(
  78. context, layout, ks, ksp, "Needed",
  79. "use_insertkey_override_needed", "use_insertkey_needed",
  80. userpref_fallback="use_keyframe_insert_needed",
  81. )
  82. SceneKeyingSetsPanel._draw_keyframing_setting(
  83. context, layout, ks, ksp, "Visual",
  84. "use_insertkey_override_visual", "use_insertkey_visual",
  85. userpref_fallback="use_visual_keying",
  86. )
  87. SceneKeyingSetsPanel._draw_keyframing_setting(
  88. context, layout, ks, ksp, "XYZ to RGB",
  89. "use_insertkey_override_xyz_to_rgb", "use_insertkey_xyz_to_rgb",
  90. )
  91. @staticmethod
  92. def _draw_keyframing_setting(context, layout, ks, ksp, label, toggle_prop, prop, userpref_fallback=None):
  93. if ksp:
  94. item = ksp
  95. if getattr(ks, toggle_prop):
  96. owner = ks
  97. propname = prop
  98. else:
  99. owner = context.preferences.edit
  100. if userpref_fallback:
  101. propname = userpref_fallback
  102. else:
  103. propname = prop
  104. else:
  105. item = ks
  106. owner = context.preferences.edit
  107. if userpref_fallback:
  108. propname = userpref_fallback
  109. else:
  110. propname = prop
  111. row = layout.row(align=True)
  112. subrow = row.row(align=True)
  113. subrow.active = getattr(item, toggle_prop)
  114. if subrow.active:
  115. subrow.prop(item, prop, text=label)
  116. else:
  117. subrow.prop(owner, propname, text=label)
  118. row.prop(item, toggle_prop, text="", icon='STYLUS_PRESSURE', toggle=True) # XXX: needs dedicated icon
  119. class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
  120. bl_label = "Keying Sets"
  121. bl_options = {'DEFAULT_CLOSED'}
  122. def draw(self, context):
  123. layout = self.layout
  124. scene = context.scene
  125. row = layout.row()
  126. col = row.column()
  127. col.template_list("UI_UL_list", "keying_sets", scene, "keying_sets", scene.keying_sets, "active_index", rows=1)
  128. col = row.column(align=True)
  129. col.operator("anim.keying_set_add", icon='ADD', text="")
  130. col.operator("anim.keying_set_remove", icon='REMOVE', text="")
  131. layout.use_property_split = True
  132. layout.use_property_decorate = False # No animation.
  133. flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
  134. ks = scene.keying_sets.active
  135. if ks and ks.is_path_absolute:
  136. col = flow.column()
  137. col.prop(ks, "bl_description")
  138. subcol = flow.column()
  139. subcol.operator_context = 'INVOKE_DEFAULT'
  140. subcol.operator("anim.keying_set_export", text="Export to File").filepath = "keyingset.py"
  141. class SCENE_PT_keyframing_settings(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
  142. bl_label = "Keyframing Settings"
  143. bl_parent_id = "SCENE_PT_keying_sets"
  144. @classmethod
  145. def poll(cls, context):
  146. ks = context.scene.keying_sets.active
  147. return (ks and ks.is_path_absolute)
  148. def draw(self, context):
  149. layout = self.layout
  150. layout.use_property_split = True
  151. layout.use_property_decorate = False # No animation.
  152. scene = context.scene
  153. ks = scene.keying_sets.active
  154. flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
  155. col = flow.column(align=True)
  156. col.alignment = 'RIGHT'
  157. col.label(text="General Override")
  158. self.draw_keyframing_settings(context, col, ks, None)
  159. ksp = ks.paths.active
  160. if ksp:
  161. col.separator()
  162. col = flow.column(align=True)
  163. col.alignment = 'RIGHT'
  164. col.label(text="Active Set Override")
  165. self.draw_keyframing_settings(context, col, ks, ksp)
  166. class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
  167. bl_label = "Active Keying Set"
  168. bl_parent_id = "SCENE_PT_keying_sets"
  169. @classmethod
  170. def poll(cls, context):
  171. ks = context.scene.keying_sets.active
  172. return (ks and ks.is_path_absolute)
  173. def draw(self, context):
  174. layout = self.layout
  175. scene = context.scene
  176. ks = scene.keying_sets.active
  177. row = layout.row()
  178. row.label(text="Paths:")
  179. row = layout.row()
  180. col = row.column()
  181. col.template_list("SCENE_UL_keying_set_paths", "", ks, "paths", ks.paths, "active_index", rows=1)
  182. col = row.column(align=True)
  183. col.operator("anim.keying_set_path_add", icon='ADD', text="")
  184. col.operator("anim.keying_set_path_remove", icon='REMOVE', text="")
  185. # TODO: 1) the template_any_ID needs to be fixed for the text alignment.
  186. # 2) use_property_decorate has to properly skip the non animatable properties.
  187. # Properties affected with needless draw:
  188. # group_method, template_any_ID dropdown, use_entire_array
  189. layout.use_property_split = True
  190. layout.use_property_decorate = False # No animation (remove this later on).
  191. flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
  192. ksp = ks.paths.active
  193. if ksp:
  194. col = flow.column(align=True)
  195. col.alignment = 'RIGHT'
  196. col.template_any_ID(ksp, "id", "id_type", text="Target ID-Block")
  197. col.separator()
  198. col.template_path_builder(ksp, "data_path", ksp.id, text="Data Path")
  199. col = flow.column()
  200. col.prop(ksp, "use_entire_array", text="Array All Items")
  201. if not ksp.use_entire_array:
  202. col.prop(ksp, "array_index", text="Index")
  203. col.separator()
  204. col.prop(ksp, "group_method", text="F-Curve Grouping")
  205. if ksp.group_method == 'NAMED':
  206. col.prop(ksp, "group")
  207. class SCENE_PT_audio(SceneButtonsPanel, Panel):
  208. bl_label = "Audio"
  209. bl_options = {'DEFAULT_CLOSED'}
  210. def draw(self, context):
  211. layout = self.layout
  212. layout.use_property_split = True
  213. scene = context.scene
  214. rd = context.scene.render
  215. ffmpeg = rd.ffmpeg
  216. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
  217. col = flow.column()
  218. col.prop(scene, "audio_volume")
  219. col.separator()
  220. col.prop(scene, "audio_distance_model")
  221. col.prop(ffmpeg, "audio_channels")
  222. col.separator()
  223. col = flow.column()
  224. col.prop(ffmpeg, "audio_mixrate", text="Sample Rate")
  225. col.separator()
  226. col = col.column(align=True)
  227. col.prop(scene, "audio_doppler_speed", text="Doppler Speed")
  228. col.prop(scene, "audio_doppler_factor", text="Doppler Factor")
  229. col.separator()
  230. layout.operator("sound.bake_animation")
  231. class SCENE_PT_physics(SceneButtonsPanel, Panel):
  232. bl_label = "Gravity"
  233. bl_options = {'DEFAULT_CLOSED'}
  234. def draw_header(self, context):
  235. self.layout.prop(context.scene, "use_gravity", text="")
  236. def draw(self, context):
  237. layout = self.layout
  238. layout.use_property_split = True
  239. scene = context.scene
  240. layout.active = scene.use_gravity
  241. layout.prop(scene, "gravity")
  242. class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
  243. bl_label = "Rigid Body World"
  244. bl_options = {'DEFAULT_CLOSED'}
  245. def draw_header(self, context):
  246. scene = context.scene
  247. rbw = scene.rigidbody_world
  248. if rbw is not None:
  249. self.layout.prop(rbw, "enabled", text="")
  250. def draw(self, context):
  251. layout = self.layout
  252. layout.use_property_split = True
  253. scene = context.scene
  254. rbw = scene.rigidbody_world
  255. if rbw is None:
  256. layout.operator("rigidbody.world_add")
  257. else:
  258. layout.operator("rigidbody.world_remove")
  259. class RigidBodySubPanel(SceneButtonsPanel):
  260. bl_parent_id = "SCENE_PT_rigid_body_world"
  261. @classmethod
  262. def poll(cls, context):
  263. scene = context.scene
  264. return scene and scene.rigidbody_world
  265. class SCENE_PT_rigid_body_world_settings(RigidBodySubPanel, Panel):
  266. bl_label = "Settings"
  267. def draw(self, context):
  268. layout = self.layout
  269. layout.use_property_split = True
  270. scene = context.scene
  271. rbw = scene.rigidbody_world
  272. if rbw:
  273. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
  274. col = flow.column()
  275. col.active = rbw.enabled
  276. col = col.column()
  277. col.prop(rbw, "collection")
  278. col.prop(rbw, "constraints")
  279. col = col.column()
  280. col.prop(rbw, "time_scale", text="Speed")
  281. col = flow.column()
  282. col.active = rbw.enabled
  283. col.prop(rbw, "use_split_impulse")
  284. col = col.column()
  285. col.prop(rbw, "steps_per_second", text="Steps Per Second")
  286. col.prop(rbw, "solver_iterations", text="Solver Iterations")
  287. class SCENE_PT_rigid_body_cache(RigidBodySubPanel, Panel):
  288. bl_label = "Cache"
  289. bl_options = {'DEFAULT_CLOSED'}
  290. def draw(self, context):
  291. scene = context.scene
  292. rbw = scene.rigidbody_world
  293. point_cache_ui(self, rbw.point_cache, rbw.point_cache.is_baked is False and rbw.enabled, 'RIGID_BODY')
  294. class SCENE_PT_rigid_body_field_weights(RigidBodySubPanel, Panel):
  295. bl_label = "Field Weights"
  296. bl_parent_id = "SCENE_PT_rigid_body_world"
  297. bl_options = {'DEFAULT_CLOSED'}
  298. def draw(self, context):
  299. scene = context.scene
  300. rbw = scene.rigidbody_world
  301. effector_weights_ui(self, rbw.effector_weights, 'RIGID_BODY')
  302. class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
  303. _context_path = "scene"
  304. _property_type = bpy.types.Scene
  305. classes = (
  306. SCENE_UL_keying_set_paths,
  307. SCENE_PT_scene,
  308. SCENE_PT_unit,
  309. SCENE_PT_physics,
  310. SCENE_PT_keying_sets,
  311. SCENE_PT_keying_set_paths,
  312. SCENE_PT_keyframing_settings,
  313. SCENE_PT_audio,
  314. SCENE_PT_rigid_body_world,
  315. SCENE_PT_rigid_body_world_settings,
  316. SCENE_PT_rigid_body_cache,
  317. SCENE_PT_rigid_body_field_weights,
  318. SCENE_PT_custom_props,
  319. )
  320. if __name__ == "__main__": # only for live edit.
  321. from bpy.utils import register_class
  322. for cls in classes:
  323. register_class(cls)