Files
test2/scripts/startup/bl_ui/space_nla.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

430 lines
13 KiB
Python
Raw Normal View History

# SPDX-FileCopyrightText: 2009-2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
from bpy.types import Header, Menu, Panel
from bpy.app.translations import contexts as i18n_contexts
from bl_ui.space_dopesheet import (
DopesheetFilterPopoverBase,
DopesheetActionPanelBase,
dopesheet_filter,
2018-06-26 22:56:39 +02:00
)
from bl_ui.space_time import playback_controls
Anim: Common Playhead snapping for all editors This patch adds snapping options for the playhead to all animation editors. The options can be modified through a new dropdown in the editor header. All editors will show all those options, and they are shared, so toggling the option in on editor will change it for all other editors too. Some options are not working/relevant in some editors for example Strips in the Dope Sheet. However for consistency the option is still shown. This is a separate menu from the transform snapping menu because you can toggle the snapping for transform and playhead separately. Putting it in the existing snapping transform menu would imply that it can be turned off with the magnet which is not the case. Playhead snapping is explicitly disabled for the drivers editor because there is no playhead to drag around. Snapping to Frame/Second intervals takes the scene start as a starting point. That means you can snap to the n-th second of the animation even though it might not start at frame 1. The preview range is NOT taken into account by design since the use case is working on a sub-section of the animation in which case the snap target should not change. Snapping is toggled by pressing CTRL as indicated by the status bar. Snapping to Frames/Seconds is absolute, meaning no matter how far away your cursor it will snap to the closest snap point. All others only snap to things if they are close to the cursor in pixel values. When mixing those two behaviors, it prefers relative snapping. If no point is close enough to snap relative, it will fall back to absolute snapping. Based on the prototype #135913 Part of #135794 Pull Request: https://projects.blender.org/blender/blender/pulls/137278
2025-05-22 10:17:19 +02:00
class NLA_HT_header(Header):
bl_space_type = 'NLA_EDITOR'
def draw(self, context):
layout = self.layout
layout.template_header()
NLA_MT_editor_menus.draw_collapsible(context, layout)
layout.separator_spacer()
dopesheet_filter(layout, context)
2018-06-26 22:56:39 +02:00
layout.popover(
panel="NLA_PT_filters",
2018-06-26 22:56:39 +02:00
text="",
icon='FILTER',
)
row = layout.row(align=True)
tool_settings = context.tool_settings
row.prop(tool_settings, "use_snap_anim", text="")
sub = row.row(align=True)
sub.popover(
panel="NLA_PT_snapping",
text="",
)
class NLA_HT_playback_controls(Header):
bl_space_type = 'NLA_EDITOR'
bl_region_type = 'FOOTER'
def draw(self, context):
layout = self.layout
playback_controls(layout, context)
class NLA_PT_snapping(Panel):
bl_space_type = 'NLA_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Snapping"
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text="Snap To")
tool_settings = context.tool_settings
col.prop(tool_settings, "snap_anim_element", expand=True)
if tool_settings.snap_anim_element != 'MARKER':
col.prop(tool_settings, "use_snap_time_absolute")
class NLA_PT_filters(DopesheetFilterPopoverBase, Panel):
bl_space_type = 'NLA_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Filters"
def draw(self, context):
layout = self.layout
DopesheetFilterPopoverBase.draw_generic_filters(context, layout)
layout.separator()
DopesheetFilterPopoverBase.draw_search_filters(context, layout)
layout.separator()
DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
class NLA_PT_action(DopesheetActionPanelBase, Panel):
bl_space_type = 'NLA_EDITOR'
bl_category = "Strip"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
strip = context.active_nla_strip
return strip and strip.type == 'CLIP' and strip.action
def draw(self, context):
action = context.active_nla_strip.action
self.draw_generic_panel(context, self.layout, action)
class NLA_MT_editor_menus(Menu):
bl_idname = "NLA_MT_editor_menus"
bl_label = ""
def draw(self, context):
st = context.space_data
layout = self.layout
layout.menu("NLA_MT_view")
layout.menu("NLA_MT_select")
if st.show_markers:
layout.menu("NLA_MT_marker")
layout.menu("NLA_MT_add")
layout.menu("NLA_MT_tracks")
layout.menu("NLA_MT_strips")
class NLA_MT_view(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
st = context.space_data
layout.prop(st, "show_region_ui")
layout.prop(st, "show_region_hud")
layout.prop(st, "show_region_channels")
layout.prop(st, "show_region_footer")
layout.separator()
layout.operator("nla.view_selected")
layout.operator("nla.view_all")
if context.scene.use_preview_range:
layout.operator("anim.scene_range_frame", text="Frame Preview Range")
else:
layout.operator("anim.scene_range_frame", text="Frame Scene Range")
layout.operator("nla.view_frame")
layout.separator()
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_strip_curves")
layout.separator()
layout.prop(st, "show_markers")
layout.prop(st, "show_local_markers")
layout.prop(st, "show_seconds")
layout.prop(st, "show_locked_time")
layout.separator()
layout.operator("anim.previewrange_set")
layout.operator("anim.previewrange_clear")
2014-04-28 19:37:29 +12:00
layout.operator("nla.previewrange_set")
2011-07-20 00:36:28 +00:00
layout.separator()
layout.menu("INFO_MT_area")
class NLA_MT_select(Menu):
bl_label = "Select"
def draw(self, _context):
layout = self.layout
layout.operator("nla.select_all", text="All").action = 'SELECT'
layout.operator("nla.select_all", text="None").action = 'DESELECT'
layout.operator("nla.select_all", text="Invert").action = 'INVERT'
layout.separator()
layout.operator("nla.select_box").axis_range = False
layout.operator("nla.select_box", text="Box Select (Axis Range)").axis_range = True
2011-02-14 03:04:59 +00:00
layout.separator()
props = layout.operator("nla.select_leftright", text="Before Current Frame")
props.extend = False
props.mode = 'LEFT'
props = layout.operator("nla.select_leftright", text="After Current Frame")
props.extend = False
props.mode = 'RIGHT'
2011-02-14 03:04:59 +00:00
class NLA_MT_marker(Menu):
bl_label = "Marker"
2011-01-13 23:00:51 +00:00
def draw(self, context):
layout = self.layout
2011-01-13 23:00:51 +00:00
from bl_ui.space_time import marker_menu_generic
marker_menu_generic(layout, context)
2011-01-13 23:00:51 +00:00
class NLA_MT_marker_select(Menu):
bl_label = "Select"
def draw(self, _context):
layout = self.layout
layout.operator("marker.select_all", text="All").action = 'SELECT'
layout.operator("marker.select_all", text="None").action = 'DESELECT'
layout.operator("marker.select_all", text="Invert").action = 'INVERT'
layout.separator()
layout.operator("marker.select_leftright", text="Before Current Frame").mode = 'LEFT'
layout.operator("marker.select_leftright", text="After Current Frame").mode = 'RIGHT'
class NLA_MT_add(Menu):
bl_label = "Add"
bl_translation_context = i18n_contexts.operator_default
def draw(self, _context):
layout = self.layout
layout.operator("nla.actionclip_add", text="Action")
layout.operator("nla.transition_add", text="Transition")
layout.operator("nla.soundclip_add", text="Sound")
layout.separator()
layout.operator("nla.selected_objects_add", text="Selected Objects")
class NLA_MT_tracks(Menu):
bl_label = "Track"
bl_translation_context = i18n_contexts.id_action
def draw(self, _context):
layout = self.layout
layout.operator("nla.tracks_add", text="Add").above_selected = False
layout.operator("nla.tracks_add", text="Add Above Selected").above_selected = True
layout.operator("nla.tracks_delete", text="Delete")
layout.separator()
layout.operator_menu_enum("anim.channels_move", "direction", text="Move")
layout.separator()
layout.operator("anim.channels_clean_empty")
class NLA_MT_strips(Menu):
bl_label = "Strip"
def draw(self, context):
layout = self.layout
scene = context.scene
layout.menu("NLA_MT_strips_transform", text="Transform")
layout.operator_menu_enum("nla.snap", "type", text="Snap")
layout.separator()
layout.operator("nla.split", text="Split")
layout.separator()
layout.operator("nla.duplicate", text="Duplicate").linked = False
layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
layout.operator("nla.delete", text="Delete")
layout.separator()
layout.operator("nla.meta_add", text="Make Meta")
layout.operator("nla.meta_remove", text="Remove Meta")
layout.separator()
layout.operator("nla.mute_toggle")
layout.separator()
layout.operator("nla.bake", text="Bake Action")
layout.separator()
layout.operator("nla.apply_scale")
layout.operator("nla.clear_scale")
layout.operator("nla.action_sync_length").active = False
layout.separator()
layout.operator("nla.make_single_user")
layout.separator()
2010-08-18 08:26:18 +00:00
if scene.is_nla_tweakmode:
layout.operator("nla.tweakmode_exit", text="Stop Editing Stashed Action").isolate_action = True
layout.operator("nla.tweakmode_exit", text="Stop Tweaking Strip Actions")
else:
layout.operator("nla.tweakmode_enter", text="Start Editing Stashed Action").isolate_action = True
layout.operator(
"nla.tweakmode_enter",
text="Start Tweaking Strip Actions (Full Stack)",
).use_upper_stack_evaluation = True
layout.operator(
"nla.tweakmode_enter",
text="Start Tweaking Strip Actions (Lower Stack)",
).use_upper_stack_evaluation = False
class NLA_MT_strips_transform(Menu):
bl_label = "Transform"
def draw(self, _context):
layout = self.layout
layout.operator("transform.translate", text="Move")
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE'
layout.separator()
layout.operator("nla.swap", text="Swap")
layout.separator()
layout.operator("nla.move_up", text="Move Up")
layout.operator("nla.move_down", text="Move Down")
2018-09-27 09:41:18 +10:00
class NLA_MT_snap_pie(Menu):
bl_label = "Snap"
def draw(self, _context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("nla.snap", text="Selection to Current Frame").type = 'CFRA'
pie.operator("nla.snap", text="Selection to Nearest Frame").type = 'NEAREST_FRAME'
pie.operator("nla.snap", text="Selection to Nearest Second").type = 'NEAREST_SECOND'
pie.operator("nla.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
2019-05-22 00:27:01 +10:00
UI: Introduce View pie in more editors #### Motivation The View pie menu is a convenient way to access operators such as `Frame Selected` and `Frame All` which are usually mapped to `PERIOD` or `HOME` keys on the right side of most keyboard, making it hard hard to reach with the left hand. The motivation for this patch comes from working with a 75% keyboard (no numpad). Most laptops face a similar problem. #### Implementation The View pie menu has been added to the following editors and sub-modes where applicable: * Node Editor * Video Sequencer * Dopesheet * Graph * NLA * Image * Clip * Outliner More options could definitely be added to this menu for convenience, as long as it maintains the common options in the same place (Frame Selected on the left, Frame All on the right). For positioning I went with the following layout: {F11791186, size=full} I've added `Zoom 1:1`to the Image Editor and the VSE Preview since there is no way to reset the zoom on keyboards without numpad (unless Emulate Numpad is turned on). The Outliner uses `Show Active` and `Show Hierarchy` which are the closest ones to the equivalent in other editors. Should `Show Active` be renamed to `Frame Selected`? The shortcut assigned is the same as the 3D Viewport (`ACCENT_GRAVE`). #### Screenshots Node Editor {F11778387, size=full} Dopesheet {F11778400, size=full} Graph {F11778403, size=full} Image Editor (Paint and View) {F11791113, size=full} Image Editor (Mask) {F11791114, size=full} UV Editor {F11791119, size=full} Clip Editor (Tracking) {F11791137, size=full} Clip Editor (Mask) {F11791140, size=full} Clip Editor (Graph) {F11791151, size=full} View operators are not yet implemented in Clip Editor Dopesheet mode (left a note about this in the menu poll). Reviewed By: #user_interface, campbellbarton Differential Revision: https://developer.blender.org/D13169
2021-11-10 02:17:24 +01:00
class NLA_MT_view_pie(Menu):
bl_label = "View"
def draw(self, context):
UI: Introduce View pie in more editors #### Motivation The View pie menu is a convenient way to access operators such as `Frame Selected` and `Frame All` which are usually mapped to `PERIOD` or `HOME` keys on the right side of most keyboard, making it hard hard to reach with the left hand. The motivation for this patch comes from working with a 75% keyboard (no numpad). Most laptops face a similar problem. #### Implementation The View pie menu has been added to the following editors and sub-modes where applicable: * Node Editor * Video Sequencer * Dopesheet * Graph * NLA * Image * Clip * Outliner More options could definitely be added to this menu for convenience, as long as it maintains the common options in the same place (Frame Selected on the left, Frame All on the right). For positioning I went with the following layout: {F11791186, size=full} I've added `Zoom 1:1`to the Image Editor and the VSE Preview since there is no way to reset the zoom on keyboards without numpad (unless Emulate Numpad is turned on). The Outliner uses `Show Active` and `Show Hierarchy` which are the closest ones to the equivalent in other editors. Should `Show Active` be renamed to `Frame Selected`? The shortcut assigned is the same as the 3D Viewport (`ACCENT_GRAVE`). #### Screenshots Node Editor {F11778387, size=full} Dopesheet {F11778400, size=full} Graph {F11778403, size=full} Image Editor (Paint and View) {F11791113, size=full} Image Editor (Mask) {F11791114, size=full} UV Editor {F11791119, size=full} Clip Editor (Tracking) {F11791137, size=full} Clip Editor (Mask) {F11791140, size=full} Clip Editor (Graph) {F11791151, size=full} View operators are not yet implemented in Clip Editor Dopesheet mode (left a note about this in the menu poll). Reviewed By: #user_interface, campbellbarton Differential Revision: https://developer.blender.org/D13169
2021-11-10 02:17:24 +01:00
layout = self.layout
pie = layout.menu_pie()
pie.operator("nla.view_all")
pie.operator("nla.view_selected", icon='ZOOM_SELECTED')
pie.operator("nla.view_frame")
if context.scene.use_preview_range:
pie.operator("anim.scene_range_frame", text="Frame Preview Range")
else:
pie.operator("anim.scene_range_frame", text="Frame Scene Range")
UI: Introduce View pie in more editors #### Motivation The View pie menu is a convenient way to access operators such as `Frame Selected` and `Frame All` which are usually mapped to `PERIOD` or `HOME` keys on the right side of most keyboard, making it hard hard to reach with the left hand. The motivation for this patch comes from working with a 75% keyboard (no numpad). Most laptops face a similar problem. #### Implementation The View pie menu has been added to the following editors and sub-modes where applicable: * Node Editor * Video Sequencer * Dopesheet * Graph * NLA * Image * Clip * Outliner More options could definitely be added to this menu for convenience, as long as it maintains the common options in the same place (Frame Selected on the left, Frame All on the right). For positioning I went with the following layout: {F11791186, size=full} I've added `Zoom 1:1`to the Image Editor and the VSE Preview since there is no way to reset the zoom on keyboards without numpad (unless Emulate Numpad is turned on). The Outliner uses `Show Active` and `Show Hierarchy` which are the closest ones to the equivalent in other editors. Should `Show Active` be renamed to `Frame Selected`? The shortcut assigned is the same as the 3D Viewport (`ACCENT_GRAVE`). #### Screenshots Node Editor {F11778387, size=full} Dopesheet {F11778400, size=full} Graph {F11778403, size=full} Image Editor (Paint and View) {F11791113, size=full} Image Editor (Mask) {F11791114, size=full} UV Editor {F11791119, size=full} Clip Editor (Tracking) {F11791137, size=full} Clip Editor (Mask) {F11791140, size=full} Clip Editor (Graph) {F11791151, size=full} View operators are not yet implemented in Clip Editor Dopesheet mode (left a note about this in the menu poll). Reviewed By: #user_interface, campbellbarton Differential Revision: https://developer.blender.org/D13169
2021-11-10 02:17:24 +01:00
class NLA_MT_context_menu(Menu):
bl_label = "NLA"
def draw(self, context):
layout = self.layout
scene = context.scene
if scene.is_nla_tweakmode:
layout.operator("nla.tweakmode_exit", text="Stop Editing Stashed Action").isolate_action = True
layout.operator("nla.tweakmode_exit", text="Stop Tweaking Strip Actions")
else:
layout.operator("nla.tweakmode_enter", text="Start Editing Stashed Action").isolate_action = True
layout.operator(
"nla.tweakmode_enter",
text="Start Tweaking Strip Actions (Full Stack)",
).use_upper_stack_evaluation = True
layout.operator(
"nla.tweakmode_enter",
text="Start Tweaking Strip Actions (Lower Stack)",
).use_upper_stack_evaluation = False
layout.separator()
props = layout.operator("wm.call_panel", text="Rename...")
props.name = "TOPBAR_PT_name"
props.keep_open = False
layout.operator("nla.duplicate_move")
layout.operator("nla.duplicate_linked_move")
layout.separator()
layout.operator("nla.split")
layout.operator("nla.delete")
layout.separator()
layout.operator("nla.meta_add")
layout.operator("nla.meta_remove")
layout.separator()
layout.operator("nla.swap")
layout.separator()
layout.operator_menu_enum("nla.snap", "type", text="Snap")
class NLA_MT_channel_context_menu(Menu):
bl_label = "NLA Tracks"
2019-05-28 16:22:21 +10:00
def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("anim.channels_move", "direction", text="Track Ordering...")
layout.separator()
layout.operator("nla.tracks_add", text="Add Track").above_selected = False
layout.operator("nla.tracks_add", text="Add Track Above Selected").above_selected = True
layout.separator()
layout.operator("nla.tracks_delete")
layout.operator("anim.channels_clean_empty")
classes = (
NLA_HT_header,
NLA_HT_playback_controls,
NLA_MT_editor_menus,
NLA_MT_view,
NLA_MT_select,
NLA_MT_marker,
NLA_MT_marker_select,
NLA_MT_add,
NLA_MT_tracks,
NLA_MT_strips,
NLA_MT_strips_transform,
NLA_MT_snap_pie,
UI: Introduce View pie in more editors #### Motivation The View pie menu is a convenient way to access operators such as `Frame Selected` and `Frame All` which are usually mapped to `PERIOD` or `HOME` keys on the right side of most keyboard, making it hard hard to reach with the left hand. The motivation for this patch comes from working with a 75% keyboard (no numpad). Most laptops face a similar problem. #### Implementation The View pie menu has been added to the following editors and sub-modes where applicable: * Node Editor * Video Sequencer * Dopesheet * Graph * NLA * Image * Clip * Outliner More options could definitely be added to this menu for convenience, as long as it maintains the common options in the same place (Frame Selected on the left, Frame All on the right). For positioning I went with the following layout: {F11791186, size=full} I've added `Zoom 1:1`to the Image Editor and the VSE Preview since there is no way to reset the zoom on keyboards without numpad (unless Emulate Numpad is turned on). The Outliner uses `Show Active` and `Show Hierarchy` which are the closest ones to the equivalent in other editors. Should `Show Active` be renamed to `Frame Selected`? The shortcut assigned is the same as the 3D Viewport (`ACCENT_GRAVE`). #### Screenshots Node Editor {F11778387, size=full} Dopesheet {F11778400, size=full} Graph {F11778403, size=full} Image Editor (Paint and View) {F11791113, size=full} Image Editor (Mask) {F11791114, size=full} UV Editor {F11791119, size=full} Clip Editor (Tracking) {F11791137, size=full} Clip Editor (Mask) {F11791140, size=full} Clip Editor (Graph) {F11791151, size=full} View operators are not yet implemented in Clip Editor Dopesheet mode (left a note about this in the menu poll). Reviewed By: #user_interface, campbellbarton Differential Revision: https://developer.blender.org/D13169
2021-11-10 02:17:24 +01:00
NLA_MT_view_pie,
NLA_MT_context_menu,
NLA_MT_channel_context_menu,
NLA_PT_filters,
NLA_PT_action,
NLA_PT_snapping,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)