Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2021-09-21 10:38:30 +0300
committerRichard Antalik <richardantalik@gmail.com>2021-09-21 11:55:04 +0300
commitfa2c1698b077f510175e79adf3dbf3e1602b1030 (patch)
tree7b15540db52813ae7de54eceeda7e78cce25b724 /source/blender/editors/transform
parent26f9b1ef49772d568560f8ac1d8d2d15bb77849f (diff)
VSE: Image transform tools
Add tools for image manipulation in sequencer preview region. This includes: - Translate, rotate and resize operators, tools and gizmos - Origin for image transformation - Median point and individual origins pivot modes - Select and Box select operator works in preview - Image overlay drawing ref T90156 Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D12105
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/CMakeLists.txt1
-rw-r--r--source/blender/editors/transform/transform.c12
-rw-r--r--source/blender/editors/transform/transform.h12
-rw-r--r--source/blender/editors/transform/transform_convert.c18
-rw-r--r--source/blender/editors/transform/transform_convert.h4
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer_image.c195
-rw-r--r--source/blender/editors/transform/transform_draw_cursors.c2
-rw-r--r--source/blender/editors/transform/transform_generics.c7
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c71
-rw-r--r--source/blender/editors/transform/transform_mode.c2
-rw-r--r--source/blender/editors/transform/transform_snap_sequencer.c4
11 files changed, 309 insertions, 19 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index e9efed3cd61..64a720322c1 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -60,6 +60,7 @@ set(SRC
transform_convert_particle.c
transform_convert_sculpt.c
transform_convert_sequencer.c
+ transform_convert_sequencer_image.c
transform_convert_tracking.c
transform_draw_cursors.c
transform_generics.c
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 58491f8c2d3..e58e524e341 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1703,11 +1703,13 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->draw_handle_cursor = WM_paint_cursor_activate(
SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
- else if (t->spacetype == SPACE_SEQ) {
- t->draw_handle_view = ED_region_draw_cb_activate(
- t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- }
- else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP, SPACE_NODE, SPACE_GRAPH, SPACE_ACTION)) {
+ else if (ELEM(t->spacetype,
+ SPACE_IMAGE,
+ SPACE_CLIP,
+ SPACE_NODE,
+ SPACE_GRAPH,
+ SPACE_ACTION,
+ SPACE_SEQ)) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index d1a1937cef1..7f4e533ccd7 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -87,15 +87,16 @@ typedef enum {
CTX_PAINT_CURVE = (1 << 7),
CTX_POSE_BONE = (1 << 8),
CTX_TEXTURE_SPACE = (1 << 9),
+ CTX_SEQUENCER_IMAGE = (1 << 10),
- CTX_NO_PET = (1 << 10),
- CTX_AUTOCONFIRM = (1 << 11),
+ CTX_NO_PET = (1 << 11),
+ CTX_AUTOCONFIRM = (1 << 12),
/** When transforming object's, adjust the object data so it stays in the same place. */
- CTX_OBMODE_XFORM_OBDATA = (1 << 12),
+ CTX_OBMODE_XFORM_OBDATA = (1 << 13),
/** Transform object parents without moving their children. */
- CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 13),
+ CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 14),
/** Enable edge scrolling in 2D views */
- CTX_VIEW2D_EDGE_PAN = (1 << 14),
+ CTX_VIEW2D_EDGE_PAN = (1 << 15),
} eTContext;
/** #TransInfo.flag */
@@ -240,6 +241,7 @@ typedef enum {
TC_PARTICLE_VERTS,
TC_SCULPT,
TC_SEQ_DATA,
+ TC_SEQ_IMAGE_DATA,
TC_TRACKING_DATA,
} eTConvertType;
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index d756e2c90a6..557fa79e7ac 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -955,6 +955,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
case TC_OBJECT_TEXSPACE:
case TC_PAINT_CURVE_VERTS:
case TC_PARTICLE_VERTS:
+ case TC_SEQ_IMAGE_DATA:
case TC_NONE:
default:
break;
@@ -1042,6 +1043,7 @@ static void init_proportional_edit(TransInfo *t)
case TC_PAINT_CURVE_VERTS:
case TC_SCULPT:
case TC_SEQ_DATA:
+ case TC_SEQ_IMAGE_DATA:
case TC_TRACKING_DATA:
case TC_NONE:
default:
@@ -1120,6 +1122,7 @@ static void init_TransDataContainers(TransInfo *t,
case TC_PARTICLE_VERTS:
case TC_SCULPT:
case TC_SEQ_DATA:
+ case TC_SEQ_IMAGE_DATA:
case TC_TRACKING_DATA:
case TC_NONE:
default:
@@ -1204,6 +1207,7 @@ static eTFlag flags_from_data_type(eTConvertType data_type)
case TC_NODE_DATA:
case TC_PAINT_CURVE_VERTS:
case TC_SEQ_DATA:
+ case TC_SEQ_IMAGE_DATA:
case TC_TRACKING_DATA:
return T_POINTS | T_2D_EDIT;
case TC_ARMATURE_VERTS:
@@ -1282,7 +1286,12 @@ static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armatur
convert_type = TC_NLA_DATA;
}
else if (t->spacetype == SPACE_SEQ) {
- convert_type = TC_SEQ_DATA;
+ if (t->options & CTX_SEQUENCER_IMAGE) {
+ convert_type = TC_SEQ_IMAGE_DATA;
+ }
+ else {
+ convert_type = TC_SEQ_DATA;
+ }
}
else if (t->spacetype == SPACE_GRAPH) {
convert_type = TC_GRAPH_EDIT_DATA;
@@ -1470,6 +1479,10 @@ void createTransData(bContext *C, TransInfo *t)
t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transform. */
createTransSeqData(t);
break;
+ case TC_SEQ_IMAGE_DATA:
+ t->obedit_type = -1;
+ createTransSeqImageData(t);
+ break;
case TC_TRACKING_DATA:
createTransTrackingData(C, t);
break;
@@ -1746,6 +1759,9 @@ void recalcData(TransInfo *t)
case TC_SEQ_DATA:
recalcData_sequencer(t);
break;
+ case TC_SEQ_IMAGE_DATA:
+ recalcData_sequencer_image(t);
+ break;
case TC_TRACKING_DATA:
recalcData_tracking(t);
break;
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index 9cb0400cad9..66d84bca2d2 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -218,6 +218,10 @@ void createTransSeqData(TransInfo *t);
void recalcData_sequencer(TransInfo *t);
void special_aftertrans_update__sequencer(bContext *C, TransInfo *t);
+/* transform_convert_sequencer_image.c */
+void createTransSeqImageData(TransInfo *t);
+void recalcData_sequencer_image(TransInfo *t);
+
/* transform_convert_tracking.c */
void createTransTrackingData(bContext *C, TransInfo *t);
void recalcData_tracking(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_convert_sequencer_image.c b/source/blender/editors/transform/transform_convert_sequencer_image.c
new file mode 100644
index 00000000000..465f8b9a694
--- /dev/null
+++ b/source/blender/editors/transform/transform_convert_sequencer_image.c
@@ -0,0 +1,195 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_space_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+
+#include "SEQ_iterator.h"
+#include "SEQ_relations.h"
+#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
+#include "SEQ_utils.h"
+
+#include "UI_view2d.h"
+
+#include "transform.h"
+#include "transform_convert.h"
+
+/** Used for sequencer transform. */
+typedef struct TransDataSeq {
+ struct Sequence *seq;
+ float orig_origin_position[2];
+ float orig_translation[2];
+ float orig_scale[2];
+ float orig_rotation;
+} TransDataSeq;
+
+static TransData *SeqToTransData(const Scene *scene,
+ Sequence *seq,
+ TransData *td,
+ TransData2D *td2d,
+ TransDataSeq *tdseq,
+ int vert_index)
+{
+ const StripTransform *transform = seq->strip->transform;
+ float origin[2];
+ SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, origin);
+ float vertex[2] = {origin[0], origin[1]};
+
+ /* Add control vertex, so rotation and scale can be calculated. */
+ if (vert_index == 1) {
+ vertex[0] += 1.0f;
+ }
+ else if (vert_index == 2) {
+ vertex[1] += 1.0f;
+ }
+
+ td2d->loc[0] = vertex[0];
+ td2d->loc[1] = vertex[1];
+ td2d->loc2d = NULL;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->iloc, td->loc);
+
+ td->center[0] = origin[0];
+ td->center[1] = origin[1];
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ tdseq->seq = seq;
+ copy_v2_v2(tdseq->orig_origin_position, origin);
+ tdseq->orig_translation[0] = transform->xofs;
+ tdseq->orig_translation[1] = transform->yofs;
+ tdseq->orig_scale[0] = transform->scale_x;
+ tdseq->orig_scale[1] = transform->scale_y;
+ tdseq->orig_rotation = transform->rotation;
+
+ td->extra = (void *)tdseq;
+ td->ext = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ return td;
+}
+
+static void freeSeqData(TransInfo *UNUSED(t), TransDataContainer *tc, TransCustomData *UNUSED(custom_data))
+{
+ TransData *td = (TransData *)tc->data;
+ MEM_freeN(td->extra);
+}
+
+void createTransSeqImageData(TransInfo *t)
+{
+ Editing *ed = SEQ_editing_get(t->scene);
+ ListBase *seqbase = SEQ_active_seqbase_get(ed);
+ SeqCollection *strips = SEQ_query_rendered_strips(seqbase, t->scene->r.cfra, 0);
+ SEQ_filter_selected_strips(strips);
+
+ const int count = SEQ_collection_len(strips);
+ if (ed == NULL || count == 0) {
+ SEQ_collection_free(strips);
+ return;
+ }
+
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ tc->custom.type.free_cb = freeSeqData;
+
+ tc->data_len = count * 3; /* 3 vertices per sequence are needed. */
+ TransData *td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransSeq TransData");
+ TransData2D *td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
+ "TransSeq TransData2D");
+ TransDataSeq *tdseq = MEM_callocN(tc->data_len * sizeof(TransDataSeq), "TransSeq TransDataSeq");
+
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ /* One `Sequence` needs 3 `TransData` entries - center point placed in image origin, then 2
+ * points offset by 1 in X and Y direction respectively, so rotation and scale can be
+ * calculated from these points. */
+ SeqToTransData(t->scene, seq, td++, td2d++, tdseq++, 0);
+ SeqToTransData(t->scene, seq, td++, td2d++, tdseq++, 1);
+ SeqToTransData(t->scene, seq, td++, td2d++, tdseq++, 2);
+ }
+
+ SEQ_collection_free(strips);
+}
+
+void recalcData_sequencer_image(TransInfo *t)
+{
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ int i;
+
+ for (i = 0, td = tc->data, td2d = tc->data_2d; i < tc->data_len; i++, td++, td2d++) {
+ /* Origin. */
+ float loc[2];
+ copy_v2_v2(loc, td2d->loc);
+ i++, td++, td2d++;
+
+ /* X and Y control points used to read scale and rotation. */
+ float handle_x[2];
+ copy_v2_v2(handle_x, td2d->loc);
+ sub_v2_v2(handle_x, loc);
+ i++, td++, td2d++;
+ float handle_y[2];
+ copy_v2_v2(handle_y, td2d->loc);
+ sub_v2_v2(handle_y, loc);
+
+ TransDataSeq *tdseq = td->extra;
+ Sequence *seq = tdseq->seq;
+ StripTransform *transform = seq->strip->transform;
+ float mirror[2];
+ SEQ_image_transform_mirror_factor_get(seq, mirror);
+
+ /* Calculate translation. */
+ float translation[2];
+ copy_v2_v2(translation, tdseq->orig_origin_position);
+ sub_v2_v2(translation, loc);
+ mul_v2_v2(translation, mirror);
+ transform->xofs = tdseq->orig_translation[0] - translation[0];
+ transform->yofs = tdseq->orig_translation[1] - translation[1];
+
+ /* Scale. */
+ transform->scale_x = tdseq->orig_scale[0] * fabs(len_v2(handle_x));
+ transform->scale_y = tdseq->orig_scale[1] * fabs(len_v2(handle_y));
+
+ /* Rotation. Scaling can cause negative rotation. */
+ if (t->mode == TFM_ROTATION) {
+ float rotation = angle_signed_v2v2(handle_x, (float[]){1, 0}) * mirror[0] * mirror[1];
+ transform->rotation = tdseq->orig_rotation + rotation;
+ transform->rotation += DEG2RAD(360.0);
+ transform->rotation = fmod(transform->rotation, DEG2RAD(360.0));
+ }
+ SEQ_relations_invalidate_cache_preprocessed(t->scene, seq);
+ }
+}
diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c
index ead8eae0997..af1f3cb72a4 100644
--- a/source/blender/editors/transform/transform_draw_cursors.c
+++ b/source/blender/editors/transform/transform_draw_cursors.c
@@ -95,7 +95,7 @@ static void drawArrow(const uint pos_id, const enum eArrowDirection dir)
bool transform_draw_cursor_poll(bContext *C)
{
ARegion *region = CTX_wm_region(C);
- return (region && region->regiontype == RGN_TYPE_WINDOW) ? 1 : 0;
+ return (region && ELEM(region->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW)) ? 1 : 0;
}
/**
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index c493b9bd102..fa323f0c1f7 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -59,6 +59,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "SEQ_sequencer.h"
+
#include "transform.h"
#include "transform_convert.h"
#include "transform_mode.h"
@@ -335,6 +337,11 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->options |= CTX_MASK;
}
}
+ else if (t->spacetype == SPACE_SEQ && region->regiontype == RGN_TYPE_PREVIEW) {
+ t->view = &region->v2d;
+ t->around = SEQ_tool_settings_pivot_point_get(t->scene);
+ t->options |= CTX_SEQUENCER_IMAGE;
+ }
else {
if (region) {
/* XXX: For now, get View2D from the active region. */
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index 0b677e2560b..0d66db0d7e1 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -49,6 +49,11 @@
#include "ED_screen.h"
#include "ED_uvedit.h"
+#include "SEQ_iterator.h"
+#include "SEQ_sequencer.h"
+#include "SEQ_time.h"
+#include "SEQ_transform.h"
+
#include "transform.h" /* own include */
/* -------------------------------------------------------------------- */
@@ -234,17 +239,66 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
return changed;
}
+static float gizmo2d_calc_rotation(const bContext *C)
+{
+ ScrArea *area = CTX_wm_area(C);
+ if (area->spacetype != SPACE_SEQ) {
+ return 0.0f;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = SEQ_editing_get(scene);
+ ListBase *seqbase = SEQ_active_seqbase_get(ed);
+ SeqCollection *strips = SEQ_query_rendered_strips(seqbase, scene->r.cfra, 0);
+ SEQ_filter_selected_strips(strips);
+
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ if (seq == ed->act_seq) {
+ StripTransform *transform = seq->strip->transform;
+ float mirror[2];
+ SEQ_image_transform_mirror_factor_get(seq, mirror);
+ SEQ_collection_free(strips);
+ return transform->rotation * mirror[0] * mirror[1];
+ }
+ }
+
+ SEQ_collection_free(strips);
+ return 0.0f;
+}
+
static bool gizmo2d_calc_center(const bContext *C, float r_center[2])
{
ScrArea *area = CTX_wm_area(C);
+ Scene *scene = CTX_data_scene(C);
bool has_select = false;
zero_v2(r_center);
if (area->spacetype == SPACE_IMAGE) {
SpaceImage *sima = area->spacedata.first;
- Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
ED_uvedit_center_from_pivot_ex(sima, scene, view_layer, r_center, sima->around, &has_select);
}
+ else if (area->spacetype == SPACE_SEQ) {
+ ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(scene));
+ SeqCollection *strips = SEQ_query_rendered_strips(seqbase, scene->r.cfra, 0);
+ SEQ_filter_selected_strips(strips);
+
+ if (SEQ_collection_len(strips) <= 0) {
+ SEQ_collection_free(strips);
+ return false;
+ }
+
+ has_select = true;
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ float origin[2];
+ SEQ_image_transform_origin_offset_pixelspace_get(scene, seq, origin);
+ add_v2_v2(r_center, origin);
+ }
+ mul_v2_fl(r_center, 1.0f / SEQ_collection_len(strips));
+
+ SEQ_collection_free(strips);
+ }
return has_select;
}
@@ -338,7 +392,7 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
}
}
- RNA_boolean_set(ptr, "release_confirm", 1);
+ RNA_boolean_set(ptr, "release_confirm", true);
}
{
@@ -539,6 +593,7 @@ void ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set(wmGizmoGroupType *gzgt)
typedef struct GizmoGroup_Resize2D {
wmGizmo *gizmo_xy[3];
float origin[2];
+ float rotation;
} GizmoGroup_Resize2D;
static GizmoGroup_Resize2D *gizmogroup2d_resize_init(wmGizmoGroup *gzgroup)
@@ -571,6 +626,7 @@ static void gizmo2d_resize_refresh(const bContext *C, wmGizmoGroup *gzgroup)
ggd->gizmo_xy[i]->flag &= ~WM_GIZMO_HIDDEN;
}
copy_v2_v2(ggd->origin, origin);
+ ggd->rotation = gizmo2d_calc_rotation(C);
}
}
@@ -595,6 +651,13 @@ static void gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup
for (int i = 0; i < ARRAY_SIZE(ggd->gizmo_xy); i++) {
wmGizmo *gz = ggd->gizmo_xy[i];
WM_gizmo_set_matrix_location(gz, origin);
+
+ if (i < 2) {
+ float axis[3] = {0.0f}, rotated_axis[3];
+ axis[i] = 1.0f;
+ rotate_v3_v3v3fl(rotated_axis, axis, (float[3]){0, 0, 1}, ggd->rotation);
+ WM_gizmo_set_matrix_rotation_from_z_axis(gz, rotated_axis);
+ }
}
}
@@ -617,10 +680,6 @@ static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
/* set up widget data */
RNA_float_set(gz->ptr, "length", 1.0f);
- float axis[3] = {0.0f};
- axis[i] = 1.0f;
- WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis);
-
RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX);
WM_gizmo_set_line_width(gz, GIZMO_AXIS_LINE_WIDTH);
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index b9fb8a86752..b14d499cb66 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -75,7 +75,7 @@ bool transdata_check_local_center(const TransInfo *t, short around)
/* implicit: (t->flag & T_EDIT) */
(ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) ||
(t->spacetype == SPACE_GRAPH) ||
- (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))));
+ (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE | CTX_SEQUENCER_IMAGE))));
}
/* Informs if the mode can be switched during modal. */
diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c
index e82a00bcc77..2acdf5cfd9c 100644
--- a/source/blender/editors/transform/transform_snap_sequencer.c
+++ b/source/blender/editors/transform/transform_snap_sequencer.c
@@ -254,6 +254,10 @@ static int seq_snap_threshold_get_frame_distance(const TransInfo *t)
TransSeqSnapData *transform_snap_sequencer_data_alloc(const TransInfo *t)
{
+ if (t->data_type == TC_SEQ_IMAGE_DATA) {
+ return NULL;
+ }
+
TransSeqSnapData *snap_data = MEM_callocN(sizeof(TransSeqSnapData), __func__);
ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(t->scene));