From 2ae953d7f5f80d091b1b96aed4f9ddbe9a185aa5 Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 2 Oct 2025 09:44:53 +0200 Subject: [PATCH] UI: remove the Timeline This adds versioning code that replaces any timeline with a dopesheet where the footer is shown, AND it removes the timeline from the menu options. If the area is too small to show both, the footer and the header then only the footer is shown. This assumes that users created the small timeline just for the playback controls Any uses of `SACTCONT_TIMELINE` (except for versioning) have been removed. part of #145577 Pull Request: https://projects.blender.org/blender/blender/pulls/147058 --- scripts/startup/bl_ui/space_dopesheet.py | 12 +-- scripts/startup/bl_ui/space_time.py | 68 ------------- .../blender/blenkernel/BKE_blender_version.h | 2 +- .../blenloader/intern/versioning_500.cc | 29 ++++++ .../blender/editors/animation/anim_filter.cc | 27 +----- .../interface_template_search_menu.cc | 5 +- source/blender/editors/screen/screen_ops.cc | 8 +- .../editors/space_action/action_draw.cc | 4 - .../editors/space_action/space_action.cc | 95 ++----------------- source/blender/makesrna/RNA_enum_items.hh | 1 - source/blender/makesrna/intern/rna_action.cc | 1 - source/blender/makesrna/intern/rna_space.cc | 32 +------ 12 files changed, 48 insertions(+), 236 deletions(-) diff --git a/scripts/startup/bl_ui/space_dopesheet.py b/scripts/startup/bl_ui/space_dopesheet.py index d852ba8e13f..5fcb64b08f8 100644 --- a/scripts/startup/bl_ui/space_dopesheet.py +++ b/scripts/startup/bl_ui/space_dopesheet.py @@ -205,16 +205,10 @@ class DOPESHEET_HT_header(Header): st = context.space_data layout.template_header() + layout.prop(st, "ui_mode", text="") - if st.mode == 'TIMELINE': - from bl_ui.space_time import TIME_MT_editor_menus - TIME_MT_editor_menus.draw_collapsible(context, layout) - playback_controls(layout, context) - else: - layout.prop(st, "ui_mode", text="") - - DOPESHEET_MT_editor_menus.draw_collapsible(context, layout) - DOPESHEET_HT_editor_buttons.draw_header(context, layout) + DOPESHEET_MT_editor_menus.draw_collapsible(context, layout) + DOPESHEET_HT_editor_buttons.draw_header(context, layout) # Header for "normal" dopesheet editor modes (e.g. Dope Sheet, Action, Shape Keys, etc.) diff --git a/scripts/startup/bl_ui/space_time.py b/scripts/startup/bl_ui/space_time.py index 9f4b0f66ea0..bb055ac1f53 100644 --- a/scripts/startup/bl_ui/space_time.py +++ b/scripts/startup/bl_ui/space_time.py @@ -126,71 +126,6 @@ def playback_controls(layout, context): sub.prop(scene, "frame_preview_end", text="End") -class TIME_MT_editor_menus(Menu): - bl_idname = "TIME_MT_editor_menus" - bl_label = "" - - def draw(self, context): - layout = self.layout - horizontal = (layout.direction == 'VERTICAL') - st = context.space_data - if horizontal: - row = layout.row() - sub = row.row(align=True) - else: - sub = layout - - sub.menu("TIME_MT_view") - if st.show_markers: - sub.menu("TIME_MT_marker") - - -class TIME_MT_marker(Menu): - bl_label = "Marker" - - def draw(self, context): - layout = self.layout - - marker_menu_generic(layout, context) - - -class TIME_MT_view(Menu): - bl_label = "View" - - def draw(self, context): - layout = self.layout - - scene = context.scene - st = context.space_data - - layout.prop(st, "show_region_hud") - layout.prop(st, "show_region_channels") - layout.separator() - - # NOTE: "action" now, since timeline is in the dopesheet editor, instead of as own editor - layout.operator("action.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("action.view_frame") - layout.separator() - - layout.prop(st, "show_markers") - layout.prop(st, "show_seconds") - layout.prop(st, "show_locked_time") - layout.separator() - - layout.prop(scene, "show_keys_from_selected_only") - layout.prop(st.dopesheet, "show_only_errors") - layout.separator() - - layout.menu("DOPESHEET_MT_cache") - layout.separator() - - layout.menu("INFO_MT_area") - - def marker_menu_generic(layout, context): # layout.operator_context = 'EXEC_REGION_WIN' @@ -357,9 +292,6 @@ class TIME_PT_auto_keyframing(TimelinePanelButtons, Panel): ################################### classes = ( - TIME_MT_editor_menus, - TIME_MT_marker, - TIME_MT_view, TIME_PT_playback, TIME_PT_keyframing_settings, TIME_PT_auto_keyframing, diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 7b810a88d15..427e9178fd4 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 99 +#define BLENDER_FILE_SUBVERSION 100 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index 41c9bbc0e73..f2238ff0804 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -3778,6 +3778,35 @@ void blo_do_versions_500(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 100)) { + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (!ELEM(sl->spacetype, SPACE_ACTION)) { + continue; + } + SpaceAction *saction = reinterpret_cast(sl); + if (saction->mode != SACTCONT_TIMELINE) { + continue; + } + /* Switching to dopesheet since that is the closest to the timeline view. */ + saction->mode = SACTCONT_DOPESHEET; + /* The multiplication by 2 assumes that the time control footer has the same size as the + * header. The header is only shown if there is enough space for both. */ + const bool show_header = area->winy > (HEADERY * UI_SCALE_FAC) * 2; + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (!show_header && region->regiontype == RGN_TYPE_HEADER) { + region->flag |= RGN_FLAG_HIDDEN; + } + if (region->regiontype == RGN_TYPE_FOOTER) { + region->flag &= ~RGN_FLAG_HIDDEN; + } + } + } + } + } + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/editors/animation/anim_filter.cc b/source/blender/editors/animation/anim_filter.cc index 17436d39f00..a33b1127c13 100644 --- a/source/blender/editors/animation/anim_filter.cc +++ b/source/blender/editors/animation/anim_filter.cc @@ -140,11 +140,13 @@ bAction *ANIM_active_action_from_area(Scene *scene, case SACTCONT_DOPESHEET: case SACTCONT_MASK: case SACTCONT_CACHEFILE: - case SACTCONT_TIMELINE: if (r_action_user) { *r_action_user = nullptr; } return nullptr; + case SACTCONT_TIMELINE: + BLI_assert_unreachable(); + break; } BLI_assert_unreachable(); @@ -247,29 +249,6 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->data = &saction->ads; return true; - case SACTCONT_TIMELINE: /* Timeline */ - /* update scene-pointer (no need to check for pinning yet, as not implemented) */ - saction->ads.source = reinterpret_cast(ac->scene); - - /* sync scene's "selected keys only" flag with our "only selected" flag - * - * XXX: This is a workaround for #55525. We shouldn't really be syncing the flags like this, - * but it's a simpler fix for now than also figuring out how the next/prev keyframe - * tools should work in the 3D View if we allowed full access to the timeline's - * dopesheet filters (i.e. we'd have to figure out where to host those settings, - * to be on a scene level like this flag currently is, along with several other unknowns). - */ - if (ac->scene->flag & SCE_KEYS_NO_SELONLY) { - saction->ads.filterflag &= ~ADS_FILTER_ONLYSEL; - } - else { - saction->ads.filterflag |= ADS_FILTER_ONLYSEL; - } - - ac->datatype = ANIMCONT_TIMELINE; - ac->data = &saction->ads; - return true; - default: /* unhandled yet */ ac->datatype = ANIMCONT_NONE; ac->data = nullptr; diff --git a/source/blender/editors/interface/templates/interface_template_search_menu.cc b/source/blender/editors/interface/templates/interface_template_search_menu.cc index 7639643aee8..03ad498fe9b 100644 --- a/source/blender/editors/interface/templates/interface_template_search_menu.cc +++ b/source/blender/editors/interface/templates/interface_template_search_menu.cc @@ -624,10 +624,7 @@ static MenuSearch_Data *menu_items_from_ui_create(bContext *C, SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_ACTION, - (((const SpaceAction *)sl)->mode == SACTCONT_TIMELINE) ? - "TIME_MT_editor_menus" : - "DOPESHEET_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_ACTION, "DOPESHEET_MT_editor_menus"); SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); diff --git a/source/blender/editors/screen/screen_ops.cc b/source/blender/editors/screen/screen_ops.cc index 73f07eb99c3..49609e61c25 100644 --- a/source/blender/editors/screen/screen_ops.cc +++ b/source/blender/editors/screen/screen_ops.cc @@ -5584,12 +5584,8 @@ static bool match_region_with_redraws(const ScrArea *area, } } else if (regiontype == RGN_TYPE_HEADER) { - if (spacetype == SPACE_ACTION) { - /* The timeline shows the current frame in the header. Other headers - * don't need to be updated. */ - SpaceAction *saction = (SpaceAction *)area->spacedata.first; - return saction->mode == SACTCONT_TIMELINE; - } + /* Since the timeline does not exist anymore, this doesn't need updating. */ + return false; } else if (regiontype == RGN_TYPE_FOOTER) { /* The footer region in animation editors shows the current frame. */ diff --git a/source/blender/editors/space_action/action_draw.cc b/source/blender/editors/space_action/action_draw.cc index 6810beca53a..14fbaac7d8b 100644 --- a/source/blender/editors/space_action/action_draw.cc +++ b/source/blender/editors/space_action/action_draw.cc @@ -319,10 +319,6 @@ static void draw_keyframes(bAnimContext *ac, int action_flag = saction->flag; bDopeSheet *ads = &saction->ads; - if (saction->mode == SACTCONT_TIMELINE) { - action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES); - } - const float channel_step = ANIM_UI_get_channel_step(); float ymax = ANIM_UI_get_first_channel_top(v2d); diff --git a/source/blender/editors/space_action/space_action.cc b/source/blender/editors/space_action/space_action.cc index 7886aa2c3e8..05339c72b28 100644 --- a/source/blender/editors/space_action/space_action.cc +++ b/source/blender/editors/space_action/space_action.cc @@ -564,7 +564,7 @@ static void action_listener(const wmSpaceTypeListenerParams *params) switch (wmn->category) { case NC_GPENCIL: /* only handle these events for containers in which GPencil frames are displayed */ - if (ELEM(saction->mode, SACTCONT_GPENCIL, SACTCONT_DOPESHEET, SACTCONT_TIMELINE)) { + if (ELEM(saction->mode, SACTCONT_GPENCIL, SACTCONT_DOPESHEET)) { if (wmn->action == NA_EDITED) { ED_area_tag_redraw(area); } @@ -626,10 +626,8 @@ static void action_listener(const wmSpaceTypeListenerParams *params) } break; default: - if (saction->mode != SACTCONT_TIMELINE) { - /* Just redrawing the view will do. */ - ED_area_tag_redraw(area); - } + /* Just redrawing the view will do. */ + ED_area_tag_redraw(area); break; } break; @@ -647,11 +645,6 @@ static void action_listener(const wmSpaceTypeListenerParams *params) case ND_POINTCACHE: case ND_MODIFIER: case ND_PARTICLE: - /* only needed in timeline mode */ - if (saction->mode == SACTCONT_TIMELINE) { - ED_area_tag_refresh(area); - ED_area_tag_redraw(area); - } break; default: /* just redrawing the view will do */ ED_area_tag_redraw(area); @@ -710,39 +703,18 @@ static void action_listener(const wmSpaceTypeListenerParams *params) static void action_header_region_listener(const wmRegionListenerParams *params) { - ScrArea *area = params->area; ARegion *region = params->region; const wmNotifier *wmn = params->notifier; - SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ switch (wmn->category) { case NC_SCREEN: - if (saction->mode == SACTCONT_TIMELINE) { - if (wmn->data == ND_ANIMPLAY) { - ED_region_tag_redraw(region); - } - } break; case NC_SCENE: - if (saction->mode == SACTCONT_TIMELINE) { - switch (wmn->data) { - case ND_RENDER_RESULT: - case ND_OB_SELECT: - case ND_FRAME: - case ND_FRAME_RANGE: - case ND_KEYINGSET: - case ND_RENDER_OPTIONS: - ED_region_tag_redraw(region); - break; - } - } - else { - switch (wmn->data) { - case ND_OB_ACTIVE: - ED_region_tag_redraw(region); - break; - } + switch (wmn->data) { + case ND_OB_ACTIVE: + ED_region_tag_redraw(region); + break; } break; case NC_ID: @@ -898,54 +870,6 @@ static void action_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data) } } -/** - * \note Used for splitting out a subset of modes is more involved, - * The previous non-timeline mode is stored so switching back to the - * dope-sheet doesn't always reset the sub-mode. - */ -static int action_space_subtype_get(ScrArea *area) -{ - SpaceAction *sact = static_cast(area->spacedata.first); - return sact->mode == SACTCONT_TIMELINE ? SACTCONT_TIMELINE : SACTCONT_DOPESHEET; -} - -static void action_space_subtype_set(ScrArea *area, int value) -{ - SpaceAction *sact = static_cast(area->spacedata.first); - if (value == SACTCONT_TIMELINE) { - if (sact->mode != SACTCONT_TIMELINE) { - sact->mode_prev = sact->mode; - } - sact->mode = value; - } - else { - sact->mode = sact->mode_prev; - } -} - -static void action_space_subtype_item_extend(bContext * /*C*/, - EnumPropertyItem **item, - int *totitem) -{ - RNA_enum_items_add(item, totitem, rna_enum_space_action_mode_items); -} - -static blender::StringRefNull action_space_name_get(const ScrArea *area) -{ - SpaceAction *sact = static_cast(area->spacedata.first); - const int index = max_ii(0, RNA_enum_from_value(rna_enum_space_action_mode_items, sact->mode)); - const EnumPropertyItem item = rna_enum_space_action_mode_items[index]; - return item.name; -} - -static int action_space_icon_get(const ScrArea *area) -{ - SpaceAction *sact = static_cast(area->spacedata.first); - const int index = max_ii(0, RNA_enum_from_value(rna_enum_space_action_mode_items, sact->mode)); - const EnumPropertyItem item = rna_enum_space_action_mode_items[index]; - return item.icon; -} - static void action_space_blend_read_data(BlendDataReader * /*reader*/, SpaceLink *sl) { SpaceAction *saction = (SpaceAction *)sl; @@ -975,11 +899,6 @@ void ED_spacetype_action() st->refresh = action_refresh; st->id_remap = action_id_remap; st->foreach_id = action_foreach_id; - st->space_subtype_item_extend = action_space_subtype_item_extend; - st->space_subtype_get = action_space_subtype_get; - st->space_subtype_set = action_space_subtype_set; - st->space_name_get = action_space_name_get; - st->space_icon_get = action_space_icon_get; st->blend_read_data = action_space_blend_read_data; st->blend_read_after_liblink = nullptr; st->blend_write = action_space_blend_write; diff --git a/source/blender/makesrna/RNA_enum_items.hh b/source/blender/makesrna/RNA_enum_items.hh index 5f9b424617e..b99926dd40a 100644 --- a/source/blender/makesrna/RNA_enum_items.hh +++ b/source/blender/makesrna/RNA_enum_items.hh @@ -38,7 +38,6 @@ DEF_ENUM(rna_enum_space_sequencer_view_type_items) DEF_ENUM(rna_enum_space_type_items) DEF_ENUM(rna_enum_space_image_mode_items) DEF_ENUM(rna_enum_space_image_mode_all_items) -DEF_ENUM(rna_enum_space_action_mode_items) DEF_ENUM(rna_enum_fileselect_params_sort_items) DEF_ENUM(rna_enum_region_type_items) DEF_ENUM(rna_enum_object_modifier_type_items) diff --git a/source/blender/makesrna/intern/rna_action.cc b/source/blender/makesrna/intern/rna_action.cc index 1c3db9d3892..2b1913bd5d7 100644 --- a/source/blender/makesrna/intern/rna_action.cc +++ b/source/blender/makesrna/intern/rna_action.cc @@ -1507,7 +1507,6 @@ bool rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value) case SACTCONT_DOPESHEET: case SACTCONT_MASK: case SACTCONT_CACHEFILE: - case SACTCONT_TIMELINE: break; } diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc index 6c9b67c98e4..f59632b585c 100644 --- a/source/blender/makesrna/intern/rna_space.cc +++ b/source/blender/makesrna/intern/rna_space.cc @@ -212,10 +212,6 @@ const EnumPropertyItem rna_enum_space_file_browse_mode_items[] = { { \ SACTCONT_DOPESHEET, "DOPESHEET", ICON_ACTION, "Dope Sheet", "Edit all keyframes in scene" \ } -#define SACT_ITEM_TIMELINE \ - { \ - SACTCONT_TIMELINE, "TIMELINE", ICON_TIME, "Timeline", "Timeline and playback controls" \ - } #define SACT_ITEM_ACTION \ { \ SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", \ @@ -246,7 +242,6 @@ const EnumPropertyItem rna_enum_space_file_browse_mode_items[] = { * so show that using object-icon hint */ static EnumPropertyItem rna_enum_space_action_mode_all_items[] = { SACT_ITEM_DOPESHEET, - SACT_ITEM_TIMELINE, SACT_ITEM_ACTION, SACT_ITEM_SHAPEKEY, SACT_ITEM_GPENCIL, @@ -256,7 +251,6 @@ static EnumPropertyItem rna_enum_space_action_mode_all_items[] = { }; static EnumPropertyItem rna_enum_space_action_ui_mode_items[] = { SACT_ITEM_DOPESHEET, - /* SACT_ITEM_TIMELINE, */ SACT_ITEM_ACTION, SACT_ITEM_SHAPEKEY, SACT_ITEM_GPENCIL, @@ -266,16 +260,7 @@ static EnumPropertyItem rna_enum_space_action_ui_mode_items[] = { }; #endif -/* Expose as `ui_mode`. */ - -const EnumPropertyItem rna_enum_space_action_mode_items[] = { - SACT_ITEM_DOPESHEET, - SACT_ITEM_TIMELINE, - {0, nullptr, 0, nullptr, nullptr}, -}; - #undef SACT_ITEM_DOPESHEET -#undef SACT_ITEM_TIMELINE #undef SACT_ITEM_ACTION #undef SACT_ITEM_SHAPEKEY #undef SACT_ITEM_GPENCIL @@ -2349,21 +2334,10 @@ static void rna_SpaceDopeSheetEditor_mode_update(bContext *C, PointerRNA *ptr) SpaceAction *saction = (SpaceAction *)(ptr->data); ScrArea *area = CTX_wm_area(C); - /* Collapse (and show) summary channel and hide channel list for timeline */ - if (saction->mode == SACTCONT_TIMELINE) { - saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; - saction->ads.filterflag |= ADS_FILTER_SUMMARY; - } - if (area && area->spacedata.first == saction) { ARegion *channels_region = BKE_area_find_region_type(area, RGN_TYPE_CHANNELS); if (channels_region) { - if (saction->mode == SACTCONT_TIMELINE) { - channels_region->flag |= RGN_FLAG_HIDDEN; - } - else { - channels_region->flag &= ~RGN_FLAG_HIDDEN; - } + channels_region->flag &= ~RGN_FLAG_HIDDEN; ED_region_visibility_change_update(C, area, channels_region); } } @@ -2373,9 +2347,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(bContext *C, PointerRNA *ptr) /* store current mode as "old mode", * so that returning from other editors doesn't always reset to "Action Editor" */ - if (saction->mode != SACTCONT_TIMELINE) { - saction->mode_prev = saction->mode; - } + saction->mode_prev = saction->mode; } /* Space Graph Editor */