UI: rename "OpenGL" render engine to "Workbench".
[blender.git] / release / scripts / startup / bl_ui / properties_scene.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
21 import bpy
22 from bpy.types import (
23     Panel,
24     UIList,
25 )
26
27 from rna_prop_ui import PropertyPanel
28 from bl_operators.presets import PresetMenu
29
30 from .properties_physics_common import (
31     point_cache_ui,
32     effector_weights_ui,
33 )
34
35
36 class SCENE_UL_keying_set_paths(UIList):
37     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
38         # assert(isinstance(item, bpy.types.KeyingSetPath)
39         kspath = item
40         icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
41         if self.layout_type in {'DEFAULT', 'COMPACT'}:
42             # Do not make this one editable in uiList for now...
43             layout.label(text=kspath.data_path, translate=False, icon_value=icon)
44         elif self.layout_type == 'GRID':
45             layout.alignment = 'CENTER'
46             layout.label(text="", icon_value=icon)
47
48
49 class SceneButtonsPanel:
50     bl_space_type = 'PROPERTIES'
51     bl_region_type = 'WINDOW'
52     bl_context = "scene"
53
54     @classmethod
55     def poll(cls, context):
56         return (context.engine in cls.COMPAT_ENGINES)
57
58
59 class SCENE_PT_scene(SceneButtonsPanel, Panel):
60     bl_label = "Scene"
61     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
62
63     def draw(self, context):
64         layout = self.layout
65         layout.use_property_split = True
66         layout.use_property_decorate = False
67
68         scene = context.scene
69
70         layout.prop(scene, "camera")
71         layout.prop(scene, "background_set")
72         layout.prop(scene, "active_clip")
73
74
75 class SCENE_PT_unit(SceneButtonsPanel, Panel):
76     bl_label = "Units"
77     bl_options = {'DEFAULT_CLOSED'}
78     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
79
80     def draw(self, context):
81         layout = self.layout
82
83         unit = context.scene.unit_settings
84
85         layout.use_property_split = True
86         layout.use_property_decorate = False
87
88         layout.prop(unit, "system")
89
90         col = layout.column()
91         col.enabled = unit.system != 'NONE'
92         col.prop(unit, "scale_length")
93         col.prop(unit, "use_separate")
94
95         col = layout.column()
96         col.prop(unit, "system_rotation", text="Rotation")
97         subcol = col.column()
98         subcol.enabled = unit.system != 'NONE'
99         subcol.prop(unit, "length_unit", text="Length")
100         subcol.prop(unit, "mass_unit", text="Mass")
101         subcol.prop(unit, "time_unit", text="Time")
102
103
104 class SceneKeyingSetsPanel:
105
106     @staticmethod
107     def draw_keyframing_settings(context, layout, ks, ksp):
108         SceneKeyingSetsPanel._draw_keyframing_setting(
109             context, layout, ks, ksp, "Needed",
110             "use_insertkey_override_needed", "use_insertkey_needed",
111             userpref_fallback="use_keyframe_insert_needed",
112         )
113         SceneKeyingSetsPanel._draw_keyframing_setting(
114             context, layout, ks, ksp, "Visual",
115             "use_insertkey_override_visual", "use_insertkey_visual",
116             userpref_fallback="use_visual_keying",
117         )
118         SceneKeyingSetsPanel._draw_keyframing_setting(
119             context, layout, ks, ksp, "XYZ to RGB",
120             "use_insertkey_override_xyz_to_rgb", "use_insertkey_xyz_to_rgb",
121         )
122
123     @staticmethod
124     def _draw_keyframing_setting(context, layout, ks, ksp, label, toggle_prop, prop, userpref_fallback=None):
125         if ksp:
126             item = ksp
127
128             if getattr(ks, toggle_prop):
129                 owner = ks
130                 propname = prop
131             else:
132                 owner = context.user_preferences.edit
133                 if userpref_fallback:
134                     propname = userpref_fallback
135                 else:
136                     propname = prop
137         else:
138             item = ks
139
140             owner = context.user_preferences.edit
141             if userpref_fallback:
142                 propname = userpref_fallback
143             else:
144                 propname = prop
145
146         row = layout.row(align=True)
147
148         subrow = row.row(align=True)
149         subrow.active = getattr(item, toggle_prop)
150
151         if subrow.active:
152             subrow.prop(item, prop, text=label)
153         else:
154             subrow.prop(owner, propname, text=label)
155
156         row.prop(item, toggle_prop, text="", icon='STYLUS_PRESSURE', toggle=True)  # XXX: needs dedicated icon
157
158
159 class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
160     bl_label = "Keying Sets"
161     bl_options = {'DEFAULT_CLOSED'}
162     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
163
164     def draw(self, context):
165         layout = self.layout
166
167         scene = context.scene
168
169         row = layout.row()
170
171         col = row.column()
172         col.template_list("UI_UL_list", "keying_sets", scene, "keying_sets", scene.keying_sets, "active_index", rows=1)
173
174         col = row.column(align=True)
175         col.operator("anim.keying_set_add", icon='ADD', text="")
176         col.operator("anim.keying_set_remove", icon='REMOVE', text="")
177
178         layout.use_property_split = True
179         layout.use_property_decorate = False  # No animation.
180
181         flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
182
183         ks = scene.keying_sets.active
184         if ks and ks.is_path_absolute:
185             col = flow.column()
186             col.prop(ks, "bl_description")
187
188             subcol = flow.column()
189             subcol.operator_context = 'INVOKE_DEFAULT'
190             subcol.operator("anim.keying_set_export", text="Export to File").filepath = "keyingset.py"
191
192
193 class SCENE_PT_keyframing_settings(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
194     bl_label = "Keyframing Settings"
195     bl_parent_id = "SCENE_PT_keying_sets"
196     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
197
198     @classmethod
199     def poll(cls, context):
200         ks = context.scene.keying_sets.active
201         return (ks and ks.is_path_absolute)
202
203     def draw(self, context):
204         layout = self.layout
205         layout.use_property_split = True
206         layout.use_property_decorate = False  # No animation.
207
208         scene = context.scene
209         ks = scene.keying_sets.active
210
211         flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
212
213         col = flow.column(align=True)
214         col.alignment = 'RIGHT'
215         col.label(text="General Override")
216
217         self.draw_keyframing_settings(context, col, ks, None)
218
219         ksp = ks.paths.active
220         if ksp:
221             col.separator()
222
223             col = flow.column(align=True)
224             col.alignment = 'RIGHT'
225             col.label(text="Active Set Override")
226
227             self.draw_keyframing_settings(context, col, ks, ksp)
228
229
230 class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel):
231     bl_label = "Active Keying Set"
232     bl_parent_id = "SCENE_PT_keying_sets"
233     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
234
235     @classmethod
236     def poll(cls, context):
237         ks = context.scene.keying_sets.active
238         return (ks and ks.is_path_absolute)
239
240     def draw(self, context):
241         layout = self.layout
242
243         scene = context.scene
244         ks = scene.keying_sets.active
245
246         row = layout.row()
247         row.label(text="Paths:")
248
249         row = layout.row()
250
251         col = row.column()
252         col.template_list("SCENE_UL_keying_set_paths", "", ks, "paths", ks.paths, "active_index", rows=1)
253
254         col = row.column(align=True)
255         col.operator("anim.keying_set_path_add", icon='ADD', text="")
256         col.operator("anim.keying_set_path_remove", icon='REMOVE', text="")
257
258         # TODO: 1) the template_any_ID needs to be fixed for the text alignment.
259         #       2) use_property_decorate has to properly skip the non animatable properties.
260         #          Properties affected with needless draw:
261         #          group_method, template_any_ID dropdown, use_entire_array
262
263         layout.use_property_split = True
264         layout.use_property_decorate = False  # No animation (remove this later on).
265
266         flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
267
268         ksp = ks.paths.active
269         if ksp:
270             col = flow.column(align=True)
271             col.alignment = 'RIGHT'
272
273             col.template_any_ID(ksp, "id", "id_type", text="Target ID-Block")
274
275             col.separator()
276
277             col.template_path_builder(ksp, "data_path", ksp.id, text="Data Path")
278
279             col = flow.column()
280
281             col.prop(ksp, "use_entire_array", text="Array All Items")
282
283             if not ksp.use_entire_array:
284                 col.prop(ksp, "array_index", text="Index")
285
286             col.separator()
287
288             col.prop(ksp, "group_method", text="F-Curve Grouping")
289             if ksp.group_method == 'NAMED':
290                 col.prop(ksp, "group")
291
292
293 class SCENE_PT_audio(SceneButtonsPanel, Panel):
294     bl_label = "Audio"
295     bl_options = {'DEFAULT_CLOSED'}
296     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
297
298     def draw(self, context):
299         layout = self.layout
300         layout.use_property_split = True
301
302         scene = context.scene
303         rd = context.scene.render
304         ffmpeg = rd.ffmpeg
305
306         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
307
308         col = flow.column()
309         col.prop(scene, "audio_volume")
310
311         col.separator()
312
313         col.prop(scene, "audio_distance_model")
314         col.prop(ffmpeg, "audio_channels")
315
316         col.separator()
317
318         col = flow.column()
319         col.prop(ffmpeg, "audio_mixrate", text="Sample Rate")
320
321         col.separator()
322
323         col = col.column(align=True)
324         col.prop(scene, "audio_doppler_speed", text="Doppler Speed")
325         col.prop(scene, "audio_doppler_factor", text="Doppler Factor")
326
327         col.separator()
328
329         layout.operator("sound.bake_animation")
330
331
332 class SCENE_PT_physics(SceneButtonsPanel, Panel):
333     bl_label = "Gravity"
334     bl_options = {'DEFAULT_CLOSED'}
335     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
336
337     def draw_header(self, context):
338         self.layout.prop(context.scene, "use_gravity", text="")
339
340     def draw(self, context):
341         layout = self.layout
342         layout.use_property_split = True
343
344         scene = context.scene
345
346         layout.active = scene.use_gravity
347
348         layout.prop(scene, "gravity")
349
350
351 class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
352     bl_label = "Rigid Body World"
353     bl_options = {'DEFAULT_CLOSED'}
354     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
355
356     @classmethod
357     def poll(cls, context):
358         return (context.engine in cls.COMPAT_ENGINES)
359
360     def draw_header(self, context):
361         scene = context.scene
362         rbw = scene.rigidbody_world
363         if rbw is not None:
364             self.layout.prop(rbw, "enabled", text="")
365
366     def draw(self, context):
367         layout = self.layout
368         layout.use_property_split = True
369
370         scene = context.scene
371         rbw = scene.rigidbody_world
372
373         if rbw is None:
374             layout.operator("rigidbody.world_add")
375         else:
376             layout.operator("rigidbody.world_remove")
377
378
379 class SCENE_PT_rigid_body_world_settings(SceneButtonsPanel, Panel):
380     bl_label = "Settings"
381     bl_parent_id = "SCENE_PT_rigid_body_world"
382     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'}
383
384     @classmethod
385     def poll(cls, context):
386         scene = context.scene
387         return scene and scene.rigidbody_world and (context.engine in cls.COMPAT_ENGINES)
388
389     def draw(self, context):
390         layout = self.layout
391         layout.use_property_split = True
392
393         scene = context.scene
394         rbw = scene.rigidbody_world
395
396         if rbw:
397             flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
398
399             col = flow.column()
400             col.active = rbw.enabled
401
402             col = col.column()
403             col.prop(rbw, "group")
404             col.prop(rbw, "constraints")
405
406             col = col.column()
407             col.prop(rbw, "time_scale", text="Speed")
408
409             col = flow.column()
410             col.active = rbw.enabled
411             col.prop(rbw, "use_split_impulse")
412
413             col = col.column()
414             col.prop(rbw, "steps_per_second", text="Steps Per Second")
415             col.prop(rbw, "solver_iterations", text="Solver Iterations")
416
417
418 class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel):
419     bl_label = "Cache"
420     bl_parent_id = "SCENE_PT_rigid_body_world"
421     bl_options = {'DEFAULT_CLOSED'}
422     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
423
424     @classmethod
425     def poll(cls, context):
426         scene = context.scene
427         return scene and scene.rigidbody_world and (context.engine in cls.COMPAT_ENGINES)
428
429     def draw(self, context):
430         scene = context.scene
431         rbw = scene.rigidbody_world
432
433         point_cache_ui(self, context, rbw.point_cache, rbw.point_cache.is_baked is False and rbw.enabled, 'RIGID_BODY')
434
435
436 class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
437     bl_label = "Field Weights"
438     bl_parent_id = "SCENE_PT_rigid_body_world"
439     bl_options = {'DEFAULT_CLOSED'}
440     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
441
442     @classmethod
443     def poll(cls, context):
444         scene = context.scene
445         return scene and scene.rigidbody_world and (context.engine in cls.COMPAT_ENGINES)
446
447     def draw(self, context):
448         scene = context.scene
449         rbw = scene.rigidbody_world
450
451         effector_weights_ui(self, context, rbw.effector_weights, 'RIGID_BODY')
452
453
454 class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
455     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
456     _context_path = "scene"
457     _property_type = bpy.types.Scene
458
459
460 classes = (
461     SCENE_UL_keying_set_paths,
462     SCENE_PT_scene,
463     SCENE_PT_unit,
464     SCENE_PT_physics,
465     SCENE_PT_keying_sets,
466     SCENE_PT_keying_set_paths,
467     SCENE_PT_keyframing_settings,
468     SCENE_PT_audio,
469     SCENE_PT_rigid_body_world,
470     SCENE_PT_rigid_body_world_settings,
471     SCENE_PT_rigid_body_cache,
472     SCENE_PT_rigid_body_field_weights,
473     SCENE_PT_custom_props,
474 )
475
476 if __name__ == "__main__":  # only for live edit.
477     from bpy.utils import register_class
478     for cls in classes:
479         register_class(cls)