diff options
Diffstat (limited to 'source/blender/editors/transform/transform_gizmo_2d.c')
-rw-r--r-- | source/blender/editors/transform/transform_gizmo_2d.c | 322 |
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(®ion->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; } |