Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_mode_rotate.c
| Show All 27 Lines | |||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_unit.h" | #include "BKE_unit.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_data.h" | |||||
| #include "transform_mode.h" | #include "transform_mode.h" | ||||
| #include "transform_snap.h" | #include "transform_snap.h" | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /* Transform (Rotation) */ | /* Transform (Rotation) */ | ||||
| /** \name Transform Rotation | /** \name Transform Rotation | ||||
| * \{ */ | * \{ */ | ||||
| Show All 11 Lines | |||||
| } | } | ||||
| static void applyRotationValue(TransInfo *t, | static void applyRotationValue(TransInfo *t, | ||||
| float angle, | float angle, | ||||
| float axis[3], | float axis[3], | ||||
| const bool is_large_rotation) | const bool is_large_rotation) | ||||
| { | { | ||||
| float mat[3][3]; | float mat[3][3]; | ||||
| int i; | |||||
| const float angle_sign = angle < 0.0f ? -1.0f : 1.0f; | const float angle_sign = angle < 0.0f ? -1.0f : 1.0f; | ||||
| /* We cannot use something too close to 180°, or 'continuous' rotation may fail | /* We cannot use something too close to 180°, or 'continuous' rotation may fail | ||||
| * due to computing error... */ | * due to computing error... */ | ||||
| const float angle_step = angle_sign * (float)(0.9 * M_PI); | const float angle_step = angle_sign * (float)(0.9 * M_PI); | ||||
| if (is_large_rotation) { | if (is_large_rotation) { | ||||
| /* Just in case, calling code should have already done that in practice | /* Just in case, calling code should have already done that in practice | ||||
| * (for UI feedback reasons). */ | * (for UI feedback reasons). */ | ||||
| angle = large_rotation_limit(angle); | angle = large_rotation_limit(angle); | ||||
| } | } | ||||
| axis_angle_normalized_to_mat3(mat, axis, angle); | axis_angle_normalized_to_mat3(mat, axis, angle); | ||||
| /* Counter for needed updates (when we need to update to non-default matrix, | /* Counter for needed updates (when we need to update to non-default matrix, | ||||
| * we also need another update on next iteration to go back to default matrix, | * we also need another update on next iteration to go back to default matrix, | ||||
| * hence the '2' value used here, instead of a mere boolean). */ | * hence the '2' value used here, instead of a mere boolean). */ | ||||
| short do_update_matrix = 0; | short do_update_matrix = 0; | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (i = 0; i < tc->data_len; i++, td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| if (td->flag & TD_SKIP) { | if (td->basic[tdi].flag & TD_SKIP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| float angle_final = angle; | float angle_final = angle; | ||||
| if (t->con.applyRot) { | if (t->con.applyRot) { | ||||
| t->con.applyRot(t, tc, td, axis, NULL); | t->con.applyRot(t, tc, tdi, axis, NULL); | ||||
| angle_final = angle * td->factor; | angle_final = angle * td->prop[tdi].factor; | ||||
| /* Even though final angle might be identical to orig value, | /* Even though final angle might be identical to orig value, | ||||
| * we have to update the rotation matrix in that case... */ | * we have to update the rotation matrix in that case... */ | ||||
| do_update_matrix = 2; | do_update_matrix = 2; | ||||
| } | } | ||||
| else if (t->flag & T_PROP_EDIT) { | else if (t->flag & T_PROP_EDIT) { | ||||
| angle_final = angle * td->factor; | angle_final = angle * td->prop[tdi].factor; | ||||
| } | } | ||||
| /* Rotation is very likely to be above 180°, we need to do rotation by steps. | /* Rotation is very likely to be above 180°, we need to do rotation by steps. | ||||
| * Note that this is only needed when doing 'absolute' rotation | * Note that this is only needed when doing 'absolute' rotation | ||||
| * (i.e. from initial rotation again, typically when using numinput). | * (i.e. from initial rotation again, typically when using numinput). | ||||
| * regular incremental rotation (from mouse/widget/...) will be called often enough, | * regular incremental rotation (from mouse/widget/...) will be called often enough, | ||||
| * hence steps are small enough to be properly handled without that complicated trick. | * hence steps are small enough to be properly handled without that complicated trick. | ||||
| * Note that we can only do that kind of stepped rotation if we have initial rotation values | * Note that we can only do that kind of stepped rotation if we have initial rotation values | ||||
| * (and access to some actual rotation value storage). | * (and access to some actual rotation value storage). | ||||
| * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing). | * Otherwise, just assume it's useless (e.g. in case of mesh/UV/etc. editing). | ||||
| * Also need to be in Euler rotation mode, the others never allow more than one turn anyway. | * Also need to be in Euler rotation mode, the others never allow more than one turn anyway. | ||||
| */ | */ | ||||
| if (is_large_rotation && td->ext != NULL && td->ext->rotOrder == ROT_MODE_EUL) { | if (is_large_rotation && td->ext && td->ext[tdi].rotOrder == ROT_MODE_EUL) { | ||||
| copy_v3_v3(td->ext->rot, td->ext->irot); | copy_v3_v3(td->ext[tdi].rot, td->ext[tdi].irot); | ||||
| for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final); | for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final); | ||||
| angle_progress += angle_step) { | angle_progress += angle_step) { | ||||
| axis_angle_normalized_to_mat3(mat, axis, angle_progress); | axis_angle_normalized_to_mat3(mat, axis, angle_progress); | ||||
| ElementRotation(t, tc, td, mat, t->around); | ElementRotation(t, tc, tdi, mat, t->around); | ||||
| } | } | ||||
| do_update_matrix = 2; | do_update_matrix = 2; | ||||
| } | } | ||||
| else if (angle_final != angle) { | else if (angle_final != angle) { | ||||
| do_update_matrix = 2; | do_update_matrix = 2; | ||||
| } | } | ||||
| if (do_update_matrix > 0) { | if (do_update_matrix > 0) { | ||||
| axis_angle_normalized_to_mat3(mat, axis, angle_final); | axis_angle_normalized_to_mat3(mat, axis, angle_final); | ||||
| do_update_matrix--; | do_update_matrix--; | ||||
| } | } | ||||
| ElementRotation(t, tc, td, mat, t->around); | ElementRotation(t, tc, tdi, mat, t->around); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) | static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) | ||||
| { | { | ||||
| char str[UI_MAX_DRAW_STR]; | char str[UI_MAX_DRAW_STR]; | ||||
| float final; | float final; | ||||
| final = t->values[0]; | final = t->values[0]; | ||||
| snapGridIncrement(t, &final); | snapGridIncrement(t, &final); | ||||
| float axis_final[3]; | float axis_final[3]; | ||||
| /* Use the negative axis to match the default Z axis of the view matrix. */ | /* Use the negative axis to match the default Z axis of the view matrix. */ | ||||
| negate_v3_v3(axis_final, t->spacemtx[t->orient_axis]); | negate_v3_v3(axis_final, t->spacemtx[t->orient_axis]); | ||||
| if ((t->con.mode & CON_APPLY) && t->con.applyRot) { | if ((t->con.mode & CON_APPLY) && t->con.applyRot) { | ||||
| t->con.applyRot(t, NULL, NULL, axis_final, NULL); | t->con.applyRot(t, NULL, 0, axis_final, NULL); | ||||
| } | } | ||||
| applySnapping(t, &final); | applySnapping(t, &final); | ||||
| if (applyNumInput(&t->num, &final)) { | if (applyNumInput(&t->num, &final)) { | ||||
| /* We have to limit the amount of turns to a reasonable number here, | /* We have to limit the amount of turns to a reasonable number here, | ||||
| * to avoid things getting *very* slow, see how applyRotationValue() handles those... */ | * to avoid things getting *very* slow, see how applyRotationValue() handles those... */ | ||||
| final = large_rotation_limit(final); | final = large_rotation_limit(final); | ||||
| Show All 38 Lines | |||||