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:
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/transform.c19
-rw-r--r--source/blender/editors/transform/transform_constraints.c12
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer_image.c30
-rw-r--r--source/blender/editors/transform/transform_generics.c52
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c322
-rw-r--r--source/blender/editors/transform/transform_mode.c12
-rw-r--r--source/blender/editors/transform/transform_mode.h2
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c35
-rw-r--r--source/blender/editors/transform/transform_mode_shrink_fatten.c4
-rw-r--r--source/blender/editors/transform/transform_ops.c14
-rw-r--r--source/blender/editors/transform/transform_orientations.c13
11 files changed, 398 insertions, 117 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 9dcd3a3e510..ec3847acbce 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -797,6 +797,25 @@ static bool transform_event_modal_constraint(TransInfo *t, short modal_type)
if (constraint_new == CON_AXIS2) {
return false;
}
+
+ if (t->data_type == TC_SEQ_IMAGE_DATA) {
+ /* Setup the 2d msg string so it writes out the transform space. */
+ msg_2d = msg_3d;
+
+ short orient_index = 1;
+ if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) {
+ /* Successive presses on existing axis, cycle orientation modes. */
+ orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
+ }
+
+ transform_orientations_current_set(t, orient_index);
+ if (orient_index != 0) {
+ /* Make sure that we don't stop the constraint unless we are looped back around to
+ * "no constraint". */
+ constraint_curr = -1;
+ }
+ }
+
if (constraint_curr == constraint_new) {
stopConstraint(t);
}
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index e2ad89e0dbc..23ba335476c 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -755,7 +755,7 @@ void drawConstraint(TransInfo *t)
{
TransCon *tc = &(t->con);
- if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE, SPACE_SEQ)) {
return;
}
if (!(tc->mode & CON_APPLY)) {
@@ -921,6 +921,16 @@ static void drawObjectConstraint(TransInfo *t)
}
}
+ if (t->options & CTX_SEQUENCER_IMAGE) {
+ /* Because we construct an "L" shape to deform the sequence, we should skip
+ * all points except the first vertex. Otherwise we will draw the same axis constraint line
+ * 3 times for each strip.
+ */
+ if (i % 3 != 0) {
+ continue;
+ }
+ }
+
if (t->flag & T_EDIT) {
mul_v3_m4v3(co, tc->mat, td->center);
diff --git a/source/blender/editors/transform/transform_convert_sequencer_image.c b/source/blender/editors/transform/transform_convert_sequencer_image.c
index 6e3f12de472..2b5ed268504 100644
--- a/source/blender/editors/transform/transform_convert_sequencer_image.c
+++ b/source/blender/editors/transform/transform_convert_sequencer_image.c
@@ -64,12 +64,16 @@ static TransData *SeqToTransData(const Scene *scene,
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. */
+ /* Add control vertex, so rotation and scale can be calculated.
+ * All three vertices will form a "L" shape that is aligned to the local strip axis.
+ */
if (vert_index == 1) {
- vertex[0] += 1.0f;
+ vertex[0] += cosf(transform->rotation);
+ vertex[1] += sinf(transform->rotation);
}
else if (vert_index == 2) {
- vertex[1] += 1.0f;
+ vertex[0] -= sinf(transform->rotation);
+ vertex[1] += cosf(transform->rotation);
}
td2d->loc[0] = vertex[0];
@@ -81,10 +85,12 @@ static TransData *SeqToTransData(const Scene *scene,
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);
+ unit_m3(td->axismtx);
+
+ rotate_m3(td->axismtx, transform->rotation);
+ normalize_m3(td->axismtx);
tdseq->seq = seq;
copy_v2_v2(tdseq->orig_origin_position, origin);
@@ -159,18 +165,18 @@ void recalcData_sequencer_image(TransInfo *t)
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);
+ float origin[2];
+ copy_v2_v2(origin, 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);
+ sub_v2_v2(handle_x, origin);
i++, td++, td2d++;
float handle_y[2];
copy_v2_v2(handle_y, td2d->loc);
- sub_v2_v2(handle_y, loc);
+ sub_v2_v2(handle_y, origin);
TransDataSeq *tdseq = td->extra;
Sequence *seq = tdseq->seq;
@@ -181,8 +187,9 @@ void recalcData_sequencer_image(TransInfo *t)
/* Calculate translation. */
float translation[2];
copy_v2_v2(translation, tdseq->orig_origin_position);
- sub_v2_v2(translation, loc);
+ sub_v2_v2(translation, origin);
mul_v2_v2(translation, mirror);
+
transform->xofs = tdseq->orig_translation[0] - translation[0];
transform->yofs = tdseq->orig_translation[1] - translation[1];
@@ -192,7 +199,8 @@ void recalcData_sequencer_image(TransInfo *t)
/* 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];
+ const float orig_dir[2] = {cosf(tdseq->orig_rotation), sinf(tdseq->orig_rotation)};
+ float rotation = angle_signed_v2v2(handle_x, orig_dir) * mirror[0] * mirror[1];
transform->rotation = tdseq->orig_rotation + rotation;
transform->rotation += DEG2RAD(360.0);
transform->rotation = fmod(transform->rotation, DEG2RAD(360.0));
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 09c338046ed..8effb82173b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -73,42 +73,56 @@
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)
{
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_SEQ)) {
+ return;
+ }
+
float v1[3], v2[3], v3[3];
uchar col[3], col2[3];
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = t->view;
- GPU_matrix_push();
-
copy_v3_v3(v3, dir);
mul_v3_fl(v3, v3d->clip_end);
sub_v3_v3v3(v2, center, v3);
add_v3_v3v3(v1, center, v3);
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ View2D *v2d = t->view;
- if (options & DRAWLIGHT) {
- col[0] = col[1] = col[2] = 220;
- }
- else {
- UI_GetThemeColor3ubv(TH_GRID, col);
- }
- UI_make_axis_color(col, col2, axis);
+ copy_v3_v3(v3, dir);
+ float max_dist = max_ff(BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur));
+ mul_v3_fl(v3, max_dist);
+
+ sub_v3_v3v3(v2, center, v3);
+ add_v3_v3v3(v1, center, v3);
+ }
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_matrix_push();
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor3ubv(col2);
+ if (options & DRAWLIGHT) {
+ col[0] = col[1] = col[2] = 220;
+ }
+ else {
+ UI_GetThemeColor3ubv(TH_GRID, col);
+ }
+ UI_make_axis_color(col, col2, axis);
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v2);
- immEnd();
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immUnbindProgram();
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col2);
- GPU_matrix_pop();
- }
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
+
+ GPU_matrix_pop();
}
/**
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index 61119c72ad6..7ba52ec823d 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -173,6 +173,7 @@ typedef struct GizmoGroup2D {
float origin[2];
float min[2];
float max[2];
+ float rotation;
bool no_cage;
@@ -241,7 +242,7 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
}
ScrArea *area = CTX_wm_area(C);
- bool changed = false;
+ bool has_select = false;
if (area->spacetype == SPACE_IMAGE) {
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -249,18 +250,75 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
view_layer, NULL, &objects_len);
if (ED_uvedit_minmax_multi(scene, objects, objects_len, r_min, r_max)) {
- changed = true;
+ has_select = true;
}
MEM_freeN(objects);
}
+ else if (area->spacetype == SPACE_SEQ) {
+ Scene *scene = CTX_data_scene(C);
+ 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);
+ int selected_strips = SEQ_collection_len(strips);
+ if (selected_strips > 0) {
+ INIT_MINMAX2(r_min, r_max);
+ has_select = true;
- if (changed == false) {
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
+ float quad[4][2];
+ SEQ_image_transform_quad_get(scene, seq, selected_strips != 1, quad);
+ for (int i = 0; i < 4; i++) {
+ minmax_v2v2_v2(r_min, r_max, quad[i]);
+ }
+ }
+ }
+ SEQ_collection_free(strips);
+ if (selected_strips > 1) {
+ /* Don't draw the cage as transforming multiple strips isn't currently very useful as it
+ * doesn't behave as one would expect.
+ *
+ * This is because our current transform system doesn't support shearing which would make the
+ * scaling transforms of the bounding box behave weirdly.
+ * In addition to this, the rotation of the bounding box can not currently be hooked up
+ * properly to read the result from the transform system (when transforming multiple strips).
+ */
+ mid_v2_v2v2(r_center, r_min, r_max);
+ zero_v2(r_min);
+ zero_v2(r_max);
+ return has_select;
+ }
+ }
+
+ if (has_select == false) {
zero_v2(r_min);
zero_v2(r_max);
}
mid_v2_v2v2(r_center, r_min, r_max);
- return changed;
+ return has_select;
+}
+
+static int gizmo2d_calc_transform_orientation(const bContext *C)
+{
+ ScrArea *area = CTX_wm_area(C);
+ if (area->spacetype != SPACE_SEQ) {
+ return V3D_ORIENT_GLOBAL;
+ }
+
+ 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);
+
+ bool use_local_orient = SEQ_collection_len(strips) == 1;
+ SEQ_collection_free(strips);
+
+ if (use_local_orient) {
+ return V3D_ORIENT_LOCAL;
+ }
+ return V3D_ORIENT_GLOBAL;
}
static float gizmo2d_calc_rotation(const bContext *C)
@@ -276,9 +334,10 @@ static float gizmo2d_calc_rotation(const bContext *C)
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) {
+ if (SEQ_collection_len(strips) == 1) {
+ /* Only return the strip rotation if only one is selected. */
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips) {
StripTransform *transform = seq->strip->transform;
float mirror[2];
SEQ_image_transform_mirror_factor_get(seq, mirror);
@@ -436,17 +495,17 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL);
PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL);
- RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
RNA_property_boolean_set(ptr, prop_release_confirm, true);
- ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ ptr = WM_gizmo_operator_set(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
ptr = WM_gizmo_operator_set(
ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL);
@@ -465,87 +524,51 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup
}
}
-static void gizmo2d_xform_setup_no_cage(const bContext *C, wmGizmoGroup *gzgroup)
+static void rotate_around_center_v2(float point[2], const float center[2], const float angle)
{
- gizmo2d_xform_setup(C, gzgroup);
- GizmoGroup2D *ggd = gzgroup->customdata;
- ggd->no_cage = true;
+ float tmp[2];
+
+ sub_v2_v2v2(tmp, point, center);
+ rotate_v2_v2fl(point, tmp, angle);
+ add_v2_v2(point, center);
}
static void gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
{
GizmoGroup2D *ggd = gzgroup->customdata;
- float origin[3];
bool has_select;
if (ggd->no_cage) {
- has_select = gizmo2d_calc_center(C, origin);
+ has_select = gizmo2d_calc_center(C, ggd->origin);
}
else {
- has_select = gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
+ has_select = gizmo2d_calc_bounds(C, ggd->origin, ggd->min, ggd->max);
+ ggd->rotation = gizmo2d_calc_rotation(C);
}
- copy_v2_v2(ggd->origin, origin);
+
bool show_cage = !ggd->no_cage && !equals_v2v2(ggd->min, ggd->max);
if (has_select == false) {
+ /* Nothing selected. Disable gizmo drawing and return. */
+ ggd->cage->flag |= WM_GIZMO_HIDDEN;
for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
ggd->translate_xy[i]->flag |= WM_GIZMO_HIDDEN;
}
- ggd->cage->flag |= WM_GIZMO_HIDDEN;
+ return;
}
- else {
- if (show_cage) {
- ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
- for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
- wmGizmo *gz = ggd->translate_xy[i];
- gz->flag |= WM_GIZMO_HIDDEN;
- }
- }
- else {
- ggd->cage->flag |= WM_GIZMO_HIDDEN;
- for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
- wmGizmo *gz = ggd->translate_xy[i];
- gz->flag &= ~WM_GIZMO_HIDDEN;
- }
- }
- if (show_cage) {
- wmGizmoOpElem *gzop;
- float mid[2];
- const float *min = ggd->min;
- const float *max = ggd->max;
- mid_v2_v2v2(mid, min, max);
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
- PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
-
- gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
- RNA_property_float_set_array(
- &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
+ if (!show_cage) {
+ /* Disable cage gizmo drawing and return. */
+ ggd->cage->flag |= WM_GIZMO_HIDDEN;
+ for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
+ ggd->translate_xy[i]->flag &= ~WM_GIZMO_HIDDEN;
}
+ return;
+ }
+
+ /* We will show the cage gizmo! Setup all necessary data. */
+ ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
+ for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
+ ggd->translate_xy[i]->flag |= WM_GIZMO_HIDDEN;
}
}
@@ -554,7 +577,6 @@ static void gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
ARegion *region = CTX_wm_region(C);
GizmoGroup2D *ggd = gzgroup->customdata;
float origin[3] = {UNPACK2(ggd->origin), 0.0f};
- const float origin_aa[3] = {UNPACK2(ggd->origin), 0.0f};
gizmo2d_origin_to_region(region, origin);
@@ -564,19 +586,128 @@ static void gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
}
UI_view2d_view_to_region_m4(&region->v2d, ggd->cage->matrix_space);
- WM_gizmo_set_matrix_offset_location(ggd->cage, origin_aa);
+ /* Define the bounding box of the gizmo in the offset transform matrix. */
+ unit_m4(ggd->cage->matrix_offset);
ggd->cage->matrix_offset[0][0] = (ggd->max[0] - ggd->min[0]);
ggd->cage->matrix_offset[1][1] = (ggd->max[1] - ggd->min[1]);
+
+ ScrArea *area = CTX_wm_area(C);
+
+ if (area->spacetype == SPACE_SEQ) {
+ gizmo2d_calc_center(C, origin);
+
+ float matrix_rotate[4][4];
+ unit_m4(matrix_rotate);
+ copy_v3_v3(matrix_rotate[3], origin);
+ rotate_m4(matrix_rotate, 'Z', ggd->rotation);
+ unit_m4(ggd->cage->matrix_basis);
+ mul_m4_m4m4(ggd->cage->matrix_basis, matrix_rotate, ggd->cage->matrix_basis);
+
+ float mid[2];
+ sub_v2_v2v2(mid, origin, ggd->origin);
+ mul_v2_fl(mid, -1.0f);
+ copy_v2_v2(ggd->cage->matrix_offset[3], mid);
+ }
+ else {
+ const float origin_aa[3] = {UNPACK2(ggd->origin), 0.0f};
+ WM_gizmo_set_matrix_offset_location(ggd->cage, origin_aa);
+ }
}
-static void gizmo2d_xform_no_cage_message_subscribe(const struct bContext *C,
- struct wmGizmoGroup *gzgroup,
- struct wmMsgBus *mbus)
+static void gizmo2d_xform_invoke_prepare(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ wmGizmo *UNUSED(gz),
+ const wmEvent *UNUSED(event))
{
- bScreen *screen = CTX_wm_screen(C);
+ GizmoGroup2D *ggd = gzgroup->customdata;
+ wmGizmoOpElem *gzop;
+ const float *mid = ggd->origin;
+ const float *min = ggd->min;
+ const float *max = ggd->max;
+
+ /* Define the different transform center points that will be used when grabbing the corners or
+ * rotating with the gizmo.
+ *
+ * The coordinates are referred to as their cardinal directions:
+ * N
+ * o
+ *NW | NE
+ * x-----------x
+ * | |
+ *W| C |E
+ * | |
+ * x-----------x
+ *SW S SE
+ */
+ float n[3] = {mid[0], max[1], 0.0f};
+ float w[3] = {min[0], mid[1], 0.0f};
+ float e[3] = {max[0], mid[1], 0.0f};
+ float s[3] = {mid[0], min[1], 0.0f};
+
+ float nw[3] = {min[0], max[1], 0.0f};
+ float ne[3] = {max[0], max[1], 0.0f};
+ float sw[3] = {min[0], min[1], 0.0f};
+ float se[3] = {max[0], min[1], 0.0f};
+
+ float c[3] = {mid[0], mid[1], 0.0f};
+
+ float orient_matrix[3][3];
+ unit_m3(orient_matrix);
+
ScrArea *area = CTX_wm_area(C);
- ARegion *region = CTX_wm_region(C);
- gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, area, region);
+
+ if (ggd->rotation != 0.0f && area->spacetype == SPACE_SEQ) {
+ float origin[3];
+ gizmo2d_calc_center(C, origin);
+ /* We need to rotate the cardinal points so they align with the rotated bounding box. */
+
+ rotate_around_center_v2(n, origin, ggd->rotation);
+ rotate_around_center_v2(w, origin, ggd->rotation);
+ rotate_around_center_v2(e, origin, ggd->rotation);
+ rotate_around_center_v2(s, origin, ggd->rotation);
+
+ rotate_around_center_v2(nw, origin, ggd->rotation);
+ rotate_around_center_v2(ne, origin, ggd->rotation);
+ rotate_around_center_v2(sw, origin, ggd->rotation);
+ rotate_around_center_v2(se, origin, ggd->rotation);
+
+ rotate_around_center_v2(c, origin, ggd->rotation);
+
+ rotate_m3(orient_matrix, ggd->rotation);
+ }
+
+ int orient_type = gizmo2d_calc_transform_orientation(C);
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
+ PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
+ PropertyRNA *prop_mouse_dir = RNA_struct_find_property(&gzop->ptr, "mouse_dir_constraint");
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, e);
+ RNA_property_float_set_array(&gzop->ptr, prop_mouse_dir, orient_matrix[0]);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_type);
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, w);
+ RNA_property_float_set_array(&gzop->ptr, prop_mouse_dir, orient_matrix[0]);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_type);
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, n);
+ RNA_property_float_set_array(&gzop->ptr, prop_mouse_dir, orient_matrix[1]);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_type);
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, s);
+ RNA_property_float_set_array(&gzop->ptr, prop_mouse_dir, orient_matrix[1]);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_type);
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, ne);
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, se);
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, nw);
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, sw);
+
+ gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
+ RNA_property_float_set_array(&gzop->ptr, prop_center_override, c);
}
void ED_widgetgroup_gizmo2d_xform_callbacks_set(wmGizmoGroupType *gzgt)
@@ -586,6 +717,24 @@ void ED_widgetgroup_gizmo2d_xform_callbacks_set(wmGizmoGroupType *gzgt)
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = gizmo2d_xform_refresh;
gzgt->draw_prepare = gizmo2d_xform_draw_prepare;
+ gzgt->invoke_prepare = gizmo2d_xform_invoke_prepare;
+}
+
+static void gizmo2d_xform_setup_no_cage(const bContext *C, wmGizmoGroup *gzgroup)
+{
+ gizmo2d_xform_setup(C, gzgroup);
+ GizmoGroup2D *ggd = gzgroup->customdata;
+ ggd->no_cage = true;
+}
+
+static void gizmo2d_xform_no_cage_message_subscribe(const struct bContext *C,
+ struct wmGizmoGroup *gzgroup,
+ struct wmMsgBus *mbus)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ gizmo2d_pivot_point_message_subscribe(gzgroup, mbus, screen, area, region);
}
void ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set(wmGizmoGroupType *gzgt)
@@ -726,6 +875,18 @@ static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgrou
}
}
+static void gizmo2d_resize_invoke_prepare(const bContext *C,
+ wmGizmoGroup *UNUSED(gzgroup),
+ wmGizmo *gz,
+ const wmEvent *UNUSED(event))
+{
+ wmGizmoOpElem *gzop;
+ int orient_type = gizmo2d_calc_transform_orientation(C);
+
+ gzop = WM_gizmo_operator_get(gz, 0);
+ RNA_enum_set(&gzop->ptr, "orient_type", orient_type);
+}
+
static void gizmo2d_resize_message_subscribe(const struct bContext *C,
struct wmGizmoGroup *gzgroup,
struct wmMsgBus *mbus)
@@ -743,6 +904,7 @@ void ED_widgetgroup_gizmo2d_resize_callbacks_set(wmGizmoGroupType *gzgt)
gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
gzgt->refresh = gizmo2d_resize_refresh;
gzgt->draw_prepare = gizmo2d_resize_draw_prepare;
+ gzgt->invoke_prepare = gizmo2d_resize_invoke_prepare;
gzgt->message_subscribe = gizmo2d_resize_message_subscribe;
}
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index b14d499cb66..7f92c96d25f 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -1082,9 +1082,17 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
case TFM_ROTATION:
initRotation(t);
break;
- case TFM_RESIZE:
- initResize(t);
+ case TFM_RESIZE: {
+ float mouse_dir_constraint[3];
+ if (op) {
+ RNA_float_get_array(op->ptr, "mouse_dir_constraint", mouse_dir_constraint);
+ }
+ else {
+ zero_v3(mouse_dir_constraint);
+ }
+ initResize(t, mouse_dir_constraint);
break;
+ }
case TFM_SKIN_RESIZE:
initSkinResize(t);
break;
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
index d8601000ddb..c561d1c8a4f 100644
--- a/source/blender/editors/transform/transform_mode.h
+++ b/source/blender/editors/transform/transform_mode.h
@@ -121,7 +121,7 @@ void initMirror(TransInfo *t);
void initPushPull(TransInfo *t);
/* transform_mode_resize.c */
-void initResize(TransInfo *t);
+void initResize(TransInfo *t, float mouse_dir_constraint[3]);
/* transform_mode_rotate.c */
void initRotation(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index 65f4623b3be..28323460626 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -201,14 +201,45 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
ED_area_status_text(t->area, str);
}
-void initResize(TransInfo *t)
+void initResize(TransInfo *t, float mouse_dir_constraint[3])
{
t->mode = TFM_RESIZE;
t->transform = applyResize;
t->tsnap.applySnap = ApplySnapResize;
t->tsnap.distance = ResizeBetween;
- initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ if (is_zero_v3(mouse_dir_constraint)) {
+ initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
+ }
+ else {
+ int mval_start[2], mval_end[2];
+ float mval_dir[3], t_mval[2];
+ float viewmat[3][3];
+
+ copy_m3_m4(viewmat, t->viewmat);
+ mul_v3_m3v3(mval_dir, viewmat, mouse_dir_constraint);
+ normalize_v2(mval_dir);
+ if (is_zero_v2(mval_dir)) {
+ /* The screen space direction is orthogonal to the view.
+ * Fall back to constraining on the Y axis. */
+ mval_dir[0] = 0;
+ mval_dir[1] = 1;
+ }
+
+ mval_start[0] = t->center2d[0];
+ mval_start[1] = t->center2d[1];
+
+ t_mval[0] = t->mval[0] - mval_start[0];
+ t_mval[1] = t->mval[1] - mval_start[1];
+ project_v2_v2v2(mval_dir, t_mval, mval_dir);
+
+ mval_end[0] = t->center2d[0] + mval_dir[0];
+ mval_end[1] = t->center2d[1] + mval_dir[1];
+
+ setCustomPoints(t, &t->mouse, mval_end, mval_start);
+
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+ }
t->flag |= T_NULL_ONE;
t->num.val_flag[0] |= NUM_NULL_ONE;
diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c
index b96b8103392..b18e0aa0c7f 100644
--- a/source/blender/editors/transform/transform_mode_shrink_fatten.c
+++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c
@@ -188,7 +188,9 @@ void initShrinkFatten(TransInfo *t)
{
/* If not in mesh edit mode, fallback to Resize. */
if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) {
- initResize(t);
+ float no_mouse_dir_constraint[3];
+ zero_v3(no_mouse_dir_constraint);
+ initResize(t, no_mouse_dir_constraint);
}
else {
t->mode = TFM_SHRINKFATTEN;
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 3a4a9342e18..5ed340abf97 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -59,6 +59,7 @@ typedef struct TransformModeItem {
void (*opfunc)(wmOperatorType *);
} TransformModeItem;
+static const float VecZero[3] = {0, 0, 0};
static const float VecOne[3] = {1, 1, 1};
static const char OP_TRANSLATION[] = "TRANSFORM_OT_translate";
@@ -783,6 +784,19 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
RNA_def_float_vector(
ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Scale", "", -FLT_MAX, FLT_MAX);
+ PropertyRNA *prop;
+ prop = RNA_def_float_vector(ot->srna,
+ "mouse_dir_constraint",
+ 3,
+ VecZero,
+ -FLT_MAX,
+ FLT_MAX,
+ "Mouse Directional Constraint",
+ "",
+ -FLT_MAX,
+ FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
WM_operatortype_props_advanced_begin(ot);
Transform_Properties(ot,
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 1e3acdf1071..298cd00bb46 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -30,6 +30,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
@@ -52,6 +53,8 @@
#include "ED_armature.h"
+#include "SEQ_select.h"
+
#include "transform.h"
#include "transform_orientations.h"
@@ -602,6 +605,16 @@ short transform_orientation_matrix_get(bContext *C,
return V3D_ORIENT_CUSTOM_MATRIX;
}
+ if (t->spacetype == SPACE_SEQ && t->options & CTX_SEQUENCER_IMAGE) {
+ Scene *scene = t->scene;
+ Sequence *seq = SEQ_select_active_get(scene);
+ if (seq && seq->strip->transform && orient_index == V3D_ORIENT_LOCAL) {
+ unit_m3(r_spacemtx);
+ rotate_m3(r_spacemtx, seq->strip->transform->rotation);
+ return orient_index;
+ }
+ }
+
Object *ob = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
Scene *scene = t->scene;