Commit: f5799af5d293711002726e2f9d18e16a7d62ded1 Author: Richard Antalik Date: Mon Nov 14 15:40:42 2022 +0100 Branches: temp-vse-retiming-tool https://developer.blender.org/rBf5799af5d293711002726e2f9d18e16a7d62ded1
VSE: Add retiming tool This tools allows to change strip playback speed by manipulating retiming handles. More handles can be added to single strip to create variable playback speed. Demo: {F13511886} Ref: T100337 Differential Revision: https://developer.blender.org/D15945 =================================================================== M release/scripts/startup/bl_ui/space_sequencer.py M release/scripts/startup/bl_ui/space_toolsystem_toolbar.py M source/blender/editors/space_sequencer/CMakeLists.txt A source/blender/editors/space_sequencer/sequencer_gizmo_retime.cc A source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc M source/blender/editors/space_sequencer/sequencer_intern.h M source/blender/editors/space_sequencer/sequencer_ops.c A source/blender/editors/space_sequencer/sequencer_retiming.cc M source/blender/editors/space_sequencer/space_sequencer.c M source/blender/makesdna/DNA_sequence_types.h M source/blender/makesrna/intern/rna_internal.h M source/blender/makesrna/intern/rna_sequencer.c M source/blender/makesrna/intern/rna_sequencer_api.c M source/blender/sequencer/CMakeLists.txt A source/blender/sequencer/SEQ_retiming.hh M source/blender/sequencer/SEQ_time.h M source/blender/sequencer/intern/sequencer.c A source/blender/sequencer/intern/strip_retiming.cc M source/blender/sequencer/intern/strip_time.c M source/blender/sequencer/intern/strip_time.h =================================================================== diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index e703cf7f9c6..3f72454015b 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -1870,11 +1870,17 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): split.label(text="Channel") split.prop(strip, "channel", text="") + use_retiming_tool = strip.use_retiming_tool + if not is_effect: - split = layout.split(factor=0.5 + max_factor) - split.alignment = 'RIGHT' - split.label(text="Speed Factor") - split.prop(strip, "speed_factor", text="") + if not use_retiming_tool: + split = layout.split(factor=0.5 + max_factor) + split.alignment = 'RIGHT' + split.label(text="Speed Factor") + split.prop(strip, "speed_factor", text="") + else: + layout.operator("sequencer.retiming_reset") + sub = layout.column(align=True) split = sub.split(factor=0.5 + max_factor, align=True) diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 20021762d5a..a38b6c8451f 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -2558,6 +2558,17 @@ class _defs_sequencer_generic: options={'KEYMAP_FALLBACK'}, ) + @ToolDef.from_fn + def retime(): + return dict( + idname="builtin.retime", + label="Retime", + icon="none", + widget="SEQUENCER_GGT_gizmo_retime", + operator="transform.translate", + keymap=None, + ) + @ToolDef.from_fn def sample(): return dict( @@ -3248,6 +3259,7 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel): 'SEQUENCER': [ *_tools_select, _defs_sequencer_generic.blade, + _defs_sequencer_generic.retime, ], 'SEQUENCER_PREVIEW': [ *_tools_select, diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 5466beca255..419265ff299 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -33,10 +33,13 @@ set(SRC sequencer_drag_drop.c sequencer_draw.c sequencer_edit.c + sequencer_gizmo_retime.cc + sequencer_gizmo_retime_type.cc sequencer_modifier.c sequencer_ops.c sequencer_preview.c sequencer_proxy.c + sequencer_retiming.cc sequencer_scopes.c sequencer_select.c sequencer_thumbnails.c diff --git a/source/blender/editors/space_sequencer/sequencer_gizmo_retime.cc b/source/blender/editors/space_sequencer/sequencer_gizmo_retime.cc new file mode 100644 index 00000000000..dde5708dca4 --- /dev/null +++ b/source/blender/editors/space_sequencer/sequencer_gizmo_retime.cc @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup spseq + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + +#include "BKE_context.h" + +#include "BLI_span.hh" + +#include "RNA_access.h" + +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_gizmo_library.h" + +#include "SEQ_iterator.h" +#include "SEQ_retiming.hh" +#include "SEQ_time.h" +#include "SEQ_sequencer.h" + +/* Own include. */ +#include "sequencer_intern.h" + +typedef struct GizmoGroup_retime { + wmGizmo *add_handle_gizmo; + wmGizmo *move_handle_gizmo; + wmGizmo *remove_handle_gizmo; +} GizmoGroup_retime; + +static bool gizmogroup_retime_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +{ + if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) { + return false; + } + + ScrArea *area = CTX_wm_area(C); + if (area == NULL && area->spacetype != SPACE_SEQ) { + return false; + } + + const SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first; + if (sseq->gizmo_flag & (SEQ_GIZMO_HIDE | SEQ_GIZMO_HIDE_TOOL)) { + return false; + } + + Editing *ed = SEQ_editing_get(CTX_data_scene(C)); + Sequence *seq = ed->act_seq; + + if (ed == NULL || seq == NULL || !SEQ_retiming_is_allowed(seq)) { + return false; + } + + return true; +} + +static void gizmogroup_retime_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +{ + GizmoGroup_retime *ggd = (GizmoGroup_retime *)MEM_callocN(sizeof(GizmoGroup_retime), __func__); + + /* Assign gizmos. */ + const wmGizmoType *gzt_add_handle = WM_gizmotype_find("GIZMO_GT_retime_handle_add", true); + ggd->add_handle_gizmo = WM_gizmo_new_ptr(gzt_add_handle, gzgroup, NULL); + const wmGizmoType *gzt_remove_handle = WM_gizmotype_find("GIZMO_GT_retime_handle_remove", true); + ggd->remove_handle_gizmo = WM_gizmo_new_ptr(gzt_remove_handle, gzgroup, NULL); + const wmGizmoType *gzt_move_handle = WM_gizmotype_find("GIZMO_GT_retime_handle_move", true); + ggd->move_handle_gizmo = WM_gizmo_new_ptr(gzt_move_handle, gzgroup, NULL); + + /* Assign operators. */ + wmOperatorType *ot = WM_operatortype_find("SEQUENCER_OT_retiming_handle_move", true); + WM_gizmo_operator_set(ggd->move_handle_gizmo, 0, ot, NULL); + ot = WM_operatortype_find("SEQUENCER_OT_retiming_handle_add", true); + WM_gizmo_operator_set(ggd->add_handle_gizmo, 0, ot, NULL); + ot = WM_operatortype_find("SEQUENCER_OT_retiming_handle_remove", true); + WM_gizmo_operator_set(ggd->remove_handle_gizmo, 0, ot, NULL); +} + +void SEQUENCER_GGT_gizmo_retime(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Sequencer Transform Gizmo Retime"; + gzgt->idname = "SEQUENCER_GGT_gizmo_retime"; + + gzgt->flag = WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL; + + gzgt->gzmap_params.spaceid = SPACE_SEQ; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; + + gzgt->poll = gizmogroup_retime_poll; + gzgt->setup = gizmogroup_retime_setup; +} + +/** \} */ diff --git a/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc b/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc new file mode 100644 index 00000000000..4ea496cd786 --- /dev/null +++ b/source/blender/editors/space_sequencer/sequencer_gizmo_retime_type.cc @@ -0,0 +1,578 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup spseq + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_span.hh" + +#include "DNA_anim_types.h" + +#include "BKE_context.h" +#include "BKE_fcurve.h" +#include "BKE_scene.h" + +#include "BLF_api.h" + +#include "GPU_batch.h" +#include "GPU_batch_utils.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_select.h" +#include "GPU_state.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_gizmo_library.h" +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "SEQ_iterator.h" +#include "SEQ_retiming.hh" +#include "SEQ_sequencer.h" +#include "SEQ_time.h" + +/* Own include. */ +#include "sequencer_intern.h" + +using blender::MutableSpan; + +#define REMOVE_GIZMO_HEIGHT 12.0f * U.dpi_fac /* Pixels from bottom of strip. */ +#define RETIME_HANDLE_TRIANGLE_SIZE 10.0f * U.dpi_fac /* Also used for mouseover test. */ +#define RETIME_BUTTON_SIZE 0.6f /* Factor based on icon size. */ + +static float strip_y_rescale(const Sequence *seq, const float y_value) +{ + const float y_range = SEQ_STRIP_OFSTOP - SEQ_STRIP_OFSBOTTOM; + return (y_value * y_range) + seq->machine + SEQ_STRIP_OFSBOTTOM; +} + +static float handle_x_get(const Sequence *seq, const SeqRetimingHandle *handle) +{ + + const SeqRetimingHandle *last_handle = SEQ_retiming_last_handle_get(seq); + const bool is_last_handle = (handle == last_handle); + + return SEQ_time_start_frame_get(seq) + handle->strip_frame_index + + (is_last_handle ? 1 : 0); +} + +static float handle_y_get(const Sequence *seq, const SeqRetimingHandle *handle) +{ + return strip_y_rescale(seq, handle->retiming_factor); +} + +static const SeqRetimingHandle *mouse_over_handle_get(const Sequence *seq, + const View2D *v2d, + const int mval[2]) +{ + int best_distance = INT_MAX; + const SeqRetimingHandle *best_handle = NULL; + + MutableSpan handles = SEQ_retiming_handles_get(seq); + for (const SeqRetimingHandle& handle : handles) { + int distance = round_fl_to_int(fabsf(UI_view2d_view_to_region_x(v2d, handle_x_get(seq, &handle)) - mval[0])); + + if (distance < RETIME_HANDLE_TRIANGLE_SIZE && distance < best_distance) { + best_distance = distance; + best_handle = &handle; + } + } + + return best_handle; +} + +static float pixels_to_view_width(const bContext *C, const float width) +{ + const View2D *v2d = UI_view2d_fromcontext(C); + float scale_x = UI_view2d_view_to_region_x(v2d, 1) - UI_view2d_view_to_region_x(v2d, 0.0f); + return width / scale_x; +} + +static float pixels_to_view_height(const bContext *C, const float height) +{ + const View2D *v2d = UI_view2d_fromcontext(C); + float scale_y = UI_view2d_view_to_region_y(v2d, 1) - UI_view2d_view_to_region_y(v2d, 0.0f); + return height / scale_y; +} + +static float strip_start_screenspace_get(const bContext *C, const Sequence *seq) +{ + const View2D *v2d = UI_view2d_fromcontext(C); + const Scene *scene = CTX_data_scene(C); + return UI_view2d_view_to_region_x(v2d, SEQ_time_left_handle_frame_get(scene, seq)); +} + +static float strip_end_screenspace_get(const bContext *C, const Sequence *seq) +{ + const View2D *v2d = UI_view2d_fromcontext(C); + const Scene *scene = CTX_data_scene(C); + return UI_view2d_view_to_region_x(v2d, SEQ_time_right_handle_frame_get(scene, seq)); +} + +static Sequence @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs