2023-08-16 00:20:26 +10:00
|
|
|
# SPDX-FileCopyrightText: 2009-2023 Blender Authors
|
2023-06-15 13:09:04 +10:00
|
|
|
#
|
2022-02-11 09:07:11 +11:00
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
2009-12-07 21:51:44 +00:00
|
|
|
|
|
|
|
|
import bpy
|
2018-09-27 13:27:53 +10:00
|
|
|
from bpy.types import (
|
|
|
|
|
Header,
|
|
|
|
|
Menu,
|
|
|
|
|
Panel,
|
|
|
|
|
)
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2024-04-29 15:14:31 +02:00
|
|
|
from bl_ui.properties_data_grease_pencil import (
|
|
|
|
|
GreasePencil_LayerMaskPanel,
|
|
|
|
|
GreasePencil_LayerTransformPanel,
|
|
|
|
|
GreasPencil_LayerRelationsPanel,
|
|
|
|
|
)
|
|
|
|
|
|
2022-06-23 11:11:53 +02:00
|
|
|
from rna_prop_ui import PropertyPanel
|
|
|
|
|
|
2011-01-10 22:10:28 +00:00
|
|
|
#######################################
|
2018-06-26 21:12:25 +12:00
|
|
|
# DopeSheet Filtering - Header Buttons
|
2011-01-01 07:20:34 +00:00
|
|
|
|
2010-09-13 00:53:47 +00:00
|
|
|
# used for DopeSheet, NLA, and Graph Editors
|
2018-10-01 08:42:58 +10:00
|
|
|
|
|
|
|
|
|
2019-05-07 15:09:14 +02:00
|
|
|
def dopesheet_filter(layout, context):
|
2010-08-27 01:23:53 +00:00
|
|
|
dopesheet = context.space_data.dopesheet
|
|
|
|
|
is_nla = context.area.type == 'NLA_EDITOR'
|
2024-07-04 14:44:19 +02:00
|
|
|
is_action_editor = not is_nla and context.space_data.mode == 'ACTION'
|
2010-08-27 01:23:53 +00:00
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
2024-07-04 14:44:19 +02:00
|
|
|
if is_action_editor and context.preferences.experimental.use_animation_baklava:
|
2024-07-05 16:59:34 +02:00
|
|
|
row.prop(dopesheet, "show_all_slots", text="")
|
2010-08-27 01:23:53 +00:00
|
|
|
row.prop(dopesheet, "show_only_selected", text="")
|
|
|
|
|
row.prop(dopesheet, "show_hidden", text="")
|
2011-02-04 09:27:25 +00:00
|
|
|
|
Animation Editors - Small Visual Tweaks for Usability
== Datablock filters in the headers are now hidden by default ==
This has been done because users were generally not frequently
toggling these, so quick access vs screen-estate cost wasn't really
worth it to have these always showing and taking up space on the
header.
Usage notes:
- To show these again, click on the "Filter more..." toggle.
- The "Filter more..." button DOES NOT affect whether those filters
apply.
Design notes:
- I tried many other button/icon combinations, but those were either
too space-hogging, vague, or had wrong button order.
- I also tried putting a box around these, but there was too much
padding.
- The ordering of the filters has also been modified a bit so that the
group/fcurve-name filters occur earlier in the list, given that
they're used more frequently
== Graph Editor - Use Fancy Drawing ==
Renamed this option to "Use High Quality Drawing" as suggested by
Matt. "Fancy" isn't really descriptive enough.
== Icons for Mode Dropdowns ==
The mode dropdowns in the DopeSheet and Graph Editors now have icons.
- These were important enough (compared to the auto-snap mode) that
some visual decoration was perhaps warranted.
- It makes it easier to see at a glance what mode the view is in
Icon choices:
- In some cases, the icons seem like quite a natural fit IMO (i.e.
outliner<->dopesheet, key<->shapekey editor, grease pencil, fcurve
editor)
- Action Editor uses an "object" icon to indicate that this is object-
level only for now (though I hope to find a way to address this
soon/later). This will be kept like this until then.
- There isn't any icon for drivers, so after trying a few
alternatives, I settled on area-link icon, since it ties together two
entities using some link.
2011-06-29 13:00:19 +00:00
|
|
|
if is_nla:
|
2011-08-22 02:14:39 +00:00
|
|
|
row.prop(dopesheet, "show_missing_nla", text="")
|
2013-03-11 02:19:58 +00:00
|
|
|
else: # graph and dopesheet editors - F-Curves and drivers only
|
2012-10-10 08:46:07 +00:00
|
|
|
row.prop(dopesheet, "show_only_errors", text="")
|
|
|
|
|
|
2018-06-26 21:12:25 +12:00
|
|
|
#######################################
|
2023-09-05 10:49:20 +10:00
|
|
|
# Dope-sheet Filtering Popovers
|
2018-06-26 21:12:25 +12:00
|
|
|
|
|
|
|
|
# Generic Layout - Used as base for filtering popovers used in all animation editors
|
|
|
|
|
# Used for DopeSheet, NLA, and Graph Editors
|
2018-06-26 22:56:39 +02:00
|
|
|
|
|
|
|
|
|
2018-06-26 21:12:25 +12:00
|
|
|
class DopesheetFilterPopoverBase:
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Filters"
|
|
|
|
|
|
2023-09-03 21:35:03 +10:00
|
|
|
# Generic = Affects all data-types.
|
2018-06-26 21:12:25 +12:00
|
|
|
# XXX: Perhaps we want these to stay in the header instead, for easy/fast access
|
|
|
|
|
@classmethod
|
|
|
|
|
def draw_generic_filters(cls, context, layout):
|
|
|
|
|
dopesheet = context.space_data.dopesheet
|
|
|
|
|
is_nla = context.area.type == 'NLA_EDITOR'
|
|
|
|
|
|
|
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(dopesheet, "show_only_selected", icon='NONE')
|
|
|
|
|
col.prop(dopesheet, "show_hidden", icon='NONE')
|
|
|
|
|
|
|
|
|
|
if is_nla:
|
|
|
|
|
col.prop(dopesheet, "show_missing_nla", icon='NONE')
|
2023-09-05 10:49:20 +10:00
|
|
|
else: # Graph and dope-sheet editors - F-Curves and drivers only.
|
2018-06-26 21:12:25 +12:00
|
|
|
col.prop(dopesheet, "show_only_errors", icon='NONE')
|
|
|
|
|
|
|
|
|
|
# Name/Membership Filters
|
|
|
|
|
# XXX: Perhaps these should just stay in the headers (exclusively)?
|
|
|
|
|
@classmethod
|
|
|
|
|
def draw_search_filters(cls, context, layout, generic_filters_only=False):
|
|
|
|
|
dopesheet = context.space_data.dopesheet
|
|
|
|
|
is_nla = context.area.type == 'NLA_EDITOR'
|
|
|
|
|
|
2018-06-26 21:41:08 +12:00
|
|
|
col = layout.column(align=True)
|
2018-06-26 21:12:25 +12:00
|
|
|
if not is_nla:
|
2018-06-26 21:41:08 +12:00
|
|
|
row = col.row(align=True)
|
2018-06-26 21:35:31 +12:00
|
|
|
row.prop(dopesheet, "filter_fcurve_name", text="")
|
2018-06-26 21:12:25 +12:00
|
|
|
else:
|
2018-06-26 21:41:08 +12:00
|
|
|
row = col.row(align=True)
|
2018-06-26 21:35:31 +12:00
|
|
|
row.prop(dopesheet, "filter_text", text="")
|
2018-06-26 21:12:25 +12:00
|
|
|
|
2019-10-30 05:40:36 +11:00
|
|
|
if (not generic_filters_only) and bpy.data.collections:
|
2018-06-26 21:41:08 +12:00
|
|
|
col = layout.column(align=True)
|
|
|
|
|
col.prop(dopesheet, "filter_collection", text="")
|
|
|
|
|
|
2018-06-26 21:12:25 +12:00
|
|
|
# Standard = Present in all panels
|
|
|
|
|
@classmethod
|
|
|
|
|
def draw_standard_filters(cls, context, layout):
|
|
|
|
|
dopesheet = context.space_data.dopesheet
|
|
|
|
|
|
|
|
|
|
# datablock filters
|
2018-10-28 17:51:40 +01:00
|
|
|
layout.label(text="Filter by Type:")
|
2018-07-01 09:23:51 +02:00
|
|
|
flow = layout.grid_flow(row_major=True, columns=2, even_rows=False, align=False)
|
2018-06-26 21:12:25 +12:00
|
|
|
|
|
|
|
|
flow.prop(dopesheet, "show_scenes", text="Scenes")
|
|
|
|
|
flow.prop(dopesheet, "show_nodes", text="Node Trees")
|
|
|
|
|
|
2018-10-28 17:51:40 +01:00
|
|
|
# object types
|
2018-06-26 21:12:25 +12:00
|
|
|
if bpy.data.armatures:
|
|
|
|
|
flow.prop(dopesheet, "show_armatures", text="Armatures")
|
|
|
|
|
if bpy.data.cameras:
|
|
|
|
|
flow.prop(dopesheet, "show_cameras", text="Cameras")
|
2024-07-19 17:33:07 +02:00
|
|
|
if bpy.data.grease_pencils_v3:
|
2018-06-26 21:12:25 +12:00
|
|
|
flow.prop(dopesheet, "show_gpencil", text="Grease Pencil Objects")
|
2018-06-27 14:41:53 +02:00
|
|
|
if bpy.data.lights:
|
|
|
|
|
flow.prop(dopesheet, "show_lights", text="Lights")
|
2018-06-26 21:12:25 +12:00
|
|
|
if bpy.data.meshes:
|
|
|
|
|
flow.prop(dopesheet, "show_meshes", text="Meshes")
|
|
|
|
|
if bpy.data.curves:
|
|
|
|
|
flow.prop(dopesheet, "show_curves", text="Curves")
|
|
|
|
|
if bpy.data.lattices:
|
|
|
|
|
flow.prop(dopesheet, "show_lattices", text="Lattices")
|
2018-10-28 17:51:40 +01:00
|
|
|
if bpy.data.metaballs:
|
|
|
|
|
flow.prop(dopesheet, "show_metaballs", text="Metaballs")
|
Curves: Rename "Hair" types, variables, and functions to "Curves"
Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".
This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.
The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.
Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
since that is also used by the old hair particle system.
Differential Revision: https://developer.blender.org/D14007
2022-02-07 11:55:54 -06:00
|
|
|
if hasattr(bpy.data, "hair_curves") and bpy.data.hair_curves:
|
|
|
|
|
flow.prop(dopesheet, "show_hair_curves", text="Hair Curves")
|
2020-03-17 14:41:48 +01:00
|
|
|
if hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds:
|
|
|
|
|
flow.prop(dopesheet, "show_pointclouds", text="Point Clouds")
|
|
|
|
|
if bpy.data.volumes:
|
|
|
|
|
flow.prop(dopesheet, "show_volumes", text="Volumes")
|
2018-10-28 17:51:40 +01:00
|
|
|
|
|
|
|
|
# data types
|
|
|
|
|
flow.prop(dopesheet, "show_worlds", text="Worlds")
|
|
|
|
|
if bpy.data.particles:
|
|
|
|
|
flow.prop(dopesheet, "show_particles", text="Particles")
|
2018-06-26 21:12:25 +12:00
|
|
|
if bpy.data.linestyles:
|
|
|
|
|
flow.prop(dopesheet, "show_linestyles", text="Line Styles")
|
|
|
|
|
if bpy.data.speakers:
|
|
|
|
|
flow.prop(dopesheet, "show_speakers", text="Speakers")
|
2018-10-28 17:51:40 +01:00
|
|
|
if bpy.data.materials:
|
|
|
|
|
flow.prop(dopesheet, "show_materials", text="Materials")
|
|
|
|
|
if bpy.data.textures:
|
|
|
|
|
flow.prop(dopesheet, "show_textures", text="Textures")
|
|
|
|
|
if bpy.data.shape_keys:
|
|
|
|
|
flow.prop(dopesheet, "show_shapekeys", text="Shape Keys")
|
2019-01-31 15:42:59 +13:00
|
|
|
if bpy.data.cache_files:
|
|
|
|
|
flow.prop(dopesheet, "show_cache_files", text="Cache Files")
|
2019-07-08 17:27:57 +02:00
|
|
|
if bpy.data.movieclips:
|
|
|
|
|
flow.prop(dopesheet, "show_movieclips", text="Movie Clips")
|
2018-06-26 21:12:25 +12:00
|
|
|
|
|
|
|
|
layout.separator()
|
2018-11-04 10:08:55 +11:00
|
|
|
|
2018-10-28 17:51:40 +01:00
|
|
|
# Object Data Filters
|
|
|
|
|
|
|
|
|
|
# TODO: Add per-channel/axis convenience toggles?
|
|
|
|
|
split = layout.split()
|
|
|
|
|
|
|
|
|
|
col = split.column()
|
|
|
|
|
col.prop(dopesheet, "show_transforms", text="Transforms")
|
2018-11-04 10:08:55 +11:00
|
|
|
|
2018-10-28 17:51:40 +01:00
|
|
|
col = split.column()
|
|
|
|
|
col.prop(dopesheet, "show_modifiers", text="Modifiers")
|
2018-11-04 10:08:55 +11:00
|
|
|
|
2018-10-28 17:51:40 +01:00
|
|
|
layout.separator()
|
2018-06-26 21:12:25 +12:00
|
|
|
|
|
|
|
|
# performance-related options (users will mostly have these enabled)
|
|
|
|
|
col = layout.column(align=True)
|
2018-08-28 12:34:51 +10:00
|
|
|
col.label(text="Options:")
|
2018-06-26 21:12:25 +12:00
|
|
|
col.prop(dopesheet, "use_datablock_sort", icon='NONE')
|
|
|
|
|
|
|
|
|
|
|
2023-09-03 21:35:03 +10:00
|
|
|
# Popover for Dope-sheet Editor(s) - Dope-sheet, Action, Shape-key, GPencil, Mask, etc.
|
2018-06-26 21:12:25 +12:00
|
|
|
class DOPESHEET_PT_filters(DopesheetFilterPopoverBase, Panel):
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Filters"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
dopesheet = context.space_data.dopesheet
|
|
|
|
|
ds_mode = context.space_data.mode
|
|
|
|
|
|
|
|
|
|
layout.prop(dopesheet, "show_summary", text="Summary")
|
|
|
|
|
|
|
|
|
|
DopesheetFilterPopoverBase.draw_generic_filters(context, layout)
|
|
|
|
|
|
|
|
|
|
if ds_mode in {'DOPESHEET', 'ACTION', 'GPENCIL'}:
|
|
|
|
|
layout.separator()
|
|
|
|
|
generic_filters_only = ds_mode != 'DOPESHEET'
|
2024-03-15 10:04:03 +11:00
|
|
|
DopesheetFilterPopoverBase.draw_search_filters(context, layout, generic_filters_only=generic_filters_only)
|
2018-06-26 21:12:25 +12:00
|
|
|
|
|
|
|
|
if ds_mode == 'DOPESHEET':
|
|
|
|
|
layout.separator()
|
|
|
|
|
DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2016-08-01 11:54:02 +10:00
|
|
|
|
2011-01-10 22:10:28 +00:00
|
|
|
#######################################
|
|
|
|
|
# DopeSheet Editor - General/Standard UI
|
2010-08-27 01:23:53 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_HT_header(Header):
|
2009-12-08 07:11:43 +00:00
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
st = context.space_data
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2019-04-21 04:49:19 +10:00
|
|
|
layout.template_header()
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2018-04-19 14:41:20 +02:00
|
|
|
if st.mode == 'TIMELINE':
|
2019-06-11 16:08:32 +10:00
|
|
|
from bl_ui.space_time import (
|
2018-09-27 13:27:53 +10:00
|
|
|
TIME_MT_editor_menus,
|
|
|
|
|
TIME_HT_editor_buttons,
|
|
|
|
|
)
|
2018-04-19 14:41:20 +02:00
|
|
|
TIME_MT_editor_menus.draw_collapsible(context, layout)
|
|
|
|
|
TIME_HT_editor_buttons.draw_header(context, layout)
|
|
|
|
|
else:
|
2018-06-20 20:05:19 +02:00
|
|
|
layout.prop(st, "ui_mode", text="")
|
2018-06-28 00:49:04 +02:00
|
|
|
|
2018-04-19 14:41:20 +02:00
|
|
|
DOPESHEET_MT_editor_menus.draw_collapsible(context, layout)
|
|
|
|
|
DOPESHEET_HT_editor_buttons.draw_header(context, layout)
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2018-04-19 14:41:20 +02:00
|
|
|
|
|
|
|
|
# Header for "normal" dopesheet editor modes (e.g. Dope Sheet, Action, Shape Keys, etc.)
|
2020-09-17 14:38:45 +10:00
|
|
|
class DOPESHEET_HT_editor_buttons:
|
2018-04-19 14:41:20 +02:00
|
|
|
|
2024-09-02 14:10:49 +02:00
|
|
|
@classmethod
|
|
|
|
|
def draw_header(cls, context, layout):
|
2018-04-19 14:41:20 +02:00
|
|
|
st = context.space_data
|
2018-12-17 17:26:47 +11:00
|
|
|
tool_settings = context.tool_settings
|
2015-04-03 02:10:20 +13:00
|
|
|
|
|
|
|
|
if st.mode in {'ACTION', 'SHAPEKEY'}:
|
2019-01-30 09:03:37 +11:00
|
|
|
# TODO: These buttons need some tidying up -
|
|
|
|
|
# Probably by using a popover, and bypassing the template_id() here
|
2015-04-03 23:15:56 +13:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.operator("action.layer_prev", text="", icon='TRIA_DOWN')
|
|
|
|
|
row.operator("action.layer_next", text="", icon='TRIA_UP')
|
|
|
|
|
|
2015-04-03 02:10:20 +13:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN')
|
|
|
|
|
row.operator("action.stash", text="Stash", icon='FREEZE')
|
|
|
|
|
|
2024-08-27 15:13:17 +02:00
|
|
|
if context.object:
|
|
|
|
|
layout.separator_spacer()
|
2024-09-02 14:10:49 +02:00
|
|
|
cls._draw_action_selector(context, layout)
|
2024-07-25 17:20:27 +02:00
|
|
|
|
2019-12-04 14:13:21 +01:00
|
|
|
# Layer management
|
|
|
|
|
if st.mode == 'GPENCIL':
|
2020-03-11 16:10:10 +01:00
|
|
|
ob = context.active_object
|
2019-12-04 14:13:21 +01:00
|
|
|
|
2024-06-17 13:50:41 +02:00
|
|
|
enable_but = ob is not None and ob.type == 'GREASEPENCIL'
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.enabled = enable_but
|
|
|
|
|
row.operator("grease_pencil.layer_add", icon='ADD', text="")
|
|
|
|
|
row.operator("grease_pencil.layer_remove", icon='REMOVE', text="")
|
|
|
|
|
row.menu("GREASE_PENCIL_MT_grease_pencil_add_layer_extra", icon='DOWNARROW_HLT', text="")
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.enabled = enable_but
|
|
|
|
|
row.operator("anim.channels_move", icon='TRIA_UP', text="").direction = 'UP'
|
|
|
|
|
row.operator("anim.channels_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.enabled = enable_but
|
|
|
|
|
row.operator("grease_pencil.layer_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
|
|
|
|
|
row.operator("grease_pencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
2019-12-04 14:13:21 +01:00
|
|
|
|
2018-06-28 00:49:04 +02:00
|
|
|
layout.separator_spacer()
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
if st.mode == 'DOPESHEET':
|
2010-08-27 01:23:53 +00:00
|
|
|
dopesheet_filter(layout, context)
|
2011-02-01 22:21:43 +00:00
|
|
|
elif st.mode == 'ACTION':
|
2019-05-07 15:09:14 +02:00
|
|
|
dopesheet_filter(layout, context)
|
2015-12-13 21:03:13 +13:00
|
|
|
elif st.mode == 'GPENCIL':
|
|
|
|
|
row = layout.row(align=True)
|
2020-03-11 16:10:10 +01:00
|
|
|
row.prop(st.dopesheet, "show_only_selected", text="")
|
|
|
|
|
row.prop(st.dopesheet, "show_hidden", text="")
|
2010-08-27 01:23:53 +00:00
|
|
|
|
2018-06-28 00:49:04 +02:00
|
|
|
layout.popover(
|
2018-07-13 19:13:44 +02:00
|
|
|
panel="DOPESHEET_PT_filters",
|
2018-06-28 00:49:04 +02:00
|
|
|
text="",
|
|
|
|
|
icon='FILTER',
|
|
|
|
|
)
|
|
|
|
|
|
2018-07-02 15:53:46 +02:00
|
|
|
# Grease Pencil mode doesn't need snapping, as it's frame-aligned only
|
|
|
|
|
if st.mode != 'GPENCIL':
|
2023-09-05 10:06:55 +02:00
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(tool_settings, "use_snap_anim", text="")
|
|
|
|
|
sub = row.row(align=True)
|
|
|
|
|
sub.popover(
|
|
|
|
|
panel="DOPESHEET_PT_snapping",
|
2023-09-26 20:28:57 +02:00
|
|
|
text="",
|
2023-09-05 10:06:55 +02:00
|
|
|
)
|
2018-07-02 15:53:46 +02:00
|
|
|
|
2015-04-07 16:45:29 +02:00
|
|
|
row = layout.row(align=True)
|
2018-12-17 17:26:47 +11:00
|
|
|
row.prop(tool_settings, "use_proportional_action", text="", icon_only=True)
|
2018-06-11 16:57:35 +02:00
|
|
|
sub = row.row(align=True)
|
2018-12-17 17:26:47 +11:00
|
|
|
sub.active = tool_settings.use_proportional_action
|
2023-05-04 16:39:22 +02:00
|
|
|
sub.prop_with_popover(
|
|
|
|
|
tool_settings,
|
|
|
|
|
"proportional_edit_falloff",
|
|
|
|
|
text="",
|
|
|
|
|
icon_only=True,
|
|
|
|
|
panel="DOPESHEET_PT_proportional_edit",
|
|
|
|
|
)
|
|
|
|
|
|
2024-09-05 12:02:23 +02:00
|
|
|
@classmethod
|
|
|
|
|
def _draw_action_selector(cls, context, layout):
|
|
|
|
|
animated_id = cls._get_animated_id(context)
|
|
|
|
|
if not animated_id:
|
|
|
|
|
return
|
|
|
|
|
|
2024-09-13 15:54:24 +02:00
|
|
|
row = layout.row()
|
|
|
|
|
if animated_id.animation_data and animated_id.animation_data.use_tweak_mode:
|
|
|
|
|
row.enabled = False
|
|
|
|
|
|
|
|
|
|
row.template_action(animated_id, new="action.new", unlink="action.unlink")
|
2024-09-02 14:10:49 +02:00
|
|
|
|
|
|
|
|
if not context.preferences.experimental.use_animation_baklava:
|
|
|
|
|
return
|
|
|
|
|
|
2024-09-05 12:02:23 +02:00
|
|
|
adt = animated_id and animated_id.animation_data
|
2024-09-02 14:10:49 +02:00
|
|
|
if not adt or not adt.action or not adt.action.is_action_layered:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Store the animated ID in the context, so that the new/unlink operators
|
|
|
|
|
# have access to it.
|
2024-09-13 15:54:24 +02:00
|
|
|
row.context_pointer_set("animated_id", animated_id)
|
|
|
|
|
row.template_search(
|
2024-09-02 14:10:49 +02:00
|
|
|
adt, "action_slot",
|
|
|
|
|
adt, "action_slots",
|
|
|
|
|
new="anim.slot_new_for_id",
|
|
|
|
|
unlink="anim.slot_unassign_from_id",
|
|
|
|
|
)
|
|
|
|
|
|
2024-09-05 12:02:23 +02:00
|
|
|
@staticmethod
|
|
|
|
|
def _get_animated_id(context):
|
|
|
|
|
st = context.space_data
|
|
|
|
|
match st.mode:
|
|
|
|
|
case 'ACTION':
|
|
|
|
|
return context.object
|
|
|
|
|
case 'SHAPEKEY':
|
2024-10-01 10:20:14 +10:00
|
|
|
return getattr(context.object.data, "shape_keys", None)
|
2024-09-05 12:02:23 +02:00
|
|
|
case _:
|
2024-10-01 10:13:40 +10:00
|
|
|
print("Dope Sheet mode '{:s}' not expected to have an Action selector".format(st.mode))
|
2024-09-05 12:02:23 +02:00
|
|
|
return context.object
|
|
|
|
|
|
2023-05-04 16:39:22 +02:00
|
|
|
|
2023-09-05 10:06:55 +02:00
|
|
|
class DOPESHEET_PT_snapping(Panel):
|
|
|
|
|
bl_space_type = 'DOPESHEET_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)
|
2023-10-05 13:53:20 +11:00
|
|
|
if tool_settings.snap_anim_element != 'MARKER':
|
2023-09-05 10:06:55 +02:00
|
|
|
col.prop(tool_settings, "use_snap_time_absolute")
|
|
|
|
|
|
|
|
|
|
|
2023-05-04 16:39:22 +02:00
|
|
|
class DOPESHEET_PT_proportional_edit(Panel):
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
|
|
|
|
bl_region_type = 'HEADER'
|
|
|
|
|
bl_label = "Proportional Editing"
|
|
|
|
|
bl_ui_units_x = 8
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
tool_settings = context.tool_settings
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = tool_settings.use_proportional_action
|
|
|
|
|
|
|
|
|
|
col.prop(tool_settings, "proportional_edit_falloff", expand=True)
|
|
|
|
|
col.prop(tool_settings, "proportional_size")
|
2015-04-07 16:45:29 +02:00
|
|
|
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2014-01-27 18:38:53 +11:00
|
|
|
class DOPESHEET_MT_editor_menus(Menu):
|
|
|
|
|
bl_idname = "DOPESHEET_MT_editor_menus"
|
|
|
|
|
bl_label = ""
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
2018-12-20 12:02:21 +11:00
|
|
|
layout = self.layout
|
2014-01-27 18:38:53 +11:00
|
|
|
st = context.space_data
|
|
|
|
|
|
|
|
|
|
layout.menu("DOPESHEET_MT_view")
|
|
|
|
|
layout.menu("DOPESHEET_MT_select")
|
2019-11-30 17:03:22 +11:00
|
|
|
if st.show_markers:
|
|
|
|
|
layout.menu("DOPESHEET_MT_marker")
|
2014-01-27 18:38:53 +11:00
|
|
|
|
|
|
|
|
if st.mode == 'DOPESHEET' or (st.mode == 'ACTION' and st.action is not None):
|
|
|
|
|
layout.menu("DOPESHEET_MT_channel")
|
|
|
|
|
elif st.mode == 'GPENCIL':
|
|
|
|
|
layout.menu("DOPESHEET_MT_gpencil_channel")
|
|
|
|
|
|
2024-10-04 13:05:09 +02:00
|
|
|
layout.menu("DOPESHEET_MT_key")
|
2014-01-27 18:38:53 +11:00
|
|
|
|
2024-09-27 14:34:24 +02:00
|
|
|
if st.mode in {'ACTION', 'SHAPEKEY'} and st.action is not None:
|
|
|
|
|
if context.preferences.experimental.use_animation_baklava:
|
|
|
|
|
layout.menu("DOPESHEET_MT_action")
|
|
|
|
|
|
2014-01-27 18:38:53 +11:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_view(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "View"
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
st = context.space_data
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2019-04-18 12:16:03 +02:00
|
|
|
layout.prop(st, "show_region_ui")
|
2022-09-20 14:36:20 +02:00
|
|
|
layout.prop(st, "show_region_hud")
|
2024-02-05 12:13:31 +01:00
|
|
|
layout.prop(st, "show_region_channels")
|
2024-01-23 12:11:22 +01:00
|
|
|
layout.separator()
|
2019-04-18 12:16:03 +02:00
|
|
|
|
2024-01-23 12:11:22 +01:00
|
|
|
layout.operator("action.view_selected")
|
|
|
|
|
layout.operator("action.view_all")
|
2024-05-30 17:19:10 +02:00
|
|
|
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")
|
2024-01-23 12:11:22 +01:00
|
|
|
layout.operator("action.view_frame")
|
2016-05-08 14:38:30 +12:00
|
|
|
layout.separator()
|
|
|
|
|
|
2020-10-24 11:42:17 -07:00
|
|
|
layout.prop(st.dopesheet, "use_multi_word_filter", text="Multi-Word Match Search")
|
2018-06-28 00:49:04 +02:00
|
|
|
layout.separator()
|
|
|
|
|
|
2010-08-17 07:49:53 +00:00
|
|
|
layout.prop(st, "use_realtime_update")
|
2020-10-07 12:22:22 +02:00
|
|
|
|
|
|
|
|
# Sliders are always shown in the Shape Key Editor regardless of this setting.
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = context.space_data.mode != 'SHAPEKEY'
|
|
|
|
|
col.prop(st, "show_sliders")
|
|
|
|
|
|
Dope Sheet: new option to display keyframe interpolation mode and extremes.
With the new automatic handle algorithm, it is possible to do a lot
of the animation via keyframes without touching the curves. It is
however necessary to change the keyframe interpolation and handle
types in certain cases. Currently the dopesheet/action editor
allows changing the types, but does not show them in any way.
To fix, add a new menu option to display this information. For handle
type, it is represented using the shape of the key icons: diamond for
Free, clipped diamond for Aligned, square for Vector, circle for Auto
Clamp, and cirle with dot for Automatic.
Non-bezier interpolation is a property of intervals between keys,
so it is marked by drawing lines, similar to holds. In this initial
version, only the fact of non-bezier interpolation is displayed,
without distinguishing types. For summaries, the line is drawn at
half alpha if not all curves in the group are non-bezier.
In addition, it is sometimes helpful to know the general direction
of change of the curve, and which keys are extremes. This commit
also adds an option to highlight extremes, based on comparing the
keyed values with adjacent keys. Half-intensity display is used
for overshot bezier extremes, or non-uniform summaries.
Reviewers: brecht, aligorith, billreynish
Differential Revision: https://developer.blender.org/D3788
2018-10-19 18:55:19 +03:00
|
|
|
layout.prop(st, "show_interpolation")
|
|
|
|
|
layout.prop(st, "show_extremes")
|
2010-08-17 07:49:53 +00:00
|
|
|
layout.prop(st, "use_auto_merge_keyframes")
|
2019-11-30 17:03:22 +11:00
|
|
|
layout.separator()
|
|
|
|
|
|
2024-01-23 12:11:22 +01:00
|
|
|
layout.prop(st, "show_markers")
|
2012-01-14 14:17:12 +00:00
|
|
|
layout.prop(st, "show_seconds")
|
2014-05-01 14:49:47 +10:00
|
|
|
layout.prop(st, "show_locked_time")
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2024-01-23 12:11:22 +01:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.operator("anim.previewrange_set")
|
|
|
|
|
layout.operator("anim.previewrange_clear")
|
|
|
|
|
layout.operator("action.previewrange_set")
|
|
|
|
|
layout.separator()
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2018-11-29 19:07:00 +11:00
|
|
|
# Add this to show key-binding (reverse action in dope-sheet).
|
2019-03-04 22:06:23 +11:00
|
|
|
props = layout.operator("wm.context_set_enum", text="Toggle Graph Editor", icon='GRAPH')
|
2018-11-29 19:07:00 +11:00
|
|
|
props.data_path = "area.type"
|
|
|
|
|
props.value = 'GRAPH_EDITOR'
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2024-01-23 12:11:22 +01:00
|
|
|
|
2018-05-24 18:35:19 +02:00
|
|
|
layout.menu("INFO_MT_area")
|
2009-12-07 21:51:44 +00: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 DOPESHEET_MT_view_pie(Menu):
|
|
|
|
|
bl_label = "View"
|
|
|
|
|
|
2024-05-30 17:19:10 +02:00
|
|
|
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("action.view_all")
|
|
|
|
|
pie.operator("action.view_selected", icon='ZOOM_SELECTED')
|
|
|
|
|
pie.operator("action.view_frame")
|
2024-05-30 17:19:10 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_select(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Select"
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2018-07-03 15:44:56 +02:00
|
|
|
layout.operator("action.select_all", text="All").action = 'SELECT'
|
|
|
|
|
layout.operator("action.select_all", text="None").action = 'DESELECT'
|
|
|
|
|
layout.operator("action.select_all", text="Invert").action = 'INVERT'
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2018-10-05 10:27:04 +10:00
|
|
|
layout.operator("action.select_box").axis_range = False
|
2019-08-06 16:10:48 +10:00
|
|
|
layout.operator("action.select_box", text="Box Select (Axis Range)").axis_range = True
|
2016-06-23 23:16:14 +12:00
|
|
|
layout.operator("action.select_circle")
|
2021-09-17 12:09:30 +10:00
|
|
|
layout.operator_menu_enum("action.select_lasso", "mode")
|
2016-06-23 23:16:14 +12:00
|
|
|
|
2024-05-13 16:27:23 +02:00
|
|
|
# FIXME: grease pencil mode isn't supported for these yet, so skip for that mode only
|
|
|
|
|
if context.space_data.mode != 'GPENCIL':
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("action.select_more", text="More")
|
|
|
|
|
layout.operator("action.select_less", text="Less")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("action.select_linked")
|
|
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("action.select_column", text="Columns on Selected Keys").mode = 'KEYS'
|
|
|
|
|
layout.operator("action.select_column", text="Column on Current Frame").mode = 'CFRA'
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("action.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN'
|
|
|
|
|
layout.operator("action.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-02-14 02:30:33 +00:00
|
|
|
layout.separator()
|
2015-01-29 17:34:05 +01:00
|
|
|
props = layout.operator("action.select_leftright", text="Before Current Frame")
|
|
|
|
|
props.extend = False
|
|
|
|
|
props.mode = 'LEFT'
|
|
|
|
|
props = layout.operator("action.select_leftright", text="After Current Frame")
|
|
|
|
|
props.extend = False
|
|
|
|
|
props.mode = 'RIGHT'
|
2010-04-05 11:47:55 +00:00
|
|
|
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_marker(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Marker"
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-01-06 04:47:57 +00:00
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2019-06-11 16:08:32 +10:00
|
|
|
from bl_ui.space_time import marker_menu_generic
|
2019-03-13 11:52:54 +11:00
|
|
|
marker_menu_generic(layout, context)
|
2011-01-06 04:47:57 +00:00
|
|
|
|
2011-11-03 12:47:39 +00:00
|
|
|
st = context.space_data
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-03-07 13:23:45 +00:00
|
|
|
if st.mode in {'ACTION', 'SHAPEKEY'} and st.action:
|
2011-01-09 23:16:05 +00:00
|
|
|
layout.separator()
|
|
|
|
|
layout.prop(st, "show_pose_markers")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2011-02-26 06:28:24 +00:00
|
|
|
if st.show_pose_markers is False:
|
|
|
|
|
layout.operator("action.markers_make_local")
|
|
|
|
|
|
2018-11-05 15:11:18 +01:00
|
|
|
layout.prop(st, "use_marker_sync")
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-01-10 22:10:28 +00:00
|
|
|
#######################################
|
|
|
|
|
# Keyframe Editing
|
|
|
|
|
|
2018-12-20 13:01:40 +11:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_channel(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Channel"
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-12-08 07:11:43 +00:00
|
|
|
layout = self.layout
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2010-02-07 23:39:44 +00:00
|
|
|
layout.operator_context = 'INVOKE_REGION_CHANNELS'
|
|
|
|
|
|
2010-09-13 00:53:47 +00:00
|
|
|
layout.operator("anim.channels_delete")
|
2023-10-06 13:51:04 +02:00
|
|
|
layout.operator("action.clean", text="Clean Channels").channels = True
|
2010-09-13 00:53:47 +00:00
|
|
|
|
2013-02-22 01:49:51 +00:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_group")
|
|
|
|
|
layout.operator("anim.channels_ungroup")
|
|
|
|
|
|
2010-09-13 00:53:47 +00:00
|
|
|
layout.separator()
|
2012-11-20 02:03:20 +00:00
|
|
|
layout.operator_menu_enum("anim.channels_setting_toggle", "type")
|
|
|
|
|
layout.operator_menu_enum("anim.channels_setting_enable", "type")
|
|
|
|
|
layout.operator_menu_enum("anim.channels_setting_disable", "type")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_editable_toggle")
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator_menu_enum("action.extrapolation_type", "type", text="Extrapolation Mode")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_expand")
|
|
|
|
|
layout.operator("anim.channels_collapse")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2010-11-07 12:09:15 +00:00
|
|
|
layout.separator()
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2010-11-11 11:56:50 +00:00
|
|
|
layout.separator()
|
2010-11-11 21:49:40 +00:00
|
|
|
layout.operator("anim.channels_fcurves_enable")
|
2010-11-11 11:56:50 +00:00
|
|
|
|
2024-07-04 17:12:04 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_bake")
|
|
|
|
|
|
2023-02-20 11:51:16 +01:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_view_selected")
|
|
|
|
|
|
2010-11-11 11:56:50 +00:00
|
|
|
|
2024-09-27 14:34:24 +02:00
|
|
|
class DOPESHEET_MT_action(Menu):
|
|
|
|
|
bl_label = "Action"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.operator("anim.merge_animation")
|
2024-09-27 16:39:29 +02:00
|
|
|
layout.operator("anim.separate_slots")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.slot_channels_move_to_new_action")
|
2024-09-27 14:34:24 +02:00
|
|
|
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_key(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Key"
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-12-08 07:11:43 +00:00
|
|
|
layout = self.layout
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.menu("DOPESHEET_MT_key_transform", text="Transform")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator_menu_enum("action.snap", "type", text="Snap")
|
|
|
|
|
layout.operator_menu_enum("action.mirror", "type", text="Mirror")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2009-12-31 23:56:45 +00:00
|
|
|
layout.operator("action.keyframe_insert")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2012-10-15 03:52:27 +00:00
|
|
|
layout.separator()
|
2013-01-15 23:15:32 +00:00
|
|
|
layout.operator("action.frame_jump")
|
|
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2018-10-08 19:10:10 +02:00
|
|
|
layout.operator("action.copy")
|
|
|
|
|
layout.operator("action.paste")
|
|
|
|
|
layout.operator("action.paste", text="Paste Flipped").flipped = True
|
2011-07-13 12:02:39 +00:00
|
|
|
layout.operator("action.duplicate_move")
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.operator("action.delete")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type")
|
|
|
|
|
layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
|
|
|
|
|
layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
|
2020-03-10 14:02:16 +01:00
|
|
|
layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2009-12-08 07:11:43 +00:00
|
|
|
layout.separator()
|
2015-10-13 12:58:04 +02:00
|
|
|
layout.operator("action.clean").channels = False
|
2023-09-12 09:42:01 +02:00
|
|
|
layout.operator("action.bake_keys")
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2022-04-29 14:53:14 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("graph.euler_filter", text="Discontinuity (Euler) Filter")
|
|
|
|
|
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_key_transform(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Transform"
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2009-12-08 07:11:43 +00:00
|
|
|
layout = self.layout
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2018-09-06 12:13:01 +02:00
|
|
|
layout.operator("transform.transform", text="Move").mode = 'TIME_TRANSLATE'
|
2011-09-21 15:18:38 +00:00
|
|
|
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
|
|
|
|
|
layout.operator("transform.transform", text="Slide").mode = 'TIME_SLIDE'
|
|
|
|
|
layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE'
|
2009-12-07 21:51:44 +00:00
|
|
|
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2021-05-03 00:03:00 +03:00
|
|
|
class DopesheetActionPanelBase:
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_label = "Action"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
2022-01-07 14:39:01 +11:00
|
|
|
def draw_generic_panel(cls, _context, layout, action):
|
2024-07-01 22:35:58 +02:00
|
|
|
layout.label(text=action.name, icon='ACTION', translate=False)
|
2021-05-03 00:03:00 +03:00
|
|
|
|
|
|
|
|
layout.prop(action, "use_frame_range")
|
|
|
|
|
|
|
|
|
|
col = layout.column()
|
|
|
|
|
col.active = action.use_frame_range
|
|
|
|
|
|
|
|
|
|
row = col.row(align=True)
|
|
|
|
|
row.prop(action, "frame_start", text="Start")
|
|
|
|
|
row.prop(action, "frame_end", text="End")
|
|
|
|
|
|
2021-07-27 10:39:52 +03:00
|
|
|
col.prop(action, "use_cyclic")
|
|
|
|
|
|
2021-05-03 00:03:00 +03:00
|
|
|
|
2022-06-23 11:11:53 +02:00
|
|
|
class DOPESHEET_PT_custom_props_action(PropertyPanel, Panel):
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
2022-06-24 17:08:54 +03:00
|
|
|
bl_category = "Action"
|
2022-06-23 11:11:53 +02:00
|
|
|
bl_region_type = 'UI'
|
2023-01-06 13:52:57 +11:00
|
|
|
bl_context = "data"
|
2022-06-24 17:08:54 +03:00
|
|
|
_context_path = "active_action"
|
2022-06-23 11:11:53 +02:00
|
|
|
_property_type = bpy.types.Action
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2022-06-24 17:08:54 +03:00
|
|
|
return bool(context.active_action)
|
2022-06-23 11:11:53 +02:00
|
|
|
|
|
|
|
|
|
2021-05-03 00:03:00 +03:00
|
|
|
class DOPESHEET_PT_action(DopesheetActionPanelBase, Panel):
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
2022-06-24 17:08:54 +03:00
|
|
|
bl_category = "Action"
|
2021-05-03 00:03:00 +03:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2022-07-10 12:28:44 +03:00
|
|
|
return bool(context.active_action)
|
2021-05-03 00:03:00 +03:00
|
|
|
|
|
|
|
|
def draw(self, context):
|
2022-07-10 12:28:44 +03:00
|
|
|
action = context.active_action
|
2021-05-03 00:03:00 +03:00
|
|
|
self.draw_generic_panel(context, self.layout, action)
|
|
|
|
|
|
|
|
|
|
|
2024-07-12 11:59:04 +02:00
|
|
|
class DOPESHEET_PT_action_slot(Panel):
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "Action"
|
|
|
|
|
bl_label = "Slot"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
2024-07-25 11:41:37 +02:00
|
|
|
if not context.preferences.experimental.use_animation_baklava:
|
|
|
|
|
return False
|
2024-07-12 11:59:04 +02:00
|
|
|
action = context.active_action
|
|
|
|
|
return bool(action and action.slots.active)
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False
|
|
|
|
|
|
|
|
|
|
action = context.active_action
|
|
|
|
|
slot = action.slots.active
|
|
|
|
|
|
2024-09-26 15:33:44 +02:00
|
|
|
layout.prop(slot, "name_display", text="Name")
|
|
|
|
|
|
|
|
|
|
# Draw the ID type of the slot.
|
|
|
|
|
try:
|
|
|
|
|
enum_items = slot.bl_rna.properties['id_root'].enum_items
|
|
|
|
|
idtype_label = enum_items[slot.id_root].name
|
|
|
|
|
except (KeyError, IndexError, AttributeError) as ex:
|
|
|
|
|
idtype_label = str(ex)
|
|
|
|
|
|
|
|
|
|
split = layout.split(factor=0.4)
|
|
|
|
|
split.alignment = 'RIGHT'
|
|
|
|
|
split.label(text="Type")
|
|
|
|
|
split.alignment = 'LEFT'
|
|
|
|
|
|
|
|
|
|
split.label(text=idtype_label, icon_value=slot.id_root_icon)
|
2024-07-12 11:59:04 +02:00
|
|
|
|
|
|
|
|
|
2011-01-10 22:10:28 +00:00
|
|
|
#######################################
|
|
|
|
|
# Grease Pencil Editing
|
|
|
|
|
|
2011-08-12 06:57:00 +00:00
|
|
|
class DOPESHEET_MT_gpencil_channel(Menu):
|
2011-09-15 13:20:18 +00:00
|
|
|
bl_label = "Channel"
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2011-01-10 22:10:28 +00:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator_context = 'INVOKE_REGION_CHANNELS'
|
|
|
|
|
|
|
|
|
|
layout.operator("anim.channels_delete")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_setting_toggle")
|
|
|
|
|
layout.operator("anim.channels_setting_enable")
|
|
|
|
|
layout.operator("anim.channels_setting_disable")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_editable_toggle")
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2011-01-10 22:10:28 +00:00
|
|
|
# XXX: to be enabled when these are ready for use!
|
2018-06-05 16:32:11 +02:00
|
|
|
# layout.separator()
|
|
|
|
|
# layout.operator("anim.channels_expand")
|
|
|
|
|
# layout.operator("anim.channels_collapse")
|
2011-01-10 22:10:28 +00:00
|
|
|
|
2020-01-04 22:02:03 +01:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
|
2011-01-10 22:10:28 +00:00
|
|
|
|
2023-02-20 11:51:16 +01:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_view_selected")
|
|
|
|
|
|
2011-01-13 23:00:51 +00:00
|
|
|
|
2015-04-10 11:52:54 +02:00
|
|
|
class DOPESHEET_MT_delete(Menu):
|
|
|
|
|
bl_label = "Delete"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2015-04-10 11:52:54 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
|
|
|
|
layout.operator("action.delete")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2015-10-13 13:58:43 +02:00
|
|
|
layout.operator("action.clean").channels = False
|
2015-05-20 15:30:33 +02:00
|
|
|
layout.operator("action.clean", text="Clean Channels").channels = True
|
|
|
|
|
|
2015-04-10 11:52:54 +02:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class DOPESHEET_MT_context_menu(Menu):
|
2023-09-25 16:25:55 +02:00
|
|
|
bl_label = "Dope Sheet"
|
2018-06-05 09:12:19 +02:00
|
|
|
|
2021-06-15 10:49:46 +10:00
|
|
|
def draw(self, context):
|
2018-06-05 09:12:19 +02:00
|
|
|
layout = self.layout
|
2021-06-15 10:49:46 +10:00
|
|
|
st = context.space_data
|
2018-06-05 09:12:19 +02:00
|
|
|
|
2019-05-24 12:01:15 +02:00
|
|
|
layout.operator_context = 'INVOKE_DEFAULT'
|
|
|
|
|
|
2019-05-07 20:52:41 +02:00
|
|
|
layout.operator("action.copy", text="Copy", icon='COPYDOWN')
|
|
|
|
|
layout.operator("action.paste", text="Paste", icon='PASTEDOWN')
|
|
|
|
|
layout.operator("action.paste", text="Paste Flipped", icon='PASTEFLIPDOWN').flipped = True
|
2018-06-05 09:12:19 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-06-17 18:54:08 +02:00
|
|
|
layout.operator_menu_enum("action.keyframe_type", "type", text="Keyframe Type")
|
2021-03-22 14:22:37 +11:00
|
|
|
|
2021-03-16 17:26:20 +01:00
|
|
|
if st.mode != 'GPENCIL':
|
2021-07-06 12:05:27 +10:00
|
|
|
layout.operator_menu_enum("action.handle_type", "type", text="Handle Type")
|
|
|
|
|
layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode")
|
|
|
|
|
layout.operator_menu_enum("action.easing_type", "type", text="Easing Mode")
|
2018-06-05 09:12:19 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("action.keyframe_insert").type = 'SEL'
|
|
|
|
|
layout.operator("action.duplicate_move")
|
2021-03-16 17:26:20 +01:00
|
|
|
|
|
|
|
|
if st.mode == 'GPENCIL':
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
2019-05-24 12:01:15 +02:00
|
|
|
layout.operator_context = 'EXEC_REGION_WIN'
|
2018-06-05 09:12:19 +02:00
|
|
|
layout.operator("action.delete")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator_menu_enum("action.mirror", "type", text="Mirror")
|
|
|
|
|
layout.operator_menu_enum("action.snap", "type", text="Snap")
|
|
|
|
|
|
2018-06-05 16:35:20 +02:00
|
|
|
|
2019-03-12 10:59:57 +11:00
|
|
|
class DOPESHEET_MT_channel_context_menu(Menu):
|
2023-12-14 09:09:30 +01:00
|
|
|
bl_label = "Channel"
|
2018-06-05 09:12:19 +02:00
|
|
|
|
2020-03-10 14:18:19 +01:00
|
|
|
def draw(self, context):
|
2018-06-05 09:12:19 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
|
2021-03-22 20:12:08 +11:00
|
|
|
# This menu is used from the graph editor too.
|
|
|
|
|
is_graph_editor = context.area.type == 'GRAPH_EDITOR'
|
|
|
|
|
|
2023-08-23 09:40:27 +02:00
|
|
|
layout.operator_context = 'INVOKE_REGION_CHANNELS'
|
|
|
|
|
|
2023-02-20 11:51:16 +01:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_view_selected")
|
|
|
|
|
|
2018-06-05 16:35:20 +02:00
|
|
|
layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE'
|
|
|
|
|
layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE'
|
2018-06-05 09:12:19 +02:00
|
|
|
layout.separator()
|
2018-06-05 16:35:20 +02:00
|
|
|
layout.operator("anim.channels_setting_enable", text="Protect Channels").type = 'PROTECT'
|
|
|
|
|
layout.operator("anim.channels_setting_disable", text="Unprotect Channels").type = 'PROTECT'
|
2018-06-05 09:12:19 +02:00
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_group")
|
|
|
|
|
layout.operator("anim.channels_ungroup")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_editable_toggle")
|
2020-03-10 14:18:19 +01:00
|
|
|
|
2021-03-22 20:12:08 +11:00
|
|
|
if is_graph_editor:
|
2020-03-10 14:18:19 +01:00
|
|
|
operator = "graph.extrapolation_type"
|
|
|
|
|
else:
|
|
|
|
|
operator = "action.extrapolation_type"
|
|
|
|
|
layout.operator_menu_enum(operator, "type", text="Extrapolation Mode")
|
2018-06-05 09:12:19 +02:00
|
|
|
|
2023-02-03 13:06:15 +01:00
|
|
|
if is_graph_editor:
|
|
|
|
|
layout.operator_menu_enum("graph.fmodifier_add", "type", text="Add F-Curve Modifier").only_active = False
|
2023-09-27 09:29:44 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("graph.hide", text="Hide Selected Curves").unselected = False
|
|
|
|
|
layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True
|
|
|
|
|
layout.operator("graph.reveal")
|
2023-02-03 13:06:15 +01:00
|
|
|
|
2018-06-05 09:12:19 +02:00
|
|
|
layout.separator()
|
|
|
|
|
layout.operator("anim.channels_expand")
|
|
|
|
|
layout.operator("anim.channels_collapse")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
|
|
|
|
|
|
|
|
|
|
layout.separator()
|
|
|
|
|
|
|
|
|
|
layout.operator("anim.channels_delete")
|
|
|
|
|
|
2023-09-27 09:29:44 +02:00
|
|
|
if is_graph_editor and context.space_data.mode == 'DRIVERS':
|
|
|
|
|
layout.operator("graph.driver_delete_invalid")
|
|
|
|
|
|
2018-06-05 09:12:19 +02:00
|
|
|
|
2018-09-26 17:32:11 +02:00
|
|
|
class DOPESHEET_MT_snap_pie(Menu):
|
|
|
|
|
bl_label = "Snap"
|
|
|
|
|
|
2019-04-19 07:32:24 +02:00
|
|
|
def draw(self, _context):
|
2018-09-26 17:32:11 +02:00
|
|
|
layout = self.layout
|
|
|
|
|
pie = layout.menu_pie()
|
|
|
|
|
|
2020-10-28 14:06:26 -04:00
|
|
|
pie.operator("action.snap", text="Selection to Current Frame").type = 'CFRA'
|
|
|
|
|
pie.operator("action.snap", text="Selection to Nearest Frame").type = 'NEAREST_FRAME'
|
|
|
|
|
pie.operator("action.snap", text="Selection to Nearest Second").type = 'NEAREST_SECOND'
|
|
|
|
|
pie.operator("action.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
|
2018-09-26 17:32:11 +02:00
|
|
|
|
2019-12-16 14:29:03 +11:00
|
|
|
|
2019-12-04 14:13:21 +01:00
|
|
|
class LayersDopeSheetPanel:
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "View"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
st = context.space_data
|
|
|
|
|
ob = context.object
|
|
|
|
|
if st.mode != 'GPENCIL' or ob is None or ob.type != 'GPENCIL':
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
gpd = ob.data
|
|
|
|
|
gpl = gpd.layers.active
|
|
|
|
|
if gpl:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2024-04-29 15:14:31 +02:00
|
|
|
class GreasePencilLayersDopeSheetPanel:
|
|
|
|
|
bl_space_type = 'DOPESHEET_EDITOR'
|
|
|
|
|
bl_region_type = 'UI'
|
|
|
|
|
bl_category = "View"
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def poll(cls, context):
|
|
|
|
|
st = context.space_data
|
|
|
|
|
ob = context.object
|
|
|
|
|
if st.mode != 'GPENCIL' or ob is None or ob.type != 'GREASEPENCIL':
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
grease_pencil = ob.data
|
2024-07-23 11:47:56 +02:00
|
|
|
active_layer = grease_pencil.layers.active
|
2024-04-29 15:14:31 +02:00
|
|
|
if active_layer:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DOPESHEET_PT_grease_pencil_mode(GreasePencilLayersDopeSheetPanel, Panel):
|
|
|
|
|
bl_label = "Layer"
|
|
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
|
layout = self.layout
|
|
|
|
|
layout.use_property_split = True
|
|
|
|
|
layout.use_property_decorate = False
|
|
|
|
|
|
|
|
|
|
ob = context.object
|
|
|
|
|
grease_pencil = ob.data
|
2024-07-23 11:47:56 +02:00
|
|
|
active_layer = grease_pencil.layers.active
|
2024-04-29 15:14:31 +02:00
|
|
|
|
|
|
|
|
if active_layer:
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(active_layer, "blend_mode", text="Blend")
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(active_layer, "opacity", text="Opacity", slider=True)
|
|
|
|
|
|
|
|
|
|
row = layout.row(align=True)
|
|
|
|
|
row.prop(active_layer, "use_lights", text="Lights")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DOPESHEET_PT_grease_pencil_layer_masks(GreasePencilLayersDopeSheetPanel, GreasePencil_LayerMaskPanel, Panel):
|
|
|
|
|
bl_label = "Masks"
|
|
|
|
|
bl_parent_id = "DOPESHEET_PT_grease_pencil_mode"
|
|
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DOPESHEET_PT_grease_pencil_layer_transform(
|
|
|
|
|
GreasePencilLayersDopeSheetPanel,
|
|
|
|
|
GreasePencil_LayerTransformPanel,
|
|
|
|
|
Panel):
|
|
|
|
|
bl_label = "Transform"
|
|
|
|
|
bl_parent_id = "DOPESHEET_PT_grease_pencil_mode"
|
|
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DOPESHEET_PT_grease_pencil_layer_relations(
|
|
|
|
|
GreasePencilLayersDopeSheetPanel,
|
|
|
|
|
GreasPencil_LayerRelationsPanel,
|
|
|
|
|
Panel):
|
|
|
|
|
bl_label = "Relations"
|
|
|
|
|
bl_parent_id = "DOPESHEET_PT_grease_pencil_mode"
|
|
|
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
|
|
|
|
|
|
|
|
|
2017-03-18 20:03:24 +11:00
|
|
|
classes = (
|
|
|
|
|
DOPESHEET_HT_header,
|
2023-05-04 16:39:22 +02:00
|
|
|
DOPESHEET_PT_proportional_edit,
|
2017-03-18 20:03:24 +11:00
|
|
|
DOPESHEET_MT_editor_menus,
|
2017-03-20 02:34:32 +11:00
|
|
|
DOPESHEET_MT_view,
|
|
|
|
|
DOPESHEET_MT_select,
|
|
|
|
|
DOPESHEET_MT_marker,
|
|
|
|
|
DOPESHEET_MT_channel,
|
2024-09-27 14:34:24 +02:00
|
|
|
DOPESHEET_MT_action,
|
2017-03-18 20:03:24 +11:00
|
|
|
DOPESHEET_MT_key,
|
|
|
|
|
DOPESHEET_MT_key_transform,
|
2017-03-20 02:34:32 +11:00
|
|
|
DOPESHEET_MT_gpencil_channel,
|
|
|
|
|
DOPESHEET_MT_delete,
|
2019-03-12 10:59:57 +11:00
|
|
|
DOPESHEET_MT_context_menu,
|
|
|
|
|
DOPESHEET_MT_channel_context_menu,
|
2018-09-26 17:32:11 +02:00
|
|
|
DOPESHEET_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
|
|
|
DOPESHEET_MT_view_pie,
|
2018-06-26 21:12:25 +12:00
|
|
|
DOPESHEET_PT_filters,
|
2021-05-03 00:03:00 +03:00
|
|
|
DOPESHEET_PT_action,
|
2024-07-12 11:59:04 +02:00
|
|
|
DOPESHEET_PT_action_slot,
|
2022-06-23 11:11:53 +02:00
|
|
|
DOPESHEET_PT_custom_props_action,
|
2024-04-29 15:14:31 +02:00
|
|
|
DOPESHEET_PT_snapping,
|
|
|
|
|
DOPESHEET_PT_grease_pencil_mode,
|
|
|
|
|
DOPESHEET_PT_grease_pencil_layer_masks,
|
|
|
|
|
DOPESHEET_PT_grease_pencil_layer_transform,
|
|
|
|
|
DOPESHEET_PT_grease_pencil_layer_relations,
|
2017-03-18 20:03:24 +11:00
|
|
|
)
|
|
|
|
|
|
2011-04-04 10:13:04 +00:00
|
|
|
if __name__ == "__main__": # only for live edit.
|
2017-03-18 20:03:24 +11:00
|
|
|
from bpy.utils import register_class
|
|
|
|
|
for cls in classes:
|
|
|
|
|
register_class(cls)
|