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/transform_gizmo_2d.c')
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c322
1 files changed, 242 insertions, 80 deletions
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;
}