2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-03-01 06:36:16 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-03-01 06:36:16 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:29:51 +00:00
|
|
|
/** \file blender/editors/space_view3d/view3d_snap.c
|
|
|
|
* \ingroup spview3d
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2018-05-14 12:51:55 +02:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
#include "DNA_armature_types.h"
|
2010-08-04 04:01:27 +00:00
|
|
|
#include "DNA_object_types.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2013-11-20 02:40:29 +11:00
|
|
|
#include "BLI_math.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2015-02-23 23:05:54 +11:00
|
|
|
#include "BKE_action.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
#include "BKE_armature.h"
|
2010-08-01 12:47:49 +00:00
|
|
|
#include "BKE_context.h"
|
2018-05-14 12:51:55 +02:00
|
|
|
#include "BKE_editmesh.h"
|
|
|
|
#include "BKE_layer.h"
|
2015-03-04 14:38:16 +11:00
|
|
|
#include "BKE_main.h"
|
2013-06-28 18:19:55 +00:00
|
|
|
#include "BKE_mball.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
#include "BKE_object.h"
|
2016-07-15 18:40:16 +10:00
|
|
|
#include "BKE_report.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "BKE_tracking.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
2018-05-20 09:33:31 +02:00
|
|
|
#include "DEG_depsgraph_query.h"
|
2017-06-08 10:14:53 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
2013-07-20 17:12:33 +00:00
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2015-02-23 23:05:54 +11:00
|
|
|
#include "ED_object.h"
|
2013-11-20 02:40:29 +11:00
|
|
|
#include "ED_transverts.h"
|
2011-10-10 12:56:21 +00:00
|
|
|
#include "ED_keyframing.h"
|
2009-03-01 06:36:16 +00:00
|
|
|
#include "ED_screen.h"
|
|
|
|
|
|
|
|
#include "view3d_intern.h"
|
|
|
|
|
2013-07-20 17:12:33 +00:00
|
|
|
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]);
|
2015-03-04 15:10:48 +11:00
|
|
|
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]);
|
2013-07-20 17:12:33 +00:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
|
|
|
|
/* *********************** operators ******************** */
|
|
|
|
|
2013-07-28 17:06:31 +00:00
|
|
|
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2018-04-06 12:07:27 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2018-05-22 16:34:53 +02:00
|
|
|
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
RegionView3D *rv3d = CTX_wm_region_data(C);
|
2013-11-20 02:40:29 +11:00
|
|
|
TransVertStore tvs = {NULL};
|
2009-03-01 06:36:16 +00:00
|
|
|
TransVert *tv;
|
|
|
|
float gridf, imat[3][3], bmat[3][3], vec[3];
|
|
|
|
int a;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
gridf = rv3d->gridview;
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (obedit) {
|
2018-05-14 12:51:55 +02:00
|
|
|
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, &objects_len);
|
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
obedit = objects[ob_index];
|
|
|
|
if (ED_transverts_check_obedit(obedit)) {
|
|
|
|
ED_transverts_create_from_obedit(&tvs, obedit, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tvs.transverts_tot == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
copy_m3_m4(bmat, obedit->obmat);
|
|
|
|
invert_m3_m3(imat, bmat);
|
|
|
|
|
|
|
|
tv = tvs.transverts;
|
|
|
|
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
|
|
|
|
copy_v3_v3(vec, tv->loc);
|
|
|
|
mul_m3_v3(bmat, vec);
|
|
|
|
add_v3_v3(vec, obedit->obmat[3]);
|
|
|
|
vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
|
|
|
|
vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
|
|
|
|
vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
|
|
|
|
sub_v3_v3(vec, obedit->obmat[3]);
|
|
|
|
|
|
|
|
mul_m3_v3(imat, vec);
|
|
|
|
copy_v3_v3(tv->loc, vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
ED_transverts_update_obedit(&tvs, obedit);
|
|
|
|
ED_transverts_free(&tvs);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2018-05-14 12:51:55 +02:00
|
|
|
MEM_freeN(objects);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-10-23 05:08:02 +00:00
|
|
|
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2018-05-22 16:34:53 +02:00
|
|
|
FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(view_layer_eval, ob_eval)
|
2012-04-30 16:22:40 +00:00
|
|
|
{
|
2018-05-22 16:34:53 +02:00
|
|
|
Object *ob = DEG_get_original_object(ob_eval);
|
2018-04-05 18:20:27 +02:00
|
|
|
if (ob->mode & OB_MODE_POSE) {
|
2018-05-22 16:34:53 +02:00
|
|
|
bPoseChannel *pchan_eval;
|
|
|
|
bArmature *arm_eval = ob_eval->data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-05-22 16:34:53 +02:00
|
|
|
invert_m4_m4(ob_eval->imat, ob_eval->obmat);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-05-22 16:34:53 +02:00
|
|
|
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) {
|
2011-12-07 15:55:37 +00:00
|
|
|
float nLoc[3];
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* get nearest grid point to snap to */
|
2018-05-22 16:34:53 +02:00
|
|
|
copy_v3_v3(nLoc, pchan_eval->pose_mat[3]);
|
2011-12-07 15:55:37 +00:00
|
|
|
/* We must operate in world space! */
|
2018-05-22 16:34:53 +02:00
|
|
|
mul_m4_v3(ob_eval->obmat, nLoc);
|
2013-11-20 02:40:29 +11:00
|
|
|
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);
|
2011-12-07 15:55:37 +00:00
|
|
|
/* Back in object space... */
|
2018-05-22 16:34:53 +02:00
|
|
|
mul_m4_v3(ob_eval->imat, vec);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-01-17 13:30:20 +00:00
|
|
|
/* Get location of grid point in pose space. */
|
2018-05-22 16:34:53 +02:00
|
|
|
BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-05-22 16:34:53 +02:00
|
|
|
/* adjust location on the original pchan*/
|
|
|
|
bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name);
|
2012-03-25 23:54:33 +00:00
|
|
|
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];
|
2011-10-10 12:56:21 +00:00
|
|
|
|
|
|
|
/* auto-keyframing */
|
|
|
|
ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2011-12-07 15:55:37 +00:00
|
|
|
/* if the bone has a parent and is connected to the parent,
|
|
|
|
* don't do anything - will break chain unless we do auto-ik.
|
2009-03-01 06:36:16 +00:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-05-22 16:34:53 +02:00
|
|
|
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);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ob->parent) {
|
2013-07-12 11:18:34 +00:00
|
|
|
float originmat[3][3];
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
invert_m3_m3(imat, originmat);
|
|
|
|
mul_m3_v3(imat, vec);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_LOCX) == 0)
|
2018-05-22 16:34:53 +02:00
|
|
|
ob->loc[0] = ob_eval->loc[0] + vec[0];
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_LOCY) == 0)
|
2018-05-22 16:34:53 +02:00
|
|
|
ob->loc[1] = ob_eval->loc[1] + vec[1];
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
|
2018-05-22 16:34:53 +02:00
|
|
|
ob->loc[2] = ob_eval->loc[2] + vec[2];
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* auto-keyframing */
|
2011-10-10 12:56:21 +00:00
|
|
|
ED_autokeyframe_object(C, scene, ob, ks);
|
2013-02-21 19:33:04 +00:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-22 16:34:53 +02:00
|
|
|
FOREACH_SELECTED_EDITABLE_OBJECT_END;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2009-11-24 11:48:16 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Snap Selection to Grid";
|
2013-07-29 03:01:53 +00:00
|
|
|
ot->description = "Snap selected item(s) to nearest grid division";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "VIEW3D_OT_snap_selected_to_grid";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* api callbacks */
|
2013-07-28 17:06:31 +00:00
|
|
|
ot->exec = snap_sel_to_grid_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_region_view3d_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* *************************************************** */
|
|
|
|
|
2016-07-15 17:12:43 +10:00
|
|
|
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2018-04-06 12:07:27 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2012-03-25 23:54:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2015-03-04 14:38:16 +11:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
Object *obact = CTX_data_active_object(C);
|
2012-03-25 23:54:33 +00:00
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
2013-11-20 02:40:29 +11:00
|
|
|
TransVertStore tvs = {NULL};
|
2009-03-01 06:36:16 +00:00
|
|
|
TransVert *tv;
|
2013-07-20 15:43:48 +00:00
|
|
|
float imat[3][3], bmat[3][3];
|
2013-07-20 17:12:33 +00:00
|
|
|
float center_global[3];
|
|
|
|
float offset_global[3];
|
2009-03-01 06:36:16 +00:00
|
|
|
int a;
|
|
|
|
|
2013-07-20 17:12:33 +00:00
|
|
|
if (use_offset) {
|
2018-05-12 21:56:47 +02:00
|
|
|
if ((v3d && scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) &&
|
2015-03-04 15:10:48 +11:00
|
|
|
snap_calc_active_center(C, true, center_global))
|
2015-02-23 22:24:48 +11:00
|
|
|
{
|
|
|
|
/* pass */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
snap_curs_to_sel_ex(C, center_global);
|
|
|
|
}
|
2016-07-15 17:12:43 +10:00
|
|
|
sub_v3_v3v3(offset_global, snap_target_global, center_global);
|
2013-07-20 17:12:33 +00:00
|
|
|
}
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (obedit) {
|
2016-07-15 17:12:43 +10:00
|
|
|
float snap_target_local[3];
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
if (ED_transverts_check_obedit(obedit))
|
|
|
|
ED_transverts_create_from_obedit(&tvs, obedit, 0);
|
|
|
|
if (tvs.transverts_tot == 0)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_m3_m4(bmat, obedit->obmat);
|
|
|
|
invert_m3_m3(imat, bmat);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-07-20 17:12:33 +00:00
|
|
|
/* get the cursor in object space */
|
2016-07-15 17:12:43 +10:00
|
|
|
sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
|
|
|
|
mul_m3_v3(imat, snap_target_local);
|
2013-07-20 17:12:33 +00:00
|
|
|
|
|
|
|
if (use_offset) {
|
|
|
|
float offset_local[3];
|
|
|
|
|
|
|
|
mul_v3_m3v3(offset_local, imat, offset_global);
|
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
tv = tvs.transverts;
|
|
|
|
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
|
2013-07-20 17:12:33 +00:00
|
|
|
add_v3_v3(tv->loc, offset_local);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-11-20 02:40:29 +11:00
|
|
|
tv = tvs.transverts;
|
|
|
|
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
|
2016-07-15 17:12:43 +10:00
|
|
|
copy_v3_v3(tv->loc, snap_target_local);
|
2013-07-20 17:12:33 +00:00
|
|
|
}
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
ED_transverts_update_obedit(&tvs, obedit);
|
|
|
|
ED_transverts_free(&tvs);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (obact && (obact->mode & OB_MODE_POSE)) {
|
2011-10-23 05:08:02 +00:00
|
|
|
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
|
2011-10-10 12:56:21 +00:00
|
|
|
|
2015-03-04 14:38:16 +11:00
|
|
|
bPoseChannel *pchan;
|
|
|
|
bArmature *arm = obact->data;
|
2016-07-15 17:12:43 +10:00
|
|
|
float snap_target_local[3];
|
2013-07-20 17:12:33 +00:00
|
|
|
|
2015-03-04 14:38:16 +11:00
|
|
|
invert_m4_m4(obact->imat, obact->obmat);
|
2016-07-15 17:12:43 +10:00
|
|
|
mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);
|
2015-03-04 14:38:16 +11:00
|
|
|
|
|
|
|
for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
|
|
|
|
if ((pchan->bone->flag & BONE_SELECTED) &&
|
|
|
|
(PBONE_VISIBLE(arm, pchan->bone)) &&
|
|
|
|
/* if the bone has a parent and is connected to the parent,
|
|
|
|
* don't do anything - will break chain unless we do auto-ik.
|
|
|
|
*/
|
|
|
|
(pchan->bone->flag & BONE_CONNECTED) == 0)
|
|
|
|
{
|
|
|
|
pchan->bone->flag |= BONE_TRANSFORM;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pchan->bone->flag &= ~BONE_TRANSFORM;
|
|
|
|
}
|
|
|
|
}
|
2013-07-20 17:12:33 +00:00
|
|
|
|
2015-03-04 14:38:16 +11:00
|
|
|
for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
|
|
|
|
if ((pchan->bone->flag & BONE_TRANSFORM) &&
|
|
|
|
/* check that our parents not transformed (if we have one) */
|
|
|
|
((pchan->bone->parent &&
|
|
|
|
BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
|
|
|
|
{
|
|
|
|
/* Get position in pchan (pose) space. */
|
|
|
|
float cursor_pose[3];
|
2012-01-17 13:30:20 +00:00
|
|
|
|
2015-03-04 14:38:16 +11:00
|
|
|
if (use_offset) {
|
|
|
|
mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
|
|
|
|
add_v3_v3(cursor_pose, offset_global);
|
2011-10-10 12:56:21 +00:00
|
|
|
|
2015-03-04 14:38:16 +11:00
|
|
|
mul_m4_v3(obact->imat, cursor_pose);
|
|
|
|
BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2015-03-04 14:38:16 +11:00
|
|
|
else {
|
2016-07-15 17:12:43 +10:00
|
|
|
BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
|
2015-03-04 14:38:16 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/* copy new position */
|
|
|
|
if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
|
|
|
|
pchan->loc[0] = cursor_pose[0];
|
|
|
|
if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
|
|
|
|
pchan->loc[1] = cursor_pose[1];
|
|
|
|
if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
|
|
|
|
pchan->loc[2] = cursor_pose[2];
|
|
|
|
|
|
|
|
/* auto-keyframing */
|
|
|
|
ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2015-03-04 14:38:16 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
|
|
|
|
pchan->bone->flag &= ~BONE_TRANSFORM;
|
|
|
|
}
|
|
|
|
|
|
|
|
obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
|
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&obact->id, OB_RECALC_DATA);
|
2015-03-04 14:38:16 +11:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
|
|
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
|
|
|
|
ListBase ctx_data_list;
|
|
|
|
CollectionPointerLink *ctx_ob;
|
|
|
|
Object *ob;
|
|
|
|
|
|
|
|
CTX_data_selected_editable_objects(C, &ctx_data_list);
|
|
|
|
|
|
|
|
/* reset flags */
|
|
|
|
for (ob = bmain->object.first; ob; ob = ob->id.next) {
|
|
|
|
ob->flag &= ~OB_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* tag objects we're transforming */
|
|
|
|
for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
|
|
|
|
ob = ctx_ob->ptr.data;
|
|
|
|
ob->flag |= OB_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
|
|
|
|
ob = ctx_ob->ptr.data;
|
|
|
|
|
|
|
|
if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {
|
|
|
|
|
2013-07-20 15:43:48 +00:00
|
|
|
float cursor_parent[3]; /* parent-relative */
|
2013-07-20 17:12:33 +00:00
|
|
|
|
|
|
|
if (use_offset) {
|
|
|
|
add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
|
|
|
|
}
|
|
|
|
else {
|
2016-07-15 17:12:43 +10:00
|
|
|
copy_v3_v3(cursor_parent, snap_target_global);
|
2013-07-20 17:12:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub_v3_v3(cursor_parent, ob->obmat[3]);
|
2015-03-04 14:38:16 +11:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ob->parent) {
|
2013-07-12 11:18:34 +00:00
|
|
|
float originmat[3][3];
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat);
|
2015-03-04 14:38:16 +11:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
invert_m3_m3(imat, originmat);
|
2013-07-20 15:43:48 +00:00
|
|
|
mul_m3_v3(imat, cursor_parent);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_LOCX) == 0)
|
2013-07-20 15:43:48 +00:00
|
|
|
ob->loc[0] += cursor_parent[0];
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_LOCY) == 0)
|
2013-07-20 15:43:48 +00:00
|
|
|
ob->loc[1] += cursor_parent[1];
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
|
2013-07-20 15:43:48 +00:00
|
|
|
ob->loc[2] += cursor_parent[2];
|
2011-10-10 12:56:21 +00:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* auto-keyframing */
|
2011-10-10 12:56:21 +00:00
|
|
|
ED_autokeyframe_object(C, scene, ob, ks);
|
2013-02-21 19:33:04 +00:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-04 14:38:16 +11:00
|
|
|
|
|
|
|
BLI_freelistN(&ctx_data_list);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2009-11-24 11:48:16 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2016-07-15 17:07:18 +10:00
|
|
|
static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
|
|
|
|
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
|
|
|
2018-05-08 14:18:09 +02:00
|
|
|
const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d)->location;
|
2016-07-15 17:07:18 +10:00
|
|
|
|
|
|
|
return snap_selected_to_location(C, snap_target_global, use_offset);
|
|
|
|
}
|
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Snap Selection to Cursor";
|
|
|
|
ot->description = "Snap selected item(s) to cursor";
|
|
|
|
ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* api callbacks */
|
2016-07-15 17:07:18 +10:00
|
|
|
ot->exec = snap_selected_to_cursor_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_view3d_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2013-07-20 17:12:33 +00:00
|
|
|
|
|
|
|
/* rna */
|
|
|
|
RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", "");
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
2016-07-15 17:07:18 +10:00
|
|
|
static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2016-07-15 18:40:16 +10:00
|
|
|
float snap_target_global[3];
|
2016-07-15 17:07:18 +10:00
|
|
|
|
|
|
|
if (snap_calc_active_center(C, false, snap_target_global) == false) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active element found!");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return snap_selected_to_location(C, snap_target_global, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Snap Selection to Active";
|
|
|
|
ot->description = "Snap selected item(s) to the active item";
|
|
|
|
ot->idname = "VIEW3D_OT_snap_selected_to_active";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec = snap_selected_to_active_exec;
|
|
|
|
ot->poll = ED_operator_view3d_active;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* *************************************************** */
|
|
|
|
|
2013-07-28 17:06:31 +00:00
|
|
|
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
RegionView3D *rv3d = CTX_wm_region_data(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
2009-03-01 06:36:16 +00:00
|
|
|
float gridf, *curs;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
gridf = rv3d->gridview;
|
2018-05-08 14:18:09 +02:00
|
|
|
curs = ED_view3d_cursor3d_get(scene, v3d)->location;
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
curs[0] = gridf * floorf(0.5f + curs[0] / gridf);
|
|
|
|
curs[1] = gridf * floorf(0.5f + curs[1] / gridf);
|
|
|
|
curs[2] = gridf * floorf(0.5f + curs[2] / gridf);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-07-08 20:36:00 +00:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); /* hrm */
|
2018-05-20 09:33:31 +02:00
|
|
|
DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
|
2012-07-08 20:36:00 +00:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Snap Cursor to Grid";
|
2013-07-29 03:01:53 +00:00
|
|
|
ot->description = "Snap cursor to nearest grid division";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "VIEW3D_OT_snap_cursor_to_grid";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* api callbacks */
|
2013-07-28 17:06:31 +00:00
|
|
|
ot->exec = snap_curs_to_grid_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_region_view3d_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* **************************************************** */
|
|
|
|
|
2018-05-29 16:11:08 +02:00
|
|
|
static void bundle_midpoint(Depsgraph *depsgraph, Scene *scene, Object *ob, float vec[3])
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2013-09-09 11:37:37 +00:00
|
|
|
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
|
2011-12-31 03:45:31 +00:00
|
|
|
MovieTracking *tracking;
|
|
|
|
MovieTrackingObject *object;
|
2014-04-11 11:25:41 +10:00
|
|
|
bool ok = false;
|
2014-04-29 18:12:44 +10:00
|
|
|
float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (!clip)
|
2011-11-07 12:55:18 +00:00
|
|
|
return;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
tracking = &clip->tracking;
|
2011-12-15 16:10:49 +00:00
|
|
|
|
2012-01-04 11:20:50 +00:00
|
|
|
copy_m4_m4(cammat, ob->obmat);
|
2011-12-15 16:10:49 +00:00
|
|
|
|
2018-05-29 16:11:08 +02:00
|
|
|
BKE_tracking_get_camera_object_matrix(depsgraph, scene, ob, mat);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
for (object = tracking->objects.first; object; object = object->next) {
|
2012-06-15 11:03:23 +00:00
|
|
|
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
|
2012-03-25 23:54:33 +00:00
|
|
|
MovieTrackingTrack *track = tracksbase->first;
|
2011-12-15 16:10:49 +00:00
|
|
|
float obmat[4][4];
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (object->flag & TRACKING_OBJECT_CAMERA) {
|
2011-12-15 16:10:49 +00:00
|
|
|
copy_m4_m4(obmat, mat);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
float imat[4][4];
|
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, scene->r.cfra, imat);
|
2011-12-15 16:10:49 +00:00
|
|
|
invert_m4(imat);
|
|
|
|
|
2013-05-26 18:36:25 +00:00
|
|
|
mul_m4_m4m4(obmat, cammat, imat);
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
while (track) {
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
|
|
|
|
ok = 1;
|
2011-12-15 16:10:49 +00:00
|
|
|
mul_v3_m4v3(pos, obmat, track->bundle_pos);
|
2012-05-13 11:05:52 +00:00
|
|
|
minmax_v3v3_v3(min, max, pos);
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
track = track->next;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ok) {
|
2011-11-08 09:02:47 +00:00
|
|
|
mid_v3_v3v3(vec, min, max);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-20 17:12:33 +00:00
|
|
|
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2018-05-29 16:11:08 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2018-05-20 09:33:31 +02:00
|
|
|
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
2013-11-20 02:40:29 +11:00
|
|
|
TransVertStore tvs = {NULL};
|
2009-03-01 06:36:16 +00:00
|
|
|
TransVert *tv;
|
2013-07-20 17:12:33 +00:00
|
|
|
float bmat[3][3], vec[3], min[3], max[3], centroid[3];
|
2009-03-01 06:36:16 +00:00
|
|
|
int count, a;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
count = 0;
|
2009-03-01 06:36:16 +00:00
|
|
|
INIT_MINMAX(min, max);
|
2012-03-23 20:18:09 +00:00
|
|
|
zero_v3(centroid);
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (obedit) {
|
2013-11-20 02:40:29 +11:00
|
|
|
if (ED_transverts_check_obedit(obedit))
|
|
|
|
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
|
2013-07-20 17:12:33 +00:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
if (tvs.transverts_tot == 0) {
|
2013-07-20 17:12:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-20 09:33:31 +02:00
|
|
|
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
|
|
|
|
copy_m3_m4(bmat, obedit_eval->obmat);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
tv = tvs.transverts;
|
|
|
|
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
|
2011-10-28 12:40:15 +00:00
|
|
|
copy_v3_v3(vec, tv->loc);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m3_v3(bmat, vec);
|
2018-05-20 09:33:31 +02:00
|
|
|
add_v3_v3(vec, obedit_eval->obmat[3]);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(centroid, vec);
|
2012-05-13 11:05:52 +00:00
|
|
|
minmax_v3v3_v3(min, max, vec);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-05-12 21:56:47 +02:00
|
|
|
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEAN) {
|
2013-11-20 02:40:29 +11:00
|
|
|
mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
|
2013-07-20 17:12:33 +00:00
|
|
|
copy_v3_v3(cursor, centroid);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-07-20 17:12:33 +00:00
|
|
|
mid_v3_v3v3(cursor, min, max);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2013-11-20 02:40:29 +11:00
|
|
|
|
|
|
|
ED_transverts_free(&tvs);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *obact = CTX_data_active_object(C);
|
2018-05-20 09:33:31 +02:00
|
|
|
|
2018-04-05 18:20:27 +02:00
|
|
|
if (obact && (obact->mode & OB_MODE_POSE)) {
|
2018-05-20 09:33:31 +02:00
|
|
|
Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
|
|
|
|
bArmature *arm = obact_eval->data;
|
2009-03-01 06:36:16 +00:00
|
|
|
bPoseChannel *pchan;
|
2018-05-20 09:33:31 +02:00
|
|
|
for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) {
|
2012-02-22 16:52:06 +00:00
|
|
|
if (arm->layer & pchan->bone->layer) {
|
|
|
|
if (pchan->bone->flag & BONE_SELECTED) {
|
2011-10-28 12:40:15 +00:00
|
|
|
copy_v3_v3(vec, pchan->pose_head);
|
2018-05-20 09:33:31 +02:00
|
|
|
mul_m4_v3(obact_eval->obmat, vec);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(centroid, vec);
|
2012-05-13 11:05:52 +00:00
|
|
|
minmax_v3v3_v3(min, max, vec);
|
2009-03-01 06:36:16 +00:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-05-20 09:33:31 +02:00
|
|
|
FOREACH_SELECTED_OBJECT_BEGIN(view_layer_eval, ob_eval)
|
2012-04-30 16:22:40 +00:00
|
|
|
{
|
2018-05-20 09:33:31 +02:00
|
|
|
copy_v3_v3(vec, ob_eval->obmat[3]);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* special case for camera -- snap to bundles */
|
2018-05-20 09:33:31 +02:00
|
|
|
if (ob_eval->type == OB_CAMERA) {
|
2011-11-07 12:55:18 +00:00
|
|
|
/* snap to bundles should happen only when bundles are visible */
|
2012-03-25 23:54:33 +00:00
|
|
|
if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
|
2018-05-29 16:11:08 +02:00
|
|
|
bundle_midpoint(depsgraph, scene, DEG_get_original_object(ob_eval), vec);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(centroid, vec);
|
2012-05-13 11:05:52 +00:00
|
|
|
minmax_v3v3_v3(min, max, vec);
|
2009-03-01 06:36:16 +00:00
|
|
|
count++;
|
|
|
|
}
|
2018-05-20 09:33:31 +02:00
|
|
|
FOREACH_SELECTED_OBJECT_END;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2013-07-20 17:12:33 +00:00
|
|
|
|
|
|
|
if (count == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-12 21:56:47 +02:00
|
|
|
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEAN) {
|
2013-07-20 17:12:33 +00:00
|
|
|
mul_v3_fl(centroid, 1.0f / (float)count);
|
|
|
|
copy_v3_v3(cursor, centroid);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mid_v3_v3v3(cursor, min, max);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-20 17:12:33 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-07-28 17:06:31 +00:00
|
|
|
static int snap_curs_to_sel_exec(bContext *C, wmOperator *UNUSED(op))
|
2013-07-20 17:12:33 +00:00
|
|
|
{
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
|
|
float *curs;
|
|
|
|
|
2018-05-08 14:18:09 +02:00
|
|
|
curs = ED_view3d_cursor3d_get(scene, v3d)->location;
|
2013-07-20 17:12:33 +00:00
|
|
|
|
|
|
|
if (snap_curs_to_sel_ex(C, curs)) {
|
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
|
2018-05-20 09:33:31 +02:00
|
|
|
DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
|
2013-07-20 17:12:33 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Snap Cursor to Selected";
|
|
|
|
ot->description = "Snap cursor to center of selected item(s)";
|
|
|
|
ot->idname = "VIEW3D_OT_snap_cursor_to_selected";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* api callbacks */
|
2013-07-28 17:06:31 +00:00
|
|
|
ot->exec = snap_curs_to_sel_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_view3d_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ********************************************** */
|
|
|
|
|
2015-02-23 23:05:54 +11:00
|
|
|
/* this could be exported to be a generic function
|
|
|
|
* see: calculateCenterActive */
|
|
|
|
|
2015-03-04 15:10:48 +11:00
|
|
|
static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3])
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2018-05-20 09:33:31 +02:00
|
|
|
const Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
if (obedit) {
|
2018-05-20 09:33:31 +02:00
|
|
|
Object *ob_edit_eval = DEG_get_evaluated_object(depsgraph, obedit);
|
|
|
|
|
|
|
|
if (ED_object_editmode_calc_active_center(ob_edit_eval, select_only, r_center)) {
|
|
|
|
mul_m4_v3(ob_edit_eval->obmat, r_center);
|
2015-03-04 13:28:45 +11:00
|
|
|
return true;
|
2013-06-09 20:28:08 +00:00
|
|
|
}
|
2015-02-23 23:05:54 +11:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
if (ob) {
|
2018-05-20 09:33:31 +02:00
|
|
|
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
|
|
|
|
2018-04-05 18:20:27 +02:00
|
|
|
if (ob->mode & OB_MODE_POSE) {
|
2018-05-20 09:33:31 +02:00
|
|
|
bPoseChannel *pchan = BKE_pose_channel_active(ob_eval);
|
2015-02-23 23:05:54 +11:00
|
|
|
if (pchan) {
|
2015-03-04 15:10:48 +11:00
|
|
|
if (!select_only || (pchan->bone->flag & BONE_SELECTED)) {
|
|
|
|
copy_v3_v3(r_center, pchan->pose_head);
|
2018-05-20 09:33:31 +02:00
|
|
|
mul_m4_v3(ob_eval->obmat, r_center);
|
2015-03-04 15:10:48 +11:00
|
|
|
return true;
|
|
|
|
}
|
2015-02-23 23:05:54 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-05-20 09:33:31 +02:00
|
|
|
|
|
|
|
if (!select_only || (ob_eval->flag & SELECT)) {
|
|
|
|
copy_v3_v3(r_center, ob_eval->obmat[3]);
|
2015-03-04 15:10:48 +11:00
|
|
|
return true;
|
|
|
|
}
|
2013-06-09 20:28:08 +00:00
|
|
|
}
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-23 22:24:48 +11:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op))
|
|
|
|
{
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
|
|
float *curs;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-05-08 14:18:09 +02:00
|
|
|
curs = ED_view3d_cursor3d_get(scene, v3d)->location;
|
2015-02-23 22:24:48 +11:00
|
|
|
|
2015-03-04 15:10:48 +11:00
|
|
|
if (snap_calc_active_center(C, false, curs)) {
|
2015-02-23 22:24:48 +11:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
|
2018-05-20 09:33:31 +02:00
|
|
|
DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
|
|
|
|
|
2015-02-23 22:24:48 +11:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Snap Cursor to Active";
|
|
|
|
ot->description = "Snap cursor to active item";
|
|
|
|
ot->idname = "VIEW3D_OT_snap_cursor_to_active";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* api callbacks */
|
2013-07-28 17:06:31 +00:00
|
|
|
ot->exec = snap_curs_to_active_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_view3d_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
|
|
|
|
2010-01-13 22:17:56 +00:00
|
|
|
/* **************************************************** */
|
|
|
|
/*New Code - Snap Cursor to Center -*/
|
2013-07-28 17:06:31 +00:00
|
|
|
static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
2010-03-22 09:30:00 +00:00
|
|
|
float *curs;
|
2018-05-08 14:18:09 +02:00
|
|
|
curs = ED_view3d_cursor3d_get(scene, v3d)->location;
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
zero_v3(curs);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
|
2018-05-20 09:33:31 +02:00
|
|
|
DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE);
|
|
|
|
|
2009-03-01 06:36:16 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2010-01-13 22:17:56 +00:00
|
|
|
void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Snap Cursor to Center";
|
2018-07-14 01:37:01 +02:00
|
|
|
ot->description = "Snap cursor to world origin";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "VIEW3D_OT_snap_cursor_to_center";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2011-12-07 15:55:37 +00:00
|
|
|
/* api callbacks */
|
2013-07-28 17:06:31 +00:00
|
|
|
ot->exec = snap_curs_to_center_exec;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = ED_operator_view3d_active;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-03-22 09:30:00 +00:00
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2010-01-13 22:17:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* **************************************************** */
|
|
|
|
|
|
|
|
|
2013-03-20 23:14:18 +00:00
|
|
|
bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
|
2009-03-01 06:36:16 +00:00
|
|
|
{
|
2013-11-20 02:40:29 +11:00
|
|
|
TransVertStore tvs = {NULL};
|
2009-03-01 06:36:16 +00:00
|
|
|
TransVert *tv;
|
|
|
|
float centroid[3], vec[3], bmat[3][3];
|
|
|
|
int a;
|
|
|
|
|
2013-06-28 06:54:49 +00:00
|
|
|
/* metaballs are an exception */
|
|
|
|
if (obedit->type == OB_MBALL) {
|
2013-06-28 18:19:55 +00:00
|
|
|
float ob_min[3], ob_max[3];
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed;
|
2013-06-28 06:54:49 +00:00
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT);
|
|
|
|
if (changed) {
|
2013-06-28 18:19:55 +00:00
|
|
|
minmax_v3v3_v3(min, max, ob_min);
|
|
|
|
minmax_v3v3_v3(min, max, ob_max);
|
2013-06-28 06:54:49 +00:00
|
|
|
}
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2013-06-28 06:54:49 +00:00
|
|
|
}
|
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
if (ED_transverts_check_obedit(obedit))
|
|
|
|
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
if (tvs.transverts_tot == 0)
|
|
|
|
return false;
|
2009-03-01 06:36:16 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
copy_m3_m4(bmat, obedit->obmat);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
tv = tvs.transverts;
|
|
|
|
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
|
2012-02-03 02:36:03 +00:00
|
|
|
copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc);
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m3_v3(bmat, vec);
|
2010-04-21 12:27:48 +00:00
|
|
|
add_v3_v3(vec, obedit->obmat[3]);
|
|
|
|
add_v3_v3(centroid, vec);
|
2012-05-13 11:05:52 +00:00
|
|
|
minmax_v3v3_v3(min, max, vec);
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-11-20 02:40:29 +11:00
|
|
|
ED_transverts_free(&tvs);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-20 23:14:18 +00:00
|
|
|
return true;
|
2009-03-01 06:36:16 +00:00
|
|
|
}
|