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