UI: use subpanel for particle emission source, as an example.
[blender.git] / release / scripts / startup / bl_ui / space_time.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 Header, Menu, Panel
22
23
24 # Header buttons for timeline header (play, etc.)
25 class TIME_HT_editor_buttons(Header):
26     bl_idname = "TIME_HT_editor_buttons"
27     bl_space_type = 'DOPESHEET_EDITOR'
28     bl_label = ""
29
30     def draw(self, context):
31         pass
32
33     @staticmethod
34     def draw_header(context, layout):
35         scene = context.scene
36         toolsettings = context.tool_settings
37         screen = context.screen
38
39         layout.separator()   # XXX: This should be dynamic (e.g. layout.separator(stretch=1.0))
40         layout.separator()
41         layout.separator()
42         layout.separator()
43         layout.separator()
44         layout.separator()
45         layout.separator()
46
47         row = layout.row(align=True)
48         row.prop(toolsettings, "use_keyframe_insert_auto", text="", toggle=True)
49
50         row.operator("screen.frame_jump", text="", icon='REW').end = False
51         row.operator("screen.keyframe_jump", text="", icon='PREV_KEYFRAME').next = False
52         if not screen.is_animation_playing:
53             # if using JACK and A/V sync:
54             #   hide the play-reversed button
55             #   since JACK transport doesn't support reversed playback
56             if scene.sync_mode == 'AUDIO_SYNC' and context.user_preferences.system.audio_device == 'JACK':
57                 sub = row.row(align=True)
58                 sub.scale_x = 1.4
59                 sub.operator("screen.animation_play", text="", icon='PLAY')
60             else:
61                 row.operator("screen.animation_play", text="", icon='PLAY_REVERSE').reverse = True
62                 row.operator("screen.animation_play", text="", icon='PLAY')
63         else:
64             sub = row.row(align=True)
65             sub.scale_x = 1.4
66             sub.operator("screen.animation_play", text="", icon='PAUSE')
67         row.operator("screen.keyframe_jump", text="", icon='NEXT_KEYFRAME').next = True
68         row.operator("screen.frame_jump", text="", icon='FF').end = True
69
70         layout.separator()  # XXX: This should be dynamic (e.g. layout.separator(stretch=1.0))
71         layout.separator()
72         layout.separator()
73         layout.separator()
74         layout.separator()
75         layout.separator()
76         layout.separator()
77
78         row = layout.row()
79         row.scale_x = 0.95
80         if scene.show_subframe:
81             row.prop(scene, "frame_float", text="")
82         else:
83             row.prop(scene, "frame_current", text="")
84
85         layout.separator()
86         layout.separator()
87
88         row = layout.row(align=True)
89         row.prop(scene, "use_preview_range", text="", toggle=True)
90         sub = row.row(align=True)
91         sub.scale_x = 0.8
92         if not scene.use_preview_range:
93             sub.prop(scene, "frame_start", text="Start")
94             sub.prop(scene, "frame_end", text="End")
95         else:
96             sub.prop(scene, "frame_preview_start", text="Start")
97             sub.prop(scene, "frame_preview_end", text="End")
98
99
100 class TIME_MT_editor_menus(Menu):
101     bl_idname = "TIME_MT_editor_menus"
102     bl_label = ""
103
104     def draw(self, context):
105         self.draw_menus(self.layout, context)
106
107     @staticmethod
108     def draw_menus(layout, context):
109         layout.menu("TIME_MT_view")
110         layout.menu("TIME_MT_marker")
111         layout.popover(space_type='DOPESHEET_EDITOR',
112                        region_type='HEADER',
113                        panel_type="TIME_PT_playback",
114                        text="Playback")
115         layout.popover(space_type='DOPESHEET_EDITOR',
116                        region_type='HEADER',
117                        panel_type="TIME_PT_keyframing_settings",
118                        text="Keying")
119
120 class TIME_MT_marker(Menu):
121     bl_label = "Marker"
122
123     def draw(self, context):
124         layout = self.layout
125
126         marker_menu_generic(layout)
127
128
129 class TIME_MT_view(Menu):
130     bl_label = "View"
131
132     def draw(self, context):
133         layout = self.layout
134
135         scene = context.scene
136         st = context.space_data
137
138         layout.prop(st, "show_seconds")
139         layout.prop(st, "show_locked_time")
140
141         layout.separator()
142
143         layout.prop(st, "show_frame_indicator")
144         layout.prop(scene, "show_keys_from_selected_only")
145
146         layout.separator()
147
148         layout.menu("TIME_MT_cache")
149
150         layout.separator()
151
152         # NOTE: "action" now, since timeline is in the dopesheet editor, instead of as own editor
153         layout.operator("action.view_all")
154         layout.operator("action.view_frame")
155
156         layout.separator()
157
158         layout.menu("INFO_MT_area")
159
160
161 class TIME_MT_cache(Menu):
162     bl_label = "Cache"
163
164     def draw(self, context):
165         layout = self.layout
166
167         st = context.space_data
168
169         layout.prop(st, "show_cache")
170
171         layout.separator()
172
173         col = layout.column()
174         col.enabled = st.show_cache
175         col.prop(st, "cache_softbody")
176         col.prop(st, "cache_particles")
177         col.prop(st, "cache_cloth")
178         col.prop(st, "cache_smoke")
179         col.prop(st, "cache_dynamicpaint")
180         col.prop(st, "cache_rigidbody")
181
182
183 def marker_menu_generic(layout):
184     from bpy import context
185
186     # layout.operator_context = 'EXEC_REGION_WIN'
187
188     layout.column()
189     layout.operator("marker.add", "Add Marker")
190     layout.operator("marker.duplicate", text="Duplicate Marker")
191
192     if len(bpy.data.scenes) > 10:
193         layout.operator_context = 'INVOKE_DEFAULT'
194         layout.operator("marker.make_links_scene", text="Duplicate Marker to Scene...", icon='OUTLINER_OB_EMPTY')
195     else:
196         layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene")
197
198     layout.operator("marker.delete", text="Delete Marker")
199
200     layout.separator()
201
202     layout.operator("marker.rename", text="Rename Marker")
203     layout.operator("marker.move", text="Grab/Move Marker")
204
205     layout.separator()
206
207     layout.operator("marker.camera_bind")
208
209     layout.separator()
210
211     layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True
212     layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False
213
214     layout.separator()
215     ts = context.tool_settings
216     layout.prop(ts, "lock_markers")
217
218 ###################################
219
220 class TimelinePanelButtons:
221     bl_space_type = 'DOPESHEET_EDITOR'
222     bl_region_type = 'UI'
223
224     @staticmethod
225     def has_timeline(context):
226         return context.space_data.mode == 'TIMELINE'
227
228
229 class TIME_PT_playback(TimelinePanelButtons, Panel):
230     bl_label = "Playback"
231     bl_region_type = 'HEADER'
232
233     def draw(self, context):
234         layout = self.layout
235
236         screen = context.screen
237         scene = context.scene
238
239         layout.prop(scene, "sync_mode", text="")
240         layout.prop(scene, "use_audio_scrub")
241         layout.prop(scene, "use_audio", text="Mute Audio")
242
243         layout.prop(scene, "show_subframe", text="Subframes")
244
245         layout.prop(scene, "lock_frame_selection_to_range", text="Limit Playhead to Frame Range")
246         layout.prop(screen, "use_follow", text="Follow Playhead")
247
248         layout.separator()
249
250         col = layout.column()
251         col.label("Play Animation In:")
252         layout.prop(screen, "use_play_top_left_3d_editor", text="Active Editor Only")
253         layout.prop(screen, "use_play_3d_editors")
254         layout.prop(screen, "use_play_animation_editors")
255         layout.prop(screen, "use_play_properties_editors")
256         layout.prop(screen, "use_play_image_editors")
257         layout.prop(screen, "use_play_sequence_editors")
258         layout.prop(screen, "use_play_node_editors")
259         layout.prop(screen, "use_play_clip_editors")
260
261         layout.separator()
262
263         row = layout.row(align=True)
264         row.operator("anim.start_frame_set")
265         row.operator("anim.end_frame_set")
266
267
268 class TIME_PT_keyframing_settings(TimelinePanelButtons, Panel):
269     bl_label = "Keyframing Settings"
270     bl_options = {'HIDE_HEADER'}
271     bl_region_type = 'HEADER'
272
273     @classmethod
274     def poll(cls, context):
275         # only for timeline editor
276         return cls.has_timeline(context)
277
278     def draw(self, context):
279         layout = self.layout
280
281         scene = context.scene
282         toolsettings = context.tool_settings
283         userprefs = context.user_preferences
284
285         col = layout.column(align=True)
286         col.label("Active Keying Set:")
287         row = col.row(align=True)
288         row.prop_search(scene.keying_sets_all, "active", scene, "keying_sets_all", text="")
289         row.operator("anim.keyframe_insert", text="", icon='KEY_HLT')
290         row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
291
292         col = layout.column(align=True)
293         col.label("New Keyframe Type:")
294         col.prop(toolsettings, "keyframe_type", text="")
295         
296         col = layout.column(align=True)
297         col.label("Auto Keyframing:")
298         row = col.row()
299         row.prop(toolsettings, "auto_keying_mode", text="")
300         row.prop(toolsettings, "use_keyframe_insert_keyingset", text="")
301         if not userprefs.edit.use_keyframe_insert_available:
302             col.prop(toolsettings, "use_record_with_nla", text="Layered Recording")
303
304
305 ###################################
306
307 classes = (
308     TIME_HT_editor_buttons,
309     TIME_MT_editor_menus,
310     TIME_MT_marker,
311     TIME_MT_view,
312     TIME_MT_cache,
313     TIME_PT_playback,
314     TIME_PT_keyframing_settings,
315 )
316
317 if __name__ == "__main__":  # only for live edit.
318     from bpy.utils import register_class
319     for cls in classes:
320         register_class(cls)