UI: expand more image editor scope panels by default
[blender.git] / release / scripts / startup / bl_ui / space_graph.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 from bpy.types import Header, Menu, Panel
22 from .space_dopesheet import (
23     DopesheetFilterPopoverBase,
24     dopesheet_filter,
25 )
26
27
28 class GRAPH_HT_header(Header):
29     bl_space_type = 'GRAPH_EDITOR'
30
31     def draw(self, context):
32         layout = self.layout
33         tool_settings = context.tool_settings
34
35         st = context.space_data
36
37         layout.template_header()
38
39         # Now a exposed as a sub-space type
40         # layout.prop(st, "mode", text="")
41
42         GRAPH_MT_editor_menus.draw_collapsible(context, layout)
43
44         row = layout.row(align=True)
45         row.prop(st, "use_normalization", icon='NORMALIZE_FCURVES', text="Normalize", toggle=True)
46         sub = row.row(align=True)
47         sub.active = st.use_normalization
48         sub.prop(st, "use_auto_normalization", icon='FILE_REFRESH', text="", toggle=True)
49
50         layout.separator_spacer()
51
52         dopesheet_filter(layout, context)
53
54         row = layout.row(align=True)
55         if st.has_ghost_curves:
56             row.operator("graph.ghost_curves_clear", text="", icon='GHOST_DISABLED')
57         else:
58             row.operator("graph.ghost_curves_create", text="", icon='GHOST_ENABLED')
59
60         layout.popover(
61             panel="GRAPH_PT_filters",
62             text="",
63             icon='FILTER',
64         )
65
66         layout.prop(st, "pivot_point", icon_only=True)
67
68         layout.prop(st, "auto_snap", text="")
69
70         row = layout.row(align=True)
71         row.prop(tool_settings, "use_proportional_fcurve", text="", icon_only=True)
72         sub = row.row(align=True)
73         sub.active = tool_settings.use_proportional_fcurve
74         sub.prop(tool_settings, "proportional_edit_falloff", text="", icon_only=True)
75
76
77 class GRAPH_PT_filters(DopesheetFilterPopoverBase, Panel):
78     bl_space_type = 'GRAPH_EDITOR'
79     bl_region_type = 'HEADER'
80     bl_label = "Filters"
81
82     def draw(self, context):
83         layout = self.layout
84
85         DopesheetFilterPopoverBase.draw_generic_filters(context, layout)
86         layout.separator()
87         DopesheetFilterPopoverBase.draw_search_filters(context, layout)
88         layout.separator()
89         DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
90
91
92 class GRAPH_MT_editor_menus(Menu):
93     bl_idname = "GRAPH_MT_editor_menus"
94     bl_label = ""
95
96     def draw(self, _context):
97         layout = self.layout
98         layout.menu("GRAPH_MT_view")
99         layout.menu("GRAPH_MT_select")
100         layout.menu("GRAPH_MT_marker")
101         layout.menu("GRAPH_MT_channel")
102         layout.menu("GRAPH_MT_key")
103
104
105 class GRAPH_MT_view(Menu):
106     bl_label = "View"
107
108     def draw(self, context):
109         layout = self.layout
110
111         st = context.space_data
112
113         layout.prop(st, "show_region_ui")
114         layout.separator()
115
116         layout.prop(st, "use_realtime_update")
117         layout.prop(st, "show_frame_indicator")
118         layout.prop(st, "show_cursor")
119         layout.prop(st, "show_sliders")
120         layout.prop(st, "show_group_colors")
121         layout.prop(st, "show_marker_lines")
122         layout.prop(st, "use_auto_merge_keyframes")
123
124         layout.separator()
125         layout.prop(st, "use_beauty_drawing")
126
127         layout.separator()
128
129         layout.prop(st, "show_handles")
130
131         layout.prop(st, "use_only_selected_curves_handles")
132         layout.prop(st, "use_only_selected_keyframe_handles")
133
134         layout.prop(st, "show_seconds")
135         layout.prop(st, "show_locked_time")
136
137         layout.separator()
138         layout.operator("anim.previewrange_set")
139         layout.operator("anim.previewrange_clear")
140         layout.operator("graph.previewrange_set")
141
142         layout.separator()
143         layout.operator("graph.view_all")
144         layout.operator("graph.view_selected")
145         layout.operator("graph.view_frame")
146
147         # Add this to show key-binding (reverse action in dope-sheet).
148         layout.separator()
149         props = layout.operator("wm.context_set_enum", text="Toggle Dope Sheet")
150         props.data_path = "area.type"
151         props.value = 'DOPESHEET_EDITOR'
152
153         layout.separator()
154         layout.menu("INFO_MT_area")
155
156
157 class GRAPH_MT_select(Menu):
158     bl_label = "Select"
159
160     def draw(self, _context):
161         layout = self.layout
162
163         layout.operator("graph.select_all", text="All").action = 'SELECT'
164         layout.operator("graph.select_all", text="None").action = 'DESELECT'
165         layout.operator("graph.select_all", text="Invert").action = 'INVERT'
166
167         layout.separator()
168
169         props = layout.operator("graph.select_box")
170         props.axis_range = False
171         props.include_handles = False
172         props = layout.operator("graph.select_box", text="Border Axis Range")
173         props.axis_range = True
174         props.include_handles = False
175         props = layout.operator("graph.select_box", text="Border (Include Handles)")
176         props.axis_range = False
177         props.include_handles = True
178
179         layout.operator("graph.select_circle")
180
181         layout.separator()
182         layout.operator("graph.select_column", text="Columns on Selected Keys").mode = 'KEYS'
183         layout.operator("graph.select_column", text="Column on Current Frame").mode = 'CFRA'
184
185         layout.operator("graph.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN'
186         layout.operator("graph.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
187
188         layout.separator()
189         props = layout.operator("graph.select_leftright", text="Before Current Frame")
190         props.extend = False
191         props.mode = 'LEFT'
192         props = layout.operator("graph.select_leftright", text="After Current Frame")
193         props.extend = False
194         props.mode = 'RIGHT'
195
196         layout.separator()
197         layout.operator("graph.select_more")
198         layout.operator("graph.select_less")
199
200         layout.separator()
201         layout.operator("graph.select_linked")
202
203
204 class GRAPH_MT_marker(Menu):
205     bl_label = "Marker"
206
207     def draw(self, context):
208         layout = self.layout
209
210         from .space_time import marker_menu_generic
211         marker_menu_generic(layout, context)
212
213         # TODO: pose markers for action edit mode only?
214
215
216 class GRAPH_MT_channel(Menu):
217     bl_label = "Channel"
218
219     def draw(self, context):
220         layout = self.layout
221
222         layout.operator_context = 'INVOKE_REGION_CHANNELS'
223
224         layout.operator("anim.channels_delete")
225         if context.space_data.mode == 'DRIVERS':
226             layout.operator("graph.driver_delete_invalid")
227
228         layout.separator()
229         layout.operator("anim.channels_group")
230         layout.operator("anim.channels_ungroup")
231
232         layout.separator()
233         layout.operator_menu_enum("anim.channels_setting_toggle", "type")
234         layout.operator_menu_enum("anim.channels_setting_enable", "type")
235         layout.operator_menu_enum("anim.channels_setting_disable", "type")
236
237         layout.separator()
238         layout.operator("anim.channels_editable_toggle")
239         layout.operator_menu_enum("graph.extrapolation_type", "type", text="Extrapolation Mode")
240
241         layout.separator()
242         layout.operator("graph.hide", text="Hide Selected Curves").unselected = False
243         layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True
244         layout.operator("graph.reveal")
245
246         layout.separator()
247         layout.operator("anim.channels_expand")
248         layout.operator("anim.channels_collapse")
249
250         layout.separator()
251         layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
252
253         layout.separator()
254         layout.operator("anim.channels_fcurves_enable")
255
256
257 class GRAPH_MT_key(Menu):
258     bl_label = "Key"
259
260     def draw(self, _context):
261         layout = self.layout
262
263         layout.menu("GRAPH_MT_key_transform", text="Transform")
264
265         layout.operator_menu_enum("graph.snap", "type", text="Snap")
266         layout.operator_menu_enum("graph.mirror", "type", text="Mirror")
267
268         layout.separator()
269         layout.operator_menu_enum("graph.keyframe_insert", "type")
270         layout.operator_menu_enum("graph.fmodifier_add", "type")
271         layout.operator("graph.sound_bake")
272
273         layout.separator()
274         layout.operator("graph.frame_jump")
275
276         layout.separator()
277         layout.operator("graph.copy")
278         layout.operator("graph.paste")
279         layout.operator("graph.paste", text="Paste Flipped").flipped = True
280         layout.operator("graph.duplicate_move")
281         layout.operator("graph.delete")
282
283         layout.separator()
284         layout.operator_menu_enum("graph.handle_type", "type", text="Handle Type")
285         layout.operator_menu_enum("graph.interpolation_type", "type", text="Interpolation Mode")
286         layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type")
287
288         layout.separator()
289         layout.operator("graph.clean").channels = False
290         layout.operator("graph.clean", text="Clean Channels").channels = True
291         layout.operator("graph.smooth")
292         layout.operator("graph.sample")
293         layout.operator("graph.bake")
294
295         layout.separator()
296         layout.operator("graph.euler_filter", text="Discontinuity (Euler) Filter")
297
298
299 class GRAPH_MT_key_transform(Menu):
300     bl_label = "Transform"
301
302     def draw(self, _context):
303         layout = self.layout
304
305         layout.operator("transform.translate", text="Move")
306         layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
307         layout.operator("transform.rotate", text="Rotate")
308         layout.operator("transform.resize", text="Scale")
309
310
311 class GRAPH_MT_delete(Menu):
312     bl_label = "Delete"
313
314     def draw(self, _context):
315         layout = self.layout
316
317         layout.operator("graph.delete")
318
319         layout.separator()
320
321         layout.operator("graph.clean").channels = False
322         layout.operator("graph.clean", text="Clean Channels").channels = True
323
324
325 class GRAPH_MT_context_menu(Menu):
326     bl_label = "F-Curve Context Menu"
327
328     def draw(self, _context):
329         layout = self.layout
330
331         layout.operator("graph.copy", text="Copy", icon='COPYDOWN')
332         layout.operator("graph.paste", text="Paste", icon='PASTEDOWN')
333         layout.operator("graph.paste", text="Paste Flipped", icon='PASTEFLIPDOWN').flipped = True
334
335         layout.separator()
336
337         layout.operator_menu_enum("graph.handle_type", "type", text="Handle Type")
338         layout.operator_menu_enum("graph.interpolation_type", "type", text="Interpolation Mode")
339         layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type")
340
341         layout.separator()
342
343         layout.operator("graph.keyframe_insert").type = 'SEL'
344         layout.operator("graph.duplicate_move")
345         layout.operator("graph.delete")
346
347         layout.separator()
348
349         layout.operator_menu_enum("graph.mirror", "type", text="Mirror")
350         layout.operator_menu_enum("graph.snap", "type", text="Snap")
351
352
353 class GRAPH_MT_pivot_pie(Menu):
354     bl_label = "Pivot Point"
355
356     def draw(self, context):
357         layout = self.layout
358         pie = layout.menu_pie()
359
360         pie.prop_enum(context.space_data, "pivot_point", value='BOUNDING_BOX_CENTER')
361         pie.prop_enum(context.space_data, "pivot_point", value='CURSOR')
362         pie.prop_enum(context.space_data, "pivot_point", value='INDIVIDUAL_ORIGINS')
363
364
365 class GRAPH_MT_snap_pie(Menu):
366     bl_label = "Snap"
367
368     def draw(self, _context):
369         layout = self.layout
370         pie = layout.menu_pie()
371
372         pie.operator("graph.snap", text="Current Frame").type = 'CFRA'
373         pie.operator("graph.snap", text="Cursor Value").type = 'VALUE'
374         pie.operator("graph.snap", text="Nearest Frame").type = 'NEAREST_FRAME'
375         pie.operator("graph.snap", text="Nearest Second").type = 'NEAREST_SECOND'
376         pie.operator("graph.snap", text="Nearest Marker").type = 'NEAREST_MARKER'
377         pie.operator("graph.snap", text="Flatten Handles").type = 'HORIZONTAL'
378
379
380 class GRAPH_MT_channel_context_menu(Menu):
381     bl_label = "F-Curve Channel Context Menu"
382
383     def draw(self, context):
384         layout = self.layout
385         st = context.space_data
386
387         layout.separator()
388         layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE'
389         layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE'
390         layout.separator()
391         layout.operator("anim.channels_setting_enable", text="Protect Channels").type = 'PROTECT'
392         layout.operator("anim.channels_setting_disable", text="Unprotect Channels").type = 'PROTECT'
393
394         layout.separator()
395         layout.operator("anim.channels_group")
396         layout.operator("anim.channels_ungroup")
397
398         layout.separator()
399         layout.operator("anim.channels_editable_toggle")
400         layout.operator_menu_enum("graph.extrapolation_type", "type", text="Extrapolation Mode")
401
402         layout.separator()
403         layout.operator("graph.hide", text="Hide Selected Curves").unselected = False
404         layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True
405         layout.operator("graph.reveal")
406
407         layout.separator()
408         layout.operator("anim.channels_expand")
409         layout.operator("anim.channels_collapse")
410
411         layout.separator()
412         layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
413
414         layout.separator()
415
416         layout.operator("anim.channels_delete")
417         if st.mode == 'DRIVERS':
418             layout.operator("graph.driver_delete_invalid")
419
420
421 classes = (
422     GRAPH_HT_header,
423     GRAPH_MT_editor_menus,
424     GRAPH_MT_view,
425     GRAPH_MT_select,
426     GRAPH_MT_marker,
427     GRAPH_MT_channel,
428     GRAPH_MT_key,
429     GRAPH_MT_key_transform,
430     GRAPH_MT_delete,
431     GRAPH_MT_context_menu,
432     GRAPH_MT_channel_context_menu,
433     GRAPH_MT_pivot_pie,
434     GRAPH_MT_snap_pie,
435     GRAPH_PT_filters,
436 )
437
438 if __name__ == "__main__":  # only for live edit.
439     from bpy.utils import register_class
440     for cls in classes:
441         register_class(cls)