2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup spseq
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
|
2009-01-12 19:02:08 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2023-12-07 15:39:51 +01:00
|
|
|
#include "BLI_fileops.h"
|
2025-02-11 16:59:42 +01:00
|
|
|
#include "BLI_listbase.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_vector.h"
|
2024-09-26 21:13:39 +10:00
|
|
|
#include "BLI_path_utils.hh"
|
2023-06-19 11:37:05 +10:00
|
|
|
#include "BLI_string.h"
|
2015-07-03 12:34:23 +02:00
|
|
|
#include "BLI_timecode.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2024-02-09 18:59:42 +01:00
|
|
|
#include "BLT_translation.hh"
|
2012-10-26 17:32:50 +00:00
|
|
|
|
2021-06-11 15:47:19 +02:00
|
|
|
#include "DNA_anim_types.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2016-01-27 11:01:41 +01:00
|
|
|
#include "DNA_sound_types.h"
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_context.hh"
|
2024-02-10 18:25:14 +01:00
|
|
|
#include "BKE_global.hh"
|
2025-02-07 17:47:16 +01:00
|
|
|
#include "BKE_library.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2024-02-10 18:34:29 +01:00
|
|
|
#include "BKE_report.hh"
|
2009-08-09 21:16:39 +00:00
|
|
|
#include "BKE_sound.h"
|
2012-02-29 12:08:26 +00:00
|
|
|
|
2023-11-02 01:05:06 +01:00
|
|
|
#include "SEQ_add.hh"
|
|
|
|
|
#include "SEQ_animation.hh"
|
|
|
|
|
#include "SEQ_channels.hh"
|
2024-08-22 14:54:42 +02:00
|
|
|
#include "SEQ_connect.hh"
|
2023-11-02 01:05:06 +01:00
|
|
|
#include "SEQ_edit.hh"
|
|
|
|
|
#include "SEQ_effects.hh"
|
|
|
|
|
#include "SEQ_iterator.hh"
|
|
|
|
|
#include "SEQ_prefetch.hh"
|
|
|
|
|
#include "SEQ_relations.hh"
|
|
|
|
|
#include "SEQ_render.hh"
|
|
|
|
|
#include "SEQ_select.hh"
|
|
|
|
|
#include "SEQ_sequencer.hh"
|
VSE: Faster and more consistent thumbnails
Implementing part of design outlined in #126087.
- VSE thumbnail cache has a new implementation, hopefully simpler
and easier to understand.
- Instead of cache key being a VSE strip, frame index, plus
complicated logic for cache items linking etc.,
- The cache is keyed by media file path (if multiple strips
use the same input file, they will share cache entries), frame
index within media file, and any extra data (e.g. steam index
for multi-steam videos)
- Much reduced cache flickering and strange/weird thumbnail choices.
- Likewise, thumbnails no longer disappear-and-reload on operations
like Undo, dragging new video strip into timeline, or F12 render.
- Thumbnails now load faster.
- Images use dedicated/faster thumbnail loading routines when a
format can do that (e.g. JPG and EXR can).
- Movies reuse ffmpeg decoding context for neighboring strips
that use the same file (as often happens when cutting footage)
- Thumbnail requests are processed on several threads now too.
Images and more detail in PR.
Pull Request: https://projects.blender.org/blender/blender/pulls/126405
2024-08-29 08:27:12 +02:00
|
|
|
#include "SEQ_thumbnail_cache.hh"
|
2023-11-02 01:05:06 +01:00
|
|
|
#include "SEQ_time.hh"
|
|
|
|
|
#include "SEQ_transform.hh"
|
|
|
|
|
#include "SEQ_utils.hh"
|
2020-11-01 21:03:31 +01:00
|
|
|
|
2024-09-24 09:59:48 +02:00
|
|
|
#include "ANIM_action_legacy.hh"
|
|
|
|
|
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "WM_api.hh"
|
|
|
|
|
#include "WM_types.hh"
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2023-08-10 22:40:27 +02:00
|
|
|
#include "RNA_define.hh"
|
|
|
|
|
#include "RNA_enum_types.hh"
|
2024-07-10 18:30:02 +02:00
|
|
|
#include "RNA_prototypes.hh"
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* For menu, popup, icons, etc. */
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_fileselect.hh"
|
|
|
|
|
#include "ED_numinput.hh"
|
|
|
|
|
#include "ED_scene.hh"
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "ED_screen.hh"
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_sequencer.hh"
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "UI_interface.hh"
|
|
|
|
|
#include "UI_resources.hh"
|
|
|
|
|
#include "UI_view2d.hh"
|
2014-11-24 18:18:35 +01:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
|
|
|
|
#include "DEG_depsgraph_build.hh"
|
2019-06-04 16:52:48 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Own include. */
|
2023-09-08 08:23:01 -04:00
|
|
|
#include "sequencer_intern.hh"
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2025-03-06 06:22:14 +01:00
|
|
|
namespace blender::ed::vse {
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Public Context Checks
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool maskedit_mask_poll(bContext *C)
|
2012-07-24 09:53:29 +00:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
return maskedit_poll(C);
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool check_show_maskedit(SpaceSeq *sseq, Scene *scene)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
|
|
|
|
if (sseq && sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
|
2025-03-06 13:04:39 +01:00
|
|
|
return (seq::active_mask_get(scene) != nullptr);
|
2009-01-26 09:13:15 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool maskedit_poll(bContext *C)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
|
|
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
|
|
|
|
|
|
|
|
|
if (sseq) {
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
return check_show_maskedit(sseq, scene);
|
2020-06-18 05:25:20 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool check_show_imbuf(SpaceSeq *sseq)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
2021-10-08 12:55:26 +11:00
|
|
|
return (sseq->mainb == SEQ_DRAW_IMG_IMBUF) &&
|
2022-10-07 22:52:53 +11:00
|
|
|
ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW);
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool check_show_strip(SpaceSeq *sseq)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
2021-10-08 12:55:26 +11:00
|
|
|
return ELEM(sseq->view, SEQ_VIEW_SEQUENCE, SEQ_VIEW_SEQUENCE_PREVIEW);
|
2009-01-20 14:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-11 15:47:19 +02:00
|
|
|
static bool sequencer_fcurves_targets_color_strip(const FCurve *fcurve)
|
|
|
|
|
{
|
2025-01-21 11:30:20 +01:00
|
|
|
if (!BLI_str_startswith(fcurve->rna_path, "sequence_editor.strips_all[\"")) {
|
2021-06-11 15:47:19 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!BLI_str_endswith(fcurve->rna_path, "\"].color")) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool has_playback_animation(const SpaceSeq *sseq, const Scene *scene)
|
2021-06-11 15:47:19 +02:00
|
|
|
{
|
2021-06-15 09:31:03 +02:00
|
|
|
if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 15:47:19 +02:00
|
|
|
if (!scene->adt) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!scene->adt->action) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-24 09:59:48 +02:00
|
|
|
for (FCurve *fcurve : blender::animrig::legacy::fcurves_for_assigned_action(scene->adt)) {
|
2021-06-11 15:47:19 +02:00
|
|
|
if (sequencer_fcurves_targets_color_strip(fcurve)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2020-11-19 12:59:29 +01:00
|
|
|
/** \name Shared Poll Functions
|
2020-06-06 00:05:54 +10:00
|
|
|
* \{ */
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
bool sequencer_edit_poll(bContext *C)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
return (seq::editing_get(CTX_data_scene(C)) != nullptr);
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-30 14:52:54 +10:00
|
|
|
bool sequencer_edit_with_channel_region_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
if (!sequencer_edit_poll(C)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
if (!(region && (region->regiontype == RGN_TYPE_CHANNELS))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-23 18:11:33 +02:00
|
|
|
bool sequencer_editing_initialized_and_active(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
return ED_operator_sequencer_active(C) && sequencer_edit_poll(C);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
#if 0 /* UNUSED */
|
|
|
|
|
bool sequencer_strip_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
Editing *ed;
|
2025-03-06 13:04:39 +01:00
|
|
|
return (((ed = seq::editing_get(CTX_data_scene(C))) != nullptr) && (ed->act_seq != nullptr));
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-12-06 10:06:40 +11:00
|
|
|
bool sequencer_strip_editable_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2024-05-16 14:53:09 +02:00
|
|
|
if (!ID_IS_EDITABLE(&scene->id)) {
|
2023-12-06 10:06:40 +11:00
|
|
|
return false;
|
|
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2023-12-06 10:06:40 +11:00
|
|
|
return (ed && (ed->act_seq != nullptr));
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
bool sequencer_strip_has_path_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
Editing *ed;
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip;
|
2025-03-06 13:04:39 +01:00
|
|
|
return (((ed = seq::editing_get(CTX_data_scene(C))) != nullptr) &&
|
2025-01-07 16:33:39 +01:00
|
|
|
((strip = ed->act_seq) != nullptr) && STRIP_HAS_PATH(strip));
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-11-30 11:09:58 +01:00
|
|
|
bool sequencer_view_has_preview_poll(bContext *C)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
|
|
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
2023-06-14 18:36:17 +02:00
|
|
|
if (sseq == nullptr) {
|
2021-10-08 01:54:48 +11:00
|
|
|
return false;
|
|
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::editing_get(CTX_data_scene(C)) == nullptr) {
|
2021-10-08 01:54:48 +11:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!(ELEM(sseq->view, SEQ_VIEW_PREVIEW, SEQ_VIEW_SEQUENCE_PREVIEW) &&
|
|
|
|
|
(sseq->mainb == SEQ_DRAW_IMG_IMBUF)))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
if (!(region && region->regiontype == RGN_TYPE_PREVIEW)) {
|
|
|
|
|
return false;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-08 01:54:48 +11:00
|
|
|
return true;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-11-30 11:09:58 +01:00
|
|
|
bool sequencer_view_preview_only_poll(const bContext *C)
|
|
|
|
|
{
|
|
|
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
2023-06-14 18:36:17 +02:00
|
|
|
if (sseq == nullptr) {
|
2021-11-30 11:09:58 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::editing_get(CTX_data_scene(C)) == nullptr) {
|
2021-11-30 11:09:58 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!(ELEM(sseq->view, SEQ_VIEW_PREVIEW) && (sseq->mainb == SEQ_DRAW_IMG_IMBUF))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
if (!(region && region->regiontype == RGN_TYPE_PREVIEW)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
bool sequencer_view_strips_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
2023-06-14 18:36:17 +02:00
|
|
|
if (sseq == nullptr) {
|
2021-10-08 01:54:48 +11:00
|
|
|
return false;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
if (!check_show_strip(sseq)) {
|
2021-10-08 01:54:48 +11:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
if (!(region && region->regiontype == RGN_TYPE_WINDOW)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Remove Gaps Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2013-03-26 20:34:13 +00:00
|
|
|
static int sequencer_gap_remove_exec(bContext *C, wmOperator *op)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2013-03-26 15:00:56 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2020-12-15 21:42:06 +01:00
|
|
|
const bool do_all = RNA_boolean_get(op->ptr, "all");
|
2025-03-06 13:04:39 +01:00
|
|
|
const Editing *ed = seq::editing_get(scene);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::edit_remove_gaps(scene, ed->seqbasep, scene->r.cfra, do_all);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-26 15:00:56 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2019-08-01 10:19:19 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-26 15:00:56 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_gap_remove(wmOperatorType *ot)
|
2013-03-26 15:00:56 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2013-03-26 20:34:13 +00:00
|
|
|
ot->name = "Remove Gaps";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_gap_remove";
|
2013-03-27 18:31:18 +00:00
|
|
|
ot->description =
|
|
|
|
|
"Remove gap at current frame to first strip at the right, independent of selection or "
|
|
|
|
|
"locked state of strips";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2013-03-26 15:00:56 +00:00
|
|
|
// ot->invoke = sequencer_snap_invoke;
|
2013-03-26 20:34:13 +00:00
|
|
|
ot->exec = sequencer_gap_remove_exec;
|
2013-03-26 15:00:56 +00:00
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2013-03-26 15:00:56 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
RNA_def_boolean(ot->srna, "all", false, "All Gaps", "Do all gaps to right of current frame");
|
2013-03-26 15:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Insert Gaps Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2013-03-26 20:34:13 +00:00
|
|
|
static int sequencer_gap_insert_exec(bContext *C, wmOperator *op)
|
2013-03-26 15:00:56 +00:00
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2020-12-15 21:42:06 +01:00
|
|
|
const int frames = RNA_int_get(op->ptr, "frames");
|
2025-03-06 13:04:39 +01:00
|
|
|
const Editing *ed = seq::editing_get(scene);
|
|
|
|
|
seq::transform_offset_after_frame(scene, ed->seqbasep, frames, scene->r.cfra);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-26 15:00:56 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
return OPERATOR_FINISHED;
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_gap_insert(wmOperatorType *ot)
|
2010-07-08 10:03:29 +00:00
|
|
|
{
|
2020-11-19 12:59:29 +01:00
|
|
|
/* Identifiers. */
|
|
|
|
|
ot->name = "Insert Gaps";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_gap_insert";
|
|
|
|
|
ot->description =
|
|
|
|
|
"Insert gap at current frame to first strips at the right, independent of selection or "
|
|
|
|
|
"locked state of strips";
|
2010-07-08 10:03:29 +00:00
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
/* Api callbacks. */
|
|
|
|
|
// ot->invoke = sequencer_snap_invoke;
|
|
|
|
|
ot->exec = sequencer_gap_insert_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2009-06-09 21:29:59 +00:00
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2015-01-05 02:12:50 +11:00
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
RNA_def_int(ot->srna,
|
|
|
|
|
"frames",
|
|
|
|
|
10,
|
|
|
|
|
0,
|
|
|
|
|
INT_MAX,
|
|
|
|
|
"Frames",
|
|
|
|
|
"Frames to insert after current strip",
|
|
|
|
|
0,
|
|
|
|
|
1000);
|
2015-01-05 02:12:50 +11:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Snap Strips to the Current Frame Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2009-06-09 21:29:59 +00:00
|
|
|
static int sequencer_snap_exec(bContext *C, wmOperator *op)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *channels = seq::channels_displayed_get(ed);
|
2009-06-09 21:29:59 +00:00
|
|
|
int snap_frame;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
snap_frame = RNA_int_get(op->ptr, "frame");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-05-14 17:35:22 +10:00
|
|
|
/* Check meta-strips. */
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (strip->flag & SELECT && !seq::transform_is_locked(channels, strip) &&
|
|
|
|
|
seq::transform_sequence_can_be_translated(strip))
|
2020-12-19 05:57:27 +01:00
|
|
|
{
|
2025-01-07 14:09:45 +01:00
|
|
|
if ((strip->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::transform_translate_sequence(
|
2025-01-07 14:09:45 +01:00
|
|
|
scene, strip, (snap_frame - strip->startofs) - strip->start);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip->flag & SEQ_LEFTSEL) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::time_left_handle_frame_set(scene, strip, snap_frame);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else { /* SEQ_RIGHTSEL */
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::time_right_handle_frame_set(scene, strip, snap_frame);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-11-18 04:09:44 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_composite(scene, strip);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-31 09:27:31 +02:00
|
|
|
/* Test for effects and overlap. */
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (strip->flag & SELECT && !seq::transform_is_locked(channels, strip)) {
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->flag &= ~SEQ_OVERLAP;
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, ed->seqbasep, strip)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(ed->seqbasep, strip, scene);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-06-18 04:26:41 +02:00
|
|
|
}
|
|
|
|
|
|
2021-01-25 05:51:36 +01:00
|
|
|
/* Recalculate bounds of effect strips, offsetting the keyframes if not snapping any handle. */
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->type & STRIP_TYPE_EFFECT) {
|
2025-01-07 14:09:45 +01:00
|
|
|
const bool either_handle_selected = (strip->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) != 0;
|
2021-01-25 05:51:36 +01:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip->seq1 && (strip->seq1->flag & SELECT)) {
|
2021-01-25 05:51:36 +01:00
|
|
|
if (!either_handle_selected) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::offset_animdata(
|
|
|
|
|
scene, strip, (snap_frame - seq::time_left_handle_frame_get(scene, strip)));
|
2021-01-25 05:51:36 +01:00
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2025-01-07 14:09:45 +01:00
|
|
|
else if (strip->seq2 && (strip->seq2->flag & SELECT)) {
|
2021-01-25 05:51:36 +01:00
|
|
|
if (!either_handle_selected) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::offset_animdata(
|
|
|
|
|
scene, strip, (snap_frame - seq::time_left_handle_frame_get(scene, strip)));
|
2021-01-25 05:51:36 +01:00
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-28 18:02:14 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-06-09 21:29:59 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2009-06-09 21:29:59 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-06-09 21:29:59 +00:00
|
|
|
int snap_frame;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2022-06-30 18:36:42 +02:00
|
|
|
snap_frame = scene->r.cfra;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-06-09 21:29:59 +00:00
|
|
|
RNA_int_set(op->ptr, "frame", snap_frame);
|
|
|
|
|
return sequencer_snap_exec(C, op);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_snap(wmOperatorType *ot)
|
2009-06-09 21:29:59 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2020-06-01 14:41:12 +10:00
|
|
|
ot->name = "Snap Strips to the Current Frame";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "SEQUENCER_OT_snap";
|
|
|
|
|
ot->description = "Frame where selected strips will be snapped";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = sequencer_snap_invoke;
|
|
|
|
|
ot->exec = sequencer_snap_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-09-12 17:16:12 +00:00
|
|
|
RNA_def_int(ot->srna,
|
|
|
|
|
"frame",
|
|
|
|
|
0,
|
|
|
|
|
INT_MIN,
|
|
|
|
|
INT_MAX,
|
|
|
|
|
"Frame",
|
|
|
|
|
"Frame where selected strips will be snapped",
|
|
|
|
|
INT_MIN,
|
|
|
|
|
INT_MAX);
|
2009-06-09 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Trim Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
struct SlipData {
|
2014-10-21 19:02:05 +02:00
|
|
|
float init_mouseloc[2];
|
2023-12-21 18:04:56 +01:00
|
|
|
int previous_offset;
|
2024-06-19 13:36:47 +02:00
|
|
|
float previous_subframe_offset;
|
|
|
|
|
float subframe_restore;
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip **strip_array;
|
2014-10-21 19:02:05 +02:00
|
|
|
int num_seq;
|
|
|
|
|
bool slow;
|
2020-04-05 23:55:51 +02:00
|
|
|
int slow_offset; /* Offset at the point where offset was turned on. */
|
2015-02-06 16:38:32 +01:00
|
|
|
NumInput num_input;
|
2023-06-14 18:36:17 +02:00
|
|
|
};
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
static void slip_add_sequences(ListBase *seqbasep, Strip **strip_array)
|
2014-10-20 15:40:06 +02:00
|
|
|
{
|
2023-12-21 18:04:56 +01:00
|
|
|
int i = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, seqbasep) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if (!(strip->type & STRIP_TYPE_EFFECT) && (strip->flag & SELECT)) {
|
2025-01-07 16:03:11 +01:00
|
|
|
strip_array[i] = strip;
|
2023-12-21 18:04:56 +01:00
|
|
|
i++;
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-21 18:04:56 +01:00
|
|
|
static int slip_count_sequences(ListBase *seqbasep)
|
2014-10-21 19:02:05 +02:00
|
|
|
{
|
2014-10-20 15:40:06 +02:00
|
|
|
int trimmed_sequences = 0;
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, seqbasep) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if (!(strip->type & STRIP_TYPE_EFFECT) && (strip->flag & SELECT)) {
|
2014-10-20 17:37:13 +02:00
|
|
|
trimmed_sequences++;
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return trimmed_sequences;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 16:48:34 +02:00
|
|
|
static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2014-10-20 15:40:06 +02:00
|
|
|
{
|
2014-10-23 16:48:34 +02:00
|
|
|
SlipData *data;
|
2014-10-20 15:40:06 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2014-10-20 15:40:06 +02:00
|
|
|
float mouseloc[2];
|
2020-09-09 18:41:07 +02:00
|
|
|
int num_seq;
|
2014-10-20 15:40:06 +02:00
|
|
|
View2D *v2d = UI_view2d_fromcontext(C);
|
|
|
|
|
|
2023-12-21 18:04:56 +01:00
|
|
|
/* Count the amount of elements to trim. */
|
|
|
|
|
num_seq = slip_count_sequences(ed->seqbasep);
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (num_seq == 0) {
|
2014-10-20 15:40:06 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2025-03-05 16:35:09 +01:00
|
|
|
data = MEM_callocN<SlipData>("trimdata");
|
2023-06-14 18:36:17 +02:00
|
|
|
op->customdata = static_cast<void *>(data);
|
2025-03-05 16:35:09 +01:00
|
|
|
data->strip_array = MEM_calloc_arrayN<Strip *>(num_seq, "trimdata_strips");
|
2014-10-20 15:40:06 +02:00
|
|
|
data->num_seq = num_seq;
|
2023-12-21 18:04:56 +01:00
|
|
|
data->previous_offset = 0;
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2015-02-06 16:38:32 +01:00
|
|
|
initNumInput(&data->num_input);
|
|
|
|
|
data->num_input.idx_max = 0;
|
|
|
|
|
data->num_input.unit_sys = USER_UNIT_NONE;
|
|
|
|
|
data->num_input.unit_type[0] = 0;
|
|
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
slip_add_sequences(ed->seqbasep, data->strip_array);
|
2014-10-20 15:40:06 +02:00
|
|
|
|
|
|
|
|
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
|
|
|
|
|
|
|
|
|
|
copy_v2_v2(data->init_mouseloc, mouseloc);
|
|
|
|
|
|
|
|
|
|
data->slow = false;
|
|
|
|
|
|
|
|
|
|
WM_event_add_modal_handler(C, op);
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Notify so we draw extensions immediately. */
|
2014-10-20 15:40:06 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 13:36:47 +02:00
|
|
|
static void sequencer_slip_strips(Scene *scene, SlipData *data, int delta, float subframe_delta)
|
2014-10-20 15:40:06 +02:00
|
|
|
{
|
2020-03-10 16:05:43 +11:00
|
|
|
for (int i = data->num_seq - 1; i >= 0; i--) {
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip *strip = data->strip_array[i];
|
2020-03-10 16:05:43 +11:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *channels = seq::channels_displayed_get(seq::editing_get(scene));
|
|
|
|
|
if (seq::transform_is_locked(channels, strip)) {
|
2023-08-14 05:51:29 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::time_slip_strip(scene, strip, delta, subframe_delta);
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
2022-05-18 21:26:47 +02:00
|
|
|
|
|
|
|
|
for (int i = data->num_seq - 1; i >= 0; i--) {
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip *strip = data->strip_array[i];
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2020-03-10 16:05:43 +11:00
|
|
|
}
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-21 18:04:56 +01:00
|
|
|
/* Make sure, that each strip contains at least 1 frame of content.
|
|
|
|
|
* Returns clamped offset relative to current strip positions. */
|
|
|
|
|
static int sequencer_slip_apply_limits(const Scene *scene, SlipData *data, int *offset)
|
2020-04-06 02:09:20 +02:00
|
|
|
{
|
2023-12-21 18:04:56 +01:00
|
|
|
int delta_offset = *offset - data->previous_offset;
|
|
|
|
|
|
2020-04-06 02:09:20 +02:00
|
|
|
for (int i = 0; i < data->num_seq; i++) {
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip *strip = data->strip_array[i];
|
2025-03-06 13:04:39 +01:00
|
|
|
int strip_content_start = seq::time_start_frame_get(strip) + delta_offset;
|
2025-01-07 16:03:11 +01:00
|
|
|
int strip_content_end = strip_content_start + strip->len + strip->anim_startofs +
|
|
|
|
|
strip->anim_endofs;
|
2023-12-21 18:04:56 +01:00
|
|
|
int diff = 0;
|
2020-04-06 02:09:20 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
if (strip_content_start >= seq::time_right_handle_frame_get(scene, strip)) {
|
|
|
|
|
diff = seq::time_right_handle_frame_get(scene, strip) - strip_content_start - 1;
|
2020-04-06 02:09:20 +02:00
|
|
|
}
|
2023-12-21 18:04:56 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
if (strip_content_end <= seq::time_left_handle_frame_get(scene, strip)) {
|
|
|
|
|
diff = seq::time_left_handle_frame_get(scene, strip) - strip_content_end + 1;
|
2023-12-21 18:04:56 +01:00
|
|
|
}
|
|
|
|
|
*offset += diff;
|
|
|
|
|
delta_offset += diff;
|
2020-04-06 02:09:20 +02:00
|
|
|
}
|
2023-12-21 18:04:56 +01:00
|
|
|
data->previous_offset = *offset;
|
|
|
|
|
|
|
|
|
|
return delta_offset;
|
2020-04-06 02:09:20 +02:00
|
|
|
}
|
|
|
|
|
|
2014-10-23 16:48:34 +02:00
|
|
|
static int sequencer_slip_exec(bContext *C, wmOperator *op)
|
2014-10-20 15:40:06 +02:00
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2023-12-21 18:04:56 +01:00
|
|
|
/* Count the amount of elements to trim. */
|
|
|
|
|
int num_seq = slip_count_sequences(ed->seqbasep);
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (num_seq == 0) {
|
2014-10-20 15:40:06 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2025-03-05 16:35:09 +01:00
|
|
|
SlipData *data = MEM_callocN<SlipData>("trimdata");
|
2023-06-14 18:36:17 +02:00
|
|
|
op->customdata = static_cast<void *>(data);
|
2025-03-05 16:35:09 +01:00
|
|
|
data->strip_array = MEM_calloc_arrayN<Strip *>(num_seq, "trimdata_strips");
|
2014-10-20 15:40:06 +02:00
|
|
|
data->num_seq = num_seq;
|
|
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
slip_add_sequences(ed->seqbasep, data->strip_array);
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2024-06-19 13:36:47 +02:00
|
|
|
float offset_fl = RNA_float_get(op->ptr, "offset");
|
|
|
|
|
int offset = round_fl_to_int(offset_fl);
|
|
|
|
|
|
|
|
|
|
float subframe_delta = 0.0f;
|
|
|
|
|
if (std::trunc(offset_fl) != offset_fl) {
|
|
|
|
|
/* Only apply subframe offsets if the input is not an integer. */
|
|
|
|
|
subframe_delta = offset_fl - offset;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-29 12:45:59 +02:00
|
|
|
sequencer_slip_apply_limits(scene, data, &offset);
|
2024-06-19 13:36:47 +02:00
|
|
|
sequencer_slip_strips(scene, data, offset, subframe_delta);
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
MEM_freeN(data->strip_array);
|
2014-10-20 15:40:06 +02:00
|
|
|
MEM_freeN(data);
|
|
|
|
|
|
2022-05-18 21:26:47 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
|
|
|
|
return OPERATOR_FINISHED;
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:25:03 +02:00
|
|
|
static void sequencer_slip_update_header(Scene *scene, ScrArea *area, SlipData *data, int offset)
|
2015-02-06 16:38:32 +01:00
|
|
|
{
|
2024-04-23 15:06:50 +10:00
|
|
|
if (area == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-02-06 16:38:32 +01:00
|
|
|
|
2024-04-23 15:06:50 +10:00
|
|
|
char msg[UI_MAX_DRAW_STR];
|
|
|
|
|
if (hasNumInput(&data->num_input)) {
|
|
|
|
|
char num_str[NUM_STR_REP_LEN];
|
2025-01-08 21:22:45 +11:00
|
|
|
outputNumInput(&data->num_input, num_str, scene->unit);
|
2024-04-23 15:06:50 +10:00
|
|
|
SNPRINTF(msg, IFACE_("Slip offset: %s"), num_str);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
SNPRINTF(msg, IFACE_("Slip offset: %d"), offset);
|
2015-02-06 16:38:32 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-03 13:25:03 +02:00
|
|
|
ED_area_status_text(area, msg);
|
2015-02-06 16:38:32 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-19 13:36:47 +02:00
|
|
|
static void handle_number_input(
|
|
|
|
|
bContext *C, wmOperator *op, ScrArea *area, SlipData *data, Scene *scene)
|
|
|
|
|
{
|
|
|
|
|
float offset_fl;
|
|
|
|
|
applyNumInput(&data->num_input, &offset_fl);
|
|
|
|
|
int offset = round_fl_to_int(offset_fl);
|
|
|
|
|
|
|
|
|
|
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
|
|
|
|
sequencer_slip_update_header(scene, area, data, offset);
|
|
|
|
|
|
|
|
|
|
RNA_float_set(op->ptr, "offset", offset_fl);
|
|
|
|
|
|
|
|
|
|
float subframe_delta = 0.0f;
|
|
|
|
|
if (data->subframe_restore != 0.0f) {
|
2024-07-13 16:56:57 +10:00
|
|
|
/* Always remove the previous sub-frame adjustments we have potentially made with the mouse
|
|
|
|
|
* input when the user starts entering values by hand.
|
2024-06-19 13:36:47 +02:00
|
|
|
*/
|
|
|
|
|
subframe_delta = -data->subframe_restore;
|
|
|
|
|
data->subframe_restore = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
if (std::trunc(offset_fl) != offset_fl) {
|
2024-07-13 16:56:57 +10:00
|
|
|
/* Only apply sub-frame offsets if the input is not an integer. */
|
2024-06-19 13:36:47 +02:00
|
|
|
subframe_delta = offset_fl - data->previous_subframe_offset - delta_offset;
|
|
|
|
|
data->subframe_restore += subframe_delta;
|
|
|
|
|
}
|
|
|
|
|
data->previous_subframe_offset = offset_fl;
|
|
|
|
|
sequencer_slip_strips(scene, data, delta_offset, subframe_delta);
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 16:48:34 +02:00
|
|
|
static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
2014-10-20 15:40:06 +02:00
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2014-10-23 16:48:34 +02:00
|
|
|
SlipData *data = (SlipData *)op->customdata;
|
2020-04-03 13:25:03 +02:00
|
|
|
ScrArea *area = CTX_wm_area(C);
|
2015-02-06 16:38:32 +01:00
|
|
|
const bool has_numInput = hasNumInput(&data->num_input);
|
|
|
|
|
bool handled = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Modal numinput active, try to handle numeric inputs. */
|
2015-02-06 16:38:32 +01:00
|
|
|
if (event->val == KM_PRESS && has_numInput && handleNumInput(C, &data->num_input, event)) {
|
2024-06-19 13:36:47 +02:00
|
|
|
handle_number_input(C, op, area, data, scene);
|
2015-02-06 16:38:32 +01:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-20 15:40:06 +02:00
|
|
|
switch (event->type) {
|
|
|
|
|
case MOUSEMOVE: {
|
2015-02-06 16:38:32 +01:00
|
|
|
if (!has_numInput) {
|
|
|
|
|
float mouseloc[2];
|
|
|
|
|
int offset;
|
2024-06-19 13:36:47 +02:00
|
|
|
float mouse_x;
|
2015-02-06 16:38:32 +01:00
|
|
|
View2D *v2d = UI_view2d_fromcontext(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-02-06 16:38:32 +01:00
|
|
|
if (data->slow) {
|
|
|
|
|
mouse_x = event->mval[0] - data->slow_offset;
|
|
|
|
|
mouse_x *= 0.1f;
|
|
|
|
|
mouse_x += data->slow_offset;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
mouse_x = event->mval[0];
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-06-01 14:41:12 +10:00
|
|
|
/* Choose the side based on which side of the current frame the mouse is. */
|
2015-02-06 16:38:32 +01:00
|
|
|
UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
|
2024-06-19 13:36:47 +02:00
|
|
|
float offset_fl = mouseloc[0] - data->init_mouseloc[0];
|
|
|
|
|
offset = offset_fl;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-12-21 18:04:56 +01:00
|
|
|
const int delta_offset = sequencer_slip_apply_limits(scene, data, &offset);
|
2020-04-03 13:25:03 +02:00
|
|
|
sequencer_slip_update_header(scene, area, data, offset);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-06-19 13:36:47 +02:00
|
|
|
if (!data->slow) {
|
|
|
|
|
RNA_float_set(op->ptr, "offset", offset);
|
|
|
|
|
}
|
|
|
|
|
float subframe_delta = 0.0f;
|
|
|
|
|
if (data->slow) {
|
|
|
|
|
RNA_float_set(op->ptr, "offset", offset_fl);
|
|
|
|
|
subframe_delta = offset_fl - data->previous_subframe_offset - delta_offset;
|
|
|
|
|
data->subframe_restore += subframe_delta;
|
|
|
|
|
}
|
|
|
|
|
else if (data->subframe_restore != 0.0f) {
|
|
|
|
|
/* If we exit slow mode, make sure we undo the fractional adjustments we have done. */
|
|
|
|
|
subframe_delta = -data->subframe_restore;
|
|
|
|
|
data->subframe_restore = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
data->previous_subframe_offset = offset_fl;
|
|
|
|
|
sequencer_slip_strips(scene, data, delta_offset, subframe_delta);
|
2023-12-21 18:04:56 +01:00
|
|
|
|
2022-05-18 21:26:47 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-20 15:40:06 +02:00
|
|
|
case LEFTMOUSE:
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_RETKEY:
|
2025-01-15 17:24:38 +01:00
|
|
|
case EVT_PADENTER:
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_SPACEKEY: {
|
2025-01-07 16:03:11 +01:00
|
|
|
MEM_freeN(data->strip_array);
|
2014-10-20 15:40:06 +02:00
|
|
|
MEM_freeN(data);
|
2023-06-14 18:36:17 +02:00
|
|
|
op->customdata = nullptr;
|
2020-04-03 13:25:03 +02:00
|
|
|
if (area) {
|
2023-06-14 18:36:17 +02:00
|
|
|
ED_area_status_text(area, nullptr);
|
2018-06-28 12:06:00 +02:00
|
|
|
}
|
2019-10-08 09:46:37 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2014-10-20 15:40:06 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_ESCKEY:
|
2014-10-20 15:40:06 +02:00
|
|
|
case RIGHTMOUSE: {
|
2024-06-19 13:36:47 +02:00
|
|
|
int offset = data->previous_offset;
|
|
|
|
|
float subframe_delta = data->subframe_restore;
|
|
|
|
|
sequencer_slip_strips(scene, data, -offset, -subframe_delta);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
MEM_freeN(data->strip_array);
|
2014-10-20 15:40:06 +02:00
|
|
|
MEM_freeN(data);
|
2023-06-14 18:36:17 +02:00
|
|
|
op->customdata = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-20 15:40:06 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-03 13:25:03 +02:00
|
|
|
if (area) {
|
2023-06-14 18:36:17 +02:00
|
|
|
ED_area_status_text(area, nullptr);
|
2018-06-28 12:06:00 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-20 15:40:06 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_RIGHTSHIFTKEY:
|
|
|
|
|
case EVT_LEFTSHIFTKEY:
|
2015-02-06 16:38:32 +01:00
|
|
|
if (!has_numInput) {
|
|
|
|
|
if (event->val == KM_PRESS) {
|
|
|
|
|
data->slow = true;
|
|
|
|
|
data->slow_offset = event->mval[0];
|
|
|
|
|
}
|
|
|
|
|
else if (event->val == KM_RELEASE) {
|
|
|
|
|
data->slow = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-02-06 16:38:32 +01:00
|
|
|
}
|
2014-10-20 15:40:06 +02:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-20 15:40:06 +02:00
|
|
|
default:
|
2015-02-06 16:38:32 +01:00
|
|
|
handled = false;
|
2014-10-20 15:40:06 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Modal numinput inactive, try to handle numeric inputs. */
|
2015-02-06 16:38:32 +01:00
|
|
|
if (!handled && event->val == KM_PRESS && handleNumInput(C, &data->num_input, event)) {
|
2024-06-19 13:36:47 +02:00
|
|
|
handle_number_input(C, op, area, data, scene);
|
2015-02-06 16:38:32 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-20 15:40:06 +02:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_slip(wmOperatorType *ot)
|
2014-10-20 15:40:06 +02:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2021-09-30 21:11:09 +02:00
|
|
|
ot->name = "Slip Strips";
|
2014-10-23 16:48:34 +02:00
|
|
|
ot->idname = "SEQUENCER_OT_slip";
|
2021-09-30 21:11:09 +02:00
|
|
|
ot->description = "Slip the contents of selected strips";
|
2014-10-20 15:40:06 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2014-10-23 16:48:34 +02:00
|
|
|
ot->invoke = sequencer_slip_invoke;
|
|
|
|
|
ot->modal = sequencer_slip_modal;
|
|
|
|
|
ot->exec = sequencer_slip_exec;
|
2014-10-20 15:40:06 +02:00
|
|
|
ot->poll = sequencer_edit_poll;
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2014-10-20 15:40:06 +02:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
2024-06-19 13:36:47 +02:00
|
|
|
/* Properties. */
|
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
|
|
prop = RNA_def_float(ot->srna,
|
|
|
|
|
"offset",
|
|
|
|
|
0,
|
|
|
|
|
-FLT_MAX,
|
|
|
|
|
FLT_MAX,
|
|
|
|
|
"Offset",
|
|
|
|
|
"Offset to the data of the strip",
|
|
|
|
|
-FLT_MAX,
|
|
|
|
|
FLT_MAX);
|
|
|
|
|
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 100, 0);
|
2014-10-20 15:40:06 +02:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Mute Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
static int sequencer_mute_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *channels = seq::channels_displayed_get(ed);
|
2023-06-14 18:36:17 +02:00
|
|
|
|
2014-04-01 11:34:00 +11:00
|
|
|
bool selected;
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
selected = !RNA_boolean_get(op->ptr, "unselected");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (!seq::transform_is_locked(channels, strip)) {
|
2020-04-05 23:55:51 +02:00
|
|
|
if (selected) {
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip->flag & SELECT) {
|
|
|
|
|
strip->flag |= SEQ_MUTE;
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_dependent(scene, strip);
|
2012-09-13 10:51:18 +00:00
|
|
|
}
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2025-01-07 14:09:45 +01:00
|
|
|
if ((strip->flag & SELECT) == 0) {
|
|
|
|
|
strip->flag |= SEQ_MUTE;
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_dependent(scene, strip);
|
2012-09-13 10:51:18 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-06-04 16:52:48 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_mute(wmOperatorType *ot)
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Mute Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_mute";
|
2015-06-12 14:04:07 +02:00
|
|
|
ot->description = "Mute (un)selected strips";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_mute_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2011-09-19 12:26:20 +00:00
|
|
|
RNA_def_boolean(
|
2023-07-22 11:36:59 +10:00
|
|
|
ot->srna, "unselected", false, "Unselected", "Mute unselected rather than selected strips");
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Unmute Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
static int sequencer_unmute_exec(bContext *C, wmOperator *op)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *channels = seq::channels_displayed_get(ed);
|
2014-04-01 11:34:00 +11:00
|
|
|
bool selected;
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
selected = !RNA_boolean_get(op->ptr, "unselected");
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (!seq::transform_is_locked(channels, strip)) {
|
2020-04-05 23:55:51 +02:00
|
|
|
if (selected) {
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip->flag & SELECT) {
|
|
|
|
|
strip->flag &= ~SEQ_MUTE;
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_dependent(scene, strip);
|
2012-09-13 10:51:18 +00:00
|
|
|
}
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2025-01-07 14:09:45 +01:00
|
|
|
if ((strip->flag & SELECT) == 0) {
|
|
|
|
|
strip->flag &= ~SEQ_MUTE;
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_dependent(scene, strip);
|
2012-09-13 10:51:18 +00:00
|
|
|
}
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-06-04 16:52:48 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_unmute(wmOperatorType *ot)
|
2009-01-12 19:02:08 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2018-11-22 02:02:03 +01:00
|
|
|
ot->name = "Unmute Strips";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "SEQUENCER_OT_unmute";
|
2015-06-12 14:04:07 +02:00
|
|
|
ot->description = "Unmute (un)selected strips";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_unmute_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
|
"unselected",
|
|
|
|
|
false,
|
|
|
|
|
"Unselected",
|
|
|
|
|
"Unmute unselected rather than selected strips");
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Lock Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_lock_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
|
|
|
|
if (strip->flag & SELECT) {
|
|
|
|
|
strip->flag |= SEQ_LOCK;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_lock(wmOperatorType *ot)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Lock Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_lock";
|
2019-03-13 08:48:55 +11:00
|
|
|
ot->description = "Lock strips so they can't be transformed";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_lock_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Unlock Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_unlock_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
|
|
|
|
if (strip->flag & SELECT) {
|
|
|
|
|
strip->flag &= ~SEQ_LOCK;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_unlock(wmOperatorType *ot)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2018-11-22 02:02:03 +01:00
|
|
|
ot->name = "Unlock Strips";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "SEQUENCER_OT_unlock";
|
2019-03-13 08:48:55 +11:00
|
|
|
ot->description = "Unlock strips so they can be transformed";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_unlock_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2024-08-22 14:54:42 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Connect Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static int sequencer_connect_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *active_seqbase = seq::active_seqbase_get(ed);
|
2024-08-22 14:54:42 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
blender::VectorSet<Strip *> selected = seq::query_selected_strips(active_seqbase);
|
2024-08-22 14:54:42 +02:00
|
|
|
|
|
|
|
|
if (selected.is_empty()) {
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
|
2025-03-06 13:04:39 +01:00
|
|
|
if (toggle && seq::are_strips_connected_together(selected)) {
|
|
|
|
|
seq::disconnect(selected);
|
2024-08-22 14:54:42 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::connect(selected);
|
2024-08-22 14:54:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_connect(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
ot->name = "Connect Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_connect";
|
|
|
|
|
ot->description = "Link selected strips together for simplified group selection";
|
|
|
|
|
|
|
|
|
|
ot->exec = sequencer_connect_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
|
|
|
|
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
RNA_def_boolean(ot->srna, "toggle", true, "Toggle", "Toggle strip connections");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Disconnect Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static int sequencer_disconnect_exec(bContext *C, wmOperator * /*op*/)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *active_seqbase = seq::active_seqbase_get(ed);
|
2024-08-22 14:54:42 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
blender::VectorSet<Strip *> selected = seq::query_selected_strips(active_seqbase);
|
2024-08-22 14:54:42 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::disconnect(selected)) {
|
2024-08-22 14:54:42 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
2025-01-26 20:08:00 +01:00
|
|
|
return OPERATOR_CANCELLED;
|
2024-08-22 14:54:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_disconnect(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
ot->name = "Disconnect Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_disconnect";
|
|
|
|
|
ot->description = "Unlink selected strips so that they can be selected individually";
|
|
|
|
|
|
|
|
|
|
ot->exec = sequencer_disconnect_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
|
|
|
|
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Reload Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2012-03-26 22:26:30 +00:00
|
|
|
static int sequencer_reload_exec(bContext *C, wmOperator *op)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2019-06-11 10:55:13 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2014-02-03 18:55:59 +11:00
|
|
|
const bool adjust_length = RNA_boolean_get(op->ptr, "adjust_length");
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
|
|
|
|
if (strip->flag & SELECT) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::add_reload_new_file(bmain, scene, strip, !adjust_length);
|
2025-01-07 14:09:45 +01:00
|
|
|
blender::seq::thumbnail_cache_invalidate_strip(scene, strip);
|
2012-03-26 22:26:30 +00:00
|
|
|
|
|
|
|
|
if (adjust_length) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, ed->seqbasep, strip)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(ed->seqbasep, strip, scene);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-03-26 22:26:30 +00:00
|
|
|
}
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_reload(wmOperatorType *ot)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2012-03-26 22:26:30 +00:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Reload Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_reload";
|
|
|
|
|
ot->description = "Reload strips in the sequencer";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_reload_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER; /* No undo, the data changed is stored outside 'main'. */
|
2012-03-26 13:48:45 +00:00
|
|
|
|
2012-04-14 15:44:31 +00:00
|
|
|
prop = RNA_def_boolean(ot->srna,
|
|
|
|
|
"adjust_length",
|
2023-07-22 11:36:59 +10:00
|
|
|
false,
|
2012-04-14 15:44:31 +00:00
|
|
|
"Adjust Length",
|
2012-05-16 14:25:25 +00:00
|
|
|
"Adjust length of strips to their data length");
|
2012-03-26 22:26:30 +00:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2012-03-26 13:48:45 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Refresh Sequencer Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool sequencer_refresh_all_poll(bContext *C)
|
2015-07-28 18:20:25 +02:00
|
|
|
{
|
|
|
|
|
if (G.is_rendering) {
|
2023-07-22 11:36:59 +10:00
|
|
|
return false;
|
2015-07-28 18:20:25 +02:00
|
|
|
}
|
|
|
|
|
return sequencer_edit_poll(C);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_refresh_all_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_free_imbuf(scene, &ed->seqbase, false);
|
2024-04-24 19:54:44 +02:00
|
|
|
blender::seq::media_presence_free(scene);
|
2024-09-12 14:48:20 +02:00
|
|
|
blender::seq::thumbnail_cache_clear(scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-01-25 14:53:41 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_refresh_all(wmOperatorType *ot)
|
2009-01-25 14:53:41 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Refresh Sequencer";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_refresh_all";
|
|
|
|
|
ot->description = "Refresh the sequencer editor";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_refresh_all_exec;
|
2015-07-28 18:20:25 +02:00
|
|
|
ot->poll = sequencer_refresh_all_poll;
|
2009-01-25 14:53:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Reassign Inputs Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
bool strip_effect_get_new_inputs(Scene *scene,
|
|
|
|
|
bool ignore_active,
|
|
|
|
|
int num_inputs,
|
|
|
|
|
Strip **r_seq1,
|
|
|
|
|
Strip **r_seq2,
|
|
|
|
|
const char **r_error_str)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2025-01-06 14:19:24 +01:00
|
|
|
Strip *seq1 = nullptr, *seq2 = nullptr;
|
2020-11-19 12:59:29 +01:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
*r_error_str = nullptr;
|
2020-11-19 12:59:29 +01:00
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (num_inputs == 0) {
|
|
|
|
|
*r_seq1 = *r_seq2 = nullptr;
|
|
|
|
|
return true;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
blender::VectorSet<Strip *> new_inputs = seq::query_selected_strips(ed->seqbasep);
|
2025-01-16 01:40:36 +01:00
|
|
|
// Ignore sound strips for now (avoids unnecessary errors when connected strips are
|
|
|
|
|
// selected together, and the intent to operate on strips with video content is clear).
|
|
|
|
|
new_inputs.remove_if([&](Strip *strip) { return strip->type == STRIP_TYPE_SOUND_RAM; });
|
2024-03-02 18:34:00 +01:00
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (ignore_active) {
|
|
|
|
|
// If `ignore_active` is true, this function is being called from the reassign inputs
|
|
|
|
|
// operator, meaning the active strip must be the effect strip to reassign.
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
2025-01-16 01:40:36 +01:00
|
|
|
new_inputs.remove_if([&](Strip *strip) { return strip == active_strip; });
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (new_inputs.size() > 2) {
|
|
|
|
|
*r_error_str = N_("Cannot apply effect to more than 2 sequence strips with video content");
|
|
|
|
|
return false;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (num_inputs == 2) {
|
|
|
|
|
if (new_inputs.size() != 2) {
|
|
|
|
|
*r_error_str = N_("Exactly 2 selected sequence strips with video content are needed");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
seq1 = new_inputs[0];
|
|
|
|
|
seq2 = new_inputs[1];
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
2025-01-16 01:40:36 +01:00
|
|
|
else if (num_inputs == 1) {
|
|
|
|
|
if (new_inputs.size() != 1) {
|
|
|
|
|
*r_error_str = N_("Exactly one selected sequence strip with video content is needed");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
seq1 = new_inputs[0];
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
*r_seq1 = seq1;
|
|
|
|
|
*r_seq2 = seq2;
|
|
|
|
|
|
|
|
|
|
return true;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-03 22:25:22 +00:00
|
|
|
static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-01-16 01:40:36 +01:00
|
|
|
Strip *seq1, *seq2;
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
2010-12-03 17:05:21 +00:00
|
|
|
const char *error_msg;
|
2025-03-06 13:04:39 +01:00
|
|
|
const int num_inputs = seq::effect_get_num_inputs(active_strip->type);
|
2010-07-03 22:25:22 +00:00
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (num_inputs == 0) {
|
2020-06-18 05:25:20 +02:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: strip has no inputs");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (!strip_effect_get_new_inputs(scene, true, num_inputs, &seq1, &seq2, &error_msg)) {
|
2010-07-03 22:25:22 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, error_msg);
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Check if reassigning would create recursivity. */
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::relations_render_loop_check(seq1, active_strip) ||
|
|
|
|
|
seq::relations_render_loop_check(seq2, active_strip))
|
2020-12-19 05:57:27 +01:00
|
|
|
{
|
2020-08-04 13:26:21 +02:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected");
|
2010-07-03 22:25:22 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
active_strip->seq1 = seq1;
|
|
|
|
|
active_strip->seq2 = seq2;
|
2010-07-03 22:25:22 +00:00
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
int old_start = active_strip->start;
|
2021-11-15 20:23:57 +01:00
|
|
|
|
2023-02-16 00:48:52 +01:00
|
|
|
/* Force time position update for reassigned effects.
|
|
|
|
|
* TODO(Richard): This is because internally startdisp is still used, due to poor performance of
|
|
|
|
|
* mapping effect range to inputs. This mapping could be cached though. */
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::strip_lookup_invalidate(scene->ed);
|
|
|
|
|
seq::time_left_handle_frame_set(scene, seq1, seq::time_left_handle_frame_get(scene, seq1));
|
2023-02-16 00:48:52 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, active_strip);
|
|
|
|
|
seq::offset_animdata(scene, active_strip, (active_strip->start - old_start));
|
2010-07-03 22:25:22 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2010-07-03 22:25:22 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool sequencer_effect_poll(bContext *C)
|
2010-07-03 22:25:22 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2010-07-03 22:25:22 +00:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (ed) {
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
2025-01-16 01:40:36 +01:00
|
|
|
if (active_strip && (active_strip->type & STRIP_TYPE_EFFECT)) {
|
2023-07-22 11:36:59 +10:00
|
|
|
return true;
|
2010-07-03 22:25:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
return false;
|
2010-07-03 22:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_reassign_inputs(wmOperatorType *ot)
|
2010-07-03 22:25:22 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Reassign Inputs";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_reassign_inputs";
|
|
|
|
|
ot->description = "Reassign the inputs for the effect strip";
|
2010-07-03 22:25:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_reassign_inputs_exec;
|
|
|
|
|
ot->poll = sequencer_effect_poll;
|
2010-07-03 22:25:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2010-07-03 22:25:22 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Swap Inputs Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2010-10-30 12:04:00 +00:00
|
|
|
static int sequencer_swap_inputs_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
2010-10-30 12:04:00 +00:00
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
if (active_strip->seq1 == nullptr || active_strip->seq2 == nullptr) {
|
2010-10-30 12:04:00 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No valid inputs to swap");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 01:40:36 +01:00
|
|
|
Strip *strip = active_strip->seq1;
|
|
|
|
|
active_strip->seq1 = active_strip->seq2;
|
|
|
|
|
active_strip->seq2 = strip;
|
2010-10-30 12:04:00 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, active_strip);
|
2010-10-30 12:04:00 +00:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2010-10-30 12:04:00 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_swap_inputs(wmOperatorType *ot)
|
2010-10-30 12:04:00 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Swap Inputs";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_swap_inputs";
|
2024-09-11 17:56:22 +02:00
|
|
|
ot->description = "Swap the two inputs of the effect strip";
|
2010-10-30 12:04:00 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_swap_inputs_exec;
|
|
|
|
|
ot->poll = sequencer_effect_poll;
|
2010-10-30 12:04:00 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2010-10-30 12:04:00 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Split Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
|
|
|
|
|
{
|
|
|
|
|
int mval[2];
|
|
|
|
|
float mouseloc[2];
|
|
|
|
|
|
|
|
|
|
mval[0] = mouse_x;
|
|
|
|
|
mval[1] = 0;
|
|
|
|
|
|
|
|
|
|
/* Choose the side based on which side of the current frame the mouse is on. */
|
|
|
|
|
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
return mouseloc[0] > frame ? seq::SIDE_RIGHT : seq::SIDE_LEFT;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2020-02-16 21:39:12 +01:00
|
|
|
static const EnumPropertyItem prop_split_types[] = {
|
2025-03-06 13:04:39 +01:00
|
|
|
{seq::SPLIT_SOFT, "SOFT", 0, "Soft", ""},
|
|
|
|
|
{seq::SPLIT_HARD, "HARD", 0, "Hard", ""},
|
2023-06-14 18:36:17 +02:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
};
|
|
|
|
|
|
2024-04-08 12:03:03 +10:00
|
|
|
const EnumPropertyItem prop_side_types[] = {
|
2025-03-06 13:04:39 +01:00
|
|
|
{seq::SIDE_MOUSE, "MOUSE", 0, "Mouse Position", ""},
|
|
|
|
|
{seq::SIDE_LEFT, "LEFT", 0, "Left", ""},
|
|
|
|
|
{seq::SIDE_RIGHT, "RIGHT", 0, "Right", ""},
|
|
|
|
|
{seq::SIDE_BOTH, "BOTH", 0, "Both", ""},
|
|
|
|
|
{seq::SIDE_NO_CHANGE, "NO_CHANGE", 0, "No Change", ""},
|
2023-06-14 18:36:17 +02:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2020-11-19 12:59:29 +01:00
|
|
|
};
|
|
|
|
|
|
2023-10-02 16:20:31 +02:00
|
|
|
/* Get the splitting side for the Split Strips's operator exec() callback. */
|
|
|
|
|
static int sequence_split_side_for_exec_get(wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
const int split_side = RNA_enum_get(op->ptr, "side");
|
|
|
|
|
|
|
|
|
|
/* The mouse position can not be resolved from the exec() as the mouse coordinate is not
|
|
|
|
|
* accessible. So fall-back to the RIGHT side instead.
|
|
|
|
|
*
|
|
|
|
|
* The SEQ_SIDE_MOUSE is used by the Strip menu, together with the EXEC_DEFAULT operator
|
|
|
|
|
* context in order to have properly resolved shortcut in the menu. */
|
2025-03-06 13:04:39 +01:00
|
|
|
if (split_side == seq::SIDE_MOUSE) {
|
|
|
|
|
return seq::SIDE_RIGHT;
|
2023-10-02 16:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return split_side;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-16 21:39:12 +01:00
|
|
|
static int sequencer_split_exec(bContext *C, wmOperator *op)
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
{
|
2019-06-11 10:55:13 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2020-11-19 05:26:57 +01:00
|
|
|
bool changed = false;
|
2025-01-07 16:03:11 +01:00
|
|
|
bool strip_selected = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-19 05:26:57 +01:00
|
|
|
const bool use_cursor_position = RNA_boolean_get(op->ptr, "use_cursor_position");
|
2023-10-02 16:20:31 +02:00
|
|
|
|
2023-11-16 10:40:37 +01:00
|
|
|
const int split_frame = RNA_struct_property_is_set(op->ptr, "frame") ?
|
|
|
|
|
RNA_int_get(op->ptr, "frame") :
|
|
|
|
|
scene->r.cfra;
|
|
|
|
|
const int split_channel = RNA_int_get(op->ptr, "channel");
|
2023-10-02 16:20:31 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
const seq::eSplitMethod method = seq::eSplitMethod(RNA_enum_get(op->ptr, "type"));
|
2023-10-02 16:20:31 +02:00
|
|
|
const int split_side = sequence_split_side_for_exec_get(op);
|
2020-11-19 05:26:57 +01:00
|
|
|
const bool ignore_selection = RNA_boolean_get(op->ptr, "ignore_selection");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::prefetch_stop(scene);
|
2020-07-29 15:02:44 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH_BACKWARD (Strip *, strip, ed->seqbasep) {
|
|
|
|
|
if (use_cursor_position && strip->machine != split_channel) {
|
2020-11-19 05:26:57 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
if (ignore_selection || strip->flag & SELECT) {
|
2023-06-14 18:36:17 +02:00
|
|
|
const char *error_msg = nullptr;
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::edit_strip_split(
|
2025-01-07 14:09:45 +01:00
|
|
|
bmain, scene, ed->seqbasep, strip, split_frame, method, &error_msg) != nullptr)
|
2023-06-14 18:36:17 +02:00
|
|
|
{
|
2020-11-19 05:26:57 +01:00
|
|
|
changed = true;
|
|
|
|
|
}
|
2023-06-14 18:36:17 +02:00
|
|
|
if (error_msg != nullptr) {
|
2021-08-24 00:52:24 +02:00
|
|
|
BKE_report(op->reports, RPT_ERROR, error_msg);
|
|
|
|
|
}
|
2020-11-19 05:26:57 +01:00
|
|
|
}
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
2020-11-19 05:26:57 +01:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
if (changed) { /* Got new strips? */
|
2020-01-22 14:54:44 +01:00
|
|
|
if (ignore_selection) {
|
|
|
|
|
if (use_cursor_position) {
|
2025-03-06 13:04:39 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, seq::active_seqbase_get(ed)) {
|
|
|
|
|
if (seq::time_right_handle_frame_get(scene, strip) == split_frame &&
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->machine == split_channel)
|
2024-01-02 18:12:54 +01:00
|
|
|
{
|
2025-01-07 16:33:39 +01:00
|
|
|
strip_selected = strip->flag & STRIP_ALLSEL;
|
2009-01-31 09:58:38 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2025-01-07 16:03:11 +01:00
|
|
|
if (!strip_selected) {
|
2025-03-06 13:04:39 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, seq::active_seqbase_get(ed)) {
|
|
|
|
|
if (seq::time_left_handle_frame_get(scene, strip) == split_frame &&
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->machine == split_channel)
|
2024-01-02 18:12:54 +01:00
|
|
|
{
|
2025-01-07 16:33:39 +01:00
|
|
|
strip->flag &= ~STRIP_ALLSEL;
|
2020-01-22 14:54:44 +01:00
|
|
|
}
|
2009-01-31 09:58:38 +00:00
|
|
|
}
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-22 14:54:44 +01:00
|
|
|
else {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (split_side != seq::SIDE_BOTH) {
|
|
|
|
|
LISTBASE_FOREACH (Strip *, strip, seq::active_seqbase_get(ed)) {
|
|
|
|
|
if (split_side == seq::SIDE_LEFT) {
|
|
|
|
|
if (seq::time_left_handle_frame_get(scene, strip) >= split_frame) {
|
2025-01-07 16:33:39 +01:00
|
|
|
strip->flag &= ~STRIP_ALLSEL;
|
2020-01-22 14:54:44 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::time_right_handle_frame_get(scene, strip) <= split_frame) {
|
2025-01-07 16:33:39 +01:00
|
|
|
strip->flag &= ~STRIP_ALLSEL;
|
2020-01-22 14:54:44 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
if (changed) {
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2011-09-20 08:48:48 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
2020-07-03 17:20:58 +02:00
|
|
|
|
|
|
|
|
/* Passthrough to selection if used as tool. */
|
|
|
|
|
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
|
|
|
|
|
2020-02-16 21:39:12 +01:00
|
|
|
static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
{
|
2009-01-24 06:08:46 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2012-03-29 22:26:11 +00:00
|
|
|
View2D *v2d = UI_view2d_fromcontext(C);
|
2010-05-19 08:44:38 +00:00
|
|
|
|
2020-02-16 21:39:12 +01:00
|
|
|
int split_side = RNA_enum_get(op->ptr, "side");
|
2022-06-30 18:36:42 +02:00
|
|
|
int split_frame = scene->r.cfra;
|
2010-05-19 08:44:38 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
if (split_side == seq::SIDE_MOUSE) {
|
2018-09-05 11:56:31 +10:00
|
|
|
if (ED_operator_sequencer_active(C) && v2d) {
|
2020-02-16 21:39:12 +01:00
|
|
|
split_side = mouse_frame_side(v2d, event->mval[0], split_frame);
|
2018-09-05 11:56:31 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2025-03-06 13:04:39 +01:00
|
|
|
split_side = seq::SIDE_BOTH;
|
2018-09-05 11:56:31 +10:00
|
|
|
}
|
|
|
|
|
}
|
2020-01-22 14:54:44 +01:00
|
|
|
float mouseloc[2];
|
2023-04-30 14:52:54 +10:00
|
|
|
if (v2d) {
|
|
|
|
|
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
|
|
|
|
|
if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
|
|
|
|
|
split_frame = mouseloc[0];
|
|
|
|
|
}
|
|
|
|
|
RNA_int_set(op->ptr, "channel", mouseloc[1]);
|
2020-01-22 14:54:44 +01:00
|
|
|
}
|
2023-04-30 14:52:54 +10:00
|
|
|
RNA_int_set(op->ptr, "frame", split_frame);
|
2020-02-16 21:39:12 +01:00
|
|
|
RNA_enum_set(op->ptr, "side", split_side);
|
2022-01-14 10:47:50 +11:00
|
|
|
// RNA_enum_set(op->ptr, "type", split_hard);
|
2020-04-05 23:55:51 +02:00
|
|
|
|
2020-02-16 21:39:12 +01:00
|
|
|
return sequencer_split_exec(C, op);
|
2009-01-12 19:02:08 +00:00
|
|
|
}
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static void sequencer_split_ui(bContext * /*C*/, wmOperator *op)
|
2020-08-19 13:36:55 +02:00
|
|
|
{
|
|
|
|
|
uiLayout *layout = op->layout;
|
|
|
|
|
uiLayoutSetPropSep(layout, true);
|
|
|
|
|
uiLayoutSetPropDecorate(layout, false);
|
|
|
|
|
|
|
|
|
|
uiLayout *row = uiLayoutRow(layout, false);
|
2024-12-06 14:08:10 +01:00
|
|
|
uiItemR(row, op->ptr, "type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
|
|
|
|
|
uiItemR(layout, op->ptr, "frame", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
|
|
|
|
uiItemR(layout, op->ptr, "side", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
2020-08-19 13:36:55 +02:00
|
|
|
|
|
|
|
|
uiItemS(layout);
|
|
|
|
|
|
2024-12-06 14:08:10 +01:00
|
|
|
uiItemR(layout, op->ptr, "use_cursor_position", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
2021-04-20 00:13:26 +10:00
|
|
|
if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
|
2024-12-06 14:08:10 +01:00
|
|
|
uiItemR(layout, op->ptr, "channel", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
2020-08-19 13:36:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_split(wmOperatorType *ot)
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2020-02-16 21:39:12 +01:00
|
|
|
ot->name = "Split Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_split";
|
|
|
|
|
ot->description = "Split the selected strips in two";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2020-02-16 21:39:12 +01:00
|
|
|
ot->invoke = sequencer_split_invoke;
|
|
|
|
|
ot->exec = sequencer_split_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = sequencer_edit_poll;
|
2020-08-19 13:36:55 +02:00
|
|
|
ot->ui = sequencer_split_ui;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-09-05 11:56:31 +10:00
|
|
|
PropertyRNA *prop;
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
RNA_def_int(ot->srna,
|
|
|
|
|
"frame",
|
|
|
|
|
0,
|
|
|
|
|
INT_MIN,
|
|
|
|
|
INT_MAX,
|
|
|
|
|
"Frame",
|
2020-02-16 21:39:12 +01:00
|
|
|
"Frame where selected strips will be split",
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
INT_MIN,
|
|
|
|
|
INT_MAX);
|
2020-01-22 14:54:44 +01:00
|
|
|
RNA_def_int(ot->srna,
|
|
|
|
|
"channel",
|
|
|
|
|
0,
|
|
|
|
|
INT_MIN,
|
|
|
|
|
INT_MAX,
|
|
|
|
|
"Channel",
|
|
|
|
|
"Channel in which strip will be cut",
|
|
|
|
|
INT_MIN,
|
|
|
|
|
INT_MAX);
|
2009-09-12 17:16:12 +00:00
|
|
|
RNA_def_enum(ot->srna,
|
|
|
|
|
"type",
|
2020-02-16 21:39:12 +01:00
|
|
|
prop_split_types,
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::SPLIT_SOFT,
|
2009-09-12 17:16:12 +00:00
|
|
|
"Type",
|
2020-02-16 21:39:12 +01:00
|
|
|
"The type of split operation to perform on strips");
|
|
|
|
|
|
2020-01-22 14:54:44 +01:00
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
|
"use_cursor_position",
|
2023-07-22 11:36:59 +10:00
|
|
|
false,
|
2020-01-22 14:54:44 +01:00
|
|
|
"Use Cursor Position",
|
2020-06-01 14:41:12 +10:00
|
|
|
"Split at position of the cursor instead of current frame");
|
2020-02-16 21:39:12 +01:00
|
|
|
|
2018-09-05 11:56:31 +10:00
|
|
|
prop = RNA_def_enum(ot->srna,
|
|
|
|
|
"side",
|
|
|
|
|
prop_side_types,
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::SIDE_MOUSE,
|
2018-09-05 11:56:31 +10:00
|
|
|
"Side",
|
2020-02-16 21:39:12 +01:00
|
|
|
"The side that remains selected after splitting");
|
2020-01-22 14:54:44 +01:00
|
|
|
|
2018-09-05 11:56:31 +10:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2020-01-22 14:54:44 +01:00
|
|
|
|
|
|
|
|
prop = RNA_def_boolean(
|
|
|
|
|
ot->srna,
|
|
|
|
|
"ignore_selection",
|
|
|
|
|
false,
|
|
|
|
|
"Ignore Selection",
|
2023-07-24 21:22:07 +02:00
|
|
|
"Make cut even if strip is not selected preserving selection state after cut");
|
2020-01-22 14:54:44 +01:00
|
|
|
|
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN);
|
Added back some functionality to the sequencer
- removed static vars _last_seq, last_imagename and last_sounddir, replacing them with with vars in the "Editing" struct. didnt manage to get the active sequence to load so currently thats lost when loading.
- removed flag SEQ_ACTIVE
- Added operators cut, mute, unmute, deselect_all, select_invert, select, select_more, select_less, select_pick_linked, select_linked and borderselect.
2009-01-19 21:42:18 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Duplicate Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_add_duplicate_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-21 18:47:09 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2024-12-17 15:52:23 +01:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (ed == nullptr) {
|
2009-01-28 22:36:34 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *active_seq = seq::select_active_get(scene);
|
2023-06-14 18:36:17 +02:00
|
|
|
ListBase duplicated_strips = {nullptr, nullptr};
|
2021-06-02 21:36:09 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::sequence_base_dupli_recursive(scene, scene, &duplicated_strips, ed->seqbasep, 0, 0);
|
|
|
|
|
deselect_all_strips(scene);
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (duplicated_strips.first == nullptr) {
|
2022-01-19 14:12:23 +01:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2010-02-16 17:58:50 +00:00
|
|
|
|
2022-01-19 14:12:23 +01:00
|
|
|
/* Duplicate animation.
|
|
|
|
|
* First backup original curves from scene and duplicate strip curves from backup into scene.
|
|
|
|
|
* This way, when pasted strips are renamed, curves are renamed with them. Finally, restore
|
|
|
|
|
* original curves from backup.
|
|
|
|
|
*/
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::AnimationBackup animation_backup = {{nullptr}};
|
|
|
|
|
seq::animation_backup_original(scene, &animation_backup);
|
2022-01-19 14:12:23 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *seqbase = seq::active_seqbase_get(seq::editing_get(scene));
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip *strip_last = static_cast<Strip *>(seqbase->last);
|
2022-01-19 14:12:23 +01:00
|
|
|
|
2023-12-10 16:33:54 +11:00
|
|
|
/* Rely on the `duplicated_strips` list being added at the end.
|
2024-01-22 13:47:13 +01:00
|
|
|
* Their UIDs has been re-generated by the #SEQ_sequence_base_dupli_recursive(). */
|
2022-01-19 14:12:23 +01:00
|
|
|
BLI_movelisttolist(ed->seqbasep, &duplicated_strips);
|
|
|
|
|
|
|
|
|
|
/* Handle duplicated strips: set active, select, ensure unique name and duplicate animation
|
|
|
|
|
* data. */
|
2025-01-07 16:03:11 +01:00
|
|
|
for (Strip *strip = strip_last->next; strip; strip = strip->next) {
|
2025-01-07 14:09:45 +01:00
|
|
|
if (active_seq != nullptr && STREQ(strip->name, active_seq->name)) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::select_active_set(scene, strip);
|
2022-01-19 14:12:23 +01:00
|
|
|
}
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK);
|
|
|
|
|
strip->flag |= SEQ_IGNORE_CHANNEL_LOCK;
|
2023-01-28 03:24:44 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::animation_duplicate_backup_to_scene(scene, strip, &animation_backup);
|
|
|
|
|
seq::ensure_unique_name(strip, scene);
|
2010-02-16 17:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
2024-12-17 15:52:23 +01:00
|
|
|
/* Special case for duplicating strips in preview: Do not duplicate sound strips and handle
|
|
|
|
|
* overlap, because strips won't be translated. */
|
|
|
|
|
if (region->regiontype == RGN_TYPE_PREVIEW && sequencer_view_preview_only_poll(C)) {
|
2025-01-07 16:03:11 +01:00
|
|
|
for (Strip *strip = strip_last->next; strip; strip = strip->next) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->type == STRIP_TYPE_SOUND_RAM) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::edit_flag_for_removal(scene, ed->seqbasep, strip);
|
2024-12-17 15:52:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::edit_remove_flagged_sequences(scene, ed->seqbasep);
|
2024-12-17 15:52:23 +01:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
for (Strip *strip = strip_last->next; strip; strip = strip->next) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, ed->seqbasep, strip)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(ed->seqbasep, strip, scene);
|
2024-12-17 15:52:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::animation_restore_original(scene, &animation_backup);
|
2022-01-19 14:12:23 +01:00
|
|
|
|
2023-01-28 03:24:44 +01:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
|
|
|
|
DEG_relations_tag_update(CTX_data_main(C));
|
2022-01-19 14:12:23 +01:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
2009-01-21 18:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-08 21:41:35 +00:00
|
|
|
void SEQUENCER_OT_duplicate(wmOperatorType *ot)
|
2009-01-21 18:47:09 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Duplicate Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_duplicate";
|
|
|
|
|
ot->description = "Duplicate the selected strips";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_add_duplicate_exec;
|
|
|
|
|
ot->poll = ED_operator_sequencer_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-01-21 18:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Erase Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
static void sequencer_delete_strip_data(bContext *C, Strip *strip)
|
2022-05-16 20:19:33 +02:00
|
|
|
{
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->type != STRIP_TYPE_SCENE) {
|
2022-05-16 20:19:33 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Main *bmain = CTX_data_main(C);
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip->scene) {
|
|
|
|
|
if (ED_scene_delete(C, bmain, strip->scene)) {
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, strip->scene);
|
2022-05-16 20:19:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sequencer_delete_exec(bContext *C, wmOperator *op)
|
2009-01-21 18:47:09 +00:00
|
|
|
{
|
2019-06-07 11:27:34 +02:00
|
|
|
Main *bmain = CTX_data_main(C);
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *seqbasep = seq::active_seqbase_get(seq::editing_get(scene));
|
2022-05-16 20:19:33 +02:00
|
|
|
const bool delete_data = RNA_boolean_get(op->ptr, "delete_data");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-01 12:30:57 +01:00
|
|
|
if (sequencer_view_has_preview_poll(C) && !sequencer_view_preview_only_poll(C)) {
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::prefetch_stop(scene);
|
2020-08-05 01:40:02 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
for (Strip *strip : selected_strips_from_context(C)) {
|
|
|
|
|
seq::edit_flag_for_removal(scene, seqbasep, strip);
|
2022-05-16 20:19:33 +02:00
|
|
|
if (delete_data) {
|
2025-01-07 14:09:45 +01:00
|
|
|
sequencer_delete_strip_data(C, strip);
|
2022-05-16 20:19:33 +02:00
|
|
|
}
|
2014-02-20 13:52:49 +06:00
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::edit_remove_flagged_sequences(scene, seqbasep);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-04 16:52:48 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2024-10-07 13:31:14 +02:00
|
|
|
if (scene->adt && scene->adt->action) {
|
|
|
|
|
DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
|
|
|
|
|
}
|
2019-06-07 11:27:34 +02:00
|
|
|
DEG_relations_tag_update(bmain);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2024-10-07 13:31:14 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_ANIMCHAN, scene);
|
2009-01-21 18:47:09 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2012-08-27 09:15:48 +00:00
|
|
|
{
|
2022-06-30 20:41:09 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
|
ListBase *markers = &scene->markers;
|
2012-08-27 09:15:48 +00:00
|
|
|
|
2023-04-30 14:52:54 +10:00
|
|
|
if (!BLI_listbase_is_empty(markers)) {
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
if (region && (region->regiontype == RGN_TYPE_WINDOW)) {
|
|
|
|
|
/* Bounding box of 30 pixels is used for markers shortcuts,
|
|
|
|
|
* prevent conflict with markers shortcuts here. */
|
|
|
|
|
if (event->mval[1] <= 30) {
|
|
|
|
|
return OPERATOR_PASS_THROUGH;
|
|
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-08-27 09:15:48 +00:00
|
|
|
}
|
|
|
|
|
|
2020-05-29 09:53:52 -04:00
|
|
|
return sequencer_delete_exec(C, op);
|
2012-08-27 09:15:48 +00:00
|
|
|
}
|
2009-01-21 18:47:09 +00:00
|
|
|
|
|
|
|
|
void SEQUENCER_OT_delete(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2023-04-30 15:10:49 +10:00
|
|
|
ot->name = "Delete Strips";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "SEQUENCER_OT_delete";
|
2023-04-30 15:10:49 +10:00
|
|
|
ot->description = "Delete selected strips from the sequencer";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-08-27 09:15:48 +00:00
|
|
|
ot->invoke = sequencer_delete_invoke;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_delete_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2022-05-16 20:19:33 +02:00
|
|
|
|
|
|
|
|
/* Properties. */
|
|
|
|
|
ot->prop = RNA_def_boolean(ot->srna,
|
|
|
|
|
"delete_data",
|
|
|
|
|
false,
|
|
|
|
|
"Delete Data",
|
|
|
|
|
"After removing the Strip, delete the associated data also");
|
|
|
|
|
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
|
2009-01-21 18:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Clear Strip Offset Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_offset_clear_exec(bContext *C, wmOperator * /*op*/)
|
2011-08-14 03:59:22 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip;
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *channels = seq::channels_displayed_get(seq::editing_get(scene));
|
2011-08-14 03:59:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* For effects, try to find a replacement input. */
|
2025-01-07 14:09:45 +01:00
|
|
|
for (strip = static_cast<Strip *>(ed->seqbasep->first); strip;
|
|
|
|
|
strip = static_cast<Strip *>(strip->next))
|
2023-06-14 18:36:17 +02:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_is_locked(channels, strip)) {
|
2023-08-14 05:51:29 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-07 16:10:36 +01:00
|
|
|
if ((strip->type & STRIP_TYPE_EFFECT) == 0 && (strip->flag & SELECT)) {
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->startofs = strip->endofs = 0;
|
2011-08-14 03:59:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Update lengths, etc. */
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = static_cast<Strip *>(ed->seqbasep->first);
|
|
|
|
|
while (strip) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = strip->next;
|
2011-08-14 03:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
for (strip = static_cast<Strip *>(ed->seqbasep->first); strip;
|
|
|
|
|
strip = static_cast<Strip *>(strip->next))
|
2023-06-14 18:36:17 +02:00
|
|
|
{
|
2025-01-07 16:10:36 +01:00
|
|
|
if ((strip->type & STRIP_TYPE_EFFECT) == 0 && (strip->flag & SELECT)) {
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, ed->seqbasep, strip)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(ed->seqbasep, strip, scene);
|
2011-08-14 03:59:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2011-08-14 03:59:22 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_offset_clear(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Clear Strip Offset";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_offset_clear";
|
|
|
|
|
ot->description = "Clear strip offsets from the start and end frames";
|
2011-08-14 03:59:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_offset_clear_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2011-08-14 03:59:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-08-14 03:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Separate Images Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2009-01-21 18:47:09 +00:00
|
|
|
static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *seqbase = seq::active_seqbase_get(ed);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip, *strip_new;
|
2024-12-20 18:02:31 +01:00
|
|
|
StripData *data_new;
|
2009-01-21 18:47:09 +00:00
|
|
|
StripElem *se, *se_new;
|
2020-11-06 14:10:59 +01:00
|
|
|
int start_ofs, timeline_frame, frame_end;
|
2012-03-29 22:26:11 +00:00
|
|
|
int step = RNA_int_get(op->ptr, "length");
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = static_cast<Strip *>(seqbase->first); /* Poll checks this is valid. */
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::prefetch_stop(scene);
|
2020-08-17 20:19:11 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
while (strip) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if ((strip->flag & SELECT) && (strip->type == STRIP_TYPE_IMAGE) && (strip->len > 1)) {
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip_next;
|
2014-03-18 22:45:33 +06:00
|
|
|
|
2021-07-01 10:25:35 +10:00
|
|
|
/* TODO: remove f-curve and assign to split image strips.
|
2025-01-07 14:09:45 +01:00
|
|
|
* The old animation system would remove the user of `strip->ipo`. */
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
start_ofs = timeline_frame = seq::time_left_handle_frame_get(scene, strip);
|
|
|
|
|
frame_end = seq::time_right_handle_frame_get(scene, strip);
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2020-11-06 14:10:59 +01:00
|
|
|
while (timeline_frame < frame_end) {
|
2025-01-07 14:09:45 +01:00
|
|
|
/* New strip. */
|
2025-03-06 13:04:39 +01:00
|
|
|
se = seq::render_give_stripelem(scene, strip, timeline_frame);
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
strip_new = seq::sequence_dupli_recursive(
|
2025-01-07 16:33:39 +01:00
|
|
|
scene, scene, seqbase, strip, STRIP_DUPE_UNIQUE_NAME);
|
2011-07-06 10:58:23 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip_new->start = start_ofs;
|
2025-01-07 16:10:36 +01:00
|
|
|
strip_new->type = STRIP_TYPE_IMAGE;
|
2025-01-07 14:09:45 +01:00
|
|
|
strip_new->len = 1;
|
|
|
|
|
strip_new->flag |= SEQ_SINGLE_FRAME_CONTENT;
|
|
|
|
|
strip_new->endofs = 1 - step;
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* New strip. */
|
2025-01-07 14:09:45 +01:00
|
|
|
data_new = strip_new->data;
|
2024-12-20 18:02:31 +01:00
|
|
|
data_new->us = 1;
|
2009-01-21 18:47:09 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* New stripdata, only one element now. */
|
2019-01-15 23:24:20 +11:00
|
|
|
/* Note this assume all elements (images) have the same dimension,
|
|
|
|
|
* since we only copy the name here. */
|
2024-12-20 18:02:31 +01:00
|
|
|
se_new = static_cast<StripElem *>(MEM_reallocN(data_new->stripdata, sizeof(*se_new)));
|
2023-05-13 17:34:29 +10:00
|
|
|
STRNCPY(se_new->filename, se->filename);
|
2024-12-20 18:02:31 +01:00
|
|
|
data_new->stripdata = se_new;
|
2014-07-21 22:55:06 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (step > 1) {
|
2025-01-07 14:09:45 +01:00
|
|
|
strip_new->flag &= ~SEQ_OVERLAP;
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, seqbase, strip_new)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(seqbase, strip_new, scene);
|
2010-07-03 17:47:06 +00:00
|
|
|
}
|
2009-01-21 18:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
2010-07-03 17:47:06 +00:00
|
|
|
/* XXX, COPY FCURVES */
|
2009-12-13 03:20:29 +00:00
|
|
|
|
2020-11-06 14:10:59 +01:00
|
|
|
timeline_frame++;
|
2009-01-21 18:47:09 +00:00
|
|
|
start_ofs += step;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip_next = static_cast<Strip *>(strip->next);
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::edit_flag_for_removal(scene, seqbase, strip);
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = strip_next;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = strip->next;
|
2009-01-21 18:47:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::edit_remove_flagged_sequences(scene, seqbase);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-01-21 18:47:09 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 16:29:19 +02:00
|
|
|
static int sequencer_separate_images_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
return WM_operator_props_popup_confirm_ex(
|
|
|
|
|
C, op, event, IFACE_("Separate Sequence Images"), IFACE_("Separate"));
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-12 20:32:42 +00:00
|
|
|
void SEQUENCER_OT_images_separate(wmOperatorType *ot)
|
2009-01-21 18:47:09 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Separate Images";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_images_separate";
|
|
|
|
|
ot->description = "On image sequence strips, it returns a strip for each image";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_separate_images_exec;
|
2024-05-01 16:29:19 +02:00
|
|
|
ot->invoke = sequencer_separate_images_invoke;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-10-19 21:34:38 +00:00
|
|
|
|
2012-10-11 23:46:12 +00:00
|
|
|
RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000);
|
2009-01-21 18:47:09 +00:00
|
|
|
}
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Toggle Meta Strip Operator
|
|
|
|
|
* \{ */
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_meta_toggle_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-23 23:14:02 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::prefetch_stop(scene);
|
2022-01-11 06:12:15 +01:00
|
|
|
|
2025-01-07 16:10:36 +01:00
|
|
|
if (active_strip && active_strip->type == STRIP_TYPE_META && active_strip->flag & SELECT) {
|
2025-01-07 14:09:45 +01:00
|
|
|
/* Deselect active meta strip. */
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::select_active_set(scene, nullptr);
|
|
|
|
|
seq::meta_stack_set(scene, active_strip);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2021-05-14 17:35:22 +10:00
|
|
|
/* Exit meta-strip if possible. */
|
2009-01-23 23:14:02 +00:00
|
|
|
if (BLI_listbase_is_empty(&ed->metastack)) {
|
|
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2022-06-27 19:29:41 +02:00
|
|
|
/* Display parent meta. */
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *meta_parent = seq::meta_stack_pop(ed);
|
|
|
|
|
seq::select_active_set(scene, meta_parent);
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 17:39:23 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-12-08 13:57:51 +00:00
|
|
|
|
2009-01-23 23:14:02 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Toggle Meta Strip";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_meta_toggle";
|
2021-05-14 17:35:22 +10:00
|
|
|
ot->description = "Toggle a meta-strip (to edit enclosed strips)";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_meta_toggle_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Make Meta Strip Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-01-11 20:45:46 +01:00
|
|
|
static int sequencer_meta_make_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-23 23:14:02 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
|
|
|
|
ListBase *active_seqbase = seq::active_seqbase_get(ed);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
blender::VectorSet<Strip *> selected = seq::query_selected_strips(active_seqbase);
|
2025-01-11 20:45:46 +01:00
|
|
|
|
|
|
|
|
if (selected.is_empty()) {
|
2009-01-23 23:14:02 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::prefetch_stop(scene);
|
2020-08-17 20:19:11 +02:00
|
|
|
|
2024-06-26 06:10:14 +02:00
|
|
|
int channel_max = 1, channel_min = INT_MAX, meta_start_frame = MAXFRAME,
|
|
|
|
|
meta_end_frame = MINFRAME;
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *seqm = seq::sequence_alloc(active_seqbase, 1, 1, STRIP_TYPE_META);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2021-03-02 12:34:03 +01:00
|
|
|
/* Remove all selected from main list, and put in meta.
|
2024-01-22 13:47:13 +01:00
|
|
|
* Sequence is moved within the same edit, no need to re-generate the UID. */
|
2025-01-06 14:19:24 +01:00
|
|
|
blender::VectorSet<Strip *> strips_to_move;
|
2025-01-11 20:45:46 +01:00
|
|
|
strips_to_move.add_multiple(selected);
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::iterator_set_expand(
|
|
|
|
|
scene, active_seqbase, strips_to_move, seq::query_strip_connected_and_effect_chain);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
for (Strip *strip : strips_to_move) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2025-01-07 14:09:45 +01:00
|
|
|
BLI_remlink(active_seqbase, strip);
|
|
|
|
|
BLI_addtail(&seqm->seqbase, strip);
|
|
|
|
|
channel_max = max_ii(strip->machine, channel_max);
|
|
|
|
|
channel_min = min_ii(strip->machine, channel_min);
|
2025-03-06 13:04:39 +01:00
|
|
|
meta_start_frame = min_ii(seq::time_left_handle_frame_get(scene, strip), meta_start_frame);
|
|
|
|
|
meta_end_frame = max_ii(seq::time_right_handle_frame_get(scene, strip), meta_end_frame);
|
2024-09-23 18:51:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *channels_cur = seq::channels_displayed_get(ed);
|
2024-06-26 06:10:14 +02:00
|
|
|
ListBase *channels_meta = &seqm->channels;
|
|
|
|
|
for (int i = channel_min; i <= channel_max; i++) {
|
2025-03-06 13:04:39 +01:00
|
|
|
SeqTimelineChannel *channel_cur = seq::channel_get_by_index(channels_cur, i);
|
|
|
|
|
SeqTimelineChannel *channel_meta = seq::channel_get_by_index(channels_meta, i);
|
2024-07-07 00:03:57 +10:00
|
|
|
STRNCPY(channel_meta->name, channel_cur->name);
|
2024-06-26 06:10:14 +02:00
|
|
|
channel_meta->flag = channel_cur->flag;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
seqm->machine = active_strip ? active_strip->machine : channel_max;
|
2024-07-07 12:27:30 +02:00
|
|
|
BLI_strncpy(seqm->name + 2, DATA_("MetaStrip"), sizeof(seqm->name) - 2);
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::sequence_base_unique_name_recursive(scene, &ed->seqbase, seqm);
|
2021-03-02 12:34:03 +01:00
|
|
|
seqm->start = meta_start_frame;
|
|
|
|
|
seqm->len = meta_end_frame - meta_start_frame;
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::select_active_set(scene, seqm);
|
|
|
|
|
if (seq::transform_test_overlap(scene, active_seqbase, seqm)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(active_seqbase, seqm, scene);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::strip_lookup_invalidate(ed);
|
2019-06-04 16:52:48 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-12-08 13:57:51 +00:00
|
|
|
|
2009-01-23 23:14:02 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_meta_make(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Make Meta Strip";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_meta_make";
|
2021-05-14 17:35:22 +10:00
|
|
|
ot->description = "Group selected strips into a meta-strip";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_meta_make_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name UnMeta Strip Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_meta_separate_exec(bContext *C, wmOperator * /*op*/)
|
2009-01-23 23:14:02 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
Strip *active_strip = seq::select_active_get(scene);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2025-01-07 16:10:36 +01:00
|
|
|
if (active_strip == nullptr || active_strip->type != STRIP_TYPE_META) {
|
2009-01-23 23:14:02 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::prefetch_stop(scene);
|
2020-08-17 20:19:11 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, &active_strip->seqbase) {
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2014-06-04 22:05:33 +06:00
|
|
|
}
|
|
|
|
|
|
2021-03-02 12:34:03 +01:00
|
|
|
/* Remove all selected from meta, and put in main list.
|
2024-01-22 13:47:13 +01:00
|
|
|
* Sequence is moved within the same edit, no need to re-generate the UID. */
|
2025-01-07 14:09:45 +01:00
|
|
|
BLI_movelisttolist(ed->seqbasep, &active_strip->seqbase);
|
|
|
|
|
BLI_listbase_clear(&active_strip->seqbase);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *active_seqbase = seq::active_seqbase_get(ed);
|
|
|
|
|
seq::edit_flag_for_removal(scene, active_seqbase, active_strip);
|
|
|
|
|
seq::edit_remove_flagged_sequences(scene, active_seqbase);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
2021-03-02 12:34:03 +01:00
|
|
|
/* Test for effects and overlap. */
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, active_seqbase) {
|
|
|
|
|
if (strip->flag & SELECT) {
|
|
|
|
|
strip->flag &= ~SEQ_OVERLAP;
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, active_seqbase, strip)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(active_seqbase, strip, scene);
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-04 16:52:48 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-01-23 23:14:02 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "UnMeta Strip";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_meta_separate";
|
2021-05-14 17:35:22 +10:00
|
|
|
ot->description = "Put the contents of a meta-strip back in the sequencer";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_meta_separate_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-01-23 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Jump to Strip Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
static bool strip_jump_internal(Scene *scene,
|
|
|
|
|
const short side,
|
2014-02-03 18:55:59 +11:00
|
|
|
const bool do_skip_mute,
|
|
|
|
|
const bool do_center)
|
2009-10-29 10:03:34 +00:00
|
|
|
{
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2022-06-30 18:36:42 +02:00
|
|
|
int timeline_frame = scene->r.cfra;
|
2025-03-06 13:04:39 +01:00
|
|
|
int next_frame = seq::time_find_next_prev_edit(
|
2020-11-06 14:10:59 +01:00
|
|
|
scene, timeline_frame, side, do_skip_mute, do_center, false);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-11-06 14:10:59 +01:00
|
|
|
if (next_frame != timeline_frame) {
|
2022-06-30 18:36:42 +02:00
|
|
|
scene->r.cfra = next_frame;
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2009-10-28 19:53:25 +00:00
|
|
|
}
|
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2009-10-28 19:53:25 +00:00
|
|
|
}
|
|
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool sequencer_strip_jump_poll(bContext *C)
|
2012-12-06 05:48:51 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Prevent changes during render. */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (G.is_rendering) {
|
2023-07-22 11:36:59 +10:00
|
|
|
return false;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-12-06 05:48:51 +00:00
|
|
|
|
|
|
|
|
return sequencer_edit_poll(C);
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-23 07:39:51 +00:00
|
|
|
static int sequencer_strip_jump_exec(bContext *C, wmOperator *op)
|
2009-10-28 19:53:25 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2014-02-03 18:55:59 +11:00
|
|
|
const bool next = RNA_boolean_get(op->ptr, "next");
|
|
|
|
|
const bool center = RNA_boolean_get(op->ptr, "center");
|
2009-10-28 19:53:25 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Currently do_skip_mute is always true. */
|
2025-03-06 13:04:39 +01:00
|
|
|
if (!strip_jump_internal(scene, next ? seq::SIDE_RIGHT : seq::SIDE_LEFT, true, center)) {
|
2009-12-08 13:57:51 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2012-08-23 08:10:45 +00:00
|
|
|
}
|
2009-12-08 13:57:51 +00:00
|
|
|
|
2022-02-03 21:32:50 +11:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-10-28 19:53:25 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-23 07:39:51 +00:00
|
|
|
void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
|
2009-10-28 19:53:25 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-08-23 07:39:51 +00:00
|
|
|
ot->name = "Jump to Strip";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_strip_jump";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->description = "Move frame to previous edit point";
|
2012-08-23 08:10:45 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-08-23 07:39:51 +00:00
|
|
|
ot->exec = sequencer_strip_jump_exec;
|
2012-12-06 05:48:51 +00:00
|
|
|
ot->poll = sequencer_strip_jump_poll;
|
2012-08-23 08:10:45 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2020-01-22 02:07:54 +01:00
|
|
|
ot->flag = OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Properties. */
|
2014-04-01 11:34:00 +11:00
|
|
|
RNA_def_boolean(ot->srna, "next", true, "Next Strip", "");
|
2020-12-24 11:07:32 -06:00
|
|
|
RNA_def_boolean(ot->srna, "center", true, "Use Strip Center", "");
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Swap Strip Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-11-19 12:59:29 +01:00
|
|
|
static const EnumPropertyItem prop_side_lr_types[] = {
|
2025-03-06 13:04:39 +01:00
|
|
|
{seq::SIDE_LEFT, "LEFT", 0, "Left", ""},
|
|
|
|
|
{seq::SIDE_RIGHT, "RIGHT", 0, "Right", ""},
|
2023-06-14 18:36:17 +02:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2020-11-19 12:59:29 +01:00
|
|
|
};
|
|
|
|
|
|
2025-01-06 14:19:24 +01:00
|
|
|
static void swap_sequence(Scene *scene, Strip *seqa, Strip *seqb)
|
2009-10-30 20:40:41 +00:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
int gap = seq::time_left_handle_frame_get(scene, seqb) -
|
|
|
|
|
seq::time_right_handle_frame_get(scene, seqa);
|
2025-01-07 16:03:11 +01:00
|
|
|
int strip_a_start;
|
|
|
|
|
int strip_b_start;
|
2013-02-03 12:19:14 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
strip_b_start = (seqb->start - seq::time_left_handle_frame_get(scene, seqb)) +
|
|
|
|
|
seq::time_left_handle_frame_get(scene, seqa);
|
|
|
|
|
seq::transform_translate_sequence(scene, seqb, strip_b_start - seqb->start);
|
|
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, seqb);
|
2013-02-03 12:19:14 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
strip_a_start = (seqa->start - seq::time_left_handle_frame_get(scene, seqa)) +
|
|
|
|
|
seq::time_right_handle_frame_get(scene, seqb) + gap;
|
|
|
|
|
seq::transform_translate_sequence(scene, seqa, strip_a_start - seqa->start);
|
|
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, seqa);
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
|
|
|
|
|
2025-01-06 14:19:24 +01:00
|
|
|
static Strip *find_next_prev_sequence(Scene *scene, Strip *test, int lr, int sel)
|
2009-10-30 20:40:41 +00:00
|
|
|
{
|
2020-11-19 12:59:29 +01:00
|
|
|
/* sel: 0==unselected, 1==selected, -1==don't care. */
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip, *best_strip = nullptr;
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2020-11-19 12:59:29 +01:00
|
|
|
|
|
|
|
|
int dist, best_dist;
|
|
|
|
|
best_dist = MAXFRAME * 2;
|
2009-10-30 20:40:41 +00:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (ed == nullptr) {
|
|
|
|
|
return nullptr;
|
2019-05-31 23:21:16 +10:00
|
|
|
}
|
2009-10-30 20:40:41 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = static_cast<Strip *>(ed->seqbasep->first);
|
|
|
|
|
while (strip) {
|
|
|
|
|
if ((strip != test) && (test->machine == strip->machine) &&
|
|
|
|
|
((sel == -1) || (sel == (strip->flag & SELECT))))
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
|
|
|
|
dist = MAXFRAME * 2;
|
|
|
|
|
|
|
|
|
|
switch (lr) {
|
2025-03-06 13:04:39 +01:00
|
|
|
case seq::SIDE_LEFT:
|
|
|
|
|
if (seq::time_right_handle_frame_get(scene, strip) <=
|
|
|
|
|
seq::time_left_handle_frame_get(scene, test))
|
2024-01-02 18:12:54 +01:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
dist = seq::time_right_handle_frame_get(scene, test) -
|
|
|
|
|
seq::time_left_handle_frame_get(scene, strip);
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2025-03-06 13:04:39 +01:00
|
|
|
case seq::SIDE_RIGHT:
|
|
|
|
|
if (seq::time_left_handle_frame_get(scene, strip) >=
|
|
|
|
|
seq::time_right_handle_frame_get(scene, test))
|
2024-01-02 18:12:54 +01:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
dist = seq::time_left_handle_frame_get(scene, strip) -
|
|
|
|
|
seq::time_right_handle_frame_get(scene, test);
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dist == 0) {
|
2025-01-07 14:09:45 +01:00
|
|
|
best_strip = strip;
|
2020-11-19 12:59:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (dist < best_dist) {
|
|
|
|
|
best_dist = dist;
|
2025-01-07 14:09:45 +01:00
|
|
|
best_strip = strip;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = static_cast<Strip *>(strip->next);
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
2025-01-07 14:09:45 +01:00
|
|
|
return best_strip; /* Can be nullptr. */
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
2009-10-30 20:40:41 +00:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
static bool strip_is_parent(const Strip *par, const Strip *strip)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
2025-01-07 14:09:45 +01:00
|
|
|
return ((par->seq1 == strip) || (par->seq2 == strip));
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
|
|
|
|
|
2009-12-15 10:04:54 +00:00
|
|
|
static int sequencer_swap_exec(bContext *C, wmOperator *op)
|
2009-10-30 20:40:41 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
Strip *active_seq = seq::select_active_get(scene);
|
|
|
|
|
ListBase *seqbase = seq::active_seqbase_get(ed);
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip;
|
2012-03-29 22:26:11 +00:00
|
|
|
int side = RNA_enum_get(op->ptr, "side");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (active_seq == nullptr) {
|
2019-03-26 21:16:47 +11:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip = find_next_prev_sequence(scene, active_seq, side, -1);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Disallow effect strips. */
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::effect_get_num_inputs(strip->type) >= 1 &&
|
2025-01-07 14:09:45 +01:00
|
|
|
(strip->effectdata || strip->seq1 || strip->seq2))
|
|
|
|
|
{
|
2009-10-30 20:40:41 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
if ((seq::effect_get_num_inputs(active_seq->type) >= 1) &&
|
2024-09-11 17:56:22 +02:00
|
|
|
(active_seq->effectdata || active_seq->seq1 || active_seq->seq2))
|
2019-03-26 21:16:47 +11:00
|
|
|
{
|
2009-10-30 20:40:41 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
ListBase *channels = seq::channels_displayed_get(seq::editing_get(scene));
|
|
|
|
|
if (seq::transform_is_locked(channels, strip) ||
|
|
|
|
|
seq::transform_is_locked(channels, active_seq))
|
2025-01-07 14:09:45 +01:00
|
|
|
{
|
2023-08-14 05:51:29 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-30 20:40:41 +00:00
|
|
|
switch (side) {
|
2025-03-06 13:04:39 +01:00
|
|
|
case seq::SIDE_LEFT:
|
2025-01-07 14:09:45 +01:00
|
|
|
swap_sequence(scene, strip, active_seq);
|
2009-10-30 20:40:41 +00:00
|
|
|
break;
|
2025-03-06 13:04:39 +01:00
|
|
|
case seq::SIDE_RIGHT:
|
2025-01-07 14:09:45 +01:00
|
|
|
swap_sequence(scene, active_seq, strip);
|
2009-10-30 20:40:41 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Do this in a new loop since both effects need to be calculated first. */
|
2025-01-06 14:19:24 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, iseq, seqbase) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if ((iseq->type & STRIP_TYPE_EFFECT) &&
|
2025-01-07 16:03:11 +01:00
|
|
|
(strip_is_parent(iseq, active_seq) || strip_is_parent(iseq, strip)))
|
2012-06-07 15:49:02 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* This may now overlap. */
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::transform_test_overlap(scene, seqbase, iseq)) {
|
|
|
|
|
seq::transform_seqbase_shuffle(seqbase, iseq, scene);
|
2009-12-13 15:48:57 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2009-12-08 13:57:51 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-12-08 13:57:51 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2009-10-30 20:40:41 +00:00
|
|
|
}
|
|
|
|
|
|
2009-12-15 10:04:54 +00:00
|
|
|
void SEQUENCER_OT_swap(wmOperatorType *ot)
|
2009-10-30 20:40:41 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Swap Strip";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_swap";
|
|
|
|
|
ot->description = "Swap active strip with strip to the right or left";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_swap_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Properties. */
|
2025-03-06 13:04:39 +01:00
|
|
|
RNA_def_enum(
|
|
|
|
|
ot->srna, "side", prop_side_lr_types, seq::SIDE_RIGHT, "Side", "Side of the strip to swap");
|
2009-10-30 21:40:07 +00:00
|
|
|
}
|
2009-11-08 15:03:10 +00:00
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Set Render Size Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_rendersize_exec(bContext *C, wmOperator * /*op*/)
|
2009-11-08 15:03:10 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *active_seq = seq::select_active_get(scene);
|
2023-06-14 18:36:17 +02:00
|
|
|
StripElem *se = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-12-20 18:02:31 +01:00
|
|
|
if (active_seq == nullptr || active_seq->data == nullptr) {
|
2009-12-15 10:35:50 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-23 15:36:54 +02:00
|
|
|
switch (active_seq->type) {
|
2025-01-07 16:10:36 +01:00
|
|
|
case STRIP_TYPE_IMAGE:
|
2025-03-06 13:04:39 +01:00
|
|
|
se = seq::render_give_stripelem(scene, active_seq, scene->r.cfra);
|
2021-04-23 15:36:54 +02:00
|
|
|
break;
|
2025-01-07 16:10:36 +01:00
|
|
|
case STRIP_TYPE_MOVIE:
|
2024-12-20 18:02:31 +01:00
|
|
|
se = active_seq->data->stripdata;
|
2021-04-23 15:36:54 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return OPERATOR_CANCELLED;
|
2009-11-08 15:03:10 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (se == nullptr) {
|
2021-04-23 15:36:54 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Prevent setting the render size if sequence values aren't initialized. */
|
|
|
|
|
if (se->orig_width <= 0 || se->orig_height <= 0) {
|
|
|
|
|
return OPERATOR_CANCELLED;
|
2010-11-28 18:23:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-23 15:36:54 +02:00
|
|
|
scene->r.xsch = se->orig_width;
|
|
|
|
|
scene->r.ysch = se->orig_height;
|
|
|
|
|
|
2024-12-20 18:02:31 +01:00
|
|
|
active_seq->data->transform->scale_x = active_seq->data->transform->scale_y = 1.0f;
|
|
|
|
|
active_seq->data->transform->xofs = active_seq->data->transform->yofs = 0.0f;
|
2021-04-23 16:39:21 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, active_seq);
|
2021-04-23 15:36:54 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
|
2023-06-14 18:36:17 +02:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, nullptr);
|
2021-04-23 16:39:21 +02:00
|
|
|
|
2021-04-23 15:36:54 +02:00
|
|
|
return OPERATOR_FINISHED;
|
2009-11-08 15:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_rendersize(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Set Render Size";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_rendersize";
|
|
|
|
|
ot->description = "Set render size and aspect from active sequence";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_rendersize_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-11-11 09:59:51 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Copy Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2009-12-17 14:45:47 +00:00
|
|
|
void SEQUENCER_OT_copy(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Copy";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_copy";
|
2023-04-14 12:12:30 +02:00
|
|
|
ot->description = "Copy the selected strips to the internal clipboard";
|
2009-12-17 14:45:47 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2023-12-07 15:39:51 +01:00
|
|
|
ot->exec = sequencer_clipboard_copy_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = sequencer_edit_poll;
|
2009-12-17 14:45:47 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER;
|
2009-12-17 14:45:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Paste Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
bool deselect_all_strips(Scene *scene)
|
2020-11-19 12:59:29 +01:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2023-02-10 21:49:42 +11:00
|
|
|
bool changed = false;
|
2020-11-19 12:59:29 +01:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (ed == nullptr) {
|
2023-02-10 21:49:42 +11:00
|
|
|
return changed;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, seq::active_seqbase_get(ed)) {
|
2025-01-07 16:33:39 +01:00
|
|
|
if (strip->flag & STRIP_ALLSEL) {
|
|
|
|
|
strip->flag &= ~STRIP_ALLSEL;
|
2023-02-10 21:49:42 +11:00
|
|
|
changed = true;
|
|
|
|
|
}
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
2023-02-10 21:49:42 +11:00
|
|
|
return changed;
|
2020-11-19 12:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
2009-12-17 14:45:47 +00:00
|
|
|
void SEQUENCER_OT_paste(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Paste";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_paste";
|
2023-04-14 12:12:30 +02:00
|
|
|
ot->description = "Paste strips from the internal clipboard";
|
2009-12-17 14:45:47 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2023-12-07 15:39:51 +01:00
|
|
|
ot->exec = sequencer_clipboard_paste_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_sequencer_active;
|
2009-12-17 14:45:47 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2020-12-15 22:01:58 +01:00
|
|
|
|
|
|
|
|
/* Properties. */
|
|
|
|
|
PropertyRNA *prop = RNA_def_boolean(
|
2021-06-22 17:03:22 +10:00
|
|
|
ot->srna,
|
|
|
|
|
"keep_offset",
|
|
|
|
|
false,
|
|
|
|
|
"Keep Offset",
|
|
|
|
|
"Keep strip offset relative to the current frame when pasting");
|
2020-12-15 22:01:58 +01:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
2009-12-17 14:45:47 +00:00
|
|
|
}
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Sequencer Swap Data Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2010-06-21 17:37:50 +00:00
|
|
|
static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip *strip_act;
|
|
|
|
|
Strip *strip_other;
|
2011-05-28 09:59:34 +00:00
|
|
|
const char *error_msg;
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::select_active_get_pair(scene, &strip_act, &strip_other) == false) {
|
2012-10-14 15:29:09 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Please select two strips");
|
2010-06-21 17:37:50 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::edit_sequence_swap(scene, strip_act, strip_other, &error_msg) == false) {
|
2011-05-28 09:59:34 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, error_msg);
|
2010-06-21 17:37:50 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
if (strip_act->scene_sound) {
|
|
|
|
|
BKE_sound_remove_scene_sound(scene, strip_act->scene_sound);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-07-02 10:41:56 +00:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
if (strip_other->scene_sound) {
|
|
|
|
|
BKE_sound_remove_scene_sound(scene, strip_other->scene_sound);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-07-04 10:51:10 +00:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
strip_act->scene_sound = nullptr;
|
|
|
|
|
strip_other->scene_sound = nullptr;
|
2010-07-04 10:51:10 +00:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
if (strip_act->sound) {
|
|
|
|
|
BKE_sound_add_scene_sound_defaults(scene, strip_act);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2025-01-07 16:03:11 +01:00
|
|
|
if (strip_other->sound) {
|
|
|
|
|
BKE_sound_add_scene_sound_defaults(scene, strip_other);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-07-04 10:22:31 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_raw(scene, strip_act);
|
|
|
|
|
seq::relations_invalidate_cache_raw(scene, strip_other);
|
2017-05-31 14:26:04 +02:00
|
|
|
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2010-06-21 17:37:50 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_swap_data(wmOperatorType *ot)
|
|
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Sequencer Swap Data";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_swap_data";
|
|
|
|
|
ot->description = "Swap 2 sequencer strips";
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_swap_data_exec;
|
|
|
|
|
ot->poll = ED_operator_sequencer_active;
|
2010-06-21 17:37:50 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2010-06-21 17:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Change Effect Input Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2011-08-12 06:08:22 +00:00
|
|
|
static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *strip = seq::select_active_get(scene);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip **strip_1 = &strip->seq1, **strip_2 = &strip->seq2;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
if (*strip_1 == nullptr || *strip_2 == nullptr) {
|
2012-10-26 17:32:50 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, cannot swap");
|
2011-08-12 06:08:22 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2020-07-03 17:20:58 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
std::swap(*strip_1, *strip_2);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_change_effect_input(wmOperatorType *ot)
|
2011-08-12 06:08:22 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Change Effect Input";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_change_effect_input";
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_change_effect_input_exec;
|
|
|
|
|
ot->poll = sequencer_effect_poll;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Change Effect Type Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2024-04-08 12:03:03 +10:00
|
|
|
const EnumPropertyItem sequencer_prop_effect_types[] = {
|
2025-01-07 16:10:36 +01:00
|
|
|
{STRIP_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
|
|
|
|
|
{STRIP_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
|
|
|
|
|
{STRIP_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
|
|
|
|
|
{STRIP_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
|
|
|
|
|
{STRIP_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
|
|
|
|
|
{STRIP_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
|
|
|
|
|
{STRIP_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
|
|
|
|
|
{STRIP_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
|
|
|
|
|
{STRIP_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
|
|
|
|
|
{STRIP_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
|
|
|
|
|
{STRIP_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
|
|
|
|
|
{STRIP_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
|
|
|
|
|
{STRIP_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
|
|
|
|
|
{STRIP_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
|
|
|
|
|
{STRIP_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
|
|
|
|
|
{STRIP_TYPE_TEXT, "TEXT", 0, "Text", ""},
|
|
|
|
|
{STRIP_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
|
2023-06-14 18:36:17 +02:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2020-11-19 12:59:29 +01:00
|
|
|
};
|
|
|
|
|
|
2011-08-12 06:08:22 +00:00
|
|
|
static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *strip = seq::select_active_get(scene);
|
2012-03-29 22:26:11 +00:00
|
|
|
const int new_type = RNA_enum_get(op->ptr, "type");
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Free previous effect and init new effect. */
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::EffectHandle sh;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-01-07 16:10:36 +01:00
|
|
|
if ((strip->type & STRIP_TYPE_EFFECT) == 0) {
|
2011-08-12 06:08:22 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Can someone explain the logic behind only allowing to increase this,
|
2011-08-12 06:08:22 +00:00
|
|
|
* copied from 2.4x - campbell */
|
2025-03-06 13:04:39 +01:00
|
|
|
if (seq::effect_get_num_inputs(strip->type) < seq::effect_get_num_inputs(new_type)) {
|
2011-08-12 06:08:22 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "New effect needs more input strips");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
sh = seq::effect_handle_get(strip);
|
2025-01-07 14:09:45 +01:00
|
|
|
sh.free(strip, true);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->type = new_type;
|
2020-07-03 17:20:58 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
sh = seq::effect_handle_get(strip);
|
2025-01-07 14:09:45 +01:00
|
|
|
sh.init(strip);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_change_effect_type(wmOperatorType *ot)
|
2011-08-12 06:08:22 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Change Effect Type";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_change_effect_type";
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_change_effect_type_exec;
|
|
|
|
|
ot->poll = sequencer_effect_poll;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2012-06-07 15:49:02 +00:00
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
|
|
|
"type",
|
|
|
|
|
sequencer_prop_effect_types,
|
2025-01-07 16:10:36 +01:00
|
|
|
STRIP_TYPE_CROSS,
|
2012-06-07 15:49:02 +00:00
|
|
|
"Type",
|
|
|
|
|
"Sequencer effect type");
|
2023-09-04 16:16:26 +02:00
|
|
|
RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_SEQUENCE);
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Change Data/Files Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2011-08-12 06:08:22 +00:00
|
|
|
static int sequencer_change_path_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *strip = seq::select_active_get(scene);
|
2014-04-11 11:25:41 +10:00
|
|
|
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
|
2015-04-20 18:07:34 +02:00
|
|
|
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
|
2020-11-06 14:10:59 +01:00
|
|
|
int minext_frameme, numdigits;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->type == STRIP_TYPE_IMAGE) {
|
2011-08-12 06:08:22 +00:00
|
|
|
char directory[FILE_MAX];
|
2015-04-20 18:07:34 +02:00
|
|
|
int len;
|
2011-08-12 06:08:22 +00:00
|
|
|
StripElem *se;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Need to find min/max frame for placeholders. */
|
2015-04-20 18:07:34 +02:00
|
|
|
if (use_placeholders) {
|
2025-01-07 14:09:45 +01:00
|
|
|
len = sequencer_image_seq_get_minmax_frame(op, strip->sfra, &minext_frameme, &numdigits);
|
2015-04-20 18:07:34 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
|
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
if (len == 0) {
|
2011-08-12 06:08:22 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-12 06:08:22 +00:00
|
|
|
RNA_string_get(op->ptr, "directory", directory);
|
2011-10-12 00:21:08 +00:00
|
|
|
if (is_relative_path) {
|
2023-02-09 11:30:25 +11:00
|
|
|
/* TODO(@ideasman42): shouldn't this already be relative from the filesel?
|
2011-10-12 00:21:08 +00:00
|
|
|
* (as the 'filepath' is) for now just make relative here,
|
2021-07-03 23:08:40 +10:00
|
|
|
* but look into changing after 2.60. */
|
2018-06-05 15:10:33 +02:00
|
|
|
BLI_path_rel(directory, BKE_main_blendfile_path(bmain));
|
2011-10-12 00:21:08 +00:00
|
|
|
}
|
2025-01-07 14:09:45 +01:00
|
|
|
STRNCPY(strip->data->dirpath, directory);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip->data->stripdata) {
|
|
|
|
|
MEM_freeN(strip->data->stripdata);
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
2025-03-05 16:35:09 +01:00
|
|
|
strip->data->stripdata = se = MEM_calloc_arrayN<StripElem>(len, "stripelem");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-20 18:07:34 +02:00
|
|
|
if (use_placeholders) {
|
2020-11-06 14:10:59 +01:00
|
|
|
sequencer_image_seq_reserve_frames(op, se, len, minext_frameme, numdigits);
|
2015-04-20 18:07:34 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
RNA_BEGIN (op->ptr, itemptr, "files") {
|
2023-06-14 18:36:17 +02:00
|
|
|
char *filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
|
2023-05-13 17:34:29 +10:00
|
|
|
STRNCPY(se->filename, filename);
|
2015-04-20 18:07:34 +02:00
|
|
|
MEM_freeN(filename);
|
|
|
|
|
se++;
|
|
|
|
|
}
|
|
|
|
|
RNA_END;
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-07 20:25:27 +01:00
|
|
|
if (len == 1) {
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->flag |= SEQ_SINGLE_FRAME_CONTENT;
|
2023-03-07 20:25:27 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->flag &= ~SEQ_SINGLE_FRAME_CONTENT;
|
2023-03-07 20:25:27 +01:00
|
|
|
}
|
|
|
|
|
|
2021-06-22 10:42:32 -07:00
|
|
|
/* Reset these else we won't see all the images. */
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->anim_startofs = strip->anim_endofs = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Correct start/end frames so we don't move.
|
2025-01-07 14:09:45 +01:00
|
|
|
* Important not to set strip->len = len; allow the function to handle it. */
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::add_reload_new_file(bmain, scene, strip, true);
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
2025-01-07 16:10:36 +01:00
|
|
|
else if (strip->type == STRIP_TYPE_SOUND_RAM) {
|
2025-01-07 14:09:45 +01:00
|
|
|
bSound *sound = strip->sound;
|
2023-06-14 18:36:17 +02:00
|
|
|
if (sound == nullptr) {
|
2016-01-27 11:01:41 +01:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
char filepath[FILE_MAX];
|
|
|
|
|
RNA_string_get(op->ptr, "filepath", filepath);
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(sound->filepath, filepath);
|
2016-01-27 11:01:41 +01:00
|
|
|
BKE_sound_load(bmain, sound);
|
|
|
|
|
}
|
2011-08-12 06:08:22 +00:00
|
|
|
else {
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Lame, set rna filepath. */
|
2011-08-14 14:43:11 +00:00
|
|
|
PropertyRNA *prop;
|
2011-08-12 06:08:22 +00:00
|
|
|
char filepath[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-24 16:45:32 +01:00
|
|
|
PointerRNA strip_ptr = RNA_pointer_create_discrete(&scene->id, &RNA_Strip, strip);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-12 06:08:22 +00:00
|
|
|
RNA_string_get(op->ptr, "filepath", filepath);
|
2025-01-07 16:03:11 +01:00
|
|
|
prop = RNA_struct_find_property(&strip_ptr, "filepath");
|
|
|
|
|
RNA_property_string_set(&strip_ptr, prop, filepath);
|
|
|
|
|
RNA_property_update(C, &strip_ptr, prop);
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_sequence_free_anim(strip);
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_raw(scene, strip);
|
2012-03-29 22:26:11 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-12 06:08:22 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
2011-08-12 06:08:22 +00:00
|
|
|
{
|
2012-03-29 22:26:11 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *strip = seq::select_active_get(scene);
|
2012-12-06 02:38:39 +00:00
|
|
|
char filepath[FILE_MAX];
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
BLI_path_join(
|
|
|
|
|
filepath, sizeof(filepath), strip->data->dirpath, strip->data->stripdata->filename);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
RNA_string_set(op->ptr, "directory", strip->data->dirpath);
|
2012-12-06 02:38:39 +00:00
|
|
|
RNA_string_set(op->ptr, "filepath", filepath);
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
/* Set default display depending on strip type. */
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->type == STRIP_TYPE_IMAGE) {
|
2014-04-01 11:34:00 +11:00
|
|
|
RNA_boolean_set(op->ptr, "filter_movie", false);
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2014-04-01 11:34:00 +11:00
|
|
|
RNA_boolean_set(op->ptr, "filter_image", false);
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WM_event_add_fileselect(C, op);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_change_path(wmOperatorType *ot)
|
2011-08-12 06:08:22 +00:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Change Data/Files";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_change_path";
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = sequencer_change_path_exec;
|
|
|
|
|
ot->invoke = sequencer_change_path_invoke;
|
|
|
|
|
ot->poll = sequencer_strip_has_path_poll;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2012-03-29 22:26:11 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-08-12 06:08:22 +00:00
|
|
|
|
2016-02-07 22:56:20 +11:00
|
|
|
WM_operator_properties_filesel(ot,
|
|
|
|
|
FILE_TYPE_FOLDER,
|
|
|
|
|
FILE_SPECIAL,
|
|
|
|
|
FILE_OPENFILE,
|
|
|
|
|
WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH |
|
|
|
|
|
WM_FILESEL_FILES,
|
|
|
|
|
FILE_DEFAULTDISPLAY,
|
2020-11-02 23:55:59 +01:00
|
|
|
FILE_SORT_DEFAULT);
|
2015-04-20 18:07:34 +02:00
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
|
"use_placeholders",
|
|
|
|
|
false,
|
|
|
|
|
"Use Placeholders",
|
|
|
|
|
"Use placeholders for missing frames of the strip");
|
2011-08-12 06:08:22 +00:00
|
|
|
}
|
2015-07-03 12:34:23 +02:00
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2022-05-16 19:41:50 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Change Strip Scene Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-05-17 10:01:30 +10:00
|
|
|
static bool sequencer_strip_change_scene_poll(bContext *C)
|
2022-05-16 19:41:50 +02:00
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(CTX_data_scene(C));
|
2023-06-14 18:36:17 +02:00
|
|
|
if (ed == nullptr) {
|
2022-05-16 19:41:50 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip = ed->act_seq;
|
2025-01-07 16:10:36 +01:00
|
|
|
return ((strip != nullptr) && (strip->type == STRIP_TYPE_SCENE));
|
2022-05-16 19:41:50 +02:00
|
|
|
}
|
|
|
|
|
static int sequencer_change_scene_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2023-06-14 18:36:17 +02:00
|
|
|
Scene *scene_seq = static_cast<Scene *>(
|
|
|
|
|
BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
|
2022-05-16 19:41:50 +02:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (scene_seq == nullptr) {
|
2022-05-16 19:41:50 +02:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Scene not found");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Assign new scene. */
|
2025-03-06 13:04:39 +01:00
|
|
|
Strip *strip = seq::select_active_get(scene);
|
2025-01-07 14:09:45 +01:00
|
|
|
if (strip) {
|
|
|
|
|
strip->scene = scene_seq;
|
2022-05-16 19:41:50 +02:00
|
|
|
/* Do a refresh of the sequencer data. */
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_raw(scene, strip);
|
2022-05-16 19:41:50 +02:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO | ID_RECALC_SEQUENCER_STRIPS);
|
|
|
|
|
DEG_relations_tag_update(bmain);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene);
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sequencer_change_scene_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
if (!RNA_struct_property_is_set(op->ptr, "scene")) {
|
|
|
|
|
return WM_enum_search_invoke(C, op, event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sequencer_change_scene_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_change_scene(wmOperatorType *ot)
|
2022-05-16 19:41:50 +02:00
|
|
|
{
|
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
|
|
/* Identifiers. */
|
|
|
|
|
ot->name = "Change Scene";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_change_scene";
|
|
|
|
|
ot->description = "Change Scene assigned to Strip";
|
|
|
|
|
|
|
|
|
|
/* Api callbacks. */
|
|
|
|
|
ot->exec = sequencer_change_scene_exec;
|
|
|
|
|
ot->invoke = sequencer_change_scene_invoke;
|
|
|
|
|
ot->poll = sequencer_strip_change_scene_poll;
|
|
|
|
|
|
|
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
/* Properties. */
|
2023-08-25 12:57:52 +10:00
|
|
|
prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
|
2022-05-16 19:41:50 +02:00
|
|
|
RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf);
|
|
|
|
|
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
|
|
|
|
|
ot->prop = prop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Export Subtitles Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-07-15 15:49:25 +02:00
|
|
|
/** Comparison function suitable to be used with BLI_listbase_sort(). */
|
2025-01-07 16:03:11 +01:00
|
|
|
static int strip_cmp_time_startdisp_channel(void *thunk, const void *a, const void *b)
|
2021-07-15 15:49:25 +02:00
|
|
|
{
|
2023-06-14 18:36:17 +02:00
|
|
|
const Scene *scene = static_cast<Scene *>(thunk);
|
2025-01-07 16:03:11 +01:00
|
|
|
const Strip *strip_a = static_cast<const Strip *>(a);
|
|
|
|
|
const Strip *strip_b = static_cast<const Strip *>(b);
|
2021-07-15 15:49:25 +02:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
int strip_a_start = seq::time_left_handle_frame_get(scene, strip_a);
|
|
|
|
|
int strip_b_start = seq::time_left_handle_frame_get(scene, strip_b);
|
2021-07-15 15:49:25 +02:00
|
|
|
|
2022-09-06 16:25:20 +10:00
|
|
|
/* If strips have the same start frame favor the one with a higher channel. */
|
2025-01-07 16:03:11 +01:00
|
|
|
if (strip_a_start == strip_b_start) {
|
|
|
|
|
return strip_a->machine > strip_b->machine;
|
2021-07-15 15:49:25 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
return (strip_a_start > strip_b_start);
|
2021-07-15 15:49:25 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-03 12:34:23 +02:00
|
|
|
static int sequencer_export_subtitles_invoke(bContext *C,
|
|
|
|
|
wmOperator *op,
|
2023-06-14 18:36:17 +02:00
|
|
|
const wmEvent * /*event*/)
|
2015-07-03 12:34:23 +02:00
|
|
|
{
|
2022-09-07 13:27:27 +03:00
|
|
|
ED_fileselect_ensure_default_filepath(C, op, ".srt");
|
2015-07-03 12:34:23 +02:00
|
|
|
|
|
|
|
|
WM_event_add_fileselect(C, op);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
struct Seq_get_text_cb_data {
|
2021-08-20 16:30:34 +02:00
|
|
|
ListBase *text_seq;
|
|
|
|
|
Scene *scene;
|
2023-06-14 18:36:17 +02:00
|
|
|
};
|
2021-08-20 16:30:34 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
static bool strip_get_text_strip_cb(Strip *strip, void *user_data)
|
2021-08-20 16:30:34 +02:00
|
|
|
{
|
|
|
|
|
Seq_get_text_cb_data *cd = (Seq_get_text_cb_data *)user_data;
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(cd->scene);
|
|
|
|
|
ListBase *channels = seq::channels_displayed_get(ed);
|
2021-08-20 16:30:34 +02:00
|
|
|
/* Only text strips that are not muted and don't end with negative frame. */
|
2025-03-06 13:04:39 +01:00
|
|
|
if ((strip->type == STRIP_TYPE_TEXT) && !seq::render_is_muted(channels, strip) &&
|
|
|
|
|
(seq::time_right_handle_frame_get(cd->scene, strip) > cd->scene->r.sfra))
|
2022-06-29 12:45:59 +02:00
|
|
|
{
|
2025-01-07 14:09:45 +01:00
|
|
|
BLI_addtail(cd->text_seq, MEM_dupallocN(strip));
|
2021-08-20 16:30:34 +02:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-03 12:34:23 +02:00
|
|
|
static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-01-07 16:03:11 +01:00
|
|
|
Strip *strip, *strip_next;
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2023-08-03 19:14:53 +10:00
|
|
|
ListBase text_seq = {nullptr};
|
2024-05-04 15:06:46 +10:00
|
|
|
int iter = 1; /* Sequence numbers in `.srt` files are 1-indexed. */
|
2015-07-03 12:34:23 +02:00
|
|
|
FILE *file;
|
|
|
|
|
char filepath[FILE_MAX];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-07 13:27:27 +03:00
|
|
|
if (!RNA_struct_property_is_set_ex(op->ptr, "filepath", false)) {
|
2023-05-27 15:10:59 +10:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No filepath given");
|
2015-07-03 12:34:23 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-03 12:34:23 +02:00
|
|
|
RNA_string_get(op->ptr, "filepath", filepath);
|
2018-06-17 16:13:24 +02:00
|
|
|
BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Avoid File write exceptions. */
|
2015-07-03 12:34:23 +02:00
|
|
|
if (!BLI_exists(filepath)) {
|
2023-05-03 11:49:47 +10:00
|
|
|
BLI_file_ensure_parent_dir_exists(filepath);
|
2015-07-03 12:34:23 +02:00
|
|
|
if (!BLI_file_touch(filepath)) {
|
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Can't create subtitle file");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-07-03 12:34:23 +02:00
|
|
|
}
|
|
|
|
|
else if (!BLI_file_is_writable(filepath)) {
|
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (ed != nullptr) {
|
2021-08-20 16:30:34 +02:00
|
|
|
Seq_get_text_cb_data cb_data = {&text_seq, scene};
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::for_each_callback(&ed->seqbase, strip_get_text_strip_cb, &cb_data);
|
2015-07-03 12:34:23 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-04 16:42:19 +02:00
|
|
|
if (BLI_listbase_is_empty(&text_seq)) {
|
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "No subtitles (text strips) to export");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
BLI_listbase_sort_r(&text_seq, strip_cmp_time_startdisp_channel, scene);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Open and write file. */
|
2015-10-04 16:42:19 +02:00
|
|
|
file = BLI_fopen(filepath, "w");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
for (strip = static_cast<Strip *>(text_seq.first); strip; strip = strip_next) {
|
2025-01-07 14:09:45 +01:00
|
|
|
TextVars *data = static_cast<TextVars *>(strip->effectdata);
|
2015-10-04 16:42:19 +02:00
|
|
|
char timecode_str_start[32];
|
|
|
|
|
char timecode_str_end[32];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-07-02 12:11:54 +10:00
|
|
|
/* Write time-code relative to start frame of scene. Don't allow negative time-codes. */
|
2022-06-02 01:39:40 +02:00
|
|
|
BLI_timecode_string_from_time(
|
|
|
|
|
timecode_str_start,
|
|
|
|
|
sizeof(timecode_str_start),
|
|
|
|
|
-2,
|
2025-03-06 13:04:39 +01:00
|
|
|
FRA2TIME(max_ii(seq::time_left_handle_frame_get(scene, strip) - scene->r.sfra, 0)),
|
2022-06-29 12:45:59 +02:00
|
|
|
FPS,
|
|
|
|
|
USER_TIMECODE_SUBRIP);
|
|
|
|
|
BLI_timecode_string_from_time(
|
|
|
|
|
timecode_str_end,
|
|
|
|
|
sizeof(timecode_str_end),
|
|
|
|
|
-2,
|
2025-03-06 13:04:39 +01:00
|
|
|
FRA2TIME(seq::time_right_handle_frame_get(scene, strip) - scene->r.sfra),
|
2022-06-02 01:39:40 +02:00
|
|
|
FPS,
|
|
|
|
|
USER_TIMECODE_SUBRIP);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-04 16:42:19 +02:00
|
|
|
fprintf(
|
|
|
|
|
file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-07 16:03:11 +01:00
|
|
|
strip_next = static_cast<Strip *>(strip->next);
|
2025-01-07 14:09:45 +01:00
|
|
|
MEM_freeN(strip);
|
2015-10-04 16:42:19 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-03 12:34:23 +02:00
|
|
|
fclose(file);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-03 12:34:23 +02:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool sequencer_strip_is_text_poll(bContext *C)
|
2015-07-03 12:34:23 +02:00
|
|
|
{
|
|
|
|
|
Editing *ed;
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip;
|
2025-03-06 13:04:39 +01:00
|
|
|
return (((ed = seq::editing_get(CTX_data_scene(C))) != nullptr) &&
|
2025-01-07 16:10:36 +01:00
|
|
|
((strip = ed->act_seq) != nullptr) && (strip->type == STRIP_TYPE_TEXT));
|
2015-07-03 12:34:23 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_export_subtitles(wmOperatorType *ot)
|
2015-07-03 12:34:23 +02:00
|
|
|
{
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2015-07-03 12:34:23 +02:00
|
|
|
ot->name = "Export Subtitles";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_export_subtitles";
|
|
|
|
|
ot->description = "Export .srt file containing text strips";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2015-07-03 12:34:23 +02:00
|
|
|
ot->exec = sequencer_export_subtitles_exec;
|
|
|
|
|
ot->invoke = sequencer_export_subtitles_invoke;
|
|
|
|
|
ot->poll = sequencer_strip_is_text_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2015-07-03 12:34:23 +02:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-07 22:56:20 +11:00
|
|
|
WM_operator_properties_filesel(ot,
|
|
|
|
|
FILE_TYPE_FOLDER,
|
|
|
|
|
FILE_BLENDER,
|
|
|
|
|
FILE_SAVE,
|
|
|
|
|
WM_FILESEL_FILEPATH,
|
|
|
|
|
FILE_DEFAULTDISPLAY,
|
2020-11-02 23:55:59 +01:00
|
|
|
FILE_SORT_DEFAULT);
|
2015-07-03 12:34:23 +02:00
|
|
|
}
|
2019-11-02 22:53:39 -07:00
|
|
|
|
2020-06-06 00:05:54 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Set Range to Strips Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2019-11-02 22:53:39 -07:00
|
|
|
static int sequencer_set_range_to_strips_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2019-11-02 22:53:39 -07:00
|
|
|
|
|
|
|
|
int sfra = MAXFRAME;
|
|
|
|
|
int efra = -MAXFRAME;
|
|
|
|
|
bool selected = false;
|
|
|
|
|
const bool preview = RNA_boolean_get(op->ptr, "preview");
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
|
|
|
|
if (strip->flag & SELECT) {
|
2019-11-02 22:53:39 -07:00
|
|
|
selected = true;
|
2025-03-06 13:04:39 +01:00
|
|
|
sfra = min_ii(sfra, seq::time_left_handle_frame_get(scene, strip));
|
2023-09-08 16:58:00 +10:00
|
|
|
/* Offset of -1 is needed because in the sequencer every frame has width.
|
|
|
|
|
* Range from 1 to 1 is drawn as range 1 to 2, because 1 frame long strip starts at frame 1
|
|
|
|
|
* and ends at frame 2. See #106480. */
|
2025-03-06 13:04:39 +01:00
|
|
|
efra = max_ii(efra, seq::time_right_handle_frame_get(scene, strip) - 1);
|
2019-11-02 22:53:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!selected) {
|
|
|
|
|
BKE_report(op->reports, RPT_WARNING, "Select one or more strips");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2020-07-03 17:20:58 +02:00
|
|
|
if (efra < 0) {
|
2019-11-02 22:53:39 -07:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Can't set a negative range");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (preview) {
|
|
|
|
|
scene->r.flag |= SCER_PRV_RANGE;
|
|
|
|
|
scene->r.psfra = max_ii(0, sfra);
|
|
|
|
|
scene->r.pefra = efra;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
scene->r.flag &= ~SCER_PRV_RANGE;
|
|
|
|
|
scene->r.sfra = max_ii(0, sfra);
|
|
|
|
|
scene->r.efra = efra;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 13:17:23 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_FRAME_RANGE, scene);
|
2019-11-02 22:53:39 -07:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_set_range_to_strips(wmOperatorType *ot)
|
2019-11-02 22:53:39 -07:00
|
|
|
{
|
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Identifiers. */
|
2019-11-02 22:53:39 -07:00
|
|
|
ot->name = "Set Range to Strips";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_set_range_to_strips";
|
|
|
|
|
ot->description = "Set the frame range to the selected strips start and end";
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Api callbacks. */
|
2019-11-02 22:53:39 -07:00
|
|
|
ot->exec = sequencer_set_range_to_strips_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
|
|
|
|
|
2020-04-05 23:55:51 +02:00
|
|
|
/* Flags. */
|
2019-11-02 22:53:39 -07:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
prop = RNA_def_boolean(ot->srna, "preview", false, "Preview", "Set the preview range instead");
|
2020-01-22 02:07:54 +01:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
2019-11-02 22:53:39 -07:00
|
|
|
}
|
2020-06-06 00:05:54 +10:00
|
|
|
|
|
|
|
|
/** \} */
|
2020-11-19 12:59:29 +01:00
|
|
|
|
2020-12-16 20:34:26 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Clear Strip Transform Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
STRIP_TRANSFORM_POSITION,
|
|
|
|
|
STRIP_TRANSFORM_SCALE,
|
|
|
|
|
STRIP_TRANSFORM_ROTATION,
|
|
|
|
|
STRIP_TRANSFORM_ALL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const EnumPropertyItem transform_reset_properties[] = {
|
|
|
|
|
{STRIP_TRANSFORM_POSITION, "POSITION", 0, "Position", "Reset strip transform location"},
|
|
|
|
|
{STRIP_TRANSFORM_SCALE, "SCALE", 0, "Scale", "Reset strip transform scale"},
|
|
|
|
|
{STRIP_TRANSFORM_ROTATION, "ROTATION", 0, "Rotation", "Reset strip transform rotation"},
|
|
|
|
|
{STRIP_TRANSFORM_ALL, "ALL", 0, "All", "Reset strip transform location, scale and rotation"},
|
2023-06-14 18:36:17 +02:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2020-12-16 20:34:26 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
const Editing *ed = seq::editing_get(scene);
|
2020-12-16 20:34:26 +01:00
|
|
|
const int property = RNA_enum_get(op->ptr, "property");
|
|
|
|
|
|
2025-02-19 14:28:14 +01:00
|
|
|
const bool use_autokeyframe = blender::animrig::is_autokey_on(scene);
|
|
|
|
|
const bool only_when_keyed = blender::animrig::is_keying_flag(scene,
|
|
|
|
|
AUTOKEY_FLAG_INSERTAVAILABLE);
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->flag & SELECT && strip->type != STRIP_TYPE_SOUND_RAM) {
|
2025-01-07 14:09:45 +01:00
|
|
|
StripTransform *transform = strip->data->transform;
|
2025-02-19 14:28:14 +01:00
|
|
|
PropertyRNA *prop;
|
|
|
|
|
PointerRNA ptr = RNA_pointer_create_discrete(&scene->id, &RNA_StripTransform, transform);
|
2020-12-16 20:34:26 +01:00
|
|
|
switch (property) {
|
|
|
|
|
case STRIP_TRANSFORM_POSITION:
|
|
|
|
|
transform->xofs = 0;
|
|
|
|
|
transform->yofs = 0;
|
2025-02-19 14:28:14 +01:00
|
|
|
if (use_autokeyframe) {
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "offset_x");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "offset_y");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
}
|
2020-12-16 20:34:26 +01:00
|
|
|
break;
|
|
|
|
|
case STRIP_TRANSFORM_SCALE:
|
|
|
|
|
transform->scale_x = 1.0f;
|
|
|
|
|
transform->scale_y = 1.0f;
|
2025-02-19 14:28:14 +01:00
|
|
|
if (use_autokeyframe) {
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "scale_x");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "scale_y");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
}
|
2020-12-16 20:34:26 +01:00
|
|
|
break;
|
|
|
|
|
case STRIP_TRANSFORM_ROTATION:
|
|
|
|
|
transform->rotation = 0.0f;
|
2025-02-19 14:28:14 +01:00
|
|
|
if (use_autokeyframe) {
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "rotation");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
}
|
2020-12-16 20:34:26 +01:00
|
|
|
break;
|
|
|
|
|
case STRIP_TRANSFORM_ALL:
|
|
|
|
|
transform->xofs = 0;
|
|
|
|
|
transform->yofs = 0;
|
|
|
|
|
transform->scale_x = 1.0f;
|
|
|
|
|
transform->scale_y = 1.0f;
|
|
|
|
|
transform->rotation = 0.0f;
|
2025-02-19 14:28:14 +01:00
|
|
|
if (use_autokeyframe) {
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "offset_x");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "offset_y");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "scale_x");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "scale_y");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
prop = RNA_struct_find_property(&ptr, "rotation");
|
|
|
|
|
blender::animrig::autokeyframe_property(
|
|
|
|
|
C, scene, &ptr, prop, -1, scene->r.cfra, only_when_keyed);
|
|
|
|
|
}
|
2020-12-16 20:34:26 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2020-12-16 20:34:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_strip_transform_clear(wmOperatorType *ot)
|
2020-12-16 20:34:26 +01:00
|
|
|
{
|
|
|
|
|
/* Identifiers. */
|
|
|
|
|
ot->name = "Clear Strip Transform";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_strip_transform_clear";
|
|
|
|
|
ot->description = "Reset image transformation to default value";
|
|
|
|
|
|
|
|
|
|
/* Api callbacks. */
|
|
|
|
|
ot->exec = sequencer_strip_transform_clear_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
|
|
|
|
|
|
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
|
|
|
"property",
|
|
|
|
|
transform_reset_properties,
|
|
|
|
|
STRIP_TRANSFORM_ALL,
|
|
|
|
|
"Property",
|
|
|
|
|
"Strip transform property to be reset");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Transform Set Fit Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static const EnumPropertyItem scale_fit_methods[] = {
|
|
|
|
|
{SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image so fits in preview"},
|
|
|
|
|
{SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image so it fills preview completely"},
|
|
|
|
|
{SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image so it fills preview"},
|
2023-06-14 18:36:17 +02:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2020-12-16 20:34:26 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
const Editing *ed = seq::editing_get(scene);
|
2023-06-14 18:36:17 +02:00
|
|
|
const eSeqImageFitMethod fit_method = eSeqImageFitMethod(RNA_enum_get(op->ptr, "fit_method"));
|
2020-12-16 20:34:26 +01:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
2025-01-07 16:10:36 +01:00
|
|
|
if (strip->flag & SELECT && strip->type != STRIP_TYPE_SOUND_RAM) {
|
2022-06-30 18:36:42 +02:00
|
|
|
const int timeline_frame = scene->r.cfra;
|
2025-03-06 13:04:39 +01:00
|
|
|
StripElem *strip_elem = seq::render_give_stripelem(scene, strip, timeline_frame);
|
2020-12-16 20:34:26 +01:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
if (strip_elem == nullptr) {
|
2020-12-16 20:34:26 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::set_scale_to_fit(strip,
|
|
|
|
|
strip_elem->orig_width,
|
|
|
|
|
strip_elem->orig_height,
|
|
|
|
|
scene->r.xsch,
|
|
|
|
|
scene->r.ysch,
|
|
|
|
|
fit_method);
|
|
|
|
|
seq::relations_invalidate_cache_preprocessed(scene, strip);
|
2020-12-16 20:34:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_strip_transform_fit(wmOperatorType *ot)
|
2020-12-16 20:34:26 +01:00
|
|
|
{
|
|
|
|
|
/* Identifiers. */
|
|
|
|
|
ot->name = "Strip Transform Set Fit";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_strip_transform_fit";
|
|
|
|
|
|
|
|
|
|
/* Api callbacks. */
|
|
|
|
|
ot->exec = sequencer_strip_transform_fit_exec;
|
|
|
|
|
ot->poll = sequencer_edit_poll;
|
|
|
|
|
|
|
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
|
|
|
"fit_method",
|
|
|
|
|
scale_fit_methods,
|
|
|
|
|
SEQ_SCALE_TO_FIT,
|
|
|
|
|
"Fit Method",
|
|
|
|
|
"Scale fit fit_method");
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-29 14:29:32 +02:00
|
|
|
static int sequencer_strip_color_tag_set_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
const Editing *ed = seq::editing_get(scene);
|
2021-09-29 14:29:32 +02:00
|
|
|
const short color_tag = RNA_enum_get(op->ptr, "color");
|
|
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
LISTBASE_FOREACH (Strip *, strip, ed->seqbasep) {
|
|
|
|
|
if (strip->flag & SELECT) {
|
|
|
|
|
strip->color_tag = color_tag;
|
2021-09-29 14:29:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-04 08:14:06 +02:00
|
|
|
static bool sequencer_strip_color_tag_set_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2023-06-14 18:36:17 +02:00
|
|
|
if (scene == nullptr) {
|
2021-10-04 08:14:06 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2023-06-14 18:36:17 +02:00
|
|
|
if (ed == nullptr) {
|
2021-10-04 08:14:06 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-06 14:19:24 +01:00
|
|
|
Strip *act_seq = ed->act_seq;
|
2023-06-14 18:36:17 +02:00
|
|
|
return act_seq != nullptr;
|
2021-10-04 08:14:06 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void SEQUENCER_OT_strip_color_tag_set(wmOperatorType *ot)
|
2021-09-29 14:29:32 +02:00
|
|
|
{
|
|
|
|
|
/* Identifiers. */
|
|
|
|
|
ot->name = "Set Color Tag";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_strip_color_tag_set";
|
|
|
|
|
ot->description = "Set a color tag for the selected strips";
|
|
|
|
|
|
|
|
|
|
/* Api callbacks. */
|
|
|
|
|
ot->exec = sequencer_strip_color_tag_set_exec;
|
2021-10-04 08:14:06 +02:00
|
|
|
ot->poll = sequencer_strip_color_tag_set_poll;
|
2021-09-29 14:29:32 +02:00
|
|
|
|
|
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
2025-01-07 16:05:12 +01:00
|
|
|
RNA_def_enum(ot->srna, "color", rna_enum_strip_color_items, STRIP_COLOR_NONE, "Color Tag", "");
|
2021-09-29 14:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-16 20:34:26 +01:00
|
|
|
/** \} */
|
2021-10-07 12:32:04 +11:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Set 2D Cursor Operator
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static int sequencer_set_2d_cursor_exec(bContext *C, wmOperator *op)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
|
SpaceSeq *sseq = CTX_wm_space_seq(C);
|
|
|
|
|
|
|
|
|
|
float cursor_pixel[2];
|
|
|
|
|
RNA_float_get_array(op->ptr, "location", cursor_pixel);
|
|
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
blender::float2 cursor_region = seq::image_preview_unit_from_px(scene, cursor_pixel);
|
2025-02-17 11:23:00 +01:00
|
|
|
copy_v2_v2(sseq->cursor, cursor_region);
|
2021-10-07 12:32:04 +11:00
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, nullptr);
|
2021-10-07 12:32:04 +11:00
|
|
|
|
2022-03-03 20:31:18 +11:00
|
|
|
/* Use pass-through to allow click-drag to transform the cursor. */
|
|
|
|
|
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
|
2021-10-07 12:32:04 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int sequencer_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|
|
|
|
{
|
|
|
|
|
ARegion *region = CTX_wm_region(C);
|
|
|
|
|
float cursor_pixel[2];
|
|
|
|
|
UI_view2d_region_to_view(
|
|
|
|
|
®ion->v2d, event->mval[0], event->mval[1], &cursor_pixel[0], &cursor_pixel[1]);
|
|
|
|
|
|
|
|
|
|
RNA_float_set_array(op->ptr, "location", cursor_pixel);
|
|
|
|
|
|
|
|
|
|
return sequencer_set_2d_cursor_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_cursor_set(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Set 2D Cursor";
|
|
|
|
|
ot->description = "Set 2D cursor location";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_cursor_set";
|
|
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
|
ot->exec = sequencer_set_2d_cursor_exec;
|
|
|
|
|
ot->invoke = sequencer_set_2d_cursor_invoke;
|
2021-11-30 11:09:58 +01:00
|
|
|
ot->poll = sequencer_view_has_preview_poll;
|
2021-10-07 12:32:04 +11:00
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
|
RNA_def_float_vector(ot->srna,
|
|
|
|
|
"location",
|
|
|
|
|
2,
|
2023-06-14 18:36:17 +02:00
|
|
|
nullptr,
|
2021-10-07 12:32:04 +11:00
|
|
|
-FLT_MAX,
|
|
|
|
|
FLT_MAX,
|
|
|
|
|
"Location",
|
|
|
|
|
"Cursor location in normalized preview coordinates",
|
|
|
|
|
-10.0f,
|
|
|
|
|
10.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
2023-01-30 07:47:29 +01:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Update scene strip frame range
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-14 18:36:17 +02:00
|
|
|
static int sequencer_scene_frame_range_update_exec(bContext *C, wmOperator * /*op*/)
|
2023-01-30 07:47:29 +01:00
|
|
|
{
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(scene);
|
2025-01-07 14:09:45 +01:00
|
|
|
Strip *strip = ed->act_seq;
|
2023-01-30 07:47:29 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
const int old_start = seq::time_left_handle_frame_get(scene, strip);
|
|
|
|
|
const int old_end = seq::time_right_handle_frame_get(scene, strip);
|
2023-01-30 07:47:29 +01:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
Scene *target_scene = strip->scene;
|
2023-01-30 07:47:29 +01:00
|
|
|
|
2025-01-07 14:09:45 +01:00
|
|
|
strip->len = target_scene->r.efra - target_scene->r.sfra + 1;
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::time_left_handle_frame_set(scene, strip, old_start);
|
|
|
|
|
seq::time_right_handle_frame_set(scene, strip, old_end);
|
2023-01-30 07:47:29 +01:00
|
|
|
|
2025-03-06 13:04:39 +01:00
|
|
|
seq::relations_invalidate_cache_raw(scene, strip);
|
2023-01-30 07:47:29 +01:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO | ID_RECALC_SEQUENCER_STRIPS);
|
2023-06-14 18:36:17 +02:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_SEQUENCER, nullptr);
|
2023-01-30 07:47:29 +01:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool sequencer_scene_frame_range_update_poll(bContext *C)
|
|
|
|
|
{
|
2025-03-06 13:04:39 +01:00
|
|
|
Editing *ed = seq::editing_get(CTX_data_scene(C));
|
2025-01-07 16:10:36 +01:00
|
|
|
return (ed != nullptr && ed->act_seq != nullptr && (ed->act_seq->type & STRIP_TYPE_SCENE) != 0);
|
2023-01-30 07:47:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SEQUENCER_OT_scene_frame_range_update(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Update Scene Frame Range";
|
|
|
|
|
ot->description = "Update frame range of scene strip";
|
|
|
|
|
ot->idname = "SEQUENCER_OT_scene_frame_range_update";
|
|
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
|
ot->exec = sequencer_scene_frame_range_update_exec;
|
|
|
|
|
ot->poll = sequencer_scene_frame_range_update_poll;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
2025-03-06 06:22:14 +01:00
|
|
|
|
|
|
|
|
} // namespace blender::ed::vse
|