diff options
Diffstat (limited to 'source/blender/editors/transform')
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 = ®ion->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)); |