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:
authorJulian Eisel <julian@blender.org>2020-07-01 18:13:57 +0300
committerJulian Eisel <julian@blender.org>2020-07-01 18:13:57 +0300
commit0829cebeb024095c268f190c34daa8ae9a5a224c (patch)
tree12ee5a4a1c2a32e12eff47c8eb9bb0ed217791c1 /source/blender/editors/transform
parentcfde6ebf450594faa57c4bfeaecff10fe512c91b (diff)
parent42be3964eb201180f6b0fa1ff6ce43b8c3845bc2 (diff)
Merge branch 'master' into asset-uuid--archivedasset-uuid--archived
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r--source/blender/editors/transform/transform.c63
-rw-r--r--source/blender/editors/transform/transform_constraints.c164
-rw-r--r--source/blender/editors/transform/transform_constraints.h6
-rw-r--r--source/blender/editors/transform/transform_convert.c45
-rw-r--r--source/blender/editors/transform/transform_convert.h2
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c33
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mask.c2
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c929
-rw-r--r--source/blender/editors/transform/transform_data.h4
-rw-r--r--source/blender/editors/transform/transform_generics.c64
-rw-r--r--source/blender/editors/transform/transform_mode.c40
-rw-r--r--source/blender/editors/transform/transform_mode.h4
-rw-r--r--source/blender/editors/transform/transform_mode_bbone_resize.c5
-rw-r--r--source/blender/editors/transform/transform_mode_boneenvelope.c1
-rw-r--r--source/blender/editors/transform/transform_mode_edge_slide.c323
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c35
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c63
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c31
-rw-r--r--source/blender/editors/transform/transform_mode_vert_slide.c38
-rw-r--r--source/blender/editors/transform/transform_ops.c4
-rw-r--r--source/blender/editors/transform/transform_snap.c259
-rw-r--r--source/blender/editors/transform/transform_snap.h2
-rw-r--r--source/blender/editors/transform/transform_snap_object.c114
24 files changed, 1224 insertions, 1009 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b02b1814c67..eb60273fc79 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -526,8 +526,11 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
}
/* redraw UV editor */
- if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) &&
- (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
+ const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ?
+ UVCALC_TRANSFORM_CORRECT_SLIDE :
+ UVCALC_TRANSFORM_CORRECT;
+
+ if ((t->data_type == TC_MESH_VERTS) && (t->settings->uvcalc_flag & uvcalc_correct_flag)) {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
@@ -1591,17 +1594,24 @@ static void drawTransformPixel(const struct bContext *C, ARegion *region, void *
void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
{
ToolSettings *ts = CTX_data_tool_settings(C);
- int proportional = 0;
PropertyRNA *prop;
if (!(t->con.mode & CON_APPLY) && (t->flag & T_MODAL) &&
ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE)) {
/* When redoing these modes the first time, it's more convenient to save
- * the Global orientation. */
- mul_m3_v3(t->spacemtx, t->values_final);
- unit_m3(t->spacemtx);
+ * in the Global orientation. */
+ if (t->mode == TFM_TRANSLATION) {
+ mul_m3_v3(t->spacemtx, t->values_final);
+ }
+ else {
+ float tmat[3][3], sizemat[3][3];
+ size_to_mat3(sizemat, t->values_final);
+ mul_m3_m3m3(tmat, t->spacemtx, sizemat);
+ mat3_to_size(t->values_final, tmat);
+ }
BLI_assert(t->orient_curr == 0);
+ unit_m3(t->spacemtx);
t->orient[0].type = V3D_ORIENT_GLOBAL;
}
@@ -1619,15 +1629,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
+ bool use_prop_edit = false;
+ int prop_edit_flag = 0;
if (t->flag & T_PROP_EDIT_ALL) {
if (t->flag & T_PROP_EDIT) {
- proportional |= PROP_EDIT_USE;
+ use_prop_edit = true;
}
if (t->flag & T_PROP_CONNECTED) {
- proportional |= PROP_EDIT_CONNECTED;
+ prop_edit_flag |= PROP_EDIT_CONNECTED;
}
if (t->flag & T_PROP_PROJECTED) {
- proportional |= PROP_EDIT_PROJECTED;
+ prop_edit_flag |= PROP_EDIT_PROJECTED;
}
}
@@ -1639,20 +1651,27 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if (!(t->options & CTX_NO_PET)) {
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) &&
!RNA_property_is_set(op->ptr, prop)) {
+ const Object *obact = OBACT(t->view_layer);
+
if (t->spacetype == SPACE_GRAPH) {
- ts->proportional_fcurve = proportional;
+ ts->proportional_fcurve = use_prop_edit;
}
else if (t->spacetype == SPACE_ACTION) {
- ts->proportional_action = proportional;
- }
- else if (t->obedit_type != -1) {
- ts->proportional_edit = proportional;
+ ts->proportional_action = use_prop_edit;
}
else if (t->options & CTX_MASK) {
- ts->proportional_mask = proportional != 0;
+ ts->proportional_mask = use_prop_edit;
}
- else if ((t->options & CTX_CURSOR) == 0) {
- ts->proportional_objects = proportional != 0;
+ else if (obact && obact->mode == OB_MODE_OBJECT) {
+ ts->proportional_objects = use_prop_edit;
+ }
+ else {
+ if (use_prop_edit) {
+ ts->proportional_edit |= PROP_EDIT_USE;
+ }
+ else {
+ ts->proportional_edit &= ~PROP_EDIT_USE;
+ }
}
}
@@ -1685,9 +1704,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
- RNA_property_boolean_set(op->ptr, prop, proportional & PROP_EDIT_USE);
- RNA_boolean_set(op->ptr, "use_proportional_connected", proportional & PROP_EDIT_CONNECTED);
- RNA_boolean_set(op->ptr, "use_proportional_projected", proportional & PROP_EDIT_PROJECTED);
+ RNA_property_boolean_set(op->ptr, prop, use_prop_edit);
+ RNA_boolean_set(op->ptr, "use_proportional_connected", prop_edit_flag & PROP_EDIT_CONNECTED);
+ RNA_boolean_set(op->ptr, "use_proportional_projected", prop_edit_flag & PROP_EDIT_PROJECTED);
RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
RNA_float_set(op->ptr, "proportional_size", t->prop_size);
}
@@ -1768,7 +1787,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) {
RNA_property_boolean_set(
- op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
+ op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0);
}
}
@@ -1819,6 +1838,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
int options = 0;
PropertyRNA *prop;
+ mode = transform_mode_really_used(C, mode);
+
t->context = C;
/* added initialize, for external calls to set stuff in TransInfo, like undo string */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 838c1880881..66b90eb159f 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -79,6 +79,27 @@ static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3])
}
/* ************************** CONSTRAINTS ************************* */
+#define CONSTRAIN_EPSILON 0.0001f
+
+static void constraint_plane_calc(TransInfo *t, float r_plane[4])
+{
+ const float *constraint_vector[2];
+ int n = 0;
+ for (int i = 0; i < 3; i++) {
+ if (t->con.mode & (CON_AXIS0 << i)) {
+ constraint_vector[n++] = t->spacemtx[i];
+ if (n == 2) {
+ break;
+ }
+ }
+ }
+ BLI_assert(n == 2);
+
+ cross_v3_v3v3(r_plane, constraint_vector[0], constraint_vector[1]);
+ normalize_v3(r_plane);
+ r_plane[3] = -dot_v3v3(r_plane, t->center_global);
+}
+
static void constraintValuesFinal(TransInfo *t, float vec[3])
{
int mode = t->con.mode;
@@ -297,32 +318,83 @@ static void axisProjection(const TransInfo *t,
}
/**
- * Return true if the 2x axis are both aligned when projected into the view.
- * In this case, we can't usefully project the cursor onto the plane.
+ * Snap to the intersection between the edge direction and the constraint plane.
*/
-static bool isPlaneProjectionViewAligned(const TransInfo *t)
+static void constraint_snap_plane_to_edge(const TransInfo *t, const float plane[4], float r_out[3])
{
- const float eps = 0.001f;
- const float *constraint_vector[2];
- int n = 0;
- for (int i = 0; i < 3; i++) {
- if (t->con.mode & (CON_AXIS0 << i)) {
- constraint_vector[n++] = t->spacemtx[i];
- if (n == 2) {
- break;
- }
- }
+ float lambda;
+ const float *edge_snap_point = t->tsnap.snapPoint;
+ const float *edge_dir = t->tsnap.snapNormal;
+ bool is_aligned = fabsf(dot_v3v3(edge_dir, plane)) < CONSTRAIN_EPSILON;
+ if (!is_aligned && isect_ray_plane_v3(edge_snap_point, edge_dir, plane, &lambda, false)) {
+ madd_v3_v3v3fl(r_out, edge_snap_point, edge_dir, lambda);
+ sub_v3_v3(r_out, t->tsnap.snapTarget);
}
- BLI_assert(n == 2);
+}
+
+/**
+ * Snap to the nearest point between the snap point and the line that
+ * intersects the face plane with the constraint plane.
+ */
+static void constraint_snap_plane_to_face(const TransInfo *t, const float plane[4], float r_out[3])
+{
+ float face_plane[4], isect_orig[3], isect_dir[3];
+ const float *face_snap_point = t->tsnap.snapPoint;
+ const float *face_normal = t->tsnap.snapNormal;
+ plane_from_point_normal_v3(face_plane, face_snap_point, face_normal);
+ bool is_aligned = fabsf(dot_v3v3(plane, face_plane)) > (1.0f - CONSTRAIN_EPSILON);
+ if (!is_aligned && isect_plane_plane_v3(plane, face_plane, isect_orig, isect_dir)) {
+ closest_to_ray_v3(r_out, face_snap_point, isect_orig, isect_dir);
+ sub_v3_v3(r_out, t->tsnap.snapTarget);
+ }
+}
- float view_to_plane[3], plane_normal[3];
+/**
+ * Snap to the nearest point on the axis to the edge/line element.
+ */
+void transform_constraint_snap_axis_to_edge(const TransInfo *t,
+ const float axis[3],
+ float r_out[3])
+{
+ float lambda;
+ const float *edge_snap_point = t->tsnap.snapPoint;
+ const float *edge_dir = t->tsnap.snapNormal;
+ bool is_aligned = fabsf(dot_v3v3(axis, edge_dir)) > (1.0f - CONSTRAIN_EPSILON);
+ if (!is_aligned &&
+ isect_ray_ray_v3(t->tsnap.snapTarget, axis, edge_snap_point, edge_dir, &lambda, NULL)) {
+ mul_v3_v3fl(r_out, axis, lambda);
+ }
+}
- getViewVector(t, t->center_global, view_to_plane);
+/**
+ * Snap to the intersection of the axis and the plane defined by the face.
+ */
+void transform_constraint_snap_axis_to_face(const TransInfo *t,
+ const float axis[3],
+ float r_out[3])
+{
+ float lambda;
+ float face_plane[4];
+ const float *face_snap_point = t->tsnap.snapPoint;
+ const float *face_normal = t->tsnap.snapNormal;
+ plane_from_point_normal_v3(face_plane, face_snap_point, face_normal);
+ bool is_aligned = fabsf(dot_v3v3(axis, face_plane)) < CONSTRAIN_EPSILON;
+ if (!is_aligned && isect_ray_plane_v3(t->tsnap.snapTarget, axis, face_plane, &lambda, false)) {
+ mul_v3_v3fl(r_out, axis, lambda);
+ }
+}
- cross_v3_v3v3(plane_normal, constraint_vector[0], constraint_vector[1]);
- normalize_v3(plane_normal);
+/**
+ * Return true if the 2x axis are both aligned when projected into the view.
+ * In this case, we can't usefully project the cursor onto the plane.
+ */
+static bool isPlaneProjectionViewAligned(const TransInfo *t, float plane[4])
+{
+ const float eps = 0.001f;
+ float view_to_plane[3];
+ getViewVector(t, t->center_global, view_to_plane);
- float factor = dot_v3v3(plane_normal, view_to_plane);
+ float factor = dot_v3v3(plane, view_to_plane);
return fabsf(factor) < eps;
}
@@ -361,14 +433,31 @@ static void applyAxisConstraintVec(
copy_v3_v3(out, in);
if (!td && t->con.mode & CON_APPLY) {
mul_m3_v3(t->con.pmtx, out);
+ bool is_snap_to_edge = false, is_snap_to_face = false;
+ if (activeSnap(t)) {
+ is_snap_to_edge = (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) != 0;
+ is_snap_to_face = (t->tsnap.snapElem & SCE_SNAP_MODE_FACE) != 0;
+ }
- // With snap, a projection is alright, no need to correct for view alignment
- if (!validSnap(t)) {
+ /* With snap points, a projection is alright, no adjustments needed. */
+ if (!validSnap(t) || is_snap_to_edge || is_snap_to_face) {
const int dims = getConstraintSpaceDimension(t);
if (dims == 2) {
if (!is_zero_v3(out)) {
- if (!isPlaneProjectionViewAligned(t)) {
- planeProjection(t, in, out);
+ float plane[4];
+ constraint_plane_calc(t, plane);
+
+ if (is_snap_to_edge) {
+ constraint_snap_plane_to_edge(t, plane, out);
+ }
+ else if (is_snap_to_face) {
+ constraint_snap_plane_to_face(t, plane, out);
+ }
+ else {
+ /* View alignment correction. */
+ if (!isPlaneProjectionViewAligned(t, plane)) {
+ planeProjection(t, in, out);
+ }
}
}
}
@@ -384,7 +473,17 @@ static void applyAxisConstraintVec(
else if (t->con.mode & CON_AXIS2) {
copy_v3_v3(c, t->spacemtx[2]);
}
- axisProjection(t, c, in, out);
+
+ if (is_snap_to_edge) {
+ transform_constraint_snap_axis_to_edge(t, c, out);
+ }
+ else if (is_snap_to_face) {
+ transform_constraint_snap_axis_to_face(t, c, out);
+ }
+ else {
+ /* View alignment correction. */
+ axisProjection(t, c, in, out);
+ }
}
}
postConstraintChecks(t, out);
@@ -779,12 +878,21 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformThemeColor(TH_GRID);
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_blend(true);
+
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", 3.0f * U.pixelsize);
+
+ immUniformThemeColorShadeAlpha(TH_GRID, -20, 255);
+ imm_drawcircball(t->center_global, t->prop_size, imat, pos);
- GPU_logic_op_invert_set(true);
+ immUniform1f("lineWidth", 1.0f * U.pixelsize);
+ immUniformThemeColorShadeAlpha(TH_GRID, 20, 255);
imm_drawcircball(t->center_global, t->prop_size, imat, pos);
- GPU_logic_op_invert_set(false);
immUnbindProgram();
diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h
index c41b9361ca4..282060af2c3 100644
--- a/source/blender/editors/transform/transform_constraints.h
+++ b/source/blender/editors/transform/transform_constraints.h
@@ -27,6 +27,12 @@
struct TransInfo;
void constraintNumInput(TransInfo *t, float vec[3]);
+void transform_constraint_snap_axis_to_edge(const TransInfo *t,
+ const float axis[3],
+ float r_out[3]);
+void transform_constraint_snap_axis_to_face(const TransInfo *t,
+ const float axis[3],
+ float r_out[3]);
void setConstraint(TransInfo *t, int mode, const char text[]);
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]);
void setLocalConstraint(TransInfo *t, int mode, const char text[]);
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 064057990e0..5d1fd1543df 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -774,7 +774,7 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
bConstraint *con;
/* loop through constraints, checking if there's one of the mentioned
- * constraints needing special crazyspace corrections
+ * constraints needing special crazy-space corrections
*/
if (list) {
for (con = list->first; con; con = con->next) {
@@ -1148,21 +1148,6 @@ void createTransData(bContext *C, TransInfo *t)
}
t->flag |= T_OBJECT;
-
- /* Check if we're transforming the camera from the camera */
- if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
- View3D *v3d = t->view;
- RegionView3D *rv3d = t->region->regiondata;
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
- /* we could have a flag to easily check an object is being transformed */
- if (v3d->camera->id.tag & LIB_TAG_DOIT) {
- t->flag |= T_CAMERA;
- }
- }
- else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) {
- t->flag |= T_CAMERA;
- }
- }
convert_type = TC_OBJECT;
}
@@ -1175,6 +1160,7 @@ void createTransData(bContext *C, TransInfo *t)
break;
case TC_POSE:
createTransPose(t);
+ /* Disable PET, its not usable in pose mode yet [#32444] */
init_prop_edit = false;
break;
case TC_ARMATURE_VERTS:
@@ -1224,6 +1210,20 @@ void createTransData(bContext *C, TransInfo *t)
break;
case TC_OBJECT:
createTransObject(C, t);
+ /* Check if we're transforming the camera from the camera */
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ View3D *v3d = t->view;
+ RegionView3D *rv3d = t->region->regiondata;
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
+ /* we could have a flag to easily check an object is being transformed */
+ if (v3d->camera->id.tag & LIB_TAG_DOIT) {
+ t->flag |= T_CAMERA;
+ }
+ }
+ else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) {
+ t->flag |= T_CAMERA;
+ }
+ }
break;
case TC_OBJECT_TEXSPACE:
createTransTexspace(t);
@@ -1292,18 +1292,9 @@ void createTransData(bContext *C, TransInfo *t)
* and are still added into transform data. */
sort_trans_data_selected_first(t);
}
- }
-
- /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
- if (t->mode == TFM_BONESIZE) {
- t->flag &= ~(T_EDIT | T_POINTS);
- t->flag |= T_POSE;
- t->obedit_type = -1;
- t->data_type = TC_NONE;
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- tc->poseobj = tc->obedit;
- tc->obedit = NULL;
+ if (!init_prop_edit) {
+ t->flag &= ~T_PROP_EDIT_ALL;
}
}
diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h
index a94bd609d94..f7eea286983 100644
--- a/source/blender/editors/transform/transform_convert.h
+++ b/source/blender/editors/transform/transform_convert.h
@@ -47,7 +47,7 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
void clipUVData(TransInfo *t);
/* transform_convert_mesh.c */
-void trans_mesh_customdata_correction_init(TransInfo *t, struct TransDataContainer *tc);
+void trans_mesh_customdata_correction_init(TransInfo *t);
/* transform_convert_sequencer.c */
int transform_convert_sequencer_get_snap_bound(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 75b51b3d2c4..f721ed0b866 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -553,8 +553,7 @@ static void pose_mirror_info_init(PoseInitData_Mirror *pid,
/** \name Convert Armature
* \{ */
-static void add_pose_transdata(
- TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td)
+static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
{
Bone *bone = pchan->bone;
float pmat[3][3], omat[3][3];
@@ -667,20 +666,16 @@ static void add_pose_transdata(
mul_m3_m3m3(td->axismtx, omat, pmat);
normalize_m3(td->axismtx);
- if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
- bArmature *arm = tc->poseobj->data;
-
- if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
- td->loc = NULL;
- td->val = &bone->dist;
- td->ival = bone->dist;
- }
- else {
- // abusive storage of scale in the loc pointer :)
- td->loc = &bone->xwidth;
- copy_v3_v3(td->iloc, td->loc);
- td->val = NULL;
- }
+ if (t->mode == TFM_BONE_ENVELOPE_DIST) {
+ td->loc = NULL;
+ td->val = &bone->dist;
+ td->ival = bone->dist;
+ }
+ else if (t->mode == TFM_BONESIZE) {
+ // abusive storage of scale in the loc pointer :)
+ td->loc = &bone->xwidth;
+ copy_v3_v3(td->iloc, td->loc);
+ td->val = NULL;
}
/* in this case we can do target-less IK grabbing */
@@ -836,7 +831,7 @@ void createTransPose(TransInfo *t)
td = tc->data;
LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
if (pchan->bone->flag & BONE_TRANSFORM) {
- add_pose_transdata(t, pchan, ob, tc, td);
+ add_pose_transdata(t, pchan, ob, td);
td++;
}
}
@@ -862,8 +857,6 @@ void createTransPose(TransInfo *t)
}
t->flag |= T_POSE;
- /* disable PET, its not usable in pose mode yet [#32444] */
- t->flag &= ~T_PROP_EDIT_ALL;
}
void createTransArmatureVerts(TransInfo *t)
@@ -988,7 +981,7 @@ void createTransArmatureVerts(TransInfo *t)
}
else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) {
if (ebo->flag & BONE_SELECTED) {
- if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) {
+ if (t->mode == TFM_BONE_ENVELOPE_DIST) {
td->loc = NULL;
td->val = &ebo->dist;
td->ival = ebo->dist;
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
index 6c03f86f883..37e37072ed7 100644
--- a/source/blender/editors/transform/transform_convert_curve.c
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -87,7 +87,7 @@ void createTransCurveVerts(TransInfo *t)
t->data_len_all = 0;
- /* Count control points (one per bez-triple) if any number of handles are selected.
+ /* Count control points (one per #BezTriple) if any number of handles are selected.
* Needed for #transform_around_single_fallback_ex. */
int data_len_all_pt = 0;
diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c
index 66c27bca207..6f34c49bdac 100644
--- a/source/blender/editors/transform/transform_convert_mask.c
+++ b/source/blender/editors/transform/transform_convert_mask.c
@@ -149,7 +149,7 @@ static void MaskPointToTransData(Scene *scene,
/* CV coords are scaled by aspects. this is needed for rotations and
* proportional editing to be consistent with the stretched CV coords
- * that are displayed. this also means that for display and numinput,
+ * that are displayed. this also means that for display and number-input,
* and when the CV coords are flushed, these are converted each time */
mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]);
td2d->loc[0] *= asp[0];
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 27ddad262f7..1c286415ea6 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -50,10 +50,11 @@
/* Own include. */
#include "transform_convert.h"
-/* Used for both mirror epsilon and TD_MIRROR_EDGE_ */
-#define TRANSFORM_MAXDIST_MIRROR 0.00002f
+/* -------------------------------------------------------------------- */
+/** \name Island Creation
+ *
+ * \{ */
-/* when transforming islands */
struct TransIslandData {
float (*center)[3];
float (*axismtx)[3][3];
@@ -61,8 +62,186 @@ struct TransIslandData {
int *island_vert_map;
};
+static void editmesh_islands_info_calc(BMEditMesh *em,
+ const bool calc_single_islands,
+ const bool calc_island_center,
+ const bool calc_island_axismtx,
+ struct TransIslandData *r_island_data)
+{
+ BMesh *bm = em->bm;
+ char htype;
+ char itype;
+ int i;
+
+ /* group vars */
+ float(*center)[3] = NULL;
+ float(*axismtx)[3][3] = NULL;
+ int *groups_array;
+ int(*group_index)[2];
+ int group_tot;
+ void **ele_array;
+
+ int *vert_map;
+
+ if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
+ group_tot = BM_mesh_calc_edge_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
+
+ htype = BM_EDGE;
+ itype = BM_VERTS_OF_EDGE;
+ }
+ else { /* (bm->selectmode & SCE_SELECT_FACE) */
+ groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
+
+ htype = BM_FACE;
+ itype = BM_VERTS_OF_FACE;
+ }
+
+ if (calc_island_center) {
+ center = MEM_mallocN(sizeof(*center) * group_tot, __func__);
+ }
+
+ if (calc_island_axismtx) {
+ axismtx = MEM_mallocN(sizeof(*axismtx) * group_tot, __func__);
+ }
+
+ vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
+ /* we shouldn't need this, but with incorrect selection flushing
+ * its possible we have a selected vertex that's not in a face,
+ * for now best not crash in that case. */
+ copy_vn_i(vert_map, bm->totvert, -1);
+
+ BM_mesh_elem_table_ensure(bm, htype);
+ ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ /* may be an edge OR a face array */
+ for (i = 0; i < group_tot; i++) {
+ BMEditSelection ese = {NULL};
+
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ float co[3], no[3], tangent[3];
+ int j;
+
+ zero_v3(co);
+ zero_v3(no);
+ zero_v3(tangent);
+
+ ese.htype = htype;
+
+ /* loop on each face or edge in this group:
+ * - assign r_vert_map
+ * - calculate (co, no)
+ */
+ for (j = 0; j < fg_len; j++) {
+ ese.ele = ele_array[groups_array[fg_sta + j]];
+
+ if (center) {
+ float tmp_co[3];
+ BM_editselection_center(&ese, tmp_co);
+ add_v3_v3(co, tmp_co);
+ }
+
+ if (axismtx) {
+ float tmp_no[3], tmp_tangent[3];
+ BM_editselection_normal(&ese, tmp_no);
+ BM_editselection_plane(&ese, tmp_tangent);
+ add_v3_v3(no, tmp_no);
+ add_v3_v3(tangent, tmp_tangent);
+ }
+
+ {
+ /* setup vertex map */
+ BMIter iter;
+ BMVert *v;
+
+ /* connected edge-verts */
+ BM_ITER_ELEM (v, &iter, ese.ele, itype) {
+ vert_map[BM_elem_index_get(v)] = i;
+ }
+ }
+ }
+
+ if (center) {
+ mul_v3_v3fl(center[i], co, 1.0f / (float)fg_len);
+ }
+
+ if (axismtx) {
+ if (createSpaceNormalTangent(axismtx[i], no, tangent)) {
+ /* pass */
+ }
+ else {
+ if (normalize_v3(no) != 0.0f) {
+ axis_dominant_v3_to_m3(axismtx[i], no);
+ invert_m3(axismtx[i]);
+ }
+ else {
+ unit_m3(axismtx[i]);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
+
+ /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
+ if (calc_single_islands) {
+ BMIter viter;
+ BMVert *v;
+ int group_tot_single = 0;
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
+ group_tot_single += 1;
+ }
+ }
+
+ if (group_tot_single != 0) {
+ if (center) {
+ center = MEM_reallocN(center, sizeof(*center) * (group_tot + group_tot_single));
+ }
+ if (axismtx) {
+ axismtx = MEM_reallocN(axismtx, sizeof(*axismtx) * (group_tot + group_tot_single));
+ }
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
+ vert_map[i] = group_tot;
+ if (center) {
+ copy_v3_v3(center[group_tot], v->co);
+ }
+ if (axismtx) {
+ if (is_zero_v3(v->no) != 0.0f) {
+ axis_dominant_v3_to_m3(axismtx[group_tot], v->no);
+ invert_m3(axismtx[group_tot]);
+ }
+ else {
+ unit_m3(axismtx[group_tot]);
+ }
+ }
+
+ group_tot += 1;
+ }
+ }
+ }
+ }
+
+ r_island_data->axismtx = axismtx;
+ r_island_data->center = center;
+ r_island_data->island_tot = group_tot;
+ r_island_data->island_vert_map = vert_map;
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
-/** \name Edit Mesh Verts Transform Creation
+/** \name Connectivity Distance for Proportional Editing
*
* \{ */
@@ -243,171 +422,25 @@ static void editmesh_set_connectivity_distance(BMesh *bm,
}
}
-static void editmesh_islands_info_calc(BMEditMesh *em,
- const bool calc_single_islands,
- const bool calc_island_axismtx,
- struct TransIslandData *r_island_data)
-{
- BMesh *bm = em->bm;
- char htype;
- char itype;
- int i;
-
- /* group vars */
- float(*center)[3];
- float(*axismtx)[3][3] = NULL;
- int *groups_array;
- int(*group_index)[2];
- int group_tot;
- void **ele_array;
-
- int *vert_map;
-
- if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
- group_tot = BM_mesh_calc_edge_groups(
- bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
-
- htype = BM_EDGE;
- itype = BM_VERTS_OF_EDGE;
- }
- else { /* (bm->selectmode & SCE_SELECT_FACE) */
- groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
- group_tot = BM_mesh_calc_face_groups(
- bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
-
- htype = BM_FACE;
- itype = BM_VERTS_OF_FACE;
- }
-
- center = MEM_mallocN(sizeof(*center) * group_tot, __func__);
-
- if (calc_island_axismtx) {
- axismtx = MEM_mallocN(sizeof(*axismtx) * group_tot, __func__);
- }
-
- vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__);
- /* we shouldn't need this, but with incorrect selection flushing
- * its possible we have a selected vertex that's not in a face,
- * for now best not crash in that case. */
- copy_vn_i(vert_map, bm->totvert, -1);
-
- BM_mesh_elem_table_ensure(bm, htype);
- ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- /* may be an edge OR a face array */
- for (i = 0; i < group_tot; i++) {
- BMEditSelection ese = {NULL};
-
- const int fg_sta = group_index[i][0];
- const int fg_len = group_index[i][1];
- float co[3], no[3], tangent[3];
- int j;
-
- zero_v3(co);
- zero_v3(no);
- zero_v3(tangent);
-
- ese.htype = htype;
-
- /* loop on each face or edge in this group:
- * - assign r_vert_map
- * - calculate (co, no)
- */
- for (j = 0; j < fg_len; j++) {
- float tmp_co[3], tmp_no[3], tmp_tangent[3];
-
- ese.ele = ele_array[groups_array[fg_sta + j]];
-
- BM_editselection_center(&ese, tmp_co);
- add_v3_v3(co, tmp_co);
-
- if (axismtx) {
- BM_editselection_normal(&ese, tmp_no);
- BM_editselection_plane(&ese, tmp_tangent);
- add_v3_v3(no, tmp_no);
- add_v3_v3(tangent, tmp_tangent);
- }
-
- {
- /* setup vertex map */
- BMIter iter;
- BMVert *v;
-
- /* connected edge-verts */
- BM_ITER_ELEM (v, &iter, ese.ele, itype) {
- vert_map[BM_elem_index_get(v)] = i;
- }
- }
- }
-
- mul_v3_v3fl(center[i], co, 1.0f / (float)fg_len);
-
- if (axismtx) {
- if (createSpaceNormalTangent(axismtx[i], no, tangent)) {
- /* pass */
- }
- else {
- if (normalize_v3(no) != 0.0f) {
- axis_dominant_v3_to_m3(axismtx[i], no);
- invert_m3(axismtx[i]);
- }
- else {
- unit_m3(axismtx[i]);
- }
- }
- }
- }
-
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
-
- /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
- if (calc_single_islands) {
- BMIter viter;
- BMVert *v;
- int group_tot_single = 0;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
- group_tot_single += 1;
- }
- }
-
- if (group_tot_single != 0) {
- center = MEM_reallocN(center, sizeof(*center) * (group_tot + group_tot_single));
- if (axismtx) {
- axismtx = MEM_reallocN(axismtx, sizeof(*axismtx) * (group_tot + group_tot_single));
- }
+/** \} */
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
- vert_map[i] = group_tot;
- copy_v3_v3(center[group_tot], v->co);
+/* -------------------------------------------------------------------- */
+/** \name TransDataMirror Creation
+ *
+ * \{ */
- if (axismtx) {
- if (is_zero_v3(v->no) != 0.0f) {
- axis_dominant_v3_to_m3(axismtx[group_tot], v->no);
- invert_m3(axismtx[group_tot]);
- }
- else {
- unit_m3(axismtx[group_tot]);
- }
- }
+/* Used for both mirror epsilon and TD_MIRROR_EDGE_ */
+#define TRANSFORM_MAXDIST_MIRROR 0.00002f
- group_tot += 1;
- }
- }
- }
- }
+struct MirrorDataVert {
+ int index;
+ int flag;
+};
- r_island_data->axismtx = axismtx;
- r_island_data->center = center;
- r_island_data->island_tot = group_tot;
- r_island_data->island_vert_map = vert_map;
-}
+struct TransMirrorData {
+ struct MirrorDataVert *vert_map;
+ int mirror_elem_len;
+};
static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon)
{
@@ -423,172 +456,124 @@ static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const fl
return true;
}
-static TransDataMirror *editmesh_mirror_data_calc(BMEditMesh *em,
- bool use_select,
- const bool use_topology,
- const bool mirror_axis[3],
- int *r_mirror_data_len,
- BLI_bitmap **r_mirror_bitmap)
+static void editmesh_mirror_data_calc(BMEditMesh *em,
+ const bool use_select,
+ const bool use_topology,
+ const bool mirror_axis[3],
+ struct TransMirrorData *r_mirror_data)
{
- BMesh *bm = em->bm;
- int *index[3] = {NULL};
- int i;
-
- bool test_selected_only = use_select && (mirror_axis[0] + mirror_axis[1] + mirror_axis[2]) == 1;
- for (i = 0; i < 3; i++) {
- if (mirror_axis[i]) {
- index[i] = MEM_mallocN(bm->totvert * sizeof(int), __func__);
- EDBM_verts_mirror_cache_begin_ex(
- em, i, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[i]);
- }
- }
+ struct MirrorDataVert *vert_map;
+ BMesh *bm = em->bm;
BMVert *eve;
BMIter iter;
+ int i, flag, totvert = bm->totvert;
- int quadrant[3];
- {
- float select_sum[3] = {0};
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- continue;
- }
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- add_v3_v3(select_sum, eve->co);
- }
- }
-
- for (i = 0; i < 3; i++) {
- if (mirror_axis[i]) {
- quadrant[i] = select_sum[i] >= 0.0f ? 1 : -1;
- }
- else {
- quadrant[i] = 0;
- }
- }
- }
+ vert_map = MEM_mallocN(totvert * sizeof(*vert_map), __func__);
- /* Tag only elements that will be transformed within the quadrant. */
+ float select_sum[3] = {0};
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ vert_map[i] = (struct MirrorDataVert){-1, 0};
if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
continue;
}
- if ((!use_select || BM_elem_flag_test(eve, BM_ELEM_SELECT)) &&
- is_in_quadrant_v3(eve->co, quadrant, TRANSFORM_MAXDIST_MIRROR)) {
- BM_elem_flag_enable(eve, BM_ELEM_TAG);
- BM_elem_index_set(eve, i);
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ add_v3_v3(select_sum, eve->co);
+ }
+ }
+
+ /* Tag only elements that will be transformed within the quadrant. */
+ int quadrant[3];
+ for (int a = 0; a < 3; a++) {
+ if (mirror_axis[a]) {
+ quadrant[a] = select_sum[a] >= 0.0f ? 1 : -1;
}
else {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- BM_elem_index_set(eve, -1);
+ quadrant[a] = 0;
}
}
+ uint mirror_elem_len = 0;
+ int *index[3] = {NULL, NULL, NULL};
+ bool test_selected_only = use_select && (mirror_axis[0] + mirror_axis[1] + mirror_axis[2]) == 1;
for (int a = 0; a < 3; a++) {
- int *index_iter = index[a];
- if (index_iter == NULL) {
+ if (!mirror_axis[a]) {
continue;
}
+
+ index[a] = MEM_mallocN(totvert * sizeof(*index[a]), __func__);
+ EDBM_verts_mirror_cache_begin_ex(
+ em, a, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]);
+
+ flag = TD_MIRROR_X << a;
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ int i_mirr = index[a][i];
+ if (i_mirr < 0) {
+ continue;
+ }
if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
continue;
}
- if (test_selected_only && !BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (use_select && !BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
continue;
}
- int elem_index = BM_elem_index_get(eve);
- if (elem_index != -1) {
- int i_mirr = index_iter[i];
- if (i_mirr >= 0) {
- BMVert *vmir = BM_vert_at_index(bm, i_mirr);
- BM_elem_index_set(vmir, elem_index);
-
- /* The slot of this element in the index array no longer needs to be read.
- * Use to set the mirror sign. */
- if (index[0] && a > 0) {
- index[0][i_mirr] = index[0][i];
- }
- if (index[1] && a > 1) {
- index[1][i_mirr] = index[1][i];
- }
- /* Use -2 to differ from -1, but both can work. */
- index_iter[i_mirr] = -2;
- }
+ if (!is_in_quadrant_v3(eve->co, quadrant, TRANSFORM_MAXDIST_MIRROR)) {
+ continue;
}
- }
- }
- /* Count mirror elements. */
- uint mirror_elem_len = 0;
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN | BM_ELEM_TAG)) {
- /* Not a mirror element. */
- BM_elem_index_set(eve, -1);
- continue;
- }
- int elem_index = BM_elem_index_get(eve);
- if (elem_index != -1) {
+ vert_map[i_mirr] = (struct MirrorDataVert){i, flag};
mirror_elem_len++;
}
}
- TransDataMirror *td_mirror_iter, *td_mirror = NULL;
- if (mirror_elem_len != 0) {
- td_mirror = MEM_mallocN(mirror_elem_len * sizeof(*td_mirror), __func__);
- td_mirror_iter = &td_mirror[0];
-
- *r_mirror_bitmap = BLI_BITMAP_NEW(bm->totvert, __func__);
-
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- int elem_index = BM_elem_index_get(eve);
- if (elem_index != -1) {
- BMVert *v_src = BM_vert_at_index(bm, elem_index);
+ if (mirror_elem_len) {
+ for (int a = 0; a < 3; a++) {
+ if (!mirror_axis[a]) {
+ continue;
+ }
- int flag = 0;
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- flag |= TD_SELECTED;
- }
- if (index[0] && index[0][i] == -2) {
- flag |= TD_MIRROR_X;
- }
- if (index[1] && index[1][i] == -2) {
- flag |= TD_MIRROR_Y;
+ flag = TD_MIRROR_X << a;
+ for (i = 0; i < totvert; i++) {
+ int i_mirr = index[a][i];
+ if (i_mirr < 0) {
+ continue;
}
- if (index[2] && index[2][i] == -2) {
- flag |= TD_MIRROR_Z;
+ if (vert_map[i].index != -1 && !(vert_map[i].flag & flag)) {
+ if (vert_map[i_mirr].index == -1) {
+ mirror_elem_len++;
+ }
+ vert_map[i_mirr].index = vert_map[i].index;
+ vert_map[i_mirr].flag |= vert_map[i].flag | flag;
}
-
- td_mirror_iter->extra = eve;
- td_mirror_iter->loc = eve->co;
- copy_v3_v3(td_mirror_iter->iloc, eve->co);
- td_mirror_iter->flag = flag;
- td_mirror_iter->loc_src = v_src->co;
- /** `center` will be set in the main createTransEditVerts loop.
- * copy_v3_v3(td_mirror_iter->center, eve->co); */
-
- td_mirror_iter++;
-
- BLI_BITMAP_ENABLE(*r_mirror_bitmap, i);
}
}
}
+ else {
+ MEM_freeN(vert_map);
+ vert_map = NULL;
+ }
MEM_SAFE_FREE(index[0]);
MEM_SAFE_FREE(index[1]);
MEM_SAFE_FREE(index[2]);
- bm->elem_index_dirty |= BM_VERT;
- *r_mirror_data_len = mirror_elem_len;
- return td_mirror;
+ r_mirror_data->vert_map = vert_map;
+ r_mirror_data->mirror_elem_len = mirror_elem_len;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Edit Mesh Verts Transform Creation
+ *
+ * \{ */
+
static void transdata_center_get(const struct TransIslandData *island_data,
const int island_index,
- const bool no_island_center,
const float iloc[3],
float r_center[3])
{
- if (island_index != -1 && !no_island_center) {
+ if (island_data->center && island_index != -1) {
copy_v3_v3(r_center, island_data->center[island_index]);
}
else {
@@ -604,8 +589,7 @@ static void VertsToTransData(TransInfo *t,
BMVert *eve,
float *bweight,
const struct TransIslandData *island_data,
- const int island_index,
- const bool no_island_center)
+ const int island_index)
{
float *no, _no[3];
BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
@@ -626,7 +610,7 @@ static void VertsToTransData(TransInfo *t,
no = eve->no;
}
- transdata_center_get(island_data, island_index, no_island_center, td->iloc, td->center);
+ transdata_center_get(island_data, island_index, td->iloc, td->center);
if ((island_index != -1) && island_data->axismtx) {
copy_m3_m3(td->axismtx, island_data->axismtx[island_index]);
@@ -676,31 +660,12 @@ void createTransEditVerts(TransInfo *t)
BMesh *bm = em->bm;
BMVert *eve;
BMIter iter;
- float(*mappedcos)[3] = NULL, (*quats)[4] = NULL;
- float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
- float *dists = NULL;
+ float mtx[3][3], smtx[3][3];
int a;
const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0;
- int cd_vert_bweight_offset = -1;
struct TransIslandData island_data = {NULL};
-
- /* Snap rotation along normal needs a common axis for whole islands,
- * otherwise one get random crazy results, see T59104.
- * However, we do not want to use the island center for the pivot/translation reference. */
- const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
- /* There is not guarantee that snapping
- * is initialized yet at this point... */
- (usingSnappingNormal(t) ||
- (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
- (t->around != V3D_AROUND_LOCAL_ORIGINS));
- /* Even for translation this is needed because of island-orientation, see: T51651. */
- const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
- /* Original index of our connected vertex when connected distances are calculated.
- * Optional, allocate if needed. */
- int *dists_index = NULL;
-
- BLI_bitmap *mirror_bitmap = NULL;
+ struct TransMirrorData mirror_data = {NULL};
/**
* Quick check if we can transform.
@@ -711,20 +676,7 @@ void createTransEditVerts(TransInfo *t)
/* Support other objects using PET to adjust these, unless connected is enabled. */
if ((!prop_mode || (prop_mode & T_PROP_CONNECTED)) && (bm->totvertsel == 0)) {
- goto cleanup;
- }
-
- if (t->mode == TFM_BWEIGHT) {
- BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
- cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- }
-
- if (tc->use_mirror_axis_any) {
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- bool use_select = (t->flag & T_PROP_EDIT) == 0;
- bool mirror_axis[3] = {tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z};
- tc->data_mirror = editmesh_mirror_data_calc(
- em, use_select, use_topology, mirror_axis, &tc->data_mirror_len, &mirror_bitmap);
+ continue;
}
int data_len = 0;
@@ -734,44 +686,41 @@ void createTransEditVerts(TransInfo *t)
data_len++;
}
}
-
- if (data_len == 0) {
- goto cleanup;
- }
-
- /* allocating scratch arrays */
- if (prop_mode & T_PROP_CONNECTED) {
- dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
- if (is_island_center) {
- dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
- }
- }
}
else {
data_len = bm->totvertsel;
}
- if (mirror_bitmap) {
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
- if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- if (BLI_BITMAP_TEST(mirror_bitmap, a)) {
- data_len--;
- }
- }
- }
+ if (data_len == 0) {
+ continue;
}
- BLI_assert(data_len != 0);
+ /* Snap rotation along normal needs a common axis for whole islands,
+ * otherwise one get random crazy results, see T59104.
+ * However, we do not want to use the island center for the pivot/translation reference. */
+ const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) &&
+ /* There is not guarantee that snapping
+ * is initialized yet at this point... */
+ (usingSnappingNormal(t) ||
+ (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) &&
+ (t->around != V3D_AROUND_LOCAL_ORIGINS));
- tc->data_len = data_len;
- tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
- if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
- /* warning, this is overkill, we only need 2 extra floats,
- * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
- * since we may not use the 'alt' transform mode to maintain shell thickness,
- * but with generic transform code its hard to lazy init vars */
- tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
- "TransObData ext");
+ /* Even for translation this is needed because of island-orientation, see: T51651. */
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate;
+ if (is_island_center) {
+ /* In this specific case, near-by vertices will need to know
+ * the island of the nearest connected vertex. */
+ const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
+ (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (em->selectmode & SCE_SELECT_VERTEX));
+
+ const bool calc_island_center = !is_snap_rotate;
+ /* The island axismtx is only necessary in some modes.
+ * TODO(Germano): Extend the list to exclude other modes. */
+ const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN);
+
+ editmesh_islands_info_calc(
+ em, calc_single_islands, calc_island_center, calc_island_axismtx, &island_data);
}
copy_m3_m4(mtx, tc->obedit->obmat);
@@ -779,26 +728,58 @@ void createTransEditVerts(TransInfo *t)
* matrix inversion still works and we can still moving along the other */
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+ /* Original index of our connected vertex when connected distances are calculated.
+ * Optional, allocate if needed. */
+ int *dists_index = NULL;
+ float *dists = NULL;
if (prop_mode & T_PROP_CONNECTED) {
+ dists = MEM_mallocN(bm->totvert * sizeof(float), __func__);
+ if (is_island_center) {
+ dists_index = MEM_mallocN(bm->totvert * sizeof(int), __func__);
+ }
editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
}
- if (is_island_center) {
- /* In this specific case, near-by vertices will need to know
- * the island of the nearest connected vertex. */
- const bool calc_single_islands = ((prop_mode & T_PROP_CONNECTED) &&
- (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
- (em->selectmode & SCE_SELECT_VERTEX));
+ /* Create TransDataMirror. */
+ if (tc->use_mirror_axis_any) {
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ bool use_select = (t->flag & T_PROP_EDIT) == 0;
+ bool mirror_axis[3] = {tc->use_mirror_axis_x, tc->use_mirror_axis_y, tc->use_mirror_axis_z};
+ editmesh_mirror_data_calc(em, use_select, use_topology, mirror_axis, &mirror_data);
- /* The island axismtx is only necessary in some modes.
- * TODO(Germano): Extend the list to exclude other modes. */
- const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN);
+ if (mirror_data.vert_map) {
+ tc->data_mirror_len = mirror_data.mirror_elem_len;
+ tc->data_mirror = MEM_mallocN(mirror_data.mirror_elem_len * sizeof(*tc->data_mirror),
+ __func__);
+
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
+ if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (mirror_data.vert_map[a].index != -1) {
+ data_len--;
+ }
+ }
+ }
+ }
+ }
- editmesh_islands_info_calc(em, calc_single_islands, calc_island_axismtx, &island_data);
+ /* Create TransData. */
+ BLI_assert(data_len >= 1);
+ tc->data_len = data_len;
+ tc->data = MEM_callocN(data_len * sizeof(TransData), "TransObData(Mesh EditMode)");
+ if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
+ /* warning, this is overkill, we only need 2 extra floats,
+ * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill
+ * since we may not use the 'alt' transform mode to maintain shell thickness,
+ * but with generic transform code its hard to lazy init vars */
+ tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension),
+ "TransObData ext");
}
/* detect CrazySpace [tm] */
+ float(*quats)[4] = NULL;
+ float(*defmats)[3][3] = NULL;
if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) {
+ float(*defcos)[3] = NULL;
int totleft = -1;
if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) {
BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
@@ -813,16 +794,17 @@ void createTransEditVerts(TransInfo *t)
t->depsgraph, scene_eval, obedit_eval, em_eval, &defmats, &defcos);
}
- /* if we still have more modifiers, also do crazyspace
- * correction with quats, relative to the coordinates after
- * the modifiers that support deform matrices (defcos) */
+ /* If we still have more modifiers, also do crazy-space
+ * correction with \a quats, relative to the coordinates after
+ * the modifiers that support deform matrices \a defcos. */
-#if 0 /* TODO, fix crazyspace+extrude so it can be enabled for general use - campbell */
+#if 0 /* TODO, fix crazy-space & extrude so it can be enabled for general use - campbell */
if ((totleft > 0) || (totleft == -1))
#else
if (totleft > 0)
#endif
{
+ float(*mappedcos)[3] = NULL;
mappedcos = BKE_crazyspace_get_mapped_editverts(t->depsgraph, tc->obedit);
quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
@@ -836,6 +818,12 @@ void createTransEditVerts(TransInfo *t)
}
}
+ int cd_vert_bweight_offset = -1;
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_VERT_BWEIGHT);
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ }
+
TransData *tob = tc->data;
TransDataMirror *td_mirror = tc->data_mirror;
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
@@ -849,9 +837,20 @@ void createTransEditVerts(TransInfo *t)
island_index = island_data.island_vert_map[connected_index];
}
- if (mirror_bitmap && BLI_BITMAP_TEST(mirror_bitmap, a)) {
- transdata_center_get(
- &island_data, island_index, is_snap_rotate, td_mirror->iloc, td_mirror->center);
+ if (mirror_data.vert_map && mirror_data.vert_map[a].index != -1) {
+ int elem_index = mirror_data.vert_map[a].index;
+ BMVert *v_src = BM_vert_at_index(bm, elem_index);
+
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ mirror_data.vert_map[a].flag |= TD_SELECTED;
+ }
+
+ td_mirror->extra = eve;
+ td_mirror->loc = eve->co;
+ copy_v3_v3(td_mirror->iloc, eve->co);
+ td_mirror->flag = mirror_data.vert_map[a].flag;
+ td_mirror->loc_src = v_src->co;
+ transdata_center_get(&island_data, island_index, td_mirror->iloc, td_mirror->center);
td_mirror++;
}
@@ -862,8 +861,7 @@ void createTransEditVerts(TransInfo *t)
/* Do not use the island center in case we are using islands
* only to get axis for snap/rotate to normal... */
- VertsToTransData(
- t, tob, tx, em, eve, bweight, &island_data, island_index, is_snap_rotate);
+ VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index);
if (tx) {
tx++;
}
@@ -933,17 +931,15 @@ void createTransEditVerts(TransInfo *t)
if (island_data.center) {
MEM_freeN(island_data.center);
}
-
if (island_data.axismtx) {
MEM_freeN(island_data.axismtx);
}
-
if (island_data.island_vert_map) {
MEM_freeN(island_data.island_vert_map);
}
-
- cleanup:
- /* crazy space free */
+ if (mirror_data.vert_map) {
+ MEM_freeN(mirror_data.vert_map);
+ }
if (quats) {
MEM_freeN(quats);
}
@@ -956,9 +952,6 @@ void createTransEditVerts(TransInfo *t)
if (dists_index) {
MEM_freeN(dists_index);
}
- if (mirror_bitmap) {
- MEM_freeN(mirror_bitmap);
- }
}
}
@@ -1075,99 +1068,118 @@ static void create_trans_vert_customdata_layer(BMVert *v,
BLI_ghash_insert(tcld->origverts, v, r_tcld_vert);
}
-void trans_mesh_customdata_correction_init(TransInfo *t, TransDataContainer *tc)
+static void trans_mesh_customdata_correction_init_container(TransInfo *t, TransDataContainer *tc)
{
if (tc->custom.type.data) {
/* Custom data correction has initiated before. */
BLI_assert(tc->custom.type.free_cb == trans_mesh_customdata_free_cb);
return;
}
- int i;
+
+ if (!ELEM(t->mode,
+ TFM_TRANSLATION,
+ TFM_ROTATION,
+ TFM_RESIZE,
+ TFM_TOSPHERE,
+ TFM_SHEAR,
+ TFM_BEND,
+ TFM_SHRINKFATTEN,
+ TFM_TRACKBALL,
+ TFM_PUSHPULL,
+ TFM_ALIGN)) {
+ /* Currently only modes that change the position of vertices are supported. */
+ return;
+ }
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
BMesh *bm = em->bm;
- bool use_origfaces;
- int cd_loop_mdisp_offset;
- {
- const bool has_layer_math = CustomData_has_math(&bm->ldata);
- cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) &&
- /* don't do this at all for non-basis shape keys, too easy to
- * accidentally break uv maps or vertex colors then */
- (bm->shapenr <= 1) && (has_layer_math || (cd_loop_mdisp_offset != -1))) {
- use_origfaces = true;
- }
- else {
- use_origfaces = false;
- cd_loop_mdisp_offset = -1;
- }
+ if (bm->shapenr > 1) {
+ /* Don't do this at all for non-basis shape keys, too easy to
+ * accidentally break uv maps or vertex colors then */
+ /* create copies of faces for customdata projection. */
+ return;
}
- if (use_origfaces) {
- /* create copies of faces for customdata projection */
- bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
-
- struct GHash *origfaces = BLI_ghash_ptr_new(__func__);
- struct BMesh *bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default,
- &((struct BMeshCreateParams){
- .use_toolflags = false,
- }));
-
- /* we need to have matching customdata */
- BM_mesh_copy_init_customdata(bm_origfaces, bm, NULL);
-
- int *layer_math_map = NULL;
- int layer_index_dst = 0;
- {
- /* TODO: We don't need `sod->layer_math_map` when there are no loops linked
- * to one of the sliding vertices. */
- if (CustomData_has_math(&bm->ldata)) {
- /* over alloc, only 'math' layers are indexed */
- layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i)) {
- layer_math_map[layer_index_dst++] = i;
- }
+ const bool has_layer_math = CustomData_has_math(&bm->ldata);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ if (!has_layer_math && (cd_loop_mdisp_offset == -1)) {
+ return;
+ }
+
+ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+
+ struct GHash *origfaces = BLI_ghash_ptr_new(__func__);
+ struct BMesh *bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){
+ .use_toolflags = false,
+ }));
+
+ /* we need to have matching customdata */
+ BM_mesh_copy_init_customdata(bm_origfaces, bm, NULL);
+
+ int *layer_math_map = NULL;
+ int layer_math_map_len = 0;
+ {
+ /* TODO: We don't need `sod->layer_math_map` when there are no loops linked
+ * to one of the sliding vertices. */
+ if (has_layer_math) {
+ /* over alloc, only 'math' layers are indexed */
+ layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
+ for (int i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ layer_math_map[layer_math_map_len++] = i;
}
- BLI_assert(layer_index_dst != 0);
}
+ BLI_assert(layer_math_map_len != 0);
}
+ }
- struct TransCustomDataLayer *tcld;
- tc->custom.type.data = tcld = MEM_mallocN(sizeof(*tcld), __func__);
- tc->custom.type.free_cb = trans_mesh_customdata_free_cb;
-
- tcld->bm = bm;
- tcld->origfaces = origfaces;
- tcld->bm_origfaces = bm_origfaces;
- tcld->cd_loop_mdisp_offset = cd_loop_mdisp_offset;
- tcld->layer_math_map = layer_math_map;
- tcld->layer_math_map_num = layer_index_dst;
- tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ struct TransCustomDataLayer *tcld = MEM_mallocN(sizeof(*tcld), __func__);
+ int data_len = tc->data_len + tc->data_mirror_len;
- int data_len = tc->data_len + tc->data_mirror_len;
- struct GHash *origverts = BLI_ghash_ptr_new_ex(__func__, data_len);
- tcld->origverts = origverts;
+ tcld->bm = bm;
+ tcld->origfaces = origfaces;
+ tcld->bm_origfaces = bm_origfaces;
+ tcld->cd_loop_mdisp_offset = cd_loop_mdisp_offset;
+ tcld->layer_math_map = layer_math_map;
+ tcld->layer_math_map_num = layer_math_map_len;
+ tcld->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ tcld->origverts = BLI_ghash_ptr_new_ex(__func__, data_len);
+ tcld->data = BLI_memarena_alloc(tcld->arena, data_len * sizeof(*tcld->data));
+ tcld->data_len = data_len;
- struct TransCustomDataLayerVert *tcld_vert, *tcld_vert_iter;
- tcld_vert = BLI_memarena_alloc(tcld->arena, data_len * sizeof(*tcld_vert));
- tcld_vert_iter = &tcld_vert[0];
+ {
+ /* Setup Verts. */
+ struct TransCustomDataLayerVert *tcld_vert_iter = &tcld->data[0];
- TransData *tob;
- for (i = tc->data_len, tob = tc->data; i--; tob++, tcld_vert_iter++) {
+ TransData *tob = tc->data;
+ for (int i = tc->data_len; i--; tob++, tcld_vert_iter++) {
BMVert *v = tob->extra;
create_trans_vert_customdata_layer(v, tcld, tcld_vert_iter);
}
TransDataMirror *td_mirror = tc->data_mirror;
- for (i = tc->data_mirror_len; i--; td_mirror++, tcld_vert_iter++) {
+ for (int i = tc->data_mirror_len; i--; td_mirror++, tcld_vert_iter++) {
BMVert *v = td_mirror->extra;
create_trans_vert_customdata_layer(v, tcld, tcld_vert_iter);
}
+ }
+
+ tc->custom.type.data = tcld;
+ tc->custom.type.free_cb = trans_mesh_customdata_free_cb;
+}
+
+void trans_mesh_customdata_correction_init(TransInfo *t)
+{
+ const char uvcalc_correct_flag = ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) ?
+ UVCALC_TRANSFORM_CORRECT_SLIDE :
+ UVCALC_TRANSFORM_CORRECT;
- tcld->data = tcld_vert;
- tcld->data_len = data_len;
+ if (t->settings->uvcalc_flag & uvcalc_correct_flag) {
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ trans_mesh_customdata_correction_init_container(t, tc);
+ }
}
}
@@ -1187,19 +1199,17 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa
BMesh *bm = tcld->bm;
BMVert *v = tcld_vert->v;
const float *co_orig_3d = tcld_vert->co_orig_3d;
- struct LinkNode **cd_loop_groups = tcld_vert->cd_loop_groups;
BMIter liter;
int j, l_num;
float *loop_weights;
const bool is_moved = (len_squared_v3v3(v->co, co_orig_3d) > FLT_EPSILON);
- const bool do_loop_weight = tcld->layer_math_map_num && is_moved;
- const bool do_loop_mdisps = is_final && is_moved && (tcld->cd_loop_mdisp_offset != -1);
+ const bool do_loop_weight = is_moved && tcld->layer_math_map_num;
const float *v_proj_axis = v->no;
/* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */
float v_proj[3][3];
- if (do_loop_weight || do_loop_mdisps) {
+ if (do_loop_weight) {
project_plane_normalized_v3_v3v3(v_proj[1], co_orig_3d, v_proj_axis);
}
@@ -1264,6 +1274,7 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa
}
}
+ struct LinkNode **cd_loop_groups = tcld_vert->cd_loop_groups;
if (tcld->layer_math_map_num && cd_loop_groups) {
if (do_loop_weight) {
for (j = 0; j < tcld->layer_math_map_num; j++) {
@@ -1283,6 +1294,7 @@ static void trans_mesh_customdata_correction_apply_vert(struct TransCustomDataLa
* Interpolate from every other loop (not ideal)
* However values will only be taken from loops which overlap other mdisps.
* */
+ const bool do_loop_mdisps = is_moved && is_final && (tcld->cd_loop_mdisp_offset != -1);
if (do_loop_mdisps) {
float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num);
BMLoop *l;
@@ -1386,13 +1398,9 @@ void recalcData_mesh(TransInfo *t)
}
}
- if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- trans_mesh_customdata_correction_apply(tc, false);
- }
- }
-
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ trans_mesh_customdata_correction_apply(tc, false);
+
DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
EDBM_mesh_normals_update(em);
@@ -1408,18 +1416,9 @@ void recalcData_mesh(TransInfo *t)
void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
{
const bool canceled = (t->state == TRANS_CANCEL);
+ const bool use_automerge = !canceled && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
- if (canceled) {
- /* Exception, edge slide transformed UVs too. */
- if (t->mode == TFM_EDGE_SLIDE) {
- doEdgeSlide(t, 0.0f);
- }
- else if (t->mode == TFM_VERT_SLIDE) {
- doVertSlide(t, 0.0f);
- }
- }
-
- if (ELEM(t->mode, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.type.data != NULL) {
/* Handle multires re-projection, done
* on transform completion since it's
* really slow -joeedh. */
@@ -1428,10 +1427,8 @@ void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
}
}
- bool use_automerge = !canceled && (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
if (use_automerge) {
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
BMesh *bm = em->bm;
char hflag;
diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h
index bc95fdad59c..48ed9ecf34b 100644
--- a/source/blender/editors/transform/transform_data.h
+++ b/source/blender/editors/transform/transform_data.h
@@ -88,8 +88,8 @@ typedef struct TransDataExtension {
* It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */
float l_smtx[3][3];
/** The rotscale matrix of pose bone, to allow using snap-align in translation mode,
- * when td->mtx is the loc pose bone matrix (and hence can't be used to apply
- * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */
+ * when #TransData.mtx is the loc pose bone matrix (and hence can't be used to apply
+ * rotation in some cases, namely when a bone is in "No-Local" or "Hinge" mode)... */
float r_mtx[3][3];
/** Inverse of previous one. */
float r_smtx[3][3];
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 78c47014d62..cce6ef1f3bd 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -131,21 +131,6 @@ void resetTransRestrictions(TransInfo *t)
t->flag &= ~T_ALL_RESTRICTIONS;
}
-static int initTransInfo_edit_pet_to_flag(const int proportional)
-{
- int flag = 0;
- if (proportional & PROP_EDIT_USE) {
- flag |= T_PROP_EDIT;
- }
- if (proportional & PROP_EDIT_CONNECTED) {
- flag |= T_PROP_CONNECTED;
- }
- if (proportional & PROP_EDIT_PROJECTED) {
- flag |= T_PROP_PROJECTED;
- }
- return flag;
-}
-
void initTransDataContainers_FromObjectData(TransInfo *t,
Object *obact,
Object **objects,
@@ -390,15 +375,15 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
if (RNA_property_is_set(op->ptr, prop)) {
if (RNA_property_boolean_get(op->ptr, prop)) {
- t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
+ t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT_SLIDE;
}
else {
- t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
+ t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT_SLIDE;
}
}
else {
RNA_property_boolean_set(
- op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
+ op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_SLIDE) != 0);
}
}
}
@@ -550,7 +535,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
orient_types[2] = orient_type_scene;
}
else {
- if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode))) {
+ if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode)) &&
+ (t->mode != TFM_ALIGN)) {
orient_types[0] = V3D_ORIENT_VIEW;
}
else {
@@ -636,45 +622,45 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
if (op && (prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
if (RNA_property_is_set(op->ptr, prop)) {
- int proportional = 0;
if (RNA_property_boolean_get(op->ptr, prop)) {
- proportional |= PROP_EDIT_USE;
+ t->flag |= T_PROP_EDIT;
if (RNA_boolean_get(op->ptr, "use_proportional_connected")) {
- proportional |= PROP_EDIT_CONNECTED;
+ t->flag |= T_PROP_CONNECTED;
}
if (RNA_boolean_get(op->ptr, "use_proportional_projected")) {
- proportional |= PROP_EDIT_PROJECTED;
+ t->flag |= T_PROP_PROJECTED;
}
}
- t->flag |= initTransInfo_edit_pet_to_flag(proportional);
}
else {
/* use settings from scene only if modal */
if (t->flag & T_MODAL) {
if ((t->options & CTX_NO_PET) == 0) {
+ bool use_prop_edit = false;
if (t->spacetype == SPACE_GRAPH) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
+ use_prop_edit = ts->proportional_fcurve;
}
else if (t->spacetype == SPACE_ACTION) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
+ use_prop_edit = ts->proportional_action;
}
- else if (t->obedit_type != -1) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_edit);
+ else if (t->options & CTX_MASK) {
+ use_prop_edit = ts->proportional_mask;
}
- else if (t->options & CTX_GPENCIL_STROKES) {
- t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_edit);
+ else if (obact && obact->mode == OB_MODE_OBJECT) {
+ use_prop_edit = ts->proportional_objects;
}
- else if (t->options & CTX_MASK) {
- if (ts->proportional_mask) {
- t->flag |= T_PROP_EDIT;
-
- if (ts->proportional_edit & PROP_EDIT_CONNECTED) {
- t->flag |= T_PROP_CONNECTED;
- }
- }
+ else {
+ use_prop_edit = (ts->proportional_edit & PROP_EDIT_USE) != 0;
}
- else if (!(t->options & CTX_CURSOR) && ts->proportional_objects) {
+
+ if (use_prop_edit) {
t->flag |= T_PROP_EDIT;
+ if (ts->proportional_edit & PROP_EDIT_CONNECTED) {
+ t->flag |= T_PROP_CONNECTED;
+ }
+ if (ts->proportional_edit & PROP_EDIT_PROJECTED) {
+ t->flag |= T_PROP_PROJECTED;
+ }
}
}
}
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index f028044809f..831ea90b4e4 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -50,6 +50,23 @@
/* Own include. */
#include "transform_mode.h"
+int transform_mode_really_used(bContext *C, int mode)
+{
+ if (mode == TFM_BONESIZE) {
+ Object *ob = CTX_data_active_object(C);
+ BLI_assert(ob);
+ if (ob->type != OB_ARMATURE) {
+ return TFM_RESIZE;
+ }
+ bArmature *arm = ob->data;
+ if (arm->drawtype == ARM_ENVELOPE) {
+ return TFM_BONE_ENVELOPE_DIST;
+ }
+ }
+
+ return mode;
+}
+
bool transdata_check_local_center(TransInfo *t, short around)
{
return ((around == V3D_AROUND_LOCAL_ORIGINS) &&
@@ -1174,25 +1191,12 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
case TFM_CREASE:
initCrease(t);
break;
- case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
- /* Note: we have to pick one, use the active object. */
- TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
- bArmature *arm = tc->poseobj->data;
- if (arm->drawtype == ARM_ENVELOPE) {
- initBoneEnvelope(t);
- t->mode = TFM_BONE_ENVELOPE_DIST;
- }
- else {
- initBoneSize(t);
- }
+ case TFM_BONESIZE:
+ initBoneSize(t);
break;
- }
case TFM_BONE_ENVELOPE:
- initBoneEnvelope(t);
- break;
case TFM_BONE_ENVELOPE_DIST:
initBoneEnvelope(t);
- t->mode = TFM_BONE_ENVELOPE_DIST;
break;
case TFM_EDGE_SLIDE:
case TFM_VERT_SLIDE: {
@@ -1267,6 +1271,12 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
break;
}
+ if (t->data_type == TC_MESH_VERTS) {
+ /* Init Custom Data correction.
+ * Ideally this should be called when creating the TransData. */
+ trans_mesh_customdata_correction_init(t);
+ }
+
/* TODO(germano): Some of these operations change the `t->mode`.
* This can be bad for Redo.
* BLI_assert(t->mode == mode); */
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
index 464deff983b..5cda8e3063a 100644
--- a/source/blender/editors/transform/transform_mode.h
+++ b/source/blender/editors/transform/transform_mode.h
@@ -26,6 +26,7 @@
#define __TRANSFORM_MODE_H__
struct AnimData;
+struct bContext;
struct LinkNode;
struct TransData;
struct TransDataContainer;
@@ -40,6 +41,7 @@ typedef struct TransDataGenericSlideVert {
} TransDataGenericSlideVert;
/* transform_mode.c */
+int transform_mode_really_used(struct bContext *C, int mode);
bool transdata_check_local_center(TransInfo *t, short around);
bool transform_mode_is_changeable(const int mode);
void protectedTransBits(short protectflag, float vec[3]);
@@ -95,7 +97,6 @@ void initSeqSlide(TransInfo *t);
/* transform_mode_edge_slide.c */
void drawEdgeSlide(TransInfo *t);
-void doEdgeSlide(TransInfo *t, float perc);
void initEdgeSlide_ex(
TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp);
void initEdgeSlide(TransInfo *t);
@@ -153,7 +154,6 @@ void initTranslation(TransInfo *t);
/* transform_mode_vert_slide.c */
void drawVertSlide(TransInfo *t);
-void doVertSlide(TransInfo *t, float perc);
void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp);
void initVertSlide(TransInfo *t);
#endif
diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c
index 77850e74785..2c2253630c0 100644
--- a/source/blender/editors/transform/transform_mode_bbone_resize.c
+++ b/source/blender/editors/transform/transform_mode_bbone_resize.c
@@ -132,6 +132,11 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
if (t->con.applySize) {
t->con.applySize(t, NULL, NULL, mat);
+ for (i = 0; i < 3; i++) {
+ if (!(t->con.mode & (CON_AXIS0 << i))) {
+ t->values_final[i] = 1.0f;
+ }
+ }
}
copy_m3_m3(t->mat, mat); // used in gizmo
diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c
index 7045d190478..b7a34769f5a 100644
--- a/source/blender/editors/transform/transform_mode_boneenvelope.c
+++ b/source/blender/editors/transform/transform_mode_boneenvelope.c
@@ -96,7 +96,6 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
void initBoneEnvelope(TransInfo *t)
{
- t->mode = TFM_BONE_ENVELOPE;
t->transform = applyBoneEnvelope;
initMouseInputMode(t, &t->mouse, INPUT_SPRING);
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c
index 42f75f041b9..ed22afc404e 100644
--- a/source/blender/editors/transform/transform_mode_edge_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_slide.c
@@ -50,6 +50,7 @@
#include "BLT_translation.h"
#include "transform.h"
+#include "transform_constraints.h"
#include "transform_convert.h"
#include "transform_mode.h"
#include "transform_snap.h"
@@ -96,24 +97,28 @@ typedef struct EdgeSlideParams {
} EdgeSlideParams;
/**
- * Get the first valid EdgeSlideData.
+ * Get the first valid TransDataContainer *.
*
* Note we cannot trust TRANS_DATA_CONTAINER_FIRST_OK because of multi-object that
* may leave items with invalid custom data in the transform data container.
*/
-static EdgeSlideData *edgeSlideFirstGet(TransInfo *t)
+static TransDataContainer *edge_slide_container_first_ok(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- EdgeSlideData *sld = tc->custom.mode.data;
- if (sld == NULL) {
- continue;
+ if (tc->custom.mode.data) {
+ return tc;
}
- return sld;
}
BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid");
return NULL;
}
+static EdgeSlideData *edgeSlideFirstGet(TransInfo *t)
+{
+ TransDataContainer *tc = edge_slide_container_first_ok(t);
+ return tc->custom.mode.data;
+}
+
static void calcEdgeSlideCustomPoints(struct TransInfo *t)
{
EdgeSlideData *sld = edgeSlideFirstGet(t);
@@ -1129,132 +1134,226 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
void drawEdgeSlide(TransInfo *t)
{
- if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) {
- const EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld = edgeSlideFirstGet(t);
- const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (t->mode != TFM_EDGE_SLIDE) {
+ return;
+ }
- /* Even mode */
- if ((slp->use_even == true) || (is_clamp == false)) {
- const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
+ EdgeSlideData *sld = edgeSlideFirstGet(t);
+ if (sld == NULL) {
+ return;
+ }
- GPU_depth_test(false);
+ const EdgeSlideParams *slp = t->custom.mode.data;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
- GPU_matrix_push();
- GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
+ GPU_depth_test(false);
- uint pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_matrix_push();
+ GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat);
- if (slp->use_even == true) {
- float co_a[3], co_b[3], co_mark[3];
- TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- const float fac = (slp->perc + 1.0f) / 2.0f;
- const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
- const float guide_size = ctrl_size - 0.5f;
- const int alpha_shade = -30;
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]);
- add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- GPU_line_width(line_size);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBeginAtMost(GPU_PRIM_LINES, 4);
- if (curr_sv->v_side[0]) {
- immVertex3fv(pos, curr_sv->v_side[0]->co);
- immVertex3fv(pos, curr_sv->v_co_orig);
- }
+ if (slp->use_even == true) {
+ /* Even mode */
+ float co_a[3], co_b[3], co_mark[3];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const float fac = (slp->perc + 1.0f) / 2.0f;
+ const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
+ const float guide_size = ctrl_size - 0.5f;
+ const int alpha_shade = -30;
+
+ add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]);
+ add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBeginAtMost(GPU_PRIM_LINES, 4);
+ if (curr_sv->v_side[0]) {
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ }
+ if (curr_sv->v_side[1]) {
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ }
+ immEnd();
+
+ {
+ float *co_test = NULL;
+ if (slp->flipped) {
if (curr_sv->v_side[1]) {
- immVertex3fv(pos, curr_sv->v_side[1]->co);
- immVertex3fv(pos, curr_sv->v_co_orig);
+ co_test = curr_sv->v_side[1]->co;
}
- immEnd();
-
- {
- float *co_test = NULL;
- if (slp->flipped) {
- if (curr_sv->v_side[1]) {
- co_test = curr_sv->v_side[1]->co;
- }
- }
- else {
- if (curr_sv->v_side[0]) {
- co_test = curr_sv->v_side[0]->co;
- }
- }
-
- if (co_test != NULL) {
- immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
- GPU_point_size(ctrl_size);
- immBegin(GPU_PRIM_POINTS, 1);
- immVertex3fv(pos, co_test);
- immEnd();
- }
+ }
+ else {
+ if (curr_sv->v_side[0]) {
+ co_test = curr_sv->v_side[0]->co;
}
+ }
- immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
- GPU_point_size(guide_size);
+ if (co_test != NULL) {
+ immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ GPU_point_size(ctrl_size);
immBegin(GPU_PRIM_POINTS, 1);
- interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- immVertex3fv(pos, co_mark);
+ immVertex3fv(pos, co_test);
immEnd();
}
+ }
+
+ immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ GPU_point_size(guide_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
+ immVertex3fv(pos, co_mark);
+ immEnd();
+ }
+ else if (is_clamp == false) {
+ const int side_index = sld->curr_side_unclamp;
+ TransDataEdgeSlideVert *sv;
+ int i;
+ const int alpha_shade = -160;
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBegin(GPU_PRIM_LINES, sld->totsv * 2);
+
+ /* TODO(campbell): Loop over all verts */
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+
+ if (!is_zero_v3(sv->dir_side[side_index])) {
+ copy_v3_v3(a, sv->dir_side[side_index]);
+ }
else {
- if (is_clamp == false) {
- const int side_index = sld->curr_side_unclamp;
- TransDataEdgeSlideVert *sv;
- int i;
- const int alpha_shade = -160;
+ copy_v3_v3(a, sv->dir_side[!side_index]);
+ }
- GPU_line_width(line_size);
- immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- immBegin(GPU_PRIM_LINES, sld->totsv * 2);
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->v_co_orig);
+ add_v3_v3(b, sv->v_co_orig);
- /* TODO(campbell): Loop over all verts */
- sv = sld->sv;
- for (i = 0; i < sld->totsv; i++, sv++) {
- float a[3], b[3];
+ immVertex3fv(pos, a);
+ immVertex3fv(pos, b);
+ }
+ immEnd();
+ }
+ else {
+ /* Common case. */
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ const int alpha_shade = -160;
+
+ float co_dir[3];
+ add_v3_v3v3(co_dir, curr_sv->v_co_orig, curr_sv->dir_side[sld->curr_side_unclamp]);
+
+ GPU_line_width(line_size);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBeginAtMost(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, curr_sv->v_co_orig);
+ immVertex3fv(pos, co_dir);
+ immEnd();
+ }
- if (!is_zero_v3(sv->dir_side[side_index])) {
- copy_v3_v3(a, sv->dir_side[side_index]);
- }
- else {
- copy_v3_v3(a, sv->dir_side[!side_index]);
- }
+ immUnbindProgram();
- mul_v3_fl(a, 100.0f);
- negate_v3_v3(b, a);
- add_v3_v3(a, sv->v_co_orig);
- add_v3_v3(b, sv->v_co_orig);
+ GPU_matrix_pop();
- immVertex3fv(pos, a);
- immVertex3fv(pos, b);
- }
- immEnd();
- }
- else {
- BLI_assert(0);
- }
- }
+ GPU_blend(false);
- immUnbindProgram();
+ GPU_depth_test(true);
+}
- GPU_matrix_pop();
+static void edge_slide_snap_apply(TransInfo *t, float *value)
+{
+ TransDataContainer *tc = edge_slide_container_first_ok(t);
+ EdgeSlideParams *slp = t->custom.mode.data;
+ EdgeSlideData *sld_active = tc->custom.mode.data;
+ TransDataEdgeSlideVert *sv = &sld_active->sv[sld_active->curr_sv_index];
+ float snap_point[3], co_orig[3], co_dest[2][3], dvec[3];
+
+ copy_v3_v3(co_orig, sv->v_co_orig);
+ add_v3_v3v3(co_dest[0], co_orig, sv->dir_side[0]);
+ add_v3_v3v3(co_dest[1], co_orig, sv->dir_side[1]);
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, co_orig);
+ mul_m4_v3(tc->mat, co_dest[0]);
+ mul_m4_v3(tc->mat, co_dest[1]);
+ }
- GPU_blend(false);
+ getSnapPoint(t, dvec);
+ sub_v3_v3(dvec, t->tsnap.snapTarget);
+ add_v3_v3v3(snap_point, co_orig, dvec);
- GPU_depth_test(true);
+ float perc = *value;
+ int side_index;
+ float t_mid;
+ if (slp->use_even == false) {
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ side_index = perc < 0.0f;
+ }
+ else {
+ side_index = sld_active->curr_side_unclamp;
}
}
+ else {
+ /* Could be pre-calculated. */
+ t_mid = line_point_factor_v3((float[3]){0.0f, 0.0f, 0.0f}, sv->dir_side[0], sv->dir_side[1]);
+
+ float t_snap = line_point_factor_v3(snap_point, co_dest[0], co_dest[1]);
+ side_index = t_snap >= t_mid;
+ }
+
+ if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
+ float co_dir[3];
+ sub_v3_v3v3(co_dir, co_dest[side_index], co_orig);
+ if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) {
+ transform_constraint_snap_axis_to_edge(t, co_dir, dvec);
+ }
+ else {
+ transform_constraint_snap_axis_to_face(t, co_dir, dvec);
+ }
+ add_v3_v3v3(snap_point, co_orig, dvec);
+ }
+
+ perc = line_point_factor_v3(snap_point, co_orig, co_dest[side_index]);
+ if (slp->use_even == false) {
+ if (side_index) {
+ perc *= -1;
+ }
+ }
+ else {
+ if (!side_index) {
+ perc = (1.0f - perc) * t_mid;
+ }
+ else {
+ perc = perc * (1.0f - t_mid) + t_mid;
+ }
+
+ if (slp->flipped) {
+ perc = 1.0f - perc;
+ }
+
+ perc = (2 * perc) - 1.0f;
+
+ if (!slp->flipped) {
+ perc *= -1;
+ }
+ }
+
+ *value = perc;
}
-void doEdgeSlide(TransInfo *t, float perc)
+static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideParams *slp = t->custom.mode.data;
EdgeSlideData *sld_active = edgeSlideFirstGet(t);
@@ -1365,6 +1464,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
+ applySnapping(t, &final);
snapGridIncrement(t, &final);
/* only do this so out of range values are not displayed */
@@ -1413,6 +1513,8 @@ void initEdgeSlide_ex(
t->mode = TFM_EDGE_SLIDE;
t->transform = applyEdgeSlide;
t->handleEvent = handleEventEdgeSlide;
+ t->tsnap.applySnap = edge_slide_snap_apply;
+ t->tsnap.distance = transform_snap_distance_len_squared_fn;
{
EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
@@ -1432,16 +1534,13 @@ void initEdgeSlide_ex(
t->custom.mode.use_free = true;
}
- if (use_double_side) {
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sld = use_double_side ? createEdgeSlideVerts_double_side(t, tc) :
- createEdgeSlideVerts_single_side(t, tc);
- if (sld) {
- tc->custom.mode.data = sld;
- tc->custom.mode.free_cb = freeEdgeSlideVerts;
- trans_mesh_customdata_correction_init(t, tc);
- ok = true;
- }
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ sld = use_double_side ? createEdgeSlideVerts_double_side(t, tc) :
+ createEdgeSlideVerts_single_side(t, tc);
+ if (sld) {
+ tc->custom.mode.data = sld;
+ tc->custom.mode.free_cb = freeEdgeSlideVerts;
+ ok = true;
}
}
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index ebce32a598e..5fb46b30e0d 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -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);
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index 6480cb6c30e..4fa5dffc473 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -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);
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 60caa257a40..aee05197f10 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -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,34 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
}
}
+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 +405,8 @@ void initTranslation(TransInfo *t)
}
t->transform = applyTranslation;
+ t->tsnap.applySnap = ApplySnapTranslation;
+ t->tsnap.distance = transform_snap_distance_len_squared_fn;
initMouseInputMode(t, &t->mouse, INPUT_VECTOR);
diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c
index 62415b1ddc6..4b75c362da9 100644
--- a/source/blender/editors/transform/transform_mode_vert_slide.c
+++ b/source/blender/editors/transform/transform_mode_vert_slide.c
@@ -47,6 +47,7 @@
#include "BLT_translation.h"
#include "transform.h"
+#include "transform_constraints.h"
#include "transform_convert.h"
#include "transform_mode.h"
#include "transform_snap.h"
@@ -491,7 +492,7 @@ void drawVertSlide(TransInfo *t)
}
}
-void doVertSlide(TransInfo *t, float perc)
+static void doVertSlide(TransInfo *t, float perc)
{
VertSlideParams *slp = t->custom.mode.data;
@@ -538,6 +539,37 @@ void doVertSlide(TransInfo *t, float perc)
}
}
+static void vert_slide_snap_apply(TransInfo *t, float *value)
+{
+ TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t);
+ VertSlideData *sld = tc->custom.mode.data;
+ TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
+
+ float snap_point[3], co_orig_3d[3], co_curr_3d[3], dvec[3];
+ copy_v3_v3(co_orig_3d, sv->co_orig_3d);
+ copy_v3_v3(co_curr_3d, sv->co_link_orig_3d[sv->co_link_curr]);
+ if (tc->use_local_mat) {
+ mul_m4_v3(tc->mat, co_orig_3d);
+ mul_m4_v3(tc->mat, co_curr_3d);
+ }
+
+ getSnapPoint(t, dvec);
+ sub_v3_v3(dvec, t->tsnap.snapTarget);
+ if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
+ float co_dir_3d[3];
+ sub_v3_v3v3(co_dir_3d, co_curr_3d, co_orig_3d);
+ if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) {
+ transform_constraint_snap_axis_to_edge(t, co_dir_3d, dvec);
+ }
+ else {
+ transform_constraint_snap_axis_to_face(t, co_dir_3d, dvec);
+ }
+ }
+
+ add_v3_v3v3(snap_point, co_orig_3d, dvec);
+ *value = line_point_factor_v3(snap_point, co_orig_3d, co_curr_3d);
+}
+
static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
{
char str[UI_MAX_DRAW_STR];
@@ -551,6 +583,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
+ applySnapping(t, &final);
snapGridIncrement(t, &final);
/* only do this so out of range values are not displayed */
@@ -596,6 +629,8 @@ void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
t->mode = TFM_VERT_SLIDE;
t->transform = applyVertSlide;
t->handleEvent = handleEventVertSlide;
+ t->tsnap.applySnap = vert_slide_snap_apply;
+ t->tsnap.distance = transform_snap_distance_len_squared_fn;
{
VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__);
@@ -617,7 +652,6 @@ void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
if (sld) {
tc->custom.mode.data = sld;
tc->custom.mode.free_cb = freeVertSlideVerts;
- trans_mesh_customdata_correction_init(t, tc);
ok = true;
}
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 95249f4d17b..f86bcc41bee 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -1049,11 +1049,11 @@ static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editarmature;
+ ot->poll = ED_operator_object_active;
ot->poll_property = transform_poll_property;
RNA_def_float_translation(
- ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Display Size", "", -FLT_MAX, FLT_MAX);
+ ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Display Size", "", -FLT_MAX, FLT_MAX);
WM_operatortype_props_advanced_begin(ot);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index b508507cd4e..2943c3cb8ea 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -22,23 +22,13 @@
*/
#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 +48,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 +69,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 +77,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]);
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -143,6 +124,12 @@ bool transformModeUseSnap(const TransInfo *t)
if (t->mode == TFM_RESIZE) {
return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0;
}
+ if (t->mode == TFM_VERT_SLIDE) {
+ return true;
+ }
+ if (t->mode == TFM_EDGE_SLIDE) {
+ return true;
+ }
return false;
}
@@ -476,7 +463,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 +543,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 +588,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 +696,13 @@ 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)) {
+ t->tsnap.targetSnap = TargetSnapCenter;
+ break;
+ }
+ /* Can't do TARGET_CENTER with these modes,
+ * use TARGET_MEDIAN instead. */
+ ATTR_FALLTHROUGH;
case SCE_SNAP_TARGET_MEDIAN:
t->tsnap.targetSnap = TargetSnapMedian;
break;
@@ -729,36 +710,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)
@@ -859,145 +810,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)
* \{ */
@@ -1734,3 +1546,16 @@ static void applyGridIncrement(
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic callbacks
+ * \{ */
+
+float transform_snap_distance_len_squared_fn(TransInfo *UNUSED(t),
+ const float p1[3],
+ const float p2[3])
+{
+ return len_squared_v3v3(p1, p2);
+}
+
+/** \} */
diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h
index c088cf80f0d..688661bc2cb 100644
--- a/source/blender/editors/transform/transform_snap.h
+++ b/source/blender/editors/transform/transform_snap.h
@@ -87,4 +87,6 @@ void addSnapPoint(TransInfo *t);
eRedrawFlag updateSelectedSnapPoint(TransInfo *t);
void removeSnapPoint(TransInfo *t);
+float transform_snap_distance_len_squared_fn(TransInfo *t, const float p1[3], const float p2[3]);
+
#endif /* __TRANSFORM_SNAP_H__ */
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 08ef5109a74..4198b4c02a3 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -367,17 +367,15 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
* \{ */
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
- bool use_obedit,
- bool use_backface_culling,
Object *ob,
float obmat[4][4],
+ bool use_obedit,
+ bool use_backface_culling,
+ bool is_object_active,
void *data);
/**
* Walks through all objects in the scene to create the list of objects to snap.
- *
- * \param sctx: Snap context to store data.
- * \param snap_select: from enum #eSnapSelect.
*/
static void iter_snap_objects(SnapObjectContext *sctx,
Depsgraph *depsgraph,
@@ -393,7 +391,6 @@ static void iter_snap_objects(SnapObjectContext *sctx,
Base *base_act = view_layer->basact;
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
-
if (!BASE_VISIBLE(v3d, base)) {
continue;
}
@@ -405,13 +402,14 @@ static void iter_snap_objects(SnapObjectContext *sctx,
continue;
}
+ const bool is_object_active = (base == base_act);
if (snap_select == SNAP_NOT_SELECTED) {
if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) {
continue;
}
}
else if (snap_select == SNAP_NOT_ACTIVE) {
- if (base == base_act) {
+ if (is_object_active) {
continue;
}
}
@@ -421,14 +419,24 @@ static void iter_snap_objects(SnapObjectContext *sctx,
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- sob_callback(
- sctx, use_object_edit_cage, use_backface_culling, dupli_ob->ob, dupli_ob->mat, data);
+ sob_callback(sctx,
+ dupli_ob->ob,
+ dupli_ob->mat,
+ use_object_edit_cage,
+ use_backface_culling,
+ is_object_active,
+ data);
}
free_object_duplilist(lb);
}
- sob_callback(
- sctx, use_object_edit_cage, use_backface_culling, obj_eval, obj_eval->obmat, data);
+ sob_callback(sctx,
+ obj_eval,
+ obj_eval->obmat,
+ use_object_edit_cage,
+ use_backface_culling,
+ is_object_active,
+ data);
}
}
@@ -956,10 +964,11 @@ struct RaycastObjUserData {
* \note Duplicate args here are documented at #snapObjectsRay
*/
static void raycast_obj_fn(SnapObjectContext *sctx,
- bool use_obedit,
- bool use_backface_culling,
Object *ob,
float obmat[4][4],
+ bool use_obedit,
+ bool use_backface_culling,
+ bool is_object_active,
void *data)
{
struct RaycastObjUserData *dt = data;
@@ -1032,24 +1041,26 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
case OB_CURVE:
case OB_SURF:
case OB_FONT: {
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval) {
- retval = raycastMesh(sctx,
- dt->ray_start,
- dt->ray_dir,
- ob,
- mesh_eval,
- obmat,
- ob_index,
- false,
- use_backface_culling,
- ray_depth,
- dt->r_loc,
- dt->r_no,
- dt->r_index,
- dt->r_hit_list);
- break;
+ if (!is_object_active) {
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ if (mesh_eval) {
+ retval = raycastMesh(sctx,
+ dt->ray_start,
+ dt->ray_dir,
+ ob,
+ mesh_eval,
+ obmat,
+ ob_index,
+ false,
+ use_backface_culling,
+ ray_depth,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
+ }
}
+ break;
}
}
@@ -1071,9 +1082,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
* Walks through all objects in the scene to find the `hit` on object surface.
*
* \param sctx: Snap context to store data.
- * \param snap_select: from enum eSnapSelect.
- * \param use_object_edit_cage: Uses the coordinates of BMesh(if any) to do the snapping.
- * \param obj_list: List with objects to snap (created in `create_object_list`).
+ * \param params: Snapping behavior.
*
* Read/Write Args
* ---------------
@@ -2054,15 +2063,15 @@ static short snapCurve(SnapData *snapdata,
}
/* may extend later (for now just snaps to empty center) */
-static short snapEmpty(SnapData *snapdata,
- Object *ob,
- const float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3],
- float *UNUSED(r_no),
- int *r_index)
+static short snap_object_center(SnapData *snapdata,
+ Object *ob,
+ const float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
short retval = 0;
@@ -2117,7 +2126,7 @@ static short snapCamera(const SnapObjectContext *sctx,
float *dist_px,
/* return args */
float r_loc[3],
- float *UNUSED(r_no),
+ float *r_no,
int *r_index)
{
short retval = 0;
@@ -2132,7 +2141,7 @@ static short snapCamera(const SnapObjectContext *sctx,
MovieTracking *tracking;
if (clip == NULL) {
- return retval;
+ return snap_object_center(snapdata, object, obmat, dist_px, r_loc, r_no, r_index);
}
if (object->transflag & OB_DUPLI) {
return retval;
@@ -2650,11 +2659,12 @@ struct SnapObjUserData {
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static void sanp_obj_fn(SnapObjectContext *sctx,
- bool use_obedit,
- bool use_backface_culling,
+static void snap_obj_fn(SnapObjectContext *sctx,
Object *ob,
float obmat[4][4],
+ bool use_obedit,
+ bool use_backface_culling,
+ bool UNUSED(is_object_active),
void *data)
{
struct SnapObjUserData *dt = data;
@@ -2729,10 +2739,10 @@ static void sanp_obj_fn(SnapObjectContext *sctx,
break;
}
case OB_EMPTY:
- retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
- break;
case OB_GPENCIL:
- retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
+ case OB_LAMP:
+ retval = snap_object_center(
+ dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CAMERA:
retval = snapCamera(
@@ -2800,7 +2810,7 @@ static short snapObjectsRay(SnapObjectContext *sctx,
.ret = 0,
};
- iter_snap_objects(sctx, depsgraph, params, sanp_obj_fn, &data);
+ iter_snap_objects(sctx, depsgraph, params, snap_obj_fn, &data);
return data.ret;
}
@@ -3205,7 +3215,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
* \param mval: Screenspace coordinate.
* \param prev_co: Coordinate for perpendicular point calculation (optional).
* \param dist_px: Maximum distance to snap (in pixels).
- * \param r_co: hit location.
+ * \param r_loc: hit location.
* \param r_no: hit normal (optional).
* \return Snap success
*/