Cleanup: Move snap callbacks to their respective transform mode

These functions are very specific to the mode.

More modes can support snap, and there is no reason to keep all
callbacks for each mode in the transform_snap.c file.
This commit is contained in:
Germano Cavalcante 2020-06-18 09:08:27 -03:00
parent d56444392f
commit b89898cbd3
Notes: blender-bot 2023-02-14 07:45:38 +01:00
Referenced by issue #77867, Duplicate Object, then Linked Duplicate Object, then Repeat Last Tool causes crash
4 changed files with 160 additions and 217 deletions

View File

@ -44,6 +44,39 @@
/** \name Transform Resize
* \{ */
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
float d1[3], d2[3], len_d1;
sub_v3_v3v3(d1, p1, t->center_global);
sub_v3_v3v3(d2, p2, t->center_global);
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
mul_m3_v3(t->con.pmtx, d1);
mul_m3_v3(t->con.pmtx, d2);
}
project_v3_v3v3(d1, d1, d2);
len_d1 = len_v3(d1);
/* Use 'invalid' dist when `center == p1` (after projecting),
* in this case scale will _never_ move the point in relation to the center,
* so it makes no sense to take it into account when scaling. see: T46503 */
return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
}
static void ApplySnapResize(TransInfo *t, float vec[3])
{
float point[3];
getSnapPoint(t, point);
float dist = ResizeBetween(t, t->tsnap.snapTarget, point);
if (dist != TRANSFORM_DIST_INVALID) {
copy_v3_fl(vec, dist);
}
}
static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
{
float mat[3][3];
@ -134,6 +167,8 @@ void initResize(TransInfo *t)
{
t->mode = TFM_RESIZE;
t->transform = applyResize;
t->tsnap.applySnap = ApplySnapResize;
t->tsnap.distance = ResizeBetween;
initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);

View File

@ -42,6 +42,67 @@
/** \name Transform Rotation
* \{ */
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
float angle, start[3], end[3];
sub_v3_v3v3(start, p1, t->center_global);
sub_v3_v3v3(end, p2, t->center_global);
// Angle around a constraint axis (error prone, will need debug)
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
float axis[3], tmp[3];
t->con.applyRot(t, NULL, NULL, axis, NULL);
project_v3_v3v3(tmp, end, axis);
sub_v3_v3v3(end, end, tmp);
project_v3_v3v3(tmp, start, axis);
sub_v3_v3v3(start, start, tmp);
normalize_v3(end);
normalize_v3(start);
cross_v3_v3v3(tmp, start, end);
if (dot_v3v3(tmp, axis) < 0.0f) {
angle = -acosf(dot_v3v3(start, end));
}
else {
angle = acosf(dot_v3v3(start, end));
}
}
else {
float mtx[3][3];
copy_m3_m4(mtx, t->viewmat);
mul_m3_v3(mtx, end);
mul_m3_v3(mtx, start);
angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
}
if (angle > (float)M_PI) {
angle = angle - 2 * (float)M_PI;
}
else if (angle < -((float)M_PI)) {
angle = 2.0f * (float)M_PI + angle;
}
return angle;
}
static void ApplySnapRotation(TransInfo *t, float *value)
{
float point[3];
getSnapPoint(t, point);
float dist = RotationBetween(t, t->tsnap.snapTarget, point);
*value = dist;
}
static float large_rotation_limit(float angle)
{
/* Limit rotation to 1001 turns max
@ -173,6 +234,8 @@ void initRotation(TransInfo *t)
{
t->mode = TFM_ROTATION;
t->transform = applyRotation;
t->tsnap.applySnap = ApplySnapRotation;
t->tsnap.distance = RotationBetween;
setInputPostFct(&t->mouse, postInputRotation);
initMouseInputMode(t, &t->mouse, INPUT_ANGLE);

View File

@ -34,6 +34,7 @@
#include "BKE_report.h"
#include "BKE_unit.h"
#include "ED_node.h"
#include "ED_screen.h"
#include "WM_api.h"
@ -214,6 +215,39 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
}
}
static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const float p2[3])
{
return len_squared_v3v3(p1, p2);
}
static void ApplySnapTranslation(TransInfo *t, float vec[3])
{
float point[3];
getSnapPoint(t, point);
if (t->spacetype == SPACE_NODE) {
char border = t->tsnap.snapNodeBorder;
if (border & (NODE_LEFT | NODE_RIGHT)) {
vec[0] = point[0] - t->tsnap.snapTarget[0];
}
if (border & (NODE_BOTTOM | NODE_TOP)) {
vec[1] = point[1] - t->tsnap.snapTarget[1];
}
}
else {
if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
if (ED_view3d_project_float_global(t->region, point, point, V3D_PROJ_TEST_NOP) !=
V3D_PROJ_RET_OK) {
zero_v3(point); /* no good answer here... */
}
}
}
sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
}
}
static void applyTranslationValue(TransInfo *t, const float vec[3])
{
const bool apply_snap_align_rotation = usingSnappingNormal(
@ -376,6 +410,8 @@ void initTranslation(TransInfo *t)
}
t->transform = applyTranslation;
t->tsnap.applySnap = ApplySnapTranslation;
t->tsnap.distance = TranslationBetween;
initMouseInputMode(t, &t->mouse, INPUT_VECTOR);

View File

@ -21,24 +21,15 @@
* \ingroup edtransform
*/
/* clang-format off */
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "PIL_time.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
@ -58,7 +49,6 @@
#include "ED_node.h"
#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@ -80,10 +70,6 @@
static void setSnappingCallback(TransInfo *t);
static void ApplySnapTranslation(TransInfo *t, float vec[3]);
static void ApplySnapRotation(TransInfo *t, float *vec);
static void ApplySnapResize(TransInfo *t, float vec[2]);
/* static void CalcSnapGrid(TransInfo *t, float *vec); */
static void CalcSnapGeometry(TransInfo *t, float *vec);
@ -92,10 +78,6 @@ static void TargetSnapCenter(TransInfo *t);
static void TargetSnapClosest(TransInfo *t);
static void TargetSnapActive(TransInfo *t);
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]);
static float TranslationBetween(TransInfo *t, const float p1[3], const float p2[3]);
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]);
/** \} */
/* -------------------------------------------------------------------- */
@ -476,7 +458,6 @@ void resetSnapping(TransInfo *t)
t->tsnap.modeSelect = 0;
t->tsnap.target = 0;
t->tsnap.last = 0;
t->tsnap.applySnap = NULL;
t->tsnap.snapNormal[0] = 0;
t->tsnap.snapNormal[1] = 0;
@ -557,35 +538,32 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.mode = ts->snap_mode;
}
if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && /* Only 3D view or UV */
(t->flag & T_CAMERA) == 0) /* Not with camera selected in camera view */
{
if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && (t->flag & T_CAMERA) == 0) {
/* Only 3D view or UV. */
/* Not with camera selected in camera view. */
setSnappingCallback(t);
/* Edit mode */
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
((obedit_type != -1) &&
/* Temporary limited to edit mode meshes, armature, curves, metaballs. */
ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL))) {
/* Exclude editmesh if using proportional edit */
if ((obedit_type != -1) &&
ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
/* Edit mode */
/* Temporary limited to edit mode meshes, armature, curves, metaballs. */
if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
/* Exclude editmesh if using proportional edit */
t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
}
else {
t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
}
}
/* Particles edit mode*/
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
((obedit_type == -1) && base_act && base_act->object &&
base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
else if ((obedit_type == -1) && base_act && base_act->object &&
(base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
/* Particles edit mode. */
t->tsnap.modeSelect = SNAP_ALL;
}
/* Object mode */
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
(obedit_type == -1)) // Object Mode
{
else if (obedit_type == -1) {
/* Object mode */
if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) {
/* In "Edit Strokes" mode,
* snap tool can perform snap to selected or active objects (see T49632)
@ -605,14 +583,7 @@ static void initSnappingMode(TransInfo *t)
}
else if (t->spacetype == SPACE_NODE) {
setSnappingCallback(t);
if (t->tsnap.applySnap != NULL) {
t->tsnap.modeSelect = SNAP_NOT_SELECTED;
}
else {
/* Grid if snap is not possible */
t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
}
t->tsnap.modeSelect = SNAP_NOT_SELECTED;
}
else if (t->spacetype == SPACE_SEQ) {
/* We do our own snapping currently, so nothing here */
@ -720,8 +691,15 @@ static void setSnappingCallback(TransInfo *t)
t->tsnap.targetSnap = TargetSnapClosest;
break;
case SCE_SNAP_TARGET_CENTER:
t->tsnap.targetSnap = TargetSnapCenter;
break;
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
/* Can't do TARGET_CENTER with these modes,
* use TARGET_MEDIAN instead. */
ATTR_FALLTHROUGH;
}
else {
t->tsnap.targetSnap = TargetSnapCenter;
break;
}
case SCE_SNAP_TARGET_MEDIAN:
t->tsnap.targetSnap = TargetSnapMedian;
break;
@ -729,36 +707,6 @@ static void setSnappingCallback(TransInfo *t)
t->tsnap.targetSnap = TargetSnapActive;
break;
}
switch (t->mode) {
case TFM_TRANSLATION:
t->tsnap.applySnap = ApplySnapTranslation;
t->tsnap.distance = TranslationBetween;
break;
case TFM_ROTATION:
t->tsnap.applySnap = ApplySnapRotation;
t->tsnap.distance = RotationBetween;
// Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
}
break;
case TFM_RESIZE:
t->tsnap.applySnap = ApplySnapResize;
t->tsnap.distance = ResizeBetween;
// Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
}
break;
default:
t->tsnap.applySnap = NULL;
break;
}
}
void addSnapPoint(TransInfo *t)
@ -858,145 +806,6 @@ void getSnapPoint(const TransInfo *t, float vec[3])
/** \} */
/* -------------------------------------------------------------------- */
/** \name Apply Snap
* \{ */
static void ApplySnapTranslation(TransInfo *t, float vec[3])
{
float point[3];
getSnapPoint(t, point);
if (t->spacetype == SPACE_NODE) {
char border = t->tsnap.snapNodeBorder;
if (border & (NODE_LEFT | NODE_RIGHT)) {
vec[0] = point[0] - t->tsnap.snapTarget[0];
}
if (border & (NODE_BOTTOM | NODE_TOP)) {
vec[1] = point[1] - t->tsnap.snapTarget[1];
}
}
else {
if (t->spacetype == SPACE_VIEW3D) {
if (t->options & CTX_PAINT_CURVE) {
if (ED_view3d_project_float_global(t->region, point, point, V3D_PROJ_TEST_NOP) !=
V3D_PROJ_RET_OK) {
zero_v3(point); /* no good answer here... */
}
}
}
sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
}
}
static void ApplySnapRotation(TransInfo *t, float *value)
{
float point[3];
getSnapPoint(t, point);
float dist = RotationBetween(t, t->tsnap.snapTarget, point);
*value = dist;
}
static void ApplySnapResize(TransInfo *t, float vec[3])
{
float point[3];
getSnapPoint(t, point);
float dist = ResizeBetween(t, t->tsnap.snapTarget, point);
if (dist != TRANSFORM_DIST_INVALID) {
copy_v3_fl(vec, dist);
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Distance
* \{ */
static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const float p2[3])
{
return len_squared_v3v3(p1, p2);
}
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
float angle, start[3], end[3];
sub_v3_v3v3(start, p1, t->center_global);
sub_v3_v3v3(end, p2, t->center_global);
// Angle around a constraint axis (error prone, will need debug)
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
float axis[3], tmp[3];
t->con.applyRot(t, NULL, NULL, axis, NULL);
project_v3_v3v3(tmp, end, axis);
sub_v3_v3v3(end, end, tmp);
project_v3_v3v3(tmp, start, axis);
sub_v3_v3v3(start, start, tmp);
normalize_v3(end);
normalize_v3(start);
cross_v3_v3v3(tmp, start, end);
if (dot_v3v3(tmp, axis) < 0.0f) {
angle = -acosf(dot_v3v3(start, end));
}
else {
angle = acosf(dot_v3v3(start, end));
}
}
else {
float mtx[3][3];
copy_m3_m4(mtx, t->viewmat);
mul_m3_v3(mtx, end);
mul_m3_v3(mtx, start);
angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
}
if (angle > (float)M_PI) {
angle = angle - 2 * (float)M_PI;
}
else if (angle < -((float)M_PI)) {
angle = 2.0f * (float)M_PI + angle;
}
return angle;
}
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
float d1[3], d2[3], len_d1;
sub_v3_v3v3(d1, p1, t->center_global);
sub_v3_v3v3(d2, p2, t->center_global);
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
mul_m3_v3(t->con.pmtx, d1);
mul_m3_v3(t->con.pmtx, d2);
}
project_v3_v3v3(d1, d1, d2);
len_d1 = len_v3(d1);
/* Use 'invalid' dist when `center == p1` (after projecting),
* in this case scale will _never_ move the point in relation to the center,
* so it makes no sense to take it into account when scaling. see: T46503 */
return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Calc Snap (Generic)
* \{ */