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.
This commit is contained in:
parent
213ac7b1ac
commit
86c0ee8020
|
@ -4329,6 +4329,14 @@ class VIEW3D_PT_view3d_cursor(Panel):
|
|||
scene = context.scene
|
||||
|
||||
layout.column().prop(scene, "cursor_location", text="Location")
|
||||
rotation_mode = scene.cursor_rotation_mode
|
||||
if rotation_mode == 'QUATERNION':
|
||||
layout.column().prop(scene, "cursor_rotation_quaternion", text="Rotation")
|
||||
elif rotation_mode == 'AXIS_ANGLE':
|
||||
layout.column().prop(scene, "cursor_rotation_axis_angle", text="Rotation")
|
||||
else:
|
||||
layout.column().prop(scene, "cursor_rotation_euler", text="Rotation")
|
||||
layout.row().prop(scene, "cursor_rotation_mode")
|
||||
|
||||
|
||||
class VIEW3D_PT_collections(Panel):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, -);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue