From 86c0ee80209cdd52e4b360ffcf854144922ac2e6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 26 Feb 2019 00:58:35 +1100 Subject: 3D View: support for editing cursor rotation Add buttons for editing the cursor rotation as well as rotation modes, similar to object and pose bones. --- source/blender/blenkernel/BKE_scene.h | 7 ++ source/blender/blenkernel/intern/scene.c | 99 +++++++++++++++++++++- source/blender/blenloader/intern/readfile.c | 4 +- source/blender/blenloader/intern/versioning_280.c | 16 ++-- source/blender/draw/intern/draw_view.c | 15 +++- source/blender/editors/space_view3d/view3d_edit.c | 33 ++++++-- source/blender/editors/space_view3d/view3d_utils.c | 7 +- .../editors/transform/transform_conversions.c | 30 ++++++- source/blender/makesdna/DNA_view3d_types.h | 9 +- source/blender/makesrna/intern/rna_scene.c | 61 ++++++++++++- 10 files changed, 255 insertions(+), 26 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 7638f8c95d5..a0525a4e9f7 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -36,6 +36,7 @@ struct RenderData; struct Scene; struct TransformOrientation; struct UnitSettings; +struct View3DCursor; struct ViewLayer; struct ViewRender; struct WorkSpace; @@ -201,6 +202,12 @@ struct TransformOrientation *BKE_scene_transform_orientation_find( int BKE_scene_transform_orientation_get_index( const struct Scene *scene, const struct TransformOrientation *orientation); +void BKE_scene_cursor_rot_to_mat3(const struct View3DCursor *cursor, float mat[3][3]); +void BKE_scene_cursor_mat3_to_rot(struct View3DCursor *cursor, const float mat[3][3], bool use_compat); + +void BKE_scene_cursor_rot_to_quat(const struct View3DCursor *cursor, float quat[4]); +void BKE_scene_cursor_quat_to_rot(struct View3DCursor *cursor, const float quat[4], bool use_compat); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b055c3695bc..c73c6ef6ac2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -547,7 +547,10 @@ void BKE_scene_init(Scene *sce) BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(sce, id)); - unit_qt(sce->cursor.rotation); + + sce->cursor.rotation_mode = ROT_MODE_XYZ; + sce->cursor.rotation_quaternion[0] = 1.0f; + sce->cursor.rotation_axis[1] = 1.0f; sce->r.mode = R_OSA; sce->r.cfra = 1; @@ -2242,3 +2245,97 @@ int BKE_scene_transform_orientation_get_index( } /** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name Scene Cursor Rotation + * + * Matches #BKE_object_rot_to_mat3 and #BKE_object_mat3_to_rot. + * \{ */ + +void BKE_scene_cursor_rot_to_mat3(const View3DCursor *cursor, float mat[3][3]) +{ + if (cursor->rotation_mode > 0) { + eulO_to_mat3(mat, cursor->rotation_euler, cursor->rotation_mode); + } + else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) { + axis_angle_to_mat3(mat, cursor->rotation_axis, cursor->rotation_angle); + } + else { + float tquat[4]; + normalize_qt_qt(tquat, cursor->rotation_quaternion); + quat_to_mat3(mat, tquat); + } +} + +void BKE_scene_cursor_rot_to_quat(const View3DCursor *cursor, float quat[4]) +{ + if (cursor->rotation_mode > 0) { + eulO_to_quat(quat, cursor->rotation_euler, cursor->rotation_mode); + } + else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) { + axis_angle_to_quat(quat, cursor->rotation_axis, cursor->rotation_angle); + } + else { + normalize_qt_qt(quat, cursor->rotation_quaternion); + } +} + +void BKE_scene_cursor_mat3_to_rot(View3DCursor *cursor, const float mat[3][3], bool use_compat) +{ + BLI_ASSERT_UNIT_M3(mat); + + switch (cursor->rotation_mode) { + case ROT_MODE_QUAT: + { + mat3_normalized_to_quat(cursor->rotation_quaternion, mat); + break; + } + case ROT_MODE_AXISANGLE: + { + mat3_to_axis_angle(cursor->rotation_axis, &cursor->rotation_angle, mat); + break; + } + default: + { + if (use_compat) { + mat3_to_compatible_eulO(cursor->rotation_euler, cursor->rotation_euler, cursor->rotation_mode, mat); + } + else { + mat3_to_eulO(cursor->rotation_euler, cursor->rotation_mode, mat); + } + break; + } + } +} + +void BKE_scene_cursor_quat_to_rot(View3DCursor *cursor, const float quat[4], bool use_compat) +{ + BLI_ASSERT_UNIT_QUAT(quat); + + switch (cursor->rotation_mode) { + case ROT_MODE_QUAT: + { + copy_qt_qt(cursor->rotation_quaternion, quat); + break; + } + case ROT_MODE_AXISANGLE: + { + quat_to_axis_angle(cursor->rotation_axis, &cursor->rotation_angle, quat); + break; + } + default: + { + if (use_compat) { + quat_to_compatible_eulO(cursor->rotation_euler, cursor->rotation_euler, cursor->rotation_mode, quat); + } + else { + quat_to_eulO(cursor->rotation_euler, cursor->rotation_mode, quat); + } + break; + } + } +} + + +/** \} */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7c455c7c20f..e9053d55390 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -8086,8 +8086,8 @@ void blo_lib_link_restore(Main *oldmain, Main *newmain, wmWindowManager *curwm, BKE_workspace_active_set(win->workspace_hook, workspace); /* keep cursor location through undo */ - copy_v3_v3(win->scene->cursor.location, oldscene->cursor.location); - copy_qt_qt(win->scene->cursor.rotation, oldscene->cursor.rotation); + memcpy(&win->scene->cursor, &oldscene->cursor, sizeof(win->scene->cursor)); + lib_link_window_scene_data_restore(win, win->scene, cur_view_layer); BLI_assert(win->screen == NULL); diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 5234efdce03..0c0b4f6c364 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1336,12 +1336,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } - - if (!DNA_struct_find(fd->filesdna, "View3DCursor")) { - for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { - unit_qt(scene->cursor.rotation); - } - } } if (!MAIN_VERSION_ATLEAST(bmain, 280, 14)) { @@ -2821,5 +2815,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + if (!DNA_struct_elem_find(fd->filesdna, "View3DCursor", "short", "rotation_mode")) { + for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { + if (is_zero_v3(scene->cursor.rotation_axis)) { + scene->cursor.rotation_mode = ROT_MODE_XYZ; + scene->cursor.rotation_quaternion[0] = 1.0f; + scene->cursor.rotation_axis[1] = 1.0f; + } + } + } } } diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 2426e98ec84..9bc4e7e8470 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -201,12 +201,18 @@ void DRW_draw_cursor(void) if (is_cursor_visible(draw_ctx, scene, view_layer)) { int co[2]; + + /* Get cursor data into quaternion form */ const View3DCursor *cursor = &scene->cursor; + if (ED_view3d_project_int_global( ar, cursor->location, co, V3D_PROJ_TEST_NOP | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { RegionView3D *rv3d = ar->regiondata; + float cursor_quat[4]; + BKE_scene_cursor_rot_to_quat(cursor, cursor_quat); + /* Draw nice Anti Aliased cursor. */ GPU_line_width(1.0f); glEnable(GL_BLEND); @@ -214,7 +220,12 @@ void DRW_draw_cursor(void) float eps = 1e-5f; rv3d->viewquat[0] = -rv3d->viewquat[0]; - const bool is_aligned = compare_v4v4(cursor->rotation, rv3d->viewquat, eps); + bool is_aligned = compare_v4v4(cursor_quat, rv3d->viewquat, eps); + if (is_aligned == false) { + float tquat[4]; + rotation_between_quats_to_quat(tquat, rv3d->viewquat, cursor_quat); + is_aligned = tquat[0] - eps < -1.0f; + } rv3d->viewquat[0] = -rv3d->viewquat[0]; /* Draw lines */ @@ -241,7 +252,7 @@ void DRW_draw_cursor(void) for (int axis = 0; axis < 3; axis++) { float axis_vec[3] = {0}; axis_vec[axis] = scale; - mul_qt_v3(cursor->rotation, axis_vec); + mul_qt_v3(cursor_quat, axis_vec); CURSOR_EDGE(axis_vec, axis, +); CURSOR_EDGE(axis_vec, axis, -); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 9adcd4c264a..c84e8d9da20 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2712,7 +2712,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op) zero_v3(min); zero_v3(max); zero_v3(cursor->location); - unit_qt(cursor->rotation); + unit_qt(cursor->rotation_quaternion); + zero_v3(cursor->rotation_euler); + ARRAY_SET_ITEMS(cursor->rotation_axis, 0.0f, 1.0f, 0.0f); + cursor->rotation_angle = 0.0f; } else { INIT_MINMAX(min, max); @@ -4762,10 +4765,30 @@ void ED_view3d_cursor3d_update( View3DCursor *cursor_curr = &scene->cursor; View3DCursor cursor_prev = *cursor_curr; - ED_view3d_cursor3d_position_rotation( - C, mval, - use_depth, orientation, - cursor_curr->location, cursor_curr->rotation); + { + float quat[4], quat_prev[4]; + BKE_scene_cursor_rot_to_quat(cursor_curr, quat); + copy_qt_qt(quat_prev, quat); + ED_view3d_cursor3d_position_rotation( + C, mval, + use_depth, orientation, + cursor_curr->location, quat); + + if (!equals_v4v4(quat_prev, quat)) { + if ((cursor_curr->rotation_mode == ROT_MODE_AXISANGLE) && + RV3D_VIEW_IS_AXIS(rv3d->view)) + { + float tmat[3][3], cmat[3][3]; + quat_to_mat3(tmat, quat); + negate_v3_v3(cursor_curr->rotation_axis, tmat[2]); + axis_angle_to_mat3(cmat, cursor_curr->rotation_axis, 0.0f); + cursor_curr->rotation_angle = angle_signed_on_axis_v3v3_v3(cmat[0], tmat[0], cursor_curr->rotation_axis); + } + else { + BKE_scene_cursor_quat_to_rot(cursor_curr, quat, true); + } + } + } /* offset the cursor lock to avoid jumping to new offset */ if (v3d->ob_centre_cursor) { diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 1d8f7e2606c..8a343281bf1 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -45,6 +45,7 @@ #include "BKE_context.h" #include "BKE_object.h" #include "BKE_screen.h" +#include "BKE_scene.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -88,13 +89,15 @@ void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float void ED_view3d_cursor3d_calc_mat3(const Scene *scene, float mat[3][3]) { const View3DCursor *cursor = &scene->cursor; - quat_to_mat3(mat, cursor->rotation); + BKE_scene_cursor_rot_to_mat3(cursor, mat); } void ED_view3d_cursor3d_calc_mat4(const Scene *scene, float mat[4][4]) { const View3DCursor *cursor = &scene->cursor; - quat_to_mat4(mat, cursor->rotation); + float mat3[3][3]; + BKE_scene_cursor_rot_to_mat3(cursor, mat3); + copy_m4_m3(mat, mat3); copy_v3_v3(mat[3], cursor->location); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9da07e0cd06..90ddee99f9c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -405,15 +405,39 @@ static void createTransCursor_view3d(TransInfo *t) td->ob = NULL; unit_m3(td->mtx); - quat_to_mat3(td->axismtx, cursor->rotation); + BKE_scene_cursor_rot_to_mat3(cursor, td->axismtx); normalize_m3(td->axismtx); pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); td->loc = cursor->location; copy_v3_v3(td->iloc, cursor->location); - td->ext->quat = cursor->rotation; - copy_qt_qt(td->ext->iquat, cursor->rotation); + if (cursor->rotation_mode > 0) { + td->ext->rot = cursor->rotation_euler; + td->ext->rotAxis = NULL; + td->ext->rotAngle = NULL; + td->ext->quat = NULL; + + copy_v3_v3(td->ext->irot, cursor->rotation_euler); + } + else if (cursor->rotation_mode == ROT_MODE_AXISANGLE) { + td->ext->rot = NULL; + td->ext->rotAxis = cursor->rotation_axis; + td->ext->rotAngle = &cursor->rotation_angle; + td->ext->quat = NULL; + + td->ext->irotAngle = cursor->rotation_angle; + copy_v3_v3(td->ext->irotAxis, cursor->rotation_axis); + } + else { + td->ext->rot = NULL; + td->ext->rotAxis = NULL; + td->ext->rotAngle = NULL; + td->ext->quat = cursor->rotation_quaternion; + + copy_qt_qt(td->ext->iquat, cursor->rotation_quaternion); + } + td->ext->rotOrder = cursor->rotation_mode; } /** \} */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 32f22ead652..78bebd0b654 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -136,8 +136,13 @@ typedef struct RegionView3D { typedef struct View3DCursor { float location[3]; - float rotation[4]; - char _pad[4]; + + float rotation_quaternion[4]; + float rotation_euler[3]; + float rotation_axis[3], rotation_angle; + short rotation_mode; + + char _pad[6]; } View3DCursor; /* 3D Viewport Shading settings */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index e91670ea61c..babb26a531d 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -40,6 +40,7 @@ #include "BLT_translation.h" +#include "BKE_armature.h" #include "BKE_editmesh.h" #include "BKE_paint.h" @@ -1634,7 +1635,36 @@ static void rna_Scene_sync_mode_set(PointerRNA *ptr, int value) } } +static void rna_Scene_cursor_rotation_mode_set(PointerRNA *ptr, int value) +{ + Scene *scene = ptr->id.data; + View3DCursor *cursor = &scene->cursor; + + /* use API Method for conversions... */ + BKE_rotMode_change_values( + cursor->rotation_quaternion, + cursor->rotation_euler, + cursor->rotation_axis, &cursor->rotation_angle, cursor->rotation_mode, (short)value); + /* finally, set the new rotation type */ + cursor->rotation_mode = value; +} + +static void rna_Scene_cursor_rotation_axis_angle_get(PointerRNA *ptr, float *value) +{ + Scene *scene = ptr->id.data; + View3DCursor *cursor = &scene->cursor; + value[0] = cursor->rotation_angle; + copy_v3_v3(&value[1], cursor->rotation_axis); +} + +static void rna_Scene_cursor_rotation_axis_angle_set(PointerRNA *ptr, const float *value) +{ + Scene *scene = ptr->id.data; + View3DCursor *cursor = &scene->cursor; + cursor->rotation_angle = value[0]; + copy_v3_v3(cursor->rotation_axis, &value[1]); +} static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[], int frame) { @@ -6303,6 +6333,10 @@ void RNA_def_scene(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static float default_quat[4] = {1, 0, 0, 0}; /* default quaternion values */ + static float default_axisAngle[4] = {0, 0, 1, 0}; /* default axis-angle rotation values */ + + /* Struct definition */ srna = RNA_def_struct(brna, "Scene", "ID"); RNA_def_struct_ui_text(srna, "Scene", "Scene data-block, consisting in objects and " @@ -6336,9 +6370,30 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 4); RNA_def_property_update(prop, NC_WINDOW, NULL); - prop = RNA_def_property(srna, "cursor_rotation", PROP_FLOAT, PROP_QUATERNION); - RNA_def_property_float_sdna(prop, NULL, "cursor.rotation"); - RNA_def_property_ui_text(prop, "Cursor Rotation", "3D cursor rotation in quaternions (keep normalized)"); + prop = RNA_def_property(srna, "cursor_rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); + RNA_def_property_float_sdna(prop, NULL, "cursor.rotation_quaternion"); + RNA_def_property_float_array_default(prop, default_quat); + RNA_def_property_ui_text(prop, "Cursor Quaternion Rotation", "3D cursor rotation in quaternions (keep normalized)"); + RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop = RNA_def_property(srna, "cursor_rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); + RNA_def_property_array(prop, 4); + RNA_def_property_float_funcs(prop, "rna_Scene_cursor_rotation_axis_angle_get", + "rna_Scene_cursor_rotation_axis_angle_set", NULL); + RNA_def_property_float_array_default(prop, default_axisAngle); + RNA_def_property_ui_text(prop, "Cursor Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation"); + RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop = RNA_def_property(srna, "cursor_rotation_euler", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "cursor.rotation_euler"); + RNA_def_property_ui_text(prop, "Cursor Euler Rotation", "3D cursor rotation"); + RNA_def_property_update(prop, NC_WINDOW, NULL); + + prop = RNA_def_property(srna, "cursor_rotation_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "cursor.rotation_mode"); + RNA_def_property_enum_items(prop, rna_enum_object_rotation_mode_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_Scene_cursor_rotation_mode_set", NULL); + RNA_def_property_ui_text(prop, "Cursor Rotation Mode", ""); RNA_def_property_update(prop, NC_WINDOW, NULL); prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); -- cgit v1.2.3