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:
authorYimingWu <xp8110@outlook.com>2020-02-01 05:35:40 +0300
committerYimingWu <xp8110@outlook.com>2020-02-01 05:35:40 +0300
commitf7770cb97bb9d19d0806f67da9377129fd4d09b0 (patch)
tree2cd22d612ffba3a509d5548332c9cc8a06a1a638 /source/blender/editors/space_view3d
parentb47883a990ee68e659a8a8b44729be9b8e0d002f (diff)
parentdc3f073d1c5255e79763dfff3ef17f6216f1b391 (diff)
Merge remote-tracking branch 'origin/master' into temp-lanpr-review
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c106
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c19
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c258
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2
7 files changed, 288 insertions, 126 deletions
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 76d9065905a..e2d32181bb3 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1032,19 +1032,9 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
}
}
-/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
- if (WM_cursor_set_from_tool(win, sa, ar)) {
- return;
- }
-
- ViewLayer *view_layer = WM_window_get_active_view_layer(win);
- Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
- if (obedit) {
- WM_cursor_set(win, WM_CURSOR_EDIT);
- }
- else {
+ if (!WM_cursor_set_from_tool(win, sa, ar)) {
WM_cursor_set(win, WM_CURSOR_DEFAULT);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index d40f79cea3f..83fb87264e3 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -158,6 +158,12 @@ typedef struct ViewOpsData {
float trackvec[3];
/** Dolly only. */
float mousevec[3];
+
+ /**
+ * #RegionView3D.persp set after auto-perspective is applied.
+ * If we want the value before running the operator, add a separate member.
+ */
+ char persp;
} init;
/** Previous state (previous modal event handled). */
@@ -413,6 +419,7 @@ static void viewops_data_create(bContext *C,
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
+ vod->init.persp = rv3d->persp;
vod->init.dist = rv3d->dist;
vod->init.camzoom = rv3d->camzoom;
copy_qt_qt(vod->init.quat, rv3d->viewquat);
@@ -613,6 +620,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
float zaxis_best[3];
int x, y, z;
bool found = false;
+ bool is_axis_aligned = false;
invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
@@ -630,6 +638,10 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) {
copy_v3_v3(zaxis_best, zaxis_test);
found = true;
+
+ if (abs(x) + abs(y) + abs(z) == 1) {
+ is_axis_aligned = true;
+ }
}
}
}
@@ -700,6 +712,17 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
copy_qt_qt(rv3d->viewquat, quat_best);
viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
+
+ if (U.uiflag & USER_AUTOPERSP) {
+ if (is_axis_aligned) {
+ if (rv3d->persp == RV3D_PERSP) {
+ rv3d->persp = RV3D_ORTHO;
+ }
+ }
+ }
+ }
+ else if (U.uiflag & USER_AUTOPERSP) {
+ rv3d->persp = vod->init.persp;
}
}
@@ -758,7 +781,32 @@ static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
quat_to_mat3(m, vod->curr.viewquat);
invert_m3_m3(m_inv, m);
- /* avoid gimble lock */
+ /* Avoid Gimble Lock
+ *
+ * Even though turn-table mode is in use, this can occur when the user exits the camera view
+ * or when aligning the view to a rotated object.
+ *
+ * We have gimble lock when the user's view is rotated +/- 90 degrees along the view axis.
+ * In this case the vertical rotation is the same as the sideways turntable motion.
+ * Making it impossible to get out of the gimble locked state without resetting the view.
+ *
+ * The logic below lets the user exit out of this state without any abrupt 'fix'
+ * which would be disorienting.
+ *
+ * This works by blending two horizons:
+ * - Rotated-horizon: `cross_v3_v3v3(xaxis, zvec_global, m_inv[2])`
+ * When only this is used, this turntable rotation works - but it's side-ways
+ * (as if the entire turn-table has been placed on it's side)
+ * While there is no gimble lock, it's also awkward to use.
+ * - Un-rotated-horizon: `m_inv[0]`
+ * When only this is used, the turntable rotation can have gimbal lock.
+ *
+ * The solution used here is to blend between these two values,
+ * so the severity of the gimbal lock is used to blend the rotated horizon.
+ * Blending isn't essential, it just makes the transition smoother.
+ *
+ * This allows sideways turn-table rotation on a Z axis that isn't world-space Z,
+ * While up-down turntable rotation eventually corrects gimble lock. */
#if 1
if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) {
float fac;
@@ -834,6 +882,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_APPLY;
break;
case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
+ vod->rv3d->persp = vod->init.persp;
vod->axis_snap = false;
event_code = VIEW_APPLY;
break;
@@ -1448,10 +1497,20 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) ||
ED_view3d_offset_lock_check(v3d, rv3d);
const bool has_rotation = ndof_has_rotate(ndof, rv3d);
- const bool has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d);
- const bool has_zoom = (ndof->tvec[2] != 0.0f);
+ bool has_translate, has_zoom;
- /* Rotation first because dynamic offset resets offset otherwise (and disasbles panning). */
+ if (is_orbit_around_pivot) {
+ /* Orbit preference or forced lock (Z zooms). */
+ has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d);
+ has_zoom = (ndof->tvec[2] != 0.0f);
+ }
+ else {
+ /* Free preference (Z translates). */
+ has_translate = ndof_has_translate(ndof, v3d, rv3d);
+ has_zoom = false;
+ }
+
+ /* Rotation first because dynamic offset resets offset otherwise (and disables panning). */
if (has_rotation) {
const float dist_backup = rv3d->dist;
if (!is_orbit_around_pivot) {
@@ -4944,6 +5003,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = false,
+ .use_occlusion_test = true,
},
mval_fl,
NULL,
@@ -4957,10 +5017,9 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
copy_v3_v3(cursor_co, ray_co);
}
- float tquat[4];
-
/* Math normal (Z). */
{
+ float tquat[4];
float z_src[3] = {0, 0, 1};
mul_qt_v3(cursor_quat, z_src);
rotation_between_vecs_to_quat(tquat, z_src, ray_no);
@@ -4975,13 +5034,34 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
dot_v3v3(ray_no, obmat[2]),
};
const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot);
- float x_src[3] = {1, 0, 0};
- float x_dst[3];
- mul_qt_v3(cursor_quat, x_src);
- project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no);
- normalize_v3(x_dst);
- rotation_between_vecs_to_quat(tquat, x_src, x_dst);
- mul_qt_qtqt(cursor_quat, tquat, cursor_quat);
+
+ float tquat_best[4];
+ float angle_best = -1.0f;
+
+ float tan_dst[3];
+ project_plane_v3_v3v3(tan_dst, obmat[ortho_axis], ray_no);
+ normalize_v3(tan_dst);
+
+ /* As the tangent is arbitrary from the users point of view,
+ * make the cursor 'roll' on the shortest angle.
+ * otherwise this can cause noticeable 'flipping', see T72419. */
+ for (int axis = 0; axis < 2; axis++) {
+ float tan_src[3] = {0, 0, 0};
+ tan_src[axis] = 1.0f;
+ mul_qt_v3(cursor_quat, tan_src);
+
+ for (int axis_sign = 0; axis_sign < 2; axis_sign++) {
+ float tquat_test[4];
+ rotation_between_vecs_to_quat(tquat_test, tan_src, tan_dst);
+ const float angle_test = angle_normalized_qt(tquat_test);
+ if (angle_test < angle_best || angle_best == -1.0f) {
+ angle_best = angle_test;
+ copy_qt_qt(tquat_best, tquat_test);
+ }
+ negate_v3(tan_src);
+ }
+ }
+ mul_qt_qtqt(cursor_quat, tquat_best, cursor_quat);
}
}
ED_transform_snap_object_context_destroy(snap_context);
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
index 504b10888e8..75ab6518a4f 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
@@ -515,12 +515,9 @@ static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mv
return -1;
}
-static int gizmo_axis_cursor_get(wmGizmo *gz)
+static int gizmo_axis_cursor_get(wmGizmo *UNUSED(gz))
{
- if (gz->highlight_part > 0) {
- return WM_CURSOR_EDIT;
- }
- return WM_CURSOR_NSEW_SCROLL;
+ return WM_CURSOR_DEFAULT;
}
void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt)
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
index 8cd5ed7a478..75d0384182b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c
@@ -22,6 +22,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -52,10 +53,6 @@ static const char *handle_free_id;
static bool WIDGETGROUP_tool_generic_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
- if (!USER_EXPERIMENTAL_TEST(&U, use_tool_fallback)) {
- return false;
- }
-
if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
return false;
}
@@ -65,6 +62,11 @@ static bool WIDGETGROUP_tool_generic_poll(const bContext *C, wmGizmoGroupType *g
return false;
}
+ /* Without this, refreshing the gizmo jitters in some cases with edit-mesh smooth. See T72948. */
+ if (G.moving & G_TRANSFORM_EDIT) {
+ return false;
+ }
+
return true;
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 092142a83cd..89baf60bd8c 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1785,7 +1785,13 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
return hits;
}
-/* returns basact */
+/**
+ * \param has_bones: When true, skip non-bone hits, also allow bases to be used
+ * that are visible but not select-able,
+ * since you may be in pose mode with an an unselect-able object.
+ *
+ * \return the active base or NULL.
+ */
static Base *mouse_select_eval_buffer(ViewContext *vc,
const uint *buffer,
int hits,
@@ -1827,7 +1833,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
base = FIRSTBASE(view_layer);
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
+ if (has_bones ? BASE_VISIBLE(v3d, base) : BASE_SELECTABLE(v3d, base)) {
if (base->object->runtime.select_id == selcol) {
break;
}
@@ -1844,7 +1850,8 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
while (base) {
/* skip objects with select restriction, to prevent prematurely ending this loop
* with an un-selectable choice */
- if ((base->flag & BASE_SELECTABLE) == 0) {
+ if (has_bones ? (base->flag & BASE_VISIBLE_VIEWLAYER) == 0 :
+ (base->flag & BASE_SELECTABLE) == 0) {
base = base->next;
if (base == NULL) {
base = FIRSTBASE(view_layer);
@@ -1854,7 +1861,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
}
}
- if (BASE_SELECTABLE(v3d, base)) {
+ if (has_bones ? BASE_VISIBLE(v3d, base) : BASE_SELECTABLE(v3d, base)) {
for (a = 0; a < hits; a++) {
if (has_bones) {
/* skip non-bone objects */
@@ -2077,7 +2084,8 @@ static bool ed_object_select_pick(bContext *C,
if (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
- if (oldbasact == basact) {
+ MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
+ if (clip != NULL && oldbasact == basact) {
int i, hitresult;
bool changed = false;
@@ -2094,7 +2102,6 @@ static bool ed_object_select_pick(bContext *C,
* in height word, this buffer value belongs to camera. not to bundle
*/
if (buffer[4 * i + 3] & 0xFFFF0000) {
- MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase;
MovieTrackingTrack *track;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 35a116dc4b3..f13f41779c2 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -61,14 +61,16 @@
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]);
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]);
-/* *********************** operators ******************** */
+/* -------------------------------------------------------------------- */
+/** \name Snap Selection to Grid Operator
+ * \{ */
/** Snaps every individual object center to its nearest point on the grid. */
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
- Object *obedit = CTX_data_edit_object(C);
+ Object *obact = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
RegionView3D *rv3d = CTX_wm_region_data(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -79,13 +81,13 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL);
- if (obedit) {
+ if (OBEDIT_FROM_OBACT(obact)) {
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
view_layer, CTX_wm_view3d(C), &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- obedit = objects[ob_index];
+ Object *obedit = objects[ob_index];
if (obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -122,91 +124,117 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
}
MEM_freeN(objects);
}
- else {
+ else if (OBPOSE_FROM_OBACT(obact)) {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
-
- FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
+ uint objects_len = 0;
+ Object **objects_eval = BKE_object_pose_array_get(view_layer_eval, v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_eval = objects_eval[ob_index];
Object *ob = DEG_get_original_object(ob_eval);
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan_eval;
- bArmature *arm_eval = ob_eval->data;
-
- invert_m4_m4(ob_eval->imat, ob_eval->obmat);
-
- for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval;
- pchan_eval = pchan_eval->next) {
- if (pchan_eval->bone->flag & BONE_SELECTED) {
- if (pchan_eval->bone->layer & arm_eval->layer) {
- if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
- float nLoc[3];
-
- /* get nearest grid point to snap to */
- copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
- /* We must operate in world space! */
- mul_m4_v3(ob_eval->obmat, nLoc);
- vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
- vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
- vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
- /* Back in object space... */
- mul_m4_v3(ob_eval->imat, vec);
-
- /* Get location of grid point in pose space. */
- BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
-
- /* adjust location on the original pchan*/
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
- if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
- pchan->loc[0] = vec[0];
- }
- if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
- pchan->loc[1] = vec[1];
- }
- if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
- pchan->loc[2] = vec[2];
- }
-
- /* auto-keyframing */
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
+ bPoseChannel *pchan_eval;
+ bArmature *arm_eval = ob_eval->data;
+
+ invert_m4_m4(ob_eval->imat, ob_eval->obmat);
+
+ for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) {
+ if (pchan_eval->bone->flag & BONE_SELECTED) {
+ if (pchan_eval->bone->layer & arm_eval->layer) {
+ if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) {
+ float nLoc[3];
+
+ /* get nearest grid point to snap to */
+ copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
+ /* We must operate in world space! */
+ mul_m4_v3(ob_eval->obmat, nLoc);
+ vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
+ vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
+ vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
+ /* Back in object space... */
+ mul_m4_v3(ob_eval->imat, vec);
+
+ /* Get location of grid point in pose space. */
+ BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
+
+ /* adjust location on the original pchan*/
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
+ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) {
+ pchan->loc[0] = vec[0];
}
- /* if the bone has a parent and is connected to the parent,
- * don't do anything - will break chain unless we do auto-ik.
- */
+ if ((pchan->protectflag & OB_LOCK_LOCY) == 0) {
+ pchan->loc[1] = vec[1];
+ }
+ if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) {
+ pchan->loc[2] = vec[2];
+ }
+
+ /* auto-keyframing */
+ ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
}
+ /* if the bone has a parent and is connected to the parent,
+ * don't do anything - will break chain unless we do auto-ik.
+ */
}
}
- ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
- else {
- vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
- vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
- vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
+ ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
- if (ob->parent) {
- float originmat[3][3];
- BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ MEM_freeN(objects_eval);
+ }
+ else {
+ /* Object mode. */
+ Main *bmain = CTX_data_main(C);
- invert_m3_m3(imat, originmat);
- mul_m3_v3(imat, vec);
- }
- if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
- ob->loc[0] = ob_eval->loc[0] + vec[0];
- }
- if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
- ob->loc[1] = ob_eval->loc[1] + vec[1];
- }
- if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
- ob->loc[2] = ob_eval->loc[2] + vec[2];
- }
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- /* auto-keyframing */
- ED_autokeyframe_object(C, scene, ob, ks);
+ const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
+ SCE_XFORM_DATA_ORIGIN);
+ struct XFormObjectData_Container *xds = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if (use_transform_data_origin) {
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ xds = ED_object_data_xform_container_create();
+ }
+
+ FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) {
+ Object *ob = DEG_get_original_object(ob_eval);
+ vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf);
+ vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf);
+ vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf);
+
+ if (ob->parent) {
+ float originmat[3][3];
+ BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
+
+ invert_m3_m3(imat, originmat);
+ mul_m3_v3(imat, vec);
+ }
+ if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
+ ob->loc[0] = ob_eval->loc[0] + vec[0];
+ }
+ if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
+ ob->loc[1] = ob_eval->loc[1] + vec[1];
}
+ if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
+ ob->loc[2] = ob_eval->loc[2] + vec[2];
+ }
+
+ /* auto-keyframing */
+ ED_autokeyframe_object(C, scene, ob, ks);
+
+ if (use_transform_data_origin) {
+ ED_object_data_xform_container_item_ensure(xds, ob);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
FOREACH_SELECTED_EDITABLE_OBJECT_END;
+
+ if (use_transform_data_origin) {
+ ED_object_data_xform_container_update_all(xds, bmain, depsgraph);
+ ED_object_data_xform_container_destroy(xds);
+ }
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -229,7 +257,11 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* *************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Selection to Location (Utility)
+ * \{ */
/**
* Snaps the selection as a whole (use_offset=true) or each selected object to the given location.
@@ -317,12 +349,12 @@ static int snap_selected_to_location(bContext *C,
}
MEM_freeN(objects);
}
- else if (obact && (obact->mode & OB_MODE_POSE)) {
+ else if (OBPOSE_FROM_OBACT(obact)) {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
- view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE);
+ Object **objects = BKE_object_pose_array_get(view_layer, v3d, &objects_len);
+
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob = objects[ob_index];
bPoseChannel *pchan;
@@ -393,6 +425,7 @@ static int snap_selected_to_location(bContext *C,
else {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
ListBase ctx_data_list;
CollectionPointerLink *ctx_ob;
@@ -411,6 +444,22 @@ static int snap_selected_to_location(bContext *C,
ob->flag |= OB_DONE;
}
+ const bool use_transform_data_origin = (scene->toolsettings->transform_flag &
+ SCE_XFORM_DATA_ORIGIN);
+ struct XFormObjectData_Container *xds = NULL;
+
+ if (use_transform_data_origin) {
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ xds = ED_object_data_xform_container_create();
+
+ /* Initialize the transform data in a separate loop because the depsgraph
+ * may be evaluated while setting the locations. */
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ ob = ctx_ob->ptr.data;
+ ED_object_data_xform_container_item_ensure(xds, ob);
+ }
+ }
+
for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
ob = ctx_ob->ptr.data;
@@ -431,7 +480,7 @@ static int snap_selected_to_location(bContext *C,
float originmat[3][3], parentmat[4][4];
/* Use the evaluated object here because sometimes
* `ob->parent->runtime.curve_cache` is required. */
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat);
@@ -457,6 +506,11 @@ static int snap_selected_to_location(bContext *C,
}
BLI_freelistN(&ctx_data_list);
+
+ if (use_transform_data_origin) {
+ ED_object_data_xform_container_update_all(xds, bmain, depsgraph);
+ ED_object_data_xform_container_destroy(xds);
+ }
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -464,6 +518,12 @@ static int snap_selected_to_location(bContext *C,
return OPERATOR_FINISHED;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Selection to Cursor Operator
+ * \{ */
+
static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
{
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
@@ -497,7 +557,11 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
"If the selection should be snapped as a whole or by each object center");
}
-/* *************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Selection to Active Operator
+ * \{ */
/** Snaps each selected object to the location of the active selected object. */
static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
@@ -527,7 +591,11 @@ void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* *************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Cursor to Grid Operator
+ * \{ */
/** Snaps the 3D cursor location to its nearest point on the grid. */
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
@@ -565,7 +633,11 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* **************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Cursor to Selection Operator
+ * \{ */
/**
* Returns the center position of a tracking marker visible on the viewport
@@ -761,7 +833,11 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Cursor to Active Operator
+ * \{ */
/**
* Calculates the center position of the active object in global space.
@@ -809,7 +885,11 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* **************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Snap Cursor to Center Operator
+ * \{ */
/** Snaps the 3D cursor location to the origin and clears cursor rotation. */
static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
@@ -842,7 +922,11 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* **************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Min/Max Object Vertices Utility
+ * \{ */
/**
* Calculates the bounding box corners (min and max) for \a obedit.
@@ -890,3 +974,5 @@ bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3])
return true;
}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 494e7529975..34470896fb9 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -676,7 +676,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event)
return;
}
- if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) {
+ if ((walk->is_cursor_absolute == false) && event->tablet.is_motion_absolute) {
walk->is_cursor_absolute = true;
copy_v2_v2_int(walk->prev_mval, event->mval);
copy_v2_v2_int(walk->center_mval, event->mval);